Skip to content

lib: expose setupInstance method on WASI class #57214

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 3 commits into
base: main
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
37 changes: 24 additions & 13 deletions lib/wasi.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,16 @@ const {
ObjectEntries,
String,
Symbol,
globalThis,
} = primordials;
const {
WebAssembly,
} = globalThis;

const {
ERR_INVALID_ARG_VALUE,
ERR_WASI_ALREADY_STARTED,
ERR_INVALID_ARG_TYPE,
} = require('internal/errors').codes;
const {
emitExperimentalWarning,
Expand All @@ -34,15 +39,6 @@ const kBindingName = Symbol('kBindingName');

emitExperimentalWarning('WASI');


function setupInstance(self, instance) {
validateObject(instance, 'instance');
validateObject(instance.exports, 'instance.exports');

self[kInstance] = instance;
self[kSetMemory](instance.exports.memory);
}

class WASI {
constructor(options = kEmptyObject) {
validateObject(options, 'options');
Expand Down Expand Up @@ -118,14 +114,30 @@ class WASI {
this[kInstance] = undefined;
}

setupInstance(instance, memory) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This works great, I'd just make two suggestions - changing the name to setupBindings() or finalizeBindings() and having a { memory } object for extensibility as the second argument.

  1. Formally speaking, we are not setting up the instance here, rather we are setting up the WASI host bindings themselves, closing the loop on the deferred instance bindings being passed back to WASI. Therefore I think setupBindings(), finalizeBindings() or finalizeWASI() or something like that might make more sense as a name than setupInstance().
  2. Right now we just want to bind memory, but in theory there might be benefit in future binding other things like tables or function registrations from the instance. To give some flexibility it would help to have setupBindings(instance, { memory = instance.exports.memory } = {}) as the signature.

Otherwise the overall approach seems great to me though.

validateObject(instance, 'instance');
validateObject(instance.exports, 'instance.exports');
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should also move the if (this[kStarted]) throw new ERR_WASI_ALREADY_STARTED() error here as we should't allow this to be called twice.


if (memory != null) {
if (!(memory instanceof WebAssembly.Memory)) {
throw new ERR_INVALID_ARG_TYPE('memory', 'WebAssembly.Memory', memory);
}
this[kSetMemory](memory);
} else {
this[kSetMemory](instance.exports.memory);
}

this[kInstance] = instance;
this[kStarted] = true;
}

// Must not export _initialize, must export _start
start(instance) {
if (this[kStarted]) {
throw new ERR_WASI_ALREADY_STARTED();
}
this[kStarted] = true;

setupInstance(this, instance);
this.setupInstance(instance);

const { _start, _initialize } = this[kInstance].exports;

Expand All @@ -148,9 +160,8 @@ class WASI {
if (this[kStarted]) {
throw new ERR_WASI_ALREADY_STARTED();
}
this[kStarted] = true;

setupInstance(this, instance);
this.setupInstance(instance);

const { _start, _initialize } = this[kInstance].exports;

Expand Down
Loading