Skip to content

Commit

Permalink
feat: eval esm modules with fallback loader (#300)
Browse files Browse the repository at this point in the history
  • Loading branch information
pi0 authored Sep 25, 2024
1 parent 50e4280 commit a59ed9f
Show file tree
Hide file tree
Showing 4 changed files with 36 additions and 11 deletions.
32 changes: 21 additions & 11 deletions src/eval.ts
Original file line number Diff line number Diff line change
Expand Up @@ -125,20 +125,24 @@ export function evalModule(

// Compile wrapped script
let compiled;
const wrapped = wrapModule(source, { async: evalOptions.async });
try {
compiled = vm.runInThisContext(
wrapModule(source, { async: evalOptions.async }),
{
filename,
lineOffset: 0,
displayErrors: false,
},
);
compiled = vm.runInThisContext(wrapped, {
filename,
lineOffset: 0,
displayErrors: false,
});
} catch (error: any) {
if (ctx.opts.moduleCache) {
delete ctx.nativeRequire.cache[filename];
if (error.name === "SyntaxError" && evalOptions.async && ctx.nativeImport) {
// Support cases such as import.meta.[custom]
debug(ctx, "[esm]", "[import]", "[fallback]", filename);
compiled = esmEval(wrapped, ctx.nativeImport!);
} else {
if (ctx.opts.moduleCache) {
delete ctx.nativeRequire.cache[filename];
}
ctx.onError!(error);
}
ctx.onError!(error);
}

// Evaluate module
Expand Down Expand Up @@ -182,3 +186,9 @@ export function evalModule(

return evalOptions.async ? Promise.resolve(evalResult).then(next) : next();
}

function esmEval(code: string, nativeImport: (id: string) => Promise<any>) {
const uri = `data:text/javascript;base64,${Buffer.from(`export default ${code}`).toString("base64")}`;
return (...args: any[]) =>
nativeImport(uri).then((mod) => mod.default(...args));
}
2 changes: 2 additions & 0 deletions test/__snapshots__/fixtures.test.ts.snap
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,8 @@ exports[`fixtures > hashbang > stdout 1`] = `"1"`;
exports[`fixtures > import-map > stdout 1`] = `"{ alias: 'alias' }"`;
exports[`fixtures > import-meta > stdout 1`] = `"hello! { hello: 'world' }"`;
exports[`fixtures > json > stdout 1`] = `
"Imported : { test: 123 } .default: { test: 123 }
Imported with assertion : { test: 123 } .default: { test: 123 }
Expand Down
10 changes: 10 additions & 0 deletions test/fixtures/import-meta/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
declare global {
interface ImportMeta {
custom: any;
}
}

import.meta.custom = { hello: "world" };
console.log("hello!", import.meta.custom);

export {};
3 changes: 3 additions & 0 deletions test/fixtures/import-meta/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"type": "module"
}

0 comments on commit a59ed9f

Please sign in to comment.