Skip to content

Commit

Permalink
Add support for import() calls lowered to require()
Browse files Browse the repository at this point in the history
  • Loading branch information
eduardoboucas committed Jun 2, 2021
1 parent 33fc625 commit 539af45
Show file tree
Hide file tree
Showing 2 changed files with 55 additions and 5 deletions.
14 changes: 9 additions & 5 deletions internal/js_parser/js_parser.go
Original file line number Diff line number Diff line change
Expand Up @@ -11978,6 +11978,10 @@ func (p *parser) visitExprInOut(expr js_ast.Expr, in exprIn) (js_ast.Expr, exprO
}}
}

// This is an import with a dynamic expression. Use the string
// representation of the expression as the import path.
r := js_lexer.RangeOfCallExpr(p.source, expr.Loc)

// We need to convert this into a call to "require()" if ES6 syntax is
// not supported in the current output format. The full conversion:
//
Expand All @@ -11994,10 +11998,13 @@ func (p *parser) visitExprInOut(expr js_ast.Expr, in exprIn) (js_ast.Expr, exprO
// and the linker currently need an import record to handle this case
// correctly, and you need a string literal to get an import record.
if p.options.unsupportedJSFeatures.Has(compat.DynamicImport) {
importRecordIndex := p.addDynamicExpressionImportRecord(ast.ImportRequire, expr.Loc, p.source.TextForRange(r))

var then js_ast.Expr
value := p.callRuntime(arg.Loc, "__toModule", []js_ast.Expr{{Loc: expr.Loc, Data: &js_ast.ECall{
Target: p.valueToSubstituteForRequire(expr.Loc),
Args: []js_ast.Expr{arg},
Target: p.valueToSubstituteForRequire(expr.Loc),
Args: []js_ast.Expr{arg},
DynamicExpressionImportIndex: &importRecordIndex,
}}})
body := js_ast.FnBody{Loc: expr.Loc, Stmts: []js_ast.Stmt{{Loc: expr.Loc, Data: &js_ast.SReturn{ValueOrNil: value}}}}
if p.options.unsupportedJSFeatures.Has(compat.Arrow) {
Expand All @@ -12021,9 +12028,6 @@ func (p *parser) visitExprInOut(expr js_ast.Expr, in exprIn) (js_ast.Expr, exprO
}}
}

// This is a require with a dynamic expression. Use the string
// representation of the expression as the import path.
r := js_lexer.RangeOfCallExpr(p.source, expr.Loc)
importRecordIndex := p.addDynamicExpressionImportRecord(ast.ImportDynamic, expr.Loc, p.source.TextForRange(r))

return js_ast.Expr{Loc: expr.Loc, Data: &js_ast.EImportCall{
Expand Down
46 changes: 46 additions & 0 deletions scripts/plugin-tests.js
Original file line number Diff line number Diff line change
Expand Up @@ -2497,6 +2497,52 @@ let syncTests = {
assert.strictEqual(result.stdout.trim(), shimData)
},

async onDynamicImportPluginImportES5({ esbuild, testDir }) {
const input = path.join(testDir, "in.js")
const output = path.join(testDir, "out.js")
const shimData = { foo: 'bar' }
await writeFileAsync(
input,
`
var loadFile = name => {
var file = import(\`./files/\${name}.json\`)
return file
}
module.exports = loadFile
`
)
await esbuild.build({
entryPoints: [input],
bundle: true,
outfile: output,
format: "cjs",
target: "es5",
plugins: [
{
name: "name",
setup(build) {
build.onDynamicImport({}, (args) => {
assert.strictEqual(args.expression, 'import(`./files/${name}.json`)');
assert.strictEqual(args.importer, input);
assert.strictEqual(args.namespace, 'file');
assert.strictEqual(args.resolveDir, path.join(rootTestDir, 'onDynamicImportPluginImportES5'))

return {
contents: `module.exports = () => (${JSON.stringify(shimData)})`,
};
});
},
},
],
})
const bundle = require(output)
const result = await bundle()

assert.deepStrictEqual(result.default, shimData)
},

async onDynamicImportPluginRequireUnclaimed({ esbuild, testDir }) {
const input = path.join(testDir, "in.js");
const output = path.join(testDir, "out.js");
Expand Down

0 comments on commit 539af45

Please sign in to comment.