api.js 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449
  1. //-------------------------------------------------------------------------------------------------------
  2. // Copyright (C) Microsoft Corporation and contributors. All rights reserved.
  3. // Licensed under the MIT license. See LICENSE.txt file in the project root for full license information.
  4. //-------------------------------------------------------------------------------------------------------
  5. let verbose = false;
  6. let doInvalid = true;
  7. const buf = readbuffer("binaries/api.wasm");
  8. const imports = {
  9. test: {
  10. fn() {return 1;},
  11. fn2() {return 2.14;},
  12. memory: new WebAssembly.Memory({initial: 1, maximum: 1}),
  13. g1: 45,
  14. g2: -8,
  15. },
  16. table: {"": new WebAssembly.Table({element: "anyfunc", initial: 30, maximum: 100})}
  17. };
  18. function overrideImports(overrides) {
  19. return {
  20. test: Object.assign({}, imports.test, overrides),
  21. table: overrides.table ? {"":overrides.table} : imports.table
  22. };
  23. }
  24. function objectToString(o, maxDepth = 5, depth = 0) {
  25. if (depth >= maxDepth) {
  26. return o.toString();
  27. }
  28. if (Array.isArray(o)) {
  29. return `[${o.map(e => objectToString(e, maxDepth, depth + 1)).join(", ")}]`;
  30. } else if (typeof o === "object") {
  31. return `{${Object.keys(o).map(k => `"${k}":"${objectToString(o[k], maxDepth, depth + 1)}"`).join(", ")}}`;
  32. }
  33. return o.toString();
  34. }
  35. function test(module, {exports} = {}) {
  36. if (module) {
  37. console.log("Testing module");
  38. console.log("exports");
  39. console.log(objectToString(WebAssembly.Module.exports(module)));
  40. console.log("imports");
  41. console.log(objectToString(WebAssembly.Module.imports(module)));
  42. }
  43. if (exports) {
  44. console.log("Testing instance");
  45. console.log(`f1: ${exports.f1()}`);
  46. console.log(`fn: ${exports.fn()}`);
  47. console.log(`fn2: ${exports.fn2()}`);
  48. console.log(`g1: ${exports.g1}`);
  49. console.log(`g2: ${exports.g2}`);
  50. console.log(`g3: ${exports.g3}`);
  51. }
  52. }
  53. async function testInvalidCases(tests) {
  54. if (!doInvalid) return;
  55. let i = 0;
  56. for (const testCase of tests) {
  57. if (verbose) {
  58. console.log(testCase);
  59. }
  60. try {
  61. await testCase();
  62. console.log(`Test ${i++} failed. Should have thrown error`);
  63. } catch (e) {
  64. console.log(`Test ${i++} passed. Expected Error: ${e}`);
  65. }
  66. }
  67. }
  68. function createView(bytes) {
  69. const buffer = new ArrayBuffer(bytes.length);
  70. const view = new Uint8Array(buffer);
  71. for (let i = 0; i < bytes.length; ++i) {
  72. view[i] = bytes.charCodeAt(i);
  73. }
  74. return view;
  75. }
  76. const invalidBuffers = [
  77. ,
  78. "",
  79. "123",
  80. 4568,
  81. {},
  82. {length: 15},
  83. function() {},
  84. new ArrayBuffer(),
  85. createView("\x00\x61\x73\x6d\x01\x00\x00\x00\x01\x85\x80\x80"),
  86. new Proxy(buf, {get(target, name) {return target[name];}}),
  87. ];
  88. const invalidImports = [
  89. ,
  90. "",
  91. 123,
  92. function() {},
  93. {wrongNamespace: imports.test, table: imports.table},
  94. ];
  95. const invalidModules = [
  96. null,
  97. "123",
  98. {},
  99. new Proxy({}, {})
  100. ];
  101. async function testValidate() {
  102. console.log("\nWebAssembly.validate tests");
  103. await testInvalidCases([
  104. // Invalid buffer source
  105. ...(invalidBuffers.map(b => () => {
  106. if (!WebAssembly.validate(b)) {
  107. throw new Error("Buffer source is the right type, but doesn't validate");
  108. }
  109. })),
  110. ]);
  111. // Make sure empty buffer doesn't validate and doesn't throw
  112. const emptyBuffer = new ArrayBuffer();
  113. console.log(`WebAssembly.validate(new ArrayBuffer()) = ${WebAssembly.validate(emptyBuffer)}`);
  114. console.log(`WebAssembly.validate(new Uint8Array(emptyBuffer)) = ${WebAssembly.validate(new Uint8Array(emptyBuffer))}`);
  115. console.log(`api.wasm valid: ${WebAssembly.validate(buf)}`);
  116. }
  117. async function testCompile() {
  118. console.log("\nWebAssembly.compile tests");
  119. await testInvalidCases([
  120. ...(invalidBuffers.map(b => () => WebAssembly.compile(b))),
  121. ]);
  122. const module = await WebAssembly.compile(buf);
  123. test(module);
  124. }
  125. async function testInstantiate(baseModule) {
  126. console.log("\nWebAssembly.instantiate tests");
  127. await testInvalidCases([
  128. // Invalid buffer source
  129. ...(invalidBuffers.map(b => () => WebAssembly.instantiate(b))),
  130. // Invalid Imports
  131. ...(invalidImports.map(i => () => WebAssembly.instantiate(buf, i))),
  132. ...(invalidImports.map(i => () => WebAssembly.instantiate(baseModule, i))),
  133. ]);
  134. const {module, instance} = await WebAssembly.instantiate(buf, imports);
  135. test(module, instance);
  136. const instance2 = await WebAssembly.instantiate(baseModule, imports);
  137. test(baseModule, instance2);
  138. }
  139. async function testModuleConstructor() {
  140. console.log("\nnew WebAssembly.Module tests");
  141. await testInvalidCases([
  142. () => WebAssembly.Module(),
  143. () => WebAssembly.Module(buf),
  144. ...(invalidBuffers.map(b => () => new WebAssembly.Module(b))),
  145. ]);
  146. const module = new WebAssembly.Module(buf);
  147. test(module);
  148. }
  149. async function testModuleApi() {
  150. console.log("\nWebAssembly.Module api tests");
  151. console.log("\nWebAssembly.Module.exports invalid tests");
  152. await testInvalidCases([
  153. ...(invalidModules.map(b => () => WebAssembly.Module.exports(b))),
  154. ]);
  155. console.log("\nWebAssembly.Module.imports invalid tests");
  156. await testInvalidCases([
  157. ...(invalidModules.map(b => () => WebAssembly.Module.imports(b))),
  158. ]);
  159. }
  160. async function testModuleCustomSection(baseModule) {
  161. console.log("\nWebAssembly.Module.customSections tests");
  162. await testInvalidCases([
  163. ...(invalidModules.map(b => () => WebAssembly.Module.customSections(b))),
  164. () => WebAssembly.Module.customSections(baseModule, {toString() {throw new Error("Doesn't support toString");}}),
  165. () => WebAssembly.Module.customSections(baseModule, Symbol()),
  166. ]);
  167. const baseSections = WebAssembly.Module.customSections(baseModule, "");
  168. if (!Array.isArray(baseSections) || baseSections.length !== 0) {
  169. console.log("Invalid result for WebAssembly.Module.customSections");
  170. console.log(baseSections);
  171. }
  172. let passed = 0, failed = 0;
  173. function compare(module, customSectionName, expected) {
  174. const sections = WebAssembly.Module.customSections(module, customSectionName);
  175. if (sections.length !== expected.length) {
  176. console.log(`Invalid length. Got ${sections.length}, expected ${expected.length}. ${(new Error()).stack}`);
  177. ++failed;
  178. return;
  179. }
  180. let asExpected = true;
  181. for (let iSection = 0; iSection < sections.length; ++iSection) {
  182. const resBuffer = sections[iSection];
  183. const expectedStr = expected[iSection];
  184. const view = new Uint8Array(resBuffer);
  185. let resStr = "";
  186. for (let i = 0; i < view.length; ++i) {
  187. resStr += String.fromCharCode(view[i]);
  188. }
  189. if (resStr !== expectedStr) {
  190. asExpected = false;
  191. console.log(`Invalid buffer result. Got ${resStr}, expected ${expectedStr}. ${(new Error()).stack}`);
  192. }
  193. }
  194. passed += asExpected;
  195. failed += !asExpected;
  196. }
  197. // See wasts/custom_section.wast for reference
  198. const module1 = new WebAssembly.Module(createView("\x00\x61\x73\x6d\x01\x00\x00\x00\x00\x24\x10\x61\x20\x63\x75\x73\x74\x6f\x6d\x20\x73\x65\x63\x74\x69\x6f\x6e\x74\x68\x69\x73\x20\x69\x73\x20\x74\x68\x65\x20\x70\x61\x79\x6c\x6f\x61\x64\x00\x20\x10\x61\x20\x63\x75\x73\x74\x6f\x6d\x20\x73\x65\x63\x74\x69\x6f\x6e\x74\x68\x69\x73\x20\x69\x73\x20\x70\x61\x79\x6c\x6f\x61\x64\x00\x11\x10\x61\x20\x63\x75\x73\x74\x6f\x6d\x20\x73\x65\x63\x74\x69\x6f\x6e\x00\x10\x00\x74\x68\x69\x73\x20\x69\x73\x20\x70\x61\x79\x6c\x6f\x61\x64\x00\x01\x00\x00\x24\x10\x00\x00\x63\x75\x73\x74\x6f\x6d\x20\x73\x65\x63\x74\x69\x6f\x00\x74\x68\x69\x73\x20\x69\x73\x20\x74\x68\x65\x20\x70\x61\x79\x6c\x6f\x61\x64"));
  199. compare(module1, "a custom section", [
  200. "this is the payload",
  201. "this is payload",
  202. "",
  203. ]);
  204. compare(module1, "", [
  205. "this is payload",
  206. "",
  207. ]);
  208. compare(module1, "\00\00custom sectio\00", [
  209. "this is the payload",
  210. ]);
  211. const module2 = new WebAssembly.Module(createView("\x00\x61\x73\x6d\x01\x00\x00\x00\x00\x0e\x06\x63\x75\x73\x74\x6f\x6d\x70\x61\x79\x6c\x6f\x61\x64\x00\x0e\x06\x63\x75\x73\x74\x6f\x6d\x70\x61\x79\x6c\x6f\x61\x64\x01\x01\x00\x00\x0e\x06\x63\x75\x73\x74\x6f\x6d\x70\x61\x79\x6c\x6f\x61\x64\x00\x0e\x06\x63\x75\x73\x74\x6f\x6d\x70\x61\x79\x6c\x6f\x61\x64\x02\x01\x00\x00\x0e\x06\x63\x75\x73\x74\x6f\x6d\x70\x61\x79\x6c\x6f\x61\x64\x00\x0e\x06\x63\x75\x73\x74\x6f\x6d\x70\x61\x79\x6c\x6f\x61\x64\x03\x01\x00\x00\x0e\x06\x63\x75\x73\x74\x6f\x6d\x70\x61\x79\x6c\x6f\x61\x64\x00\x0e\x06\x63\x75\x73\x74\x6f\x6d\x70\x61\x79\x6c\x6f\x61\x64\x04\x01\x00\x00\x0e\x06\x63\x75\x73\x74\x6f\x6d\x70\x61\x79\x6c\x6f\x61\x64\x00\x0e\x06\x63\x75\x73\x74\x6f\x6d\x70\x61\x79\x6c\x6f\x61\x64\x05\x01\x00\x00\x0e\x06\x63\x75\x73\x74\x6f\x6d\x70\x61\x79\x6c\x6f\x61\x64\x00\x0e\x06\x63\x75\x73\x74\x6f\x6d\x70\x61\x79\x6c\x6f\x61\x64\x06\x01\x00\x00\x0e\x06\x63\x75\x73\x74\x6f\x6d\x70\x61\x79\x6c\x6f\x61\x64\x00\x0e\x06\x63\x75\x73\x74\x6f\x6d\x70\x61\x79\x6c\x6f\x61\x64\x07\x01\x00\x00\x0e\x06\x63\x75\x73\x74\x6f\x6d\x70\x61\x79\x6c\x6f\x61\x64\x00\x0e\x06\x63\x75\x73\x74\x6f\x6d\x70\x61\x79\x6c\x6f\x61\x64\x09\x01\x00\x00\x0e\x06\x63\x75\x73\x74\x6f\x6d\x70\x61\x79\x6c\x6f\x61\x64\x00\x0e\x06\x63\x75\x73\x74\x6f\x6d\x70\x61\x79\x6c\x6f\x61\x64\x0a\x01\x00\x00\x0e\x06\x63\x75\x73\x74\x6f\x6d\x70\x61\x79\x6c\x6f\x61\x64\x00\x0e\x06\x63\x75\x73\x74\x6f\x6d\x70\x61\x79\x6c\x6f\x61\x64\x0b\x01\x00\x00\x0e\x06\x63\x75\x73\x74\x6f\x6d\x70\x61\x79\x6c\x6f\x61\x64\x00\x0e\x06\x63\x75\x73\x74\x6f\x6d\x70\x61\x79\x6c\x6f\x61\x64"));
  212. compare(module2, "custom", new Proxy({length: 22}, {
  213. get: (target, name) => name in target ? target[name] : "payload"
  214. }));
  215. const module3 = new WebAssembly.Module(createView("\x00\x61\x73\x6d\x01\x00\x00\x00\x01\x07\x01\x60\x02\x7f\x7f\x01\x7f\x00\x1a\x06\x63\x75\x73\x74\x6f\x6d\x74\x68\x69\x73\x20\x69\x73\x20\x74\x68\x65\x20\x70\x61\x79\x6c\x6f\x61\x64\x03\x02\x01\x00\x07\x0a\x01\x06\x61\x64\x64\x54\x77\x6f\x00\x00\x0a\x09\x01\x07\x00\x20\x00\x20\x01\x6a\x0b\x00\x1b\x07\x63\x75\x73\x74\x6f\x6d\x32\x74\x68\x69\x73\x20\x69\x73\x20\x74\x68\x65\x20\x70\x61\x79\x6c\x6f\x61\x64"));
  216. compare(module3, "custom", ["this is the payload"]);
  217. compare(module3, "custom2", ["this is the payload"]);
  218. console.log(`${passed}/${passed + failed} tests passed`);
  219. }
  220. async function testInstanceConstructor(module) {
  221. console.log("\nnew WebAssembly.Instance tests");
  222. const instance = new WebAssembly.Instance(module, imports);
  223. await testInvalidCases([
  224. () => WebAssembly.Instance(),
  225. () => WebAssembly.Instance(module, imports),
  226. ...(invalidImports.map(i => () => new WebAssembly.Instance(module, i))),
  227. () => new WebAssembly.Instance(module, overrideImports({fn: 4})),
  228. () => new WebAssembly.Instance(module, overrideImports({fn2: instance.exports.fn /*wrong signature*/})),
  229. () => new WebAssembly.Instance(module, overrideImports({memory: 123})),
  230. () => new WebAssembly.Instance(module, overrideImports({memory: ""})),
  231. () => new WebAssembly.Instance(module, overrideImports({memory: {}})),
  232. () => new WebAssembly.Instance(module, overrideImports({table: 123})),
  233. () => new WebAssembly.Instance(module, overrideImports({table: "135"})),
  234. () => new WebAssembly.Instance(module, overrideImports({table: {}})),
  235. ]);
  236. test(null, instance);
  237. }
  238. async function testMemoryApi(baseModule) {
  239. console.log("\nWebAssembly.Memory tests");
  240. await testInvalidCases([
  241. () => WebAssembly.Memory({initial: 1, maximum: 2}),
  242. () => new WebAssembly.Memory(),
  243. () => new WebAssembly.Memory(0),
  244. () => new WebAssembly.Memory(""),
  245. () => Reflect.apply(WebAssembly.Memory.prototype.buffer, null, []),
  246. () => Reflect.apply(WebAssembly.Memory.prototype.buffer, {}, []),
  247. () => Reflect.apply(WebAssembly.Memory.prototype.buffer, baseModule, []),
  248. () => Reflect.apply(WebAssembly.Memory.prototype.grow, null, []),
  249. () => Reflect.apply(WebAssembly.Memory.prototype.grow, {}, []),
  250. () => Reflect.apply(WebAssembly.Memory.prototype.grow, baseModule, []),
  251. // todo:: test invalid memory imports, need to find the spec
  252. ]);
  253. const toHex = v => typeof v === "number" ? `0x${v.toString(16)}` : "undefined";
  254. const memory = new WebAssembly.Memory({initial: 1, maximum: 2});
  255. const {exports: {load}} = new WebAssembly.Instance(baseModule, overrideImports({memory}));
  256. const v1 = load(1);
  257. const v2 = load(5);
  258. const v3 = load(9) & 0xFFFF;
  259. console.log(`${toHex(v1)} == "0123"`);
  260. console.log(`${toHex(v2)} == "4567"`);
  261. console.log(`${toHex(v3)} == "89"`);
  262. memory.buffer = null; // make sure we can't modify the buffer
  263. let view = new Int32Array(memory.buffer);
  264. view[0] = 45;
  265. console.log(`heap32[0] = ${load(0)}`);
  266. function testOutOfBounds(index) {
  267. try {
  268. load(index);
  269. console.log("Should have trap with out of bounds error");
  270. } catch (e) {
  271. if (e instanceof WebAssembly.RuntimeError) {
  272. console.log(`Correctly trap on heap access at ${index}`);
  273. } else {
  274. console.log(`Unexpected Error: ${e}`);
  275. }
  276. }
  277. }
  278. const pageSize = 64 * 1024;
  279. console.log(`memory.buffer.byteLength = ${memory.buffer.byteLength} == ${pageSize}`);
  280. {
  281. view[pageSize / 4 - 1] = 0x12345678;
  282. console.log(`view32[${pageSize / 4 - 1}] = ${toHex(view[pageSize / 4 - 1])}`);
  283. console.log(`view32[${pageSize / 4}] = ${toHex(view[pageSize / 4])}`);
  284. console.log(`heap[${pageSize - 4}] = ${toHex(load(pageSize - 4))}`);
  285. testOutOfBounds(pageSize - 3);
  286. testOutOfBounds(pageSize - 2);
  287. testOutOfBounds(pageSize - 1);
  288. testOutOfBounds(pageSize);
  289. }
  290. console.log("grow by 1 page");
  291. memory.grow(1);
  292. console.log(`memory.buffer.byteLength = ${memory.buffer.byteLength} == 2 * ${pageSize}`);
  293. view = new Int32Array(memory.buffer); // buffer has been detached, reset the view
  294. {
  295. view[2 * pageSize / 4 - 1] = 0x87654321;
  296. console.log(`view32[${2 * pageSize / 4 - 1}] = ${toHex(view[2 * pageSize / 4 - 1])}`);
  297. console.log(`view32[${2 * pageSize / 4}] = ${toHex(view[2 * pageSize / 4])}`);
  298. console.log(`heap[${pageSize - 4}] = ${toHex(load(pageSize - 4))}`);
  299. console.log(`heap[${2 * pageSize - 4}] = ${toHex(load(2 * pageSize - 4))}`);
  300. testOutOfBounds(2 * pageSize - 3);
  301. testOutOfBounds(2 * pageSize - 2);
  302. testOutOfBounds(2 * pageSize - 1);
  303. testOutOfBounds(2 * pageSize);
  304. }
  305. try {
  306. memory.grow(1);
  307. console.log("Should have trap when growing past maximum");
  308. } catch (e) {
  309. if (e instanceof RangeError) {
  310. console.log("Correctly trap when growing past maximum");
  311. } else {
  312. console.log(`Unexpected Error: ${e}`);
  313. }
  314. }
  315. }
  316. async function testTableApi(baseModule) {
  317. //new WebAssembly.Table({element: "anyfunc", initial: 30, maximum: 100})
  318. const table = new WebAssembly.Table({element: "anyfunc", initial: 30, maximum: 100});
  319. console.log("\nWebAssembly.Table tests");
  320. await testInvalidCases([
  321. () => WebAssembly.Table({element: "anyfunc", initial: 30, maximum: 100}),
  322. () => new WebAssembly.Table(),
  323. () => new WebAssembly.Table(0),
  324. () => new WebAssembly.Table(""),
  325. () => new WebAssembly.Table({element: "notanyfunc", initial: 30, maximum: 100}),
  326. () => Reflect.apply(WebAssembly.Table.prototype.length, null, []),
  327. () => Reflect.apply(WebAssembly.Table.prototype.length, {}, []),
  328. () => Reflect.apply(WebAssembly.Table.prototype.length, baseModule, []),
  329. () => Reflect.apply(WebAssembly.Table.prototype.grow, null, []),
  330. () => Reflect.apply(WebAssembly.Table.prototype.grow, {}, []),
  331. () => Reflect.apply(WebAssembly.Table.prototype.grow, baseModule, []),
  332. () => Reflect.apply(WebAssembly.Table.prototype.get, null, [0]),
  333. () => Reflect.apply(WebAssembly.Table.prototype.get, {}, [0]),
  334. () => Reflect.apply(WebAssembly.Table.prototype.get, baseModule, [0]),
  335. () => table.get(30),
  336. () => table.get(100),
  337. () => Reflect.apply(WebAssembly.Table.prototype.get, table, [30]),
  338. () => Reflect.apply(WebAssembly.Table.prototype.get, table, [100]),
  339. ]);
  340. const {instance: {exports: {"f32.load": load}}} = await WebAssembly.instantiate(readbuffer("f32address.wasm"), {});
  341. const {exports: {fn, call_i32, call_f32}} = new WebAssembly.Instance(baseModule, overrideImports({table, fn2: load}));
  342. const {exports: {fn: myFn}} = new WebAssembly.Instance(baseModule, overrideImports({fn: () => 123456}));
  343. await testInvalidCases([
  344. () => table.set(30, fn),
  345. () => table.set(100, fn),
  346. () => table.set(0),
  347. () => table.set(0, {}),
  348. () => table.set(0, ""),
  349. () => table.set(0, 123),
  350. () => table.set(0, function(){}),
  351. () => table.set(0, () => 2),
  352. () => call_i32(0),
  353. () => call_f32(0),
  354. () => call_i32(29),
  355. () => call_i32(30),
  356. () => call_i32(2),
  357. () => call_f32(1),
  358. ]);
  359. console.log(`Current length: ${table.length}`);
  360. table.length = 456;
  361. console.log(`Length after attempt to modify : ${table.length}`);
  362. console.log(`Is element in table the same as the one exported: ${table.get(1) === fn}`);
  363. console.log(`Unset element should be null: ${table.get(0)}`);
  364. table.set(0, myFn);
  365. console.log(`call_i32(0): ${call_i32(0)}`);
  366. console.log(`call_i32(1): ${call_i32(1)}`);
  367. console.log(`call_f32(2): ${call_f32(2)}`);
  368. table.set(0, fn);
  369. console.log(`call_i32(0): ${call_i32(0)}`);
  370. table.set(29, myFn);
  371. table.grow(1);
  372. table.set(30, myFn);
  373. console.log(`call_i32(29): ${call_i32(29)}`);
  374. console.log(`call_i32(30): ${call_i32(30)}`);
  375. const table2 = new WebAssembly.Table({element: "anyfunc"});
  376. table.grow(0);
  377. try {table2.get(0); console.log("Failed. Unexpected successfull call to table2.get(0)");} catch (e) {}
  378. table.grow(1);
  379. table.set(0, myFn);
  380. console.log(`table2[0](): ${table.get(0)()}`);
  381. }
  382. async function main() {
  383. const args = WScript.Arguments;
  384. verbose = args.includes("-v");
  385. doInvalid = !args.includes("-i");
  386. const [start = 0, end = 99] = args
  387. .filter(a => !a.startsWith("-"))
  388. .map(a => parseInt(a));
  389. const baseModule = new WebAssembly.Module(buf);
  390. const tests = [
  391. /*0*/ testValidate,
  392. /*1*/ testCompile,
  393. /*2*/ testInstantiate,
  394. /*3*/ testModuleConstructor,
  395. /*4*/ testModuleApi,
  396. /*5*/ testModuleCustomSection,
  397. /*6*/ testInstanceConstructor,
  398. /*7*/ testMemoryApi,
  399. /*8*/ testTableApi,
  400. ];
  401. for (let i = 0; i < tests.length; ++i) {
  402. if (i >= start && i <= end) {
  403. try {
  404. await tests[i](baseModule);
  405. } catch (e) {
  406. console.log("Unexpected error");
  407. console.log(e.stack);
  408. }
  409. }
  410. }
  411. }
  412. main().then(() => console.log("done"), err => {
  413. console.log(err);
  414. console.log(err.stack);
  415. });