Skip to content

Commit 65817f2

Browse files
committed
Test dynamic import() from eval/dynamic function.
1 parent 968ace2 commit 65817f2

File tree

3 files changed

+241
-0
lines changed

3 files changed

+241
-0
lines changed
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
/*
2+
* Copyright (c) 2023, 2023, Oracle and/or its affiliates. All rights reserved.
3+
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4+
*
5+
* Licensed under the Universal Permissive License v 1.0 as shown at http://oss.oracle.com/licenses/upl.
6+
*/
7+
8+
/**
9+
* Tests dynamic import via indirect eval and dynamic function.
10+
*
11+
* @option unhandled-rejections=throw
12+
*/
13+
14+
var importedUrl = './GR-38391import.mjs';
15+
16+
17+
async function basic() {
18+
await import(importedUrl);
19+
}
20+
async function directEval() {
21+
await eval("import(importedUrl)");
22+
}
23+
async function indirectEval() {
24+
await (0,eval)("import(importedUrl)");
25+
}
26+
async function dynamicFunction() {
27+
await (new Function("return import(importedUrl)"))();
28+
}
29+
[basic, directEval, indirectEval, dynamicFunction].reduce((p, f) => p.then(() => f().catch(err => {
30+
console.error(`${f.name}() => ${err}`);
31+
throw err;
32+
})), Promise.resolve());
Lines changed: 154 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,154 @@
1+
/*
2+
* Copyright (c) 2023, 2023, Oracle and/or its affiliates. All rights reserved.
3+
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4+
*
5+
* The Universal Permissive License (UPL), Version 1.0
6+
*
7+
* Subject to the condition set forth below, permission is hereby granted to any
8+
* person obtaining a copy of this software, associated documentation and/or
9+
* data (collectively the "Software"), free of charge and under any and all
10+
* copyright rights in the Software, and any and all patent rights owned or
11+
* freely licensable by each licensor hereunder covering either (i) the
12+
* unmodified Software as contributed to or provided by such licensor, or (ii)
13+
* the Larger Works (as defined below), to deal in both
14+
*
15+
* (a) the Software, and
16+
*
17+
* (b) any piece of software and/or hardware listed in the lrgrwrks.txt file if
18+
* one is included with the Software each a "Larger Work" to which the Software
19+
* is contributed by such licensors),
20+
*
21+
* without restriction, including without limitation the rights to copy, create
22+
* derivative works of, display, perform, and distribute the Software and make,
23+
* use, sell, offer for sale, import, export, have made, and have sold the
24+
* Software and the Larger Work(s), and to sublicense the foregoing rights on
25+
* either these or other terms.
26+
*
27+
* This license is subject to the following condition:
28+
*
29+
* The above copyright notice and either this complete permission notice or at a
30+
* minimum a reference to the UPL must be included in all copies or substantial
31+
* portions of the Software.
32+
*
33+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
34+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
35+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
36+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
37+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
38+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
39+
* SOFTWARE.
40+
*/
41+
42+
const assert = require('node:assert');
43+
globalThis.importedUrl = './dynamically_imported.mjs';
44+
globalThis.nonExistent = './does-not-exist.mjs';
45+
46+
describe('dynamic import', function () {
47+
48+
describe('of existing module should work', function () {
49+
it('from normal import expression', async function () {
50+
const module = await import(importedUrl);
51+
assert.strictEqual(42, module.default);
52+
});
53+
it('from direct eval', async function () {
54+
const module = await eval("import(importedUrl)");
55+
assert.strictEqual(42, module.default);
56+
});
57+
it('from indirect eval', async function () {
58+
const module = await (0,eval)("import(importedUrl)");
59+
assert.strictEqual(42, module.default);
60+
});
61+
it('from indirect eval via call method', async function () {
62+
const module = await eval.call(undefined, "import(importedUrl)");
63+
assert.strictEqual(42, module.default);
64+
});
65+
it('from dynamic function', async function () {
66+
const module = await (new Function("return import(importedUrl)"))();
67+
assert.strictEqual(42, module.default);
68+
});
69+
it('from dynamic function via Reflect.construct', async function () {
70+
const module = await Reflect.construct(Function, ["return import(importedUrl)"])();
71+
assert.strictEqual(42, module.default);
72+
});
73+
});
74+
75+
describe('of non-existent module should throw ERR_MODULE_NOT_FOUND', function () {
76+
const ERR_MODULE_NOT_FOUND = err => {
77+
assert(err instanceof Error);
78+
assert.strictEqual(err.name, 'Error');
79+
assert.strictEqual(err.code, 'ERR_MODULE_NOT_FOUND');
80+
return true;
81+
};
82+
it('from normal import expression', async function () {
83+
await assert.rejects(
84+
async () => await import(nonExistent),
85+
ERR_MODULE_NOT_FOUND
86+
);
87+
});
88+
it('from direct eval', async function () {
89+
await assert.rejects(
90+
async () => await eval("import(nonExistent)"),
91+
ERR_MODULE_NOT_FOUND
92+
);
93+
});
94+
it('from indirect eval', async function () {
95+
await assert.rejects(
96+
async () => await (0,eval)("import(nonExistent)"),
97+
ERR_MODULE_NOT_FOUND
98+
);
99+
});
100+
it('from indirect eval via call method', async function () {
101+
await assert.rejects(
102+
async () => await eval.call(undefined, "import(nonExistent)"),
103+
ERR_MODULE_NOT_FOUND
104+
);
105+
});
106+
it('from dynamic function', async function () {
107+
await assert.rejects(
108+
async () => await (new Function("return import(nonExistent)"))(),
109+
ERR_MODULE_NOT_FOUND
110+
);
111+
});
112+
it('from dynamic function via Reflect.construct', async function () {
113+
await assert.rejects(
114+
async () => await Reflect.construct(Function, ["return import(nonExistent)"])(),
115+
ERR_MODULE_NOT_FOUND
116+
);
117+
});
118+
});
119+
120+
it('should import from active script or module', async function () {
121+
function importFromScriptFunction(src) {
122+
return new Function(`return import(${JSON.stringify(src)})`);
123+
}
124+
const module = await import(importedUrl);
125+
try {
126+
await (module.importFromModuleFunction(nonExistent)());
127+
assert.fail("should have thrown");
128+
} catch (e) {
129+
assert(e.message.includes('from') && e.message.includes('imported.mjs'), e.message);
130+
}
131+
132+
try {
133+
await (module.callAsync(importFromScriptFunction(), nonExistent));
134+
assert.fail("should have thrown");
135+
} catch (e) {
136+
assert(e.message.includes('from') && !e.message.includes('imported.mjs'), e.message);
137+
}
138+
139+
try {
140+
await (module.indirectEval("import(nonExistent)"));
141+
assert.fail("should have thrown");
142+
} catch (e) {
143+
assert(e.message.includes('from') && e.message.includes('imported.mjs'), e.message);
144+
}
145+
146+
try {
147+
await (module.directEval("import(nonExistent)"));
148+
assert.fail("should have thrown");
149+
} catch (e) {
150+
assert(e.message.includes('from') && e.message.includes('imported.mjs'), e.message);
151+
}
152+
});
153+
154+
});
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
/*
2+
* Copyright (c) 2023, 2023, Oracle and/or its affiliates. All rights reserved.
3+
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4+
*
5+
* The Universal Permissive License (UPL), Version 1.0
6+
*
7+
* Subject to the condition set forth below, permission is hereby granted to any
8+
* person obtaining a copy of this software, associated documentation and/or
9+
* data (collectively the "Software"), free of charge and under any and all
10+
* copyright rights in the Software, and any and all patent rights owned or
11+
* freely licensable by each licensor hereunder covering either (i) the
12+
* unmodified Software as contributed to or provided by such licensor, or (ii)
13+
* the Larger Works (as defined below), to deal in both
14+
*
15+
* (a) the Software, and
16+
*
17+
* (b) any piece of software and/or hardware listed in the lrgrwrks.txt file if
18+
* one is included with the Software each a "Larger Work" to which the Software
19+
* is contributed by such licensors),
20+
*
21+
* without restriction, including without limitation the rights to copy, create
22+
* derivative works of, display, perform, and distribute the Software and make,
23+
* use, sell, offer for sale, import, export, have made, and have sold the
24+
* Software and the Larger Work(s), and to sublicense the foregoing rights on
25+
* either these or other terms.
26+
*
27+
* This license is subject to the following condition:
28+
*
29+
* The above copyright notice and either this complete permission notice or at a
30+
* minimum a reference to the UPL must be included in all copies or substantial
31+
* portions of the Software.
32+
*
33+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
34+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
35+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
36+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
37+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
38+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
39+
* SOFTWARE.
40+
*/
41+
42+
export default 42;
43+
44+
export function importFromModuleFunction(src) {
45+
return new Function(`return import(${JSON.stringify(src)})`);
46+
}
47+
export async function callAsync(f, ...args) {
48+
return await f(...args);
49+
};
50+
export function directEval(src) {
51+
return eval(src);
52+
};
53+
export function indirectEval(src) {
54+
return (0, eval)(src);
55+
};

0 commit comments

Comments
 (0)