Skip to content

Commit 3031ac1

Browse files
committed
Improvements to bundling.
Moves to using a minimal System loader for bundles generated by Deno. TypeScript in 3.8 will be able to output TLA for modules, and the loader is written to take advantage of that as soon as we update Deno to TS 3.8. System also allows us to support `import.meta` and provide more ESM aligned assignment of exports, as well as there is better handling of circular imports. The loader is also very terse versus to try to save overhead. Also, fixed an issue where abstract classes were not being rexported. Fixes denoland#2553 Fixes denoland#3559 Fixes denoland#3751 Fixes denoland#3825 Refs denoland#3301
1 parent 83d59b8 commit 3031ac1

File tree

7 files changed

+112
-25
lines changed

7 files changed

+112
-25
lines changed

cli/js/compiler_api_test.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -78,15 +78,15 @@ test(async function bundleApiSources() {
7878
"/bar.ts": `export const bar = "bar";\n`
7979
});
8080
assert(diagnostics == null);
81-
assert(actual.includes(`instantiate("foo")`));
82-
assert(actual.includes(`__rootExports["bar"]`));
81+
assert(actual.includes(`__inst("foo")`));
82+
assert(actual.includes(`__exp["bar"]`));
8383
});
8484

8585
test(async function bundleApiNoSources() {
8686
const [diagnostics, actual] = await bundle("./cli/tests/subdir/mod1.ts");
8787
assert(diagnostics == null);
88-
assert(actual.includes(`instantiate("mod1")`));
89-
assert(actual.includes(`__rootExports["printHello3"]`));
88+
assert(actual.includes(`__inst("mod1")`));
89+
assert(actual.includes(`__exp["printHello3"]`));
9090
});
9191

