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:
parent
05e702d9f1
commit
b0f114ddb0
5
lib/internal/loader/ModuleWrap.js
Normal file
5
lib/internal/loader/ModuleWrap.js
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
// exposes ModuleWrap for testing
|
||||||
|
|
||||||
|
module.exports = internalBinding('module_wrap').ModuleWrap;
|
@ -8,6 +8,7 @@ const {
|
|||||||
getConstructorOf,
|
getConstructorOf,
|
||||||
customInspectSymbol,
|
customInspectSymbol,
|
||||||
} = require('internal/util');
|
} = require('internal/util');
|
||||||
|
const { SafePromise } = require('internal/safe_globals');
|
||||||
|
|
||||||
const {
|
const {
|
||||||
ModuleWrap,
|
ModuleWrap,
|
||||||
@ -131,27 +132,26 @@ class Module {
|
|||||||
const wrap = wrapMap.get(this);
|
const wrap = wrapMap.get(this);
|
||||||
if (wrap.getStatus() !== kUninstantiated)
|
if (wrap.getStatus() !== kUninstantiated)
|
||||||
throw new errors.Error('ERR_VM_MODULE_STATUS', 'must be uninstantiated');
|
throw new errors.Error('ERR_VM_MODULE_STATUS', 'must be uninstantiated');
|
||||||
|
|
||||||
linkingStatusMap.set(this, 'linking');
|
linkingStatusMap.set(this, 'linking');
|
||||||
const promises = [];
|
|
||||||
wrap.link((specifier) => {
|
const promises = wrap.link(async (specifier) => {
|
||||||
const p = (async () => {
|
const m = await linker(specifier, this);
|
||||||
const m = await linker(specifier, this);
|
if (!m || !wrapMap.has(m))
|
||||||
if (!m || !wrapMap.has(m))
|
throw new errors.Error('ERR_VM_MODULE_NOT_MODULE');
|
||||||
throw new errors.Error('ERR_VM_MODULE_NOT_MODULE');
|
if (m.context !== this.context)
|
||||||
if (m.context !== this.context)
|
throw new errors.Error('ERR_VM_MODULE_DIFFERENT_CONTEXT');
|
||||||
throw new errors.Error('ERR_VM_MODULE_DIFFERENT_CONTEXT');
|
const childLinkingStatus = linkingStatusMap.get(m);
|
||||||
const childLinkingStatus = linkingStatusMap.get(m);
|
if (childLinkingStatus === 'errored')
|
||||||
if (childLinkingStatus === 'errored')
|
throw new errors.Error('ERR_VM_MODULE_LINKING_ERRORED');
|
||||||
throw new errors.Error('ERR_VM_MODULE_LINKING_ERRORED');
|
if (childLinkingStatus === 'unlinked')
|
||||||
if (childLinkingStatus === 'unlinked')
|
await m.link(linker);
|
||||||
await m.link(linker);
|
return wrapMap.get(m);
|
||||||
return wrapMap.get(m);
|
|
||||||
})();
|
|
||||||
promises.push(p);
|
|
||||||
return p;
|
|
||||||
});
|
});
|
||||||
|
|
||||||
try {
|
try {
|
||||||
await Promise.all(promises);
|
if (promises !== undefined)
|
||||||
|
await SafePromise.all(promises);
|
||||||
linkingStatusMap.set(this, 'linked');
|
linkingStatusMap.set(this, 'linked');
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
linkingStatusMap.set(this, 'errored');
|
linkingStatusMap.set(this, 'errored');
|
||||||
|
1
node.gyp
1
node.gyp
@ -107,6 +107,7 @@
|
|||||||
'lib/internal/loader/DefaultResolve.js',
|
'lib/internal/loader/DefaultResolve.js',
|
||||||
'lib/internal/loader/ModuleJob.js',
|
'lib/internal/loader/ModuleJob.js',
|
||||||
'lib/internal/loader/ModuleMap.js',
|
'lib/internal/loader/ModuleMap.js',
|
||||||
|
'lib/internal/loader/ModuleWrap.js',
|
||||||
'lib/internal/loader/Translators.js',
|
'lib/internal/loader/Translators.js',
|
||||||
'lib/internal/safe_globals.js',
|
'lib/internal/safe_globals.js',
|
||||||
'lib/internal/net.js',
|
'lib/internal/net.js',
|
||||||
|
@ -209,7 +209,7 @@ void ModuleWrap::Link(const FunctionCallbackInfo<Value>& args) {
|
|||||||
Local<Promise> resolve_promise = resolve_return_value.As<Promise>();
|
Local<Promise> resolve_promise = resolve_return_value.As<Promise>();
|
||||||
obj->resolve_cache_[specifier_std].Reset(env->isolate(), resolve_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);
|
args.GetReturnValue().Set(promises);
|
||||||
|
29
test/parallel/test-internal-module-wrap.js
Normal file
29
test/parallel/test-internal-module-wrap.js
Normal 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);
|
||||||
|
})();
|
Loading…
x
Reference in New Issue
Block a user