// Copyright 2016 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 load("test/mjsunit/wasm/wasm-module-builder.js"); // Collect the Callsite objects instead of just a string: Error.prepareStackTrace = function(error, frames) { return frames; }; function testTrapLocations(instance, expected_stack_length) { function testWasmTrap(value, reason, position) { let function_name = arguments.callee.name; try { instance.exports.main(value); fail('expected wasm exception'); } catch (e) { assertEquals(kTrapMsgs[reason], e.message, 'trap reason'); // Check that the trapping function is the one which was called from this // function. assertTrue( e.stack[1].toString().startsWith(function_name), 'stack depth'); assertEquals(0, e.stack[0].getLineNumber(), 'wasmFunctionIndex'); assertEquals(position, e.stack[0].getPosition(), 'position'); } } // The actual tests: testWasmTrap(0, kTrapDivByZero, 14); testWasmTrap(1, kTrapMemOutOfBounds, 15); testWasmTrap(2, kTrapUnreachable, 28); testWasmTrap(3, kTrapFuncInvalid, 32); } var builder = new WasmModuleBuilder(); builder.addMemory(0, 1, false); var sig_index = builder.addType(kSig_i_v) // Build a function to resemble this code: // if (idx < 2) { // return load(-2 / idx); // } else if (idx == 2) { // unreachable; // } else { // return call_indirect(idx); // } // There are four different traps which are triggered by different input values: // (0) division by zero; (1) mem oob; (2) unreachable; (3) invalid call target // Each of them also has a different location where it traps. builder.addFunction("main", kSig_i_i) .addBody([ // offset 1 kExprBlock, kWasmI32, kExprGetLocal, 0, kExprI32Const, 2, kExprI32LtU, kExprIf, kWasmStmt, // offset 9 kExprI32Const, 0x7e /* -2 */, kExprGetLocal, 0, kExprI32DivU, // offset 15 kExprI32LoadMem, 0, 0, kExprBr, 1, kExprEnd, // offset 21 kExprGetLocal, 0, kExprI32Const, 2, kExprI32Eq, kExprIf, kWasmStmt, kExprUnreachable, kExprEnd, // offset 30 kExprGetLocal, 0, kExprCallIndirect, sig_index, kTableZero, kExprEnd, ]) .exportAs("main"); builder.appendToTable([0]); let buffer = builder.toBuffer(); // Test async compilation and instantiation. assertPromiseResult(WebAssembly.instantiate(buffer), pair => { testTrapLocations(pair.instance, 5); }); // Test sync compilation and instantiation. testTrapLocations(builder.instantiate(), 4);