summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--cli/js/compiler_api_test.ts8
-rw-r--r--cli/js/compiler_bootstrap.ts2
-rw-r--r--cli/js/compiler_bundler.ts13
-rw-r--r--cli/js/compiler_host.ts2
-rw-r--r--cli/tests/bundle.test.out26
-rw-r--r--cli/tests/integration_tests.rs34
-rw-r--r--cli/tests/subdir/circular1.ts7
-rw-r--r--cli/tests/subdir/circular2.ts7
-rw-r--r--deno_typescript/lib.rs2
-rw-r--r--deno_typescript/system_loader.js85
10 files changed, 161 insertions, 25 deletions
diff --git a/cli/js/compiler_api_test.ts b/cli/js/compiler_api_test.ts
index 72b65ab5d..eef12c8cc 100644
--- a/cli/js/compiler_api_test.ts
+++ b/cli/js/compiler_api_test.ts
@@ -78,15 +78,15 @@ test(async function bundleApiSources() {
"/bar.ts": `export const bar = "bar";\n`
});
assert(diagnostics == null);
- assert(actual.includes(`instantiate("foo")`));
- assert(actual.includes(`__rootExports["bar"]`));
+ assert(actual.includes(`__inst("foo")`));
+ assert(actual.includes(`__exp["bar"]`));
});
test(async function bundleApiNoSources() {
const [diagnostics, actual] = await bundle("./cli/tests/subdir/mod1.ts");
assert(diagnostics == null);
- assert(actual.includes(`instantiate("mod1")`));
- assert(actual.includes(`__rootExports["printHello3"]`));
+ assert(actual.includes(`__inst("mod1")`));
+ assert(actual.includes(`__exp["printHello3"]`));
});
test(async function bundleApiConfig() {
diff --git a/cli/js/compiler_bootstrap.ts b/cli/js/compiler_bootstrap.ts
index 585aec016..817486d12 100644
--- a/cli/js/compiler_bootstrap.ts
+++ b/cli/js/compiler_bootstrap.ts
@@ -55,4 +55,4 @@ export const TS_SNAPSHOT_PROGRAM = ts.createProgram({
* We read all static assets during the snapshotting process, which is
* why this is located in compiler_bootstrap.
*/
-export const BUNDLE_LOADER = getAsset("bundle_loader.js");
+export const SYSTEM_LOADER = getAsset("system_loader.js");
diff --git a/cli/js/compiler_bundler.ts b/cli/js/compiler_bundler.ts
index d334b0fc3..b9893620a 100644
--- a/cli/js/compiler_bundler.ts
+++ b/cli/js/compiler_bundler.ts
@@ -1,6 +1,6 @@
// Copyright 2018-2020 the Deno authors. All rights reserved. MIT license.
-import { BUNDLE_LOADER } from "./compiler_bootstrap.ts";
+import { SYSTEM_LOADER } from "./compiler_bootstrap.ts";
import {
assert,
commonPath,
@@ -44,18 +44,18 @@ export function buildBundle(
.replace(/\.\w+$/i, "");
let instantiate: string;
if (rootExports && rootExports.length) {
- instantiate = `const __rootExports = instantiate("${rootName}");\n`;
+ instantiate = `const __exp = await __inst("${rootName}");\n`;
for (const rootExport of rootExports) {
if (rootExport === "default") {
- instantiate += `export default __rootExports["${rootExport}"];\n`;
+ instantiate += `export default __exp["${rootExport}"];\n`;
} else {
- instantiate += `export const ${rootExport} = __rootExports["${rootExport}"];\n`;
+ instantiate += `export const ${rootExport} = __exp["${rootExport}"];\n`;
}
}
} else {
- instantiate = `instantiate("${rootName}");\n`;
+ instantiate = `await __inst("${rootName}");\n`;
}
- return `${BUNDLE_LOADER}\n${data}\n${instantiate}`;
+ return `${SYSTEM_LOADER}\n${data}\n${instantiate}`;
}
/** Set the rootExports which will by the `emitBundle()` */
@@ -80,6 +80,7 @@ export function setRootExports(program: ts.Program, rootModule: string): void {
// out, so inspecting SymbolFlags that might be present that are type only
.filter(
sym =>
+ sym.flags & ts.SymbolFlags.Class ||
!(
sym.flags & ts.SymbolFlags.Interface ||
sym.flags & ts.SymbolFlags.TypeLiteral ||
diff --git a/cli/js/compiler_host.ts b/cli/js/compiler_host.ts
index 291f6fbc5..0f6aa4d08 100644
--- a/cli/js/compiler_host.ts
+++ b/cli/js/compiler_host.ts
@@ -34,7 +34,7 @@ export const ASSETS = "$asset$";
* runtime). */
export const defaultBundlerOptions: ts.CompilerOptions = {
inlineSourceMap: false,
- module: ts.ModuleKind.AMD,
+ module: ts.ModuleKind.System,
outDir: undefined,
outFile: `${OUT_DIR}/bundle.js`,
// disabled until we have effective way to modify source maps
diff --git a/cli/tests/bundle.test.out b/cli/tests/bundle.test.out
index 23b7de35e..1379eb7e5 100644
--- a/cli/tests/bundle.test.out
+++ b/cli/tests/bundle.test.out
@@ -1,22 +1,24 @@
[WILDCARD]
-let define;
+let System;
+let __inst;
[WILDCARD]
-let instantiate;
-[WILDCARD]
-(function() {
+(() => {
[WILDCARD]
})();
-define("print_hello", ["require", "exports"], function (require, exports) {
+System.register("print_hello", [], function (exports_1, context_1) {
[WILDCARD]
});
-define("mod1", ["require", "exports", "subdir2/mod2"], function (require, exports, mod2_ts_1) {
+System.register("subdir2/mod2", ["print_hello"], function (exports_2, context_2) {
+[WILDCARD]
+});
+System.register("mod1", ["subdir2/mod2"], function (exports_3, context_3) {
[WILDCARD]
});
-const __rootExports = instantiate("mod1");
-export const returnsHi = __rootExports["returnsHi"];
-export const returnsFoo2 = __rootExports["returnsFoo2"];
-export const printHello3 = __rootExports["printHello3"];
-export const throwsError = __rootExports["throwsError"];
-
+const __exp = await __inst("mod1");
+export const returnsHi = __exp["returnsHi"];
+export const returnsFoo2 = __exp["returnsFoo2"];
+export const printHello3 = __exp["printHello3"];
+export const throwsError = __exp["throwsError"];
+[WILDCARD]
diff --git a/cli/tests/integration_tests.rs b/cli/tests/integration_tests.rs
index 013e4c41b..a41fdd032 100644
--- a/cli/tests/integration_tests.rs
+++ b/cli/tests/integration_tests.rs
@@ -252,6 +252,40 @@ fn bundle_exports() {
assert_eq!(output.stderr, b"");
}
+#[test]
+fn bundle_circular() {
+ use tempfile::TempDir;
+
+ // First we have to generate a bundle of some module that has exports.
+ let circular1 = util::root_path().join("cli/tests/subdir/circular1.ts");
+ assert!(circular1.is_file());
+ let t = TempDir::new().expect("tempdir fail");
+ let bundle = t.path().join("circular1.bundle.js");
+ let mut deno = util::deno_cmd()
+ .current_dir(util::root_path())
+ .arg("bundle")
+ .arg(circular1)
+ .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 the bundle program.
+ assert!(std::str::from_utf8(&output.stdout)
+ .unwrap()
+ .trim()
+ .ends_with("f1\nf2"));
+ assert_eq!(output.stderr, b"");
+}
+
// TODO(#2933): Rewrite this test in rust.
#[test]
fn repl_test() {
diff --git a/cli/tests/subdir/circular1.ts b/cli/tests/subdir/circular1.ts
new file mode 100644
index 000000000..f9054338f
--- /dev/null
+++ b/cli/tests/subdir/circular1.ts
@@ -0,0 +1,7 @@
+import * as circular2 from "./circular2.ts";
+
+export function f1(): void {
+ console.log("f1");
+}
+
+circular2.f2();
diff --git a/cli/tests/subdir/circular2.ts b/cli/tests/subdir/circular2.ts
new file mode 100644
index 000000000..a96ffb13d
--- /dev/null
+++ b/cli/tests/subdir/circular2.ts
@@ -0,0 +1,7 @@
+import * as circular1 from "./circular1.ts";
+
+export function f2(): void {
+ console.log("f2");
+}
+
+circular1.f1();
diff --git a/deno_typescript/lib.rs b/deno_typescript/lib.rs
index 7977b7cfe..9056fd903 100644
--- a/deno_typescript/lib.rs
+++ b/deno_typescript/lib.rs
@@ -245,7 +245,7 @@ pub fn get_asset(name: &str) -> Option<&'static str> {
};
}
match name {
- "bundle_loader.js" => Some(include_str!("bundle_loader.js")),
+ "system_loader.js" => Some(include_str!("system_loader.js")),
"bootstrap.ts" => Some("console.log(\"hello deno\");"),
"typescript.d.ts" => inc!("typescript.d.ts"),
"lib.esnext.d.ts" => inc!("lib.esnext.d.ts"),
diff --git a/deno_typescript/system_loader.js b/deno_typescript/system_loader.js
new file mode 100644
index 000000000..c1365f6c8
--- /dev/null
+++ b/deno_typescript/system_loader.js
@@ -0,0 +1,85 @@
+// Copyright 2018-2020 the Deno authors. All rights reserved. MIT license.
+
+// This is a specialised implementation of a System module loader.
+
+// eslint-disable-next-line @typescript-eslint/no-unused-vars
+let System;
+let __inst;
+
+(() => {
+ const mMap = new Map();
+ System = {
+ register(id, deps, f) {
+ mMap.set(id, {
+ id,
+ deps,
+ f,
+ exp: {}
+ });
+ }
+ };
+
+ const gC = (data, main) => {
+ const { id } = data;
+ return {
+ id,
+ import: async id => mMap.get(id)?.exp,
+ meta: { url: id, main }
+ };
+ };
+
+ const gE = data => {
+ const { exp } = data;
+ return (id, value) => {
+ const values = typeof id === "string" ? { [id]: value } : id;
+ for (const [id, value] of Object.entries(values)) {
+ Object.defineProperty(exp, id, {
+ value,
+ writable: true,
+ enumerable: true
+ });
+ }
+ };
+ };
+
+ const iQ = [];
+
+ const enq = ids => {
+ for (const id of ids) {
+ if (!iQ.includes(id)) {
+ const { deps } = mMap.get(id);
+ iQ.push(id);
+ enq(deps);
+ }
+ }
+ };
+
+ const dr = async main => {
+ const rQ = [];
+ let id;
+ while ((id = iQ.pop())) {
+ const m = mMap.get(id);
+ const { f } = m;
+ if (!f) {
+ return;
+ }
+ rQ.push([m.deps, f(gE(m), gC(m, id === main))]);
+ m.f = undefined;
+ }
+ let r;
+ while ((r = rQ.shift())) {
+ const [deps, { execute, setters }] = r;
+ for (let i = 0; i < deps.length; i++) setters[i](mMap.get(deps[i])?.exp);
+ const e = execute();
+ if (e) await e;
+ }
+ };
+
+ __inst = async id => {
+ System = undefined;
+ __inst = undefined;
+ enq([id]);
+ await dr(id);
+ return mMap.get(id)?.exp;
+ };
+})();