exceptions-shared.js 5.64 KB
Newer Older
1 2 3 4 5 6
// Copyright 2018 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

// Flags: --expose-wasm --experimental-wasm-eh

7
d8.file.execute("test/mjsunit/wasm/wasm-module-builder.js");
8 9 10 11 12

// Helper function to return a new exported exception with the {kSig_v_v} type
// signature from an anonymous module. The underlying module is thrown away.
function NewExportedException() {
  let builder = new WasmModuleBuilder();
13 14
  let except = builder.addTag(kSig_v_v);
  builder.addExportOfKind("ex", kExternalTag, except);
15 16 17 18 19 20 21 22 23 24 25
  let instance = builder.instantiate();
  return instance.exports.ex;
}

// Check that an instance matches an exception thrown by itself, even when the
// exception is re-thrown by a regular JavaScript function.
(function TestSingleInstance() {
  print(arguments.callee.name);
  let builder = new WasmModuleBuilder();
  let sig_index = builder.addType(kSig_v_v);
  let fun = builder.addImport("m", "f", sig_index);
26
  let except = builder.addTag(kSig_v_v);
27 28 29 30 31 32
  builder.addFunction("throw", kSig_v_v)
      .addBody([
        kExprThrow, except
      ]).exportFunc();
  builder.addFunction("catch", kSig_v_v)
      .addBody([
33
        kExprTry, kWasmVoid,
34
          kExprCallFunction, fun,
35
        kExprCatch, except,
36 37 38 39 40
        kExprEnd,
      ]).exportFunc();
  let ex_obj = new Error("my exception");
  let instance = builder.instantiate({ m: { f: function() { throw ex_obj }}});

41
  assertThrows(() => instance.exports.throw(), WebAssembly.Exception);
42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57
  assertThrowsEquals(() => instance.exports.catch(), ex_obj);
  try {
    instance.exports.throw();
  } catch (e) {
    ex_obj = e;
  }
  assertDoesNotThrow(() => instance.exports.catch());
})();

// Check that two instances distinguish their individual exceptions if they are
// not shared, even when declared by the same underlying module.
(function TestMultiInstanceNonShared() {
  print(arguments.callee.name);
  let builder = new WasmModuleBuilder();
  let sig_index = builder.addType(kSig_v_v);
  let fun = builder.addImport("m", "f", sig_index);
58
  let except = builder.addTag(kSig_v_v);
59 60 61 62 63 64
  builder.addFunction("throw", kSig_v_v)
      .addBody([
        kExprThrow, except
      ]).exportFunc();
  builder.addFunction("catch", kSig_v_v)
      .addBody([
65
        kExprTry, kWasmVoid,
66
          kExprCallFunction, fun,
67
        kExprCatch, except,
68 69 70 71 72 73
        kExprEnd,
      ]).exportFunc();
  let ex_obj = new Error("my exception");
  let instance1 = builder.instantiate({ m: { f: assertUnreachable }});
  let instance2 = builder.instantiate({ m: { f: function() { throw ex_obj }}});

74
  assertThrows(() => instance1.exports.throw(), WebAssembly.Exception);
75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90
  assertThrowsEquals(() => instance2.exports.catch(), ex_obj);
  try {
    instance1.exports.throw();
  } catch (e) {
    ex_obj = e;
  }
  assertThrowsEquals(() => instance2.exports.catch(), ex_obj);
})();

// Check that two instances match their exceptions if they are shared properly,
// even if the local exception index of export and import is different.
(function TestMultiInstanceShared() {
  print(arguments.callee.name);
  let builder = new WasmModuleBuilder();
  let sig_index = builder.addType(kSig_v_v);
  let fun = builder.addImport("m", "f", sig_index);
91 92 93
  let except1 = builder.addImportedTag("m", "ex1", kSig_v_v);
  let except2 = builder.addTag(kSig_v_v);
  builder.addExportOfKind("ex2", kExternalTag, except2);
94 95 96 97 98 99
  builder.addFunction("throw", kSig_v_v)
      .addBody([
        kExprThrow, except2
      ]).exportFunc();
  builder.addFunction("catch", kSig_v_v)
      .addBody([
100
        kExprTry, kWasmVoid,
101
          kExprCallFunction, fun,
102
        kExprCatch, except1,
103 104 105 106 107 108 109 110
        kExprEnd,
      ]).exportFunc();
  let ex_obj = new Error("my exception");
  let instance1 = builder.instantiate({ m: { f: assertUnreachable,
                                             ex1: NewExportedException() }});
  let instance2 = builder.instantiate({ m: { f: function() { throw ex_obj },
                                             ex1: instance1.exports.ex2 }});

111
  assertThrows(() => instance1.exports.throw(), WebAssembly.Exception);
112 113 114 115 116 117 118 119 120 121 122 123 124 125
  assertThrowsEquals(() => instance2.exports.catch(), ex_obj);
  try {
    instance1.exports.throw();
  } catch (e) {
    ex_obj = e;
  }
  assertDoesNotThrow(() => instance2.exports.catch());
})();

// Check that two instances based on different modules match their exceptions if
// they are shared properly, even if the local exception index is different.
(function TestMultiModuleShared() {
  print(arguments.callee.name);
  let builder1 = new WasmModuleBuilder();
126 127 128
  let except1 = builder1.addTag(kSig_v_v);
  let except2 = builder1.addTag(kSig_v_v);
  builder1.addExportOfKind("ex", kExternalTag, except2);
129 130 131 132 133 134 135
  builder1.addFunction("throw", kSig_v_v)
      .addBody([
        kExprThrow, except2
      ]).exportFunc();
  let builder2 = new WasmModuleBuilder();
  let sig_index = builder2.addType(kSig_v_v);
  let fun = builder2.addImport("m", "f", sig_index);
136
  let except = builder2.addImportedTag("m", "ex", kSig_v_v);
137 138
  builder2.addFunction("catch", kSig_v_v)
      .addBody([
139
        kExprTry, kWasmVoid,
140
          kExprCallFunction, fun,
141
        kExprCatch, except,
142 143 144 145 146 147 148
        kExprEnd,
      ]).exportFunc();
  let ex_obj = new Error("my exception");
  let instance1 = builder1.instantiate();
  let instance2 = builder2.instantiate({ m: { f: function() { throw ex_obj },
                                              ex: instance1.exports.ex }});

149
  assertThrows(() => instance1.exports.throw(), WebAssembly.Exception);
150 151 152 153 154 155 156 157
  assertThrowsEquals(() => instance2.exports.catch(), ex_obj);
  try {
    instance1.exports.throw();
  } catch (e) {
    ex_obj = e;
  }
  assertDoesNotThrow(() => instance2.exports.catch());
})();