Skip to content

Commit 64d5a92

Browse files
authored
Return rejected promise when stringify import specifier throws (#15290)
Fixes #15261
1 parent 6a3421c commit 64d5a92

File tree

24 files changed

+149
-33
lines changed

24 files changed

+149
-33
lines changed

packages/babel-helper-module-transforms/src/dynamic-import.ts

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
import * as t from "@babel/types";
55
import template from "@babel/template";
66

7+
// TODO(Babel 8): Remove this
78
export function getDynamicImportSource(
89
node: t.CallExpression,
910
): t.StringLiteral | t.TemplateLiteral {
@@ -13,3 +14,49 @@ export function getDynamicImportSource(
1314
? source
1415
: (template.expression.ast`\`\${${source}}\`` as t.TemplateLiteral);
1516
}
17+
18+
export function buildDynamicImport(
19+
node: t.CallExpression,
20+
deferToThen: boolean,
21+
wrapWithPromise: boolean,
22+
builder: (specifier: t.Expression) => t.Expression,
23+
): t.Expression {
24+
const [specifier] = node.arguments;
25+
26+
if (
27+
t.isStringLiteral(specifier) ||
28+
(t.isTemplateLiteral(specifier) && specifier.quasis.length === 0)
29+
) {
30+
if (deferToThen) {
31+
return template.expression.ast`
32+
Promise.resolve().then(() => ${builder(specifier)})
33+
`;
34+
} else return builder(specifier);
35+
}
36+
37+
const specifierToString = t.isTemplateLiteral(specifier)
38+
? t.identifier("specifier")
39+
: t.templateLiteral(
40+
[t.templateElement({ raw: "" }), t.templateElement({ raw: "" })],
41+
[t.identifier("specifier")],
42+
);
43+
44+
if (deferToThen) {
45+
return template.expression.ast`
46+
(specifier =>
47+
new Promise(r => r(${specifierToString}))
48+
.then(s => ${builder(t.identifier("s"))})
49+
)(${specifier})
50+
`;
51+
} else if (wrapWithPromise) {
52+
return template.expression.ast`
53+
(specifier =>
54+
new Promise(r => r(${builder(specifierToString)}))
55+
)(${specifier})
56+
`;
57+
} else {
58+
return template.expression.ast`
59+
(specifier => ${builder(specifierToString)})(${specifier})
60+
`;
61+
}
62+
}

packages/babel-helper-module-transforms/src/index.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ import type {
3535
} from "./normalize-and-load-metadata";
3636
import type { NodePath } from "@babel/traverse";
3737

38-
export { getDynamicImportSource } from "./dynamic-import";
38+
export { buildDynamicImport, getDynamicImportSource } from "./dynamic-import";
3939

4040
export { default as getModuleName } from "./get-module-name";
4141
export type { PluginOptions } from "./get-module-name";
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
import(2);
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
define(["require"], function (_require) {
2+
(specifier => new Promise((_resolve, _reject) => _require([`${specifier}`], imported => _resolve(babelHelpers.interopRequireWildcard(imported)), _reject)))(2);
3+
});
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
module.exports = 1;
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
let x = 1;
2+
return expect(import(`./${x}.js`))
3+
.resolves.toHaveProperty("default", 1);
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
{
2+
"parserOpts": {
3+
"allowReturnOutsideFunction": true
4+
}
5+
}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
expect(() => {
2+
function f() { throw "should throw"; }
3+
import(f());
4+
}).toThrow("should throw");
5+
6+
expect(() => {
7+
const a = {
8+
get x() { throw "should throw"; },
9+
};
10+
import(a.x);
11+
}).toThrow("should throw");
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
return expect(import({
2+
[Symbol.toPrimitive](hint) {
3+
if (hint === "string") return "./foo.js";
4+
return null;
5+
}
6+
})).resolves.toHaveProperty("default", "foo");
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
module.exports = "foo";

0 commit comments

Comments
 (0)