Skip to content

Instantly share code, notes, and snippets.

@TimothyGu
Created January 15, 2018 20:35
Show Gist options
  • Save TimothyGu/301c233d02acbca1d335f1a3d65eb79c to your computer and use it in GitHub Desktop.
Save TimothyGu/301c233d02acbca1d335f1a3d65eb79c to your computer and use it in GitHub Desktop.
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