text: // Copyright 2022 The IREE Authors
  //
  // Licensed under the Apache License v2.0 with LLVM Exceptions.
  // See https://llvm.org/LICENSE.txt for license information.
  // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  
  // TODO(scotttodd): configure this through the build system / scripts?
  // const MAIN_SCRIPT_URL = 'web-sample-dynamic-multithreaded.js';
  const MAIN_SCRIPT_URL = 'web-sample-dynamic-sync.js';
  
  let wasmSetupSampleFn;
  let wasmCleanupSampleFn;
  let wasmLoadProgramFn;
  let wasmInspectProgramFn;
  let wasmUnloadProgramFn;
  let wasmCallFunctionFn;
  
  let sampleState;
  
  var Module = {
    print: function(text) {
      console.log('(C)', text);
    },
    printErr: function(text) {
      console.error('(C)', text);
    },
    onRuntimeInitialized: function() {
      wasmSetupSampleFn = Module.cwrap('setup_sample', 'number', []);
      wasmCleanupSampleFn = Module.cwrap('cleanup_sample', null, ['number']);
      wasmLoadProgramFn =
          Module.cwrap('load_program', 'number', ['number', 'number', 'number']);
      wasmInspectProgramFn = Module.cwrap('inspect_program', null, ['number']);
      wasmUnloadProgramFn = Module.cwrap('unload_program', null, ['number']);
      wasmCallFunctionFn = Module.cwrap(
          'call_function', 'string', ['number', 'string', 'string', 'number']);
  
      sampleState = wasmSetupSampleFn();
  
      postMessage({
        'messageType': 'initialized',
      });
    },
    noInitialRun: true,
  };
  
  function loadProgramBuffer(id, programDataBuffer) {
    const programDataView = new Int8Array(programDataBuffer);
  
    const programDataWasmBuffer = Module._malloc(
        programDataView.length * programDataView.BYTES_PER_ELEMENT);
    Module.HEAP8.set(programDataView, programDataWasmBuffer);
  
    // Note: we transfer ownership of the FlatBuffer data here, so there is
    // no need to call `Module._free(programDataWasmBuffer)` later.
    const programState = wasmLoadProgramFn(
        sampleState, programDataWasmBuffer, programDataBuffer.byteLength);
  
    if (programState !== 0) {
      postMessage({
        'messageType': 'callResult',
        'id': id,
        'payload': programState,
      });
    } else {
      postMessage({
        'messageType': 'callResult',
        'id': id,
        'error': 'Wasm module error, check console for details',
      });
    }
  }
  
  function loadProgram(id, vmfbPathOrBuffer) {
    if (vmfbPathOrBuffer instanceof ArrayBuffer) {
      loadProgramBuffer(id, vmfbPathOrBuffer);
      return;
    }
  
    const fetchRequest = new XMLHttpRequest();
    fetchRequest.onload = function(progressEvent) {
      loadProgramBuffer(id, progressEvent.target.response);
    };
    fetchRequest.open('GET', vmfbPathOrBuffer);
    fetchRequest.responseType = 'arraybuffer';
    fetchRequest.send();
  }
  
  function inspectProgram(id, programState) {
    wasmInspectProgramFn(programState);
  
    postMessage({
      'messageType': 'callResult',
      'id': id,
    });
  }
  
  function unloadProgram(id, programState) {
    wasmUnloadProgramFn(programState);
  
    postMessage({
      'messageType': 'callResult',
      'id': id,
    });
  }
  
  function callFunction(id, functionParams) {
    const {programState, functionName, inputs, iterations} = functionParams;
  
    let inputsJoined;
    if (Array.isArray(inputs)) {
      inputsJoined = inputs.join(';');
    } else if (typeof (inputs) === 'string') {
      inputsJoined = inputs;
    } else {
      postMessage({
        'messageType': 'callResult',
        'id': id,
        'error': 'Expected \'inputs\' to be a String or an array of Strings',
      });
      return;
    }
  
    const returnValue =
        wasmCallFunctionFn(programState, functionName, inputsJoined, iterations);
  
    if (returnValue === '') {
      postMessage({
        'messageType': 'callResult',
        'id': id,
        'error': 'Wasm module error, check console for details',
      });
    } else {
      postMessage({
        'messageType': 'callResult',
        'id': id,
        'payload': JSON.parse(returnValue),
      });
      // TODO(scotttodd): free char* buffer? Or does Emscripten handle that?
      // Could refactor to
      //   1) return void*
      //   2) convert to String manually using UTF8ToString(pointer)
      //   3) Module._free(pointer)
    }
  }
  
  self.onmessage = function(messageEvent) {
    const {messageType, id, payload} = messageEvent.data;
  
    if (messageType == 'loadProgram') {
      loadProgram(id, payload);
    } else if (messageType == 'inspectProgram') {
      inspectProgram(id, payload);
    } else if (messageType == 'unloadProgram') {
      unloadProgram(id, payload);
    } else if (messageType == 'callFunction') {
      callFunction(id, payload);
    }
  };
  
  importScripts(MAIN_SCRIPT_URL);
  