9292
test(async function bundleApiConfig() {

cli/js/compiler_bootstrap.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,4 +49,4 @@ export const TS_SNAPSHOT_PROGRAM = ts.createProgram({
4949
* We read all static assets during the snapshotting process, which is
5050
* why this is located in compiler_bootstrap.
5151
*/
52-
export const BUNDLE_LOADER = getAsset("bundle_loader.js");
52+
export const SYSTEM_LOADER = getAsset("system_loader.js");

cli/js/compiler_bundler.ts

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
// Copyright 2018-2020 the Deno authors. All rights reserved. MIT license.
22

3-
import { BUNDLE_LOADER } from "./compiler_bootstrap.ts";
3+
import { SYSTEM_LOADER } from "./compiler_bootstrap.ts";
44
import {
55
assert,
66
commonPath,
@@ -44,18 +44,18 @@ export function buildBundle(
4444
.replace(/\.\w+$/i, "");
4545
let instantiate: string;
4646
if (rootExports && rootExports.length) {
47-
instantiate = `const __rootExports = instantiate("${rootName}");\n`;
47+
instantiate = `const __exp = await __inst("${rootName}");\n`;
4848
for (const rootExport of rootExports) {
4949
if (rootExport === "default") {
50-
instantiate += `export default __rootExports["${rootExport}"];\n`;
50+
instantiate += `export default __exp["${rootExport}"];\n`;
5151
} else {
52-
instantiate += `export const ${rootExport} = __rootExports["${rootExport}"];\n`;
52+
instantiate += `export const ${rootExport} = __exp["${rootExport}"];\n`;
5353
}
5454
}
5555
} else {
56-
instantiate = `instantiate("${rootName}");\n`;
56+
instantiate = `await __inst("${rootName}");\n`;
5757
}
58-
return `${BUNDLE_LOADER}\n${data}\n${instantiate}`;
58+
return `${SYSTEM_LOADER}\n${data}\n${instantiate}`;
5959
}
6060

6161
/** Set the rootExports which will by the `emitBundle()` */
@@ -80,6 +80,7 @@ export function setRootExports(program: ts.Program, rootModule: string): void {
8080
// out, so inspecting SymbolFlags that might be present that are type only
8181
.filter(
8282
sym =>
83+
sym.flags & ts.SymbolFlags.Class ||
8384
!(
8485
sym.flags & ts.SymbolFlags.Interface ||
8586
sym.flags & ts.SymbolFlags.TypeLiteral ||

cli/js/compiler_host.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ export interface ConfigureResponse {
3838
* runtime). */
3939
export const defaultBundlerOptions: ts.CompilerOptions = {
4040
inlineSourceMap: false,
41-
module: ts.ModuleKind.AMD,
41+
module: ts.ModuleKind.System,
4242
outDir: undefined,
4343
outFile: `${OUT_DIR}/bundle.js`,
4444
// disabled until we have effective way to modify source maps

cli/tests/bundle.test.out

Lines changed: 14 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,24 @@
11
[WILDCARD]
2-
let define;
2+
let System;
3+
let __inst;
34
[WILDCARD]
4-
let instantiate;
5-
[WILDCARD]
6-
(function() {
5+
(() => {
76
[WILDCARD]
87
})();
98

10-
define("print_hello", ["require", "exports"], function (require, exports) {
9+
System.register("print_hello", [], function (exports_1, context_1) {
1110
[WILDCARD]
1211
});
13-
define("mod1", ["require", "exports", "subdir2/mod2"], function (require, exports, mod2_ts_1) {
12+
System.register("subdir2/mod2", ["print_hello"], function (exports_2, context_2) {
13+
[WILDCARD]
14+
});
15+
System.register("mod1", ["subdir2/mod2"], function (exports_3, context_3) {
1416
[WILDCARD]
1517
});
1618

17-
const __rootExports = instantiate("mod1");
18-
export const returnsHi = __rootExports["returnsHi"];
19-
export const returnsFoo2 = __rootExports["returnsFoo2"];
20-
export const printHello3 = __rootExports["printHello3"];
21-
export const throwsError = __rootExports["throwsError"];
22-
19+
const __exp = await __inst("mod1");
20+
export const returnsHi = __exp["returnsHi"];
21+
export const returnsFoo2 = __exp["returnsFoo2"];
22+
export const printHello3 = __exp["printHello3"];
23+
export const throwsError = __exp["throwsError"];
24+
[WILDCARD]

deno_typescript/lib.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -245,7 +245,7 @@ pub fn get_asset(name: &str) -> Option<&'static str> {
245245
};
246246
}
247247
match name {
248-
"bundle_loader.js" => Some(include_str!("bundle_loader.js")),
248+
"system_loader.js" => Some(include_str!("system_loader.js")),
249249
"bootstrap.ts" => Some("console.log(\"hello deno\");"),
250250
"typescript.d.ts" => inc!("typescript.d.ts"),
251251
"lib.esnext.d.ts" => inc!("lib.esnext.d.ts"),

deno_typescript/system_loader.js

Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
// Copyright 2018-2020 the Deno authors. All rights reserved. MIT license.
2+
3+
// This is a specialised implementation of a System module loader.
4+
5+
let System;
6+
let __inst;
7+
8+
(() => {
9+
const mMap = new Map();
10+
System = {
11+
register(id, deps, f) {
12+
mMap.set(id, {
13+
id,
14+
deps,
15+
f,
16+
exp: {}
17+
});
18+
}
19+
};
20+
21+
const gC = (data, main) => {
22+
const { id } = data;
23+
return {
24+
id,
25+
import: async id => mMap.get(id)?.exp,
26+
meta: { url: id, main }
27+
};
28+
};
29+
30+
const gE = data => {
31+
const { exp } = data;
32+
return (id, value) => {
33+
const values = typeof id === "string" ? { [id]: value } : id;
34+
for (const [id, value] of Object.entries(values)) {
35+
Object.defineProperty(exp, id, {
36+
value,
37+
writable: true,
38+
enumerable: true
39+
});
40+
}
41+
};
42+
};
43+
44+
const iQ = [];
45+
46+
const enq = ids => {
47+
for (const id of ids) {
48+
if (!iQ.includes(id)) {
49+
const { deps } = mMap.get(id);
50+
iQ.push(id);
51+
enq(deps);
52+
}
53+
}
54+
};
55+
56+
const dr = async main => {
57+
const rQ = [];
58+
let id;
59+
while ((id = iQ.pop())) {
60+
const m = mMap.get(id);
61+
const { f } = m;
62+
if (!f) {
63+
return;
64+
}
65+
rQ.push([m.deps, f(gE(m), gC(m, id === main))]);
66+
m.f = undefined;
67+
}
68+
let r;
69+
while ((r = rQ.shift())) {
70+
const [deps, { execute, setters }] = r;
71+
for (let i = 0; i < deps.length; i++) setters[i](mMap.get(deps[i])?.exp);
72+
const e = execute();
73+
if (e) await e;
74+
}
75+
};
76+
77+
__inst = async id => {
78+
System = undefined;
79+
__inst = undefined;
80+
enq([id]);
81+
await dr(id);
82+
return mMap.get(id)?.exp;
83+
};
84+
})();

0 commit comments

Comments
 (0)