Import Cobalt 13.102542 Change-Id: I6bda7b03a2e33edfd735efcb981e2a731696b90d
diff --git a/src/v8/test/inspector/debugger/access-obsolete-frame-expected.txt b/src/v8/test/inspector/debugger/access-obsolete-frame-expected.txt new file mode 100644 index 0000000..7093d76 --- /dev/null +++ b/src/v8/test/inspector/debugger/access-obsolete-frame-expected.txt
@@ -0,0 +1,9 @@ +Tests that accessing no longer valid call frames returns an error +Paused on 'debugger;' +resume +restartFrame +PASS, error message as expected +evaluateOnFrame +PASS, error message as expected +setVariableValue +PASS, error message as expected
diff --git a/src/v8/test/inspector/debugger/access-obsolete-frame.js b/src/v8/test/inspector/debugger/access-obsolete-frame.js new file mode 100644 index 0000000..9d498e0 --- /dev/null +++ b/src/v8/test/inspector/debugger/access-obsolete-frame.js
@@ -0,0 +1,69 @@ +// 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. + +let {session, contextGroup, Protocol} = InspectorTest.start('Tests that accessing no longer valid call frames returns an error'); + +contextGroup.addScript(` +function testFunction() +{ + debugger; +} +//# sourceURL=foo.js`); + +Protocol.Debugger.enable(); + +Protocol.Debugger.oncePaused().then(handleDebuggerPausedOne); + +Protocol.Runtime.evaluate({ "expression": "setTimeout(testFunction, 0)" }); + +var obsoleteTopFrameId; + +function handleDebuggerPausedOne(messageObject) +{ + InspectorTest.log("Paused on 'debugger;'"); + + var topFrame = messageObject.params.callFrames[0]; + obsoleteTopFrameId = topFrame.callFrameId; + + Protocol.Debugger.resume().then(callbackResume); +} + +function callbackResume(response) +{ + InspectorTest.log("resume"); + InspectorTest.log("restartFrame"); + Protocol.Debugger.restartFrame({ callFrameId: obsoleteTopFrameId }).then(callbackRestartFrame); +} + +function callbackRestartFrame(response) +{ + logErrorResponse(response); + InspectorTest.log("evaluateOnFrame"); + Protocol.Debugger.evaluateOnCallFrame({ callFrameId: obsoleteTopFrameId, expression: "0"}).then(callbackEvaluate); +} + +function callbackEvaluate(response) +{ + logErrorResponse(response); + InspectorTest.log("setVariableValue"); + Protocol.Debugger.setVariableValue({ callFrameId: obsoleteTopFrameId, scopeNumber: 0, variableName: "a", newValue: { value: 0 } }).then(callbackSetVariableValue); +} + +function callbackSetVariableValue(response) +{ + logErrorResponse(response); + InspectorTest.completeTest(); +} + +function logErrorResponse(response) +{ + if (response.error) { + if (response.error.message.indexOf("Can only perform operation while paused.") !== -1) { + InspectorTest.log("PASS, error message as expected"); + return; + } + } + InspectorTest.log("FAIL, unexpected error message"); + InspectorTest.log(JSON.stringify(response)); +}
diff --git a/src/v8/test/inspector/debugger/asm-js-breakpoint-before-exec-expected.txt b/src/v8/test/inspector/debugger/asm-js-breakpoint-before-exec-expected.txt new file mode 100644 index 0000000..ae15e5d --- /dev/null +++ b/src/v8/test/inspector/debugger/asm-js-breakpoint-before-exec-expected.txt
@@ -0,0 +1,69 @@ +This test runs asm.js which calls back to JS. Before executing (after the script is parsed) we set breakpoints in the asm.js code. + +Running test: enableDebugger + +Running test: addScript +Script nr 1 parsed! +First script; assuming testFunction. +Flooding script with breakpoints for the lines 3 to 20... +Setting breakpoint on line 3 +error: undefined +Setting breakpoint on line 4 +error: undefined +Setting breakpoint on line 5 +error: undefined +Setting breakpoint on line 6 +error: undefined +Setting breakpoint on line 7 +error: undefined +Setting breakpoint on line 8 +error: undefined +Setting breakpoint on line 9 +error: undefined +Setting breakpoint on line 10 +error: undefined +Setting breakpoint on line 11 +error: undefined +Setting breakpoint on line 12 +error: undefined +Setting breakpoint on line 13 +error: undefined +Setting breakpoint on line 14 +error: undefined +Setting breakpoint on line 15 +error: undefined +Setting breakpoint on line 16 +error: undefined +Setting breakpoint on line 17 +error: undefined +Setting breakpoint on line 18 +error: undefined +Setting breakpoint on line 19 +error: undefined + +Running test: runTestFunction +Script nr 2 parsed! +Paused #1 + - [0] {"functionName":"testFunction","function_lineNumber":0,"function_columnNumber":21,"lineNumber":17,"columnNumber":2} + - [1] {"functionName":"","function_lineNumber":0,"function_columnNumber":0,"lineNumber":0,"columnNumber":0} +Paused #2 + - [0] {"functionName":"testFunction","function_lineNumber":0,"function_columnNumber":21,"lineNumber":18,"columnNumber":12} + - [1] {"functionName":"","function_lineNumber":0,"function_columnNumber":0,"lineNumber":0,"columnNumber":0} +Paused #3 + - [0] {"functionName":"testFunction","function_lineNumber":0,"function_columnNumber":21,"lineNumber":19,"columnNumber":2} + - [1] {"functionName":"","function_lineNumber":0,"function_columnNumber":0,"lineNumber":0,"columnNumber":0} +Paused #4 + - [0] {"functionName":"call_debugger","function_lineNumber":13,"function_columnNumber":24,"lineNumber":14,"columnNumber":4} + - [1] {"functionName":"callDebugger","lineNumber":5,"columnNumber":6} + - [2] {"functionName":"redirectFun","lineNumber":8,"columnNumber":6} + - [3] {"functionName":"testFunction","function_lineNumber":0,"function_columnNumber":21,"lineNumber":19,"columnNumber":2} + - [4] {"functionName":"","function_lineNumber":0,"function_columnNumber":0,"lineNumber":0,"columnNumber":0} +Paused #5 + - [0] {"functionName":"call_debugger","function_lineNumber":13,"function_columnNumber":24,"lineNumber":15,"columnNumber":2} + - [1] {"functionName":"callDebugger","lineNumber":5,"columnNumber":6} + - [2] {"functionName":"redirectFun","lineNumber":8,"columnNumber":6} + - [3] {"functionName":"testFunction","function_lineNumber":0,"function_columnNumber":21,"lineNumber":19,"columnNumber":2} + - [4] {"functionName":"","function_lineNumber":0,"function_columnNumber":0,"lineNumber":0,"columnNumber":0} + +Running test: finished +Finished TestSuite.
diff --git a/src/v8/test/inspector/debugger/asm-js-breakpoint-before-exec.js b/src/v8/test/inspector/debugger/asm-js-breakpoint-before-exec.js new file mode 100644 index 0000000..ec760ec --- /dev/null +++ b/src/v8/test/inspector/debugger/asm-js-breakpoint-before-exec.js
@@ -0,0 +1,128 @@ +// 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: --validate-asm --allow-natives-syntax + +let {session, contextGroup, Protocol} = InspectorTest.start( + 'This test runs asm.js which calls back to JS. Before executing (after ' + + 'the script is parsed) we set breakpoints in the asm.js code.'); + +function testFunction() { + function generateAsmJs(stdlib, foreign, heap) { + 'use asm'; + var debugger_fun = foreign.call_debugger; + function callDebugger() { + debugger_fun(); + } + function redirectFun() { + callDebugger(); + } + return redirectFun; + } + + function call_debugger() { + debugger; + } + + %OptimizeFunctionOnNextCall(generateAsmJs); + var fun = generateAsmJs(this, {'call_debugger': call_debugger}, undefined); + fun(); +} + +Protocol.Debugger.onPaused(handleDebuggerPaused); +Protocol.Debugger.onScriptParsed(handleScriptParsed); + +function printResultAndContinue(next, message) { + if (message.result && message.result.exceptionDetails) + InspectorTest.logMessage(message.result.exceptionDetails); + else if (message.error) + InspectorTest.logMessage(message.error); + else if (message.result && message.result.type !== undefined) + InspectorTest.logMessage(message.result); + next(); +} + +InspectorTest.runTestSuite([ + function enableDebugger(next) { + Protocol.Debugger.enable().then(next); + }, + + function addScript(next) { + afterScriptParsedCallback = next; + contextGroup.addScript(testFunction.toString()); + }, + + function runTestFunction(next) { + Protocol.Runtime.evaluate({'expression': 'testFunction()'}) + .then(printResultAndContinue.bind(null, next)); + }, + + function finished(next) { + InspectorTest.log('Finished TestSuite.'); + next(); + }, +]); + +function locationToString(callFrame) { + var res = {functionName: callFrame.functionName}; + for (var attr in callFrame.functionLocation) { + if (attr == 'scriptId') continue; + res['function_' + attr] = callFrame.functionLocation[attr]; + } + for (var attr in callFrame.location) { + if (attr == 'scriptId') continue; + res[attr] = callFrame.location[attr]; + } + return JSON.stringify(res); +} + +function logStackTrace(messageObject) { + var frames = messageObject.params.callFrames; + for (var i = 0; i < frames.length; ++i) { + InspectorTest.log(' - [' + i + '] ' + locationToString(frames[i])); + } +} + +var numPaused = 0; + +function handleDebuggerPaused(messageObject) +{ + ++numPaused; + InspectorTest.log('Paused #' + numPaused); + logStackTrace(messageObject); + Protocol.Debugger.resume(); +} + +var numScripts = 0; + +function handleScriptParsed(messageObject) +{ + var scriptId = messageObject.params.scriptId; + ++numScripts; + InspectorTest.log('Script nr ' + numScripts + ' parsed!'); + if (numScripts > 1) return; + + var startLine = messageObject.params.startLine + 3; + var endLine = messageObject.params.endLine; + InspectorTest.log('First script; assuming testFunction.'); + InspectorTest.log( + 'Flooding script with breakpoints for the lines ' + startLine + ' to ' + + endLine + '...'); + var currentLine = startLine; + function setNextBreakpoint(message) { + if (message) InspectorTest.logMessage('error: ' + message.error); + if (currentLine == endLine) { + afterScriptParsedCallback(); + return; + } + var thisLine = currentLine; + currentLine += 1; + InspectorTest.log('Setting breakpoint on line ' + thisLine); + Protocol.Debugger + .setBreakpoint( + {'location': {'scriptId': scriptId, 'lineNumber': thisLine}}) + .then(setNextBreakpoint); + } + setNextBreakpoint(); +}
diff --git a/src/v8/test/inspector/debugger/asm-js-breakpoint-during-exec-expected.txt b/src/v8/test/inspector/debugger/asm-js-breakpoint-during-exec-expected.txt new file mode 100644 index 0000000..feb4a3b --- /dev/null +++ b/src/v8/test/inspector/debugger/asm-js-breakpoint-during-exec-expected.txt
@@ -0,0 +1,86 @@ +This test runs asm.js which calls back to JS. JS triggers a break, on pause we set breakpoints in the asm.js code. + +Running test: enableDebugger + +Running test: addScript +Script nr 1 parsed! + +Running test: runTestFunction +Script nr 2 parsed! +Paused #1 + - [0] {"functionName":"call_debugger","function_lineNumber":13,"function_columnNumber":24,"lineNumber":14,"columnNumber":4} + - [1] {"functionName":"callDebugger","lineNumber":5,"columnNumber":6} + - [2] {"functionName":"redirectFun","lineNumber":8,"columnNumber":6} + - [3] {"functionName":"testFunction","function_lineNumber":0,"function_columnNumber":21,"lineNumber":19,"columnNumber":2} + - [4] {"functionName":"","function_lineNumber":0,"function_columnNumber":0,"lineNumber":0,"columnNumber":0} +First time paused, setting breakpoints! +Flooding script with breakpoints for all lines (0 - 23)... +Setting breakpoint on line 0 +error: undefined +Setting breakpoint on line 1 +error: undefined +Setting breakpoint on line 2 +error: undefined +Setting breakpoint on line 3 +error: undefined +Setting breakpoint on line 4 +error: undefined +Setting breakpoint on line 5 +error: undefined +Setting breakpoint on line 6 +error: undefined +Setting breakpoint on line 7 +error: undefined +Setting breakpoint on line 8 +error: undefined +Setting breakpoint on line 9 +error: undefined +Setting breakpoint on line 10 +error: undefined +Setting breakpoint on line 11 +error: undefined +Setting breakpoint on line 12 +error: undefined +Setting breakpoint on line 13 +error: undefined +Setting breakpoint on line 14 +error: undefined +Setting breakpoint on line 15 +error: undefined +Setting breakpoint on line 16 +error: undefined +Setting breakpoint on line 17 +error: undefined +Setting breakpoint on line 18 +error: undefined +Setting breakpoint on line 19 +error: undefined +Setting breakpoint on line 20 +error: undefined +Setting breakpoint on line 21 +error: undefined +Setting breakpoint on line 22 +error: undefined +Script nr 3 parsed! +Resuming... +Paused #2 + - [0] {"functionName":"call_debugger","function_lineNumber":13,"function_columnNumber":24,"lineNumber":15,"columnNumber":2} + - [1] {"functionName":"callDebugger","lineNumber":5,"columnNumber":6} + - [2] {"functionName":"redirectFun","lineNumber":8,"columnNumber":6} + - [3] {"functionName":"testFunction","function_lineNumber":0,"function_columnNumber":21,"lineNumber":19,"columnNumber":2} + - [4] {"functionName":"","function_lineNumber":0,"function_columnNumber":0,"lineNumber":0,"columnNumber":0} +Script nr 4 parsed! +Resuming... +Paused #3 + - [0] {"functionName":"testFunction","function_lineNumber":0,"function_columnNumber":21,"lineNumber":21,"columnNumber":17} + - [1] {"functionName":"","function_lineNumber":0,"function_columnNumber":0,"lineNumber":0,"columnNumber":0} +Script nr 5 parsed! +Resuming... +Paused #4 + - [0] {"functionName":"testFunction","function_lineNumber":0,"function_columnNumber":21,"lineNumber":22,"columnNumber":2} + - [1] {"functionName":"","function_lineNumber":0,"function_columnNumber":0,"lineNumber":0,"columnNumber":0} +Script nr 6 parsed! +Resuming... + +Running test: finished +Finished TestSuite.
diff --git a/src/v8/test/inspector/debugger/asm-js-breakpoint-during-exec.js b/src/v8/test/inspector/debugger/asm-js-breakpoint-during-exec.js new file mode 100644 index 0000000..af3ac51 --- /dev/null +++ b/src/v8/test/inspector/debugger/asm-js-breakpoint-during-exec.js
@@ -0,0 +1,165 @@ +// 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: --validate-asm --allow-natives-syntax + +let {session, contextGroup, Protocol} = InspectorTest.start( + 'This test runs asm.js which calls back to JS. JS triggers a break, on ' + + 'pause we set breakpoints in the asm.js code.'); + +function testFunction() { + function generateAsmJs(stdlib, foreign, heap) { + 'use asm'; + var debugger_fun = foreign.call_debugger; + function callDebugger() { + debugger_fun(); + } + function redirectFun() { + callDebugger(); + } + return redirectFun; + } + + function call_debugger() { + debugger; + } + + %OptimizeFunctionOnNextCall(generateAsmJs); + var fun = generateAsmJs(this, {'call_debugger': call_debugger}, undefined); + fun(); + + var finished = 'finished'; + debugger; +} + +Protocol.Debugger.onPaused(handleDebuggerPaused); +Protocol.Debugger.onScriptParsed(handleScriptParsed); + +function printResultAndContinue(next, message) { + if (message.result && message.result.exceptionDetails) + InspectorTest.logMessage(message.result.exceptionDetails); + else if (message.error) + InspectorTest.logMessage(message.error); + else if (message.result && message.result.type !== undefined) + InspectorTest.logMessage(message.result); + if (next) next(); +} + +InspectorTest.runTestSuite([ + function enableDebugger(next) { + Protocol.Debugger.enable().then(next); + }, + + function addScript(next) { + afterScriptParsedCallback = next; + contextGroup.addScript(testFunction.toString()); + }, + + function runTestFunction(next) { + afterFinishedTestFunctionCallback = next; + Protocol.Runtime.evaluate({'expression': 'testFunction()'}) + .then(printResultAndContinue.bind(null, null)); + }, + + function finished(next) { + InspectorTest.log('Finished TestSuite.'); + next(); + }, +]); + +function locationToString(callFrame) { + var res = {functionName: callFrame.functionName}; + for (var attr in callFrame.functionLocation) { + if (attr == 'scriptId') continue; + res['function_' + attr] = callFrame.functionLocation[attr]; + } + for (var attr in callFrame.location) { + if (attr == 'scriptId') continue; + res[attr] = callFrame.location[attr]; + } + return JSON.stringify(res); +} + +function logStackTrace(messageObject) { + var frames = messageObject.params.callFrames; + for (var i = 0; i < frames.length; ++i) { + InspectorTest.log(' - [' + i + '] ' + locationToString(frames[i])); + } +} + +var numPaused = 0; +var parsedScriptParams; + +function handleDebuggerPaused(messageObject) +{ + ++numPaused; + InspectorTest.log('Paused #' + numPaused); + logStackTrace(messageObject); + + function cont() { + var topFrameId = messageObject.params.callFrames[0].callFrameId; + Protocol.Debugger + .evaluateOnCallFrame({ + callFrameId: topFrameId, + expression: 'typeof finished' + }) + .then(callbackEvaluate); + function callbackEvaluate(message) { + var finished = message.result && message.result.result && + message.result.result.value === 'string'; + + InspectorTest.log('Resuming...'); + Protocol.Debugger.resume(); + + if (finished) + afterFinishedTestFunctionCallback(); + } + } + + if (numPaused > 1) { + cont(); + return; + } + + InspectorTest.log('First time paused, setting breakpoints!'); + + var startLine = parsedScriptParams.startLine; + var endLine = parsedScriptParams.endLine; + InspectorTest.log( + 'Flooding script with breakpoints for all lines (' + startLine + ' - ' + + endLine + ')...'); + var currentLine = startLine; + function setNextBreakpoint(message) { + if (message) InspectorTest.logMessage('error: ' + message.error); + if (currentLine == endLine) { + cont(); + return; + } + var thisLine = currentLine; + currentLine += 1; + InspectorTest.log('Setting breakpoint on line ' + thisLine); + Protocol.Debugger + .setBreakpoint({ + 'location': { + 'scriptId': parsedScriptParams.scriptId, + 'lineNumber': thisLine + } + }) + .then(setNextBreakpoint); + } + setNextBreakpoint(); +} + +var numScripts = 0; + +function handleScriptParsed(messageObject) +{ + var scriptId = messageObject.params.scriptId; + ++numScripts; + InspectorTest.log('Script nr ' + numScripts + ' parsed!'); + if (numScripts == 1) { + parsedScriptParams = JSON.parse(JSON.stringify(messageObject.params)); + afterScriptParsedCallback(); + } +}
diff --git a/src/v8/test/inspector/debugger/asm-js-stack-expected.txt b/src/v8/test/inspector/debugger/asm-js-stack-expected.txt new file mode 100644 index 0000000..e028f2a --- /dev/null +++ b/src/v8/test/inspector/debugger/asm-js-stack-expected.txt
@@ -0,0 +1,18 @@ +Tests that asm-js scripts produce correct stack +Paused on 'debugger;' +Number of frames: 5 + - [0] {"functionName":"call_debugger","function_lineNumber":13,"function_columnNumber":24,"lineNumber":14,"columnNumber":4} + - [1] {"functionName":"callDebugger","lineNumber":5,"columnNumber":6} + - [2] {"functionName":"redirectFun","lineNumber":8,"columnNumber":6} + - [3] {"functionName":"testFunction","function_lineNumber":0,"function_columnNumber":21,"lineNumber":18,"columnNumber":2} + - [4] {"functionName":"","function_lineNumber":0,"function_columnNumber":0,"lineNumber":0,"columnNumber":0} +Getting v8-generated stack trace... +Result of evaluate (string): +Error: getting stack trace + -- skipped -- + at call_debugger (<anonymous>:15:5) + at callDebugger (<anonymous>:6:7) + at redirectFun (<anonymous>:9:7) + at testFunction (<anonymous>:19:3) + at <anonymous>:1:1 +Finished!
diff --git a/src/v8/test/inspector/debugger/asm-js-stack.js b/src/v8/test/inspector/debugger/asm-js-stack.js new file mode 100644 index 0000000..916ac5f --- /dev/null +++ b/src/v8/test/inspector/debugger/asm-js-stack.js
@@ -0,0 +1,81 @@ +// 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: --validate-asm + +let {session, contextGroup, Protocol} = InspectorTest.start('Tests that asm-js scripts produce correct stack'); + +function testFunction() { + function generateAsmJs(stdlib, foreign, heap) { + 'use asm'; + var debugger_fun = foreign.call_debugger; + function callDebugger() { + debugger_fun(); + } + function redirectFun() { + callDebugger(); + } + return redirectFun; + } + + function call_debugger() { + debugger; + } + + var fun = generateAsmJs(this, {'call_debugger': call_debugger}, undefined); + fun(); +} + +contextGroup.addScript(testFunction.toString()); + +Protocol.Debugger.enable(); +Protocol.Debugger.oncePaused().then(handleDebuggerPaused); +Protocol.Runtime.evaluate({'expression': 'testFunction()'}); + +function locationToString(callFrame) { + var res = {functionName: callFrame.functionName}; + for (var attr in callFrame.functionLocation) { + if (attr == 'scriptId') continue; + res['function_'+attr] = callFrame.functionLocation[attr]; + } + for (var attr in callFrame.location) { + if (attr == 'scriptId') continue; + res[attr] = callFrame.location[attr]; + } + return JSON.stringify(res); +} + +function logStackTrace(messageObject) { + var frames = messageObject.params.callFrames; + InspectorTest.log('Number of frames: ' + frames.length); + for (var i = 0; i < frames.length; ++i) { + InspectorTest.log(' - [' + i + '] ' + locationToString(frames[i])); + } +} + +function handleDebuggerPaused(messageObject) +{ + InspectorTest.log('Paused on \'debugger;\''); + logStackTrace(messageObject); + InspectorTest.log('Getting v8-generated stack trace...'); + var topFrameId = messageObject.params.callFrames[0].callFrameId; + Protocol.Debugger + .evaluateOnCallFrame({ + callFrameId: topFrameId, + expression: '(new Error("getting stack trace")).stack' + }) + .then(callbackEvaluate); +} + +function callbackEvaluate(response) +{ + InspectorTest.log( + 'Result of evaluate (' + response.result.result.type + '):'); + var result_lines = response.result.result.value.split("\n"); + // Skip the second line, containing the 'evaluate' position. + result_lines[1] = " -- skipped --"; + InspectorTest.log(result_lines.join('\n')); + InspectorTest.log('Finished!'); + InspectorTest.completeTest(); +}
diff --git a/src/v8/test/inspector/debugger/async-console-count-doesnt-crash-expected.txt b/src/v8/test/inspector/debugger/async-console-count-doesnt-crash-expected.txt new file mode 100644 index 0000000..aaaf9eb --- /dev/null +++ b/src/v8/test/inspector/debugger/async-console-count-doesnt-crash-expected.txt
@@ -0,0 +1 @@ +setTimeout(console.count, 0) doesn't crash with enabled async stacks.
diff --git a/src/v8/test/inspector/debugger/async-console-count-doesnt-crash.js b/src/v8/test/inspector/debugger/async-console-count-doesnt-crash.js new file mode 100644 index 0000000..14f09b3 --- /dev/null +++ b/src/v8/test/inspector/debugger/async-console-count-doesnt-crash.js
@@ -0,0 +1,10 @@ +// 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. + +let {session, contextGroup, Protocol} = InspectorTest.start("setTimeout(console.count, 0) doesn't crash with enabled async stacks.") + +Protocol.Debugger.enable(); +Protocol.Debugger.setAsyncCallStackDepth({ maxDepth: 1 }); +Protocol.Runtime.evaluate({ expression: "setTimeout(console.count, 0)" }); +InspectorTest.waitForPendingTasks().then(InspectorTest.completeTest);
diff --git a/src/v8/test/inspector/debugger/async-for-await-of-promise-stack-expected.txt b/src/v8/test/inspector/debugger/async-for-await-of-promise-stack-expected.txt new file mode 100644 index 0000000..0cfa3c4 --- /dev/null +++ b/src/v8/test/inspector/debugger/async-for-await-of-promise-stack-expected.txt
@@ -0,0 +1,58 @@ +Checks that async chains for for-await-of are correct. + +Running test: testBasic +Debugger (test.js:12:2) +Basic (test.js:50:4) +-- async function -- +Basic (test.js:48:20) +(anonymous) (testBasic.js:0:0) + + +Running test: testUncaughtReject +Debugger (test.js:12:2) +-- async function -- +UncaughtReject (test.js:54:29) +(anonymous) (testUncaughtReject.js:0:0) + + +Running test: testUncaughtThrow +Debugger (test.js:12:2) +-- async function -- +UncaughtThrow (test.js:63:28) +(anonymous) (testUncaughtThrow.js:0:0) + + +Running test: testCaughtReject +Debugger (test.js:12:2) +CaughtReject (test.js:78:4) +-- async function -- +CaughtReject (test.js:72:27) +(anonymous) (testCaughtReject.js:0:0) + + +Running test: testCaughtThrow +Debugger (test.js:12:2) +CaughtThrow (test.js:88:4) +-- async function -- +CaughtThrow (test.js:82:26) +(anonymous) (testCaughtThrow.js:0:0) + + +Running test: testUncaughtRejectOnBreak + +Running test: testUncaughtThrowOnBreak +Debugger (test.js:12:2) +-- async function -- +UncaughtThrowOnBreak (test.js:101:35) +(anonymous) (testUncaughtThrowOnBreak.js:0:0) + + +Running test: testCaughtRejectOnBreak + +Running test: testCaughtThrowOnBreak +Debugger (test.js:12:2) +CaughtThrowOnBreak (test.js:126:4) +-- async function -- +CaughtThrowOnBreak (test.js:120:33) +(anonymous) (testCaughtThrowOnBreak.js:0:0) +
diff --git a/src/v8/test/inspector/debugger/async-for-await-of-promise-stack.js b/src/v8/test/inspector/debugger/async-for-await-of-promise-stack.js new file mode 100644 index 0000000..6a2f4ce --- /dev/null +++ b/src/v8/test/inspector/debugger/async-for-await-of-promise-stack.js
@@ -0,0 +1,164 @@ +// 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: --harmony-async-iteration + +let {session, contextGroup, Protocol} = InspectorTest.start('Checks that async chains for for-await-of are correct.'); + +contextGroup.addScript(` + +function Debugger(value) { + debugger; +} + +function Reject(reason) { + var reject; + var promise = new Promise(function(resolvefn, rejectfn) { + reject = rejectfn; + }); + setTimeout(reject.bind(undefined, reason), 0); + return promise; +} + +function Throw(reason) { + return { + get then() { throw reason; } + }; +} + +function ThrowOnReturn(items) { + var it = items[Symbol.iterator](); + return { + [Symbol.iterator]() { return this; }, + next(v) { return it.next(v); }, + return(v) { throw new Error("boop"); } + }; +} + +function RejectOnReturn(items) { + var it = items[Symbol.iterator](); + return { + [Symbol.iterator]() { return this; }, + next(v) { return it.next(v); }, + return(v) { return Reject(new Error("boop")); } + }; +} + +async function Basic() { + for await (let x of ["a"]) { + Debugger(); + } +} +// TODO(kozyatinskiy): this stack trace is suspicious. +async function UncaughtReject() { + async function loop() { + for await (let x of [Reject(new Error("boop"))]) { + Debugger(); + } + } + return loop().catch(Debugger); +} +// TODO(kozyatinskiy): this stack trace is suspicious. +async function UncaughtThrow() { + async function loop() { + for await (let x of [Throw(new Error("boop"))]) { + Debugger(); + } + } + return loop().catch(Debugger); +} + +async function CaughtReject() { + try { + for await (let x of [Reject(new Error("boop"))]) { + Debugger(x); + } + } catch (e) { + Debugger(e); + } +} + +async function CaughtThrow() { + try { + for await (let x of [Throw(new Error("boop"))]) { + Debugger(x); + } + } catch (e) { + Debugger(e); + } +} +// TODO(kozyatinskiy): this stack trace is suspicious. +async function UncaughtRejectOnBreak() { + async function loop() { + for await (let x of RejectOnReturn(["0", "1"])) { + break; + } + } + return loop().catch(Debugger); +} +// TODO(kozyatinskiy): this stack trace is suspicious. +async function UncaughtThrowOnBreak() { + async function loop() { + for await (let x of ThrowOnReturn(["0", "1"])) { + break; + } + } + return loop().catch(Debugger); +} +// TODO(kozyatinskiy): this stack trace is suspicious. +async function CaughtRejectOnBreak() { + try { + for await (let x of RejectOnReturn(["0", "1"])) { + break; + } + } catch (e) { + Debugger(e); + } +} + +async function CaughtThrowOnBreak() { + try { + for await (let x of ThrowOnReturn(["0", "1"])) { + break; + } + } catch (e) { + Debugger(e); + } +} +//# sourceURL=test.js`, 9, 26); + +session.setupScriptMap(); +Protocol.Debugger.onPaused(message => { + session.logCallFrames(message.params.callFrames); + session.logAsyncStackTrace(message.params.asyncStackTrace); + InspectorTest.log(''); + Protocol.Debugger.resume(); +}); + +Protocol.Debugger.enable(); +Protocol.Debugger.setAsyncCallStackDepth({ maxDepth: 128 }); +var testList = [ + 'Basic', + 'UncaughtReject', + 'UncaughtThrow', + 'CaughtReject', + 'CaughtThrow', + 'UncaughtRejectOnBreak', + 'UncaughtThrowOnBreak', + 'CaughtRejectOnBreak', + 'CaughtThrowOnBreak', +] +InspectorTest.runTestSuite(testList.map(name => { + return eval(` + (function test${capitalize(name)}(next) { + Protocol.Runtime.evaluate({ expression: \`${name}() +//# sourceURL=test${capitalize(name)}.js\`, awaitPromise: true}) + .then(next); + }) + `); +})); + +function capitalize(string) { + return string.charAt(0).toUpperCase() + string.slice(1); +}
diff --git a/src/v8/test/inspector/debugger/async-instrumentation-expected.txt b/src/v8/test/inspector/debugger/async-instrumentation-expected.txt new file mode 100644 index 0000000..3b9f58a --- /dev/null +++ b/src/v8/test/inspector/debugger/async-instrumentation-expected.txt
@@ -0,0 +1,43 @@ +Checks async instrumentation enabled in the middle. + +Running test: beforeAsyncTaskScheduled +test (test.js:16:2) +(anonymous) (expr1.js:0:0) + +test (test.js:21:2) +(anonymous) (expr1.js:0:0) + +foo (test.js:10:2) +-- Promise.resolve -- +test (test.js:19:14) +(anonymous) (expr1.js:0:0) + +foo (test.js:12:2) +-- Promise.resolve -- +test (test.js:19:14) +(anonymous) (expr1.js:0:0) + + +Running test: afterAsyncTaskScheduled +test (test.js:16:2) +(anonymous) (expr1.js:0:0) + +test (test.js:21:2) +(anonymous) (expr1.js:0:0) + +foo (test.js:10:2) + +foo (test.js:12:2) + + +Running test: afterAsyncTaskStarted +test (test.js:16:2) +(anonymous) (expr1.js:0:0) + +test (test.js:21:2) +(anonymous) (expr1.js:0:0) + +foo (test.js:10:2) + +foo (test.js:12:2) +
diff --git a/src/v8/test/inspector/debugger/async-instrumentation.js b/src/v8/test/inspector/debugger/async-instrumentation.js new file mode 100644 index 0000000..6de2ce7 --- /dev/null +++ b/src/v8/test/inspector/debugger/async-instrumentation.js
@@ -0,0 +1,68 @@ +// 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. + +let {session, contextGroup, Protocol} = InspectorTest.start('Checks async instrumentation enabled in the middle.'); + +contextGroup.addScript(` +function foo() { + // asyncTaskStarted + debugger; + // asyncTaskFinished + debugger; +} + +function test() { + debugger; + var resolve1; + var p1 = new Promise(resolve => resolve1 = resolve); + var p2 = p1.then(foo); + resolve1(); // asyncTaskScheduled + debugger; + return p2; +} + +//# sourceURL=test.js`, 7, 26); + +session.setupScriptMap(); +Protocol.Debugger.onPaused(message => { + if (enableOnPause-- === 0) + Protocol.Debugger.setAsyncCallStackDepth({ maxDepth: 128 }); + session.logCallFrames(message.params.callFrames); + var asyncStackTrace = message.params.asyncStackTrace; + while (asyncStackTrace) { + InspectorTest.log(`-- ${asyncStackTrace.description} --`); + session.logCallFrames(asyncStackTrace.callFrames); + asyncStackTrace = asyncStackTrace.parent; + } + InspectorTest.log(''); + Protocol.Debugger.resume(); +}); + +Protocol.Debugger.enable(); +var enableOnPause = 0; +InspectorTest.runTestSuite([ + function beforeAsyncTaskScheduled(next) { + enableOnPause = 0; + Protocol.Runtime.evaluate({ expression: 'test()//# sourceURL=expr1.js', + awaitPromise: true }) + .then(() => Protocol.Debugger.setAsyncCallStackDepth({ maxDepth: 0 })) + .then(next); + }, + + function afterAsyncTaskScheduled(next) { + enableOnPause = 2; + Protocol.Runtime.evaluate({ expression: 'test()//# sourceURL=expr1.js', + awaitPromise: true }) + .then(() => Protocol.Debugger.setAsyncCallStackDepth({ maxDepth: 0 })) + .then(next); + }, + + function afterAsyncTaskStarted(next) { + enableOnPause = 3; + Protocol.Runtime.evaluate({ expression: 'test()//# sourceURL=expr1.js', + awaitPromise: true }) + .then(() => Protocol.Debugger.setAsyncCallStackDepth({ maxDepth: 0 })) + .then(next); + } +]);
diff --git a/src/v8/test/inspector/debugger/async-promise-late-then-expected.txt b/src/v8/test/inspector/debugger/async-promise-late-then-expected.txt new file mode 100644 index 0000000..dfdf81f --- /dev/null +++ b/src/v8/test/inspector/debugger/async-promise-late-then-expected.txt
@@ -0,0 +1,16 @@ +Checks async stack for late .then handlers with gc +foo1 (test.js:11:2) +-- Promise.resolve -- +test (test.js:18:14) +(anonymous) (expr.js:0:0) + +foo1 (test.js:11:2) +-- Promise.resolve -- +test (test.js:22:14) +(anonymous) (expr.js:0:0) + +foo1 (test.js:11:2) +-- Promise.resolve -- +test (test.js:24:14) +(anonymous) (expr.js:0:0) +
diff --git a/src/v8/test/inspector/debugger/async-promise-late-then.js b/src/v8/test/inspector/debugger/async-promise-late-then.js new file mode 100644 index 0000000..cad3c7e --- /dev/null +++ b/src/v8/test/inspector/debugger/async-promise-late-then.js
@@ -0,0 +1,48 @@ +// 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-gc + +let {session, contextGroup, Protocol} = InspectorTest.start('Checks async stack for late .then handlers with gc'); + +contextGroup.addScript(` +function foo1() { + gc(); + debugger; +} + +function test() { + var resolve1; + var p1 = new Promise(resolve => resolve1 = resolve); + gc(); + var p2 = p1.then(foo1); + gc(); + resolve1(); + gc(); + var p3 = p1.then(foo1); + gc(); + var p4 = p1.then(foo1); + gc(); + return Promise.all([p2,p3,p4]); +} +//# sourceURL=test.js`, 8, 26); + +session.setupScriptMap(); +Protocol.Debugger.onPaused(message => { + session.logCallFrames(message.params.callFrames); + var asyncStackTrace = message.params.asyncStackTrace; + while (asyncStackTrace) { + InspectorTest.log(`-- ${asyncStackTrace.description} --`); + session.logCallFrames(asyncStackTrace.callFrames); + asyncStackTrace = asyncStackTrace.parent; + } + InspectorTest.log(''); + Protocol.Debugger.resume(); +}); + +Protocol.Debugger.enable(); +Protocol.Debugger.setAsyncCallStackDepth({ maxDepth: 128 }); +Protocol.Runtime.evaluate({ expression: 'test()//# sourceURL=expr.js', + awaitPromise: true }) + .then(() => Protocol.Runtime.evaluate({ expression: 'gc()'})) + .then(InspectorTest.completeTest);
diff --git a/src/v8/test/inspector/debugger/async-set-timeout-expected.txt b/src/v8/test/inspector/debugger/async-set-timeout-expected.txt new file mode 100644 index 0000000..80cbb1f --- /dev/null +++ b/src/v8/test/inspector/debugger/async-set-timeout-expected.txt
@@ -0,0 +1,11 @@ +Checks that async stack contains setTimeout +inner1 (test.js:11:4) +foo1 (test.js:14:2) +-- setTimeout -- +inner2 (test.js:18:4) +foo2 (test.js:20:2) +-- setTimeout -- +inner3 (test.js:25:4) +foo3 (test.js:27:2) +(anonymous) (expr.js:0:0) +
diff --git a/src/v8/test/inspector/debugger/async-set-timeout.js b/src/v8/test/inspector/debugger/async-set-timeout.js new file mode 100644 index 0000000..30096b6 --- /dev/null +++ b/src/v8/test/inspector/debugger/async-set-timeout.js
@@ -0,0 +1,48 @@ +// 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. + +let {session, contextGroup, Protocol} = InspectorTest.start('Checks that async stack contains setTimeout'); + +contextGroup.addScript(` +var resolveCallback; +function foo1() { + function inner1() { + debugger; + resolveCallback(); + } + inner1(); +} +function foo2() { + function inner2() { + setTimeout(foo1, 0); + } + inner2(); +} +function foo3() { + var promise = new Promise(resolve => resolveCallback = resolve); + function inner3() { + setTimeout(foo2, 0); + } + inner3(); + return promise; +} +//# sourceURL=test.js`, 7, 26); + +session.setupScriptMap(); +Protocol.Debugger.onPaused(message => { + session.logCallFrames(message.params.callFrames); + var asyncStackTrace = message.params.asyncStackTrace; + while (asyncStackTrace) { + InspectorTest.log(`-- ${asyncStackTrace.description} --`); + session.logCallFrames(asyncStackTrace.callFrames); + asyncStackTrace = asyncStackTrace.parent; + } + InspectorTest.log(''); + Protocol.Debugger.resume(); +}); + +Protocol.Debugger.enable(); +Protocol.Debugger.setAsyncCallStackDepth({ maxDepth: 128 }); +Protocol.Runtime.evaluate({ expression: "foo3()//# sourceURL=expr.js", awaitPromise: true }) + .then(InspectorTest.completeTest);
diff --git a/src/v8/test/inspector/debugger/async-stack-await-expected.txt b/src/v8/test/inspector/debugger/async-stack-await-expected.txt new file mode 100644 index 0000000..4ebcefa --- /dev/null +++ b/src/v8/test/inspector/debugger/async-stack-await-expected.txt
@@ -0,0 +1,42 @@ +Checks that async stacks works for async/await +foo2 (test.js:15:2) +-- async function -- +foo2 (test.js:13:19) +test (test.js:24:8) +(anonymous) (expr.js:0:0) + +foo2 (test.js:17:2) +-- async function -- +foo2 (test.js:13:19) +test (test.js:24:8) +(anonymous) (expr.js:0:0) + +foo1 (test.js:9:2) +foo2 (test.js:18:8) +-- async function -- +foo2 (test.js:13:19) +test (test.js:24:8) +(anonymous) (expr.js:0:0) + +foo1 (test.js:9:2) +-- Promise.resolve -- +foo2 (test.js:19:43) +-- async function -- +foo2 (test.js:13:19) +test (test.js:24:8) +(anonymous) (expr.js:0:0) + +foo2 (test.js:20:2) +-- async function -- +foo2 (test.js:13:19) +test (test.js:24:8) +(anonymous) (expr.js:0:0) + +{ + id : <messageId> + result : { + result : { + type : undefined + } + } +}
diff --git a/src/v8/test/inspector/debugger/async-stack-await.js b/src/v8/test/inspector/debugger/async-stack-await.js new file mode 100644 index 0000000..8f4b162 --- /dev/null +++ b/src/v8/test/inspector/debugger/async-stack-await.js
@@ -0,0 +1,41 @@ +// 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. + +let {session, contextGroup, Protocol} = InspectorTest.start('Checks that async stacks works for async/await'); + +contextGroup.addScript(` +async function foo1() { + debugger; + return Promise.resolve(); +} + +async function foo2() { + await Promise.resolve(); + debugger; + await Promise.resolve(); + debugger; + await foo1(); + await Promise.all([ Promise.resolve() ]).then(foo1); + debugger; +} + +async function test() { + await foo2(); +} +//# sourceURL=test.js`, 7, 26); + +session.setupScriptMap(); +Protocol.Debugger.onPaused(message => { + session.logCallFrames(message.params.callFrames); + session.logAsyncStackTrace(message.params.asyncStackTrace); + InspectorTest.log(''); + Protocol.Debugger.resume(); +}); + +Protocol.Debugger.enable(); +Protocol.Debugger.setAsyncCallStackDepth({ maxDepth: 128 }); +Protocol.Runtime.evaluate({ expression: 'test()//# sourceURL=expr.js', + awaitPromise: true }) + .then(InspectorTest.logMessage) + .then(InspectorTest.completeTest);
diff --git a/src/v8/test/inspector/debugger/async-stack-created-frame-expected.txt b/src/v8/test/inspector/debugger/async-stack-created-frame-expected.txt new file mode 100644 index 0000000..f5197a1 --- /dev/null +++ b/src/v8/test/inspector/debugger/async-stack-created-frame-expected.txt
@@ -0,0 +1,91 @@ +Checks created frame for async call chain + +Running test: testPromise +foo1 (test.js:10:2) +-- Promise.resolve -- +promise (test.js:20:14) +(anonymous) (expr.js:0:0) + + +Running test: testPromiseThen +foo1 (test.js:10:2) +-- Promise.resolve -- +promiseThen (test.js:28:14) +(anonymous) (expr.js:0:0) + +foo2 (test.js:14:2) +-- Promise.resolve -- +promiseThen (test.js:29:14) +(anonymous) (expr.js:0:0) + + +Running test: testPromiseThenThen +foo1 (test.js:10:2) +-- Promise.resolve -- +promiseThenThen (test.js:37:14) +(anonymous) (expr.js:0:0) + +foo1 (test.js:10:2) +-- Promise.resolve -- +promiseThenThen (test.js:38:14) +(anonymous) (expr.js:0:0) + +foo2 (test.js:14:2) +-- Promise.resolve -- +promiseThenThen (test.js:37:25) +(anonymous) (expr.js:0:0) + + +Running test: testPromiseResolve +foo1 (test.js:10:2) +-- Promise.resolve -- +promiseResolve (test.js:44:27) +(anonymous) (expr.js:0:0) + + +Running test: testPromiseReject +foo1 (test.js:10:2) +-- Promise.reject -- +promiseReject (test.js:48:31) +(anonymous) (expr.js:0:0) + + +Running test: testPromiseAll +foo1 (test.js:10:2) +-- Promise.resolve -- +promiseAll (test.js:52:44) +(anonymous) (expr.js:0:0) + + +Running test: testPromiseRace +foo1 (test.js:10:2) +-- Promise.resolve -- +promiseRace (test.js:56:45) +(anonymous) (expr.js:0:0) + + +Running test: testThenableJob1 +foo1 (test.js:10:2) +-- Promise.resolve -- +thenableJob1 (test.js:60:72) +(anonymous) (expr.js:0:0) + + +Running test: testThenableJob2 +foo1 (test.js:10:2) +-- Promise.resolve -- +thenableJob2 (test.js:64:57) +(anonymous) (expr.js:0:0) + + +Running test: testSetTimeouts +foo1 (test.js:10:2) +setTimeout (test.js:72:25) +-- setTimeout -- +setTimeout (test.js:72:6) +-- setTimeout -- +setTimeout (test.js:71:4) +-- setTimeout -- +setTimeouts (test.js:70:2) +(anonymous) (expr.js:0:0) +
diff --git a/src/v8/test/inspector/debugger/async-stack-created-frame.js b/src/v8/test/inspector/debugger/async-stack-created-frame.js new file mode 100644 index 0000000..0f2c7a1 --- /dev/null +++ b/src/v8/test/inspector/debugger/async-stack-created-frame.js
@@ -0,0 +1,179 @@ +// Copyright 2017 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. + +// TODO(kozyatinskiy): fix this test. +let {session, contextGroup, Protocol} = InspectorTest.start('Checks created frame for async call chain'); + +contextGroup.addScript( + ` +function foo1() { + debugger; +} + +function foo2() { + debugger; +} + +function promise() { + var resolve; + var p1 = new Promise(r => resolve = r); + var p2 = p1.then(foo1); + resolve(); + return p2; +} + +function promiseThen() { + var resolve; + var p1 = new Promise(r => resolve = r); + var p2 = p1.then(foo1); + var p3 = p2.then(foo2); + resolve(); + return p3; +} + +function promiseThenThen() { + var resolve; + var p1 = new Promise(r => resolve = r); + var p2 = p1.then(foo1).then(foo2); + var p3 = p1.then(foo1); + resolve(); + return p2; +} + +function promiseResolve() { + return Promise.resolve().then(foo1); +} + +function promiseReject() { + return Promise.reject().catch(foo1); +} + +function promiseAll() { + return Promise.all([ Promise.resolve() ]).then(foo1); +} + +function promiseRace() { + return Promise.race([ Promise.resolve() ]).then(foo1); +} + +function thenableJob1() { + return Promise.resolve().then(() => Promise.resolve().then(() => 42)).then(foo1); +} + +function thenableJob2() { + return Promise.resolve().then(() => Promise.resolve()).then(foo1); +} + +function setTimeouts() { + var resolve; + var p = new Promise(r => resolve = r); + setTimeout(() => + setTimeout(() => + setTimeout(() => { foo1(); resolve(); }, 0), 0), 0); + return p; +} + +//# sourceURL=test.js`, + 8, 4); + +session.setupScriptMap(); +Protocol.Debugger.onPaused(message => { + session.logCallFrames(message.params.callFrames); + session.logAsyncStackTrace(message.params.asyncStackTrace); + InspectorTest.log(''); + Protocol.Debugger.resume(); +}); + +Protocol.Debugger.enable(); +Protocol.Debugger.setAsyncCallStackDepth({maxDepth: 128}); + +InspectorTest.runTestSuite([ + function testPromise(next) { + Protocol.Runtime + .evaluate( + {expression: 'promise()//# sourceURL=expr.js', awaitPromise: true}) + .then(next); + }, + + function testPromiseThen(next) { + Protocol.Runtime + .evaluate({ + expression: 'promiseThen()//# sourceURL=expr.js', + awaitPromise: true + }) + .then(next); + }, + + function testPromiseThenThen(next) { + Protocol.Runtime + .evaluate({ + expression: 'promiseThenThen()//# sourceURL=expr.js', + awaitPromise: true + }) + .then(next); + }, + + function testPromiseResolve(next) { + Protocol.Runtime + .evaluate({ + expression: 'promiseResolve()//# sourceURL=expr.js', + awaitPromise: true + }) + .then(next); + }, + + function testPromiseReject(next) { + Protocol.Runtime + .evaluate({ + expression: 'promiseReject()//# sourceURL=expr.js', + awaitPromise: true + }) + .then(next); + }, + + function testPromiseAll(next) { + Protocol.Runtime + .evaluate({ + expression: 'promiseAll()//# sourceURL=expr.js', + awaitPromise: true + }) + .then(next); + }, + + function testPromiseRace(next) { + Protocol.Runtime + .evaluate({ + expression: 'promiseRace()//# sourceURL=expr.js', + awaitPromise: true + }) + .then(next); + }, + + function testThenableJob1(next) { + Protocol.Runtime + .evaluate({ + expression: 'thenableJob1()//# sourceURL=expr.js', + awaitPromise: true + }) + .then(next); + }, + + function testThenableJob2(next) { + Protocol.Runtime + .evaluate({ + expression: 'thenableJob2()//# sourceURL=expr.js', + awaitPromise: true + }) + .then(next); + }, + + function testSetTimeouts(next) { + Protocol.Runtime + .evaluate({ + expression: 'setTimeouts()//# sourceURL=expr.js', + awaitPromise: true + }) + .then(next); + } +]);
diff --git a/src/v8/test/inspector/debugger/async-stack-for-promise-expected.txt b/src/v8/test/inspector/debugger/async-stack-for-promise-expected.txt new file mode 100644 index 0000000..8164084 --- /dev/null +++ b/src/v8/test/inspector/debugger/async-stack-for-promise-expected.txt
@@ -0,0 +1,119 @@ +Checks that async chains for promises are correct. + +Running test: testPromise +foo1 (test.js:9:2) +-- Promise.resolve -- +promise (test.js:19:14) +(anonymous) (testPromise.js:0:0) + + +Running test: testPromiseResolvedBySetTimeout +foo1 (test.js:9:2) +-- Promise.resolve -- +promiseResolvedBySetTimeout (test.js:27:14) +(anonymous) (testPromiseResolvedBySetTimeout.js:0:0) + + +Running test: testPromiseAll +foo1 (test.js:9:2) +-- Promise.resolve -- +promiseAll (test.js:37:35) +(anonymous) (testPromiseAll.js:0:0) + + +Running test: testPromiseAllReverseOrder +foo1 (test.js:9:2) +-- Promise.resolve -- +promiseAllReverseOrder (test.js:48:35) +(anonymous) (testPromiseAllReverseOrder.js:0:0) + + +Running test: testPromiseRace +foo1 (test.js:9:2) +-- Promise.resolve -- +promiseRace (test.js:59:36) +(anonymous) (testPromiseRace.js:0:0) + + +Running test: testTwoChainedCallbacks +foo1 (test.js:9:2) +-- Promise.resolve -- +twoChainedCallbacks (test.js:68:14) +(anonymous) (testTwoChainedCallbacks.js:0:0) + +foo2 (test.js:13:2) +-- Promise.resolve -- +twoChainedCallbacks (test.js:68:25) +(anonymous) (testTwoChainedCallbacks.js:0:0) + + +Running test: testPromiseResolve +foo1 (test.js:9:2) +-- Promise.resolve -- +promiseResolve (test.js:74:27) +(anonymous) (testPromiseResolve.js:0:0) + +foo2 (test.js:13:2) +-- Promise.resolve -- +promiseResolve (test.js:74:38) +(anonymous) (testPromiseResolve.js:0:0) + + +Running test: testThenableJobResolvedInSetTimeout +foo1 (test.js:9:2) +-- Promise.resolve -- +thenableJobResolvedInSetTimeout (test.js:86:40) +(anonymous) (testThenableJobResolvedInSetTimeout.js:0:0) + + +Running test: testThenableJobResolvedInSetTimeoutWithStack +foo1 (test.js:9:2) +-- Promise.resolve -- +thenableJobResolvedInSetTimeoutWithStack (test.js:104:40) +(anonymous) (testThenableJobResolvedInSetTimeoutWithStack.js:0:0) + + +Running test: testThenableJobResolvedByPromise +foo1 (test.js:9:2) +-- Promise.resolve -- +thenableJobResolvedByPromise (test.js:118:40) +(anonymous) (testThenableJobResolvedByPromise.js:0:0) + + +Running test: testThenableJobResolvedByPromiseWithStack +foo1 (test.js:9:2) +-- Promise.resolve -- +thenableJobResolvedByPromiseWithStack (test.js:136:40) +(anonymous) (testThenableJobResolvedByPromiseWithStack.js:0:0) + + +Running test: testLateThenCallback +foo1 (test.js:9:2) +-- Promise.resolve -- +lateThenCallback (test.js:145:12) +(anonymous) (testLateThenCallback.js:0:0) + + +Running test: testComplex +inner1 (test.js:154:6) +foo1 (test.js:156:4) +-- Promise.resolve -- +complex (test.js:202:5) +(anonymous) (testComplex.js:0:0) + +p.then (test.js:207:8) +-- Promise.resolve -- +p.then (test.js:206:8) +-- Promise.resolve -- +setTimeout (test.js:205:6) +-- setTimeout -- +complex (test.js:204:2) +(anonymous) (testComplex.js:0:0) + + +Running test: testReject +foo1 (test.js:9:2) +-- Promise.reject -- +reject (test.js:217:31) +(anonymous) (testReject.js:0:0) +
diff --git a/src/v8/test/inspector/debugger/async-stack-for-promise.js b/src/v8/test/inspector/debugger/async-stack-for-promise.js new file mode 100644 index 0000000..198c971 --- /dev/null +++ b/src/v8/test/inspector/debugger/async-stack-for-promise.js
@@ -0,0 +1,260 @@ +// 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. + +let {session, contextGroup, Protocol} = InspectorTest.start('Checks that async chains for promises are correct.'); + +contextGroup.addScript(` +function foo1() { + debugger; +} + +function foo2() { + debugger; +} + +function promise() { + var resolve; + var p1 = new Promise(r => resolve = r); + var p2 = p1.then(foo1); + resolve(); + return p2; +} + +function promiseResolvedBySetTimeout() { + var resolve; + var p1 = new Promise(r => resolve = r); + var p2 = p1.then(foo1); + setTimeout(resolve, 0); + return p2; +} + +function promiseAll() { + var resolve1; + var resolve2; + var p1 = new Promise(resolve => resolve1 = resolve); + var p2 = new Promise(resolve => resolve2 = resolve); + var p3 = Promise.all([ p1, p2 ]).then(foo1); + resolve1(); + resolve2(); + return p3; +} + +function promiseAllReverseOrder() { + var resolve1; + var resolve2; + var p1 = new Promise(resolve => resolve1 = resolve); + var p2 = new Promise(resolve => resolve2 = resolve); + var p3 = Promise.all([ p1, p2 ]).then(foo1); + resolve2(); + resolve1(); + return p3; +} + +function promiseRace() { + var resolve1; + var resolve2; + var p1 = new Promise(resolve => resolve1 = resolve); + var p2 = new Promise(resolve => resolve2 = resolve); + var p3 = Promise.race([ p1, p2 ]).then(foo1); + resolve1(); + resolve2(); + return p3; +} + +function twoChainedCallbacks() { + var resolve1; + var p1 = new Promise(resolve => resolve1 = resolve); + var p2 = p1.then(foo1).then(foo2); + resolve1(); + return p2; +} + +function promiseResolve() { + return Promise.resolve().then(foo1).then(foo2); +} + +function thenableJobResolvedInSetTimeout() { + function thenableJob() { + var resolve2; + var p2 = new Promise(resolve => resolve2 = resolve); + setTimeout(resolve2, 0); + return p2; + } + var resolve1; + var p1 = new Promise(resolve => resolve1 = resolve); + var p3 = p1.then(() => thenableJob()).then(foo1); + resolve1(); + return p3; +} + +function thenableJobResolvedInSetTimeoutWithStack() { + function thenableJob() { + function inner() { + resolve2(); + } + + var resolve2; + var p2 = new Promise(resolve => resolve2 = resolve); + setTimeout(inner, 0); + return p2; + } + var resolve1; + var p1 = new Promise(resolve => resolve1 = resolve); + var p3 = p1.then(() => thenableJob()).then(foo1); + resolve1(); + return p3; +} + +function thenableJobResolvedByPromise() { + function thenableJob() { + var resolve2; + var p2 = new Promise(resolve => resolve2 = resolve); + Promise.resolve().then(resolve2); + return p2; + } + var resolve1; + var p1 = new Promise(resolve => resolve1 = resolve); + var p3 = p1.then(() => thenableJob()).then(foo1); + resolve1(); + return p3; +} + +function thenableJobResolvedByPromiseWithStack() { + function thenableJob() { + function inner() { + resolve2(); + } + + var resolve2; + var p2 = new Promise(resolve => resolve2 = resolve); + Promise.resolve().then(inner); + return p2; + } + var resolve1; + var p1 = new Promise(resolve => resolve1 = resolve); + var p3 = p1.then(() => thenableJob()).then(foo1); + resolve1(); + return p3; +} + +function lateThenCallback() { + var resolve1; + var p1 = new Promise(resolve => resolve1 = resolve); + resolve1(); + return p1.then(foo1); +} + +function complex() { + var testResolve; + var testPromise = new Promise(resolve => testResolve = resolve); + + function foo1() { + function inner1() { + debugger; + } + inner1(); + } + + function foo2() { + var resolve20; + function inner2() { + resolve20(); + } + var p20 = new Promise(resolve => resolve20 = resolve); + Promise.resolve().then(inner2); + return p20; + } + + function foo3() { + var resolve17; + function inner3() { + resolve17(); + } + var p17 = new Promise(resolve => resolve17 = resolve); + setTimeout(inner3, 0); + return p17; + } + + function foo4() { + function inner4() { + return; + } + return inner4(); + } + + function foo5() { + return Promise.all([ Promise.resolve(), Promise.resolve() ]) + .then(() => 42); + } + + function foo6() { + return Promise.race([ Promise.resolve(), Promise.resolve()]) + .then(() => 42); + } + + var p = Promise.resolve() + .then(foo6) + .then(foo5) + .then(foo4) + .then(foo3) + .then(foo2) + .then(foo1); + + setTimeout(() => { + p.then(() => { + p.then(() => { + debugger; + testResolve(); + }) + }) + }, 0) + + return testPromise; +} + +function reject() { + return Promise.reject().catch(foo1); +} + +//# sourceURL=test.js`, 7, 26); + +session.setupScriptMap(); +Protocol.Debugger.onPaused(message => { + session.logCallFrames(message.params.callFrames); + session.logAsyncStackTrace(message.params.asyncStackTrace); + InspectorTest.log(''); + Protocol.Debugger.resume(); +}); + +Protocol.Debugger.enable(); +Protocol.Debugger.setAsyncCallStackDepth({ maxDepth: 128 }); +var testList = [ + 'promise', + 'promiseResolvedBySetTimeout', + 'promiseAll', + 'promiseAllReverseOrder', + 'promiseRace', + 'twoChainedCallbacks', + 'promiseResolve', + 'thenableJobResolvedInSetTimeout', + 'thenableJobResolvedInSetTimeoutWithStack', + 'thenableJobResolvedByPromise', + 'thenableJobResolvedByPromiseWithStack', + 'lateThenCallback', + 'complex', + 'reject', +] +InspectorTest.runTestSuite(testList.map(name => { + return eval(` + (function test${capitalize(name)}(next) { + Protocol.Runtime.evaluate({ expression: \`${name}() +//# sourceURL=test${capitalize(name)}.js\`, awaitPromise: true}) + .then(next); + }) + `); +})); + +function capitalize(string) { + return string.charAt(0).toUpperCase() + string.slice(1); +}
diff --git a/src/v8/test/inspector/debugger/break-location-function-calls-expected.txt b/src/v8/test/inspector/debugger/break-location-function-calls-expected.txt new file mode 100644 index 0000000..23e30a4 --- /dev/null +++ b/src/v8/test/inspector/debugger/break-location-function-calls-expected.txt
@@ -0,0 +1,219 @@ +Break locations around function calls + +Running test: testFunctionCallAsArgument +Break locations in expression: +function test() { +|C|foo2(|C|foo1()) +} + +Breakpoint at: +function test() { +#foo2(foo1()) +} + +Break at: +function test() { +#foo2(foo1()) +} + +Debugger.stepInto called + +function foo1() {#} +function foo2() {} + +Breakpoint at: +function test() { +foo2(#foo1()) +} + +Break at: +function test() { +foo2(#foo1()) +} + +Debugger.stepInto called + +function foo1() {#} +function foo2() {} + +Breakpoint at expression line. +function test() { +#foo2(foo1()) +} + +Debugger.stepInto called + +function foo1() {#} +function foo2() {} + + +Running test: testFunctionCallAsArgument +Break locations in expression: +function test() { +|C|foo2(|C|foo1()); +} + +Breakpoint at: +function test() { +#foo2(foo1()); +} + +Break at: +function test() { +#foo2(foo1()); +} + +Debugger.stepInto called + +function foo1() {#} +function foo2() {} + +Breakpoint at: +function test() { +foo2(#foo1()); +} + +Break at: +function test() { +foo2(#foo1()); +} + +Debugger.stepInto called + +function foo1() {#} +function foo2() {} + +Breakpoint at expression line. +function test() { +#foo2(foo1()); +} + +Debugger.stepInto called + +function foo1() {#} +function foo2() {} + + +Running test: testFunctionCallAsArguments +Break locations in expression: +function test() { +|C|foo3(|C|foo1(), |C|foo2()); +} + +Breakpoint at: +function test() { +#foo3(foo1(), foo2()); +} + +Break at: +function test() { +#foo3(foo1(), foo2()); +} + +Debugger.stepInto called + +function foo1() {#} +function foo2() {} + +Breakpoint at: +function test() { +foo3(#foo1(), foo2()); +} + +Break at: +function test() { +foo3(#foo1(), foo2()); +} + +Debugger.stepInto called + +function foo1() {#} +function foo2() {} + +Breakpoint at: +function test() { +foo3(foo1(), #foo2()); +} + +Break at: +function test() { +foo3(foo1(), #foo2()); +} + +Debugger.stepInto called +function foo1() {} +function foo2() {#} +function foo3() {} + +Breakpoint at expression line. +function test() { +#foo3(foo1(), foo2()); +} + +Debugger.stepInto called + +function foo1() {#} +function foo2() {} + + +Running test: testFunctionCallInBinaryExpression +Break locations in expression: +function test() { +|C|foo3(|C|foo1() + |C|foo2()); +} + +Breakpoint at: +function test() { +#foo3(foo1() + foo2()); +} + +Break at: +function test() { +#foo3(foo1() + foo2()); +} + +Debugger.stepInto called + +function foo1() {#} +function foo2() {} + +Breakpoint at: +function test() { +foo3(#foo1() + foo2()); +} + +Break at: +function test() { +foo3(#foo1() + foo2()); +} + +Debugger.stepInto called + +function foo1() {#} +function foo2() {} + +Breakpoint at: +function test() { +foo3(foo1() + #foo2()); +} + +Break at: +function test() { +foo3(foo1() + #foo2()); +} + +Debugger.stepInto called +function foo1() {} +function foo2() {#} +function foo3() {} + +Breakpoint at expression line. +function test() { +#foo3(foo1() + foo2()); +} + +Debugger.stepInto called + +function foo1() {#} +function foo2() {} +
diff --git a/src/v8/test/inspector/debugger/break-location-function-calls.js b/src/v8/test/inspector/debugger/break-location-function-calls.js new file mode 100644 index 0000000..c32eaff --- /dev/null +++ b/src/v8/test/inspector/debugger/break-location-function-calls.js
@@ -0,0 +1,82 @@ +// Copyright 2017 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. + +let {session, contextGroup, Protocol} = + InspectorTest.start('Break locations around function calls'); + +contextGroup.addScript(` +function foo1() {} +function foo2() {} +function foo3() {} +//# sourceURL=test.js`); + +InspectorTest.logProtocolCommandCalls('Debugger.stepInto'); +session.setupScriptMap(); +InspectorTest.runAsyncTestSuite([ + async function testFunctionCallAsArgument() { + await testExpression('foo2(foo1())'); + }, + + async function testFunctionCallAsArgument() { + await testExpression('foo2(foo1());'); + }, + + async function testFunctionCallAsArguments() { + await testExpression('foo3(foo1(), foo2());'); + }, + + async function testFunctionCallInBinaryExpression() { + await testExpression('foo3(foo1() + foo2());'); + }, +]); + +async function logPauseLocation() { + let {params:{callFrames}} = await Protocol.Debugger.oncePaused(); + session.logSourceLocation(callFrames[0].location); +} + +async function testExpression(expression) { + await Protocol.Debugger.enable(); + let wrapper = `function test() { +${expression} +} +//# sourceURL=test-function.js`; + Protocol.Runtime.evaluate({expression: wrapper}); + let {params:{scriptId}} = await Protocol.Debugger.onceScriptParsed(); + let {result:{locations}} = await Protocol.Debugger.getPossibleBreakpoints({ + start: {lineNumber: 0, columnNumber : 0, scriptId}}); + locations = locations.filter(location => location.lineNumber === 1); + InspectorTest.log('Break locations in expression:'); + await session.logBreakLocations(locations); + + for (let location of locations) { + InspectorTest.log('Breakpoint at:'); + await session.logSourceLocation(location); + let {result:{breakpointId}} = await Protocol.Debugger.setBreakpoint({ + location}); + let evaluate = Protocol.Runtime.evaluate({ + expression: 'test();\n//# sourceURL=expr.js'}); + InspectorTest.log('Break at:'); + await logPauseLocation(); + Protocol.Debugger.stepInto(); + await logPauseLocation(); + await Protocol.Debugger.removeBreakpoint({breakpointId}); + Protocol.Debugger.resume(); + await evaluate; + } + + InspectorTest.log('Breakpoint at expression line.') + let {result:{breakpointId}} = await Protocol.Debugger.setBreakpointByUrl({ + lineNumber: 1, url: 'test-function.js'}); + let evaluate = Protocol.Runtime.evaluate({ + expression: 'test();\n//# sourceURL=expr.js'}); + await logPauseLocation(); + Protocol.Debugger.stepInto(); + await logPauseLocation(); + await Protocol.Debugger.removeBreakpoint({breakpointId}); + Protocol.Debugger.resume(); + await evaluate; + + await Protocol.Debugger.disable(); +}
diff --git a/src/v8/test/inspector/debugger/break-locations-await-expected.txt b/src/v8/test/inspector/debugger/break-locations-await-expected.txt new file mode 100644 index 0000000..1bf0317 --- /dev/null +++ b/src/v8/test/inspector/debugger/break-locations-await-expected.txt
@@ -0,0 +1,361 @@ +Tests breakable locations in await expression. + +Running test: testBreakLocations + +function testFunction() { + async function f1() { + for (let x = |_|0; x |_|< 1; ++|_|x) |_|await x; + |_|return await Promise.|C|resolve(2); + |R|} + + async function f2() { + let r = |_|await |C|f1() + await |C|f1(); + |_|await |C|f1(); + |_|await |C|f1().|C|then(x => x |_|* 2|R|); + |_|await [1].|C|map(x => Promise.|C|resolve(x)|R|)[0]; + |_|await Promise.|C|resolve().|C|then(x => x |_|* 2|R|); + let p = |_|Promise.|C|resolve(42); + |_|await p; + |_|return r; + |R|} + + return |C|f2();|R| +} + + +Running test: testStepInto +(anonymous) (expr.js:0:0) + + +testFunction (test.js:18:9) +(anonymous) (expr.js:0:0) + + return #f2(); +} + +f2 (test.js:8:12) +testFunction (test.js:18:9) +(anonymous) (expr.js:0:0) + async function f2() { + let r = #await f1() + await f1(); + await f1(); + +f1 (test.js:3:17) +f2 (test.js:8:18) +testFunction (test.js:18:9) +(anonymous) (expr.js:0:0) + async function f1() { + for (let x = #0; x < 1; ++x) await x; + return await Promise.resolve(2); + +f1 (test.js:3:22) +f2 (test.js:8:18) +testFunction (test.js:18:9) +(anonymous) (expr.js:0:0) + async function f1() { + for (let x = 0; x #< 1; ++x) await x; + return await Promise.resolve(2); + +f1 (test.js:3:32) +f2 (test.js:8:18) +testFunction (test.js:18:9) +(anonymous) (expr.js:0:0) + async function f1() { + for (let x = 0; x < 1; ++x) #await x; + return await Promise.resolve(2); + +f1 (test.js:3:29) + async function f1() { + for (let x = 0; x < 1; ++#x) await x; + return await Promise.resolve(2); + +f1 (test.js:3:22) + async function f1() { + for (let x = 0; x #< 1; ++x) await x; + return await Promise.resolve(2); + +f1 (test.js:4:4) + for (let x = 0; x < 1; ++x) await x; + #return await Promise.resolve(2); + } + +f1 (test.js:5:2) + return await Promise.resolve(2); + #} + + +f2 (test.js:8:31) + async function f2() { + let r = await f1() + await #f1(); + await f1(); + +f1 (test.js:3:17) +f2 (test.js:8:31) + async function f1() { + for (let x = #0; x < 1; ++x) await x; + return await Promise.resolve(2); + +f1 (test.js:3:22) +f2 (test.js:8:31) + async function f1() { + for (let x = 0; x #< 1; ++x) await x; + return await Promise.resolve(2); + +f1 (test.js:3:32) +f2 (test.js:8:31) + async function f1() { + for (let x = 0; x < 1; ++x) #await x; + return await Promise.resolve(2); + +f1 (test.js:3:29) + async function f1() { + for (let x = 0; x < 1; ++#x) await x; + return await Promise.resolve(2); + +f1 (test.js:3:22) + async function f1() { + for (let x = 0; x #< 1; ++x) await x; + return await Promise.resolve(2); + +f1 (test.js:4:4) + for (let x = 0; x < 1; ++x) await x; + #return await Promise.resolve(2); + } + +f1 (test.js:5:2) + return await Promise.resolve(2); + #} + + +f2 (test.js:9:4) + let r = await f1() + await f1(); + #await f1(); + await f1().then(x => x * 2); + +f1 (test.js:3:17) +f2 (test.js:9:10) + async function f1() { + for (let x = #0; x < 1; ++x) await x; + return await Promise.resolve(2); + +f1 (test.js:3:22) +f2 (test.js:9:10) + async function f1() { + for (let x = 0; x #< 1; ++x) await x; + return await Promise.resolve(2); + +f1 (test.js:3:32) +f2 (test.js:9:10) + async function f1() { + for (let x = 0; x < 1; ++x) #await x; + return await Promise.resolve(2); + +f1 (test.js:3:29) + async function f1() { + for (let x = 0; x < 1; ++#x) await x; + return await Promise.resolve(2); + +f1 (test.js:3:22) + async function f1() { + for (let x = 0; x #< 1; ++x) await x; + return await Promise.resolve(2); + +f1 (test.js:4:4) + for (let x = 0; x < 1; ++x) await x; + #return await Promise.resolve(2); + } + +f1 (test.js:5:2) + return await Promise.resolve(2); + #} + + +f2 (test.js:10:4) + await f1(); + #await f1().then(x => x * 2); + await [1].map(x => Promise.resolve(x))[0]; + +f1 (test.js:3:17) +f2 (test.js:10:10) + async function f1() { + for (let x = #0; x < 1; ++x) await x; + return await Promise.resolve(2); + +f1 (test.js:3:22) +f2 (test.js:10:10) + async function f1() { + for (let x = 0; x #< 1; ++x) await x; + return await Promise.resolve(2); + +f1 (test.js:3:32) +f2 (test.js:10:10) + async function f1() { + for (let x = 0; x < 1; ++x) #await x; + return await Promise.resolve(2); + +f1 (test.js:3:29) + async function f1() { + for (let x = 0; x < 1; ++#x) await x; + return await Promise.resolve(2); + +f1 (test.js:3:22) + async function f1() { + for (let x = 0; x #< 1; ++x) await x; + return await Promise.resolve(2); + +f1 (test.js:4:4) + for (let x = 0; x < 1; ++x) await x; + #return await Promise.resolve(2); + } + +f1 (test.js:5:2) + return await Promise.resolve(2); + #} + + +f1.then.x (test.js:10:27) + await f1(); + await f1().then(x => x #* 2); + await [1].map(x => Promise.resolve(x))[0]; + +f1.then.x (test.js:10:30) + await f1(); + await f1().then(x => x * 2#); + await [1].map(x => Promise.resolve(x))[0]; + +f2 (test.js:11:4) + await f1().then(x => x * 2); + #await [1].map(x => Promise.resolve(x))[0]; + await Promise.resolve().then(x => x * 2); + +map.x (test.js:11:31) +f2 (test.js:11:14) + await f1().then(x => x * 2); + await [1].map(x => Promise.#resolve(x))[0]; + await Promise.resolve().then(x => x * 2); + +map.x (test.js:11:41) +f2 (test.js:11:14) + await f1().then(x => x * 2); + await [1].map(x => Promise.resolve(x)#)[0]; + await Promise.resolve().then(x => x * 2); + +f2 (test.js:12:4) + await [1].map(x => Promise.resolve(x))[0]; + #await Promise.resolve().then(x => x * 2); + let p = Promise.resolve(42); + +f2 (test.js:13:12) + await Promise.resolve().then(x => x * 2); + let p = #Promise.resolve(42); + await p; + +f2 (test.js:14:4) + let p = Promise.resolve(42); + #await p; + return r; + +f2 (test.js:15:4) + await p; + #return r; + } + +f2 (test.js:16:2) + return r; + #} + + + +Running test: testStepOver +f2 (test.js:8:12) +testFunction (test.js:18:9) +(anonymous) (expr.js:0:0) + async function f2() { + let r = #await f1() + await f1(); + await f1(); + +f2 (test.js:8:31) + async function f2() { + let r = await f1() + await #f1(); + await f1(); + +f2 (test.js:9:4) + let r = await f1() + await f1(); + #await f1(); + await f1().then(x => x * 2); + +f2 (test.js:10:4) + await f1(); + #await f1().then(x => x * 2); + await [1].map(x => Promise.resolve(x))[0]; + +f2 (test.js:11:4) + await f1().then(x => x * 2); + #await [1].map(x => Promise.resolve(x))[0]; + await Promise.resolve().then(x => x * 2); + +f2 (test.js:12:4) + await [1].map(x => Promise.resolve(x))[0]; + #await Promise.resolve().then(x => x * 2); + let p = Promise.resolve(42); + +f2 (test.js:13:12) + await Promise.resolve().then(x => x * 2); + let p = #Promise.resolve(42); + await p; + +f2 (test.js:14:4) + let p = Promise.resolve(42); + #await p; + return r; + +f2 (test.js:15:4) + await p; + #return r; + } + +f2 (test.js:16:2) + return r; + #} + + + +Running test: testStepIntoAfterBreakpoint +f2 (test.js:9:4) + let r = await f1() + await f1(); + #await f1(); + await f1().then(x => x * 2); + +f1 (test.js:3:17) +f2 (test.js:9:10) + async function f1() { + for (let x = #0; x < 1; ++x) await x; + return await Promise.resolve(2); + +f1 (test.js:3:22) +f2 (test.js:9:10) + async function f1() { + for (let x = 0; x #< 1; ++x) await x; + return await Promise.resolve(2); + +f1 (test.js:3:32) +f2 (test.js:9:10) + async function f1() { + for (let x = 0; x < 1; ++x) #await x; + return await Promise.resolve(2); + +f1 (test.js:3:29) + async function f1() { + for (let x = 0; x < 1; ++#x) await x; + return await Promise.resolve(2); + +f1 (test.js:3:22) + async function f1() { + for (let x = 0; x #< 1; ++x) await x; + return await Promise.resolve(2); + +f1 (test.js:4:4) + for (let x = 0; x < 1; ++x) await x; + #return await Promise.resolve(2); + } +
diff --git a/src/v8/test/inspector/debugger/break-locations-await.js b/src/v8/test/inspector/debugger/break-locations-await.js new file mode 100644 index 0000000..665ab83 --- /dev/null +++ b/src/v8/test/inspector/debugger/break-locations-await.js
@@ -0,0 +1,126 @@ +// Copyright 2017 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. + +let {session, contextGroup, Protocol} = + InspectorTest.start('Tests breakable locations in await expression.'); + +let source = ` +function testFunction() { + async function f1() { + for (let x = 0; x < 1; ++x) await x; + return await Promise.resolve(2); + } + + async function f2() { + let r = await f1() + await f1(); + await f1(); + await f1().then(x => x * 2); + await [1].map(x => Promise.resolve(x))[0]; + await Promise.resolve().then(x => x * 2); + let p = Promise.resolve(42); + await p; + return r; + } + + return f2(); +} +//# sourceURL=test.js`; + +contextGroup.addScript(source); +session.setupScriptMap(); + +InspectorTest.runAsyncTestSuite([ + async function testBreakLocations() { + Protocol.Debugger.enable(); + let {params:{scriptId}} = await Protocol.Debugger.onceScriptParsed(); + let {result:{locations}} = await Protocol.Debugger.getPossibleBreakpoints({ + start: {lineNumber: 0, columnNumber : 0, scriptId}}); + dumpAllLocations(locations); + }, + + async function testStepInto() { + Protocol.Debugger.pause(); + let fin = Protocol.Runtime.evaluate({ + expression: 'testFunction()//# sourceURL=expr.js', awaitPromise: true}).then(() => false); + let result; + while (result = await Promise.race([fin, Protocol.Debugger.oncePaused()])) { + let {params:{callFrames}} = result; + session.logCallFrames(callFrames); + session.logSourceLocation(callFrames[0].location); + Protocol.Debugger.stepInto(); + } + Protocol.Runtime.evaluate({expression: '42'}); + await Protocol.Debugger.oncePaused(); + await Protocol.Debugger.resume(); + }, + + async function testStepOver() { + Protocol.Debugger.pause(); + let fin = Protocol.Runtime.evaluate({ + expression: 'testFunction()//# sourceURL=expr.js', awaitPromise: true}).then(() => false); + Protocol.Debugger.stepInto(); + await Protocol.Debugger.oncePaused(); + Protocol.Debugger.stepInto(); + await Protocol.Debugger.oncePaused(); + + let result; + while (result = await Promise.race([fin, Protocol.Debugger.oncePaused()])) { + let {params:{callFrames}} = result; + session.logCallFrames(callFrames); + session.logSourceLocation(callFrames[0].location); + Protocol.Debugger.stepOver(); + } + Protocol.Runtime.evaluate({expression: '42'}); + await Protocol.Debugger.oncePaused(); + await Protocol.Debugger.resume(); + }, + + async function testStepIntoAfterBreakpoint() { + Protocol.Debugger.setBreakpointByUrl({lineNumber: 9, url: 'test.js'}); + Protocol.Runtime.evaluate({ + expression: 'testFunction()//# sourceURL=expr.js'}); + await awaitPausedAndDump(); + Protocol.Debugger.stepInto(); + await awaitPausedAndDump(); + Protocol.Debugger.stepInto(); + await awaitPausedAndDump(); + Protocol.Debugger.stepInto(); + await awaitPausedAndDump(); + Protocol.Debugger.stepInto(); + await awaitPausedAndDump(); + Protocol.Debugger.stepInto(); + await awaitPausedAndDump(); + Protocol.Debugger.stepInto(); + await awaitPausedAndDump(); + await Protocol.Debugger.resume(); + + async function awaitPausedAndDump() { + let {params:{callFrames}} = await Protocol.Debugger.oncePaused(); + session.logCallFrames(callFrames); + session.logSourceLocation(callFrames[0].location); + } + } +]); + +function dumpAllLocations(locations) { + var lines = source.split('\n'); + var locations = locations.sort((loc1, loc2) => { + if (loc2.lineNumber !== loc1.lineNumber) return loc2.lineNumber - loc1.lineNumber; + return loc2.columnNumber - loc1.columnNumber; + }); + for (var location of locations) { + var line = lines[location.lineNumber]; + line = line.slice(0, location.columnNumber) + locationMark(location.type) + line.slice(location.columnNumber); + lines[location.lineNumber] = line; + } + lines = lines.filter(line => line.indexOf('//# sourceURL=') === -1); + InspectorTest.log(lines.join('\n') + '\n'); +} + +function locationMark(type) { + if (type === 'return') return '|R|'; + if (type === 'call') return '|C|'; + if (type === 'debuggerStatement') return '|D|'; + return '|_|'; +}
diff --git a/src/v8/test/inspector/debugger/break-locations-var-init-expected.txt b/src/v8/test/inspector/debugger/break-locations-var-init-expected.txt new file mode 100644 index 0000000..2242088 --- /dev/null +++ b/src/v8/test/inspector/debugger/break-locations-var-init-expected.txt
@@ -0,0 +1,170 @@ +Tests breakable locations in variable initializations. + +Running test: testBreakLocations + +Running test: testStepInto + +function testFunction() { + var obj1 = |_|{a : 1}; + var arr1 = |_|[1]; + var promise = |_|Promise.|C|resolve(1).|C|then(x => x |_|* 2|R|).|C|then(x => x |_|/ 2|R|); + |_|Promise.|C|resolve(1).|C|then(x => x |_|* 2|R|).|C|then(x => x |_|/ 2|R|); + |_|promise = Promise.|C|resolve(1).|C|then(x => x |_|* 2|R|).|C|then(x => x |_|/ 2|R|); + var a = |_|1; + const x = |_|(a = 20); + var y = |_|(a = 100); + var z = |_|x + (a = 1) + (a = 2) + (a = 3) + |C|f(); + function f() { + for (let { x, y } = |_|{ x: 0, y: 1 }; y |_|> 0; --|_|y) { let z = |_|x + y; } + |R|} + var b = obj1.|_|a; + |_|(async function asyncF() { + let r = |_|await Promise.|C|resolve(42); + |_|return r; + |R|})|C|(); + |_|return promise;|R| +} + +(anonymous) (expr.js:0:0) + + +testFunction (test.js:2:13) +(anonymous) (expr.js:0:0) +function testFunction() { + var obj1 = #{a : 1}; + var arr1 = [1]; + +testFunction (test.js:3:13) +(anonymous) (expr.js:0:0) + var obj1 = {a : 1}; + var arr1 = #[1]; + var promise = Promise.resolve(1).then(x => x * 2).then(x => x / 2); + +testFunction (test.js:4:16) +(anonymous) (expr.js:0:0) + var arr1 = [1]; + var promise = #Promise.resolve(1).then(x => x * 2).then(x => x / 2); + Promise.resolve(1).then(x => x * 2).then(x => x / 2); + +testFunction (test.js:5:2) +(anonymous) (expr.js:0:0) + var promise = Promise.resolve(1).then(x => x * 2).then(x => x / 2); + #Promise.resolve(1).then(x => x * 2).then(x => x / 2); + promise = Promise.resolve(1).then(x => x * 2).then(x => x / 2); + +testFunction (test.js:6:2) +(anonymous) (expr.js:0:0) + Promise.resolve(1).then(x => x * 2).then(x => x / 2); + #promise = Promise.resolve(1).then(x => x * 2).then(x => x / 2); + var a = 1; + +testFunction (test.js:7:10) +(anonymous) (expr.js:0:0) + promise = Promise.resolve(1).then(x => x * 2).then(x => x / 2); + var a = #1; + const x = (a = 20); + +testFunction (test.js:8:12) +(anonymous) (expr.js:0:0) + var a = 1; + const x = #(a = 20); + var y = (a = 100); + +testFunction (test.js:9:10) +(anonymous) (expr.js:0:0) + const x = (a = 20); + var y = #(a = 100); + var z = x + (a = 1) + (a = 2) + (a = 3) + f(); + +testFunction (test.js:10:10) +(anonymous) (expr.js:0:0) + var y = (a = 100); + var z = #x + (a = 1) + (a = 2) + (a = 3) + f(); + function f() { + +f (test.js:12:24) +testFunction (test.js:10:44) +(anonymous) (expr.js:0:0) + function f() { + for (let { x, y } = #{ x: 0, y: 1 }; y > 0; --y) { let z = x + y; } + } + +f (test.js:12:42) +testFunction (test.js:10:44) +(anonymous) (expr.js:0:0) + function f() { + for (let { x, y } = { x: 0, y: 1 }; y #> 0; --y) { let z = x + y; } + } + +f (test.js:12:62) +testFunction (test.js:10:44) +(anonymous) (expr.js:0:0) + function f() { + for (let { x, y } = { x: 0, y: 1 }; y > 0; --y) { let z = #x + y; } + } + +f (test.js:12:49) +testFunction (test.js:10:44) +(anonymous) (expr.js:0:0) + function f() { + for (let { x, y } = { x: 0, y: 1 }; y > 0; --#y) { let z = x + y; } + } + +f (test.js:12:42) +testFunction (test.js:10:44) +(anonymous) (expr.js:0:0) + function f() { + for (let { x, y } = { x: 0, y: 1 }; y #> 0; --y) { let z = x + y; } + } + +f (test.js:13:2) +testFunction (test.js:10:44) +(anonymous) (expr.js:0:0) + for (let { x, y } = { x: 0, y: 1 }; y > 0; --y) { let z = x + y; } + #} + var b = obj1.a; + +testFunction (test.js:14:15) +(anonymous) (expr.js:0:0) + } + var b = obj1.#a; + (async function asyncF() { + +testFunction (test.js:15:2) +(anonymous) (expr.js:0:0) + var b = obj1.a; + #(async function asyncF() { + let r = await Promise.resolve(42); + +asyncF (test.js:16:12) +testFunction (test.js:18:4) +(anonymous) (expr.js:0:0) + (async function asyncF() { + let r = #await Promise.resolve(42); + return r; + +asyncF (test.js:17:4) + let r = await Promise.resolve(42); + #return r; + })(); + +asyncF (test.js:18:2) + return r; + #})(); + return promise; + + +Running test: testStepIntoAfterBreakpoint +testFunction (test.js:10:10) +(anonymous) (expr.js:0:0) + var y = (a = 100); + var z = #x + (a = 1) + (a = 2) + (a = 3) + f(); + function f() { + +f (test.js:12:24) +testFunction (test.js:10:44) +(anonymous) (expr.js:0:0) + function f() { + for (let { x, y } = #{ x: 0, y: 1 }; y > 0; --y) { let z = x + y; } + } +
diff --git a/src/v8/test/inspector/debugger/break-locations-var-init.js b/src/v8/test/inspector/debugger/break-locations-var-init.js new file mode 100644 index 0000000..291de8f --- /dev/null +++ b/src/v8/test/inspector/debugger/break-locations-var-init.js
@@ -0,0 +1,74 @@ +// Copyright 2017 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. + +let {session, contextGroup, Protocol} = + InspectorTest.start('Tests breakable locations in variable initializations.'); + +let source = ` +function testFunction() { + var obj1 = {a : 1}; + var arr1 = [1]; + var promise = Promise.resolve(1).then(x => x * 2).then(x => x / 2); + Promise.resolve(1).then(x => x * 2).then(x => x / 2); + promise = Promise.resolve(1).then(x => x * 2).then(x => x / 2); + var a = 1; + const x = (a = 20); + var y = (a = 100); + var z = x + (a = 1) + (a = 2) + (a = 3) + f(); + function f() { + for (let { x, y } = { x: 0, y: 1 }; y > 0; --y) { let z = x + y; } + } + var b = obj1.a; + (async function asyncF() { + let r = await Promise.resolve(42); + return r; + })(); + return promise; +} +//# sourceURL=test.js`; + +contextGroup.addScript(source); +session.setupScriptMap(); + +InspectorTest.runAsyncTestSuite([ + async function testBreakLocations() { + Protocol.Debugger.enable(); + let {params:{scriptId}} = await Protocol.Debugger.onceScriptParsed(); + let {result:{locations}} = await Protocol.Debugger.getPossibleBreakpoints({ + start: {lineNumber: 0, columnNumber : 0, scriptId}}); + session.logBreakLocations(locations); + }, + + async function testStepInto() { + Protocol.Debugger.pause(); + let fin = Protocol.Runtime.evaluate({ + expression: 'testFunction()//# sourceURL=expr.js', awaitPromise: true}).then(() => false); + let result; + while (result = await Promise.race([fin, Protocol.Debugger.oncePaused()])) { + let {params:{callFrames}} = result; + session.logCallFrames(callFrames); + session.logSourceLocation(callFrames[0].location); + Protocol.Debugger.stepInto(); + } + Protocol.Runtime.evaluate({expression: '42'}); + await Protocol.Debugger.oncePaused(); + await Protocol.Debugger.resume(); + }, + + async function testStepIntoAfterBreakpoint() { + Protocol.Debugger.setBreakpointByUrl({lineNumber: 10, url: 'test.js'}); + Protocol.Runtime.evaluate({ + expression: 'testFunction()//# sourceURL=expr.js'}); + await awaitPausedAndDump(); + Protocol.Debugger.stepInto(); + await awaitPausedAndDump(); + await Protocol.Debugger.resume(); + + async function awaitPausedAndDump() { + let {params:{callFrames}} = await Protocol.Debugger.oncePaused(); + session.logCallFrames(callFrames); + session.logSourceLocation(callFrames[0].location); + } + } +]);
diff --git a/src/v8/test/inspector/debugger/break-on-exception-expected.txt b/src/v8/test/inspector/debugger/break-on-exception-expected.txt new file mode 100644 index 0000000..f4d70f0 --- /dev/null +++ b/src/v8/test/inspector/debugger/break-on-exception-expected.txt
@@ -0,0 +1,12 @@ +Check that inspector correctly change break on exception state. + +Running test: noBreakOnExceptionAfterEnabled + +Running test: breakOnUncaughtException +paused in throwUncaughtException + +Running test: breakOnCaughtException +paused in throwUncaughtException +paused in throwCaughtException + +Running test: noBreakInEvaluateInSilentMode
diff --git a/src/v8/test/inspector/debugger/break-on-exception.js b/src/v8/test/inspector/debugger/break-on-exception.js new file mode 100644 index 0000000..6f47ec8 --- /dev/null +++ b/src/v8/test/inspector/debugger/break-on-exception.js
@@ -0,0 +1,71 @@ +// 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. + +let {session, contextGroup, Protocol} = InspectorTest.start("Check that inspector correctly change break on exception state."); + +contextGroup.addScript(` +function scheduleUncaughtException() +{ + setTimeout(throwUncaughtException, 0); +} +function throwUncaughtException() +{ + throw new Error(); +} +function throwCaughtException() +{ + throw new Error(); +}`); + +Protocol.Debugger.onPaused(message => { + InspectorTest.log("paused in " + message.params.callFrames[0].functionName); + Protocol.Debugger.resume(); +}); + +Protocol.Runtime.enable(); + +InspectorTest.runTestSuite([ + function noBreakOnExceptionAfterEnabled(next) + { + Protocol.Debugger.enable(); + Protocol.Debugger.setPauseOnExceptions({ state: "all" }); + Protocol.Debugger.disable(); + Protocol.Debugger.enable(); + Protocol.Runtime.evaluate({ expression: "scheduleUncaughtException()" }) + .then(() => Protocol.Runtime.evaluate({ expression: "throwCaughtException()" })) + .then(() => Protocol.Debugger.disable()) + .then(next); + }, + + function breakOnUncaughtException(next) + { + Protocol.Debugger.enable(); + Protocol.Debugger.setPauseOnExceptions({ state: "uncaught" }); + Protocol.Runtime.evaluate({ expression: "scheduleUncaughtException()" }) + .then(() => Protocol.Runtime.onceExceptionThrown()) + .then(() => Protocol.Runtime.evaluate({ expression: "throwCaughtException()" })) + .then(() => Protocol.Debugger.disable()) + .then(next); + }, + + function breakOnCaughtException(next) + { + Protocol.Debugger.enable(); + Protocol.Debugger.setPauseOnExceptions({ state: "all" }); + Protocol.Runtime.evaluate({ expression: "scheduleUncaughtException()" }) + .then(() => Protocol.Runtime.onceExceptionThrown()) + .then(() => Protocol.Runtime.evaluate({ expression: "throwCaughtException()" })) + .then(() => Protocol.Debugger.disable()) + .then(next); + }, + + function noBreakInEvaluateInSilentMode(next) + { + Protocol.Debugger.enable(); + Protocol.Debugger.setPauseOnExceptions({ state: "all" }) + .then(() => Protocol.Runtime.evaluate({ expression: "throwCaughtException()", silent: true })) + .then(() => Protocol.Debugger.disable()) + .then(next); + } +]);
diff --git a/src/v8/test/inspector/debugger/call-frame-function-location-expected.txt b/src/v8/test/inspector/debugger/call-frame-function-location-expected.txt new file mode 100644 index 0000000..211352c --- /dev/null +++ b/src/v8/test/inspector/debugger/call-frame-function-location-expected.txt
@@ -0,0 +1,4 @@ +Tests that function location in call frames is correct +Paused on 'debugger;' +Top frame location: {"scriptId":"42","lineNumber":3,"columnNumber":4} +Top frame functionLocation: {"scriptId":"42","lineNumber":0,"columnNumber":21}
diff --git a/src/v8/test/inspector/debugger/call-frame-function-location.js b/src/v8/test/inspector/debugger/call-frame-function-location.js new file mode 100644 index 0000000..4775b30 --- /dev/null +++ b/src/v8/test/inspector/debugger/call-frame-function-location.js
@@ -0,0 +1,27 @@ +// 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. + +let {session, contextGroup, Protocol} = InspectorTest.start('Tests that function location in call frames is correct'); + +contextGroup.addScript( +`function testFunction() +{ + var a = 2; + debugger; +}`); + +Protocol.Debugger.enable(); +Protocol.Debugger.oncePaused().then(handleDebuggerPaused); +Protocol.Runtime.evaluate({ "expression": "setTimeout(testFunction, 0)" }); + +function handleDebuggerPaused(messageObject) +{ + InspectorTest.log("Paused on 'debugger;'"); + var topFrame = messageObject.params.callFrames[0]; + topFrame.location.scriptId = "42"; + topFrame.functionLocation.scriptId = "42"; + InspectorTest.log("Top frame location: " + JSON.stringify(topFrame.location)); + InspectorTest.log("Top frame functionLocation: " + JSON.stringify(topFrame.functionLocation)); + InspectorTest.completeTest(); +}
diff --git a/src/v8/test/inspector/debugger/call-frame-url-expected.txt b/src/v8/test/inspector/debugger/call-frame-url-expected.txt new file mode 100644 index 0000000..b27b40d --- /dev/null +++ b/src/v8/test/inspector/debugger/call-frame-url-expected.txt
@@ -0,0 +1,15 @@ +Tests url in Debugger.CallFrame. +[ + [0] : { + url : + } + [1] : { + url : source-url.js + } + [2] : { + url : test.js + } + [3] : { + url : expr.js + } +]
diff --git a/src/v8/test/inspector/debugger/call-frame-url.js b/src/v8/test/inspector/debugger/call-frame-url.js new file mode 100644 index 0000000..af8e908 --- /dev/null +++ b/src/v8/test/inspector/debugger/call-frame-url.js
@@ -0,0 +1,20 @@ +// Copyright 2017 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. + +let {session, contextGroup, Protocol} = + InspectorTest.start('Tests url in Debugger.CallFrame.'); + +contextGroup.addScript(` +eval('function foo1() { debugger; }'); +eval('function foo2() { foo1() } //# sourceURL=source-url.js'); +function foo3() { foo2(); } +`, 0, 0, 'test.js'); + +(async function test() { + Protocol.Debugger.enable(); + Protocol.Runtime.evaluate({expression: 'foo3()//# sourceURL=expr.js'}); + let {params:{callFrames}} = await Protocol.Debugger.oncePaused(); + InspectorTest.logMessage(callFrames.map(frame => ({url: frame.url}))); + InspectorTest.completeTest(); +})();
diff --git a/src/v8/test/inspector/debugger/caught-exception-from-framework-inside-async-expected.txt b/src/v8/test/inspector/debugger/caught-exception-from-framework-inside-async-expected.txt new file mode 100644 index 0000000..aff06b2 --- /dev/null +++ b/src/v8/test/inspector/debugger/caught-exception-from-framework-inside-async-expected.txt
@@ -0,0 +1,4 @@ +Async caught exception prediction and blackboxing. +paused at: +#debugger; +
diff --git a/src/v8/test/inspector/debugger/caught-exception-from-framework-inside-async.js b/src/v8/test/inspector/debugger/caught-exception-from-framework-inside-async.js new file mode 100644 index 0000000..f59e71f --- /dev/null +++ b/src/v8/test/inspector/debugger/caught-exception-from-framework-inside-async.js
@@ -0,0 +1,38 @@ +// Copyright 2017 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. + +let {session, contextGroup, Protocol} = InspectorTest.start('Async caught exception prediction and blackboxing.'); + +contextGroup.addScript(` +function constructorThrow() { + return new Promise((resolve, reject) => + Promise.resolve().then(() => + reject("f") // Exception f + ) + ); +} + +function dotCatch(producer) { + Promise.resolve(producer()).catch(() => {}); +} +//# sourceURL=framework.js`); + +session.setupScriptMap(); +(async function test() { + Protocol.Debugger.enable(); + Protocol.Debugger.setBlackboxPatterns({patterns: ['framework\.js']}); + Protocol.Debugger.setPauseOnExceptions({state: 'all'}); + Protocol.Runtime.evaluate({expression: 'dotCatch(constructorThrow);'}); + // Should break at this debugger statement, not at reject. + Protocol.Runtime.evaluate({expression: 'setTimeout(\'debugger;\', 0);'}); + await waitPauseAndDumpLocation(); + InspectorTest.completeTest(); +})(); + +async function waitPauseAndDumpLocation() { + var message = await Protocol.Debugger.oncePaused(); + InspectorTest.log('paused at:'); + session.logSourceLocation(message.params.callFrames[0].location); + return message; +}
diff --git a/src/v8/test/inspector/debugger/caught-uncaught-exceptions-expected.txt b/src/v8/test/inspector/debugger/caught-uncaught-exceptions-expected.txt new file mode 100644 index 0000000..b784fa5 --- /dev/null +++ b/src/v8/test/inspector/debugger/caught-uncaught-exceptions-expected.txt
@@ -0,0 +1,5 @@ +Check that inspector correctly passes caught/uncaught information. +paused in throwCaught +uncaught: false +paused in throwUncaught +uncaught: true
diff --git a/src/v8/test/inspector/debugger/caught-uncaught-exceptions.js b/src/v8/test/inspector/debugger/caught-uncaught-exceptions.js new file mode 100644 index 0000000..38b622d --- /dev/null +++ b/src/v8/test/inspector/debugger/caught-uncaught-exceptions.js
@@ -0,0 +1,25 @@ +// 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. + +let {session, contextGroup, Protocol} = InspectorTest.start("Check that inspector correctly passes caught/uncaught information."); + +contextGroup.addScript( +`function throwCaught() { try { throw new Error(); } catch (_) {} } + function throwUncaught() { throw new Error(); } + function schedule(f) { setTimeout(f, 0); } +`); + +Protocol.Debugger.enable(); + +Protocol.Debugger.setPauseOnExceptions({ "state": "all" }); +Protocol.Debugger.onPaused(message => { + InspectorTest.log("paused in " + message.params.callFrames[0].functionName); + InspectorTest.log("uncaught: " + message.params.data.uncaught); + Protocol.Debugger.resume(); +}); + +Protocol.Runtime.evaluate({ "expression": "schedule(throwCaught);" }) + .then(() => Protocol.Runtime.evaluate( + { "expression": "schedule(throwUncaught);" })) + .then(() => InspectorTest.completeTest());
diff --git a/src/v8/test/inspector/debugger/clear-breakpoints-on-disable-expected.txt b/src/v8/test/inspector/debugger/clear-breakpoints-on-disable-expected.txt new file mode 100644 index 0000000..0d3794e --- /dev/null +++ b/src/v8/test/inspector/debugger/clear-breakpoints-on-disable-expected.txt
@@ -0,0 +1,5 @@ +Tests that we clear breakpoints on agent disabled +function foo() {#} + +foo();#debugger; +
diff --git a/src/v8/test/inspector/debugger/clear-breakpoints-on-disable.js b/src/v8/test/inspector/debugger/clear-breakpoints-on-disable.js new file mode 100644 index 0000000..729af84 --- /dev/null +++ b/src/v8/test/inspector/debugger/clear-breakpoints-on-disable.js
@@ -0,0 +1,28 @@ +// Copyright 2017 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. + +let {session, contextGroup, Protocol} = + InspectorTest.start('Tests that we clear breakpoints on agent disabled'); + +(async function test() { +session.setupScriptMap(); + Protocol.Runtime.evaluate({expression: 'function foo() {}'}); + Protocol.Debugger.enable(); + let {params:{scriptId}} = await Protocol.Debugger.onceScriptParsed(); + await Protocol.Debugger.setBreakpoint({ + location: { + lineNumber: 0, columnNumber: 16, scriptId + } + }); + Protocol.Runtime.evaluate({expression: 'foo()'}); + var {params:{callFrames}} = await Protocol.Debugger.oncePaused(); + await session.logSourceLocation(callFrames[0].location); + await Protocol.Debugger.disable(); + await Protocol.Debugger.enable(); + Protocol.Debugger.onPaused(InspectorTest.logMessage); + Protocol.Runtime.evaluate({expression: 'foo();debugger;'}); + var {params:{callFrames}} = await Protocol.Debugger.oncePaused(); + await session.logSourceLocation(callFrames[0].location); + InspectorTest.completeTest(); +})()
diff --git a/src/v8/test/inspector/debugger/collect-obsolete-async-tasks-expected.txt b/src/v8/test/inspector/debugger/collect-obsolete-async-tasks-expected.txt new file mode 100644 index 0000000..c114e34 --- /dev/null +++ b/src/v8/test/inspector/debugger/collect-obsolete-async-tasks-expected.txt
@@ -0,0 +1,37 @@ +Checks that we collect obsolete async tasks with async stacks. +Async stacks count: 2 +Scheduled async tasks: 1 +Created async tasks: 1 +Async tasks with parent: 0 +Recurring async tasks: 1 + +Async stacks count: 0 +Scheduled async tasks: 0 +Created async tasks: 0 +Async tasks with parent: 0 +Recurring async tasks: 0 + +Async stacks count: 2 +Scheduled async tasks: 0 +Created async tasks: 2 +Async tasks with parent: 2 +Recurring async tasks: 0 + +Async stacks count: 0 +Scheduled async tasks: 0 +Created async tasks: 0 +Async tasks with parent: 0 +Recurring async tasks: 0 + +Async stacks count: 1 +Scheduled async tasks: 1 +Created async tasks: 0 +Async tasks with parent: 0 +Recurring async tasks: 0 + +Async stacks count: 0 +Scheduled async tasks: 0 +Created async tasks: 0 +Async tasks with parent: 0 +Recurring async tasks: 0 +
diff --git a/src/v8/test/inspector/debugger/collect-obsolete-async-tasks.js b/src/v8/test/inspector/debugger/collect-obsolete-async-tasks.js new file mode 100644 index 0000000..cfef345 --- /dev/null +++ b/src/v8/test/inspector/debugger/collect-obsolete-async-tasks.js
@@ -0,0 +1,35 @@ +// Copyright 2017 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. + +let {session, contextGroup, Protocol} = InspectorTest.start('Checks that we collect obsolete async tasks with async stacks.'); + +contextGroup.addScript(` +function test() { + inspector.setMaxAsyncTaskStacks(128); + var p = Promise.resolve(); + + inspector.dumpAsyncTaskStacksStateForTest(); + inspector.setMaxAsyncTaskStacks(128); + inspector.dumpAsyncTaskStacksStateForTest(); + + p.then(() => 42).then(() => 239); + + inspector.dumpAsyncTaskStacksStateForTest(); + inspector.setMaxAsyncTaskStacks(128); + inspector.dumpAsyncTaskStacksStateForTest(); + + setTimeout(() => 42, 0); + + inspector.dumpAsyncTaskStacksStateForTest(); + inspector.setMaxAsyncTaskStacks(128); + inspector.dumpAsyncTaskStacksStateForTest(); +} +`); + +(async function test() { + Protocol.Debugger.enable(); + Protocol.Debugger.setAsyncCallStackDepth({maxDepth: 128}); + await Protocol.Runtime.evaluate({expression: 'test()'}); + InspectorTest.completeTest(); +})()
diff --git a/src/v8/test/inspector/debugger/collect-old-async-call-chains-expected.txt b/src/v8/test/inspector/debugger/collect-old-async-call-chains-expected.txt new file mode 100644 index 0000000..64fef4a --- /dev/null +++ b/src/v8/test/inspector/debugger/collect-old-async-call-chains-expected.txt
@@ -0,0 +1,211 @@ +Checks that we drop old async call chains. + +Running test: testInfrastructure +inspector.setMaxAsyncTaskStacks(1024) +Run expression 'console.trace(42)' with async chain len: 1 +actual async chain len: 1 + +inspector.setMaxAsyncTaskStacks(1024) +Run expression 'console.trace(42)' with async chain len: 2 +actual async chain len: 1 + +inspector.setMaxAsyncTaskStacks(1024) +Run expression 'console.trace(42)' with async chain len: 5 +actual async chain len: 1 + +inspector.setMaxAsyncTaskStacks(1024) +Run expression 'console.trace(42)' with async chain len: 1 +actual async chain len: 1 + +inspector.setMaxAsyncTaskStacks(1024) +Run expression 'console.trace(42)' with async chain len: 2 +actual async chain len: 2 + +inspector.setMaxAsyncTaskStacks(1024) +Run expression 'console.trace(42)' with async chain len: 5 +actual async chain len: 5 + + +Running test: testZeroLimit +inspector.setMaxAsyncTaskStacks(0) +Run expression 'console.trace(42)' with async chain len: 1 +actual async chain len: 0 + +inspector.setMaxAsyncTaskStacks(0) +Run expression 'console.trace(42)' with async chain len: 2 +actual async chain len: 0 + +inspector.setMaxAsyncTaskStacks(0) +Run expression 'console.trace(42)' with async chain len: 1 +actual async chain len: 0 + +inspector.setMaxAsyncTaskStacks(0) +Run expression 'console.trace(42)' with async chain len: 2 +actual async chain len: 0 + + +Running test: testOneLimit +inspector.setMaxAsyncTaskStacks(1) +Run expression 'console.trace(42)' with async chain len: 1 +actual async chain len: 1 + +inspector.setMaxAsyncTaskStacks(1) +Run expression 'console.trace(42)' with async chain len: 2 +actual async chain len: 1 + +inspector.setMaxAsyncTaskStacks(1) +Run expression 'console.trace(42)' with async chain len: 1 +actual async chain len: 1 + +inspector.setMaxAsyncTaskStacks(1) +Run expression 'console.trace(42)' with async chain len: 2 +actual async chain len: 1 + + +Running test: testTwoLimit +inspector.setMaxAsyncTaskStacks(2) +Run expression 'console.trace(42)' with async chain len: 1 +actual async chain len: 1 + +inspector.setMaxAsyncTaskStacks(2) +Run expression 'console.trace(42)' with async chain len: 2 +actual async chain len: 0 + +inspector.setMaxAsyncTaskStacks(2) +Run expression 'console.trace(42)' with async chain len: 3 +actual async chain len: 1 + +inspector.setMaxAsyncTaskStacks(2) +Run expression 'console.trace(42)' with async chain len: 1 +actual async chain len: 1 + +inspector.setMaxAsyncTaskStacks(2) +Run expression 'console.trace(42)' with async chain len: 2 +actual async chain len: 2 + +inspector.setMaxAsyncTaskStacks(2) +Run expression 'console.trace(42)' with async chain len: 3 +actual async chain len: 1 + + +Running test: testMoreThanTwoLimit +inspector.setMaxAsyncTaskStacks(3) +Run expression 'console.trace(42)' with async chain len: 1 +actual async chain len: 1 + +inspector.setMaxAsyncTaskStacks(3) +Run expression 'console.trace(42)' with async chain len: 2 +actual async chain len: 1 + +inspector.setMaxAsyncTaskStacks(3) +Run expression 'console.trace(42)' with async chain len: 3 +actual async chain len: 1 + +inspector.setMaxAsyncTaskStacks(3) +Run expression 'console.trace(42)' with async chain len: 1 +actual async chain len: 1 + +inspector.setMaxAsyncTaskStacks(3) +Run expression 'console.trace(42)' with async chain len: 2 +actual async chain len: 2 + +inspector.setMaxAsyncTaskStacks(3) +Run expression 'console.trace(42)' with async chain len: 3 +actual async chain len: 3 + +inspector.setMaxAsyncTaskStacks(4) +Run expression 'console.trace(42)' with async chain len: 1 +actual async chain len: 1 + +inspector.setMaxAsyncTaskStacks(4) +Run expression 'console.trace(42)' with async chain len: 2 +actual async chain len: 1 + +inspector.setMaxAsyncTaskStacks(4) +Run expression 'console.trace(42)' with async chain len: 3 +actual async chain len: 1 + +inspector.setMaxAsyncTaskStacks(4) +Run expression 'console.trace(42)' with async chain len: 1 +actual async chain len: 1 + +inspector.setMaxAsyncTaskStacks(4) +Run expression 'console.trace(42)' with async chain len: 2 +actual async chain len: 2 + +inspector.setMaxAsyncTaskStacks(4) +Run expression 'console.trace(42)' with async chain len: 3 +actual async chain len: 3 + +inspector.setMaxAsyncTaskStacks(5) +Run expression 'console.trace(42)' with async chain len: 1 +actual async chain len: 1 + +inspector.setMaxAsyncTaskStacks(5) +Run expression 'console.trace(42)' with async chain len: 2 +actual async chain len: 1 + +inspector.setMaxAsyncTaskStacks(5) +Run expression 'console.trace(42)' with async chain len: 3 +actual async chain len: 1 + +inspector.setMaxAsyncTaskStacks(5) +Run expression 'console.trace(42)' with async chain len: 1 +actual async chain len: 1 + +inspector.setMaxAsyncTaskStacks(5) +Run expression 'console.trace(42)' with async chain len: 2 +actual async chain len: 2 + +inspector.setMaxAsyncTaskStacks(5) +Run expression 'console.trace(42)' with async chain len: 3 +actual async chain len: 3 + +inspector.setMaxAsyncTaskStacks(6) +Run expression 'console.trace(42)' with async chain len: 1 +actual async chain len: 1 + +inspector.setMaxAsyncTaskStacks(6) +Run expression 'console.trace(42)' with async chain len: 2 +actual async chain len: 1 + +inspector.setMaxAsyncTaskStacks(6) +Run expression 'console.trace(42)' with async chain len: 3 +actual async chain len: 1 + +inspector.setMaxAsyncTaskStacks(6) +Run expression 'console.trace(42)' with async chain len: 1 +actual async chain len: 1 + +inspector.setMaxAsyncTaskStacks(6) +Run expression 'console.trace(42)' with async chain len: 2 +actual async chain len: 2 + +inspector.setMaxAsyncTaskStacks(6) +Run expression 'console.trace(42)' with async chain len: 3 +actual async chain len: 3 + +inspector.setMaxAsyncTaskStacks(7) +Run expression 'console.trace(42)' with async chain len: 1 +actual async chain len: 1 + +inspector.setMaxAsyncTaskStacks(7) +Run expression 'console.trace(42)' with async chain len: 2 +actual async chain len: 1 + +inspector.setMaxAsyncTaskStacks(7) +Run expression 'console.trace(42)' with async chain len: 3 +actual async chain len: 1 + +inspector.setMaxAsyncTaskStacks(7) +Run expression 'console.trace(42)' with async chain len: 1 +actual async chain len: 1 + +inspector.setMaxAsyncTaskStacks(7) +Run expression 'console.trace(42)' with async chain len: 2 +actual async chain len: 2 + +inspector.setMaxAsyncTaskStacks(7) +Run expression 'console.trace(42)' with async chain len: 3 +actual async chain len: 3 +
diff --git a/src/v8/test/inspector/debugger/collect-old-async-call-chains.js b/src/v8/test/inspector/debugger/collect-old-async-call-chains.js new file mode 100644 index 0000000..7ac8225 --- /dev/null +++ b/src/v8/test/inspector/debugger/collect-old-async-call-chains.js
@@ -0,0 +1,171 @@ +// Copyright 2017 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. + +let {session, contextGroup, Protocol} = InspectorTest.start('Checks that we drop old async call chains.'); + +Protocol.Debugger.enable(); +Protocol.Runtime.enable(); +InspectorTest.runAsyncTestSuite([ + async function testInfrastructure() { + Protocol.Debugger.setAsyncCallStackDepth({maxDepth: 128}); + await setMaxAsyncTaskStacks(1024); + runWithAsyncChainPromise(1, 'console.trace(42)'); + dumpAsyncChainLength(await Protocol.Runtime.onceConsoleAPICalled()); + + await setMaxAsyncTaskStacks(1024); + runWithAsyncChainPromise(2, 'console.trace(42)'); + dumpAsyncChainLength(await Protocol.Runtime.onceConsoleAPICalled()); + + await setMaxAsyncTaskStacks(1024); + runWithAsyncChainPromise(5, 'console.trace(42)'); + dumpAsyncChainLength(await Protocol.Runtime.onceConsoleAPICalled()); + + await setMaxAsyncTaskStacks(1024); + runWithAsyncChainSetTimeout(1, 'console.trace(42)'); + dumpAsyncChainLength(await Protocol.Runtime.onceConsoleAPICalled()); + + await setMaxAsyncTaskStacks(1024); + runWithAsyncChainSetTimeout(2, 'console.trace(42)'); + dumpAsyncChainLength(await Protocol.Runtime.onceConsoleAPICalled()); + + await setMaxAsyncTaskStacks(1024); + runWithAsyncChainSetTimeout(5, 'console.trace(42)'); + dumpAsyncChainLength(await Protocol.Runtime.onceConsoleAPICalled()); + }, + + async function testZeroLimit() { + const limit = 0; + Protocol.Debugger.setAsyncCallStackDepth({maxDepth: 128}); + + await setMaxAsyncTaskStacks(limit); + runWithAsyncChainPromise(1, 'console.trace(42)'); + dumpAsyncChainLength(await Protocol.Runtime.onceConsoleAPICalled()); + + await setMaxAsyncTaskStacks(limit); + runWithAsyncChainPromise(2, 'console.trace(42)'); + dumpAsyncChainLength(await Protocol.Runtime.onceConsoleAPICalled()); + + await setMaxAsyncTaskStacks(limit); + runWithAsyncChainSetTimeout(1, 'console.trace(42)'); + dumpAsyncChainLength(await Protocol.Runtime.onceConsoleAPICalled()); + + await setMaxAsyncTaskStacks(limit); + runWithAsyncChainSetTimeout(2, 'console.trace(42)'); + dumpAsyncChainLength(await Protocol.Runtime.onceConsoleAPICalled()); + }, + + async function testOneLimit() { + const limit = 1; + Protocol.Debugger.setAsyncCallStackDepth({maxDepth: 128}); + + await setMaxAsyncTaskStacks(limit); + runWithAsyncChainPromise(1, 'console.trace(42)'); + dumpAsyncChainLength(await Protocol.Runtime.onceConsoleAPICalled()); + + await setMaxAsyncTaskStacks(limit); + runWithAsyncChainPromise(2, 'console.trace(42)'); + dumpAsyncChainLength(await Protocol.Runtime.onceConsoleAPICalled()); + + await setMaxAsyncTaskStacks(limit); + runWithAsyncChainSetTimeout(1, 'console.trace(42)'); + dumpAsyncChainLength(await Protocol.Runtime.onceConsoleAPICalled()); + + await setMaxAsyncTaskStacks(limit); + runWithAsyncChainSetTimeout(2, 'console.trace(42)'); + dumpAsyncChainLength(await Protocol.Runtime.onceConsoleAPICalled()); + }, + + async function testTwoLimit() { + const limit = 2; + Protocol.Debugger.setAsyncCallStackDepth({maxDepth: 128}); + + await setMaxAsyncTaskStacks(limit); + runWithAsyncChainPromise(1, 'console.trace(42)'); + dumpAsyncChainLength(await Protocol.Runtime.onceConsoleAPICalled()); + + await setMaxAsyncTaskStacks(limit); + runWithAsyncChainPromise(2, 'console.trace(42)'); + dumpAsyncChainLength(await Protocol.Runtime.onceConsoleAPICalled()); + + await setMaxAsyncTaskStacks(limit); + runWithAsyncChainPromise(3, 'console.trace(42)'); + dumpAsyncChainLength(await Protocol.Runtime.onceConsoleAPICalled()); + + await setMaxAsyncTaskStacks(limit); + runWithAsyncChainSetTimeout(1, 'console.trace(42)'); + dumpAsyncChainLength(await Protocol.Runtime.onceConsoleAPICalled()); + + await setMaxAsyncTaskStacks(limit); + runWithAsyncChainSetTimeout(2, 'console.trace(42)'); + dumpAsyncChainLength(await Protocol.Runtime.onceConsoleAPICalled()); + + await setMaxAsyncTaskStacks(limit); + runWithAsyncChainSetTimeout(3, 'console.trace(42)'); + dumpAsyncChainLength(await Protocol.Runtime.onceConsoleAPICalled()); + }, + + async function testMoreThanTwoLimit() { + for (let limit = 3; limit <= 7; ++limit) { + Protocol.Debugger.setAsyncCallStackDepth({maxDepth: 128}); + + await setMaxAsyncTaskStacks(limit); + runWithAsyncChainPromise(1, 'console.trace(42)'); + dumpAsyncChainLength(await Protocol.Runtime.onceConsoleAPICalled()); + + await setMaxAsyncTaskStacks(limit); + runWithAsyncChainPromise(2, 'console.trace(42)'); + dumpAsyncChainLength(await Protocol.Runtime.onceConsoleAPICalled()); + + await setMaxAsyncTaskStacks(limit); + runWithAsyncChainPromise(3, 'console.trace(42)'); + dumpAsyncChainLength(await Protocol.Runtime.onceConsoleAPICalled()); + + await setMaxAsyncTaskStacks(limit); + runWithAsyncChainSetTimeout(1, 'console.trace(42)'); + dumpAsyncChainLength(await Protocol.Runtime.onceConsoleAPICalled()); + + await setMaxAsyncTaskStacks(limit); + runWithAsyncChainSetTimeout(2, 'console.trace(42)'); + dumpAsyncChainLength(await Protocol.Runtime.onceConsoleAPICalled()); + + await setMaxAsyncTaskStacks(limit); + runWithAsyncChainSetTimeout(3, 'console.trace(42)'); + dumpAsyncChainLength(await Protocol.Runtime.onceConsoleAPICalled()); + } + }, +]); + +function runWithAsyncChainPromise(len, source) { + InspectorTest.log(`Run expression '${source}' with async chain len: ${len}`); + let then = '.then(() => 1)'; + let pause = `.then(() => { ${source} })`; + Protocol.Runtime.evaluate({ + expression: `Promise.resolve()${then.repeat(len - 1)}${pause}` + }); +} + +function runWithAsyncChainSetTimeout(len, source) { + InspectorTest.log(`Run expression '${source}' with async chain len: ${len}`); + let setTimeoutPrefix = '() => setTimeout('; + let setTimeoutSuffix = ', 0)'; + Protocol.Runtime.evaluate({ + expression: `setTimeout(${setTimeoutPrefix.repeat(len - 1)}'${source}'${setTimeoutSuffix.repeat(len - 1)}, 0)` + }); +} + +function dumpAsyncChainLength(message) { + let stackTrace = message.params.asyncStackTrace || message.params.stackTrace.parent; + let asyncChainCount = 0; + while (stackTrace) { + ++asyncChainCount; + stackTrace = stackTrace.parent; + } + InspectorTest.log(`actual async chain len: ${asyncChainCount}\n`); +} + +async function setMaxAsyncTaskStacks(max) { + let expression = `inspector.setMaxAsyncTaskStacks(${max})`; + InspectorTest.log(expression); + await Protocol.Runtime.evaluate({expression}); +}
diff --git a/src/v8/test/inspector/debugger/command-line-api-with-bound-function-expected.txt b/src/v8/test/inspector/debugger/command-line-api-with-bound-function-expected.txt new file mode 100644 index 0000000..338b136 --- /dev/null +++ b/src/v8/test/inspector/debugger/command-line-api-with-bound-function-expected.txt
@@ -0,0 +1,23 @@ +Check that debug and monitor methods from Command Line API works with bound function. +> debug foo and bar +> call foo and bar +paused in foo +paused in boo +> undebug foo and bar +> call foo and bar +> monitor foo and bar +> call foo and bar +function foo called +function boo called +> unmonitor foo and bar +> call foo and bar +> monitor and debug bar +> call bar +function boo called +paused in boo +> undebug bar +> call bar +function boo called +> debug and unmonitor bar +> call bar +paused in boo
diff --git a/src/v8/test/inspector/debugger/command-line-api-with-bound-function.js b/src/v8/test/inspector/debugger/command-line-api-with-bound-function.js new file mode 100644 index 0000000..3c00585 --- /dev/null +++ b/src/v8/test/inspector/debugger/command-line-api-with-bound-function.js
@@ -0,0 +1,64 @@ +// 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. + +let {session, contextGroup, Protocol} = InspectorTest.start("Check that debug and monitor methods from Command Line API works with bound function."); + +contextGroup.addScript(` +function foo() {} +function boo() {} +var bar = boo.bind(null); + +function testFunction() { + console.log("> debug foo and bar"); + debug(foo); + debug(bar); + console.log("> call foo and bar"); + foo(); + bar(); + console.log("> undebug foo and bar"); + undebug(foo); + undebug(bar); + console.log("> call foo and bar"); + foo(); + bar(); + + console.log("> monitor foo and bar"); + monitor(foo); + monitor(bar); + console.log("> call foo and bar"); + foo(); + bar(); + console.log("> unmonitor foo and bar"); + unmonitor(foo); + unmonitor(bar); + console.log("> call foo and bar"); + foo(); + bar(); + + console.log("> monitor and debug bar"); + monitor(bar); + debug(bar); + console.log("> call bar"); + bar(); + console.log("> undebug bar"); + undebug(bar); + console.log("> call bar"); + bar(); + console.log("> debug and unmonitor bar"); + debug(bar); + unmonitor(bar); + console.log("> call bar"); + bar(); +}`); + +Protocol.Runtime.enable(); +Protocol.Debugger.enable(); +Protocol.Debugger.onPaused(message => { + var functionName = message.params.callFrames[0].functionName; + InspectorTest.log(`paused in ${functionName}`); + Protocol.Debugger.resume(); +}); +Protocol.Runtime.onConsoleAPICalled(message => InspectorTest.log(message.params.args[0].value)); +Protocol.Runtime.evaluate({ expression: "testFunction()", includeCommandLineAPI: true }) + .then(InspectorTest.completeTest);
diff --git a/src/v8/test/inspector/debugger/continue-to-location-expected.txt b/src/v8/test/inspector/debugger/continue-to-location-expected.txt new file mode 100644 index 0000000..948edd8 --- /dev/null +++ b/src/v8/test/inspector/debugger/continue-to-location-expected.txt
@@ -0,0 +1,31 @@ +Tests Debugger.continueToLocation +Paused on debugger statement +Paused after continueToLocation +Stopped on line 8, expected 8, requested 8, (0-based numbers). +Control parameter 'step' calculation result: 1, expected: 1 +SUCCESS +Paused on debugger statement +Paused after continueToLocation +Stopped on line 8, expected 8, requested 8, (0-based numbers). +Control parameter 'step' calculation result: 1, expected: 1 +SUCCESS +Paused on debugger statement +Paused after continueToLocation +Stopped on line 17, expected 17, requested 12, (0-based numbers). +Control parameter 'step' calculation result: 6, expected: 6 +SUCCESS +Paused on debugger statement +Paused after continueToLocation +Stopped on line 17, expected 17, requested 13, (0-based numbers). +Control parameter 'step' calculation result: 6, expected: 6 +SUCCESS +Paused on debugger statement +Paused after continueToLocation +Stopped on line 17, expected 17, requested 17, (0-based numbers). +Control parameter 'step' calculation result: 6, expected: 6 +SUCCESS +Paused on debugger statement +Paused after continueToLocation +Stopped on line 17, expected 17, requested 17, (0-based numbers). +Control parameter 'step' calculation result: 6, expected: 6 +SUCCESS
diff --git a/src/v8/test/inspector/debugger/continue-to-location-target-call-frames-expected.txt b/src/v8/test/inspector/debugger/continue-to-location-target-call-frames-expected.txt new file mode 100644 index 0000000..1f41dcf --- /dev/null +++ b/src/v8/test/inspector/debugger/continue-to-location-target-call-frames-expected.txt
@@ -0,0 +1,81 @@ +Check that continue-to-location works with different strategies. + +Running test: testAwaitAny +(anonymous) (expr.js:0:0) + +asyncFact (test.js:9:2) +(anonymous) (expr.js:0:0) + +asyncFact (test.js:11:2) +-- async function -- +asyncFact (test.js:8:24) +asyncFact (test.js:10:20) +asyncFact (test.js:10:20) +asyncFact (test.js:10:20) +(anonymous) (expr.js:0:0) + + +Running test: testAwaitCurrent +(anonymous) (expr.js:0:0) + +asyncFact (test.js:9:2) +(anonymous) (expr.js:0:0) + +asyncFact (test.js:11:2) +-- async function -- +asyncFact (test.js:8:24) +(anonymous) (expr.js:0:0) + + +Running test: testAny +(anonymous) (expr.js:0:0) + +fact (test.js:16:2) +(anonymous) (expr.js:0:0) + +fact (test.js:18:2) +fact (test.js:17:14) +fact (test.js:17:14) +fact (test.js:17:14) +(anonymous) (expr.js:0:0) + + +Running test: testCurrent +(anonymous) (expr.js:0:0) + +fact (test.js:16:2) +(anonymous) (expr.js:0:0) + +fact (test.js:18:2) +(anonymous) (expr.js:0:0) + + +Running test: testTopLevelAny +(anonymous) (expr.js:0:0) + +topLevel (test.js:23:2) +(anonymous) (expr.js:0:0) + +(anonymous) (:1:10) +topLevel (test.js:23:2) +(anonymous) (expr.js:0:0) + +(anonymous) (:4:10) +topLevel (test.js:23:2) +(anonymous) (expr.js:0:0) + + +Running test: testTopLevelCurrent +(anonymous) (expr.js:0:0) + +topLevel (test.js:23:2) +(anonymous) (expr.js:0:0) + +(anonymous) (:1:10) +topLevel (test.js:23:2) +(anonymous) (expr.js:0:0) + +(anonymous) (:4:10) +topLevel (test.js:23:2) +(anonymous) (expr.js:0:0) +
diff --git a/src/v8/test/inspector/debugger/continue-to-location-target-call-frames.js b/src/v8/test/inspector/debugger/continue-to-location-target-call-frames.js new file mode 100644 index 0000000..c33ff6b --- /dev/null +++ b/src/v8/test/inspector/debugger/continue-to-location-target-call-frames.js
@@ -0,0 +1,139 @@ +// Copyright 2017 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. + +let {session, contextGroup, Protocol} = InspectorTest.start('Check that continue-to-location works with different strategies.'); + +contextGroup.addScript(` +async function asyncFact(n) { + if (n == 0) return 1; + let r = n * await asyncFact(n - 1); + console.log(r); + return r; +} + +function fact(n) { + if (n == 0) return 1; + let r = n * fact(n - 1); + console.log(r); + return r; +} + +function topLevel() { + eval(` + '`' + ` + var a = 1; + var b = 2; + fact(3); + console.log(a + b); + ` + '`' + `); +} + +//# sourceURL=test.js`, 7, 26); + +session.setupScriptMap(); +InspectorTest.runAsyncTestSuite([ + async function testAwaitAny() { + Protocol.Debugger.enable(); + Protocol.Debugger.setAsyncCallStackDepth({ maxDepth: 128 }); + Protocol.Debugger.pause(); + Protocol.Runtime.evaluate({expression: 'asyncFact(4)//# sourceURL=expr.js'}); + await pausedAndDumpStack(); + Protocol.Debugger.stepInto(); + let message = await pausedAndDumpStack(); + let location = message.params.callFrames[0].location; + location.lineNumber = 11; + Protocol.Debugger.continueToLocation({location, targetCallFrames: 'any'}); + await pausedAndDumpStack(); + Protocol.Debugger.disable(); + }, + + async function testAwaitCurrent() { + Protocol.Debugger.enable(); + Protocol.Debugger.setAsyncCallStackDepth({ maxDepth: 128 }); + Protocol.Debugger.pause(); + Protocol.Runtime.evaluate({expression: 'asyncFact(4)//# sourceURL=expr.js'}); + await pausedAndDumpStack(); + Protocol.Debugger.stepInto(); + let message = await pausedAndDumpStack(); + let location = message.params.callFrames[0].location; + location.lineNumber = 11; + Protocol.Debugger.continueToLocation({location, targetCallFrames: 'current'}); + await pausedAndDumpStack(); + await Protocol.Debugger.resume(); + Protocol.Debugger.disable(); + }, + + async function testAny() { + Protocol.Debugger.enable(); + Protocol.Debugger.setAsyncCallStackDepth({ maxDepth: 128 }); + Protocol.Debugger.pause(); + Protocol.Runtime.evaluate({expression: 'fact(4)//# sourceURL=expr.js'}); + await pausedAndDumpStack(); + Protocol.Debugger.stepInto(); + let message = await pausedAndDumpStack(); + let location = message.params.callFrames[0].location; + location.lineNumber = 18; + Protocol.Debugger.continueToLocation({location, targetCallFrames: 'any'}); + await pausedAndDumpStack(); + Protocol.Debugger.disable(); + }, + + async function testCurrent() { + Protocol.Debugger.enable(); + Protocol.Debugger.setAsyncCallStackDepth({ maxDepth: 128 }); + Protocol.Debugger.pause(); + Protocol.Runtime.evaluate({expression: 'fact(4)//# sourceURL=expr.js'}); + await pausedAndDumpStack(); + Protocol.Debugger.stepInto(); + let message = await pausedAndDumpStack(); + let location = message.params.callFrames[0].location; + location.lineNumber = 18; + Protocol.Debugger.continueToLocation({location, targetCallFrames: 'current'}); + await pausedAndDumpStack(); + await Protocol.Debugger.resume(); + Protocol.Debugger.disable(); + }, + + async function testTopLevelAny() { + Protocol.Debugger.enable(); + Protocol.Debugger.setAsyncCallStackDepth({ maxDepth: 128 }); + Protocol.Debugger.pause(); + Protocol.Runtime.evaluate({expression: 'topLevel()//# sourceURL=expr.js'}); + await pausedAndDumpStack(); + Protocol.Debugger.stepInto(); + await pausedAndDumpStack(); + Protocol.Debugger.stepInto(); + let message = await pausedAndDumpStack(); + let location = message.params.callFrames[0].location; + location.lineNumber = 4; + Protocol.Debugger.continueToLocation({location, targetCallFrames: 'any'}); + await pausedAndDumpStack(); + Protocol.Debugger.disable(); + }, + + async function testTopLevelCurrent() { + Protocol.Debugger.enable(); + Protocol.Debugger.setAsyncCallStackDepth({ maxDepth: 128 }); + Protocol.Debugger.pause(); + Protocol.Runtime.evaluate({expression: 'topLevel()//# sourceURL=expr.js'}); + await pausedAndDumpStack(); + Protocol.Debugger.stepInto(); + await pausedAndDumpStack(); + Protocol.Debugger.stepInto(); + let message = await pausedAndDumpStack(); + let location = message.params.callFrames[0].location; + location.lineNumber = 4; + Protocol.Debugger.continueToLocation({location, targetCallFrames: 'current'}); + await pausedAndDumpStack(); + await Protocol.Debugger.resume(); + Protocol.Debugger.disable(); + } +]); + +async function pausedAndDumpStack() { + let message = await Protocol.Debugger.oncePaused(); + session.logCallFrames(message.params.callFrames); + session.logAsyncStackTrace(message.params.asyncStackTrace); + InspectorTest.log(''); + return message; +}
diff --git a/src/v8/test/inspector/debugger/continue-to-location.js b/src/v8/test/inspector/debugger/continue-to-location.js new file mode 100644 index 0000000..878499d --- /dev/null +++ b/src/v8/test/inspector/debugger/continue-to-location.js
@@ -0,0 +1,116 @@ +// 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. + +let {session, contextGroup, Protocol} = InspectorTest.start('Tests Debugger.continueToLocation'); + +contextGroup.addScript( +`function statementsExample() +{ + var self = arguments.callee; + + debugger; + + self.step = 1; + + self.step = 2; + + void [ + self.step = 3, + self.step = 4, + self.step = 5, + self.step = 6 + ]; + + self.step = 7; +}`); + +var scenario = [ + // requested line number, expected control parameter 'step', expected line number + [ 8, 1, 8 ], + [ 8, 1, 8 ], + [ 12, 6, 17 ], + [ 13, 6, 17 ], + [ 17, 6, 17 ], + [ 17, 6, 17 ], +]; + +Protocol.Debugger.enable(); + +Protocol.Runtime.evaluate({ "expression": "statementsExample" }).then(callbackEvalFunctionObject); + +function callbackEvalFunctionObject(response) +{ + var functionObjectId = response.result.result.objectId; + Protocol.Runtime.getProperties({ objectId: functionObjectId }).then(callbackFunctionDetails); +} + +function callbackFunctionDetails(response) +{ + var result = response.result; + var scriptId; + for (var prop of result.internalProperties) { + if (prop.name === "[[FunctionLocation]]") + scriptId = prop.value.value.scriptId; + } + + nextScenarioStep(0); + + function nextScenarioStep(pos) + { + if (pos < scenario.length) + gotoSinglePassChain(scriptId, scenario[pos][0], scenario[pos][1], scenario[pos][2], nextScenarioStep.bind(this, pos + 1)); + else + InspectorTest.completeTest(); + } +} + +function gotoSinglePassChain(scriptId, lineNumber, expectedResult, expectedLineNumber, next) +{ + Protocol.Debugger.oncePaused().then(handleDebuggerPausedOne); + + Protocol.Runtime.evaluate({ "expression": "setTimeout(statementsExample, 0)" }); + + function handleDebuggerPausedOne(messageObject) + { + InspectorTest.log("Paused on debugger statement"); + + Protocol.Debugger.oncePaused().then(handleDebuggerPausedTwo); + + Protocol.Debugger.continueToLocation({ location: { scriptId: scriptId, lineNumber: lineNumber, columnNumber: 0} }).then(logContinueToLocation); + + function logContinueToLocation(response) + { + if (response.error) { + InspectorTest.log("Failed to execute continueToLocation " + JSON.stringify(response.error)); + InspectorTest.completeTest(); + } + } + } + function handleDebuggerPausedTwo(messageObject) + { + InspectorTest.log("Paused after continueToLocation"); + var actualLineNumber = messageObject.params.callFrames[0].location.lineNumber; + + InspectorTest.log("Stopped on line " + actualLineNumber + ", expected " + expectedLineNumber + ", requested " + lineNumber + ", (0-based numbers)."); + + Protocol.Debugger.oncePaused(handleDebuggerPausedUnexpected); + + Protocol.Runtime.evaluate({ "expression": "statementsExample.step" }).then(callbackStepEvaluate); + } + + function callbackStepEvaluate(response) + { + var resultValue = response.result.result.value; + InspectorTest.log("Control parameter 'step' calculation result: " + resultValue + ", expected: " + expectedResult); + InspectorTest.log(resultValue === expectedResult ? "SUCCESS" : "FAIL"); + Protocol.Debugger.resume(); + next(); + } + + function handleDebuggerPausedUnexpected(messageObject) + { + InspectorTest.log("Unexpected debugger pause"); + InspectorTest.completeTest(); + } +}
diff --git a/src/v8/test/inspector/debugger/destory-in-break-program-expected.txt b/src/v8/test/inspector/debugger/destory-in-break-program-expected.txt new file mode 100644 index 0000000..c0ce88e --- /dev/null +++ b/src/v8/test/inspector/debugger/destory-in-break-program-expected.txt
@@ -0,0 +1 @@ +Check destroying agent inside of breakProgram
diff --git a/src/v8/test/inspector/debugger/destory-in-break-program.js b/src/v8/test/inspector/debugger/destory-in-break-program.js new file mode 100644 index 0000000..e002328 --- /dev/null +++ b/src/v8/test/inspector/debugger/destory-in-break-program.js
@@ -0,0 +1,13 @@ +// Copyright 2017 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. + +let {session, contextGroup, Protocol} = InspectorTest.start('Check destroying agent inside of breakProgram'); + +(async function test(){ + await Protocol.Debugger.enable(); + Protocol.Runtime.evaluate({expression: 'inspector.breakProgram(\'\', \'{}\')'}); + await Protocol.Debugger.oncePaused(); + session.disconnect(); + InspectorTest.quitImmediately(); +})();
diff --git a/src/v8/test/inspector/debugger/doesnt-step-into-injected-script-expected.txt b/src/v8/test/inspector/debugger/doesnt-step-into-injected-script-expected.txt new file mode 100644 index 0000000..29ac3bf --- /dev/null +++ b/src/v8/test/inspector/debugger/doesnt-step-into-injected-script-expected.txt
@@ -0,0 +1,17 @@ +Check that stepInto at then end of the script go to next user script instead InjectedScriptSource.js. +paused at: +(function boo() { setTimeout(() => 239, 0); #debugger; })() + + +paused at: +(function boo() { setTimeout(() => 239, 0); debugger; #})() + + +paused at: +(function boo() { setTimeout(() => 239, 0); debugger; })()# + + +paused at: +(function boo() { setTimeout(() => #239, 0); debugger; })() + +
diff --git a/src/v8/test/inspector/debugger/doesnt-step-into-injected-script.js b/src/v8/test/inspector/debugger/doesnt-step-into-injected-script.js new file mode 100644 index 0000000..98c7bf2 --- /dev/null +++ b/src/v8/test/inspector/debugger/doesnt-step-into-injected-script.js
@@ -0,0 +1,27 @@ +// 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. + +let {session, contextGroup, Protocol} = InspectorTest.start('Check that stepInto at then end of the script go to next user script instead InjectedScriptSource.js.'); + +(async function test() { + session.setupScriptMap(); + await Protocol.Debugger.enable(); + Protocol.Runtime.evaluate({expression: '(function boo() { setTimeout(() => 239, 0); debugger; })()\n'}); + await waitPauseAndDumpLocation(); + Protocol.Debugger.stepInto(); + await waitPauseAndDumpLocation(); + Protocol.Debugger.stepInto(); + await waitPauseAndDumpLocation(); + Protocol.Debugger.stepInto(); + await waitPauseAndDumpLocation(); + await Protocol.Debugger.disable(); + InspectorTest.completeTest(); +})(); + +async function waitPauseAndDumpLocation() { + var message = await Protocol.Debugger.oncePaused(); + InspectorTest.log('paused at:'); + session.logSourceLocation(message.params.callFrames[0].location); + return message; +}
diff --git a/src/v8/test/inspector/debugger/es6-module-script-parsed-expected.txt b/src/v8/test/inspector/debugger/es6-module-script-parsed-expected.txt new file mode 100644 index 0000000..7639ab6 --- /dev/null +++ b/src/v8/test/inspector/debugger/es6-module-script-parsed-expected.txt
@@ -0,0 +1,58 @@ +Debugger.scriptParsed and Debugger.scriptFailedToParse with ES6 module + +Running test: testLoadedModulesOnDebuggerEnable +{ + method : Debugger.scriptParsed + params : { + endColumn : 1 + endLine : 3 + executionContextId : <executionContextId> + hasSourceURL : false + hash : F8E59942466284E2766FD161CA6FFD024048A807 + isLiveEdit : false + isModule : true + length : 39 + scriptId : <scriptId> + sourceMapURL : + startColumn : 0 + startLine : 0 + url : module1.js + } +} + +Running test: testScriptEventsWhenDebuggerIsEnabled +{ + method : Debugger.scriptParsed + params : { + endColumn : 1 + endLine : 3 + executionContextId : <executionContextId> + hasSourceURL : false + hash : F8E59942466284E2766FD161CA6FFD024048A807 + isLiveEdit : false + isModule : true + length : 39 + scriptId : <scriptId> + sourceMapURL : + startColumn : 0 + startLine : 0 + url : module2.js + } +} +{ + method : Debugger.scriptFailedToParse + params : { + endColumn : 1 + endLine : 0 + executionContextId : <executionContextId> + hasSourceURL : false + hash : FF746120E4E4F1BA4CB5762843D429DC872EBA18 + isModule : true + length : 1 + scriptId : <scriptId> + sourceMapURL : + startColumn : 0 + startLine : 0 + url : module-with-syntax-error-2.js + } +}
diff --git a/src/v8/test/inspector/debugger/es6-module-script-parsed.js b/src/v8/test/inspector/debugger/es6-module-script-parsed.js new file mode 100644 index 0000000..94b623d --- /dev/null +++ b/src/v8/test/inspector/debugger/es6-module-script-parsed.js
@@ -0,0 +1,28 @@ +// Copyright 2017 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. + +let {session, contextGroup, Protocol} = InspectorTest.start('Debugger.scriptParsed and Debugger.scriptFailedToParse with ES6 module'); + +let moduleSource = ` +export function foo() { + return 42; +}`; + +contextGroup.addModule(moduleSource, 'module1.js'); +contextGroup.addModule('}', 'module-with-syntax-error-1.js'); + +Protocol.Debugger.onScriptParsed(InspectorTest.logMessage); +Protocol.Debugger.onScriptFailedToParse(InspectorTest.logMessage); + +InspectorTest.runTestSuite([ + function testLoadedModulesOnDebuggerEnable(next) { + Protocol.Debugger.enable().then(next); + }, + + function testScriptEventsWhenDebuggerIsEnabled(next) { + contextGroup.addModule(moduleSource, 'module2.js'); + contextGroup.addModule('}', 'module-with-syntax-error-2.js'); + InspectorTest.waitForPendingTasks().then(next); + } +]);
diff --git a/src/v8/test/inspector/debugger/es6-module-set-script-source-expected.txt b/src/v8/test/inspector/debugger/es6-module-set-script-source-expected.txt new file mode 100644 index 0000000..cd0ef1f --- /dev/null +++ b/src/v8/test/inspector/debugger/es6-module-set-script-source-expected.txt
@@ -0,0 +1,8 @@ +Checks that Debugger.setScriptSource doesn't crash with modules +{ + error : { + code : -32000 + message : Editing module's script is not supported. + } + id : <messageId> +}
diff --git a/src/v8/test/inspector/debugger/es6-module-set-script-source.js b/src/v8/test/inspector/debugger/es6-module-set-script-source.js new file mode 100644 index 0000000..81d97b6 --- /dev/null +++ b/src/v8/test/inspector/debugger/es6-module-set-script-source.js
@@ -0,0 +1,33 @@ +// Copyright 2017 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. + +let {session, contextGroup, Protocol} = InspectorTest.start('Checks that Debugger.setScriptSource doesn\'t crash with modules'); + +var module1 = ` +export function foo() { + return 42; +}`; + +var editedModule1 = ` +export function foo() { + return 239; +}`; + +var module2 = ` +import { foo } from 'module1'; +console.log(foo()); +`; + +var module1Id; +Protocol.Debugger.onScriptParsed(message => { + if (message.params.url === 'module1') + module1Id = message.params.scriptId; +}); +Protocol.Debugger.enable() + .then(() => contextGroup.addModule(module1, 'module1')) + .then(() => contextGroup.addModule(module2, 'module2')) + .then(() => InspectorTest.waitForPendingTasks()) + .then(() => Protocol.Debugger.setScriptSource({ scriptId: module1Id, scriptSource: editedModule1 })) + .then(InspectorTest.logMessage) + .then(InspectorTest.completeTest);
diff --git a/src/v8/test/inspector/debugger/eval-scopes-expected.txt b/src/v8/test/inspector/debugger/eval-scopes-expected.txt new file mode 100644 index 0000000..71d6618 --- /dev/null +++ b/src/v8/test/inspector/debugger/eval-scopes-expected.txt
@@ -0,0 +1,20 @@ +Tests that variables introduced in eval scopes are accessible +{ + id : <messageId> + result : { + result : [ + [0] : { + configurable : true + enumerable : true + isOwn : true + name : hest + value : { + description : 420 + type : number + value : 420 + } + writable : true + } + ] + } +}
diff --git a/src/v8/test/inspector/debugger/eval-scopes.js b/src/v8/test/inspector/debugger/eval-scopes.js new file mode 100644 index 0000000..e5a0f13 --- /dev/null +++ b/src/v8/test/inspector/debugger/eval-scopes.js
@@ -0,0 +1,45 @@ +// 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. + +let {session, contextGroup, Protocol} = InspectorTest.start('Tests that variables introduced in eval scopes are accessible'); + +contextGroup.addScript( +`function testNonEmptyEvalScope() { + eval("'use strict'; var hest = 420; debugger;"); +} +function testEmptyEvalScope() { + eval("var fisk = 42; testNonEmptyEvalScope();"); +}`); + +Protocol.Debugger.enable(); +Protocol.Debugger.oncePaused().then(dumpScopeOnPause); +Protocol.Runtime.evaluate({ "expression": "testEmptyEvalScope();" }); + +var waitScopeObjects = 0; +function dumpScopeOnPause(message) +{ + var scopeChain = message.params.callFrames[0].scopeChain; + var evalScopeObjectIds = []; + for (var scope of scopeChain) { + if (scope.type === "eval") { + evalScopeObjectIds.push(scope.object.objectId); + } + } + waitScopeObjects = evalScopeObjectIds.length; + if (!waitScopeObjects) { + InspectorTest.completeTest(); + } else { + for (var objectId of evalScopeObjectIds) + Protocol.Runtime.getProperties({ "objectId" : objectId }) + .then(dumpProperties); + } +} + +function dumpProperties(message) +{ + InspectorTest.logMessage(message); + --waitScopeObjects; + if (!waitScopeObjects) + Protocol.Debugger.resume().then(InspectorTest.completeTest); +}
diff --git a/src/v8/test/inspector/debugger/evaluate-on-call-frame-in-module-expected.txt b/src/v8/test/inspector/debugger/evaluate-on-call-frame-in-module-expected.txt new file mode 100644 index 0000000..e4819bd --- /dev/null +++ b/src/v8/test/inspector/debugger/evaluate-on-call-frame-in-module-expected.txt
@@ -0,0 +1,505 @@ +Tests evaluateOnCallFrame in module. + +Running test: testTotal +foo1 (module1:7:2) +foo2 (module2:6:9) +(anonymous) (module3:4:0) +local:foo1 +[ + [0] : c1 = 12 + [1] : g1 = 2 +] +module +[ + [0] : a1 = 10 + [1] : g1 = 1 + [2] : b1 = 11 + [3] : foo1 = function foo1() { let c1 = 12; let g1 = 2; debugger; return a1 + b1 + c1 + g1; } +] +global +[ + ... +] +Check variables in frame#0 + let g1 = 2; + #debugger; + return a1 + b1 + c1 + g1; + +Array = +{ + className : Function + description : function Array() { [native code] } + objectId : <objectId> + type : function +} +c1 = +{ + description : 12 + type : number + value : 12 +} +Evaluating: ++c1 +updated c1 = +{ + description : 13 + type : number + value : 13 +} +Evaluating: --c1 +g1 = +{ + description : 2 + type : number + value : 2 +} +Evaluating: ++g1 +updated g1 = +{ + description : 3 + type : number + value : 3 +} +Evaluating: --g1 +a1 = +{ + description : 10 + type : number + value : 10 +} +Evaluating: ++a1 +updated a1 = +{ + description : 11 + type : number + value : 11 +} +Evaluating: --a1 +b1 = +{ + description : 11 + type : number + value : 11 +} +Evaluating: ++b1 +updated b1 = +{ + description : 12 + type : number + value : 12 +} +Evaluating: --b1 +foo1 = +{ + className : Function + description : function foo1() { let c1 = 12; let g1 = 2; debugger; return a1 + b1 + c1 + g1; } + objectId : <objectId> + type : function +} +local:foo2 +[ + [0] : c2 = 22 +] +module +[ + [0] : a2 = 20 + [1] : foo1 = function foo1() { let c1 = 12; let g1 = 2; debugger; return a1 + b1 + c1 + g1; } + [2] : b2 = 21 + [3] : foo2 = function foo2() { let c2 = 22; return foo1() + a2 + b2 + c2; } +] +global +[ + ... +] +Check variables in frame#1 + let c2 = 22; + return #foo1() + a2 + b2 + c2; +} + +Array = +{ + className : Function + description : function Array() { [native code] } + objectId : <objectId> + type : function +} +c2 = +{ + description : 22 + type : number + value : 22 +} +Evaluating: ++c2 +updated c2 = +{ + description : 23 + type : number + value : 23 +} +Evaluating: --c2 +a2 = +{ + description : 20 + type : number + value : 20 +} +Evaluating: ++a2 +updated a2 = +{ + description : 21 + type : number + value : 21 +} +Evaluating: --a2 +foo1 = +{ + className : Function + description : function foo1() { let c1 = 12; let g1 = 2; debugger; return a1 + b1 + c1 + g1; } + objectId : <objectId> + type : function +} +b2 = +{ + description : 21 + type : number + value : 21 +} +Evaluating: ++b2 +updated b2 = +{ + description : 22 + type : number + value : 22 +} +Evaluating: --b2 +foo2 = +{ + className : Function + description : function foo2() { let c2 = 22; return foo1() + a2 + b2 + c2; } + objectId : <objectId> + type : function +} +module +[ + [0] : a3 = 30 + [1] : foo2 = function foo2() { let c2 = 22; return foo1() + a2 + b2 + c2; } + [2] : b3 = 31 +] +global +[ + ... +] +Check variables in frame#2 +export let b3 = 31; +#foo2(); + + +Array = +{ + className : Function + description : function Array() { [native code] } + objectId : <objectId> + type : function +} +a3 = +{ + description : 30 + type : number + value : 30 +} +Evaluating: ++a3 +updated a3 = +{ + description : 31 + type : number + value : 31 +} +Evaluating: --a3 +foo2 = +{ + className : Function + description : function foo2() { let c2 = 22; return foo1() + a2 + b2 + c2; } + objectId : <objectId> + type : function +} +b3 = +{ + description : 31 + type : number + value : 31 +} +Evaluating: ++b3 +updated b3 = +{ + description : 32 + type : number + value : 32 +} +Evaluating: --b3 + +Running test: testAnother +(anonymous) (module4:5:13) +bar (module4:5:24) +(anonymous) (module4:7:0) +local +[ +] +closure:bar +[ + [0] : a = 0 +] +module +[ + [0] : a = 1 + [1] : b = 2 + [2] : bar = function bar() { let a = 0; (() => {a; debugger;})(); } +] +global +[ + ... +] +Check variables in frame#0 + let a = 0; + (() => {a; #debugger;})(); +}; + +Array = +{ + className : Function + description : function Array() { [native code] } + objectId : <objectId> + type : function +} +a = +{ + description : 0 + type : number + value : 0 +} +Evaluating: ++a +updated a = +{ + description : 1 + type : number + value : 1 +} +Evaluating: --a +b = +{ + description : 2 + type : number + value : 2 +} +Evaluating: ++b +updated b = +{ + description : 3 + type : number + value : 3 +} +Evaluating: --b +bar = +{ + className : Function + description : function bar() { let a = 0; (() => {a; debugger;})(); } + objectId : <objectId> + type : function +} +local:bar +[ + [0] : a = 0 +] +module +[ + [0] : a = 1 + [1] : b = 2 + [2] : bar = function bar() { let a = 0; (() => {a; debugger;})(); } +] +global +[ + ... +] +Check variables in frame#1 + let a = 0; + (() => {a; debugger;})#(); +}; + +Array = +{ + className : Function + description : function Array() { [native code] } + objectId : <objectId> + type : function +} +a = +{ + description : 0 + type : number + value : 0 +} +Evaluating: ++a +updated a = +{ + description : 1 + type : number + value : 1 +} +Evaluating: --a +b = +{ + description : 2 + type : number + value : 2 +} +Evaluating: ++b +updated b = +{ + description : 3 + type : number + value : 3 +} +Evaluating: --b +bar = +{ + className : Function + description : function bar() { let a = 0; (() => {a; debugger;})(); } + objectId : <objectId> + type : function +} +module +[ + [0] : a = 1 + [1] : b = 2 + [2] : bar = function bar() { let a = 0; (() => {a; debugger;})(); } +] +global +[ + ... +] +Check variables in frame#2 +}; +#bar(); + +Array = +{ + className : Function + description : function Array() { [native code] } + objectId : <objectId> + type : function +} +a = +{ + description : 1 + type : number + value : 1 +} +Evaluating: ++a +updated a = +{ + description : 2 + type : number + value : 2 +} +Evaluating: --a +b = +{ + description : 2 + type : number + value : 2 +} +Evaluating: ++b +updated b = +{ + description : 3 + type : number + value : 3 +} +Evaluating: --b +bar = +{ + className : Function + description : function bar() { let a = 0; (() => {a; debugger;})(); } + objectId : <objectId> + type : function +} + +Running test: testDifferentModuleVariables +(anonymous) (module5:5:0) +module +[ + [0] : b2 = 21 + [1] : a = 0 + [2] : b = 0 + [3] : c = 0 +] +global +[ + ... +] +Check variables in frame#0 +export var c = 0; +#debugger; + + +Array = +{ + className : Function + description : function Array() { [native code] } + objectId : <objectId> + type : function +} +b2 = +{ + description : 21 + type : number + value : 21 +} +Evaluating: ++b2 +updated b2 = +{ + description : 21 + type : number + value : 21 +} +Evaluating: --b2 +a = +{ + description : 0 + type : number + value : 0 +} +Evaluating: ++a +updated a = +{ + description : 0 + type : number + value : 0 +} +Evaluating: --a +b = +{ + description : 0 + type : number + value : 0 +} +Evaluating: ++b +updated b = +{ + description : 1 + type : number + value : 1 +} +Evaluating: --b +c = +{ + description : 0 + type : number + value : 0 +} +Evaluating: ++c +updated c = +{ + description : 1 + type : number + value : 1 +} +Evaluating: --c
diff --git a/src/v8/test/inspector/debugger/evaluate-on-call-frame-in-module.js b/src/v8/test/inspector/debugger/evaluate-on-call-frame-in-module.js new file mode 100644 index 0000000..ef9050e --- /dev/null +++ b/src/v8/test/inspector/debugger/evaluate-on-call-frame-in-module.js
@@ -0,0 +1,141 @@ +// Copyright 2017 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. + +let {session, contextGroup, Protocol} = + InspectorTest.start('Tests evaluateOnCallFrame in module.'); + +var module1 = ` +let a1 = 10; +let g1 = 1; +export let b1 = 11; +export function foo1() { + let c1 = 12; + let g1 = 2; + debugger; + return a1 + b1 + c1 + g1; +}`; + +var module2 = ` +import { foo1 } from 'module1'; +let a2 = 20; +export let b2 = 21; +export function foo2() { + let c2 = 22; + return foo1() + a2 + b2 + c2; +}`; + +var module3 = ` +import { foo2 } from 'module2'; +let a3 = 30; +export let b3 = 31; +foo2(); +`; + +var module4 = ` +let a = 1; +let b = 2; +function bar() { + let a = 0; + (() => {a; debugger;})(); +}; +bar();`; + +var module5 = ` +import { b2 } from 'module2'; +export const a = 0; +export let b = 0; +export var c = 0; +debugger; +`; + +InspectorTest.runAsyncTestSuite([ + async function testTotal() { + session.setupScriptMap(); + Protocol.Debugger.enable(); + contextGroup.addModule(module1, 'module1'); + contextGroup.addModule(module2, 'module2'); + contextGroup.addModule(module3, 'module3'); + let {params:{callFrames}} = (await Protocol.Debugger.oncePaused()); + session.logCallFrames(callFrames); + for (let i = 0; i < callFrames.length; ++i) { + await checkFrame(callFrames[i], i); + } + await Protocol.Debugger.resume(); + }, + + async function testAnother() { + contextGroup.addModule(module4, 'module4'); + let {params:{callFrames}} = (await Protocol.Debugger.oncePaused()); + session.logCallFrames(callFrames); + for (let i = 0; i < callFrames.length; ++i) { + await checkFrame(callFrames[i], i); + } + await Protocol.Debugger.resume(); + }, + + async function testDifferentModuleVariables() { + contextGroup.addModule(module5, 'module5'); + let {params:{callFrames}} = (await Protocol.Debugger.oncePaused()); + session.logCallFrames(callFrames); + for (let i = 0; i < callFrames.length; ++i) { + await checkFrame(callFrames[i], i); + } + await Protocol.Debugger.resume(); + } +]); + +async function checkFrame(frame, i) { + let variables = new Set(); + variables.add('Array'); + + for (let scopeChain of frame.scopeChain) { + if (scopeChain.name) { + InspectorTest.log(scopeChain.type + ':' + scopeChain.name); + } else { + InspectorTest.log(scopeChain.type); + } + if (scopeChain.type === 'global') { + InspectorTest.log('[\n ...\n]'); + continue; + } + let {result: {result}} = await Protocol.Runtime.getProperties({ + objectId: scopeChain.object.objectId}); + result.forEach(v => variables.add(v.name)); + result = result.map(v => v.value ? + (v.name + ' = ' + v.value.description) : (v.name)); + InspectorTest.logMessage(result); + } + + InspectorTest.log(`Check variables in frame#${i}`); + await session.logSourceLocation(frame.location); + await checkVariables(frame.callFrameId, variables); +} + +async function checkVariables(callFrameId, names) { + for (let name of names) { + var {result:{result}} = await Protocol.Debugger.evaluateOnCallFrame({ + callFrameId, expression: name}); + if (result.type === 'object' && result.subtype && result.subtype === 'error') { + continue; + } + InspectorTest.log(name + ' = '); + InspectorTest.logMessage(result); + if (result.type === "number") { + let updateExpression = '++' + name; + InspectorTest.log('Evaluating: ' + updateExpression); + await Protocol.Debugger.evaluateOnCallFrame({ + callFrameId, expression: updateExpression}); + + var {result:{result}} = await Protocol.Debugger.evaluateOnCallFrame({ + callFrameId, expression: name}); + InspectorTest.log('updated ' + name + ' = '); + InspectorTest.logMessage(result); + + updateExpression = '--' + name; + InspectorTest.log('Evaluating: ' + updateExpression); + await Protocol.Debugger.evaluateOnCallFrame({ + callFrameId, expression: updateExpression}); + } + } +}
diff --git a/src/v8/test/inspector/debugger/for-of-loops-expected.txt b/src/v8/test/inspector/debugger/for-of-loops-expected.txt new file mode 100644 index 0000000..6d23c94 --- /dev/null +++ b/src/v8/test/inspector/debugger/for-of-loops-expected.txt
@@ -0,0 +1,395 @@ +Tests breakable locations in for-of loops. + +Running test: testBreakLocations + +Running test: testStepInto + +function testFunction() { + var obj = |_|{a : 1}; + var arr = |_|[1]; + var all = |_|[]; + for (var |_|k in |_|arr) { all.|C|push(k); } + for (var |_|k of |_|arr) { all.|C|push(k); } + for (var |_|k in |_|obj) { all.|C|push(k); } + for (let |_|k in |_|arr) { all.|C|push(k); } + for (let |_|k of |_|arr) { all.|C|push(k); } + for (let |_|k in |_|obj) { all.|C|push(k); } + + var iterable = |_|{ + [Symbol.iterator]() { + |_|return { + i: 0, + next() { + if (this.|_|i < 1) { + |_|return { value: this.i++, done: false };|R| + } + |_|return { value: undefined, done: true };|R| + } + };|R| + } + }; + for (var |_|k of |_|iterable) { all.|C|push(k); } + |_|iterable.i = 0; + for (let |_|k of |_|iterable) { all.|C|push(k); } +|R|} + +(anonymous) (expr.js:0:0) + + +testFunction (test.js:2:12) +(anonymous) (expr.js:0:0) +function testFunction() { + var obj = #{a : 1}; + var arr = [1]; + +testFunction (test.js:3:12) +(anonymous) (expr.js:0:0) + var obj = {a : 1}; + var arr = #[1]; + var all = []; + +testFunction (test.js:4:12) +(anonymous) (expr.js:0:0) + var arr = [1]; + var all = #[]; + for (var k in arr) { all.push(k); } + +testFunction (test.js:5:16) +(anonymous) (expr.js:0:0) + var all = []; + for (var k in #arr) { all.push(k); } + for (var k of arr) { all.push(k); } + +testFunction (test.js:5:11) +(anonymous) (expr.js:0:0) + var all = []; + for (var #k in arr) { all.push(k); } + for (var k of arr) { all.push(k); } + +testFunction (test.js:5:27) +(anonymous) (expr.js:0:0) + var all = []; + for (var k in arr) { all.#push(k); } + for (var k of arr) { all.push(k); } + +testFunction (test.js:5:11) +(anonymous) (expr.js:0:0) + var all = []; + for (var #k in arr) { all.push(k); } + for (var k of arr) { all.push(k); } + +testFunction (test.js:6:16) +(anonymous) (expr.js:0:0) + for (var k in arr) { all.push(k); } + for (var k of #arr) { all.push(k); } + for (var k in obj) { all.push(k); } + +testFunction (test.js:6:11) +(anonymous) (expr.js:0:0) + for (var k in arr) { all.push(k); } + for (var #k of arr) { all.push(k); } + for (var k in obj) { all.push(k); } + +testFunction (test.js:6:27) +(anonymous) (expr.js:0:0) + for (var k in arr) { all.push(k); } + for (var k of arr) { all.#push(k); } + for (var k in obj) { all.push(k); } + +testFunction (test.js:6:11) +(anonymous) (expr.js:0:0) + for (var k in arr) { all.push(k); } + for (var #k of arr) { all.push(k); } + for (var k in obj) { all.push(k); } + +testFunction (test.js:7:16) +(anonymous) (expr.js:0:0) + for (var k of arr) { all.push(k); } + for (var k in #obj) { all.push(k); } + for (let k in arr) { all.push(k); } + +testFunction (test.js:7:11) +(anonymous) (expr.js:0:0) + for (var k of arr) { all.push(k); } + for (var #k in obj) { all.push(k); } + for (let k in arr) { all.push(k); } + +testFunction (test.js:7:27) +(anonymous) (expr.js:0:0) + for (var k of arr) { all.push(k); } + for (var k in obj) { all.#push(k); } + for (let k in arr) { all.push(k); } + +testFunction (test.js:7:11) +(anonymous) (expr.js:0:0) + for (var k of arr) { all.push(k); } + for (var #k in obj) { all.push(k); } + for (let k in arr) { all.push(k); } + +testFunction (test.js:8:16) +(anonymous) (expr.js:0:0) + for (var k in obj) { all.push(k); } + for (let k in #arr) { all.push(k); } + for (let k of arr) { all.push(k); } + +testFunction (test.js:8:11) +(anonymous) (expr.js:0:0) + for (var k in obj) { all.push(k); } + for (let #k in arr) { all.push(k); } + for (let k of arr) { all.push(k); } + +testFunction (test.js:8:27) +(anonymous) (expr.js:0:0) + for (var k in obj) { all.push(k); } + for (let k in arr) { all.#push(k); } + for (let k of arr) { all.push(k); } + +testFunction (test.js:8:11) +(anonymous) (expr.js:0:0) + for (var k in obj) { all.push(k); } + for (let #k in arr) { all.push(k); } + for (let k of arr) { all.push(k); } + +testFunction (test.js:9:16) +(anonymous) (expr.js:0:0) + for (let k in arr) { all.push(k); } + for (let k of #arr) { all.push(k); } + for (let k in obj) { all.push(k); } + +testFunction (test.js:9:11) +(anonymous) (expr.js:0:0) + for (let k in arr) { all.push(k); } + for (let #k of arr) { all.push(k); } + for (let k in obj) { all.push(k); } + +testFunction (test.js:9:27) +(anonymous) (expr.js:0:0) + for (let k in arr) { all.push(k); } + for (let k of arr) { all.#push(k); } + for (let k in obj) { all.push(k); } + +testFunction (test.js:9:11) +(anonymous) (expr.js:0:0) + for (let k in arr) { all.push(k); } + for (let #k of arr) { all.push(k); } + for (let k in obj) { all.push(k); } + +testFunction (test.js:10:16) +(anonymous) (expr.js:0:0) + for (let k of arr) { all.push(k); } + for (let k in #obj) { all.push(k); } + + +testFunction (test.js:10:11) +(anonymous) (expr.js:0:0) + for (let k of arr) { all.push(k); } + for (let #k in obj) { all.push(k); } + + +testFunction (test.js:10:27) +(anonymous) (expr.js:0:0) + for (let k of arr) { all.push(k); } + for (let k in obj) { all.#push(k); } + + +testFunction (test.js:10:11) +(anonymous) (expr.js:0:0) + for (let k of arr) { all.push(k); } + for (let #k in obj) { all.push(k); } + + +testFunction (test.js:12:17) +(anonymous) (expr.js:0:0) + + var iterable = #{ + [Symbol.iterator]() { + +testFunction (test.js:25:16) +(anonymous) (expr.js:0:0) + }; + for (var k of #iterable) { all.push(k); } + iterable.i = 0; + +[Symbol.iterator] (test.js:14:6) +testFunction (test.js:25:16) +(anonymous) (expr.js:0:0) + [Symbol.iterator]() { + #return { + i: 0, + +[Symbol.iterator] (test.js:22:8) +testFunction (test.js:25:16) +(anonymous) (expr.js:0:0) + } + };# + } + +testFunction (test.js:25:11) +(anonymous) (expr.js:0:0) + }; + for (var #k of iterable) { all.push(k); } + iterable.i = 0; + +next (test.js:17:19) +testFunction (test.js:25:11) +(anonymous) (expr.js:0:0) + next() { + if (this.#i < 1) { + return { value: this.i++, done: false }; + +next (test.js:18:12) +testFunction (test.js:25:11) +(anonymous) (expr.js:0:0) + if (this.i < 1) { + #return { value: this.i++, done: false }; + } + +next (test.js:18:52) +testFunction (test.js:25:11) +(anonymous) (expr.js:0:0) + if (this.i < 1) { + return { value: this.i++, done: false };# + } + +testFunction (test.js:25:32) +(anonymous) (expr.js:0:0) + }; + for (var k of iterable) { all.#push(k); } + iterable.i = 0; + +testFunction (test.js:25:11) +(anonymous) (expr.js:0:0) + }; + for (var #k of iterable) { all.push(k); } + iterable.i = 0; + +next (test.js:17:19) +testFunction (test.js:25:11) +(anonymous) (expr.js:0:0) + next() { + if (this.#i < 1) { + return { value: this.i++, done: false }; + +next (test.js:20:10) +testFunction (test.js:25:11) +(anonymous) (expr.js:0:0) + } + #return { value: undefined, done: true }; + } + +next (test.js:20:50) +testFunction (test.js:25:11) +(anonymous) (expr.js:0:0) + } + return { value: undefined, done: true };# + } + +testFunction (test.js:26:2) +(anonymous) (expr.js:0:0) + for (var k of iterable) { all.push(k); } + #iterable.i = 0; + for (let k of iterable) { all.push(k); } + +testFunction (test.js:27:16) +(anonymous) (expr.js:0:0) + iterable.i = 0; + for (let k of #iterable) { all.push(k); } +} + +[Symbol.iterator] (test.js:14:6) +testFunction (test.js:27:16) +(anonymous) (expr.js:0:0) + [Symbol.iterator]() { + #return { + i: 0, + +[Symbol.iterator] (test.js:22:8) +testFunction (test.js:27:16) +(anonymous) (expr.js:0:0) + } + };# + } + +testFunction (test.js:27:11) +(anonymous) (expr.js:0:0) + iterable.i = 0; + for (let #k of iterable) { all.push(k); } +} + +next (test.js:17:19) +testFunction (test.js:27:11) +(anonymous) (expr.js:0:0) + next() { + if (this.#i < 1) { + return { value: this.i++, done: false }; + +next (test.js:18:12) +testFunction (test.js:27:11) +(anonymous) (expr.js:0:0) + if (this.i < 1) { + #return { value: this.i++, done: false }; + } + +next (test.js:18:52) +testFunction (test.js:27:11) +(anonymous) (expr.js:0:0) + if (this.i < 1) { + return { value: this.i++, done: false };# + } + +testFunction (test.js:27:32) +(anonymous) (expr.js:0:0) + iterable.i = 0; + for (let k of iterable) { all.#push(k); } +} + +testFunction (test.js:27:11) +(anonymous) (expr.js:0:0) + iterable.i = 0; + for (let #k of iterable) { all.push(k); } +} + +next (test.js:17:19) +testFunction (test.js:27:11) +(anonymous) (expr.js:0:0) + next() { + if (this.#i < 1) { + return { value: this.i++, done: false }; + +next (test.js:20:10) +testFunction (test.js:27:11) +(anonymous) (expr.js:0:0) + } + #return { value: undefined, done: true }; + } + +next (test.js:20:50) +testFunction (test.js:27:11) +(anonymous) (expr.js:0:0) + } + return { value: undefined, done: true };# + } + +testFunction (test.js:28:0) +(anonymous) (expr.js:0:0) + for (let k of iterable) { all.push(k); } +#} + +(anonymous) (expr.js:0:34) + + + +Running test: testStepIntoAfterBreakpoint +testFunction (test.js:25:11) +(anonymous) (expr.js:0:0) + }; + for (var #k of iterable) { all.push(k); } + iterable.i = 0; + +next (test.js:17:19) +testFunction (test.js:25:11) +(anonymous) (expr.js:0:0) + next() { + if (this.#i < 1) { + return { value: this.i++, done: false }; +
diff --git a/src/v8/test/inspector/debugger/for-of-loops.js b/src/v8/test/inspector/debugger/for-of-loops.js new file mode 100644 index 0000000..0fa0a26 --- /dev/null +++ b/src/v8/test/inspector/debugger/for-of-loops.js
@@ -0,0 +1,82 @@ +// Copyright 2017 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. + +let {session, contextGroup, Protocol} = + InspectorTest.start('Tests breakable locations in for-of loops.'); + +let source = ` +function testFunction() { + var obj = {a : 1}; + var arr = [1]; + var all = []; + for (var k in arr) { all.push(k); } + for (var k of arr) { all.push(k); } + for (var k in obj) { all.push(k); } + for (let k in arr) { all.push(k); } + for (let k of arr) { all.push(k); } + for (let k in obj) { all.push(k); } + + var iterable = { + [Symbol.iterator]() { + return { + i: 0, + next() { + if (this.i < 1) { + return { value: this.i++, done: false }; + } + return { value: undefined, done: true }; + } + }; + } + }; + for (var k of iterable) { all.push(k); } + iterable.i = 0; + for (let k of iterable) { all.push(k); } +} +//# sourceURL=test.js`; + +contextGroup.addScript(source); +session.setupScriptMap(); + +InspectorTest.runAsyncTestSuite([ + async function testBreakLocations() { + Protocol.Debugger.enable(); + let {params:{scriptId}} = await Protocol.Debugger.onceScriptParsed(); + let {result:{locations}} = await Protocol.Debugger.getPossibleBreakpoints({ + start: {lineNumber: 0, columnNumber : 0, scriptId}}); + session.logBreakLocations(locations); + }, + + async function testStepInto() { + Protocol.Debugger.pause(); + let fin = Protocol.Runtime.evaluate({ + expression: 'testFunction()//# sourceURL=expr.js'}).then(() => false); + let result; + while (result = await Promise.race([fin, Protocol.Debugger.oncePaused()])) { + let {params:{callFrames}} = result; + session.logCallFrames(callFrames); + session.logSourceLocation(callFrames[0].location); + Protocol.Debugger.stepInto(); + } + Protocol.Runtime.evaluate({expression: '42'}); + await Protocol.Debugger.oncePaused(); + await Protocol.Debugger.resume(); + }, + + async function testStepIntoAfterBreakpoint() { + Protocol.Debugger.setBreakpointByUrl({lineNumber: 25, url: 'test.js'}); + Protocol.Runtime.evaluate({ + expression: 'testFunction()//# sourceURL=expr.js'}); + await awaitPausedAndDump(); + Protocol.Debugger.stepInto(); + await awaitPausedAndDump(); + await Protocol.Debugger.resume(); + + async function awaitPausedAndDump() { + let {params:{callFrames}} = await Protocol.Debugger.oncePaused(); + session.logCallFrames(callFrames); + session.logSourceLocation(callFrames[0].location); + } + } +]);
diff --git a/src/v8/test/inspector/debugger/framework-break-expected.txt b/src/v8/test/inspector/debugger/framework-break-expected.txt new file mode 100644 index 0000000..e858e83 --- /dev/null +++ b/src/v8/test/inspector/debugger/framework-break-expected.txt
@@ -0,0 +1,70 @@ +Checks that breaks in framework code correctly processed. + +Running test: testConsoleAssert +> all frames in framework: +> mixed, top frame in framework: +frameworkAssert (framework.js:10:10) +(anonymous) (user.js:0:0) + + +Running test: testCaughtException +> all frames in framework: +> mixed, top frame in framework: + +Running test: testUncaughtException +> all frames in framework: +> mixed, top frame in framework: +throwUncaughtError (framework.js:21:2) +(anonymous) (user.js:0:0) + + +Running test: testUncaughtExceptionWithInlinedFrame +> mixed top frame in framework: +throwUserException (user.js:66:2) +inlinedWrapper (framework.js:56:4) +throwInlinedUncaughtError (framework.js:59:2) +(anonymous) (framework.js:0:0) + + +Running test: testBreakpoint +> all frames in framework: +breakpoint (framework.js:25:2) +(anonymous) (framework.js:0:0) + +> mixed, top frame in framework: +breakpoint (framework.js:25:2) +(anonymous) (user.js:0:0) + + +Running test: testDebuggerStatement +> all frames in framework: +> mixed, top frame in framework: + +Running test: testSyncDOMBreakpoint +> all frames in framework: +> mixed, top frame in framework: +syncDOMBreakpoint (framework.js:33:12) +(anonymous) (user.js:0:0) + + +Running test: testSyncDOMBreakpointWithInlinedUserFrame +> mixed, top frame in framework: +syncDOMBreakpoint (framework.js:33:12) +userFunction (user.js:70:2) +inlinedWrapper (framework.js:64:4) +syncDOMBreakpointWithInlinedUserFrame (framework.js:67:2) +(anonymous) (framework.js:0:0) + + +Running test: testAsyncDOMBreakpoint +> all frames in framework: +(anonymous) (user.js:0:0) + + +Running test: testCaughtSyntaxError +> all frames in framework: +> mixed, top frame in framework: + +Running test: testCaughtJSONParseError +> all frames in framework: +> mixed, top frame in framework:
diff --git a/src/v8/test/inspector/debugger/framework-break.js b/src/v8/test/inspector/debugger/framework-break.js new file mode 100644 index 0000000..9b9fee6 --- /dev/null +++ b/src/v8/test/inspector/debugger/framework-break.js
@@ -0,0 +1,234 @@ +// Copyright 2017 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: --allow-natives-syntax + +let {session, contextGroup, Protocol} = InspectorTest.start('Checks that breaks in framework code correctly processed.'); + +contextGroup.addScript(` +function frameworkAssert() { + console.assert(false); +} + +function throwCaughtError() { + try { + throw new Error(); + } catch (e) { + } +} + +function throwUncaughtError() { + throw new Error(); +} + +function breakpoint() { + return 239; +} + +function debuggerStatement() { + debugger; +} + +function syncDOMBreakpoint() { + inspector.breakProgram('', ''); +} + +function asyncDOMBreakpoint() { + return 42; +} + +function throwCaughtSyntaxError() { + try { + eval('}'); + } catch (e) { + } +} + +function throwFromJSONParse() { + try { + JSON.parse('ping'); + } catch (e) { + } +} + +function throwInlinedUncaughtError() { + function inlinedWrapper() { + throwUserException(); + } + %OptimizeFunctionOnNextCall(inlinedWrapper); + inlinedWrapper(); +} + +function syncDOMBreakpointWithInlinedUserFrame() { + function inlinedWrapper() { + userFunction(); + } + %OptimizeFunctionOnNextCall(inlinedWrapper); + inlinedWrapper(); +} + +//# sourceURL=framework.js`, 8, 26); + +contextGroup.addScript(` +function throwUserException() { + throw new Error(); +} + +function userFunction() { + syncDOMBreakpoint(); +} + +//# sourceURL=user.js`, 64, 26) + +session.setupScriptMap(); +Protocol.Debugger.onPaused(message => { + session.logCallFrames(message.params.callFrames); + InspectorTest.log(''); + Protocol.Debugger.resume(); +}); + +Protocol.Debugger.enable(); +Protocol.Debugger.setBlackboxPatterns({patterns: ['framework\.js']}); + +InspectorTest.runTestSuite([ + function testConsoleAssert(next) { + Protocol.Debugger.setPauseOnExceptions({state: 'all'}) + .then(() => InspectorTest.log('> all frames in framework:')) + .then( + () => Protocol.Runtime.evaluate( + {expression: 'frameworkAssert()//# sourceURL=framework.js'})) + .then(() => InspectorTest.log('> mixed, top frame in framework:')) + .then( + () => Protocol.Runtime.evaluate( + {expression: 'frameworkAssert()//# sourceURL=user.js'})) + .then(() => Protocol.Debugger.setPauseOnExceptions({state: 'none'})) + .then(next); + }, + + function testCaughtException(next) { + Protocol.Debugger.setPauseOnExceptions({state: 'all'}) + .then(() => InspectorTest.log('> all frames in framework:')) + .then( + () => Protocol.Runtime.evaluate( + {expression: 'throwCaughtError()//# sourceURL=framework.js'})) + .then(() => InspectorTest.log('> mixed, top frame in framework:')) + .then( + () => Protocol.Runtime.evaluate( + {expression: 'throwCaughtError()//# sourceURL=user.js'})) + .then(() => Protocol.Debugger.setPauseOnExceptions({state: 'none'})) + .then(next); + }, + + function testUncaughtException(next) { + Protocol.Debugger.setPauseOnExceptions({state: 'all'}) + .then(() => InspectorTest.log('> all frames in framework:')) + .then( + () => Protocol.Runtime.evaluate( + {expression: 'setTimeout(\'throwUncaughtError()//# sourceURL=framework.js\', 0)//# sourceURL=framework.js'})) + .then(() => Protocol.Runtime.evaluate({ expression: "new Promise(resolve => setTimeout(resolve, 0))", awaitPromise: true})) + .then(() => InspectorTest.log('> mixed, top frame in framework:')) + .then( + () => Protocol.Runtime.evaluate( + {expression: 'setTimeout(\'throwUncaughtError()//# sourceURL=user.js\', 0)'})) + .then(() => Protocol.Runtime.evaluate({ expression: "new Promise(resolve => setTimeout(resolve, 0))", awaitPromise: true})) + .then(() => Protocol.Debugger.setPauseOnExceptions({state: 'none'})) + .then(next); + }, + + function testUncaughtExceptionWithInlinedFrame(next) { + Protocol.Debugger.setPauseOnExceptions({state: 'all'}) + .then(() => InspectorTest.log('> mixed top frame in framework:')) + .then( + () => Protocol.Runtime.evaluate( + {expression: 'setTimeout(\'throwInlinedUncaughtError()//# sourceURL=framework.js\', 0)//# sourceURL=framework.js'})) + .then(() => Protocol.Runtime.evaluate({ expression: "new Promise(resolve => setTimeout(resolve, 0))", awaitPromise: true})) + .then(next); + }, + + function testBreakpoint(next) { + Protocol.Debugger.setBreakpointByUrl({lineNumber: 25, url: 'framework.js'}) + .then(() => InspectorTest.log('> all frames in framework:')) + .then( + () => Protocol.Runtime.evaluate( + {expression: 'breakpoint()//# sourceURL=framework.js'})) + .then(() => InspectorTest.log('> mixed, top frame in framework:')) + .then( + () => Protocol.Runtime.evaluate( + {expression: 'breakpoint()//# sourceURL=user.js'})) + .then(next); + }, + + function testDebuggerStatement(next) { + InspectorTest.log('> all frames in framework:'); + Protocol.Runtime + .evaluate({expression: 'debuggerStatement()//# sourceURL=framework.js'}) + .then(() => InspectorTest.log('> mixed, top frame in framework:')) + .then( + () => Protocol.Runtime.evaluate( + {expression: 'debuggerStatement()//# sourceURL=user.js'})) + .then(next); + }, + + function testSyncDOMBreakpoint(next) { + InspectorTest.log('> all frames in framework:'); + Protocol.Runtime + .evaluate({expression: 'syncDOMBreakpoint()//# sourceURL=framework.js'}) + .then(() => InspectorTest.log('> mixed, top frame in framework:')) + .then( + () => Protocol.Runtime.evaluate( + {expression: 'syncDOMBreakpoint()//# sourceURL=user.js'})) + .then(next); + }, + + function testSyncDOMBreakpointWithInlinedUserFrame(next) { + InspectorTest.log('> mixed, top frame in framework:'); + Protocol.Runtime + .evaluate({expression: 'syncDOMBreakpointWithInlinedUserFrame()//# sourceURL=framework.js'}) + .then(next); + }, + + function testAsyncDOMBreakpoint(next) { + contextGroup.schedulePauseOnNextStatement('', ''); + InspectorTest.log('> all frames in framework:'); + Protocol.Runtime + .evaluate( + {expression: 'asyncDOMBreakpoint()//# sourceURL=framework.js'}) + .then(() => contextGroup.cancelPauseOnNextStatement()) + .then( + () => Protocol.Runtime.evaluate( + {expression: '42//# sourceURL=user.js'})) + .then(() => contextGroup.schedulePauseOnNextStatement('', '')) + .then( + () => Protocol.Runtime.evaluate( + {expression: 'asyncDOMBreakpoint()//# sourceURL=user.js'})) + .then(next); + }, + + function testCaughtSyntaxError(next) { + Protocol.Debugger.setPauseOnExceptions({state: 'all'}) + .then(() => InspectorTest.log('> all frames in framework:')) + .then(() => Protocol.Runtime.evaluate({ + expression: 'throwCaughtSyntaxError()//# sourceURL=framework.js' + })) + .then(() => InspectorTest.log('> mixed, top frame in framework:')) + .then( + () => Protocol.Runtime.evaluate( + {expression: 'throwCaughtSyntaxError()//# sourceURL=user.js'})) + .then(() => Protocol.Debugger.setPauseOnExceptions({state: 'none'})) + .then(next); + }, + + function testCaughtJSONParseError(next) { + Protocol.Debugger.setPauseOnExceptions({state: 'all'}) + .then(() => InspectorTest.log('> all frames in framework:')) + .then( + () => Protocol.Runtime.evaluate( + {expression: 'throwFromJSONParse()//# sourceURL=framework.js'})) + .then(() => InspectorTest.log('> mixed, top frame in framework:')) + .then( + () => Protocol.Runtime.evaluate( + {expression: 'throwFromJSONParse()//# sourceURL=user.js'})) + .then(() => Protocol.Debugger.setPauseOnExceptions({state: 'none'})) + .then(next); + } +]);
diff --git a/src/v8/test/inspector/debugger/framework-nested-scheduled-break-expected.txt b/src/v8/test/inspector/debugger/framework-nested-scheduled-break-expected.txt new file mode 100644 index 0000000..f9901f0 --- /dev/null +++ b/src/v8/test/inspector/debugger/framework-nested-scheduled-break-expected.txt
@@ -0,0 +1,41 @@ +Checks nested scheduled break in framework code. +break reason: framework-break +break aux data: { + "data": "data for framework-break" +} +doFrameworkBreak (framework.js:20:12) +doFrameworkWork (framework.js:15:12) +frameworkCall (framework.js:9:12) +testFunction (user.js:27:12) +(anonymous) (expr.js:0:0) + +break reason: ambiguous +break aux data: { + "reasons": [ + { + "reason": "top-scheduled-break" + }, + { + "reason": "top-framework-scheduled-break", + "auxData": { + "data": "data for top-framework-scheduled-break" + } + } + ] +} +callback (user.js:31:17) +doFrameworkWork (framework.js:16:2) +frameworkCall (framework.js:9:12) +testFunction (user.js:27:12) +(anonymous) (expr.js:0:0) + +break reason: user-break +break aux data: { + "data": "data for user-break" +} +callback (user.js:32:12) +doFrameworkWork (framework.js:16:2) +frameworkCall (framework.js:9:12) +testFunction (user.js:27:12) +(anonymous) (expr.js:0:0) +
diff --git a/src/v8/test/inspector/debugger/framework-nested-scheduled-break.js b/src/v8/test/inspector/debugger/framework-nested-scheduled-break.js new file mode 100644 index 0000000..3e62991 --- /dev/null +++ b/src/v8/test/inspector/debugger/framework-nested-scheduled-break.js
@@ -0,0 +1,49 @@ +// Copyright 2017 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. + +let {session, contextGroup, Protocol} = InspectorTest.start('Checks nested scheduled break in framework code.'); + +contextGroup.addScript(` +function frameworkCall(callback) { + inspector.callWithScheduledBreak(doFrameworkWork.bind(null, callback), + 'top-framework-scheduled-break', + JSON.stringify({ data: 'data for top-framework-scheduled-break' })); +} + +function doFrameworkWork(callback) { + inspector.callWithScheduledBreak(doFrameworkBreak, 'should-not-be-a-reason', ''); + callback(); +} + +function doFrameworkBreak() { + inspector.breakProgram('framework-break', JSON.stringify({ data: 'data for framework-break' })); +} + +//# sourceURL=framework.js`, 7, 26); + +contextGroup.addScript(` +function testFunction() { + inspector.callWithScheduledBreak(frameworkCall.bind(null, callback), + 'top-scheduled-break', ''); +} + +function callback() { + inspector.breakProgram('user-break', JSON.stringify({ data: 'data for user-break' })); + return 42; +} + +//# sourceURL=user.js`, 25, 26); + +session.setupScriptMap(); +Protocol.Debugger.onPaused(message => { + InspectorTest.log('break reason: ' + message.params.reason); + InspectorTest.log('break aux data: ' + JSON.stringify(message.params.data || {}, null, ' ')); + session.logCallFrames(message.params.callFrames); + InspectorTest.log(''); + Protocol.Debugger.resume(); +}); +Protocol.Debugger.enable() + .then(() => Protocol.Debugger.setBlackboxPatterns({patterns: ['framework\.js']})) + .then(() => Protocol.Runtime.evaluate({ expression: 'testFunction()//# sourceURL=expr.js'})) + .then(InspectorTest.completeTest);
diff --git a/src/v8/test/inspector/debugger/framework-precise-ranges-expected.txt b/src/v8/test/inspector/debugger/framework-precise-ranges-expected.txt new file mode 100644 index 0000000..0e0791d --- /dev/null +++ b/src/v8/test/inspector/debugger/framework-precise-ranges-expected.txt
@@ -0,0 +1,140 @@ +Checks framework debugging with blackboxed ranges. + +Running test: testEntireScript +{ + id : <messageId> + result : { + } +} + +Running test: testFooNotBlackboxed +{ + id : <messageId> + result : { + } +} +foo (test.js:8:12) +testFunction (test.js:15:2) +(anonymous) (expr.js:0:0) + +foo (test.js:9:2) +testFunction (test.js:15:2) +(anonymous) (expr.js:0:0) + +foo (test.js:9:15) +testFunction (test.js:15:2) +(anonymous) (expr.js:0:0) + + +Running test: testFooBlackboxed +{ + id : <messageId> + result : { + } +} +testFunction (test.js:14:21) +(anonymous) (expr.js:0:0) + +testFunction (test.js:15:2) +(anonymous) (expr.js:0:0) + +boo (test.js:12:2) +foo (test.js:9:9) +testFunction (test.js:15:2) +(anonymous) (expr.js:0:0) + +boo (test.js:12:12) +foo (test.js:9:9) +testFunction (test.js:15:2) +(anonymous) (expr.js:0:0) + +testFunction (test.js:16:0) +(anonymous) (expr.js:0:0) + + +Running test: testBooPartiallyBlackboxed1 +{ + id : <messageId> + result : { + } +} +foo (test.js:8:12) +testFunction (test.js:15:2) +(anonymous) (expr.js:0:0) + +foo (test.js:9:2) +testFunction (test.js:15:2) +(anonymous) (expr.js:0:0) + +boo (test.js:12:2) +foo (test.js:9:9) +testFunction (test.js:15:2) +(anonymous) (expr.js:0:0) + +boo (test.js:12:12) +foo (test.js:9:9) +testFunction (test.js:15:2) +(anonymous) (expr.js:0:0) + +foo (test.js:9:15) +testFunction (test.js:15:2) +(anonymous) (expr.js:0:0) + + +Running test: testBooPartiallyBlackboxed2 +{ + id : <messageId> + result : { + } +} +foo (test.js:8:12) +testFunction (test.js:15:2) +(anonymous) (expr.js:0:0) + +foo (test.js:9:2) +testFunction (test.js:15:2) +(anonymous) (expr.js:0:0) + +boo (test.js:12:2) +foo (test.js:9:9) +testFunction (test.js:15:2) +(anonymous) (expr.js:0:0) + +boo (test.js:12:12) +foo (test.js:9:9) +testFunction (test.js:15:2) +(anonymous) (expr.js:0:0) + +foo (test.js:9:15) +testFunction (test.js:15:2) +(anonymous) (expr.js:0:0) + + +Running test: testBooPartiallyBlackboxed3 +{ + id : <messageId> + result : { + } +} +foo (test.js:8:12) +testFunction (test.js:15:2) +(anonymous) (expr.js:0:0) + +foo (test.js:9:2) +testFunction (test.js:15:2) +(anonymous) (expr.js:0:0) + +boo (test.js:12:2) +foo (test.js:9:9) +testFunction (test.js:15:2) +(anonymous) (expr.js:0:0) + +boo (test.js:12:12) +foo (test.js:9:9) +testFunction (test.js:15:2) +(anonymous) (expr.js:0:0) + +foo (test.js:9:15) +testFunction (test.js:15:2) +(anonymous) (expr.js:0:0) +
diff --git a/src/v8/test/inspector/debugger/framework-precise-ranges.js b/src/v8/test/inspector/debugger/framework-precise-ranges.js new file mode 100644 index 0000000..4f76033 --- /dev/null +++ b/src/v8/test/inspector/debugger/framework-precise-ranges.js
@@ -0,0 +1,78 @@ +// Copyright 2017 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. + +let {session, contextGroup, Protocol} = InspectorTest.start('Checks framework debugging with blackboxed ranges.'); + +contextGroup.addScript( + ` +function foo() { + return boo(); +} +function boo() { + return 42; +} +function testFunction() { + foo(); +} +//# sourceURL=test.js`, + 7, 26); + +session.setupScriptMap(); +Protocol.Debugger.onPaused(message => { + session.logCallFrames(message.params.callFrames); + InspectorTest.log(''); + Protocol.Debugger.stepInto(); +}); +var scriptId; +Protocol.Debugger.onScriptParsed(message => { + if (message.params.url === 'test.js') { + scriptId = message.params.scriptId; + } +}); + +Protocol.Debugger.enable() + .then(() => Protocol.Debugger.setBlackboxPatterns({patterns: ['expr\.js']})) + .then(() => InspectorTest.runTestSuite(testSuite)); + +var testSuite = [ + function testEntireScript(next) { + testPositions([position(0, 0)]).then(next); + }, + function testFooNotBlackboxed(next) { + testPositions([position(11, 0)]).then(next); + }, + function testFooBlackboxed(next) { + testPositions([position(8, 0), position(10, 3)]).then(next); + }, + function testBooPartiallyBlackboxed1(next) { + // first line is not blackboxed, second and third - blackboxed. + testPositions([position(12, 0)]).then(next); + }, + function testBooPartiallyBlackboxed2(next) { + // first line is blackboxed, second - not, third - blackboxed. + testPositions([ + position(11, 0), position(12, 0), position(13, 0) + ]).then(next); + }, + function testBooPartiallyBlackboxed3(next) { + // first line is blackboxed, second and third - not. + testPositions([ + position(11, 0), position(12, 0), position(14, 0) + ]).then(next); + } +]; + +function testPositions(positions) { + contextGroup.schedulePauseOnNextStatement('', ''); + return Protocol.Debugger + .setBlackboxedRanges({scriptId: scriptId, positions: positions}) + .then(InspectorTest.logMessage) + .then( + () => Protocol.Runtime.evaluate( + {expression: 'testFunction()//# sourceURL=expr.js'})); +} + +function position(line, column) { + return {lineNumber: line, columnNumber: column}; +}
diff --git a/src/v8/test/inspector/debugger/framework-stepping-expected.txt b/src/v8/test/inspector/debugger/framework-stepping-expected.txt new file mode 100644 index 0000000..fa2bb35 --- /dev/null +++ b/src/v8/test/inspector/debugger/framework-stepping-expected.txt
@@ -0,0 +1,102 @@ +Checks stepping with blackboxed frames on stack + +Running test: testStepIntoFromUser +(anonymous) (expr.js:0:0) + +Executing stepInto... +Executing stepInto... +userFoo (user.js:23:2) +frameworkCall (framework.js:10:23) +testStepFromUser (user.js:31:2) +(anonymous) (expr.js:0:0) + +Executing stepInto... +Executing stepInto... +userBoo (user.js:27:2) +frameworkCall (framework.js:10:23) +testStepFromUser (user.js:31:2) +(anonymous) (expr.js:0:0) + +Executing stepInto... +Executing stepInto... +testStepFromUser (user.js:32:0) +(anonymous) (expr.js:0:0) + +Executing resume... + +Running test: testStepOverFromUser +(anonymous) (expr.js:0:0) + +Executing stepInto... +Executing stepInto... +userFoo (user.js:23:2) +frameworkCall (framework.js:10:23) +testStepFromUser (user.js:31:2) +(anonymous) (expr.js:0:0) + +Executing stepOver... +Executing stepOver... +userBoo (user.js:27:2) +frameworkCall (framework.js:10:23) +testStepFromUser (user.js:31:2) +(anonymous) (expr.js:0:0) + +Executing stepOver... +Executing stepOver... +testStepFromUser (user.js:32:0) +(anonymous) (expr.js:0:0) + +Executing resume... + +Running test: testStepOutFromUser +(anonymous) (expr.js:0:0) + +Executing stepInto... +Executing stepInto... +userFoo (user.js:23:2) +frameworkCall (framework.js:10:23) +testStepFromUser (user.js:31:2) +(anonymous) (expr.js:0:0) + +Executing stepOut... +userBoo (user.js:27:2) +frameworkCall (framework.js:10:23) +testStepFromUser (user.js:31:2) +(anonymous) (expr.js:0:0) + +Executing resume... + +Running test: testStepIntoFromFramework +frameworkBreakAndCall (framework.js:14:12) +testStepFromFramework (user.js:35:2) +(anonymous) (expr.js:0:0) + +Executing stepInto... +userFoo (user.js:23:2) +frameworkBreakAndCall (framework.js:15:23) +testStepFromFramework (user.js:35:2) +(anonymous) (expr.js:0:0) + +Executing resume... + +Running test: testStepOverFromFramework +frameworkBreakAndCall (framework.js:14:12) +testStepFromFramework (user.js:35:2) +(anonymous) (expr.js:0:0) + +Executing stepOver... +testStepFromFramework (user.js:36:0) +(anonymous) (expr.js:0:0) + +Executing resume... + +Running test: testStepOutFromFramework +frameworkBreakAndCall (framework.js:14:12) +testStepFromFramework (user.js:35:2) +(anonymous) (expr.js:0:0) + +Executing stepOut... +testStepFromFramework (user.js:36:0) +(anonymous) (expr.js:0:0) + +Executing resume...
diff --git a/src/v8/test/inspector/debugger/framework-stepping.js b/src/v8/test/inspector/debugger/framework-stepping.js new file mode 100644 index 0000000..f91c06b --- /dev/null +++ b/src/v8/test/inspector/debugger/framework-stepping.js
@@ -0,0 +1,113 @@ +// Copyright 2017 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. + +let {session, contextGroup, Protocol} = InspectorTest.start('Checks stepping with blackboxed frames on stack'); + +contextGroup.addScript( + ` +function frameworkCall(funcs) { + for (var f of funcs) f(); +} + +function frameworkBreakAndCall(funcs) { + inspector.breakProgram('', ''); + for (var f of funcs) f(); +} +//# sourceURL=framework.js`, + 8, 4); + +contextGroup.addScript( + ` +function userFoo() { + return 1; +} + +function userBoo() { + return 2; +} + +function testStepFromUser() { + frameworkCall([userFoo, userBoo]) +} + +function testStepFromFramework() { + frameworkBreakAndCall([userFoo, userBoo]); +} +//# sourceURL=user.js`, + 21, 4); + +session.setupScriptMap(); + +Protocol.Debugger.enable() + .then( + () => Protocol.Debugger.setBlackboxPatterns( + {patterns: ['framework\.js']})) + .then(() => InspectorTest.runTestSuite(testSuite)); + +var testSuite = [ + function testStepIntoFromUser(next) { + contextGroup.schedulePauseOnNextStatement('', ''); + test('testStepFromUser()', [ + 'print', // before testStepFromUser call + 'stepInto', 'stepInto', 'print', // userFoo + 'stepInto', 'stepInto', 'print', // userBoo + 'stepInto', 'stepInto', 'print' // testStepFromUser + ]).then(next); + }, + + function testStepOverFromUser(next) { + contextGroup.schedulePauseOnNextStatement('', ''); + test('testStepFromUser()', [ + 'print', // before testStepFromUser call + 'stepInto', 'stepInto', 'print', // userFoo + 'stepOver', 'stepOver', 'print', // userBoo + 'stepOver', 'stepOver', 'print' // testStepFromUser + ]).then(next); + }, + + function testStepOutFromUser(next) { + contextGroup.schedulePauseOnNextStatement('', ''); + test('testStepFromUser()', [ + 'print', // before testStepFromUser call + 'stepInto', 'stepInto', 'print', // userFoo + 'stepOut', 'print' // testStepFromUser + ]).then(next); + }, + + function testStepIntoFromFramework(next) { + test('testStepFromFramework()', [ + 'print', // frameworkBreakAndCall + 'stepInto', 'print', // userFoo + ]).then(next); + }, + + function testStepOverFromFramework(next) { + test('testStepFromFramework()', [ + 'print', // frameworkBreakAndCall + 'stepOver', 'print', // testStepFromFramework + ]).then(next); + }, + + function testStepOutFromFramework(next) { + test('testStepFromFramework()', [ + 'print', // frameworkBreakAndCall + 'stepOut', 'print', // testStepFromFramework + ]).then(next); + } +]; + +function test(entryExpression, actions) { + Protocol.Debugger.onPaused(message => { + var action = actions.shift() || 'resume'; + if (action === 'print') { + session.logCallFrames(message.params.callFrames); + InspectorTest.log(''); + action = actions.shift() || 'resume'; + } + if (action) InspectorTest.log(`Executing ${action}...`); + Protocol.Debugger[action](); + }); + return Protocol.Runtime.evaluate( + {expression: entryExpression + '//# sourceURL=expr.js'}); +}
diff --git a/src/v8/test/inspector/debugger/get-possible-breakpoints-array-literal-expected.txt b/src/v8/test/inspector/debugger/get-possible-breakpoints-array-literal-expected.txt new file mode 100644 index 0000000..c5d8c24 --- /dev/null +++ b/src/v8/test/inspector/debugger/get-possible-breakpoints-array-literal-expected.txt
@@ -0,0 +1,30 @@ +Tests possible breakpoints in array literal +{ + id : <messageId> + result : { + locations : [ + [0] : { + columnNumber : 0 + lineNumber : 0 + scriptId : <scriptId> + } + [1] : { + columnNumber : 6 + lineNumber : 0 + scriptId : <scriptId> + } + [2] : { + columnNumber : 7 + lineNumber : 0 + scriptId : <scriptId> + type : return + } + [3] : { + columnNumber : 8 + lineNumber : 0 + scriptId : <scriptId> + type : return + } + ] + } +}
diff --git a/src/v8/test/inspector/debugger/get-possible-breakpoints-array-literal.js b/src/v8/test/inspector/debugger/get-possible-breakpoints-array-literal.js new file mode 100644 index 0000000..a5aeeff --- /dev/null +++ b/src/v8/test/inspector/debugger/get-possible-breakpoints-array-literal.js
@@ -0,0 +1,14 @@ +// 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. + +let {session, contextGroup, Protocol} = InspectorTest.start('Tests possible breakpoints in array literal'); + +Protocol.Debugger.enable(); + +Protocol.Debugger.onceScriptParsed().then(message => message.params.scriptId) + .then((scriptId) => Protocol.Debugger.getPossibleBreakpoints({ start: { lineNumber: 0, columnNumber: 0, scriptId: scriptId }})) + .then(InspectorTest.logMessage) + .then(InspectorTest.completeTest); + +contextGroup.addScript("() => []");
diff --git a/src/v8/test/inspector/debugger/get-possible-breakpoints-expected.txt b/src/v8/test/inspector/debugger/get-possible-breakpoints-expected.txt new file mode 100644 index 0000000..972a757 --- /dev/null +++ b/src/v8/test/inspector/debugger/get-possible-breakpoints-expected.txt
@@ -0,0 +1,271 @@ +Test for Debugger.getPossibleBreakpoints + +Running test: getPossibleBreakpointsInRange +Test start.scriptId != end.scriptId. +{ + error : { + code : -32000 + message : Locations should contain the same scriptId + } + id : <messageId> +} +Test not existing scriptId. +{ + error : { + code : -32000 + message : Script not found + } + id : <messageId> +} +Test end < start. +function foo(){ return Promise.resolve(); } +function boo(){ return Promise.resolve().then(() => 42); } + + +Test empty range in first line. +function foo(){ return Promise.resolve(); } +function boo(){ return Promise.resolve().then(() => 42); } + + +Test one character range in first line. +function foo(){ #return Promise.resolve(); } +function boo(){ return Promise.resolve().then(() => 42); } + + +Test empty range in not first line. +function foo(){ return Promise.resolve(); } +function boo(){ return Promise.resolve().then(() => 42); } + + +Test one character range in not first line. +function foo(){ return Promise.resolve(); } +function boo(){ #return Promise.resolve().then(() => 42); } + + +Test end is undefined +function foo(){ #return Promise.#resolve();# } +function boo(){ #return Promise.#resolve().#then(() => #42#);# } +# + +Test end.lineNumber > scripts.lineCount() +function foo(){ #return Promise.#resolve();# } +function boo(){ #return Promise.#resolve().#then(() => #42#);# } +# + +Test one string +function foo(){ #return Promise.#resolve();# } +function boo(){ return Promise.resolve().then(() => 42); } + + +Test end.columnNumber > end.line.length(), should be the same as previous. +function foo(){ #return Promise.#resolve();# } +function boo(){ return Promise.resolve().then(() => 42); } + + + +Running test: getPossibleBreakpointsInArrow +function foo() { #return Promise.#resolve().#then(() => #239#).#then(() => #42#).#then(() => #() => #42#)# #} + +Running test: arrowFunctionFirstLine +function foo1() { #Promise.#resolve().#then(() => #42#) #} +function foo2() { Promise.resolve().then(() => 42) } +paused in foo1 +function foo1() { ^Promise.resolve().then(() => 42) } +function foo2() { Promise.resolve().then(() => 42) } +paused in foo1 +function foo1() { Promise.^resolve().then(() => 42) } +function foo2() { Promise.resolve().then(() => 42) } +paused in foo1 +function foo1() { Promise.resolve().^then(() => 42) } +function foo2() { Promise.resolve().then(() => 42) } +paused in foo1 +function foo1() { Promise.resolve().then(() => 42) ^} +function foo2() { Promise.resolve().then(() => 42) } +paused in Promise.resolve.then +function foo1() { Promise.resolve().then(() => ^42) } +function foo2() { Promise.resolve().then(() => 42) } +paused in Promise.resolve.then +function foo1() { Promise.resolve().then(() => 42^) } +function foo2() { Promise.resolve().then(() => 42) } + +Running test: arrowFunctionOnPause +#debugger; function foo3() { #Promise.#resolve().#then(() => #42#) #} +function foo4() { #Promise.#resolve().#then(() => #42#) #}; +#foo3(); +#foo4()#; +paused in +debugger; function foo3() { Promise.resolve().then(() => 42) } +function foo4() { Promise.resolve().then(() => 42) }; +^foo3(); +foo4(); +paused in foo3 +debugger; function foo3() { ^Promise.resolve().then(() => 42) } +function foo4() { Promise.resolve().then(() => 42) }; +foo3(); +foo4(); +paused in foo3 +debugger; function foo3() { Promise.^resolve().then(() => 42) } +function foo4() { Promise.resolve().then(() => 42) }; +foo3(); +foo4(); +paused in foo3 +debugger; function foo3() { Promise.resolve().^then(() => 42) } +function foo4() { Promise.resolve().then(() => 42) }; +foo3(); +foo4(); +paused in foo3 +debugger; function foo3() { Promise.resolve().then(() => 42) ^} +function foo4() { Promise.resolve().then(() => 42) }; +foo3(); +foo4(); +paused in +debugger; function foo3() { Promise.resolve().then(() => 42) } +function foo4() { Promise.resolve().then(() => 42) }; +foo3(); +^foo4(); +paused in foo4 +debugger; function foo3() { Promise.resolve().then(() => 42) } +function foo4() { ^Promise.resolve().then(() => 42) }; +foo3(); +foo4(); +paused in foo4 +debugger; function foo3() { Promise.resolve().then(() => 42) } +function foo4() { Promise.^resolve().then(() => 42) }; +foo3(); +foo4(); +paused in foo4 +debugger; function foo3() { Promise.resolve().then(() => 42) } +function foo4() { Promise.resolve().^then(() => 42) }; +foo3(); +foo4(); +paused in foo4 +debugger; function foo3() { Promise.resolve().then(() => 42) } +function foo4() { Promise.resolve().then(() => 42) ^}; +foo3(); +foo4(); +paused in +debugger; function foo3() { Promise.resolve().then(() => 42) } +function foo4() { Promise.resolve().then(() => 42) }; +foo3(); +foo4()^; +paused in Promise.resolve.then +debugger; function foo3() { Promise.resolve().then(() => ^42) } +function foo4() { Promise.resolve().then(() => 42) }; +foo3(); +foo4(); +paused in Promise.resolve.then +debugger; function foo3() { Promise.resolve().then(() => 42^) } +function foo4() { Promise.resolve().then(() => 42) }; +foo3(); +foo4(); +paused in Promise.resolve.then +debugger; function foo3() { Promise.resolve().then(() => 42) } +function foo4() { Promise.resolve().then(() => ^42) }; +foo3(); +foo4(); +paused in Promise.resolve.then +debugger; function foo3() { Promise.resolve().then(() => 42) } +function foo4() { Promise.resolve().then(() => 42^) }; +foo3(); +foo4(); + +Running test: getPossibleBreakpointsInRangeWithOffset +Test empty range in first line. +function foo(){ return Promise.resolve(); } +function boo(){ return Promise.resolve().then(() => 42); } + + +Test one character range in first line. +function foo(){ #return Promise.resolve(); } +function boo(){ return Promise.resolve().then(() => 42); } + + +Test empty range in not first line. +function foo(){ return Promise.resolve(); } +function boo(){ return Promise.resolve().then(() => 42); } + + +Test one character range in not first line. +function foo(){ return Promise.resolve(); } +function boo(){ #return Promise.resolve().then(() => 42); } + + +Test end is undefined +function foo(){ #return Promise.#resolve();# } +function boo(){ #return Promise.#resolve().#then(() => #42#);# } +# + +Test end.lineNumber > scripts.lineCount() +function foo(){ #return Promise.#resolve();# } +function boo(){ #return Promise.#resolve().#then(() => #42#);# } +# + +Test one string +function foo(){ #return Promise.#resolve();# } +function boo(){ return Promise.resolve().then(() => 42); } + + +Test end.columnNumber > end.line.length(), should be the same as previous. +function foo(){ #return Promise.#resolve();# } +function boo(){ return Promise.resolve().then(() => 42); } + + + +Running test: withOffset +function foo5() { #Promise.#resolve().#then(() => #42#) #} +function foo6() { #Promise.#resolve().#then(() => #42#) #} +paused in foo5 +function foo5() { ^Promise.resolve().then(() => 42) } +function foo6() { Promise.resolve().then(() => 42) } +paused in foo5 +function foo5() { Promise.^resolve().then(() => 42) } +function foo6() { Promise.resolve().then(() => 42) } +paused in foo5 +function foo5() { Promise.resolve().^then(() => 42) } +function foo6() { Promise.resolve().then(() => 42) } +paused in foo5 +function foo5() { Promise.resolve().then(() => 42) ^} +function foo6() { Promise.resolve().then(() => 42) } +paused in foo6 +function foo5() { Promise.resolve().then(() => 42) } +function foo6() { ^Promise.resolve().then(() => 42) } +paused in foo6 +function foo5() { Promise.resolve().then(() => 42) } +function foo6() { Promise.^resolve().then(() => 42) } +paused in foo6 +function foo5() { Promise.resolve().then(() => 42) } +function foo6() { Promise.resolve().^then(() => 42) } +paused in foo6 +function foo5() { Promise.resolve().then(() => 42) } +function foo6() { Promise.resolve().then(() => 42) ^} +paused in Promise.resolve.then +function foo5() { Promise.resolve().then(() => ^42) } +function foo6() { Promise.resolve().then(() => 42) } +paused in Promise.resolve.then +function foo5() { Promise.resolve().then(() => 42^) } +function foo6() { Promise.resolve().then(() => 42) } +paused in Promise.resolve.then +function foo5() { Promise.resolve().then(() => 42) } +function foo6() { Promise.resolve().then(() => ^42) } +paused in Promise.resolve.then +function foo5() { Promise.resolve().then(() => 42) } +function foo6() { Promise.resolve().then(() => 42^) } + +Running test: arrowFunctionReturn +#() => #239# + +function foo() { function boo() { #return 239# } #}# + +#() => { #239 #}# + +function foo() { #239 #}# + +#() => #23#9# +#() => { #return 239# #} + +Running test: argumentsAsCalls +function foo(){#} +function boo(){#} +function main(f1,f2){#} +#main(#foo(), #boo());# +
diff --git a/src/v8/test/inspector/debugger/get-possible-breakpoints-lazy-error-expected.txt b/src/v8/test/inspector/debugger/get-possible-breakpoints-lazy-error-expected.txt new file mode 100644 index 0000000..9c65ba2 --- /dev/null +++ b/src/v8/test/inspector/debugger/get-possible-breakpoints-lazy-error-expected.txt
@@ -0,0 +1,26 @@ +getPossibleBreakpoints should not crash during lazy compilation (crbug.com/715334) +{ + method : Debugger.scriptParsed + params : { + endColumn : 21 + endLine : 2 + executionContextId : <executionContextId> + hasSourceURL : true + hash : FA2A959297747012766FE9C5006E7F522D88FA72 + isLiveEdit : false + isModule : false + length : 52 + scriptId : <scriptId> + sourceMapURL : + startColumn : 0 + startLine : 0 + url : test.js + } +} +{ + id : <messageId> + result : { + locations : [ + ] + } +}
diff --git a/src/v8/test/inspector/debugger/get-possible-breakpoints-lazy-error.js b/src/v8/test/inspector/debugger/get-possible-breakpoints-lazy-error.js new file mode 100644 index 0000000..d1326e9 --- /dev/null +++ b/src/v8/test/inspector/debugger/get-possible-breakpoints-lazy-error.js
@@ -0,0 +1,28 @@ +// Copyright 2017 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. + +let {session, contextGroup, Protocol} = InspectorTest.start('getPossibleBreakpoints should not crash during lazy compilation (crbug.com/715334)'); + +contextGroup.addScript(` +function test() { continue; } +//# sourceURL=test.js`); + +(async function test() { + Protocol.Debugger.enable(); + let script = await Protocol.Debugger.onceScriptParsed(); + InspectorTest.logMessage(script); + let scriptId = script.params.scriptId; + Protocol.Debugger.onScriptFailedToParse(msg => { + InspectorTest.logMessage(msg); + if (msg.params.scriptId !== script.params.scriptId) { + InspectorTest.log('Failed script to parse event has different scriptId'); + } else { + InspectorTest.log('One script is reported twice'); + } + }); + let response = await Protocol.Debugger.getPossibleBreakpoints({ + start: {scriptId, lineNumber: 0, columnNumber: 0}}); + InspectorTest.logMessage(response); + InspectorTest.completeTest(); +})();
diff --git a/src/v8/test/inspector/debugger/get-possible-breakpoints-master-expected.txt b/src/v8/test/inspector/debugger/get-possible-breakpoints-master-expected.txt new file mode 100644 index 0000000..7ea0920 --- /dev/null +++ b/src/v8/test/inspector/debugger/get-possible-breakpoints-master-expected.txt
@@ -0,0 +1,271 @@ +Checks Debugger.getPossibleBreakpoints +// Copyright 2017 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. + +function testEval() { + |C|eval('// comment only'); + |C|eval('// comment only\n'); +|R|} + +// function without return +function procedure() { + var a = |_|1; + var b = |_|2; +|R|} + +function testProcedure() { + |C|procedure(); +|R|} + +function returnTrue() { + |_|return true;|R| +} + +function testIf() { + var a; + if (true) |_|a = true; + |_|if (!a) { + |_|a = true; + } else { + |_|a = false; + } + |_|if (|C|returnTrue()) { + |_|a = false; + } else { + |_|a = true; + } +|R|} + +function emptyFunction() {|R|} + +function testEmptyFunction() { + |C|emptyFunction(); +|R|} + +function twoArguments(a1, a2) { +|R|} + +function testCallArguments() { + |C|twoArguments(|C|emptyFunction(), |C|emptyFunction()); +|R|} + +function testNested() { + function nested1() { + function nested2() { + function nested3() { + |R|} + |C|nested3(); + |_|return;|R| + } + return |C|nested2();|R| + } + |C|nested1(); +|R|} + +function return42() { + |_|return 42;|R| +} + +function returnCall() { + |_|return |C|return42();|R| +} + +function testCallAtReturn() { + |_|return |C|returnCall();|R| +} + +function returnObject() { + |_|return ({ foo: () => |_|42|R| });|R| +} + +function testWith() { + |_|with (|C|returnObject()) { + |C|foo(); + } + |_|with({}) { + |_|return;|R| + } +} + +function testForLoop() { + for (var i = |_|0; i |_|< 1; ++|_|i) {} + for (var i = |_|0; i |_|< 1; ++|_|i) i; + for (var i = |_|0; i |_|< 0; ++|_|i) {} +|R|} + +function testForOfLoop() { + for (var |_|k of |_|[]) {} + for (var |_|k of |_|[1]) |_|k; + var a = |_|[]; + for (var |_|k of |_|a) {} +|R|} + +function testForInLoop() { + var o = |_|{}; + for (var |_|k in |_|o) {} + for (var |_|k in |_|o) |_|k; + for (var |_|k in |_|{ a:1 }) {} + for (var |_|k in |_|{ a:1 }) |_|k; +|R|} + +function testSimpleExpressions() { + 1 + 2 + 3; + var a = |_|1; + |_|++a; + |_|a--; +|R|} + +Object.defineProperty(this, 'getterFoo', { + get: () => |_|return42|R| +}); + +function testGetter() { + |C|getterFoo(); +|R|} + +var obj = { + foo: () => (|_|{ + boo: () => |_|return42|R| + })|R| +}; + +function testChainedCalls() { + |_|obj.|C|foo().|C|boo()|C|(); +|R|} + +function testChainedWithNative() { + |_|Array.|C|from([1]).|C|concat([2]).|C|map(v => v |_|* 2|R|); +|R|} + +function testPromiseThen() { + |_|return Promise.|C|resolve().|C|then(v => v |_|* 2|R|).|C|then(v => v |_|* 2|R|);|R| +} + +function testSwitch() { + for (var i = |_|0; i |_|< 3; ++|_|i) { + |_|switch(i) { + case 0: |_|continue; + case 1: |C|return42(); |_|break; + default: |_|return;|R| + } + } +|R|} + +function* idMaker() { + |_|yield 1; + |_|yield 2; + |_|yield 3; +|R|} + +function testGenerator() { + var gen = |C|idMaker(); + |C|return42(); + gen.|C|next().value; + |D|debugger; + gen.|C|next().value; + |C|return42(); + gen.|C|next().value; + |C|return42(); + gen.|C|next().value; +|R|} + +function throwException() { + |_|throw |C|new Error(); +} + +function testCaughtException() { + try { + |C|throwException() + } catch (e) { + |_|return;|R| + } +|R|} + +function testClasses() { + class Cat { + constructor(name) { + |_|this.name = name; + |R|} + + speak() { + |R|} + } + class Lion extends Cat { + constructor(name) { + |C|super(name); + |R|} + + speak() { + |_|super.|C|speak(); + |R|} + } + |C|new Lion().|C|speak(); +|R|} + +async function asyncFoo() { + |_|await Promise.|C|resolve().|C|then(v => v |_|* 2|R|); + |C|return42(); + |_|await |C|asyncBoo(); +|R|} + +async function asyncBoo() { + |_|await Promise.|C|resolve(); +|R|} + +async function testAsyncAwait() { + |_|await |C|asyncFoo(); + |_|await |C|awaitBoo(); +|R|} + +// TODO(kozyatinskiy): fix this. +async function testPromiseAsyncWithCode() { + var nextTest; + var testPromise = |C|new Promise(resolve => nextTest |_|= resolve|R|); + async function main() { + async function foo() { + var resolveNested; + var p = |C|new Promise(resolve => resolveNested |_|= resolve|R|); + |C|setTimeout(resolveNested, 0); + |_|await p; + |R|} + |C|setTimeout(returnCall, 0); + await |C|foo(); + await |C|foo(); + |C|nextTest(); + |R|} + |C|main(); + |_|return testPromise; +|R|} + +function returnFunction() { + |_|return returnObject;|R| +} + +async function testPromiseComplex() { + var nextTest; + var testPromise = |C|new Promise(resolve => nextTest |_|= resolve|R|); + async function main() { + async function foo() { + |_|await Promise.|C|resolve(); + |_|return 42; + |R|} + var x = |_|1; + var y = |_|2; + |C|returnFunction(|C|emptyFunction(), x++, --y, x => 2 |_|* x|R|, |C|returnCall())|C|().a = await |C|foo((a => 2 |_|*a|R|)|C|(5)); + |C|nextTest(); + |R|} + |C|main(); + |_|return testPromise; +|R|} + +function twiceDefined() { + return a + b; +} + +function twiceDefined() { + |_|return a + b;|R| +} + + +
diff --git a/src/v8/test/inspector/debugger/get-possible-breakpoints-master.js b/src/v8/test/inspector/debugger/get-possible-breakpoints-master.js new file mode 100644 index 0000000..33a3d63 --- /dev/null +++ b/src/v8/test/inspector/debugger/get-possible-breakpoints-master.js
@@ -0,0 +1,15 @@ +// Copyright 2017 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. + +let {session, contextGroup, Protocol} = InspectorTest.start('Checks Debugger.getPossibleBreakpoints'); + +var source = utils.read('test/inspector/debugger/resources/break-locations.js'); +contextGroup.addScript(source); +session.setupScriptMap(); + +Protocol.Debugger.onceScriptParsed() + .then(message => Protocol.Debugger.getPossibleBreakpoints({ start: { lineNumber: 0, columnNumber : 0, scriptId: message.params.scriptId }})) + .then(message => session.logBreakLocations(message.result.locations)) + .then(InspectorTest.completeTest); +Protocol.Debugger.enable();
diff --git a/src/v8/test/inspector/debugger/get-possible-breakpoints-restrict-to-function-expected.txt b/src/v8/test/inspector/debugger/get-possible-breakpoints-restrict-to-function-expected.txt new file mode 100644 index 0000000..0225fc3 --- /dev/null +++ b/src/v8/test/inspector/debugger/get-possible-breakpoints-restrict-to-function-expected.txt
@@ -0,0 +1,177 @@ +Checks Debugger.getPossibleBreakpoints with ignoreNestedFunctions + +Running test: testWholeFunction + +function test() { + |_|Array.|C|from([1,2]).|C|map(() => |_|1|R|).|C|filter(() => |_|true|R|); + function nested1() { + |_|Array.|C|from([1,2]).|C|map(() => |_|1|R|).|C|filter(() => |_|true|R|); + |R|} + function nested2() { + |_|Array.|C|from([1,2]).|C|map(() => |_|1|R|).|C|filter(() => |_|true|R|); + |R|} + |C|nested1(); + |C|nested2(); +|R|} + + +Running test: testWholeFunctionWithoutNested + +function test() { + |_|Array.|C|from([1,2]).|C|map(() => |_|1|R|).|C|filter(() => |_|true|R|); + function nested1() { + |_|Array.|C|from([1,2]).|C|map(() => |_|1|R|).|C|filter(() => |_|true|R|); + |R|} + function nested2() { + |_|Array.|C|from([1,2]).|C|map(() => |_|1|R|).|C|filter(() => |_|true|R|); + |R|} + |C|nested1(); + |C|nested2(); +|R|} + + +Running test: testPartOfFunctionWithoutNested + +function test() { + |_|Array.|C|from([1,2]).map(() => 1).filter(() => true); + function nested1() { + Array.from([1,2]).map(() => 1).filter(() => true); + } + function nested2() { + Array.from([1,2]).map(() => 1).filter(() => true); + } + nested1(); + nested2(); +} + + +Running test: testNestedFunction + +function test() { + Array.from([1,2]).map(() => 1).filter(() => true); + function nested1() { + |_|Array.|C|from([1,2]).|C|map(() => |_|1|R|).|C|filter(() => |_|true|R|); + |R|} + function nested2() { + |_|Array.|C|from([1,2]).|C|map(() => |_|1|R|).|C|filter(() => |_|true|R|); + |R|} + |C|nested1(); + |C|nested2(); +|R|} + +Run test() to check breakpoints.. + } + #nested1(); + nested2(); + + function nested1() { + #Array.from([1,2]).map(() => 1).filter(() => true); + } + + function nested1() { + Array.#from([1,2]).map(() => 1).filter(() => true); + } + + function nested1() { + Array.from([1,2]).#map(() => 1).filter(() => true); + } + + function nested1() { + Array.from([1,2]).map(() => #1).filter(() => true); + } + + function nested1() { + Array.from([1,2]).map(() => 1#).filter(() => true); + } + + function nested1() { + Array.from([1,2]).map(() => #1).filter(() => true); + } + + function nested1() { + Array.from([1,2]).map(() => 1#).filter(() => true); + } + + function nested1() { + Array.from([1,2]).map(() => 1).#filter(() => true); + } + + function nested1() { + Array.from([1,2]).map(() => 1).filter(() => #true); + } + + function nested1() { + Array.from([1,2]).map(() => 1).filter(() => true#); + } + + function nested1() { + Array.from([1,2]).map(() => 1).filter(() => #true); + } + + function nested1() { + Array.from([1,2]).map(() => 1).filter(() => true#); + } + + Array.from([1,2]).map(() => 1).filter(() => true); + #} + function nested2() { + + nested1(); + #nested2(); +} + + function nested2() { + #Array.from([1,2]).map(() => 1).filter(() => true); + } + + function nested2() { + Array.#from([1,2]).map(() => 1).filter(() => true); + } + + function nested2() { + Array.from([1,2]).#map(() => 1).filter(() => true); + } + + function nested2() { + Array.from([1,2]).map(() => #1).filter(() => true); + } + + function nested2() { + Array.from([1,2]).map(() => 1#).filter(() => true); + } + + function nested2() { + Array.from([1,2]).map(() => #1).filter(() => true); + } + + function nested2() { + Array.from([1,2]).map(() => 1#).filter(() => true); + } + + function nested2() { + Array.from([1,2]).map(() => 1).#filter(() => true); + } + + function nested2() { + Array.from([1,2]).map(() => 1).filter(() => #true); + } + + function nested2() { + Array.from([1,2]).map(() => 1).filter(() => true#); + } + + function nested2() { + Array.from([1,2]).map(() => 1).filter(() => #true); + } + + function nested2() { + Array.from([1,2]).map(() => 1).filter(() => true#); + } + + Array.from([1,2]).map(() => 1).filter(() => true); + #} + nested1(); + + nested2(); +#} +
diff --git a/src/v8/test/inspector/debugger/get-possible-breakpoints-restrict-to-function.js b/src/v8/test/inspector/debugger/get-possible-breakpoints-restrict-to-function.js new file mode 100644 index 0000000..2a20bca --- /dev/null +++ b/src/v8/test/inspector/debugger/get-possible-breakpoints-restrict-to-function.js
@@ -0,0 +1,85 @@ +// 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. + +let {session, contextGroup, Protocol} = InspectorTest.start('Checks Debugger.getPossibleBreakpoints with ignoreNestedFunctions'); + +var source = ` +function test() { + Array.from([1,2]).map(() => 1).filter(() => true); + function nested1() { + Array.from([1,2]).map(() => 1).filter(() => true); + } + function nested2() { + Array.from([1,2]).map(() => 1).filter(() => true); + } + nested1(); + nested2(); +} +//# sourceURL=test.js`; +contextGroup.addScript(source); + +var scriptId; +Protocol.Debugger.onceScriptParsed().then(message => { + if (message.params.url === 'test.js') + scriptId = message.params.scriptId; +}).then(() => InspectorTest.runTestSuite(tests)); + +session.setupScriptMap(); +Protocol.Debugger.onPaused(message => { + session.logSourceLocation(message.params.callFrames[0].location); + Protocol.Debugger.resume(); +}); + +Protocol.Debugger.enable(); +var tests = [ + function testWholeFunction(next) { + Protocol.Debugger.getPossibleBreakpoints({ start: location(1, 18), ignoreNestedFunctions: false }) + .then(message => session.logBreakLocations(message.result.locations)) + .then(next); + }, + + function testWholeFunctionWithoutNested(next) { + Protocol.Debugger.getPossibleBreakpoints({ start: location(1, 18), ignoreNestedFunctions: true }) + .then(message => session.logBreakLocations(message.result.locations)) + .then(next); + }, + + function testPartOfFunctionWithoutNested(next) { + Protocol.Debugger.getPossibleBreakpoints({ start: location(1, 18), end: location(2, 18), ignoreNestedFunctions: true }) + .then(message => session.logBreakLocations(message.result.locations)) + .then(next); + }, + + function testNestedFunction(next) { + Protocol.Debugger.getPossibleBreakpoints({ start: location(4, 0), ignoreNestedFunctions: true }) + .then(message => session.logBreakLocations(message.result.locations)) + .then(setAllBreakpoints) + .then(() => InspectorTest.log('Run test() to check breakpoints..')) + .then(() => Protocol.Runtime.evaluate({ expression: 'test()' })) + .then(next); + } +]; + +function location(lineNumber, columnNumber) { + return { lineNumber: lineNumber, columnNumber: columnNumber, scriptId: scriptId }; +} + +function setAllBreakpoints(locations) { + var promises = []; + for (var location of locations) + promises.push(Protocol.Debugger.setBreakpoint({ location: location }).then(checkBreakpoint)); + return Promise.all(promises); +} + +function checkBreakpoint(message) { + if (message.error) { + InspectorTest.log('FAIL: error in setBreakpoint'); + InspectorTest.logMessage(message); + return; + } + var id_data = message.result.breakpointId.split(':'); + if (parseInt(id_data[1]) !== message.result.actualLocation.lineNumber || parseInt(id_data[2]) !== message.result.actualLocation.columnNumber) { + InspectorTest.log('FAIL: possible breakpoint was resolved in another location'); + } +}
diff --git a/src/v8/test/inspector/debugger/get-possible-breakpoints.js b/src/v8/test/inspector/debugger/get-possible-breakpoints.js new file mode 100644 index 0000000..3232d59 --- /dev/null +++ b/src/v8/test/inspector/debugger/get-possible-breakpoints.js
@@ -0,0 +1,233 @@ +// 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. + +let {session, contextGroup, Protocol} = InspectorTest.start('Test for Debugger.getPossibleBreakpoints'); + +Protocol.Runtime.enable(); +Protocol.Debugger.enable(); + +InspectorTest.runTestSuite([ + + function getPossibleBreakpointsInRange(next) { + var source = 'function foo(){ return Promise.resolve(); }\nfunction boo(){ return Promise.resolve().then(() => 42); }\n\n'; + var scriptId; + compileScript(source) + .then(id => scriptId = id) + .then(() => InspectorTest.log('Test start.scriptId != end.scriptId.')) + .then(() => Protocol.Debugger.getPossibleBreakpoints({ start: { lineNumber: 0, columnNumber: 0, scriptId: scriptId }, end: { lineNumber: 0, columnNumber: 0, scriptId: scriptId + '0' }})) + .then(message => dumpAllLocations(message, source)) + .then(() => InspectorTest.log('Test not existing scriptId.')) + .then(() => Protocol.Debugger.getPossibleBreakpoints({ start: { lineNumber: 0, columnNumber: 0, scriptId: '-1' }})) + .then(message => dumpAllLocations(message, source)) + .then(() => InspectorTest.log('Test end < start.')) + .then(() => Protocol.Debugger.getPossibleBreakpoints({ start: { lineNumber: 1, columnNumber: 0, scriptId: scriptId }, end: { lineNumber: 0, columnNumber: 0, scriptId: scriptId }})) + .then(message => dumpAllLocations(message, source)) + .then(() => InspectorTest.log('Test empty range in first line.')) + .then(() => Protocol.Debugger.getPossibleBreakpoints({ start: { lineNumber: 0, columnNumber: 16, scriptId: scriptId }, end: { lineNumber: 0, columnNumber: 16, scriptId: scriptId }})) + .then(message => dumpAllLocations(message, source)) + .then(() => InspectorTest.log('Test one character range in first line.')) + .then(() => Protocol.Debugger.getPossibleBreakpoints({ start: { lineNumber: 0, columnNumber: 16, scriptId: scriptId }, end: { lineNumber: 0, columnNumber: 17, scriptId: scriptId }})) + .then(message => dumpAllLocations(message, source)) + .then(() => InspectorTest.log('Test empty range in not first line.')) + .then(() => Protocol.Debugger.getPossibleBreakpoints({ start: { lineNumber: 1, columnNumber: 16, scriptId: scriptId }, end: { lineNumber: 1, columnNumber: 16, scriptId: scriptId }})) + .then(message => dumpAllLocations(message, source)) + .then(() => InspectorTest.log('Test one character range in not first line.')) + .then(() => Protocol.Debugger.getPossibleBreakpoints({ start: { lineNumber: 1, columnNumber: 16, scriptId: scriptId }, end: { lineNumber: 1, columnNumber: 17, scriptId: scriptId }})) + .then(message => dumpAllLocations(message, source)) + .then(() => InspectorTest.log('Test end is undefined')) + .then(() => Protocol.Debugger.getPossibleBreakpoints({ start: { lineNumber: 0, columnNumber: 0, scriptId: scriptId }})) + .then(message => dumpAllLocations(message, source)) + .then(() => InspectorTest.log('Test end.lineNumber > scripts.lineCount()')) + .then(() => Protocol.Debugger.getPossibleBreakpoints({ start: { lineNumber: 0, columnNumber: 0, scriptId: scriptId }, end: { lineNumber: 5, columnNumber: 0, scriptId: scriptId }})) + .then(message => dumpAllLocations(message, source)) + .then(() => InspectorTest.log('Test one string')) + .then(() => Protocol.Debugger.getPossibleBreakpoints({ start: { lineNumber: 0, columnNumber: 0, scriptId: scriptId }, end: { lineNumber: 1, columnNumber: 0, scriptId: scriptId }})) + .then(message => dumpAllLocations(message, source)) + .then(() => InspectorTest.log('Test end.columnNumber > end.line.length(), should be the same as previous.')) + .then(() => Protocol.Debugger.getPossibleBreakpoints({ start: { lineNumber: 0, columnNumber: 0, scriptId: scriptId }, end: { lineNumber: 0, columnNumber: 256, scriptId: scriptId }})) + .then(message => dumpAllLocations(message, source)) + .then(next); + }, + + function getPossibleBreakpointsInArrow(next) { + var source = 'function foo() { return Promise.resolve().then(() => 239).then(() => 42).then(() => () => 42) }'; + var scriptId; + compileScript(source) + .then(id => scriptId = id) + .then(() => Protocol.Debugger.getPossibleBreakpoints({ start: { lineNumber: 0, columnNumber: 0, scriptId: scriptId }})) + .then(message => dumpAllLocations(message, source)) + .then(next); + }, + + function arrowFunctionFirstLine(next) { + Protocol.Debugger.onPaused(message => dumpBreakLocationInSourceAndResume(message, source)); + + var source = `function foo1() { Promise.resolve().then(() => 42) } +function foo2() { Promise.resolve().then(() => 42) }`; + waitForPossibleBreakpoints(source, { lineNumber: 0, columnNumber: 0 }, { lineNumber: 1, columnNumber: 0 }) + .then(message => dumpAllLocations(message, source)) + .then(setAllBreakpoints) + .then(() => Protocol.Runtime.evaluate({ expression: 'foo1(); foo2()'})) + .then(next); + }, + + function arrowFunctionOnPause(next) { + var source = `debugger; function foo3() { Promise.resolve().then(() => 42) } +function foo4() { Promise.resolve().then(() => 42) };\nfoo3();\nfoo4();`; + waitForPossibleBreakpointsOnPause(source, { lineNumber: 0, columnNumber: 0 }, undefined, next) + .then(message => dumpAllLocations(message, source)) + .then(setAllBreakpoints) + .then(() => Protocol.Debugger.onPaused(message => dumpBreakLocationInSourceAndResume(message, source))) + .then(() => Protocol.Debugger.resume()); + }, + + function getPossibleBreakpointsInRangeWithOffset(next) { + var source = 'function foo(){ return Promise.resolve(); }\nfunction boo(){ return Promise.resolve().then(() => 42); }\n\n'; + var scriptId; + compileScript(source, { name: 'with-offset.js', line_offset: 1, column_offset: 1 }) + .then(id => scriptId = id) + .then(() => InspectorTest.log('Test empty range in first line.')) + .then(() => Protocol.Debugger.getPossibleBreakpoints({ start: { lineNumber: 1, columnNumber: 17, scriptId: scriptId }, end: { lineNumber: 1, columnNumber: 17, scriptId: scriptId }})) + .then(message => dumpAllLocations(message, source, 1, 1)) + .then(() => InspectorTest.log('Test one character range in first line.')) + .then(() => Protocol.Debugger.getPossibleBreakpoints({ start: { lineNumber: 1, columnNumber: 17, scriptId: scriptId }, end: { lineNumber: 1, columnNumber: 18, scriptId: scriptId }})) + .then(message => dumpAllLocations(message, source, 1, 1)) + .then(() => InspectorTest.log('Test empty range in not first line.')) + .then(() => Protocol.Debugger.getPossibleBreakpoints({ start: { lineNumber: 2, columnNumber: 16, scriptId: scriptId }, end: { lineNumber: 2, columnNumber: 16, scriptId: scriptId }})) + .then(message => dumpAllLocations(message, source, 1, 1)) + .then(() => InspectorTest.log('Test one character range in not first line.')) + .then(() => Protocol.Debugger.getPossibleBreakpoints({ start: { lineNumber: 2, columnNumber: 16, scriptId: scriptId }, end: { lineNumber: 2, columnNumber: 17, scriptId: scriptId }})) + .then(message => dumpAllLocations(message, source, 1, 1)) + .then(() => InspectorTest.log('Test end is undefined')) + .then(() => Protocol.Debugger.getPossibleBreakpoints({ start: { lineNumber: 0, columnNumber: 0, scriptId: scriptId }})) + .then(message => dumpAllLocations(message, source, 1, 1)) + .then(() => InspectorTest.log('Test end.lineNumber > scripts.lineCount()')) + .then(() => Protocol.Debugger.getPossibleBreakpoints({ start: { lineNumber: 0, columnNumber: 0, scriptId: scriptId }, end: { lineNumber: 5, columnNumber: 0, scriptId: scriptId }})) + .then(message => dumpAllLocations(message, source, 1, 1)) + .then(() => InspectorTest.log('Test one string')) + .then(() => Protocol.Debugger.getPossibleBreakpoints({ start: { lineNumber: 1, columnNumber: 1, scriptId: scriptId }, end: { lineNumber: 2, columnNumber: 0, scriptId: scriptId }})) + .then(message => dumpAllLocations(message, source, 1, 1)) + .then(() => InspectorTest.log('Test end.columnNumber > end.line.length(), should be the same as previous.')) + .then(() => Protocol.Debugger.getPossibleBreakpoints({ start: { lineNumber: 1, columnNumber: 1, scriptId: scriptId }, end: { lineNumber: 1, columnNumber: 256, scriptId: scriptId }})) + .then(message => dumpAllLocations(message, source, 1, 1)) + .then(next); + }, + + function withOffset(next) { + Protocol.Debugger.onPaused(message => dumpBreakLocationInSourceAndResume(message, source, 3, 18)); + + var source = `function foo5() { Promise.resolve().then(() => 42) } +function foo6() { Promise.resolve().then(() => 42) }`; + waitForPossibleBreakpoints(source, { lineNumber: 0, columnNumber: 0 }, undefined, { name: 'with-offset.js', line_offset: 3, column_offset: 18 }) + .then(message => dumpAllLocations(message, source, 3, 18)) + .then(setAllBreakpoints) + .then(() => Protocol.Runtime.evaluate({ expression: 'foo5(); foo6()'})) + .then(next); + }, + + function arrowFunctionReturn(next) { + function checkSource(source, location) { + return waitForPossibleBreakpoints(source, location) + .then(message => dumpAllLocations(message, source)); + } + + checkSource('() => 239\n', { lineNumber: 0, columnNumber: 0 }) + .then(() => checkSource('function foo() { function boo() { return 239 } }\n', { lineNumber: 0, columnNumber: 0 })) + .then(() => checkSource('() => { 239 }\n', { lineNumber: 0, columnNumber: 0 })) + .then(() => checkSource('function foo() { 239 }\n', { lineNumber: 0, columnNumber: 0 })) + // TODO(kozyatinskiy): lineNumber for return position should be only 9, not 8. + .then(() => checkSource('() => 239', { lineNumber: 0, columnNumber: 0 })) + .then(() => checkSource('() => { return 239 }', { lineNumber: 0, columnNumber: 0 })) + .then(next); + }, + + function argumentsAsCalls(next) { + var source = 'function foo(){}\nfunction boo(){}\nfunction main(f1,f2){}\nmain(foo(), boo());\n'; + waitForPossibleBreakpoints(source, { lineNumber: 0, columnNumber: 0 }) + .then(message => dumpAllLocations(message, source)) + .then(next); + } +]); + +function compileScript(source, origin) { + var promise = Protocol.Debugger.onceScriptParsed().then(message => message.params.scriptId); + if (!origin) origin = { name: '', line_offset: 0, column_offset: 0 }; + contextGroup.addScript(source, origin.line_offset, origin.column_offset, origin.name); + return promise; +} + +function waitForPossibleBreakpoints(source, start, end, origin) { + return compileScript(source, origin) + .then(scriptId => { (start || {}).scriptId = scriptId; (end || {}).scriptId = scriptId }) + .then(() => Protocol.Debugger.getPossibleBreakpoints({ start: start, end: end })); +} + +function waitForPossibleBreakpointsOnPause(source, start, end, next) { + var promise = Protocol.Debugger.oncePaused() + .then(msg => { (start || {}).scriptId = msg.params.callFrames[0].location.scriptId; (end || {}).scriptId = msg.params.callFrames[0].location.scriptId }) + .then(() => Protocol.Debugger.getPossibleBreakpoints({ start: start, end: end })); + Protocol.Runtime.evaluate({ expression: source }).then(next); + return promise; +} + +function setAllBreakpoints(message) { + var promises = []; + for (var location of message.result.locations) + promises.push(Protocol.Debugger.setBreakpoint({ location: location }).then(checkBreakpoint)); + return Promise.all(promises); +} + +function checkBreakpoint(message) { + if (message.error) { + InspectorTest.log('FAIL: error in setBreakpoint'); + InspectorTest.logMessage(message); + return; + } + var id_data = message.result.breakpointId.split(':'); + if (parseInt(id_data[1]) !== message.result.actualLocation.lineNumber || parseInt(id_data[2]) !== message.result.actualLocation.columnNumber) { + InspectorTest.log('FAIL: possible breakpoint was resolved in another location'); + } +} + +function dumpAllLocations(message, source, lineOffset, columnOffset) { + if (message.error) { + InspectorTest.logMessage(message); + return; + } + + lineOffset = lineOffset || 0; + columnOffset = columnOffset || 0; + + var sourceLines = source.split('\n') + var lineOffsets = Array(sourceLines.length).fill(0); + for (var location of message.result.locations) { + var lineNumber = location.lineNumber - lineOffset; + var columnNumber = lineNumber !== 0 ? location.columnNumber : location.columnNumber - columnOffset; + var line = sourceLines[lineNumber] || ''; + var offset = lineOffsets[lineNumber]; + line = line.slice(0, columnNumber + offset) + '#' + line.slice(columnNumber + offset); + ++lineOffsets[lineNumber]; + sourceLines[lineNumber] = line; + } + InspectorTest.log(sourceLines.join('\n')); + return message; +} + +function dumpBreakLocationInSourceAndResume(message, source, lineOffset, columnOffset) { + lineOffset = lineOffset || 0; + columnOffset = columnOffset || 0; + + InspectorTest.log('paused in ' + message.params.callFrames[0].functionName); + var location = message.params.callFrames[0].location; + var sourceLines = source.split('\n') + + var lineNumber = location.lineNumber - lineOffset; + var columnNumber = lineNumber !== 0 ? location.columnNumber : location.columnNumber - columnOffset; + + var line = sourceLines[lineNumber]; + line = line.slice(0, columnNumber) + '^' + line.slice(columnNumber); + sourceLines[lineNumber] = line; + InspectorTest.log(sourceLines.join('\n')); + Protocol.Debugger.resume(); +}
diff --git a/src/v8/test/inspector/debugger/inspector-break-api-expected.txt b/src/v8/test/inspector/debugger/inspector-break-api-expected.txt new file mode 100644 index 0000000..1677b59 --- /dev/null +++ b/src/v8/test/inspector/debugger/inspector-break-api-expected.txt
@@ -0,0 +1,38 @@ +Checks breakProgram,(schedule|cancel)PauseOnNextStatement test API + +Running test: testBreakProgram +Stack: +callBreakProgram (:9:12) +(anonymous) (:0:0) +Other data: +{ + method : Debugger.paused + params : { + data : { + a : 42 + } + hitBreakpoints : [ + ] + reason : reason + } +} + + +Running test: testSchedulePauseOnNextStatement +Stack: +(anonymous) (expr1.js:0:0) +Other data: +{ + method : Debugger.paused + params : { + data : { + a : 42 + } + hitBreakpoints : [ + ] + reason : reason + } +} + + +Running test: testCancelPauseOnNextStatement
diff --git a/src/v8/test/inspector/debugger/inspector-break-api.js b/src/v8/test/inspector/debugger/inspector-break-api.js new file mode 100644 index 0000000..dc39924 --- /dev/null +++ b/src/v8/test/inspector/debugger/inspector-break-api.js
@@ -0,0 +1,50 @@ +// Copyright 2017 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. + +let {session, contextGroup, Protocol} = InspectorTest.start("Checks breakProgram,(schedule|cancel)PauseOnNextStatement test API"); + +contextGroup.addScript(` +function callBreakProgram() { + inspector.breakProgram('reason', JSON.stringify({a: 42})); +} + +function foo() { + return 42; +}`, 7, 26); + +session.setupScriptMap(); +Protocol.Debugger.onPaused(message => { + InspectorTest.log('Stack:'); + session.logCallFrames(message.params.callFrames); + delete message.params.callFrames; + InspectorTest.log('Other data:'); + InspectorTest.logMessage(message); + InspectorTest.log(''); + Protocol.Debugger.resume(); +}); + +Protocol.Debugger.enable(); + +InspectorTest.runTestSuite([ + function testBreakProgram(next) { + Protocol.Runtime.evaluate({ expression: 'callBreakProgram()'}) + .then(next); + }, + + function testSchedulePauseOnNextStatement(next) { + contextGroup.schedulePauseOnNextStatement('reason', JSON.stringify({a: 42})); + Protocol.Runtime.evaluate({ expression: 'foo()//# sourceURL=expr1.js'}) + .then(() => Protocol.Runtime.evaluate({ + expression: 'foo()//# sourceURL=expr2.js'})) + .then(() => contextGroup.cancelPauseOnNextStatement()) + .then(next); + }, + + function testCancelPauseOnNextStatement(next) { + contextGroup.schedulePauseOnNextStatement('reason', JSON.stringify({a: 42})); + contextGroup.cancelPauseOnNextStatement(); + Protocol.Runtime.evaluate({ expression: 'foo()'}) + .then(next); + } +]);
diff --git a/src/v8/test/inspector/debugger/max-async-call-chain-depth-expected.txt b/src/v8/test/inspector/debugger/max-async-call-chain-depth-expected.txt new file mode 100644 index 0000000..0c421da --- /dev/null +++ b/src/v8/test/inspector/debugger/max-async-call-chain-depth-expected.txt
@@ -0,0 +1,91 @@ +Checks that we trim async call chains correctly. +set async chain depth to 8 + +Running test: testDebuggerPaused +Run expression 'debugger;' with async chain len: 4 +actual async chain len: 1 +Run expression 'debugger;' with async chain len: 8 +actual async chain len: 1 +Run expression 'debugger;' with async chain len: 9 +actual async chain len: 1 +Run expression 'debugger;' with async chain len: 32 +actual async chain len: 1 + +Running test: testConsoleTrace +Run expression 'console.trace(42);' with async chain len: 4 +actual async chain len: 1 +Run expression 'console.trace(42);' with async chain len: 8 +actual async chain len: 1 +Run expression 'console.trace(42);' with async chain len: 9 +actual async chain len: 1 +Run expression 'console.trace(42);' with async chain len: 32 +actual async chain len: 1 + +Running test: testDebuggerPausedSetTimeout +Run expression 'debugger;' with async chain len: 4 +actual async chain len: 4 +Run expression 'debugger;' with async chain len: 8 +actual async chain len: 8 +Run expression 'debugger;' with async chain len: 9 +actual async chain len: 8 +Run expression 'debugger;' with async chain len: 32 +actual async chain len: 8 + +Running test: testConsoleTraceSetTimeout +Run expression 'console.trace(42);' with async chain len: 4 +actual async chain len: 4 +Run expression 'console.trace(42);' with async chain len: 8 +actual async chain len: 8 +Run expression 'console.trace(42);' with async chain len: 9 +actual async chain len: 8 +Run expression 'console.trace(42);' with async chain len: 32 +actual async chain len: 8 + +Running test: testConsoleTraceWithEmptySync +{ + callFrames : [ + [0] : { + columnNumber : 66 + functionName : Promise.then + lineNumber : 0 + scriptId : <scriptId> + url : + } + ] + parent : { + callFrames : [ + [0] : { + columnNumber : 47 + functionName : + lineNumber : 0 + scriptId : <scriptId> + url : + } + ] + description : Promise.resolve + } +} + +Running test: testDebuggerPausedThenableJob +Run expression 'debugger;' with async chain len: 4 +actual async chain len: 1 +Run expression 'debugger;' with async chain len: 8 +actual async chain len: 1 +Run expression 'debugger;' with async chain len: 9 +actual async chain len: 1 +Run expression 'debugger;' with async chain len: 32 +actual async chain len: 1 + +Running test: testConsoleTraceThenableJob +Run expression 'console.trace(42);' with async chain len: 4 +actual async chain len: 1 +Run expression 'console.trace(42);' with async chain len: 8 +actual async chain len: 1 +Run expression 'console.trace(42);' with async chain len: 9 +actual async chain len: 1 +Run expression 'console.trace(42);' with async chain len: 32 +actual async chain len: 1 + +Running test: twoConsoleAssert +actual async chain len: 1 +actual async chain len: 2
diff --git a/src/v8/test/inspector/debugger/max-async-call-chain-depth.js b/src/v8/test/inspector/debugger/max-async-call-chain-depth.js new file mode 100644 index 0000000..ae98f55 --- /dev/null +++ b/src/v8/test/inspector/debugger/max-async-call-chain-depth.js
@@ -0,0 +1,162 @@ +// Copyright 2017 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. + +// TODO(kozyatinskiy): fix or remove it later. +let {session, contextGroup, Protocol} = InspectorTest.start('Checks that we trim async call chains correctly.'); + +Protocol.Debugger.enable(); +InspectorTest.log('set async chain depth to 8'); +Protocol.Debugger.setAsyncCallStackDepth({maxDepth: 8}); +InspectorTest.runAsyncTestSuite([ + async function testDebuggerPaused() { + runWithAsyncChain(4, 'debugger;'); + dumpAsyncChainLength(await Protocol.Debugger.oncePaused()); + await Protocol.Debugger.resume(); + + runWithAsyncChain(8, 'debugger;'); + dumpAsyncChainLength(await Protocol.Debugger.oncePaused()); + await Protocol.Debugger.resume(); + + runWithAsyncChain(9, 'debugger;'); + dumpAsyncChainLength(await Protocol.Debugger.oncePaused()); + await Protocol.Debugger.resume(); + + runWithAsyncChain(32, 'debugger;'); + dumpAsyncChainLength(await Protocol.Debugger.oncePaused()); + await Protocol.Debugger.resume(); + }, + + async function testConsoleTrace() { + Protocol.Runtime.enable(); + runWithAsyncChain(4, 'console.trace(42);'); + dumpAsyncChainLength(await Protocol.Runtime.onceConsoleAPICalled()); + + runWithAsyncChain(8, 'console.trace(42);'); + dumpAsyncChainLength(await Protocol.Runtime.onceConsoleAPICalled()); + + runWithAsyncChain(9, 'console.trace(42);'); + dumpAsyncChainLength(await Protocol.Runtime.onceConsoleAPICalled()); + + runWithAsyncChain(32, 'console.trace(42);'); + dumpAsyncChainLength(await Protocol.Runtime.onceConsoleAPICalled()); + }, + + async function testDebuggerPausedSetTimeout() { + runWithAsyncChainSetTimeout(4, 'debugger;'); + dumpAsyncChainLength(await Protocol.Debugger.oncePaused()); + await Protocol.Debugger.resume(); + + runWithAsyncChainSetTimeout(8, 'debugger;'); + dumpAsyncChainLength(await Protocol.Debugger.oncePaused()); + await Protocol.Debugger.resume(); + + runWithAsyncChainSetTimeout(9, 'debugger;'); + dumpAsyncChainLength(await Protocol.Debugger.oncePaused()); + await Protocol.Debugger.resume(); + + runWithAsyncChainSetTimeout(32, 'debugger;'); + dumpAsyncChainLength(await Protocol.Debugger.oncePaused()); + await Protocol.Debugger.resume(); + }, + + async function testConsoleTraceSetTimeout() { + runWithAsyncChainSetTimeout(4, 'console.trace(42);'); + dumpAsyncChainLength(await Protocol.Runtime.onceConsoleAPICalled()); + + runWithAsyncChainSetTimeout(8, 'console.trace(42);'); + dumpAsyncChainLength(await Protocol.Runtime.onceConsoleAPICalled()); + + runWithAsyncChainSetTimeout(9, 'console.trace(42);'); + dumpAsyncChainLength(await Protocol.Runtime.onceConsoleAPICalled()); + + runWithAsyncChainSetTimeout(32, 'console.trace(42);'); + dumpAsyncChainLength(await Protocol.Runtime.onceConsoleAPICalled()); + }, + + async function testConsoleTraceWithEmptySync() { + Protocol.Runtime.evaluate({ + expression: 'new Promise(resolve => setTimeout(resolve, 0)).then(() => console.trace(42))' + }); + InspectorTest.logMessage((await Protocol.Runtime.onceConsoleAPICalled()).params.stackTrace); + }, + + async function testDebuggerPausedThenableJob() { + runWithThenableJob(4, 'debugger;'); + dumpAsyncChainLength(await Protocol.Debugger.oncePaused()); + await Protocol.Debugger.resume(); + + runWithThenableJob(8, 'debugger;'); + dumpAsyncChainLength(await Protocol.Debugger.oncePaused()); + await Protocol.Debugger.resume(); + + runWithThenableJob(9, 'debugger;'); + dumpAsyncChainLength(await Protocol.Debugger.oncePaused()); + await Protocol.Debugger.resume(); + + runWithThenableJob(32, 'debugger;'); + dumpAsyncChainLength(await Protocol.Debugger.oncePaused()); + await Protocol.Debugger.resume(); + }, + + async function testConsoleTraceThenableJob() { + runWithThenableJob(4, 'console.trace(42);'); + dumpAsyncChainLength(await Protocol.Runtime.onceConsoleAPICalled()); + + runWithThenableJob(8, 'console.trace(42);'); + dumpAsyncChainLength(await Protocol.Runtime.onceConsoleAPICalled()); + + runWithThenableJob(9, 'console.trace(42);'); + dumpAsyncChainLength(await Protocol.Runtime.onceConsoleAPICalled()); + + runWithThenableJob(32, 'console.trace(42);'); + dumpAsyncChainLength(await Protocol.Runtime.onceConsoleAPICalled()); + }, + + async function twoConsoleAssert() { + Protocol.Runtime.evaluate({ + expression: 'setTimeout(' + + 'setTimeout.bind(null, ' + + 'setTimeout.bind(null, () => { console.assert(); setTimeout(console.assert, 0) }, 0), 0), 0)' + }); + dumpAsyncChainLength(await Protocol.Runtime.onceConsoleAPICalled()); + dumpAsyncChainLength(await Protocol.Runtime.onceConsoleAPICalled()); + } +]); + +function runWithAsyncChain(len, source) { + InspectorTest.log(`Run expression '${source}' with async chain len: ${len}`); + let then = '.then(() => 1)'; + let pause = `.then(() => { ${source} })`; + Protocol.Runtime.evaluate({ + expression: `Promise.resolve()${then.repeat(len - 1)}${pause}` + }); +} + +function runWithAsyncChainSetTimeout(len, source) { + InspectorTest.log(`Run expression '${source}' with async chain len: ${len}`); + let setTimeout = 'setTimeout(() => {'; + let suffix = '}, 0)'; + Protocol.Runtime.evaluate({ + expression: `${setTimeout.repeat(len)}${source}${suffix.repeat(len)}` + }); +} + +function runWithThenableJob(len, source) { + InspectorTest.log(`Run expression '${source}' with async chain len: ${len}`); + let then = '.then(Promise.resolve.bind(Promise, 0))'; + let pause = `.then(() => { ${source} })`; + Protocol.Runtime.evaluate({ + expression: `Promise.resolve()${then.repeat(len - 1)}${pause}` + }); +} + +function dumpAsyncChainLength(message) { + let stackTrace = message.params.asyncStackTrace || message.params.stackTrace.parent; + let asyncChainCount = 0; + while (stackTrace) { + ++asyncChainCount; + stackTrace = stackTrace.parent; + } + InspectorTest.log(`actual async chain len: ${asyncChainCount}`); +}
diff --git a/src/v8/test/inspector/debugger/not-hold-promises-expected.txt b/src/v8/test/inspector/debugger/not-hold-promises-expected.txt new file mode 100644 index 0000000..93929b1 --- /dev/null +++ b/src/v8/test/inspector/debugger/not-hold-promises-expected.txt
@@ -0,0 +1,2 @@ +Tests that we don't hold promises. +SUCCESS
diff --git a/src/v8/test/inspector/debugger/not-hold-promises.js b/src/v8/test/inspector/debugger/not-hold-promises.js new file mode 100644 index 0000000..815b618 --- /dev/null +++ b/src/v8/test/inspector/debugger/not-hold-promises.js
@@ -0,0 +1,36 @@ +// Copyright 2017 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. + +let {session, contextGroup, Protocol} = + InspectorTest.start('Tests that we don\'t hold promises.'); + +(async function test() { + Protocol.Runtime.enable(); + Protocol.Debugger.enable(); + Protocol.Debugger.setAsyncCallStackDepth({maxDepth: 128}); + Protocol.HeapProfiler.enable(); + // Force inspector internal scripts compilation. + await Protocol.Runtime.evaluate({expression: ''}); + let snapshot = ''; + Protocol.HeapProfiler.onAddHeapSnapshotChunk(msg => snapshot += msg.params.chunk); + await Protocol.HeapProfiler.collectGarbage(); + await Protocol.HeapProfiler.takeHeapSnapshot(); + let initial_node_count = JSON.parse(snapshot).snapshot.node_count; + + await Protocol.Runtime.evaluate({ + expression: `for (let i = 0; i < ${initial_node_count / 4}; ++i) Promise.resolve()`}); + snapshot = ''; + Protocol.HeapProfiler.onAddHeapSnapshotChunk(msg => snapshot += msg.params.chunk); + await Protocol.HeapProfiler.collectGarbage(); + await Protocol.HeapProfiler.takeHeapSnapshot(); + let without_storing_node_count = JSON.parse(snapshot).snapshot.node_count; + let diff_without_storing = (without_storing_node_count - initial_node_count); + + if (diff_without_storing < initial_node_count / 4) { + InspectorTest.log('SUCCESS'); + } else { + InspectorTest.log('FAILED: looks like all promises were not collected.'); + } + InspectorTest.completeTest(); +})();
diff --git a/src/v8/test/inspector/debugger/object-preview-internal-properties-expected.txt b/src/v8/test/inspector/debugger/object-preview-internal-properties-expected.txt new file mode 100644 index 0000000..394c1be --- /dev/null +++ b/src/v8/test/inspector/debugger/object-preview-internal-properties-expected.txt
@@ -0,0 +1,248 @@ +Check internal properties reported in object preview. + +Running test: boxedObjects +expression: new Number(239) +{ + name : [[PrimitiveValue]] + type : number + value : 239 +} + +expression: new Boolean(false) +{ + name : [[PrimitiveValue]] + type : boolean + value : false +} + +expression: new String("abc") +{ + name : [[PrimitiveValue]] + type : string + value : abc +} + +expression: Object(Symbol(42)) +{ + name : [[PrimitiveValue]] + type : symbol + valuePreview : { + description : Symbol + overflow : false + properties : [ + ] + type : object + } +} + + +Running test: promise +expression: Promise.resolve(42) +{ + name : [[PromiseStatus]] + type : string + value : resolved +} +{ + name : [[PromiseValue]] + type : number + value : 42 +} + +expression: new Promise(() => undefined) +{ + name : [[PromiseStatus]] + type : string + value : pending +} +{ + name : [[PromiseValue]] + type : undefined + value : undefined +} + + +Running test: generatorObject +expression: (function* foo() { yield 1 })() +{ + name : [[GeneratorStatus]] + type : string + value : suspended +} + + +Running test: entriesInMapAndSet +expression: new Map([[1,2]]) +[[Entries]]: +[ + [0] : { + key : { + description : 1 + overflow : false + properties : [ + ] + type : number + } + value : { + description : 2 + overflow : false + properties : [ + ] + type : number + } + } +] + +expression: new Set([1]) +[[Entries]]: +[ + [0] : { + value : { + description : 1 + overflow : false + properties : [ + ] + type : number + } + } +] + +expression: new WeakMap([[{}, 42]]) +[[Entries]]: +[ + [0] : { + key : { + description : Object + overflow : false + properties : [ + ] + type : object + } + value : { + description : 42 + overflow : false + properties : [ + ] + type : number + } + } +] + +expression: new WeakSet([{}]) +[[Entries]]: +[ + [0] : { + value : { + description : Object + overflow : false + properties : [ + ] + type : object + } + } +] + + +Running test: iteratorObject +expression: (new Map([[1,2]])).entries() +[[Entries]]: +[ + [0] : { + key : { + description : 1 + overflow : false + properties : [ + ] + type : number + } + value : { + description : 2 + overflow : false + properties : [ + ] + type : number + } + } +] + +expression: (new Set([[1,2]])).entries() +[[Entries]]: +[ + [0] : { + value : { + description : Array(2) + overflow : false + properties : [ + [0] : { + name : 0 + type : number + value : 1 + } + [1] : { + name : 1 + type : number + value : 2 + } + ] + subtype : array + type : object + } + } +] + + +Running test: noPreviewForFunctionObject +(function foo(){}) +{ + id : <messageId> + result : { + result : { + className : Function + description : function foo(){} + objectId : <objectId> + type : function + } + } +} + +Running test: otherObjects +expression: [1,2,3] +{ + name : 0 + type : number + value : 1 +} +{ + name : 1 + type : number + value : 2 +} +{ + name : 2 + type : number + value : 3 +} + +expression: /123/ +{ + name : lastIndex + type : number + value : 0 +} + +expression: ({}) + + +Running test: overridenArrayGetter +expression: Promise.resolve(42) +{ + name : [[PromiseStatus]] + type : string + value : resolved +} +{ + name : [[PromiseValue]] + type : number + value : 42 +} +
diff --git a/src/v8/test/inspector/debugger/object-preview-internal-properties.js b/src/v8/test/inspector/debugger/object-preview-internal-properties.js new file mode 100644 index 0000000..6c655d1 --- /dev/null +++ b/src/v8/test/inspector/debugger/object-preview-internal-properties.js
@@ -0,0 +1,107 @@ +// 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. + +let {session, contextGroup, Protocol} = InspectorTest.start("Check internal properties reported in object preview."); + +Protocol.Debugger.enable(); +Protocol.Runtime.enable(); +Protocol.Runtime.onConsoleAPICalled(dumpInternalPropertiesAndEntries); + +contextGroup.setupInjectedScriptEnvironment(); + +InspectorTest.runTestSuite([ + function boxedObjects(next) + { + checkExpression("new Number(239)") + .then(() => checkExpression("new Boolean(false)")) + .then(() => checkExpression("new String(\"abc\")")) + .then(() => checkExpression("Object(Symbol(42))")) + .then(next); + }, + + function promise(next) + { + checkExpression("Promise.resolve(42)") + .then(() => checkExpression("new Promise(() => undefined)")) + .then(next); + }, + + function generatorObject(next) + { + checkExpression("(function* foo() { yield 1 })()") + .then(next); + }, + + function entriesInMapAndSet(next) + { + checkExpression("new Map([[1,2]])") + .then(() => checkExpression("new Set([1])")) + .then(() => checkExpression("new WeakMap([[{}, 42]])")) + .then(() => checkExpression("new WeakSet([{}])")) + .then(next); + }, + + function iteratorObject(next) + { + checkExpression("(new Map([[1,2]])).entries()") + .then(() => checkExpression("(new Set([[1,2]])).entries()")) + .then(next); + }, + + function noPreviewForFunctionObject(next) + { + var expression = "(function foo(){})"; + InspectorTest.log(expression); + Protocol.Runtime.evaluate({ expression: expression, generatePreview: true}) + .then(message => InspectorTest.logMessage(message)) + .then(next); + }, + + function otherObjects(next) + { + checkExpression("[1,2,3]") + .then(() => checkExpression("/123/")) + .then(() => checkExpression("({})")) + .then(next); + }, + + function overridenArrayGetter(next) + { + Protocol.Runtime.evaluate({ expression: "Array.prototype.__defineGetter__(\"0\",() => { throw new Error() }) "}) + .then(() => checkExpression("Promise.resolve(42)")) + .then(next); + } +]); + +function checkExpression(expression) +{ + InspectorTest.log(`expression: ${expression}`); + // console.table has higher limits for internal properties amount in preview. + return Protocol.Runtime.evaluate({ expression: `console.table(${expression})`, generatePreview: true }); +} + +function dumpInternalPropertiesAndEntries(message) +{ + var properties; + var entries; + try { + var preview = message.params.args[0].preview; + properties = preview.properties; + entries = preview.entries; + } catch (e) { + InspectorTest.logMessage(message); + return; + } + if (!properties) { + InspectorTest.logMessage(message); + return; + } + for (var property of properties) + InspectorTest.logMessage(property); + if (entries) { + InspectorTest.log("[[Entries]]:"); + InspectorTest.logMessage(entries); + } + InspectorTest.log(""); +}
diff --git a/src/v8/test/inspector/debugger/pause-at-negative-offset-expected.txt b/src/v8/test/inspector/debugger/pause-at-negative-offset-expected.txt new file mode 100644 index 0000000..23c5490 --- /dev/null +++ b/src/v8/test/inspector/debugger/pause-at-negative-offset-expected.txt
@@ -0,0 +1,2 @@ +Tests that we dont crash on pause at negative offset +(anonymous) (test.js:-3:-3)
diff --git a/src/v8/test/inspector/debugger/pause-at-negative-offset.js b/src/v8/test/inspector/debugger/pause-at-negative-offset.js new file mode 100644 index 0000000..4d0928b --- /dev/null +++ b/src/v8/test/inspector/debugger/pause-at-negative-offset.js
@@ -0,0 +1,15 @@ +// Copyright 2017 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. + +let {session, contextGroup, Protocol} = + InspectorTest.start('Tests that we dont crash on pause at negative offset'); + +(async function test() { + session.setupScriptMap(); + await Protocol.Debugger.enable(); + contextGroup.addScript(`debugger;//# sourceURL=test.js`, -3, -3); + let {params:{callFrames}} = await Protocol.Debugger.oncePaused(); + session.logCallFrames(callFrames); + InspectorTest.completeTest(); +})();
diff --git a/src/v8/test/inspector/debugger/pause-expected.txt b/src/v8/test/inspector/debugger/pause-expected.txt new file mode 100644 index 0000000..2489191 --- /dev/null +++ b/src/v8/test/inspector/debugger/pause-expected.txt
@@ -0,0 +1,73 @@ +Checks Debugger.pause + +Running test: testPause +paused at: +#var a = 42; + + +Running test: testSkipFrameworks +paused at: +#var a = 239; + + +Running test: testSkipOtherContext1 +paused at: +var a = #1; + + +Running test: testSkipOtherContext2 +paused at: +#var a = 239; + +paused at: +var a = #239; + + +Running test: testWithNativeBreakpoint +paused at: +#var a = 42; + +paused at: +#var a = 42; + +paused at: +#var a = 42; + + +Running test: testResumeAnotherGroup +paused at: +#var a = 42; + +{ + error : { + code : -32000 + message : Can only perform operation while paused. + } + id : <messageId> +} +{ + error : { + code : -32000 + message : Can only perform operation while paused. + } + id : <messageId> +} +{ + error : { + code : -32000 + message : Can only perform operation while paused. + } + id : <messageId> +} +{ + error : { + code : -32000 + message : Can only perform operation while paused. + } + id : <messageId> +} + +Running test: testDisableBreaksShouldCancelPause +paused at: +#debugger +
diff --git a/src/v8/test/inspector/debugger/pause-on-oom-expected.txt b/src/v8/test/inspector/debugger/pause-on-oom-expected.txt new file mode 100644 index 0000000..4ca988d --- /dev/null +++ b/src/v8/test/inspector/debugger/pause-on-oom-expected.txt
@@ -0,0 +1,2 @@ +Check pause on OOM +reason: OOM
diff --git a/src/v8/test/inspector/debugger/pause-on-oom.js b/src/v8/test/inspector/debugger/pause-on-oom.js new file mode 100644 index 0000000..fe5d61b --- /dev/null +++ b/src/v8/test/inspector/debugger/pause-on-oom.js
@@ -0,0 +1,28 @@ +// Copyright 2017 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: --max-old-space-size=8 + +let {session, contextGroup, Protocol} = InspectorTest.start('Check pause on OOM'); + +contextGroup.addScript(` +var arr = []; +var stop = false; +function generateGarbage() { + while(!stop) { + arr.push(42); + } +} +//# sourceURL=test.js`, 10, 26); + +Protocol.Debugger.onPaused((message) => { + InspectorTest.log(`reason: ${message.params.reason}`); + Protocol.Debugger.evaluateOnCallFrame({ + callFrameId: message.params.callFrames[0].callFrameId, + expression: 'arr = []; stop = true;' + }).then(() => Protocol.Debugger.resume()); +}); +Protocol.Debugger.enable(); +Protocol.Runtime.evaluate({ expression: 'generateGarbage()' }) + .then(InspectorTest.completeTest);
diff --git a/src/v8/test/inspector/debugger/pause.js b/src/v8/test/inspector/debugger/pause.js new file mode 100644 index 0000000..fdef666 --- /dev/null +++ b/src/v8/test/inspector/debugger/pause.js
@@ -0,0 +1,118 @@ +// Copyright 2017 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. + +InspectorTest.log('Checks Debugger.pause'); +let contextGroup1 = new InspectorTest.ContextGroup(); +let session1 = contextGroup1.connect(); +let Protocol1 = session1.Protocol; + +session1.setupScriptMap(); +Protocol1.Debugger.enable(); +InspectorTest.runAsyncTestSuite([ + async function testPause() { + Protocol1.Debugger.pause(); + Protocol1.Runtime.evaluate({expression: 'var a = 42;'}); + await waitPauseAndDumpLocation(session1); + await Protocol1.Debugger.resume(); + }, + + async function testSkipFrameworks() { + Protocol1.Debugger.setBlackboxPatterns({patterns: ['framework\.js']}); + Protocol1.Debugger.pause(); + Protocol1.Runtime.evaluate({expression: 'var a = 42; //# sourceURL=framework.js'}); + Protocol1.Runtime.evaluate({expression: 'var a = 239;'}); + await waitPauseAndDumpLocation(session1); + await Protocol1.Debugger.resume(); + }, + + async function testSkipOtherContext1() { + let contextGroup2 = new InspectorTest.ContextGroup(); + let session2 = contextGroup2.connect(); + let Protocol2 = session2.Protocol; + Protocol2.Debugger.enable({}); + Protocol1.Debugger.pause(); + Protocol1.Runtime.evaluate({expression: 'var a = 42; //# sourceURL=framework.js'}); + Protocol2.Runtime.evaluate({expression: 'var a = 239;'}); + Protocol1.Runtime.evaluate({expression: 'var a = 1;'}); + await waitPauseAndDumpLocation(session1); + await Protocol1.Debugger.resume(); + await Protocol2.Debugger.disable({}); + }, + + async function testSkipOtherContext2() { + let contextGroup2 = new InspectorTest.ContextGroup(); + let session2 = contextGroup2.connect(); + let Protocol2 = session2.Protocol; + session2.setupScriptMap(); + Protocol2.Debugger.enable({}); + Protocol2.Debugger.pause({}); + Protocol1.Runtime.evaluate({expression: 'var a = 42; //# sourceURL=framework.js'}); + Protocol2.Runtime.evaluate({expression: 'var a = 239;'}); + Protocol1.Runtime.evaluate({expression: 'var a = 1;'}); + await waitPauseAndDumpLocation(session2); + // should not resume pause from different context group id. + Protocol1.Debugger.resume(); + Protocol2.Debugger.stepOver({}); + await waitPauseAndDumpLocation(session2); + await Protocol2.Debugger.resume({}); + await Protocol2.Debugger.disable({}); + }, + + async function testWithNativeBreakpoint() { + contextGroup1.schedulePauseOnNextStatement('', ''); + await Protocol1.Debugger.pause(); + contextGroup1.cancelPauseOnNextStatement(); + Protocol1.Runtime.evaluate({expression: 'var a = 42;'}); + await waitPauseAndDumpLocation(session1); + await Protocol1.Debugger.resume(); + + await Protocol1.Debugger.pause(); + contextGroup1.schedulePauseOnNextStatement('', ''); + contextGroup1.cancelPauseOnNextStatement(); + Protocol1.Runtime.evaluate({expression: 'var a = 42;'}); + await waitPauseAndDumpLocation(session1); + await Protocol1.Debugger.resume(); + + contextGroup1.schedulePauseOnNextStatement('', ''); + contextGroup1.cancelPauseOnNextStatement(); + await Protocol1.Debugger.pause(); + Protocol1.Runtime.evaluate({expression: 'var a = 42;'}); + await waitPauseAndDumpLocation(session1); + await Protocol1.Debugger.resume(); + }, + + async function testResumeAnotherGroup() { + let contextGroup2 = new InspectorTest.ContextGroup(); + let session2 = contextGroup2.connect(); + session2.setupScriptMap(); + let Protocol2 = session2.Protocol; + Protocol2.Debugger.enable(); + Protocol1.Debugger.pause(); + Protocol1.Runtime.evaluate({expression: 'var a = 42;'}); + await waitPauseAndDumpLocation(session1); + InspectorTest.logMessage(await Protocol2.Debugger.resume()); + InspectorTest.logMessage(await Protocol2.Debugger.stepOver()); + InspectorTest.logMessage(await Protocol2.Debugger.stepInto()); + InspectorTest.logMessage(await Protocol2.Debugger.stepOut()); + await Protocol1.Debugger.resume(); + await Protocol2.Debugger.disable(); + }, + + async function testDisableBreaksShouldCancelPause() { + await Protocol1.Debugger.pause(); + await Protocol1.Debugger.setBreakpointsActive({active: false}); + Protocol1.Runtime.evaluate({expression: 'var a = 42;'}) + .then(() => Protocol1.Debugger.setBreakpointsActive({active: true})) + .then(() => Protocol1.Runtime.evaluate({expression: 'debugger'})); + await waitPauseAndDumpLocation(session1); + await Protocol1.Debugger.resume(); + } +]); + +async function waitPauseAndDumpLocation(session) { + var message = await session.Protocol.Debugger.oncePaused(); + InspectorTest.log('paused at:'); + await session.logSourceLocation(message.params.callFrames[0].location); + return message; +}
diff --git a/src/v8/test/inspector/debugger/promise-chain-when-limit-hit-expected.txt b/src/v8/test/inspector/debugger/promise-chain-when-limit-hit-expected.txt new file mode 100644 index 0000000..57357ab --- /dev/null +++ b/src/v8/test/inspector/debugger/promise-chain-when-limit-hit-expected.txt
@@ -0,0 +1,235 @@ +Tests how async promise chains behave when reaching the limit of stacks +Checks correctness of promise chains when limit hit +inspector.setMaxAsyncTaskStacks(3) +Run expression 'console.trace()' with async chain len: 3 +{ + method : Runtime.consoleAPICalled + params : { + args : [ + [0] : { + type : string + value : console.trace + } + ] + executionContextId : <executionContextId> + stackTrace : { + callFrames : [ + [0] : { + columnNumber : 67 + functionName : Promise.resolve.then.then.then + lineNumber : 0 + scriptId : <scriptId> + url : + } + ] + parent : { + callFrames : [ + [0] : { + columnNumber : 46 + functionName : + lineNumber : 0 + scriptId : <scriptId> + url : + } + ] + } + } + timestamp : <timestamp> + type : trace + } +} +inspector.setMaxAsyncTaskStacks(4) +Run expression 'console.trace()' with async chain len: 3 +{ + method : Runtime.consoleAPICalled + params : { + args : [ + [0] : { + type : string + value : console.trace + } + ] + executionContextId : <executionContextId> + stackTrace : { + callFrames : [ + [0] : { + columnNumber : 67 + functionName : Promise.resolve.then.then.then + lineNumber : 0 + scriptId : <scriptId> + url : + } + ] + parent : { + callFrames : [ + [0] : { + columnNumber : 46 + functionName : + lineNumber : 0 + scriptId : <scriptId> + url : + } + ] + description : Promise.resolve + } + } + timestamp : <timestamp> + type : trace + } +} +inspector.setMaxAsyncTaskStacks(5) +Run expression 'console.trace()' with async chain len: 3 +{ + method : Runtime.consoleAPICalled + params : { + args : [ + [0] : { + type : string + value : console.trace + } + ] + executionContextId : <executionContextId> + stackTrace : { + callFrames : [ + [0] : { + columnNumber : 67 + functionName : Promise.resolve.then.then.then + lineNumber : 0 + scriptId : <scriptId> + url : + } + ] + parent : { + callFrames : [ + [0] : { + columnNumber : 46 + functionName : + lineNumber : 0 + scriptId : <scriptId> + url : + } + ] + description : Promise.resolve + } + } + timestamp : <timestamp> + type : trace + } +} +inspector.setMaxAsyncTaskStacks(6) +Run expression 'console.trace()' with async chain len: 3 +{ + method : Runtime.consoleAPICalled + params : { + args : [ + [0] : { + type : string + value : console.trace + } + ] + executionContextId : <executionContextId> + stackTrace : { + callFrames : [ + [0] : { + columnNumber : 67 + functionName : Promise.resolve.then.then.then + lineNumber : 0 + scriptId : <scriptId> + url : + } + ] + parent : { + callFrames : [ + [0] : { + columnNumber : 46 + functionName : + lineNumber : 0 + scriptId : <scriptId> + url : + } + ] + description : Promise.resolve + } + } + timestamp : <timestamp> + type : trace + } +} +inspector.setMaxAsyncTaskStacks(7) +Run expression 'console.trace()' with async chain len: 3 +{ + method : Runtime.consoleAPICalled + params : { + args : [ + [0] : { + type : string + value : console.trace + } + ] + executionContextId : <executionContextId> + stackTrace : { + callFrames : [ + [0] : { + columnNumber : 67 + functionName : Promise.resolve.then.then.then + lineNumber : 0 + scriptId : <scriptId> + url : + } + ] + parent : { + callFrames : [ + [0] : { + columnNumber : 46 + functionName : + lineNumber : 0 + scriptId : <scriptId> + url : + } + ] + description : Promise.resolve + } + } + timestamp : <timestamp> + type : trace + } +} +inspector.setMaxAsyncTaskStacks(8) +Run expression 'console.trace()' with async chain len: 3 +{ + method : Runtime.consoleAPICalled + params : { + args : [ + [0] : { + type : string + value : console.trace + } + ] + executionContextId : <executionContextId> + stackTrace : { + callFrames : [ + [0] : { + columnNumber : 67 + functionName : Promise.resolve.then.then.then + lineNumber : 0 + scriptId : <scriptId> + url : + } + ] + parent : { + callFrames : [ + [0] : { + columnNumber : 46 + functionName : + lineNumber : 0 + scriptId : <scriptId> + url : + } + ] + description : Promise.resolve + } + } + timestamp : <timestamp> + type : trace + } +}
diff --git a/src/v8/test/inspector/debugger/promise-chain-when-limit-hit.js b/src/v8/test/inspector/debugger/promise-chain-when-limit-hit.js new file mode 100644 index 0000000..072af73 --- /dev/null +++ b/src/v8/test/inspector/debugger/promise-chain-when-limit-hit.js
@@ -0,0 +1,54 @@ +// Copyright 2017 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. + +// TODO(kozyatinskiy): fix or remove it later. +let {session, contextGroup, Protocol} = InspectorTest.start('Tests how async promise chains behave when reaching the limit of stacks'); + +(async function test(){ + InspectorTest.log('Checks correctness of promise chains when limit hit'); + await Protocol.Runtime.enable(); + await Protocol.Debugger.enable(); + Protocol.Debugger.setAsyncCallStackDepth({maxDepth: 128}); + + await setMaxAsyncTaskStacks(3); + runWithAsyncChainPromise(3, 'console.trace()'); + InspectorTest.logMessage(await Protocol.Runtime.onceConsoleAPICalled()); + + await setMaxAsyncTaskStacks(4); + runWithAsyncChainPromise(3, 'console.trace()'); + InspectorTest.logMessage(await Protocol.Runtime.onceConsoleAPICalled()); + + await setMaxAsyncTaskStacks(5); + runWithAsyncChainPromise(3, 'console.trace()'); + InspectorTest.logMessage(await Protocol.Runtime.onceConsoleAPICalled()); + + await setMaxAsyncTaskStacks(6); + runWithAsyncChainPromise(3, 'console.trace()'); + InspectorTest.logMessage(await Protocol.Runtime.onceConsoleAPICalled()); + + await setMaxAsyncTaskStacks(7); + runWithAsyncChainPromise(3, 'console.trace()'); + InspectorTest.logMessage(await Protocol.Runtime.onceConsoleAPICalled()); + + await setMaxAsyncTaskStacks(8); + runWithAsyncChainPromise(3, 'console.trace()'); + InspectorTest.logMessage(await Protocol.Runtime.onceConsoleAPICalled()); + + InspectorTest.completeTest(); +})(); + +function runWithAsyncChainPromise(len, source) { + InspectorTest.log(`Run expression '${source}' with async chain len: ${len}`); + let then = '.then(() => 1)'; + let pause = `.then(() => { ${source} })`; + Protocol.Runtime.evaluate({ + expression: `Promise.resolve()${then.repeat(len - 1)}${pause}` + }); +} + +async function setMaxAsyncTaskStacks(max) { + let expression = `inspector.setMaxAsyncTaskStacks(${max})`; + InspectorTest.log(expression); + await Protocol.Runtime.evaluate({expression}); +}
diff --git a/src/v8/test/inspector/debugger/protocol-string-to-double-locale-expected.txt b/src/v8/test/inspector/debugger/protocol-string-to-double-locale-expected.txt new file mode 100644 index 0000000..52919c1 --- /dev/null +++ b/src/v8/test/inspector/debugger/protocol-string-to-double-locale-expected.txt
@@ -0,0 +1,8 @@ +Tests that double numbers are parsed and serialized correctly on different locales +This test verifies that we correctly parse doubles with non-US locale +{ + a : 0.5 +} +{ + a : 1 +}
diff --git a/src/v8/test/inspector/debugger/protocol-string-to-double-locale.js b/src/v8/test/inspector/debugger/protocol-string-to-double-locale.js new file mode 100644 index 0000000..89b6d82 --- /dev/null +++ b/src/v8/test/inspector/debugger/protocol-string-to-double-locale.js
@@ -0,0 +1,24 @@ +// Copyright 2017 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. + +let {session, contextGroup, Protocol} = InspectorTest.start('Tests that double numbers are parsed and serialized correctly on different locales'); + +(async function() { + InspectorTest.log('This test verifies that we correctly parse doubles with non-US locale'); + utils.setlocale("fr_CA.UTF-8"); + Protocol.Debugger.enable(); + Protocol.Runtime.evaluate({ + expression: 'inspector.breakProgram(\'\', JSON.stringify({a: 0.5}))'}); + let message = await Protocol.Debugger.oncePaused(); + InspectorTest.logObject(message.params.data || {}); + Protocol.Debugger.resume(); + + Protocol.Runtime.evaluate({ + expression: 'inspector.breakProgram(\'\', JSON.stringify({a: 1}))'}); + message = await Protocol.Debugger.oncePaused(); + InspectorTest.logObject(message.params.data || {}); + Protocol.Debugger.resume(); + + InspectorTest.completeTest(); +})();
diff --git a/src/v8/test/inspector/debugger/resources/break-locations.js b/src/v8/test/inspector/debugger/resources/break-locations.js new file mode 100644 index 0000000..c16ae67 --- /dev/null +++ b/src/v8/test/inspector/debugger/resources/break-locations.js
@@ -0,0 +1,269 @@ +// Copyright 2017 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. + +function testEval() { + eval('// comment only'); + eval('// comment only\n'); +} + +// function without return +function procedure() { + var a = 1; + var b = 2; +} + +function testProcedure() { + procedure(); +} + +function returnTrue() { + return true; +} + +function testIf() { + var a; + if (true) a = true; + if (!a) { + a = true; + } else { + a = false; + } + if (returnTrue()) { + a = false; + } else { + a = true; + } +} + +function emptyFunction() {} + +function testEmptyFunction() { + emptyFunction(); +} + +function twoArguments(a1, a2) { +} + +function testCallArguments() { + twoArguments(emptyFunction(), emptyFunction()); +} + +function testNested() { + function nested1() { + function nested2() { + function nested3() { + } + nested3(); + return; + } + return nested2(); + } + nested1(); +} + +function return42() { + return 42; +} + +function returnCall() { + return return42(); +} + +function testCallAtReturn() { + return returnCall(); +} + +function returnObject() { + return ({ foo: () => 42 }); +} + +function testWith() { + with (returnObject()) { + foo(); + } + with({}) { + return; + } +} + +function testForLoop() { + for (var i = 0; i < 1; ++i) {} + for (var i = 0; i < 1; ++i) i; + for (var i = 0; i < 0; ++i) {} +} + +function testForOfLoop() { + for (var k of []) {} + for (var k of [1]) k; + var a = []; + for (var k of a) {} +} + +function testForInLoop() { + var o = {}; + for (var k in o) {} + for (var k in o) k; + for (var k in { a:1 }) {} + for (var k in { a:1 }) k; +} + +function testSimpleExpressions() { + 1 + 2 + 3; + var a = 1; + ++a; + a--; +} + +Object.defineProperty(this, 'getterFoo', { + get: () => return42 +}); + +function testGetter() { + getterFoo(); +} + +var obj = { + foo: () => ({ + boo: () => return42 + }) +}; + +function testChainedCalls() { + obj.foo().boo()(); +} + +function testChainedWithNative() { + Array.from([1]).concat([2]).map(v => v * 2); +} + +function testPromiseThen() { + return Promise.resolve().then(v => v * 2).then(v => v * 2); +} + +function testSwitch() { + for (var i = 0; i < 3; ++i) { + switch(i) { + case 0: continue; + case 1: return42(); break; + default: return; + } + } +} + +function* idMaker() { + yield 1; + yield 2; + yield 3; +} + +function testGenerator() { + var gen = idMaker(); + return42(); + gen.next().value; + debugger; + gen.next().value; + return42(); + gen.next().value; + return42(); + gen.next().value; +} + +function throwException() { + throw new Error(); +} + +function testCaughtException() { + try { + throwException() + } catch (e) { + return; + } +} + +function testClasses() { + class Cat { + constructor(name) { + this.name = name; + } + + speak() { + } + } + class Lion extends Cat { + constructor(name) { + super(name); + } + + speak() { + super.speak(); + } + } + new Lion().speak(); +} + +async function asyncFoo() { + await Promise.resolve().then(v => v * 2); + return42(); + await asyncBoo(); +} + +async function asyncBoo() { + await Promise.resolve(); +} + +async function testAsyncAwait() { + await asyncFoo(); + await awaitBoo(); +} + +// TODO(kozyatinskiy): fix this. +async function testPromiseAsyncWithCode() { + var nextTest; + var testPromise = new Promise(resolve => nextTest = resolve); + async function main() { + async function foo() { + var resolveNested; + var p = new Promise(resolve => resolveNested = resolve); + setTimeout(resolveNested, 0); + await p; + } + setTimeout(returnCall, 0); + await foo(); + await foo(); + nextTest(); + } + main(); + return testPromise; +} + +function returnFunction() { + return returnObject; +} + +async function testPromiseComplex() { + var nextTest; + var testPromise = new Promise(resolve => nextTest = resolve); + async function main() { + async function foo() { + await Promise.resolve(); + return 42; + } + var x = 1; + var y = 2; + returnFunction(emptyFunction(), x++, --y, x => 2 * x, returnCall())().a = await foo((a => 2 *a)(5)); + nextTest(); + } + main(); + return testPromise; +} + +function twiceDefined() { + return a + b; +} + +function twiceDefined() { + return a + b; +} + +//# sourceURL=break-locations.js
diff --git a/src/v8/test/inspector/debugger/restore-breakpoint-expected.txt b/src/v8/test/inspector/debugger/restore-breakpoint-expected.txt new file mode 100644 index 0000000..ac23487 --- /dev/null +++ b/src/v8/test/inspector/debugger/restore-breakpoint-expected.txt
@@ -0,0 +1,76 @@ +Checks that debugger agent uses source content to restore breakpoints. + +Running test: testSameSource +function foo() { +#boo(); +} +function foo() { +#boo(); +} + +Running test: testOneLineOffset +function foo() { +#boo(); +} +function foo() { +#boo(); +boo(); +} + +Running test: testTwoSimilarLinesCloseToOriginalLocation1 +function foo() { + + +#boo(); +} +function foo() { +#boo(); + +newCode(); +boo(); + + + +boo(); +} + +Running test: testTwoSimilarLinesCloseToOriginalLocation2 +function foo() { + + +#boo(); +} +function foo() { +boo(); +newLongCode(); +newCode(); +#boo(); + + + +boo(); +} + +Running test: testHintIgnoreWhiteSpaces +function foo() { + + + +#boo(); +} +function foo() { +foo(); + + +#boo(); +} + +Running test: testCheckOnlyLimitedOffsets +function foo() { +#boo(); +} +function foo() { +#newCode(); +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;... +boo(); +}
diff --git a/src/v8/test/inspector/debugger/restore-breakpoint.js b/src/v8/test/inspector/debugger/restore-breakpoint.js new file mode 100644 index 0000000..e0d2b84 --- /dev/null +++ b/src/v8/test/inspector/debugger/restore-breakpoint.js
@@ -0,0 +1,69 @@ +// Copyright 2017 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. + +let {session, contextGroup, Protocol} = InspectorTest.start('Checks that debugger agent uses source content to restore breakpoints.'); + +Protocol.Debugger.enable(); +InspectorTest.runTestSuite([ + function testSameSource(next) { + var source = 'function foo() {\nboo();\n}'; + test(source, source, { lineNumber: 1, columnNumber: 0 }, next); + }, + + function testOneLineOffset(next) { + var source = 'function foo() {\nboo();\n}'; + var newSource = 'function foo() {\nboo();\nboo();\n}'; + test(source, newSource, { lineNumber: 1, columnNumber: 0 }, next); + }, + + function testTwoSimilarLinesCloseToOriginalLocation1(next) { + var source = 'function foo() {\n\n\nboo();\n}'; + var newSource = 'function foo() {\nboo();\n\nnewCode();\nboo();\n\n\n\nboo();\n}'; + test(source, newSource, { lineNumber: 3, columnNumber: 0 }, next); + }, + + function testTwoSimilarLinesCloseToOriginalLocation2(next) { + var source = 'function foo() {\n\n\nboo();\n}'; + var newSource = 'function foo() {\nboo();\nnewLongCode();\nnewCode();\nboo();\n\n\n\nboo();\n}'; + test(source, newSource, { lineNumber: 3, columnNumber: 0 }, next); + }, + + function testHintIgnoreWhiteSpaces(next) { + var source = 'function foo() {\n\n\n\nboo();\n}'; + var newSource = 'function foo() {\nfoo();\n\n\nboo();\n}'; + test(source, newSource, { lineNumber: 1, columnNumber: 0 }, next); + }, + + function testCheckOnlyLimitedOffsets(next) { + var source = 'function foo() {\nboo();\n}'; + var longString = ';'.repeat(1000); + var newSource = `function foo() {\nnewCode();\n${longString};\nboo();\n}`; + test(source, newSource, { lineNumber: 1, columnNumber: 0 }, next); + } +]); + +var finishedTests = 0; +async function test(source, newSource, location, next) { + var firstBreakpoint = true; + Protocol.Debugger.onBreakpointResolved(message => { + var lineNumber = message.params.location.lineNumber; + var columnNumber = message.params.location.columnNumber; + var currentSource = firstBreakpoint ? source : newSource; + var lines = currentSource.split('\n'); + lines = lines.map(line => line.length > 80 ? line.substring(0, 77) + '...' : line); + lines[lineNumber] = lines[lineNumber].slice(0, columnNumber) + '#' + lines[lineNumber].slice(columnNumber); + InspectorTest.log(lines.join('\n')); + firstBreakpoint = false; + }); + + var sourceURL = `test${++finishedTests}.js`; + await Protocol.Debugger.setBreakpointByUrl({ + url: sourceURL, + lineNumber: location.lineNumber, + columnNumber: location.columnNumber + }); + await Protocol.Runtime.evaluate({ expression: `${source}\n//# sourceURL=${sourceURL}` }); + await Protocol.Runtime.evaluate({ expression: `${newSource}\n//# sourceURL=${sourceURL}` }); + next(); +}
diff --git a/src/v8/test/inspector/debugger/return-break-locations-expected.txt b/src/v8/test/inspector/debugger/return-break-locations-expected.txt new file mode 100644 index 0000000..688faf8 --- /dev/null +++ b/src/v8/test/inspector/debugger/return-break-locations-expected.txt
@@ -0,0 +1,29 @@ +Return break locations within function + +Running test: testTailCall +[ + [0] : { + columnNumber : 20 + lineNumber : 2 + scriptId : <scriptId> + type : return + } + [1] : { + columnNumber : 24 + lineNumber : 3 + scriptId : <scriptId> + type : return + } + [2] : { + columnNumber : 29 + lineNumber : 4 + scriptId : <scriptId> + type : return + } + [3] : { + columnNumber : 59 + lineNumber : 5 + scriptId : <scriptId> + type : return + } +]
diff --git a/src/v8/test/inspector/debugger/return-break-locations.js b/src/v8/test/inspector/debugger/return-break-locations.js new file mode 100644 index 0000000..b253b88 --- /dev/null +++ b/src/v8/test/inspector/debugger/return-break-locations.js
@@ -0,0 +1,26 @@ +// Copyright 2017 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. + +let {session, contextGroup, Protocol} = InspectorTest.start('Return break locations within function'); + +contextGroup.addScript(` +function fib(x) { + if (x < 0) return; + if (x === 0) return 1; + if (x === 1) return fib(0); + return x > 2 ? fib(x - 1) + fib(x - 2) : fib(1) + fib(0); +} +`); + +InspectorTest.runAsyncTestSuite([ + async function testTailCall() { + var scriptPromise = Protocol.Debugger.onceScriptParsed(); + Protocol.Debugger.enable(); + var scriptId = (await scriptPromise).params.scriptId; + var locations = (await Protocol.Debugger.getPossibleBreakpoints({ + start: { lineNumber: 0, columnNumber: 0, scriptId } + })).result.locations; + InspectorTest.logMessage(locations.filter(location => location.type === 'return')); + } +]);
diff --git a/src/v8/test/inspector/debugger/schedule-step-into-async-expected.txt b/src/v8/test/inspector/debugger/schedule-step-into-async-expected.txt new file mode 100644 index 0000000..be3cad1 --- /dev/null +++ b/src/v8/test/inspector/debugger/schedule-step-into-async-expected.txt
@@ -0,0 +1,191 @@ +Checks Debugger.scheduleStepIntoAsync. + +Running test: testScheduleErrors +paused at: +function testNoScheduledTask() { + #debugger; + return 42; + +{ + error : { + code : -32000 + message : Current scheduled step into async was overriden with new one. + } + id : <messageId> +} +{ + error : { + code : -32000 + message : No async tasks were scheduled before pause. + } + id : <messageId> +} +paused at: + debugger; + #return 42; +} + + +Running test: testSimple +paused at: +function testSimple() { + #debugger; + Promise.resolve().then(v => v * 2); + +paused at: + debugger; + #Promise.resolve().then(v => v * 2); +} + +{ + id : <messageId> + result : { + } +} +paused at: + debugger; + Promise.resolve().then(#v => v * 2); +} + + +Running test: testNotResolvedPromise +paused at: + var p = new Promise(resolve => resolveCallback = resolve); + #debugger; + p.then(v => v * 2); + +paused at: + debugger; + p.#then(v => v * 2); + resolveCallback(); + +{ + id : <messageId> + result : { + } +} +paused at: + debugger; + p.then(#v => v * 2); + resolveCallback(); + + +Running test: testTwoAsyncTasks +paused at: +function testTwoAsyncTasks() { + #debugger; + Promise.resolve().then(v => v * 2); + +{ + id : <messageId> + result : { + } +} +paused at: + debugger; + Promise.resolve().then(#v => v * 2); + Promise.resolve().then(v => v * 4); + + +Running test: testTwoTasksAndGoToSecond +paused at: +function testTwoAsyncTasks() { + #debugger; + Promise.resolve().then(v => v * 2); + +paused at: + debugger; + #Promise.resolve().then(v => v * 2); + Promise.resolve().then(v => v * 4); + +paused at: + Promise.resolve().then(v => v * 2); + #Promise.resolve().then(v => v * 4); +} + +{ + id : <messageId> + result : { + } +} +paused at: + Promise.resolve().then(v => v * 2); + Promise.resolve().then(#v => v * 4); +} + + +Running test: testTwoAsyncTasksWithBreak +paused at: +function testTwoAsyncTasksWithBreak() { + #debugger; + Promise.resolve().then(v => v * 2); + +paused at: + debugger; + #Promise.resolve().then(v => v * 2); + debugger; + +{ + id : <messageId> + result : { + } +} +paused at: + Promise.resolve().then(v => v * 2); + #debugger; + Promise.resolve().then(v => v * 4); + +{ + id : <messageId> + result : { + } +} +paused at: + debugger; + Promise.resolve().then(#v => v * 4); +} + + +Running test: testPromiseAll +paused at: +function testPromiseAll() { + #debugger; + Promise.all([ Promise.resolve(), Promise.resolve() ]).then(v => v * 2); + +paused at: + debugger; + #Promise.all([ Promise.resolve(), Promise.resolve() ]).then(v => v * 2); +} + +{ + id : <messageId> + result : { + } +} +paused at: + debugger; + Promise.all([ Promise.resolve(), Promise.resolve() ]).then(#v => v * 2); +} + + +Running test: testWithBlackboxedCode +paused at: +function testBlackboxedCreatePromise() { + #debugger; + createPromise().then(v => v * 2); + +paused at: + debugger; + #createPromise().then(v => v * 2); +} + +{ + id : <messageId> + result : { + } +} +paused at: + debugger; + createPromise().then(#v => v * 2); +} +
diff --git a/src/v8/test/inspector/debugger/schedule-step-into-async-set-timeout-expected.txt b/src/v8/test/inspector/debugger/schedule-step-into-async-set-timeout-expected.txt new file mode 100644 index 0000000..afcc5e3 --- /dev/null +++ b/src/v8/test/inspector/debugger/schedule-step-into-async-set-timeout-expected.txt
@@ -0,0 +1,45 @@ +Checks Debugger.scheduleStepIntoAsync with setTimeout. + +Running test: testSetTimeout +paused at: +debugger; #setTimeout(() => 1, 0); + +paused at: +debugger; setTimeout(#() => 1, 0); + + +Running test: testDebuggerStmtBeforeCallback1 +paused at: +debugger; #setTimeout(() => 1, 0);debugger; + +paused at: +debugger; setTimeout(() => 1, 0);#debugger; + +paused at: +#debugger//should-break-here + + +Running test: testDebuggerStmtBeforeCallback2 +paused at: +debugger; setTimeout(() => 1#, 0);debugger; + +paused at: +#debugger//should-break-here + + +Running test: testSetTimeoutWithoutJS +paused at: +debugger; #setTimeout('}', 0); +setTimeout('var a = 239;', 0); + +paused at: +#debugger//should-break-here + + +Running test: testResume +paused at: +#setTimeout(() => 42, 0) + +paused at: +setTimeout(#() => 42, 0) +
diff --git a/src/v8/test/inspector/debugger/schedule-step-into-async-set-timeout.js b/src/v8/test/inspector/debugger/schedule-step-into-async-set-timeout.js new file mode 100644 index 0000000..f2171a5 --- /dev/null +++ b/src/v8/test/inspector/debugger/schedule-step-into-async-set-timeout.js
@@ -0,0 +1,75 @@ +// Copyright 2017 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. + +let {session, contextGroup, Protocol} = InspectorTest.start('Checks Debugger.scheduleStepIntoAsync with setTimeout.'); +session.setupScriptMap(); +Protocol.Debugger.enable(); +InspectorTest.runAsyncTestSuite([ + async function testSetTimeout() { + Protocol.Runtime.evaluate({expression: 'debugger; setTimeout(() => 1, 0);'}); + await Protocol.Debugger.oncePaused(); + Protocol.Debugger.stepOver(); + await waitPauseAndDumpLocation(); + Protocol.Debugger.scheduleStepIntoAsync(); + Protocol.Debugger.stepOver(); + await waitPauseAndDumpLocation(); + await Protocol.Debugger.resume(); + }, + + async function testDebuggerStmtBeforeCallback1() { + Protocol.Runtime.evaluate({expression: 'debugger; setTimeout(() => 1, 0);debugger;'}); + Protocol.Runtime.evaluate({expression: 'setTimeout(\'debugger//should-break-here\', 0)'}); + await Protocol.Debugger.oncePaused(); + Protocol.Debugger.stepOver(); + await waitPauseAndDumpLocation(); + Protocol.Debugger.scheduleStepIntoAsync(); + Protocol.Debugger.stepOver(); + await waitPauseAndDumpLocation(); + await Protocol.Debugger.resume(); + await waitPauseAndDumpLocation(); + await Protocol.Debugger.resume(); + }, + + async function testDebuggerStmtBeforeCallback2() { + Protocol.Runtime.evaluate({expression: 'debugger;\nsetTimeout(\'debugger//should-break-here\', 0);\nsetTimeout(() => 1, 0);'}); + await Protocol.Debugger.oncePaused(); + Protocol.Debugger.stepOver(); + await Protocol.Debugger.oncePaused(); + Protocol.Debugger.stepOver(); + await waitPauseAndDumpLocation(); + Protocol.Debugger.scheduleStepIntoAsync(); + Protocol.Debugger.stepOver(); + await waitPauseAndDumpLocation(); + await Protocol.Debugger.resume(); + await InspectorTest.waitForPendingTasks(); + }, + + async function testSetTimeoutWithoutJS() { + Protocol.Runtime.evaluate({expression: 'debugger; setTimeout(\'}\', 0);\nsetTimeout(\'var a = 239;\', 0);\nsetTimeout(\'debugger//should-break-here\', 0);'}); + await Protocol.Debugger.oncePaused(); + Protocol.Debugger.stepOver(); + await waitPauseAndDumpLocation(); + Protocol.Debugger.scheduleStepIntoAsync(); + Protocol.Debugger.stepOver(); + await waitPauseAndDumpLocation(); + await Protocol.Debugger.resume(); + }, + + async function testResume() { + Protocol.Debugger.pause(); + Protocol.Runtime.evaluate({expression: 'setTimeout(() => 42, 0)'}); + await waitPauseAndDumpLocation(); + Protocol.Debugger.scheduleStepIntoAsync(); + Protocol.Debugger.resume(); + await waitPauseAndDumpLocation(); + await Protocol.Debugger.resume(); + } +]); + +async function waitPauseAndDumpLocation() { + var message = await Protocol.Debugger.oncePaused(); + InspectorTest.log('paused at:'); + await session.logSourceLocation(message.params.callFrames[0].location); + return message; +}
diff --git a/src/v8/test/inspector/debugger/schedule-step-into-async.js b/src/v8/test/inspector/debugger/schedule-step-into-async.js new file mode 100644 index 0000000..c4dfb73 --- /dev/null +++ b/src/v8/test/inspector/debugger/schedule-step-into-async.js
@@ -0,0 +1,159 @@ +// Copyright 2017 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. + +let {session, contextGroup, Protocol} = InspectorTest.start('Checks Debugger.scheduleStepIntoAsync.'); + +contextGroup.addScript(` +function testNoScheduledTask() { + debugger; + return 42; +} + +function testSimple() { + debugger; + Promise.resolve().then(v => v * 2); +} + +function testNotResolvedPromise() { + var resolveCallback; + var p = new Promise(resolve => resolveCallback = resolve); + debugger; + p.then(v => v * 2); + resolveCallback(); +} + +function testTwoAsyncTasks() { + debugger; + Promise.resolve().then(v => v * 2); + Promise.resolve().then(v => v * 4); +} + +function testTwoAsyncTasksWithBreak() { + debugger; + Promise.resolve().then(v => v * 2); + debugger; + Promise.resolve().then(v => v * 4); +} + +function testPromiseAll() { + debugger; + Promise.all([ Promise.resolve(), Promise.resolve() ]).then(v => v * 2); +} + +function testBlackboxedCreatePromise() { + debugger; + createPromise().then(v => v * 2); +} +//# sourceURL=test.js`); + +contextGroup.addScript(` + +function createPromise() { + return Promise.resolve().then(v => v * 3).then(v => v * 4); +} + +//# sourceURL=framework.js`) + +session.setupScriptMap(); + +Protocol.Debugger.enable(); +InspectorTest.runAsyncTestSuite([ + async function testScheduleErrors() { + Protocol.Runtime.evaluate({ expression: 'testNoScheduledTask()' }); + await waitPauseAndDumpLocation(); + Protocol.Debugger.scheduleStepIntoAsync().then(InspectorTest.logMessage); + Protocol.Debugger.scheduleStepIntoAsync().then(InspectorTest.logMessage); + Protocol.Debugger.stepInto(); + await waitPauseAndDumpLocation(); + await Protocol.Debugger.resume(); + }, + + async function testSimple() { + Protocol.Runtime.evaluate({ expression: 'testSimple()' }); + await waitPauseAndDumpLocation(); + Protocol.Debugger.stepOver(); + await waitPauseAndDumpLocation(); + Protocol.Debugger.scheduleStepIntoAsync().then(InspectorTest.logMessage); + Protocol.Debugger.stepInto(); + await waitPauseAndDumpLocation(); + await Protocol.Debugger.resume(); + }, + + async function testNotResolvedPromise() { + Protocol.Runtime.evaluate({ expression: 'testNotResolvedPromise()' }); + await waitPauseAndDumpLocation(); + Protocol.Debugger.stepOver(); + await waitPauseAndDumpLocation(); + Protocol.Debugger.scheduleStepIntoAsync().then(InspectorTest.logMessage); + Protocol.Debugger.stepInto(); + await waitPauseAndDumpLocation(); + await Protocol.Debugger.resume(); + }, + + async function testTwoAsyncTasks() { + Protocol.Runtime.evaluate({ expression: 'testTwoAsyncTasks()' }); + await waitPauseAndDumpLocation(); + Protocol.Debugger.scheduleStepIntoAsync().then(InspectorTest.logMessage); + Protocol.Debugger.resume(); + await waitPauseAndDumpLocation(); + await Protocol.Debugger.resume(); + }, + + async function testTwoTasksAndGoToSecond() { + Protocol.Runtime.evaluate({ expression: 'testTwoAsyncTasks()' }); + await waitPauseAndDumpLocation(); + Protocol.Debugger.stepOver(); + await waitPauseAndDumpLocation(); + Protocol.Debugger.stepOver(); + await waitPauseAndDumpLocation(); + Protocol.Debugger.scheduleStepIntoAsync().then(InspectorTest.logMessage); + Protocol.Debugger.resume(); + await waitPauseAndDumpLocation(); + await Protocol.Debugger.resume(); + }, + + async function testTwoAsyncTasksWithBreak() { + Protocol.Runtime.evaluate({ expression: 'testTwoAsyncTasksWithBreak()' }); + await waitPauseAndDumpLocation(); + Protocol.Debugger.stepOver(); + await waitPauseAndDumpLocation(); + Protocol.Debugger.scheduleStepIntoAsync().then(InspectorTest.logMessage); + Protocol.Debugger.resume(); + await waitPauseAndDumpLocation(); + Protocol.Debugger.scheduleStepIntoAsync().then(InspectorTest.logMessage); + Protocol.Debugger.resume(); + await waitPauseAndDumpLocation(); + await Protocol.Debugger.resume(); + }, + + async function testPromiseAll() { + Protocol.Runtime.evaluate({ expression: 'testPromiseAll()' }); + await waitPauseAndDumpLocation(); + Protocol.Debugger.stepOver(); + await waitPauseAndDumpLocation(); + Protocol.Debugger.scheduleStepIntoAsync().then(InspectorTest.logMessage); + Protocol.Debugger.stepOver(); + await waitPauseAndDumpLocation(); + await Protocol.Debugger.resume(); + }, + + async function testWithBlackboxedCode() { + Protocol.Runtime.evaluate({ expression: 'testBlackboxedCreatePromise()' }); + await waitPauseAndDumpLocation(); + Protocol.Debugger.stepOver(); + await waitPauseAndDumpLocation(); + await Protocol.Debugger.setBlackboxPatterns({patterns: ['framework\.js'] }); + Protocol.Debugger.scheduleStepIntoAsync().then(InspectorTest.logMessage); + Protocol.Debugger.stepOver(); + await waitPauseAndDumpLocation(); + await Protocol.Debugger.resume(); + } +]); + +async function waitPauseAndDumpLocation() { + var message = await Protocol.Debugger.oncePaused(); + InspectorTest.log('paused at:'); + session.logSourceLocation(message.params.callFrames[0].location); + return message; +}
diff --git a/src/v8/test/inspector/debugger/scope-skip-variables-with-empty-name-expected.txt b/src/v8/test/inspector/debugger/scope-skip-variables-with-empty-name-expected.txt new file mode 100644 index 0000000..626f978 --- /dev/null +++ b/src/v8/test/inspector/debugger/scope-skip-variables-with-empty-name-expected.txt
@@ -0,0 +1,20 @@ +Tests that scopes do not report variables with empty names +{ + id : <messageId> + result : { + result : [ + [0] : { + configurable : true + enumerable : true + isOwn : true + name : a + value : { + description : 2 + type : number + value : 2 + } + writable : true + } + ] + } +}
diff --git a/src/v8/test/inspector/debugger/scope-skip-variables-with-empty-name.js b/src/v8/test/inspector/debugger/scope-skip-variables-with-empty-name.js new file mode 100644 index 0000000..72cbeee --- /dev/null +++ b/src/v8/test/inspector/debugger/scope-skip-variables-with-empty-name.js
@@ -0,0 +1,44 @@ +// 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. + +let {session, contextGroup, Protocol} = InspectorTest.start('Tests that scopes do not report variables with empty names'); + +contextGroup.addScript( +`function testFunction() +{ + for (var a of [1]) { + ++a; + debugger; + } +}`); + +Protocol.Debugger.enable(); +Protocol.Debugger.oncePaused().then(dumpScopeOnPause); +Protocol.Runtime.evaluate({ "expression": "testFunction()" }); + +var waitScopeObjects = 0; +function dumpScopeOnPause(message) +{ + var scopeChain = message.params.callFrames[0].scopeChain; + var localScopeObjectIds = []; + for (var scope of scopeChain) { + if (scope.type === "local") + localScopeObjectIds.push(scope.object.objectId); + } + waitScopeObjects = localScopeObjectIds.length; + if (!waitScopeObjects) { + InspectorTest.completeTest(); + } else { + for (var objectId of localScopeObjectIds) + Protocol.Runtime.getProperties({ "objectId" : objectId }).then(dumpProperties); + } +} + +function dumpProperties(message) +{ + InspectorTest.logMessage(message); + --waitScopeObjects; + if (!waitScopeObjects) + Protocol.Debugger.resume().then(InspectorTest.completeTest); +}
diff --git a/src/v8/test/inspector/debugger/script-end-location-expected.txt b/src/v8/test/inspector/debugger/script-end-location-expected.txt new file mode 100644 index 0000000..3d0b480 --- /dev/null +++ b/src/v8/test/inspector/debugger/script-end-location-expected.txt
@@ -0,0 +1,91 @@ +Checks that we report correct endLine, endColumn and source for scripts. +{ + compiled : { + endColumn : 0 + endLine : 0 + } + returned : { + endColumn : 0 + endLine : 0 + } +} +{ + compiled : { + endColumn : 1 + endLine : 0 + } + returned : { + endColumn : 1 + endLine : 0 + } +} +{ + compiled : { + endColumn : 2 + endLine : 0 + } + returned : { + endColumn : 2 + endLine : 0 + } +} +{ + compiled : { + endColumn : 0 + endLine : 1 + } + returned : { + endColumn : 0 + endLine : 1 + } +} +{ + compiled : { + endColumn : 1 + endLine : 1 + } + returned : { + endColumn : 1 + endLine : 1 + } +} +{ + compiled : { + endColumn : 3 + endLine : 1 + } + returned : { + endColumn : 3 + endLine : 1 + } +} +{ + compiled : { + endColumn : 0 + endLine : 2 + } + returned : { + endColumn : 0 + endLine : 2 + } +} +{ + compiled : { + endColumn : 1 + endLine : 2 + } + returned : { + endColumn : 1 + endLine : 2 + } +} +{ + compiled : { + endColumn : 2 + endLine : 2 + } + returned : { + endColumn : 2 + endLine : 2 + } +}
diff --git a/src/v8/test/inspector/debugger/script-end-location.js b/src/v8/test/inspector/debugger/script-end-location.js new file mode 100644 index 0000000..57d1235 --- /dev/null +++ b/src/v8/test/inspector/debugger/script-end-location.js
@@ -0,0 +1,48 @@ +// Copyright 2017 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. + +let {session, contextGroup, Protocol} = InspectorTest.start('Checks that we report correct endLine, endColumn and source for scripts.'); + +var sources = [ +'', +' ', +' ', +` +`, +` + `, +` + `, +` + +`, +` + + `, +` + + `]; + +(async function test() { + Protocol.Debugger.enable(); + for (let source of sources) { + contextGroup.addScript(source); + var message = await Protocol.Debugger.onceScriptParsed(); + var inspectorSource = (await Protocol.Debugger.getScriptSource({ scriptId: message.params.scriptId })).result.scriptSource; + var lines = source.split('\n'); + var returned = { endLine: message.params.endLine, endColumn: message.params.endColumn }; + var compiled = { endLine: lines.length - 1, endColumn: lines[lines.length - 1].length }; + InspectorTest.logObject({ returned, compiled }); + if (returned.endLine != compiled.endLine) { + InspectorTest.log('error: incorrect endLine'); + } + if (returned.endColumn != compiled.endColumn) { + InspectorTest.log('error: incorrect endColumn'); + } + if (source !== inspectorSource) { + InspectorTest.log('error: incorrect source'); + } + } + InspectorTest.completeTest(); +})();
diff --git a/src/v8/test/inspector/debugger/script-on-after-compile-expected.txt b/src/v8/test/inspector/debugger/script-on-after-compile-expected.txt new file mode 100644 index 0000000..53e24c0 --- /dev/null +++ b/src/v8/test/inspector/debugger/script-on-after-compile-expected.txt
@@ -0,0 +1,753 @@ +Checks that inspector correctly process compiled scripts +scriptParsed +{ + scriptSource : function foo1(){}//# sourceURL=oneline.js<nl> +} +{ + endColumn : 0 + endLine : 1 + executionContextId : <executionContextId> + hasSourceURL : true + hash : 2ACD11425BF645075D5696189A7BA7EB4048D6F7 + isLiveEdit : false + isModule : false + length : 42 + scriptId : <scriptId> + sourceMapURL : + startColumn : 0 + startLine : 0 + url : oneline.js +} +scriptParsed +{ + scriptSource : function foo2(){}//# sourceURL=oneline-without-nl.js +} +{ + endColumn : 52 + endLine : 0 + executionContextId : <executionContextId> + hasSourceURL : true + hash : 0CD3C4132CE40E415D5696189A7BA7EB4048D6F7 + isLiveEdit : false + isModule : false + length : 52 + scriptId : <scriptId> + sourceMapURL : + startColumn : 0 + startLine : 0 + url : oneline-without-nl.js +} +scriptParsed +{ + scriptSource : function foo3(){}<nl>//# sourceURL=twoline.js<nl> +} +{ + endColumn : 0 + endLine : 2 + executionContextId : <executionContextId> + hasSourceURL : true + hash : 0E35E860580550805D5681F7BCD47D855B794EB3 + isLiveEdit : false + isModule : false + length : 43 + scriptId : <scriptId> + sourceMapURL : + startColumn : 0 + startLine : 0 + url : twoline.js +} +scriptParsed +{ + scriptSource : function foo4(){}<nl><nl>//# sourceURL=threeline.js<nl> +} +{ + endColumn : 0 + endLine : 3 + executionContextId : <executionContextId> + hasSourceURL : true + hash : AD4760425BF645075D5681F7D1786BD4DA9A86A7 + isLiveEdit : false + isModule : false + length : 46 + scriptId : <scriptId> + sourceMapURL : + startColumn : 0 + startLine : 0 + url : threeline.js +} +scriptParsed +{ + scriptSource : function foo5(){}//# sourceMappingURL=oneline-map<nl> +} +{ + endColumn : 0 + endLine : 1 + executionContextId : <executionContextId> + hasSourceURL : false + hash : 3E60CE61913387795D5696189A7BA7EB4048B715 + isLiveEdit : false + isModule : false + length : 50 + scriptId : <scriptId> + sourceMapURL : oneline-map + startColumn : 0 + startLine : 0 + url : +} +scriptParsed +{ + scriptSource : function foo6(){}//# sourceMappingURL=oneline-without-nl-map +} +{ + endColumn : 60 + endLine : 0 + executionContextId : <executionContextId> + hasSourceURL : false + hash : 3E60CE617215C621E8825B319A7BA7EB4048B715 + isLiveEdit : false + isModule : false + length : 60 + scriptId : <scriptId> + sourceMapURL : oneline-without-nl-map + startColumn : 0 + startLine : 0 + url : +} +scriptParsed +{ + scriptSource : function foo7(){}<nl>//# sourceMappingURL=twoline-map<nl> +} +{ + endColumn : 0 + endLine : 2 + executionContextId : <executionContextId> + hasSourceURL : false + hash : F2A32D219EFACBF470C48663BCD47D85864D1A22 + isLiveEdit : false + isModule : false + length : 51 + scriptId : <scriptId> + sourceMapURL : twoline-map + startColumn : 0 + startLine : 0 + url : +} +scriptParsed +{ + scriptSource : function foo8(){}<nl><nl>//# sourceMappingURL=threeline-map<nl> +} +{ + endColumn : 0 + endLine : 3 + executionContextId : <executionContextId> + hasSourceURL : false + hash : 46927EC1BFB78C355D5681F7D1786BD4216D5124 + isLiveEdit : false + isModule : false + length : 54 + scriptId : <scriptId> + sourceMapURL : threeline-map + startColumn : 0 + startLine : 0 + url : +} +scriptParsed +{ + scriptSource : function foo9(){}//# sourceMappingURL=source-mapping-url-map<nl>//# sourceURL=source-url.js +} +{ + endColumn : 27 + endLine : 1 + executionContextId : <executionContextId> + hasSourceURL : true + hash : 793E2411EDECF405E8825B31460F7CD9A656E096 + isLiveEdit : false + isModule : false + length : 88 + scriptId : <scriptId> + sourceMapURL : source-mapping-url-map + startColumn : 0 + startLine : 0 + url : source-url.js +} +scriptParsed +{ + scriptSource : function foo10(){}//# sourceURL=source-url.js<nl>//# sourceMappingURL=source-mapping-url-map +} +{ + endColumn : 43 + endLine : 1 + executionContextId : <executionContextId> + hasSourceURL : true + hash : DED761235CC24EE21D0E9277CF599B5A292D8053 + isLiveEdit : false + isModule : false + length : 89 + scriptId : <scriptId> + sourceMapURL : source-mapping-url-map + startColumn : 0 + startLine : 0 + url : source-url.js +} +scriptParsed +{ + scriptSource : function foo11(){}<nl>//# sourceURL=end1.js +} +{ + endColumn : 21 + endLine : 1 + executionContextId : <executionContextId> + hasSourceURL : true + hash : 9CF28A415BF64507692D5A84D1786BD4437C3511 + isLiveEdit : false + isModule : false + length : 40 + scriptId : <scriptId> + sourceMapURL : + startColumn : 0 + startLine : 0 + url : end1.js +} +scriptParsed +{ + scriptSource : function foo12(){}<nl>//# sourceURL=end2.js +} +{ + endColumn : 22 + endLine : 1 + executionContextId : <executionContextId> + hasSourceURL : true + hash : BEE49C625BF64507692D5A84D1786BD4437C3511 + isLiveEdit : false + isModule : false + length : 41 + scriptId : <scriptId> + sourceMapURL : + startColumn : 0 + startLine : 0 + url : end2.js +} +scriptParsed +{ + scriptSource : function foo13(){} +} +{ + endColumn : 18 + endLine : 0 + executionContextId : <executionContextId> + hasSourceURL : false + hash : 9CF28A415BF64507692D5A8443D429DC872EBA18 + isLiveEdit : false + isModule : false + length : 18 + scriptId : <scriptId> + sourceMapURL : + startColumn : 0 + startLine : 0 + url : +} +scriptParsed +{ + scriptSource : function foo15(){}; eval("function foo14(){}//# sourceURL=eval.js")//# sourceURL=eval-wrapper.js +} +{ + endColumn : 96 + endLine : 0 + executionContextId : <executionContextId> + hasSourceURL : true + hash : D26251F019679C792E2B4EF437A20E96134D5C26 + isLiveEdit : false + isModule : false + length : 96 + scriptId : <scriptId> + sourceMapURL : + startColumn : 0 + startLine : 0 + url : eval-wrapper.js +} +scriptParsed +{ + scriptSource : function foo14(){}//# sourceURL=eval.js +} +{ + endColumn : 39 + endLine : 0 + executionContextId : <executionContextId> + hasSourceURL : true + hash : 814AEF635BF64507692D5A84BCD47D85C4031CD2 + isLiveEdit : false + isModule : false + length : 39 + scriptId : <scriptId> + sourceMapURL : + startColumn : 0 + startLine : 0 + url : eval.js +} +scriptParsed +{ + scriptSource : function foo16(){}<nl> +} +{ + endColumn : 0 + endLine : 1 + executionContextId : <executionContextId> + hasSourceURL : false + hash : 9CF28A415BF64507692D5A84A8DC8126872EBA18 + isLiveEdit : false + isModule : false + length : 19 + scriptId : <scriptId> + sourceMapURL : + startColumn : 0 + startLine : 0 + url : +} +scriptParsed +{ + scriptSource : function foo17(){}<nl><nl> +} +{ + endColumn : 0 + endLine : 2 + executionContextId : <executionContextId> + hasSourceURL : false + hash : 9CF28A415BF64507692D5A8443D429DC872EBA18 + isLiveEdit : false + isModule : false + length : 20 + scriptId : <scriptId> + sourceMapURL : + startColumn : 0 + startLine : 0 + url : +} +scriptParsed +{ + scriptSource : function foo18(){}<nl><nl><nl> +} +{ + endColumn : 0 + endLine : 3 + executionContextId : <executionContextId> + hasSourceURL : false + hash : 9CF28A415BF64507692D5A84A8DC8126872EBA18 + isLiveEdit : false + isModule : false + length : 21 + scriptId : <scriptId> + sourceMapURL : + startColumn : 0 + startLine : 0 + url : +} +scriptParsed +{ + scriptSource : function foo19(){}<nl><nl><nl><nl> +} +{ + endColumn : 0 + endLine : 4 + executionContextId : <executionContextId> + hasSourceURL : false + hash : 9CF28A415BF64507692D5A8443D429DC872EBA18 + isLiveEdit : false + isModule : false + length : 22 + scriptId : <scriptId> + sourceMapURL : + startColumn : 0 + startLine : 0 + url : +} +scriptParsed +{ + scriptSource : function foo1(){}//# sourceURL=oneline.js<nl> +} +{ + endColumn : 0 + endLine : 1 + executionContextId : <executionContextId> + hasSourceURL : true + hash : 2ACD11425BF645075D5696189A7BA7EB4048D6F7 + isLiveEdit : false + isModule : false + length : 42 + scriptId : <scriptId> + sourceMapURL : + startColumn : 0 + startLine : 0 + url : oneline.js +} +scriptParsed +{ + scriptSource : function foo2(){}//# sourceURL=oneline-without-nl.js +} +{ + endColumn : 52 + endLine : 0 + executionContextId : <executionContextId> + hasSourceURL : true + hash : 0CD3C4132CE40E415D5696189A7BA7EB4048D6F7 + isLiveEdit : false + isModule : false + length : 52 + scriptId : <scriptId> + sourceMapURL : + startColumn : 0 + startLine : 0 + url : oneline-without-nl.js +} +scriptParsed +{ + scriptSource : function foo3(){}<nl>//# sourceURL=twoline.js<nl> +} +{ + endColumn : 0 + endLine : 2 + executionContextId : <executionContextId> + hasSourceURL : true + hash : 0E35E860580550805D5681F7BCD47D855B794EB3 + isLiveEdit : false + isModule : false + length : 43 + scriptId : <scriptId> + sourceMapURL : + startColumn : 0 + startLine : 0 + url : twoline.js +} +scriptParsed +{ + scriptSource : function foo4(){}<nl><nl>//# sourceURL=threeline.js<nl> +} +{ + endColumn : 0 + endLine : 3 + executionContextId : <executionContextId> + hasSourceURL : true + hash : AD4760425BF645075D5681F7D1786BD4DA9A86A7 + isLiveEdit : false + isModule : false + length : 46 + scriptId : <scriptId> + sourceMapURL : + startColumn : 0 + startLine : 0 + url : threeline.js +} +scriptParsed +{ + scriptSource : function foo5(){}//# sourceMappingURL=oneline-map<nl> +} +{ + endColumn : 0 + endLine : 1 + executionContextId : <executionContextId> + hasSourceURL : false + hash : 3E60CE61913387795D5696189A7BA7EB4048B715 + isLiveEdit : false + isModule : false + length : 50 + scriptId : <scriptId> + sourceMapURL : oneline-map + startColumn : 0 + startLine : 0 + url : +} +scriptParsed +{ + scriptSource : function foo6(){}//# sourceMappingURL=oneline-without-nl-map +} +{ + endColumn : 60 + endLine : 0 + executionContextId : <executionContextId> + hasSourceURL : false + hash : 3E60CE617215C621E8825B319A7BA7EB4048B715 + isLiveEdit : false + isModule : false + length : 60 + scriptId : <scriptId> + sourceMapURL : oneline-without-nl-map + startColumn : 0 + startLine : 0 + url : +} +scriptParsed +{ + scriptSource : function foo7(){}<nl>//# sourceMappingURL=twoline-map<nl> +} +{ + endColumn : 0 + endLine : 2 + executionContextId : <executionContextId> + hasSourceURL : false + hash : F2A32D219EFACBF470C48663BCD47D85864D1A22 + isLiveEdit : false + isModule : false + length : 51 + scriptId : <scriptId> + sourceMapURL : twoline-map + startColumn : 0 + startLine : 0 + url : +} +scriptParsed +{ + scriptSource : function foo8(){}<nl><nl>//# sourceMappingURL=threeline-map<nl> +} +{ + endColumn : 0 + endLine : 3 + executionContextId : <executionContextId> + hasSourceURL : false + hash : 46927EC1BFB78C355D5681F7D1786BD4216D5124 + isLiveEdit : false + isModule : false + length : 54 + scriptId : <scriptId> + sourceMapURL : threeline-map + startColumn : 0 + startLine : 0 + url : +} +scriptParsed +{ + scriptSource : function foo9(){}//# sourceMappingURL=source-mapping-url-map<nl>//# sourceURL=source-url.js +} +{ + endColumn : 27 + endLine : 1 + executionContextId : <executionContextId> + hasSourceURL : true + hash : 793E2411EDECF405E8825B31460F7CD9A656E096 + isLiveEdit : false + isModule : false + length : 88 + scriptId : <scriptId> + sourceMapURL : source-mapping-url-map + startColumn : 0 + startLine : 0 + url : source-url.js +} +scriptParsed +{ + scriptSource : function foo10(){}//# sourceURL=source-url.js<nl>//# sourceMappingURL=source-mapping-url-map +} +{ + endColumn : 43 + endLine : 1 + executionContextId : <executionContextId> + hasSourceURL : true + hash : DED761235CC24EE21D0E9277CF599B5A292D8053 + isLiveEdit : false + isModule : false + length : 89 + scriptId : <scriptId> + sourceMapURL : source-mapping-url-map + startColumn : 0 + startLine : 0 + url : source-url.js +} +scriptParsed +{ + scriptSource : function foo11(){}<nl>//# sourceURL=end1.js +} +{ + endColumn : 21 + endLine : 1 + executionContextId : <executionContextId> + hasSourceURL : true + hash : 9CF28A415BF64507692D5A84D1786BD4437C3511 + isLiveEdit : false + isModule : false + length : 40 + scriptId : <scriptId> + sourceMapURL : + startColumn : 0 + startLine : 0 + url : end1.js +} +scriptParsed +{ + scriptSource : function foo12(){}<nl>//# sourceURL=end2.js +} +{ + endColumn : 22 + endLine : 1 + executionContextId : <executionContextId> + hasSourceURL : true + hash : BEE49C625BF64507692D5A84D1786BD4437C3511 + isLiveEdit : false + isModule : false + length : 41 + scriptId : <scriptId> + sourceMapURL : + startColumn : 0 + startLine : 0 + url : end2.js +} +scriptParsed +{ + scriptSource : function foo13(){} +} +{ + endColumn : 18 + endLine : 0 + executionContextId : <executionContextId> + hasSourceURL : false + hash : 9CF28A415BF64507692D5A8443D429DC872EBA18 + isLiveEdit : false + isModule : false + length : 18 + scriptId : <scriptId> + sourceMapURL : + startColumn : 0 + startLine : 0 + url : +} +scriptParsed +{ + scriptSource : function foo15(){}; eval("function foo14(){}//# sourceURL=eval.js")//# sourceURL=eval-wrapper.js +} +{ + endColumn : 96 + endLine : 0 + executionContextId : <executionContextId> + hasSourceURL : true + hash : D26251F019679C792E2B4EF437A20E96134D5C26 + isLiveEdit : false + isModule : false + length : 96 + scriptId : <scriptId> + sourceMapURL : + startColumn : 0 + startLine : 0 + url : eval-wrapper.js +} +scriptParsed +{ + scriptSource : function foo14(){}//# sourceURL=eval.js +} +{ + endColumn : 39 + endLine : 0 + executionContextId : <executionContextId> + hasSourceURL : true + hash : 814AEF635BF64507692D5A84BCD47D85C4031CD2 + isLiveEdit : false + isModule : false + length : 39 + scriptId : <scriptId> + sourceMapURL : + stackTrace : { + callFrames : [ + [0] : { + columnNumber : 20 + functionName : + lineNumber : 0 + scriptId : <scriptId> + url : eval-wrapper.js + } + ] + } + startColumn : 0 + startLine : 0 + url : eval.js +} +scriptFailedToParse +{ + scriptSource : }//# sourceURL=failed.js<nl>//# sourceMappingURL=failed-map +} +{ + endColumn : 31 + endLine : 1 + executionContextId : <executionContextId> + hasSourceURL : true + hash : C0C37C619263496792D5CFE7CA6F2911028287A6 + isModule : false + length : 56 + scriptId : <scriptId> + sourceMapURL : failed-map + startColumn : 0 + startLine : 0 + url : failed.js +} +scriptParsed +{ + scriptSource : function foo16(){}<nl> +} +{ + endColumn : 0 + endLine : 1 + executionContextId : <executionContextId> + hasSourceURL : false + hash : 9CF28A415BF64507692D5A84A8DC8126872EBA18 + isLiveEdit : false + isModule : false + length : 19 + scriptId : <scriptId> + sourceMapURL : + startColumn : 0 + startLine : 0 + url : +} +scriptParsed +{ + scriptSource : function foo17(){}<nl><nl> +} +{ + endColumn : 0 + endLine : 2 + executionContextId : <executionContextId> + hasSourceURL : false + hash : 9CF28A415BF64507692D5A8443D429DC872EBA18 + isLiveEdit : false + isModule : false + length : 20 + scriptId : <scriptId> + sourceMapURL : + startColumn : 0 + startLine : 0 + url : +} +scriptParsed +{ + scriptSource : function foo18(){}<nl><nl><nl> +} +{ + endColumn : 0 + endLine : 3 + executionContextId : <executionContextId> + hasSourceURL : false + hash : 9CF28A415BF64507692D5A84A8DC8126872EBA18 + isLiveEdit : false + isModule : false + length : 21 + scriptId : <scriptId> + sourceMapURL : + startColumn : 0 + startLine : 0 + url : +} +scriptParsed +{ + scriptSource : function foo19(){}<nl><nl><nl><nl> +} +{ + endColumn : 0 + endLine : 4 + executionContextId : <executionContextId> + hasSourceURL : false + hash : 9CF28A415BF64507692D5A8443D429DC872EBA18 + isLiveEdit : false + isModule : false + length : 22 + scriptId : <scriptId> + sourceMapURL : + startColumn : 0 + startLine : 0 + url : +} +Remove script references and re-enable debugger.
diff --git a/src/v8/test/inspector/debugger/script-on-after-compile.js b/src/v8/test/inspector/debugger/script-on-after-compile.js new file mode 100644 index 0000000..544dbaa --- /dev/null +++ b/src/v8/test/inspector/debugger/script-on-after-compile.js
@@ -0,0 +1,73 @@ +// 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. + +let {session, contextGroup, Protocol} = InspectorTest.start("Checks that inspector correctly process compiled scripts"); + +function addScripts() { + // sourceURL in the same line + return addScript("function foo1(){}//# sourceURL=oneline.js\n") + // sourceURL without end line + .then(() => addScript("function foo2(){}//# sourceURL=oneline-without-nl.js")) + // other source urls + .then(() => addScript("function foo3(){}\n//# sourceURL=twoline.js\n")) + .then(() => addScript("function foo4(){}\n\n//# sourceURL=threeline.js\n")) + + // sourceMappingURL in the same line + .then(() => addScript("function foo5(){}//# sourceMappingURL=oneline-map\n")) + // sourceMappingURL without end line + .then(() => addScript("function foo6(){}//# sourceMappingURL=oneline-without-nl-map")) + // other sourceMappingURLs + .then(() => addScript("function foo7(){}\n//# sourceMappingURL=twoline-map\n")) + .then(() => addScript("function foo8(){}\n\n//# sourceMappingURL=threeline-map\n")) + + // sourceURL + sourceMappingURL + .then(() => addScript("function foo9(){}//# sourceMappingURL=source-mapping-url-map\n//# sourceURL=source-url.js")) + .then(() => addScript("function foo10(){}//# sourceURL=source-url.js\n//# sourceMappingURL=source-mapping-url-map")) + + // non zero endLine and endColumn.. + .then(() => addScript("function foo11(){}\n//# sourceURL=end1.js")) + // .. + 1 character + .then(() => addScript("function foo12(){}\n//# sourceURL=end2.js ")) + // script without sourceURL + .then(() => addScript("function foo13(){}")) + // script in eval + .then(() => addScript("function foo15(){}; eval(\"function foo14(){}//# sourceURL=eval.js\")//# sourceURL=eval-wrapper.js")) + // sourceURL and sourceMappingURL works even for script with syntax error + .then(() => addScript("}//# sourceURL=failed.js\n//# sourceMappingURL=failed-map")) + // empty lines at end + .then(() => addScript("function foo16(){}\n")) + .then(() => addScript("function foo17(){}\n\n")) + .then(() => addScript("function foo18(){}\n\n\n")) + .then(() => addScript("function foo19(){}\n\n\n\n")); +} + +Protocol.Debugger.onScriptParsed((message) => requestSourceAndDump(message, true)); +Protocol.Debugger.onScriptFailedToParse((message) => requestSourceAndDump(message, false)); +addScripts() + .then(() => Protocol.Debugger.enable()) + .then(addScripts) + .then(() => Protocol.Debugger.disable()) + .then(() => InspectorTest.log("Remove script references and re-enable debugger.")) + .then(() => Protocol.Runtime.evaluate( + { expression: "for (let i = 1; i < 20; ++i) eval(`foo${i} = undefined`);" })) + .then(() => Protocol.HeapProfiler.collectGarbage()) + .then(() => Protocol.Debugger.enable()) + .then(InspectorTest.completeTest); + +function addScript(source) { + return Protocol.Runtime.evaluate({ expression: source }); +} + +function requestSourceAndDump(scriptParsedMessage, scriptParsed) { + Protocol.Debugger.getScriptSource({ scriptId: scriptParsedMessage.params.scriptId }) + .then((sourceMessage) => dumpScriptParsed(scriptParsedMessage, sourceMessage, scriptParsed)); +} + +function dumpScriptParsed(scriptParsedMessage, sourceMessage, scriptParsed) { + var sourceResult = sourceMessage.result; + sourceResult.scriptSource = sourceResult.scriptSource.replace(/\n/g, "<nl>"); + InspectorTest.log(scriptParsed ? "scriptParsed" : "scriptFailedToParse"); + InspectorTest.logObject(sourceResult); + InspectorTest.logMessage(scriptParsedMessage.params); +}
diff --git a/src/v8/test/inspector/debugger/script-parsed-for-runtime-evaluate-expected.txt b/src/v8/test/inspector/debugger/script-parsed-for-runtime-evaluate-expected.txt new file mode 100644 index 0000000..75014e1 --- /dev/null +++ b/src/v8/test/inspector/debugger/script-parsed-for-runtime-evaluate-expected.txt
@@ -0,0 +1,266 @@ +Checks that inspector reports script compiled in Runtime.evaluate, Runtime.callFunctionOn and Runtime.compileScript +Runtime.evaluate with valid expression +{ + method : Debugger.scriptParsed + params : { + endColumn : 29 + endLine : 0 + executionContextId : <executionContextId> + hasSourceURL : true + hash : 9D04F7335D1661503EAB9AF3EACAF92020803F34 + isLiveEdit : false + isModule : false + length : 29 + scriptId : <scriptId> + sourceMapURL : + startColumn : 0 + startLine : 0 + url : evaluate.js + } +} +Runtime.evaluate with syntax error +{ + method : Debugger.scriptFailedToParse + params : { + endColumn : 39 + endLine : 0 + executionContextId : <executionContextId> + hasSourceURL : true + hash : 9BCA34A10E5386925E74C1716C857BEB02821E15 + isModule : false + length : 39 + scriptId : <scriptId> + sourceMapURL : + startColumn : 0 + startLine : 0 + url : evaluate-syntax-error.js + } +} +Runtime.callFunctionOn with valid functionDeclaration +{ + method : Debugger.scriptParsed + params : { + endColumn : 18 + endLine : 0 + executionContextId : <executionContextId> + hasSourceURL : false + hash : 9D04CEA1B54DF92A01A0498543D429DC872EBA18 + isLiveEdit : false + isModule : false + length : 18 + scriptId : <scriptId> + sourceMapURL : + startColumn : 0 + startLine : 0 + url : + } +} +Runtime.callFunctionOn with syntax error +{ + method : Debugger.scriptFailedToParse + params : { + endColumn : 3 + endLine : 0 + executionContextId : <executionContextId> + hasSourceURL : false + hash : 9D04D83251E2B7F64CB5762843D429DC872EBA18 + isModule : false + length : 3 + scriptId : <scriptId> + sourceMapURL : + startColumn : 0 + startLine : 0 + url : + } +} +Runtime.compileScript with valid expression +{ + method : Debugger.scriptParsed + params : { + endColumn : 4 + endLine : 0 + executionContextId : <executionContextId> + hasSourceURL : false + hash : 9D04F733E4E4F1BA4CB5762843D429DC872EBA18 + isLiveEdit : false + isModule : false + length : 4 + scriptId : <scriptId> + sourceMapURL : + startColumn : 0 + startLine : 0 + url : compile-script.js + } +} +Runtime.compileScript with syntax error +{ + method : Debugger.scriptFailedToParse + params : { + endColumn : 1 + endLine : 0 + executionContextId : <executionContextId> + hasSourceURL : false + hash : FF746120E4E4F1BA4CB5762843D429DC872EBA18 + isModule : false + length : 1 + scriptId : <scriptId> + sourceMapURL : + startColumn : 0 + startLine : 0 + url : compile-script-syntax-error.js + } +} +Runtime.compileScript persistScript: false (should be no script events) +Runtime.evaluate compiled script with stack trace +{ + method : Debugger.scriptParsed + params : { + endColumn : 8 + endLine : 0 + executionContextId : <executionContextId> + hasSourceURL : false + hash : A2185340E4E4F1BA4CB5762843D429DC872EBA18 + isLiveEdit : false + isModule : false + length : 8 + scriptId : <scriptId> + sourceMapURL : + startColumn : 0 + startLine : 0 + url : + } +} +{ + method : Debugger.scriptParsed + params : { + endColumn : 39 + endLine : 4 + executionContextId : <executionContextId> + hasSourceURL : true + hash : 6AF4ED72C355E471C4E94D74464A25541932A242 + isLiveEdit : false + isModule : false + length : 86 + scriptId : <scriptId> + sourceMapURL : + stackTrace : { + callFrames : [ + [0] : { + columnNumber : 2 + functionName : fooTop + lineNumber : 10 + scriptId : <scriptId> + url : top-frame.js + } + ] + } + startColumn : 0 + startLine : 0 + url : second-frame.js + } +} +{ + method : Debugger.scriptParsed + params : { + endColumn : 4 + endLine : 0 + executionContextId : <executionContextId> + hasSourceURL : false + hash : 9D04F733E4E4F1BA4CB5762843D429DC872EBA18 + isLiveEdit : false + isModule : false + length : 4 + scriptId : <scriptId> + sourceMapURL : + stackTrace : { + callFrames : [ + [0] : { + columnNumber : 6 + functionName : foo + lineNumber : 2 + scriptId : <scriptId> + url : second-frame.js + } + ] + } + startColumn : 0 + startLine : 0 + url : + } +} +Runtime.evaluate compile script error with stack trace +{ + method : Debugger.scriptParsed + params : { + endColumn : 12 + endLine : 0 + executionContextId : <executionContextId> + hasSourceURL : false + hash : A218534034AA14704CB5762843D429DC872EBA18 + isLiveEdit : false + isModule : false + length : 12 + scriptId : <scriptId> + sourceMapURL : + startColumn : 0 + startLine : 0 + url : + } +} +{ + method : Debugger.scriptParsed + params : { + endColumn : 48 + endLine : 4 + executionContextId : <executionContextId> + hasSourceURL : true + hash : 5FD5C8C38F2D44588A4078148B0BC5635152B0C0 + isLiveEdit : false + isModule : false + length : 98 + scriptId : <scriptId> + sourceMapURL : + stackTrace : { + callFrames : [ + [0] : { + columnNumber : 2 + functionName : fooTopFail + lineNumber : 20 + scriptId : <scriptId> + url : top-frame-fail.js + } + ] + } + startColumn : 0 + startLine : 0 + url : second-frame-fail.js + } +} +{ + method : Debugger.scriptFailedToParse + params : { + endColumn : 3 + endLine : 0 + executionContextId : <executionContextId> + hasSourceURL : false + hash : 9D04F7336C348CA34CB5762843D429DC872EBA18 + isModule : false + length : 3 + scriptId : <scriptId> + sourceMapURL : + stackTrace : { + callFrames : [ + [0] : { + columnNumber : 6 + functionName : fooFail + lineNumber : 2 + scriptId : <scriptId> + url : second-frame-fail.js + } + ] + } + startColumn : 0 + startLine : 0 + url : + } +}
diff --git a/src/v8/test/inspector/debugger/script-parsed-for-runtime-evaluate.js b/src/v8/test/inspector/debugger/script-parsed-for-runtime-evaluate.js new file mode 100644 index 0000000..bebf64b --- /dev/null +++ b/src/v8/test/inspector/debugger/script-parsed-for-runtime-evaluate.js
@@ -0,0 +1,79 @@ +// 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. + +let {session, contextGroup, Protocol} = InspectorTest.start("Checks that inspector reports script compiled in Runtime.evaluate, " + + "Runtime.callFunctionOn and Runtime.compileScript"); + +contextGroup.addScript(` +function fooTop() { + eval(\` + function foo() { + eval("({})") + } + foo() //# sourceURL=second-frame.js\`); +} +//# sourceURL=top-frame.js`, 8, 26); + +contextGroup.addScript(` +function fooTopFail() { + eval(\` + function fooFail() { + eval("({}") + } + fooFail() //# sourceURL=second-frame-fail.js\`); +} +//# sourceURL=top-frame-fail.js`, 18, 26); + +Promise.prototype.thenLog = function log(message) { + return this.then(() => InspectorTest.log(message)); +} + +var objectId; +Protocol.Runtime.enable(); +Protocol.Debugger.enable() + .then(() => Protocol.Debugger.onScriptParsed(InspectorTest.logMessage)) + .then(() => Protocol.Debugger.onScriptFailedToParse(InspectorTest.logMessage)) + + .thenLog('Runtime.evaluate with valid expression') + .then(() => Protocol.Runtime.evaluate({ + expression: "({})//# sourceURL=evaluate.js"})) + .then(msg => objectId = msg.result.result.objectId) + + .thenLog('Runtime.evaluate with syntax error') + .then(() => Protocol.Runtime.evaluate({ + expression: "}//# sourceURL=evaluate-syntax-error.js"})) + + .thenLog('Runtime.callFunctionOn with valid functionDeclaration') + .then(() => Protocol.Runtime.callFunctionOn({ objectId: objectId, + functionDeclaration: "function foo(){}"})) + + .thenLog('Runtime.callFunctionOn with syntax error') + .then(() => Protocol.Runtime.callFunctionOn({ objectId: objectId, + functionDeclaration: "}"})) + + .thenLog('Runtime.compileScript with valid expression') + .then(() => Protocol.Runtime.compileScript({ expression: "({})", + sourceURL: "compile-script.js", persistScript: true })) + + .thenLog('Runtime.compileScript with syntax error') + .then(() => Protocol.Runtime.compileScript({ expression: "}", + sourceURL: "compile-script-syntax-error.js", persistScript: true })) + + .thenLog('Runtime.compileScript persistScript: false (should be no script events)') + .then(() => Protocol.Runtime.compileScript({ expression: "({})", + sourceURL: "compile-script-syntax-error.js", persistScript: false })) + .then(() => Protocol.Runtime.compileScript({ expression: "}", + sourceURL: "compile-script-syntax-error.js", persistScript: false })) + + .thenLog('Runtime.evaluate compiled script with stack trace') + .then(() => Protocol.Runtime.evaluate({ + expression: "fooTop()"})) + .then(msg => objectId = msg.result.result.objectId) + + .thenLog('Runtime.evaluate compile script error with stack trace') + .then(() => Protocol.Runtime.evaluate({ + expression: "fooTopFail()"})) + .then(msg => objectId = msg.result.result.objectId) + + .then(InspectorTest.completeTest);
diff --git a/src/v8/test/inspector/debugger/script-parsed-hash-expected.txt b/src/v8/test/inspector/debugger/script-parsed-hash-expected.txt new file mode 100644 index 0000000..88cb394 --- /dev/null +++ b/src/v8/test/inspector/debugger/script-parsed-hash-expected.txt
@@ -0,0 +1,46 @@ +Tests scripts hasing +{ + endColumn : 1 + endLine : 0 + executionContextId : <executionContextId> + hasSourceURL : false + hash : 1C6D2E82E4E4F1BA4CB5762843D429DC872EBA18 + isLiveEdit : false + isModule : false + length : 1 + scriptId : <scriptId> + sourceMapURL : + startColumn : 0 + startLine : 0 + url : foo1.js +} +{ + endColumn : 3 + endLine : 0 + executionContextId : <executionContextId> + hasSourceURL : false + hash : EBF1ECD351E7A3294CB5762843D429DC872EBA18 + isLiveEdit : false + isModule : false + length : 3 + scriptId : <scriptId> + sourceMapURL : + startColumn : 0 + startLine : 0 + url : foo2.js +} +{ + endColumn : 8106 + endLine : 0 + executionContextId : <executionContextId> + hasSourceURL : false + hash : 885818413D7FC3E2220B3E367FF57CB1D1572095 + isLiveEdit : false + isModule : false + length : 8106 + scriptId : <scriptId> + sourceMapURL : + startColumn : 0 + startLine : 0 + url : foo3.js +}
diff --git a/src/v8/test/inspector/debugger/script-parsed-hash.js b/src/v8/test/inspector/debugger/script-parsed-hash.js new file mode 100644 index 0000000..05d0ed6 --- /dev/null +++ b/src/v8/test/inspector/debugger/script-parsed-hash.js
@@ -0,0 +1,29 @@ +// 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. + +let {session, contextGroup, Protocol} = + InspectorTest.start('Tests scripts hasing'); + +(async function test() { + await Protocol.Debugger.enable(); + await Protocol.Runtime.enable(); + Protocol.Runtime.compileScript({ + expression: "1", sourceURL: "foo1.js", persistScript: true}); + let {params} = await Protocol.Debugger.onceScriptParsed(); + InspectorTest.logMessage(params); + Protocol.Runtime.compileScript({ + expression: "239", sourceURL: "foo2.js", persistScript: true}); + ({params} = await Protocol.Debugger.onceScriptParsed()); + InspectorTest.logMessage(params); + var script = "var b = 1;"; + for (var i = 0; i < 2024; ++i) { + script += "++b;"; + } + Protocol.Runtime.compileScript({ + expression: script, sourceURL: "foo3.js", + persistScript: true}); + ({params} = await Protocol.Debugger.onceScriptParsed()); + InspectorTest.logMessage(params); + InspectorTest.completeTest(); +})()
diff --git a/src/v8/test/inspector/debugger/set-async-call-stack-depth-expected.txt b/src/v8/test/inspector/debugger/set-async-call-stack-depth-expected.txt new file mode 100644 index 0000000..98fcceb --- /dev/null +++ b/src/v8/test/inspector/debugger/set-async-call-stack-depth-expected.txt
@@ -0,0 +1,37 @@ +Checks that we report not more then maxDepth call chains. + +Running test: testPaused +Actual call chain length: 8 +setAsyncCallStackDepth(maxDepth): 16 +reported: 1 + +Actual call chain length: 8 +setAsyncCallStackDepth(maxDepth): 8 +reported: 1 + +Actual call chain length: 8 +setAsyncCallStackDepth(maxDepth): 7 +reported: 1 + +Actual call chain length: 8 +setAsyncCallStackDepth(maxDepth): 0 +reported: 0 + + +Running test: testConsoleTrace +Actual call chain length: 8 +setAsyncCallStackDepth(maxDepth): 16 +reported: 1 + +Actual call chain length: 8 +setAsyncCallStackDepth(maxDepth): 8 +reported: 1 + +Actual call chain length: 8 +setAsyncCallStackDepth(maxDepth): 7 +reported: 1 + +Actual call chain length: 8 +setAsyncCallStackDepth(maxDepth): 0 +reported: 0 +
diff --git a/src/v8/test/inspector/debugger/set-async-call-stack-depth.js b/src/v8/test/inspector/debugger/set-async-call-stack-depth.js new file mode 100644 index 0000000..0c7567f --- /dev/null +++ b/src/v8/test/inspector/debugger/set-async-call-stack-depth.js
@@ -0,0 +1,79 @@ +// Copyright 2017 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. + +// TODO(kozyatinskiy): fix or remove it later with new stack traces it's almost +// imposible to hit limit. +let {session, contextGroup, Protocol} = InspectorTest.start('Checks that we report not more then maxDepth call chains.'); + +contextGroup.addScript(` +function promisesChain(num) { + var p = Promise.resolve(); + for (var i = 0; i < num - 1; ++i) { + p = p.then(() => 42); + } + return p; +} +`); + +Protocol.Debugger.enable(); +InspectorTest.runAsyncTestSuite([ + async function testPaused() { + let callback = '() => { debugger; }'; + startTest({ generated: 8, limit: 16, callback}); + dumpCaptured((await Protocol.Debugger.oncePaused()).params.asyncStackTrace); + await Protocol.Debugger.resume(); + + startTest({ generated: 8, limit: 8, callback}); + dumpCaptured((await Protocol.Debugger.oncePaused()).params.asyncStackTrace); + await Protocol.Debugger.resume(); + + startTest({ generated: 8, limit: 7, callback}); + dumpCaptured((await Protocol.Debugger.oncePaused()).params.asyncStackTrace); + await Protocol.Debugger.resume(); + + startTest({ generated: 8, limit: 0, callback}); + dumpCaptured((await Protocol.Debugger.oncePaused()).params.asyncStackTrace); + await Protocol.Debugger.resume(); + }, + + async function testConsoleTrace() { + await Protocol.Runtime.enable(); + let callback = '() => { console.trace(42); }'; + startTest({ generated: 8, limit: 16, callback}); + let msg = await Protocol.Runtime.onceConsoleAPICalled(); + dumpCaptured(msg.params.stackTrace.parent); + + startTest({ generated: 8, limit: 8, callback}); + msg = await Protocol.Runtime.onceConsoleAPICalled(); + dumpCaptured(msg.params.stackTrace.parent); + + startTest({ generated: 8, limit: 7, callback}); + msg = await Protocol.Runtime.onceConsoleAPICalled(); + dumpCaptured(msg.params.stackTrace.parent); + + startTest({ generated: 8, limit: 0, callback}); + msg = await Protocol.Runtime.onceConsoleAPICalled(); + dumpCaptured(msg.params.stackTrace.parent); + + await Protocol.Runtime.disable(); + } +]); + +function startTest(params) { + InspectorTest.log('Actual call chain length: ' + params.generated); + InspectorTest.log('setAsyncCallStackDepth(maxDepth): ' + params.limit); + + Protocol.Debugger.setAsyncCallStackDepth({maxDepth: params.limit}); + Protocol.Runtime.evaluate({expression: + `promisesChain(${params.generated}).then(${params.callback})`}); +} + +function dumpCaptured(stack) { + let count = 0; + while (stack) { + ++count; + stack = stack.parent; + } + InspectorTest.log('reported: ' + count + '\n'); +}
diff --git a/src/v8/test/inspector/debugger/set-blackbox-patterns-expected.txt b/src/v8/test/inspector/debugger/set-blackbox-patterns-expected.txt new file mode 100644 index 0000000..cd1f11e --- /dev/null +++ b/src/v8/test/inspector/debugger/set-blackbox-patterns-expected.txt
@@ -0,0 +1,26 @@ +Tests blackboxing by patterns +Pattern parser error: Uncaught SyntaxError: Invalid regular expression: /(foo([)/: Unterminated character class +Paused in +(...):1 +Paused in +(...):1 +Paused in +qwe:3 +baz:3 +(...):1 +Paused in +bar:3 +foo:3 +qwe:3 +baz:3 +(...):1 +Paused in +qwe:4 +baz:3 +(...):1 +Paused in +qwe:4 +baz:3 +(...):1 +Paused in +(...):1
diff --git a/src/v8/test/inspector/debugger/set-blackbox-patterns.js b/src/v8/test/inspector/debugger/set-blackbox-patterns.js new file mode 100644 index 0000000..d060c90 --- /dev/null +++ b/src/v8/test/inspector/debugger/set-blackbox-patterns.js
@@ -0,0 +1,61 @@ +// 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. + +let {session, contextGroup, Protocol} = InspectorTest.start('Tests blackboxing by patterns'); + +contextGroup.addScript( +`function bar() +{ + return 42; +}`); + +contextGroup.addScript( +`function foo() +{ + var a = bar(); + return a + 1; +} +//# sourceURL=foo.js`); + +contextGroup.addScript( +`function qwe() +{ + var a = foo(); + return a + 1; +} +//# sourceURL=qwe.js`); + +contextGroup.addScript( +`function baz() +{ + var a = qwe(); + return a + 1; +} +//# sourceURL=baz.js`); + +Protocol.Debugger.enable(); +Protocol.Debugger.setBlackboxPatterns({ patterns: [ "foo([" ] }).then(dumpError); + +function dumpError(message) +{ + InspectorTest.log(message.error.message); + Protocol.Debugger.onPaused(dumpStackAndRunNextCommand); + Protocol.Debugger.setBlackboxPatterns({ patterns: [ "baz\.js", "foo\.js" ] }); + Protocol.Runtime.evaluate({ "expression": "debugger;baz()" }); +} + +var commands = [ "stepInto", "stepInto", "stepInto", "stepOut", "stepInto", "stepInto" ]; +function dumpStackAndRunNextCommand(message) +{ + InspectorTest.log("Paused in"); + var callFrames = message.params.callFrames; + for (var callFrame of callFrames) + InspectorTest.log((callFrame.functionName || "(...)") + ":" + (callFrame.location.lineNumber + 1)); + var command = commands.shift(); + if (!command) { + InspectorTest.completeTest(); + return; + } + Protocol.Debugger[command](); +}
diff --git a/src/v8/test/inspector/debugger/set-breakpoint-before-enabling-expected.txt b/src/v8/test/inspector/debugger/set-breakpoint-before-enabling-expected.txt new file mode 100644 index 0000000..2601734 --- /dev/null +++ b/src/v8/test/inspector/debugger/set-breakpoint-before-enabling-expected.txt
@@ -0,0 +1,7 @@ +Tests that setting breakpoint before enabling debugger produces an error +setBreakpointByUrl error: undefined +setBreakpoint error: { + "code": -32602, + "message": "Invalid parameters", + "data": "location: object expected" +}
diff --git a/src/v8/test/inspector/debugger/set-breakpoint-before-enabling.js b/src/v8/test/inspector/debugger/set-breakpoint-before-enabling.js new file mode 100644 index 0000000..84541be --- /dev/null +++ b/src/v8/test/inspector/debugger/set-breakpoint-before-enabling.js
@@ -0,0 +1,19 @@ +// 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. + +let {session, contextGroup, Protocol} = InspectorTest.start('Tests that setting breakpoint before enabling debugger produces an error'); + +Protocol.Debugger.setBreakpointByUrl({ url: "http://example.com", lineNumber: 10 }).then(didSetBreakpointByUrlBeforeEnable); + +function didSetBreakpointByUrlBeforeEnable(message) +{ + InspectorTest.log("setBreakpointByUrl error: " + JSON.stringify(message.error, null, 2)); + Protocol.Debugger.setBreakpoint().then(didSetBreakpointBeforeEnable); +} + +function didSetBreakpointBeforeEnable(message) +{ + InspectorTest.log("setBreakpoint error: " + JSON.stringify(message.error, null, 2)); + InspectorTest.completeTest(); +}
diff --git a/src/v8/test/inspector/debugger/set-script-source-2-expected.txt b/src/v8/test/inspector/debugger/set-script-source-2-expected.txt new file mode 100644 index 0000000..683381b --- /dev/null +++ b/src/v8/test/inspector/debugger/set-script-source-2-expected.txt
@@ -0,0 +1,73 @@ +Tests Debugger.setScriptSource + +Running test: addLineAfter +var x = 1; +#debugger; +return x + 2; + +--- +Break location after LiveEdit: +var x = 1; +#debugger; +var x = 3; + +stackChanged: true +Protocol.Debugger.stepInto +function foo() { +var x = #1; +debugger; + + +Running test: addLineBefore +var x = 1; +#debugger; +return x + 2; + +--- +Break location after LiveEdit: +var x = 1; +var x = #3; +debugger; + +stackChanged: true +Protocol.Debugger.stepInto +function foo() { +var x = #1; +var x = 3; + + +Running test: breakAtFirstLineAddLineAfter +function boo() { +#debugger; +var x = 1; + +--- +Break location after LiveEdit: +function boo() { +#debugger; +var x = 3; + +stackChanged: true +Protocol.Debugger.stepInto +function boo() { +#debugger; +var x = 3; + + +Running test: breakAtFirstLineAddLineBefore +function boo() { +#debugger; +var x = 1; + +--- +Break location after LiveEdit: +function boo() { +var x = #3; +debugger; + +stackChanged: true +Protocol.Debugger.stepInto +var x = 3; +#debugger; +var x = 1; +
diff --git a/src/v8/test/inspector/debugger/set-script-source-2.js b/src/v8/test/inspector/debugger/set-script-source-2.js new file mode 100644 index 0000000..053ccee --- /dev/null +++ b/src/v8/test/inspector/debugger/set-script-source-2.js
@@ -0,0 +1,97 @@ +// Copyright 2017 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. + +let {session, contextGroup, Protocol} = + InspectorTest.start('Tests Debugger.setScriptSource'); + +session.setupScriptMap(); + +function foo() { +var x = 1; +debugger; +return x + 2; +} + +function boo() { +debugger; +var x = 1; +return x + 2; +} + +InspectorTest.runAsyncTestSuite([ + async function addLineAfter() { + await Protocol.Debugger.enable(); + Protocol.Runtime.evaluate({expression: foo.toString()}); + let {params:{scriptId}} = await Protocol.Debugger.onceScriptParsed(); + Protocol.Runtime.evaluate({ + expression: 'setTimeout(foo, 0)//# sourceURL=test.js'}); + let {params:{callFrames}} = await Protocol.Debugger.oncePaused(); + await session.logSourceLocation(callFrames[0].location); + await replaceInSource(scriptId, 'debugger;', 'debugger;\nvar x = 3;'); + + Protocol.Debugger.resume(); + await Protocol.Debugger.oncePaused(); + await Protocol.Debugger.disable(); + }, + + async function addLineBefore() { + await Protocol.Debugger.enable(); + Protocol.Runtime.evaluate({expression: foo.toString()}); + let {params:{scriptId}} = await Protocol.Debugger.onceScriptParsed(); + Protocol.Runtime.evaluate({ + expression: 'setTimeout(foo, 0)//# sourceURL=test.js'}); + let {params:{callFrames}} = await Protocol.Debugger.oncePaused(); + await session.logSourceLocation(callFrames[0].location); + await replaceInSource(scriptId, 'debugger;', 'var x = 3;\ndebugger;'); + + Protocol.Debugger.resume(); + await Protocol.Debugger.oncePaused(); + await Protocol.Debugger.disable(); + }, + + async function breakAtFirstLineAddLineAfter() { + await Protocol.Debugger.enable(); + Protocol.Runtime.evaluate({expression: boo.toString()}); + let {params:{scriptId}} = await Protocol.Debugger.onceScriptParsed(); + Protocol.Runtime.evaluate({ + expression: 'setTimeout(boo, 0)//# sourceURL=test.js'}); + let {params:{callFrames}} = await Protocol.Debugger.oncePaused(); + await session.logSourceLocation(callFrames[0].location); + await replaceInSource(scriptId, 'debugger;', 'debugger;\nvar x = 3;'); + + await Protocol.Debugger.disable(); + }, + + async function breakAtFirstLineAddLineBefore() { + await Protocol.Debugger.enable(); + Protocol.Runtime.evaluate({expression: boo.toString()}); + let {params:{scriptId}} = await Protocol.Debugger.onceScriptParsed(); + Protocol.Runtime.evaluate({ + expression: 'setTimeout(boo, 0)//# sourceURL=test.js'}); + let {params:{callFrames}} = await Protocol.Debugger.oncePaused(); + await session.logSourceLocation(callFrames[0].location); + await replaceInSource(scriptId, 'debugger;', 'var x = 3;\ndebugger;'); + + await Protocol.Debugger.disable(); + } +]); + +async function replaceInSource(scriptId, oldString, newString) { + InspectorTest.log('---'); + let {result:{scriptSource}} = + await Protocol.Debugger.getScriptSource({scriptId}); + let {result} = await Protocol.Debugger.setScriptSource({ + scriptId, + scriptSource: scriptSource.replace(oldString, newString) + }); + InspectorTest.log('Break location after LiveEdit:'); + await session.logSourceLocation(result.callFrames[0].location, true); + InspectorTest.log('stackChanged: ' + result.stackChanged); + if (result.stackChanged) { + InspectorTest.log('Protocol.Debugger.stepInto'); + Protocol.Debugger.stepInto(); + var {params:{callFrames}} = await Protocol.Debugger.oncePaused(); + await session.logSourceLocation(callFrames[0].location); + } +}
diff --git a/src/v8/test/inspector/debugger/set-script-source-exception-expected.txt b/src/v8/test/inspector/debugger/set-script-source-exception-expected.txt new file mode 100644 index 0000000..376c11d --- /dev/null +++ b/src/v8/test/inspector/debugger/set-script-source-exception-expected.txt
@@ -0,0 +1,23 @@ +Check that setScriptSource completes correctly when an exception is thrown. + +Running test: testIncorrectScriptId +{ + error : { + code : -32000 + message : No script with given id found + } + id : <messageId> +} + +Running test: testSourceWithSyntaxError +{ + id : <messageId> + result : { + exceptionDetails : { + columnNumber : 2 + exceptionId : <exceptionId> + lineNumber : 0 + text : Invalid or unexpected token + } + } +}
diff --git a/src/v8/test/inspector/debugger/set-script-source-exception.js b/src/v8/test/inspector/debugger/set-script-source-exception.js new file mode 100644 index 0000000..627aa7e --- /dev/null +++ b/src/v8/test/inspector/debugger/set-script-source-exception.js
@@ -0,0 +1,23 @@ +// Copyright 2017 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. + +let {session, contextGroup, Protocol} = InspectorTest.start('Check that setScriptSource completes correctly when an exception is thrown.'); + +Protocol.Debugger.enable(); + +InspectorTest.runTestSuite([ + function testIncorrectScriptId(next) { + Protocol.Debugger.setScriptSource({ scriptId: '-1', scriptSource: '0' }) + .then(InspectorTest.logMessage) + .then(next); + }, + + function testSourceWithSyntaxError(next) { + Protocol.Debugger.onceScriptParsed() + .then(message => Protocol.Debugger.setScriptSource({ scriptId: message.params.scriptId, scriptSource: 'a # b' })) + .then(InspectorTest.logMessage) + .then(next); + contextGroup.addScript('function foo() {}'); + } +]);
diff --git a/src/v8/test/inspector/debugger/set-script-source-expected.txt b/src/v8/test/inspector/debugger/set-script-source-expected.txt new file mode 100644 index 0000000..e77aafd --- /dev/null +++ b/src/v8/test/inspector/debugger/set-script-source-expected.txt
@@ -0,0 +1,8 @@ +Tests Debugger.setScriptSource +Function evaluate: {"type":"number","value":6,"description":"6"} +PASS, result value: 6 +Function evaluate: {"type":"number","value":8,"description":"8"} +PASS, result value: 8 +Has error reported: PASS +Reported error is a compile error: PASS +PASS, result value: 1
diff --git a/src/v8/test/inspector/debugger/set-script-source.js b/src/v8/test/inspector/debugger/set-script-source.js new file mode 100644 index 0000000..f13a3a3 --- /dev/null +++ b/src/v8/test/inspector/debugger/set-script-source.js
@@ -0,0 +1,154 @@ +// 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. + +let {session, contextGroup, Protocol} = InspectorTest.start('Tests Debugger.setScriptSource'); + +contextGroup.addScript( +`function TestExpression(a, b) { + return a + b; +}`); + +// A general-purpose engine for sending a sequence of protocol commands. +// The clients provide requests and response handlers, while the engine catches +// errors and makes sure that once there's nothing to do completeTest() is called. +// @param step is an object with command, params and callback fields +function runRequestSeries(step) { + processStep(step); + + function processStep(currentStep) { + try { + processStepOrFail(currentStep); + } catch (e) { + InspectorTest.log(e.stack); + InspectorTest.completeTest(); + } + } + + function processStepOrFail(currentStep) { + if (!currentStep) { + InspectorTest.completeTest(); + return; + } + if (!currentStep.command) { + // A simple loopback step. + var next = currentStep.callback(); + processStep(next); + return; + } + + var innerCallback = function(response) { + var next; + if ("error" in response) { + if (!("errorHandler" in currentStep)) { + // Error message is not logged intentionally, it may be platform-specific. + InspectorTest.log("Protocol command '" + currentStep.command + "' failed"); + InspectorTest.completeTest(); + return; + } + try { + next = currentStep.errorHandler(response.error); + } catch (e) { + InspectorTest.log(e.stack); + InspectorTest.completeTest(); + return; + } + } else { + try { + next = currentStep.callback(response.result); + } catch (e) { + InspectorTest.log(e.stack); + InspectorTest.completeTest(); + return; + } + } + processStep(next); + } + var command = currentStep.command.split("."); + Protocol[command[0]][command[1]](currentStep.params).then(innerCallback); + } +} + +function logEqualsCheck(actual, expected) +{ + if (actual === expected) { + InspectorTest.log("PASS, result value: " + actual); + } else { + InspectorTest.log("FAIL, actual value: " + actual + ", expected: " + expected); + } +} +function logCheck(description, success) +{ + InspectorTest.log(description + ": " + (success ? "PASS" : "FAIL")); +} + +var firstStep = { callback: enableDebugger }; + +runRequestSeries(firstStep); + +function enableDebugger() { + return { command: "Debugger.enable", params: {}, callback: evalFunction }; +} + +function evalFunction(response) { + var expression = "TestExpression(2, 4)"; + return { command: "Runtime.evaluate", params: { expression: expression }, callback: callbackEvalFunction }; +} + +function callbackEvalFunction(result) { + InspectorTest.log("Function evaluate: " + JSON.stringify(result.result)); + logEqualsCheck(result.result.value, 6); + + return { command: "Runtime.evaluate", params: { expression: "TestExpression" }, callback: callbackEvalFunctionObject }; +} + +function callbackEvalFunctionObject(result) { + return { command: "Runtime.getProperties", params: { objectId: result.result.objectId }, callback: callbackFunctionDetails }; +} + +function callbackFunctionDetails(result) +{ + var scriptId; + for (var prop of result.internalProperties) { + if (prop.name === "[[FunctionLocation]]") + scriptId = prop.value.value.scriptId; + } + return createScriptManipulationArc(scriptId, null); +} + +// Several steps with scriptId in context. +function createScriptManipulationArc(scriptId, next) { + return { command: "Debugger.getScriptSource", params: { scriptId: scriptId }, callback: callbackGetScriptSource }; + + var originalText; + + function callbackGetScriptSource(result) { + originalText = result.scriptSource; + var patched = originalText.replace("a + b", "a * b"); + + return { command: "Debugger.setScriptSource", params: { scriptId: scriptId, scriptSource: patched }, callback: callbackSetScriptSource }; + } + + function callbackSetScriptSource(result) { + var expression = "TestExpression(2, 4)"; + return { command: "Runtime.evaluate", params: { expression: expression }, callback: callbackEvalFunction2 }; + } + + function callbackEvalFunction2(result) { + InspectorTest.log("Function evaluate: " + JSON.stringify(result.result)); + logEqualsCheck(result.result.value, 8); + + var patched = originalText.replace("a + b", "a # b"); + + return { command: "Debugger.setScriptSource", params: { scriptId: scriptId, scriptSource: patched }, callback: errorCallbackSetScriptSource2 }; + } + + function errorCallbackSetScriptSource2(result) { + var exceptionDetails = result.exceptionDetails; + logCheck("Has error reported", !!exceptionDetails); + logCheck("Reported error is a compile error", !!exceptionDetails); + if (exceptionDetails) + logEqualsCheck(exceptionDetails.lineNumber, 1); + return next; + } +}
diff --git a/src/v8/test/inspector/debugger/set-skip-all-pauses-expected.txt b/src/v8/test/inspector/debugger/set-skip-all-pauses-expected.txt new file mode 100644 index 0000000..1ef5fec --- /dev/null +++ b/src/v8/test/inspector/debugger/set-skip-all-pauses-expected.txt
@@ -0,0 +1,7 @@ +Tests that Debugger.setSkipAllPauses skips breaks and does not block resumed notifications +paused at: +#debugger; + +paused at: +#debugger +
diff --git a/src/v8/test/inspector/debugger/set-skip-all-pauses.js b/src/v8/test/inspector/debugger/set-skip-all-pauses.js new file mode 100644 index 0000000..c361487 --- /dev/null +++ b/src/v8/test/inspector/debugger/set-skip-all-pauses.js
@@ -0,0 +1,31 @@ +// Copyright 2017 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. + +let {session, contextGroup, Protocol} = InspectorTest.start('Tests that Debugger.setSkipAllPauses skips breaks and does not block resumed notifications'); +session.setupScriptMap(); + +(async function test() { + await Protocol.Debugger.enable(); + Protocol.Runtime.evaluate({expression: 'debugger;'}); + await waitForPause(); + await Protocol.Debugger.resume(); + + await Protocol.Debugger.setSkipAllPauses({skip: true}); + await Protocol.Runtime.evaluate({expression: 'debugger'}); + + await Protocol.Debugger.setSkipAllPauses({skip: false}); + Protocol.Runtime.evaluate({expression: 'debugger'}); + await waitForPause(); + Protocol.Debugger.setSkipAllPauses({skip: true}); + Protocol.Debugger.resume(); + await Protocol.Debugger.onceResumed(); + + InspectorTest.completeTest(); +})(); + +async function waitForPause() { + var message = await Protocol.Debugger.oncePaused(); + InspectorTest.log('paused at:'); + session.logSourceLocation(message.params.callFrames[0].location); +}
diff --git a/src/v8/test/inspector/debugger/side-effect-free-debug-evaluate-expected.txt b/src/v8/test/inspector/debugger/side-effect-free-debug-evaluate-expected.txt new file mode 100644 index 0000000..6d11386 --- /dev/null +++ b/src/v8/test/inspector/debugger/side-effect-free-debug-evaluate-expected.txt
@@ -0,0 +1,6 @@ +Tests side-effect-free evaluation +Paused on 'debugger;' +f() returns 1 +g() returns 2 +f() returns 1 +g() throws EvalError
diff --git a/src/v8/test/inspector/debugger/side-effect-free-debug-evaluate.js b/src/v8/test/inspector/debugger/side-effect-free-debug-evaluate.js new file mode 100644 index 0000000..4e7d9e9 --- /dev/null +++ b/src/v8/test/inspector/debugger/side-effect-free-debug-evaluate.js
@@ -0,0 +1,56 @@ +// Copyright 2017 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. + +let {session, contextGroup, Protocol} = InspectorTest.start('Tests side-effect-free evaluation'); + +contextGroup.addScript(` +function testFunction() +{ + var o = 0; + function f() { return 1; } + function g() { o = 2; return o; } + debugger; +} +//# sourceURL=foo.js`); + +Protocol.Debugger.enable(); + +Protocol.Debugger.oncePaused().then(debuggerPaused); + +Protocol.Runtime.evaluate({ "expression": "setTimeout(testFunction, 0)" }); + +var topFrameId; + +function debuggerPaused(messageObject) +{ + InspectorTest.log("Paused on 'debugger;'"); + + topFrameId = messageObject.params.callFrames[0].callFrameId; + Protocol.Debugger.evaluateOnCallFrame({ callFrameId: topFrameId, expression: "f()"}).then(evaluatedFirst); +} + +function evaluatedFirst(response) +{ + InspectorTest.log("f() returns " + response.result.result.value); + Protocol.Debugger.evaluateOnCallFrame({ callFrameId: topFrameId, expression: "g()"}).then(evaluatedSecond); +} + +function evaluatedSecond(response) +{ + InspectorTest.log("g() returns " + response.result.result.value); + Protocol.Debugger.evaluateOnCallFrame({ callFrameId: topFrameId, expression: "f()", throwOnSideEffect: true}).then(evaluatedThird); +} + +function evaluatedThird(response) +{ + InspectorTest.log("f() returns " + response.result.result.value); + Protocol.Debugger.evaluateOnCallFrame({ callFrameId: topFrameId, expression: "g()", throwOnSideEffect: true}).then(evaluatedFourth); + InspectorTest.completeTest(); +} + +function evaluatedFourth(response) +{ + InspectorTest.log("g() throws " + response.result.result.className); + InspectorTest.completeTest(); +}
diff --git a/src/v8/test/inspector/debugger/step-into-expected.txt b/src/v8/test/inspector/debugger/step-into-expected.txt new file mode 100644 index 0000000..30ba7e7 --- /dev/null +++ b/src/v8/test/inspector/debugger/step-into-expected.txt
@@ -0,0 +1,1024 @@ +Checks possible break locations. + +Running test: testEval +break at: +function testEval() { + #eval('// comment only'); + eval('// comment only\n'); + +break at: +// comment onl#y + +break at: + eval('// comment only'); + #eval('// comment only\n'); +} + +break at: +// comment only# + + +break at: + eval('// comment only\n'); +#} + + + +Running test: testProcedure +break at: +function testProcedure() { + #procedure(); +} + +break at: +function procedure() { + var a = #1; + var b = 2; + +break at: + var a = 1; + var b = #2; +} + +break at: + var b = 2; +#} + + +break at: + procedure(); +#} + + + +Running test: testIf +break at: + var a; + if (true) #a = true; + if (!a) { + +break at: + if (true) a = true; + #if (!a) { + a = true; + +break at: + } else { + #a = false; + } + +break at: + } + #if (returnTrue()) { + a = false; + +break at: +function returnTrue() { + #return true; +} + +break at: +function returnTrue() { + return true;# +} + +break at: + if (returnTrue()) { + #a = false; + } else { + +break at: + } +#} + + + +Running test: testEmptyFunction +break at: +function testEmptyFunction() { + #emptyFunction(); +} + +break at: + +function emptyFunction() {#} + + +break at: + emptyFunction(); +#} + + + +Running test: testCallArguments +break at: +function testCallArguments() { + #twoArguments(emptyFunction(), emptyFunction()); +} + +break at: + +function emptyFunction() {#} + + +break at: +function testCallArguments() { + twoArguments(emptyFunction(), #emptyFunction()); +} + +break at: + +function emptyFunction() {#} + + +break at: +function testCallArguments() { + #twoArguments(emptyFunction(), emptyFunction()); +} + +break at: +function twoArguments(a1, a2) { +#} + + +break at: + twoArguments(emptyFunction(), emptyFunction()); +#} + + + +Running test: testNested +break at: + } + #nested1(); +} + +break at: + } + return #nested2(); + } + +break at: + } + #nested3(); + return; + +break at: + function nested3() { + #} + nested3(); + +break at: + nested3(); + #return; + } + +break at: + nested3(); + return;# + } + +break at: + } + return nested2();# + } + +break at: + nested1(); +#} + + + +Running test: testCallAtReturn +break at: +function testCallAtReturn() { + #return returnCall(); +} + +break at: +function returnCall() { + #return return42(); +} + +break at: +function return42() { + #return 42; +} + +break at: +function return42() { + return 42;# +} + +break at: +function returnCall() { + return return42();# +} + +break at: +function testCallAtReturn() { + return returnCall();# +} + + +Running test: testWith +break at: +function testWith() { + #with (returnObject()) { + foo(); + +break at: +function returnObject() { + #return ({ foo: () => 42 }); +} + +break at: +function returnObject() { + return ({ foo: () => 42 });# +} + +break at: + with (returnObject()) { + #foo(); + } + +break at: +function returnObject() { + return ({ foo: () => #42 }); +} + +break at: +function returnObject() { + return ({ foo: () => 42# }); +} + +break at: + } + #with({}) { + return; + +break at: + with({}) { + #return; + } + +break at: + with({}) { + return;# + } + + +Running test: testForLoop +break at: +function testForLoop() { + for (var i = #0; i < 1; ++i) {} + for (var i = 0; i < 1; ++i) i; + +break at: +function testForLoop() { + for (var i = 0; i #< 1; ++i) {} + for (var i = 0; i < 1; ++i) i; + +break at: +function testForLoop() { + for (var i = 0; i < 1; ++#i) {} + for (var i = 0; i < 1; ++i) i; + +break at: +function testForLoop() { + for (var i = 0; i #< 1; ++i) {} + for (var i = 0; i < 1; ++i) i; + +break at: + for (var i = 0; i < 1; ++i) {} + for (var i = #0; i < 1; ++i) i; + for (var i = 0; i < 0; ++i) {} + +break at: + for (var i = 0; i < 1; ++i) {} + for (var i = 0; i #< 1; ++i) i; + for (var i = 0; i < 0; ++i) {} + +break at: + for (var i = 0; i < 1; ++i) {} + for (var i = 0; i < 1; ++#i) i; + for (var i = 0; i < 0; ++i) {} + +break at: + for (var i = 0; i < 1; ++i) {} + for (var i = 0; i #< 1; ++i) i; + for (var i = 0; i < 0; ++i) {} + +break at: + for (var i = 0; i < 1; ++i) i; + for (var i = #0; i < 0; ++i) {} +} + +break at: + for (var i = 0; i < 1; ++i) i; + for (var i = 0; i #< 0; ++i) {} +} + +break at: + for (var i = 0; i < 0; ++i) {} +#} + + + +Running test: testForOfLoop +break at: +function testForOfLoop() { + for (var k of #[]) {} + for (var k of [1]) k; + +break at: +function testForOfLoop() { + for (var #k of []) {} + for (var k of [1]) k; + +break at: + for (var k of []) {} + for (var k of #[1]) k; + var a = []; + +break at: + for (var k of []) {} + for (var #k of [1]) k; + var a = []; + +break at: + for (var k of []) {} + for (var k of [1]) #k; + var a = []; + +break at: + for (var k of []) {} + for (var #k of [1]) k; + var a = []; + +break at: + for (var k of [1]) k; + var a = #[]; + for (var k of a) {} + +break at: + var a = []; + for (var k of #a) {} +} + +break at: + var a = []; + for (var #k of a) {} +} + +break at: + for (var k of a) {} +#} + + + +Running test: testForInLoop +break at: +function testForInLoop() { + var o = #{}; + for (var k in o) {} + +break at: + var o = {}; + for (var k in #o) {} + for (var k in o) k; + +break at: + var o = {}; + for (var #k in o) {} + for (var k in o) k; + +break at: + for (var k in o) {} + for (var k in #o) k; + for (var k in { a:1 }) {} + +break at: + for (var k in o) {} + for (var #k in o) k; + for (var k in { a:1 }) {} + +break at: + for (var k in o) k; + for (var k in #{ a:1 }) {} + for (var k in { a:1 }) k; + +break at: + for (var k in o) k; + for (var #k in { a:1 }) {} + for (var k in { a:1 }) k; + +break at: + for (var k in { a:1 }) {} + for (var k in #{ a:1 }) k; +} + +break at: + for (var k in { a:1 }) {} + for (var #k in { a:1 }) k; +} + +break at: + for (var k in { a:1 }) {} + for (var k in { a:1 }) #k; +} + +break at: + for (var k in { a:1 }) {} + for (var #k in { a:1 }) k; +} + +break at: + for (var k in { a:1 }) k; +#} + + + +Running test: testSimpleExpressions +break at: + 1 + 2 + 3; + var a = #1; + ++a; + +break at: + var a = 1; + #++a; + a--; + +break at: + ++a; + #a--; +} + +break at: + a--; +#} + + + +Running test: testGetter +break at: +function testGetter() { + #getterFoo(); +} + +break at: +Object.defineProperty(this, 'getterFoo', { + get: () => #return42 +}); + +break at: +Object.defineProperty(this, 'getterFoo', { + get: () => return42# +}); + +break at: +function testGetter() { + #getterFoo(); +} + +break at: +function return42() { + #return 42; +} + +break at: +function return42() { + return 42;# +} + +break at: + getterFoo(); +#} + + + +Running test: testChainedCalls +break at: +function testChainedCalls() { + #obj.foo().boo()(); +} + +break at: +var obj = { + foo: () => (#{ + boo: () => return42 + +break at: + boo: () => return42 + })# +}; + +break at: +function testChainedCalls() { + obj.foo().#boo()(); +} + +break at: + foo: () => ({ + boo: () => #return42 + }) + +break at: + foo: () => ({ + boo: () => return42# + }) + +break at: +function testChainedCalls() { + obj.foo().boo()#(); +} + +break at: +function return42() { + #return 42; +} + +break at: +function return42() { + return 42;# +} + +break at: + obj.foo().boo()(); +#} + + + +Running test: testChainedWithNative +break at: +function testChainedWithNative() { + #Array.from([1]).concat([2]).map(v => v * 2); +} + +break at: +function testChainedWithNative() { + Array.from([1]).concat([2]).map(v => v #* 2); +} + +break at: +function testChainedWithNative() { + Array.from([1]).concat([2]).map(v => v * 2#); +} + +break at: +function testChainedWithNative() { + Array.from([1]).concat([2]).map(v => v #* 2); +} + +break at: +function testChainedWithNative() { + Array.from([1]).concat([2]).map(v => v * 2#); +} + +break at: + Array.from([1]).concat([2]).map(v => v * 2); +#} + + + +Running test: testPromiseThen +break at: +function testPromiseThen() { + #return Promise.resolve().then(v => v * 2).then(v => v * 2); +} + +break at: +function testPromiseThen() { + return Promise.resolve().then(v => v * 2).then(v => v * 2);# +} + + +Running test: testSwitch +break at: +function testSwitch() { + for (var i = #0; i < 3; ++i) { + switch(i) { + +break at: +function testSwitch() { + for (var i = 0; i #< 3; ++i) { + switch(i) { + +break at: + for (var i = 0; i < 3; ++i) { + #switch(i) { + case 0: continue; + +break at: + switch(i) { + case 0: #continue; + case 1: return42(); break; + +break at: +function testSwitch() { + for (var i = 0; i < 3; ++#i) { + switch(i) { + +break at: +function testSwitch() { + for (var i = 0; i #< 3; ++i) { + switch(i) { + +break at: + for (var i = 0; i < 3; ++i) { + #switch(i) { + case 0: continue; + +break at: + case 0: continue; + case 1: #return42(); break; + default: return; + +break at: +function return42() { + #return 42; +} + +break at: +function return42() { + return 42;# +} + +break at: + case 0: continue; + case 1: return42(); #break; + default: return; + +break at: +function testSwitch() { + for (var i = 0; i < 3; ++#i) { + switch(i) { + +break at: +function testSwitch() { + for (var i = 0; i #< 3; ++i) { + switch(i) { + +break at: + for (var i = 0; i < 3; ++i) { + #switch(i) { + case 0: continue; + +break at: + case 1: return42(); break; + default: #return; + } + +break at: + case 1: return42(); break; + default: return;# + } + + +Running test: testGenerator +break at: +function testGenerator() { + var gen = #idMaker(); + return42(); + +break at: +function* idMaker() { + #yield 1; + yield 2; + +break at: + gen.next().value; + #debugger; + gen.next().value; + +break at: + debugger; + gen.#next().value; + return42(); + +break at: + yield 1; + #yield 2; + yield 3; + +break at: + yield 2; + #yield 3; +} + +break at: + yield 3; +#} + + +break at: + gen.next().value; +#} + + + +Running test: testCaughtException +break at: + try { + #throwException() + } catch (e) { + +break at: +function throwException() { + #throw new Error(); +} + +break at: + } catch (e) { + #return; + } + +break at: + } catch (e) { + return;# + } + + +Running test: testClasses +break at: + } + #new Lion().speak(); +} + +break at: + constructor(name) { + #super(name); + } + +break at: + constructor(name) { + #this.name = name; + } + +break at: + this.name = name; + #} + + +break at: + super(name); + #} + + +break at: + } + new Lion().#speak(); +} + +break at: + speak() { + #super.speak(); + } + +break at: + speak() { + #} + } + +break at: + super.speak(); + #} + } + +break at: + new Lion().speak(); +#} + + + +Running test: testAsyncAwait +break at: +async function testAsyncAwait() { + #await asyncFoo(); + await awaitBoo(); + +break at: +async function asyncFoo() { + #await Promise.resolve().then(v => v * 2); + return42(); + +break at: +function return42() { + #return 42; +} + +break at: +function return42() { + return 42;# +} + +break at: +async function asyncBoo() { + #await Promise.resolve(); +} + + +Running test: testPromiseAsyncWithCode +break at: + var nextTest; + var testPromise = #new Promise(resolve => nextTest = resolve); + async function main() { + +break at: + var nextTest; + var testPromise = new Promise(resolve => nextTest #= resolve); + async function main() { + +break at: + var nextTest; + var testPromise = new Promise(resolve => nextTest = resolve#); + async function main() { + +break at: + } + #main(); + return testPromise; + +break at: + } + #setTimeout(returnCall, 0); + await foo(); + +break at: + setTimeout(returnCall, 0); + await #foo(); + await foo(); + +break at: + var resolveNested; + var p = #new Promise(resolve => resolveNested = resolve); + setTimeout(resolveNested, 0); + +break at: + var resolveNested; + var p = new Promise(resolve => resolveNested #= resolve); + setTimeout(resolveNested, 0); + +break at: + var resolveNested; + var p = new Promise(resolve => resolveNested = resolve#); + setTimeout(resolveNested, 0); + +break at: + var p = new Promise(resolve => resolveNested = resolve); + #setTimeout(resolveNested, 0); + await p; + +break at: + setTimeout(resolveNested, 0); + #await p; + } + +break at: + var resolveNested; + var p = #new Promise(resolve => resolveNested = resolve); + setTimeout(resolveNested, 0); + +break at: + var resolveNested; + var p = new Promise(resolve => resolveNested #= resolve); + setTimeout(resolveNested, 0); + +break at: + var resolveNested; + var p = new Promise(resolve => resolveNested = resolve#); + setTimeout(resolveNested, 0); + +break at: + var p = new Promise(resolve => resolveNested = resolve); + #setTimeout(resolveNested, 0); + await p; + +break at: + setTimeout(resolveNested, 0); + #await p; + } + + +Running test: testPromiseComplex +break at: + var nextTest; + var testPromise = #new Promise(resolve => nextTest = resolve); + async function main() { + +break at: + var nextTest; + var testPromise = new Promise(resolve => nextTest #= resolve); + async function main() { + +break at: + var nextTest; + var testPromise = new Promise(resolve => nextTest = resolve#); + async function main() { + +break at: + } + #main(); + return testPromise; + +break at: + } + var x = #1; + var y = 2; + +break at: + var x = 1; + var y = #2; + returnFunction(emptyFunction(), x++, --y, x => 2 * x, returnCall())().a = await foo((a => 2 *a)(5)); + +break at: + var y = 2; + #returnFunction(emptyFunction(), x++, --y, x => 2 * x, returnCall())().a = await foo((a => 2 *a)(5)); + nextTest(); + +break at: + +function emptyFunction() {#} + + +break at: + var y = 2; + returnFunction(emptyFunction(), x++, --y, x => 2 * x, #returnCall())().a = await foo((a => 2 *a)(5)); + nextTest(); + +break at: +function returnCall() { + #return return42(); +} + +break at: +function return42() { + #return 42; +} + +break at: +function return42() { + return 42;# +} + +break at: +function returnCall() { + return return42();# +} + +break at: + var y = 2; + #returnFunction(emptyFunction(), x++, --y, x => 2 * x, returnCall())().a = await foo((a => 2 *a)(5)); + nextTest(); + +break at: +function returnFunction() { + #return returnObject; +} + +break at: +function returnFunction() { + return returnObject;# +} + +break at: + var y = 2; + returnFunction(emptyFunction(), x++, --y, x => 2 * x, returnCall())#().a = await foo((a => 2 *a)(5)); + nextTest(); + +break at: +function returnObject() { + #return ({ foo: () => 42 }); +} + +break at: +function returnObject() { + return ({ foo: () => 42 });# +} + +break at: + var y = 2; + returnFunction(emptyFunction(), x++, --y, x => 2 * x, returnCall())().a = await foo((a => 2 *a)#(5)); + nextTest(); + +break at: + var y = 2; + returnFunction(emptyFunction(), x++, --y, x => 2 * x, returnCall())().a = await foo((a => 2 #*a)(5)); + nextTest(); + +break at: + var y = 2; + returnFunction(emptyFunction(), x++, --y, x => 2 * x, returnCall())().a = await foo((a => 2 *a#)(5)); + nextTest(); + +break at: + var y = 2; + returnFunction(emptyFunction(), x++, --y, x => 2 * x, returnCall())().a = await #foo((a => 2 *a)(5)); + nextTest(); + +break at: + async function foo() { + #await Promise.resolve(); + return 42; +
diff --git a/src/v8/test/inspector/debugger/step-into-nested-arrow-expected.txt b/src/v8/test/inspector/debugger/step-into-nested-arrow-expected.txt new file mode 100644 index 0000000..5061a96 --- /dev/null +++ b/src/v8/test/inspector/debugger/step-into-nested-arrow-expected.txt
@@ -0,0 +1,17 @@ +Checks that stepInto nested arrow function doesn't produce crash. +paused +(anonymous) (test.js:2:0) +(anonymous) (:0:6) +paused +rec (test.js:1:19) +(anonymous) (test.js:2:0) +(anonymous) (:0:6) +paused +rec (test.js:2:5) +(anonymous) (test.js:2:0) +(anonymous) (:0:6) +paused +(anonymous) (test.js:2:5) +(anonymous) (:0:6) +paused +(anonymous) (:0:8)
diff --git a/src/v8/test/inspector/debugger/step-into-nested-arrow.js b/src/v8/test/inspector/debugger/step-into-nested-arrow.js new file mode 100644 index 0000000..3057967 --- /dev/null +++ b/src/v8/test/inspector/debugger/step-into-nested-arrow.js
@@ -0,0 +1,23 @@ +// Copyright 2017 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. + +let {session, contextGroup, Protocol} = InspectorTest.start( + 'Checks that stepInto nested arrow function doesn\'t produce crash.'); + +session.setupScriptMap(); +contextGroup.addScript(` +const rec = (x) => (y) => +rec(); +//# sourceURL=test.js`); + +Protocol.Debugger.onPaused(message => { + InspectorTest.log("paused"); + session.logCallFrames(message.params.callFrames); + Protocol.Debugger.stepInto(); +}) + +Protocol.Debugger.enable(); +Protocol.Debugger.setBreakpointByUrl({ url: 'test.js', lineNumber: 2 }) + .then(() => Protocol.Runtime.evaluate({ expression: 'rec(5)(4)' })) + .then(InspectorTest.completeTest);
diff --git a/src/v8/test/inspector/debugger/step-into-next-script-expected.txt b/src/v8/test/inspector/debugger/step-into-next-script-expected.txt new file mode 100644 index 0000000..5fbd13e --- /dev/null +++ b/src/v8/test/inspector/debugger/step-into-next-script-expected.txt
@@ -0,0 +1,71 @@ +Debugger breaks in next script after stepOut from previous one. + +Running test: testStepOut +test (foo.js:12:2) +(anonymous) (:0:0) + +(anonymous) (:0:5) + +(anonymous) (timeout1.js:0:8) + +foo (timeout2.js:2:2) + +(anonymous) (timeout3.js:0:8) + + +Running test: testStepOver +(anonymous) (:0:0) + +test (foo.js:12:2) +(anonymous) (:0:0) + +test (foo.js:13:0) +(anonymous) (:0:0) + +(anonymous) (:0:5) + +(anonymous) (timeout1.js:0:8) + +(anonymous) (timeout1.js:0:34) + +foo (timeout2.js:2:2) + +foo (timeout2.js:2:12) + +(anonymous) (timeout3.js:0:8) + +(anonymous) (timeout3.js:0:34) + + +Running test: testStepInto +(anonymous) (:0:0) + +test (foo.js:9:2) +(anonymous) (:0:0) + +test (foo.js:10:2) +(anonymous) (:0:0) + +test (foo.js:11:2) +(anonymous) (:0:0) + +test (foo.js:12:2) +(anonymous) (:0:0) + +test (foo.js:13:0) +(anonymous) (:0:0) + +(anonymous) (:0:5) + +(anonymous) (timeout1.js:0:8) + +(anonymous) (timeout1.js:0:34) + +foo (timeout2.js:2:2) + +foo (timeout2.js:2:12) + +(anonymous) (timeout3.js:0:8) + +(anonymous) (timeout3.js:0:34) +
diff --git a/src/v8/test/inspector/debugger/step-into-next-script.js b/src/v8/test/inspector/debugger/step-into-next-script.js new file mode 100644 index 0000000..80e9a91 --- /dev/null +++ b/src/v8/test/inspector/debugger/step-into-next-script.js
@@ -0,0 +1,51 @@ +// Copyright 2017 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. + +let {session, contextGroup, Protocol} = InspectorTest.start('Debugger breaks in next script after stepOut from previous one.'); + +contextGroup.addScript(` +function test() { + setTimeout('var a = 1;//# sourceURL=timeout1.js', 0); + setTimeout(foo, 0); + setTimeout('var a = 3;//# sourceURL=timeout3.js', 0); + debugger; +} +//# sourceURL=foo.js`, 7, 26); + +contextGroup.addScript(` +function foo() { + return 42; +} +//# sourceURL=timeout2.js`) + +session.setupScriptMap(); +var stepAction; +Protocol.Debugger.onPaused(message => { + session.logCallFrames(message.params.callFrames); + InspectorTest.log(''); + Protocol.Debugger[stepAction](); +}); +Protocol.Debugger.enable() +InspectorTest.runTestSuite([ + function testStepOut(next) { + stepAction = 'stepOut'; + Protocol.Runtime.evaluate({ expression: 'test()' }) + .then(() => InspectorTest.waitForPendingTasks()) + .then(next); + }, + + function testStepOver(next) { + stepAction = 'stepOver'; + Protocol.Runtime.evaluate({ expression: 'test()' }) + .then(() => InspectorTest.waitForPendingTasks()) + .then(next); + }, + + function testStepInto(next) { + stepAction = 'stepInto'; + Protocol.Runtime.evaluate({ expression: 'test()' }) + .then(() => InspectorTest.waitForPendingTasks()) + .then(next); + } +]);
diff --git a/src/v8/test/inspector/debugger/step-into.js b/src/v8/test/inspector/debugger/step-into.js new file mode 100644 index 0000000..0c15d8a --- /dev/null +++ b/src/v8/test/inspector/debugger/step-into.js
@@ -0,0 +1,32 @@ +// Copyright 2017 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. + +let {session, contextGroup, Protocol} = InspectorTest.start('Checks possible break locations.'); + +session.setupScriptMap(); +Protocol.Debugger.onPaused(message => { + var frames = message.params.callFrames; + if (frames.length === 1) { + Protocol.Debugger.stepInto(); + return; + } + var scriptId = frames[0].location.scriptId; + InspectorTest.log('break at:'); + session.logSourceLocation(frames[0].location) + .then(() => Protocol.Debugger.stepInto()); +}); + +contextGroup.loadScript('test/inspector/debugger/resources/break-locations.js'); + +Protocol.Debugger.enable(); +Protocol.Runtime.evaluate({ expression: 'Object.keys(this).filter(name => name.indexOf(\'test\') === 0)', returnByValue: true }) + .then(runTests); + +function runTests(message) { + var tests = message.result.result.value; + InspectorTest.runTestSuite(tests.map(test => eval(`(function ${test}(next) { + Protocol.Runtime.evaluate({ expression: 'debugger; ${test}()', awaitPromise: ${test.indexOf('testPromise') === 0}}) + .then(next); + })`))); +}
diff --git a/src/v8/test/inspector/debugger/step-out-async-await-expected.txt b/src/v8/test/inspector/debugger/step-out-async-await-expected.txt new file mode 100644 index 0000000..7b58576 --- /dev/null +++ b/src/v8/test/inspector/debugger/step-out-async-await-expected.txt
@@ -0,0 +1,67 @@ +StepOut from return position of async function. + +Running test: testStepInto + p.then(() => 1); + #debugger; + return p; + + debugger; + #return p; + } + + return p; + #} + await foo(); + + await p; + p.then(() => #1); + debugger; + + +Running test: testStepOver + p.then(() => 1); + #debugger; + return p; + + debugger; + #return p; + } + + return p; + #} + await foo(); + + await p; + p.then(() => #1); + debugger; + + await p; + p.then(() => 1#); + debugger; + + await foo(); + #} + + + +Running test: testStepOut + p.then(() => 1); + #debugger; + return p; + + debugger; + #return p; + } + + return p; + #} + await foo(); + + await p; + p.then(() => #1); + debugger; + + await foo(); + #} + +
diff --git a/src/v8/test/inspector/debugger/step-out-async-await.js b/src/v8/test/inspector/debugger/step-out-async-await.js new file mode 100644 index 0000000..ff83b82 --- /dev/null +++ b/src/v8/test/inspector/debugger/step-out-async-await.js
@@ -0,0 +1,72 @@ +// Copyright 2017 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. + +// TODO(kozyatinskiy): on StepOut and probably StepNext at return position +// of async generator we should break at next instruction of resumed generator +// instead of next scheduled microtask. + +let {session, contextGroup, Protocol} = InspectorTest.start('StepOut from return position of async function.'); + +contextGroup.addScript(` + async function testFunction() { + async function foo() { + var p = Promise.resolve(); + await p; + p.then(() => 1); + debugger; + return p; + } + await foo(); + } +`); + +session.setupScriptMap(); +Protocol.Debugger.enable(); +InspectorTest.runAsyncTestSuite([ + async function testStepInto() { + Protocol.Runtime.evaluate({expression: 'testFunction()'}); + await logPauseLocation(await Protocol.Debugger.oncePaused()); + Protocol.Debugger.stepInto(); + await logPauseLocation(await Protocol.Debugger.oncePaused()); + Protocol.Debugger.stepInto(); + await logPauseLocation(await Protocol.Debugger.oncePaused()); + Protocol.Debugger.stepInto(); + await logPauseLocation(await Protocol.Debugger.oncePaused()); + Protocol.Debugger.resume(); + }, + + async function testStepOver() { + Protocol.Runtime.evaluate({expression: 'testFunction()'}); + await logPauseLocation(await Protocol.Debugger.oncePaused()); + Protocol.Debugger.stepInto(); + await logPauseLocation(await Protocol.Debugger.oncePaused()); + Protocol.Debugger.stepInto(); + await logPauseLocation(await Protocol.Debugger.oncePaused()); + Protocol.Debugger.stepOver(); + await logPauseLocation(await Protocol.Debugger.oncePaused()); + Protocol.Debugger.stepOver(); + await logPauseLocation(await Protocol.Debugger.oncePaused()); + Protocol.Debugger.stepOver(); + await logPauseLocation(await Protocol.Debugger.oncePaused()); + Protocol.Debugger.resume(); + }, + + async function testStepOut() { + Protocol.Runtime.evaluate({expression: 'testFunction()'}); + await logPauseLocation(await Protocol.Debugger.oncePaused()); + Protocol.Debugger.stepInto(); + await logPauseLocation(await Protocol.Debugger.oncePaused()); + Protocol.Debugger.stepInto(); + await logPauseLocation(await Protocol.Debugger.oncePaused()); + Protocol.Debugger.stepOut(); + await logPauseLocation(await Protocol.Debugger.oncePaused()); + Protocol.Debugger.stepOut(); + await logPauseLocation(await Protocol.Debugger.oncePaused()); + Protocol.Debugger.resume(); + }, +]); + +function logPauseLocation(message) { + return session.logSourceLocation(message.params.callFrames[0].location); +}
diff --git a/src/v8/test/inspector/debugger/step-over-another-context-group-expected.txt b/src/v8/test/inspector/debugger/step-over-another-context-group-expected.txt new file mode 100644 index 0000000..c403c15 --- /dev/null +++ b/src/v8/test/inspector/debugger/step-over-another-context-group-expected.txt
@@ -0,0 +1,7 @@ +Checks stepping with more then one context group. +paused at: +#debugger + +paused at: +setTimeout(() => #42, 0) +
diff --git a/src/v8/test/inspector/debugger/step-over-another-context-group.js b/src/v8/test/inspector/debugger/step-over-another-context-group.js new file mode 100644 index 0000000..758ff84 --- /dev/null +++ b/src/v8/test/inspector/debugger/step-over-another-context-group.js
@@ -0,0 +1,36 @@ +// Copyright 2017 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. + +InspectorTest.log('Checks stepping with more then one context group.'); + +var contextGroup1 = new InspectorTest.ContextGroup(); +var session1 = contextGroup1.connect(); +session1.setupScriptMap(); + +let contextGroup2 = new InspectorTest.ContextGroup(); +let session2 = contextGroup2.connect(); +session2.setupScriptMap(); + +(async function test() { + await session1.Protocol.Debugger.enable(); + await session2.Protocol.Debugger.enable({}); + session1.Protocol.Runtime.evaluate({expression: 'debugger'}); + session2.Protocol.Runtime.evaluate({expression: 'setTimeout(() => { debugger }, 0)'}); + session1.Protocol.Runtime.evaluate({expression: 'setTimeout(() => 42, 0)'}); + await waitPauseAndDumpLocation(session1); + session1.Protocol.Debugger.stepOver(); + await session1.Protocol.Debugger.oncePaused(); + session1.Protocol.Debugger.stepOver(); + await waitPauseAndDumpLocation(session1); + await session2.Protocol.Debugger.disable({}); + await session1.Protocol.Debugger.disable(); + InspectorTest.completeTest(); +})(); + +async function waitPauseAndDumpLocation(session) { + var message = await session.Protocol.Debugger.oncePaused(); + InspectorTest.log('paused at:'); + await session.logSourceLocation(message.params.callFrames[0].location); + return message; +}
diff --git a/src/v8/test/inspector/debugger/step-over-caught-exception-expected.txt b/src/v8/test/inspector/debugger/step-over-caught-exception-expected.txt new file mode 100644 index 0000000..5b72d4c --- /dev/null +++ b/src/v8/test/inspector/debugger/step-over-caught-exception-expected.txt
@@ -0,0 +1,5 @@ +Tests that stepping over caught exception will pause when asked for +testFunction:9 +testFunction:11 +testFunction:9 +testFunction:11
diff --git a/src/v8/test/inspector/debugger/step-over-caught-exception.js b/src/v8/test/inspector/debugger/step-over-caught-exception.js new file mode 100644 index 0000000..c8e711b --- /dev/null +++ b/src/v8/test/inspector/debugger/step-over-caught-exception.js
@@ -0,0 +1,78 @@ +// 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. + +let {session, contextGroup, Protocol} = InspectorTest.start('Tests that stepping over caught exception will pause when asked for'); + +contextGroup.addScript( +`function testFunction() +{ + function foo() + { + try { + throw new Error(); + } catch (e) { + } + } + debugger; + foo(); + console.log("completed"); +}`); + +Protocol.Debugger.enable(); +Protocol.Runtime.enable(); +step1(); + +function step1() +{ + Protocol.Runtime.evaluate({ "expression": "setTimeout(testFunction, 0);"}); + var commands = [ "Print", "stepOver", "stepOver", "Print", "resume" ]; + Protocol.Debugger.onPaused(function(messageObject) + { + var command = commands.shift(); + if (command === "Print") { + var callFrames = messageObject.params.callFrames; + for (var callFrame of callFrames) + InspectorTest.log(callFrame.functionName + ":" + callFrame.location.lineNumber); + command = commands.shift(); + } + if (command) + Protocol.Debugger[command](); + }); + + Protocol.Runtime.onConsoleAPICalled(function(messageObject) + { + if (messageObject.params.args[0].value === "completed") { + if (commands.length) + InspectorTest.log("[FAIL]: execution was resumed too earlier.") + step2(); + } + }); +} + +function step2() +{ + Protocol.Runtime.evaluate({ "expression": "setTimeout(testFunction, 0);"}); + var commands = [ "Print", "stepOver", "stepInto", "stepOver", "stepOver", "Print", "resume" ]; + Protocol.Debugger.onPaused(function(messageObject) + { + var command = commands.shift(); + if (command === "Print") { + var callFrames = messageObject.params.callFrames; + for (var callFrame of callFrames) + InspectorTest.log(callFrame.functionName + ":" + callFrame.location.lineNumber); + command = commands.shift(); + } + if (command) + Protocol.Debugger[command](); + }); + + Protocol.Runtime.onConsoleAPICalled(function(messageObject) + { + if (messageObject.params.args[0].value === "completed") { + if (commands.length) + InspectorTest.log("[FAIL]: execution was resumed too earlier.") + InspectorTest.completeTest(); + } + }); +}
diff --git a/src/v8/test/inspector/debugger/step-snapshot-expected.txt b/src/v8/test/inspector/debugger/step-snapshot-expected.txt new file mode 100644 index 0000000..911ca71 --- /dev/null +++ b/src/v8/test/inspector/debugger/step-snapshot-expected.txt
@@ -0,0 +1,35 @@ +Embedding script 'function c(f, ...args) { return f(...args); }' +Tests that stepping works on snapshotted function +paused + } + #debugger; + c(f, 2); + +paused + debugger; + #c(f, 2); +} + +paused +function c(f, ...args) { #return f(...args); } + +paused + function f(x) { + #return x * 2; + } + +paused + function f(x) { + return x * 2;# + } + +paused +function c(f, ...args) { return f(...args);# } + +paused + c(f, 2); +#} + +paused +test(#) +
diff --git a/src/v8/test/inspector/debugger/step-snapshot.js b/src/v8/test/inspector/debugger/step-snapshot.js new file mode 100644 index 0000000..a4ecbf2 --- /dev/null +++ b/src/v8/test/inspector/debugger/step-snapshot.js
@@ -0,0 +1,31 @@ +// Copyright 2017 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. + +// Embed a user function in the snapshot and step through it. + +// Flags: --embed 'function c(f, ...args) { return f(...args); }' + +let {session, contextGroup, Protocol} = InspectorTest.start('Tests that stepping works on snapshotted function'); +session.setupScriptMap(); + +contextGroup.addScript(` +function test() { + function f(x) { + return x * 2; + } + debugger; + c(f, 2); +} +//# sourceURL=test.js`); + +Protocol.Debugger.onPaused(message => { + InspectorTest.log("paused"); + var frames = message.params.callFrames; + session.logSourceLocation(frames[0].location); + Protocol.Debugger.stepInto(); +}) + +Protocol.Debugger.enable() + .then(() => Protocol.Runtime.evaluate({ expression: 'test()' })) + .then(InspectorTest.completeTest);
diff --git a/src/v8/test/inspector/debugger/stepping-after-get-possible-breakpoints-expected.txt b/src/v8/test/inspector/debugger/stepping-after-get-possible-breakpoints-expected.txt new file mode 100644 index 0000000..67f3830 --- /dev/null +++ b/src/v8/test/inspector/debugger/stepping-after-get-possible-breakpoints-expected.txt
@@ -0,0 +1,11 @@ +Tests that stepping works after calling getPossibleBreakpoints +-- call boo: +(top) +(top) +boo +(top) +-- call foo: +(top) +(top) +foo +(top)
diff --git a/src/v8/test/inspector/debugger/stepping-after-get-possible-breakpoints.js b/src/v8/test/inspector/debugger/stepping-after-get-possible-breakpoints.js new file mode 100644 index 0000000..c36a36c --- /dev/null +++ b/src/v8/test/inspector/debugger/stepping-after-get-possible-breakpoints.js
@@ -0,0 +1,28 @@ +// 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. + +let {session, contextGroup, Protocol} = InspectorTest.start('Tests that stepping works after calling getPossibleBreakpoints'); + +contextGroup.addScript(` +function boo() {} +boo(); +function foo() {} +//# sourceURL=foo.js`); + +Protocol.Debugger.onPaused((message) => { + InspectorTest.logMessage(message.params.callFrames[0].functionName || "(top)"); + Protocol.Debugger.stepInto(); +}); +var scriptId; +Protocol.Debugger.onScriptParsed(message => { + if (message.params.url === 'foo.js') + scriptId = message.params.scriptId; +}); +Protocol.Debugger.enable() + .then(() => Protocol.Debugger.getPossibleBreakpoints({start: {scriptId, lineNumber:0,columnNumber:0}})) + .then(() => InspectorTest.log('-- call boo:')) + .then(() => Protocol.Runtime.evaluate({ expression: 'debugger; boo();'})) + .then(() => InspectorTest.log('-- call foo:')) + .then(() => Protocol.Runtime.evaluate({ expression: 'debugger; foo();'})) + .then(InspectorTest.completeTest);
diff --git a/src/v8/test/inspector/debugger/stepping-and-break-program-api-expected.txt b/src/v8/test/inspector/debugger/stepping-and-break-program-api-expected.txt new file mode 100644 index 0000000..438177a --- /dev/null +++ b/src/v8/test/inspector/debugger/stepping-and-break-program-api-expected.txt
@@ -0,0 +1,19 @@ +Checks that stepping is cleared after breakProgram. +paused at: +function callBreakProgram() { + #debugger; + inspector.breakProgram('reason', ''); + +paused at: + debugger; + #inspector.breakProgram('reason', ''); +} + +paused at: + debugger; + inspector.#breakProgram('reason', ''); +} + +paused at: +#debugger; +
diff --git a/src/v8/test/inspector/debugger/stepping-and-break-program-api.js b/src/v8/test/inspector/debugger/stepping-and-break-program-api.js new file mode 100644 index 0000000..f54bad8 --- /dev/null +++ b/src/v8/test/inspector/debugger/stepping-and-break-program-api.js
@@ -0,0 +1,34 @@ +// Copyright 2017 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. + +let {session, contextGroup, Protocol} = InspectorTest.start('Checks that stepping is cleared after breakProgram.'); + +contextGroup.addScript(` +function callBreakProgram() { + debugger; + inspector.breakProgram('reason', ''); +}`); + +session.setupScriptMap(); +(async function test() { + Protocol.Debugger.enable(); + Protocol.Runtime.evaluate({expression: 'callBreakProgram();'}); + // Should break at this debugger statement, not at end of callBreakProgram. + Protocol.Runtime.evaluate({expression: 'setTimeout(\'debugger;\', 0);'}); + await waitPauseAndDumpLocation(); + Protocol.Debugger.stepOver(); + await waitPauseAndDumpLocation(); + Protocol.Debugger.stepOver(); + await waitPauseAndDumpLocation(); + Protocol.Debugger.resume(); + await waitPauseAndDumpLocation(); + InspectorTest.completeTest(); +})(); + +async function waitPauseAndDumpLocation() { + var message = await Protocol.Debugger.oncePaused(); + InspectorTest.log('paused at:'); + session.logSourceLocation(message.params.callFrames[0].location); + return message; +}
diff --git a/src/v8/test/inspector/debugger/stepping-ignores-injected-script-expected.txt b/src/v8/test/inspector/debugger/stepping-ignores-injected-script-expected.txt new file mode 100644 index 0000000..5a63493 --- /dev/null +++ b/src/v8/test/inspector/debugger/stepping-ignores-injected-script-expected.txt
@@ -0,0 +1,2 @@ +Tests that stepping ignores injected script +InjectedSciptSource was not reached
diff --git a/src/v8/test/inspector/debugger/stepping-ignores-injected-script.js b/src/v8/test/inspector/debugger/stepping-ignores-injected-script.js new file mode 100644 index 0000000..9021664 --- /dev/null +++ b/src/v8/test/inspector/debugger/stepping-ignores-injected-script.js
@@ -0,0 +1,21 @@ +// Copyright 2017 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. + +let {session, contextGroup, Protocol} = InspectorTest.start('Tests that stepping ignores injected script'); + +Protocol.Debugger.onPaused(message => { + let url = session._scriptMap.get(message.params.callFrames[0].location.scriptId).url; + if (url !== 'test.js') { + InspectorTest.log('InjectedSciptSource on stack.'); + InspectorTest.completeTest(); + } + Protocol.Debugger.stepInto(); +}); + +session.setupScriptMap(); +Protocol.Debugger.enable(); +Protocol.Debugger.pause(); +Protocol.Runtime.evaluate({expression: 'console.log(42)//# sourceURL=test.js'}) + .then(() => InspectorTest.log('InjectedSciptSource was not reached')) + .then(InspectorTest.completeTest);
diff --git a/src/v8/test/inspector/debugger/stepping-tail-call-expected.txt b/src/v8/test/inspector/debugger/stepping-tail-call-expected.txt new file mode 100644 index 0000000..95b21b4 --- /dev/null +++ b/src/v8/test/inspector/debugger/stepping-tail-call-expected.txt
@@ -0,0 +1,177 @@ +Checks stepping over tail calls. + +Running test: testStepOver +f (:2:14) +f (:3:22) +f (:3:22) +f (:3:22) +(anonymous) (:5:0) +function f(x) { + if (x == 2) #debugger; + if (x-- > 0) return f(x); + +Debugger.stepOver called +f (:3:2) +f (:3:22) +f (:3:22) +f (:3:22) +(anonymous) (:5:0) + if (x == 2) debugger; + #if (x-- > 0) return f(x); +} + +Debugger.stepOver called +f (:3:15) +f (:3:22) +f (:3:22) +f (:3:22) +(anonymous) (:5:0) + if (x == 2) debugger; + if (x-- > 0) #return f(x); +} + +Debugger.stepOver called +f (:3:27) +f (:3:22) +f (:3:22) +f (:3:22) +(anonymous) (:5:0) + if (x == 2) debugger; + if (x-- > 0) return f(x);# +} + +Debugger.stepOver called +f (:3:27) +f (:3:22) +f (:3:22) +(anonymous) (:5:0) + if (x == 2) debugger; + if (x-- > 0) return f(x);# +} + +Debugger.stepOver called +f (:3:27) +f (:3:22) +(anonymous) (:5:0) + if (x == 2) debugger; + if (x-- > 0) return f(x);# +} + +Debugger.stepOver called +f (:3:27) +(anonymous) (:5:0) + if (x == 2) debugger; + if (x-- > 0) return f(x);# +} + +Debugger.stepOver called +(anonymous) (:5:5) +} +f(5);# + + +Debugger.resume called + +Running test: testStepOut +f (:2:14) +f (:3:22) +f (:3:22) +f (:3:22) +(anonymous) (:5:0) +function f(x) { + if (x == 2) #debugger; + if (x-- > 0) return f(x); + +Debugger.stepOut called +f (:3:27) +f (:3:22) +f (:3:22) +(anonymous) (:5:0) + if (x == 2) debugger; + if (x-- > 0) return f(x);# +} + +Debugger.stepOut called +f (:3:27) +f (:3:22) +(anonymous) (:5:0) + if (x == 2) debugger; + if (x-- > 0) return f(x);# +} + +Debugger.stepOut called +f (:3:27) +(anonymous) (:5:0) + if (x == 2) debugger; + if (x-- > 0) return f(x);# +} + +Debugger.stepOut called +(anonymous) (:5:5) +} +f(5);# + + +Debugger.resume called + +Running test: testStepOutFromReturn +f (:2:14) +f (:3:22) +f (:3:22) +f (:3:22) +(anonymous) (:5:0) +function f(x) { + if (x == 2) #debugger; + if (x-- > 0) return f(x); + +Debugger.stepOver called +f (:3:2) +f (:3:22) +f (:3:22) +f (:3:22) +(anonymous) (:5:0) + if (x == 2) debugger; + #if (x-- > 0) return f(x); +} + +Debugger.stepOver called +f (:3:15) +f (:3:22) +f (:3:22) +f (:3:22) +(anonymous) (:5:0) + if (x == 2) debugger; + if (x-- > 0) #return f(x); +} + +Debugger.stepOut called +f (:3:27) +f (:3:22) +f (:3:22) +(anonymous) (:5:0) + if (x == 2) debugger; + if (x-- > 0) return f(x);# +} + +Debugger.stepOut called +f (:3:27) +f (:3:22) +(anonymous) (:5:0) + if (x == 2) debugger; + if (x-- > 0) return f(x);# +} + +Debugger.stepOut called +f (:3:27) +(anonymous) (:5:0) + if (x == 2) debugger; + if (x-- > 0) return f(x);# +} + +Debugger.stepOut called +(anonymous) (:5:5) +} +f(5);# + + +Debugger.resume called
diff --git a/src/v8/test/inspector/debugger/stepping-tail-call.js b/src/v8/test/inspector/debugger/stepping-tail-call.js new file mode 100644 index 0000000..797df7d --- /dev/null +++ b/src/v8/test/inspector/debugger/stepping-tail-call.js
@@ -0,0 +1,81 @@ +// Copyright 2017 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. + +let {session, contextGroup, Protocol} = InspectorTest.start('Checks stepping over tail calls.'); + +session.setupScriptMap(); +InspectorTest.logProtocolCommandCalls('Debugger.pause'); +InspectorTest.logProtocolCommandCalls('Debugger.stepInto'); +InspectorTest.logProtocolCommandCalls('Debugger.stepOver'); +InspectorTest.logProtocolCommandCalls('Debugger.stepOut'); +InspectorTest.logProtocolCommandCalls('Debugger.resume'); + +let source = ` +function f(x) { + if (x == 2) debugger; + if (x-- > 0) return f(x); +} +f(5); +`; + +Protocol.Debugger.enable(); +Protocol.Debugger.setBlackboxPatterns({patterns: ['framework\.js']}); +InspectorTest.runAsyncTestSuite([ + async function testStepOver() { + Protocol.Runtime.evaluate({expression: source}); + await logPauseLocation(await Protocol.Debugger.oncePaused()); + Protocol.Debugger.stepOver(); + await logPauseLocation(await Protocol.Debugger.oncePaused()); + Protocol.Debugger.stepOver(); + await logPauseLocation(await Protocol.Debugger.oncePaused()); + Protocol.Debugger.stepOver(); + await logPauseLocation(await Protocol.Debugger.oncePaused()); + Protocol.Debugger.stepOver(); + await logPauseLocation(await Protocol.Debugger.oncePaused()); + Protocol.Debugger.stepOver(); + await logPauseLocation(await Protocol.Debugger.oncePaused()); + Protocol.Debugger.stepOver(); + await logPauseLocation(await Protocol.Debugger.oncePaused()); + Protocol.Debugger.stepOver(); + await logPauseLocation(await Protocol.Debugger.oncePaused()); + await Protocol.Debugger.resume(); + }, + + async function testStepOut() { + Protocol.Runtime.evaluate({expression: source}); + await logPauseLocation(await Protocol.Debugger.oncePaused()); + Protocol.Debugger.stepOut(); + await logPauseLocation(await Protocol.Debugger.oncePaused()); + Protocol.Debugger.stepOut(); + await logPauseLocation(await Protocol.Debugger.oncePaused()); + Protocol.Debugger.stepOut(); + await logPauseLocation(await Protocol.Debugger.oncePaused()); + Protocol.Debugger.stepOut(); + await logPauseLocation(await Protocol.Debugger.oncePaused()); + await Protocol.Debugger.resume(); + }, + + async function testStepOutFromReturn() { + Protocol.Runtime.evaluate({expression: source}); + await logPauseLocation(await Protocol.Debugger.oncePaused()); + Protocol.Debugger.stepOver(); + await logPauseLocation(await Protocol.Debugger.oncePaused()); + Protocol.Debugger.stepOver(); + await logPauseLocation(await Protocol.Debugger.oncePaused()); + Protocol.Debugger.stepOut(); + await logPauseLocation(await Protocol.Debugger.oncePaused()); + Protocol.Debugger.stepOut(); + await logPauseLocation(await Protocol.Debugger.oncePaused()); + Protocol.Debugger.stepOut(); + await logPauseLocation(await Protocol.Debugger.oncePaused()); + Protocol.Debugger.stepOut(); + await logPauseLocation(await Protocol.Debugger.oncePaused()); + await Protocol.Debugger.resume(); + } +]); + +function logPauseLocation(message) { + session.logCallFrames(message.params.callFrames); + return session.logSourceLocation(message.params.callFrames[0].location); +}
diff --git a/src/v8/test/inspector/debugger/stepping-with-blackboxed-ranges-expected.txt b/src/v8/test/inspector/debugger/stepping-with-blackboxed-ranges-expected.txt new file mode 100644 index 0000000..4c7af7e --- /dev/null +++ b/src/v8/test/inspector/debugger/stepping-with-blackboxed-ranges-expected.txt
@@ -0,0 +1,56 @@ +Tests that blackboxed ranges are respected while stepping +foo: 8:4 +blackboxedBoo: 3:12 +notBlackboxedFoo: 3:12 +blackboxedFoo: 10:12 +notBlackboxedBoo: 17:12 +testFunction: 2:4 + +Try to set positions: [{"lineNumber":0,"columnNumber":0},{"lineNumber":0,"columnNumber":0}] +Input positions array is not sorted or contains duplicate values. +Try to set positions: [{"lineNumber":0,"columnNumber":1},{"lineNumber":0,"columnNumber":0}] +Input positions array is not sorted or contains duplicate values. +Try to set positions: [{"lineNumber":0,"columnNumber":-1}] +Position missing 'column' or 'column' < 0. +action: stepOut +notBlackboxedFoo: 4:4 +blackboxedFoo: 10:12 +notBlackboxedBoo: 17:12 +testFunction: 2:4 + +action: stepOut +notBlackboxedBoo: 18:4 +testFunction: 2:4 + +action: stepOut +testFunction: 3:4 + +action: stepInto +notBlackboxedBoo: 16:12 +testFunction: 3:4 + +action: stepOver +action: stepInto +notBlackboxedFoo: 2:12 +blackboxedFoo: 10:12 +notBlackboxedBoo: 17:12 +testFunction: 3:4 + +action: stepOver +action: stepInto +foo: 8:4 +blackboxedBoo: 3:12 +notBlackboxedFoo: 3:12 +blackboxedFoo: 10:12 +notBlackboxedBoo: 17:12 +testFunction: 3:4 + +action: stepOver +action: stepInto +foo: 9:15 +blackboxedBoo: 3:12 +notBlackboxedFoo: 3:12 +blackboxedFoo: 10:12 +notBlackboxedBoo: 17:12 +testFunction: 3:4 +
diff --git a/src/v8/test/inspector/debugger/stepping-with-blackboxed-ranges.js b/src/v8/test/inspector/debugger/stepping-with-blackboxed-ranges.js new file mode 100644 index 0000000..c1029a8 --- /dev/null +++ b/src/v8/test/inspector/debugger/stepping-with-blackboxed-ranges.js
@@ -0,0 +1,135 @@ +// 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. + +let {session, contextGroup, Protocol} = InspectorTest.start('Tests that blackboxed ranges are respected while stepping'); + +contextGroup.addScript( +`function blackboxedBoo() +{ + var a = 42; + var b = foo(); + return a + b; +} +//# sourceURL=blackboxed-script.js`); + +contextGroup.addScript( +`function notBlackboxedFoo() +{ + var a = 42; + var b = blackboxedBoo(); + return a + b; +} + +function blackboxedFoo() +{ + var a = 42; + var b = notBlackboxedFoo(); + return a + b; +} + +function notBlackboxedBoo() +{ + var a = 42; + var b = blackboxedFoo(); + return a + b; +} +//# sourceURL=mixed-source.js`); + +contextGroup.addScript( +`function testFunction() +{ + notBlackboxedBoo(); // for setup ranges and stepOut + notBlackboxedBoo(); // for stepIn +} + +function foo() +{ + debugger; + return 239; +}`); + +Protocol.Debugger.oncePaused().then(setBlackboxedScriptRanges); +Protocol.Debugger.enable().then(callTestFunction); + +function callTestFunction(response) +{ + Protocol.Runtime.evaluate({ expression: "setTimeout(testFunction, 0);"}); +} + +function setBlackboxedScriptRanges(response) +{ + var callFrames = response.params.callFrames; + printCallFrames(callFrames); + Protocol.Debugger.setBlackboxedRanges({ + scriptId: callFrames[1].location.scriptId, + positions: [ { lineNumber: 0, columnNumber: 0 } ] // blackbox ranges for blackboxed.js + }).then(setIncorrectRanges.bind(null, callFrames[2].location.scriptId)); +} + +var incorrectPositions = [ + [ { lineNumber: 0, columnNumber: 0 }, { lineNumber: 0, columnNumber: 0 } ], + [ { lineNumber: 0, columnNumber: 1 }, { lineNumber: 0, columnNumber: 0 } ], + [ { lineNumber: 0, columnNumber: -1 } ], +]; + +function setIncorrectRanges(scriptId, response) +{ + if (response.error) + InspectorTest.log(response.error.message); + var positions = incorrectPositions.shift(); + if (!positions) { + setMixedSourceRanges(scriptId); + return; + } + InspectorTest.log("Try to set positions: " + JSON.stringify(positions)); + Protocol.Debugger.setBlackboxedRanges({ + scriptId: scriptId, + positions: positions + }).then(setIncorrectRanges.bind(null, scriptId)); +} + +function setMixedSourceRanges(scriptId) +{ + Protocol.Debugger.onPaused(runAction); + Protocol.Debugger + .setBlackboxedRanges({ + scriptId: scriptId, + positions: [ + {lineNumber: 6, columnNumber: 0}, + {lineNumber: 14, columnNumber: 0} + ] // blackbox ranges for mixed.js + }) + .then(runAction); +} + +var actions = [ "stepOut", "print", "stepOut", "print", "stepOut", "print", + "stepInto", "print", "stepOver", "stepInto", "print", "stepOver", "stepInto", "print", + "stepOver", "stepInto", "print" ]; + +function runAction(response) +{ + var action = actions.shift(); + if (!action) { + InspectorTest.completeTest(); + return; + } + + if (action === "print") { + printCallFrames(response.params.callFrames); + runAction({}); + } else { + InspectorTest.log("action: " + action); + Protocol.Debugger[action](); + } +} + +function printCallFrames(callFrames) +{ + var topCallFrame = callFrames[0]; + if (topCallFrame.functionName.startsWith("blackboxed")) + InspectorTest.log("FAIL: blackboxed function in top call frame"); + for (var callFrame of callFrames) + InspectorTest.log(callFrame.functionName + ": " + callFrame.location.lineNumber + ":" + callFrame.location.columnNumber); + InspectorTest.log(""); +}
diff --git a/src/v8/test/inspector/debugger/stepping-with-exposed-injected-script-expected.txt b/src/v8/test/inspector/debugger/stepping-with-exposed-injected-script-expected.txt new file mode 100644 index 0000000..65c32c3 --- /dev/null +++ b/src/v8/test/inspector/debugger/stepping-with-exposed-injected-script-expected.txt
@@ -0,0 +1,2 @@ +Tests that stepping does not ignore injected script when passed a flag +InjectedSciptSource on stack.
diff --git a/src/v8/test/inspector/debugger/stepping-with-exposed-injected-script.js b/src/v8/test/inspector/debugger/stepping-with-exposed-injected-script.js new file mode 100644 index 0000000..d608137 --- /dev/null +++ b/src/v8/test/inspector/debugger/stepping-with-exposed-injected-script.js
@@ -0,0 +1,22 @@ +// Copyright 2017 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-inspector-scripts + +let {session, contextGroup, Protocol} = InspectorTest.start('Tests that stepping does not ignore injected script when passed a flag'); + +Protocol.Debugger.onPaused(message => { + let url = session._scriptMap.get(message.params.callFrames[0].location.scriptId).url; + if (url !== 'test.js') { + InspectorTest.log('InjectedSciptSource on stack.'); + InspectorTest.completeTest(); + } + Protocol.Debugger.stepInto(); +}); + +session.setupScriptMap(); +Protocol.Debugger.enable(); +Protocol.Debugger.pause(); +Protocol.Runtime.evaluate({expression: 'console.log(42)//# sourceURL=test.js'}) + .then(() => InspectorTest.log('InjectedSciptSource was not reached')) + .then(InspectorTest.completeTest);
diff --git a/src/v8/test/inspector/debugger/stepping-with-natives-and-frameworks-expected.txt b/src/v8/test/inspector/debugger/stepping-with-natives-and-frameworks-expected.txt new file mode 100644 index 0000000..ac26a16 --- /dev/null +++ b/src/v8/test/inspector/debugger/stepping-with-natives-and-frameworks-expected.txt
@@ -0,0 +1,310 @@ +Stepping with natives and frameworks. + +Running test: testNativeCodeStepOut +Debugger.pause called +#[1,2].map(v => v); + +Debugger.stepInto called +[1,2].map(v => #v); + +Debugger.stepOut called +[1,2].map(v => v)#; + +Debugger.resume called + +Running test: testNativeCodeStepOver +Debugger.pause called +#[1,2].map(v => v); + +Debugger.stepInto called +[1,2].map(v => #v); + +Debugger.stepOver called +[1,2].map(v => v#); + +Debugger.stepOver called +[1,2].map(v => #v); + +Debugger.stepOver called +[1,2].map(v => v#); + +Debugger.stepOver called +[1,2].map(v => v)#; + +Debugger.resume called + +Running test: testNativeCodeStepInto +Debugger.pause called +#[1,2].map(v => v); + +Debugger.stepInto called +[1,2].map(v => #v); + +Debugger.stepInto called +[1,2].map(v => v#); + +Debugger.stepInto called +[1,2].map(v => #v); + +Debugger.stepInto called +[1,2].map(v => v#); + +Debugger.stepInto called +[1,2].map(v => v)#; + +Debugger.resume called + +Running test: testFrameworkCodeStepInto +Debugger.pause called +#callAll(() => 1, () => 2); + +Debugger.stepInto called +callAll(() => #1, () => 2); + +Debugger.stepInto called +callAll(() => 1#, () => 2); + +Debugger.stepInto called +callAll(() => 1, () => #2); + +Debugger.stepInto called +callAll(() => 1, () => 2#); + +Debugger.stepInto called +callAll(() => 1, () => 2)#; + +Debugger.resume called + +Running test: testFrameworkCodeStepOver +Debugger.pause called +#callAll(() => 1, () => 2); + +Debugger.stepInto called +callAll(() => #1, () => 2); + +Debugger.stepOver called +callAll(() => 1#, () => 2); + +Debugger.stepOver called +callAll(() => 1, () => #2); + +Debugger.stepOver called +callAll(() => 1, () => 2#); + +Debugger.stepOver called +callAll(() => 1, () => 2)#; + +Debugger.resume called + +Running test: testFrameworkCodeStepOut +Debugger.pause called +#callAll(() => 1, () => 2); + +Debugger.stepInto called +callAll(() => #1, () => 2); + +Debugger.stepOut called +callAll(() => 1, () => #2); + +Debugger.stepOut called +callAll(() => 1, () => 2)#; + +Debugger.resume called + +Running test: testFrameworkNextCallDeeperStepOut +Debugger.pause called +#callAll(() => 1, callAll.bind(null, () => 2)); + +Debugger.stepInto called +callAll(() => #1, callAll.bind(null, () => 2)); + +Debugger.stepOut called +callAll(() => 1, callAll.bind(null, () => #2)); + +Debugger.stepOut called +callAll(() => 1, callAll.bind(null, () => 2))#; + +Debugger.resume called + +Running test: testFrameworkNextCallDeeperStepOutSameFunction +Debugger.pause called +#callAll(foo, callAll.bind(null, foo)); + +Debugger.stepInto called +foo = () => #1 + +Debugger.stepOut called +callAll(foo, callAll.bind(null, foo))#; + +Debugger.resume called + +Running test: testFrameworkNextCallDeeperStepInto +Debugger.pause called +#callAll(() => 1, callAll.bind(null, () => 2)); + +Debugger.stepInto called +callAll(() => #1, callAll.bind(null, () => 2)); + +Debugger.stepOver called +callAll(() => 1#, callAll.bind(null, () => 2)); + +Debugger.stepOver called +callAll(() => 1, callAll.bind(null, () => #2)); + +Debugger.stepOver called +callAll(() => 1, callAll.bind(null, () => 2#)); + +Debugger.stepOver called +callAll(() => 1, callAll.bind(null, () => 2))#; + +Debugger.resume called + +Running test: testFrameworkNextCallDeeperStepOver +Debugger.pause called +#callAll(() => 1, callAll.bind(null, () => 2)); + +Debugger.stepInto called +callAll(() => #1, callAll.bind(null, () => 2)); + +Debugger.stepOver called +callAll(() => 1#, callAll.bind(null, () => 2)); + +Debugger.stepOver called +callAll(() => 1, callAll.bind(null, () => #2)); + +Debugger.stepOver called +callAll(() => 1, callAll.bind(null, () => 2#)); + +Debugger.stepOver called +callAll(() => 1, callAll.bind(null, () => 2))#; + +Debugger.resume called + +Running test: testFrameworkCurrentCallDeeperStepOut +Debugger.pause called +#callAll(callAll.bind(null, () => 1), () => 2); + +Debugger.stepInto called +callAll(callAll.bind(null, () => #1), () => 2); + +Debugger.stepOut called +callAll(callAll.bind(null, () => 1), () => #2); + +Debugger.stepOut called +callAll(callAll.bind(null, () => 1), () => 2)#; + +Debugger.resume called + +Running test: testFrameworkCurrentCallDeeperStepOutSameFunction +Debugger.pause called +#callAll(callAll.bind(null, foo), foo); + +Debugger.stepInto called +foo = () => #1 + +Debugger.stepOut called +callAll(callAll.bind(null, foo), foo)#; + +Debugger.resume called + +Running test: testFrameworkCurrentCallDeeperStepOver +Debugger.pause called +#callAll(callAll.bind(null, () => 1), () => 2); + +Debugger.stepInto called +callAll(callAll.bind(null, () => #1), () => 2); + +Debugger.stepOver called +callAll(callAll.bind(null, () => 1#), () => 2); + +Debugger.stepOver called +callAll(callAll.bind(null, () => 1), () => #2); + +Debugger.stepOver called +callAll(callAll.bind(null, () => 1), () => 2#); + +Debugger.stepOver called +callAll(callAll.bind(null, () => 1), () => 2)#; + +Debugger.resume called + +Running test: testFrameworkCurrentCallDeeperStepInto +Debugger.pause called +#callAll(callAll.bind(null, () => 1), () => 2); + +Debugger.stepInto called +callAll(callAll.bind(null, () => #1), () => 2); + +Debugger.stepInto called +callAll(callAll.bind(null, () => 1#), () => 2); + +Debugger.stepInto called +callAll(callAll.bind(null, () => 1), () => #2); + +Debugger.stepInto called +callAll(callAll.bind(null, () => 1), () => 2#); + +Debugger.stepInto called +callAll(callAll.bind(null, () => 1), () => 2)#; + +Debugger.resume called + +Running test: testFrameworkStepOverMixed +Debugger.pause called +#callAll(foo, foo, () => 2); + +Debugger.stepInto called +foo = () => #1 + +Debugger.stepOver called +foo = () => 1# + +Debugger.stepOver called +foo = () => #1 + +Debugger.stepOver called +foo = () => 1# + +Debugger.stepOver called +callAll(foo, foo, () => #2); + +Debugger.stepOver called +callAll(foo, foo, () => 2#); + +Debugger.stepOver called +callAll(foo, foo, () => 2)#; + +Debugger.resume called + +Running test: testFrameworkStepOutMixed +Debugger.pause called +#callAll(foo, foo, () => 2); + +Debugger.stepInto called +foo = () => #1 + +Debugger.stepOut called +callAll(foo, foo, () => #2); + +Debugger.stepOut called +callAll(foo, foo, () => 2)#; + +Debugger.resume called + +Running test: testStepOutFrameworkSameFunctionAtReturn +Debugger.pause called +#callAll(foo, foo, () => 2); + +Debugger.stepInto called +foo = () => #1 + +Debugger.stepOver called +foo = () => 1# + +Debugger.stepOut called +callAll(foo, foo, () => #2); + +Debugger.stepOut called +callAll(foo, foo, () => 2)#; + +Debugger.resume called
diff --git a/src/v8/test/inspector/debugger/stepping-with-natives-and-frameworks.js b/src/v8/test/inspector/debugger/stepping-with-natives-and-frameworks.js new file mode 100644 index 0000000..c6648ec --- /dev/null +++ b/src/v8/test/inspector/debugger/stepping-with-natives-and-frameworks.js
@@ -0,0 +1,300 @@ +// Copyright 2017 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. + +let {session, contextGroup, Protocol} = InspectorTest.start('Stepping with natives and frameworks.'); + +contextGroup.addScript(` +function callAll() { + for (var f of arguments) + f(); +} +//# sourceURL=framework.js`); + +session.setupScriptMap(); +InspectorTest.logProtocolCommandCalls('Debugger.pause'); +InspectorTest.logProtocolCommandCalls('Debugger.stepInto'); +InspectorTest.logProtocolCommandCalls('Debugger.stepOver'); +InspectorTest.logProtocolCommandCalls('Debugger.stepOut'); +InspectorTest.logProtocolCommandCalls('Debugger.resume'); + +Protocol.Debugger.enable(); +Protocol.Debugger.setBlackboxPatterns({patterns: ['framework\.js']}); +InspectorTest.runAsyncTestSuite([ + async function testNativeCodeStepOut() { + Protocol.Debugger.pause(); + Protocol.Runtime.evaluate({expression: '[1,2].map(v => v);'}); + await logPauseLocation(await Protocol.Debugger.oncePaused()); + Protocol.Debugger.stepInto(); + await logPauseLocation(await Protocol.Debugger.oncePaused()); + Protocol.Debugger.stepOut(); + await logPauseLocation(await Protocol.Debugger.oncePaused()); + await Protocol.Debugger.resume(); + }, + + async function testNativeCodeStepOver() { + Protocol.Debugger.pause(); + Protocol.Runtime.evaluate({expression: '[1,2].map(v => v);'}); + await logPauseLocation(await Protocol.Debugger.oncePaused()); + Protocol.Debugger.stepInto(); + await logPauseLocation(await Protocol.Debugger.oncePaused()); + Protocol.Debugger.stepOver(); + await logPauseLocation(await Protocol.Debugger.oncePaused()); + Protocol.Debugger.stepOver(); + await logPauseLocation(await Protocol.Debugger.oncePaused()); + Protocol.Debugger.stepOver(); + await logPauseLocation(await Protocol.Debugger.oncePaused()); + Protocol.Debugger.stepOver(); + await logPauseLocation(await Protocol.Debugger.oncePaused()); + await Protocol.Debugger.resume(); + }, + + async function testNativeCodeStepInto() { + Protocol.Debugger.pause(); + Protocol.Runtime.evaluate({expression: '[1,2].map(v => v);'}); + await logPauseLocation(await Protocol.Debugger.oncePaused()); + Protocol.Debugger.stepInto(); + await logPauseLocation(await Protocol.Debugger.oncePaused()); + Protocol.Debugger.stepInto(); + await logPauseLocation(await Protocol.Debugger.oncePaused()); + Protocol.Debugger.stepInto(); + await logPauseLocation(await Protocol.Debugger.oncePaused()); + Protocol.Debugger.stepInto(); + await logPauseLocation(await Protocol.Debugger.oncePaused()); + Protocol.Debugger.stepInto(); + await logPauseLocation(await Protocol.Debugger.oncePaused()); + await Protocol.Debugger.resume(); + }, + + async function testFrameworkCodeStepInto() { + Protocol.Debugger.pause(); + Protocol.Runtime.evaluate({expression: 'callAll(() => 1, () => 2);'}); + await logPauseLocation(await Protocol.Debugger.oncePaused()); + Protocol.Debugger.stepInto(); + await logPauseLocation(await Protocol.Debugger.oncePaused()); + Protocol.Debugger.stepInto(); + await logPauseLocation(await Protocol.Debugger.oncePaused()); + Protocol.Debugger.stepInto(); + await logPauseLocation(await Protocol.Debugger.oncePaused()); + Protocol.Debugger.stepInto(); + await logPauseLocation(await Protocol.Debugger.oncePaused()); + Protocol.Debugger.stepInto(); + await logPauseLocation(await Protocol.Debugger.oncePaused()); + await Protocol.Debugger.resume(); + }, + + async function testFrameworkCodeStepOver() { + Protocol.Debugger.pause(); + Protocol.Runtime.evaluate({expression: 'callAll(() => 1, () => 2);'}); + await logPauseLocation(await Protocol.Debugger.oncePaused()); + Protocol.Debugger.stepInto(); + await logPauseLocation(await Protocol.Debugger.oncePaused()); + Protocol.Debugger.stepOver(); + await logPauseLocation(await Protocol.Debugger.oncePaused()); + Protocol.Debugger.stepOver(); + await logPauseLocation(await Protocol.Debugger.oncePaused()); + Protocol.Debugger.stepOver(); + await logPauseLocation(await Protocol.Debugger.oncePaused()); + Protocol.Debugger.stepOver(); + await logPauseLocation(await Protocol.Debugger.oncePaused()); + await Protocol.Debugger.resume(); + }, + + async function testFrameworkCodeStepOut() { + Protocol.Debugger.pause(); + Protocol.Runtime.evaluate({expression: 'callAll(() => 1, () => 2);'}); + await logPauseLocation(await Protocol.Debugger.oncePaused()); + Protocol.Debugger.stepInto(); + await logPauseLocation(await Protocol.Debugger.oncePaused()); + Protocol.Debugger.stepOut(); + await logPauseLocation(await Protocol.Debugger.oncePaused()); + Protocol.Debugger.stepOut(); + await logPauseLocation(await Protocol.Debugger.oncePaused()); + await Protocol.Debugger.resume(); + }, + + async function testFrameworkNextCallDeeperStepOut() { + Protocol.Debugger.pause(); + Protocol.Runtime.evaluate({ + expression: 'callAll(() => 1, callAll.bind(null, () => 2));'}); + await logPauseLocation(await Protocol.Debugger.oncePaused()); + Protocol.Debugger.stepInto(); + await logPauseLocation(await Protocol.Debugger.oncePaused()); + Protocol.Debugger.stepOut(); + await logPauseLocation(await Protocol.Debugger.oncePaused()); + Protocol.Debugger.stepOut(); + await logPauseLocation(await Protocol.Debugger.oncePaused()); + await Protocol.Debugger.resume(); + }, + + async function testFrameworkNextCallDeeperStepOutSameFunction() { + await Protocol.Runtime.evaluate({expression: 'foo = () => 1'}); + Protocol.Debugger.pause(); + Protocol.Runtime.evaluate({ + expression: 'callAll(foo, callAll.bind(null, foo));'}); + await logPauseLocation(await Protocol.Debugger.oncePaused()); + Protocol.Debugger.stepInto(); + await logPauseLocation(await Protocol.Debugger.oncePaused()); + Protocol.Debugger.stepOut(); + await logPauseLocation(await Protocol.Debugger.oncePaused()); + await Protocol.Debugger.resume(); + }, + + async function testFrameworkNextCallDeeperStepInto() { + Protocol.Debugger.pause(); + Protocol.Runtime.evaluate({ + expression: 'callAll(() => 1, callAll.bind(null, () => 2));'}); + await logPauseLocation(await Protocol.Debugger.oncePaused()); + Protocol.Debugger.stepInto(); + await logPauseLocation(await Protocol.Debugger.oncePaused()); + Protocol.Debugger.stepOver(); + await logPauseLocation(await Protocol.Debugger.oncePaused()); + Protocol.Debugger.stepOver(); + await logPauseLocation(await Protocol.Debugger.oncePaused()); + Protocol.Debugger.stepOver(); + await logPauseLocation(await Protocol.Debugger.oncePaused()); + Protocol.Debugger.stepOver(); + await logPauseLocation(await Protocol.Debugger.oncePaused()); + await Protocol.Debugger.resume(); + }, + + async function testFrameworkNextCallDeeperStepOver() { + Protocol.Debugger.pause(); + Protocol.Runtime.evaluate({ + expression: 'callAll(() => 1, callAll.bind(null, () => 2));'}); + await logPauseLocation(await Protocol.Debugger.oncePaused()); + Protocol.Debugger.stepInto(); + await logPauseLocation(await Protocol.Debugger.oncePaused()); + Protocol.Debugger.stepOver(); + await logPauseLocation(await Protocol.Debugger.oncePaused()); + Protocol.Debugger.stepOver(); + await logPauseLocation(await Protocol.Debugger.oncePaused()); + Protocol.Debugger.stepOver(); + await logPauseLocation(await Protocol.Debugger.oncePaused()); + Protocol.Debugger.stepOver(); + await logPauseLocation(await Protocol.Debugger.oncePaused()); + await Protocol.Debugger.resume(); + }, + + async function testFrameworkCurrentCallDeeperStepOut() { + Protocol.Debugger.pause(); + Protocol.Runtime.evaluate({ + expression: 'callAll(callAll.bind(null, () => 1), () => 2);'}); + await logPauseLocation(await Protocol.Debugger.oncePaused()); + Protocol.Debugger.stepInto(); + await logPauseLocation(await Protocol.Debugger.oncePaused()); + Protocol.Debugger.stepOut(); + await logPauseLocation(await Protocol.Debugger.oncePaused()); + Protocol.Debugger.stepOut(); + await logPauseLocation(await Protocol.Debugger.oncePaused()); + await Protocol.Debugger.resume(); + }, + + async function testFrameworkCurrentCallDeeperStepOutSameFunction() { + await Protocol.Runtime.evaluate({expression: 'foo = () => 1'}); + Protocol.Debugger.pause(); + Protocol.Runtime.evaluate({ + expression: 'callAll(callAll.bind(null, foo), foo);'}); + await logPauseLocation(await Protocol.Debugger.oncePaused()); + Protocol.Debugger.stepInto(); + await logPauseLocation(await Protocol.Debugger.oncePaused()); + Protocol.Debugger.stepOut(); + await logPauseLocation(await Protocol.Debugger.oncePaused()); + await Protocol.Debugger.resume(); + }, + + async function testFrameworkCurrentCallDeeperStepOver() { + Protocol.Debugger.pause(); + Protocol.Runtime.evaluate({ + expression: 'callAll(callAll.bind(null, () => 1), () => 2);'}); + await logPauseLocation(await Protocol.Debugger.oncePaused()); + Protocol.Debugger.stepInto(); + await logPauseLocation(await Protocol.Debugger.oncePaused()); + Protocol.Debugger.stepOver(); + await logPauseLocation(await Protocol.Debugger.oncePaused()); + Protocol.Debugger.stepOver(); + await logPauseLocation(await Protocol.Debugger.oncePaused()); + Protocol.Debugger.stepOver(); + await logPauseLocation(await Protocol.Debugger.oncePaused()); + Protocol.Debugger.stepOver(); + await logPauseLocation(await Protocol.Debugger.oncePaused()); + await Protocol.Debugger.resume(); + }, + + async function testFrameworkCurrentCallDeeperStepInto() { + Protocol.Debugger.pause(); + Protocol.Runtime.evaluate({ + expression: 'callAll(callAll.bind(null, () => 1), () => 2);'}); + await logPauseLocation(await Protocol.Debugger.oncePaused()); + Protocol.Debugger.stepInto(); + await logPauseLocation(await Protocol.Debugger.oncePaused()); + Protocol.Debugger.stepInto(); + await logPauseLocation(await Protocol.Debugger.oncePaused()); + Protocol.Debugger.stepInto(); + await logPauseLocation(await Protocol.Debugger.oncePaused()); + Protocol.Debugger.stepInto(); + await logPauseLocation(await Protocol.Debugger.oncePaused()); + Protocol.Debugger.stepInto(); + await logPauseLocation(await Protocol.Debugger.oncePaused()); + await Protocol.Debugger.resume(); + }, + + async function testFrameworkStepOverMixed() { + await Protocol.Runtime.evaluate({expression: 'foo = () => 1'}); + Protocol.Debugger.pause(); + Protocol.Runtime.evaluate({ + expression: 'callAll(foo, foo, () => 2);'}); + await logPauseLocation(await Protocol.Debugger.oncePaused()); + Protocol.Debugger.stepInto(); + await logPauseLocation(await Protocol.Debugger.oncePaused()); + Protocol.Debugger.stepOver(); + await logPauseLocation(await Protocol.Debugger.oncePaused()); + Protocol.Debugger.stepOver(); + await logPauseLocation(await Protocol.Debugger.oncePaused()); + Protocol.Debugger.stepOver(); + await logPauseLocation(await Protocol.Debugger.oncePaused()); + Protocol.Debugger.stepOver(); + await logPauseLocation(await Protocol.Debugger.oncePaused()); + Protocol.Debugger.stepOver(); + await logPauseLocation(await Protocol.Debugger.oncePaused()); + Protocol.Debugger.stepOver(); + await logPauseLocation(await Protocol.Debugger.oncePaused()); + await Protocol.Debugger.resume(); + }, + + async function testFrameworkStepOutMixed() { + await Protocol.Runtime.evaluate({expression: 'foo = () => 1'}); + Protocol.Debugger.pause(); + Protocol.Runtime.evaluate({ + expression: 'callAll(foo, foo, () => 2);'}); + await logPauseLocation(await Protocol.Debugger.oncePaused()); + Protocol.Debugger.stepInto(); + await logPauseLocation(await Protocol.Debugger.oncePaused()); + Protocol.Debugger.stepOut(); + await logPauseLocation(await Protocol.Debugger.oncePaused()); + Protocol.Debugger.stepOut(); + await logPauseLocation(await Protocol.Debugger.oncePaused()); + await Protocol.Debugger.resume(); + }, + + async function testStepOutFrameworkSameFunctionAtReturn() { + await Protocol.Runtime.evaluate({expression: 'foo = () => 1'}); + Protocol.Debugger.pause(); + Protocol.Runtime.evaluate({ + expression: 'callAll(foo, foo, () => 2);'}); + await logPauseLocation(await Protocol.Debugger.oncePaused()); + Protocol.Debugger.stepInto(); + await logPauseLocation(await Protocol.Debugger.oncePaused()); + Protocol.Debugger.stepOver(); + await logPauseLocation(await Protocol.Debugger.oncePaused()); + Protocol.Debugger.stepOut(); + await logPauseLocation(await Protocol.Debugger.oncePaused()); + Protocol.Debugger.stepOut(); + await logPauseLocation(await Protocol.Debugger.oncePaused()); + await Protocol.Debugger.resume(); + } +]); + +function logPauseLocation(message) { + return session.logSourceLocation(message.params.callFrames[0].location); +}
diff --git a/src/v8/test/inspector/debugger/suspended-generator-scopes-expected.txt b/src/v8/test/inspector/debugger/suspended-generator-scopes-expected.txt new file mode 100644 index 0000000..57dc2aa --- /dev/null +++ b/src/v8/test/inspector/debugger/suspended-generator-scopes-expected.txt
@@ -0,0 +1,55 @@ +Tests that suspended generators produce scopes + +Running test: testScopesPaused +[ + [0] : { + configurable : true + enumerable : true + isOwn : true + name : b + value : { + description : 42 + type : number + value : 42 + } + writable : true + } + [1] : { + configurable : true + enumerable : true + isOwn : true + name : a + value : { + description : 420 + type : number + value : 420 + } + writable : true + } +] + +Running test: testScopesNonPaused +[ + [0] : { + configurable : true + enumerable : true + isOwn : true + name : b + value : { + type : undefined + } + writable : true + } + [1] : { + configurable : true + enumerable : true + isOwn : true + name : a + value : { + description : 430 + type : number + value : 430 + } + writable : true + } +]
diff --git a/src/v8/test/inspector/debugger/suspended-generator-scopes.js b/src/v8/test/inspector/debugger/suspended-generator-scopes.js new file mode 100644 index 0000000..55a1fd5 --- /dev/null +++ b/src/v8/test/inspector/debugger/suspended-generator-scopes.js
@@ -0,0 +1,69 @@ +// 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. + +let {session, contextGroup, Protocol} = InspectorTest.start('Tests that suspended generators produce scopes'); + +contextGroup.addScript(` +function *gen(a) { + var b = 42; + yield a; + return b; +} + +function testSuspendedGenerator() { + var g = gen(420); + g.next(); + debugger; + return g; +}`); + +InspectorTest.runAsyncTestSuite([ + async function testScopesPaused() { + Protocol.Debugger.enable(); + Protocol.Runtime.evaluate({expression: 'testSuspendedGenerator()'}); + let {params:{callFrames:[callFrame]}} = await Protocol.Debugger.oncePaused(); + // Current local scope. + let localScope = callFrame.scopeChain.find(scope => scope.type === 'local'); + let variables = (await Protocol.Runtime.getProperties({ + objectId: localScope.object.objectId + })).result.result; + let genObjectId = + variables.find(variable => variable.name === 'g').value.objectId; + let {result:{internalProperties}} = await Protocol.Runtime.getProperties({ + objectId: genObjectId + }); + // Generator [[Scopes]]. + let scopes = internalProperties.find(prop => prop.name === '[[Scopes]]'); + let {result:{result}} = await Protocol.Runtime.getProperties({ + objectId: scopes.value.objectId + }); + // Locals from generator. + let scope = result.find(scope => scope.value.description === 'Local (gen)'); + ({result:{result}} = await Protocol.Runtime.getProperties({ + objectId: scope.value.objectId + })); + InspectorTest.logMessage(result); + await Protocol.Debugger.disable(); + }, + + async function testScopesNonPaused() { + let {result:{result:{objectId}}} = await Protocol.Runtime.evaluate({ + expression: 'gen(430)' + }); + let {result:{internalProperties}} = await Protocol.Runtime.getProperties({ + objectId + }); + // Generator [[Scopes]]. + let scopes = internalProperties.find(prop => prop.name === '[[Scopes]]'); + let {result:{result}} = await Protocol.Runtime.getProperties({ + objectId: scopes.value.objectId + }); + // Locals from generator. + let scope = result.find(scope => scope.value.description === 'Local (gen)'); + ({result:{result}} = await Protocol.Runtime.getProperties({ + objectId: scope.value.objectId + })); + InspectorTest.logMessage(result); + } +]);
diff --git a/src/v8/test/inspector/debugger/update-call-frame-scopes-expected.txt b/src/v8/test/inspector/debugger/update-call-frame-scopes-expected.txt new file mode 100644 index 0000000..acad9ce --- /dev/null +++ b/src/v8/test/inspector/debugger/update-call-frame-scopes-expected.txt
@@ -0,0 +1,7 @@ +Tests updating call frame scopes +Paused on 'debugger;' +Variable value changed +Stacktrace re-read again +Scope variables downloaded anew +New variable is 55, expected is 55, old was: 2 +SUCCESS
diff --git a/src/v8/test/inspector/debugger/update-call-frame-scopes.js b/src/v8/test/inspector/debugger/update-call-frame-scopes.js new file mode 100644 index 0000000..e0b7307 --- /dev/null +++ b/src/v8/test/inspector/debugger/update-call-frame-scopes.js
@@ -0,0 +1,65 @@ +// 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. + +let {session, contextGroup, Protocol} = InspectorTest.start('Tests updating call frame scopes'); + +contextGroup.addScript( +`function TestFunction() +{ + var a = 2; + debugger; + debugger; +}`); + +var newVariableValue = 55; + +Protocol.Debugger.enable(); + +Protocol.Debugger.oncePaused().then(handleDebuggerPaused); + +Protocol.Runtime.evaluate({ "expression": "setTimeout(TestFunction, 0)" }); + +function handleDebuggerPaused(messageObject) +{ + InspectorTest.log("Paused on 'debugger;'"); + + var topFrame = messageObject.params.callFrames[0]; + var topFrameId = topFrame.callFrameId; + Protocol.Debugger.evaluateOnCallFrame({ "callFrameId": topFrameId, "expression": "a = " + newVariableValue }).then(callbackChangeValue); +} + +function callbackChangeValue(response) +{ + InspectorTest.log("Variable value changed"); + Protocol.Debugger.oncePaused().then(callbackGetBacktrace); + Protocol.Debugger.resume(); +} + +function callbackGetBacktrace(response) +{ + InspectorTest.log("Stacktrace re-read again"); + var localScope = response.params.callFrames[0].scopeChain[0]; + Protocol.Runtime.getProperties({ "objectId": localScope.object.objectId }).then(callbackGetProperties); +} + +function callbackGetProperties(response) +{ + InspectorTest.log("Scope variables downloaded anew"); + var varNamedA; + var propertyList = response.result.result; + for (var i = 0; i < propertyList.length; i++) { + if (propertyList[i].name === "a") { + varNamedA = propertyList[i]; + break; + } + } + if (varNamedA) { + var actualValue = varNamedA.value.value; + InspectorTest.log("New variable is " + actualValue + ", expected is " + newVariableValue + ", old was: 2"); + InspectorTest.log(actualValue === newVariableValue ? "SUCCESS" : "FAIL"); + } else { + InspectorTest.log("Failed to find variable in scope"); + } + InspectorTest.completeTest(); +}
diff --git a/src/v8/test/inspector/debugger/wasm-get-breakable-locations-expected.txt b/src/v8/test/inspector/debugger/wasm-get-breakable-locations-expected.txt new file mode 100644 index 0000000..96c7a64 --- /dev/null +++ b/src/v8/test/inspector/debugger/wasm-get-breakable-locations-expected.txt
@@ -0,0 +1,88 @@ +Tests breakable locations in wasm +Running testFunction... +Script nr 0 parsed. URL: v8://test/setup +Script nr 1 parsed. URL: v8://test/runTestFunction +Script nr 2 parsed. URL: wasm://wasm/wasm-354ada0e/wasm-354ada0e-0 +This is a wasm script (nr 0). +Script nr 3 parsed. URL: wasm://wasm/wasm-354ada0e/wasm-354ada0e-1 +This is a wasm script (nr 1). +Querying breakable locations for all wasm scripts now... +Requesting all breakable locations in wasm script 0 +4 breakable location(s): +[0] 2:2 || >nop +[1] 3:2 || >i32.const 12 +[2] 4:2 || >set_local 0 +[3] 5:0 || >end +Requesting breakable locations in lines [0,3) +1 breakable location(s): +[0] 2:2 || >nop +Requesting breakable locations in lines [4,6) +2 breakable location(s): +[0] 4:2 || >set_local 0 +[1] 5:0 || >end +Requesting all breakable locations in wasm script 1 +7 breakable location(s): +[0] 1:2 || >get_local 0 +[1] 2:2 || >if +[2] 3:4 || >block +[3] 4:6 || >call 0 +[4] 5:4 || >end +[5] 6:2 || >end +[6] 7:0 || >end +Requesting breakable locations in lines [0,3) +2 breakable location(s): +[0] 1:2 || >get_local 0 +[1] 2:2 || >if +Requesting breakable locations in lines [4,6) +2 breakable location(s): +[0] 4:6 || >call 0 +[1] 5:4 || >end +Setting a breakpoint on each breakable location... +Setting at wasm://wasm/wasm-354ada0e/wasm-354ada0e-0:2:2 +Success! +Setting at wasm://wasm/wasm-354ada0e/wasm-354ada0e-0:3:2 +Success! +Setting at wasm://wasm/wasm-354ada0e/wasm-354ada0e-0:4:2 +Success! +Setting at wasm://wasm/wasm-354ada0e/wasm-354ada0e-0:5:0 +Success! +Setting at wasm://wasm/wasm-354ada0e/wasm-354ada0e-1:1:2 +Success! +Setting at wasm://wasm/wasm-354ada0e/wasm-354ada0e-1:2:2 +Success! +Setting at wasm://wasm/wasm-354ada0e/wasm-354ada0e-1:3:4 +Success! +Setting at wasm://wasm/wasm-354ada0e/wasm-354ada0e-1:4:6 +Success! +Setting at wasm://wasm/wasm-354ada0e/wasm-354ada0e-1:5:4 +Success! +Setting at wasm://wasm/wasm-354ada0e/wasm-354ada0e-1:6:2 +Success! +Setting at wasm://wasm/wasm-354ada0e/wasm-354ada0e-1:7:0 +Success! +Running wasm code... +Missing breakpoints: 11 +Script nr 4 parsed. URL: v8://test/runWasm +Stopped at wasm://wasm/wasm-354ada0e/wasm-354ada0e-1:1:2 +Missing breakpoints: 10 +Stopped at wasm://wasm/wasm-354ada0e/wasm-354ada0e-1:2:2 +Missing breakpoints: 9 +Stopped at wasm://wasm/wasm-354ada0e/wasm-354ada0e-1:3:4 +Missing breakpoints: 8 +Stopped at wasm://wasm/wasm-354ada0e/wasm-354ada0e-1:4:6 +Missing breakpoints: 7 +Stopped at wasm://wasm/wasm-354ada0e/wasm-354ada0e-0:2:2 +Missing breakpoints: 6 +Stopped at wasm://wasm/wasm-354ada0e/wasm-354ada0e-0:3:2 +Missing breakpoints: 5 +Stopped at wasm://wasm/wasm-354ada0e/wasm-354ada0e-0:4:2 +Missing breakpoints: 4 +Stopped at wasm://wasm/wasm-354ada0e/wasm-354ada0e-0:5:0 +Missing breakpoints: 3 +Stopped at wasm://wasm/wasm-354ada0e/wasm-354ada0e-1:5:4 +Missing breakpoints: 2 +Stopped at wasm://wasm/wasm-354ada0e/wasm-354ada0e-1:6:2 +Missing breakpoints: 1 +Stopped at wasm://wasm/wasm-354ada0e/wasm-354ada0e-1:7:0 +Missing breakpoints: 0 +Finished!
diff --git a/src/v8/test/inspector/debugger/wasm-get-breakable-locations.js b/src/v8/test/inspector/debugger/wasm-get-breakable-locations.js new file mode 100644 index 0000000..ea2a116 --- /dev/null +++ b/src/v8/test/inspector/debugger/wasm-get-breakable-locations.js
@@ -0,0 +1,210 @@ +// 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 + +let {session, contextGroup, Protocol} = InspectorTest.start('Tests breakable locations in wasm'); + +utils.load('test/mjsunit/wasm/wasm-constants.js'); +utils.load('test/mjsunit/wasm/wasm-module-builder.js'); + +var builder = new WasmModuleBuilder(); + +// clang-format off +var func_idx = builder.addFunction('helper', kSig_v_v) + .addLocals({i32_count: 1}) + .addBody([ + kExprNop, + kExprI32Const, 12, + kExprSetLocal, 0, + ]).index; + +builder.addFunction('main', kSig_v_i) + .addBody([ + kExprGetLocal, 0, + kExprIf, kWasmStmt, + kExprBlock, kWasmStmt, + kExprCallFunction, func_idx, + kExprEnd, + kExprEnd + ]).exportAs('main'); +// clang-format on + +var module_bytes = builder.toArray(); + +function testFunction(bytes) { + var buffer = new ArrayBuffer(bytes.length); + var view = new Uint8Array(buffer); + for (var i = 0; i < bytes.length; i++) { + view[i] = bytes[i] | 0; + } + + var module = new WebAssembly.Module(buffer); + // Set global variable. + instance = new WebAssembly.Instance(module); +} + +var evalWithUrl = (code, url) => Protocol.Runtime.evaluate( + {'expression': code + '\n//# sourceURL=v8://test/' + url}); + +var setupCode = testFunction.toString() + ';\nvar module_bytes = ' + + JSON.stringify(module_bytes) + ';\nvar instance;'; + +Protocol.Debugger.enable(); +Protocol.Debugger.onScriptParsed(handleScriptParsed); +InspectorTest.log('Running testFunction...'); +evalWithUrl(setupCode, 'setup') + .then(() => evalWithUrl('testFunction(module_bytes)', 'runTestFunction')) + .then(getBreakableLocationsForAllWasmScripts) + .then(setAllBreakableLocations) + .then(() => InspectorTest.log('Running wasm code...')) + .then(() => (evalWithUrl('instance.exports.main(1)', 'runWasm'), 0)) + .then(waitForAllPauses) + .then(() => InspectorTest.log('Finished!')) + .then(InspectorTest.completeTest); + +var allBreakableLocations = []; + +var urls = {}; +var numScripts = 0; +var wasmScripts = []; +function handleScriptParsed(messageObject) { + var scriptId = messageObject.params.scriptId; + var url = messageObject.params.url; + urls[scriptId] = url; + InspectorTest.log('Script nr ' + numScripts + ' parsed. URL: ' + url); + ++numScripts; + + if (url.startsWith('wasm://')) { + InspectorTest.log('This is a wasm script (nr ' + wasmScripts.length + ').'); + wasmScripts.push(scriptId); + } +} + +function printFailure(message) { + if (!message.result) { + InspectorTest.logMessage(message); + } + return message; +} + +function printBreakableLocations(message, expectedScriptId, source) { + var lines = source.split('\n'); + var locations = message.result.locations; + InspectorTest.log(locations.length + ' breakable location(s):'); + for (var i = 0; i < locations.length; ++i) { + if (locations[i].scriptId != expectedScriptId) { + InspectorTest.log( + 'SCRIPT ID MISMATCH!! ' + locations[i].scriptId + ' != ' + + expectedScriptId); + } + var line = '<illegal line number>'; + if (locations[i].lineNumber < lines.length) { + line = lines[locations[i].lineNumber]; + if (locations[i].columnNumber < line.length) { + line = line.substr(0, locations[i].columnNumber) + '>' + + line.substr(locations[i].columnNumber); + } + } + InspectorTest.log( + '[' + i + '] ' + locations[i].lineNumber + ':' + + locations[i].columnNumber + ' || ' + line); + } +} + +function checkGetBreakableLocations(wasmScriptNr) { + InspectorTest.log( + 'Requesting all breakable locations in wasm script ' + wasmScriptNr); + var scriptId = wasmScripts[wasmScriptNr]; + var source; + return Protocol.Debugger.getScriptSource({scriptId: scriptId}) + .then(msg => source = msg.result.scriptSource) + .then( + () => Protocol.Debugger.getPossibleBreakpoints( + {start: {lineNumber: 0, columnNumber: 0, scriptId: scriptId}})) + .then(printFailure) + .then(msg => (allBreakableLocations.push(...msg.result.locations), msg)) + .then(msg => printBreakableLocations(msg, scriptId, source)) + .then( + () => InspectorTest.log( + 'Requesting breakable locations in lines [0,3)')) + .then(() => Protocol.Debugger.getPossibleBreakpoints({ + start: {lineNumber: 0, columnNumber: 0, scriptId: scriptId}, + end: {lineNumber: 3, columnNumber: 0, scriptId: scriptId} + })) + .then(printFailure) + .then(msg => printBreakableLocations(msg, scriptId, source)) + .then( + () => InspectorTest.log( + 'Requesting breakable locations in lines [4,6)')) + .then(() => Protocol.Debugger.getPossibleBreakpoints({ + start: {lineNumber: 4, columnNumber: 0, scriptId: scriptId}, + end: {lineNumber: 6, columnNumber: 0, scriptId: scriptId} + })) + .then(printFailure) + .then(msg => printBreakableLocations(msg, scriptId, source)); +} + +function getBreakableLocationsForAllWasmScripts() { + InspectorTest.log('Querying breakable locations for all wasm scripts now...'); + var promise = Promise.resolve(); + for (var wasmScriptNr = 0; wasmScriptNr < wasmScripts.length; + ++wasmScriptNr) { + promise = promise.then(checkGetBreakableLocations.bind(null, wasmScriptNr)); + } + return promise; +} + +function locationMatches(loc1, loc2) { + return loc1.scriptId == loc2.scriptId && loc1.lineNumber == loc2.lineNumber && + loc1.columnNumber == loc2.columnNumber; +} + +function locationStr(loc) { + return urls[loc.scriptId] + ':' + loc.lineNumber + ':' + loc.columnNumber; +} + +function setBreakpoint(loc) { + InspectorTest.log('Setting at ' + locationStr(loc)); + function check(msg) { + if (locationMatches(loc, msg.result.actualLocation)) { + InspectorTest.log("Success!"); + } else { + InspectorTest.log("Mismatch!"); + InspectorTest.logMessage(msg); + } + } + return Protocol.Debugger.setBreakpoint({'location': loc}) + .then(printFailure) + .then(check); +} + +function setAllBreakableLocations() { + InspectorTest.log('Setting a breakpoint on each breakable location...'); + var promise = Promise.resolve(); + for (var loc of allBreakableLocations) { + promise = promise.then(setBreakpoint.bind(null, loc)); + } + return promise; +} + +function removePausedLocation(msg) { + var topLocation = msg.params.callFrames[0].location; + InspectorTest.log('Stopped at ' + locationStr(topLocation)); + for (var i = 0; i < allBreakableLocations.length; ++i) { + if (locationMatches(topLocation, allBreakableLocations[i])) { + allBreakableLocations.splice(i, 1); + --i; + } + } +} + +function waitForAllPauses() { + InspectorTest.log('Missing breakpoints: ' + allBreakableLocations.length); + if (allBreakableLocations.length == 0) return; + return Protocol.Debugger.oncePaused() + .then(removePausedLocation) + .then(Protocol.Debugger.resume()) + .then(waitForAllPauses); +}
diff --git a/src/v8/test/inspector/debugger/wasm-imports-expected.txt b/src/v8/test/inspector/debugger/wasm-imports-expected.txt new file mode 100644 index 0000000..073c8af --- /dev/null +++ b/src/v8/test/inspector/debugger/wasm-imports-expected.txt
@@ -0,0 +1,25 @@ +Tests imports in wasm +Installing code and global variable. +Calling instantiate function for module A. +Waiting for wasm script to be parsed. +Got wasm script! +Setting breakpoint in line 1: +func $func + #nop +end + +Calling instantiate function for module B. +Calling main function on module B. +Paused at 1:2. +func $func + #nop +end + +Getting current stack trace via "new Error().stack". +Error + at v8://test/getStack:1:1 + at func (wasm-function[0]:1) + at main (wasm-function[1]:1) + at v8://test/runWasm:1:22 +exports.main returned. +Finished.
diff --git a/src/v8/test/inspector/debugger/wasm-imports.js b/src/v8/test/inspector/debugger/wasm-imports.js new file mode 100644 index 0000000..dbe96ce --- /dev/null +++ b/src/v8/test/inspector/debugger/wasm-imports.js
@@ -0,0 +1,110 @@ +// Copyright 2017 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. + +let {session, contextGroup, Protocol} = InspectorTest.start('Tests imports in wasm'); + +utils.load('test/mjsunit/wasm/wasm-constants.js'); +utils.load('test/mjsunit/wasm/wasm-module-builder.js'); + +// Build two modules A and B. A defines function func, which contains a +// breakpoint. This function is then imported by B and called via main. The +// breakpoint must be hit. +// This failed before (http://crbug.com/v8/5971). + +var builder_a = new WasmModuleBuilder(); +var func_idx = builder_a.addFunction('func', kSig_v_v) + .addBody([kExprNop]) + .exportFunc() + .index; +var module_a_bytes = builder_a.toArray(); + +var builder_b = new WasmModuleBuilder(); +var import_idx = builder_b.addImport('imp', 'f', kSig_v_v); +builder_b.addFunction('main', kSig_v_v) + .addBody([kExprCallFunction, import_idx]) + .exportFunc(); +var module_b_bytes = builder_b.toArray(); + +function instantiate(bytes, imp) { + var buffer = new ArrayBuffer(bytes.length); + var view = new Uint8Array(buffer); + for (var i = 0; i < bytes.length; ++i) { + view[i] = bytes[i] | 0; + } + + var module = new WebAssembly.Module(buffer); + // Add to global instances array. + instances.push(new WebAssembly.Instance(module, imp)); +} + +var evalWithUrl = (code, url) => Protocol.Runtime.evaluate( + {'expression': code + '\n//# sourceURL=v8://test/' + url}); + +session.setupScriptMap(); + +// Main promise chain: +Protocol.Debugger.enable() + .then(() => InspectorTest.log('Installing code and global variable.')) + .then( + () => evalWithUrl( + 'var instances = [];\n' + instantiate.toString(), 'setup')) + .then(() => InspectorTest.log('Calling instantiate function for module A.')) + .then( + () => + (evalWithUrl( + 'instantiate(' + JSON.stringify(module_a_bytes) + ')', + 'instantiateA'), + 0)) + .then(() => InspectorTest.log('Waiting for wasm script to be parsed.')) + .then(waitForWasmScript) + .then(url => (InspectorTest.log('Setting breakpoint in line 1:'), url)) + .then( + url => + Protocol.Debugger.setBreakpointByUrl({lineNumber: 1, url: url})) + .then(printFailure) + .then(msg => session.logSourceLocations(msg.result.locations)) + .then(() => InspectorTest.log('Calling instantiate function for module B.')) + .then( + () => + (evalWithUrl( + 'instantiate(' + JSON.stringify(module_b_bytes) + + ', {imp: {f: instances[0].exports.func}})', + 'instantiateB'), + 0)) + .then(() => InspectorTest.log('Calling main function on module B.')) + .then(() => evalWithUrl('instances[1].exports.main()', 'runWasm')) + .then(() => InspectorTest.log('exports.main returned.')) + .then(() => InspectorTest.log('Finished.')) + .then(InspectorTest.completeTest); + +// Separate promise chain for the asynchronous pause: +Protocol.Debugger.oncePaused() + .then(msg => msg.params.callFrames[0].location) + .then( + loc => + (InspectorTest.log( + 'Paused at ' + loc.lineNumber + ':' + loc.columnNumber + '.'), + loc)) + .then(session.logSourceLocation.bind(session)) + .then( + () => InspectorTest.log( + 'Getting current stack trace via "new Error().stack".')) + .then(() => evalWithUrl('new Error().stack', 'getStack')) + .then(msg => InspectorTest.log(msg.result.result.value)) + .then(Protocol.Debugger.resume); + +function printFailure(message) { + if (!message.result) { + InspectorTest.logMessage(message); + } + return message; +} + +function waitForWasmScript(msg) { + if (!msg || !msg.params.url.startsWith('wasm://')) { + return Protocol.Debugger.onceScriptParsed().then(waitForWasmScript); + } + InspectorTest.log('Got wasm script!'); + return Promise.resolve(msg.params.url); +}
diff --git a/src/v8/test/inspector/debugger/wasm-scope-info-expected.txt b/src/v8/test/inspector/debugger/wasm-scope-info-expected.txt new file mode 100644 index 0000000..7701468 --- /dev/null +++ b/src/v8/test/inspector/debugger/wasm-scope-info-expected.txt
@@ -0,0 +1,166 @@ +Test retrieving scope information when pausing in wasm functions +Installing code and global variable. +Calling instantiate function. +Waiting for wasm script to be parsed. +Got wasm script! +Setting breakpoint on line 2 (first instruction) +{ + columnNumber : 2 + lineNumber : 2 + scriptId : <scriptId> +} +Paused: +(local i32 f64) + #i32.const 11 + set_local 0 + +at func (2:2): + - scope (global): + -- skipped + - scope (local): + locals: "i32Arg": 4 (number), "local#1": 0 (number), "unicodeā¼f64": 0 (number) + stack: +at (anonymous) (0:17): + - scope (global): + -- skipped +Paused: + i32.const 11 + #set_local 0 + i32.const 47 + +at func (3:2): + - scope (global): + -- skipped + - scope (local): + locals: "i32Arg": 4 (number), "local#1": 0 (number), "unicodeā¼f64": 0 (number) + stack: "0": 11 (number) +at (anonymous) (0:17): + - scope (global): + -- skipped +Paused: + set_local 0 + #i32.const 47 + set_local 1 + +at func (4:2): + - scope (global): + -- skipped + - scope (local): + locals: "i32Arg": 11 (number), "local#1": 0 (number), "unicodeā¼f64": 0 (number) + stack: +at (anonymous) (0:17): + - scope (global): + -- skipped +Paused: + i32.const 47 + #set_local 1 + i32.const 1 + +at func (5:2): + - scope (global): + -- skipped + - scope (local): + locals: "i32Arg": 11 (number), "local#1": 0 (number), "unicodeā¼f64": 0 (number) + stack: "0": 47 (number) +at (anonymous) (0:17): + - scope (global): + -- skipped +Paused: + set_local 1 + #i32.const 1 + f64.convert_u/i32 + +at func (6:2): + - scope (global): + -- skipped + - scope (local): + locals: "i32Arg": 11 (number), "local#1": 47 (number), "unicodeā¼f64": 0 (number) + stack: +at (anonymous) (0:17): + - scope (global): + -- skipped +Paused: + i32.const 1 + #f64.convert_u/i32 + i32.const 7 + +at func (7:2): + - scope (global): + -- skipped + - scope (local): + locals: "i32Arg": 11 (number), "local#1": 47 (number), "unicodeā¼f64": 0 (number) + stack: "0": 1 (number) +at (anonymous) (0:17): + - scope (global): + -- skipped +Paused: + f64.convert_u/i32 + #i32.const 7 + f64.convert_u/i32 + +at func (8:2): + - scope (global): + -- skipped + - scope (local): + locals: "i32Arg": 11 (number), "local#1": 47 (number), "unicodeā¼f64": 0 (number) + stack: "0": 1 (number) +at (anonymous) (0:17): + - scope (global): + -- skipped +Paused: + i32.const 7 + #f64.convert_u/i32 + f64.div + +at func (9:2): + - scope (global): + -- skipped + - scope (local): + locals: "i32Arg": 11 (number), "local#1": 47 (number), "unicodeā¼f64": 0 (number) + stack: "0": 1 (number), "1": 7 (number) +at (anonymous) (0:17): + - scope (global): + -- skipped +Paused: + f64.convert_u/i32 + #f64.div + set_local 2 + +at func (10:2): + - scope (global): + -- skipped + - scope (local): + locals: "i32Arg": 11 (number), "local#1": 47 (number), "unicodeā¼f64": 0 (number) + stack: "0": 1 (number), "1": 7 (number) +at (anonymous) (0:17): + - scope (global): + -- skipped +Paused: + f64.div + #set_local 2 +end + +at func (11:2): + - scope (global): + -- skipped + - scope (local): + locals: "i32Arg": 11 (number), "local#1": 47 (number), "unicodeā¼f64": 0 (number) + stack: "0": 0.14285714285714285 (number) +at (anonymous) (0:17): + - scope (global): + -- skipped +Paused: + set_local 2 +#end + + +at func (12:0): + - scope (global): + -- skipped + - scope (local): + locals: "i32Arg": 11 (number), "local#1": 47 (number), "unicodeā¼f64": 0.14285714285714285 (number) + stack: +at (anonymous) (0:17): + - scope (global): + -- skipped +exports.main returned. Test finished.
diff --git a/src/v8/test/inspector/debugger/wasm-scope-info.js b/src/v8/test/inspector/debugger/wasm-scope-info.js new file mode 100644 index 0000000..9a20d6a --- /dev/null +++ b/src/v8/test/inspector/debugger/wasm-scope-info.js
@@ -0,0 +1,137 @@ +// Copyright 2017 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. + +let {session, contextGroup, Protocol} = InspectorTest.start( + 'Test retrieving scope information when pausing in wasm functions'); +session.setupScriptMap(); +Protocol.Debugger.enable(); + +let evaluate = code => Protocol.Runtime.evaluate({expression: code}); + +(async function test() { + let scriptId = await instantiateWasm(); + await setBreakpoint(scriptId); + printPauseLocationsAndContinue(); + await evaluate('instance.exports.main(4)'); + InspectorTest.log('exports.main returned. Test finished.'); + InspectorTest.completeTest(); +})(); + +async function printPauseLocationsAndContinue() { + while (true) { + let msg = await Protocol.Debugger.oncePaused(); + let loc = msg.params.callFrames[0].location; + InspectorTest.log('Paused:'); + await session.logSourceLocation(loc); + await dumpScopeChainsOnPause(msg); + Protocol.Debugger.stepOver(); + } +} + +async function instantiateWasm() { + utils.load('test/mjsunit/wasm/wasm-constants.js'); + utils.load('test/mjsunit/wasm/wasm-module-builder.js'); + + var builder = new WasmModuleBuilder(); + + builder.addFunction('func', kSig_v_i) + .addLocals( + {i32_count: 1, f64_count: 1}, ['i32Arg', undefined, 'unicodeā¼f64']) + .addBody([ + // Set param 0 to 11. + kExprI32Const, 11, kExprSetLocal, 0, + // Set local 1 to 47. + kExprI32Const, 47, kExprSetLocal, 1, + // Set local 2 to 1/7. + kExprI32Const, 1, kExprF64UConvertI32, kExprI32Const, 7, + kExprF64UConvertI32, kExprF64Div, kExprSetLocal, 2 + ]) + .exportAs('main'); + + var module_bytes = builder.toArray(); + + function instantiate(bytes) { + var buffer = new ArrayBuffer(bytes.length); + var view = new Uint8Array(buffer); + for (var i = 0; i < bytes.length; ++i) { + view[i] = bytes[i] | 0; + } + + var module = new WebAssembly.Module(buffer); + // Set global variable. + instance = new WebAssembly.Instance(module); + } + + InspectorTest.log('Installing code and global variable.'); + await evaluate('var instance;\n' + instantiate.toString()); + InspectorTest.log('Calling instantiate function.'); + evaluate('instantiate(' + JSON.stringify(module_bytes) + ')'); + return waitForWasmScript(); +} + +async function setBreakpoint(scriptId) { + InspectorTest.log('Setting breakpoint on line 2 (first instruction)'); + let breakpoint = await Protocol.Debugger.setBreakpoint( + {'location': {'scriptId': scriptId, 'lineNumber': 2}}); + printFailure(breakpoint); + InspectorTest.logMessage(breakpoint.result.actualLocation); +} + +function printFailure(message) { + if (!message.result) { + InspectorTest.logMessage(message); + } + return message; +} + +async function waitForWasmScript() { + InspectorTest.log('Waiting for wasm script to be parsed.'); + while (true) { + let script_msg = await Protocol.Debugger.onceScriptParsed(); + let url = script_msg.params.url; + if (!url.startsWith('wasm://')) { + continue; + } + InspectorTest.log('Got wasm script!'); + return script_msg.params.scriptId; + } +} + +async function getValueString(value) { + if (value.type == 'object') { + var msg = await Protocol.Runtime.getProperties({objectId: value.objectId}); + printFailure(msg); + let printProperty = elem => '"' + elem.name + '"' + + ': ' + elem.value.description + ' (' + elem.value.type + ')'; + return msg.result.result.map(printProperty).join(', '); + } + return JSON.stringify(value.value) + ' (' + value.type + ')'; +} + +async function dumpProperties(message) { + printFailure(message); + for (var value of message.result.result) { + var value_str = await getValueString(value.value); + InspectorTest.log(' ' + value.name + ': ' + value_str); + } +} + +async function dumpScopeChainsOnPause(message) { + for (var frame of message.params.callFrames) { + var functionName = frame.functionName || '(anonymous)'; + var lineNumber = frame.location ? frame.location.lineNumber : frame.lineNumber; + var columnNumber = frame.location ? frame.location.columnNumber : frame.columnNumber; + InspectorTest.log(`at ${functionName} (${lineNumber}:${columnNumber}):`); + for (var scope of frame.scopeChain) { + InspectorTest.logObject(' - scope (' + scope.type + '):'); + if (scope.type == 'global') { + InspectorTest.logObject(' -- skipped'); + } else { + var properties = await Protocol.Runtime.getProperties( + {'objectId': scope.object.objectId}); + await dumpProperties(properties); + } + } + } +}
diff --git a/src/v8/test/inspector/debugger/wasm-scripts-expected.txt b/src/v8/test/inspector/debugger/wasm-scripts-expected.txt new file mode 100644 index 0000000..5d23605 --- /dev/null +++ b/src/v8/test/inspector/debugger/wasm-scripts-expected.txt
@@ -0,0 +1,19 @@ +Tests how wasm scripts are reported +Check that inspector gets two wasm scripts at module creation time. +Script #0 parsed. URL: v8://test/testFunction +Script #1 parsed. URL: v8://test/runTestRunction +Script #2 parsed. URL: wasm://wasm/wasm-7b04570e/wasm-7b04570e-0 +Script #3 parsed. URL: wasm://wasm/wasm-7b04570e/wasm-7b04570e-1 +Source for wasm://wasm/wasm-7b04570e/wasm-7b04570e-0: +func $nopFunction + nop +end + +Source for wasm://wasm/wasm-7b04570e/wasm-7b04570e-1: +func $main + block + i32.const 2 + drop + end +end +
diff --git a/src/v8/test/inspector/debugger/wasm-scripts.js b/src/v8/test/inspector/debugger/wasm-scripts.js new file mode 100644 index 0000000..0993f11 --- /dev/null +++ b/src/v8/test/inspector/debugger/wasm-scripts.js
@@ -0,0 +1,72 @@ +// 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 + +let {session, contextGroup, Protocol} = InspectorTest.start('Tests how wasm scripts are reported'); + +utils.load('test/mjsunit/wasm/wasm-constants.js'); +utils.load('test/mjsunit/wasm/wasm-module-builder.js'); + +// Add two empty functions. Both should be registered as individual scripts at +// module creation time. +var builder = new WasmModuleBuilder(); +builder.addFunction('nopFunction', kSig_v_v).addBody([kExprNop]); +builder.addFunction('main', kSig_v_v) + .addBody([kExprBlock, kWasmStmt, kExprI32Const, 2, kExprDrop, kExprEnd]) + .exportAs('main'); +var module_bytes = builder.toArray(); + +function testFunction(bytes) { + var buffer = new ArrayBuffer(bytes.length); + var view = new Uint8Array(buffer); + for (var i = 0; i < bytes.length; i++) { + view[i] = bytes[i] | 0; + } + + // Compilation triggers registration of wasm scripts. + new WebAssembly.Module(buffer); +} + +contextGroup.addScript(testFunction.toString(), 0, 0, 'v8://test/testFunction'); +contextGroup.addScript('var module_bytes = ' + JSON.stringify(module_bytes)); + +Protocol.Debugger.enable(); +Protocol.Debugger.onScriptParsed(handleScriptParsed); +InspectorTest.log( + 'Check that inspector gets two wasm scripts at module creation time.'); +Protocol.Runtime + .evaluate({ + 'expression': '//# sourceURL=v8://test/runTestRunction\n' + + 'testFunction(module_bytes)' + }) + .then(checkFinished); + +var num_scripts = 0; +var missing_sources = 0; + +function checkFinished() { + if (missing_sources == 0) + InspectorTest.completeTest(); +} + +function handleScriptParsed(messageObject) +{ + var url = messageObject.params.url; + InspectorTest.log("Script #" + num_scripts + " parsed. URL: " + url); + ++num_scripts; + + if (url.startsWith("wasm://")) { + ++missing_sources; + function dumpScriptSource(message) { + InspectorTest.log("Source for " + url + ":"); + InspectorTest.log(message.result.scriptSource); + --missing_sources; + } + + Protocol.Debugger.getScriptSource({scriptId: messageObject.params.scriptId}) + .then(dumpScriptSource.bind(null)) + .then(checkFinished); + } +}
diff --git a/src/v8/test/inspector/debugger/wasm-source-expected.txt b/src/v8/test/inspector/debugger/wasm-source-expected.txt new file mode 100644 index 0000000..b140be0 --- /dev/null +++ b/src/v8/test/inspector/debugger/wasm-source-expected.txt
@@ -0,0 +1,10 @@ +Tests how wasm scrips report the source +Check that inspector gets disassembled wasm code +Paused on debugger! +Number of frames: 5 +[0] debugger; +[1] call 0 +[2] call_indirect 2 +[3] instance.exports.main(); +[4] testFunction(module_bytes) +Finished.
diff --git a/src/v8/test/inspector/debugger/wasm-source.js b/src/v8/test/inspector/debugger/wasm-source.js new file mode 100644 index 0000000..bf7bab7 --- /dev/null +++ b/src/v8/test/inspector/debugger/wasm-source.js
@@ -0,0 +1,81 @@ +// 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 + +let {session, contextGroup, Protocol} = InspectorTest.start('Tests how wasm scrips report the source'); + +utils.load('test/mjsunit/wasm/wasm-constants.js'); +utils.load('test/mjsunit/wasm/wasm-module-builder.js'); + +var builder = new WasmModuleBuilder(); + +var imported_idx = builder.addImport("xxx", "func", kSig_v_v); + +var call_imported_idx = builder.addFunction("call_func", kSig_v_v) + .addBody([kExprCallFunction, imported_idx]) + .index; + +var sig_index = builder.addType(kSig_v_v); + +builder.addFunction('main', kSig_v_v) + .addBody([ + kExprBlock, kWasmStmt, kExprI32Const, 0, kExprCallIndirect, sig_index, + kTableZero, kExprEnd + ]) + .exportAs('main'); + +builder.appendToTable([call_imported_idx]); + +var module_bytes = builder.toArray(); + +function testFunction(bytes) { + function call_debugger() { + debugger; + } + + var buffer = new ArrayBuffer(bytes.length); + var view = new Uint8Array(buffer); + for (var i = 0; i < bytes.length; i++) { + view[i] = bytes[i] | 0; + } + + var module = new WebAssembly.Module(buffer); + var instance = new WebAssembly.Instance(module, {xxx: {func: call_debugger}}); + + instance.exports.main(); +} + +contextGroup.addScript(testFunction.toString()); +contextGroup.addScript('var module_bytes = ' + JSON.stringify(module_bytes)); + +Protocol.Debugger.enable(); +Protocol.Debugger.onPaused(handleDebuggerPaused); +InspectorTest.log('Check that inspector gets disassembled wasm code'); +Protocol.Runtime.evaluate({'expression': 'testFunction(module_bytes)'}); + +function handleDebuggerPaused(message) { + InspectorTest.log('Paused on debugger!'); + var frames = message.params.callFrames; + InspectorTest.log('Number of frames: ' + frames.length); + function dumpSourceLine(frameId, sourceMessage) { + if (sourceMessage.error) InspectorTest.logObject(sourceMessage); + var text = sourceMessage.result.scriptSource; + var lineNr = frames[frameId].location.lineNumber; + var line = text.split('\n')[lineNr]; + InspectorTest.log('[' + frameId + '] ' + line); + } + function next(frameId) { + if (frameId == frames.length) return Promise.resolve(); + return Protocol.Debugger + .getScriptSource({scriptId: frames[frameId].location.scriptId}) + .then(dumpSourceLine.bind(null, frameId)) + .then(() => next(frameId + 1)); + } + function finished() { + InspectorTest.log('Finished.'); + InspectorTest.completeTest(); + } + next(0).then(finished); +}
diff --git a/src/v8/test/inspector/debugger/wasm-stack-expected.txt b/src/v8/test/inspector/debugger/wasm-stack-expected.txt new file mode 100644 index 0000000..bba3009 --- /dev/null +++ b/src/v8/test/inspector/debugger/wasm-stack-expected.txt
@@ -0,0 +1,19 @@ +Tests call stack in wasm scripts +Running testFunction with generated wasm bytes... +Paused on 'debugger;' +Number of frames: 5 + - [0] {"functionName":"call_debugger","function_lineNumber":1,"function_columnNumber":24,"lineNumber":2,"columnNumber":4} + - [1] {"functionName":"call_func","lineNumber":1,"columnNumber":2} + - [2] {"functionName":"main","lineNumber":2,"columnNumber":4} + - [3] {"functionName":"testFunction","function_lineNumber":0,"function_columnNumber":21,"lineNumber":14,"columnNumber":19} + - [4] {"functionName":"","function_lineNumber":0,"function_columnNumber":0,"lineNumber":0,"columnNumber":0} +Getting v8-generated stack trace... +Result of evaluate (string): +Error: this is your stack trace: + -- skipped -- + at call_debugger (<anonymous>:3:5) + at call_func (wasm-function[1]:1) + at main (wasm-function[2]:3) + at testFunction (<anonymous>:15:20) + at <anonymous>:1:1 +Finished!
diff --git a/src/v8/test/inspector/debugger/wasm-stack.js b/src/v8/test/inspector/debugger/wasm-stack.js new file mode 100644 index 0000000..0234dab --- /dev/null +++ b/src/v8/test/inspector/debugger/wasm-stack.js
@@ -0,0 +1,98 @@ +// 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 + +let {session, contextGroup, Protocol} = InspectorTest.start('Tests call stack in wasm scripts'); + +utils.load('test/mjsunit/wasm/wasm-constants.js'); +utils.load('test/mjsunit/wasm/wasm-module-builder.js'); + +var builder = new WasmModuleBuilder(); + +var imported_idx = builder.addImport("mode", "func", kSig_v_v); + +var call_imported_idx = builder.addFunction('call_func', kSig_v_v) + .addBody([kExprCallFunction, imported_idx]) + .index; + +// Open a block in order to make the positions more interesting... +builder.addFunction('main', kSig_v_v) + .addBody( + [kExprBlock, kWasmStmt, kExprCallFunction, call_imported_idx, kExprEnd]) + .exportAs('main'); + +var module_bytes = builder.toArray(); + +function testFunction(bytes) { + function call_debugger() { + debugger; + } + + var buffer = new ArrayBuffer(bytes.length); + var view = new Uint8Array(buffer); + for (var i = 0; i < bytes.length; i++) { + view[i] = bytes[i] | 0; + } + + var module = new WebAssembly.Module(buffer); + var instance = new WebAssembly.Instance(module, {mode: {func: call_debugger}}); + + instance.exports.main(); +} + +contextGroup.addScript(testFunction.toString()); + +Protocol.Debugger.enable(); +Protocol.Debugger.onPaused(handleDebuggerPaused); +InspectorTest.log('Running testFunction with generated wasm bytes...'); +Protocol.Runtime.evaluate( + {'expression': 'testFunction(' + JSON.stringify(module_bytes) + ')'}); + +function locationToString(callFrame) { + var res = {functionName: callFrame.functionName}; + for (var attr in callFrame.functionLocation) { + if (attr == 'scriptId') continue; + res['function_'+attr] = callFrame.functionLocation[attr]; + } + for (var attr in callFrame.location) { + if (attr == 'scriptId') continue; + res[attr] = callFrame.location[attr]; + } + return JSON.stringify(res); +} + +function logStackTrace(messageObject) { + var frames = messageObject.params.callFrames; + InspectorTest.log('Number of frames: ' + frames.length); + for (var i = 0; i < frames.length; ++i) { + InspectorTest.log(' - [' + i + '] ' + locationToString(frames[i])); + } +} + +function handleDebuggerPaused(messageObject) +{ + InspectorTest.log('Paused on \'debugger;\''); + logStackTrace(messageObject); + InspectorTest.log('Getting v8-generated stack trace...'); + var topFrameId = messageObject.params.callFrames[0].callFrameId; + Protocol.Debugger + .evaluateOnCallFrame({ + callFrameId: topFrameId, + expression: '(new Error("this is your stack trace:")).stack' + }) + .then(callbackEvaluate); +} + +function callbackEvaluate(response) +{ + InspectorTest.log( + 'Result of evaluate (' + response.result.result.type + '):'); + var result_lines = response.result.result.value.split('\n'); + // Skip the second line, containing the 'evaluate' position. + result_lines[1] = ' -- skipped --'; + InspectorTest.log(result_lines.join('\n')); + InspectorTest.log('Finished!'); + InspectorTest.completeTest(); +}
diff --git a/src/v8/test/inspector/debugger/wasm-stepping-expected.txt b/src/v8/test/inspector/debugger/wasm-stepping-expected.txt new file mode 100644 index 0000000..7af75aa --- /dev/null +++ b/src/v8/test/inspector/debugger/wasm-stepping-expected.txt
@@ -0,0 +1,330 @@ +Tests stepping through wasm scripts +Installing code an global variable. +Calling instantiate function. +Waiting for two wasm scripts to be parsed. +Ignoring script with url v8://test/callInstantiate +Got wasm script: wasm://wasm/wasm-0c10a5fe/wasm-0c10a5fe-0 +Requesting source for wasm://wasm/wasm-0c10a5fe/wasm-0c10a5fe-0... +Got wasm script: wasm://wasm/wasm-0c10a5fe/wasm-0c10a5fe-1 +Requesting source for wasm://wasm/wasm-0c10a5fe/wasm-0c10a5fe-1... +func $wasm_A + nop + nop +end + +func $wasm_B (param i32) + loop + get_local 0 + if + get_local 0 + i32.const 1 + i32.sub + set_local 0 + call 0 + br 1 + end + end +end + +Setting breakpoint on line 7 (on the setlocal before the call), url wasm://wasm/wasm-0c10a5fe/wasm-0c10a5fe-1 +{ + columnNumber : 6 + lineNumber : 7 + scriptId : <scriptId> +} +Paused at wasm://wasm/wasm-0c10a5fe/wasm-0c10a5fe-1:7:6: >set_local 0 +at wasm_B (7:6): + - scope (global): + -- skipped + - scope (local): + locals: {"arg#0":4} (Object) + stack: {"0":3} (Object) +at (anonymous) (0:17): + - scope (global): + -- skipped +Debugger.stepInto called +Paused at wasm://wasm/wasm-0c10a5fe/wasm-0c10a5fe-1:8:6: >call 0 +at wasm_B (8:6): + - scope (global): + -- skipped + - scope (local): + locals: {"arg#0":3} (Object) + stack: {} (Object) +at (anonymous) (0:17): + - scope (global): + -- skipped +Debugger.stepInto called +Paused at wasm://wasm/wasm-0c10a5fe/wasm-0c10a5fe-0:1:2: >nop +at wasm_A (1:2): + - scope (global): + -- skipped + - scope (local): + stack: {} (Object) +at wasm_B (8:6): + - scope (global): + -- skipped + - scope (local): + locals: {"arg#0":3} (Object) + stack: {} (Object) +at (anonymous) (0:17): + - scope (global): + -- skipped +Debugger.stepOver called +Paused at wasm://wasm/wasm-0c10a5fe/wasm-0c10a5fe-0:2:2: >nop +at wasm_A (2:2): + - scope (global): + -- skipped + - scope (local): + stack: {} (Object) +at wasm_B (8:6): + - scope (global): + -- skipped + - scope (local): + locals: {"arg#0":3} (Object) + stack: {} (Object) +at (anonymous) (0:17): + - scope (global): + -- skipped +Debugger.stepOut called +Paused at wasm://wasm/wasm-0c10a5fe/wasm-0c10a5fe-1:9:6: >br 1 +at wasm_B (9:6): + - scope (global): + -- skipped + - scope (local): + locals: {"arg#0":3} (Object) + stack: {} (Object) +at (anonymous) (0:17): + - scope (global): + -- skipped +Debugger.stepOut called +Paused at wasm://wasm/wasm-0c10a5fe/wasm-0c10a5fe-1:7:6: >set_local 0 +at wasm_B (7:6): + - scope (global): + -- skipped + - scope (local): + locals: {"arg#0":3} (Object) + stack: {"0":2} (Object) +at (anonymous) (0:17): + - scope (global): + -- skipped +Debugger.stepOver called +Paused at wasm://wasm/wasm-0c10a5fe/wasm-0c10a5fe-1:8:6: >call 0 +at wasm_B (8:6): + - scope (global): + -- skipped + - scope (local): + locals: {"arg#0":2} (Object) + stack: {} (Object) +at (anonymous) (0:17): + - scope (global): + -- skipped +Debugger.stepOver called +Paused at wasm://wasm/wasm-0c10a5fe/wasm-0c10a5fe-1:9:6: >br 1 +at wasm_B (9:6): + - scope (global): + -- skipped + - scope (local): + locals: {"arg#0":2} (Object) + stack: {} (Object) +at (anonymous) (0:17): + - scope (global): + -- skipped +Debugger.resume called +Paused at wasm://wasm/wasm-0c10a5fe/wasm-0c10a5fe-1:7:6: >set_local 0 +at wasm_B (7:6): + - scope (global): + -- skipped + - scope (local): + locals: {"arg#0":2} (Object) + stack: {"0":1} (Object) +at (anonymous) (0:17): + - scope (global): + -- skipped +Debugger.stepInto called +Paused at wasm://wasm/wasm-0c10a5fe/wasm-0c10a5fe-1:8:6: >call 0 +at wasm_B (8:6): + - scope (global): + -- skipped + - scope (local): + locals: {"arg#0":1} (Object) + stack: {} (Object) +at (anonymous) (0:17): + - scope (global): + -- skipped +Debugger.stepInto called +Paused at wasm://wasm/wasm-0c10a5fe/wasm-0c10a5fe-0:1:2: >nop +at wasm_A (1:2): + - scope (global): + -- skipped + - scope (local): + stack: {} (Object) +at wasm_B (8:6): + - scope (global): + -- skipped + - scope (local): + locals: {"arg#0":1} (Object) + stack: {} (Object) +at (anonymous) (0:17): + - scope (global): + -- skipped +Debugger.stepOut called +Paused at wasm://wasm/wasm-0c10a5fe/wasm-0c10a5fe-1:9:6: >br 1 +at wasm_B (9:6): + - scope (global): + -- skipped + - scope (local): + locals: {"arg#0":1} (Object) + stack: {} (Object) +at (anonymous) (0:17): + - scope (global): + -- skipped +Debugger.stepInto called +Paused at wasm://wasm/wasm-0c10a5fe/wasm-0c10a5fe-1:1:2: >loop +at wasm_B (1:2): + - scope (global): + -- skipped + - scope (local): + locals: {"arg#0":1} (Object) + stack: {} (Object) +at (anonymous) (0:17): + - scope (global): + -- skipped +Debugger.stepInto called +Paused at wasm://wasm/wasm-0c10a5fe/wasm-0c10a5fe-1:2:4: >get_local 0 +at wasm_B (2:4): + - scope (global): + -- skipped + - scope (local): + locals: {"arg#0":1} (Object) + stack: {} (Object) +at (anonymous) (0:17): + - scope (global): + -- skipped +Debugger.stepInto called +Paused at wasm://wasm/wasm-0c10a5fe/wasm-0c10a5fe-1:3:4: >if +at wasm_B (3:4): + - scope (global): + -- skipped + - scope (local): + locals: {"arg#0":1} (Object) + stack: {"0":1} (Object) +at (anonymous) (0:17): + - scope (global): + -- skipped +Debugger.stepInto called +Paused at wasm://wasm/wasm-0c10a5fe/wasm-0c10a5fe-1:4:6: >get_local 0 +at wasm_B (4:6): + - scope (global): + -- skipped + - scope (local): + locals: {"arg#0":1} (Object) + stack: {} (Object) +at (anonymous) (0:17): + - scope (global): + -- skipped +Debugger.stepInto called +Paused at wasm://wasm/wasm-0c10a5fe/wasm-0c10a5fe-1:5:6: >i32.const 1 +at wasm_B (5:6): + - scope (global): + -- skipped + - scope (local): + locals: {"arg#0":1} (Object) + stack: {"0":1} (Object) +at (anonymous) (0:17): + - scope (global): + -- skipped +Debugger.stepInto called +Paused at wasm://wasm/wasm-0c10a5fe/wasm-0c10a5fe-1:6:6: >i32.sub +at wasm_B (6:6): + - scope (global): + -- skipped + - scope (local): + locals: {"arg#0":1} (Object) + stack: {"0":1,"1":1} (Object) +at (anonymous) (0:17): + - scope (global): + -- skipped +Debugger.stepInto called +Paused at wasm://wasm/wasm-0c10a5fe/wasm-0c10a5fe-1:7:6: >set_local 0 +at wasm_B (7:6): + - scope (global): + -- skipped + - scope (local): + locals: {"arg#0":1} (Object) + stack: {"0":0} (Object) +at (anonymous) (0:17): + - scope (global): + -- skipped +Debugger.stepInto called +Paused at wasm://wasm/wasm-0c10a5fe/wasm-0c10a5fe-1:8:6: >call 0 +at wasm_B (8:6): + - scope (global): + -- skipped + - scope (local): + locals: {"arg#0":0} (Object) + stack: {} (Object) +at (anonymous) (0:17): + - scope (global): + -- skipped +Debugger.stepInto called +Paused at wasm://wasm/wasm-0c10a5fe/wasm-0c10a5fe-0:1:2: >nop +at wasm_A (1:2): + - scope (global): + -- skipped + - scope (local): + stack: {} (Object) +at wasm_B (8:6): + - scope (global): + -- skipped + - scope (local): + locals: {"arg#0":0} (Object) + stack: {} (Object) +at (anonymous) (0:17): + - scope (global): + -- skipped +Debugger.stepInto called +Paused at wasm://wasm/wasm-0c10a5fe/wasm-0c10a5fe-0:2:2: >nop +at wasm_A (2:2): + - scope (global): + -- skipped + - scope (local): + stack: {} (Object) +at wasm_B (8:6): + - scope (global): + -- skipped + - scope (local): + locals: {"arg#0":0} (Object) + stack: {} (Object) +at (anonymous) (0:17): + - scope (global): + -- skipped +Debugger.stepInto called +Paused at wasm://wasm/wasm-0c10a5fe/wasm-0c10a5fe-0:3:0: >end +at wasm_A (3:0): + - scope (global): + -- skipped + - scope (local): + stack: {} (Object) +at wasm_B (8:6): + - scope (global): + -- skipped + - scope (local): + locals: {"arg#0":0} (Object) + stack: {} (Object) +at (anonymous) (0:17): + - scope (global): + -- skipped +Debugger.stepInto called +Paused at wasm://wasm/wasm-0c10a5fe/wasm-0c10a5fe-1:9:6: >br 1 +at wasm_B (9:6): + - scope (global): + -- skipped + - scope (local): + locals: {"arg#0":0} (Object) + stack: {} (Object) +at (anonymous) (0:17): + - scope (global): + -- skipped +Debugger.resume called +exports.main returned! +Finished!
diff --git a/src/v8/test/inspector/debugger/wasm-stepping.js b/src/v8/test/inspector/debugger/wasm-stepping.js new file mode 100644 index 0000000..d3a2c64 --- /dev/null +++ b/src/v8/test/inspector/debugger/wasm-stepping.js
@@ -0,0 +1,203 @@ +// Copyright 2017 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. + +let {session, contextGroup, Protocol} = InspectorTest.start('Tests stepping through wasm scripts'); + +utils.load('test/mjsunit/wasm/wasm-constants.js'); +utils.load('test/mjsunit/wasm/wasm-module-builder.js'); + +var builder = new WasmModuleBuilder(); + +var func_a_idx = + builder.addFunction('wasm_A', kSig_v_v).addBody([kExprNop, kExprNop]).index; + +// wasm_B calls wasm_A <param0> times. +builder.addFunction('wasm_B', kSig_v_i) + .addBody([ + // clang-format off + kExprLoop, kWasmStmt, // while + kExprGetLocal, 0, // - + kExprIf, kWasmStmt, // if <param0> != 0 + kExprGetLocal, 0, // - + kExprI32Const, 1, // - + kExprI32Sub, // - + kExprSetLocal, 0, // decrease <param0> + kExprCallFunction, func_a_idx, // - + kExprBr, 1, // continue + kExprEnd, // - + kExprEnd, // break + // clang-format on + ]) + .exportAs('main'); + +var module_bytes = builder.toArray(); + +function instantiate(bytes) { + var buffer = new ArrayBuffer(bytes.length); + var view = new Uint8Array(buffer); + for (var i = 0; i < bytes.length; ++i) { + view[i] = bytes[i] | 0; + } + + var module = new WebAssembly.Module(buffer); + // Set global variable. + instance = new WebAssembly.Instance(module); +} + +var evalWithUrl = (code, url) => Protocol.Runtime.evaluate( + {'expression': code + '\n//# sourceURL=v8://test/' + url}); + +Protocol.Debugger.onPaused(handlePaused); +var wasm_B_scriptId; +var step_actions = [ + 'stepInto', // == stepOver, to call instruction + 'stepInto', // into call to wasm_A + 'stepOver', // over first nop + 'stepOut', // out of wasm_A + 'stepOut', // out of wasm_B, stop on breakpoint again + 'stepOver', // to call + 'stepOver', // over call + 'resume', // to next breakpoint (third iteration) + 'stepInto', // to call + 'stepInto', // into wasm_A + 'stepOut', // out to wasm_B + // now step 9 times, until we are in wasm_A again. + 'stepInto', 'stepInto', 'stepInto', 'stepInto', 'stepInto', 'stepInto', + 'stepInto', 'stepInto', 'stepInto', + // 3 more times, back to wasm_B. + 'stepInto', 'stepInto', 'stepInto', + // then just resume. + 'resume' +]; +for (var action of step_actions) { + InspectorTest.logProtocolCommandCalls('Debugger.' + action) +} +var sources = {}; +var urls = {}; +var afterTwoSourcesCallback; + +Protocol.Debugger.enable() + .then(() => InspectorTest.log('Installing code an global variable.')) + .then( + () => evalWithUrl('var instance;\n' + instantiate.toString(), 'setup')) + .then(() => InspectorTest.log('Calling instantiate function.')) + .then( + () => + (evalWithUrl( + 'instantiate(' + JSON.stringify(module_bytes) + ')', + 'callInstantiate'), + 0)) + .then(waitForTwoWasmScripts) + .then( + () => InspectorTest.log( + 'Setting breakpoint on line 7 (on the setlocal before the call), url ' + + urls[wasm_B_scriptId])) + .then( + () => Protocol.Debugger.setBreakpoint( + {'location': {'scriptId': wasm_B_scriptId, 'lineNumber': 7}})) + .then(printFailure) + .then(msg => InspectorTest.logMessage(msg.result.actualLocation)) + .then(() => evalWithUrl('instance.exports.main(4)', 'runWasm')) + .then(() => InspectorTest.log('exports.main returned!')) + .then(() => InspectorTest.log('Finished!')) + .then(InspectorTest.completeTest); + +function printFailure(message) { + if (!message.result) { + InspectorTest.logMessage(message); + } + return message; +} + +function waitForTwoWasmScripts() { + var num = 0; + InspectorTest.log('Waiting for two wasm scripts to be parsed.'); + var promise = new Promise(fulfill => gotBothSources = fulfill); + function waitForMore() { + if (num == 2) return promise; + Protocol.Debugger.onceScriptParsed() + .then(handleNewScript) + .then(waitForMore); + } + function handleNewScript(msg) { + var url = msg.params.url; + if (!url.startsWith('wasm://')) { + InspectorTest.log('Ignoring script with url ' + url); + return; + } + num += 1; + var scriptId = msg.params.scriptId; + urls[scriptId] = url; + InspectorTest.log('Got wasm script: ' + url); + if (url.substr(-2) == '-1') wasm_B_scriptId = scriptId; + InspectorTest.log('Requesting source for ' + url + '...'); + Protocol.Debugger.getScriptSource({scriptId: scriptId}) + .then(printFailure) + .then(msg => sources[scriptId] = msg.result.scriptSource) + .then(InspectorTest.log) + .then(() => Object.keys(sources).length == 2 ? gotBothSources() : 0); + } + waitForMore(); + return promise; +} + +function printPauseLocation(scriptId, lineNr, columnNr) { + var lines = sources[scriptId].split('\n'); + var line = '<illegal line number>'; + if (lineNr < lines.length) { + line = lines[lineNr]; + if (columnNr < line.length) { + line = line.substr(0, columnNr) + '>' + line.substr(columnNr); + } + } + InspectorTest.log( + 'Paused at ' + urls[scriptId] + ':' + lineNr + ':' + columnNr + ': ' + + line); +} + +async function getValueString(value) { + if (value.type == 'object') { + var msg = await Protocol.Runtime.callFunctionOn({ + objectId: value.objectId, + functionDeclaration: 'function () { return JSON.stringify(this); }' + }); + printFailure(msg); + return msg.result.result.value + ' (' + value.description + ')'; + } + return value.value + ' (' + value.type + ')'; +} + +async function dumpProperties(message) { + printFailure(message); + for (var value of message.result.result) { + var value_str = await getValueString(value.value); + InspectorTest.log(' ' + value.name + ': ' + value_str); + } +} + +async function dumpScopeChainsOnPause(message) { + for (var frame of message.params.callFrames) { + var functionName = frame.functionName || '(anonymous)'; + var lineNumber = frame.location ? frame.location.lineNumber : frame.lineNumber; + var columnNumber = frame.location ? frame.location.columnNumber : frame.columnNumber; + InspectorTest.log(`at ${functionName} (${lineNumber}:${columnNumber}):`); + for (var scope of frame.scopeChain) { + InspectorTest.logObject(' - scope (' + scope.type + '):'); + if (scope.type == 'global') { + InspectorTest.logObject(' -- skipped'); + } else { + var properties = await Protocol.Runtime.getProperties( + {'objectId': scope.object.objectId}); + await dumpProperties(properties); + } + } + } +} + +function handlePaused(msg) { + var loc = msg.params.callFrames[0].location; + printPauseLocation(loc.scriptId, loc.lineNumber, loc.columnNumber); + dumpScopeChainsOnPause(msg) + .then(Protocol.Debugger[step_actions.shift() || 'resume']); +}