1 // Copyright 2016 the V8 project authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 // clang-format off 6 // Flags: --expose-wasm 7 8 load("test/mjsunit/wasm/wasm-constants.js"); 9 load("test/mjsunit/wasm/wasm-module-builder.js"); 10 11 // The stack trace contains file path, only keep "stack.js". 12 function stripPath(s) { 13 return s.replace(/[^ (]*stack\.js/g, "stack.js"); 14 } 15 16 function verifyStack(frames, expected) { 17 assertEquals(expected.length, frames.length, "number of frames mismatch"); 18 expected.forEach(function(exp, i) { 19 assertEquals(exp[1], frames[i].getFunctionName(), 20 "["+i+"].getFunctionName()"); 21 assertEquals(exp[2], frames[i].getLineNumber(), "["+i+"].getLineNumber()"); 22 if (exp[0]) 23 assertEquals(exp[3], frames[i].getPosition(), 24 "["+i+"].getPosition()"); 25 assertContains(exp[4], frames[i].getFileName(), "["+i+"].getFileName()"); 26 var toString; 27 if (exp[0]) { 28 toString = exp[1] + " (<WASM>[" + exp[2] + "]+" + exp[3] + ")"; 29 } else { 30 toString = exp[4] + ":" + exp[2] + ":"; 31 } 32 assertContains(toString, frames[i].toString(), "["+i+"].toString()"); 33 }); 34 } 35 36 37 var stack; 38 function STACK() { 39 var e = new Error(); 40 stack = e.stack; 41 } 42 43 var builder = new WasmModuleBuilder(); 44 45 builder.addImport("func", kSig_v_v); 46 47 builder.addFunction("main", kSig_v_v) 48 .addBody([kExprCallImport, kArity0, 0]) 49 .exportAs("main"); 50 51 builder.addFunction("exec_unreachable", kSig_v_v) 52 .addBody([kExprUnreachable]) 53 .exportAs("exec_unreachable"); 54 55 // Make this function unnamed, just to test also this case. 56 var mem_oob_func = builder.addFunction(undefined, kSig_v_v) 57 // Access the memory at offset -1, to provoke a trap. 58 .addBody([kExprI32Const, 0x7f, kExprI32LoadMem8S, 0, 0]) 59 .exportAs("mem_out_of_bounds"); 60 61 // Call the mem_out_of_bounds function, in order to have two WASM stack frames. 62 builder.addFunction("call_mem_out_of_bounds", kSig_v_v) 63 .addBody([kExprCallFunction, kArity0, mem_oob_func.index]) 64 .exportAs("call_mem_out_of_bounds"); 65 66 var module = builder.instantiate({func: STACK}); 67 68 (function testSimpleStack() { 69 var expected_string = "Error\n" + 70 // The line numbers below will change as this test gains / loses lines.. 71 " at STACK (stack.js:39:11)\n" + // -- 72 " at main (<WASM>[0]+1)\n" + // -- 73 " at testSimpleStack (stack.js:76:18)\n" + // -- 74 " at stack.js:78:3"; // -- 75 76 module.exports.main(); 77 assertEquals(expected_string, stripPath(stack)); 78 })(); 79 80 // For the remaining tests, collect the Callsite objects instead of just a 81 // string: 82 Error.prepareStackTrace = function(error, frames) { 83 return frames; 84 }; 85 86 (function testStackFrames() { 87 module.exports.main(); 88 89 verifyStack(stack, [ 90 // isWasm function line pos file 91 [ false, "STACK", 39, 0, "stack.js"], 92 [ true, "main", 0, 1, null], 93 [ false, "testStackFrames", 87, 0, "stack.js"], 94 [ false, null, 96, 0, "stack.js"] 95 ]); 96 })(); 97 98 (function testWasmUnreachable() { 99 try { 100 module.exports.exec_unreachable(); 101 fail("expected wasm exception"); 102 } catch (e) { 103 assertContains("unreachable", e.message); 104 verifyStack(e.stack, [ 105 // isWasm function line pos file 106 [ true, "exec_unreachable", 1, 1, null], 107 [ false, "testWasmUnreachable", 100, 0, "stack.js"], 108 [ false, null, 111, 0, "stack.js"] 109 ]); 110 } 111 })(); 112 113 (function testWasmMemOutOfBounds() { 114 try { 115 module.exports.call_mem_out_of_bounds(); 116 fail("expected wasm exception"); 117 } catch (e) { 118 assertContains("out of bounds", e.message); 119 verifyStack(e.stack, [ 120 // isWasm function line pos file 121 [ true, "", 2, 3, null], 122 [ true, "call_mem_out_of_bounds", 3, 1, null], 123 [ false, "testWasmMemOutOfBounds", 115, 0, "stack.js"], 124 [ false, null, 127, 0, "stack.js"] 125 ]); 126 } 127 })(); 128