michael@0: // tests calling script functions via Debugger.Object.prototype.apply/call michael@0: michael@0: load(libdir + "asserts.js"); michael@0: michael@0: var g = newGlobal(); michael@0: g.eval("function f() { debugger; }"); michael@0: var dbg = new Debugger(g); michael@0: michael@0: var hits = 0; michael@0: function test(usingApply) { michael@0: dbg.onDebuggerStatement = function (frame) { michael@0: var fn = frame.arguments[0]; michael@0: var cv = usingApply ? fn.apply(null, [9, 16]) : fn.call(null, 9, 16); michael@0: assertEq(Object.keys(cv).join(","), "return"); michael@0: assertEq(Object.getPrototypeOf(cv), Object.prototype); michael@0: assertEq(cv.return, 25); michael@0: michael@0: cv = usingApply ? fn.apply(null, ["hello ", "world"]) : fn.call(null, "hello ", "world"); michael@0: assertEq(Object.keys(cv).join(","), "return"); michael@0: assertEq(cv.return, "hello world"); michael@0: michael@0: // Handle more or less arguments. michael@0: assertEq((usingApply ? fn.apply(null, [1, 5, 100]) : fn.call(null, 1, 5, 100)).return, 6); michael@0: assertEq((usingApply ? fn.apply(null, []) : fn.call(null)).return, NaN); michael@0: assertEq((usingApply ? fn.apply() : fn.call()).return, NaN); michael@0: michael@0: // Throw if a this-value or argument is an object but not a Debugger.Object. michael@0: assertThrowsInstanceOf(function () { usingApply ? fn.apply({}, []) : fn.call({}); }, michael@0: TypeError); michael@0: assertThrowsInstanceOf(function () { usingApply ? fn.apply(null, [{}]) : fn.call(null, {}); }, michael@0: TypeError); michael@0: hits++; michael@0: }; michael@0: g.eval("f(function (a, b) { return a + b; });"); michael@0: michael@0: // The callee receives the right arguments even if more arguments are provided michael@0: // than the callee's .length. michael@0: dbg.onDebuggerStatement = function (frame) { michael@0: assertEq((usingApply ? frame.arguments[0].apply(null, ['one', 'two']) michael@0: : frame.arguments[0].call(null, 'one', 'two')).return, michael@0: 2); michael@0: hits++; michael@0: }; michael@0: g.eval("f(function () { return arguments.length; });"); michael@0: michael@0: // Exceptions are reported as {throw:} completion values. michael@0: dbg.onDebuggerStatement = function (frame) { michael@0: var lose = frame.arguments[0]; michael@0: var cv = usingApply ? lose.apply(null, []) : lose.call(null); michael@0: assertEq(Object.keys(cv).join(","), "throw"); michael@0: assertEq(cv.throw, frame.callee); michael@0: hits++; michael@0: }; michael@0: g.eval("f(function lose() { throw f; });"); michael@0: } michael@0: michael@0: test(true); michael@0: test(false); michael@0: assertEq(hits, 6);