loader: fix up #18394

This commit fixes up some issues in #18394.

* Switch vm.Module internals to use the new link method properly
* Fix bug with ModuleWrap::Link
* Add tests for ModuleWrap::Link

PR-URL: https://github.com/nodejs/node/pull/18509
Fixes: https://github.com/nodejs/node/issues/18249
Refs: https://github.com/nodejs/node/pull/18394
Reviewed-By: Tiancheng "Timothy" Gu <timothygu99@gmail.com>
This commit is contained in:
Gus Caplan 2018-02-01 09:44:27 -06:00 committed by Timothy Gu
parent 05e702d9f1
commit b0f114ddb0
No known key found for this signature in database
GPG Key ID: 7FE6B095B582B0D4
5 changed files with 54 additions and 19 deletions

View File

@ -0,0 +1,5 @@
'use strict';
// exposes ModuleWrap for testing
module.exports = internalBinding('module_wrap').ModuleWrap;

View File

@ -8,6 +8,7 @@ const {
getConstructorOf,
customInspectSymbol,
} = require('internal/util');
const { SafePromise } = require('internal/safe_globals');
const {
ModuleWrap,
@ -131,10 +132,10 @@ class Module {
const wrap = wrapMap.get(this);
if (wrap.getStatus() !== kUninstantiated)
throw new errors.Error('ERR_VM_MODULE_STATUS', 'must be uninstantiated');
linkingStatusMap.set(this, 'linking');
const promises = [];
wrap.link((specifier) => {
const p = (async () => {
const promises = wrap.link(async (specifier) => {
const m = await linker(specifier, this);
if (!m || !wrapMap.has(m))
throw new errors.Error('ERR_VM_MODULE_NOT_MODULE');
@ -146,12 +147,11 @@ class Module {
if (childLinkingStatus === 'unlinked')
await m.link(linker);
return wrapMap.get(m);
})();
promises.push(p);
return p;
});
try {
await Promise.all(promises);
if (promises !== undefined)
await SafePromise.all(promises);
linkingStatusMap.set(this, 'linked');
} catch (err) {
linkingStatusMap.set(this, 'errored');

View File

@ -107,6 +107,7 @@
'lib/internal/loader/DefaultResolve.js',
'lib/internal/loader/ModuleJob.js',
'lib/internal/loader/ModuleMap.js',
'lib/internal/loader/ModuleWrap.js',
'lib/internal/loader/Translators.js',
'lib/internal/safe_globals.js',
'lib/internal/net.js',

View File

@ -209,7 +209,7 @@ void ModuleWrap::Link(const FunctionCallbackInfo<Value>& args) {
Local<Promise> resolve_promise = resolve_return_value.As<Promise>();
obj->resolve_cache_[specifier_std].Reset(env->isolate(), resolve_promise);
promises->Set(mod_context, specifier, resolve_promise).FromJust();
promises->Set(mod_context, i, resolve_promise).FromJust();
}
args.GetReturnValue().Set(promises);

View File

@ -0,0 +1,29 @@
'use strict';
// Flags: --expose-internals
const common = require('../common');
common.crashOnUnhandledRejection();
const assert = require('assert');
const ModuleWrap = require('internal/loader/ModuleWrap');
const { getPromiseDetails, isPromise } = process.binding('util');
const setTimeoutAsync = require('util').promisify(setTimeout);
const foo = new ModuleWrap('export * from "bar"; 6;', 'foo');
const bar = new ModuleWrap('export const five = 5', 'bar');
(async () => {
const promises = foo.link(() => setTimeoutAsync(1000).then(() => bar));
assert.strictEqual(promises.length, 1);
assert(isPromise(promises[0]));
await Promise.all(promises);
assert.strictEqual(getPromiseDetails(promises[0])[1], bar);
foo.instantiate();
assert.strictEqual(await foo.evaluate(), 6);
assert.strictEqual(foo.namespace().five, 5);
})();