Support dynamic import in bundles. (#4561)

This commit is contained in:
Kitson Kelly 2020-04-02 14:14:30 +11:00 committed by GitHub
parent 2ff8012dcc
commit 2e24385c48
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 69 additions and 1 deletions

View File

@ -490,6 +490,38 @@ fn bundle_js() {
assert_eq!(output.stderr, b"");
}
#[test]
fn bundle_dynamic_import() {
let dynamic_import =
util::root_path().join("cli/tests/subdir/subdir2/dynamic_import.ts");
assert!(dynamic_import.is_file());
let t = TempDir::new().expect("tempdir fail");
let bundle = t.path().join("dynamic_import.bundle.js");
let mut deno = util::deno_cmd()
.current_dir(util::root_path())
.arg("bundle")
.arg(dynamic_import)
.arg(&bundle)
.spawn()
.expect("failed to spawn script");
let status = deno.wait().expect("failed to wait for the child process");
assert!(status.success());
assert!(bundle.is_file());
let output = util::deno_cmd()
.current_dir(util::root_path())
.arg("run")
.arg(&bundle)
.output()
.expect("failed to spawn script");
// check the output of the test.ts program.
assert!(std::str::from_utf8(&output.stdout)
.unwrap()
.trim()
.ends_with("Hello"));
assert_eq!(output.stderr, b"");
}
#[test]
fn repl_test_console_log() {
let (out, err) = util::run_and_collect_output(

View File

@ -0,0 +1,6 @@
(async (): Promise<void> => {
const { printHello } = await import("../mod2.ts");
printHello();
})();
export {};

View File

@ -34,6 +34,17 @@ module specifier, a reference to the dynamic `import()` and the equivalent of
and its value, or an object record of keys of the named exports and the values
of the exports.
Currently, TypeScript does not re-write dynamic imports which resolve to static
strings (see
[microsoft/TypeScript#37429](https://github.com/microsoft/TypeScript/issues/37429)),
which means the import specifier for a dynamic import which has been
incorporated in the bundle does not automatically match a module specifier that
has been registered in the bundle. The `di()` function provides the capability
to try to identify relative import specifiers and resolve them to a specifier
inside the bundle. If it does this, it resolves with the exports of the module,
otherwise it simply passes the module specifier to `import()` and returns the
resulting promise.
The running of the factories is handled by `rF()`. When the factory is run, it
returns an object with two keys, `execute` and `setters`. `execute` is a
function which finalises that instantiation of the module, and `setters` which

View File

@ -15,10 +15,29 @@ let System, __instantiateAsync, __instantiate;
},
};
async function dI(mid, src) {
let id = mid.replace(/\.\w+$/i, "");
if (id.includes("./")) {
const [o, ...ia] = id.split("/").reverse(),
[, ...sa] = src.split("/").reverse(),
oa = [o];
let s = 0,
i;
while ((i = ia.shift())) {
if (i === "..") s++;
else if (i === ".") break;
else oa.push(i);
}
if (s < sa.length) oa.push(...sa.slice(s));
id = oa.reverse().join("/");
}
return r.has(id) ? gExpA(id) : import(mid);
}
function gC(id, main) {
return {
id,
import: async (id) => r.get(id)?.exp,
import: (m) => dI(m, id),
meta: { url: id, main },
};
}