'use strict';

const common = require('../common');
const assert = require('assert');
const { WASI } = require('wasi');
const { Worker, parentPort } = require('worker_threads');

// void _start(void) { for (;;); }
const bytecode = new Uint8Array([
  0x00, 0x61, 0x73, 0x6d, 0x01, 0x00, 0x00, 0x00, 0x01, 0x04, 0x01, 0x60,
  0x00, 0x00, 0x03, 0x02, 0x01, 0x00, 0x04, 0x05, 0x01, 0x70, 0x01, 0x01,
  0x01, 0x05, 0x03, 0x01, 0x00, 0x02, 0x06, 0x08, 0x01, 0x7f, 0x01, 0x41,
  0x80, 0x88, 0x04, 0x0b, 0x07, 0x13, 0x02, 0x06, 0x6d, 0x65, 0x6d, 0x6f,
  0x72, 0x79, 0x02, 0x00, 0x06, 0x5f, 0x73, 0x74, 0x61, 0x72, 0x74, 0x00,
  0x00, 0x0a, 0x09, 0x01, 0x07, 0x00, 0x03, 0x40, 0x0c, 0x00, 0x0b, 0x0b,
  0x00, 0x10, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x01, 0x09, 0x01, 0x00, 0x06,
  0x5f, 0x73, 0x74, 0x61, 0x72, 0x74, 0x00, 0x2f, 0x09, 0x70, 0x72, 0x6f,
  0x64, 0x75, 0x63, 0x65, 0x72, 0x73, 0x01, 0x0c, 0x70, 0x72, 0x6f, 0x63,
  0x65, 0x73, 0x73, 0x65, 0x64, 0x2d, 0x62, 0x79, 0x01, 0x05, 0x63, 0x6c,
  0x61, 0x6e, 0x67, 0x0f, 0x31, 0x30, 0x2e, 0x30, 0x2e, 0x30, 0x2d, 0x34,
  0x75, 0x62, 0x75, 0x6e, 0x74, 0x75, 0x31,
]);

// Do not use isMainThread so that this test itself can be run inside a Worker.
if (!process.env.HAS_STARTED_WORKER) {
  process.env.HAS_STARTED_WORKER = 1;
  const worker = new Worker(__filename);
  worker.once('message', (message) => {
    assert.strictEqual(message, 'start');
    setTimeout(() => worker.terminate(), common.platformTimeout(50));
  });
} else {
  go();
}

async function go() {
  const wasi = new WASI({ version: 'preview1', returnOnExit: true });
  const imports = { wasi_snapshot_preview1: wasi.wasiImport };
  const module = await WebAssembly.compile(bytecode);
  const instance = await WebAssembly.instantiate(module, imports);
  parentPort.postMessage('start');
  wasi.start(instance);
}
