Skip to content

Commit

Permalink
Support dynamic import in bundles. (denoland#4561)
Browse files Browse the repository at this point in the history
  • Loading branch information
kitsonk committed Apr 2, 2020
1 parent 2ff8012 commit 2e24385
Show file tree
Hide file tree
Showing 4 changed files with 69 additions and 1 deletion.
32 changes: 32 additions & 0 deletions cli/tests/integration_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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(
Expand Down
6 changes: 6 additions & 0 deletions cli/tests/subdir/subdir2/dynamic_import.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
(async (): Promise<void> => {
const { printHello } = await import("../mod2.ts");
printHello();
})();

export {};
11 changes: 11 additions & 0 deletions deno_typescript/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
21 changes: 20 additions & 1 deletion deno_typescript/system_loader.js
Original file line number Diff line number Diff line change
Expand Up @@ -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 },
};
}
Expand Down

0 comments on commit 2e24385

Please sign in to comment.