Created
January 15, 2018 20:35
-
-
Save TimothyGu/301c233d02acbca1d335f1a3d65eb79c to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
diff --git a/lib/internal/vm/Module.js b/lib/internal/vm/Module.js | |
index c7f90a83a3..806c7ae20f 100644 | |
--- a/lib/internal/vm/Module.js | |
+++ b/lib/internal/vm/Module.js | |
@@ -32,6 +32,7 @@ const perContextModuleId = new WeakMap(); | |
const wrapMap = new WeakMap(); | |
const dependencyCacheMap = new WeakMap(); | |
const linkingStatusMap = new WeakMap(); | |
+const linkingStatusDeferredMap = new WeakMap(); | |
class Module { | |
constructor(src, options = {}) { | |
@@ -78,12 +79,25 @@ class Module { | |
columnOffset: options.columnOffset | |
}); | |
+ let linkedPromiseResolve; | |
+ let linkedPromiseReject; | |
+ const linkedPromise = new Promise((resolve, reject) => { | |
+ linkedPromiseResolve = resolve; | |
+ linkedPromiseReject = reject; | |
+ }); | |
+ linkingStatusDeferredMap.set(this, { | |
+ promise: linkedPromise, | |
+ resolve: linkedPromiseResolve, | |
+ reject: linkedPromiseReject | |
+ }); | |
+ | |
wrapMap.set(this, wrap); | |
linkingStatusMap.set(this, 'unlinked'); | |
Object.defineProperties(this, { | |
url: { value: url, enumerable: true }, | |
context: { value: context, enumerable: true }, | |
+ linked: { value: linkedPromise, enumerable: true }, | |
}); | |
} | |
@@ -137,21 +151,30 @@ class Module { | |
const m = await linker(this, specifier); | |
if (!m || !wrapMap.has(m)) | |
throw new errors.Error('ERR_VM_MODULE_NOT_MODULE'); | |
- if (linkingStatusMap.get(m) === 'unlinked') | |
- throw new errors.Error('ERR_VM_MODULE_NOT_LINKED', 'to be used in linking'); | |
if (m.context !== this.context) | |
throw new errors.Error('ERR_VM_MODULE_DIFFERENT_CONTEXT'); | |
+ const childLinkingStatus = linkingStatusMap.get(m); | |
+ if (childLinkingStatus !== 'linked') { | |
+ if (childLinkingStatus === 'unlinked') { | |
+ m.link(linker); | |
+ } | |
+ await linkingStatusDeferredMap.get(m).promise; | |
+ } | |
return wrapMap.get(m); | |
})(); | |
promises.push(p); | |
return p; | |
}); | |
+ const deferred = linkingStatusDeferredMap.get(this); | |
try { | |
await Promise.all(promises); | |
+ deferred.resolve(); | |
linkingStatusMap.set(this, 'linked'); | |
} catch (err) { | |
+ deferred.reject(err); | |
linkingStatusMap.set(this, 'errored'); | |
- throw err; | |
+ } finally { | |
+ return deferred.promise; | |
} | |
} | |
diff --git a/test/parallel/test-vm-module-errors.js b/test/parallel/test-vm-module-errors.js | |
index db10919bec..82cf6240c6 100644 | |
--- a/test/parallel/test-vm-module-errors.js | |
+++ b/test/parallel/test-vm-module-errors.js | |
@@ -196,12 +196,12 @@ async function checkLinking() { | |
code: 'ERR_VM_MODULE_DIFFERENT_CONTEXT' | |
})); | |
- await rejects(async () => { | |
- const m = new Module('import "foo";'); | |
- await m.link(common.mustCall(() => new Module(''))); | |
- }, common.expectsError({ | |
- code: 'ERR_VM_MODULE_NOT_LINKED' | |
- })); | |
+ // await rejects(async () => { | |
+ // const m = new Module('import "foo";'); | |
+ // await m.link(common.mustCall(() => new Module(''))); | |
+ // }, common.expectsError({ | |
+ // code: 'ERR_VM_MODULE_NOT_LINKED' | |
+ // })); | |
} | |
// Check the JavaScript engine deals with exceptions correctly | |
diff --git a/test/parallel/test-vm-module-link.js b/test/parallel/test-vm-module-link.js | |
index d45b4a2dc7..601e40266f 100644 | |
--- a/test/parallel/test-vm-module-link.js | |
+++ b/test/parallel/test-vm-module-link.js | |
@@ -1,11 +1,12 @@ | |
'use strict'; | |
-// Flags: --vm-modules | |
+// Flags: --experimental-modules | |
const common = require('../common'); | |
common.crashOnUnhandledRejection(); | |
const assert = require('assert'); | |
+const { URL } = require('url'); | |
const { Module } = require('vm'); | |
@@ -83,10 +84,62 @@ async function circular() { | |
foo.instantiate(); | |
await foo.evaluate(); | |
assert.strictEqual(foo.namespace.default, 42); | |
+ console.log('here'); | |
} | |
-(async function main() { | |
- await simple(); | |
- await depth(); | |
- await circular(); | |
-}()); | |
+async function circular2() { | |
+ const sourceMap = { | |
+ root: ` | |
+ import * as a from './a.mjs'; | |
+ // import * as b from './b.mjs'; | |
+ if (!(fromA in a)) | |
+ throw new Error(); | |
+ if (!(fromB in a)) | |
+ throw new Error(); | |
+ if (!(fromA in b)) | |
+ throw new Error(); | |
+ if (!(fromB in b)) | |
+ throw new Error(); | |
+ console.log('made it to the end'); | |
+ `, | |
+ './a.mjs': ` | |
+ export * from './b.mjs'; | |
+ export var fromA; | |
+ `, | |
+ './b.mjs': ` | |
+ export * from './a.mjs'; | |
+ export var fromB; | |
+ ` | |
+ }; | |
+ const moduleMap = new Map(); | |
+ const rootModule = new Module(sourceMap.root, { url: 'vm:root' }); | |
+ async function link(referencingModule, specifier) { | |
+ if (moduleMap.has(specifier)) { | |
+ return moduleMap.get(specifier); | |
+ } | |
+ const mod = new Module(sourceMap[specifier], { url: new URL(specifier, 'file:///').href }); | |
+ moduleMap.set(specifier, mod); | |
+ return mod; | |
+ } | |
+ console.log('bleh'); | |
+ const prom = rootModule.link(link); | |
+ console.log(prom); | |
+ await prom; | |
+ console.log(prom); | |
+ console.log('here'); | |
+ rootModule.instantiate(); | |
+ console.log('here'); | |
+ await rootModule.evaluate(); | |
+ console.log('there'); | |
+} | |
+ | |
+circular(); | |
+// circular2(); | |
+ | |
+// (async function main() { | |
+// await simple(); | |
+// await depth(); | |
+// await circular(); | |
+// await circular2(); | |
+// }()); | |
+ |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment