Skip to content

Commit

Permalink
vm: add import assertion support
Browse files Browse the repository at this point in the history
PR-URL: #37176
Reviewed-By: Anna Henningsen <anna@addaleax.net>
Reviewed-By: Michaël Zasso <targos@protonmail.com>
  • Loading branch information
devsnek committed Mar 23, 2021
1 parent 0a77830 commit 26eed3e
Show file tree
Hide file tree
Showing 4 changed files with 40 additions and 4 deletions.
10 changes: 10 additions & 0 deletions doc/api/vm.md
Original file line number Diff line number Diff line change
Expand Up @@ -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:
<!-- eslint-skip -->
```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}
Expand Down
4 changes: 2 additions & 2 deletions lib/internal/vm/module.js
Original file line number Diff line number Diff line change
Expand Up @@ -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();
}
Expand Down
14 changes: 13 additions & 1 deletion src/module_wrap.cc
Original file line number Diff line number Diff line change
Expand Up @@ -286,8 +286,20 @@ void ModuleWrap::Link(const FunctionCallbackInfo<Value>& args) {
Utf8Value specifier_utf8(env->isolate(), specifier);
std::string specifier_std(*specifier_utf8, specifier_utf8.length());

Local<FixedArray> raw_assertions = module_request->GetImportAssertions();
Local<Object> 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<String>::Cast(raw_assertions->Get(env->context(), i)),
Local<Value>::Cast(raw_assertions->Get(env->context(), i + 1)))
.ToChecked();
}

Local<Value> argv[] = {
specifier
specifier,
assertions,
};

MaybeLocal<Value> maybe_resolve_return_value =
Expand Down
16 changes: 15 additions & 1 deletion test/parallel/test-vm-module-link.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
'use strict';

// Flags: --experimental-vm-modules
// Flags: --experimental-vm-modules --harmony-import-assertions

const common = require('../common');

Expand Down Expand Up @@ -124,12 +124,26 @@ 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() {
await simple();
await depth();
await circular();
await circular2();
await asserts();
finished();
})().then(common.mustCall());

0 comments on commit 26eed3e

Please sign in to comment.