Skip to content

fix: avoid downleveled dynamic import closing over specifier expression#49663

Merged
rbuckton merged 4 commits into
microsoft:mainfrom
Josh-Cena:fix-dynamic-import
Oct 18, 2022
Merged

fix: avoid downleveled dynamic import closing over specifier expression#49663
rbuckton merged 4 commits into
microsoft:mainfrom
Josh-Cena:fix-dynamic-import

Conversation

@Josh-Cena

Copy link
Copy Markdown
Contributor

Fixes #49652
Fixes #48285

@typescript-bot typescript-bot added the For Milestone Bug PRs that fix a bug with a specific milestone label Jun 24, 2022
Comment thread src/compiler/transformers/module/module.ts Outdated
Comment thread src/compiler/transformers/module/module.ts Outdated
Comment thread src/compiler/transformers/module/module.ts Outdated
Comment thread src/compiler/transformers/module/module.ts Outdated
@Josh-Cena

Copy link
Copy Markdown
Contributor Author

I realized Babel is transpiling it to Promise.resolve(`${arg}`).then(c => require(c)) where the template literal forces synchronous evaluation. This avoids the creation of the temp variable. I wonder—for the purpose of <ES6 emit—if there's any problem if we use String().

@rbuckton

Copy link
Copy Markdown
Contributor

I realized Babel is transpiling it to Promise.resolve(`${arg}`).then(c => require(c)) where the template literal forces synchronous evaluation. This avoids the creation of the temp variable. I wonder—for the purpose of <ES6 emit—if there's any problem if we use String().

Is there a reason to do that over what you're already doing in this PR? I'm not so concerned about the temp variable in this case.

@Josh-Cena Josh-Cena changed the title fix: evaluate dynamic import specifier expressions synchronously fix: avoid downleveled dynamic import closing over specifier expression Jul 26, 2022
@Josh-Cena

Copy link
Copy Markdown
Contributor Author

No—no adverse effects that I can think of (apart from some micro-optimizations, maybe?) If you think they both work I'll stay with the current solution.

Comment thread src/compiler/transformers/module/module.ts Outdated
var _a;
return _a = this._path, __syncRequire ? Promise.resolve().then(() => require(_a)) : new Promise((resolve_1, reject_1) => { require([_a], resolve_1, reject_1); });
var _a, _b;
return _a = this._path, __syncRequire ? (_b = _a, Promise.resolve().then(() => require(_b))) : new Promise((resolve_1, reject_1) => { require([_a], resolve_1, reject_1); });

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The additional aliasing here is unnecessary.

@Josh-Cena Josh-Cena Jul 31, 2022

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You're correct. However I'm not sure if it's possible to be fixed on a generic level, since the temp variable created from the UMD transformer may be re-assigned. I've committed the new baselines in 3baf06d with the two unnecessary aliases fixed, but there are some other places where it looks suspicious. I can't really read the output to tell if it's unsafe, so I'll appreciate if you can help to review here.

Never mind, the temp variable will never be re-assigned because it isn't leaking anywhere

var _a, _b;
const packageName = '.';
const packageJson = yield (_a = packageName + '/package.json', __syncRequire ? Promise.resolve().then(() => require(_a)) : new Promise((resolve_1, reject_1) => { require([_a], resolve_1, reject_1); }));
const packageJson = yield (_a = packageName + '/package.json', __syncRequire ? (_b = _a, Promise.resolve().then(() => require(_b))) : new Promise((resolve_1, reject_1) => { require([_a], resolve_1, reject_1); }));

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The additional aliasing here is unnecessary.

@Josh-Cena Josh-Cena requested a review from rbuckton July 31, 2022 10:10
Comment on lines +15 to +16
_a = (...["PathModule"]), Promise.resolve().then(() => require(_a));
var p1 = (_b = (...a), Promise.resolve().then(() => require(_b)));

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is invalid grammar, but the input is invalid grammar as well. I assume we can safely treat it as garbage in, garbage out?

@microsoft microsoft locked as resolved and limited conversation to collaborators Oct 22, 2025
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

For Milestone Bug PRs that fix a bug with a specific milestone

Projects

Archived in project

Development

Successfully merging this pull request may close these issues.

Missing async keyword when using import() while outputting CommonJS modules dynamic import closes over the module specifier argument

4 participants