chromium/third_party/blink/web_tests/http/tests/origin_trials/webexposed/resources/wasm-exceptions-origin-trial.js

// Copyright 2021 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

// Build a WebAssembly module which uses exception-features.
function createBuilderWithExceptions() {
  let builder = new WasmModuleBuilder();
  let except = builder.addException(kSig_v_v);
  builder.addFunction("simple_throw_catch_to_0_1", kSig_i_i)
      .addBody([
        kExprTry, kWasmI32,
          kExprLocalGet, 0,
          kExprI32Eqz,
          kExprIf, kWasmStmt,
            kExprThrow, except,
          kExprEnd,
          kExprI32Const, 42,
        kExprCatch, except,
          kExprI32Const, 23,
        kExprEnd
      ]).exportFunc();
  return builder;
}

// Starts the function provided by blobURL on a worker and checks that the data
// the worker sends with postMessage is 'true'.
function testModuleCompilationOnWorker(blobURL) {
  let resolve;
  // Create a promise which fulfills when the worker finishes.
  let promise = new Promise(function(res, rej) {
    resolve = res;
  });

  let worker = new Worker(blobURL);
  worker.addEventListener('message', e => resolve(e.data));

  // Send the module bytes to the worker, because the worker does not have
  // access to the WasmModuleBuilder.
  worker.postMessage(createBuilderWithExceptions().toBuffer());

  return promise.then(result => assert_true(result));
}

// Test that WebAssembly exceptions are disabled and a WebAssembly module which
// uses exceptions cannot be compiled.
function testWasmExceptionsDisabled() {
  // If WebAssembly exceptions are enabled even without origin trial token, then
  // we do not run this test.
  if (window.internals.runtimeFlags.webAssemblyExceptionsEnabled)
    return;

  try {
    // Compiling the WebAssembly bytes should throw a CompileError.
    createBuilderWithExceptions().toModule();
    assert_unreachable();
  } catch (e) {
    assert_true(e instanceof WebAssembly.CompileError);
  }
}

function testWasmExceptionsDisabledOnWorker() {
  // If WebAssembly exceptions are enabled even without origin trial token, then
  // we do not run this test.
  if (window.internals.runtimeFlags.webAssemblyExceptionsEnabled) {
    return Promise.resolve();
  }

  const blobURL = URL.createObjectURL(new Blob(
      [
        '(',
        function() {
          self.addEventListener('message', data => {
            try {
              // Compiling the WebAssembly bytes should throw a CompileError.
              new WebAssembly.Module(data.data);
              self.postMessage(false);
            } catch (e) {
              self.postMessage(e instanceof WebAssembly.CompileError);
            }
          });
        }.toString(),
        ')()'
      ],
      {type: 'application/javascript'}));

  return testModuleCompilationOnWorker(blobURL);
}

function testWasmExceptionsEnabled() {
  const module = createBuilderWithExceptions().toModule();
  assert_not_equals(module, undefined);
  assert_true(module instanceof WebAssembly.Module);
}

function testWasmExceptionsEnabledOnWorker() {
  let blobURL = URL.createObjectURL(new Blob(
      [
        '(',
        function() {
          self.addEventListener('message', data => {
            try {
              const module = new WebAssembly.Module(data.data);
              self.postMessage(module !== undefined);
            } catch (e) {
              console.log(e);
              self.postMessage(false);
            }
          });
        }.toString(),
        ')()'
      ],
      {type: 'application/javascript'}));

  return testModuleCompilationOnWorker(blobURL);
}

function testWasmExceptionConstructorEnabled() {
  assert_not_equals(WebAssembly.Exception, undefined);
}

function testWasmExceptionConstructorDisabled() {
  // If WebAssembly exceptions are enabled even without origin trial token, then
  // we do not run this test.
  if (window.internals.runtimeFlags.webAssemblyExceptionsEnabled)
    return;

  assert_equals(WebAssembly.Exception, undefined);
}

function testWasmExceptionConstructorEnabledOnWorker() {
  let blobURL = URL.createObjectURL(new Blob(
      [
        '(',
        function() {
          self.addEventListener('message', data => {
            self.postMessage(WebAssembly.Exception !== undefined);
          });
        }.toString(),
        ')()'
      ],
      {type: 'application/javascript'}));

  return testModuleCompilationOnWorker(blobURL);
}

function testWasmExceptionConstructorDisabledOnWorker() {
  // If WebAssembly exceptions are enabled even without origin trial token, then
  // we do not run this test.
  if (window.internals.runtimeFlags.webAssemblyExceptionsEnabled) {
    return Promise.resolve();
  }

  let blobURL = URL.createObjectURL(new Blob(
      [
        '(',
        function() {
          self.addEventListener('message', data => {
            self.postMessage(WebAssembly.Exception === undefined);
          });
        }.toString(),
        ')()'
      ],
      {type: 'application/javascript'}));

  return testModuleCompilationOnWorker(blobURL);
}