   this[kInstance] = undefined;
  }

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

    setupInstance(this, instance);

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

    validateFunction(_start, 'instance.exports._start');
    validateUndefined(_initialize, 'instance.exports._initialize');

    try {
      _start();
    } catch (err) {
      if (err !== kExitCode) {
        throw err;
      }
    }

    return this[kExitCode];
  }

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

    setupInstance(this, instance);

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

    validateUndefined(_start, 'instance.exports._start');
    if (_initialize !== undefined) {
      validateFunction(_initialize, 'instance.exports._initialize');
      _initialize();
    }
  }

  getImportObject() {
    return { [this[kBindingName]]: this.wasiImport };
  }
}

module.exports = { WASI };


function wasiReturnOnProcExit(rval) {
  // If __wasi_proc_exit() does not terminate the process, an assertion is
  // triggered in the wasm runtime. Node can sidestep the assertion and return
  // an exit code by recording the exit code, and throwing a JavaScript
  // exception that WebAssembly cannot catch.
  this[kExitCode] = rval;
  throw kExitCode;
}
