|
1 | 1 | 'use strict';
|
2 | 2 |
|
3 | 3 | const {
|
| 4 | +Array, |
4 | 5 | ArrayJoin,
|
5 |
| -ArrayPush, |
6 | 6 | ArraySome,
|
7 | 7 | Function,
|
8 | 8 | ObjectSetOf,
|
@@ -82,31 +82,8 @@ class ModuleJob extends ModuleJobBase {
|
82 | 82 | this.modulePromise = PromiseResolve(this.modulePromise);
|
83 | 83 | }
|
84 | 84 |
|
85 |
| -// Wait for the ModuleWrap instance being linked with all dependencies. |
86 |
| -const link = async () => { |
87 |
| -this.module = await this.modulePromise; |
88 |
| -assert(this.module instanceof ModuleWrap); |
89 |
| - |
90 |
| -// Explicitly keeping track of dependency jobs is needed in order |
91 |
| -// to flatten out the dependency graph below in `_instantiate()`, |
92 |
| -// so that circular dependencies can't cause a deadlock by two of |
93 |
| -// these `link` callbacks depending on each other. |
94 |
| -const dependencyJobs = []; |
95 |
| -const promises = this.module.link(async (specifier, attributes) => { |
96 |
| -const job = await this.#loader.getModuleJob(specifier, url, attributes); |
97 |
| -debug(`async link() ${this.url} -> ${specifier}`, job); |
98 |
| -ArrayPush(dependencyJobs, job); |
99 |
| -return job.modulePromise; |
100 |
| -}); |
101 |
| - |
102 |
| -if (promises !== undefined) { |
103 |
| -await SafePromiseAllReturnVoid(promises); |
104 |
| -} |
105 |
| - |
106 |
| -return SafePromiseAllReturnArrayLike(dependencyJobs); |
107 |
| -}; |
108 | 85 | // Promise for the list of all dependencyJobs.
|
109 |
| -this.linked = link(); |
| 86 | +this.linked = this._link(); |
110 | 87 | // This promise is awaited later anyway, so silence
|
111 | 88 | // 'unhandled rejection' warnings.
|
112 | 89 | PromiseThen(this.linked, undefined, noop);
|
@@ -116,6 +93,49 @@ class ModuleJob extends ModuleJobBase {
|
116 | 93 | this.instantiated = undefined;
|
117 | 94 | }
|
118 | 95 |
|
| 96 | +/** |
| 97 | +* Iterates the module requests and links with the loader. |
| 98 | +* @returns {Promise<ModuleJob[]>} Dependency module jobs. |
| 99 | +*/ |
| 100 | +async _link() { |
| 101 | +this.module = await this.modulePromise; |
| 102 | +assert(this.module instanceof ModuleWrap); |
| 103 | + |
| 104 | +const moduleRequests = this.module.getModuleRequests(); |
| 105 | +// Explicitly keeping track of dependency jobs is needed in order |
| 106 | +// to flatten out the dependency graph below in `_instantiate()`, |
| 107 | +// so that circular dependencies can't cause a deadlock by two of |
| 108 | +// these `link` callbacks depending on each other. |
| 109 | +// Create an ArrayLike to avoid calling into userspace with `.then` |
| 110 | +// when returned from the async function. |
| 111 | +const dependencyJobs = Array(moduleRequests.length); |
| 112 | +ObjectSetOf(dependencyJobs, null); |
| 113 | + |
| 114 | +// Specifiers should be aligned with the moduleRequests array in order. |
| 115 | +const specifiers = Array(moduleRequests.length); |
| 116 | +const modulePromises = Array(moduleRequests.length); |
| 117 | +// Iterate with index to avoid calling into userspace with `Symbol.iterator`. |
| 118 | +for (let idx = 0; idx < moduleRequests.length; idx++) { |
| 119 | +const { specifier, attributes } = moduleRequests[idx]; |
| 120 | + |
| 121 | +const dependencyJobPromise = this.#loader.getModuleJob( |
| 122 | +specifier, this.url, attributes, |
| 123 | +); |
| 124 | +const modulePromise = PromiseThen(dependencyJobPromise, (job) => { |
| 125 | +debug(`async link() ${this.url} -> ${specifier}`, job); |
| 126 | +dependencyJobs[idx] = job; |
| 127 | +return job.modulePromise; |
| 128 | +}); |
| 129 | +modulePromises[idx] = modulePromise; |
| 130 | +specifiers[idx] = specifier; |
| 131 | +} |
| 132 | + |
| 133 | +const modules = await SafePromiseAllReturnArrayLike(modulePromises); |
| 134 | +this.module.link(specifiers, modules); |
| 135 | + |
| 136 | +return dependencyJobs; |
| 137 | +} |
| 138 | + |
119 | 139 | instantiate() {
|
120 | 140 | if (this.instantiated === undefined) {
|
121 | 141 | this.instantiated = this._instantiate();
|
@@ -269,18 +289,20 @@ class ModuleJobSync extends ModuleJobBase {
|
269 | 289 | super(url, importAttributes, moduleWrap, isMain, inspectBrk, true);
|
270 | 290 | assert(this.module instanceof ModuleWrap);
|
271 | 291 | this.#loader = loader;
|
272 |
| -const moduleRequests = this.module.getModuleRequestsSync(); |
273 |
| -const linked = []; |
| 292 | +const moduleRequests = this.module.getModuleRequests(); |
| 293 | +// Specifiers should be aligned with the moduleRequests array in order. |
| 294 | +const specifiers = Array(moduleRequests.length); |
| 295 | +const modules = Array(moduleRequests.length); |
| 296 | +const jobs = Array(moduleRequests.length); |
274 | 297 | for (let i = 0; i < moduleRequests.length; ++i) {
|
275 |
| -const { 0: specifier, 1: attributes } = moduleRequests[i]; |
276 |
| -const job = this.#loader.getModuleWrapForRequire(specifier, url, attributes); |
277 |
| -const isLast = (i === moduleRequests.length - 1); |
278 |
| -// TODO(joyeecheung): make the resolution callback deal with both promisified |
279 |
| -// an raw module wraps, then we don't need to wrap it with a promise here. |
280 |
| -this.module.cacheResolvedWrapsSync(specifier, PromiseResolve(job.module), isLast); |
281 |
| -ArrayPush(linked, job); |
| 298 | +const { specifier, attributes } = moduleRequests[i]; |
| 299 | +const job = this.#loader.getModuleJobForRequire(specifier, url, attributes); |
| 300 | +specifiers[i] = specifier; |
| 301 | +modules[i] = job.module; |
| 302 | +jobs[i] = job; |
282 | 303 | }
|
283 |
| -this.linked = linked; |
| 304 | +this.module.link(specifiers, modules); |
| 305 | +this.linked = jobs; |
284 | 306 | }
|
285 | 307 |
|
286 | 308 | get modulePromise() {
|
|
0 commit comments