Import Cobalt 13.102542 Change-Id: I6bda7b03a2e33edfd735efcb981e2a731696b90d
diff --git a/src/v8/test/inspector/BUILD.gn b/src/v8/test/inspector/BUILD.gn new file mode 100644 index 0000000..eec613b --- /dev/null +++ b/src/v8/test/inspector/BUILD.gn
@@ -0,0 +1,33 @@ +# 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. + +import("../../gni/v8.gni") + +v8_executable("inspector-test") { + testonly = true + + sources = [ + "inspector-test.cc", + "isolate-data.cc", + "isolate-data.h", + "task-runner.cc", + "task-runner.h", + ] + + configs = [ + "../..:external_config", + "../..:internal_config_base", + ] + + deps = [ + "../..:v8", + "../..:v8_libbase", + "../..:v8_libplatform", + "//build/config:exe_and_shlib_deps", + "//build/win:default_exe_manifest", + ] + + cflags = [] + ldflags = [] +}
diff --git a/src/v8/test/inspector/console/destroy-context-during-log-expected.txt b/src/v8/test/inspector/console/destroy-context-during-log-expected.txt new file mode 100644 index 0000000..d345b12 --- /dev/null +++ b/src/v8/test/inspector/console/destroy-context-during-log-expected.txt
@@ -0,0 +1,9 @@ +Tests that destroying context from inside of console.log does not crash +{ + type : string + value : First inspector activity after attaching inspector +} +{ + type : string + value : End of test +}
diff --git a/src/v8/test/inspector/console/destroy-context-during-log.js b/src/v8/test/inspector/console/destroy-context-during-log.js new file mode 100644 index 0000000..0fa7c16 --- /dev/null +++ b/src/v8/test/inspector/console/destroy-context-during-log.js
@@ -0,0 +1,42 @@ +// 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 destroying context from inside of console.log does not crash'); + +const expression = ` + Object.defineProperty(Object.prototype, 'RemoteObject', { + configurable: true, + set(v) { + console.log("Should never be called"); + delete Object.prototype.RemoteObject; + this.RemoteObject = v; + + inspector.fireContextDestroyed(); + setTimeout(function() { + // Attach the inspector again for the sake of establishing a + // communication channel with the frontend test runner. + inspector.fireContextCreated(); + console.log("End of test"); + }, 0); + }, + }); + + // Before the whole script runs, the inspector is already attached. + // Re-attach the inspector and trigger the console API to make sure that the + // injected inspector script runs again (and triggers the above setter). + inspector.fireContextDestroyed(); + inspector.fireContextCreated(); + console.log("First inspector activity after attaching inspector"); + console.log("End of test"); +`; + +Protocol.Runtime.enable(); +Protocol.Runtime.evaluate({ expression: expression }); + +Protocol.Runtime.onConsoleAPICalled(function(result) { + InspectorTest.logObject(result.params.args[0]); + if (result.params.args[0].value == "End of test") { + InspectorTest.completeTest(); + } +});
diff --git a/src/v8/test/inspector/console/scoped-variables-expected.txt b/src/v8/test/inspector/console/scoped-variables-expected.txt new file mode 100644 index 0000000..cbafd50 --- /dev/null +++ b/src/v8/test/inspector/console/scoped-variables-expected.txt
@@ -0,0 +1,41 @@ +Tests scoped variable in Runtime.evaluate +Evaluating 'let a = 42;' +{ + type : undefined +} +Evaluating 'a' +{ + description : 42 + type : number + value : 42 +} +Evaluating 'let a = 239;' +{ + exceptionDetails : { + columnNumber : 0 + exception : { + className : SyntaxError + description : SyntaxError: Identifier 'a' has already been declared at <anonymous>:1:1 + objectId : <objectId> + subtype : error + type : object + } + exceptionId : <exceptionId> + lineNumber : 0 + scriptId : <scriptId> + text : Uncaught + } + result : { + className : SyntaxError + description : SyntaxError: Identifier 'a' has already been declared at <anonymous>:1:1 + objectId : <objectId> + subtype : error + type : object + } +} +Evaluating 'a' +{ + description : 42 + type : number + value : 42 +}
diff --git a/src/v8/test/inspector/console/scoped-variables.js b/src/v8/test/inspector/console/scoped-variables.js new file mode 100644 index 0000000..19d4926 --- /dev/null +++ b/src/v8/test/inspector/console/scoped-variables.js
@@ -0,0 +1,26 @@ +// 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 scoped variable in Runtime.evaluate'); + +(async function test() { + InspectorTest.log('Evaluating \'let a = 42;\''); + var {result:{result}} = await Protocol.Runtime.evaluate({ + expression:'let a = 42;'}); + InspectorTest.logMessage(result); + InspectorTest.log('Evaluating \'a\''); + var {result:{result}} = await Protocol.Runtime.evaluate({ + expression:'a'}); + InspectorTest.logMessage(result); + InspectorTest.log('Evaluating \'let a = 239;\''); + var {result} = await Protocol.Runtime.evaluate({ + expression:'let a = 239;'}); + InspectorTest.logMessage(result); + InspectorTest.log('Evaluating \'a\''); + var {result:{result}} = await Protocol.Runtime.evaluate({ + expression:'a'}); + InspectorTest.logMessage(result); + InspectorTest.completeTest(); +})();
diff --git a/src/v8/test/inspector/cpu-profiler/console-profile-end-parameterless-crash-expected.txt b/src/v8/test/inspector/cpu-profiler/console-profile-end-parameterless-crash-expected.txt new file mode 100644 index 0000000..a2988ad --- /dev/null +++ b/src/v8/test/inspector/cpu-profiler/console-profile-end-parameterless-crash-expected.txt
@@ -0,0 +1,3 @@ +Tests that "console.profileEnd()" does not cause crash. (webkit:105759) +SUCCESS: found 2 profile headers +SUCCESS: titled profile found
diff --git a/src/v8/test/inspector/cpu-profiler/console-profile-end-parameterless-crash.js b/src/v8/test/inspector/cpu-profiler/console-profile-end-parameterless-crash.js new file mode 100644 index 0000000..d0d995e --- /dev/null +++ b/src/v8/test/inspector/cpu-profiler/console-profile-end-parameterless-crash.js
@@ -0,0 +1,46 @@ +// 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 \"console.profileEnd()\" does not cause crash. (webkit:105759)"); + +contextGroup.addScript(` +function collectProfiles() +{ + console.profile(); + console.profile("titled"); + console.profileEnd(); + console.profileEnd(); +}`); + +InspectorTest.fail = function(message) +{ + InspectorTest.log("FAIL: " + message); + InspectorTest.completeTest(); +} + +Protocol.Profiler.enable(); +Protocol.Runtime.evaluate({ expression: "collectProfiles()"}).then(didCollectProfiles); + +var headers = []; +Protocol.Profiler.onConsoleProfileFinished(function(messageObject) +{ + headers.push({ + title: messageObject["params"]["title"] + }); +}); + +function didCollectProfiles(messageObject) +{ + if (headers.length !== 2) + return InspectorTest.fail("Cannot retrive headers: " + JSON.stringify(messageObject, null, 4)); + InspectorTest.log("SUCCESS: found 2 profile headers"); + for (var i = 0; i < headers.length; i++) { + if (headers[i].title === "titled") { + InspectorTest.log("SUCCESS: titled profile found"); + InspectorTest.completeTest(); + return; + } + } + InspectorTest.fail("Cannot find titled profile"); +}
diff --git a/src/v8/test/inspector/cpu-profiler/console-profile-expected.txt b/src/v8/test/inspector/cpu-profiler/console-profile-expected.txt new file mode 100644 index 0000000..7bb8bc9 --- /dev/null +++ b/src/v8/test/inspector/cpu-profiler/console-profile-expected.txt
@@ -0,0 +1,3 @@ +Tests that console.profile/profileEnd will record CPU profile when inspector front-end is connected. +SUCCESS: retrieved '42' profile +SUCCESS: found 'collectProfiles' function in the profile
diff --git a/src/v8/test/inspector/cpu-profiler/console-profile.js b/src/v8/test/inspector/cpu-profiler/console-profile.js new file mode 100644 index 0000000..9aa7542 --- /dev/null +++ b/src/v8/test/inspector/cpu-profiler/console-profile.js
@@ -0,0 +1,59 @@ +// 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 console.profile/profileEnd will record CPU profile when inspector front-end is connected."); + +contextGroup.addScript(` +function collectProfiles() +{ + console.profile("outer"); + console.profile(42); + console.profileEnd("outer"); + console.profileEnd(42); +}`); + +InspectorTest.fail = function(message) +{ + InspectorTest.log("FAIL: " + message); + InspectorTest.completeTest(); +} + +Protocol.Profiler.enable(); +Protocol.Runtime.evaluate({ expression: "collectProfiles()"}).then(didCollectProfiles); + +var headers = []; +Protocol.Profiler.onConsoleProfileFinished(function(messageObject) +{ + headers.push({ + profile: messageObject["params"]["profile"], + title: messageObject["params"]["title"] + }); +}); + +function didCollectProfiles(messageObject) +{ + if (headers.length !== 2) + return InspectorTest.fail("Cannot retrive headers: " + JSON.stringify(messageObject, null, 4)); + for (var i = 0; i < headers.length; i++) { + if (headers[i].title === "42") { + checkInnerProfile(headers[i].profile); + return; + } + } + InspectorTest.fail("Cannot find '42' profile header"); +} + +function checkInnerProfile(profile) +{ + InspectorTest.log("SUCCESS: retrieved '42' profile"); + if (!findFunctionInProfile(profile.nodes, "collectProfiles")) + return InspectorTest.fail("collectProfiles function not found in the profile: " + JSON.stringify(profile, null, 4)); + InspectorTest.log("SUCCESS: found 'collectProfiles' function in the profile"); + InspectorTest.completeTest(); +} + +function findFunctionInProfile(nodes, functionName) +{ + return nodes.some(n => n.callFrame.functionName === functionName); +}
diff --git a/src/v8/test/inspector/cpu-profiler/coverage-block-expected.txt b/src/v8/test/inspector/cpu-profiler/coverage-block-expected.txt new file mode 100644 index 0000000..32281e5 --- /dev/null +++ b/src/v8/test/inspector/cpu-profiler/coverage-block-expected.txt
@@ -0,0 +1,1112 @@ +Test collecting code coverage data with Profiler.collectCoverage. + +Running test: testPreciseCountBaseline +{ + id : <messageId> + result : { + result : [ + ] + } +} +{ + id : <messageId> + result : { + result : [ + ] + } +} + +Running test: testPreciseCountCoverage +{ + id : <messageId> + result : { + result : { + description : 8 + type : number + value : 8 + } + } +} +{ + id : <messageId> + result : { + result : [ + [0] : { + functions : [ + [0] : { + functionName : + isBlockCoverage : true + ranges : [ + [0] : { + count : 1 + endOffset : 221 + startOffset : 0 + } + ] + } + [1] : { + functionName : fib + isBlockCoverage : true + ranges : [ + [0] : { + count : 15 + endOffset : 73 + startOffset : 1 + } + [1] : { + count : 8 + endOffset : 41 + startOffset : 32 + } + [2] : { + count : 7 + endOffset : 71 + startOffset : 41 + } + [3] : { + count : 0 + endOffset : 72 + startOffset : 71 + } + ] + } + [2] : { + functionName : is_optimized + isBlockCoverage : false + ranges : [ + [0] : { + count : 0 + endOffset : 175 + startOffset : 74 + } + ] + } + [3] : { + functionName : iife + isBlockCoverage : true + ranges : [ + [0] : { + count : 1 + endOffset : 208 + startOffset : 177 + } + [1] : { + count : 0 + endOffset : 207 + startOffset : 206 + } + ] + } + ] + scriptId : <scriptId> + url : testPreciseCountCoverage + } + [1] : { + functions : [ + [0] : { + functionName : + isBlockCoverage : true + ranges : [ + [0] : { + count : 1 + endOffset : 38 + startOffset : 0 + } + ] + } + ] + scriptId : <scriptId> + url : + } + ] + } +} +{ + id : <messageId> + result : { + result : [ + ] + } +} + +Running test: testPreciseCountCoverageIncremental +{ + id : <messageId> + result : { + result : { + description : 8 + type : number + value : 8 + } + } +} +{ + id : <messageId> + result : { + result : [ + [0] : { + functions : [ + [0] : { + functionName : + isBlockCoverage : true + ranges : [ + [0] : { + count : 1 + endOffset : 221 + startOffset : 0 + } + ] + } + [1] : { + functionName : fib + isBlockCoverage : true + ranges : [ + [0] : { + count : 15 + endOffset : 73 + startOffset : 1 + } + [1] : { + count : 8 + endOffset : 41 + startOffset : 32 + } + [2] : { + count : 7 + endOffset : 71 + startOffset : 41 + } + [3] : { + count : 0 + endOffset : 72 + startOffset : 71 + } + ] + } + [2] : { + functionName : is_optimized + isBlockCoverage : false + ranges : [ + [0] : { + count : 0 + endOffset : 175 + startOffset : 74 + } + ] + } + [3] : { + functionName : iife + isBlockCoverage : true + ranges : [ + [0] : { + count : 1 + endOffset : 208 + startOffset : 177 + } + [1] : { + count : 0 + endOffset : 207 + startOffset : 206 + } + ] + } + ] + scriptId : <scriptId> + url : testPreciseCountCoverageIncremental + } + ] + } +} +{ + id : <messageId> + result : { + result : { + type : string + value : unoptimized + } + } +} +{ + id : <messageId> + result : { + result : { + description : 10946 + type : number + value : 10946 + } + } +} +{ + id : <messageId> + result : { + result : { + type : string + value : unoptimized + } + } +} +{ + id : <messageId> + result : { + result : [ + [0] : { + functions : [ + [0] : { + functionName : fib + isBlockCoverage : true + ranges : [ + [0] : { + count : 21891 + endOffset : 73 + startOffset : 1 + } + [1] : { + count : 10946 + endOffset : 41 + startOffset : 32 + } + [2] : { + count : 10945 + endOffset : 71 + startOffset : 41 + } + [3] : { + count : 0 + endOffset : 72 + startOffset : 71 + } + ] + } + [1] : { + functionName : is_optimized + isBlockCoverage : true + ranges : [ + [0] : { + count : 2 + endOffset : 175 + startOffset : 74 + } + [1] : { + count : 0 + endOffset : 156 + startOffset : 145 + } + [2] : { + count : 0 + endOffset : 174 + startOffset : 173 + } + ] + } + ] + scriptId : <scriptId> + url : testPreciseCountCoverageIncremental + } + [1] : { + functions : [ + [0] : { + functionName : + isBlockCoverage : true + ranges : [ + [0] : { + count : 2 + endOffset : 17 + startOffset : 0 + } + ] + } + ] + scriptId : <scriptId> + url : + } + [2] : { + functions : [ + [0] : { + functionName : + isBlockCoverage : true + ranges : [ + [0] : { + count : 1 + endOffset : 7 + startOffset : 0 + } + ] + } + ] + scriptId : <scriptId> + url : + } + ] + } +} + +Running test: testPreciseCoverageFail +{ + id : <messageId> + result : { + result : { + description : 8 + type : number + value : 8 + } + } +} +{ + error : { + code : -32000 + message : Precise coverage has not been started. + } + id : <messageId> +} + +Running test: testBestEffortCoverage +{ + id : <messageId> + result : { + result : { + description : 8 + type : number + value : 8 + } + } +} +{ + id : <messageId> + result : { + result : [ + ] + } +} +{ + id : <messageId> + result : { + result : [ + ] + } +} + +Running test: testBestEffortCoverageWithPreciseBinaryEnabled +{ + id : <messageId> + result : { + result : { + description : 8 + type : number + value : 8 + } + } +} +{ + id : <messageId> + result : { + result : [ + [0] : { + functions : [ + [0] : { + functionName : + isBlockCoverage : false + ranges : [ + [0] : { + count : 1 + endOffset : 221 + startOffset : 0 + } + ] + } + [1] : { + functionName : fib + isBlockCoverage : false + ranges : [ + [0] : { + count : 1 + endOffset : 73 + startOffset : 1 + } + ] + } + [2] : { + functionName : is_optimized + isBlockCoverage : false + ranges : [ + [0] : { + count : 0 + endOffset : 175 + startOffset : 74 + } + ] + } + [3] : { + functionName : iife + isBlockCoverage : false + ranges : [ + [0] : { + count : 1 + endOffset : 208 + startOffset : 177 + } + ] + } + ] + scriptId : <scriptId> + url : testBestEffortCoverageWithPreciseBinaryEnabled + } + [1] : { + functions : [ + [0] : { + functionName : + isBlockCoverage : false + ranges : [ + [0] : { + count : 1 + endOffset : 38 + startOffset : 0 + } + ] + } + ] + scriptId : <scriptId> + url : + } + ] + } +} +{ + id : <messageId> + result : { + result : [ + [0] : { + functions : [ + [0] : { + functionName : + isBlockCoverage : false + ranges : [ + [0] : { + count : 1 + endOffset : 221 + startOffset : 0 + } + ] + } + [1] : { + functionName : fib + isBlockCoverage : false + ranges : [ + [0] : { + count : 1 + endOffset : 73 + startOffset : 1 + } + ] + } + [2] : { + functionName : is_optimized + isBlockCoverage : false + ranges : [ + [0] : { + count : 0 + endOffset : 175 + startOffset : 74 + } + ] + } + [3] : { + functionName : iife + isBlockCoverage : false + ranges : [ + [0] : { + count : 1 + endOffset : 208 + startOffset : 177 + } + ] + } + ] + scriptId : <scriptId> + url : testBestEffortCoverageWithPreciseBinaryEnabled + } + [1] : { + functions : [ + [0] : { + functionName : + isBlockCoverage : false + ranges : [ + [0] : { + count : 1 + endOffset : 38 + startOffset : 0 + } + ] + } + ] + scriptId : <scriptId> + url : + } + ] + } +} + +Running test: testBestEffortCoverageWithPreciseCountEnabled +{ + id : <messageId> + result : { + result : { + description : 8 + type : number + value : 8 + } + } +} +{ + id : <messageId> + result : { + result : [ + [0] : { + functions : [ + [0] : { + functionName : + isBlockCoverage : false + ranges : [ + [0] : { + count : 1 + endOffset : 221 + startOffset : 0 + } + ] + } + [1] : { + functionName : fib + isBlockCoverage : false + ranges : [ + [0] : { + count : 1 + endOffset : 73 + startOffset : 1 + } + ] + } + [2] : { + functionName : is_optimized + isBlockCoverage : false + ranges : [ + [0] : { + count : 0 + endOffset : 175 + startOffset : 74 + } + ] + } + [3] : { + functionName : iife + isBlockCoverage : false + ranges : [ + [0] : { + count : 1 + endOffset : 208 + startOffset : 177 + } + ] + } + ] + scriptId : <scriptId> + url : testBestEffortCoverageWithPreciseCountEnabled + } + [1] : { + functions : [ + [0] : { + functionName : + isBlockCoverage : false + ranges : [ + [0] : { + count : 1 + endOffset : 38 + startOffset : 0 + } + ] + } + ] + scriptId : <scriptId> + url : + } + ] + } +} +{ + id : <messageId> + result : { + result : [ + [0] : { + functions : [ + [0] : { + functionName : + isBlockCoverage : false + ranges : [ + [0] : { + count : 1 + endOffset : 221 + startOffset : 0 + } + ] + } + [1] : { + functionName : fib + isBlockCoverage : false + ranges : [ + [0] : { + count : 1 + endOffset : 73 + startOffset : 1 + } + ] + } + [2] : { + functionName : is_optimized + isBlockCoverage : false + ranges : [ + [0] : { + count : 0 + endOffset : 175 + startOffset : 74 + } + ] + } + [3] : { + functionName : iife + isBlockCoverage : false + ranges : [ + [0] : { + count : 1 + endOffset : 208 + startOffset : 177 + } + ] + } + ] + scriptId : <scriptId> + url : testBestEffortCoverageWithPreciseCountEnabled + } + [1] : { + functions : [ + [0] : { + functionName : + isBlockCoverage : false + ranges : [ + [0] : { + count : 1 + endOffset : 38 + startOffset : 0 + } + ] + } + ] + scriptId : <scriptId> + url : + } + ] + } +} + +Running test: testEnablePreciseCountCoverageAtPause +{ + id : <messageId> + result : { + result : { + type : undefined + } + } +} +{ + id : <messageId> + result : { + result : [ + [0] : { + functions : [ + [0] : { + functionName : + isBlockCoverage : true + ranges : [ + [0] : { + count : 1 + endOffset : 38 + startOffset : 0 + } + ] + } + ] + scriptId : <scriptId> + url : + } + ] + } +} + +Running test: testPreciseBinaryCoverage +{ + id : <messageId> + result : { + result : { + description : 8 + type : number + value : 8 + } + } +} +{ + id : <messageId> + result : { + result : [ + [0] : { + functions : [ + [0] : { + functionName : + isBlockCoverage : true + ranges : [ + [0] : { + count : 1 + endOffset : 221 + startOffset : 0 + } + ] + } + [1] : { + functionName : fib + isBlockCoverage : true + ranges : [ + [0] : { + count : 1 + endOffset : 73 + startOffset : 1 + } + [1] : { + count : 0 + endOffset : 72 + startOffset : 71 + } + ] + } + [2] : { + functionName : is_optimized + isBlockCoverage : false + ranges : [ + [0] : { + count : 0 + endOffset : 175 + startOffset : 74 + } + ] + } + [3] : { + functionName : iife + isBlockCoverage : true + ranges : [ + [0] : { + count : 1 + endOffset : 208 + startOffset : 177 + } + [1] : { + count : 0 + endOffset : 207 + startOffset : 206 + } + ] + } + ] + scriptId : <scriptId> + url : testPreciseBinaryCoverage + } + ] + } +} +{ + id : <messageId> + result : { + result : { + type : string + value : unoptimized + } + } +} +{ + id : <messageId> + result : { + result : { + description : 10946 + type : number + value : 10946 + } + } +} +{ + id : <messageId> + result : { + result : { + type : string + value : optimized + } + } +} +{ + id : <messageId> + result : { + result : [ + [0] : { + functions : [ + [0] : { + functionName : fib + isBlockCoverage : true + ranges : [ + [0] : { + count : 0 + endOffset : 73 + startOffset : 1 + } + [1] : { + count : 1 + endOffset : 71 + startOffset : 32 + } + ] + } + [1] : { + functionName : is_optimized + isBlockCoverage : true + ranges : [ + [0] : { + count : 1 + endOffset : 175 + startOffset : 74 + } + [1] : { + count : 0 + endOffset : 174 + startOffset : 173 + } + ] + } + ] + scriptId : <scriptId> + url : testPreciseBinaryCoverage + } + [1] : { + functions : [ + [0] : { + functionName : + isBlockCoverage : true + ranges : [ + [0] : { + count : 1 + endOffset : 17 + startOffset : 0 + } + ] + } + ] + scriptId : <scriptId> + url : + } + [2] : { + functions : [ + [0] : { + functionName : + isBlockCoverage : true + ranges : [ + [0] : { + count : 1 + endOffset : 7 + startOffset : 0 + } + ] + } + ] + scriptId : <scriptId> + url : + } + ] + } +} + +Running test: testPreciseEmptyScriptCoverageEntries +{ + id : <messageId> + result : { + result : [ + ] + } +} + +Running test: testPreciseCountCoveragePartial +{ + id : <messageId> + result : { + result : { + type : undefined + } + } +} +{ + id : <messageId> + result : { + result : [ + [0] : { + functions : [ + [0] : { + functionName : + isBlockCoverage : true + ranges : [ + [0] : { + count : 1 + endOffset : 238 + startOffset : 0 + } + ] + } + [1] : { + functionName : outer + isBlockCoverage : true + ranges : [ + [0] : { + count : 1 + endOffset : 224 + startOffset : 10 + } + [1] : { + count : 0 + endOffset : 223 + startOffset : 222 + } + ] + } + [2] : { + functionName : nested_0 + isBlockCoverage : true + ranges : [ + [0] : { + count : 1 + endOffset : 176 + startOffset : 31 + } + [1] : { + count : 0 + endOffset : 175 + startOffset : 172 + } + ] + } + [3] : { + functionName : nested_1 + isBlockCoverage : true + ranges : [ + [0] : { + count : 1 + endOffset : 172 + startOffset : 64 + } + [1] : { + count : 0 + endOffset : 171 + startOffset : 166 + } + ] + } + [4] : { + functionName : nested_2 + isBlockCoverage : true + ranges : [ + [0] : { + count : 1 + endOffset : 166 + startOffset : 99 + } + [1] : { + count : 0 + endOffset : 165 + startOffset : 158 + } + ] + } + [5] : { + functionName : nested_3 + isBlockCoverage : true + ranges : [ + [0] : { + count : 1 + endOffset : 158 + startOffset : 136 + } + ] + } + [6] : { + functionName : nested_4 + isBlockCoverage : false + ranges : [ + [0] : { + count : 0 + endOffset : 201 + startOffset : 179 + } + ] + } + ] + scriptId : <scriptId> + url : testPreciseCountCoveragePartial + } + ] + } +} +{ + id : <messageId> + result : { + result : [ + [0] : { + functions : [ + [0] : { + functionName : nested_1 + isBlockCoverage : true + ranges : [ + [0] : { + count : 1 + endOffset : 172 + startOffset : 64 + } + [1] : { + count : 0 + endOffset : 171 + startOffset : 166 + } + ] + } + [1] : { + functionName : nested_2 + isBlockCoverage : true + ranges : [ + [0] : { + count : 0 + endOffset : 166 + startOffset : 99 + } + ] + } + ] + scriptId : <scriptId> + url : testPreciseCountCoveragePartial + } + [1] : { + functions : [ + [0] : { + functionName : + isBlockCoverage : true + ranges : [ + [0] : { + count : 1 + endOffset : 3 + startOffset : 0 + } + ] + } + ] + scriptId : <scriptId> + url : + } + ] + } +}
diff --git a/src/v8/test/inspector/cpu-profiler/coverage-block.js b/src/v8/test/inspector/cpu-profiler/coverage-block.js new file mode 100644 index 0000000..cba6d7d --- /dev/null +++ b/src/v8/test/inspector/cpu-profiler/coverage-block.js
@@ -0,0 +1,289 @@ +// 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 --no-always-opt --opt + +var source = +` +function fib(x) { + if (x < 2) return 1; + return fib(x-1) + fib(x-2); +} +function is_optimized(f) { + return (%GetOptimizationStatus(f) & 16) ? "optimized" : "unoptimized"; +} +(function iife() { + return 1; +})(); +fib(5); +`; + +var break_source = +` +function g() { + debugger; +} +function f(x) { + if (x == 0) g(); + else f(x - 1); +} +function h() { + g(); +} +f(3); +`; + +var nested = +` +var f = (function outer() { + function nested_0() { + return function nested_1() { + return function nested_2() { + return function nested_3() {} + } + } + } + function nested_4() {} + return nested_0(); +})(); +f()()(); +`; + +let {session, contextGroup, Protocol} = InspectorTest.start("Test collecting code coverage data with Profiler.collectCoverage."); + +function ClearAndGC() { + return Protocol.Runtime.evaluate({ expression: "fib = g = f = h = is_optimized = null;" }) + .then(GC); +} + +function GC() { + return Protocol.HeapProfiler.collectGarbage(); +} + +function LogSorted(message) { + message.result.result.sort((a, b) => parseInt(a.scriptId) - parseInt(b.scriptId)); + return InspectorTest.logMessage(message); +} + +InspectorTest.runTestSuite([ + function testPreciseCountBaseline(next) + { + Protocol.Runtime.enable() + .then(() => Protocol.Runtime.compileScript({ expression: source, sourceURL: arguments.callee.name, persistScript: true })) + .then((result) => Protocol.Runtime.runScript({ scriptId: result.result.scriptId })) + .then(GC) + .then(Protocol.Profiler.enable) + .then(() => Protocol.Profiler.startPreciseCoverage({callCount: true, detailed: true})) + .then(Protocol.Profiler.takePreciseCoverage) + .then(LogSorted) + .then(Protocol.Profiler.takePreciseCoverage) + .then(LogSorted) + .then(Protocol.Profiler.stopPreciseCoverage) + .then(Protocol.Profiler.disable) + .then(Protocol.Runtime.disable) + .then(ClearAndGC) + .then(next); + }, + function testPreciseCountCoverage(next) + { + Protocol.Runtime.enable() + .then(Protocol.Profiler.enable) + .then(() => Protocol.Profiler.startPreciseCoverage({callCount: true, detailed: true})) + .then(() => Protocol.Runtime.compileScript({ expression: source, sourceURL: arguments.callee.name, persistScript: true })) + .then((result) => Protocol.Runtime.runScript({ scriptId: result.result.scriptId })) + .then(InspectorTest.logMessage) + .then(ClearAndGC) + .then(Protocol.Profiler.takePreciseCoverage) + .then(LogSorted) + .then(Protocol.Profiler.takePreciseCoverage) + .then(LogSorted) + .then(Protocol.Profiler.stopPreciseCoverage) + .then(Protocol.Profiler.disable) + .then(Protocol.Runtime.disable) + .then(ClearAndGC) + .then(next); + }, + function testPreciseCountCoverageIncremental(next) + { + Protocol.Runtime.enable() + .then(Protocol.Profiler.enable) + .then(() => Protocol.Profiler.startPreciseCoverage({callCount: true, detailed: true})) + .then(() => Protocol.Runtime.compileScript({ expression: source, sourceURL: arguments.callee.name, persistScript: true })) + .then((result) => Protocol.Runtime.runScript({ scriptId: result.result.scriptId })) + .then(InspectorTest.logMessage) + .then(Protocol.Profiler.takePreciseCoverage) + .then(LogSorted) + .then(() => Protocol.Runtime.evaluate({ expression: "is_optimized(fib)" })) + .then(message => InspectorTest.logMessage(message)) + .then(() => Protocol.Runtime.evaluate({ expression: "fib(20)" })) + .then(message => InspectorTest.logMessage(message)) + .then(() => Protocol.Runtime.evaluate({ expression: "is_optimized(fib)" })) + .then(message => InspectorTest.logMessage(message)) + .then(Protocol.Profiler.takePreciseCoverage) + .then(LogSorted) + .then(Protocol.Profiler.stopPreciseCoverage) + .then(Protocol.Profiler.disable) + .then(Protocol.Runtime.disable) + .then(ClearAndGC) + .then(next); + }, + function testPreciseCoverageFail(next) + { + Protocol.Runtime.enable() + .then(Protocol.Profiler.enable) + .then(() => Protocol.Runtime.compileScript({ expression: source, sourceURL: arguments.callee.name, persistScript: true })) + .then((result) => Protocol.Runtime.runScript({ scriptId: result.result.scriptId })) + .then(InspectorTest.logMessage) + .then(ClearAndGC) + .then(Protocol.Profiler.takePreciseCoverage) + .then(InspectorTest.logMessage) + .then(Protocol.Profiler.disable) + .then(Protocol.Runtime.disable) + .then(ClearAndGC) + .then(next); + }, + function testBestEffortCoverage(next) + { + Protocol.Runtime.enable() + .then(() => Protocol.Runtime.compileScript({ expression: source, sourceURL: arguments.callee.name, persistScript: true })) + .then((result) => Protocol.Runtime.runScript({ scriptId: result.result.scriptId })) + .then(InspectorTest.logMessage) + .then(ClearAndGC) + .then(Protocol.Profiler.getBestEffortCoverage) + .then(LogSorted) + .then(Protocol.Profiler.getBestEffortCoverage) + .then(LogSorted) + .then(Protocol.Runtime.disable) + .then(ClearAndGC) + .then(next); + }, + function testBestEffortCoverageWithPreciseBinaryEnabled(next) + { + Protocol.Runtime.enable() + .then(Protocol.Profiler.enable) + .then(() => Protocol.Profiler.startPreciseCoverage({detailed: true})) + .then(() => Protocol.Runtime.compileScript({ expression: source, sourceURL: arguments.callee.name, persistScript: true })) + .then((result) => Protocol.Runtime.runScript({ scriptId: result.result.scriptId })) + .then(InspectorTest.logMessage) + .then(ClearAndGC) + .then(Protocol.Profiler.getBestEffortCoverage) + .then(LogSorted) + .then(Protocol.Profiler.getBestEffortCoverage) + .then(LogSorted) + .then(ClearAndGC) + .then(Protocol.Profiler.stopPreciseCoverage) + .then(Protocol.Profiler.disable) + .then(Protocol.Runtime.disable) + .then(ClearAndGC) + .then(next); + }, + function testBestEffortCoverageWithPreciseCountEnabled(next) + { + Protocol.Runtime.enable() + .then(Protocol.Profiler.enable) + .then(() => Protocol.Profiler.startPreciseCoverage({callCount: true, detailed: true})) + .then(() => Protocol.Runtime.compileScript({ expression: source, sourceURL: arguments.callee.name, persistScript: true })) + .then((result) => Protocol.Runtime.runScript({ scriptId: result.result.scriptId })) + .then(InspectorTest.logMessage) + .then(ClearAndGC) + .then(Protocol.Profiler.getBestEffortCoverage) + .then(LogSorted) + .then(Protocol.Profiler.getBestEffortCoverage) + .then(LogSorted) + .then(ClearAndGC) + .then(Protocol.Profiler.stopPreciseCoverage) + .then(Protocol.Profiler.disable) + .then(Protocol.Runtime.disable) + .then(ClearAndGC) + .then(next); + }, + function testEnablePreciseCountCoverageAtPause(next) + { + function handleDebuggerPause() { + Protocol.Profiler.enable() + .then(() => Protocol.Profiler.startPreciseCoverage({callCount: true, detailed: true})) + .then(Protocol.Debugger.resume) + } + Protocol.Debugger.enable(); + Protocol.Debugger.oncePaused().then(handleDebuggerPause); + Protocol.Runtime.enable() + .then(() => Protocol.Runtime.compileScript({ expression: break_source, sourceURL: arguments.callee.name, persistScript: true })) + .then((result) => Protocol.Runtime.runScript({ scriptId: result.result.scriptId })) + .then(InspectorTest.logMessage) + .then(ClearAndGC) + .then(Protocol.Profiler.takePreciseCoverage) + .then(LogSorted) + .then(ClearAndGC) + .then(Protocol.Profiler.stopPreciseCoverage) + .then(Protocol.Profiler.disable) + .then(Protocol.Runtime.disable) + .then(Protocol.Debugger.disable) + .then(ClearAndGC) + .then(next); + }, + function testPreciseBinaryCoverage(next) + { + Protocol.Runtime.enable() + .then(Protocol.Profiler.enable) + .then(() => Protocol.Profiler.startPreciseCoverage({detailed: true})) + .then(() => Protocol.Runtime.compileScript({ expression: source, sourceURL: arguments.callee.name, persistScript: true })) + .then((result) => Protocol.Runtime.runScript({ scriptId: result.result.scriptId })) + .then(InspectorTest.logMessage) + .then(Protocol.Profiler.takePreciseCoverage) + .then(LogSorted) + .then(() => Protocol.Runtime.evaluate({ expression: "is_optimized(fib)" })) + .then(message => InspectorTest.logMessage(message)) + .then(() => Protocol.Runtime.evaluate({ expression: "fib(20)" })) + .then(message => InspectorTest.logMessage(message)) + .then(() => Protocol.Runtime.evaluate({ expression: "is_optimized(fib)" })) + .then(message => InspectorTest.logMessage(message)) + .then(Protocol.Profiler.takePreciseCoverage) + .then(LogSorted) + .then(Protocol.Profiler.stopPreciseCoverage) + .then(Protocol.Profiler.disable) + .then(Protocol.Runtime.disable) + .then(ClearAndGC) + .then(next); + }, + function testPreciseEmptyScriptCoverageEntries(next) + { + // Enabling the debugger holds onto script objects even though its + // functions can be garbage collected. We would get empty ScriptCoverage + // entires unless we remove them. + Protocol.Debugger.enable() + .then(Protocol.Runtime.enable) + .then(() => Protocol.Runtime.compileScript({ expression: source, sourceURL: arguments.callee.name, persistScript: true })) + .then((result) => Protocol.Runtime.runScript({ scriptId: result.result.scriptId })) + .then(ClearAndGC) + .then(Protocol.Profiler.enable) + .then(() => Protocol.Profiler.startPreciseCoverage({detailed: true})) + .then(Protocol.Profiler.takePreciseCoverage) + .then(LogSorted) + .then(Protocol.Profiler.stopPreciseCoverage) + .then(Protocol.Profiler.disable) + .then(Protocol.Runtime.disable) + .then(Protocol.Debugger.disable) + .then(ClearAndGC) + .then(next); + }, + function testPreciseCountCoveragePartial(next) + { + Protocol.Runtime.enable() + .then(Protocol.Profiler.enable) + .then(() => Protocol.Profiler.startPreciseCoverage({callCount: true, detailed: true})) + .then(() => Protocol.Runtime.compileScript({ expression: nested, sourceURL: arguments.callee.name, persistScript: true })) + .then((result) => Protocol.Runtime.runScript({ scriptId: result.result.scriptId })) + .then(InspectorTest.logMessage) + .then(Protocol.Profiler.takePreciseCoverage) + .then(LogSorted) + .then(() => Protocol.Runtime.evaluate({ expression: "f()" })) + .then(Protocol.Profiler.takePreciseCoverage) + .then(LogSorted) + .then(Protocol.Profiler.stopPreciseCoverage) + .then(Protocol.Profiler.disable) + .then(Protocol.Runtime.disable) + .then(ClearAndGC) + .then(next); + }, +]);
diff --git a/src/v8/test/inspector/cpu-profiler/coverage-expected.txt b/src/v8/test/inspector/cpu-profiler/coverage-expected.txt new file mode 100644 index 0000000..15b4101 --- /dev/null +++ b/src/v8/test/inspector/cpu-profiler/coverage-expected.txt
@@ -0,0 +1,825 @@ +Test collecting code coverage data with Profiler.collectCoverage. + +Running test: testPreciseCountBaseline +{ + id : <messageId> + result : { + result : [ + ] + } +} +{ + id : <messageId> + result : { + result : [ + ] + } +} + +Running test: testPreciseCountCoverage +{ + id : <messageId> + result : { + result : { + description : 8 + type : number + value : 8 + } + } +} +{ + id : <messageId> + result : { + result : [ + [0] : { + functions : [ + [0] : { + functionName : + isBlockCoverage : false + ranges : [ + [0] : { + count : 1 + endOffset : 221 + startOffset : 0 + } + ] + } + [1] : { + functionName : fib + isBlockCoverage : false + ranges : [ + [0] : { + count : 15 + endOffset : 73 + startOffset : 1 + } + ] + } + [2] : { + functionName : is_optimized + isBlockCoverage : false + ranges : [ + [0] : { + count : 0 + endOffset : 175 + startOffset : 74 + } + ] + } + [3] : { + functionName : iife + isBlockCoverage : false + ranges : [ + [0] : { + count : 1 + endOffset : 208 + startOffset : 177 + } + ] + } + ] + scriptId : <scriptId> + url : testPreciseCountCoverage + } + [1] : { + functions : [ + [0] : { + functionName : + isBlockCoverage : false + ranges : [ + [0] : { + count : 1 + endOffset : 38 + startOffset : 0 + } + ] + } + ] + scriptId : <scriptId> + url : + } + ] + } +} +{ + id : <messageId> + result : { + result : [ + ] + } +} + +Running test: testPreciseCoverageFail +{ + id : <messageId> + result : { + result : { + description : 8 + type : number + value : 8 + } + } +} +{ + error : { + code : -32000 + message : Precise coverage has not been started. + } + id : <messageId> +} + +Running test: testBestEffortCoverage +{ + id : <messageId> + result : { + result : { + description : 8 + type : number + value : 8 + } + } +} +{ + id : <messageId> + result : { + result : [ + ] + } +} +{ + id : <messageId> + result : { + result : [ + ] + } +} + +Running test: testBestEffortCoverageWithPreciseBinaryEnabled +{ + id : <messageId> + result : { + result : { + description : 8 + type : number + value : 8 + } + } +} +{ + id : <messageId> + result : { + result : [ + [0] : { + functions : [ + [0] : { + functionName : + isBlockCoverage : false + ranges : [ + [0] : { + count : 1 + endOffset : 221 + startOffset : 0 + } + ] + } + [1] : { + functionName : fib + isBlockCoverage : false + ranges : [ + [0] : { + count : 1 + endOffset : 73 + startOffset : 1 + } + ] + } + [2] : { + functionName : is_optimized + isBlockCoverage : false + ranges : [ + [0] : { + count : 0 + endOffset : 175 + startOffset : 74 + } + ] + } + [3] : { + functionName : iife + isBlockCoverage : false + ranges : [ + [0] : { + count : 1 + endOffset : 208 + startOffset : 177 + } + ] + } + ] + scriptId : <scriptId> + url : testBestEffortCoverageWithPreciseBinaryEnabled + } + [1] : { + functions : [ + [0] : { + functionName : + isBlockCoverage : false + ranges : [ + [0] : { + count : 1 + endOffset : 38 + startOffset : 0 + } + ] + } + ] + scriptId : <scriptId> + url : + } + ] + } +} +{ + id : <messageId> + result : { + result : [ + [0] : { + functions : [ + [0] : { + functionName : + isBlockCoverage : false + ranges : [ + [0] : { + count : 1 + endOffset : 221 + startOffset : 0 + } + ] + } + [1] : { + functionName : fib + isBlockCoverage : false + ranges : [ + [0] : { + count : 1 + endOffset : 73 + startOffset : 1 + } + ] + } + [2] : { + functionName : is_optimized + isBlockCoverage : false + ranges : [ + [0] : { + count : 0 + endOffset : 175 + startOffset : 74 + } + ] + } + [3] : { + functionName : iife + isBlockCoverage : false + ranges : [ + [0] : { + count : 1 + endOffset : 208 + startOffset : 177 + } + ] + } + ] + scriptId : <scriptId> + url : testBestEffortCoverageWithPreciseBinaryEnabled + } + [1] : { + functions : [ + [0] : { + functionName : + isBlockCoverage : false + ranges : [ + [0] : { + count : 1 + endOffset : 38 + startOffset : 0 + } + ] + } + ] + scriptId : <scriptId> + url : + } + ] + } +} + +Running test: testBestEffortCoverageWithPreciseCountEnabled +{ + id : <messageId> + result : { + result : { + description : 8 + type : number + value : 8 + } + } +} +{ + id : <messageId> + result : { + result : [ + [0] : { + functions : [ + [0] : { + functionName : + isBlockCoverage : false + ranges : [ + [0] : { + count : 1 + endOffset : 221 + startOffset : 0 + } + ] + } + [1] : { + functionName : fib + isBlockCoverage : false + ranges : [ + [0] : { + count : 1 + endOffset : 73 + startOffset : 1 + } + ] + } + [2] : { + functionName : is_optimized + isBlockCoverage : false + ranges : [ + [0] : { + count : 0 + endOffset : 175 + startOffset : 74 + } + ] + } + [3] : { + functionName : iife + isBlockCoverage : false + ranges : [ + [0] : { + count : 1 + endOffset : 208 + startOffset : 177 + } + ] + } + ] + scriptId : <scriptId> + url : testBestEffortCoverageWithPreciseCountEnabled + } + [1] : { + functions : [ + [0] : { + functionName : + isBlockCoverage : false + ranges : [ + [0] : { + count : 1 + endOffset : 38 + startOffset : 0 + } + ] + } + ] + scriptId : <scriptId> + url : + } + ] + } +} +{ + id : <messageId> + result : { + result : [ + [0] : { + functions : [ + [0] : { + functionName : + isBlockCoverage : false + ranges : [ + [0] : { + count : 1 + endOffset : 221 + startOffset : 0 + } + ] + } + [1] : { + functionName : fib + isBlockCoverage : false + ranges : [ + [0] : { + count : 1 + endOffset : 73 + startOffset : 1 + } + ] + } + [2] : { + functionName : is_optimized + isBlockCoverage : false + ranges : [ + [0] : { + count : 0 + endOffset : 175 + startOffset : 74 + } + ] + } + [3] : { + functionName : iife + isBlockCoverage : false + ranges : [ + [0] : { + count : 1 + endOffset : 208 + startOffset : 177 + } + ] + } + ] + scriptId : <scriptId> + url : testBestEffortCoverageWithPreciseCountEnabled + } + [1] : { + functions : [ + [0] : { + functionName : + isBlockCoverage : false + ranges : [ + [0] : { + count : 1 + endOffset : 38 + startOffset : 0 + } + ] + } + ] + scriptId : <scriptId> + url : + } + ] + } +} + +Running test: testEnablePreciseCountCoverageAtPause +{ + id : <messageId> + result : { + result : { + type : undefined + } + } +} +{ + id : <messageId> + result : { + result : [ + [0] : { + functions : [ + [0] : { + functionName : + isBlockCoverage : false + ranges : [ + [0] : { + count : 1 + endOffset : 38 + startOffset : 0 + } + ] + } + ] + scriptId : <scriptId> + url : + } + ] + } +} + +Running test: testPreciseBinaryCoverage +{ + id : <messageId> + result : { + result : { + description : 8 + type : number + value : 8 + } + } +} +{ + id : <messageId> + result : { + result : [ + [0] : { + functions : [ + [0] : { + functionName : + isBlockCoverage : false + ranges : [ + [0] : { + count : 1 + endOffset : 221 + startOffset : 0 + } + ] + } + [1] : { + functionName : fib + isBlockCoverage : false + ranges : [ + [0] : { + count : 1 + endOffset : 73 + startOffset : 1 + } + ] + } + [2] : { + functionName : is_optimized + isBlockCoverage : false + ranges : [ + [0] : { + count : 0 + endOffset : 175 + startOffset : 74 + } + ] + } + [3] : { + functionName : iife + isBlockCoverage : false + ranges : [ + [0] : { + count : 1 + endOffset : 208 + startOffset : 177 + } + ] + } + ] + scriptId : <scriptId> + url : testPreciseBinaryCoverage + } + ] + } +} +{ + id : <messageId> + result : { + result : { + type : string + value : unoptimized + } + } +} +{ + id : <messageId> + result : { + result : { + description : 10946 + type : number + value : 10946 + } + } +} +{ + id : <messageId> + result : { + result : { + type : string + value : optimized + } + } +} +{ + id : <messageId> + result : { + result : [ + [0] : { + functions : [ + [0] : { + functionName : is_optimized + isBlockCoverage : false + ranges : [ + [0] : { + count : 1 + endOffset : 175 + startOffset : 74 + } + ] + } + ] + scriptId : <scriptId> + url : testPreciseBinaryCoverage + } + [1] : { + functions : [ + [0] : { + functionName : + isBlockCoverage : false + ranges : [ + [0] : { + count : 1 + endOffset : 17 + startOffset : 0 + } + ] + } + ] + scriptId : <scriptId> + url : + } + [2] : { + functions : [ + [0] : { + functionName : + isBlockCoverage : false + ranges : [ + [0] : { + count : 1 + endOffset : 7 + startOffset : 0 + } + ] + } + ] + scriptId : <scriptId> + url : + } + ] + } +} + +Running test: testPreciseEmptyScriptCoverageEntries +{ + id : <messageId> + result : { + result : [ + ] + } +} + +Running test: testPreciseCountCoveragePartial +{ + id : <messageId> + result : { + result : { + type : undefined + } + } +} +{ + id : <messageId> + result : { + result : [ + [0] : { + functions : [ + [0] : { + functionName : + isBlockCoverage : false + ranges : [ + [0] : { + count : 1 + endOffset : 238 + startOffset : 0 + } + ] + } + [1] : { + functionName : outer + isBlockCoverage : false + ranges : [ + [0] : { + count : 1 + endOffset : 224 + startOffset : 10 + } + ] + } + [2] : { + functionName : nested_0 + isBlockCoverage : false + ranges : [ + [0] : { + count : 1 + endOffset : 176 + startOffset : 31 + } + ] + } + [3] : { + functionName : nested_1 + isBlockCoverage : false + ranges : [ + [0] : { + count : 1 + endOffset : 172 + startOffset : 64 + } + ] + } + [4] : { + functionName : nested_2 + isBlockCoverage : false + ranges : [ + [0] : { + count : 1 + endOffset : 166 + startOffset : 99 + } + ] + } + [5] : { + functionName : nested_3 + isBlockCoverage : false + ranges : [ + [0] : { + count : 1 + endOffset : 158 + startOffset : 136 + } + ] + } + [6] : { + functionName : nested_4 + isBlockCoverage : false + ranges : [ + [0] : { + count : 0 + endOffset : 201 + startOffset : 179 + } + ] + } + ] + scriptId : <scriptId> + url : testPreciseCountCoveragePartial + } + ] + } +} +{ + id : <messageId> + result : { + result : [ + [0] : { + functions : [ + [0] : { + functionName : nested_1 + isBlockCoverage : false + ranges : [ + [0] : { + count : 1 + endOffset : 172 + startOffset : 64 + } + ] + } + [1] : { + functionName : nested_2 + isBlockCoverage : false + ranges : [ + [0] : { + count : 0 + endOffset : 166 + startOffset : 99 + } + ] + } + ] + scriptId : <scriptId> + url : testPreciseCountCoveragePartial + } + [1] : { + functions : [ + [0] : { + functionName : + isBlockCoverage : false + ranges : [ + [0] : { + count : 1 + endOffset : 3 + startOffset : 0 + } + ] + } + ] + scriptId : <scriptId> + url : + } + ] + } +}
diff --git a/src/v8/test/inspector/cpu-profiler/coverage.js b/src/v8/test/inspector/cpu-profiler/coverage.js new file mode 100644 index 0000000..dbad54b --- /dev/null +++ b/src/v8/test/inspector/cpu-profiler/coverage.js
@@ -0,0 +1,265 @@ +// 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 --no-always-opt --opt + +var source = +` +function fib(x) { + if (x < 2) return 1; + return fib(x-1) + fib(x-2); +} +function is_optimized(f) { + return (%GetOptimizationStatus(f) & 16) ? "optimized" : "unoptimized"; +} +(function iife() { + return 1; +})(); +fib(5); +`; + +var break_source = +` +function g() { + debugger; +} +function f(x) { + if (x == 0) g(); + else f(x - 1); +} +function h() { + g(); +} +f(3); +`; + +var nested = +` +var f = (function outer() { + function nested_0() { + return function nested_1() { + return function nested_2() { + return function nested_3() {} + } + } + } + function nested_4() {} + return nested_0(); +})(); +f()()(); +`; + +let {session, contextGroup, Protocol} = InspectorTest.start("Test collecting code coverage data with Profiler.collectCoverage."); + +function ClearAndGC() { + return Protocol.Runtime.evaluate({ expression: "fib = g = f = h = is_optimized = null;" }) + .then(GC); +} + +function GC() { + return Protocol.HeapProfiler.collectGarbage(); +} + +function LogSorted(message) { + message.result.result.sort((a, b) => parseInt(a.scriptId) - parseInt(b.scriptId)); + return InspectorTest.logMessage(message); +} + +InspectorTest.runTestSuite([ + function testPreciseCountBaseline(next) + { + Protocol.Runtime.enable() + .then(() => Protocol.Runtime.compileScript({ expression: source, sourceURL: arguments.callee.name, persistScript: true })) + .then((result) => Protocol.Runtime.runScript({ scriptId: result.result.scriptId })) + .then(GC) + .then(Protocol.Profiler.enable) + .then(() => Protocol.Profiler.startPreciseCoverage({callCount: true, detailed: false})) + .then(Protocol.Profiler.takePreciseCoverage) + .then(LogSorted) + .then(Protocol.Profiler.takePreciseCoverage) + .then(LogSorted) + .then(Protocol.Profiler.stopPreciseCoverage) + .then(Protocol.Profiler.disable) + .then(Protocol.Runtime.disable) + .then(ClearAndGC) + .then(next); + }, + function testPreciseCountCoverage(next) + { + Protocol.Runtime.enable() + .then(Protocol.Profiler.enable) + .then(() => Protocol.Profiler.startPreciseCoverage({callCount: true, detailed: false})) + .then(() => Protocol.Runtime.compileScript({ expression: source, sourceURL: arguments.callee.name, persistScript: true })) + .then((result) => Protocol.Runtime.runScript({ scriptId: result.result.scriptId })) + .then(InspectorTest.logMessage) + .then(ClearAndGC) + .then(Protocol.Profiler.takePreciseCoverage) + .then(LogSorted) + .then(Protocol.Profiler.takePreciseCoverage) + .then(LogSorted) + .then(Protocol.Profiler.stopPreciseCoverage) + .then(Protocol.Profiler.disable) + .then(Protocol.Runtime.disable) + .then(ClearAndGC) + .then(next); + }, + function testPreciseCoverageFail(next) + { + Protocol.Runtime.enable() + .then(Protocol.Profiler.enable) + .then(() => Protocol.Runtime.compileScript({ expression: source, sourceURL: arguments.callee.name, persistScript: true })) + .then((result) => Protocol.Runtime.runScript({ scriptId: result.result.scriptId })) + .then(InspectorTest.logMessage) + .then(ClearAndGC) + .then(Protocol.Profiler.takePreciseCoverage) + .then(InspectorTest.logMessage) + .then(Protocol.Profiler.disable) + .then(Protocol.Runtime.disable) + .then(ClearAndGC) + .then(next); + }, + function testBestEffortCoverage(next) + { + Protocol.Runtime.enable() + .then(() => Protocol.Runtime.compileScript({ expression: source, sourceURL: arguments.callee.name, persistScript: true })) + .then((result) => Protocol.Runtime.runScript({ scriptId: result.result.scriptId })) + .then(InspectorTest.logMessage) + .then(ClearAndGC) + .then(Protocol.Profiler.getBestEffortCoverage) + .then(LogSorted) + .then(Protocol.Profiler.getBestEffortCoverage) + .then(LogSorted) + .then(Protocol.Runtime.disable) + .then(ClearAndGC) + .then(next); + }, + function testBestEffortCoverageWithPreciseBinaryEnabled(next) + { + Protocol.Runtime.enable() + .then(Protocol.Profiler.enable) + .then(() => Protocol.Profiler.startPreciseCoverage({detailed: false})) + .then(() => Protocol.Runtime.compileScript({ expression: source, sourceURL: arguments.callee.name, persistScript: true })) + .then((result) => Protocol.Runtime.runScript({ scriptId: result.result.scriptId })) + .then(InspectorTest.logMessage) + .then(ClearAndGC) + .then(Protocol.Profiler.getBestEffortCoverage) + .then(LogSorted) + .then(Protocol.Profiler.getBestEffortCoverage) + .then(LogSorted) + .then(ClearAndGC) + .then(Protocol.Profiler.stopPreciseCoverage) + .then(Protocol.Profiler.disable) + .then(Protocol.Runtime.disable) + .then(ClearAndGC) + .then(next); + }, + function testBestEffortCoverageWithPreciseCountEnabled(next) + { + Protocol.Runtime.enable() + .then(Protocol.Profiler.enable) + .then(() => Protocol.Profiler.startPreciseCoverage({callCount: true, detailed: false})) + .then(() => Protocol.Runtime.compileScript({ expression: source, sourceURL: arguments.callee.name, persistScript: true })) + .then((result) => Protocol.Runtime.runScript({ scriptId: result.result.scriptId })) + .then(InspectorTest.logMessage) + .then(ClearAndGC) + .then(Protocol.Profiler.getBestEffortCoverage) + .then(LogSorted) + .then(Protocol.Profiler.getBestEffortCoverage) + .then(LogSorted) + .then(ClearAndGC) + .then(Protocol.Profiler.stopPreciseCoverage) + .then(Protocol.Profiler.disable) + .then(Protocol.Runtime.disable) + .then(ClearAndGC) + .then(next); + }, + function testEnablePreciseCountCoverageAtPause(next) + { + function handleDebuggerPause() { + Protocol.Profiler.enable() + .then(() => Protocol.Profiler.startPreciseCoverage({callCount: true, detailed: false})) + .then(Protocol.Debugger.resume) + } + Protocol.Debugger.enable(); + Protocol.Debugger.oncePaused().then(handleDebuggerPause); + Protocol.Runtime.enable() + .then(() => Protocol.Runtime.compileScript({ expression: break_source, sourceURL: arguments.callee.name, persistScript: true })) + .then((result) => Protocol.Runtime.runScript({ scriptId: result.result.scriptId })) + .then(InspectorTest.logMessage) + .then(ClearAndGC) + .then(Protocol.Profiler.takePreciseCoverage) + .then(LogSorted) + .then(ClearAndGC) + .then(Protocol.Profiler.stopPreciseCoverage) + .then(Protocol.Profiler.disable) + .then(Protocol.Runtime.disable) + .then(Protocol.Debugger.disable) + .then(ClearAndGC) + .then(next); + }, + function testPreciseBinaryCoverage(next) + { + Protocol.Runtime.enable() + .then(Protocol.Profiler.enable) + .then(() => Protocol.Profiler.startPreciseCoverage({detailed: false})) + .then(() => Protocol.Runtime.compileScript({ expression: source, sourceURL: arguments.callee.name, persistScript: true })) + .then((result) => Protocol.Runtime.runScript({ scriptId: result.result.scriptId })) + .then(InspectorTest.logMessage) + .then(Protocol.Profiler.takePreciseCoverage) + .then(LogSorted) + .then(() => Protocol.Runtime.evaluate({ expression: "is_optimized(fib)" })) + .then(message => InspectorTest.logMessage(message)) + .then(() => Protocol.Runtime.evaluate({ expression: "fib(20)" })) + .then(message => InspectorTest.logMessage(message)) + .then(() => Protocol.Runtime.evaluate({ expression: "is_optimized(fib)" })) + .then(message => InspectorTest.logMessage(message)) + .then(Protocol.Profiler.takePreciseCoverage) + .then(LogSorted) + .then(Protocol.Profiler.stopPreciseCoverage) + .then(Protocol.Profiler.disable) + .then(Protocol.Runtime.disable) + .then(ClearAndGC) + .then(next); + }, + function testPreciseEmptyScriptCoverageEntries(next) + { + // Enabling the debugger holds onto script objects even though its + // functions can be garbage collected. We would get empty ScriptCoverage + // entries unless we remove them. + Protocol.Debugger.enable() + .then(Protocol.Runtime.enable) + .then(() => Protocol.Runtime.compileScript({ expression: source, sourceURL: arguments.callee.name, persistScript: true })) + .then((result) => Protocol.Runtime.runScript({ scriptId: result.result.scriptId })) + .then(ClearAndGC) + .then(Protocol.Profiler.enable) + .then(() => Protocol.Profiler.startPreciseCoverage({detailed: false})) + .then(Protocol.Profiler.takePreciseCoverage) + .then(LogSorted) + .then(Protocol.Profiler.stopPreciseCoverage) + .then(Protocol.Profiler.disable) + .then(Protocol.Runtime.disable) + .then(Protocol.Debugger.disable) + .then(ClearAndGC) + .then(next); + }, + function testPreciseCountCoveragePartial(next) + { + Protocol.Runtime.enable() + .then(Protocol.Profiler.enable) + .then(() => Protocol.Profiler.startPreciseCoverage({callCount: true, detailed: false})) + .then(() => Protocol.Runtime.compileScript({ expression: nested, sourceURL: arguments.callee.name, persistScript: true })) + .then((result) => Protocol.Runtime.runScript({ scriptId: result.result.scriptId })) + .then(InspectorTest.logMessage) + .then(Protocol.Profiler.takePreciseCoverage) + .then(LogSorted) + .then(() => Protocol.Runtime.evaluate({ expression: "f()" })) + .then(Protocol.Profiler.takePreciseCoverage) + .then(LogSorted) + .then(Protocol.Profiler.stopPreciseCoverage) + .then(Protocol.Profiler.disable) + .then(Protocol.Runtime.disable) + .then(ClearAndGC) + .then(next); + }, +]);
diff --git a/src/v8/test/inspector/cpu-profiler/enable-disable-expected.txt b/src/v8/test/inspector/cpu-profiler/enable-disable-expected.txt new file mode 100644 index 0000000..aa3507c --- /dev/null +++ b/src/v8/test/inspector/cpu-profiler/enable-disable-expected.txt
@@ -0,0 +1,8 @@ +Test that profiling can only be started when Profiler was enabled and that Profiler.disable command will stop recording all profiles. +PASS: didFailToStartWhenDisabled +PASS: didStartFrontendProfile +PASS: console initiated profile started +PASS: didStartConsoleProfile +PASS: didDisableProfiler +PASS: no front-end initiated profiles found +PASS: didStopConsoleProfile
diff --git a/src/v8/test/inspector/cpu-profiler/enable-disable.js b/src/v8/test/inspector/cpu-profiler/enable-disable.js new file mode 100644 index 0000000..0e9b94d --- /dev/null +++ b/src/v8/test/inspector/cpu-profiler/enable-disable.js
@@ -0,0 +1,89 @@ +// 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 that profiling can only be started when Profiler was enabled and that Profiler.disable command will stop recording all profiles."); + +Protocol.Profiler.start().then(didFailToStartWhenDisabled); +disallowConsoleProfiles(); + +function disallowConsoleProfiles() +{ + Protocol.Profiler.onConsoleProfileStarted(function(messageObject) + { + InspectorTest.log("FAIL: console profile started " + JSON.stringify(messageObject, null, 4)); + }); + Protocol.Profiler.onConsoleProfileFinished(function(messageObject) + { + InspectorTest.log("FAIL: unexpected profile received " + JSON.stringify(messageObject, null, 4)); + }); +} +function allowConsoleProfiles() +{ + Protocol.Profiler.onConsoleProfileStarted(function(messageObject) + { + InspectorTest.log("PASS: console initiated profile started"); + }); + Protocol.Profiler.onConsoleProfileFinished(function(messageObject) + { + InspectorTest.log("PASS: console initiated profile received"); + }); +} +function didFailToStartWhenDisabled(messageObject) +{ + if (!expectedError("didFailToStartWhenDisabled", messageObject)) + return; + allowConsoleProfiles(); + Protocol.Profiler.enable(); + Protocol.Profiler.start().then(didStartFrontendProfile); +} +function didStartFrontendProfile(messageObject) +{ + if (!expectedSuccess("didStartFrontendProfile", messageObject)) + return; + Protocol.Runtime.evaluate({expression: "console.profile('p1');"}).then(didStartConsoleProfile); +} + +function didStartConsoleProfile(messageObject) +{ + if (!expectedSuccess("didStartConsoleProfile", messageObject)) + return; + Protocol.Profiler.disable().then(didDisableProfiler); +} + +function didDisableProfiler(messageObject) +{ + if (!expectedSuccess("didDisableProfiler", messageObject)) + return; + Protocol.Profiler.enable(); + Protocol.Profiler.stop().then(didStopFrontendProfile); +} + +function didStopFrontendProfile(messageObject) +{ + if (!expectedError("no front-end initiated profiles found", messageObject)) + return; + disallowConsoleProfiles(); + Protocol.Runtime.evaluate({expression: "console.profileEnd();"}).then(didStopConsoleProfile); +} + +function didStopConsoleProfile(messageObject) +{ + if (!expectedSuccess("didStopConsoleProfile", messageObject)) + return; + InspectorTest.completeTest(); +} + +function checkExpectation(fail, name, messageObject) +{ + if (fail === !!messageObject.error) { + InspectorTest.log("PASS: " + name); + return true; + } + + InspectorTest.log("FAIL: " + name + ": " + JSON.stringify(messageObject)); + InspectorTest.completeTest(); + return false; +} +var expectedSuccess = checkExpectation.bind(null, false); +var expectedError = checkExpectation.bind(null, true);
diff --git a/src/v8/test/inspector/cpu-profiler/record-cpu-profile-expected.txt b/src/v8/test/inspector/cpu-profiler/record-cpu-profile-expected.txt new file mode 100644 index 0000000..4ff20a2 --- /dev/null +++ b/src/v8/test/inspector/cpu-profiler/record-cpu-profile-expected.txt
@@ -0,0 +1,7 @@ +Test that profiler is able to record a profile. Also it tests that profiler returns an error when it unable to find the profile. +PASS: startFrontendProfile +PASS: startConsoleProfile +PASS: stopConsoleProfile +PASS: stoppedFrontendProfile +PASS: startFrontendProfileSecondTime +PASS: stopFrontendProfileSecondTime
diff --git a/src/v8/test/inspector/cpu-profiler/record-cpu-profile.js b/src/v8/test/inspector/cpu-profiler/record-cpu-profile.js new file mode 100644 index 0000000..3799cf7 --- /dev/null +++ b/src/v8/test/inspector/cpu-profiler/record-cpu-profile.js
@@ -0,0 +1,62 @@ +// 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 that profiler is able to record a profile. Also it tests that profiler returns an error when it unable to find the profile."); + +Protocol.Profiler.enable(); +Protocol.Profiler.start().then(didStartFrontendProfile); +function didStartFrontendProfile(messageObject) +{ + if (!expectedSuccess("startFrontendProfile", messageObject)) + return; + Protocol.Runtime.evaluate({expression: "console.profile('Profile 1');"}).then(didStartConsoleProfile); +} + +function didStartConsoleProfile(messageObject) +{ + if (!expectedSuccess("startConsoleProfile", messageObject)) + return; + Protocol.Runtime.evaluate({expression: "console.profileEnd('Profile 1');"}).then(didStopConsoleProfile); +} + +function didStopConsoleProfile(messageObject) +{ + if (!expectedSuccess("stopConsoleProfile", messageObject)) + return; + Protocol.Profiler.stop().then(didStopFrontendProfile); +} + +function didStopFrontendProfile(messageObject) +{ + if (!expectedSuccess("stoppedFrontendProfile", messageObject)) + return; + Protocol.Profiler.start().then(didStartFrontendProfile2); +} + +function didStartFrontendProfile2(messageObject) +{ + if (!expectedSuccess("startFrontendProfileSecondTime", messageObject)) + return; + Protocol.Profiler.stop().then(didStopFrontendProfile2); +} + +function didStopFrontendProfile2(messageObject) +{ + expectedSuccess("stopFrontendProfileSecondTime", messageObject) + InspectorTest.completeTest(); +} + +function checkExpectation(fail, name, messageObject) +{ + if (fail === !!messageObject.error) { + InspectorTest.log("PASS: " + name); + return true; + } + + InspectorTest.log("FAIL: " + name + ": " + JSON.stringify(messageObject)); + InspectorTest.completeTest(); + return false; +} +var expectedSuccess = checkExpectation.bind(null, false); +var expectedError = checkExpectation.bind(null, true);
diff --git a/src/v8/test/inspector/cpu-profiler/stop-without-preceeding-start-expected.txt b/src/v8/test/inspector/cpu-profiler/stop-without-preceeding-start-expected.txt new file mode 100644 index 0000000..0c0f682 --- /dev/null +++ b/src/v8/test/inspector/cpu-profiler/stop-without-preceeding-start-expected.txt
@@ -0,0 +1,2 @@ +Test that profiler doesn't crash when we call stop without preceding start. +PASS: ProfileAgent.stop
diff --git a/src/v8/test/inspector/cpu-profiler/stop-without-preceeding-start.js b/src/v8/test/inspector/cpu-profiler/stop-without-preceeding-start.js new file mode 100644 index 0000000..848e1d2 --- /dev/null +++ b/src/v8/test/inspector/cpu-profiler/stop-without-preceeding-start.js
@@ -0,0 +1,26 @@ +// 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 that profiler doesn't crash when we call stop without preceding start."); + +Protocol.Profiler.stop().then(didStopProfile); +function didStopProfile(messageObject) +{ + expectedError("ProfileAgent.stop", messageObject); + InspectorTest.completeTest(); +} + +function checkExpectation(fail, name, messageObject) +{ + if (fail === !!messageObject.error) { + InspectorTest.log("PASS: " + name); + return true; + } + + InspectorTest.log("FAIL: " + name + ": " + JSON.stringify(messageObject)); + InspectorTest.completeTest(); + return false; +} +var expectedSuccess = checkExpectation.bind(null, false); +var expectedError = checkExpectation.bind(null, true);
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']); +}
diff --git a/src/v8/test/inspector/heap-profiler/take-heap-snapshot-on-pause-expected.txt b/src/v8/test/inspector/heap-profiler/take-heap-snapshot-on-pause-expected.txt new file mode 100644 index 0000000..2d2e553 --- /dev/null +++ b/src/v8/test/inspector/heap-profiler/take-heap-snapshot-on-pause-expected.txt
@@ -0,0 +1,2 @@ +Checks that takeHeapSnapshot uses empty accessing_context for access checks. +Successfully finished
diff --git a/src/v8/test/inspector/heap-profiler/take-heap-snapshot-on-pause.js b/src/v8/test/inspector/heap-profiler/take-heap-snapshot-on-pause.js new file mode 100644 index 0000000..4e4bc40 --- /dev/null +++ b/src/v8/test/inspector/heap-profiler/take-heap-snapshot-on-pause.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('Checks that takeHeapSnapshot uses empty accessing_context for access \ +checks.'); + +contextGroup.addScript(` +function testFunction() { + var array = [ inspector.createObjectWithStrictCheck() ]; + debugger; +} +//# sourceURL=test.js`); + +Protocol.Debugger.onScriptParsed(message => { + Protocol.HeapProfiler.takeHeapSnapshot({ reportProgress: false }) + .then(() => Protocol.Debugger.resume()); +}); + +Protocol.Debugger.enable(); +Protocol.HeapProfiler.enable(); +Protocol.Runtime.evaluate({ expression: 'testFunction()' }) + .then(() => InspectorTest.log('Successfully finished')) + .then(InspectorTest.completeTest);
diff --git a/src/v8/test/inspector/inspector-test.cc b/src/v8/test/inspector/inspector-test.cc new file mode 100644 index 0000000..dcaf582 --- /dev/null +++ b/src/v8/test/inspector/inspector-test.cc
@@ -0,0 +1,884 @@ +// 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. + +#if !defined(_WIN32) && !defined(_WIN64) +#include <unistd.h> // NOLINT +#endif // !defined(_WIN32) && !defined(_WIN64) + +#include <locale.h> + +#include "include/libplatform/libplatform.h" +#include "include/v8.h" + +#include "src/base/platform/platform.h" +#include "src/flags.h" +#include "src/utils.h" +#include "src/vector.h" + +#include "test/inspector/isolate-data.h" +#include "test/inspector/task-runner.h" + +namespace { + +std::vector<TaskRunner*> task_runners; + +void Terminate() { + for (size_t i = 0; i < task_runners.size(); ++i) { + task_runners[i]->Terminate(); + task_runners[i]->Join(); + } + std::vector<TaskRunner*> empty; + task_runners.swap(empty); +} + +void Exit() { + fflush(stdout); + fflush(stderr); + Terminate(); +} + +v8::internal::Vector<uint16_t> ToVector(v8::Local<v8::String> str) { + v8::internal::Vector<uint16_t> buffer = + v8::internal::Vector<uint16_t>::New(str->Length()); + str->Write(buffer.start(), 0, str->Length()); + return buffer; +} + +v8::Local<v8::String> ToV8String(v8::Isolate* isolate, const char* str) { + return v8::String::NewFromUtf8(isolate, str, v8::NewStringType::kNormal) + .ToLocalChecked(); +} + +v8::Local<v8::String> ToV8String(v8::Isolate* isolate, const char* str, + int length) { + return v8::String::NewFromUtf8(isolate, str, v8::NewStringType::kNormal, + length) + .ToLocalChecked(); +} + +v8::Local<v8::String> ToV8String(v8::Isolate* isolate, + const v8::internal::Vector<uint16_t>& buffer) { + return v8::String::NewFromTwoByte(isolate, buffer.start(), + v8::NewStringType::kNormal, buffer.length()) + .ToLocalChecked(); +} + +v8::internal::Vector<uint16_t> ToVector( + const v8_inspector::StringView& string) { + v8::internal::Vector<uint16_t> buffer = + v8::internal::Vector<uint16_t>::New(static_cast<int>(string.length())); + for (size_t i = 0; i < string.length(); i++) { + if (string.is8Bit()) + buffer[i] = string.characters8()[i]; + else + buffer[i] = string.characters16()[i]; + } + return buffer; +} + +class FrontendChannelImpl : public v8_inspector::V8Inspector::Channel { + public: + FrontendChannelImpl(TaskRunner* task_runner, int context_group_id, + v8::Isolate* isolate, v8::Local<v8::Function> function) + : task_runner_(task_runner), + context_group_id_(context_group_id), + function_(isolate, function) {} + virtual ~FrontendChannelImpl() = default; + + void set_session_id(int session_id) { session_id_ = session_id; } + + private: + void sendResponse( + int callId, + std::unique_ptr<v8_inspector::StringBuffer> message) override { + task_runner_->Append( + new SendMessageTask(this, ToVector(message->string()))); + } + void sendNotification( + std::unique_ptr<v8_inspector::StringBuffer> message) override { + task_runner_->Append( + new SendMessageTask(this, ToVector(message->string()))); + } + void flushProtocolNotifications() override {} + + class SendMessageTask : public TaskRunner::Task { + public: + SendMessageTask(FrontendChannelImpl* channel, + const v8::internal::Vector<uint16_t>& message) + : channel_(channel), message_(message) {} + virtual ~SendMessageTask() {} + bool is_priority_task() final { return false; } + + private: + void Run(IsolateData* data) override { + v8::MicrotasksScope microtasks_scope(data->isolate(), + v8::MicrotasksScope::kRunMicrotasks); + v8::HandleScope handle_scope(data->isolate()); + v8::Local<v8::Context> context = + data->GetContext(channel_->context_group_id_); + v8::Context::Scope context_scope(context); + v8::Local<v8::Value> message = ToV8String(data->isolate(), message_); + v8::MaybeLocal<v8::Value> result; + result = channel_->function_.Get(data->isolate()) + ->Call(context, context->Global(), 1, &message); + } + FrontendChannelImpl* channel_; + v8::internal::Vector<uint16_t> message_; + }; + + TaskRunner* task_runner_; + int context_group_id_; + v8::Global<v8::Function> function_; + int session_id_; + DISALLOW_COPY_AND_ASSIGN(FrontendChannelImpl); +}; + +template <typename T> +void RunSyncTask(TaskRunner* task_runner, T callback) { + class SyncTask : public TaskRunner::Task { + public: + SyncTask(v8::base::Semaphore* ready_semaphore, T callback) + : ready_semaphore_(ready_semaphore), callback_(callback) {} + virtual ~SyncTask() = default; + bool is_priority_task() final { return true; } + + private: + void Run(IsolateData* data) override { + callback_(data); + if (ready_semaphore_) ready_semaphore_->Signal(); + } + + v8::base::Semaphore* ready_semaphore_; + T callback_; + }; + + v8::base::Semaphore ready_semaphore(0); + task_runner->Append(new SyncTask(&ready_semaphore, callback)); + ready_semaphore.Wait(); +} + +class SendMessageToBackendTask : public TaskRunner::Task { + public: + SendMessageToBackendTask(int session_id, + const v8::internal::Vector<uint16_t>& message) + : session_id_(session_id), message_(message) {} + bool is_priority_task() final { return true; } + + private: + void Run(IsolateData* data) override { + v8_inspector::StringView message_view(message_.start(), message_.length()); + data->SendMessage(session_id_, message_view); + } + + int session_id_; + v8::internal::Vector<uint16_t> message_; +}; + +void RunAsyncTask(TaskRunner* task_runner, const char* task_name, + TaskRunner::Task* task) { + class AsyncTask : public TaskRunner::Task { + public: + explicit AsyncTask(TaskRunner::Task* inner) : inner_(inner) {} + virtual ~AsyncTask() = default; + bool is_priority_task() override { return inner_->is_priority_task(); } + void Run(IsolateData* data) override { + data->AsyncTaskStarted(inner_.get()); + inner_->Run(data); + data->AsyncTaskFinished(inner_.get()); + } + + private: + std::unique_ptr<TaskRunner::Task> inner_; + DISALLOW_COPY_AND_ASSIGN(AsyncTask); + }; + + task_runner->data()->AsyncTaskScheduled( + v8_inspector::StringView(reinterpret_cast<const uint8_t*>(task_name), + strlen(task_name)), + task, false); + task_runner->Append(new AsyncTask(task)); +} + +class ExecuteStringTask : public TaskRunner::Task { + public: + ExecuteStringTask(int context_group_id, + const v8::internal::Vector<uint16_t>& expression, + v8::Local<v8::String> name, + v8::Local<v8::Integer> line_offset, + v8::Local<v8::Integer> column_offset, + v8::Local<v8::Boolean> is_module) + : expression_(expression), + name_(ToVector(name)), + line_offset_(line_offset.As<v8::Int32>()->Value()), + column_offset_(column_offset.As<v8::Int32>()->Value()), + is_module_(is_module->Value()), + context_group_id_(context_group_id) {} + ExecuteStringTask(const v8::internal::Vector<const char>& expression, + int context_group_id) + : expression_utf8_(expression), context_group_id_(context_group_id) {} + bool is_priority_task() override { return false; } + void Run(IsolateData* data) override { + v8::MicrotasksScope microtasks_scope(data->isolate(), + v8::MicrotasksScope::kRunMicrotasks); + v8::HandleScope handle_scope(data->isolate()); + v8::Local<v8::Context> context = data->GetContext(context_group_id_); + v8::Context::Scope context_scope(context); + v8::ScriptOrigin origin( + ToV8String(data->isolate(), name_), + v8::Integer::New(data->isolate(), line_offset_), + v8::Integer::New(data->isolate(), column_offset_), + /* resource_is_shared_cross_origin */ v8::Local<v8::Boolean>(), + /* script_id */ v8::Local<v8::Integer>(), + /* source_map_url */ v8::Local<v8::Value>(), + /* resource_is_opaque */ v8::Local<v8::Boolean>(), + /* is_wasm */ v8::Local<v8::Boolean>(), + v8::Boolean::New(data->isolate(), is_module_)); + v8::Local<v8::String> source; + if (expression_.length()) + source = ToV8String(data->isolate(), expression_); + else + source = ToV8String(data->isolate(), expression_utf8_.start(), + expression_utf8_.length()); + + v8::ScriptCompiler::Source scriptSource(source, origin); + if (!is_module_) { + v8::Local<v8::Script> script; + if (!v8::ScriptCompiler::Compile(context, &scriptSource).ToLocal(&script)) + return; + v8::MaybeLocal<v8::Value> result; + result = script->Run(context); + } else { + data->RegisterModule(context, name_, &scriptSource); + } + } + + private: + v8::internal::Vector<uint16_t> expression_; + v8::internal::Vector<const char> expression_utf8_; + v8::internal::Vector<uint16_t> name_; + int32_t line_offset_ = 0; + int32_t column_offset_ = 0; + bool is_module_ = false; + int context_group_id_; + + DISALLOW_COPY_AND_ASSIGN(ExecuteStringTask); +}; + +class UtilsExtension : public IsolateData::SetupGlobalTask { + public: + ~UtilsExtension() override = default; + void Run(v8::Isolate* isolate, + v8::Local<v8::ObjectTemplate> global) override { + v8::Local<v8::ObjectTemplate> utils = v8::ObjectTemplate::New(isolate); + utils->Set(ToV8String(isolate, "print"), + v8::FunctionTemplate::New(isolate, &UtilsExtension::Print)); + utils->Set(ToV8String(isolate, "quit"), + v8::FunctionTemplate::New(isolate, &UtilsExtension::Quit)); + utils->Set(ToV8String(isolate, "setlocale"), + v8::FunctionTemplate::New(isolate, &UtilsExtension::Setlocale)); + utils->Set(ToV8String(isolate, "read"), + v8::FunctionTemplate::New(isolate, &UtilsExtension::Read)); + utils->Set(ToV8String(isolate, "load"), + v8::FunctionTemplate::New(isolate, &UtilsExtension::Load)); + utils->Set(ToV8String(isolate, "compileAndRunWithOrigin"), + v8::FunctionTemplate::New( + isolate, &UtilsExtension::CompileAndRunWithOrigin)); + utils->Set(ToV8String(isolate, "setCurrentTimeMSForTest"), + v8::FunctionTemplate::New( + isolate, &UtilsExtension::SetCurrentTimeMSForTest)); + utils->Set(ToV8String(isolate, "setMemoryInfoForTest"), + v8::FunctionTemplate::New( + isolate, &UtilsExtension::SetMemoryInfoForTest)); + utils->Set(ToV8String(isolate, "schedulePauseOnNextStatement"), + v8::FunctionTemplate::New( + isolate, &UtilsExtension::SchedulePauseOnNextStatement)); + utils->Set(ToV8String(isolate, "cancelPauseOnNextStatement"), + v8::FunctionTemplate::New( + isolate, &UtilsExtension::CancelPauseOnNextStatement)); + utils->Set(ToV8String(isolate, "setLogConsoleApiMessageCalls"), + v8::FunctionTemplate::New( + isolate, &UtilsExtension::SetLogConsoleApiMessageCalls)); + utils->Set(ToV8String(isolate, "createContextGroup"), + v8::FunctionTemplate::New(isolate, + &UtilsExtension::CreateContextGroup)); + utils->Set( + ToV8String(isolate, "connectSession"), + v8::FunctionTemplate::New(isolate, &UtilsExtension::ConnectSession)); + utils->Set( + ToV8String(isolate, "disconnectSession"), + v8::FunctionTemplate::New(isolate, &UtilsExtension::DisconnectSession)); + utils->Set(ToV8String(isolate, "sendMessageToBackend"), + v8::FunctionTemplate::New( + isolate, &UtilsExtension::SendMessageToBackend)); + global->Set(ToV8String(isolate, "utils"), utils); + } + + static void set_backend_task_runner(TaskRunner* runner) { + backend_runner_ = runner; + } + + private: + static TaskRunner* backend_runner_; + + static void Print(const v8::FunctionCallbackInfo<v8::Value>& args) { + for (int i = 0; i < args.Length(); i++) { + v8::HandleScope handle_scope(args.GetIsolate()); + if (i != 0) { + printf(" "); + } + + // Explicitly catch potential exceptions in toString(). + v8::TryCatch try_catch(args.GetIsolate()); + v8::Local<v8::Value> arg = args[i]; + v8::Local<v8::String> str_obj; + + if (arg->IsSymbol()) { + arg = v8::Local<v8::Symbol>::Cast(arg)->Name(); + } + if (!arg->ToString(args.GetIsolate()->GetCurrentContext()) + .ToLocal(&str_obj)) { + try_catch.ReThrow(); + return; + } + + v8::String::Utf8Value str(args.GetIsolate(), str_obj); + int n = + static_cast<int>(fwrite(*str, sizeof(**str), str.length(), stdout)); + if (n != str.length()) { + printf("Error in fwrite\n"); + Quit(args); + } + } + printf("\n"); + fflush(stdout); + } + + static void Quit(const v8::FunctionCallbackInfo<v8::Value>& args) { Exit(); } + + static void Setlocale(const v8::FunctionCallbackInfo<v8::Value>& args) { + if (args.Length() != 1 || !args[0]->IsString()) { + fprintf(stderr, "Internal error: setlocale get one string argument."); + Exit(); + } + + v8::String::Utf8Value str(args.GetIsolate(), args[1]); + setlocale(LC_NUMERIC, *str); + } + + static bool ReadFile(v8::Isolate* isolate, v8::Local<v8::Value> name, + v8::internal::Vector<const char>* chars) { + v8::String::Utf8Value str(isolate, name); + bool exists = false; + std::string filename(*str, str.length()); + *chars = v8::internal::ReadFile(filename.c_str(), &exists); + if (!exists) { + isolate->ThrowException(ToV8String(isolate, "Error reading file")); + return false; + } + return true; + } + + static void Read(const v8::FunctionCallbackInfo<v8::Value>& args) { + if (args.Length() != 1 || !args[0]->IsString()) { + fprintf(stderr, "Internal error: read gets one string argument."); + Exit(); + } + v8::internal::Vector<const char> chars; + v8::Isolate* isolate = args.GetIsolate(); + if (ReadFile(isolate, args[0], &chars)) + args.GetReturnValue().Set(ToV8String(isolate, chars.start())); + } + + static void Load(const v8::FunctionCallbackInfo<v8::Value>& args) { + if (args.Length() != 1 || !args[0]->IsString()) { + fprintf(stderr, "Internal error: load gets one string argument."); + Exit(); + } + v8::internal::Vector<const char> chars; + v8::Isolate* isolate = args.GetIsolate(); + v8::Local<v8::Context> context = isolate->GetCurrentContext(); + IsolateData* data = IsolateData::FromContext(context); + int context_group_id = data->GetContextGroupId(context); + if (ReadFile(isolate, args[0], &chars)) { + ExecuteStringTask(chars, context_group_id).Run(data); + } + } + + static void CompileAndRunWithOrigin( + const v8::FunctionCallbackInfo<v8::Value>& args) { + if (args.Length() != 6 || !args[0]->IsInt32() || !args[1]->IsString() || + !args[2]->IsString() || !args[3]->IsInt32() || !args[4]->IsInt32() || + !args[5]->IsBoolean()) { + fprintf(stderr, + "Internal error: compileAndRunWithOrigin(context_group_id, " + "source, name, line, " + "column, is_module)."); + Exit(); + } + + backend_runner_->Append(new ExecuteStringTask( + args[0].As<v8::Int32>()->Value(), ToVector(args[1].As<v8::String>()), + args[2].As<v8::String>(), args[3].As<v8::Int32>(), + args[4].As<v8::Int32>(), args[5].As<v8::Boolean>())); + } + + static void SetCurrentTimeMSForTest( + const v8::FunctionCallbackInfo<v8::Value>& args) { + if (args.Length() != 1 || !args[0]->IsNumber()) { + fprintf(stderr, "Internal error: setCurrentTimeMSForTest(time)."); + Exit(); + } + backend_runner_->data()->SetCurrentTimeMS( + args[0].As<v8::Number>()->Value()); + } + + static void SetMemoryInfoForTest( + const v8::FunctionCallbackInfo<v8::Value>& args) { + if (args.Length() != 1) { + fprintf(stderr, "Internal error: setMemoryInfoForTest(value)."); + Exit(); + } + backend_runner_->data()->SetMemoryInfo(args[0]); + } + + static void SchedulePauseOnNextStatement( + const v8::FunctionCallbackInfo<v8::Value>& args) { + if (args.Length() != 3 || !args[0]->IsInt32() || !args[1]->IsString() || + !args[2]->IsString()) { + fprintf(stderr, + "Internal error: schedulePauseOnNextStatement(context_group_id, " + "'reason', 'details')."); + Exit(); + } + v8::internal::Vector<uint16_t> reason = ToVector(args[1].As<v8::String>()); + v8::internal::Vector<uint16_t> details = ToVector(args[2].As<v8::String>()); + int context_group_id = args[0].As<v8::Int32>()->Value(); + RunSyncTask(backend_runner_, [&context_group_id, &reason, + &details](IsolateData* data) { + data->SchedulePauseOnNextStatement( + context_group_id, + v8_inspector::StringView(reason.start(), reason.length()), + v8_inspector::StringView(details.start(), details.length())); + }); + } + + static void CancelPauseOnNextStatement( + const v8::FunctionCallbackInfo<v8::Value>& args) { + if (args.Length() != 1 || !args[0]->IsInt32()) { + fprintf(stderr, + "Internal error: cancelPauseOnNextStatement(context_group_id)."); + Exit(); + } + int context_group_id = args[0].As<v8::Int32>()->Value(); + RunSyncTask(backend_runner_, [&context_group_id](IsolateData* data) { + data->CancelPauseOnNextStatement(context_group_id); + }); + } + + static void SetLogConsoleApiMessageCalls( + const v8::FunctionCallbackInfo<v8::Value>& args) { + if (args.Length() != 1 || !args[0]->IsBoolean()) { + fprintf(stderr, "Internal error: setLogConsoleApiMessageCalls(bool)."); + Exit(); + } + backend_runner_->data()->SetLogConsoleApiMessageCalls( + args[0].As<v8::Boolean>()->Value()); + } + + static void CreateContextGroup( + const v8::FunctionCallbackInfo<v8::Value>& args) { + if (args.Length() != 0) { + fprintf(stderr, "Internal error: createContextGroup()."); + Exit(); + } + int context_group_id = 0; + RunSyncTask(backend_runner_, [&context_group_id](IsolateData* data) { + context_group_id = data->CreateContextGroup(); + }); + args.GetReturnValue().Set( + v8::Int32::New(args.GetIsolate(), context_group_id)); + } + + static void ConnectSession(const v8::FunctionCallbackInfo<v8::Value>& args) { + if (args.Length() != 3 || !args[0]->IsInt32() || !args[1]->IsString() || + !args[2]->IsFunction()) { + fprintf(stderr, + "Internal error: connectionSession(context_group_id, state, " + "dispatch)."); + Exit(); + } + v8::Local<v8::Context> context = args.GetIsolate()->GetCurrentContext(); + FrontendChannelImpl* channel = new FrontendChannelImpl( + IsolateData::FromContext(context)->task_runner(), + IsolateData::FromContext(context)->GetContextGroupId(context), + args.GetIsolate(), args[2].As<v8::Function>()); + + v8::internal::Vector<uint16_t> state = ToVector(args[1].As<v8::String>()); + int context_group_id = args[0].As<v8::Int32>()->Value(); + int session_id = 0; + RunSyncTask(backend_runner_, [&context_group_id, &session_id, &channel, + &state](IsolateData* data) { + session_id = data->ConnectSession( + context_group_id, + v8_inspector::StringView(state.start(), state.length()), channel); + channel->set_session_id(session_id); + }); + + channels_[session_id].reset(channel); + args.GetReturnValue().Set(v8::Int32::New(args.GetIsolate(), session_id)); + } + + static void DisconnectSession( + const v8::FunctionCallbackInfo<v8::Value>& args) { + if (args.Length() != 1 || !args[0]->IsInt32()) { + fprintf(stderr, "Internal error: disconnectionSession(session_id)."); + Exit(); + } + int session_id = args[0].As<v8::Int32>()->Value(); + v8::internal::Vector<uint16_t> state; + RunSyncTask(backend_runner_, [&session_id, &state](IsolateData* data) { + state = ToVector(data->DisconnectSession(session_id)->string()); + }); + channels_.erase(session_id); + args.GetReturnValue().Set(ToV8String(args.GetIsolate(), state)); + } + + static void SendMessageToBackend( + const v8::FunctionCallbackInfo<v8::Value>& args) { + if (args.Length() != 2 || !args[0]->IsInt32() || !args[1]->IsString()) { + fprintf(stderr, + "Internal error: sendMessageToBackend(session_id, message)."); + Exit(); + } + backend_runner_->Append(new SendMessageToBackendTask( + args[0].As<v8::Int32>()->Value(), ToVector(args[1].As<v8::String>()))); + } + + static std::map<int, std::unique_ptr<FrontendChannelImpl>> channels_; +}; + +TaskRunner* UtilsExtension::backend_runner_ = nullptr; +std::map<int, std::unique_ptr<FrontendChannelImpl>> UtilsExtension::channels_; + +class SetTimeoutTask : public TaskRunner::Task { + public: + SetTimeoutTask(int context_group_id, v8::Isolate* isolate, + v8::Local<v8::Function> function) + : function_(isolate, function), context_group_id_(context_group_id) {} + virtual ~SetTimeoutTask() {} + bool is_priority_task() final { return false; } + + private: + void Run(IsolateData* data) override { + v8::MicrotasksScope microtasks_scope(data->isolate(), + v8::MicrotasksScope::kRunMicrotasks); + v8::HandleScope handle_scope(data->isolate()); + v8::Local<v8::Context> context = data->GetContext(context_group_id_); + v8::Context::Scope context_scope(context); + + v8::Local<v8::Function> function = function_.Get(data->isolate()); + v8::MaybeLocal<v8::Value> result; + result = function->Call(context, context->Global(), 0, nullptr); + } + + v8::Global<v8::Function> function_; + int context_group_id_; +}; + +class SetTimeoutExtension : public IsolateData::SetupGlobalTask { + public: + void Run(v8::Isolate* isolate, + v8::Local<v8::ObjectTemplate> global) override { + global->Set( + ToV8String(isolate, "setTimeout"), + v8::FunctionTemplate::New(isolate, &SetTimeoutExtension::SetTimeout)); + } + + private: + static void SetTimeout(const v8::FunctionCallbackInfo<v8::Value>& args) { + if (args.Length() != 2 || !args[1]->IsNumber() || + (!args[0]->IsFunction() && !args[0]->IsString()) || + args[1].As<v8::Number>()->Value() != 0.0) { + fprintf( + stderr, + "Internal error: only setTimeout(function|code, 0) is supported."); + Exit(); + } + v8::Isolate* isolate = args.GetIsolate(); + v8::Local<v8::Context> context = isolate->GetCurrentContext(); + IsolateData* data = IsolateData::FromContext(context); + int context_group_id = data->GetContextGroupId(context); + if (args[0]->IsFunction()) { + RunAsyncTask(data->task_runner(), "setTimeout", + new SetTimeoutTask(context_group_id, isolate, + v8::Local<v8::Function>::Cast(args[0]))); + } else { + RunAsyncTask( + data->task_runner(), "setTimeout", + new ExecuteStringTask( + context_group_id, ToVector(args[0].As<v8::String>()), + v8::String::Empty(isolate), v8::Integer::New(isolate, 0), + v8::Integer::New(isolate, 0), v8::Boolean::New(isolate, false))); + } + } +}; + +bool StrictAccessCheck(v8::Local<v8::Context> accessing_context, + v8::Local<v8::Object> accessed_object, + v8::Local<v8::Value> data) { + CHECK(accessing_context.IsEmpty()); + return accessing_context.IsEmpty(); +} + +class InspectorExtension : public IsolateData::SetupGlobalTask { + public: + ~InspectorExtension() override = default; + void Run(v8::Isolate* isolate, + v8::Local<v8::ObjectTemplate> global) override { + v8::Local<v8::ObjectTemplate> inspector = v8::ObjectTemplate::New(isolate); + inspector->Set(ToV8String(isolate, "fireContextCreated"), + v8::FunctionTemplate::New( + isolate, &InspectorExtension::FireContextCreated)); + inspector->Set(ToV8String(isolate, "fireContextDestroyed"), + v8::FunctionTemplate::New( + isolate, &InspectorExtension::FireContextDestroyed)); + inspector->Set( + ToV8String(isolate, "freeContext"), + v8::FunctionTemplate::New(isolate, &InspectorExtension::FreeContext)); + inspector->Set(ToV8String(isolate, "addInspectedObject"), + v8::FunctionTemplate::New( + isolate, &InspectorExtension::AddInspectedObject)); + inspector->Set(ToV8String(isolate, "setMaxAsyncTaskStacks"), + v8::FunctionTemplate::New( + isolate, &InspectorExtension::SetMaxAsyncTaskStacks)); + inspector->Set( + ToV8String(isolate, "dumpAsyncTaskStacksStateForTest"), + v8::FunctionTemplate::New( + isolate, &InspectorExtension::DumpAsyncTaskStacksStateForTest)); + inspector->Set( + ToV8String(isolate, "breakProgram"), + v8::FunctionTemplate::New(isolate, &InspectorExtension::BreakProgram)); + inspector->Set( + ToV8String(isolate, "createObjectWithStrictCheck"), + v8::FunctionTemplate::New( + isolate, &InspectorExtension::CreateObjectWithStrictCheck)); + inspector->Set(ToV8String(isolate, "callWithScheduledBreak"), + v8::FunctionTemplate::New( + isolate, &InspectorExtension::CallWithScheduledBreak)); + inspector->Set(ToV8String(isolate, "allowAccessorFormatting"), + v8::FunctionTemplate::New( + isolate, &InspectorExtension::AllowAccessorFormatting)); + inspector->Set( + ToV8String(isolate, "markObjectAsNotInspectable"), + v8::FunctionTemplate::New( + isolate, &InspectorExtension::MarkObjectAsNotInspectable)); + global->Set(ToV8String(isolate, "inspector"), inspector); + } + + private: + static void FireContextCreated( + const v8::FunctionCallbackInfo<v8::Value>& args) { + v8::Local<v8::Context> context = args.GetIsolate()->GetCurrentContext(); + IsolateData* data = IsolateData::FromContext(context); + data->FireContextCreated(context, data->GetContextGroupId(context)); + } + + static void FireContextDestroyed( + const v8::FunctionCallbackInfo<v8::Value>& args) { + v8::Local<v8::Context> context = args.GetIsolate()->GetCurrentContext(); + IsolateData* data = IsolateData::FromContext(context); + data->FireContextDestroyed(context); + } + + static void FreeContext(const v8::FunctionCallbackInfo<v8::Value>& args) { + v8::Local<v8::Context> context = args.GetIsolate()->GetCurrentContext(); + IsolateData* data = IsolateData::FromContext(context); + data->FreeContext(context); + } + + static void AddInspectedObject( + const v8::FunctionCallbackInfo<v8::Value>& args) { + if (args.Length() != 2 || !args[0]->IsInt32()) { + fprintf(stderr, + "Internal error: addInspectedObject(session_id, object)."); + Exit(); + } + v8::Local<v8::Context> context = args.GetIsolate()->GetCurrentContext(); + IsolateData* data = IsolateData::FromContext(context); + data->AddInspectedObject(args[0].As<v8::Int32>()->Value(), args[1]); + } + + static void SetMaxAsyncTaskStacks( + const v8::FunctionCallbackInfo<v8::Value>& args) { + if (args.Length() != 1 || !args[0]->IsInt32()) { + fprintf(stderr, "Internal error: setMaxAsyncTaskStacks(max)."); + Exit(); + } + IsolateData::FromContext(args.GetIsolate()->GetCurrentContext()) + ->SetMaxAsyncTaskStacksForTest(args[0].As<v8::Int32>()->Value()); + } + + static void DumpAsyncTaskStacksStateForTest( + const v8::FunctionCallbackInfo<v8::Value>& args) { + if (args.Length() != 0) { + fprintf(stderr, "Internal error: dumpAsyncTaskStacksStateForTest()."); + Exit(); + } + IsolateData::FromContext(args.GetIsolate()->GetCurrentContext()) + ->DumpAsyncTaskStacksStateForTest(); + } + + static void BreakProgram(const v8::FunctionCallbackInfo<v8::Value>& args) { + if (args.Length() != 2 || !args[0]->IsString() || !args[1]->IsString()) { + fprintf(stderr, "Internal error: breakProgram('reason', 'details')."); + Exit(); + } + v8::Local<v8::Context> context = args.GetIsolate()->GetCurrentContext(); + IsolateData* data = IsolateData::FromContext(context); + v8::internal::Vector<uint16_t> reason = ToVector(args[0].As<v8::String>()); + v8_inspector::StringView reason_view(reason.start(), reason.length()); + v8::internal::Vector<uint16_t> details = ToVector(args[1].As<v8::String>()); + v8_inspector::StringView details_view(details.start(), details.length()); + data->BreakProgram(data->GetContextGroupId(context), reason_view, + details_view); + } + + static void CreateObjectWithStrictCheck( + const v8::FunctionCallbackInfo<v8::Value>& args) { + if (args.Length() != 0) { + fprintf(stderr, "Internal error: createObjectWithStrictCheck()."); + Exit(); + } + v8::Local<v8::ObjectTemplate> templ = + v8::ObjectTemplate::New(args.GetIsolate()); + templ->SetAccessCheckCallback(&StrictAccessCheck); + args.GetReturnValue().Set( + templ->NewInstance(args.GetIsolate()->GetCurrentContext()) + .ToLocalChecked()); + } + + static void CallWithScheduledBreak( + const v8::FunctionCallbackInfo<v8::Value>& args) { + if (args.Length() != 3 || !args[0]->IsFunction() || !args[1]->IsString() || + !args[2]->IsString()) { + fprintf(stderr, + "Internal error: callWithScheduledBreak('reason', 'details')."); + Exit(); + } + v8::internal::Vector<uint16_t> reason = ToVector(args[1].As<v8::String>()); + v8_inspector::StringView reason_view(reason.start(), reason.length()); + v8::internal::Vector<uint16_t> details = ToVector(args[2].As<v8::String>()); + v8_inspector::StringView details_view(details.start(), details.length()); + v8::Local<v8::Context> context = args.GetIsolate()->GetCurrentContext(); + IsolateData* data = IsolateData::FromContext(context); + int context_group_id = data->GetContextGroupId(context); + data->SchedulePauseOnNextStatement(context_group_id, reason_view, + details_view); + v8::MaybeLocal<v8::Value> result; + result = args[0].As<v8::Function>()->Call(context, context->Global(), 0, + nullptr); + data->CancelPauseOnNextStatement(context_group_id); + } + + static void AllowAccessorFormatting( + const v8::FunctionCallbackInfo<v8::Value>& args) { + if (args.Length() != 1 || !args[0]->IsObject()) { + fprintf(stderr, "Internal error: allowAccessorFormatting('object')."); + Exit(); + } + v8::Local<v8::Object> object = args[0].As<v8::Object>(); + v8::Isolate* isolate = args.GetIsolate(); + v8::Local<v8::Private> shouldFormatAccessorsPrivate = v8::Private::ForApi( + isolate, ToV8String(isolate, "allowAccessorFormatting")); + object + ->SetPrivate(isolate->GetCurrentContext(), shouldFormatAccessorsPrivate, + v8::Null(isolate)) + .ToChecked(); + } + + static void MarkObjectAsNotInspectable( + const v8::FunctionCallbackInfo<v8::Value>& args) { + if (args.Length() != 1 || !args[0]->IsObject()) { + fprintf(stderr, "Internal error: markObjectAsNotInspectable(object)."); + Exit(); + } + v8::Local<v8::Object> object = args[0].As<v8::Object>(); + v8::Isolate* isolate = args.GetIsolate(); + v8::Local<v8::Private> notInspectablePrivate = + v8::Private::ForApi(isolate, ToV8String(isolate, "notInspectable")); + object + ->SetPrivate(isolate->GetCurrentContext(), notInspectablePrivate, + v8::True(isolate)) + .ToChecked(); + } +}; + +} // namespace + +int main(int argc, char* argv[]) { + v8::V8::InitializeICUDefaultLocation(argv[0]); + v8::Platform* platform = v8::platform::CreateDefaultPlatform(); + v8::V8::InitializePlatform(platform); + v8::V8::SetFlagsFromCommandLine(&argc, argv, true); + v8::V8::InitializeExternalStartupData(argv[0]); + v8::V8::Initialize(); + + v8::base::Semaphore ready_semaphore(0); + + v8::StartupData startup_data = {nullptr, 0}; + for (int i = 1; i < argc; ++i) { + if (strcmp(argv[i], "--embed") == 0) { + argv[i++] = nullptr; + printf("Embedding script '%s'\n", argv[i]); + startup_data = v8::V8::CreateSnapshotDataBlob(argv[i]); + argv[i] = nullptr; + } + } + + IsolateData::SetupGlobalTasks frontend_extensions; + frontend_extensions.emplace_back(new UtilsExtension()); + TaskRunner frontend_runner(std::move(frontend_extensions), true, + &ready_semaphore, nullptr, false); + ready_semaphore.Wait(); + + int frontend_context_group_id = 0; + RunSyncTask(&frontend_runner, + [&frontend_context_group_id](IsolateData* data) { + frontend_context_group_id = data->CreateContextGroup(); + }); + + IsolateData::SetupGlobalTasks backend_extensions; + backend_extensions.emplace_back(new SetTimeoutExtension()); + backend_extensions.emplace_back(new InspectorExtension()); + TaskRunner backend_runner(std::move(backend_extensions), false, + &ready_semaphore, + startup_data.data ? &startup_data : nullptr, true); + ready_semaphore.Wait(); + UtilsExtension::set_backend_task_runner(&backend_runner); + + task_runners.push_back(&frontend_runner); + task_runners.push_back(&backend_runner); + + for (int i = 1; i < argc; ++i) { + // Ignore unknown flags. + if (argv[i] == nullptr || argv[i][0] == '-') continue; + + bool exists = false; + v8::internal::Vector<const char> chars = + v8::internal::ReadFile(argv[i], &exists, true); + if (!exists) { + fprintf(stderr, "Internal error: script file doesn't exists: %s\n", + argv[i]); + Exit(); + } + frontend_runner.Append( + new ExecuteStringTask(chars, frontend_context_group_id)); + } + + frontend_runner.Join(); + backend_runner.Join(); + + delete startup_data.data; + return 0; +}
diff --git a/src/v8/test/inspector/inspector.gyp b/src/v8/test/inspector/inspector.gyp new file mode 100644 index 0000000..b465f9e --- /dev/null +++ b/src/v8/test/inspector/inspector.gyp
@@ -0,0 +1,58 @@ +# 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. + +{ + 'variables': { + 'v8_code': 1, + }, + 'includes': ['../../gypfiles/toolchain.gypi', '../../gypfiles/features.gypi'], + 'targets': [ + { + 'target_name': 'inspector-test', + 'type': 'executable', + 'dependencies': [ + '../../src/v8.gyp:v8_libplatform', + '../../src/v8.gyp:v8_libbase', + '../../src/v8.gyp:v8', + ], + 'include_dirs': [ + '../..', + ], + 'sources': [ + 'inspector-test.cc', + 'isolate-data.cc', + 'isolate-data.h', + 'task-runner.cc', + 'task-runner.h', + ], + 'conditions': [ + ['v8_enable_i18n_support==1', { + 'dependencies': [ + '<(icu_gyp_path):icui18n', + '<(icu_gyp_path):icuuc', + ], + }], + ], + }, + ], + 'conditions': [ + ['test_isolation_mode != "noop"', { + 'targets': [ + { + 'target_name': 'inspector-test_run', + 'type': 'none', + 'dependencies': [ + 'inspector-test', + ], + 'includes': [ + '../../gypfiles/isolate.gypi', + ], + 'sources': [ + 'inspector.isolate', + ], + }, + ], + }], + ], +}
diff --git a/src/v8/test/inspector/inspector.isolate b/src/v8/test/inspector/inspector.isolate new file mode 100644 index 0000000..38a96c5 --- /dev/null +++ b/src/v8/test/inspector/inspector.isolate
@@ -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. +{ + 'variables': { + 'files': [ + './console/', + './cpu-profiler/', + './debugger/', + './heap-profiler/', + './inspector.status', + './json-parse-expected.txt', + './json-parse.js', + './protocol-test.js', + './runtime/', + './sessions/', + './testcfg.py', + './type-profiler/', + '../../src/inspector/injected-script-source.js', + '<(PRODUCT_DIR)/inspector-test<(EXECUTABLE_SUFFIX)', + ], + }, + 'includes': [ + '../../src/base.isolate', + '../../tools/testrunner/testrunner.isolate', + ], +}
diff --git a/src/v8/test/inspector/inspector.status b/src/v8/test/inspector/inspector.status new file mode 100644 index 0000000..0fb349e --- /dev/null +++ b/src/v8/test/inspector/inspector.status
@@ -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. + +[ + +############################################################################## +['variant != default', { + # Issue 6167. + 'debugger/eval-scopes': [PASS, FAIL], + 'debugger/scope-skip-variables-with-empty-name': [PASS, FAIL], + 'debugger/update-call-frame-scopes': [PASS, FAIL], + 'debugger/side-effect-free-debug-evaluate': [PASS, FAIL], + 'debugger/evaluate-on-call-frame-in-module': [PASS, FAIL], + # Issue 6170. Crash. + 'cpu-profiler/console-profile': [SKIP], + 'cpu-profiler/console-profile-end-parameterless-crash': [SKIP], + # Issue 6171. Timeout. + 'debugger/set-blackbox-patterns': [SKIP], +}], # variant != default + +############################################################################## +['variant == wasm_traps', { + '*': [SKIP], +}], # variant == wasm_traps + +]
diff --git a/src/v8/test/inspector/isolate-data.cc b/src/v8/test/inspector/isolate-data.cc new file mode 100644 index 0000000..e43dd21 --- /dev/null +++ b/src/v8/test/inspector/isolate-data.cc
@@ -0,0 +1,398 @@ +// 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. + +#include "test/inspector/isolate-data.h" + +#include "src/inspector/test-interface.h" +#include "test/inspector/task-runner.h" + +namespace { + +const int kIsolateDataIndex = 2; +const int kContextGroupIdIndex = 3; + +v8::internal::Vector<uint16_t> ToVector(v8::Local<v8::String> str) { + v8::internal::Vector<uint16_t> buffer = + v8::internal::Vector<uint16_t>::New(str->Length()); + str->Write(buffer.start(), 0, str->Length()); + return buffer; +} + +v8::Local<v8::String> ToString(v8::Isolate* isolate, + const v8_inspector::StringView& string) { + if (string.is8Bit()) + return v8::String::NewFromOneByte(isolate, string.characters8(), + v8::NewStringType::kNormal, + static_cast<int>(string.length())) + .ToLocalChecked(); + else + return v8::String::NewFromTwoByte(isolate, string.characters16(), + v8::NewStringType::kNormal, + static_cast<int>(string.length())) + .ToLocalChecked(); +} + +void Print(v8::Isolate* isolate, const v8_inspector::StringView& string) { + v8::Local<v8::String> v8_string = ToString(isolate, string); + v8::String::Utf8Value utf8_string(isolate, v8_string); + fwrite(*utf8_string, sizeof(**utf8_string), utf8_string.length(), stdout); +} + +class Inspectable : public v8_inspector::V8InspectorSession::Inspectable { + public: + Inspectable(v8::Isolate* isolate, v8::Local<v8::Value> object) + : object_(isolate, object) {} + ~Inspectable() override {} + v8::Local<v8::Value> get(v8::Local<v8::Context> context) override { + return object_.Get(context->GetIsolate()); + } + + private: + v8::Global<v8::Value> object_; +}; + +} // namespace + +IsolateData::IsolateData(TaskRunner* task_runner, + IsolateData::SetupGlobalTasks setup_global_tasks, + v8::StartupData* startup_data, bool with_inspector) + : task_runner_(task_runner), + setup_global_tasks_(std::move(setup_global_tasks)) { + v8::Isolate::CreateParams params; + params.array_buffer_allocator = + v8::ArrayBuffer::Allocator::NewDefaultAllocator(); + params.snapshot_blob = startup_data; + isolate_ = v8::Isolate::New(params); + isolate_->SetMicrotasksPolicy(v8::MicrotasksPolicy::kScoped); + if (with_inspector) { + isolate_->AddMessageListener(&IsolateData::MessageHandler); + isolate_->SetPromiseRejectCallback(&IsolateData::PromiseRejectHandler); + inspector_ = v8_inspector::V8Inspector::create(isolate_, this); + } + v8::HandleScope handle_scope(isolate_); + not_inspectable_private_.Reset( + isolate_, v8::Private::ForApi(isolate_, v8::String::NewFromUtf8( + isolate_, "notInspectable", + v8::NewStringType::kNormal) + .ToLocalChecked())); +} + +IsolateData* IsolateData::FromContext(v8::Local<v8::Context> context) { + return static_cast<IsolateData*>( + context->GetAlignedPointerFromEmbedderData(kIsolateDataIndex)); +} + +int IsolateData::CreateContextGroup() { + v8::HandleScope handle_scope(isolate_); + v8::Local<v8::ObjectTemplate> global_template = + v8::ObjectTemplate::New(isolate_); + for (auto it = setup_global_tasks_.begin(); it != setup_global_tasks_.end(); + ++it) { + (*it)->Run(isolate_, global_template); + } + v8::Local<v8::Context> context = + v8::Context::New(isolate_, nullptr, global_template); + context->SetAlignedPointerInEmbedderData(kIsolateDataIndex, this); + int context_group_id = ++last_context_group_id_; + // Should be 2-byte aligned. + context->SetAlignedPointerInEmbedderData( + kContextGroupIdIndex, reinterpret_cast<void*>(context_group_id * 2)); + contexts_[context_group_id].Reset(isolate_, context); + if (inspector_) FireContextCreated(context, context_group_id); + return context_group_id; +} + +v8::Local<v8::Context> IsolateData::GetContext(int context_group_id) { + return contexts_[context_group_id].Get(isolate_); +} + +int IsolateData::GetContextGroupId(v8::Local<v8::Context> context) { + return static_cast<int>( + reinterpret_cast<intptr_t>( + context->GetAlignedPointerFromEmbedderData(kContextGroupIdIndex)) / + 2); +} + +void IsolateData::RegisterModule(v8::Local<v8::Context> context, + v8::internal::Vector<uint16_t> name, + v8::ScriptCompiler::Source* source) { + v8::Local<v8::Module> module; + if (!v8::ScriptCompiler::CompileModule(isolate(), source).ToLocal(&module)) + return; + if (!module->InstantiateModule(context, &IsolateData::ModuleResolveCallback) + .FromMaybe(false)) { + return; + } + v8::Local<v8::Value> result; + if (!module->Evaluate(context).ToLocal(&result)) return; + modules_[name] = v8::Global<v8::Module>(isolate_, module); +} + +// static +v8::MaybeLocal<v8::Module> IsolateData::ModuleResolveCallback( + v8::Local<v8::Context> context, v8::Local<v8::String> specifier, + v8::Local<v8::Module> referrer) { + IsolateData* data = IsolateData::FromContext(context); + std::string str = *v8::String::Utf8Value(data->isolate_, specifier); + return data->modules_[ToVector(specifier)].Get(data->isolate_); +} + +int IsolateData::ConnectSession(int context_group_id, + const v8_inspector::StringView& state, + v8_inspector::V8Inspector::Channel* channel) { + int session_id = ++last_session_id_; + sessions_[session_id] = inspector_->connect(context_group_id, channel, state); + context_group_by_session_[sessions_[session_id].get()] = context_group_id; + return session_id; +} + +std::unique_ptr<v8_inspector::StringBuffer> IsolateData::DisconnectSession( + int session_id) { + auto it = sessions_.find(session_id); + CHECK(it != sessions_.end()); + context_group_by_session_.erase(it->second.get()); + std::unique_ptr<v8_inspector::StringBuffer> result = it->second->stateJSON(); + sessions_.erase(it); + return result; +} + +void IsolateData::SendMessage(int session_id, + const v8_inspector::StringView& message) { + auto it = sessions_.find(session_id); + if (it != sessions_.end()) it->second->dispatchProtocolMessage(message); +} + +void IsolateData::BreakProgram(int context_group_id, + const v8_inspector::StringView& reason, + const v8_inspector::StringView& details) { + for (int session_id : GetSessionIds(context_group_id)) { + auto it = sessions_.find(session_id); + if (it != sessions_.end()) it->second->breakProgram(reason, details); + } +} + +void IsolateData::SchedulePauseOnNextStatement( + int context_group_id, const v8_inspector::StringView& reason, + const v8_inspector::StringView& details) { + for (int session_id : GetSessionIds(context_group_id)) { + auto it = sessions_.find(session_id); + if (it != sessions_.end()) + it->second->schedulePauseOnNextStatement(reason, details); + } +} + +void IsolateData::CancelPauseOnNextStatement(int context_group_id) { + for (int session_id : GetSessionIds(context_group_id)) { + auto it = sessions_.find(session_id); + if (it != sessions_.end()) it->second->cancelPauseOnNextStatement(); + } +} + +void IsolateData::AsyncTaskScheduled(const v8_inspector::StringView& name, + void* task, bool recurring) { + inspector_->asyncTaskScheduled(name, task, recurring); +} + +void IsolateData::AsyncTaskStarted(void* task) { + inspector_->asyncTaskStarted(task); +} + +void IsolateData::AsyncTaskFinished(void* task) { + inspector_->asyncTaskFinished(task); +} + +void IsolateData::AddInspectedObject(int session_id, + v8::Local<v8::Value> object) { + auto it = sessions_.find(session_id); + if (it == sessions_.end()) return; + std::unique_ptr<Inspectable> inspectable(new Inspectable(isolate_, object)); + it->second->addInspectedObject(std::move(inspectable)); +} + +void IsolateData::SetMaxAsyncTaskStacksForTest(int limit) { + v8_inspector::SetMaxAsyncTaskStacksForTest(inspector_.get(), limit); +} + +void IsolateData::DumpAsyncTaskStacksStateForTest() { + v8_inspector::DumpAsyncTaskStacksStateForTest(inspector_.get()); +} + +// static +int IsolateData::HandleMessage(v8::Local<v8::Message> message, + v8::Local<v8::Value> exception) { + v8::Isolate* isolate = v8::Isolate::GetCurrent(); + v8::Local<v8::Context> context = isolate->GetEnteredContext(); + if (context.IsEmpty()) return 0; + v8_inspector::V8Inspector* inspector = + IsolateData::FromContext(context)->inspector_.get(); + + v8::Local<v8::StackTrace> stack = message->GetStackTrace(); + int script_id = + static_cast<int>(message->GetScriptOrigin().ScriptID()->Value()); + if (!stack.IsEmpty() && stack->GetFrameCount() > 0) { + int top_script_id = stack->GetFrame(0)->GetScriptId(); + if (top_script_id == script_id) script_id = 0; + } + int line_number = message->GetLineNumber(context).FromMaybe(0); + int column_number = 0; + if (message->GetStartColumn(context).IsJust()) + column_number = message->GetStartColumn(context).FromJust() + 1; + + v8_inspector::StringView detailed_message; + v8::internal::Vector<uint16_t> message_text_string = ToVector(message->Get()); + v8_inspector::StringView message_text(message_text_string.start(), + message_text_string.length()); + v8::internal::Vector<uint16_t> url_string; + if (message->GetScriptOrigin().ResourceName()->IsString()) { + url_string = + ToVector(message->GetScriptOrigin().ResourceName().As<v8::String>()); + } + v8_inspector::StringView url(url_string.start(), url_string.length()); + + return inspector->exceptionThrown( + context, message_text, exception, detailed_message, url, line_number, + column_number, inspector->createStackTrace(stack), script_id); +} + +// static +void IsolateData::MessageHandler(v8::Local<v8::Message> message, + v8::Local<v8::Value> exception) { + HandleMessage(message, exception); +} + +// static +void IsolateData::PromiseRejectHandler(v8::PromiseRejectMessage data) { + v8::Isolate* isolate = v8::Isolate::GetCurrent(); + v8::Local<v8::Context> context = isolate->GetEnteredContext(); + if (context.IsEmpty()) return; + v8::Local<v8::Promise> promise = data.GetPromise(); + v8::Local<v8::Private> id_private = v8::Private::ForApi( + isolate, + v8::String::NewFromUtf8(isolate, "id", v8::NewStringType::kNormal) + .ToLocalChecked()); + + if (data.GetEvent() == v8::kPromiseHandlerAddedAfterReject) { + v8::Local<v8::Value> id; + if (!promise->GetPrivate(context, id_private).ToLocal(&id)) return; + if (!id->IsInt32()) return; + v8_inspector::V8Inspector* inspector = + IsolateData::FromContext(context)->inspector_.get(); + const char* reason_str = "Handler added to rejected promise"; + inspector->exceptionRevoked( + context, id.As<v8::Int32>()->Value(), + v8_inspector::StringView(reinterpret_cast<const uint8_t*>(reason_str), + strlen(reason_str))); + return; + } + + v8::Local<v8::Value> exception = data.GetValue(); + int exception_id = HandleMessage( + v8::Exception::CreateMessage(isolate, exception), exception); + if (exception_id) { + promise + ->SetPrivate(isolate->GetCurrentContext(), id_private, + v8::Int32::New(isolate, exception_id)) + .ToChecked(); + } +} + +void IsolateData::FireContextCreated(v8::Local<v8::Context> context, + int context_group_id) { + v8_inspector::V8ContextInfo info(context, context_group_id, + v8_inspector::StringView()); + info.hasMemoryOnConsole = true; + inspector_->contextCreated(info); +} + +void IsolateData::FireContextDestroyed(v8::Local<v8::Context> context) { + inspector_->contextDestroyed(context); +} + +void IsolateData::FreeContext(v8::Local<v8::Context> context) { + int context_group_id = GetContextGroupId(context); + auto it = contexts_.find(context_group_id); + if (it == contexts_.end()) return; + contexts_.erase(it); +} + +std::vector<int> IsolateData::GetSessionIds(int context_group_id) { + std::vector<int> result; + for (auto& it : sessions_) { + if (context_group_by_session_[it.second.get()] == context_group_id) + result.push_back(it.first); + } + return result; +} + +bool IsolateData::formatAccessorsAsProperties(v8::Local<v8::Value> object) { + v8::Isolate* isolate = v8::Isolate::GetCurrent(); + v8::Local<v8::Context> context = isolate->GetCurrentContext(); + v8::Local<v8::Private> shouldFormatAccessorsPrivate = v8::Private::ForApi( + isolate, v8::String::NewFromUtf8(isolate, "allowAccessorFormatting", + v8::NewStringType::kNormal) + .ToLocalChecked()); + CHECK(object->IsObject()); + return object.As<v8::Object>() + ->HasPrivate(context, shouldFormatAccessorsPrivate) + .FromMaybe(false); +} + +bool IsolateData::isInspectableHeapObject(v8::Local<v8::Object> object) { + v8::Isolate* isolate = v8::Isolate::GetCurrent(); + v8::Local<v8::Context> context = isolate->GetCurrentContext(); + v8::MicrotasksScope microtasks_scope( + isolate, v8::MicrotasksScope::kDoNotRunMicrotasks); + return !object->HasPrivate(context, not_inspectable_private_.Get(isolate)) + .FromMaybe(false); +} + +v8::Local<v8::Context> IsolateData::ensureDefaultContextInGroup( + int context_group_id) { + return GetContext(context_group_id); +} + +void IsolateData::SetCurrentTimeMS(double time) { + current_time_ = time; + current_time_set_ = true; +} + +double IsolateData::currentTimeMS() { + if (current_time_set_) return current_time_; + return v8::internal::V8::GetCurrentPlatform()->CurrentClockTimeMillis(); +} + +void IsolateData::SetMemoryInfo(v8::Local<v8::Value> memory_info) { + memory_info_.Reset(isolate_, memory_info); +} + +void IsolateData::SetLogConsoleApiMessageCalls(bool log) { + log_console_api_message_calls_ = log; +} + +v8::MaybeLocal<v8::Value> IsolateData::memoryInfo(v8::Isolate* isolate, + v8::Local<v8::Context>) { + if (memory_info_.IsEmpty()) return v8::MaybeLocal<v8::Value>(); + return memory_info_.Get(isolate); +} + +void IsolateData::runMessageLoopOnPause(int) { + task_runner_->RunMessageLoop(true); +} + +void IsolateData::quitMessageLoopOnPause() { task_runner_->QuitMessageLoop(); } + +void IsolateData::consoleAPIMessage(int contextGroupId, + v8::Isolate::MessageErrorLevel level, + const v8_inspector::StringView& message, + const v8_inspector::StringView& url, + unsigned lineNumber, unsigned columnNumber, + v8_inspector::V8StackTrace* stack) { + if (!log_console_api_message_calls_) return; + Print(isolate_, message); + fprintf(stdout, " ("); + Print(isolate_, url); + fprintf(stdout, ":%d:%d)", lineNumber, columnNumber); + Print(isolate_, stack->toString()->string()); + fprintf(stdout, "\n"); +}
diff --git a/src/v8/test/inspector/isolate-data.h b/src/v8/test/inspector/isolate-data.h new file mode 100644 index 0000000..b8f3b9e --- /dev/null +++ b/src/v8/test/inspector/isolate-data.h
@@ -0,0 +1,131 @@ +// 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. + +#ifndef V8_TEST_INSPECTOR_PROTOCOL_ISOLATE_DATA_H_ +#define V8_TEST_INSPECTOR_PROTOCOL_ISOLATE_DATA_H_ + +#include <map> + +#include "include/v8-inspector.h" +#include "include/v8-platform.h" +#include "include/v8.h" +#include "src/base/macros.h" +#include "src/base/platform/platform.h" +#include "src/vector.h" + +class TaskRunner; + +class IsolateData : public v8_inspector::V8InspectorClient { + public: + class SetupGlobalTask { + public: + virtual ~SetupGlobalTask() = default; + virtual void Run(v8::Isolate* isolate, + v8::Local<v8::ObjectTemplate> global) = 0; + }; + using SetupGlobalTasks = std::vector<std::unique_ptr<SetupGlobalTask>>; + + IsolateData(TaskRunner* task_runner, SetupGlobalTasks setup_global_tasks, + v8::StartupData* startup_data, bool with_inspector); + static IsolateData* FromContext(v8::Local<v8::Context> context); + + v8::Isolate* isolate() const { return isolate_; } + TaskRunner* task_runner() const { return task_runner_; } + + // Setting things up. + int CreateContextGroup(); + v8::Local<v8::Context> GetContext(int context_group_id); + int GetContextGroupId(v8::Local<v8::Context> context); + void RegisterModule(v8::Local<v8::Context> context, + v8::internal::Vector<uint16_t> name, + v8::ScriptCompiler::Source* source); + + // Working with V8Inspector api. + int ConnectSession(int context_group_id, + const v8_inspector::StringView& state, + v8_inspector::V8Inspector::Channel* channel); + std::unique_ptr<v8_inspector::StringBuffer> DisconnectSession(int session_id); + void SendMessage(int session_id, const v8_inspector::StringView& message); + void BreakProgram(int context_group_id, + const v8_inspector::StringView& reason, + const v8_inspector::StringView& details); + void SchedulePauseOnNextStatement(int context_group_id, + const v8_inspector::StringView& reason, + const v8_inspector::StringView& details); + void CancelPauseOnNextStatement(int context_group_id); + void AsyncTaskScheduled(const v8_inspector::StringView& name, void* task, + bool recurring); + void AsyncTaskStarted(void* task); + void AsyncTaskFinished(void* task); + void AddInspectedObject(int session_id, v8::Local<v8::Value> object); + + // Test utilities. + void SetCurrentTimeMS(double time); + void SetMemoryInfo(v8::Local<v8::Value> memory_info); + void SetLogConsoleApiMessageCalls(bool log); + void SetMaxAsyncTaskStacksForTest(int limit); + void DumpAsyncTaskStacksStateForTest(); + void FireContextCreated(v8::Local<v8::Context> context, int context_group_id); + void FireContextDestroyed(v8::Local<v8::Context> context); + void FreeContext(v8::Local<v8::Context> context); + + private: + struct VectorCompare { + bool operator()(const v8::internal::Vector<uint16_t>& lhs, + const v8::internal::Vector<uint16_t>& rhs) const { + for (int i = 0; i < lhs.length() && i < rhs.length(); ++i) { + if (lhs[i] != rhs[i]) return lhs[i] < rhs[i]; + } + return false; + } + }; + static v8::MaybeLocal<v8::Module> ModuleResolveCallback( + v8::Local<v8::Context> context, v8::Local<v8::String> specifier, + v8::Local<v8::Module> referrer); + static void MessageHandler(v8::Local<v8::Message> message, + v8::Local<v8::Value> exception); + static void PromiseRejectHandler(v8::PromiseRejectMessage data); + static int HandleMessage(v8::Local<v8::Message> message, + v8::Local<v8::Value> exception); + std::vector<int> GetSessionIds(int context_group_id); + + // V8InspectorClient implementation. + bool formatAccessorsAsProperties(v8::Local<v8::Value>) override; + v8::Local<v8::Context> ensureDefaultContextInGroup( + int context_group_id) override; + double currentTimeMS() override; + v8::MaybeLocal<v8::Value> memoryInfo(v8::Isolate* isolate, + v8::Local<v8::Context>) override; + void runMessageLoopOnPause(int context_group_id) override; + void quitMessageLoopOnPause() override; + void consoleAPIMessage(int contextGroupId, + v8::Isolate::MessageErrorLevel level, + const v8_inspector::StringView& message, + const v8_inspector::StringView& url, + unsigned lineNumber, unsigned columnNumber, + v8_inspector::V8StackTrace*) override; + bool isInspectableHeapObject(v8::Local<v8::Object>) override; + + TaskRunner* task_runner_; + SetupGlobalTasks setup_global_tasks_; + v8::Isolate* isolate_; + std::unique_ptr<v8_inspector::V8Inspector> inspector_; + int last_context_group_id_ = 0; + std::map<int, v8::Global<v8::Context>> contexts_; + std::map<v8::internal::Vector<uint16_t>, v8::Global<v8::Module>, + VectorCompare> + modules_; + int last_session_id_ = 0; + std::map<int, std::unique_ptr<v8_inspector::V8InspectorSession>> sessions_; + std::map<v8_inspector::V8InspectorSession*, int> context_group_by_session_; + v8::Global<v8::Value> memory_info_; + bool current_time_set_ = false; + double current_time_ = 0.0; + bool log_console_api_message_calls_ = false; + v8::Global<v8::Private> not_inspectable_private_; + + DISALLOW_COPY_AND_ASSIGN(IsolateData); +}; + +#endif // V8_TEST_INSPECTOR_PROTOCOL_ISOLATE_DATA_H_
diff --git a/src/v8/test/inspector/json-parse-expected.txt b/src/v8/test/inspector/json-parse-expected.txt new file mode 100644 index 0000000..80d80ab --- /dev/null +++ b/src/v8/test/inspector/json-parse-expected.txt
@@ -0,0 +1,10 @@ +Tests that json parser on backend correctly works with unicode +{ + id : 1 + result : { + result : { + type : string + value : Привет мир + } + } +}
diff --git a/src/v8/test/inspector/json-parse.js b/src/v8/test/inspector/json-parse.js new file mode 100644 index 0000000..92ec84b --- /dev/null +++ b/src/v8/test/inspector/json-parse.js
@@ -0,0 +1,16 @@ +// 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 json parser on backend correctly works with unicode'); + +const id = 100500; +var command = { "method": "Runtime.evaluate", "params": { expression: "\"!!!\"" }, "id": id }; +session.sendRawCommand(id, JSON.stringify(command).replace("!!!", "\\u041F\\u0440\\u0438\\u0432\\u0435\\u0442 \\u043C\\u0438\\u0440"), step2); + +function step2(msg) +{ + msg.id = 1; + InspectorTest.logObject(msg); + InspectorTest.completeTest(); +}
diff --git a/src/v8/test/inspector/protocol-test.js b/src/v8/test/inspector/protocol-test.js new file mode 100644 index 0000000..be7314b --- /dev/null +++ b/src/v8/test/inspector/protocol-test.js
@@ -0,0 +1,408 @@ +// 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. + +InspectorTest = {}; +InspectorTest._dumpInspectorProtocolMessages = false; +InspectorTest._commandsForLogging = new Set(); +InspectorTest._sessions = new Set(); + +InspectorTest.log = utils.print.bind(utils); +InspectorTest.quitImmediately = utils.quit.bind(utils); + +InspectorTest.logProtocolCommandCalls = function(command) { + InspectorTest._commandsForLogging.add(command); +} + +InspectorTest.completeTest = function() { + var promises = []; + for (var session of InspectorTest._sessions) + promises.push(session.Protocol.Debugger.disable()); + Promise.all(promises).then(() => utils.quit()); +} + +InspectorTest.waitForPendingTasks = function() { + var promises = []; + for (var session of InspectorTest._sessions) + promises.push(session.Protocol.Runtime.evaluate({ expression: "new Promise(r => setTimeout(r, 0))//# sourceURL=wait-for-pending-tasks.js", awaitPromise: true })); + return Promise.all(promises); +} + +InspectorTest.startDumpingProtocolMessages = function() { + InspectorTest._dumpInspectorProtocolMessages = true; +} + +InspectorTest.logMessage = function(originalMessage) { + var message = JSON.parse(JSON.stringify(originalMessage)); + if (message.id) + message.id = "<messageId>"; + + const nonStableFields = new Set(["objectId", "scriptId", "exceptionId", "timestamp", + "executionContextId", "callFrameId", "breakpointId", "bindRemoteObjectFunctionId", "formatterObjectId" ]); + var objects = [ message ]; + while (objects.length) { + var object = objects.shift(); + for (var key in object) { + if (nonStableFields.has(key)) + object[key] = `<${key}>`; + else if (typeof object[key] === "string" && object[key].match(/\d+:\d+:\d+:debug/)) + object[key] = object[key].replace(/\d+/, '<scriptId>'); + else if (typeof object[key] === "object") + objects.push(object[key]); + } + } + + InspectorTest.logObject(message); + return originalMessage; +} + +InspectorTest.logObject = function(object, title) { + var lines = []; + + function dumpValue(value, prefix, prefixWithName) { + if (typeof value === "object" && value !== null) { + if (value instanceof Array) + dumpItems(value, prefix, prefixWithName); + else + dumpProperties(value, prefix, prefixWithName); + } else { + lines.push(prefixWithName + String(value).replace(/\n/g, " ")); + } + } + + function dumpProperties(object, prefix, firstLinePrefix) { + prefix = prefix || ""; + firstLinePrefix = firstLinePrefix || prefix; + lines.push(firstLinePrefix + "{"); + + var propertyNames = Object.keys(object); + propertyNames.sort(); + for (var i = 0; i < propertyNames.length; ++i) { + var name = propertyNames[i]; + if (!object.hasOwnProperty(name)) + continue; + var prefixWithName = " " + prefix + name + " : "; + dumpValue(object[name], " " + prefix, prefixWithName); + } + lines.push(prefix + "}"); + } + + function dumpItems(object, prefix, firstLinePrefix) { + prefix = prefix || ""; + firstLinePrefix = firstLinePrefix || prefix; + lines.push(firstLinePrefix + "["); + for (var i = 0; i < object.length; ++i) + dumpValue(object[i], " " + prefix, " " + prefix + "[" + i + "] : "); + lines.push(prefix + "]"); + } + + dumpValue(object, "", title || ""); + InspectorTest.log(lines.join("\n")); +} + +InspectorTest.ContextGroup = class { + constructor() { + this.id = utils.createContextGroup(); + } + + schedulePauseOnNextStatement(reason, details) { + utils.schedulePauseOnNextStatement(this.id, reason, details); + } + + cancelPauseOnNextStatement() { + utils.cancelPauseOnNextStatement(this.id); + } + + addScript(string, lineOffset, columnOffset, url) { + utils.compileAndRunWithOrigin(this.id, string, url || '', lineOffset || 0, columnOffset || 0, false); + } + + addModule(string, url, lineOffset, columnOffset) { + utils.compileAndRunWithOrigin(this.id, string, url, lineOffset || 0, columnOffset || 0, true); + } + + loadScript(fileName) { + this.addScript(utils.read(fileName)); + } + + connect() { + return new InspectorTest.Session(this); + } + + setupInjectedScriptEnvironment(session) { + let scriptSource = ''; + // First define all getters on Object.prototype. + let injectedScriptSource = utils.read('src/inspector/injected-script-source.js'); + let getterRegex = /\.[a-zA-Z0-9]+/g; + let match; + let getters = new Set(); + while (match = getterRegex.exec(injectedScriptSource)) { + getters.add(match[0].substr(1)); + } + scriptSource += `(function installSettersAndGetters() { + let defineProperty = Object.defineProperty; + let ObjectPrototype = Object.prototype; + let ArrayPrototype = Array.prototype; + defineProperty(ArrayPrototype, 0, { + set() { debugger; throw 42; }, get() { debugger; throw 42; }, + __proto__: null + });`, + scriptSource += Array.from(getters).map(getter => ` + defineProperty(ObjectPrototype, '${getter}', { + set() { debugger; throw 42; }, get() { debugger; throw 42; }, + __proto__: null + }); + `).join('\n') + '})();'; + this.addScript(scriptSource); + + if (session) { + InspectorTest.log('WARNING: setupInjectedScriptEnvironment with debug flag for debugging only and should not be landed.'); + InspectorTest.log('WARNING: run test with --expose-inspector-scripts flag to get more details.'); + InspectorTest.log('WARNING: you can additionally comment rjsmin in xxd.py to get unminified injected-script-source.js.'); + session.setupScriptMap(); + session.Protocol.Debugger.enable(); + session.Protocol.Debugger.onPaused(message => { + let callFrames = message.params.callFrames; + session.logSourceLocations(callFrames.map(frame => frame.location)); + }) + } + } +}; + +InspectorTest.Session = class { + constructor(contextGroup) { + this.contextGroup = contextGroup; + this._dispatchTable = new Map(); + this._eventHandlers = new Map(); + this._requestId = 0; + this.Protocol = this._setupProtocol(); + InspectorTest._sessions.add(this); + this.id = utils.connectSession(contextGroup.id, '', this._dispatchMessage.bind(this)); + } + + disconnect() { + InspectorTest._sessions.delete(this); + utils.disconnectSession(this.id); + } + + reconnect() { + var state = utils.disconnectSession(this.id); + this.id = utils.connectSession(this.contextGroup.id, state, this._dispatchMessage.bind(this)); + } + + async addInspectedObject(serializable) { + return this.Protocol.Runtime.evaluate({expression: `inspector.addInspectedObject(${this.id}, ${JSON.stringify(serializable)})`}); + } + + sendRawCommand(requestId, command, handler) { + if (InspectorTest._dumpInspectorProtocolMessages) + utils.print("frontend: " + command); + this._dispatchTable.set(requestId, handler); + utils.sendMessageToBackend(this.id, command); + } + + setupScriptMap() { + if (this._scriptMap) + return; + this._scriptMap = new Map(); + } + + logCallFrames(callFrames) { + for (var frame of callFrames) { + var functionName = frame.functionName || '(anonymous)'; + var url = frame.url ? frame.url : this._scriptMap.get(frame.location.scriptId).url; + var lineNumber = frame.location ? frame.location.lineNumber : frame.lineNumber; + var columnNumber = frame.location ? frame.location.columnNumber : frame.columnNumber; + InspectorTest.log(`${functionName} (${url}:${lineNumber}:${columnNumber})`); + } + } + + logSourceLocation(location, forceSourceRequest) { + var scriptId = location.scriptId; + if (!this._scriptMap || !this._scriptMap.has(scriptId)) { + InspectorTest.log("setupScriptMap should be called before Protocol.Debugger.enable."); + InspectorTest.completeTest(); + } + var script = this._scriptMap.get(scriptId); + if (!script.scriptSource || forceSourceRequest) { + return this.Protocol.Debugger.getScriptSource({ scriptId }) + .then(message => script.scriptSource = message.result.scriptSource) + .then(dumpSourceWithLocation); + } + return Promise.resolve().then(dumpSourceWithLocation); + + function dumpSourceWithLocation() { + var lines = script.scriptSource.split('\n'); + var line = lines[location.lineNumber]; + line = line.slice(0, location.columnNumber) + '#' + (line.slice(location.columnNumber) || ''); + lines[location.lineNumber] = line; + lines = lines.filter(line => line.indexOf('//# sourceURL=') === -1); + InspectorTest.log(lines.slice(Math.max(location.lineNumber - 1, 0), location.lineNumber + 2).join('\n')); + InspectorTest.log(''); + } + } + + logSourceLocations(locations) { + if (locations.length == 0) return Promise.resolve(); + return this.logSourceLocation(locations[0]).then(() => this.logSourceLocations(locations.splice(1))); + } + + async logBreakLocations(inputLocations) { + let locations = inputLocations.slice(); + let scriptId = locations[0].scriptId; + let script = this._scriptMap.get(scriptId); + if (!script.scriptSource) { + let message = await this.Protocol.Debugger.getScriptSource({scriptId}); + script.scriptSource = message.result.scriptSource; + } + let lines = script.scriptSource.split('\n'); + locations = locations.sort((loc1, loc2) => { + if (loc2.lineNumber !== loc1.lineNumber) return loc2.lineNumber - loc1.lineNumber; + return loc2.columnNumber - loc1.columnNumber; + }); + for (let location of locations) { + let 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'); + return inputLocations; + + function locationMark(type) { + if (type === 'return') return '|R|'; + if (type === 'call') return '|C|'; + if (type === 'debuggerStatement') return '|D|'; + return '|_|'; + } + } + + async logTypeProfile(typeProfile, source) { + let entries = typeProfile.entries; + + // Sort in reverse order so we can replace entries without invalidating + // the other offsets. + entries = entries.sort((a, b) => b.offset - a.offset); + + for (let entry of entries) { + source = source.slice(0, entry.offset) + typeAnnotation(entry.types) + + source.slice(entry.offset); + } + InspectorTest.log(source); + return typeProfile; + + function typeAnnotation(types) { + return `/*${types.map(t => t.name).join(', ')}*/`; + } + } + + logAsyncStackTrace(asyncStackTrace) { + while (asyncStackTrace) { + if (asyncStackTrace.promiseCreationFrame) { + var frame = asyncStackTrace.promiseCreationFrame; + InspectorTest.log(`-- ${asyncStackTrace.description} (${frame.url}:${frame.lineNumber}:${frame.columnNumber})--`); + } else { + InspectorTest.log(`-- ${asyncStackTrace.description} --`); + } + this.logCallFrames(asyncStackTrace.callFrames); + asyncStackTrace = asyncStackTrace.parent; + } + } + + _sendCommandPromise(method, params) { + if (InspectorTest._commandsForLogging.has(method)) + utils.print(method + ' called'); + var requestId = ++this._requestId; + var messageObject = { "id": requestId, "method": method, "params": params }; + return new Promise(fulfill => this.sendRawCommand(requestId, JSON.stringify(messageObject), fulfill)); + } + + _setupProtocol() { + return new Proxy({}, { get: (target, agentName, receiver) => new Proxy({}, { + get: (target, methodName, receiver) => { + const eventPattern = /^on(ce)?([A-Z][A-Za-z0-9]+)/; + var match = eventPattern.exec(methodName); + if (!match) + return args => this._sendCommandPromise(`${agentName}.${methodName}`, args || {}); + var eventName = match[2]; + eventName = eventName.charAt(0).toLowerCase() + eventName.slice(1); + if (match[1]) + return () => this._waitForEventPromise(`${agentName}.${eventName}`); + return listener => this._eventHandlers.set(`${agentName}.${eventName}`, listener); + } + })}); + } + + _dispatchMessage(messageString) { + var messageObject = JSON.parse(messageString); + if (InspectorTest._dumpInspectorProtocolMessages) + utils.print("backend: " + JSON.stringify(messageObject)); + try { + var messageId = messageObject["id"]; + if (typeof messageId === "number") { + var handler = this._dispatchTable.get(messageId); + if (handler) { + handler(messageObject); + this._dispatchTable.delete(messageId); + } + } else { + var eventName = messageObject["method"]; + var eventHandler = this._eventHandlers.get(eventName); + if (this._scriptMap && eventName === "Debugger.scriptParsed") + this._scriptMap.set(messageObject.params.scriptId, JSON.parse(JSON.stringify(messageObject.params))); + if (eventName === "Debugger.scriptParsed" && messageObject.params.url === "wait-for-pending-tasks.js") + return; + if (eventHandler) + eventHandler(messageObject); + } + } catch (e) { + InspectorTest.log("Exception when dispatching message: " + e + "\n" + e.stack + "\n message = " + JSON.stringify(messageObject, null, 2)); + InspectorTest.completeTest(); + } + }; + + _waitForEventPromise(eventName) { + return new Promise(fulfill => { + this._eventHandlers.set(eventName, result => { + delete this._eventHandlers.delete(eventName); + fulfill(result); + }); + }); + } +}; + +InspectorTest.runTestSuite = function(testSuite) { + function nextTest() { + if (!testSuite.length) { + InspectorTest.completeTest(); + return; + } + var fun = testSuite.shift(); + InspectorTest.log("\nRunning test: " + fun.name); + fun(nextTest); + } + nextTest(); +} + +InspectorTest.runAsyncTestSuite = async function(testSuite) { + for (var test of testSuite) { + InspectorTest.log("\nRunning test: " + test.name); + try { + await test(); + } catch (e) { + utils.print(e.stack); + } + } + InspectorTest.completeTest(); +} + +InspectorTest.start = function(description) { + try { + InspectorTest.log(description); + var contextGroup = new InspectorTest.ContextGroup(); + var session = contextGroup.connect(); + return { session: session, contextGroup: contextGroup, Protocol: session.Protocol }; + } catch (e) { + utils.print(e.stack); + } +}
diff --git a/src/v8/test/inspector/runtime/await-promise-expected.txt b/src/v8/test/inspector/runtime/await-promise-expected.txt new file mode 100644 index 0000000..3e23a71 --- /dev/null +++ b/src/v8/test/inspector/runtime/await-promise-expected.txt
@@ -0,0 +1,181 @@ +Tests that Runtime.awaitPromise works. + +Running test: testResolvedPromise +{ + id : <messageId> + result : { + result : { + description : 239 + type : number + value : 239 + } + } +} + +Running test: testRejectedPromise +{ + id : <messageId> + result : { + exceptionDetails : { + columnNumber : 0 + exception : { + type : object + value : { + a : 1 + } + } + exceptionId : <exceptionId> + lineNumber : 0 + stackTrace : { + callFrames : [ + ] + parent : { + callFrames : [ + [0] : { + columnNumber : 8 + functionName : + lineNumber : 0 + scriptId : <scriptId> + url : + } + ] + description : Promise.reject + } + } + text : Uncaught (in promise) + } + result : { + type : object + value : { + a : 1 + } + } + } +} + +Running test: testRejectedPromiseWithStack +{ + id : <messageId> + result : { + exceptionDetails : { + columnNumber : 0 + exception : { + description : 239 + type : number + value : 239 + } + exceptionId : <exceptionId> + lineNumber : 0 + stackTrace : { + callFrames : [ + ] + parent : { + callFrames : [ + [0] : { + columnNumber : 4 + functionName : rejectPromise + lineNumber : 17 + scriptId : <scriptId> + url : test.js + } + [1] : { + columnNumber : 0 + functionName : + lineNumber : 0 + scriptId : <scriptId> + url : + } + ] + description : Promise.reject + } + } + text : Uncaught (in promise) + } + result : { + description : 239 + type : number + value : 239 + } + } +} + +Running test: testRejectedPromiseWithError +{ + id : <messageId> + result : { + exceptionDetails : { + columnNumber : 0 + exception : { + className : Error + description : Error: MyError at rejectPromiseWithAnError (test.js:25:20) at <anonymous>:1:1 + objectId : <objectId> + subtype : error + type : object + } + exceptionId : <exceptionId> + lineNumber : 0 + stackTrace : { + callFrames : [ + ] + parent : { + callFrames : [ + [0] : { + columnNumber : 4 + functionName : rejectPromiseWithAnError + lineNumber : 24 + scriptId : <scriptId> + url : test.js + } + [1] : { + columnNumber : 0 + functionName : + lineNumber : 0 + scriptId : <scriptId> + url : + } + ] + description : Promise.reject + } + } + text : Uncaught (in promise) Error: MyError + } + result : { + className : Error + description : Error: MyError at rejectPromiseWithAnError (test.js:25:20) at <anonymous>:1:1 + objectId : <objectId> + subtype : error + type : object + } + } +} + +Running test: testPendingPromise +{ + id : <messageId> + result : { + result : { + description : 239 + type : number + value : 239 + } + } +} + +Running test: testResolvedWithoutArgsPromise +{ + id : <messageId> + result : { + result : { + type : undefined + } + } +} + +Running test: testGarbageCollectedPromise +{ + error : { + code : -32000 + message : Promise was collected + } + id : <messageId> +}
diff --git a/src/v8/test/inspector/runtime/await-promise.js b/src/v8/test/inspector/runtime/await-promise.js new file mode 100644 index 0000000..cf7d53d --- /dev/null +++ b/src/v8/test/inspector/runtime/await-promise.js
@@ -0,0 +1,143 @@ +// 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("Tests that Runtime.awaitPromise works."); + +contextGroup.addScript( +` +var resolveCallback; +var rejectCallback; +function createPromise() +{ + return new Promise((resolve, reject) => { resolveCallback = resolve; rejectCallback = reject }); +} + +function resolvePromise() +{ + resolveCallback(239); + resolveCallback = undefined; + rejectCallback = undefined; +} + +function rejectPromise() +{ + rejectCallback(239); + resolveCallback = undefined; + rejectCallback = undefined; +} + +function rejectPromiseWithAnError() +{ + rejectCallback(new Error('MyError')); + resolveCallback = undefined; + rejectCallback = undefined; +} + +function throwError() +{ + throw new Error('MyError'); +} + +//# sourceURL=test.js`); + +Protocol.Debugger.enable() + .then(() => Protocol.Debugger.setAsyncCallStackDepth({ maxDepth: 128 })) + .then(() => testSuite()); + +function testSuite() +{ + InspectorTest.runTestSuite([ + function testResolvedPromise(next) + { + Protocol.Runtime.evaluate({ expression: "Promise.resolve(239)"}) + .then(result => Protocol.Runtime.awaitPromise({ promiseObjectId: result.result.result.objectId, returnByValue: false, generatePreview: true })) + .then(result => InspectorTest.logMessage(result)) + .then(() => next()); + }, + + function testRejectedPromise(next) + { + Protocol.Runtime.evaluate({ expression: "Promise.reject({ a : 1 })"}) + .then(result => Protocol.Runtime.awaitPromise({ promiseObjectId: result.result.result.objectId, returnByValue: true, generatePreview: false })) + .then(result => InspectorTest.logMessage(result)) + .then(() => next()); + }, + + function testRejectedPromiseWithStack(next) + { + Protocol.Runtime.evaluate({ expression: "createPromise()"}) + .then(result => scheduleRejectAndAwaitPromise(result)) + .then(result => InspectorTest.logMessage(result)) + .then(() => next()); + + function scheduleRejectAndAwaitPromise(result) + { + var promise = Protocol.Runtime.awaitPromise({ promiseObjectId: result.result.result.objectId }); + Protocol.Runtime.evaluate({ expression: "rejectPromise()" }); + return promise; + } + }, + + function testRejectedPromiseWithError(next) + { + Protocol.Runtime.evaluate({ expression: "createPromise()"}) + .then(result => scheduleRejectAndAwaitPromise(result)) + .then(result => InspectorTest.logMessage(result)) + .then(() => next()); + + function scheduleRejectAndAwaitPromise(result) + { + var promise = Protocol.Runtime.awaitPromise({ promiseObjectId: result.result.result.objectId }); + Protocol.Runtime.evaluate({ expression: "rejectPromiseWithAnError()" }); + return promise; + } + }, + + function testPendingPromise(next) + { + Protocol.Runtime.evaluate({ expression: "createPromise()"}) + .then(result => scheduleFulfillAndAwaitPromise(result)) + .then(result => InspectorTest.logMessage(result)) + .then(() => next()); + + function scheduleFulfillAndAwaitPromise(result) + { + var promise = Protocol.Runtime.awaitPromise({ promiseObjectId: result.result.result.objectId }); + Protocol.Runtime.evaluate({ expression: "resolvePromise()" }); + return promise; + } + }, + + function testResolvedWithoutArgsPromise(next) + { + Protocol.Runtime.evaluate({ expression: "Promise.resolve()"}) + .then(result => Protocol.Runtime.awaitPromise({ promiseObjectId: result.result.result.objectId, returnByValue: true, generatePreview: false })) + .then(result => InspectorTest.logMessage(result)) + .then(() => next()); + }, + + function testGarbageCollectedPromise(next) + { + Protocol.Runtime.evaluate({ expression: "new Promise(() => undefined)" }) + .then(result => scheduleGCAndawaitPromise(result)) + .then(result => InspectorTest.logMessage(result)) + .then(() => next()); + + function scheduleGCAndawaitPromise(result) + { + var objectId = result.result.result.objectId; + var promise = Protocol.Runtime.awaitPromise({ promiseObjectId: objectId }); + gcPromise(objectId); + return promise; + } + + function gcPromise(objectId) + { + Protocol.Runtime.releaseObject({ objectId: objectId}) + .then(() => Protocol.Runtime.evaluate({ expression: "gc()" })); + } + } + ]); +}
diff --git a/src/v8/test/inspector/runtime/call-function-on-async-expected.txt b/src/v8/test/inspector/runtime/call-function-on-async-expected.txt new file mode 100644 index 0000000..0cbf6f1 --- /dev/null +++ b/src/v8/test/inspector/runtime/call-function-on-async-expected.txt
@@ -0,0 +1,195 @@ +Tests that Runtime.callFunctionOn works with awaitPromise flag. + +Running test: prepareTestSuite + +Running test: testArguments +{ + id : <messageId> + result : { + result : { + type : string + value : undefined|NaN|[object Object]|[object Object] + } + } +} + +Running test: testComplexArguments +{ + id : <messageId> + result : { + result : { + type : string + value : bar + } + } +} + +Running test: testSyntaxErrorInFunction +{ + id : <messageId> + result : { + exceptionDetails : { + columnNumber : 2 + exception : { + className : SyntaxError + description : SyntaxError: Unexpected token } + objectId : <objectId> + subtype : error + type : object + } + exceptionId : <exceptionId> + lineNumber : 1 + scriptId : <scriptId> + text : Uncaught + } + result : { + className : SyntaxError + description : SyntaxError: Unexpected token } + objectId : <objectId> + subtype : error + type : object + } + } +} + +Running test: testExceptionInFunctionExpression +{ + id : <messageId> + result : { + exceptionDetails : { + columnNumber : 15 + exception : { + className : Error + description : Error at <anonymous>:1:22 at <anonymous>:1:36 + objectId : <objectId> + subtype : error + type : object + } + exceptionId : <exceptionId> + lineNumber : 0 + scriptId : <scriptId> + stackTrace : { + callFrames : [ + [0] : { + columnNumber : 21 + functionName : + lineNumber : 0 + scriptId : <scriptId> + url : + } + [1] : { + columnNumber : 35 + functionName : + lineNumber : 0 + scriptId : <scriptId> + url : + } + ] + } + text : Uncaught + } + result : { + className : Error + description : Error at <anonymous>:1:22 at <anonymous>:1:36 + objectId : <objectId> + subtype : error + type : object + } + } +} + +Running test: testFunctionReturnNotPromise +{ + id : <messageId> + result : { + result : { + description : 239 + type : number + value : 239 + } + } +} + +Running test: testFunctionReturnResolvedPromiseReturnByValue +{ + id : <messageId> + result : { + result : { + type : object + value : { + a : 3 + } + } + } +} + +Running test: testFunctionReturnResolvedPromiseWithPreview +{ + id : <messageId> + result : { + result : { + className : Object + description : Object + objectId : <objectId> + preview : { + description : Object + overflow : false + properties : [ + [0] : { + name : a + type : number + value : 3 + } + ] + type : object + } + type : object + } + } +} + +Running test: testFunctionReturnRejectedPromise +{ + id : <messageId> + result : { + exceptionDetails : { + columnNumber : 0 + exception : { + type : object + value : { + a : 3 + } + } + exceptionId : <exceptionId> + lineNumber : 0 + text : Uncaught (in promise) + } + result : { + type : object + value : { + a : 3 + } + } + } +} + +Running test: testEvaluateOnExecutionContext +{ + id : <messageId> + result : { + result : { + description : 70 + type : number + value : 70 + } + } +} + +Running test: testPassingBothObjectIdAndExecutionContextId +{ + error : { + code : -32000 + message : ObjectId must not be specified together with executionContextId + } + id : <messageId> +}
diff --git a/src/v8/test/inspector/runtime/call-function-on-async.js b/src/v8/test/inspector/runtime/call-function-on-async.js new file mode 100644 index 0000000..277a01c --- /dev/null +++ b/src/v8/test/inspector/runtime/call-function-on-async.js
@@ -0,0 +1,150 @@ +// 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 Runtime.callFunctionOn works with awaitPromise flag.'); +let callFunctionOn = Protocol.Runtime.callFunctionOn.bind(Protocol.Runtime); + +let remoteObject1; +let remoteObject2; +let executionContextId; + +Protocol.Runtime.enable(); +Protocol.Runtime.onExecutionContextCreated(messageObject => { + executionContextId = messageObject.params.context.id; + InspectorTest.runAsyncTestSuite(testSuite); +}); + +let testSuite = [ + async function prepareTestSuite() { + let result = await Protocol.Runtime.evaluate({ expression: '({a : 1})' }); + remoteObject1 = result.result.result; + result = await Protocol.Runtime.evaluate({ expression: '({a : 2})' }); + remoteObject2 = result.result.result; + + await Protocol.Runtime.evaluate({ expression: 'globalObjectProperty = 42;' }); + }, + + async function testArguments() { + InspectorTest.logMessage(await callFunctionOn({ + objectId: remoteObject1.objectId, + functionDeclaration: 'function(arg1, arg2, arg3, arg4) { return \'\' + arg1 + \'|\' + arg2 + \'|\' + arg3 + \'|\' + arg4; }', + arguments: prepareArguments([undefined, NaN, remoteObject2, remoteObject1]), + returnByValue: true, + generatePreview: false, + awaitPromise: false + })); + }, + + async function testComplexArguments() { + InspectorTest.logMessage(await callFunctionOn({ + objectId: remoteObject1.objectId, + functionDeclaration: 'function(arg) { return arg.foo; }', + arguments: prepareArguments([{foo: 'bar'}]), + returnByValue: true, + generatePreview: false, + awaitPromise: false + })); + }, + + async function testSyntaxErrorInFunction() { + InspectorTest.logMessage(await callFunctionOn({ + objectId: remoteObject1.objectId, + functionDeclaration: '\n }', + arguments: prepareArguments([]), + returnByValue: false, + generatePreview: false, + awaitPromise: true + })); + }, + + async function testExceptionInFunctionExpression() { + InspectorTest.logMessage(await callFunctionOn({ + objectId: remoteObject1.objectId, + functionDeclaration: '(function() { throw new Error() })()', + arguments: prepareArguments([]), + returnByValue: false, + generatePreview: false, + awaitPromise: true + })); + }, + + async function testFunctionReturnNotPromise() { + InspectorTest.logMessage(await callFunctionOn({ + objectId: remoteObject1.objectId, + functionDeclaration: '(function() { return 239; })', + arguments: prepareArguments([]), + returnByValue: true, + generatePreview: false, + awaitPromise: true + })); + }, + + async function testFunctionReturnResolvedPromiseReturnByValue() { + InspectorTest.logMessage(await callFunctionOn({ + objectId: remoteObject1.objectId, + functionDeclaration: '(function(arg) { return Promise.resolve({a : this.a + arg.a}); })', + arguments: prepareArguments([ remoteObject2 ]), + returnByValue: true, + generatePreview: false, + awaitPromise: true + })); + }, + + async function testFunctionReturnResolvedPromiseWithPreview() { + InspectorTest.logMessage(await callFunctionOn({ + objectId: remoteObject1.objectId, + functionDeclaration: '(function(arg) { return Promise.resolve({a : this.a + arg.a}); })', + arguments: prepareArguments([ remoteObject2 ]), + returnByValue: false, + generatePreview: true, + awaitPromise: true + })); + }, + + async function testFunctionReturnRejectedPromise() { + InspectorTest.logMessage(await callFunctionOn({ + objectId: remoteObject1.objectId, + functionDeclaration: '(function(arg) { return Promise.reject({a : this.a + arg.a}); })', + arguments: prepareArguments([ remoteObject2 ]), + returnByValue: true, + generatePreview: false, + awaitPromise: true + })); + }, + + async function testEvaluateOnExecutionContext() { + InspectorTest.logMessage(await callFunctionOn({ + executionContextId, + functionDeclaration: '(function(arg) { return this.globalObjectProperty + arg; })', + arguments: prepareArguments([ 28 ]), + returnByValue: true, + generatePreview: false, + awaitPromise: false + })); + }, + + async function testPassingBothObjectIdAndExecutionContextId() { + InspectorTest.logMessage(await callFunctionOn({ + executionContextId, + objectId: remoteObject1.objectId, + functionDeclaration: '(function() { return 42; })', + arguments: prepareArguments([]), + returnByValue: true, + generatePreview: false, + awaitPromise: false + })); + }, +]; + +function prepareArguments(args) { + return args.map(arg => { + if (Object.is(arg, -0)) + return {unserializableValue: '-0'}; + if (Object.is(arg, NaN) || Object.is(arg, Infinity) || Object.is(arg, -Infinity)) + return {unserializableValue: arg + ''}; + if (arg && arg.objectId) + return {objectId: arg.objectId}; + return {value: arg}; + }); +}
diff --git a/src/v8/test/inspector/runtime/clear-of-command-line-api-expected.txt b/src/v8/test/inspector/runtime/clear-of-command-line-api-expected.txt new file mode 100644 index 0000000..f63b918 --- /dev/null +++ b/src/v8/test/inspector/runtime/clear-of-command-line-api-expected.txt
@@ -0,0 +1,177 @@ +Tests that CommandLineAPI is presented only while evaluation. + +{ + id : <messageId> + result : { + result : { + description : 15 + type : number + value : 15 + } + } +} +{ + id : <messageId> + result : { + result : { + description : 0 + type : number + value : 0 + } + } +} +setPropertyForMethod() +{ + id : <messageId> + result : { + result : { + description : 14 + type : number + value : 14 + } + } +} +{ + id : <messageId> + result : { + result : { + description : 0 + type : number + value : 0 + } + } +} +{ + id : <messageId> + result : { + result : { + description : 42 + type : number + value : 42 + } + } +} +defineValuePropertyForMethod() +{ + id : <messageId> + result : { + result : { + description : 14 + type : number + value : 14 + } + } +} +{ + id : <messageId> + result : { + result : { + description : 0 + type : number + value : 0 + } + } +} +{ + id : <messageId> + result : { + result : { + description : 42 + type : number + value : 42 + } + } +} +definePropertiesForMethod() +{ + id : <messageId> + result : { + result : { + description : 14 + type : number + value : 14 + } + } +} +{ + id : <messageId> + result : { + result : { + description : 0 + type : number + value : 0 + } + } +} +{ + id : <messageId> + result : { + result : { + description : 42 + type : number + value : 42 + } + } +} +defineAccessorPropertyForMethod() +{ + id : <messageId> + result : { + result : { + description : 14 + type : number + value : 14 + } + } +} +{ + id : <messageId> + result : { + result : { + description : 0 + type : number + value : 0 + } + } +} +{ + id : <messageId> + result : { + result : { + description : 42 + type : number + value : 42 + } + } +} +redefineGetOwnPropertyDescriptors() +{ + id : <messageId> + result : { + result : { + description : 14 + type : number + value : 14 + } + } +} +{ + id : <messageId> + result : { + result : { + description : 0 + type : number + value : 0 + } + } +} +{ + id : <messageId> + result : { + result : { + description : 42 + type : number + value : 42 + } + } +}
diff --git a/src/v8/test/inspector/runtime/clear-of-command-line-api.js b/src/v8/test/inspector/runtime/clear-of-command-line-api.js new file mode 100644 index 0000000..d67a1c5 --- /dev/null +++ b/src/v8/test/inspector/runtime/clear-of-command-line-api.js
@@ -0,0 +1,117 @@ +// 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 CommandLineAPI is presented only while evaluation."); + +contextGroup.addScript( +` +var methods = ["dir","dirxml","profile","profileEnd","clear","table","keys","values","debug","undebug","monitor","unmonitor","inspect","copy"]; +var window = this; +function presentedAPIMethods() +{ + var methodCount = 0; + for (var method of methods) { + try { + if (eval("window." + method + "&&" + method + ".toString ? " + method + ".toString().indexOf(\\"[Command Line API]\\") !== -1 : false")) + ++methodCount; + } catch (e) { + } + } + methodCount += eval("\\"$_\\" in window ? $_ === 239 : false") ? 1 : 0; + return methodCount; +} + +function setPropertyForMethod() +{ + window.dir = 42; +} + +function defineValuePropertyForMethod() +{ + Object.defineProperty(window, "dir", { value: 42 }); +} + +function defineAccessorPropertyForMethod() +{ + Object.defineProperty(window, "dir", { set: function() {}, get: function(){ return 42 } }); +} + +function definePropertiesForMethod() +{ + Object.defineProperties(window, { "dir": { set: function() {}, get: function(){ return 42 } }}); +} + +var builtinGetOwnPropertyDescriptorOnObject; +var builtinGetOwnPropertyDescriptorOnObjectPrototype; +var builtinGetOwnPropertyDescriptorOnWindow; + +function redefineGetOwnPropertyDescriptors() +{ + builtinGetOwnPropertyDescriptorOnObject = Object.getOwnPropertyDescriptor; + Object.getOwnPropertyDescriptor = function() {} + builtinGetOwnPropertyDescriptorOnObjectPrototype = Object.prototype.getOwnPropertyDescriptor; + Object.prototype.getOwnPropertyDescriptor = function() {} + builtinGetOwnPropertyDescriptorOnWindow = window.getOwnPropertyDescriptor; + window.getOwnPropertyDescriptor = function() {} +} + +function restoreGetOwnPropertyDescriptors() +{ + Object.getOwnPropertyDescriptor = builtinGetOwnPropertyDescriptorOnObject; + Object.prototype.getOwnPropertyDescriptor = builtinGetOwnPropertyDescriptorOnObjectPrototype; + window.getOwnPropertyDescriptor = builtinGetOwnPropertyDescriptorOnWindow; +}`); + +runExpressionAndDumpPresentedMethods("") + .then(dumpLeftMethods) + .then(() => runExpressionAndDumpPresentedMethods("setPropertyForMethod()")) + .then(dumpLeftMethods) + .then(dumpDir) + .then(() => runExpressionAndDumpPresentedMethods("defineValuePropertyForMethod()")) + .then(dumpLeftMethods) + .then(dumpDir) + .then(() => runExpressionAndDumpPresentedMethods("definePropertiesForMethod()")) + .then(dumpLeftMethods) + .then(dumpDir) + .then(() => runExpressionAndDumpPresentedMethods("defineAccessorPropertyForMethod()")) + .then(dumpLeftMethods) + .then(dumpDir) + .then(() => runExpressionAndDumpPresentedMethods("redefineGetOwnPropertyDescriptors()")) + .then(dumpLeftMethods) + .then(dumpDir) + .then(() => evaluate("restoreGetOwnPropertyDescriptors()", false)) + .then(InspectorTest.completeTest); + +function evaluate(expression, includeCommandLineAPI) +{ + return Protocol.Runtime.evaluate({ expression: expression, objectGroup: "console", includeCommandLineAPI: includeCommandLineAPI }); +} + +function setLastEvaluationResultTo239() +{ + return evaluate("239", false); +} + +function runExpressionAndDumpPresentedMethods(expression) +{ + InspectorTest.log(expression); + return setLastEvaluationResultTo239() + .then(() => evaluate(expression + "; var a = presentedAPIMethods(); a", true)) + .then((result) => InspectorTest.logMessage(result)); +} + +function dumpLeftMethods() +{ + // Should always be zero. + return setLastEvaluationResultTo239() + .then(() => evaluate("presentedAPIMethods()", false)) + .then((result) => InspectorTest.logMessage(result)); +} + +function dumpDir() +{ + // Should always be presented. + return evaluate("dir", false) + .then((result) => InspectorTest.logMessage(result)); +}
diff --git a/src/v8/test/inspector/runtime/client-console-api-message-expected.txt b/src/v8/test/inspector/runtime/client-console-api-message-expected.txt new file mode 100644 index 0000000..699b390 --- /dev/null +++ b/src/v8/test/inspector/runtime/client-console-api-message-expected.txt
@@ -0,0 +1,8 @@ +Checks that we passed correct arguments in V8InspectorClient::consoleAPIMessage. Note: lines and columns are 1-based. +42 (:1:9) + at (anonymous function) (:1:9) +239 (:13:15) + at b (:13:15) + at a (:15:5) + at consoleTrace (:17:3) + at (anonymous function) (:1:1)
diff --git a/src/v8/test/inspector/runtime/client-console-api-message.js b/src/v8/test/inspector/runtime/client-console-api-message.js new file mode 100644 index 0000000..15838fa --- /dev/null +++ b/src/v8/test/inspector/runtime/client-console-api-message.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('Checks that we passed correct arguments in ' + + 'V8InspectorClient::consoleAPIMessage. Note: lines and columns are 1-based.'); + +contextGroup.addScript(` +function consoleTrace() { + function a() { + function b() { + console.trace(239); + } + b(); + } + a(); +} +`, 8, 26); + +Protocol.Runtime.enable(); +utils.setLogConsoleApiMessageCalls(true); +(async function test() { + Protocol.Runtime.evaluate({expression: 'console.log(42)'}); + await Protocol.Runtime.onceConsoleAPICalled() + Protocol.Runtime.evaluate({expression: 'consoleTrace()'}); + await Protocol.Runtime.onceConsoleAPICalled() + InspectorTest.completeTest(); +})();
diff --git a/src/v8/test/inspector/runtime/command-line-api-expected.txt b/src/v8/test/inspector/runtime/command-line-api-expected.txt new file mode 100644 index 0000000..f655e7b --- /dev/null +++ b/src/v8/test/inspector/runtime/command-line-api-expected.txt
@@ -0,0 +1,683 @@ +Checks command line API. + +Running test: testKeys +{ + id : <messageId> + result : { + result : { + className : Function + description : function keys(object) { [Command Line API] } + objectId : <objectId> + type : function + } + } +} +{ + id : <messageId> + result : { + result : { + type : object + value : [ + [0] : a + ] + } + } +} +{ + id : <messageId> + result : { + result : { + type : object + value : [ + [0] : a + ] + } + } +} + +Running test: testInspect +[object Object] +{ + method : Runtime.inspectRequested + params : { + hints : { + } + object : { + className : Object + description : Object + objectId : <objectId> + type : object + } + } +} +{ + method : Runtime.inspectRequested + params : { + hints : { + } + object : { + description : 239 + type : number + value : 239 + } + } +} +{ + method : Runtime.inspectRequested + params : { + hints : { + } + object : { + description : -0 + type : number + unserializableValue : -0 + } + } +} +{ + method : Runtime.inspectRequested + params : { + hints : { + copyToClipboard : true + } + object : { + type : string + value : hello + } + } +} +{ + id : <messageId> + result : { + result : { + type : undefined + } + } +} +{ + method : Runtime.inspectRequested + params : { + hints : { + } + object : { + className : Object + description : Object + objectId : <objectId> + type : object + } + } +} + +Running test: testQueryObjects +{ + id : <messageId> + result : { + result : { + className : Function + description : function queryObjects(constructor) { [Command Line API] } + objectId : <objectId> + type : function + } + } +} +{ + method : Runtime.inspectRequested + params : { + hints : { + queryObjects : true + } + object : { + className : Promise + description : Promise + objectId : <objectId> + type : object + } + } +} +Is Promise.prototype: true +{ + method : Runtime.inspectRequested + params : { + hints : { + queryObjects : true + } + object : { + className : Promise + description : Promise + objectId : <objectId> + type : object + } + } +} +Is Promise.prototype: true +{ + method : Runtime.inspectRequested + params : { + hints : { + queryObjects : true + } + object : { + className : Object + description : Object + objectId : <objectId> + type : object + } + } +} +Is p: true +{ + method : Runtime.inspectRequested + params : { + hints : { + queryObjects : true + } + object : { + description : 1 + type : number + value : 1 + } + } +} + +Running test: testEvaluationResult +{ + id : <messageId> + result : { + result : { + type : undefined + } + } +} +{ + id : <messageId> + result : { + result : { + description : 42 + type : number + value : 42 + } + } +} +{ + id : <messageId> + result : { + result : { + description : 42 + type : number + value : 42 + } + } +} +{ + id : <messageId> + result : { + result : { + description : -0 + type : number + unserializableValue : -0 + } + } +} +{ + id : <messageId> + result : { + result : { + type : object + value : { + } + } + } +} + +Running test: testDebug +{ + id : <messageId> + result : { + result : { + className : Function + description : function debug(function) { [Command Line API] } + objectId : <objectId> + type : function + } + } +} +{ + id : <messageId> + result : { + result : { + className : Function + description : function undebug(function) { [Command Line API] } + objectId : <objectId> + type : function + } + } +} +foo (:0:16) +(anonymous) (:0:0) +[ + [0] : <scriptId>:0:12:debug +] +foo (:0:16) +(anonymous) (:0:0) +[ + [0] : <scriptId>:0:12:debug +] + +Running test: testMonitor +{ + id : <messageId> + result : { + result : { + className : Function + description : function monitor(function) { [Command Line API] } + objectId : <objectId> + type : function + } + } +} +{ + id : <messageId> + result : { + result : { + className : Function + description : function unmonitor(function) { [Command Line API] } + objectId : <objectId> + type : function + } + } +} +function foo called +after first call +store functions.. +function foo called +after first call + +Running test: testProfile +{ + id : <messageId> + result : { + result : { + className : Function + description : function profile(title) { [Command Line API] } + objectId : <objectId> + type : function + } + } +} +{ + id : <messageId> + result : { + result : { + className : Function + description : function profileEnd(title) { [Command Line API] } + objectId : <objectId> + type : function + } + } +} +{ + method : Profiler.consoleProfileStarted + params : { + id : 1 + location : { + columnNumber : 1 + lineNumber : 1 + scriptId : <scriptId> + } + title : 42 + } +} +{ + method : Profiler.consoleProfileFinished + params : { + id : 1 + location : { + columnNumber : 1 + lineNumber : 1 + scriptId : <scriptId> + } + profile : <profile> + title : 42 + } +} +{ + method : Profiler.consoleProfileStarted + params : { + id : 2 + location : { + columnNumber : 6 + lineNumber : 1 + scriptId : <scriptId> + } + title : 239 + } +} +{ + method : Profiler.consoleProfileFinished + params : { + id : 2 + location : { + columnNumber : 6 + lineNumber : 1 + scriptId : <scriptId> + } + profile : <profile> + title : 239 + } +} + +Running test: testDir +{ + id : <messageId> + result : { + result : { + className : Function + description : function dir(value) { [Command Line API] } + objectId : <objectId> + type : function + } + } +} +{ + method : Runtime.consoleAPICalled + params : { + args : [ + [0] : { + className : Object + description : Object + objectId : <objectId> + preview : { + description : Object + overflow : false + properties : [ + ] + type : object + } + type : object + } + ] + executionContextId : <executionContextId> + stackTrace : { + callFrames : [ + [0] : { + columnNumber : 0 + functionName : + lineNumber : 0 + scriptId : <scriptId> + url : + } + ] + } + timestamp : <timestamp> + type : dir + } +} +{ + method : Runtime.consoleAPICalled + params : { + args : [ + [0] : { + description : 42 + type : number + value : 42 + } + ] + executionContextId : <executionContextId> + stackTrace : { + callFrames : [ + [0] : { + columnNumber : 0 + functionName : + lineNumber : 0 + scriptId : <scriptId> + url : + } + ] + } + timestamp : <timestamp> + type : dir + } +} +{ + method : Runtime.consoleAPICalled + params : { + args : [ + [0] : { + className : Object + description : Object + objectId : <objectId> + preview : { + description : Object + overflow : false + properties : [ + ] + type : object + } + type : object + } + ] + executionContextId : <executionContextId> + stackTrace : { + callFrames : [ + [0] : { + columnNumber : 5 + functionName : + lineNumber : 0 + scriptId : <scriptId> + url : + } + ] + } + timestamp : <timestamp> + type : dir + } +} + +Running test: testDirXML +{ + id : <messageId> + result : { + result : { + className : Function + description : function dirxml(value) { [Command Line API] } + objectId : <objectId> + type : function + } + } +} +{ + method : Runtime.consoleAPICalled + params : { + args : [ + [0] : { + className : Object + description : Object + objectId : <objectId> + preview : { + description : Object + overflow : false + properties : [ + ] + type : object + } + type : object + } + ] + executionContextId : <executionContextId> + stackTrace : { + callFrames : [ + [0] : { + columnNumber : 0 + functionName : + lineNumber : 0 + scriptId : <scriptId> + url : + } + ] + } + timestamp : <timestamp> + type : dirxml + } +} +{ + method : Runtime.consoleAPICalled + params : { + args : [ + [0] : { + description : 42 + type : number + value : 42 + } + ] + executionContextId : <executionContextId> + stackTrace : { + callFrames : [ + [0] : { + columnNumber : 0 + functionName : + lineNumber : 0 + scriptId : <scriptId> + url : + } + ] + } + timestamp : <timestamp> + type : dirxml + } +} + +Running test: testTable +{ + id : <messageId> + result : { + result : { + className : Function + description : function table(data, [columns]) { [Command Line API] } + objectId : <objectId> + type : function + } + } +} +{ + method : Runtime.consoleAPICalled + params : { + args : [ + [0] : { + className : Object + description : Object + objectId : <objectId> + preview : { + description : Object + overflow : false + properties : [ + ] + type : object + } + type : object + } + ] + executionContextId : <executionContextId> + stackTrace : { + callFrames : [ + [0] : { + columnNumber : 0 + functionName : + lineNumber : 0 + scriptId : <scriptId> + url : + } + ] + } + timestamp : <timestamp> + type : table + } +} +{ + method : Runtime.consoleAPICalled + params : { + args : [ + [0] : { + description : 42 + type : number + value : 42 + } + ] + executionContextId : <executionContextId> + stackTrace : { + callFrames : [ + [0] : { + columnNumber : 0 + functionName : + lineNumber : 0 + scriptId : <scriptId> + url : + } + ] + } + timestamp : <timestamp> + type : table + } +} + +Running test: testClear +{ + id : <messageId> + result : { + result : { + className : Function + description : function clear() { [Command Line API] } + objectId : <objectId> + type : function + } + } +} +{ + method : Runtime.consoleAPICalled + params : { + args : [ + [0] : { + type : string + value : console.clear + } + ] + executionContextId : <executionContextId> + stackTrace : { + callFrames : [ + [0] : { + columnNumber : 0 + functionName : + lineNumber : 0 + scriptId : <scriptId> + url : + } + ] + } + timestamp : <timestamp> + type : clear + } +} +{ + method : Runtime.consoleAPICalled + params : { + args : [ + [0] : { + type : string + value : console.clear + } + ] + executionContextId : <executionContextId> + stackTrace : { + callFrames : [ + [0] : { + columnNumber : 5 + functionName : + lineNumber : 0 + scriptId : <scriptId> + url : + } + ] + } + timestamp : <timestamp> + type : clear + } +}
diff --git a/src/v8/test/inspector/runtime/command-line-api.js b/src/v8/test/inspector/runtime/command-line-api.js new file mode 100644 index 0000000..2826ac2 --- /dev/null +++ b/src/v8/test/inspector/runtime/command-line-api.js
@@ -0,0 +1,209 @@ +// 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 command line API.'); + +InspectorTest.runAsyncTestSuite([ + async function testKeys() { + InspectorTest.logMessage(await Protocol.Runtime.evaluate({ + expression: 'keys', includeCommandLineAPI: true})); + InspectorTest.logMessage(await Protocol.Runtime.evaluate({ + expression: 'keys({a : 1})', includeCommandLineAPI: true, returnByValue: true})); + + Protocol.Runtime.evaluate({expression: 'this.keys = keys', includeCommandLineAPI: true}); + InspectorTest.logMessage(await Protocol.Runtime.evaluate({ + expression: 'this.keys({a : 1})', returnByValue: true})); + }, + + async function testInspect() { + InspectorTest.log(await Protocol.Runtime.evaluate({expression: 'inspect', includeCommandLineAPI: true})); + await Protocol.Runtime.enable(); + Protocol.Runtime.onInspectRequested(InspectorTest.logMessage); + await Protocol.Runtime.evaluate({expression: 'inspect({})', includeCommandLineAPI: true}); + await Protocol.Runtime.evaluate({expression: 'inspect(239)', includeCommandLineAPI: true}); + await Protocol.Runtime.evaluate({expression: 'inspect(-0)', includeCommandLineAPI: true}); + await Protocol.Runtime.evaluate({expression: 'copy(\'hello\')', includeCommandLineAPI: true}); + InspectorTest.logMessage(await Protocol.Runtime.evaluate({expression: '$0', includeCommandLineAPI: true})); + + Protocol.Runtime.evaluate({expression: 'this.inspect = inspect', includeCommandLineAPI: true}); + await Protocol.Runtime.evaluate({expression: 'this.inspect({})'}); + + Protocol.Runtime.onInspectRequested(null); + await Protocol.Runtime.disable(); + }, + + async function testQueryObjects() { + InspectorTest.logMessage(await Protocol.Runtime.evaluate({expression: 'queryObjects', includeCommandLineAPI: true})); + await Protocol.Runtime.enable(); + let {result:{result:{objectId}}} = await Protocol.Runtime.evaluate({expression: 'Promise.prototype'}); + Protocol.Runtime.evaluate({expression: 'queryObjects(Promise)', includeCommandLineAPI: true}); + let request = await Protocol.Runtime.onceInspectRequested(); + InspectorTest.logMessage(request); + InspectorTest.logMessage('Is Promise.prototype: ' + await isEqual(objectId, request.params.object.objectId)); + + Protocol.Runtime.evaluate({expression: 'queryObjects(Promise.prototype)', includeCommandLineAPI: true}); + request = await Protocol.Runtime.onceInspectRequested(); + InspectorTest.logMessage(request); + InspectorTest.logMessage('Is Promise.prototype: ' + await isEqual(objectId, request.params.object.objectId)); + + ({result:{result:{objectId}}} = await Protocol.Runtime.evaluate({expression:'p = {a:1}'})); + Protocol.Runtime.evaluate({expression: 'queryObjects(p)', includeCommandLineAPI: true}); + request = await Protocol.Runtime.onceInspectRequested(); + InspectorTest.logMessage(request); + InspectorTest.logMessage('Is p: ' + await isEqual(objectId, request.params.object.objectId)); + + Protocol.Runtime.evaluate({expression: 'queryObjects(1)', includeCommandLineAPI: true}); + InspectorTest.logMessage(await Protocol.Runtime.onceInspectRequested()); + await Protocol.Runtime.disable(); + }, + + async function testEvaluationResult() { + InspectorTest.logMessage(await Protocol.Runtime.evaluate({expression: '$_', includeCommandLineAPI: true})); + await Protocol.Runtime.evaluate({expression: '42', objectGroup: 'console', includeCommandLineAPI: true}); + InspectorTest.logMessage(await Protocol.Runtime.evaluate({expression: '$_', includeCommandLineAPI: true})); + await Protocol.Runtime.evaluate({expression: '239', includeCommandLineAPI: true}); + InspectorTest.logMessage(await Protocol.Runtime.evaluate({expression: '$_', includeCommandLineAPI: true})); + await Protocol.Runtime.evaluate({expression: '-0', objectGroup: 'console', includeCommandLineAPI: true}); + InspectorTest.logMessage(await Protocol.Runtime.evaluate({expression: '$_', includeCommandLineAPI: true})); + await Protocol.Runtime.evaluate({expression: '({})', objectGroup: 'console', includeCommandLineAPI: true}); + InspectorTest.logMessage(await Protocol.Runtime.evaluate({expression: '$_', includeCommandLineAPI: true, returnByValue: true})); + }, + + async function testDebug() { + session.setupScriptMap(); + await Protocol.Debugger.enable(); + InspectorTest.logMessage(await Protocol.Runtime.evaluate({expression: 'debug', includeCommandLineAPI: true})); + InspectorTest.logMessage(await Protocol.Runtime.evaluate({expression: 'undebug', includeCommandLineAPI: true})); + await Protocol.Runtime.evaluate({expression: 'function foo() {}'}); + await Protocol.Runtime.evaluate({expression: 'debug(foo)', includeCommandLineAPI: true}); + Protocol.Runtime.evaluate({ expression: 'foo()'}); + let message = await Protocol.Debugger.oncePaused(); + session.logCallFrames(message.params.callFrames); + InspectorTest.logMessage(message.params.hitBreakpoints); + await Protocol.Debugger.resume(); + await Protocol.Runtime.evaluate({expression: 'undebug(foo)', includeCommandLineAPI: true}); + await Protocol.Runtime.evaluate({ expression: 'foo()'}); + + Protocol.Runtime.evaluate({ + expression: 'this.debug = debug; this.undebug = undebug;', includeCommandLineAPI: true}); + await Protocol.Runtime.evaluate({expression: 'this.debug(foo)'}); + Protocol.Runtime.evaluate({ expression: 'foo()'}); + message = await Protocol.Debugger.oncePaused(); + session.logCallFrames(message.params.callFrames); + InspectorTest.logMessage(message.params.hitBreakpoints); + await Protocol.Debugger.resume(); + await Protocol.Runtime.evaluate({expression: 'this.undebug(foo)'}); + await Protocol.Runtime.evaluate({expression: 'foo()'}); + + await Protocol.Debugger.disable(); + }, + + async function testMonitor() { + await Protocol.Debugger.enable(); + await Protocol.Runtime.enable(); + Protocol.Runtime.onConsoleAPICalled(message => InspectorTest.log(message.params.args[0].value)); + InspectorTest.logMessage(await Protocol.Runtime.evaluate({expression: 'monitor', includeCommandLineAPI: true})); + InspectorTest.logMessage(await Protocol.Runtime.evaluate({expression: 'unmonitor', includeCommandLineAPI: true})); + await Protocol.Runtime.evaluate({expression: 'function foo() {}'}); + + await Protocol.Runtime.evaluate({expression: 'monitor(foo)', includeCommandLineAPI: true}); + Protocol.Runtime.evaluate({ expression: 'foo(); console.log(\'after first call\')'}); + await Protocol.Runtime.evaluate({expression: 'unmonitor(foo)', includeCommandLineAPI: true}); + await Protocol.Runtime.evaluate({ expression: 'foo()'}); + + Protocol.Runtime.evaluate({ + expression: 'console.log(\'store functions..\'); this.monitor = monitor; this.unmonitor = unmonitor;', includeCommandLineAPI: true}); + await Protocol.Runtime.evaluate({expression: 'this.monitor(foo)'}); + Protocol.Runtime.evaluate({ expression: 'foo(); console.log(\'after first call\')'}); + await Protocol.Runtime.evaluate({expression: 'this.unmonitor(foo)'}); + await Protocol.Runtime.evaluate({ expression: 'foo()'}); + + Protocol.Runtime.onConsoleAPICalled(null); + await Protocol.Debugger.disable(); + await Protocol.Runtime.disable(); + }, + + async function testProfile() { + await Protocol.Profiler.enable(); + InspectorTest.logMessage(await Protocol.Runtime.evaluate({expression: 'profile', includeCommandLineAPI: true})); + InspectorTest.logMessage(await Protocol.Runtime.evaluate({expression: 'profileEnd', includeCommandLineAPI: true})); + + Protocol.Runtime.evaluate({expression: 'profile(42)', includeCommandLineAPI: true}); + InspectorTest.logMessage(await Protocol.Profiler.onceConsoleProfileStarted()); + Protocol.Runtime.evaluate({expression: 'profileEnd(42)', includeCommandLineAPI: true}); + let message = await Protocol.Profiler.onceConsoleProfileFinished(); + message.params.profile = '<profile>'; + InspectorTest.logMessage(message); + + Protocol.Runtime.evaluate({ + expression: 'this.profile = profile; this.profileEnd = profileEnd;', includeCommandLineAPI: true}); + Protocol.Runtime.evaluate({expression: 'this.profile(239)'}); + InspectorTest.logMessage(await Protocol.Profiler.onceConsoleProfileStarted()); + Protocol.Runtime.evaluate({expression: 'this.profileEnd(239)'}); + message = await Protocol.Profiler.onceConsoleProfileFinished(); + message.params.profile = '<profile>'; + InspectorTest.logMessage(message); + + await Protocol.Profiler.disable(); + }, + + async function testDir() { + InspectorTest.logMessage(await Protocol.Runtime.evaluate({expression: 'dir', includeCommandLineAPI: true})); + + await Protocol.Runtime.enable(); + Protocol.Runtime.evaluate({expression: 'dir({})', includeCommandLineAPI: true}); + InspectorTest.logMessage(await Protocol.Runtime.onceConsoleAPICalled()); + Protocol.Runtime.evaluate({expression: 'dir(42)', includeCommandLineAPI: true}); + InspectorTest.logMessage(await Protocol.Runtime.onceConsoleAPICalled()); + + Protocol.Runtime.evaluate({expression: 'this.dir = dir', includeCommandLineAPI: true}); + Protocol.Runtime.evaluate({expression: 'this.dir({})'}); + InspectorTest.logMessage(await Protocol.Runtime.onceConsoleAPICalled()); + await Protocol.Runtime.disable(); + }, + + async function testDirXML() { + InspectorTest.logMessage(await Protocol.Runtime.evaluate({expression: 'dirxml', includeCommandLineAPI: true})); + + await Protocol.Runtime.enable(); + Protocol.Runtime.evaluate({expression: 'dirxml({})', includeCommandLineAPI: true}); + InspectorTest.logMessage(await Protocol.Runtime.onceConsoleAPICalled()); + Protocol.Runtime.evaluate({expression: 'dirxml(42)', includeCommandLineAPI: true}); + InspectorTest.logMessage(await Protocol.Runtime.onceConsoleAPICalled()); + await Protocol.Runtime.disable(); + }, + + async function testTable() { + InspectorTest.logMessage(await Protocol.Runtime.evaluate({expression: 'table', includeCommandLineAPI: true})); + + await Protocol.Runtime.enable(); + Protocol.Runtime.evaluate({expression: 'table({})', includeCommandLineAPI: true}); + InspectorTest.logMessage(await Protocol.Runtime.onceConsoleAPICalled()); + Protocol.Runtime.evaluate({expression: 'table(42)', includeCommandLineAPI: true}); + InspectorTest.logMessage(await Protocol.Runtime.onceConsoleAPICalled()); + await Protocol.Runtime.disable(); + }, + + async function testClear() { + InspectorTest.logMessage(await Protocol.Runtime.evaluate({expression: 'clear', includeCommandLineAPI: true})); + + await Protocol.Runtime.enable(); + Protocol.Runtime.evaluate({expression: 'clear()', includeCommandLineAPI: true}); + InspectorTest.logMessage(await Protocol.Runtime.onceConsoleAPICalled()); + + Protocol.Runtime.evaluate({expression: 'this.clear = clear', includeCommandLineAPI: true}); + Protocol.Runtime.evaluate({expression: 'this.clear()'}); + InspectorTest.logMessage(await Protocol.Runtime.onceConsoleAPICalled()); + await Protocol.Runtime.disable(); + } +]); + +async function isEqual(objectId1, objectId2) { + return (await Protocol.Runtime.callFunctionOn({ + objectId: objectId1, + functionDeclaration: 'function(arg){return this === arg;}', + returnByValue: true, + arguments: [{objectId: objectId2}] + })).result.result.value; +}
diff --git a/src/v8/test/inspector/runtime/compile-script-expected.txt b/src/v8/test/inspector/runtime/compile-script-expected.txt new file mode 100644 index 0000000..23e6a64 --- /dev/null +++ b/src/v8/test/inspector/runtime/compile-script-expected.txt
@@ -0,0 +1,67 @@ +Tests Runtime.compileScript +Compiling script: foo1.js + persist: false +compilation result: +{ + id : <messageId> + result : { + exceptionDetails : { + columnNumber : 2 + exception : { + className : SyntaxError + description : SyntaxError: Unexpected end of input + objectId : <objectId> + subtype : error + type : object + } + exceptionId : <exceptionId> + lineNumber : 1 + scriptId : <scriptId> + text : Uncaught + } + } +} +----- +Compiling script: foo2.js + persist: true +Debugger.scriptParsed: foo2.js +compilation result: +{ + id : <messageId> + result : { + scriptId : <scriptId> + } +} +----- +Compiling script: foo3.js + persist: false +compilation result: +{ + id : <messageId> + result : { + } +} +----- +Compiling script: foo4.js + persist: false +compilation result: +{ + id : <messageId> + result : { + exceptionDetails : { + columnNumber : 13 + exception : { + className : SyntaxError + description : SyntaxError: Unexpected identifier + objectId : <objectId> + subtype : error + type : object + } + exceptionId : <exceptionId> + lineNumber : 0 + scriptId : <scriptId> + text : Uncaught + } + } +} +-----
diff --git a/src/v8/test/inspector/runtime/compile-script.js b/src/v8/test/inspector/runtime/compile-script.js new file mode 100644 index 0000000..6452e07 --- /dev/null +++ b/src/v8/test/inspector/runtime/compile-script.js
@@ -0,0 +1,52 @@ +// 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 Runtime.compileScript'); + +var executionContextId; + +Protocol.Debugger.enable().then(onDebuggerEnabled); + +function onDebuggerEnabled() +{ + Protocol.Runtime.enable(); + Protocol.Debugger.onScriptParsed(onScriptParsed); + Protocol.Runtime.onExecutionContextCreated(onExecutionContextCreated); +} + +function onScriptParsed(messageObject) +{ + if (!messageObject.params.url) + return; + InspectorTest.log("Debugger.scriptParsed: " + messageObject.params.url); +} + +function onExecutionContextCreated(messageObject) +{ + executionContextId = messageObject.params.context.id; + testCompileScript("\n (", false, "foo1.js") + .then(() => testCompileScript("239", true, "foo2.js")) + .then(() => testCompileScript("239", false, "foo3.js")) + .then(() => testCompileScript("testfunction f()\n{\n return 0;\n}\n", false, "foo4.js")) + .then(() => InspectorTest.completeTest()); +} + +function testCompileScript(expression, persistScript, sourceURL) +{ + InspectorTest.log("Compiling script: " + sourceURL); + InspectorTest.log(" persist: " + persistScript); + return Protocol.Runtime.compileScript({ + expression: expression, + sourceURL: sourceURL, + persistScript: persistScript, + executionContextId: executionContextId + }).then(onCompiled); + + function onCompiled(messageObject) + { + InspectorTest.log("compilation result: "); + InspectorTest.logMessage(messageObject); + InspectorTest.log("-----"); + } +}
diff --git a/src/v8/test/inspector/runtime/console-api-repeated-in-console-expected.txt b/src/v8/test/inspector/runtime/console-api-repeated-in-console-expected.txt new file mode 100644 index 0000000..3ec657b --- /dev/null +++ b/src/v8/test/inspector/runtime/console-api-repeated-in-console-expected.txt
@@ -0,0 +1,5 @@ +Check that console.log is reported through Console domain as well. +api call: 42 +api call: abc +console message: 42 +console message: abc
diff --git a/src/v8/test/inspector/runtime/console-api-repeated-in-console.js b/src/v8/test/inspector/runtime/console-api-repeated-in-console.js new file mode 100644 index 0000000..aafdbde --- /dev/null +++ b/src/v8/test/inspector/runtime/console-api-repeated-in-console.js
@@ -0,0 +1,37 @@ +// 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 console.log is reported through Console domain as well."); + +var expectedMessages = 4; +var messages = []; + +Protocol.Runtime.onConsoleAPICalled(consoleAPICalled); +Protocol.Console.onMessageAdded(messageAdded); +Protocol.Runtime.enable(); +Protocol.Console.enable(); +Protocol.Runtime.evaluate({ "expression": "console.log(42)" }); +Protocol.Runtime.evaluate({ "expression": "console.error('abc')" }); + +function consoleAPICalled(result) +{ + messages.push("api call: " + result.params.args[0].value); + if (!(--expectedMessages)) + done(); +} + +function messageAdded(result) +{ + messages.push("console message: " + result.params.message.text); + if (!(--expectedMessages)) + done(); +} + +function done() +{ + messages.sort(); + for (var message of messages) + InspectorTest.log(message); + InspectorTest.completeTest(); +}
diff --git a/src/v8/test/inspector/runtime/console-assert-expected.txt b/src/v8/test/inspector/runtime/console-assert-expected.txt new file mode 100644 index 0000000..bf53474 --- /dev/null +++ b/src/v8/test/inspector/runtime/console-assert-expected.txt
@@ -0,0 +1,147 @@ +Checks that console.assert works and points to correct call frame. +{ + method : Runtime.consoleAPICalled + params : { + args : [ + [0] : { + type : string + value : console.assert + } + ] + executionContextId : <executionContextId> + stackTrace : { + callFrames : [ + [0] : { + columnNumber : 10 + functionName : testFunction + lineNumber : 4 + scriptId : <scriptId> + url : test.js + } + [1] : { + columnNumber : 0 + functionName : + lineNumber : 0 + scriptId : <scriptId> + url : evaluate.js + } + ] + } + timestamp : <timestamp> + type : assert + } +} +{ + method : Runtime.consoleAPICalled + params : { + args : [ + [0] : { + description : 1 + type : number + value : 1 + } + ] + executionContextId : <executionContextId> + stackTrace : { + callFrames : [ + [0] : { + columnNumber : 10 + functionName : testFunction + lineNumber : 5 + scriptId : <scriptId> + url : test.js + } + [1] : { + columnNumber : 0 + functionName : + lineNumber : 0 + scriptId : <scriptId> + url : evaluate.js + } + ] + } + timestamp : <timestamp> + type : assert + } +} +{ + method : Runtime.consoleAPICalled + params : { + args : [ + [0] : { + description : 1 + type : number + value : 1 + } + [1] : { + description : 2 + type : number + value : 2 + } + ] + executionContextId : <executionContextId> + stackTrace : { + callFrames : [ + [0] : { + columnNumber : 10 + functionName : testFunction + lineNumber : 6 + scriptId : <scriptId> + url : test.js + } + [1] : { + columnNumber : 0 + functionName : + lineNumber : 0 + scriptId : <scriptId> + url : evaluate.js + } + ] + } + timestamp : <timestamp> + type : assert + } +} +{ + method : Runtime.consoleAPICalled + params : { + args : [ + [0] : { + type : string + value : console.assert + } + ] + executionContextId : <executionContextId> + stackTrace : { + callFrames : [ + [0] : { + columnNumber : 10 + functionName : testFunction + lineNumber : 7 + scriptId : <scriptId> + url : test.js + } + [1] : { + columnNumber : 0 + functionName : + lineNumber : 0 + scriptId : <scriptId> + url : evaluate.js + } + ] + } + timestamp : <timestamp> + type : assert + } +} +{ + id : <messageId> + result : { + result : { + className : Function + description : function assert() { [native code] } + objectId : <objectId> + type : function + } + } +}
diff --git a/src/v8/test/inspector/runtime/console-assert.js b/src/v8/test/inspector/runtime/console-assert.js new file mode 100644 index 0000000..355149b --- /dev/null +++ b/src/v8/test/inspector/runtime/console-assert.js
@@ -0,0 +1,24 @@ +// 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 console.assert works and points to correct call frame."); + +contextGroup.addScript(` +function testFunction() { + Function.prototype.apply = () => console.error('Should never call this'); + console.assert(true); + console.assert(false); + console.assert(false, 1); + console.assert(false, 1, 2); + console.assert(); + return console.assert; +} +//# sourceURL=test.js`); + +Protocol.Runtime.onConsoleAPICalled(InspectorTest.logMessage); +Protocol.Runtime.enable(); +Protocol.Runtime.evaluate({ + expression: "testFunction()//# sourceURL=evaluate.js" }) + .then(InspectorTest.logMessage) + .then(InspectorTest.completeTest);
diff --git a/src/v8/test/inspector/runtime/console-context-expected.txt b/src/v8/test/inspector/runtime/console-context-expected.txt new file mode 100644 index 0000000..941f9c3 --- /dev/null +++ b/src/v8/test/inspector/runtime/console-context-expected.txt
@@ -0,0 +1,83 @@ +Tests console.context + +Running test: testConsoleContextMethod +console.context description: +{ + className : Function + description : function context() { [native code] } + objectId : <objectId> + type : function +} +console.context() methods: +[ + [0] : debug + [1] : error + [2] : info + [3] : log + [4] : warn + [5] : dir + [6] : dirXml + [7] : table + [8] : trace + [9] : group + [10] : groupCollapsed + [11] : groupEnd + [12] : clear + [13] : count + [14] : assert + [15] : markTimeline + [16] : profile + [17] : profileEnd + [18] : timeline + [19] : timelineEnd + [20] : time + [21] : timeEnd + [22] : timeStamp +] + +Running test: testDefaultConsoleContext +undefined +undefined +undefined + +Running test: testAnonymousConsoleContext +anonymous#2 +anonymous#3 +anonymous#4 + +Running test: testNamedConsoleContext +named-context#6 +named-context#6 +named-context#6 + +Running test: testTwoConsoleContextsWithTheSameName +named-context#7 +named-context#8 + +Running test: testConsoleCountInDifferentConsoleContexts +[ + [0] : { + type : string + value : 239: 1 + } +] +[ + [0] : { + type : string + value : 239: 1 + } +] + +Running test: testConsoleCountForNamedConsoleContext +[ + [0] : { + type : string + value : 239: 1 + } +] +[ + [0] : { + type : string + value : 239: 2 + } +]
diff --git a/src/v8/test/inspector/runtime/console-context.js b/src/v8/test/inspector/runtime/console-context.js new file mode 100644 index 0000000..74996ae --- /dev/null +++ b/src/v8/test/inspector/runtime/console-context.js
@@ -0,0 +1,106 @@ +// 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 console.context'); + +InspectorTest.runAsyncTestSuite([ + async function testConsoleContextMethod() { + InspectorTest.log('console.context description:'); + var {result:{result}} = await Protocol.Runtime.evaluate({ + expression: 'console.context'}); + InspectorTest.logMessage(result); + + InspectorTest.log('console.context() methods:'); + var {result:{result:{value}}} = await Protocol.Runtime.evaluate({ + expression: 'Object.keys(console.context())', returnByValue: true}); + InspectorTest.logMessage(value); + }, + + async function testDefaultConsoleContext() { + await Protocol.Runtime.enable(); + Protocol.Runtime.evaluate({expression: 'console.log(239)'}); + var {params:{context}} = await Protocol.Runtime.onceConsoleAPICalled(); + InspectorTest.log(context); + Protocol.Runtime.evaluate({expression: 'console.info(239)'}); + var {params:{context}} = await Protocol.Runtime.onceConsoleAPICalled(); + InspectorTest.log(context); + Protocol.Runtime.evaluate({expression: 'console.debug(239)'}); + var {params:{context}} = await Protocol.Runtime.onceConsoleAPICalled(); + InspectorTest.log(context); + await Protocol.Runtime.evaluate({expression: 'console.clear()'}); + await Protocol.Runtime.disable(); + }, + + async function testAnonymousConsoleContext() { + await Protocol.Runtime.enable(); + Protocol.Runtime.evaluate({expression: 'console.context().log(239)'}); + var {params:{context}} = await Protocol.Runtime.onceConsoleAPICalled(); + InspectorTest.log(context); + Protocol.Runtime.evaluate({expression: 'console.context().info(239)'}); + var {params:{context}} = await Protocol.Runtime.onceConsoleAPICalled(); + InspectorTest.log(context); + Protocol.Runtime.evaluate({expression: 'console.context().debug(239)'}); + var {params:{context}} = await Protocol.Runtime.onceConsoleAPICalled(); + InspectorTest.log(context); + await Protocol.Runtime.evaluate({expression: 'console.context().clear()'}); + await Protocol.Runtime.disable(); + }, + + async function testNamedConsoleContext() { + await Protocol.Runtime.enable(); + Protocol.Runtime.evaluate({expression: ` + var context = console.context('named-context'); + context.log(239); + context.info(239); + context.debug(239); + `}); + var {params:{context}} = await Protocol.Runtime.onceConsoleAPICalled(); + InspectorTest.log(context); + var {params:{context}} = await Protocol.Runtime.onceConsoleAPICalled(); + InspectorTest.log(context); + var {params:{context}} = await Protocol.Runtime.onceConsoleAPICalled(); + InspectorTest.log(context); + await Protocol.Runtime.evaluate({expression: 'console.clear()'}); + await Protocol.Runtime.disable(); + }, + + async function testTwoConsoleContextsWithTheSameName() { + await Protocol.Runtime.enable(); + Protocol.Runtime.evaluate({expression: 'console.context(\'named-context\').log(239)'}); + var {params:{context}} = await Protocol.Runtime.onceConsoleAPICalled(); + InspectorTest.log(context); + Protocol.Runtime.evaluate({expression: 'console.context(\'named-context\').log(239)'}); + var {params:{context}} = await Protocol.Runtime.onceConsoleAPICalled(); + InspectorTest.log(context); + await Protocol.Runtime.evaluate({expression: 'console.clear()'}); + await Protocol.Runtime.disable(); + }, + + async function testConsoleCountInDifferentConsoleContexts() { + await Protocol.Runtime.enable(); + Protocol.Runtime.evaluate({expression: 'console.context(\'named-context\').count(239)'}); + var {params:{args}} = await Protocol.Runtime.onceConsoleAPICalled(); + InspectorTest.logMessage(args); + Protocol.Runtime.evaluate({expression: 'console.context(\'named-context\').count(239)'}); + var {params:{args}} = await Protocol.Runtime.onceConsoleAPICalled(); + InspectorTest.logMessage(args); + await Protocol.Runtime.evaluate({expression: 'console.clear()'}); + await Protocol.Runtime.disable(); + }, + + async function testConsoleCountForNamedConsoleContext() { + await Protocol.Runtime.enable(); + Protocol.Runtime.evaluate({expression: ` + var context = console.context('named-context'); + context.count(239); + context.count(239); + `}); + var {params:{args}} = await Protocol.Runtime.onceConsoleAPICalled(); + InspectorTest.logMessage(args); + var {params:{args}} = await Protocol.Runtime.onceConsoleAPICalled(); + InspectorTest.logMessage(args); + await Protocol.Runtime.evaluate({expression: 'console.clear()'}); + await Protocol.Runtime.disable(); + } +]);
diff --git a/src/v8/test/inspector/runtime/console-deprecated-methods-expected.txt b/src/v8/test/inspector/runtime/console-deprecated-methods-expected.txt new file mode 100644 index 0000000..4c1e265 --- /dev/null +++ b/src/v8/test/inspector/runtime/console-deprecated-methods-expected.txt
@@ -0,0 +1,4 @@ +Tests checks that deprecation messages for console. +'console.timeline' is deprecated. Please use 'console.time' instead. +'console.timelineEnd' is deprecated. Please use 'console.timeEnd' instead. +'console.markTimeline' is deprecated. Please use 'console.timeStamp' instead.
diff --git a/src/v8/test/inspector/runtime/console-deprecated-methods.js b/src/v8/test/inspector/runtime/console-deprecated-methods.js new file mode 100644 index 0000000..e8ccd2a --- /dev/null +++ b/src/v8/test/inspector/runtime/console-deprecated-methods.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 checks that deprecation messages for console.") + +Protocol.Runtime.onConsoleAPICalled(messageAdded); +Protocol.Runtime.enable(); + +var deprecatedMethods = [ + "console.timeline(\"42\")", + "console.timeline(\"42\")", + "console.timeline(\"42\")", // three calls should produce one warning message + "console.timelineEnd(\"42\")", + "console.markTimeline(\"42\")", +]; +Protocol.Runtime.evaluate({ expression: deprecatedMethods.join(";") }); + +var messagesLeft = 3; +function messageAdded(data) +{ + var text = data.params.args[0].value; + if (text.indexOf("deprecated") === -1) + return; + InspectorTest.log(text); + if (!--messagesLeft) + InspectorTest.completeTest(); +}
diff --git a/src/v8/test/inspector/runtime/console-line-and-column-expected.txt b/src/v8/test/inspector/runtime/console-line-and-column-expected.txt new file mode 100644 index 0000000..4e3ce1e4 --- /dev/null +++ b/src/v8/test/inspector/runtime/console-line-and-column-expected.txt
@@ -0,0 +1,53 @@ +Tests line and column numbers in console messages +{ + method : Runtime.consoleAPICalled + params : { + args : [ + [0] : { + description : 239 + type : number + value : 239 + } + ] + executionContextId : <executionContextId> + stackTrace : { + callFrames : [ + [0] : { + columnNumber : 8 + functionName : + lineNumber : 0 + scriptId : <scriptId> + url : + } + ] + } + timestamp : <timestamp> + type : log + } +} +{ + method : Runtime.consoleAPICalled + params : { + args : [ + [0] : { + description : 239 + type : number + value : 239 + } + ] + executionContextId : <executionContextId> + stackTrace : { + callFrames : [ + [0] : { + columnNumber : 2 + functionName : + lineNumber : 1 + scriptId : <scriptId> + url : + } + ] + } + timestamp : <timestamp> + type : log + } +}
diff --git a/src/v8/test/inspector/runtime/console-line-and-column.js b/src/v8/test/inspector/runtime/console-line-and-column.js new file mode 100644 index 0000000..e7011eb --- /dev/null +++ b/src/v8/test/inspector/runtime/console-line-and-column.js
@@ -0,0 +1,20 @@ +// 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 line and column numbers in console messages'); + +Protocol.Runtime.enable(); + +addConsoleMessagePromise("console.log(239)") + .then(message => InspectorTest.logMessage(message)) + .then(() => addConsoleMessagePromise("var l = console.log;\n l(239)")) + .then(message => InspectorTest.logMessage(message)) + .then(() => InspectorTest.completeTest()); + +function addConsoleMessagePromise(expression) +{ + var wait = Protocol.Runtime.onceConsoleAPICalled(); + Protocol.Runtime.evaluate({ expression: expression }); + return wait; +}
diff --git a/src/v8/test/inspector/runtime/console-log-doesnt-run-microtasks-expected.txt b/src/v8/test/inspector/runtime/console-log-doesnt-run-microtasks-expected.txt new file mode 100644 index 0000000..d1268b9 --- /dev/null +++ b/src/v8/test/inspector/runtime/console-log-doesnt-run-microtasks-expected.txt
@@ -0,0 +1,20 @@ +Check that console.log doesn't run microtasks. +{ + description : 42 + type : number + value : 42 +} +{ + description : 43 + type : number + value : 43 +} +{ + description : 239 + type : number + value : 239 +} +{ + type : string + value : finished +}
diff --git a/src/v8/test/inspector/runtime/console-log-doesnt-run-microtasks.js b/src/v8/test/inspector/runtime/console-log-doesnt-run-microtasks.js new file mode 100644 index 0000000..c24e928 --- /dev/null +++ b/src/v8/test/inspector/runtime/console-log-doesnt-run-microtasks.js
@@ -0,0 +1,26 @@ +// 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 console.log doesn't run microtasks."); + +contextGroup.addScript( +` +function testFunction() +{ + Promise.resolve().then(function(){ console.log(239); }); + console.log(42); + console.log(43); +}`); + +Protocol.Runtime.enable(); +Protocol.Runtime.onConsoleAPICalled(messageAdded); +Protocol.Runtime.evaluate({ "expression": "testFunction()" }); +Protocol.Runtime.evaluate({ "expression": "setTimeout(() => console.log(\"finished\"), 0)" }); + +function messageAdded(result) +{ + InspectorTest.logObject(result.params.args[0]); + if (result.params.args[0].value === "finished") + InspectorTest.completeTest(); +}
diff --git a/src/v8/test/inspector/runtime/console-memory-expected.txt b/src/v8/test/inspector/runtime/console-memory-expected.txt new file mode 100644 index 0000000..e0f6fca --- /dev/null +++ b/src/v8/test/inspector/runtime/console-memory-expected.txt
@@ -0,0 +1,45 @@ +Checks console.memory + +Running test: testWithoutMemory +{ + id : <messageId> + result : { + result : { + type : undefined + } + } +} + +Running test: testSetterInStrictMode +{ + id : <messageId> + result : { + result : { + type : undefined + } + } +} + +Running test: testWithMemory +{ + id : <messageId> + result : { + result : { + description : 239 + type : number + value : 239 + } + } +} + +Running test: testSetterDoesntOverride +{ + id : <messageId> + result : { + result : { + description : 42 + type : number + value : 42 + } + } +}
diff --git a/src/v8/test/inspector/runtime/console-memory.js b/src/v8/test/inspector/runtime/console-memory.js new file mode 100644 index 0000000..45f86c0 --- /dev/null +++ b/src/v8/test/inspector/runtime/console-memory.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 console.memory'); + +InspectorTest.runAsyncTestSuite([ + async function testWithoutMemory() { + InspectorTest.logMessage( + await Protocol.Runtime.evaluate({expression: 'console.memory'})); + }, + + async function testSetterInStrictMode() { + // crbug.com/468611 + InspectorTest.logMessage( + await Protocol.Runtime.evaluate({ + expression: '"use strict"\nconsole.memory = {};undefined' })); + }, + + async function testWithMemory() { + utils.setMemoryInfoForTest(239); + InspectorTest.logMessage( + await Protocol.Runtime.evaluate({expression: 'console.memory'})); + }, + + async function testSetterDoesntOverride() { + utils.setMemoryInfoForTest(42); + await Protocol.Runtime.evaluate({expression: 'console.memory = 0'}); + InspectorTest.logMessage( + await Protocol.Runtime.evaluate({expression: 'console.memory'})); + } +]);
diff --git a/src/v8/test/inspector/runtime/console-messages-limits-expected.txt b/src/v8/test/inspector/runtime/console-messages-limits-expected.txt new file mode 100644 index 0000000..3d1cd9f --- /dev/null +++ b/src/v8/test/inspector/runtime/console-messages-limits-expected.txt
@@ -0,0 +1,7 @@ +Checks that console message storage doesn't exceed limits + +Running test: testMaxConsoleMessagesCount +Messages reported: 1000 + +Running test: testMaxConsoleMessagesV8Size +Messages reported: 3
diff --git a/src/v8/test/inspector/runtime/console-messages-limits.js b/src/v8/test/inspector/runtime/console-messages-limits.js new file mode 100644 index 0000000..4a81590 --- /dev/null +++ b/src/v8/test/inspector/runtime/console-messages-limits.js
@@ -0,0 +1,44 @@ +// 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 console message storage doesn\'t exceed limits'); + +contextGroup.addScript(` +function generateEmptyMessages(n) { + for (var i = 0; i < n; ++i) { + console.log(''); + } +} + +function generate1MbMessages(n) { + for (var i = 0; i < n; ++i) { + console.log(new Array(1024 * 1024 - 32).join('!')); + } +} +//# sourceURL=test.js`, 7, 26); + +var messagesReported = 0; +Protocol.Runtime.onConsoleAPICalled(message => { + ++messagesReported; +}); + +InspectorTest.runTestSuite([ + function testMaxConsoleMessagesCount(next) { + messagesReported = 0; + Protocol.Runtime.evaluate({ expression: 'generateEmptyMessages(1005)'}) + .then(() => Protocol.Runtime.enable()) + .then(() => Protocol.Runtime.disable()) + .then(() => InspectorTest.log(`Messages reported: ${messagesReported}`)) + .then(next); + }, + + function testMaxConsoleMessagesV8Size(next) { + messagesReported = 0; + Protocol.Runtime.evaluate({ expression: 'generate1MbMessages(11)'}) + .then(() => Protocol.Runtime.enable()) + .then(() => Protocol.Runtime.disable()) + .then(() => InspectorTest.log(`Messages reported: ${messagesReported}`)) + .then(next); + } +]);
diff --git a/src/v8/test/inspector/runtime/console-methods-expected.txt b/src/v8/test/inspector/runtime/console-methods-expected.txt new file mode 100644 index 0000000..81c3c76 --- /dev/null +++ b/src/v8/test/inspector/runtime/console-methods-expected.txt
@@ -0,0 +1,727 @@ +Checks console methods +{ + method : Runtime.consoleAPICalled + params : { + args : [ + [0] : { + type : string + value : debug + } + ] + executionContextId : <executionContextId> + stackTrace : { + callFrames : [ + [0] : { + columnNumber : 10 + functionName : testFunction + lineNumber : 9 + scriptId : <scriptId> + url : test.js + } + [1] : { + columnNumber : 0 + functionName : + lineNumber : 0 + scriptId : <scriptId> + url : + } + ] + } + timestamp : <timestamp> + type : debug + } +} +{ + method : Runtime.consoleAPICalled + params : { + args : [ + [0] : { + type : string + value : error + } + ] + executionContextId : <executionContextId> + stackTrace : { + callFrames : [ + [0] : { + columnNumber : 10 + functionName : testFunction + lineNumber : 10 + scriptId : <scriptId> + url : test.js + } + [1] : { + columnNumber : 0 + functionName : + lineNumber : 0 + scriptId : <scriptId> + url : + } + ] + } + timestamp : <timestamp> + type : error + } +} +{ + method : Runtime.consoleAPICalled + params : { + args : [ + [0] : { + type : string + value : info + } + ] + executionContextId : <executionContextId> + stackTrace : { + callFrames : [ + [0] : { + columnNumber : 10 + functionName : testFunction + lineNumber : 11 + scriptId : <scriptId> + url : test.js + } + [1] : { + columnNumber : 0 + functionName : + lineNumber : 0 + scriptId : <scriptId> + url : + } + ] + } + timestamp : <timestamp> + type : info + } +} +{ + method : Runtime.consoleAPICalled + params : { + args : [ + [0] : { + type : string + value : log + } + ] + executionContextId : <executionContextId> + stackTrace : { + callFrames : [ + [0] : { + columnNumber : 10 + functionName : testFunction + lineNumber : 12 + scriptId : <scriptId> + url : test.js + } + [1] : { + columnNumber : 0 + functionName : + lineNumber : 0 + scriptId : <scriptId> + url : + } + ] + } + timestamp : <timestamp> + type : log + } +} +{ + method : Runtime.consoleAPICalled + params : { + args : [ + [0] : { + type : string + value : warn + } + ] + executionContextId : <executionContextId> + stackTrace : { + callFrames : [ + [0] : { + columnNumber : 10 + functionName : testFunction + lineNumber : 13 + scriptId : <scriptId> + url : test.js + } + [1] : { + columnNumber : 0 + functionName : + lineNumber : 0 + scriptId : <scriptId> + url : + } + ] + } + timestamp : <timestamp> + type : warning + } +} +{ + method : Runtime.consoleAPICalled + params : { + args : [ + [0] : { + type : string + value : dir + } + ] + executionContextId : <executionContextId> + stackTrace : { + callFrames : [ + [0] : { + columnNumber : 10 + functionName : testFunction + lineNumber : 14 + scriptId : <scriptId> + url : test.js + } + [1] : { + columnNumber : 0 + functionName : + lineNumber : 0 + scriptId : <scriptId> + url : + } + ] + } + timestamp : <timestamp> + type : dir + } +} +{ + method : Runtime.consoleAPICalled + params : { + args : [ + [0] : { + type : string + value : dirxml + } + ] + executionContextId : <executionContextId> + stackTrace : { + callFrames : [ + [0] : { + columnNumber : 10 + functionName : testFunction + lineNumber : 15 + scriptId : <scriptId> + url : test.js + } + [1] : { + columnNumber : 0 + functionName : + lineNumber : 0 + scriptId : <scriptId> + url : + } + ] + } + timestamp : <timestamp> + type : dirxml + } +} +{ + method : Runtime.consoleAPICalled + params : { + args : [ + [0] : { + className : Array + description : Array(2) + objectId : <objectId> + preview : { + description : Array(2) + overflow : false + properties : [ + [0] : { + name : 0 + subtype : array + type : object + valuePreview : { + description : Array(2) + overflow : false + properties : [ + [0] : { + name : 0 + type : number + value : 1 + } + [1] : { + name : 1 + type : number + value : 2 + } + ] + subtype : array + type : object + } + } + [1] : { + name : 1 + subtype : array + type : object + valuePreview : { + description : Array(2) + overflow : false + properties : [ + [0] : { + name : 0 + type : number + value : 3 + } + [1] : { + name : 1 + type : number + value : 4 + } + ] + subtype : array + type : object + } + } + ] + subtype : array + type : object + } + subtype : array + type : object + } + ] + executionContextId : <executionContextId> + stackTrace : { + callFrames : [ + [0] : { + columnNumber : 10 + functionName : testFunction + lineNumber : 16 + scriptId : <scriptId> + url : test.js + } + [1] : { + columnNumber : 0 + functionName : + lineNumber : 0 + scriptId : <scriptId> + url : + } + ] + } + timestamp : <timestamp> + type : table + } +} +{ + method : Runtime.consoleAPICalled + params : { + args : [ + [0] : { + className : Array + description : Array(2) + objectId : <objectId> + preview : { + description : Array(2) + overflow : false + properties : [ + [0] : { + name : 0 + subtype : array + type : object + valuePreview : { + description : Array(2) + overflow : false + properties : [ + [0] : { + name : 1 + type : number + value : 2 + } + ] + subtype : array + type : object + } + } + [1] : { + name : 1 + subtype : array + type : object + valuePreview : { + description : Array(2) + overflow : false + properties : [ + [0] : { + name : 1 + type : number + value : 4 + } + ] + subtype : array + type : object + } + } + ] + subtype : array + type : object + } + subtype : array + type : object + } + ] + executionContextId : <executionContextId> + stackTrace : { + callFrames : [ + [0] : { + columnNumber : 10 + functionName : testFunction + lineNumber : 17 + scriptId : <scriptId> + url : test.js + } + [1] : { + columnNumber : 0 + functionName : + lineNumber : 0 + scriptId : <scriptId> + url : + } + ] + } + timestamp : <timestamp> + type : table + } +} +{ + method : Runtime.consoleAPICalled + params : { + args : [ + [0] : { + type : string + value : trace + } + ] + executionContextId : <executionContextId> + stackTrace : { + callFrames : [ + [0] : { + columnNumber : 10 + functionName : testFunction + lineNumber : 18 + scriptId : <scriptId> + url : test.js + } + [1] : { + columnNumber : 0 + functionName : + lineNumber : 0 + scriptId : <scriptId> + url : + } + ] + } + timestamp : <timestamp> + type : trace + } +} +{ + method : Runtime.consoleAPICalled + params : { + args : [ + [0] : { + type : string + value : console.trace + } + ] + executionContextId : <executionContextId> + stackTrace : { + callFrames : [ + [0] : { + columnNumber : 10 + functionName : testFunction + lineNumber : 19 + scriptId : <scriptId> + url : test.js + } + [1] : { + columnNumber : 0 + functionName : + lineNumber : 0 + scriptId : <scriptId> + url : + } + ] + } + timestamp : <timestamp> + type : trace + } +} +{ + method : Runtime.consoleAPICalled + params : { + args : [ + [0] : { + type : string + value : console.group + } + ] + executionContextId : <executionContextId> + stackTrace : { + callFrames : [ + [0] : { + columnNumber : 10 + functionName : testFunction + lineNumber : 20 + scriptId : <scriptId> + url : test.js + } + [1] : { + columnNumber : 0 + functionName : + lineNumber : 0 + scriptId : <scriptId> + url : + } + ] + } + timestamp : <timestamp> + type : startGroup + } +} +{ + method : Runtime.consoleAPICalled + params : { + args : [ + [0] : { + type : string + value : console.groupEnd + } + ] + executionContextId : <executionContextId> + stackTrace : { + callFrames : [ + [0] : { + columnNumber : 10 + functionName : testFunction + lineNumber : 21 + scriptId : <scriptId> + url : test.js + } + [1] : { + columnNumber : 0 + functionName : + lineNumber : 0 + scriptId : <scriptId> + url : + } + ] + } + timestamp : <timestamp> + type : endGroup + } +} +{ + method : Runtime.consoleAPICalled + params : { + args : [ + [0] : { + type : string + value : console.groupCollapsed + } + ] + executionContextId : <executionContextId> + stackTrace : { + callFrames : [ + [0] : { + columnNumber : 10 + functionName : testFunction + lineNumber : 22 + scriptId : <scriptId> + url : test.js + } + [1] : { + columnNumber : 0 + functionName : + lineNumber : 0 + scriptId : <scriptId> + url : + } + ] + } + timestamp : <timestamp> + type : startGroupCollapsed + } +} +{ + method : Runtime.consoleAPICalled + params : { + args : [ + [0] : { + type : string + value : clear + } + ] + executionContextId : <executionContextId> + stackTrace : { + callFrames : [ + [0] : { + columnNumber : 10 + functionName : testFunction + lineNumber : 23 + scriptId : <scriptId> + url : test.js + } + [1] : { + columnNumber : 0 + functionName : + lineNumber : 0 + scriptId : <scriptId> + url : + } + ] + } + timestamp : <timestamp> + type : clear + } +} +{ + method : Runtime.consoleAPICalled + params : { + args : [ + [0] : { + type : string + value : console.clear + } + ] + executionContextId : <executionContextId> + stackTrace : { + callFrames : [ + [0] : { + columnNumber : 10 + functionName : testFunction + lineNumber : 24 + scriptId : <scriptId> + url : test.js + } + [1] : { + columnNumber : 0 + functionName : + lineNumber : 0 + scriptId : <scriptId> + url : + } + ] + } + timestamp : <timestamp> + type : clear + } +} +{ + method : Runtime.consoleAPICalled + params : { + args : [ + [0] : { + type : string + value : count: 1 + } + ] + executionContextId : <executionContextId> + stackTrace : { + callFrames : [ + [0] : { + columnNumber : 10 + functionName : testFunction + lineNumber : 25 + scriptId : <scriptId> + url : test.js + } + [1] : { + columnNumber : 0 + functionName : + lineNumber : 0 + scriptId : <scriptId> + url : + } + ] + } + timestamp : <timestamp> + type : count + } +} +{ + method : Runtime.consoleAPICalled + params : { + args : [ + [0] : { + type : string + value : 1 + } + ] + executionContextId : <executionContextId> + stackTrace : { + callFrames : [ + [0] : { + columnNumber : 12 + functionName : foo + lineNumber : 27 + scriptId : <scriptId> + url : test.js + } + [1] : { + columnNumber : 2 + functionName : testFunction + lineNumber : 29 + scriptId : <scriptId> + url : test.js + } + [2] : { + columnNumber : 0 + functionName : + lineNumber : 0 + scriptId : <scriptId> + url : + } + ] + } + timestamp : <timestamp> + type : count + } +} +{ + method : Runtime.consoleAPICalled + params : { + args : [ + [0] : { + type : string + value : 2 + } + ] + executionContextId : <executionContextId> + stackTrace : { + callFrames : [ + [0] : { + columnNumber : 12 + functionName : foo + lineNumber : 27 + scriptId : <scriptId> + url : test.js + } + [1] : { + columnNumber : 2 + functionName : testFunction + lineNumber : 30 + scriptId : <scriptId> + url : test.js + } + [2] : { + columnNumber : 0 + functionName : + lineNumber : 0 + scriptId : <scriptId> + url : + } + ] + } + timestamp : <timestamp> + type : count + } +}
diff --git a/src/v8/test/inspector/runtime/console-methods.js b/src/v8/test/inspector/runtime/console-methods.js new file mode 100644 index 0000000..c9e0e1d --- /dev/null +++ b/src/v8/test/inspector/runtime/console-methods.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('Checks console methods'); + +contextGroup.setupInjectedScriptEnvironment(); +contextGroup.addScript(` +function testFunction() { + console.debug('debug'); + console.error('error'); + console.info('info'); + console.log('log'); + console.warn('warn'); + console.dir('dir'); + console.dirxml('dirxml'); + console.table([[1,2],[3,4]]); + console.table([[1,2],[3,4]], [1,2]); + console.trace('trace'); + console.trace(); + console.group(); + console.groupEnd(); + console.groupCollapsed(); + console.clear('clear'); + console.clear(); + console.count('count'); + function foo() { + console.count(); + } + foo(); + foo(); +} +//# sourceURL=test.js`, 7, 26); + +Protocol.Runtime.onConsoleAPICalled(InspectorTest.logMessage); +Protocol.Runtime.enable(); +Protocol.Runtime.evaluate({ expression: 'testFunction()' }) + .then(InspectorTest.completeTest);
diff --git a/src/v8/test/inspector/runtime/console-spec-expected.txt b/src/v8/test/inspector/runtime/console-spec-expected.txt new file mode 100644 index 0000000..48cbc70 --- /dev/null +++ b/src/v8/test/inspector/runtime/console-spec-expected.txt
@@ -0,0 +1,30 @@ +Tests console object and it's prototype + +Running test: consoleExistsOnGlobal +true + +Running test: consoleHasRightPropertyDescriptor +{ + configurable : true + enumerable : false + value : <value> + writable : true +} + +Running test: ConsoleNotExistsOnGlobal +false + +Running test: prototypeChainMustBeCorrect +true + +Running test: consoleToString +[object Object] + +Running test: consoleMethodPropertyDescriptor +{ + configurable : true + enumerable : true + value : { + } + writable : true +}
diff --git a/src/v8/test/inspector/runtime/console-spec.js b/src/v8/test/inspector/runtime/console-spec.js new file mode 100644 index 0000000..f37898f --- /dev/null +++ b/src/v8/test/inspector/runtime/console-spec.js
@@ -0,0 +1,60 @@ +// 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 console object and it\'s prototype'); + +contextGroup.addScript(` +var self = this; +function checkPrototype() { + const prototype1 = Object.getPrototypeOf(console); + const prototype2 = Object.getPrototypeOf(prototype1); + if (Object.getOwnPropertyNames(prototype1).length !== 0) + return "false: The [[Prototype]] must have no properties"; + if (prototype2 !== Object.prototype) + return "false: The [[Prototype]]'s [[Prototype]] must be %ObjectPrototype%"; + return "true"; +} +`); + +InspectorTest.runAsyncTestSuite([ + async function consoleExistsOnGlobal() { + let message = await Protocol.Runtime.evaluate({ + expression: 'self.hasOwnProperty(\'console\')', returnByValue: true}); + InspectorTest.log(message.result.result.value); + }, + + async function consoleHasRightPropertyDescriptor() { + let message = await Protocol.Runtime.evaluate({ + expression: 'Object.getOwnPropertyDescriptor(self, \'console\')', + returnByValue: true}); + let result = message.result.result.value; + result.value = '<value>'; + InspectorTest.logObject(result); + }, + + async function ConsoleNotExistsOnGlobal() { + let message = await Protocol.Runtime.evaluate({ + expression: '\'Console\' in self', returnByValue: true}) + InspectorTest.log(message.result.result.value); + }, + + async function prototypeChainMustBeCorrect() { + let message = await Protocol.Runtime.evaluate({ + expression: "checkPrototype()", returnByValue: true }); + InspectorTest.log(message.result.result.value); + }, + + async function consoleToString() { + let message = await Protocol.Runtime.evaluate({ + expression: 'console.toString()', returnByValue: true}) + InspectorTest.log(message.result.result.value); + }, + + async function consoleMethodPropertyDescriptor() { + let message = await Protocol.Runtime.evaluate({ + expression: 'Object.getOwnPropertyDescriptor(console, \'log\')', + returnByValue: true}); + InspectorTest.logObject(message.result.result.value); + } +]);
diff --git a/src/v8/test/inspector/runtime/console-time-end-format-expected.txt b/src/v8/test/inspector/runtime/console-time-end-format-expected.txt new file mode 100644 index 0000000..92fa158 --- /dev/null +++ b/src/v8/test/inspector/runtime/console-time-end-format-expected.txt
@@ -0,0 +1,29 @@ +Checks format of console.timeEnd output + +Running test: zero +js: 0ms +timeEnd: 0ms + +Running test: verySmall +js: 1e-15ms +timeEnd: 1e-15ms + +Running test: small +js: 0.001ms +timeEnd: 0.001ms + +Running test: regular +js: 1.2345ms +timeEnd: 1.2345ms + +Running test: big +js: 10000.2345ms +timeEnd: 10000.2345ms + +Running test: veryBig +js: 1000000000000000.2ms +timeEnd: 1000000000000000.2ms + +Running test: huge +js: 1e+42ms +timeEnd: 1e+42ms
diff --git a/src/v8/test/inspector/runtime/console-time-end-format.js b/src/v8/test/inspector/runtime/console-time-end-format.js new file mode 100644 index 0000000..7e4ff78 --- /dev/null +++ b/src/v8/test/inspector/runtime/console-time-end-format.js
@@ -0,0 +1,45 @@ +// 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 format of console.timeEnd output'); + +Protocol.Runtime.enable(); +Protocol.Runtime.onConsoleAPICalled(message => { + InspectorTest.log(message.params.args[0].value); +}); + +InspectorTest.runTestSuite([ + function zero(next) { + checkInterval(0.0).then(next); + }, + function verySmall(next) { + checkInterval(1e-15).then(next); + }, + function small(next) { + checkInterval(0.001).then(next); + }, + function regular(next) { + checkInterval(1.2345).then(next); + }, + function big(next) { + checkInterval(10000.2345).then(next); + }, + function veryBig(next) { + checkInterval(1e+15 + 0.2345).then(next); + }, + function huge(next) { + checkInterval(1e+42).then(next); + } +]); + +function checkInterval(time) { + utils.setCurrentTimeMSForTest(0.0); + return Protocol.Runtime.evaluate({ + expression: `console.log('js: ' + ${time} + 'ms')`}) + .then(() => Protocol.Runtime.evaluate({ + expression: 'console.time(\'timeEnd\')'})) + .then(() => utils.setCurrentTimeMSForTest(time)) + .then(() => Protocol.Runtime.evaluate({ + expression: 'console.timeEnd(\'timeEnd\')'})); +}
diff --git a/src/v8/test/inspector/runtime/console-timestamp-expected.txt b/src/v8/test/inspector/runtime/console-timestamp-expected.txt new file mode 100644 index 0000000..5710530 --- /dev/null +++ b/src/v8/test/inspector/runtime/console-timestamp-expected.txt
@@ -0,0 +1,9 @@ +Tests timestamps in console +Message has timestamp: true +Message timestamp doesn't differ too much from current time (one minute interval): true +Message 1 has non-decreasing timestamp: true +Message has timestamp: true +Message timestamp doesn't differ too much from current time (one minute interval): true +Message 2 has non-decreasing timestamp: true +Message has timestamp: true +Message timestamp doesn't differ too much from current time (one minute interval): true
diff --git a/src/v8/test/inspector/runtime/console-timestamp.js b/src/v8/test/inspector/runtime/console-timestamp.js new file mode 100644 index 0000000..46ee76f --- /dev/null +++ b/src/v8/test/inspector/runtime/console-timestamp.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('Tests timestamps in console'); + +var messages = []; + +function messageAdded(data) +{ + var payload = data.params; + if (messages.length > 0) + InspectorTest.log("Message " + messages.length + " has non-decreasing timestamp: " + (payload.timestamp >= messages[messages.length - 1].timestamp)); + + messages.push(payload); + InspectorTest.log("Message has timestamp: " + !!payload.timestamp); + + InspectorTest.log("Message timestamp doesn't differ too much from current time (one minute interval): " + (Math.abs(new Date().getTime() - payload.timestamp) < 60000)); + if (messages.length === 3) + InspectorTest.completeTest(); +} + +Protocol.Runtime.onConsoleAPICalled(messageAdded); +Protocol.Runtime.enable(); +Protocol.Runtime.evaluate({ expression: "console.log('testUnique'); for (var i = 0; i < 2; ++i) console.log('testDouble');" });
diff --git a/src/v8/test/inspector/runtime/context-destroyed-on-context-collected-expected.txt b/src/v8/test/inspector/runtime/context-destroyed-on-context-collected-expected.txt new file mode 100644 index 0000000..9a5e170 --- /dev/null +++ b/src/v8/test/inspector/runtime/context-destroyed-on-context-collected-expected.txt
@@ -0,0 +1,7 @@ +Tests that contextDesrtoyed nofitication is fired when context is collected. +{ + method : Runtime.executionContextDestroyed + params : { + executionContextId : <executionContextId> + } +}
diff --git a/src/v8/test/inspector/runtime/context-destroyed-on-context-collected.js b/src/v8/test/inspector/runtime/context-destroyed-on-context-collected.js new file mode 100644 index 0000000..9f71593 --- /dev/null +++ b/src/v8/test/inspector/runtime/context-destroyed-on-context-collected.js
@@ -0,0 +1,14 @@ +// 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 contextDesrtoyed nofitication is fired when context is collected.'); + +(async function test() { + await Protocol.Runtime.enable(); + Protocol.Runtime.onExecutionContextDestroyed(InspectorTest.logMessage); + contextGroup.addScript('inspector.freeContext()'); + await Protocol.HeapProfiler.collectGarbage(); + InspectorTest.completeTest(); +})();
diff --git a/src/v8/test/inspector/runtime/create-context-expected.txt b/src/v8/test/inspector/runtime/create-context-expected.txt new file mode 100644 index 0000000..e64f75b --- /dev/null +++ b/src/v8/test/inspector/runtime/create-context-expected.txt
@@ -0,0 +1,56 @@ +Checks createContext(). +{ + method : Runtime.executionContextCreated + params : { + context : { + id : 1 + name : + origin : + } + } +} +{ + method : Runtime.executionContextCreated + params : { + context : { + id : 2 + name : + origin : + } + } +} +{ + id : <messageId> + result : { + } +} +#debugger; + +setTimeout(x => x #* 3, 0) + +Reported script's execution id: 2 +{ + method : Runtime.executionContextCreated + params : { + context : { + id : 1 + name : + origin : + } + } +} +{ + method : Runtime.executionContextCreated + params : { + context : { + id : 2 + name : + origin : + } + } +} +#debugger; + +setTimeout(x => x #* 3, 0) + +Reported script's execution id: 2
diff --git a/src/v8/test/inspector/runtime/create-context.js b/src/v8/test/inspector/runtime/create-context.js new file mode 100644 index 0000000..105bb59 --- /dev/null +++ b/src/v8/test/inspector/runtime/create-context.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. + +InspectorTest.log('Checks createContext().'); + +var executionContextIds = new Set(); +var contextGroup1 = new InspectorTest.ContextGroup(); +var session1 = contextGroup1.connect(); +setup(session1); +var contextGroup2 = new InspectorTest.ContextGroup(); +var session2 = contextGroup2.connect(); +setup(session2); + +session1.Protocol.Runtime.enable() + .then(() => session2.Protocol.Runtime.enable({})) + .then(() => session1.Protocol.Debugger.enable()) + .then(() => session2.Protocol.Debugger.enable({})) + .then(InspectorTest.logMessage) + .then(() => { + session1.Protocol.Runtime.evaluate({ expression: 'debugger;' }); + session2.Protocol.Runtime.evaluate({expression: 'setTimeout(x => x * 2, 0)'}); + session1.Protocol.Runtime.evaluate({ expression: 'setTimeout(x => x * 3, 0)' }); + }) + .then(() => InspectorTest.waitForPendingTasks()) + .then(() => { + InspectorTest.log(`Reported script's execution id: ${executionContextIds.size}`); + executionContextIds.clear(); + }) + .then(() => session1.reconnect()) + .then(() => session2.reconnect()) + .then(() => { + session1.Protocol.Runtime.evaluate({ expression: 'debugger;' }) + session2.Protocol.Runtime.evaluate({ expression: 'setTimeout(x => x * 2, 0)' }); + session1.Protocol.Runtime.evaluate({ expression: 'setTimeout(x => x * 3, 0)' }); + }) + .then(() => InspectorTest.waitForPendingTasks()) + .then(() => session2.Protocol.Debugger.disable({})) + .then(() => session1.Protocol.Debugger.disable({})) + .then(() => InspectorTest.log(`Reported script's execution id: ${executionContextIds.size}`)) + .then(InspectorTest.completeTest); + +function setup(session) { + session.Protocol.Runtime.onExecutionContextCreated(InspectorTest.logMessage); + session.setupScriptMap(); + session.Protocol.Debugger.onPaused((message) => { + session.logSourceLocation(message.params.callFrames[0].location); + session.Protocol.Debugger.stepOut(); + }); + session.Protocol.Debugger.onScriptParsed(message => executionContextIds.add(message.params.executionContextId)); +}
diff --git a/src/v8/test/inspector/runtime/es6-module-expected.txt b/src/v8/test/inspector/runtime/es6-module-expected.txt new file mode 100644 index 0000000..646fd01 --- /dev/null +++ b/src/v8/test/inspector/runtime/es6-module-expected.txt
@@ -0,0 +1,241 @@ +Checks basic ES6 modules support. +{ + method : Debugger.scriptParsed + params : { + endColumn : 17 + endLine : 5 + executionContextId : <executionContextId> + hasSourceURL : false + hash : 9C014F7249BAFA12B91017817AD15091D01A9155 + isLiveEdit : false + isModule : true + length : 83 + scriptId : <scriptId> + sourceMapURL : + startColumn : 0 + startLine : 0 + url : module1 + } +} +{ + method : Debugger.scriptParsed + params : { + endColumn : 17 + endLine : 5 + executionContextId : <executionContextId> + hasSourceURL : false + hash : 443A2FA24A6112E6B9101781E6A19B56BDC396D4 + isLiveEdit : false + isModule : true + length : 84 + scriptId : <scriptId> + sourceMapURL : + startColumn : 0 + startLine : 0 + url : module2 + } +} +{ + method : Debugger.scriptParsed + params : { + endColumn : 0 + endLine : 8 + executionContextId : <executionContextId> + hasSourceURL : false + hash : 54D834614FBF9B389082DAE06CD3EFC499BEBF13 + isLiveEdit : false + isModule : true + length : 191 + scriptId : <scriptId> + sourceMapURL : + startColumn : 0 + startLine : 0 + url : module3 + } +} +console.log(module1) +foo (module1:2:10) +(anonymous) (module3:3:12) + +console.log(42) +(anonymous) (module3:3:8) + +console.log(module2) +foo (module2:2:10) +(anonymous) (module3:4:12) + +console.log(239) +(anonymous) (module3:4:8) + +{ + method : Debugger.paused + params : { + callFrames : [ + [0] : { + callFrameId : <callFrameId> + functionLocation : { + columnNumber : 0 + lineNumber : 0 + scriptId : <scriptId> + } + functionName : + location : { + columnNumber : 0 + lineNumber : 7 + scriptId : <scriptId> + } + scopeChain : [ + [0] : { + endLocation : { + columnNumber : 0 + lineNumber : 8 + scriptId : <scriptId> + } + object : { + className : Object + description : Object + objectId : <objectId> + type : object + } + startLocation : { + columnNumber : 0 + lineNumber : 0 + scriptId : <scriptId> + } + type : module + } + [1] : { + object : { + className : global + description : global + objectId : <objectId> + type : object + } + type : global + } + ] + this : { + type : undefined + } + url : module3 + } + ] + hitBreakpoints : [ + ] + reason : other + } +} +{ + id : <messageId> + result : { + result : [ + [0] : { + configurable : true + enumerable : true + isOwn : true + name : foo1 + value : { + className : Function + description : function foo() { console.log('module1'); return 42; } + objectId : <objectId> + type : function + } + writable : true + } + [1] : { + configurable : true + enumerable : true + isOwn : true + name : foo2 + value : { + className : Function + description : function foo() { console.log('module2'); return 239; } + objectId : <objectId> + type : function + } + writable : true + } + [2] : { + configurable : true + enumerable : true + isOwn : true + name : a1 + value : { + description : 1 + type : number + value : 1 + } + writable : true + } + [3] : { + configurable : true + enumerable : true + isOwn : true + name : a2 + value : { + description : 2 + type : number + value : 2 + } + writable : true + } + ] + } +} +{ + 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 : module4 + } +} +{ + method : Runtime.exceptionThrown + params : { + exceptionDetails : { + columnNumber : 0 + exception : { + className : SyntaxError + description : SyntaxError: Unexpected token } + objectId : <objectId> + preview : { + description : SyntaxError: Unexpected token } + overflow : false + properties : [ + [0] : { + name : stack + type : string + value : SyntaxError: Unexpected token } + } + [1] : { + name : message + type : string + value : Unexpected token } + } + ] + subtype : error + type : object + } + subtype : error + type : object + } + exceptionId : <exceptionId> + executionContextId : <executionContextId> + lineNumber : 0 + scriptId : <scriptId> + text : Uncaught SyntaxError: Unexpected token } + url : module4 + } + timestamp : <timestamp> + } +}
diff --git a/src/v8/test/inspector/runtime/es6-module.js b/src/v8/test/inspector/runtime/es6-module.js new file mode 100644 index 0000000..6d9e434 --- /dev/null +++ b/src/v8/test/inspector/runtime/es6-module.js
@@ -0,0 +1,61 @@ +// 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 basic ES6 modules support.'); + +var module1 = ` +export function foo() { + console.log('module1'); + return 42; +} +export let a1 = 1`; + +var module2 = ` +export function foo() { + console.log('module2'); + return 239; +} +export let a2 = 2`; + +var module3 = ` +import { foo as foo1 } from 'module1'; +import { foo as foo2 } from 'module2'; +console.log(foo1()); +console.log(foo2()); +import { a1 } from 'module1'; +import { a2 } from 'module2'; +debugger; +`; + +var module4 = '}'; + +session.setupScriptMap(); +// We get scriptParsed events for modules .. +Protocol.Debugger.onScriptParsed(InspectorTest.logMessage); +// .. scriptFailed to parse for modules with syntax error .. +Protocol.Debugger.onScriptFailedToParse(InspectorTest.logMessage); +// .. API messages from modules contain correct stack trace .. +Protocol.Runtime.onConsoleAPICalled(message => { + InspectorTest.log(`console.log(${message.params.args[0].value})`); + session.logCallFrames(message.params.stackTrace.callFrames); + InspectorTest.log(''); +}); +// .. we could break inside module and scope contains correct list of variables .. +Protocol.Debugger.onPaused(message => { + InspectorTest.logMessage(message); + Protocol.Runtime.getProperties({ objectId: message.params.callFrames[0].scopeChain[0].object.objectId}) + .then(InspectorTest.logMessage) + .then(() => Protocol.Debugger.resume()); +}); +// .. we process uncaught errors from modules correctly. +Protocol.Runtime.onExceptionThrown(InspectorTest.logMessage); + +Protocol.Runtime.enable(); +Protocol.Debugger.enable() + .then(() => contextGroup.addModule(module1, "module1")) + .then(() => contextGroup.addModule(module2, "module2")) + .then(() => contextGroup.addModule(module3, "module3")) + .then(() => contextGroup.addModule(module4, "module4")) + .then(() => InspectorTest.waitForPendingTasks()) + .then(InspectorTest.completeTest);
diff --git a/src/v8/test/inspector/runtime/evaluate-async-expected.txt b/src/v8/test/inspector/runtime/evaluate-async-expected.txt new file mode 100644 index 0000000..763b429 --- /dev/null +++ b/src/v8/test/inspector/runtime/evaluate-async-expected.txt
@@ -0,0 +1,249 @@ +Tests that Runtime.evaluate works with awaitPromise flag. + +Running test: testResolvedPromise +{ + id : <messageId> + result : { + result : { + description : 239 + type : number + value : 239 + } + } +} + +Running test: testRejectedPromise +{ + id : <messageId> + result : { + exceptionDetails : { + columnNumber : 0 + exception : { + description : 239 + type : number + value : 239 + } + exceptionId : <exceptionId> + lineNumber : 0 + text : Uncaught (in promise) + } + result : { + description : 239 + type : number + value : 239 + } + } +} + +Running test: testRejectedPromiseWithError +{ + id : <messageId> + result : { + exceptionDetails : { + columnNumber : 11 + exception : { + className : Error + description : Error: MyError at foo (<anonymous>:13:11) at throwError (<anonymous>:15:3) at <anonymous> + objectId : <objectId> + subtype : error + type : object + } + exceptionId : <exceptionId> + lineNumber : 13 + scriptId : <scriptId> + stackTrace : { + callFrames : [ + [0] : { + columnNumber : 10 + functionName : foo + lineNumber : 12 + scriptId : <scriptId> + url : + } + [1] : { + columnNumber : 2 + functionName : throwError + lineNumber : 14 + scriptId : <scriptId> + url : + } + ] + } + text : Uncaught (in promise) Error: MyError + } + result : { + className : Error + description : Error: MyError at foo (<anonymous>:13:11) at throwError (<anonymous>:15:3) at <anonymous> + objectId : <objectId> + subtype : error + type : object + } + } +} + +Running test: testRejectedPromiseWithSyntaxError +{ + id : <messageId> + result : { + exceptionDetails : { + columnNumber : 5 + exception : { + className : SyntaxError + description : SyntaxError: Unexpected token } at foo (<anonymous>:21:5) at throwSyntaxError (<anonymous>:23:3) at <anonymous> + objectId : <objectId> + subtype : error + type : object + } + exceptionId : <exceptionId> + lineNumber : 21 + scriptId : <scriptId> + stackTrace : { + callFrames : [ + [0] : { + columnNumber : 4 + functionName : foo + lineNumber : 20 + scriptId : <scriptId> + url : + } + [1] : { + columnNumber : 2 + functionName : throwSyntaxError + lineNumber : 22 + scriptId : <scriptId> + url : + } + ] + } + text : Uncaught (in promise) SyntaxError: Unexpected token } + } + result : { + className : SyntaxError + description : SyntaxError: Unexpected token } at foo (<anonymous>:21:5) at throwSyntaxError (<anonymous>:23:3) at <anonymous> + objectId : <objectId> + subtype : error + type : object + } + } +} + +Running test: testPrimitiveValueInsteadOfPromise +{ + id : <messageId> + result : { + result : { + type : boolean + value : true + } + } +} + +Running test: testObjectInsteadOfPromise +{ + id : <messageId> + result : { + result : { + type : object + value : { + } + } + } +} + +Running test: testPendingPromise +{ + id : <messageId> + result : { + result : { + type : object + value : { + a : 239 + } + } + } +} + +Running test: testExceptionInEvaluate +{ + id : <messageId> + result : { + exceptionDetails : { + columnNumber : 0 + exception : { + description : 239 + type : number + value : 239 + } + exceptionId : <exceptionId> + lineNumber : 0 + scriptId : <scriptId> + text : Uncaught + } + result : { + description : 239 + type : number + value : 239 + } + } +} + +Running test: testThenableJob +{ + id : <messageId> + result : { + result : { + description : 42 + type : number + value : 42 + } + } +} + +Running test: testLastEvaluatedResult +{ + id : <messageId> + result : { + result : { + description : 42 + type : number + value : 42 + } + } +} +{ + id : <messageId> + result : { + result : { + description : 42 + type : number + value : 42 + } + } +} + +Running test: testRuntimeDisable +Resolving promise.. +{ + id : <messageId> + result : { + result : { + className : Object + description : Object + objectId : <objectId> + type : object + } + } +} +Promise resolved + +Running test: testImmediatelyResolvedAfterAfterContextDestroyed +Destroying context.. +{ + error : { + code : -32000 + message : Execution context was destroyed. + } + id : <messageId> +} +Context destroyed +Triggering weak callback..
diff --git a/src/v8/test/inspector/runtime/evaluate-async-with-wrap-error-expected.txt b/src/v8/test/inspector/runtime/evaluate-async-with-wrap-error-expected.txt new file mode 100644 index 0000000..743acdb --- /dev/null +++ b/src/v8/test/inspector/runtime/evaluate-async-with-wrap-error-expected.txt
@@ -0,0 +1,8 @@ +Test that Runtime.evaluate correctly process errors during wrapping async result. +{ + error : { + code : -32000 + message : Object couldn't be returned by value + } + id : <messageId> +}
diff --git a/src/v8/test/inspector/runtime/evaluate-async-with-wrap-error.js b/src/v8/test/inspector/runtime/evaluate-async-with-wrap-error.js new file mode 100644 index 0000000..43b71ad --- /dev/null +++ b/src/v8/test/inspector/runtime/evaluate-async-with-wrap-error.js
@@ -0,0 +1,15 @@ +// 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 that " + + "Runtime.evaluate correctly process errors during wrapping async result."); + +var evaluateArguments = { + expression: "Promise.resolve(Symbol(123))", + returnByValue: true, + awaitPromise: true +}; +Protocol.Runtime.evaluate(evaluateArguments) + .then(message => InspectorTest.logMessage(message)) + .then(() => InspectorTest.completeTest());
diff --git a/src/v8/test/inspector/runtime/evaluate-async.js b/src/v8/test/inspector/runtime/evaluate-async.js new file mode 100644 index 0000000..385b3f6 --- /dev/null +++ b/src/v8/test/inspector/runtime/evaluate-async.js
@@ -0,0 +1,148 @@ +// 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 Runtime.evaluate works with awaitPromise flag."); + +contextGroup.addScript(` +function createPromiseAndScheduleResolve() +{ + var resolveCallback; + var promise = new Promise((resolve) => resolveCallback = resolve); + setTimeout(resolveCallback.bind(null, { a : 239 }), 0); + return promise; +} + +function throwError() +{ + function foo() { + throw new Error('MyError'); + } + foo(); +} + +function throwSyntaxError() +{ + function foo() { + eval('}'); + } + foo(); +} +`); + +InspectorTest.runAsyncTestSuite([ + async function testResolvedPromise() + { + InspectorTest.logMessage(await Protocol.Runtime.evaluate({ + expression: "Promise.resolve(239)", + awaitPromise: true, + generatePreview: true + })); + }, + + async function testRejectedPromise() + { + InspectorTest.logMessage(await Protocol.Runtime.evaluate({ + expression: "Promise.reject(239)", + awaitPromise: true + })); + }, + + async function testRejectedPromiseWithError() + { + Protocol.Runtime.enable(); + InspectorTest.logMessage(await Protocol.Runtime.evaluate({ + expression: "Promise.resolve().then(throwError)", + awaitPromise: true + })); + await Protocol.Runtime.disable(); + }, + + async function testRejectedPromiseWithSyntaxError() + { + Protocol.Runtime.enable(); + InspectorTest.logMessage(await Protocol.Runtime.evaluate({ + expression: "Promise.resolve().then(throwSyntaxError)", + awaitPromise: true + })); + await Protocol.Runtime.disable(); + }, + + async function testPrimitiveValueInsteadOfPromise() + { + InspectorTest.logMessage(await Protocol.Runtime.evaluate({ + expression: "true", + awaitPromise: true + })); + }, + + async function testObjectInsteadOfPromise() + { + InspectorTest.logMessage(await Protocol.Runtime.evaluate({ + expression: "({})", + awaitPromise: true, + returnByValue: true + })); + }, + + async function testPendingPromise() + { + InspectorTest.logMessage(await Protocol.Runtime.evaluate({ + expression: "createPromiseAndScheduleResolve()", + awaitPromise: true, + returnByValue: true + })); + }, + + async function testExceptionInEvaluate() + { + InspectorTest.logMessage(await Protocol.Runtime.evaluate({ + expression: "throw 239", + awaitPromise: true + })); + }, + + async function testThenableJob() + { + InspectorTest.logMessage(await Protocol.Runtime.evaluate({ + expression: '({then: resolve => resolve(42)})', + awaitPromise: true})); + }, + + async function testLastEvaluatedResult() + { + InspectorTest.logMessage(await Protocol.Runtime.evaluate({ + expression: 'Promise.resolve(42)', + awaitPromise: true, + objectGroup: 'console' + })); + InspectorTest.logMessage(await Protocol.Runtime.evaluate({ + expression: '$_', + includeCommandLineAPI: true + })); + }, + + async function testRuntimeDisable() + { + await Protocol.Runtime.enable(); + Protocol.Runtime.evaluate({ + expression: 'new Promise(r1 => r = r1)', + awaitPromise: true }).then(InspectorTest.logMessage); + await Protocol.Runtime.disable(); + InspectorTest.log('Resolving promise..'); + await Protocol.Runtime.evaluate({expression: 'r({a:1})'}); + InspectorTest.log('Promise resolved'); + }, + + async function testImmediatelyResolvedAfterAfterContextDestroyed() + { + Protocol.Runtime.evaluate({ + expression: 'new Promise(() => 42)', + awaitPromise: true }).then(InspectorTest.logMessage); + InspectorTest.log('Destroying context..'); + await Protocol.Runtime.evaluate({expression: 'inspector.fireContextDestroyed()'}); + InspectorTest.log('Context destroyed'); + InspectorTest.log('Triggering weak callback..'); + await Protocol.HeapProfiler.collectGarbage(); + } +]);
diff --git a/src/v8/test/inspector/runtime/evaluate-empty-stack-expected.txt b/src/v8/test/inspector/runtime/evaluate-empty-stack-expected.txt new file mode 100644 index 0000000..90e67e8 --- /dev/null +++ b/src/v8/test/inspector/runtime/evaluate-empty-stack-expected.txt
@@ -0,0 +1,10 @@ +Tests that Runtime.evaluate works with an empty stack +{ + id : <messageId> + result : { + result : { + type : string + value : snape kills dumbledore + } + } +}
diff --git a/src/v8/test/inspector/runtime/evaluate-empty-stack.js b/src/v8/test/inspector/runtime/evaluate-empty-stack.js new file mode 100644 index 0000000..c09dfd1 --- /dev/null +++ b/src/v8/test/inspector/runtime/evaluate-empty-stack.js
@@ -0,0 +1,13 @@ +// 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 Runtime.evaluate works with an empty stack"); + +contextGroup.addScript("var text = [48116210, 34460128, 1406661984071834]"); + +var message = { expression: "text.map(x => x.toString(36)).join(' ')" }; + +Protocol.Runtime.evaluate(message) + .then(message => InspectorTest.logMessage(message)) + .then(() => InspectorTest.completeTest());
diff --git a/src/v8/test/inspector/runtime/evaluate-with-context-id-equal-zero-expected.txt b/src/v8/test/inspector/runtime/evaluate-with-context-id-equal-zero-expected.txt new file mode 100644 index 0000000..5e26aa9 --- /dev/null +++ b/src/v8/test/inspector/runtime/evaluate-with-context-id-equal-zero-expected.txt
@@ -0,0 +1,8 @@ +Tests that DevTools doesn't crash on Runtime.evaluate with contextId equals 0. +{ + error : { + code : -32000 + message : Cannot find context with specified id + } + id : <messageId> +}
diff --git a/src/v8/test/inspector/runtime/evaluate-with-context-id-equal-zero.js b/src/v8/test/inspector/runtime/evaluate-with-context-id-equal-zero.js new file mode 100644 index 0000000..272c820 --- /dev/null +++ b/src/v8/test/inspector/runtime/evaluate-with-context-id-equal-zero.js
@@ -0,0 +1,9 @@ +// 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 DevTools doesn't crash on Runtime.evaluate with contextId equals 0."); + +Protocol.Runtime.evaluate({ "contextId": 0, "expression": "" }) + .then(message => InspectorTest.logMessage(message)) + .then(() => InspectorTest.completeTest());
diff --git a/src/v8/test/inspector/runtime/evaluate-with-generate-preview-expected.txt b/src/v8/test/inspector/runtime/evaluate-with-generate-preview-expected.txt new file mode 100644 index 0000000..ef1cd1a --- /dev/null +++ b/src/v8/test/inspector/runtime/evaluate-with-generate-preview-expected.txt
@@ -0,0 +1,838 @@ +Tests that Runtime.evaluate will generate correct previews. + +Running test: testObjectPropertiesPreview +{ + description : Object + overflow : false + properties : [ + [0] : { + name : p1 + type : object + value : Object + } + [1] : { + name : p2 + type : object + value : Object + } + [2] : { + name : p3 + type : function + value : + } + [3] : { + name : p4 + type : accessor + } + [4] : { + name : p6 + type : accessor + } + ] + type : object +} + +Running test: testArrayPropertiesPreview +{ + description : Array(8) + overflow : false + properties : [ + [0] : { + name : 2 + type : number + value : 1 + } + [1] : { + name : 3 + subtype : array + type : object + value : Array(1) + } + [2] : { + name : 4 + type : function + value : + } + [3] : { + name : nonEntryFunction + type : function + value : + } + [4] : { + name : 5 + type : accessor + } + [5] : { + name : 7 + type : accessor + } + ] + subtype : array + type : object +} + +Running test: testInheritingObjectPropertiesPreview +{ + description : Object + overflow : false + properties : [ + [0] : { + name : prototype + type : object + value : Object + } + ] + type : object +} + +Running test: testInheritingArrayPropertiesPreview +{ + description : Array(0) + overflow : false + properties : [ + [0] : { + name : prototype + subtype : array + type : object + value : Array(8) + } + ] + subtype : array + type : object +} + +Running test: testShortTypedArrayPropertiesPreview +{ + description : Uint8Array(3) + overflow : false + properties : [ + [0] : { + name : 0 + type : number + value : 0 + } + [1] : { + name : 1 + type : number + value : 0 + } + [2] : { + name : 2 + type : number + value : 0 + } + ] + subtype : typedarray + type : object +} + +Running test: testLongTypedArrayPropertiesPreview +{ + description : Uint8Array(500001) + overflow : true + properties : [ + [0] : { + name : 0 + type : number + value : 0 + } + [1] : { + name : 1 + type : number + value : 0 + } + [2] : { + name : 2 + type : number + value : 0 + } + [3] : { + name : 3 + type : number + value : 0 + } + [4] : { + name : 4 + type : number + value : 0 + } + [5] : { + name : 5 + type : number + value : 0 + } + [6] : { + name : 6 + type : number + value : 0 + } + [7] : { + name : 7 + type : number + value : 0 + } + [8] : { + name : 8 + type : number + value : 0 + } + [9] : { + name : 9 + type : number + value : 0 + } + [10] : { + name : 10 + type : number + value : 0 + } + [11] : { + name : 11 + type : number + value : 0 + } + [12] : { + name : 12 + type : number + value : 0 + } + [13] : { + name : 13 + type : number + value : 0 + } + [14] : { + name : 14 + type : number + value : 0 + } + [15] : { + name : 15 + type : number + value : 0 + } + [16] : { + name : 16 + type : number + value : 0 + } + [17] : { + name : 17 + type : number + value : 0 + } + [18] : { + name : 18 + type : number + value : 0 + } + [19] : { + name : 19 + type : number + value : 0 + } + [20] : { + name : 20 + type : number + value : 0 + } + [21] : { + name : 21 + type : number + value : 0 + } + [22] : { + name : 22 + type : number + value : 0 + } + [23] : { + name : 23 + type : number + value : 0 + } + [24] : { + name : 24 + type : number + value : 0 + } + [25] : { + name : 25 + type : number + value : 0 + } + [26] : { + name : 26 + type : number + value : 0 + } + [27] : { + name : 27 + type : number + value : 0 + } + [28] : { + name : 28 + type : number + value : 0 + } + [29] : { + name : 29 + type : number + value : 0 + } + [30] : { + name : 30 + type : number + value : 0 + } + [31] : { + name : 31 + type : number + value : 0 + } + [32] : { + name : 32 + type : number + value : 0 + } + [33] : { + name : 33 + type : number + value : 0 + } + [34] : { + name : 34 + type : number + value : 0 + } + [35] : { + name : 35 + type : number + value : 0 + } + [36] : { + name : 36 + type : number + value : 0 + } + [37] : { + name : 37 + type : number + value : 0 + } + [38] : { + name : 38 + type : number + value : 0 + } + [39] : { + name : 39 + type : number + value : 0 + } + [40] : { + name : 40 + type : number + value : 0 + } + [41] : { + name : 41 + type : number + value : 0 + } + [42] : { + name : 42 + type : number + value : 0 + } + [43] : { + name : 43 + type : number + value : 0 + } + [44] : { + name : 44 + type : number + value : 0 + } + [45] : { + name : 45 + type : number + value : 0 + } + [46] : { + name : 46 + type : number + value : 0 + } + [47] : { + name : 47 + type : number + value : 0 + } + [48] : { + name : 48 + type : number + value : 0 + } + [49] : { + name : 49 + type : number + value : 0 + } + [50] : { + name : 50 + type : number + value : 0 + } + [51] : { + name : 51 + type : number + value : 0 + } + [52] : { + name : 52 + type : number + value : 0 + } + [53] : { + name : 53 + type : number + value : 0 + } + [54] : { + name : 54 + type : number + value : 0 + } + [55] : { + name : 55 + type : number + value : 0 + } + [56] : { + name : 56 + type : number + value : 0 + } + [57] : { + name : 57 + type : number + value : 0 + } + [58] : { + name : 58 + type : number + value : 0 + } + [59] : { + name : 59 + type : number + value : 0 + } + [60] : { + name : 60 + type : number + value : 0 + } + [61] : { + name : 61 + type : number + value : 0 + } + [62] : { + name : 62 + type : number + value : 0 + } + [63] : { + name : 63 + type : number + value : 0 + } + [64] : { + name : 64 + type : number + value : 0 + } + [65] : { + name : 65 + type : number + value : 0 + } + [66] : { + name : 66 + type : number + value : 0 + } + [67] : { + name : 67 + type : number + value : 0 + } + [68] : { + name : 68 + type : number + value : 0 + } + [69] : { + name : 69 + type : number + value : 0 + } + [70] : { + name : 70 + type : number + value : 0 + } + [71] : { + name : 71 + type : number + value : 0 + } + [72] : { + name : 72 + type : number + value : 0 + } + [73] : { + name : 73 + type : number + value : 0 + } + [74] : { + name : 74 + type : number + value : 0 + } + [75] : { + name : 75 + type : number + value : 0 + } + [76] : { + name : 76 + type : number + value : 0 + } + [77] : { + name : 77 + type : number + value : 0 + } + [78] : { + name : 78 + type : number + value : 0 + } + [79] : { + name : 79 + type : number + value : 0 + } + [80] : { + name : 80 + type : number + value : 0 + } + [81] : { + name : 81 + type : number + value : 0 + } + [82] : { + name : 82 + type : number + value : 0 + } + [83] : { + name : 83 + type : number + value : 0 + } + [84] : { + name : 84 + type : number + value : 0 + } + [85] : { + name : 85 + type : number + value : 0 + } + [86] : { + name : 86 + type : number + value : 0 + } + [87] : { + name : 87 + type : number + value : 0 + } + [88] : { + name : 88 + type : number + value : 0 + } + [89] : { + name : 89 + type : number + value : 0 + } + [90] : { + name : 90 + type : number + value : 0 + } + [91] : { + name : 91 + type : number + value : 0 + } + [92] : { + name : 92 + type : number + value : 0 + } + [93] : { + name : 93 + type : number + value : 0 + } + [94] : { + name : 94 + type : number + value : 0 + } + [95] : { + name : 95 + type : number + value : 0 + } + [96] : { + name : 96 + type : number + value : 0 + } + [97] : { + name : 97 + type : number + value : 0 + } + [98] : { + name : 98 + type : number + value : 0 + } + [99] : { + name : 99 + type : number + value : 0 + } + ] + subtype : typedarray + type : object +} + +Running test: testSetPropertiesPreview +{ + description : Set(3) + entries : [ + [0] : { + value : { + description : 1 + overflow : false + properties : [ + ] + type : number + } + } + [1] : { + value : { + description : 2 + overflow : false + properties : [ + ] + type : number + } + } + [2] : { + value : { + description : 3 + overflow : false + properties : [ + ] + type : number + } + } + ] + overflow : false + properties : [ + ] + subtype : set + type : object +} + +Running test: testBigSetPropertiesPreview +{ + description : Set(10) + entries : [ + [0] : { + value : { + description : 0 + overflow : false + properties : [ + ] + type : number + } + } + [1] : { + value : { + description : 1 + overflow : false + properties : [ + ] + type : number + } + } + [2] : { + value : { + description : 2 + overflow : false + properties : [ + ] + type : number + } + } + [3] : { + value : { + description : 3 + overflow : false + properties : [ + ] + type : number + } + } + [4] : { + value : { + description : 4 + overflow : false + properties : [ + ] + type : number + } + } + ] + overflow : true + properties : [ + ] + subtype : set + type : object +} + +Running test: testMixedSetPropertiesPreview +{ + description : Set(10) + entries : [ + [0] : { + value : { + description : 0 + overflow : false + properties : [ + ] + type : number + } + } + [1] : { + value : { + description : 1 + overflow : false + properties : [ + ] + type : number + } + } + [2] : { + value : { + description : 2 + overflow : false + properties : [ + ] + type : number + } + } + [3] : { + value : { + description : 3 + overflow : false + properties : [ + ] + type : number + } + } + [4] : { + value : { + description : 4 + overflow : false + properties : [ + ] + type : number + } + } + ] + overflow : true + properties : [ + [0] : { + name : _prop_0 + type : number + value : 1 + } + [1] : { + name : _prop_1 + type : number + value : 1 + } + [2] : { + name : _prop_2 + type : number + value : 1 + } + [3] : { + name : _prop_3 + type : number + value : 1 + } + [4] : { + name : _prop_4 + type : number + value : 1 + } + ] + subtype : set + type : object +} + +Running test: testObjInheritsGetterProperty +{ + description : Object + overflow : false + properties : [ + [0] : { + name : propNotNamedProto + type : number + value : NaN + } + ] + type : object +} + +Running test: testObjWithArrayAsProto +{ + description : Array + overflow : false + properties : [ + ] + type : object +}
diff --git a/src/v8/test/inspector/runtime/evaluate-with-generate-preview.js b/src/v8/test/inspector/runtime/evaluate-with-generate-preview.js new file mode 100644 index 0000000..8ea0ea4 --- /dev/null +++ b/src/v8/test/inspector/runtime/evaluate-with-generate-preview.js
@@ -0,0 +1,147 @@ +// 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 Runtime.evaluate will generate correct previews."); + +contextGroup.addScript( +` +var f1 = function(){}; + +Object.prototype[0] = 'default-first'; +var obj = {p1: {a:1}, p2: {b:'foo'}, p3: f1}; +Object.defineProperties(obj, { + p4: { + get() { return 2 } + }, + p5: { + set(x) { return x } + }, + p6: { + get() { return 2 }, + set(x) { return x } + } +}); + +Array.prototype[0] = 'default-first'; +var arr = [,, 1, [2], f1]; +Object.defineProperties(arr, { + 5: { + get() { return 2 } + }, + 6: { + set(x) { return x } + }, + 7: { + get() { return 2 }, + set(x) { return x } + } +}); +arr.nonEntryFunction = f1; + +var inheritingObj = {}; +var inheritingArr = []; +inheritingObj.prototype = obj; +inheritingArr.prototype = arr; + +var shortTypedArray = new Uint8Array(3); +var longTypedArray = new Uint8Array(500001); +var set = new Set([1, 2, 3]); +var bigSet = new Set(); +var mixedSet = new Set(); +for (var i = 0; i < 10; i++) { + bigSet.add(i); + mixedSet["_prop_" + i] = 1; + mixedSet.add(i); +} + +var deterministicNativeFunction = Math.log; +var parentObj = {}; +Object.defineProperty(parentObj, 'propNotNamedProto', { + get: deterministicNativeFunction, + set: function() {} +}); +var objInheritsGetterProperty = {__proto__: parentObj}; +inspector.allowAccessorFormatting(objInheritsGetterProperty); +`); + +contextGroup.setupInjectedScriptEnvironment(); + +InspectorTest.runTestSuite([ + function testObjectPropertiesPreview(next) + { + Protocol.Runtime.evaluate({ "expression": "obj", "generatePreview": true }) + .then(result => InspectorTest.logMessage(result.result.result.preview)) + .then(next); + }, + + function testArrayPropertiesPreview(next) + { + Protocol.Runtime.evaluate({ "expression": "arr", "generatePreview": true }) + .then(result => InspectorTest.logMessage(result.result.result.preview)) + .then(next); + }, + + function testInheritingObjectPropertiesPreview(next) + { + Protocol.Runtime.evaluate({ "expression": "inheritingObj", "generatePreview": true }) + .then(result => InspectorTest.logMessage(result.result.result.preview)) + .then(next); + }, + + function testInheritingArrayPropertiesPreview(next) + { + Protocol.Runtime.evaluate({ "expression": "inheritingArr", "generatePreview": true }) + .then(result => InspectorTest.logMessage(result.result.result.preview)) + .then(next); + }, + + function testShortTypedArrayPropertiesPreview(next) + { + Protocol.Runtime.evaluate({ "expression": "shortTypedArray", "generatePreview": true }) + .then(result => InspectorTest.logMessage(result.result.result.preview)) + .then(next); + }, + + function testLongTypedArrayPropertiesPreview(next) + { + Protocol.Runtime.evaluate({ "expression": "longTypedArray", "generatePreview": true }) + .then(result => InspectorTest.logMessage(result.result.result.preview)) + .then(next); + }, + + function testSetPropertiesPreview(next) + { + Protocol.Runtime.evaluate({ "expression": "set", "generatePreview": true }) + .then(result => InspectorTest.logMessage(result.result.result.preview)) + .then(next); + }, + + function testBigSetPropertiesPreview(next) + { + Protocol.Runtime.evaluate({ "expression": "bigSet", "generatePreview": true }) + .then(result => InspectorTest.logMessage(result.result.result.preview)) + .then(next); + }, + + function testMixedSetPropertiesPreview(next) + { + Protocol.Runtime.evaluate({ "expression": "mixedSet", "generatePreview": true }) + .then(result => InspectorTest.logMessage(result.result.result.preview)) + .then(next); + }, + + function testObjInheritsGetterProperty(next) + { + Protocol.Runtime.evaluate({ "expression": "objInheritsGetterProperty", "generatePreview": true }) + .then(result => InspectorTest.logMessage(result.result.result.preview)) + .then(next); + }, + + function testObjWithArrayAsProto(next) + { + Protocol.Runtime.evaluate({ "expression": "Object.create([1,2])", "generatePreview": true }) + .then(result => InspectorTest.logMessage(result.result.result.preview)) + .then(next); + } +]);
diff --git a/src/v8/test/inspector/runtime/exception-thrown-expected.txt b/src/v8/test/inspector/runtime/exception-thrown-expected.txt new file mode 100644 index 0000000..fb4cf70 --- /dev/null +++ b/src/v8/test/inspector/runtime/exception-thrown-expected.txt
@@ -0,0 +1,113 @@ +Check that exceptionThrown is supported by test runner. +{ + method : Runtime.exceptionThrown + params : { + exceptionDetails : { + columnNumber : 2 + exception : { + className : Error + description : Error at setTimeout (<anonymous>:2:9) + objectId : <objectId> + preview : { + description : Error at setTimeout (<anonymous>:2:9) + overflow : false + properties : [ + [0] : { + name : stack + type : string + value : Error at setTimeout (<anonymous>:2:9) + } + ] + subtype : error + type : object + } + subtype : error + type : object + } + exceptionId : <exceptionId> + executionContextId : <executionContextId> + lineNumber : 1 + stackTrace : { + callFrames : [ + [0] : { + columnNumber : 8 + functionName : setTimeout + lineNumber : 1 + scriptId : <scriptId> + url : + } + ] + } + text : Uncaught Error + } + timestamp : <timestamp> + } +} +{ + method : Runtime.exceptionThrown + params : { + exceptionDetails : { + columnNumber : 1 + exception : { + className : SyntaxError + description : SyntaxError: Unexpected token } + objectId : <objectId> + preview : { + description : SyntaxError: Unexpected token } + overflow : false + properties : [ + [0] : { + name : stack + type : string + value : SyntaxError: Unexpected token } + } + [1] : { + name : message + type : string + value : Unexpected token } + } + ] + subtype : error + type : object + } + subtype : error + type : object + } + exceptionId : <exceptionId> + executionContextId : <executionContextId> + lineNumber : 0 + scriptId : <scriptId> + text : Uncaught SyntaxError: Unexpected token } + } + timestamp : <timestamp> + } +} +{ + method : Runtime.exceptionThrown + params : { + exceptionDetails : { + columnNumber : 2 + exception : { + description : 239 + type : number + value : 239 + } + exceptionId : <exceptionId> + executionContextId : <executionContextId> + lineNumber : 1 + stackTrace : { + callFrames : [ + [0] : { + columnNumber : 2 + functionName : setTimeout + lineNumber : 1 + scriptId : <scriptId> + url : + } + ] + } + text : Uncaught 239 + } + timestamp : <timestamp> + } +}
diff --git a/src/v8/test/inspector/runtime/exception-thrown.js b/src/v8/test/inspector/runtime/exception-thrown.js new file mode 100644 index 0000000..91f48bc --- /dev/null +++ b/src/v8/test/inspector/runtime/exception-thrown.js
@@ -0,0 +1,12 @@ +// 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 exceptionThrown is supported by test runner.") + +Protocol.Runtime.enable(); +Protocol.Runtime.onExceptionThrown(message => InspectorTest.logMessage(message)); +Protocol.Runtime.evaluate({ expression: "setTimeout(() => { \n throw new Error() }, 0)" }); +Protocol.Runtime.evaluate({ expression: "setTimeout(\" }\", 0)" }); +Protocol.Runtime.evaluate({ expression: "setTimeout(() => { \n throw 239; }, 0)" }); +InspectorTest.waitForPendingTasks().then(InspectorTest.completeTest);
diff --git a/src/v8/test/inspector/runtime/function-scopes-expected.txt b/src/v8/test/inspector/runtime/function-scopes-expected.txt new file mode 100644 index 0000000..0503e31 --- /dev/null +++ b/src/v8/test/inspector/runtime/function-scopes-expected.txt
@@ -0,0 +1,53 @@ +Checks [[Scopes]] for functions +Catch: +{ + configurable : true + enumerable : true + isOwn : true + name : a + value : { + description : 1 + type : number + value : 1 + } + writable : true +} +With block: +{ + configurable : true + enumerable : true + isOwn : true + name : b + value : { + description : 2 + type : number + value : 2 + } + writable : true +} +Closure (closure): +{ + configurable : true + enumerable : true + isOwn : true + name : c + value : { + description : 3 + type : number + value : 3 + } + writable : true +} +Global: +{ + configurable : false + enumerable : true + isOwn : true + name : e + value : { + description : 5 + type : number + value : 5 + } + writable : true +}
diff --git a/src/v8/test/inspector/runtime/function-scopes.js b/src/v8/test/inspector/runtime/function-scopes.js new file mode 100644 index 0000000..bda069b --- /dev/null +++ b/src/v8/test/inspector/runtime/function-scopes.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('Checks [[Scopes]] for functions'); + +contextGroup.addScript(` +var f; +try { + throw 1; +} catch (a) { + with({b:2}) { + function closure() { + var c = 3; + function foo() { + var d = 4; + return a + b + c + d; + } + return foo; + } + f = closure; + } +} +var e = 5; +//# sourceURL=test.js`); + +(async function test() { + let {result:{result:{objectId}}} = await Protocol.Runtime.evaluate({ + expression: 'f()' + }); + let {result:{internalProperties}} = await Protocol.Runtime.getProperties({ + objectId + }); + let scopes = internalProperties.find(prop => prop.name === '[[Scopes]]'); + let {result:{result}} = await Protocol.Runtime.getProperties({ + objectId: scopes.value.objectId + }); + await Promise.all(result.map(async scope => { + scope.variables = (await Protocol.Runtime.getProperties({ + objectId: scope.value.objectId + })).result.result; + })); + let catchScope = result.find(scope => scope.value.description === 'Catch'); + InspectorTest.log('Catch:'); + InspectorTest.logMessage(catchScope.variables.find(variable => variable.name === 'a')); + InspectorTest.log('With block:'); + let withScope = result.find(scope => scope.value.description === 'With Block'); + InspectorTest.logMessage(withScope.variables.find(variable => variable.name === 'b')); + InspectorTest.log('Closure (closure):'); + let closureScope = result.find(scope => scope.value.description === 'Closure (closure)'); + InspectorTest.logMessage(closureScope.variables.find(variable => variable.name === 'c')); + InspectorTest.log('Global:'); + let globalScope = result.find(scope => scope.value.description === 'Global'); + InspectorTest.logMessage(globalScope.variables.find(variable => variable.name === 'e')); + InspectorTest.completeTest(); +})();
diff --git a/src/v8/test/inspector/runtime/get-properties-expected.txt b/src/v8/test/inspector/runtime/get-properties-expected.txt new file mode 100644 index 0000000..1f7aa50 --- /dev/null +++ b/src/v8/test/inspector/runtime/get-properties-expected.txt
@@ -0,0 +1,52 @@ +Checks Runtime.getProperties method + +Running test: testObject5 + __proto__ own object undefined + foo own string cat +Internal properties + [[PrimitiveValue]] number 5 + +Running test: testNotOwn + __defineGetter__ inherited function undefined + __defineSetter__ inherited function undefined + __lookupGetter__ inherited function undefined + __lookupSetter__ inherited function undefined + __proto__ inherited no value, getter, setter + a own number 2 + b own no value, getter, setter + c inherited number 4 + constructor inherited function undefined + d inherited no value, getter + hasOwnProperty inherited function undefined + isPrototypeOf inherited function undefined + propertyIsEnumerable inherited function undefined + toLocaleString inherited function undefined + toString inherited function undefined + valueOf inherited function undefined + +Running test: testAccessorsOnly + b own no value, getter, setter + d own no value, setter + +Running test: testArray + 0 own string red + 1 own string green + 2 own string blue + __proto__ own object undefined + length own number 3 + +Running test: testBound + __proto__ own function undefined + length own number 0 + name own string bound Number +Internal properties + [[BoundArgs]] object undefined + [[BoundThis]] object undefined + [[TargetFunction]] function undefined + +Running test: testObjectThrowsLength + __proto__ own object undefined + length own no value, getter + +Running test: testTypedArrayWithoutLength + __proto__ own object undefined
diff --git a/src/v8/test/inspector/runtime/get-properties-on-proxy-expected.txt b/src/v8/test/inspector/runtime/get-properties-on-proxy-expected.txt new file mode 100644 index 0000000..3395956 --- /dev/null +++ b/src/v8/test/inspector/runtime/get-properties-on-proxy-expected.txt
@@ -0,0 +1,11 @@ +Check that while Runtime.getProperties call on proxy object no user defined trap will be executed. +{ + id : <messageId> + result : { + result : { + description : 0 + type : number + value : 0 + } + } +}
diff --git a/src/v8/test/inspector/runtime/get-properties-on-proxy.js b/src/v8/test/inspector/runtime/get-properties-on-proxy.js new file mode 100644 index 0000000..b2981df --- /dev/null +++ b/src/v8/test/inspector/runtime/get-properties-on-proxy.js
@@ -0,0 +1,101 @@ +// 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 while Runtime.getProperties call on proxy object no user defined trap will be executed."); + +contextGroup.addScript(` +var self = this; +function testFunction() +{ + self.counter = 0; + var handler = { + get: function(target, name){ + self.counter++; + return Reflect.get.apply(this, arguments); + }, + set: function(target, name){ + self.counter++; + return Reflect.set.apply(this, arguments); + }, + getPrototypeOf: function(target) { + self.counter++; + return Reflect.getPrototypeOf.apply(this, arguments); + }, + setPrototypeOf: function(target) { + self.counter++; + return Reflect.setPrototypeOf.apply(this, arguments); + }, + isExtensible: function(target) { + self.counter++; + return Reflect.isExtensible.apply(this, arguments); + }, + isExtensible: function(target) { + self.counter++; + return Reflect.isExtensible.apply(this, arguments); + }, + isExtensible: function(target) { + self.counter++; + return Reflect.isExtensible.apply(this, arguments); + }, + preventExtensions: function() { + self.counter++; + return Reflect.preventExtensions.apply(this, arguments); + }, + getOwnPropertyDescriptor: function() { + self.counter++; + return Reflect.getOwnPropertyDescriptor.apply(this, arguments); + }, + defineProperty: function() { + self.counter++; + return Reflect.defineProperty.apply(this, arguments); + }, + has: function() { + self.counter++; + return Reflect.has.apply(this, arguments); + }, + get: function() { + self.counter++; + return Reflect.get.apply(this, arguments); + }, + set: function() { + self.counter++; + return Reflect.set.apply(this, arguments); + }, + deleteProperty: function() { + self.counter++; + return Reflect.deleteProperty.apply(this, arguments); + }, + ownKeys: function() { + self.counter++; + return Reflect.ownKeys.apply(this, arguments); + }, + apply: function() { + self.counter++; + return Reflect.apply.apply(this, arguments); + }, + construct: function() { + self.counter++; + return Reflect.construct.apply(this, arguments); + } + }; + return new Proxy({ a : 1}, handler); +}`); + +Protocol.Runtime.evaluate({ expression: "testFunction()"}).then(requestProperties); + +function requestProperties(result) +{ + Protocol.Runtime.getProperties({ objectId: result.result.objectId, generatePreview: true }).then(checkCounter); +} + +function checkCounter(result) +{ + Protocol.Runtime.evaluate({ expression: "self.counter" }).then(dumpCounter); +} + +function dumpCounter(result) +{ + InspectorTest.logMessage(result); + InspectorTest.completeTest(); +}
diff --git a/src/v8/test/inspector/runtime/get-properties-preview-expected.txt b/src/v8/test/inspector/runtime/get-properties-preview-expected.txt new file mode 100644 index 0000000..a3f4eb4 --- /dev/null +++ b/src/v8/test/inspector/runtime/get-properties-preview-expected.txt
@@ -0,0 +1,32 @@ +Tests generated previews in Runtime.getProperties +p1 : Object +p2 : Object +p1 : { + "type": "object", + "description": "Object", + "overflow": false, + "properties": [ + { + "name": "a", + "type": "number", + "value": "1" + } + ] +} +p2 : { + "type": "object", + "description": "Object", + "overflow": false, + "properties": [ + { + "name": "b", + "type": "string", + "value": "foo" + }, + { + "name": "bb", + "type": "string", + "value": "bar" + } + ] +}
diff --git a/src/v8/test/inspector/runtime/get-properties-preview.js b/src/v8/test/inspector/runtime/get-properties-preview.js new file mode 100644 index 0000000..92c6e56 --- /dev/null +++ b/src/v8/test/inspector/runtime/get-properties-preview.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 generated previews in Runtime.getProperties'); + +contextGroup.setupInjectedScriptEnvironment(); + +Protocol.Runtime.evaluate({ "expression": "({p1: {a:1}, p2: {b:'foo', bb:'bar'}})" }).then(callbackEvaluate); + +function callbackEvaluate(result) +{ + Protocol.Runtime.getProperties({ "objectId": result.result.result.objectId, "ownProperties": true }).then(callbackGetProperties.bind(null, false)); + Protocol.Runtime.getProperties({ "objectId": result.result.result.objectId, "ownProperties": true, "generatePreview": true }).then(callbackGetProperties.bind(null, true)); +} + +function callbackGetProperties(completeTest, result) +{ + for (var property of result.result.result) { + if (!property.value || property.name === "__proto__") + continue; + if (property.value.preview) + InspectorTest.log(property.name + " : " + JSON.stringify(property.value.preview, null, 4)); + else + InspectorTest.log(property.name + " : " + property.value.description); + } + if (completeTest) + InspectorTest.completeTest(); +}
diff --git a/src/v8/test/inspector/runtime/get-properties.js b/src/v8/test/inspector/runtime/get-properties.js new file mode 100644 index 0000000..56a4c4b --- /dev/null +++ b/src/v8/test/inspector/runtime/get-properties.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. + +let {session, contextGroup, Protocol} = InspectorTest.start('Checks Runtime.getProperties method'); + +InspectorTest.runAsyncTestSuite([ + async function testObject5() { + let objectId = (await Protocol.Runtime.evaluate({ + expression: '(function(){var r = Object(5); r.foo = \'cat\';return r;})()' + })).result.result.objectId; + let props = await Protocol.Runtime.getProperties({ objectId, ownProperties: true }); + logGetPropertiesResult(props.result); + }, + + async function testNotOwn() { + let objectId = (await Protocol.Runtime.evaluate({ + expression: '({ a: 2, set b(_) {}, get b() {return 5;}, __proto__: { a: 3, c: 4, get d() {return 6;} }})' + })).result.result.objectId; + let props = await Protocol.Runtime.getProperties({ objectId, ownProperties: false }); + logGetPropertiesResult(props.result); + }, + + async function testAccessorsOnly() { + let objectId = (await Protocol.Runtime.evaluate({ + expression: '({ a: 2, set b(_) {}, get b() {return 5;}, c: \'c\', set d(_){} })' + })).result.result.objectId; + let props = await Protocol.Runtime.getProperties({ objectId, ownProperties: true, accessorPropertiesOnly: true }); + logGetPropertiesResult(props.result); + }, + + async function testArray() { + let objectId = (await Protocol.Runtime.evaluate({ + expression: '[\'red\', \'green\', \'blue\']' + })).result.result.objectId; + let props = await Protocol.Runtime.getProperties({ objectId, ownProperties: true }); + logGetPropertiesResult(props.result); + }, + + async function testBound() { + let objectId = (await Protocol.Runtime.evaluate({ + expression: 'Number.bind({}, 5)' + })).result.result.objectId; + let props = await Protocol.Runtime.getProperties({ objectId, ownProperties: true }); + logGetPropertiesResult(props.result); + }, + + async function testObjectThrowsLength() { + let objectId = (await Protocol.Runtime.evaluate({ + expression: '({get length() { throw \'Length called\'; }})' + })).result.result.objectId; + let props = await Protocol.Runtime.getProperties({ objectId, ownProperties: true }); + logGetPropertiesResult(props.result); + }, + + async function testTypedArrayWithoutLength() { + let objectId = (await Protocol.Runtime.evaluate({ + expression: '({__proto__: Uint8Array.prototype})' + })).result.result.objectId; + let props = await Protocol.Runtime.getProperties({ objectId, ownProperties: true }); + logGetPropertiesResult(props.result); + }, +]); + +function logGetPropertiesResult(protocolResult) { + function hasGetterSetter(property, fieldName) { + var v = property[fieldName]; + if (!v) return false; + return v.type !== "undefined" + } + + var propertyArray = protocolResult.result; + propertyArray.sort(NamedThingComparator); + for (var i = 0; i < propertyArray.length; i++) { + var p = propertyArray[i]; + var v = p.value; + var own = p.isOwn ? "own" : "inherited"; + if (v) + InspectorTest.log(" " + p.name + " " + own + " " + v.type + " " + v.value); + else + InspectorTest.log(" " + p.name + " " + own + " no value" + + (hasGetterSetter(p, "get") ? ", getter" : "") + (hasGetterSetter(p, "set") ? ", setter" : "")); + } + var internalPropertyArray = protocolResult.internalProperties; + if (internalPropertyArray) { + InspectorTest.log("Internal properties"); + internalPropertyArray.sort(NamedThingComparator); + for (var i = 0; i < internalPropertyArray.length; i++) { + var p = internalPropertyArray[i]; + var v = p.value; + InspectorTest.log(" " + p.name + " " + v.type + " " + v.value); + } + } + + function NamedThingComparator(o1, o2) { + return o1.name === o2.name ? 0 : (o1.name < o2.name ? -1 : 1); + } +}
diff --git a/src/v8/test/inspector/runtime/internal-properties-entries-expected.txt b/src/v8/test/inspector/runtime/internal-properties-entries-expected.txt new file mode 100644 index 0000000..d395067 --- /dev/null +++ b/src/v8/test/inspector/runtime/internal-properties-entries-expected.txt
@@ -0,0 +1,691 @@ +Checks internal [[Entries]] in Runtime.getProperties output + +Running test: maps +expression: new Map([[1,2],[3,4]]) +[ + [0] : { + key : 1 + value : 2 + } + [1] : { + key : 3 + value : 4 + } +] +{ + id : <messageId> + result : { + result : [ + [0] : { + configurable : true + enumerable : true + isOwn : true + name : 0 + value : { + className : Object + description : {1 => 2} + objectId : <objectId> + subtype : internal#entry + type : object + } + writable : true + } + [1] : { + configurable : true + enumerable : true + isOwn : true + name : 1 + value : { + className : Object + description : {3 => 4} + objectId : <objectId> + subtype : internal#entry + type : object + } + writable : true + } + [2] : { + configurable : false + enumerable : false + isOwn : true + name : length + value : { + description : 2 + type : number + value : 2 + } + writable : true + } + ] + } +} +expression: new Map() +[ +] +{ + id : <messageId> + result : { + result : [ + [0] : { + configurable : false + enumerable : false + isOwn : true + name : length + value : { + description : 0 + type : number + value : 0 + } + writable : true + } + ] + } +} + +Running test: mapIterators +expression: new Map([[1,2],[3,4]]).entries() +[ + [0] : { + key : 1 + value : 2 + } + [1] : { + key : 3 + value : 4 + } +] +{ + id : <messageId> + result : { + result : [ + [0] : { + configurable : true + enumerable : true + isOwn : true + name : 0 + value : { + className : Object + description : {1 => 2} + objectId : <objectId> + subtype : internal#entry + type : object + } + writable : true + } + [1] : { + configurable : true + enumerable : true + isOwn : true + name : 1 + value : { + className : Object + description : {3 => 4} + objectId : <objectId> + subtype : internal#entry + type : object + } + writable : true + } + [2] : { + configurable : false + enumerable : false + isOwn : true + name : length + value : { + description : 2 + type : number + value : 2 + } + writable : true + } + ] + } +} +expression: it = new Map([[1,2],[3,4]]).entries(); it.next(); it +[ + [0] : { + key : 3 + value : 4 + } +] +{ + id : <messageId> + result : { + result : [ + [0] : { + configurable : true + enumerable : true + isOwn : true + name : 0 + value : { + className : Object + description : {3 => 4} + objectId : <objectId> + subtype : internal#entry + type : object + } + writable : true + } + [1] : { + configurable : false + enumerable : false + isOwn : true + name : length + value : { + description : 1 + type : number + value : 1 + } + writable : true + } + ] + } +} +expression: it = new Map([[1,2],[3,4]]).keys(); it.next(); it +[ + [0] : { + value : 3 + } +] +{ + id : <messageId> + result : { + result : [ + [0] : { + configurable : true + enumerable : true + isOwn : true + name : 0 + value : { + className : Object + description : 3 + objectId : <objectId> + subtype : internal#entry + type : object + } + writable : true + } + [1] : { + configurable : false + enumerable : false + isOwn : true + name : length + value : { + description : 1 + type : number + value : 1 + } + writable : true + } + ] + } +} +expression: it = new Map([[1,2],[3,4]]).values(); it.next(); it +[ + [0] : { + value : 4 + } +] +{ + id : <messageId> + result : { + result : [ + [0] : { + configurable : true + enumerable : true + isOwn : true + name : 0 + value : { + className : Object + description : 4 + objectId : <objectId> + subtype : internal#entry + type : object + } + writable : true + } + [1] : { + configurable : false + enumerable : false + isOwn : true + name : length + value : { + description : 1 + type : number + value : 1 + } + writable : true + } + ] + } +} +expression: it = new Map([[1,2],[3,4]]).entries(); it.next(); it.next(); it +[ +] +{ + id : <messageId> + result : { + result : [ + [0] : { + configurable : false + enumerable : false + isOwn : true + name : length + value : { + description : 0 + type : number + value : 0 + } + writable : true + } + ] + } +} + +Running test: sets +expression: new Set([1,2]) +[ + [0] : { + value : 1 + } + [1] : { + value : 2 + } +] +{ + id : <messageId> + result : { + result : [ + [0] : { + configurable : true + enumerable : true + isOwn : true + name : 0 + value : { + className : Object + description : 1 + objectId : <objectId> + subtype : internal#entry + type : object + } + writable : true + } + [1] : { + configurable : true + enumerable : true + isOwn : true + name : 1 + value : { + className : Object + description : 2 + objectId : <objectId> + subtype : internal#entry + type : object + } + writable : true + } + [2] : { + configurable : false + enumerable : false + isOwn : true + name : length + value : { + description : 2 + type : number + value : 2 + } + writable : true + } + ] + } +} +expression: new Set() +[ +] +{ + id : <messageId> + result : { + result : [ + [0] : { + configurable : false + enumerable : false + isOwn : true + name : length + value : { + description : 0 + type : number + value : 0 + } + writable : true + } + ] + } +} + +Running test: setIterators +expression: new Set([1,2]).values() +[ + [0] : { + value : 1 + } + [1] : { + value : 2 + } +] +{ + id : <messageId> + result : { + result : [ + [0] : { + configurable : true + enumerable : true + isOwn : true + name : 0 + value : { + className : Object + description : 1 + objectId : <objectId> + subtype : internal#entry + type : object + } + writable : true + } + [1] : { + configurable : true + enumerable : true + isOwn : true + name : 1 + value : { + className : Object + description : 2 + objectId : <objectId> + subtype : internal#entry + type : object + } + writable : true + } + [2] : { + configurable : false + enumerable : false + isOwn : true + name : length + value : { + description : 2 + type : number + value : 2 + } + writable : true + } + ] + } +} +expression: it = new Set([1,2]).values(); it.next(); it +[ + [0] : { + value : 2 + } +] +{ + id : <messageId> + result : { + result : [ + [0] : { + configurable : true + enumerable : true + isOwn : true + name : 0 + value : { + className : Object + description : 2 + objectId : <objectId> + subtype : internal#entry + type : object + } + writable : true + } + [1] : { + configurable : false + enumerable : false + isOwn : true + name : length + value : { + description : 1 + type : number + value : 1 + } + writable : true + } + ] + } +} +expression: it = new Set([1,2]).keys(); it.next(); it +[ + [0] : { + value : 2 + } +] +{ + id : <messageId> + result : { + result : [ + [0] : { + configurable : true + enumerable : true + isOwn : true + name : 0 + value : { + className : Object + description : 2 + objectId : <objectId> + subtype : internal#entry + type : object + } + writable : true + } + [1] : { + configurable : false + enumerable : false + isOwn : true + name : length + value : { + description : 1 + type : number + value : 1 + } + writable : true + } + ] + } +} +expression: it = new Set([1,2]).entries(); it.next(); it +[ + [0] : { + value : 2 + } +] +{ + id : <messageId> + result : { + result : [ + [0] : { + configurable : true + enumerable : true + isOwn : true + name : 0 + value : { + className : Object + description : 2 + objectId : <objectId> + subtype : internal#entry + type : object + } + writable : true + } + [1] : { + configurable : false + enumerable : false + isOwn : true + name : length + value : { + description : 1 + type : number + value : 1 + } + writable : true + } + ] + } +} +expression: it = new Set([1,2]).values(); it.next(); it.next(); it +[ +] +{ + id : <messageId> + result : { + result : [ + [0] : { + configurable : false + enumerable : false + isOwn : true + name : length + value : { + description : 0 + type : number + value : 0 + } + writable : true + } + ] + } +} + +Running test: weakMaps +expression: new WeakMap() +[ +] +{ + id : <messageId> + result : { + result : [ + [0] : { + configurable : false + enumerable : false + isOwn : true + name : length + value : { + description : 0 + type : number + value : 0 + } + writable : true + } + ] + } +} +expression: new WeakMap([[{ a: 2 }, 42]]) +[ + [0] : { + key : { + a : 2 + } + value : 42 + } +] +{ + id : <messageId> + result : { + result : [ + [0] : { + configurable : true + enumerable : true + isOwn : true + name : 0 + value : { + className : Object + description : {Object => 42} + objectId : <objectId> + subtype : internal#entry + type : object + } + writable : true + } + [1] : { + configurable : false + enumerable : false + isOwn : true + name : length + value : { + description : 1 + type : number + value : 1 + } + writable : true + } + ] + } +} + +Running test: weakSets +expression: new WeakSet() +[ +] +{ + id : <messageId> + result : { + result : [ + [0] : { + configurable : false + enumerable : false + isOwn : true + name : length + value : { + description : 0 + type : number + value : 0 + } + writable : true + } + ] + } +} +expression: new WeakSet([{a:2}]) +[ + [0] : { + value : { + a : 2 + } + } +] +{ + id : <messageId> + result : { + result : [ + [0] : { + configurable : true + enumerable : true + isOwn : true + name : 0 + value : { + className : Object + description : Object + objectId : <objectId> + subtype : internal#entry + type : object + } + writable : true + } + [1] : { + configurable : false + enumerable : false + isOwn : true + name : length + value : { + description : 1 + type : number + value : 1 + } + writable : true + } + ] + } +}
diff --git a/src/v8/test/inspector/runtime/internal-properties-entries.js b/src/v8/test/inspector/runtime/internal-properties-entries.js new file mode 100644 index 0000000..9555ae5 --- /dev/null +++ b/src/v8/test/inspector/runtime/internal-properties-entries.js
@@ -0,0 +1,65 @@ +// 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 internal [[Entries]] in Runtime.getProperties output'); + +Protocol.Runtime.enable(); + +InspectorTest.runTestSuite([ + function maps(next) { + checkExpression('new Map([[1,2],[3,4]])') + .then(() => checkExpression('new Map()')) + .then(next); + }, + + function mapIterators(next) { + checkExpression('new Map([[1,2],[3,4]]).entries()') + .then(() => checkExpression('it = new Map([[1,2],[3,4]]).entries(); it.next(); it')) + .then(() => checkExpression('it = new Map([[1,2],[3,4]]).keys(); it.next(); it')) + .then(() => checkExpression('it = new Map([[1,2],[3,4]]).values(); it.next(); it')) + .then(() => checkExpression('it = new Map([[1,2],[3,4]]).entries(); it.next(); it.next(); it')) + .then(next); + }, + + function sets(next) { + checkExpression('new Set([1,2])') + .then(() => checkExpression('new Set()')) + .then(next); + }, + + function setIterators(next) { + checkExpression('new Set([1,2]).values()') + .then(() => checkExpression('it = new Set([1,2]).values(); it.next(); it')) + .then(() => checkExpression('it = new Set([1,2]).keys(); it.next(); it')) + .then(() => checkExpression('it = new Set([1,2]).entries(); it.next(); it')) + .then(() => checkExpression('it = new Set([1,2]).values(); it.next(); it.next(); it')) + .then(next); + }, + + function weakMaps(next) { + checkExpression('new WeakMap()') + .then(() => checkExpression('new WeakMap([[{ a: 2 }, 42]])')) + .then(next); + }, + + function weakSets(next) { + checkExpression('new WeakSet()') + .then(() => checkExpression('new WeakSet([{a:2}])')) + .then(next); + } +]); + +function checkExpression(expression) +{ + InspectorTest.log(`expression: ${expression}`); + var entriesObjectId; + return Protocol.Runtime.evaluate({ expression: expression }) + .then(message => Protocol.Runtime.getProperties({ objectId: message.result.result.objectId })) + .then(message => message.result.internalProperties.filter(p => p.name === '[[Entries]]')[0]) + .then(entries => entriesObjectId = entries.value.objectId) + .then(() => Protocol.Runtime.callFunctionOn({ objectId: entriesObjectId, functionDeclaration: 'function f() { return this; }', returnByValue: true })) + .then(message => InspectorTest.logMessage(message.result.result.value)) + .then(() => Protocol.Runtime.getProperties({ objectId: entriesObjectId, ownProperties: true })) + .then(message => InspectorTest.logMessage(message)); +}
diff --git a/src/v8/test/inspector/runtime/internal-properties-expected.txt b/src/v8/test/inspector/runtime/internal-properties-expected.txt new file mode 100644 index 0000000..a44c50b --- /dev/null +++ b/src/v8/test/inspector/runtime/internal-properties-expected.txt
@@ -0,0 +1,586 @@ +Checks internal properties in Runtime.getProperties output + +Running test: generatorFunction +expression: (function* foo() { yield 1 }) +{ + id : <messageId> + result : { + internalProperties : [ + [0] : { + name : [[FunctionLocation]] + value : { + description : Object + subtype : internal#location + type : object + value : { + columnNumber : 14 + lineNumber : 0 + scriptId : <scriptId> + } + } + } + [1] : { + name : [[IsGenerator]] + value : { + type : boolean + value : true + } + } + [2] : { + name : [[Scopes]] + value : { + className : Array + description : Scopes[1] + objectId : <objectId> + subtype : internal#scopeList + type : object + } + } + ] + } +} + +Running test: regularFunction +expression: (function foo() {}) +{ + id : <messageId> + result : { + internalProperties : [ + [0] : { + name : [[FunctionLocation]] + value : { + description : Object + subtype : internal#location + type : object + value : { + columnNumber : 13 + lineNumber : 0 + scriptId : <scriptId> + } + } + } + [1] : { + name : [[Scopes]] + value : { + className : Array + description : Scopes[1] + objectId : <objectId> + subtype : internal#scopeList + type : object + } + } + ] + } +} + +Running test: boxedObjects +expression: new Number(239) +{ + id : <messageId> + result : { + internalProperties : [ + [0] : { + name : [[PrimitiveValue]] + value : { + description : 239 + type : number + value : 239 + } + } + ] + } +} +expression: new Boolean(false) +{ + id : <messageId> + result : { + internalProperties : [ + [0] : { + name : [[PrimitiveValue]] + value : { + type : boolean + value : false + } + } + ] + } +} +expression: new String('abc') +{ + id : <messageId> + result : { + internalProperties : [ + [0] : { + name : [[PrimitiveValue]] + value : { + type : string + value : abc + } + } + ] + } +} +expression: Object(Symbol(42)) +{ + id : <messageId> + result : { + internalProperties : [ + [0] : { + name : [[PrimitiveValue]] + value : { + description : Symbol(42) + objectId : <objectId> + type : symbol + } + } + ] + } +} + +Running test: promise +expression: Promise.resolve(42) +{ + id : <messageId> + result : { + internalProperties : [ + [0] : { + name : [[PromiseStatus]] + value : { + type : string + value : resolved + } + } + [1] : { + name : [[PromiseValue]] + value : { + description : 42 + type : number + value : 42 + } + } + ] + } +} +expression: new Promise(() => undefined) +{ + id : <messageId> + result : { + internalProperties : [ + [0] : { + name : [[PromiseStatus]] + value : { + type : string + value : pending + } + } + [1] : { + name : [[PromiseValue]] + value : { + type : undefined + } + } + ] + } +} + +Running test: generatorObject +expression: gen1 +{ + id : <messageId> + result : { + internalProperties : [ + [0] : { + name : [[GeneratorStatus]] + value : { + type : string + value : suspended + } + } + [1] : { + name : [[GeneratorFunction]] + value : { + className : GeneratorFunction + description : function* foo() { yield 1; } + objectId : <objectId> + type : function + } + } + [2] : { + name : [[GeneratorReceiver]] + value : { + className : global + description : global + objectId : <objectId> + type : object + } + } + [3] : { + name : [[GeneratorLocation]] + value : { + description : Object + subtype : internal#location + type : object + value : { + columnNumber : 13 + lineNumber : 8 + scriptId : <scriptId> + } + } + } + [4] : { + name : [[Scopes]] + value : { + className : Array + description : Scopes[2] + objectId : <objectId> + subtype : internal#scopeList + type : object + } + } + ] + } +} +expression: gen1.next();gen1 +{ + id : <messageId> + result : { + internalProperties : [ + [0] : { + name : [[GeneratorStatus]] + value : { + type : string + value : suspended + } + } + [1] : { + name : [[GeneratorFunction]] + value : { + className : GeneratorFunction + description : function* foo() { yield 1; } + objectId : <objectId> + type : function + } + } + [2] : { + name : [[GeneratorReceiver]] + value : { + className : global + description : global + objectId : <objectId> + type : object + } + } + [3] : { + name : [[GeneratorLocation]] + value : { + description : Object + subtype : internal#location + type : object + value : { + columnNumber : 2 + lineNumber : 9 + scriptId : <scriptId> + } + } + } + [4] : { + name : [[Scopes]] + value : { + className : Array + description : Scopes[2] + objectId : <objectId> + subtype : internal#scopeList + type : object + } + } + ] + } +} +expression: gen1.next();gen1 +{ + id : <messageId> + result : { + internalProperties : [ + [0] : { + name : [[GeneratorStatus]] + value : { + type : string + value : closed + } + } + [1] : { + name : [[GeneratorFunction]] + value : { + className : GeneratorFunction + description : function* foo() { yield 1; } + objectId : <objectId> + type : function + } + } + [2] : { + name : [[GeneratorReceiver]] + value : { + className : global + description : global + objectId : <objectId> + type : object + } + } + [3] : { + name : [[GeneratorLocation]] + value : { + description : Object + subtype : internal#location + type : object + value : { + columnNumber : 13 + lineNumber : 8 + scriptId : <scriptId> + } + } + } + ] + } +} + +Running test: generatorObjectDebuggerDisabled +expression: gen2 +{ + id : <messageId> + result : { + internalProperties : [ + [0] : { + name : [[GeneratorStatus]] + value : { + type : string + value : suspended + } + } + [1] : { + name : [[GeneratorFunction]] + value : { + className : GeneratorFunction + description : function* foo() { yield 1; } + objectId : <objectId> + type : function + } + } + [2] : { + name : [[GeneratorReceiver]] + value : { + className : global + description : global + objectId : <objectId> + type : object + } + } + [3] : { + name : [[GeneratorLocation]] + value : { + description : Object + subtype : internal#location + type : object + value : { + columnNumber : 13 + lineNumber : 8 + scriptId : <scriptId> + } + } + } + [4] : { + name : [[Scopes]] + value : { + className : Array + description : Scopes[2] + objectId : <objectId> + subtype : internal#scopeList + type : object + } + } + ] + } +} +expression: gen2.next();gen2 +{ + id : <messageId> + result : { + internalProperties : [ + [0] : { + name : [[GeneratorStatus]] + value : { + type : string + value : suspended + } + } + [1] : { + name : [[GeneratorFunction]] + value : { + className : GeneratorFunction + description : function* foo() { yield 1; } + objectId : <objectId> + type : function + } + } + [2] : { + name : [[GeneratorReceiver]] + value : { + className : global + description : global + objectId : <objectId> + type : object + } + } + [3] : { + name : [[GeneratorLocation]] + value : { + description : Object + subtype : internal#location + type : object + value : { + columnNumber : 2 + lineNumber : 9 + scriptId : <scriptId> + } + } + } + [4] : { + name : [[Scopes]] + value : { + className : Array + description : Scopes[2] + objectId : <objectId> + subtype : internal#scopeList + type : object + } + } + ] + } +} +expression: gen2.next();gen2 +{ + id : <messageId> + result : { + internalProperties : [ + [0] : { + name : [[GeneratorStatus]] + value : { + type : string + value : closed + } + } + [1] : { + name : [[GeneratorFunction]] + value : { + className : GeneratorFunction + description : function* foo() { yield 1; } + objectId : <objectId> + type : function + } + } + [2] : { + name : [[GeneratorReceiver]] + value : { + className : global + description : global + objectId : <objectId> + type : object + } + } + [3] : { + name : [[GeneratorLocation]] + value : { + description : Object + subtype : internal#location + type : object + value : { + columnNumber : 13 + lineNumber : 8 + scriptId : <scriptId> + } + } + } + ] + } +} + +Running test: iteratorObject +expression: (new Map([[1,2]])).entries() +{ + id : <messageId> + result : { + internalProperties : [ + [0] : { + name : [[IteratorHasMore]] + value : { + type : boolean + value : true + } + } + [1] : { + name : [[IteratorIndex]] + value : { + description : 0 + type : number + value : 0 + } + } + [2] : { + name : [[IteratorKind]] + value : { + type : string + value : entries + } + } + [3] : { + name : [[Entries]] + value : { + className : Array + description : Array(1) + objectId : <objectId> + subtype : array + type : object + } + } + ] + } +} +expression: (new Set([[1,2]])).entries() +{ + id : <messageId> + result : { + internalProperties : [ + [0] : { + name : [[IteratorHasMore]] + value : { + type : boolean + value : true + } + } + [1] : { + name : [[IteratorIndex]] + value : { + description : 0 + type : number + value : 0 + } + } + [2] : { + name : [[IteratorKind]] + value : { + type : string + value : entries + } + } + [3] : { + name : [[Entries]] + value : { + className : Array + description : Array(1) + objectId : <objectId> + subtype : array + type : object + } + } + ] + } +}
diff --git a/src/v8/test/inspector/runtime/internal-properties.js b/src/v8/test/inspector/runtime/internal-properties.js new file mode 100644 index 0000000..1e42f91 --- /dev/null +++ b/src/v8/test/inspector/runtime/internal-properties.js
@@ -0,0 +1,70 @@ +// 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 internal properties in Runtime.getProperties output'); + +contextGroup.addScript(` +function* foo() { + yield 1; +} +var gen1 = foo(); +var gen2 = foo(); +//# sourceURL=test.js`, 7, 26); + +Protocol.Runtime.enable(); +Protocol.Debugger.enable(); + +InspectorTest.runTestSuite([ + function generatorFunction(next) { + checkExpression('(function* foo() { yield 1 })').then(next); + }, + + function regularFunction(next) { + checkExpression('(function foo() {})').then(next); + }, + + 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('gen1') + .then(() => checkExpression('gen1.next();gen1')) + .then(() => checkExpression('gen1.next();gen1')) + .then(next); + }, + + function generatorObjectDebuggerDisabled(next) { + Protocol.Debugger.disable() + .then(() => checkExpression('gen2')) + .then(() => checkExpression('gen2.next();gen2')) + .then(() => checkExpression('gen2.next();gen2')) + .then(next); + }, + + function iteratorObject(next) { + checkExpression('(new Map([[1,2]])).entries()') + .then(() => checkExpression('(new Set([[1,2]])).entries()')) + .then(next); + } +]); + +function checkExpression(expression) +{ + InspectorTest.log(`expression: ${expression}`); + return Protocol.Runtime.evaluate({ expression: expression }) + .then(message => Protocol.Runtime.getProperties({ objectId: message.result.result.objectId })) + .then(message => { delete message.result.result; return message; }) + .then(InspectorTest.logMessage); +}
diff --git a/src/v8/test/inspector/runtime/length-or-size-description-expected.txt b/src/v8/test/inspector/runtime/length-or-size-description-expected.txt new file mode 100644 index 0000000..2736966 --- /dev/null +++ b/src/v8/test/inspector/runtime/length-or-size-description-expected.txt
@@ -0,0 +1,33 @@ +Test that descriptions for arrays, maps, and sets include the correct length or size. +Set(0) +Set(2) +Map(0) +Map(2) +Array(0) +Array(2) +Uint8Array(0) +Uint8Array(2) +ArrayBuffer(0) +ArrayBuffer(2) +SharedArrayBuffer(0) +SharedArrayBuffer(2) +DataView(0) +DataView(5) +WeakMap +WeakSet +Set(0) +Set(2) +Map(0) +Map(2) +Array(0) +Array(2) +Uint8Array(0) +Uint8Array(2) +ArrayBuffer(0) +ArrayBuffer(2) +SharedArrayBuffer(0) +SharedArrayBuffer(2) +DataView(0) +DataView(5) +WeakMap +WeakSet
diff --git a/src/v8/test/inspector/runtime/length-or-size-description.js b/src/v8/test/inspector/runtime/length-or-size-description.js new file mode 100644 index 0000000..8719a26 --- /dev/null +++ b/src/v8/test/inspector/runtime/length-or-size-description.js
@@ -0,0 +1,36 @@ +// 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-sharedarraybuffer + +let {session, contextGroup, Protocol} = InspectorTest.start("Test that descriptions for arrays, maps, and sets include the correct length or size."); + +contextGroup.setupInjectedScriptEnvironment(); + +Promise.all([ + testExpression("new Set()"), + testExpression("new Set([1,2])"), + testExpression("new Map()"), + testExpression("new Map([[1,2],[3,4]])"), + testExpression("new Array()"), + testExpression("new Array(2)"), + testExpression("new Uint8Array()"), + testExpression("new Uint8Array(2)"), + testExpression("new ArrayBuffer()"), + testExpression("new ArrayBuffer(2)"), + testExpression("new SharedArrayBuffer()"), + testExpression("new SharedArrayBuffer(2)"), + testExpression("new DataView(new ArrayBuffer())"), + testExpression("new DataView(new ArrayBuffer(5))"), + // WeakMap and WeakSet should not have size in description. + testExpression("new WeakMap([[{}, 42]])"), + testExpression("new WeakSet([{}])") +]).then(() => InspectorTest.completeTest()); + +function testExpression(expression) { + return Protocol.Runtime.evaluate({ expression: expression }) + .then(result => InspectorTest.logMessage(result.result.result.description)) + .then(() => Protocol.Runtime.evaluate({ expression: "[" + expression + "]", generatePreview: true })) + .then(result => InspectorTest.logMessage(result.result.result.preview.properties[0].value)) +}
diff --git a/src/v8/test/inspector/runtime/property-on-console-proto-expected.txt b/src/v8/test/inspector/runtime/property-on-console-proto-expected.txt new file mode 100644 index 0000000..f64914a --- /dev/null +++ b/src/v8/test/inspector/runtime/property-on-console-proto-expected.txt
@@ -0,0 +1,11 @@ +Tests that property defined on console.__proto__ doesn't observable on other Objects. +{ + id : <messageId> + result : { + result : { + description : 0 + type : number + value : 0 + } + } +}
diff --git a/src/v8/test/inspector/runtime/property-on-console-proto.js b/src/v8/test/inspector/runtime/property-on-console-proto.js new file mode 100644 index 0000000..c7ee6c2 --- /dev/null +++ b/src/v8/test/inspector/runtime/property-on-console-proto.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("Tests that property defined on console.__proto__ doesn't observable on other Objects."); + +contextGroup.addScript(` +function testFunction() +{ + var amountOfProperties = 0; + for (var p in {}) + ++amountOfProperties; + console.__proto__.debug = 239; + for (var p in {}) + --amountOfProperties; + return amountOfProperties; +}`); + +Protocol.Runtime.evaluate({ "expression": "testFunction()" }).then(dumpResult); + +function dumpResult(result) +{ + InspectorTest.logMessage(result); + InspectorTest.completeTest(); +}
diff --git a/src/v8/test/inspector/runtime/protocol-works-with-different-locale-expected.txt b/src/v8/test/inspector/runtime/protocol-works-with-different-locale-expected.txt new file mode 100644 index 0000000..da9eccc --- /dev/null +++ b/src/v8/test/inspector/runtime/protocol-works-with-different-locale-expected.txt
@@ -0,0 +1,140 @@ +Tests that protocol works with different locales + +Running test: consoleLogWithDefaultLocale +{ + method : Runtime.consoleAPICalled + params : { + args : [ + [0] : { + description : 239 + type : number + value : 239 + } + ] + executionContextId : <executionContextId> + stackTrace : { + callFrames : [ + [0] : { + columnNumber : 8 + functionName : + lineNumber : 0 + scriptId : <scriptId> + url : + } + ] + } + timestamp : <timestamp> + type : log + } +} + +Running test: consoleTimeWithCommaAsSeparator +set locale to fr_CA.UTF-8 (has comma as separator) +{ + method : Runtime.consoleAPICalled + params : { + args : [ + [0] : { + type : string + value : a: 0.001ms + } + ] + executionContextId : <executionContextId> + stackTrace : { + callFrames : [ + [0] : { + columnNumber : 8 + functionName : + lineNumber : 0 + scriptId : <scriptId> + url : + } + ] + } + timestamp : <timestamp> + type : timeEnd + } +} + +Running test: consoleLogWithCommaAsSeparator +set locale to fr_CA.UTF-8 (has comma as separator) +{ + method : Runtime.consoleAPICalled + params : { + args : [ + [0] : { + description : 239 + type : number + value : 239 + } + ] + executionContextId : <executionContextId> + stackTrace : { + callFrames : [ + [0] : { + columnNumber : 8 + functionName : + lineNumber : 0 + scriptId : <scriptId> + url : + } + ] + } + timestamp : <timestamp> + type : log + } +} + +Running test: consoleTimeWithCommaAfterConsoleLog +set locale to fr_CA.UTF-8 (has comma as separator) +{ + method : Runtime.consoleAPICalled + params : { + args : [ + [0] : { + description : 239 + type : number + value : 239 + } + ] + executionContextId : <executionContextId> + stackTrace : { + callFrames : [ + [0] : { + columnNumber : 8 + functionName : + lineNumber : 0 + scriptId : <scriptId> + url : + } + ] + } + timestamp : <timestamp> + type : log + } +} +{ + method : Runtime.consoleAPICalled + params : { + args : [ + [0] : { + type : string + value : a: 0.001ms + } + ] + executionContextId : <executionContextId> + stackTrace : { + callFrames : [ + [0] : { + columnNumber : 8 + functionName : + lineNumber : 0 + scriptId : <scriptId> + url : + } + ] + } + timestamp : <timestamp> + type : timeEnd + } +}
diff --git a/src/v8/test/inspector/runtime/protocol-works-with-different-locale.js b/src/v8/test/inspector/runtime/protocol-works-with-different-locale.js new file mode 100644 index 0000000..833b927 --- /dev/null +++ b/src/v8/test/inspector/runtime/protocol-works-with-different-locale.js
@@ -0,0 +1,42 @@ +// 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 protocol works with different locales'); + +Protocol.Runtime.enable(); + +Protocol.Runtime.onConsoleAPICalled(InspectorTest.logMessage); + +InspectorTest.runTestSuite([ + function consoleLogWithDefaultLocale(next) { + Protocol.Runtime.evaluate({ expression: "console.log(239) "}).then(next); + }, + + function consoleTimeWithCommaAsSeparator(next) { + InspectorTest.log("set locale to fr_CA.UTF-8 (has comma as separator)"); + utils.setlocale("fr_CA.UTF-8"); + utils.setCurrentTimeMSForTest(0.0); + Protocol.Runtime.evaluate({ expression: "console.time(\"a\");"}) + .then(() => utils.setCurrentTimeMSForTest(0.001)) + .then(() => Protocol.Runtime.evaluate({ expression: "console.timeEnd(\"a\");"})) + .then(next); + }, + + function consoleLogWithCommaAsSeparator(next) { + InspectorTest.log("set locale to fr_CA.UTF-8 (has comma as separator)"); + utils.setlocale("fr_CA.UTF-8"); + Protocol.Runtime.evaluate({ expression: "console.log(239) "}).then(next); + }, + + function consoleTimeWithCommaAfterConsoleLog(next) { + InspectorTest.log("set locale to fr_CA.UTF-8 (has comma as separator)"); + utils.setlocale("fr_CA.UTF-8"); + Protocol.Runtime.evaluate({ expression: "console.log(239) "}) + .then(() => utils.setCurrentTimeMSForTest(0.0)) + .then(() => Protocol.Runtime.evaluate({ expression: "console.time(\"a\");"})) + .then(() => utils.setCurrentTimeMSForTest(0.001)) + .then(() => Protocol.Runtime.evaluate({ expression: "console.timeEnd(\"a\");"})) + .then(next); + } +]);
diff --git a/src/v8/test/inspector/runtime/query-objects-expected.txt b/src/v8/test/inspector/runtime/query-objects-expected.txt new file mode 100644 index 0000000..9f365d9 --- /dev/null +++ b/src/v8/test/inspector/runtime/query-objects-expected.txt
@@ -0,0 +1,96 @@ +Checks Runtime.queryObjects + +Running test: testClass +Declare class Foo & store its constructor. +Create object with class Foo. +Query objects with Foo prototype. +Dump each object constructor name. +[ + [0] : Foo,object +] +Create object with class Foo. +Query objects with Foo prototype. +Dump each object constructor name. +[ + [0] : Foo,object + [1] : Foo,object +] + +Running test: testDerivedNewClass +Declare class Foo & store its constructor. +Declare class Boo extends Foo & store its constructor. +Query objects with Foo prototype. +Dump each object constructor name. +[ + [0] : Boo,object +] +Query objects with Boo prototype. +Dump each object constructor name. +[ +] +Create object with class Foo +Query objects with Foo prototype. +Dump each object constructor name. +[ + [0] : Boo,object + [1] : Foo,object +] +Create object with class Boo +Query objects with Foo prototype. +Dump each object constructor name. +[ + [0] : Boo,object + [1] : Boo,object + [2] : Foo,object +] +Query objects with Boo prototype. +Dump each object constructor name. +[ + [0] : Boo,object +] + +Running test: testNewFunction +Declare Foo & store it. +Create object using Foo. +Query objects with Foo prototype. +Dump each object constructor name. +[ + [0] : Foo,object +] +Create object using Foo. +Query objects with Foo prototype. +Dump each object constructor name. +[ + [0] : Foo,object + [1] : Foo,object +] + +Running test: testNonInspectable +Declare Foo & store it. +Create object using Foo. +Query objects with Foo prototype. +Dump each object constructor name. +[ + [0] : Foo,object +] +Mark object as not inspectable. +Query objects with Foo prototype. +Dump each object constructor name. +[ +] + +Running test: testObjectCreate +Declare Object p & store it. +Create object using Object.create(p). +Query objects with p prototype. +Dump each object constructor name. +[ + [0] : Object,object +] +Create object using Object.create(p). +Query objects with p prototype. +Dump each object constructor name. +[ + [0] : Object,object + [1] : Object,object +]
diff --git a/src/v8/test/inspector/runtime/query-objects.js b/src/v8/test/inspector/runtime/query-objects.js new file mode 100644 index 0000000..c3b1b2b --- /dev/null +++ b/src/v8/test/inspector/runtime/query-objects.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('Checks Runtime.queryObjects'); + +InspectorTest.runAsyncTestSuite([ + async function testClass() { + let contextGroup = new InspectorTest.ContextGroup(); + let session = contextGroup.connect(); + let Protocol = session.Protocol; + + InspectorTest.log('Declare class Foo & store its constructor.'); + await Protocol.Runtime.evaluate({ + expression: 'class Foo{constructor(){}};' + }); + let {result:{result:{objectId}}} = await Protocol.Runtime.evaluate({ + expression: 'Foo.prototype' + }); + + for (let i = 0; i < 2; ++i) { + InspectorTest.log('Create object with class Foo.'); + Protocol.Runtime.evaluate({expression: 'new Foo()'}); + await queryObjects(session, objectId, 'Foo'); + } + + session.disconnect(); + }, + + async function testDerivedNewClass() { + let contextGroup = new InspectorTest.ContextGroup(); + let session = contextGroup.connect(); + let Protocol = session.Protocol; + + InspectorTest.log('Declare class Foo & store its constructor.'); + Protocol.Runtime.evaluate({expression: 'class Foo{};'}); + let {result:{result:{objectId}}} = await Protocol.Runtime.evaluate({ + expression: 'Foo.prototype' + }); + let fooConstructorId = objectId; + + InspectorTest.log('Declare class Boo extends Foo & store its constructor.'); + Protocol.Runtime.evaluate({expression: 'class Boo extends Foo{};'}); + ({result:{result:{objectId}}} = await Protocol.Runtime.evaluate({ + expression: 'Boo.prototype' + })); + let booConstructorId = objectId; + + await queryObjects(session, fooConstructorId, 'Foo'); + await queryObjects(session, booConstructorId, 'Boo'); + + InspectorTest.log('Create object with class Foo'); + Protocol.Runtime.evaluate({expression: 'new Foo()'}); + await queryObjects(session, fooConstructorId, 'Foo'); + + InspectorTest.log('Create object with class Boo'); + Protocol.Runtime.evaluate({expression: 'new Boo()'}); + await queryObjects(session, fooConstructorId, 'Foo'); + await queryObjects(session, booConstructorId, 'Boo'); + + session.disconnect(); + }, + + async function testNewFunction() { + let contextGroup = new InspectorTest.ContextGroup(); + let session = contextGroup.connect(); + let Protocol = session.Protocol; + + InspectorTest.log('Declare Foo & store it.'); + Protocol.Runtime.evaluate({expression: 'function Foo(){}'}); + let {result:{result:{objectId}}} = await Protocol.Runtime.evaluate({ + expression: 'Foo.prototype' + }); + + for (let i = 0; i < 2; ++i) { + InspectorTest.log('Create object using Foo.'); + Protocol.Runtime.evaluate({expression: 'new Foo()'}); + await queryObjects(session, objectId, 'Foo'); + } + session.disconnect(); + }, + + async function testNonInspectable() { + let contextGroup = new InspectorTest.ContextGroup(); + let session = contextGroup.connect(); + let Protocol = session.Protocol; + + InspectorTest.log('Declare Foo & store it.'); + Protocol.Runtime.evaluate({expression: 'function Foo(){}'}); + let {result:{result:{objectId}}} = await Protocol.Runtime.evaluate({ + expression: 'Foo.prototype' + }); + + InspectorTest.log('Create object using Foo.'); + Protocol.Runtime.evaluate({expression: 'a = new Foo()'}); + await queryObjects(session, objectId, 'Foo'); + InspectorTest.log('Mark object as not inspectable.') + Protocol.Runtime.evaluate({expression: 'inspector.markObjectAsNotInspectable(a)'}); + await queryObjects(session, objectId, 'Foo'); + session.disconnect(); + }, + + async function testObjectCreate() { + let contextGroup = new InspectorTest.ContextGroup(); + let session = contextGroup.connect(); + let Protocol = session.Protocol; + + InspectorTest.log('Declare Object p & store it.'); + let {result:{result:{objectId}}} = await Protocol.Runtime.evaluate({ + expression: 'p = {a:1}' + }); + for (let i = 0; i < 2; ++i) { + InspectorTest.log('Create object using Object.create(p).'); + Protocol.Runtime.evaluate({expression: 'Object.create(p)'}); + await queryObjects(session, objectId, 'p'); + } + session.disconnect(); + } +]); + +const constructorsNameFunction = ` +function() { + return this.map(o => o.constructor.name + ',' + typeof o).sort(); +}`; + +async function queryObjects(sesion, prototypeObjectId, name) { + let {result:{objects}} = await sesion.Protocol.Runtime.queryObjects({ + prototypeObjectId + }); + InspectorTest.log(`Query objects with ${name} prototype.`); + let {result:{result:{value}}} = await sesion.Protocol.Runtime.callFunctionOn({ + objectId: objects.objectId, + functionDeclaration: constructorsNameFunction, + returnByValue: true + }); + InspectorTest.log('Dump each object constructor name.'); + InspectorTest.logMessage(value); +}
diff --git a/src/v8/test/inspector/runtime/regression-732717-expected.txt b/src/v8/test/inspector/runtime/regression-732717-expected.txt new file mode 100644 index 0000000..68ddd76 --- /dev/null +++ b/src/v8/test/inspector/runtime/regression-732717-expected.txt
@@ -0,0 +1 @@ +Regression test for crbug.com/732717
diff --git a/src/v8/test/inspector/runtime/regression-732717.js b/src/v8/test/inspector/runtime/regression-732717.js new file mode 100644 index 0000000..f874b2f --- /dev/null +++ b/src/v8/test/inspector/runtime/regression-732717.js
@@ -0,0 +1,17 @@ +// 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('Regression test for crbug.com/732717'); + +Protocol.Runtime.evaluate({expression: `var v3 = {}; +var v6 = {}; +Array.prototype.__defineGetter__(0, function() { + this[0] = 2147483647; +}) +Array.prototype.__defineSetter__(0, function() { +console.context(v3); +this[0] = v6; +}); +v60 = Array(0x8000).join();`}).then(InspectorTest.completeTest);
diff --git a/src/v8/test/inspector/runtime/regression-736302-expected.txt b/src/v8/test/inspector/runtime/regression-736302-expected.txt new file mode 100644 index 0000000..17243f2 --- /dev/null +++ b/src/v8/test/inspector/runtime/regression-736302-expected.txt
@@ -0,0 +1,82 @@ +crbug.com/736302 + +Running test: testThrowException +{ + method : Runtime.consoleAPICalled + params : { + args : [ + [0] : { + type : string + value : 1 + } + ] + executionContextId : <executionContextId> + stackTrace : { + callFrames : [ + [0] : { + columnNumber : 12 + functionName : + lineNumber : 1 + scriptId : <scriptId> + url : + } + ] + } + timestamp : <timestamp> + type : count + } +} + +Running test: testCustomName +{ + method : Runtime.consoleAPICalled + params : { + args : [ + [0] : { + type : string + value : [object MyObject]: 1 + } + ] + executionContextId : <executionContextId> + stackTrace : { + callFrames : [ + [0] : { + columnNumber : 12 + functionName : + lineNumber : 1 + scriptId : <scriptId> + url : + } + ] + } + timestamp : <timestamp> + type : count + } +} + +Running test: testObject +{ + method : Runtime.consoleAPICalled + params : { + args : [ + [0] : { + type : string + value : [object Object]: 1 + } + ] + executionContextId : <executionContextId> + stackTrace : { + callFrames : [ + [0] : { + columnNumber : 12 + functionName : + lineNumber : 1 + scriptId : <scriptId> + url : + } + ] + } + timestamp : <timestamp> + type : count + } +}
diff --git a/src/v8/test/inspector/runtime/regression-736302.js b/src/v8/test/inspector/runtime/regression-736302.js new file mode 100644 index 0000000..083e34a --- /dev/null +++ b/src/v8/test/inspector/runtime/regression-736302.js
@@ -0,0 +1,40 @@ +// 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('crbug.com/736302'); + +InspectorTest.runAsyncTestSuite([ + async function testThrowException() { + await Protocol.Runtime.enable(); + Protocol.Runtime.evaluate({expression: ` + console.count({ + get [Symbol.toStringTag]() { + throw new Error(); + } + });`}); + InspectorTest.logMessage(await Protocol.Runtime.onceConsoleAPICalled()); + await Protocol.Runtime.disable(); + }, + + async function testCustomName() { + await Protocol.Runtime.enable(); + Protocol.Runtime.evaluate({expression: ` + console.count({ + get [Symbol.toStringTag]() { + return 'MyObject'; + } + });`}); + InspectorTest.logMessage(await Protocol.Runtime.onceConsoleAPICalled()); + await Protocol.Runtime.disable(); + }, + + async function testObject() { + await Protocol.Runtime.enable(); + Protocol.Runtime.evaluate({expression: ` + console.count({});`}); + InspectorTest.logMessage(await Protocol.Runtime.onceConsoleAPICalled()); + await Protocol.Runtime.disable(); + } + +]);
diff --git a/src/v8/test/inspector/runtime/run-script-async-expected.txt b/src/v8/test/inspector/runtime/run-script-async-expected.txt new file mode 100644 index 0000000..29b9c52 --- /dev/null +++ b/src/v8/test/inspector/runtime/run-script-async-expected.txt
@@ -0,0 +1,191 @@ +Tests that Runtime.compileScript and Runtime.runScript work with awaitPromise flag. + +Running test: testRunAndCompileWithoutAgentEnable +{ + error : { + code : -32000 + message : Runtime agent is not enabled + } + id : <messageId> +} +{ + error : { + code : -32000 + message : Runtime agent is not enabled + } + id : <messageId> +} + +Running test: testSyntaxErrorInScript +{ + id : <messageId> + result : { + exceptionDetails : { + columnNumber : 1 + exception : { + className : SyntaxError + description : SyntaxError: Unexpected token } + objectId : <objectId> + subtype : error + type : object + } + exceptionId : <exceptionId> + lineNumber : 1 + scriptId : <scriptId> + text : Uncaught + } + } +} + +Running test: testSyntaxErrorInEvalInScript +{ + id : <messageId> + result : { + exceptionDetails : { + columnNumber : 0 + exception : { + className : SyntaxError + description : SyntaxError: Unexpected token } at boo.js:2:2 + objectId : <objectId> + subtype : error + type : object + } + exceptionId : <exceptionId> + lineNumber : 0 + scriptId : <scriptId> + stackTrace : { + callFrames : [ + [0] : { + columnNumber : 1 + functionName : + lineNumber : 1 + scriptId : <scriptId> + url : boo.js + } + ] + } + text : Uncaught + } + result : { + className : SyntaxError + description : SyntaxError: Unexpected token } at boo.js:2:2 + objectId : <objectId> + subtype : error + type : object + } + } +} + +Running test: testRunNotCompiledScript +{ + error : { + code : -32000 + message : No script with given id + } + id : <messageId> +} + +Running test: testRunCompiledScriptAfterAgentWasReenabled +{ + error : { + code : -32000 + message : Runtime agent is not enabled + } + id : <messageId> +} +{ + error : { + code : -32000 + message : No script with given id + } + id : <messageId> +} + +Running test: testRunScriptWithPreview +{ + id : <messageId> + result : { + result : { + className : Object + description : Object + objectId : <objectId> + preview : { + description : Object + overflow : false + properties : [ + [0] : { + name : a + type : number + value : 1 + } + ] + type : object + } + type : object + } + } +} + +Running test: testRunScriptReturnByValue +{ + id : <messageId> + result : { + result : { + type : object + value : { + a : 1 + } + } + } +} + +Running test: testAwaitNotPromise +{ + id : <messageId> + result : { + result : { + type : object + value : { + a : 1 + } + } + } +} + +Running test: testAwaitResolvedPromise +{ + id : <messageId> + result : { + result : { + type : object + value : { + a : 1 + } + } + } +} + +Running test: testAwaitRejectedPromise +{ + id : <messageId> + result : { + exceptionDetails : { + columnNumber : 0 + exception : { + type : object + value : { + a : 1 + } + } + exceptionId : <exceptionId> + lineNumber : 0 + text : Uncaught (in promise) + } + result : { + type : object + value : { + a : 1 + } + } + } +}
diff --git a/src/v8/test/inspector/runtime/run-script-async.js b/src/v8/test/inspector/runtime/run-script-async.js new file mode 100644 index 0000000..7448337 --- /dev/null +++ b/src/v8/test/inspector/runtime/run-script-async.js
@@ -0,0 +1,110 @@ +// 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 Runtime.compileScript and Runtime.runScript work with awaitPromise flag."); + +InspectorTest.runTestSuite([ + function testRunAndCompileWithoutAgentEnable(next) + { + Protocol.Runtime.compileScript({ expression: "", sourceURL: "", persistScript: true }) + .then((result) => InspectorTest.logMessage(result)) + .then(() => Protocol.Runtime.runScript({ scriptId: "1" })) + .then((result) => InspectorTest.logMessage(result)) + .then(() => next()); + }, + + function testSyntaxErrorInScript(next) + { + Protocol.Runtime.enable() + .then(() => Protocol.Runtime.compileScript({ expression: "\n }", sourceURL: "boo.js", persistScript: true })) + .then((result) => InspectorTest.logMessage(result)) + .then(() => Protocol.Runtime.disable()) + .then(() => next()); + }, + + function testSyntaxErrorInEvalInScript(next) + { + Protocol.Runtime.enable() + .then(() => Protocol.Runtime.compileScript({ expression: "{\n eval(\"\\\n}\")\n}", sourceURL: "boo.js", persistScript: true })) + .then((result) => Protocol.Runtime.runScript({ scriptId: result.result.scriptId })) + .then((result) => InspectorTest.logMessage(result)) + .then(() => Protocol.Runtime.disable()) + .then(() => next()); + }, + + function testRunNotCompiledScript(next) + { + Protocol.Runtime.enable() + .then((result) => Protocol.Runtime.runScript({ scriptId: "1" })) + .then((result) => InspectorTest.logMessage(result)) + .then(() => Protocol.Runtime.disable()) + .then(() => next()); + }, + + function testRunCompiledScriptAfterAgentWasReenabled(next) + { + var scriptId; + Protocol.Runtime.enable() + .then(() => Protocol.Runtime.compileScript({ expression: "{\n eval(\"\\\n}\")\n}", sourceURL: "boo.js", persistScript: true })) + .then((result) => scriptId = result.result.scriptId) + .then(() => Protocol.Runtime.disable()) + .then((result) => Protocol.Runtime.runScript({ scriptId: scriptId })) + .then((result) => InspectorTest.logMessage(result)) + .then(() => Protocol.Runtime.enable()) + .then((result) => Protocol.Runtime.runScript({ scriptId: scriptId })) + .then((result) => InspectorTest.logMessage(result)) + .then(() => Protocol.Runtime.disable()) + .then(() => next()); + }, + + function testRunScriptWithPreview(next) + { + Protocol.Runtime.enable() + .then(() => Protocol.Runtime.compileScript({ expression: "({a:1})", sourceURL: "boo.js", persistScript: true })) + .then((result) => Protocol.Runtime.runScript({ scriptId: result.result.scriptId, generatePreview: true })) + .then((result) => InspectorTest.logMessage(result)) + .then(() => Protocol.Runtime.disable()) + .then(() => next()); + }, + + function testRunScriptReturnByValue(next) + { + Protocol.Runtime.enable() + .then(() => Protocol.Runtime.compileScript({ expression: "({a:1})", sourceURL: "boo.js", persistScript: true })) + .then((result) => Protocol.Runtime.runScript({ scriptId: result.result.scriptId, returnByValue: true })) + .then((result) => InspectorTest.logMessage(result)) + .then(() => Protocol.Runtime.disable()) + .then(() => next()); + }, + + function testAwaitNotPromise(next) + { + Protocol.Runtime.enable() + .then(() => Protocol.Runtime.compileScript({ expression: "({a:1})", sourceURL: "boo.js", persistScript: true })) + .then((result) => Protocol.Runtime.runScript({ scriptId: result.result.scriptId, awaitPromise: true, returnByValue: true })) + .then((result) => InspectorTest.logMessage(result)) + .then(() => Protocol.Runtime.disable()) + .then(() => next()); + }, + + function testAwaitResolvedPromise(next) + { + Protocol.Runtime.enable() + .then(() => Protocol.Runtime.compileScript({ expression: "Promise.resolve({a:1})", sourceURL: "boo.js", persistScript: true })) + .then((result) => Protocol.Runtime.runScript({ scriptId: result.result.scriptId, awaitPromise: true, returnByValue: true })) + .then((result) => InspectorTest.logMessage(result)) + .then(() => Protocol.Runtime.disable()) + .then(() => next()); + }, + + function testAwaitRejectedPromise(next) + { + Protocol.Runtime.enable() + .then(() => Protocol.Runtime.compileScript({ expression: "Promise.reject({a:1})", sourceURL: "boo.js", persistScript: true })) + .then((result) => Protocol.Runtime.runScript({ scriptId: result.result.scriptId, awaitPromise: true, returnByValue: true })) + .then((result) => InspectorTest.logMessage(result)) + .then(() => Protocol.Runtime.disable()) + .then(() => next()); + } +]);
diff --git a/src/v8/test/inspector/runtime/runtime-disable-preserve-injected-script-expected.txt b/src/v8/test/inspector/runtime/runtime-disable-preserve-injected-script-expected.txt new file mode 100644 index 0000000..f0d715c --- /dev/null +++ b/src/v8/test/inspector/runtime/runtime-disable-preserve-injected-script-expected.txt
@@ -0,0 +1,26 @@ +Tests that Runtime.disable doesn't invalidate injected-script. +{ + configurable : true + enumerable : true + isOwn : true + name : a + value : { + description : 1 + type : number + value : 1 + } + writable : true +} +Disabling agent.. +{ + configurable : true + enumerable : true + isOwn : true + name : a + value : { + description : 1 + type : number + value : 1 + } + writable : true +}
diff --git a/src/v8/test/inspector/runtime/runtime-disable-preserve-injected-script.js b/src/v8/test/inspector/runtime/runtime-disable-preserve-injected-script.js new file mode 100644 index 0000000..0bf97f7 --- /dev/null +++ b/src/v8/test/inspector/runtime/runtime-disable-preserve-injected-script.js
@@ -0,0 +1,25 @@ +// 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. + +(async function test() { + let {session, contextGroup, Protocol} = + InspectorTest.start( + "Tests that Runtime.disable doesn't invalidate injected-script."); + Protocol.Runtime.enable(); + let {result:{result:{objectId}}} = await Protocol.Runtime.evaluate({ + expression: "({a:1})" + }); + var {result:{result}} = await Protocol.Runtime.getProperties({objectId}); + InspectorTest.logMessage(result.find(property => property.name === 'a')); + InspectorTest.log('Disabling agent..'); + await Protocol.Runtime.disable(); + var result = await Protocol.Runtime.getProperties({objectId}); + if (result.error) { + InspectorTest.logMessage(result); + } else { + var props = result.result.result; + InspectorTest.logMessage(props.find(property => property.name === 'a')); + } + InspectorTest.completeTest(); +})()
diff --git a/src/v8/test/inspector/runtime/runtime-evaluate-with-dirty-context-expected.txt b/src/v8/test/inspector/runtime/runtime-evaluate-with-dirty-context-expected.txt new file mode 100644 index 0000000..65dfc1b --- /dev/null +++ b/src/v8/test/inspector/runtime/runtime-evaluate-with-dirty-context-expected.txt
@@ -0,0 +1,35 @@ +Checks that Runtime.evaluate works with dirty context. +{ + method : Runtime.consoleAPICalled + params : { + args : [ + [0] : { + description : 42 + type : number + value : 42 + } + ] + executionContextId : <executionContextId> + stackTrace : { + callFrames : [ + [0] : { + columnNumber : 8 + functionName : + lineNumber : 0 + scriptId : <scriptId> + url : + } + ] + } + timestamp : <timestamp> + type : log + } +} +{ + id : <messageId> + result : { + result : { + type : undefined + } + } +}
diff --git a/src/v8/test/inspector/runtime/runtime-evaluate-with-dirty-context.js b/src/v8/test/inspector/runtime/runtime-evaluate-with-dirty-context.js new file mode 100644 index 0000000..5f42d49 --- /dev/null +++ b/src/v8/test/inspector/runtime/runtime-evaluate-with-dirty-context.js
@@ -0,0 +1,11 @@ +// 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 Runtime.evaluate works with dirty context.'); +contextGroup.setupInjectedScriptEnvironment(); +Protocol.Runtime.enable(); +Protocol.Runtime.onConsoleAPICalled(InspectorTest.logMessage); +Protocol.Runtime.evaluate({expression: 'console.log(42)'}) + .then(InspectorTest.logMessage) + .then(InspectorTest.completeTest);
diff --git a/src/v8/test/inspector/runtime/runtime-restore-expected.txt b/src/v8/test/inspector/runtime/runtime-restore-expected.txt new file mode 100644 index 0000000..d95051b --- /dev/null +++ b/src/v8/test/inspector/runtime/runtime-restore-expected.txt
@@ -0,0 +1,115 @@ +Checks that Runtime agent correctly restore its state. + +Running test: testExecutionContextsNotificationsOnRestore +{ + method : Runtime.executionContextCreated + params : { + context : { + id : 1 + name : + origin : + } + } +} +will reconnect.. +{ + method : Runtime.executionContextsCleared + params : { + } +} +{ + method : Runtime.executionContextCreated + params : { + context : { + id : 1 + name : + origin : + } + } +} + +Running test: testConsoleAPICalledAfterRestore +will reconnect.. +{ + method : Runtime.consoleAPICalled + params : { + args : [ + [0] : { + description : 42 + type : number + value : 42 + } + ] + executionContextId : <executionContextId> + stackTrace : { + callFrames : [ + [0] : { + columnNumber : 8 + functionName : + lineNumber : 0 + scriptId : <scriptId> + url : + } + ] + } + timestamp : <timestamp> + type : log + } +} + +Running test: testSetCustomObjectFormatterEnabled +will reconnect.. +will reconnect.. +{ + method : Runtime.consoleAPICalled + params : { + args : [ + [0] : { + className : Object + customPreview : { + bindRemoteObjectFunctionId : <bindRemoteObjectFunctionId> + formatterObjectId : <formatterObjectId> + hasBody : true + header : ["span",{},"Header formatted ",42] + } + description : Object + objectId : <objectId> + preview : { + description : Object + overflow : false + properties : [ + [0] : { + name : name + type : number + value : 42 + } + ] + type : object + } + type : object + } + ] + executionContextId : <executionContextId> + stackTrace : { + callFrames : [ + [0] : { + columnNumber : 8 + functionName : + lineNumber : 0 + scriptId : <scriptId> + url : + } + ] + } + timestamp : <timestamp> + type : log + } +} +{ + id : <messageId> + result : { + result : { + type : undefined + } + } +}
diff --git a/src/v8/test/inspector/runtime/runtime-restore.js b/src/v8/test/inspector/runtime/runtime-restore.js new file mode 100644 index 0000000..09e4467 --- /dev/null +++ b/src/v8/test/inspector/runtime/runtime-restore.js
@@ -0,0 +1,77 @@ +// 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.v8 + +let {session, contextGroup, Protocol} = InspectorTest.start('Checks that Runtime agent correctly restore its state.'); + +contextGroup.addScript(` +var formatter = { + header: function(x) + { + return ["span", {}, "Header formatted ", x.name]; + }, + + hasBody: function(x) + { + return true; + }, + + body: function(x) + { + return ["span", {}, "Body formatted ", x.name] + } +}; + +devtoolsFormatters = [ formatter ]; + +//# sourceURL=test.js`) + +InspectorTest.runTestSuite([ + function testExecutionContextsNotificationsOnRestore(next) { + Protocol.Runtime.onExecutionContextsCleared(InspectorTest.logMessage); + Protocol.Runtime.onExecutionContextCreated(InspectorTest.logMessage); + Protocol.Runtime.onExecutionContextDestroyed(InspectorTest.logMessage); + Protocol.Runtime.enable() + .then(reconnect) + .then(Protocol.Runtime.disable) + .then(() => { + Protocol.Runtime.onExecutionContextsCleared(null); + Protocol.Runtime.onExecutionContextCreated(null); + Protocol.Runtime.onExecutionContextDestroyed(null); + next() + }); + }, + + function testConsoleAPICalledAfterRestore(next) { + Protocol.Runtime.onConsoleAPICalled(InspectorTest.logMessage); + Protocol.Runtime.enable() + .then(reconnect) + .then(() => Protocol.Runtime.evaluate({ expression: 'console.log(42);' })) + .then(Protocol.Runtime.disable) + .then(() => { + Protocol.Runtime.onConsoleAPICalled(null); + next(); + }); + }, + + function testSetCustomObjectFormatterEnabled(next) { + Protocol.Runtime.onConsoleAPICalled(InspectorTest.logMessage); + Protocol.Runtime.discardConsoleEntries() + .then(reconnect) + .then(() => Protocol.Runtime.enable()) + .then(() => Protocol.Runtime.setCustomObjectFormatterEnabled({ enabled: true })) + .then(reconnect) + .then(() => Protocol.Runtime.evaluate({ expression: 'console.log({ name: 42 })'})) + .then(InspectorTest.logMessage) + .then(Protocol.Runtime.disable) + .then(() => { + Protocol.Runtime.onConsoleAPICalled(null); + next(); + }); + }, +]); + +function reconnect() { + InspectorTest.logMessage('will reconnect..'); + session.reconnect(); +}
diff --git a/src/v8/test/inspector/runtime/set-or-map-entries-expected.txt b/src/v8/test/inspector/runtime/set-or-map-entries-expected.txt new file mode 100644 index 0000000..edaee51 --- /dev/null +++ b/src/v8/test/inspector/runtime/set-or-map-entries-expected.txt
@@ -0,0 +1,9 @@ +Test that Runtime.getProperties doesn't truncate set and map entries in internalProperties. +Entries for "createSet(10)" +Array(10) +Entries for "createSet(1000)" +Array(1000) +Entries for "createMap(10)" +Array(10) +Entries for "createMap(1000)" +Array(1000)
diff --git a/src/v8/test/inspector/runtime/set-or-map-entries.js b/src/v8/test/inspector/runtime/set-or-map-entries.js new file mode 100644 index 0000000..4206c87 --- /dev/null +++ b/src/v8/test/inspector/runtime/set-or-map-entries.js
@@ -0,0 +1,54 @@ +// 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 that Runtime.getProperties doesn't truncate set and map entries in internalProperties.") + +contextGroup.addScript(` + function createSet(size) { + var s = new Set(); + var a = {}; + a.a = a; + for (var i = 0; i < size; ++i) s.add({ wrapper: a}); + return s; + } + + function createMap(size) { + var m = new Map(); + var a = {}; + a.a = a; + for (var i = 0; i < size; ++i) m.set(i, { wrapper: a}); + return m; + } +`); + +contextGroup.setupInjectedScriptEnvironment(); + +Protocol.Debugger.enable(); +Protocol.Runtime.enable(); + +testExpression("createSet(10)") + .then(() => testExpression("createSet(1000)")) + .then(() => testExpression("createMap(10)")) + .then(() => testExpression("createMap(1000)")) + .then(() => InspectorTest.completeTest()); + +function testExpression(expression) +{ + return Protocol.Runtime.evaluate({ "expression": expression}) + .then(result => Protocol.Runtime.getProperties({ ownProperties: true, objectId: result.result.result.objectId })) + .then(message => dumpEntriesDescription(expression, message)); +} + +function dumpEntriesDescription(expression, message) +{ + InspectorTest.log(`Entries for "${expression}"`); + var properties = message.result.internalProperties; + var property; + if (properties) + property = properties.find(property => property.name === "[[Entries]]"); + if (!property) + InspectorTest.log("[[Entries]] not found"); + else + InspectorTest.log(property.value.description); +}
diff --git a/src/v8/test/inspector/sessions/create-session-expected.txt b/src/v8/test/inspector/sessions/create-session-expected.txt new file mode 100644 index 0000000..e3d921e --- /dev/null +++ b/src/v8/test/inspector/sessions/create-session-expected.txt
@@ -0,0 +1,132 @@ +Tests that creating multiple sessions works. +Connecting session 1 +From session 1 +{ + method : Runtime.executionContextCreated + params : { + context : { + id : 1 + name : + origin : + } + } +} +Connecting session 2 +From session 2 +{ + method : Runtime.executionContextCreated + params : { + context : { + id : 1 + name : + origin : + } + } +} +Reconnecting session 2 +From session 2 +{ + method : Runtime.executionContextCreated + params : { + context : { + id : 1 + name : + origin : + } + } +} +Reconnecting session 1 +From session 1 +{ + method : Runtime.executionContextCreated + params : { + context : { + id : 1 + name : + origin : + } + } +} +Connecting session 3 +From session 3 +{ + method : Runtime.executionContextCreated + params : { + context : { + id : 1 + name : + origin : + } + } +} +Destroying and creating context +From session 2 +{ + method : Runtime.executionContextDestroyed + params : { + executionContextId : <executionContextId> + } +} +id matching: true +From session 1 +{ + method : Runtime.executionContextDestroyed + params : { + executionContextId : <executionContextId> + } +} +id matching: true +From session 3 +{ + method : Runtime.executionContextDestroyed + params : { + executionContextId : <executionContextId> + } +} +id matching: true +From session 2 +{ + method : Runtime.executionContextCreated + params : { + context : { + id : 2 + name : + origin : + } + } +} +From session 1 +{ + method : Runtime.executionContextCreated + params : { + context : { + id : 2 + name : + origin : + } + } +} +From session 3 +{ + method : Runtime.executionContextCreated + params : { + context : { + id : 2 + name : + origin : + } + } +} +Disconnecting all sessions +Connecting session 4 +From session 4 +{ + method : Runtime.executionContextCreated + params : { + context : { + id : 2 + name : + origin : + } + } +}
diff --git a/src/v8/test/inspector/sessions/create-session.js b/src/v8/test/inspector/sessions/create-session.js new file mode 100644 index 0000000..1163583 --- /dev/null +++ b/src/v8/test/inspector/sessions/create-session.js
@@ -0,0 +1,58 @@ +// 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('Tests that creating multiple sessions works.'); + +function connect(contextGroup, num) { + var session = contextGroup.connect(); + var executionContextId; + session.Protocol.Runtime.onExecutionContextCreated(message => { + InspectorTest.log('From session ' + num); + InspectorTest.logMessage(message); + executionContextId = message.params.context.id; + }); + session.Protocol.Runtime.onExecutionContextDestroyed(message => { + InspectorTest.log('From session ' + num); + InspectorTest.logMessage(message); + InspectorTest.log('id matching: ' + (message.params.executionContextId === executionContextId)); + }); + return session; +} + +(async function test() { + var contextGroup = new InspectorTest.ContextGroup(); + InspectorTest.log('Connecting session 1'); + var session1 = connect(contextGroup, 1); + await session1.Protocol.Runtime.enable(); + + InspectorTest.log('Connecting session 2'); + var session2 = connect(contextGroup, 2); + await session2.Protocol.Runtime.enable(); + + InspectorTest.log('Reconnecting session 2'); + session2.reconnect(); + await session2.Protocol.Runtime.enable(); + + InspectorTest.log('Reconnecting session 1'); + session1.reconnect(); + await session1.Protocol.Runtime.enable(); + + InspectorTest.log('Connecting session 3'); + var session3 = connect(contextGroup, 3); + await session3.Protocol.Runtime.enable(); + + InspectorTest.log('Destroying and creating context'); + await session2.Protocol.Runtime.evaluate({expression: 'inspector.fireContextDestroyed(); inspector.fireContextCreated(); '}); + + InspectorTest.log('Disconnecting all sessions'); + session1.disconnect(); + session2.disconnect(); + session3.disconnect(); + + InspectorTest.log('Connecting session 4'); + var session4 = connect(contextGroup, 4); + await session4.Protocol.Runtime.enable(); + + InspectorTest.completeTest(); +})();
diff --git a/src/v8/test/inspector/sessions/debugger-stepping-and-breakpoints-expected.txt b/src/v8/test/inspector/sessions/debugger-stepping-and-breakpoints-expected.txt new file mode 100644 index 0000000..2b7cc16 --- /dev/null +++ b/src/v8/test/inspector/sessions/debugger-stepping-and-breakpoints-expected.txt
@@ -0,0 +1,228 @@ +Tests how multiple sessions interact while pausing, stepping, setting breakpoints and blackboxing. +Connecting session 1 +Pausing in 1 +Paused in 1: + reason: other + hit breakpoints: + location: <anonymous>@0 + data: null +Connecting session 2 +Paused in 2: + reason: other + hit breakpoints: + location: <anonymous>@0 + data: null +Resuming in 2 +Resumed in 1 +Resumed in 2 +Setting breakpoints in 1 +Setting breakpoints in 2 +Evaluating common breakpoint in 1 +Paused in 1: + reason: other + hit breakpoints: test.js:11:0 + location: foo@11 + data: null +Paused in 2: + reason: other + hit breakpoints: test.js:11:0 + location: foo@11 + data: null +Resuming in 1 +Resumed in 1 +Resumed in 2 +Evaluating debugger in 1 +Paused in 1: + reason: other + hit breakpoints: + location: bar@25 + data: null +Paused in 2: + reason: other + hit breakpoints: + location: bar@25 + data: null +Resuming in 2 +Resumed in 1 +Resumed in 2 +Evaluating exclusive breakpoint in 1 +Paused in 1: + reason: other + hit breakpoints: test.js:14:0 + location: baz@14 + data: null +Paused in 2: + reason: other + hit breakpoints: + location: baz@14 + data: null +Resuming in 1 +Resumed in 1 +Resumed in 2 +Evaluating common breakpoint in 2 +Paused in 1: + reason: other + hit breakpoints: test.js:11:0 + location: foo@11 + data: null +Paused in 2: + reason: other + hit breakpoints: test.js:11:0 + location: foo@11 + data: null +Resuming in 2 +Resumed in 1 +Resumed in 2 +Evaluating debugger in 2 +Paused in 1: + reason: other + hit breakpoints: + location: bar@25 + data: null +Paused in 2: + reason: other + hit breakpoints: + location: bar@25 + data: null +Resuming in 2 +Resumed in 1 +Resumed in 2 +Evaluating exclusive breakpoint in 2 +Paused in 1: + reason: other + hit breakpoints: test.js:14:0 + location: baz@14 + data: null +Paused in 2: + reason: other + hit breakpoints: + location: baz@14 + data: null +Resuming in 1 +Resumed in 1 +Resumed in 2 +Evaluating stepping in 1 +Paused in 1: + reason: other + hit breakpoints: + location: stepping@17 + data: null +Paused in 2: + reason: other + hit breakpoints: + location: stepping@17 + data: null +Stepping into in 2 +Resumed in 1 +Resumed in 2 +Paused in 1: + reason: other + hit breakpoints: + location: stepping@18 + data: null +Paused in 2: + reason: other + hit breakpoints: + location: stepping@18 + data: null +Stepping over in 1 +Resumed in 1 +Resumed in 2 +Paused in 1: + reason: other + hit breakpoints: + location: stepping@19 + data: null +Paused in 2: + reason: other + hit breakpoints: + location: stepping@19 + data: null +Stepping out in 2 +Resumed in 1 +Resumed in 2 +Paused in 1: + reason: other + hit breakpoints: + location: <anonymous>@0 + data: null +Paused in 2: + reason: other + hit breakpoints: + location: <anonymous>@0 + data: null +Resuming in 1 +Resumed in 1 +Resumed in 2 +Pausing in next statement +Paused in 1: + reason: some-reason + hit breakpoints: + location: <anonymous>@0 + data: {"a":42} +Paused in 2: + reason: some-reason + hit breakpoints: + location: <anonymous>@0 + data: {"a":42} +Resuming in 1 +Resumed in 1 +Resumed in 2 +Pausing in next statement +Paused in 1: + reason: some-reason + hit breakpoints: + location: <anonymous>@0 + data: {"a":42} +Paused in 2: + reason: some-reason + hit breakpoints: + location: <anonymous>@0 + data: {"a":42} +Resuming in 2 +Resumed in 1 +Resumed in 2 +Blackboxing bar() in 2 +Evaluating bar() in 2 +Paused in 1: + reason: other + hit breakpoints: + location: bar@25 + data: null +Resuming in 1 +Resumed in 1 +Blackboxing bar() in 1 +Evaluating bar() in 2 +Skipping pauses in 1 +Evaluating common breakpoint in 1 +Paused in 2: + reason: other + hit breakpoints: test.js:11:0 + location: foo@11 + data: null +Resuming in 2 +Resumed in 2 +Skipping pauses in 2 +Evaluating common breakpoint in 1 +Unskipping pauses in 1 +Unskipping pauses in 2 +Deactivating breakpoints in 1 +Evaluating common breakpoint in 1 +Paused in 2: + reason: other + hit breakpoints: test.js:11:0 + location: foo@11 + data: null +Resuming in 2 +Resumed in 2 +Deactivating breakpoints in 2 +Evaluating common breakpoint in 1 +Activating breakpoints in 1 +Activating breakpoints in 2 +Disabling debugger agent in 1 +Evaluating breakpoint in 1 (should not be triggered) +Paused in 2: + reason: other + hit breakpoints: + location: <anonymous>@1 + data: null
diff --git a/src/v8/test/inspector/sessions/debugger-stepping-and-breakpoints.js b/src/v8/test/inspector/sessions/debugger-stepping-and-breakpoints.js new file mode 100644 index 0000000..b6ca626 --- /dev/null +++ b/src/v8/test/inspector/sessions/debugger-stepping-and-breakpoints.js
@@ -0,0 +1,211 @@ +// 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('Tests how multiple sessions interact while pausing, stepping, setting breakpoints and blackboxing.'); + +var contextGroup = new InspectorTest.ContextGroup(); + +contextGroup.addScript(` +function foo() { + return 1; +} +function baz() { + return 2; +} +function stepping() { + debugger; + var a = 1; + var b = 1; +} +//# sourceURL=test.js`, 9, 25); + +contextGroup.addScript(` +function bar() { + debugger; +} +//# sourceURL=test2.js`, 23, 25); + +(async function test() { + InspectorTest.log('Connecting session 1'); + var session1 = contextGroup.connect(); + await session1.Protocol.Debugger.enable(); + InspectorTest.log('Pausing in 1'); + session1.Protocol.Runtime.evaluate({expression: 'debugger;'}); + await waitForPaused(session1, 1); + InspectorTest.log('Connecting session 2'); + var session2 = contextGroup.connect(); + var enabledPromise = session2.Protocol.Debugger.enable(); + await waitForPaused(session2, 2); + await enabledPromise; + InspectorTest.log('Resuming in 2'); + session2.Protocol.Debugger.resume(); + await waitForBothResumed(); + + InspectorTest.log('Setting breakpoints in 1'); + await session1.Protocol.Debugger.setBreakpointByUrl({url: 'test.js', lineNumber: 11}); + await session1.Protocol.Debugger.setBreakpointByUrl({url: 'test.js', lineNumber: 14}); + InspectorTest.log('Setting breakpoints in 2'); + await session2.Protocol.Debugger.setBreakpointByUrl({url: 'test.js', lineNumber: 11}); + + InspectorTest.log('Evaluating common breakpoint in 1'); + session1.Protocol.Runtime.evaluate({expression: 'foo();'}); + await waitForBothPaused(); + InspectorTest.log('Resuming in 1'); + session1.Protocol.Debugger.resume(); + await waitForBothResumed(); + + InspectorTest.log('Evaluating debugger in 1'); + session1.Protocol.Runtime.evaluate({expression: 'bar();'}); + await waitForBothPaused(); + InspectorTest.log('Resuming in 2'); + session2.Protocol.Debugger.resume(); + await waitForBothResumed(); + + InspectorTest.log('Evaluating exclusive breakpoint in 1'); + session1.Protocol.Runtime.evaluate({expression: 'baz();'}); + await waitForBothPaused(); + InspectorTest.log('Resuming in 1'); + session1.Protocol.Debugger.resume(); + await waitForBothResumed(); + + InspectorTest.log('Evaluating common breakpoint in 2'); + session2.Protocol.Runtime.evaluate({expression: 'foo();'}); + await waitForBothPaused(); + InspectorTest.log('Resuming in 2'); + session2.Protocol.Debugger.resume(); + await waitForBothResumed(); + + InspectorTest.log('Evaluating debugger in 2'); + session2.Protocol.Runtime.evaluate({expression: 'bar();'}); + await waitForBothPaused(); + InspectorTest.log('Resuming in 2'); + session2.Protocol.Debugger.resume(); + await waitForBothResumed(); + + InspectorTest.log('Evaluating exclusive breakpoint in 2'); + session2.Protocol.Runtime.evaluate({expression: 'baz();'}); + await waitForBothPaused(); + InspectorTest.log('Resuming in 1'); + session1.Protocol.Debugger.resume(); + await waitForBothResumed(); + + InspectorTest.log('Evaluating stepping in 1'); + session1.Protocol.Runtime.evaluate({expression: 'stepping();'}); + await waitForBothPaused(); + InspectorTest.log('Stepping into in 2'); + session2.Protocol.Debugger.stepInto(); + await waitForBothResumed(); + await waitForBothPaused(); + InspectorTest.log('Stepping over in 1'); + session1.Protocol.Debugger.stepOver(); + await waitForBothResumed(); + await waitForBothPaused(); + InspectorTest.log('Stepping out in 2'); + session2.Protocol.Debugger.stepOut(); + await waitForBothResumed(); + await waitForBothPaused(); + InspectorTest.log('Resuming in 1'); + session1.Protocol.Debugger.resume(); + await waitForBothResumed(); + + InspectorTest.log('Pausing in next statement'); + contextGroup.schedulePauseOnNextStatement('some-reason', JSON.stringify({a: 42})); + session2.Protocol.Runtime.evaluate({expression: 'var a = 1;'}); + await waitForBothPaused(); + InspectorTest.log('Resuming in 1'); + session1.Protocol.Debugger.resume(); + await waitForBothResumed(); + + InspectorTest.log('Pausing in next statement'); + contextGroup.schedulePauseOnNextStatement('some-reason', JSON.stringify({a: 42})); + session2.Protocol.Runtime.evaluate({expression: 'var a = 1;'}); + await waitForBothPaused(); + InspectorTest.log('Resuming in 2'); + session2.Protocol.Debugger.resume(); + await waitForBothResumed(); + + InspectorTest.log('Blackboxing bar() in 2'); + await session2.Protocol.Debugger.setBlackboxPatterns({patterns: ['test2.js']}); + InspectorTest.log('Evaluating bar() in 2'); + session2.Protocol.Runtime.evaluate({expression: 'bar();'}); + await waitForPaused(session1, 1); + InspectorTest.log('Resuming in 1'); + session1.Protocol.Debugger.resume(); + await waitForResumed(session1, 1); + + InspectorTest.log('Blackboxing bar() in 1'); + await session1.Protocol.Debugger.setBlackboxPatterns({patterns: ['test2.js']}); + InspectorTest.log('Evaluating bar() in 2'); + await session2.Protocol.Runtime.evaluate({expression: 'bar();'}); + + InspectorTest.log('Skipping pauses in 1'); + await session1.Protocol.Debugger.setSkipAllPauses({skip: true}); + InspectorTest.log('Evaluating common breakpoint in 1'); + session1.Protocol.Runtime.evaluate({expression: 'foo();'}); + await waitForPaused(session2, 2); + InspectorTest.log('Resuming in 2'); + session2.Protocol.Debugger.resume(); + await waitForResumed(session2, 2); + + InspectorTest.log('Skipping pauses in 2'); + await session2.Protocol.Debugger.setSkipAllPauses({skip: true}); + InspectorTest.log('Evaluating common breakpoint in 1'); + await session1.Protocol.Runtime.evaluate({expression: 'foo();'}); + + InspectorTest.log('Unskipping pauses in 1'); + await session1.Protocol.Debugger.setSkipAllPauses({skip: false}); + InspectorTest.log('Unskipping pauses in 2'); + await session2.Protocol.Debugger.setSkipAllPauses({skip: false}); + + InspectorTest.log('Deactivating breakpoints in 1'); + await session1.Protocol.Debugger.setBreakpointsActive({active: false}); + InspectorTest.log('Evaluating common breakpoint in 1'); + session1.Protocol.Runtime.evaluate({expression: 'foo();'}); + await waitForPaused(session2, 2); + InspectorTest.log('Resuming in 2'); + session2.Protocol.Debugger.resume(); + await waitForResumed(session2, 2); + + InspectorTest.log('Deactivating breakpoints in 2'); + await session2.Protocol.Debugger.setBreakpointsActive({active: false}); + InspectorTest.log('Evaluating common breakpoint in 1'); + await session1.Protocol.Runtime.evaluate({expression: 'foo();'}); + + InspectorTest.log('Activating breakpoints in 1'); + await session1.Protocol.Debugger.setBreakpointsActive({active: true}); + InspectorTest.log('Activating breakpoints in 2'); + await session2.Protocol.Debugger.setBreakpointsActive({active: true}); + InspectorTest.log('Disabling debugger agent in 1'); + await session1.Protocol.Debugger.disable(); + InspectorTest.log('Evaluating breakpoint in 1 (should not be triggered)'); + session2.Protocol.Runtime.evaluate({expression: 'baz();\ndebugger;'}); + await waitForPaused(session2, 2); + + InspectorTest.completeTest(); + + function waitForBothPaused() { + return Promise.all([waitForPaused(session1, 1), waitForPaused(session2, 2)]); + } + + function waitForBothResumed() { + return Promise.all([waitForResumed(session1, 1), waitForResumed(session2, 2)]); + } +})(); + +function waitForPaused(session, num) { + return session.Protocol.Debugger.oncePaused().then(message => { + InspectorTest.log(`Paused in ${num}:`); + InspectorTest.log(` reason: ${message.params.reason}`); + InspectorTest.log(` hit breakpoints: ${(message.params.hitBreakpoints || []).join(';')}`); + var callFrame = message.params.callFrames[0]; + InspectorTest.log(` location: ${callFrame.functionName || '<anonymous>'}@${callFrame.location.lineNumber}`); + InspectorTest.log(` data: ${JSON.stringify(message.params.data || null)}`); + }); +} + +function waitForResumed(session, num) { + return session.Protocol.Debugger.onceResumed().then(message => { + InspectorTest.log(`Resumed in ${num}`); + }); +}
diff --git a/src/v8/test/inspector/sessions/pause-on-console-assert-expected.txt b/src/v8/test/inspector/sessions/pause-on-console-assert-expected.txt new file mode 100644 index 0000000..7b59002 --- /dev/null +++ b/src/v8/test/inspector/sessions/pause-on-console-assert-expected.txt
@@ -0,0 +1,24 @@ +Tests that multiple sessions pause once on console.assert. +Pausing on exceptions in 1 +Asserting in 1 +Paused in 1 with reason assert +Paused in 2 with reason assert +Asserting in 2 +Paused in 1 with reason assert +Paused in 2 with reason assert +Pausing on exceptions in both +Asserting in 1 +Paused in 1 with reason assert +Paused in 2 with reason assert +Asserting in 2 +Paused in 1 with reason assert +Paused in 2 with reason assert +Not pausing on exceptions +Asserting in 1 +Asserting in 2 +Pausing on exceptions in 3 (different context group) +Asserting in 3 +Paused in 3 with reason assert +Asserting in 1 +Paused in 1 with reason assert +Paused in 2 with reason assert
diff --git a/src/v8/test/inspector/sessions/pause-on-console-assert.js b/src/v8/test/inspector/sessions/pause-on-console-assert.js new file mode 100644 index 0000000..6cfdeaf --- /dev/null +++ b/src/v8/test/inspector/sessions/pause-on-console-assert.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. + +InspectorTest.log('Tests that multiple sessions pause once on console.assert.'); + +(async function test() { + var contextGroup1 = new InspectorTest.ContextGroup(); + var session1 = await connect(contextGroup1, 1); + var session2 = await connect(contextGroup1, 2); + var contextGroup2 = new InspectorTest.ContextGroup(); + var session3 = await connect(contextGroup2, 3); + + InspectorTest.log('Pausing on exceptions in 1'); + await session1.Protocol.Debugger.setPauseOnExceptions({state: 'all'}); + InspectorTest.log('Asserting in 1'); + await session1.Protocol.Runtime.evaluate({expression: 'console.assert(false)'}); + InspectorTest.log('Asserting in 2'); + await session2.Protocol.Runtime.evaluate({expression: 'console.assert(false)'}); + + InspectorTest.log('Pausing on exceptions in both'); + await session2.Protocol.Debugger.setPauseOnExceptions({state: 'all'}); + InspectorTest.log('Asserting in 1'); + await session1.Protocol.Runtime.evaluate({expression: 'console.assert(false)'}); + InspectorTest.log('Asserting in 2'); + await session2.Protocol.Runtime.evaluate({expression: 'console.assert(false)'}); + + InspectorTest.log('Not pausing on exceptions'); + await session1.Protocol.Debugger.setPauseOnExceptions({state: 'none'}); + await session2.Protocol.Debugger.setPauseOnExceptions({state: 'none'}); + InspectorTest.log('Asserting in 1'); + await session1.Protocol.Runtime.evaluate({expression: 'console.assert(false)'}); + InspectorTest.log('Asserting in 2'); + await session2.Protocol.Runtime.evaluate({expression: 'console.assert(false)'}); + + InspectorTest.log('Pausing on exceptions in 3 (different context group)'); + await session3.Protocol.Debugger.setPauseOnExceptions({state: 'all'}); + InspectorTest.log('Asserting in 3'); + await session3.Protocol.Runtime.evaluate({expression: 'console.assert(false)'}); + InspectorTest.log('Asserting in 1'); + await session1.Protocol.Runtime.evaluate({expression: 'console.assert(false)'}); + + InspectorTest.completeTest(); +})(); + +async function connect(contextGroup, num) { + var session = contextGroup.connect(); + await session.Protocol.Debugger.enable(); + session.Protocol.Debugger.onPaused(message => { + InspectorTest.log(`Paused in ${num} with reason ${message.params.reason}`); + session.Protocol.Debugger.resume(); + }); + return session; +}
diff --git a/src/v8/test/inspector/sessions/runtime-command-line-api-expected.txt b/src/v8/test/inspector/sessions/runtime-command-line-api-expected.txt new file mode 100644 index 0000000..98583a5 --- /dev/null +++ b/src/v8/test/inspector/sessions/runtime-command-line-api-expected.txt
@@ -0,0 +1,211 @@ +Tests that multiple sessions do not share command line api. +Setting $0 in 1 +Evaluating $0 in 1 +{ + id : <messageId> + result : { + result : { + description : 42 + type : number + value : 42 + } + } +} +Evaluating $0 in 2 +{ + id : <messageId> + result : { + result : { + type : undefined + } + } +} +Setting $0 in 2 +Evaluating $0 in 1 +{ + id : <messageId> + result : { + result : { + description : 42 + type : number + value : 42 + } + } +} +Evaluating $0 in 2 +{ + id : <messageId> + result : { + result : { + description : 17 + type : number + value : 17 + } + } +} +Setting $_ in 1 +Evaluating $_ in 1 +{ + id : <messageId> + result : { + result : { + description : 42 + type : number + value : 42 + } + } +} +Evaluating $_ in 2 +{ + id : <messageId> + result : { + result : { + type : undefined + } + } +} +Setting $_ in 2 +Evaluating $_ in 1 +{ + id : <messageId> + result : { + result : { + description : 42 + type : number + value : 42 + } + } +} +Evaluating $_ in 2 +{ + id : <messageId> + result : { + result : { + description : 17 + type : number + value : 17 + } + } +} +Inspecting in 1 +inspectRequested from 1 +{ + method : Runtime.inspectRequested + params : { + hints : { + } + object : { + description : 42 + type : number + value : 42 + } + } +} +Inspecting in 1 through variable +inspectRequested from 1 +{ + method : Runtime.inspectRequested + params : { + hints : { + } + object : { + description : 42 + type : number + value : 42 + } + } +} +Inspecting in 2 +inspectRequested from 2 +{ + method : Runtime.inspectRequested + params : { + hints : { + } + object : { + description : 17 + type : number + value : 17 + } + } +} +Inspecting in 2 through variable +inspectRequested from 2 +{ + method : Runtime.inspectRequested + params : { + hints : { + } + object : { + description : 17 + type : number + value : 17 + } + } +} +Inspecting in 2 through variable from 1 +inspectRequested from 1 +{ + method : Runtime.inspectRequested + params : { + hints : { + } + object : { + description : 42 + type : number + value : 42 + } + } +} +Disconnecting 1 +Evaluating $0 in 2 +{ + id : <messageId> + result : { + result : { + description : 17 + type : number + value : 17 + } + } +} +Evaluating $_ in 2 +{ + id : <messageId> + result : { + result : { + description : 17 + type : number + value : 17 + } + } +} +Inspecting in 2 +inspectRequested from 2 +{ + method : Runtime.inspectRequested + params : { + hints : { + } + object : { + description : 17 + type : number + value : 17 + } + } +} +Inspecting in 2 through variable from 1 +Inspecting in 2 through variable +inspectRequested from 2 +{ + method : Runtime.inspectRequested + params : { + hints : { + } + object : { + description : 17 + type : number + value : 17 + } + } +}
diff --git a/src/v8/test/inspector/sessions/runtime-command-line-api.js b/src/v8/test/inspector/sessions/runtime-command-line-api.js new file mode 100644 index 0000000..078783a --- /dev/null +++ b/src/v8/test/inspector/sessions/runtime-command-line-api.js
@@ -0,0 +1,76 @@ +// 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('Tests that multiple sessions do not share command line api.'); + +(async function test() { + var contextGroup = new InspectorTest.ContextGroup(); + var session1 = contextGroup.connect(); + await session1.Protocol.Runtime.enable(); + session1.Protocol.Runtime.onInspectRequested(message => { + InspectorTest.log('inspectRequested from 1'); + InspectorTest.logMessage(message); + }); + var session2 = contextGroup.connect(); + await session2.Protocol.Runtime.enable(); + session2.Protocol.Runtime.onInspectRequested(message => { + InspectorTest.log('inspectRequested from 2'); + InspectorTest.logMessage(message); + }); + + InspectorTest.log('Setting $0 in 1'); + await session1.addInspectedObject(42); + InspectorTest.log('Evaluating $0 in 1'); + InspectorTest.logMessage(await session1.Protocol.Runtime.evaluate({expression: '$0', includeCommandLineAPI: true})); + InspectorTest.log('Evaluating $0 in 2'); + InspectorTest.logMessage(await session2.Protocol.Runtime.evaluate({expression: '$0', includeCommandLineAPI: true})); + + InspectorTest.log('Setting $0 in 2'); + await session2.addInspectedObject(17); + InspectorTest.log('Evaluating $0 in 1'); + InspectorTest.logMessage(await session1.Protocol.Runtime.evaluate({expression: '$0', includeCommandLineAPI: true})); + InspectorTest.log('Evaluating $0 in 2'); + InspectorTest.logMessage(await session2.Protocol.Runtime.evaluate({expression: '$0', includeCommandLineAPI: true})); + + InspectorTest.log('Setting $_ in 1'); + await session1.Protocol.Runtime.evaluate({expression: '42', objectGroup: 'console', includeCommandLineAPI: true}); + InspectorTest.log('Evaluating $_ in 1'); + InspectorTest.logMessage(await session1.Protocol.Runtime.evaluate({expression: '$_', includeCommandLineAPI: true})); + InspectorTest.log('Evaluating $_ in 2'); + InspectorTest.logMessage(await session2.Protocol.Runtime.evaluate({expression: '$_', includeCommandLineAPI: true})); + + InspectorTest.log('Setting $_ in 2'); + await session2.Protocol.Runtime.evaluate({expression: '17', objectGroup: 'console', includeCommandLineAPI: true}); + InspectorTest.log('Evaluating $_ in 1'); + InspectorTest.logMessage(await session1.Protocol.Runtime.evaluate({expression: '$_', includeCommandLineAPI: true})); + InspectorTest.log('Evaluating $_ in 2'); + InspectorTest.logMessage(await session2.Protocol.Runtime.evaluate({expression: '$_', includeCommandLineAPI: true})); + + InspectorTest.log('Inspecting in 1'); + await session1.Protocol.Runtime.evaluate({expression: 'var inspect1=inspect; inspect(42)', includeCommandLineAPI: true}); + InspectorTest.log('Inspecting in 1 through variable'); + await session1.Protocol.Runtime.evaluate({expression: 'inspect1(42)', includeCommandLineAPI: true}); + InspectorTest.log('Inspecting in 2'); + await session2.Protocol.Runtime.evaluate({expression: 'var inspect2=inspect; inspect(17)', includeCommandLineAPI: true}); + InspectorTest.log('Inspecting in 2 through variable'); + await session2.Protocol.Runtime.evaluate({expression: 'inspect2(17)', includeCommandLineAPI: true}); + InspectorTest.log('Inspecting in 2 through variable from 1'); + await session2.Protocol.Runtime.evaluate({expression: 'inspect1(42)', includeCommandLineAPI: true}); + + InspectorTest.log('Disconnecting 1'); + session1.disconnect(); + + InspectorTest.log('Evaluating $0 in 2'); + InspectorTest.logMessage(await session2.Protocol.Runtime.evaluate({expression: '$0', includeCommandLineAPI: true})); + InspectorTest.log('Evaluating $_ in 2'); + InspectorTest.logMessage(await session2.Protocol.Runtime.evaluate({expression: '$_', includeCommandLineAPI: true})); + InspectorTest.log('Inspecting in 2'); + await session2.Protocol.Runtime.evaluate({expression: 'inspect(17)', includeCommandLineAPI: true}); + InspectorTest.log('Inspecting in 2 through variable from 1'); + await session2.Protocol.Runtime.evaluate({expression: 'inspect1(42)', includeCommandLineAPI: true}); + InspectorTest.log('Inspecting in 2 through variable'); + await session2.Protocol.Runtime.evaluate({expression: 'inspect2(17)', includeCommandLineAPI: true}); + + InspectorTest.completeTest(); +})();
diff --git a/src/v8/test/inspector/sessions/runtime-console-api-called-expected.txt b/src/v8/test/inspector/sessions/runtime-console-api-called-expected.txt new file mode 100644 index 0000000..0f679fa --- /dev/null +++ b/src/v8/test/inspector/sessions/runtime-console-api-called-expected.txt
@@ -0,0 +1,217 @@ +Tests that all sessions get console api notifications. +Error in 2 +From session 1 +{ + method : Runtime.consoleAPICalled + params : { + args : [ + [0] : { + description : 1 + type : number + value : 1 + } + ] + executionContextId : <executionContextId> + stackTrace : { + callFrames : [ + [0] : { + columnNumber : 8 + functionName : + lineNumber : 0 + scriptId : <scriptId> + url : + } + ] + } + timestamp : <timestamp> + type : error + } +} +From session 2 +{ + method : Runtime.consoleAPICalled + params : { + args : [ + [0] : { + description : 1 + type : number + value : 1 + } + ] + executionContextId : <executionContextId> + stackTrace : { + callFrames : [ + [0] : { + columnNumber : 8 + functionName : + lineNumber : 0 + scriptId : <scriptId> + url : + } + ] + } + timestamp : <timestamp> + type : error + } +} +Logging in 1 +From session 1 +{ + method : Runtime.consoleAPICalled + params : { + args : [ + [0] : { + description : 2 + type : number + value : 2 + } + ] + executionContextId : <executionContextId> + stackTrace : { + callFrames : [ + [0] : { + columnNumber : 8 + functionName : + lineNumber : 0 + scriptId : <scriptId> + url : + } + ] + } + timestamp : <timestamp> + type : log + } +} +From session 2 +{ + method : Runtime.consoleAPICalled + params : { + args : [ + [0] : { + description : 2 + type : number + value : 2 + } + ] + executionContextId : <executionContextId> + stackTrace : { + callFrames : [ + [0] : { + columnNumber : 8 + functionName : + lineNumber : 0 + scriptId : <scriptId> + url : + } + ] + } + timestamp : <timestamp> + type : log + } +} +Error in setTimeout 1 +From session 1 +{ + method : Runtime.consoleAPICalled + params : { + args : [ + [0] : { + type : string + value : a + } + ] + executionContextId : <executionContextId> + stackTrace : { + callFrames : [ + [0] : { + columnNumber : 25 + functionName : setTimeout + lineNumber : 0 + scriptId : <scriptId> + url : + } + ] + } + timestamp : <timestamp> + type : error + } +} +From session 2 +{ + method : Runtime.consoleAPICalled + params : { + args : [ + [0] : { + type : string + value : a + } + ] + executionContextId : <executionContextId> + stackTrace : { + callFrames : [ + [0] : { + columnNumber : 25 + functionName : setTimeout + lineNumber : 0 + scriptId : <scriptId> + url : + } + ] + } + timestamp : <timestamp> + type : error + } +} +Logging in setTimeout 2 +From session 1 +{ + method : Runtime.consoleAPICalled + params : { + args : [ + [0] : { + type : string + value : b + } + ] + executionContextId : <executionContextId> + stackTrace : { + callFrames : [ + [0] : { + columnNumber : 25 + functionName : setTimeout + lineNumber : 0 + scriptId : <scriptId> + url : + } + ] + } + timestamp : <timestamp> + type : log + } +} +From session 2 +{ + method : Runtime.consoleAPICalled + params : { + args : [ + [0] : { + type : string + value : b + } + ] + executionContextId : <executionContextId> + stackTrace : { + callFrames : [ + [0] : { + columnNumber : 25 + functionName : setTimeout + lineNumber : 0 + scriptId : <scriptId> + url : + } + ] + } + timestamp : <timestamp> + type : log + } +}
diff --git a/src/v8/test/inspector/sessions/runtime-console-api-called.js b/src/v8/test/inspector/sessions/runtime-console-api-called.js new file mode 100644 index 0000000..fc9d79b --- /dev/null +++ b/src/v8/test/inspector/sessions/runtime-console-api-called.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. + +InspectorTest.log('Tests that all sessions get console api notifications.'); + +function connect(contextGroup, num) { + var session = contextGroup.connect(); + session.Protocol.Runtime.onConsoleAPICalled(message => { + InspectorTest.log('From session ' + num); + InspectorTest.logMessage(message); + }); + return session; +} + +(async function test() { + var contextGroup = new InspectorTest.ContextGroup(); + var session1 = connect(contextGroup, 1); + var session2 = connect(contextGroup, 2); + await session1.Protocol.Runtime.enable(); + await session2.Protocol.Runtime.enable(); + + InspectorTest.log('Error in 2'); + await session2.Protocol.Runtime.evaluate({expression: 'console.error(1)'}); + + InspectorTest.log('Logging in 1'); + await session1.Protocol.Runtime.evaluate({expression: 'console.log(2)'}); + + InspectorTest.log('Error in setTimeout 1'); + await session1.Protocol.Runtime.evaluate({expression: 'setTimeout(() => console.error("a"), 0)'}); + await InspectorTest.waitForPendingTasks(); + + InspectorTest.log('Logging in setTimeout 2'); + await session2.Protocol.Runtime.evaluate({expression: 'setTimeout(() => console.log("b"), 0)'}); + await InspectorTest.waitForPendingTasks(); + + InspectorTest.completeTest(); +})();
diff --git a/src/v8/test/inspector/sessions/runtime-evaluate-exception-expected.txt b/src/v8/test/inspector/sessions/runtime-evaluate-exception-expected.txt new file mode 100644 index 0000000..e84c770 --- /dev/null +++ b/src/v8/test/inspector/sessions/runtime-evaluate-exception-expected.txt
@@ -0,0 +1,277 @@ +Tests that all sessions get exception notifications. +Throwing in 2 +Throwing in 1 +Throwing in setTimeout 1 +From session 1 +{ + method : Runtime.exceptionThrown + params : { + exceptionDetails : { + columnNumber : 19 + exception : { + type : string + value : error3 + } + exceptionId : <exceptionId> + executionContextId : <executionContextId> + lineNumber : 0 + stackTrace : { + callFrames : [ + [0] : { + columnNumber : 19 + functionName : setTimeout + lineNumber : 0 + scriptId : <scriptId> + url : + } + ] + } + text : Uncaught error3 + } + timestamp : <timestamp> + } +} +From session 2 +{ + method : Runtime.exceptionThrown + params : { + exceptionDetails : { + columnNumber : 19 + exception : { + type : string + value : error3 + } + exceptionId : <exceptionId> + executionContextId : <executionContextId> + lineNumber : 0 + stackTrace : { + callFrames : [ + [0] : { + columnNumber : 19 + functionName : setTimeout + lineNumber : 0 + scriptId : <scriptId> + url : + } + ] + } + text : Uncaught error3 + } + timestamp : <timestamp> + } +} +Throwing in setTimeout 2 +From session 1 +{ + method : Runtime.exceptionThrown + params : { + exceptionDetails : { + columnNumber : 19 + exception : { + type : string + value : error4 + } + exceptionId : <exceptionId> + executionContextId : <executionContextId> + lineNumber : 0 + stackTrace : { + callFrames : [ + [0] : { + columnNumber : 19 + functionName : setTimeout + lineNumber : 0 + scriptId : <scriptId> + url : + } + ] + } + text : Uncaught error4 + } + timestamp : <timestamp> + } +} +From session 2 +{ + method : Runtime.exceptionThrown + params : { + exceptionDetails : { + columnNumber : 19 + exception : { + type : string + value : error4 + } + exceptionId : <exceptionId> + executionContextId : <executionContextId> + lineNumber : 0 + stackTrace : { + callFrames : [ + [0] : { + columnNumber : 19 + functionName : setTimeout + lineNumber : 0 + scriptId : <scriptId> + url : + } + ] + } + text : Uncaught error4 + } + timestamp : <timestamp> + } +} +Rejecting in 2 +From session 1 +{ + method : Runtime.exceptionThrown + params : { + exceptionDetails : { + columnNumber : 40 + exception : { + type : string + value : error5 + } + exceptionId : <exceptionId> + executionContextId : <executionContextId> + lineNumber : 0 + stackTrace : { + callFrames : [ + [0] : { + columnNumber : 40 + functionName : setTimeout + lineNumber : 0 + scriptId : <scriptId> + url : + } + ] + } + text : Uncaught error5 + } + timestamp : <timestamp> + } +} +From session 2 +{ + method : Runtime.exceptionThrown + params : { + exceptionDetails : { + columnNumber : 40 + exception : { + type : string + value : error5 + } + exceptionId : <exceptionId> + executionContextId : <executionContextId> + lineNumber : 0 + stackTrace : { + callFrames : [ + [0] : { + columnNumber : 40 + functionName : setTimeout + lineNumber : 0 + scriptId : <scriptId> + url : + } + ] + } + text : Uncaught error5 + } + timestamp : <timestamp> + } +} +Revoking in 2 +From session 1 +{ + method : Runtime.exceptionRevoked + params : { + exceptionId : <exceptionId> + reason : Handler added to rejected promise + } +} +id matching: true +From session 2 +{ + method : Runtime.exceptionRevoked + params : { + exceptionId : <exceptionId> + reason : Handler added to rejected promise + } +} +id matching: true +Rejecting in 1 +From session 1 +{ + method : Runtime.exceptionThrown + params : { + exceptionDetails : { + columnNumber : 40 + exception : { + type : string + value : error6 + } + exceptionId : <exceptionId> + executionContextId : <executionContextId> + lineNumber : 0 + stackTrace : { + callFrames : [ + [0] : { + columnNumber : 40 + functionName : setTimeout + lineNumber : 0 + scriptId : <scriptId> + url : + } + ] + } + text : Uncaught error6 + } + timestamp : <timestamp> + } +} +From session 2 +{ + method : Runtime.exceptionThrown + params : { + exceptionDetails : { + columnNumber : 40 + exception : { + type : string + value : error6 + } + exceptionId : <exceptionId> + executionContextId : <executionContextId> + lineNumber : 0 + stackTrace : { + callFrames : [ + [0] : { + columnNumber : 40 + functionName : setTimeout + lineNumber : 0 + scriptId : <scriptId> + url : + } + ] + } + text : Uncaught error6 + } + timestamp : <timestamp> + } +} +Revoking in 1 +From session 1 +{ + method : Runtime.exceptionRevoked + params : { + exceptionId : <exceptionId> + reason : Handler added to rejected promise + } +} +id matching: true +From session 2 +{ + method : Runtime.exceptionRevoked + params : { + exceptionId : <exceptionId> + reason : Handler added to rejected promise + } +} +id matching: true
diff --git a/src/v8/test/inspector/sessions/runtime-evaluate-exception.js b/src/v8/test/inspector/sessions/runtime-evaluate-exception.js new file mode 100644 index 0000000..8f3520f --- /dev/null +++ b/src/v8/test/inspector/sessions/runtime-evaluate-exception.js
@@ -0,0 +1,59 @@ +// 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('Tests that all sessions get exception notifications.'); + +function connect(contextGroup, num) { + var session = contextGroup.connect(); + var exceptionId; + session.Protocol.Runtime.onExceptionThrown(message => { + InspectorTest.log('From session ' + num); + InspectorTest.logMessage(message); + exceptionId = message.params.exceptionDetails.exceptionId; + }); + session.Protocol.Runtime.onExceptionRevoked(message => { + InspectorTest.log('From session ' + num); + InspectorTest.logMessage(message); + InspectorTest.log('id matching: ' + (message.params.exceptionId === exceptionId)); + }); + return session; +} + +(async function test() { + var contextGroup = new InspectorTest.ContextGroup(); + var session1 = connect(contextGroup, 1); + var session2 = connect(contextGroup, 2); + await session1.Protocol.Runtime.enable(); + await session2.Protocol.Runtime.enable(); + + InspectorTest.log('Throwing in 2'); + await session2.Protocol.Runtime.evaluate({expression: 'throw "error1";'}); + + InspectorTest.log('Throwing in 1'); + await session1.Protocol.Runtime.evaluate({expression: 'throw "error2";'}); + + InspectorTest.log('Throwing in setTimeout 1'); + await session1.Protocol.Runtime.evaluate({expression: 'setTimeout(() => { throw "error3"; }, 0)'}); + await InspectorTest.waitForPendingTasks(); + + InspectorTest.log('Throwing in setTimeout 2'); + await session2.Protocol.Runtime.evaluate({expression: 'setTimeout(() => { throw "error4"; }, 0)'}); + await InspectorTest.waitForPendingTasks(); + + InspectorTest.log('Rejecting in 2'); + await session2.Protocol.Runtime.evaluate({expression: 'var p2; setTimeout(() => { p2 = Promise.reject("error5") }, 0)'}); + await InspectorTest.waitForPendingTasks(); + InspectorTest.log('Revoking in 2'); + await session2.Protocol.Runtime.evaluate({expression: 'setTimeout(() => { p2.catch() }, 0);'}); + await InspectorTest.waitForPendingTasks(); + + InspectorTest.log('Rejecting in 1'); + await session1.Protocol.Runtime.evaluate({expression: 'var p1; setTimeout(() => { p1 = Promise.reject("error6")} , 0)'}); + await InspectorTest.waitForPendingTasks(); + InspectorTest.log('Revoking in 1'); + await session1.Protocol.Runtime.evaluate({expression: 'setTimeout(() => { p1.catch() }, 0);'}); + await InspectorTest.waitForPendingTasks(); + + InspectorTest.completeTest(); +})();
diff --git a/src/v8/test/inspector/sessions/runtime-evaluate-expected.txt b/src/v8/test/inspector/sessions/runtime-evaluate-expected.txt new file mode 100644 index 0000000..f201ff6 --- /dev/null +++ b/src/v8/test/inspector/sessions/runtime-evaluate-expected.txt
@@ -0,0 +1,25 @@ +Tests that multiple sessions share the context. +Assigning in 1 +Evaluating in 2 +{ + id : <messageId> + result : { + result : { + description : 42 + type : number + value : 42 + } + } +} +Awaiting in 1 +Resolving in 2 +Should resolve in 1 +{ + id : <messageId> + result : { + result : { + type : string + value : foo + } + } +}
diff --git a/src/v8/test/inspector/sessions/runtime-evaluate.js b/src/v8/test/inspector/sessions/runtime-evaluate.js new file mode 100644 index 0000000..72ca178 --- /dev/null +++ b/src/v8/test/inspector/sessions/runtime-evaluate.js
@@ -0,0 +1,25 @@ +// 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('Tests that multiple sessions share the context.'); + +(async function test() { + var contextGroup = new InspectorTest.ContextGroup(); + var session1 = contextGroup.connect(); + var session2 = contextGroup.connect(); + + InspectorTest.log('Assigning in 1'); + await session1.Protocol.Runtime.evaluate({expression: 'var a = 42;'}); + InspectorTest.log('Evaluating in 2'); + InspectorTest.logMessage(await session2.Protocol.Runtime.evaluate({expression: 'a'})); + + InspectorTest.log('Awaiting in 1'); + var promise = session1.Protocol.Runtime.evaluate({expression: 'var cb; new Promise(f => cb = f)', awaitPromise: true}); + InspectorTest.log('Resolving in 2'); + await session2.Protocol.Runtime.evaluate({expression: 'cb("foo")'}); + InspectorTest.log('Should resolve in 1'); + InspectorTest.logMessage(await promise); + + InspectorTest.completeTest(); +})();
diff --git a/src/v8/test/inspector/sessions/runtime-remote-object-expected.txt b/src/v8/test/inspector/sessions/runtime-remote-object-expected.txt new file mode 100644 index 0000000..a8d0ec0 --- /dev/null +++ b/src/v8/test/inspector/sessions/runtime-remote-object-expected.txt
@@ -0,0 +1,103 @@ +Tests that multiple sessions do not interfere with each other's remote objects. +Evaluating in 1 +Evaluating in 2 +Retrieving properties in 2 +{ + id : <messageId> + result : { + result : [ + [0] : { + configurable : true + enumerable : true + isOwn : true + name : a + value : { + description : 17 + type : number + value : 17 + } + writable : true + } + [1] : { + configurable : true + enumerable : false + isOwn : true + name : __proto__ + value : { + className : Object + description : Object + objectId : <objectId> + type : object + } + writable : true + } + ] + } +} +Retrieving properties in 1 +{ + id : <messageId> + result : { + result : [ + [0] : { + configurable : true + enumerable : true + isOwn : true + name : a + value : { + description : 42 + type : number + value : 42 + } + writable : true + } + [1] : { + configurable : true + enumerable : false + isOwn : true + name : __proto__ + value : { + className : Object + description : Object + objectId : <objectId> + type : object + } + writable : true + } + ] + } +} +Disconnecting 2 +Retrieving properties in 1 +{ + id : <messageId> + result : { + result : [ + [0] : { + configurable : true + enumerable : true + isOwn : true + name : a + value : { + description : 42 + type : number + value : 42 + } + writable : true + } + [1] : { + configurable : true + enumerable : false + isOwn : true + name : __proto__ + value : { + className : Object + description : Object + objectId : <objectId> + type : object + } + writable : true + } + ] + } +}
diff --git a/src/v8/test/inspector/sessions/runtime-remote-object.js b/src/v8/test/inspector/sessions/runtime-remote-object.js new file mode 100644 index 0000000..aaaccb4 --- /dev/null +++ b/src/v8/test/inspector/sessions/runtime-remote-object.js
@@ -0,0 +1,30 @@ +// 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('Tests that multiple sessions do not interfere with each other\'s remote objects.'); + +(async function test() { + var contextGroup = new InspectorTest.ContextGroup(); + var session1 = contextGroup.connect(); + var session2 = contextGroup.connect(); + + InspectorTest.log('Evaluating in 1'); + var result1 = await session1.Protocol.Runtime.evaluate({expression: '({a: 42})'}); + InspectorTest.log('Evaluating in 2'); + var result2 = await session2.Protocol.Runtime.evaluate({expression: '({a: 17})'}); + + await print(2, session2, result2); + await print(1, session1, result1); + InspectorTest.log('Disconnecting 2'); + session2.disconnect(); + await print(1, session1, result1); + + InspectorTest.completeTest(); +})(); + +async function print(num, session, message) { + InspectorTest.log('Retrieving properties in ' + num); + var objectId = message.result.result.objectId; + InspectorTest.logMessage(await session.Protocol.Runtime.getProperties({objectId, ownProperties: true})); +}
diff --git a/src/v8/test/inspector/task-runner.cc b/src/v8/test/inspector/task-runner.cc new file mode 100644 index 0000000..921317d --- /dev/null +++ b/src/v8/test/inspector/task-runner.cc
@@ -0,0 +1,112 @@ +// 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. + +#include "test/inspector/task-runner.h" + +#if !defined(_WIN32) && !defined(_WIN64) +#include <unistd.h> // NOLINT +#endif // !defined(_WIN32) && !defined(_WIN64) + +namespace { + +void ReportUncaughtException(v8::Isolate* isolate, + const v8::TryCatch& try_catch) { + CHECK(try_catch.HasCaught()); + v8::HandleScope handle_scope(isolate); + std::string message = + *v8::String::Utf8Value(isolate, try_catch.Message()->Get()); + int line = try_catch.Message() + ->GetLineNumber(isolate->GetCurrentContext()) + .FromJust(); + std::string source_line = *v8::String::Utf8Value( + isolate, try_catch.Message() + ->GetSourceLine(isolate->GetCurrentContext()) + .ToLocalChecked()); + fprintf(stderr, "Unhandle exception: %s @%s[%d]\n", message.data(), + source_line.data(), line); +} + +} // namespace + +TaskRunner::TaskRunner(IsolateData::SetupGlobalTasks setup_global_tasks, + bool catch_exceptions, + v8::base::Semaphore* ready_semaphore, + v8::StartupData* startup_data, bool with_inspector) + : Thread(Options("Task Runner")), + setup_global_tasks_(std::move(setup_global_tasks)), + startup_data_(startup_data), + with_inspector_(with_inspector), + catch_exceptions_(catch_exceptions), + ready_semaphore_(ready_semaphore), + data_(nullptr), + process_queue_semaphore_(0), + nested_loop_count_(0) { + Start(); +} + +TaskRunner::~TaskRunner() { Join(); } + +void TaskRunner::Run() { + data_.reset(new IsolateData(this, std::move(setup_global_tasks_), + startup_data_, with_inspector_)); + if (ready_semaphore_) ready_semaphore_->Signal(); + RunMessageLoop(false); +} + +void TaskRunner::RunMessageLoop(bool only_protocol) { + int loop_number = ++nested_loop_count_; + while (nested_loop_count_ == loop_number && !is_terminated_.Value()) { + TaskRunner::Task* task = GetNext(only_protocol); + if (!task) return; + v8::Isolate::Scope isolate_scope(isolate()); + if (catch_exceptions_) { + v8::TryCatch try_catch(isolate()); + task->Run(data_.get()); + delete task; + if (try_catch.HasCaught()) { + ReportUncaughtException(isolate(), try_catch); + fflush(stdout); + fflush(stderr); + _exit(0); + } + } else { + task->Run(data_.get()); + delete task; + } + } +} + +void TaskRunner::QuitMessageLoop() { + DCHECK_LT(0, nested_loop_count_); + --nested_loop_count_; +} + +void TaskRunner::Append(Task* task) { + queue_.Enqueue(task); + process_queue_semaphore_.Signal(); +} + +void TaskRunner::Terminate() { + is_terminated_.Increment(1); + process_queue_semaphore_.Signal(); +} + +TaskRunner::Task* TaskRunner::GetNext(bool only_protocol) { + for (;;) { + if (is_terminated_.Value()) return nullptr; + if (only_protocol) { + Task* task = nullptr; + if (queue_.Dequeue(&task)) { + if (task->is_priority_task()) return task; + deffered_queue_.Enqueue(task); + } + } else { + Task* task = nullptr; + if (deffered_queue_.Dequeue(&task)) return task; + if (queue_.Dequeue(&task)) return task; + } + process_queue_semaphore_.Wait(); + } + return nullptr; +}
diff --git a/src/v8/test/inspector/task-runner.h b/src/v8/test/inspector/task-runner.h new file mode 100644 index 0000000..353c783 --- /dev/null +++ b/src/v8/test/inspector/task-runner.h
@@ -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. + +#ifndef V8_TEST_INSPECTOR_PROTOCOL_TASK_RUNNER_H_ +#define V8_TEST_INSPECTOR_PROTOCOL_TASK_RUNNER_H_ + +#include <map> + +#include "include/v8-inspector.h" +#include "include/v8-platform.h" +#include "include/v8.h" +#include "src/base/atomic-utils.h" +#include "src/base/macros.h" +#include "src/base/platform/platform.h" +#include "src/locked-queue-inl.h" +#include "src/vector.h" +#include "test/inspector/isolate-data.h" + +class TaskRunner : public v8::base::Thread { + public: + class Task { + public: + virtual ~Task() {} + virtual bool is_priority_task() = 0; + virtual void Run(IsolateData* data) = 0; + }; + + TaskRunner(IsolateData::SetupGlobalTasks setup_global_tasks, + bool catch_exceptions, v8::base::Semaphore* ready_semaphore, + v8::StartupData* startup_data, bool with_inspector); + virtual ~TaskRunner(); + IsolateData* data() const { return data_.get(); } + + // Thread implementation. + void Run() override; + + // Should be called from the same thread and only from task. + void RunMessageLoop(bool only_protocol); + void QuitMessageLoop(); + + // TaskRunner takes ownership. + void Append(Task* task); + + void Terminate(); + + private: + Task* GetNext(bool only_protocol); + v8::Isolate* isolate() const { return data_->isolate(); } + + IsolateData::SetupGlobalTasks setup_global_tasks_; + v8::StartupData* startup_data_; + bool with_inspector_; + bool catch_exceptions_; + v8::base::Semaphore* ready_semaphore_; + std::unique_ptr<IsolateData> data_; + + // deferred_queue_ combined with queue_ (in this order) have all tasks in the + // correct order. Sometimes we skip non-protocol tasks by moving them from + // queue_ to deferred_queue_. + v8::internal::LockedQueue<Task*> queue_; + v8::internal::LockedQueue<Task*> deffered_queue_; + v8::base::Semaphore process_queue_semaphore_; + + int nested_loop_count_; + + v8::base::AtomicNumber<int> is_terminated_; + + DISALLOW_COPY_AND_ASSIGN(TaskRunner); +}; + +#endif // V8_TEST_INSPECTOR_PROTOCOL_TASK_RUNNER_H_
diff --git a/src/v8/test/inspector/testcfg.py b/src/v8/test/inspector/testcfg.py new file mode 100644 index 0000000..9c943d9 --- /dev/null +++ b/src/v8/test/inspector/testcfg.py
@@ -0,0 +1,113 @@ +# 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. + +import itertools +import os +import re +import shlex + +from testrunner.local import testsuite +from testrunner.local import utils +from testrunner.objects import testcase + +FLAGS_PATTERN = re.compile(r"//\s+Flags:(.*)") +PROTOCOL_TEST_JS = "protocol-test.js" +EXPECTED_SUFFIX = "-expected.txt" +RESOURCES_FOLDER = "resources" + +class InspectorProtocolTestSuite(testsuite.TestSuite): + + def __init__(self, name, root): + super(InspectorProtocolTestSuite, self).__init__(name, root) + + def ListTests(self, context): + tests = [] + for dirname, dirs, files in os.walk(os.path.join(self.root), followlinks=True): + for dotted in [x for x in dirs if x.startswith('.')]: + dirs.remove(dotted) + if dirname.endswith(os.path.sep + RESOURCES_FOLDER): + continue + dirs.sort() + files.sort() + for filename in files: + if filename.endswith(".js") and filename != PROTOCOL_TEST_JS: + fullpath = os.path.join(dirname, filename) + relpath = fullpath[len(self.root) + 1 : -3] + testname = relpath.replace(os.path.sep, "/") + test = testcase.TestCase(self, testname) + tests.append(test) + return tests + + def GetFlagsForTestCase(self, testcase, context): + source = self.GetSourceForTest(testcase) + flags = [] + context.mode_flags + flags_match = re.findall(FLAGS_PATTERN, source) + for match in flags_match: + flags += shlex.split(match.strip()) + testname = testcase.path.split(os.path.sep)[-1] + testfilename = os.path.join(self.root, testcase.path + self.suffix()) + protocoltestfilename = os.path.join(self.root, PROTOCOL_TEST_JS) + return testcase.flags + flags + [ protocoltestfilename, testfilename ] + + def GetSourceForTest(self, testcase): + filename = os.path.join(self.root, testcase.path + self.suffix()) + with open(filename) as f: + return f.read() + + def shell(self): + return "inspector-test" + + def _IgnoreLine(self, string): + """Ignore empty lines, valgrind output and Android output.""" + if not string: return True + return (string.startswith("==") or string.startswith("**") or + string.startswith("ANDROID") or + # FIXME(machenbach): The test driver shouldn't try to use slow + # asserts if they weren't compiled. This fails in optdebug=2. + string == "Warning: unknown flag --enable-slow-asserts." or + string == "Try --help for options") + + def IsFailureOutput(self, testcase): + file_name = os.path.join(self.root, testcase.path) + EXPECTED_SUFFIX + with file(file_name, "r") as expected: + expected_lines = expected.readlines() + + def ExpIterator(): + for line in expected_lines: + if not line.strip(): continue + yield line.strip() + + def ActIterator(lines): + for line in lines: + if self._IgnoreLine(line.strip()): continue + yield line.strip() + + def ActBlockIterator(): + """Iterates over blocks of actual output lines.""" + lines = testcase.output.stdout.splitlines() + start_index = 0 + found_eqeq = False + for index, line in enumerate(lines): + # If a stress test separator is found: + if line.startswith("=="): + # Iterate over all lines before a separator except the first. + if not found_eqeq: + found_eqeq = True + else: + yield ActIterator(lines[start_index:index]) + # The next block of output lines starts after the separator. + start_index = index + 1 + # Iterate over complete output if no separator was found. + if not found_eqeq: + yield ActIterator(lines) + + for act_iterator in ActBlockIterator(): + for (expected, actual) in itertools.izip_longest( + ExpIterator(), act_iterator, fillvalue=''): + if expected != actual: + return True + return False + +def GetSuite(name, root): + return InspectorProtocolTestSuite(name, root)
diff --git a/src/v8/test/inspector/type-profiler/type-profile-disable-expected.txt b/src/v8/test/inspector/type-profiler/type-profile-disable-expected.txt new file mode 100644 index 0000000..b70acba --- /dev/null +++ b/src/v8/test/inspector/type-profiler/type-profile-disable-expected.txt
@@ -0,0 +1,9 @@ +Turn Profiler.startTypeProfile on and off. + +function g(/*Object*/a, /*Array*/b, /*null*/c) { + return 'bye'; +/*string*/}; +g({}, [], null); + +[ +] \ No newline at end of file
diff --git a/src/v8/test/inspector/type-profiler/type-profile-disable.js b/src/v8/test/inspector/type-profiler/type-profile-disable.js new file mode 100644 index 0000000..38a3c6f --- /dev/null +++ b/src/v8/test/inspector/type-profiler/type-profile-disable.js
@@ -0,0 +1,47 @@ +// 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: --type-profile + +const source = + ` +function g(a, b, c) { + return 'bye'; +}; +g({}, [], null); +`; + +let {session, contextGroup, Protocol} = InspectorTest.start("Turn " + + "Profiler.startTypeProfile on and off."); + +(async function testTypeProfile() { + Protocol.Runtime.enable(); + let {result: {scriptId}} = await Protocol.Runtime.compileScript({ + expression: source, + sourceURL: arguments.callee.name, persistScript: true + }); + await Protocol.Profiler.enable(); + // Start, run, take. + await Protocol.Profiler.startTypeProfile(); + Protocol.Runtime.runScript({scriptId}); + + let typeProfiles = await Protocol.Profiler.takeTypeProfile(); + session.logTypeProfile(typeProfiles.result.result[0], + source); + + // This should delete all data. + Protocol.Profiler.stopTypeProfile(); + + await Protocol.Profiler.startTypeProfile(); + typeProfiles = await Protocol.Profiler.takeTypeProfile(); + + // Should be empty because no code was run since start. + InspectorTest.logMessage(typeProfiles.result.result); + + Protocol.Profiler.stopTypeProfile(); + + Protocol.Profiler.disable(); + await Protocol.Runtime.disable(); + InspectorTest.completeTest(); +})();
diff --git a/src/v8/test/inspector/type-profiler/type-profile-expected.txt b/src/v8/test/inspector/type-profiler/type-profile-expected.txt new file mode 100644 index 0000000..8001d82 --- /dev/null +++ b/src/v8/test/inspector/type-profiler/type-profile-expected.txt
@@ -0,0 +1,8 @@ +Test collecting type profile data with Profiler.takeTypeProfile. + +function f(/*Object, number, undefined*/a, /*Array, number, null*/b, /*boolean, Object, symbol*/c) { + return 'bye'; +/*string*/}; +f({}, [], true); +f(3, 2.3, {a: 42}); +f(undefined, null, Symbol('hello'));/*string*/
diff --git a/src/v8/test/inspector/type-profiler/type-profile-start-stop-expected.txt b/src/v8/test/inspector/type-profiler/type-profile-start-stop-expected.txt new file mode 100644 index 0000000..0db7882 --- /dev/null +++ b/src/v8/test/inspector/type-profiler/type-profile-start-stop-expected.txt
@@ -0,0 +1,49 @@ +Turn Profiler.startTypeProfile on and off. + +Running test: testTypeProfile + +function g(/*Object*/a, /*Array*/b, /*null*/c) { + return 'first'; +/*string*/}; +g({}, [], null); + + +Running test: testTypeProfileFromDifferentSource + +function f(/*null*/a) { + return 'second'; +/*string*/}; +f(null); + + +Running test: testStopTypeProfileDeletesFeedback +[ +] + +Running test: testTypeProfileWithoutStartingItFirst +Type profile has not been started. + +Running test: testTypeProfileAfterStoppingIt +Type profile has not been started. + +Running test: testStartTypeProfileAfterRunning +{ + id : <messageId> + result : { + result : [ + ] + } +} + +Running test: testTypeProfileForTwoSources + +function g(/*Object*/a, /*Array*/b, /*null*/c) { + return 'first'; +/*string*/}; +g({}, [], null); + + +function f(/*null*/a) { + return 'second'; +/*string*/}; +f(null);
diff --git a/src/v8/test/inspector/type-profiler/type-profile-start-stop.js b/src/v8/test/inspector/type-profiler/type-profile-start-stop.js new file mode 100644 index 0000000..dad9874 --- /dev/null +++ b/src/v8/test/inspector/type-profiler/type-profile-start-stop.js
@@ -0,0 +1,170 @@ +// 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: --type-profile + +const source1 = + ` +function g(a, b, c) { + return 'first'; +}; +g({}, [], null); +`; + +const source2 = + ` +function f(a) { + return 'second'; +}; +f(null); +`; + +let {session, contextGroup, Protocol} = InspectorTest.start("Turn " + + "Profiler.startTypeProfile on and off."); + +InspectorTest.runAsyncTestSuite([ + async function testTypeProfile() { + Protocol.Runtime.enable(); + let {result: {scriptId}} = await Protocol.Runtime.compileScript({ + expression: source1, + sourceURL: arguments.callee.name, persistScript: true + }); + await Protocol.Profiler.enable(); + + // Start, run, take. + await Protocol.Profiler.startTypeProfile(); + Protocol.Runtime.runScript({scriptId}); + + let typeProfiles = await Protocol.Profiler.takeTypeProfile(); + await session.logTypeProfile(typeProfiles.result.result[0], + source1); + + Protocol.Profiler.stopTypeProfile(); + Protocol.Profiler.disable(); + await Protocol.Runtime.disable(); + }, + async function testTypeProfileFromDifferentSource() { + Protocol.Runtime.enable(); + let {result: {scriptId}} = await Protocol.Runtime.compileScript({ + expression: source2, + sourceURL: arguments.callee.name, persistScript: true + }); + await Protocol.Profiler.enable(); + + // Start, run different script, take. + await Protocol.Profiler.startTypeProfile(); + Protocol.Runtime.runScript({scriptId}); + + let typeProfiles = await Protocol.Profiler.takeTypeProfile(); + await session.logTypeProfile(typeProfiles.result.result[0], + source2); + + Protocol.Profiler.stopTypeProfile(); + Protocol.Profiler.disable(); + await Protocol.Runtime.disable(); + }, + async function testStopTypeProfileDeletesFeedback() { + Protocol.Runtime.enable(); + let {result: {scriptId}} = await Protocol.Runtime.compileScript({ + expression: source1, + sourceURL: arguments.callee.name, persistScript: true + }); + await Protocol.Profiler.enable(); + + // Start, run, stop. + await Protocol.Profiler.startTypeProfile(); + Protocol.Runtime.runScript({scriptId}); + await Protocol.Profiler.stopTypeProfile(); + + // Start, take. Should be empty, because no code was run. + await Protocol.Profiler.startTypeProfile(); + let typeProfiles = await Protocol.Profiler.takeTypeProfile(); + InspectorTest.logMessage(typeProfiles.result.result); + await Protocol.Profiler.stopTypeProfile(); + + Protocol.Profiler.disable(); + await Protocol.Runtime.disable(); + }, + async function testTypeProfileWithoutStartingItFirst() { + Protocol.Runtime.enable(); + let {result: {scriptId}} = await Protocol.Runtime.compileScript({ expression: source1, + sourceURL: arguments.callee.name, persistScript: true }); + Protocol.Runtime.runScript({ scriptId }); + await Protocol.Profiler.enable(); + + // This should return an error because type profile was never started. + let typeProfiles = await Protocol.Profiler.takeTypeProfile(); + InspectorTest.logObject(typeProfiles.error.message); + + Protocol.Profiler.disable(); + await Protocol.Runtime.disable(); + }, + async function testTypeProfileAfterStoppingIt() { + Protocol.Runtime.enable(); + let {result: {scriptId}} = await Protocol.Runtime.compileScript({ expression: source1, + sourceURL: arguments.callee.name, persistScript: true }); + Protocol.Runtime.runScript({ scriptId }); + await Protocol.Profiler.enable(); + await Protocol.Profiler.startTypeProfile(); + + // Make sure that this turns off type profile. + await Protocol.Profiler.stopTypeProfile(); + + // This should return an error because type profile was stopped. + let typeProfiles = await Protocol.Profiler.takeTypeProfile(); + InspectorTest.logObject(typeProfiles.error.message); + + Protocol.Profiler.disable(); + await Protocol.Runtime.disable(); + }, + async function testStartTypeProfileAfterRunning() { + Protocol.Runtime.enable(); + let {result: {scriptId}} = await Protocol.Runtime.compileScript({ + expression: source1, + sourceURL: arguments.callee.name, persistScript: true + }); + Protocol.Runtime.runScript({scriptId}); + + await Protocol.Profiler.enable(); + await Protocol.Profiler.startTypeProfile(); + + let typeProfiles = await Protocol.Profiler.takeTypeProfile(); + + // This should be empty because type profile was started after compilation. + // Only the outer script is annotated with return value "string" because + // that does not depend on runScript(). + InspectorTest.logMessage(typeProfiles); + + Protocol.Profiler.stopTypeProfile(); + Protocol.Profiler.disable(); + await Protocol.Runtime.disable(); + }, + async function testTypeProfileForTwoSources() { + Protocol.Runtime.enable(); + let {result: {scriptId: scriptId1}} = await Protocol.Runtime.compileScript({ + expression: source1, + sourceURL: arguments.callee.name, persistScript: true + }); + let {result: {scriptId: scriptId2}} = await Protocol.Runtime.compileScript({ + expression: source2, + sourceURL: arguments.callee.name, persistScript: true + }); + await Protocol.Profiler.enable(); + + // Start, run different script, take. + await Protocol.Profiler.startTypeProfile(); + Protocol.Runtime.runScript({scriptId: scriptId1}); + Protocol.Runtime.runScript({scriptId: scriptId2}); + + let typeProfiles = await Protocol.Profiler.takeTypeProfile(); + await session.logTypeProfile(typeProfiles.result.result[0], + source1); + await session.logTypeProfile(typeProfiles.result.result[1], + source2); + + Protocol.Profiler.stopTypeProfile(); + Protocol.Profiler.disable(); + await Protocol.Runtime.disable(); + } +]);
diff --git a/src/v8/test/inspector/type-profiler/type-profile-with-classes-expected.txt b/src/v8/test/inspector/type-profiler/type-profile-with-classes-expected.txt new file mode 100644 index 0000000..3c1cb36 --- /dev/null +++ b/src/v8/test/inspector/type-profiler/type-profile-with-classes-expected.txt
@@ -0,0 +1,15 @@ +Test collecting type profile data with Profiler.takeTypeProfile. + +function f(/*number*/n) { +/*undefined*/}; +f(5); +function g(/*Object, number*/a, /*Array, number*/b, /*Flower, Object*/c) { + return 'bye'; +/*string*/}; +/*undefined*/class Tree {}; +/*Flower*/class Flower extends Tree{}; +var f = new Flower(); +f.constructor = {}; +f.constructor.name = "Not a flower."; +g({}, [], f); +g(3, 2.3, {a: 42});/*string*/
diff --git a/src/v8/test/inspector/type-profiler/type-profile-with-classes.js b/src/v8/test/inspector/type-profiler/type-profile-with-classes.js new file mode 100644 index 0000000..b697ebf --- /dev/null +++ b/src/v8/test/inspector/type-profiler/type-profile-with-classes.js
@@ -0,0 +1,43 @@ +// 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: --type-profile + +const source = + ` +function f(n) { +}; +f(5); +function g(a, b, c) { + return 'bye'; +}; +class Tree {}; +class Flower extends Tree{}; +var f = new Flower(); +f.constructor = {}; +f.constructor.name = "Not a flower."; +g({}, [], f); +g(3, 2.3, {a: 42}); +`; + +let {session, contextGroup, Protocol} = InspectorTest.start("Test collecting type profile data with Profiler.takeTypeProfile."); + +(async function testTypeProfile(next) { + await Protocol.Profiler.enable(); + await Protocol.Profiler.startTypeProfile(); + + Protocol.Runtime.enable(); + let {result: {scriptId}} = await Protocol.Runtime.compileScript({ expression: source, + sourceURL: arguments.callee.name, persistScript: true }); + + Protocol.Runtime.runScript({ scriptId }); + + let typeProfiles = await Protocol.Profiler.takeTypeProfile(); + await session.logTypeProfile(typeProfiles.result.result[0], + source); + + Protocol.Profiler.disable(); + await Protocol.Runtime.disable(); + InspectorTest.completeTest(); +})();
diff --git a/src/v8/test/inspector/type-profiler/type-profile-with-to-string-tag-expected.txt b/src/v8/test/inspector/type-profiler/type-profile-with-to-string-tag-expected.txt new file mode 100644 index 0000000..fdba165 --- /dev/null +++ b/src/v8/test/inspector/type-profiler/type-profile-with-to-string-tag-expected.txt
@@ -0,0 +1,16 @@ +Test collecting type profile data with Profiler.takeTypeProfile. + +function g(/*Object, number*/a, /*Array, number*/b, /*Dog, Object*/c) { + return 'bye'; +/*string*/}; +/*undefined*/class Tree {}; +/*Flower*/class Flower extends Tree{}; +var f = new Flower(); +// We store the type when a variable is used. If a toStringTag is +// changes the type, we want to collect that changed feedback. +// This tests ensures that we collect that information rather than +// for example infer the types from the internal map, which wouldn't +// know about a toStringTag. +f[Symbol.toStringTag] = 'Dog'; +g({}, [], f); +g(3, 2.3, {a: 42});/*string*/
diff --git a/src/v8/test/inspector/type-profiler/type-profile-with-to-string-tag.js b/src/v8/test/inspector/type-profiler/type-profile-with-to-string-tag.js new file mode 100644 index 0000000..654f18a --- /dev/null +++ b/src/v8/test/inspector/type-profiler/type-profile-with-to-string-tag.js
@@ -0,0 +1,46 @@ +// 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: --type-profile + +const source = + ` +function g(a, b, c) { + return 'bye'; +}; +class Tree {}; +class Flower extends Tree{}; +var f = new Flower(); +// We store the type when a variable is used. If a toStringTag is +// changes the type, we want to collect that changed feedback. +// This tests ensures that we collect that information rather than +// for example infer the types from the internal map, which wouldn't +// know about a toStringTag. +f[Symbol.toStringTag] = 'Dog'; +g({}, [], f); +g(3, 2.3, {a: 42}); +`; + +let {session, contextGroup, Protocol} = InspectorTest.start("Test collecting " + + "type profile data with Profiler.takeTypeProfile."); + +(async function testTypeProfile() { + await Protocol.Profiler.enable(); + await Protocol.Profiler.startTypeProfile(); + + Protocol.Runtime.enable(); + let {result: {scriptId}} = await Protocol.Runtime.compileScript({ expression: source, + sourceURL: arguments.callee.name, persistScript: true }); + Protocol.Runtime.runScript({ scriptId }); + await Protocol.Profiler.startTypeProfile(); + + let typeProfiles = await Protocol.Profiler.takeTypeProfile(); + await session.logTypeProfile(typeProfiles.result.result[0], + source); + + Protocol.Profiler.stopTypeProfile(); + Protocol.Profiler.disable(); + await Protocol.Runtime.disable(); + InspectorTest.completeTest(); +})();
diff --git a/src/v8/test/inspector/type-profiler/type-profile.js b/src/v8/test/inspector/type-profiler/type-profile.js new file mode 100644 index 0000000..e912a4b --- /dev/null +++ b/src/v8/test/inspector/type-profiler/type-profile.js
@@ -0,0 +1,39 @@ +// 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: --type-profile + +const source = + ` +function f(a, b, c) { + return 'bye'; +}; +f({}, [], true); +f(3, 2.3, {a: 42}); +f(undefined, null, Symbol('hello')); +`; + +let {session, contextGroup, Protocol} = InspectorTest.start("Test collecting type profile data with Profiler.takeTypeProfile."); + +(async function testTypeProfile() { + await Protocol.Profiler.enable(); + await Protocol.Profiler.startTypeProfile(); + + Protocol.Runtime.enable(); + let {result: {scriptId}} = await Protocol.Runtime.compileScript({ + expression: source, + sourceURL: arguments.callee.name, + persistScript: true + }); + Protocol.Runtime.runScript({ scriptId }); + + let typeProfiles = await Protocol.Profiler.takeTypeProfile(); + await session.logTypeProfile(typeProfiles.result.result[0], + source); + + Protocol.Profiler.stoptTypeProfile(); + Protocol.Profiler.disable(); + await Protocol.Runtime.disable(); + InspectorTest.completeTest(); +})();