From 6bd846a780bec8a60d0a251ed1fb43e3add81be5 Mon Sep 17 00:00:00 2001 From: Kitson Kelly Date: Thu, 13 Feb 2020 08:41:51 +1100 Subject: Improvements to bundling. (#3965) 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 re-exported. Fixes #2553 Fixes #3559 Fixes #3751 Fixes #3825 Refs #3301 --- deno_typescript/system_loader.js | 85 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 85 insertions(+) create mode 100644 deno_typescript/system_loader.js (limited to 'deno_typescript/system_loader.js') 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; + }; +})(); -- cgit v1.2.3