From 26eed3e0edc9bcfe40de2ad5f21218fddbcec173 Mon Sep 17 00:00:00 2001 From: Gus Caplan Date: Mon, 1 Feb 2021 16:21:23 -0600 Subject: [PATCH] vm: add import assertion support MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit PR-URL: https://github.com/nodejs/node/pull/37176 Reviewed-By: Anna Henningsen Reviewed-By: Michaƫl Zasso --- doc/api/vm.md | 10 ++++++++++ lib/internal/vm/module.js | 4 ++-- src/module_wrap.cc | 14 +++++++++++++- test/parallel/test-vm-module-link.js | 16 +++++++++++++++- 4 files changed, 40 insertions(+), 4 deletions(-) diff --git a/doc/api/vm.md b/doc/api/vm.md index 6c9c6e43d5eca8..ec3237adfb2ec3 100644 --- a/doc/api/vm.md +++ b/doc/api/vm.md @@ -617,6 +617,16 @@ The identifier of the current module, as set in the constructor. import foo from 'foo'; // ^^^^^ the module specifier ``` + * `extra` {Object} + * `assert` {Object} The data from the assertion: + + ```js + import foo from 'foo' assert { name: 'value' }; + // ^^^^^^^^^^^^^^^^^ the assertion + ``` + Per ECMA-262, hosts are expected to ignore assertions that they do not + support, as opposed to, for example, triggering an error if an + unsupported assertion is present. * `referencingModule` {vm.Module} The `Module` object `link()` is called on. * Returns: {vm.Module|Promise} diff --git a/lib/internal/vm/module.js b/lib/internal/vm/module.js index 3052d21e1a42fe..911b8f4426e586 100644 --- a/lib/internal/vm/module.js +++ b/lib/internal/vm/module.js @@ -308,8 +308,8 @@ class SourceTextModule extends Module { this[kLink] = async (linker) => { this.#statusOverride = 'linking'; - const promises = this[kWrap].link(async (identifier) => { - const module = await linker(identifier, this); + const promises = this[kWrap].link(async (identifier, assert) => { + const module = await linker(identifier, this, { assert }); if (module[kWrap] === undefined) { throw new ERR_VM_MODULE_NOT_MODULE(); } diff --git a/src/module_wrap.cc b/src/module_wrap.cc index d33cb19b3dcead..ed48c0bc5f45a9 100644 --- a/src/module_wrap.cc +++ b/src/module_wrap.cc @@ -286,8 +286,20 @@ void ModuleWrap::Link(const FunctionCallbackInfo& args) { Utf8Value specifier_utf8(env->isolate(), specifier); std::string specifier_std(*specifier_utf8, specifier_utf8.length()); + Local raw_assertions = module_request->GetImportAssertions(); + Local assertions = + Object::New(isolate, v8::Null(env->isolate()), nullptr, nullptr, 0); + for (int i = 0; i < raw_assertions->Length(); i += 3) { + assertions + ->Set(env->context(), + Local::Cast(raw_assertions->Get(env->context(), i)), + Local::Cast(raw_assertions->Get(env->context(), i + 1))) + .ToChecked(); + } + Local argv[] = { - specifier + specifier, + assertions, }; MaybeLocal maybe_resolve_return_value = diff --git a/test/parallel/test-vm-module-link.js b/test/parallel/test-vm-module-link.js index 39520bcf8e6891..9805d8fe3eee9c 100644 --- a/test/parallel/test-vm-module-link.js +++ b/test/parallel/test-vm-module-link.js @@ -1,6 +1,6 @@ 'use strict'; -// Flags: --experimental-vm-modules +// Flags: --experimental-vm-modules --harmony-import-assertions const common = require('../common'); @@ -124,6 +124,19 @@ async function circular2() { await rootModule.evaluate(); } +async function asserts() { + const m = new SourceTextModule(` + import "foo" assert { n1: 'v1', n2: 'v2' }; + `, { identifier: 'm' }); + await m.link((s, r, p) => { + assert.strictEqual(s, 'foo'); + assert.strictEqual(r.identifier, 'm'); + assert.strictEqual(p.assert.n1, 'v1'); + assert.strictEqual(p.assert.n2, 'v2'); + return new SourceTextModule(''); + }); +} + const finished = common.mustCall(); (async function main() { @@ -131,5 +144,6 @@ const finished = common.mustCall(); await depth(); await circular(); await circular2(); + await asserts(); finished(); })().then(common.mustCall());