1// Copyright 2012 the V8 project authors. All rights reserved. 2// Redistribution and use in source and binary forms, with or without 3// modification, are permitted provided that the following conditions are 4// met: 5// 6// * Redistributions of source code must retain the above copyright 7// notice, this list of conditions and the following disclaimer. 8// * Redistributions in binary form must reproduce the above 9// copyright notice, this list of conditions and the following 10// disclaimer in the documentation and/or other materials provided 11// with the distribution. 12// * Neither the name of Google Inc. nor the names of its 13// contributors may be used to endorse or promote products derived 14// from this software without specific prior written permission. 15// 16// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 17// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 18// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 19// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 20// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 21// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 22// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 26// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 28// Return the stack frames of an Error object. 29 30Error.prepareStackTrace = function(error, frames) { 31 return frames; 32} 33 34Error.prototype.getFrames = function() { 35 var frames = this.stack; 36 return frames; 37} 38 39String.prototype.contains = function(pattern) { 40 return this.indexOf(pattern) > -1; 41} 42 43// Check for every frame that a certain method returns the 44// expected value for every frame. 45Array.prototype.verifyEquals = function(frames, func_name) { 46 this.forEach( 47 function(element, index) { 48 var frame = frames[index]; 49 if (element === null) return; 50 assertEquals(element, (frame[func_name])()); 51 } 52 ); 53} 54 55// Check for every frame that a certain method has a return value 56// that contains the expected pattern for every frame. 57Array.prototype.verifyContains = function(frames, func_name) { 58 this.forEach( 59 function(element, index) { 60 var frame = frames[index]; 61 if (element === null) return; 62 assertTrue((frame[func_name])().contains(element)); 63 } 64 ); 65} 66 67// Check for every frame that a certain method returns undefined 68// when expected. 69Array.prototype.verifyUndefined = function(frames, func_name) { 70 this.forEach( 71 function(element, index) { 72 var frame = frames[index]; 73 if (element === null) return; 74 assertEquals(element, (frame[func_name])() === undefined); 75 } 76 ); 77} 78 79 80// Simple eval. 81var code1 = "function f() { \n" + 82 " throw new Error(3); \n" + // Line 2 83 "} \n" + 84 "f(); \n"; // Line 4 85 86function g() { 87 eval(code1); 88} 89 90try { 91 g(); 92} catch (e) { 93 // We expect something like 94 // f (eval at g (eval-stack.js:87:8), <anonymous>:2:9) 95 // eval (eval at g (eval-stack.js:87:8), <anonymous>:4:1) 96 // g (eval-stack.js:87:3) 97 // eval-stack.js:94:3 98 var frames = e.getFrames(); 99 assertEquals(4, frames.length); 100 ["f", "eval", "g"] 101 .verifyEquals(frames, "getFunctionName"); 102 [2, 4] 103 .verifyEquals(frames, "getLineNumber"); 104 ["<anonymous>:2:", "<anonymous>:4:"] 105 .verifyContains(frames, "toString"); 106 [true, true, false, false] 107 .verifyUndefined(frames, "getFileName"); 108 ["eval at g", "eval at g"] 109 .verifyContains(frames, "getEvalOrigin"); 110} 111 112 113// Nested eval. 114var code2 = "function h() { \n" + 115 " // Empty \n" + 116 " eval(code1); \n" + // Line 3 117 "} \n" + 118 "h(); \n"; // Line 5 119 120try { 121 eval(code2); 122} catch (e) { 123 // We expect something like 124 // f (eval at h (eval at <anonymous> (eval-stack.js:116:8)), 125 // <anonymous>:2:9) 126 // eval (eval at h (eval at <anonymous> (eval-stack.js:116:8)), 127 // <anonymous>:4:1) 128 // h (eval at <anonymous> (eval-stack.js:116:8), <anonymous>:3:3) 129 // eval (eval at <anonymous> (eval-stack.js:116:8), <anonymous>:5:1) 130 // eval-stack.js:116:3 131 var frames = e.getFrames(); 132 assertEquals(5, frames.length); 133 ["f", "eval", "h", "eval"] 134 .verifyEquals(frames, "getFunctionName"); 135 [2, 4, 3, 5] 136 .verifyEquals(frames, "getLineNumber"); 137 ["<anonymous>:2:", "<anonymous>:4:", "<anonymous>:3:", "<anonymous>:5:"] 138 .verifyContains(frames, "toString"); 139 [true, true, true, true, false] 140 .verifyUndefined(frames, "getFileName"); 141 ["eval at h (eval at <anonymous> (", 142 "eval at h (eval at <anonymous> (", 143 "eval at <anonymous> (", 144 "eval at <anonymous> ("] 145 .verifyContains(frames, "getEvalOrigin"); 146} 147 148 149// Nested eval calling through non-eval defined function. 150var code3 = "function h() { \n" + 151 " // Empty \n" + 152 " g(); \n" + // Line 3 153 "} \n" + 154 "h(); \n"; // Line 5 155 156try { 157 eval(code3); 158} catch (e) { 159 // We expect something like 160 // f (eval at g (test.js:83:8), <anonymous>:2:9) 161 // eval (eval at g (test.js:83:8), <anonymous>:4:1) 162 // g (test.js:83:3) 163 // h (eval at <anonymous> (test.js:149:8), <anonymous>:3:3) 164 // eval (eval at <anonymous> (test.js:149:8), <anonymous>:5:1) 165 // test.js:149:3 166 var frames = e.getFrames(); 167 assertEquals(6, frames.length); 168 ["f", "eval", "g", "h", "eval"] 169 .verifyEquals(frames, "getFunctionName"); 170 [2, 4, null, 3, 5] 171 .verifyEquals(frames, "getLineNumber"); 172 ["<anonymous>:2:", "<anonymous>:4:", null, "<anonymous>:3:", "<anonymous>:5:"] 173 .verifyContains(frames, "toString"); 174 [true, true, false, true, true, false] 175 .verifyUndefined(frames, "getFileName"); 176 ["eval at g (", 177 "eval at g (", 178 null, 179 "eval at <anonymous> (", 180 "eval at <anonymous> ("] 181 .verifyContains(frames, "getEvalOrigin"); 182} 183 184 185// Calling function defined in eval. 186eval("function f() { \n" + 187 " throw new Error(3); \n" + 188 "} \n"); 189 190try { 191 f(); 192} catch (e) { 193 // We expect something like 194 // f (eval at <anonymous> (test.js:182:40), <anonymous>:2:9) 195 // test.js:186:3 196 var frames = e.getFrames(); 197 assertEquals(2, frames.length); 198 ["f"].verifyEquals(frames, "getFunctionName"); 199 [2].verifyEquals(frames, "getLineNumber"); 200 ["<anonymous>:2:"].verifyContains(frames, "toString"); 201 [true, false].verifyUndefined(frames, "getFileName"); 202 ["eval at <anonymous> ("].verifyContains(frames, "getEvalOrigin"); 203} 204