chromium/third_party/blink/web_tests/fast/wasm/wasm-limits-tests.js

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

const limit = Math.pow(2, 23);

const kWasmH0 = 0;
const kWasmH1 = 0x61;
const kWasmH2 = 0x73;
const kWasmH3 = 0x6d;

const kWasmV0 = 0x1;
const kWasmV1 = 0;
const kWasmV2 = 0;
const kWasmV3 = 0;

function wasmSignedLeb(val, max_len = 5) {
  if (val == null) throw new Error("Leb value many not be null/undefined");
  let res = [];
  for (let i = 0; i < max_len; ++i) {
    let v = val & 0x7f;
    // If {v} sign-extended from 7 to 32 bits is equal to val, we are done.
    if (((v << 25) >> 25) == val) {
      res.push(v);
      return res;
    }
    res.push(v | 0x80);
    val = val >> 7;
  }
  throw new Error(
      'Leb value <' + val + '> exceeds maximum length of ' + max_len);
}

function createTestBuffer(limit) {
  const buffer = new Uint8Array(limit);
  const header = [
    kWasmH0, kWasmH1, kWasmH2, kWasmH3, // magic word
    kWasmV0, kWasmV1, kWasmV2, kWasmV3, // version
    0                                   // custom section
  ];
  // We calculate the section length so that the total module size is `limit`.
  // For that we have to calculate the length of the leb encoding of the section
  // length.
  const sectionLength = limit - header.length -
      wasmSignedLeb(limit).length;
  const lengthBytes = wasmSignedLeb(sectionLength);
  buffer.set(header);
  buffer.set(lengthBytes, header.length);
  return buffer;
}

function NoParameters() {
  assert_throws_js(TypeError, () => new WebAssembly.Module());
  assert_throws_js(TypeError, () => new WebAssembly.Module("a"));
  assert_throws_js(TypeError, () => new WebAssembly.Instance());
  assert_throws_js(TypeError, () => new WebAssembly.Instance("a"));
}

function NoParameters_Promise() {
  function ExpectTypeError(f) {
    return f().then(assert_unreached, e => assert_true(e instanceof TypeError));
  }
  return Promise.all([
    ExpectTypeError(() => WebAssembly.compile()),
    ExpectTypeError(() => WebAssembly.compile("a")),
    ExpectTypeError(() => WebAssembly.instantiate()),
    ExpectTypeError(() => WebAssembly.instantiate("a"))
  ]);
}

function TestSyncCompile() {
  assert_true(new WebAssembly.Module(createTestBuffer(limit))
              instanceof WebAssembly.Module);
  assert_throws_js(
      RangeError, () => new WebAssembly.Module(createTestBuffer(limit + 1)));
}

function TestPromiseCompile() {
  return WebAssembly.compile(createTestBuffer(limit + 1))
    .then(m => assert_true(m instanceof WebAssembly.Module));
}

function WorkerCode() {
  onmessage = (event) => {
    const buffer = event.data;
    try {
      let module = new WebAssembly.Module(buffer);
      let instance = new WebAssembly.Instance(module);
      postMessage(
          module instanceof WebAssembly.Module &&
          instance instanceof WebAssembly.Instance);
    } catch (e) {
      postMessage(false);
    }
  }
}

function TestWorkerCompileAndInstantiate() {
  const workerBlob = new Blob(['(', WorkerCode.toString(), ')()']);
  const blobUrl = blobURL = URL.createObjectURL(
      workerBlob, {type: 'application/javascript; charset=utf-8'});
  const worker = new Worker(blobUrl);
  return new Promise((resolve, reject) => {
    worker.postMessage(createTestBuffer(limit + 1));
    worker.onmessage = function(event) {
      resolve(event.data);
    }
  })
    .then(ans => assert_true(ans),
          assert_unreached);
}

function TestPromiseCompileSyncInstantiate() {
  return WebAssembly.compile(createTestBuffer(limit + 1))
      .then(
          m => assert_throws_js(RangeError, () => new WebAssembly.Instance(m)));
}

function TestPromiseCompileAsyncInstantiateFromBuffer() {
  return WebAssembly.instantiate(createTestBuffer(limit + 1))
    .then(i => assert_true(i.instance instanceof WebAssembly.Instance),
          assert_unreached);
}

function TestPromiseCompileAsyncInstantiateFromModule() {
  return WebAssembly.compile(createTestBuffer(limit + 1)).then(m => {
    assert_true(m instanceof WebAssembly.Module);
    return WebAssembly.instantiate(m).then(
        i => assert_true(i instanceof WebAssembly.Instance), assert_unreached);
  }, assert_unreached);
}


function TestCompileFromPromise() {
  return Promise.resolve(createTestBuffer(limit + 1))
    .then(WebAssembly.compile)
    .then(m => assert_true(m instanceof WebAssembly.Module))
}

function TestInstantiateFromPromise() {
  return Promise.resolve(createTestBuffer(limit + 1))
    .then(WebAssembly.instantiate)
    .then(pair => {
      assert_true(pair.module instanceof WebAssembly.Module);
      assert_true(pair.instance instanceof WebAssembly.Instance);
    });
}

function TestInstantiateFromPromiseChain() {
  return Promise.resolve(createTestBuffer(limit + 1))
    .then(WebAssembly.compile)
    .then(WebAssembly.instantiate)
    .then(i => assert_true(i instanceof WebAssembly.Instance))
}