forked from denoland/deno
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathbundle_loader.js
121 lines (110 loc) · 3.19 KB
/
bundle_loader.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
// Copyright 2018-2019 the Deno authors. All rights reserved. MIT license.
// A script preamble that provides the ability to load a single outfile
// TypeScript "bundle" where a main module is loaded which recursively
// instantiates all the other modules in the bundle. This code is used to load
// bundles when creating snapshots, but is also used when emitting bundles from
// Deno cli.
// @ts-nocheck
/**
* @type {(name: string, deps: ReadonlyArray<string>, factory: (...deps: any[]) => void) => void=}
*/
// eslint-disable-next-line @typescript-eslint/no-unused-vars
let define;
/**
* @type {(mod: string) => any=}
*/
// eslint-disable-next-line @typescript-eslint/no-unused-vars
let instantiate;
/**
* @callback Factory
* @argument {...any[]} args
* @returns {object | void}
*/
/**
* @typedef ModuleMetaData
* @property {ReadonlyArray<string>} dependencies
* @property {(Factory | object)=} factory
* @property {object} exports
*/
(function() {
/**
* @type {Map<string, ModuleMetaData>}
*/
const modules = new Map();
/**
* Bundles in theory can support "dynamic" imports, but for internal bundles
* we can't go outside to fetch any modules that haven't been statically
* defined.
* @param {string[]} deps
* @param {(...deps: any[]) => void} resolve
* @param {(err: any) => void} reject
*/
const require = (deps, resolve, reject) => {
try {
if (deps.length !== 1) {
throw new TypeError("Expected only a single module specifier.");
}
if (!modules.has(deps[0])) {
throw new RangeError(`Module "${deps[0]}" not defined.`);
}
resolve(getExports(deps[0]));
} catch (e) {
if (reject) {
reject(e);
} else {
throw e;
}
}
};
define = (id, dependencies, factory) => {
if (modules.has(id)) {
throw new RangeError(`Module "${id}" has already been defined.`);
}
modules.set(id, {
dependencies,
factory,
exports: {}
});
};
/**
* @param {string} id
* @returns {any}
*/
function getExports(id) {
const module = modules.get(id);
if (!module) {
// because `$deno$/ts_global.d.ts` looks like a real script, it doesn't
// get erased from output as an import, but it doesn't get defined, so
// we don't have a cache for it, so because this is an internal bundle
// we can just safely return an empty object literal.
return {};
}
if (!module.factory) {
return module.exports;
} else if (module.factory) {
const { factory, exports } = module;
delete module.factory;
if (typeof factory === "function") {
const dependencies = module.dependencies.map(id => {
if (id === "require") {
return require;
} else if (id === "exports") {
return exports;
}
return getExports(id);
});
factory(...dependencies);
} else {
Object.assign(exports, factory);
}
return exports;
}
}
instantiate = dep => {
define = undefined;
const result = getExports(dep);
// clean up, or otherwise these end up in the runtime environment
instantiate = undefined;
return result;
};
})();