michael@0: /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ michael@0: /* This Source Code Form is subject to the terms of the Mozilla Public michael@0: * License, v. 2.0. If a copy of the MPL was not distributed with this michael@0: * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ michael@0: michael@0: /* michael@0: * michael@0: * Date: 28 Feb 2002 michael@0: * SUMMARY: Testing that Error.stack distinguishes between: michael@0: * michael@0: * A) top-level calls: myFunc(); michael@0: * B) no-name function calls: function() { myFunc();} () michael@0: * michael@0: * The stack frame for A) should begin with '@' michael@0: * The stack frame for B) should begin with '()' michael@0: * michael@0: * This behavior was coded by Brendan during his fix for bug 127136. michael@0: * See http://bugzilla.mozilla.org/show_bug.cgi?id=127136#c13 michael@0: * michael@0: * Note: our function getStackFrames(err) orders the array of stack frames michael@0: * so that the 0th element will correspond to the highest frame, i.e. will michael@0: * correspond to a line in top-level code. The 1st element will correspond michael@0: * to the function that is called first, and so on... michael@0: * michael@0: * NOTE: At present Rhino does not have an Error.stack property. It is an michael@0: * ECMA extension, see http://bugzilla.mozilla.org/show_bug.cgi?id=123177 michael@0: */ michael@0: //----------------------------------------------------------------------------- michael@0: var UBound = 0; michael@0: var BUGNUMBER = '(none)'; michael@0: var summary = 'Testing Error.stack'; michael@0: var status = ''; michael@0: var statusitems = []; michael@0: var actual = ''; michael@0: var actualvalues = []; michael@0: var expect= ''; michael@0: var expectedvalues = []; michael@0: var myErr = ''; michael@0: var stackFrames = ''; michael@0: michael@0: michael@0: function A(x,y) michael@0: { michael@0: return B(x+1,y+1); michael@0: } michael@0: michael@0: function B(x,z) michael@0: { michael@0: return C(x+1,z+1); michael@0: } michael@0: michael@0: function C(x,y) michael@0: { michael@0: return D(x+1,y+1); michael@0: } michael@0: michael@0: function D(x,z) michael@0: { michael@0: try michael@0: { michael@0: throw new Error('meep!'); michael@0: } michael@0: catch (e) michael@0: { michael@0: return e; michael@0: } michael@0: } michael@0: michael@0: michael@0: myErr = A(44,13); michael@0: stackFrames = getStackFrames(myErr); michael@0: status = inSection(1); michael@0: actual = stackFrames[0].substring(0,1); michael@0: expect = '@'; michael@0: addThis(); michael@0: michael@0: status = inSection(2); michael@0: actual = stackFrames[1].substring(0,2); michael@0: expect = 'A@'; michael@0: addThis(); michael@0: michael@0: status = inSection(3); michael@0: actual = stackFrames[2].substring(0,2); michael@0: expect = 'B@'; michael@0: addThis(); michael@0: michael@0: status = inSection(4); michael@0: actual = stackFrames[3].substring(0,2); michael@0: expect = 'C@'; michael@0: addThis(); michael@0: michael@0: status = inSection(5); michael@0: actual = stackFrames[4].substring(0,2); michael@0: expect = 'D@'; michael@0: addThis(); michael@0: michael@0: michael@0: michael@0: myErr = A('44:foo','13:bar'); michael@0: stackFrames = getStackFrames(myErr); michael@0: status = inSection(6); michael@0: actual = stackFrames[0].substring(0,1); michael@0: expect = '@'; michael@0: addThis(); michael@0: michael@0: status = inSection(7); michael@0: actual = stackFrames[1].substring(0,2); michael@0: expect = 'A@'; michael@0: addThis(); michael@0: michael@0: status = inSection(8); michael@0: actual = stackFrames[2].substring(0,2); michael@0: expect = 'B@'; michael@0: addThis(); michael@0: michael@0: status = inSection(9); michael@0: actual = stackFrames[3].substring(0,2); michael@0: expect = 'C@'; michael@0: addThis(); michael@0: michael@0: status = inSection(10); michael@0: actual = stackFrames[4].substring(0,2); michael@0: expect = 'D@';; michael@0: addThis(); michael@0: michael@0: michael@0: michael@0: /* michael@0: * Make the first frame occur in a function with an empty name - michael@0: */ michael@0: myErr = function() { return A(44,13); } (); michael@0: stackFrames = getStackFrames(myErr); michael@0: status = inSection(11); michael@0: actual = stackFrames[0].substring(0,1); michael@0: expect = '@'; michael@0: addThis(); michael@0: michael@0: status = inSection(12); michael@0: actual = stackFrames[1].substring(0,7); michael@0: expect = 'myErr<@'; michael@0: addThis(); michael@0: michael@0: status = inSection(13); michael@0: actual = stackFrames[2].substring(0,2); michael@0: expect = 'A@'; michael@0: addThis(); michael@0: michael@0: // etc. for the rest of the frames as above michael@0: michael@0: michael@0: michael@0: /* michael@0: * Make the first frame occur in a function with name 'anonymous' - michael@0: */ michael@0: var f = Function('return A(44,13);'); michael@0: myErr = f(); michael@0: stackFrames = getStackFrames(myErr); michael@0: status = inSection(14); michael@0: actual = stackFrames[0].substring(0,1); michael@0: expect = '@'; michael@0: addThis(); michael@0: michael@0: status = inSection(15); michael@0: actual = stackFrames[1].substring(0,10); michael@0: expect = 'anonymous@'; michael@0: addThis(); michael@0: michael@0: status = inSection(16); michael@0: actual = stackFrames[2].substring(0,2); michael@0: expect = 'A@'; michael@0: addThis(); michael@0: michael@0: // etc. for the rest of the frames as above michael@0: michael@0: michael@0: michael@0: /* michael@0: * Make a user-defined error via the Error() function - michael@0: */ michael@0: var message = 'Hi there!'; var fileName = 'file name'; var lineNumber = 0; michael@0: myErr = Error(message, fileName, lineNumber); michael@0: stackFrames = getStackFrames(myErr); michael@0: status = inSection(17); michael@0: actual = stackFrames[0].substring(0,1); michael@0: expect = '@'; michael@0: addThis(); michael@0: michael@0: michael@0: /* michael@0: * Now use the |new| keyword. Re-use the same params - michael@0: */ michael@0: myErr = new Error(message, fileName, lineNumber); michael@0: stackFrames = getStackFrames(myErr); michael@0: status = inSection(18); michael@0: actual = stackFrames[0].substring(0,1); michael@0: expect = '@'; michael@0: addThis(); michael@0: michael@0: michael@0: michael@0: michael@0: //----------------------------------------------------------------------------- michael@0: test(); michael@0: //----------------------------------------------------------------------------- michael@0: michael@0: michael@0: michael@0: /* michael@0: * Split the string |err.stack| along its '\n' delimiter. michael@0: * As of 2002-02-28 |err.stack| ends with the delimiter, so michael@0: * the resulting array has an empty string as its last element. michael@0: * michael@0: * Pop that useless element off before doing anything. michael@0: * Then reverse the array, for convenience of indexing - michael@0: */ michael@0: function getStackFrames(err) michael@0: { michael@0: var arr = err.stack.split('\n'); michael@0: arr.pop(); michael@0: return arr.reverse(); michael@0: } michael@0: michael@0: michael@0: function addThis() michael@0: { michael@0: statusitems[UBound] = status; michael@0: actualvalues[UBound] = actual; michael@0: expectedvalues[UBound] = expect; michael@0: UBound++; michael@0: } michael@0: michael@0: michael@0: function test() michael@0: { michael@0: enterFunc('test'); michael@0: printBugNumber(BUGNUMBER); michael@0: printStatus(summary); michael@0: michael@0: for (var i=0; i