Upload Kmake

This commit is contained in:
Gorochu
2026-05-26 23:36:42 -07:00
parent ba051b2f74
commit 555ec72358
41615 changed files with 13344630 additions and 1 deletions

51
deps/v8/test/inspector/BUILD.gn vendored Normal file
View File

@ -0,0 +1,51 @@
# 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_source_set("inspector_test") {
sources = [
"frontend-channel.h",
"isolate-data.cc",
"isolate-data.h",
"task-runner.cc",
"task-runner.h",
"tasks.cc",
"tasks.h",
"utils.cc",
"utils.h",
]
configs = [ "../..:internal_config_base" ]
public_deps = [
"../..:v8",
"../..:v8_libbase",
"../..:v8_libplatform",
"../../src/inspector:inspector_test_headers",
]
}
v8_executable("inspector-test") {
testonly = true
sources = [ "inspector-test.cc" ]
configs = [
"../..:external_config",
"../..:internal_config_base",
]
deps = [
":inspector_test",
"//build/win:default_exe_manifest",
]
data_deps = [ "../../tools:v8_testrunner" ]
data = [ "./" ]
cflags = []
ldflags = []
}

17
deps/v8/test/inspector/DEPS vendored Normal file
View File

@ -0,0 +1,17 @@
include_rules = [
"-src",
"+src/base",
"+src/flags/flags.h",
"+src/heap/read-only-heap.h",
"+src/inspector/test-interface.h",
"+src/init/v8.h",
"+src/libplatform/default-platform.h",
"+src/utils",
]
specific_include_rules = {
"isolate-data\.cc": [
"+src/execution/isolate.h",
"+src/heap/heap.h",
],
}

11
deps/v8/test/inspector/DIR_METADATA vendored Normal file
View File

@ -0,0 +1,11 @@
# Metadata information for this directory.
#
# For more information on DIR_METADATA files, see:
# https://source.chromium.org/chromium/infra/infra/+/master:go/src/infra/tools/dirmd/README.md
#
# For the schema of this file, see Metadata message:
# https://source.chromium.org/chromium/infra/infra/+/master:go/src/infra/tools/dirmd/proto/dir_metadata.proto
monorail {
component: "Platform>DevTools>JavaScript"
}

1
deps/v8/test/inspector/OWNERS vendored Normal file
View File

@ -0,0 +1 @@
file:../../src/inspector/OWNERS

View File

@ -0,0 +1,13 @@
Tests console.clear() does not clear timers
{
type : string
value : console.clear
}
{
type : string
value : a: <number> ms
}
{
type : string
value : End of test
}

View File

@ -0,0 +1,25 @@
// Copyright 2024 the V8 project 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.clear() does not clear timers');
const expression = `
console.time("a");
console.clear();
console.timeEnd("a");
console.log("End of test");
`;
Protocol.Runtime.enable();
Protocol.Runtime.evaluate({ expression: expression });
Protocol.Runtime.onConsoleAPICalled(function(result) {
let message = result.params.args[0];
if (message.value == "End of test") {
InspectorTest.completeTest();
}
message.value = message.value.replaceAll(/[0-9]*\.[0-9]+|[0-9]+/g, '<number>');
InspectorTest.logObject(message);
});

View File

@ -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
}

View File

@ -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();
}
});

View File

@ -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
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
objectId : <objectId>
subtype : error
type : object
}
}
Evaluating 'a'
{
description : 42
type : number
value : 42
}

View File

@ -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();
})();

View File

@ -0,0 +1,145 @@
Stack tagging API works
Running test: simpleTaskLogsCorrectAsyncTrace
---------- console.trace: Inside run ----------
runner (simpleTaskLogsCorrectAsyncTrace.js:4:14)
simpleTaskLogsCorrectAsyncTrace (simpleTaskLogsCorrectAsyncTrace.js:3:9)
(anonymous) (simpleTaskLogsCorrectAsyncTrace.js:6:4)
-- Task --
foo (simpleTaskLogsCorrectAsyncTrace.js:1:36)
simpleTaskLogsCorrectAsyncTrace (simpleTaskLogsCorrectAsyncTrace.js:2:17)
(anonymous) (simpleTaskLogsCorrectAsyncTrace.js:6:4)
Running test: nestedTasksLogCorrectAsyncTrace
---------- console.trace: Inside runInner ----------
runInner (nestedTasksLogCorrectAsyncTrace.js:5:16)
runOuter (nestedTasksLogCorrectAsyncTrace.js:4:16)
nestedTasksLogCorrectAsyncTrace (nestedTasksLogCorrectAsyncTrace.js:2:14)
(anonymous) (nestedTasksLogCorrectAsyncTrace.js:8:4)
-- Inner Task --
runOuter (nestedTasksLogCorrectAsyncTrace.js:3:32)
nestedTasksLogCorrectAsyncTrace (nestedTasksLogCorrectAsyncTrace.js:2:14)
(anonymous) (nestedTasksLogCorrectAsyncTrace.js:8:4)
-- Outer Task --
nestedTasksLogCorrectAsyncTrace (nestedTasksLogCorrectAsyncTrace.js:1:30)
(anonymous) (nestedTasksLogCorrectAsyncTrace.js:8:4)
Running test: setTimeoutWorksCorrectly
---------- console.trace: Inside runInner ----------
runInner (setTimeoutWorksCorrectly.js:6:18)
(anonymous) (setTimeoutWorksCorrectly.js:5:18)
-- Inner Task --
(anonymous) (setTimeoutWorksCorrectly.js:4:34)
-- setTimeout --
(anonymous) (setTimeoutWorksCorrectly.js:3:30)
runOuter (setTimeoutWorksCorrectly.js:3:13)
setTimeoutWorksCorrectly (setTimeoutWorksCorrectly.js:2:20)
(anonymous) (setTimeoutWorksCorrectly.js:11:4)
-- Outer Task --
setTimeoutWorksCorrectly (setTimeoutWorksCorrectly.js:1:30)
(anonymous) (setTimeoutWorksCorrectly.js:11:4)
Running test: runForwardsTheReturnValue
---------- console.log: 42 ----------
runForwardsTheReturnValue (runForwardsTheReturnValue.js:3:12)
(anonymous) (runForwardsTheReturnValue.js:4:4)
Running test: runWorksWithAsyncPayloads
---------- console.log: 42 ----------
runWorksWithAsyncPayloads (runWorksWithAsyncPayloads.js:3:12)
Running test: runWorksWithGenerators
---------- console.log: 42 ----------
runWorksWithGenerators (runWorksWithGenerators.js:3:12)
(anonymous) (runWorksWithGenerators.js:4:4)
Running test: runCanBeCalledMultipleTimes
---------- console.log: First run ----------
(anonymous) (runCanBeCalledMultipleTimes.js:2:27)
runCanBeCalledMultipleTimes (runCanBeCalledMultipleTimes.js:2:9)
(anonymous) (runCanBeCalledMultipleTimes.js:4:4)
---------- console.log: Second run ----------
(anonymous) (runCanBeCalledMultipleTimes.js:3:27)
runCanBeCalledMultipleTimes (runCanBeCalledMultipleTimes.js:3:9)
(anonymous) (runCanBeCalledMultipleTimes.js:4:4)
Running test: runForwardsExceptions
Expected exception:
{
className : Error
description : Error: Thrown from task.run at runForwardsExceptions.js:4:13 at runForwardsExceptions (runForwardsExceptions.js:3:10) at runForwardsExceptions.js:6:5
objectId : <objectId>
subtype : error
type : object
}
Running test: recursivelyCalledRunDoesntCrash
---------- console.trace: Inside nestedRunOuter ----------
nestedRunOuter (recursivelyCalledRunDoesntCrash.js:6:18)
runInner (recursivelyCalledRunDoesntCrash.js:5:18)
runOuter (recursivelyCalledRunDoesntCrash.js:4:16)
recursivelyCalledRunDoesntCrash (recursivelyCalledRunDoesntCrash.js:2:14)
(anonymous) (recursivelyCalledRunDoesntCrash.js:10:4)
-- Outer Task --
recursivelyCalledRunDoesntCrash (recursivelyCalledRunDoesntCrash.js:1:30)
(anonymous) (recursivelyCalledRunDoesntCrash.js:10:4)
Running test: scheduleThrowsAnErrorWhenCalledWithoutAnArgument
Expected exception:
{
className : Error
description : Error: First argument must be a non-empty string. at scheduleThrowsAnErrorWhenCalledWithoutAnArgument (scheduleThrowsAnErrorWhenCalledWithoutAnArgument.js:2:13) at scheduleThrowsAnErrorWhenCalledWithoutAnArgument.js:3:5
objectId : <objectId>
subtype : error
type : object
}
Running test: scheduleThrowsAnErrorWhenCalledWithAnEmptyString
Expected exception:
{
className : Error
description : Error: First argument must be a non-empty string. at scheduleThrowsAnErrorWhenCalledWithAnEmptyString (scheduleThrowsAnErrorWhenCalledWithAnEmptyString.js:2:13) at scheduleThrowsAnErrorWhenCalledWithAnEmptyString.js:3:5
objectId : <objectId>
subtype : error
type : object
}
Running test: runThrowsAnErrorWhenCalledWithoutAnArgument
Expected exception:
{
className : Error
description : Error: First argument must be a function. at runThrowsAnErrorWhenCalledWithoutAnArgument (runThrowsAnErrorWhenCalledWithoutAnArgument.js:3:10) at runThrowsAnErrorWhenCalledWithoutAnArgument.js:4:5
objectId : <objectId>
subtype : error
type : object
}
Running test: runThrowsAnErrorWhenCalledWithNonFunction
Expected exception:
{
className : Error
description : Error: First argument must be a function. at runThrowsAnErrorWhenCalledWithNonFunction (runThrowsAnErrorWhenCalledWithNonFunction.js:3:10) at runThrowsAnErrorWhenCalledWithNonFunction.js:4:5
objectId : <objectId>
subtype : error
type : object
}
Running test: runThrowsAnErrorWhenCalledWithNullReceiver
Expected exception:
{
className : Error
description : Error: 'run' called with illegal receiver. at runThrowsAnErrorWhenCalledWithNullReceiver (runThrowsAnErrorWhenCalledWithNullReceiver.js:3:14) at runThrowsAnErrorWhenCalledWithNullReceiver.js:4:5
objectId : <objectId>
subtype : error
type : object
}
Running test: runThrowsAnErrorWhenCalledWithIllegalReceiver
Expected exception:
{
className : Error
description : Error: 'run' called with illegal receiver. at runThrowsAnErrorWhenCalledWithIllegalReceiver (runThrowsAnErrorWhenCalledWithIllegalReceiver.js:3:14) at runThrowsAnErrorWhenCalledWithIllegalReceiver.js:4:5
objectId : <objectId>
subtype : error
type : object
}

View File

@ -0,0 +1,134 @@
// Copyright 2022 the V8 project 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: --experimental-async-stack-tagging-api
const { session, contextGroup, Protocol } = InspectorTest.start('Stack tagging API works');
session.setupScriptMap();
// We write the test cases as functions instead of string literals so the
// fuzzer can fuzz them as well.
const testCases = [
function simpleTaskLogsCorrectAsyncTrace() {
function foo() { return console.createTask('Task'); }
const task = foo();
task.run(function runner() {
console.trace('Inside run');
});
},
function nestedTasksLogCorrectAsyncTrace() {
const outerTask = console.createTask('Outer Task');
outerTask.run(function runOuter() {
const innerTask = console.createTask('Inner Task');
innerTask.run(function runInner() {
console.trace('Inside runInner');
});
});
},
async function setTimeoutWorksCorrectly() {
const outerTask = console.createTask('Outer Task');
await outerTask.run(async function runOuter() {
return new Promise(r => setTimeout(() => {
const innerTask = console.createTask('Inner Task');
innerTask.run(function runInner() {
console.trace('Inside runInner');
r();
});
}, 0));
});
},
function runForwardsTheReturnValue() {
const task = console.createTask('Task');
const result = task.run(() => 42);
console.log(result);
},
async function runWorksWithAsyncPayloads() {
const task = console.createTask('Task');
const result = await task.run(async () => 42);
console.log(result);
},
function runWorksWithGenerators() {
const task = console.createTask('Task');
const iter = task.run(function* () { yield 42; });
console.log(iter.next().value);
},
function runCanBeCalledMultipleTimes() {
const task = console.createTask('Task');
task.run(() => console.log('First run'));
task.run(() => console.log('Second run'));
},
function runForwardsExceptions() {
const task = console.createTask('Task');
task.run(() => {
throw new Error('Thrown from task.run');
});
},
function recursivelyCalledRunDoesntCrash() {
const outerTask = console.createTask('Outer Task');
outerTask.run(function runOuter() {
const innerTask = console.createTask('Inner Task');
innerTask.run(function runInner() {
outerTask.run(function nestedRunOuter() {
console.trace('Inside nestedRunOuter');
});
});
});
},
function scheduleThrowsAnErrorWhenCalledWithoutAnArgument() {
console.createTask();
},
function scheduleThrowsAnErrorWhenCalledWithAnEmptyString() {
console.createTask('');
},
function runThrowsAnErrorWhenCalledWithoutAnArgument() {
const task = console.createTask('Task');
task.run();
},
function runThrowsAnErrorWhenCalledWithNonFunction() {
const task = console.createTask('Task');
task.run(42);
},
function runThrowsAnErrorWhenCalledWithNullReceiver() {
const task = console.createTask('Task');
task.run.call(undefined, () => { });
},
function runThrowsAnErrorWhenCalledWithIllegalReceiver() {
const task = console.createTask('Task');
task.run.call({}, () => { }); // The private symbol is missing.
},
];
(async () => {
Protocol.Runtime.onConsoleAPICalled(({params}) => {
InspectorTest.log(`---------- console.${params.type}: ${params.args[0].value} ----------`);
session.logCallFrames(params.stackTrace.callFrames);
session.logAsyncStackTrace(params.stackTrace.parent);
});
await Protocol.Runtime.enable();
await Protocol.Debugger.enable();
await Protocol.Debugger.setAsyncCallStackDepth({ maxDepth: 128 });
for (const testCase of testCases) {
InspectorTest.log(`\nRunning test: ${testCase.name}`);
// Turn the function into an IIFE and compile + run it as a script.
const {result: {scriptId}} = await Protocol.Runtime.compileScript({
expression: `(${testCase.toString()})();`,
sourceURL: `${testCase.name}.js`,
persistScript: true,
});
const { result: { exceptionDetails } } = await Protocol.Runtime.runScript({
scriptId,
awaitPromise: true,
});
if (exceptionDetails) {
InspectorTest.log(`Expected exception: `);
InspectorTest.logMessage(exceptionDetails.exception);
}
}
InspectorTest.completeTest();
})();

View File

@ -0,0 +1,9 @@
Test console profiles for asm.js.
testEnableProfilerEarly
Compiling asm.js module with sentinel 0.
testEnableProfilerLate
Compiling asm.js module with sentinel 1.
testEnableProfilerAfterDebugger
Compiling asm.js module with sentinel 2.
testEnableProfilerBeforeDebugger
Compiling asm.js module with sentinel 3.

View File

@ -0,0 +1,94 @@
// Copyright 2021 the V8 project 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 console profiles for asm.js.');
function compile(bytes) {
let buffer = new ArrayBuffer(bytes.length);
let view = new Uint8Array(buffer);
for (var i = 0; i < bytes.length; i++) {
view[i] = bytes[i] | 0;
}
let module = new WebAssembly.Module(buffer);
let fib = undefined;
function imp(i) { return fib(i); }
let instance = new WebAssembly.Instance(module, {q: {f: imp}});
fib = instance.exports.fib;
return instance;
}
function checkError(message) {
if (!message.error) return;
InspectorTest.log('Error: ');
InspectorTest.logMessage(message);
InspectorTest.completeTest();
}
// When build asm.js modules, include a sentinel such that the module will not
// be reused from the cache.
let sentinel = 0;
function AsmModule(stdlib, foreign, heap) {
"use asm";
function f() {
return sentinel;
}
return {f: f};
}
async function compileAsmJs() {
InspectorTest.log(`Compiling asm.js module with sentinel ${sentinel}.`);
let code = AsmModule.toString().replace('sentinel', sentinel.toString());
++sentinel;
checkError(await Protocol.Runtime.evaluate({expression: `(${code})().f()`}));
}
async function testEnableProfilerEarly() {
InspectorTest.log(arguments.callee.name);
checkError(await Protocol.Profiler.enable());
checkError(await Protocol.Profiler.start());
await compileAsmJs();
checkError(await Protocol.Profiler.disable());
}
async function testEnableProfilerLate() {
InspectorTest.log(arguments.callee.name);
await compileAsmJs();
checkError(await Protocol.Profiler.enable());
checkError(await Protocol.Profiler.start());
checkError(await Protocol.Profiler.disable());
}
async function testEnableProfilerAfterDebugger() {
InspectorTest.log(arguments.callee.name);
checkError(await Protocol.Debugger.enable());
await compileAsmJs();
checkError(await Protocol.Profiler.enable());
checkError(await Protocol.Profiler.start());
checkError(await Protocol.Profiler.disable());
checkError(await Protocol.Debugger.disable());
}
async function testEnableProfilerBeforeDebugger() {
InspectorTest.log(arguments.callee.name);
await compileAsmJs();
await Protocol.Profiler.enable();
await Protocol.Debugger.enable();
checkError(await Protocol.Profiler.start());
await Protocol.Debugger.disable();
await Protocol.Profiler.disable();
}
(async function test() {
try {
await testEnableProfilerEarly();
await testEnableProfilerLate();
await testEnableProfilerAfterDebugger();
await testEnableProfilerBeforeDebugger();
} catch (e) {
InspectorTest.log('caught: ' + e);
}
})().catch(e => InspectorTest.log('caught: ' + e))
.finally(InspectorTest.completeTest);

View File

@ -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

View File

@ -0,0 +1,47 @@
Test that console profiles contain wasm function names.
Running test: testEnableProfilerEarly
Compiling wasm.
Building wasm module with sentinel 1.
Running fib with increasing input until it shows up in the profile.
Found expected functions in profile.
Wasm script id is set.
Wasm position: wasm://wasm/ed5627ce@0:47
Running test: testEnableProfilerLate
Compiling wasm.
Building wasm module with sentinel 2.
Running fib with increasing input until it shows up in the profile.
Found expected functions in profile.
Wasm script id is set.
Wasm position: wasm://wasm/def0f3f2@0:47
Running test: testEnableProfilerAfterDebugger
Compiling wasm.
Building wasm module with sentinel 3.
Running fib with increasing input until it shows up in the profile.
Found expected functions in profile.
Wasm script id is set.
Wasm position: wasm://wasm/e950bb4a@0:47
Running test: testEnableProfilerBeforeDebugger
Compiling wasm.
Building wasm module with sentinel 4.
Running fib with increasing input until it shows up in the profile.
Found expected functions in profile.
Wasm script id is set.
Wasm position: wasm://wasm/d8d4f97a@0:47
Running test: testRunningCodeInDifferentIsolate
Building wasm module with sentinel 5.
Instantiating in inspector isolate.
Instantiating in the debugged isolate.
Compiling wasm.
Enabling profiler in the debugged isolate.
Running in the inspector isolate.
Running in the debugged isolate.
Running fib with increasing input until it shows up in the profile.
Found expected functions in profile.
Wasm script id is set.
Wasm position: wasm://wasm/8ffda0ce@0:47
Disabling profiler.

View File

@ -0,0 +1,208 @@
// Copyright 2019 the V8 project 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(v8:10266): Figure out why this fails on tsan with --always-turbofan.
// Flags: --no-always-turbofan --no-turbo-inline-js-wasm-calls
let {session, contextGroup, Protocol} = InspectorTest.start(
'Test that console profiles contain wasm function names.');
utils.load('test/mjsunit/wasm/wasm-module-builder.js');
// Build module bytes, including a sentinel such that the module will not be
// reused from the cache.
let sentinel = 0;
function buildModuleBytes() {
++sentinel;
InspectorTest.log(`Building wasm module with sentinel ${sentinel}.`);
// Add fibonacci function, calling back and forth between JS and Wasm to also
// check for the occurrence of the wrappers.
var builder = new WasmModuleBuilder();
const imp_index = builder.addImport('q', 'f', kSig_i_i);
builder.addFunction('fib', kSig_i_i)
.addBody([
...wasmI32Const(sentinel), kExprDrop,
kExprLocalGet, 0,
kExprLocalGet, 0,
kExprI32Const, 2,
kExprI32LeS, // i < 2 ?
kExprBrIf, 0, // --> return i
kExprI32Const, 1, kExprI32Sub, // i - 1
kExprCallFunction, imp_index, // imp(i - 1)
kExprLocalGet, 0, kExprI32Const, 2, kExprI32Sub, // i - 2
kExprCallFunction, imp_index, // imp(i - 2)
kExprI32Add
])
.exportFunc();
return builder.toArray();
}
function instantiate(bytes) {
let buffer = new ArrayBuffer(bytes.length);
let view = new Uint8Array(buffer);
for (var i = 0; i < bytes.length; i++) {
view[i] = bytes[i] | 0;
}
let module = new WebAssembly.Module(buffer);
let fib = undefined;
function imp(i) { return fib(i); }
let instance = new WebAssembly.Instance(module, {q: {f: imp}});
fib = instance.exports.fib;
return instance;
}
function checkError(message) {
if (!message.error) return;
InspectorTest.log('Error: ');
InspectorTest.logMessage(message);
InspectorTest.completeTest();
}
let found_good_profile = false;
let found_wasm_script_id;
let wasm_position;
let finished_profiles = 0;
// Remember which sequences of functions we have seen in profiles so far. This
// is printed in the error case to aid debugging.
let seen_profiles = [];
function addSeenProfile(function_names) {
let arrays_equal = (a, b) =>
a.length == b.length && a.every((val, index) => val == b[index]);
if (seen_profiles.some(a => arrays_equal(a, function_names))) return false;
seen_profiles.push(function_names.slice());
return true;
}
function resetGlobalData() {
found_good_profile = false;
finished_profiles = 0;
seen_profiles = [];
}
Protocol.Profiler.onConsoleProfileFinished(e => {
++finished_profiles;
let nodes = e.params.profile.nodes;
let function_names = nodes.map(n => n.callFrame.functionName);
// Check for at least one full cycle of
// fib -> wasm-to-js -> imp -> js-to-wasm -> fib.
// There are two different kinds of js-to-wasm-wrappers, so there are two
// possible positive traces.
const expected = [
['fib'], ['wasm-to-js', 'wasm-to-js:i:i'], ['imp'],
['js-to-wasm', 'js-to-wasm:i:i'], ['fib']
];
if (!addSeenProfile(function_names)) return;
for (let i = 0; i <= function_names.length - expected.length; ++i) {
if (expected.every((val, idx) => val.includes(function_names[i + idx]))) {
found_good_profile = true;
let wasm_frame = nodes[i].callFrame;
found_wasm_script_id = wasm_frame.scriptId != 0;
wasm_position = `${wasm_frame.url}@${wasm_frame.lineNumber}:${
wasm_frame.columnNumber}`;
}
}
});
async function runFibUntilProfileFound() {
InspectorTest.log(
'Running fib with increasing input until it shows up in the profile.');
resetGlobalData();
const start = Date.now();
const kTimeoutMs = 30000;
for (let i = 1; !found_good_profile; ++i) {
checkError(await Protocol.Runtime.evaluate(
{expression: `console.profile('profile');`}));
checkError(await Protocol.Runtime.evaluate(
{expression: `globalThis.instance.exports.fib(${i});`}));
checkError(await Protocol.Runtime.evaluate(
{expression: `console.profileEnd('profile');`}));
if (finished_profiles != i) {
InspectorTest.log(
`Missing consoleProfileFinished message (expected ${i}, got ` +
`${finished_profiles})`);
}
if (Date.now() - start > kTimeoutMs) {
InspectorTest.log('Seen profiles so far:');
for (let profile of seen_profiles) {
InspectorTest.log(' - ' + profile.join(" -> "));
}
throw new Error(
`fib did not show up in the profile within ` +
`${kTimeoutMs}ms (after ${i} executions)`);
}
}
InspectorTest.log('Found expected functions in profile.');
InspectorTest.log(
`Wasm script id is ${found_wasm_script_id ? 'set.' : 'NOT SET.'}`);
InspectorTest.log(`Wasm position: ${wasm_position}`);
}
async function compileWasm(module_bytes) {
InspectorTest.log('Compiling wasm.');
if (module_bytes === undefined) module_bytes = buildModuleBytes();
checkError(await Protocol.Runtime.evaluate({
expression: `globalThis.instance = (${instantiate})(${
JSON.stringify(module_bytes)});`
}));
}
InspectorTest.runAsyncTestSuite([
async function testEnableProfilerEarly() {
checkError(await Protocol.Profiler.enable());
checkError(await Protocol.Profiler.start());
await compileWasm();
await runFibUntilProfileFound();
checkError(await Protocol.Profiler.disable());
},
async function testEnableProfilerLate() {
await compileWasm();
checkError(await Protocol.Profiler.enable());
checkError(await Protocol.Profiler.start());
await runFibUntilProfileFound();
checkError(await Protocol.Profiler.disable());
},
async function testEnableProfilerAfterDebugger() {
checkError(await Protocol.Debugger.enable());
await compileWasm();
checkError(await Protocol.Profiler.enable());
checkError(await Protocol.Profiler.start());
await runFibUntilProfileFound();
checkError(await Protocol.Profiler.disable());
checkError(await Protocol.Debugger.disable());
},
async function testEnableProfilerBeforeDebugger() {
await compileWasm();
await Protocol.Profiler.enable();
await Protocol.Debugger.enable();
checkError(await Protocol.Profiler.start());
await runFibUntilProfileFound();
await Protocol.Debugger.disable();
await Protocol.Profiler.disable();
},
async function testRunningCodeInDifferentIsolate() {
// Do instantiate the module in the inspector isolate *and* in the debugged
// isolate. Trigger lazy compilation in the inspector isolate then. Check
// that we can profile in the debugged isolate later, i.e. the lazily
// compiled code was logged there.
let module_bytes = buildModuleBytes();
InspectorTest.log('Instantiating in inspector isolate.');
let instance = instantiate(module_bytes);
InspectorTest.log('Instantiating in the debugged isolate.');
await compileWasm(module_bytes);
InspectorTest.log('Enabling profiler in the debugged isolate.');
await Protocol.Profiler.enable();
checkError(await Protocol.Profiler.start());
InspectorTest.log('Running in the inspector isolate.');
instance.exports.fib(26);
InspectorTest.log('Running in the debugged isolate.');
await runFibUntilProfileFound();
InspectorTest.log('Disabling profiler.');
await Protocol.Profiler.disable();
}
]);

View File

@ -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);
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,293 @@
// 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-turbofan --turbofan
// Flags: --no-stress-flush-code
// Flags: --no-stress-incremental-marking
// Flags: --no-concurrent-recompilation
// Flags: --no-maglev
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);
},
]);

View File

@ -0,0 +1,835 @@
Test collecting code coverage data with Profiler.collectCoverage.
Running test: testPreciseCountBaseline
{
id : <messageId>
result : {
result : [
]
timestamp : <timestamp>
}
}
{
id : <messageId>
result : {
result : [
]
timestamp : <timestamp>
}
}
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 :
}
]
timestamp : <timestamp>
}
}
{
id : <messageId>
result : {
result : [
]
timestamp : <timestamp>
}
}
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 :
}
]
timestamp : <timestamp>
}
}
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
}
]
timestamp : <timestamp>
}
}
{
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 :
}
]
timestamp : <timestamp>
}
}
Running test: testPreciseEmptyScriptCoverageEntries
{
id : <messageId>
result : {
result : [
]
timestamp : <timestamp>
}
}
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
}
]
timestamp : <timestamp>
}
}
{
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 :
}
]
timestamp : <timestamp>
}
}

View File

@ -0,0 +1,270 @@
// 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-turbofan --turbofan
// Flags: --no-stress-flush-code
// Flags: --no-stress-incremental-marking
// Flags: --no-concurrent-recompilation
// Flags: --no-baseline-batch-compilation
// Flags: --no-maglev
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);
},
]);

View File

@ -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

View File

@ -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);

View File

@ -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

View File

@ -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);

View File

@ -0,0 +1,2 @@
Test that profiler doesn't crash when we call stop without preceding start.
PASS: ProfileAgent.stop

View File

@ -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);

View File

@ -0,0 +1,172 @@
Tests breakable locations in array destructuring.
Running test: testBreakLocations
function testFunction() {
var [a, b, c = 4] = |C|generator1();
|_|[[a, b], c] = |C|generator2();
|_|[a, ...b] = |C|generator1();
|R|}
function generator1() {
|_|return {
[Symbol.iterator]() {
const it = |_|[1, 2].|C|values();
|_|return {next() { |_|return it.|C|next();|R| }};|R|
}
};|R|
}
function generator2() {
|_|return {
[Symbol.iterator]() {
const it = |_|[|C|generator1(), 3].|C|values();
|_|return {next() { |_|return it.|C|next();|R| }};|R|
}
};|R|
}
|R|
Running test: testStepping
Execution paused in testFunction:
function testFunction() {
var [a, b, c = 4] = #generator1();
[[a, b], c] = generator2();
Execution paused in generator1:
function generator1() {
#return {
[Symbol.iterator]() {
Called from testFunction:
function testFunction() {
var [a, b, c = 4] = #generator1();
[[a, b], c] = generator2();
Execution paused in [Symbol.iterator]:
[Symbol.iterator]() {
const it = #[1, 2].values();
return {next() { return it.next(); }};
Called from testFunction:
function testFunction() {
var [a, b, c = 4] = #generator1();
[[a, b], c] = generator2();
Execution paused in next:
const it = [1, 2].values();
return {next() { #return it.next(); }};
}
Called from testFunction:
function testFunction() {
var [#a, b, c = 4] = generator1();
[[a, b], c] = generator2();
Execution paused in testFunction:
var [a, b, c = 4] = generator1();
#[[a, b], c] = generator2();
[a, ...b] = generator1();
Execution paused in generator2:
function generator2() {
#return {
[Symbol.iterator]() {
Called from testFunction:
var [a, b, c = 4] = generator1();
[[a, b], c] = #generator2();
[a, ...b] = generator1();
Execution paused in [Symbol.iterator]:
[Symbol.iterator]() {
const it = #[generator1(), 3].values();
return {next() { return it.next(); }};
Called from testFunction:
var [a, b, c = 4] = generator1();
[[a, b], c] #= generator2();
[a, ...b] = generator1();
Execution paused in next:
const it = [generator1(), 3].values();
return {next() { #return it.next(); }};
}
Called from testFunction:
var [a, b, c = 4] = generator1();
[#[a, b], c] = generator2();
[a, ...b] = generator1();
Execution paused in [Symbol.iterator]:
[Symbol.iterator]() {
const it = #[1, 2].values();
return {next() { return it.next(); }};
Called from testFunction:
var [a, b, c = 4] = generator1();
[#[a, b], c] = generator2();
[a, ...b] = generator1();
Execution paused in next:
const it = [1, 2].values();
return {next() { #return it.next(); }};
}
Called from testFunction:
var [a, b, c = 4] = generator1();
[[#a, b], c] = generator2();
[a, ...b] = generator1();
Execution paused in next:
const it = [generator1(), 3].values();
return {next() { #return it.next(); }};
}
Called from testFunction:
var [a, b, c = 4] = generator1();
[[a, b], #c] = generator2();
[a, ...b] = generator1();
Execution paused in testFunction:
[[a, b], c] = generator2();
#[a, ...b] = generator1();
}
Execution paused in generator1:
function generator1() {
#return {
[Symbol.iterator]() {
Called from testFunction:
[[a, b], c] = generator2();
[a, ...b] = #generator1();
}
Execution paused in [Symbol.iterator]:
[Symbol.iterator]() {
const it = #[1, 2].values();
return {next() { return it.next(); }};
Called from testFunction:
[[a, b], c] = generator2();
[a, ...b] #= generator1();
}
Execution paused in next:
const it = [1, 2].values();
return {next() { #return it.next(); }};
}
Called from testFunction:
[[a, b], c] = generator2();
[#a, ...b] = generator1();
}
Execution paused in testFunction:
[a, ...b] = generator1();
#}
Resuming and finishing...

View File

@ -0,0 +1,102 @@
// Copyright 2022 the V8 project 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 array destructuring.');
const source = `
function testFunction() {
var [a, b, c = 4] = generator1();
[[a, b], c] = generator2();
[a, ...b] = generator1();
}
function generator1() {
return {
[Symbol.iterator]() {
const it = [1, 2].values();
return {next() { return it.next(); }};
}
};
}
function generator2() {
return {
[Symbol.iterator]() {
const it = [generator1(), 3].values();
return {next() { return it.next(); }};
}
};
}
`;
const url = 'test.js';
contextGroup.addScript(source, 0, 0, url);
session.setupScriptMap();
InspectorTest.runAsyncTestSuite([
async function testBreakLocations() {
let [, , {params: {scriptId}}] = await Promise.all([
Protocol.Runtime.enable(),
Protocol.Debugger.enable(),
Protocol.Debugger.onceScriptParsed(),
]);
let {result: {locations}} = await Protocol.Debugger.getPossibleBreakpoints(
{start: {lineNumber: 0, columnNumber: 0, scriptId}});
await session.logBreakLocations(locations);
await Promise.all([
Protocol.Debugger.disable(),
Protocol.Runtime.disable(),
]);
},
async function testStepping() {
let [, , {params: {scriptId}}] = await Promise.all([
Protocol.Runtime.enable(),
Protocol.Debugger.enable(),
Protocol.Debugger.onceScriptParsed(),
]);
const {breakpointId} = await Protocol.Debugger.setBreakpoint({
location: {
scriptId,
lineNumber: 2,
}
});
const evalPromise =
Protocol.Runtime.evaluate({expression: 'testFunction()'});
for (;;) {
const {method, params} = await Promise.race([
evalPromise,
Protocol.Debugger.oncePaused(),
]);
if (method !== 'Debugger.paused') {
break;
}
const callFrames = params.callFrames.filter(
callFrame => callFrame.location.scriptId === scriptId);
if (callFrames.length === 0) {
InspectorTest.log('Resuming and finishing...');
await Protocol.Debugger.resume();
} else {
const [{functionName, location}, ...callerFrames] = callFrames;
InspectorTest.log(`Execution paused in ${functionName}:`);
await session.logSourceLocation(location);
for (const {location, functionName} of callerFrames) {
InspectorTest.log(`Called from ${functionName}:`);
await session.logSourceLocation(location);
}
if (functionName === 'testFunction') {
await Protocol.Debugger.stepInto();
} else {
await Protocol.Debugger.stepOut();
}
}
}
await Promise.all([
Protocol.Debugger.removeBreakpoint({breakpointId}),
Protocol.Debugger.disable(),
Protocol.Runtime.disable(),
]);
}
]);

View File

@ -0,0 +1,75 @@
Tests breakable locations in array spread.
Running test: testBreakLocations
function testFunction() {
var a = |_|[...iterable];
var b = [...|_|a, ...iterable, ...a];
|R|}
const iterable = |_|{
[Symbol.iterator]() {
const it = |_|[1, 2].|C|values();
|_|return {next() { |_|return it.|C|next();|R| }};|R|
}
};
|R|
Running test: testStepping
Execution paused in testFunction:
function testFunction() {
var a = #[...iterable];
var b = [...a, ...iterable, ...a];
Execution paused in [Symbol.iterator]:
[Symbol.iterator]() {
const it = #[1, 2].values();
return {next() { return it.next(); }};
Called from testFunction:
function testFunction() {
var a = [...#iterable];
var b = [...a, ...iterable, ...a];
Execution paused in next:
const it = [1, 2].values();
return {next() { #return it.next(); }};
}
Called from testFunction:
function testFunction() {
var a = [...#iterable];
var b = [...a, ...iterable, ...a];
Execution paused in testFunction:
var a = [...iterable];
var b = [...#a, ...iterable, ...a];
}
Execution paused in [Symbol.iterator]:
[Symbol.iterator]() {
const it = #[1, 2].values();
return {next() { return it.next(); }};
Called from testFunction:
var a = [...iterable];
var b = [...a, ...#iterable, ...a];
}
Execution paused in next:
const it = [1, 2].values();
return {next() { #return it.next(); }};
}
Called from testFunction:
var a = [...iterable];
var b = [...a, ...#iterable, ...a];
}
Execution paused in testFunction:
var b = [...a, ...iterable, ...a];
#}
Resuming and finishing...

View File

@ -0,0 +1,90 @@
// Copyright 2022 the V8 project 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 array spread.');
const source = `
function testFunction() {
var a = [...iterable];
var b = [...a, ...iterable, ...a];
}
const iterable = {
[Symbol.iterator]() {
const it = [1, 2].values();
return {next() { return it.next(); }};
}
};
`;
const url = 'test.js';
contextGroup.addScript(source, 0, 0, url);
session.setupScriptMap();
InspectorTest.runAsyncTestSuite([
async function testBreakLocations() {
let [, , {params: {scriptId}}] = await Promise.all([
Protocol.Runtime.enable(),
Protocol.Debugger.enable(),
Protocol.Debugger.onceScriptParsed(),
]);
let {result: {locations}} = await Protocol.Debugger.getPossibleBreakpoints(
{start: {lineNumber: 0, columnNumber: 0, scriptId}});
await session.logBreakLocations(locations);
await Promise.all([
Protocol.Debugger.disable(),
Protocol.Runtime.disable(),
]);
},
async function testStepping() {
let [, , {params: {scriptId}}] = await Promise.all([
Protocol.Runtime.enable(),
Protocol.Debugger.enable(),
Protocol.Debugger.onceScriptParsed(),
]);
const {breakpointId} = await Protocol.Debugger.setBreakpoint({
location: {
scriptId,
lineNumber: 2,
}
});
const evalPromise =
Protocol.Runtime.evaluate({expression: 'testFunction()'});
for (;;) {
const {method, params} = await Promise.race([
evalPromise,
Protocol.Debugger.oncePaused(),
]);
if (method !== 'Debugger.paused') {
break;
}
const callFrames = params.callFrames.filter(
callFrame => callFrame.location.scriptId === scriptId);
if (callFrames.length === 0) {
InspectorTest.log('Resuming and finishing...');
await Protocol.Debugger.resume();
} else {
const [{functionName, location}, ...callerFrames] = callFrames;
InspectorTest.log(`Execution paused in ${functionName}:`);
await session.logSourceLocation(location);
for (const {location, functionName} of callerFrames) {
InspectorTest.log(`Called from ${functionName}:`);
await session.logSourceLocation(location);
}
if (functionName === 'testFunction') {
await Protocol.Debugger.stepInto();
} else {
await Protocol.Debugger.stepOut();
}
}
}
await Promise.all([
Protocol.Debugger.removeBreakpoint({breakpointId}),
Protocol.Debugger.disable(),
Protocol.Runtime.disable(),
]);
}
]);

View File

@ -0,0 +1,64 @@
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 19...
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
Running test: runTestFunction
Script nr 2 parsed!
Paused #1
- [0] {"functionName":"testFunction","function_lineNumber":0,"function_columnNumber":21,"lineNumber":17,"columnNumber":12}
- [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":2}
- [1] {"functionName":"","function_lineNumber":0,"function_columnNumber":0,"lineNumber":0,"columnNumber":0}
Paused #3
- [0] {"functionName":"call_debugger","function_lineNumber":13,"function_columnNumber":24,"lineNumber":14,"columnNumber":4}
- [1] {"functionName":"callDebugger","function_lineNumber":0,"function_columnNumber":105,"lineNumber":5,"columnNumber":6}
- [2] {"functionName":"redirectFun","function_lineNumber":0,"function_columnNumber":110,"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}
Paused #4
- [0] {"functionName":"call_debugger","function_lineNumber":13,"function_columnNumber":24,"lineNumber":15,"columnNumber":2}
- [1] {"functionName":"callDebugger","function_lineNumber":0,"function_columnNumber":105,"lineNumber":5,"columnNumber":6}
- [2] {"functionName":"redirectFun","function_lineNumber":0,"function_columnNumber":110,"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}
Running test: finished
Finished TestSuite.

View File

@ -0,0 +1,134 @@
// 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;
}
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;
if (startLine > endLine) {
InspectorTest.log(
`Terminating early: start line ${startLine} is after end line ${endLine}.`
);
return;
}
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();
}

View File

@ -0,0 +1,84 @@
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","function_lineNumber":0,"function_columnNumber":105,"lineNumber":5,"columnNumber":6}
- [2] {"functionName":"redirectFun","function_lineNumber":0,"function_columnNumber":110,"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}
First time paused, setting breakpoints!
Flooding script with breakpoints for all lines (0 - 22)...
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
Script nr 3 parsed!
Resuming...
Paused #2
- [0] {"functionName":"call_debugger","function_lineNumber":13,"function_columnNumber":24,"lineNumber":15,"columnNumber":2}
- [1] {"functionName":"callDebugger","function_lineNumber":0,"function_columnNumber":105,"lineNumber":5,"columnNumber":6}
- [2] {"functionName":"redirectFun","function_lineNumber":0,"function_columnNumber":110,"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}
Script nr 4 parsed!
Resuming...
Paused #3
- [0] {"functionName":"testFunction","function_lineNumber":0,"function_columnNumber":21,"lineNumber":20,"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":21,"columnNumber":2}
- [1] {"functionName":"","function_lineNumber":0,"function_columnNumber":0,"lineNumber":0,"columnNumber":0}
Script nr 6 parsed!
Resuming...
Running test: finished
Finished TestSuite.

View File

@ -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: --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;
}
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();
}
}

View File

@ -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","function_lineNumber":0,"function_columnNumber":105,"lineNumber":5,"columnNumber":6}
- [2] {"functionName":"redirectFun","function_lineNumber":0,"function_columnNumber":110,"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!

View File

@ -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();
}

View File

@ -0,0 +1,134 @@
Tests different combinations of async stacks in chains.
Regular
userFunction (test.js:1:36)
-- inner async --
runWithRegular (utils.js:2:12)
inner (test.js:2:28)
runWithNone (utils.js:27:2)
(anonymous) (test.js:3:10)
Regular - Regular
userFunction (test.js:1:36)
-- inner async --
runWithRegular (utils.js:2:12)
inner (test.js:2:28)
-- outer async --
runWithRegular (utils.js:2:12)
(anonymous) (test.js:3:10)
Regular - EmptyName
userFunction (test.js:1:36)
-- inner async --
runWithRegular (utils.js:2:12)
inner (test.js:2:28)
-- <empty> --
runWithEmptyName (utils.js:6:12)
(anonymous) (test.js:3:10)
Regular - EmptyStack
userFunction (test.js:1:36)
-- inner async --
runWithRegular (utils.js:2:12)
inner (test.js:2:28)
Regular - EmptyNameEmptyStack
userFunction (test.js:1:36)
-- inner async --
runWithRegular (utils.js:2:12)
inner (test.js:2:28)
Regular - External
userFunction (test.js:1:36)
-- inner async --
runWithRegular (utils.js:2:12)
inner (test.js:2:28)
(anonymous) (utils.js:21:4)
<external stack>
EmptyName
userFunction (test.js:1:36)
-- <empty> --
runWithEmptyName (utils.js:6:12)
inner (test.js:2:28)
runWithNone (utils.js:27:2)
(anonymous) (test.js:3:10)
EmptyName - Regular
userFunction (test.js:1:36)
-- <empty> --
runWithEmptyName (utils.js:6:12)
inner (test.js:2:28)
-- outer async --
runWithRegular (utils.js:2:12)
(anonymous) (test.js:3:10)
EmptyName - EmptyName
userFunction (test.js:1:36)
-- <empty> --
runWithEmptyName (utils.js:6:12)
inner (test.js:2:28)
-- <empty> --
runWithEmptyName (utils.js:6:12)
(anonymous) (test.js:3:10)
EmptyName - EmptyStack
userFunction (test.js:1:36)
-- <empty> --
runWithEmptyName (utils.js:6:12)
inner (test.js:2:28)
EmptyName - EmptyNameEmptyStack
userFunction (test.js:1:36)
-- <empty> --
runWithEmptyName (utils.js:6:12)
inner (test.js:2:28)
EmptyName - External
userFunction (test.js:1:36)
-- <empty> --
runWithEmptyName (utils.js:6:12)
inner (test.js:2:28)
(anonymous) (utils.js:21:4)
<external stack>
EmptyStack
userFunction (test.js:1:36)
EmptyStack - Regular
userFunction (test.js:1:36)
EmptyStack - EmptyName
userFunction (test.js:1:36)
EmptyStack - EmptyStack
userFunction (test.js:1:36)
EmptyStack - EmptyNameEmptyStack
userFunction (test.js:1:36)
EmptyStack - External
userFunction (test.js:1:36)
EmptyNameEmptyStack
userFunction (test.js:1:36)
EmptyNameEmptyStack - Regular
userFunction (test.js:1:36)
EmptyNameEmptyStack - EmptyName
userFunction (test.js:1:36)
EmptyNameEmptyStack - EmptyStack
userFunction (test.js:1:36)
EmptyNameEmptyStack - EmptyNameEmptyStack
userFunction (test.js:1:36)
EmptyNameEmptyStack - External
userFunction (test.js:1:36)
External
userFunction (test.js:1:36)
(anonymous) (utils.js:21:4)
<external stack>

View File

@ -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.
let {session, contextGroup, Protocol} = InspectorTest.start(
'Tests different combinations of async stacks in chains.');
contextGroup.addScript(`
function runWithRegular(f, name) {
inspector.scheduleWithAsyncStack(f, name, false);
}
function runWithEmptyName(f) {
inspector.scheduleWithAsyncStack(f, '', false);
}
function runWithEmptyStack(f, name) {
inspector.scheduleWithAsyncStack(f, name, true);
}
function runWithEmptyNameEmptyStack(f) {
inspector.scheduleWithAsyncStack(f, '', true);
}
function runWithExternal(f) {
const id = inspector.storeCurrentStackTrace('external');
runWithRegular(() => {
inspector.externalAsyncTaskStarted(id);
f();
inspector.externalAsyncTaskFinished(id);
}, 'not-used-async');
}
function runWithNone(f) {
f();
}
//# sourceURL=utils.js`);
session.setupScriptMap();
(async function test() {
Protocol.Debugger.enable();
Protocol.Debugger.setAsyncCallStackDepth({maxDepth: 128});
const first = ['Regular', 'EmptyName', 'EmptyStack', 'EmptyNameEmptyStack', 'External']
const second = ['None', 'Regular', 'EmptyName', 'EmptyStack', 'EmptyNameEmptyStack', 'External']
for (const stack1 of first) {
for (const stack2 of second) {
if (stack1 === 'External' && stack2 !== 'None') continue;
InspectorTest.log(stack2 === 'None' ? stack1 : `${stack1} - ${stack2}`);
Protocol.Runtime.evaluate({
expression: `
var userFunction = () => {debugger};
var inner = () => runWith${stack1}(userFunction, 'inner async');
runWith${stack2}(inner, 'outer async');
//# sourceURL=test.js`
});
await pauseAndDumpStack();
}
}
await Protocol.Debugger.disable();
InspectorTest.completeTest();
})();
async function pauseAndDumpStack() {
const {params:{callFrames, asyncStackTrace, asyncStackTraceId}}
= await Protocol.Debugger.oncePaused();
session.logCallFrames(callFrames);
if (asyncStackTrace)
session.logAsyncStackTrace(asyncStackTrace);
if (asyncStackTraceId)
InspectorTest.log(' <external stack>');
InspectorTest.log('');
return Protocol.Debugger.resume();
}

View File

@ -0,0 +1 @@
setTimeout(console.count, 0) doesn't crash with enabled async stacks.

View File

@ -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);

View File

@ -0,0 +1,54 @@
Checks that async chains for for-await-of are correct.
Running test: testBasic
Debugger (test.js:10:2)
Basic (test.js:48:4)
-- await --
(anonymous) (testBasic.js:0:0)
Running test: testUncaughtReject
Debugger (test.js:10:2)
-- Promise.catch --
UncaughtReject (test.js:58:21)
(anonymous) (testUncaughtReject.js:0:0)
Running test: testUncaughtThrow
Debugger (test.js:10:2)
-- Promise.catch --
UncaughtThrow (test.js:67:21)
(anonymous) (testUncaughtThrow.js:0:0)
Running test: testCaughtReject
Debugger (test.js:10:2)
CaughtReject (test.js:76:4)
-- await --
(anonymous) (testCaughtReject.js:0:0)
Running test: testCaughtThrow
Debugger (test.js:10:2)
CaughtThrow (test.js:86:4)
-- await --
(anonymous) (testCaughtThrow.js:0:0)
Running test: testUncaughtRejectOnBreak
Running test: testUncaughtThrowOnBreak
Debugger (test.js:10:2)
-- Promise.catch --
UncaughtThrowOnBreak (test.js:105:21)
(anonymous) (testUncaughtThrowOnBreak.js:0:0)
Running test: testCaughtRejectOnBreak
Running test: testCaughtThrowOnBreak
Debugger (test.js:10:2)
CaughtThrowOnBreak (test.js:124:4)
-- await --
(anonymous) (testCaughtThrowOnBreak.js:0:0)

View File

@ -0,0 +1,161 @@
// 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 for-await-of are correct.');
contextGroup.addInlineScript(`
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();
}
}
async function UncaughtReject() {
async function loop() {
for await (let x of [Reject(new Error("boop"))]) {
Debugger();
}
}
return loop().catch(Debugger);
}
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);
}
}
async function UncaughtRejectOnBreak() {
async function loop() {
for await (let x of RejectOnReturn(["0", "1"])) {
break;
}
}
return loop().catch(Debugger);
}
async function UncaughtThrowOnBreak() {
async function loop() {
for await (let x of ThrowOnReturn(["0", "1"])) {
break;
}
}
return loop().catch(Debugger);
}
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);
}
}`, 'test.js');
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);
}

View File

@ -0,0 +1,178 @@
stepOut async function
Running test: testTrivial
Check that we have proper async stack at return
bar (testTrivial.js:28:8)
-- await --
foo (testTrivial.js:23:14)
-- await --
test (testTrivial.js:18:14)
-- await --
(anonymous) (:0:0)
foo (testTrivial.js:24:6)
-- await --
test (testTrivial.js:18:14)
-- await --
(anonymous) (:0:0)
test (testTrivial.js:19:6)
-- await --
(anonymous) (:0:0)
Running test: testStepOutPrecision
Check that stepOut go to resumed outer generator
bar (testStepOutPrecision.js:61:8)
-- await --
foo (testStepOutPrecision.js:55:14)
-- await --
test (testStepOutPrecision.js:48:14)
-- await --
(anonymous) (:0:0)
foo (testStepOutPrecision.js:56:8)
-- await --
test (testStepOutPrecision.js:48:14)
-- await --
(anonymous) (:0:0)
test (testStepOutPrecision.js:49:8)
-- await --
(anonymous) (:0:0)
floodWithTimeouts (testStepOutPrecision.js:40:15)
-- setTimeout --
floodWithTimeouts (testStepOutPrecision.js:41:10)
-- setTimeout --
floodWithTimeouts (testStepOutPrecision.js:41:10)
-- setTimeout --
floodWithTimeouts (testStepOutPrecision.js:41:10)
-- setTimeout --
floodWithTimeouts (testStepOutPrecision.js:41:10)
test (testStepOutPrecision.js:46:8)
(anonymous) (:0:0)
test (testStepOutPrecision.js:50:8)
-- await --
(anonymous) (:0:0)
floodWithTimeouts (testStepOutPrecision.js:40:15)
-- setTimeout --
floodWithTimeouts (testStepOutPrecision.js:41:10)
-- setTimeout --
floodWithTimeouts (testStepOutPrecision.js:41:10)
-- setTimeout --
floodWithTimeouts (testStepOutPrecision.js:41:10)
-- setTimeout --
floodWithTimeouts (testStepOutPrecision.js:41:10)
-- setTimeout --
floodWithTimeouts (testStepOutPrecision.js:41:10)
test (testStepOutPrecision.js:46:8)
(anonymous) (:0:0)
Running test: testStepIntoAtReturn
Check that stepInto at return go to resumed outer generator
bar (testStepIntoAtReturn.js:93:8)
-- await --
foo (testStepIntoAtReturn.js:88:14)
-- await --
test (testStepIntoAtReturn.js:82:14)
-- await --
(anonymous) (:0:0)
bar (testStepIntoAtReturn.js:94:6)
-- await --
foo (testStepIntoAtReturn.js:88:14)
-- await --
test (testStepIntoAtReturn.js:82:14)
-- await --
(anonymous) (:0:0)
foo (testStepIntoAtReturn.js:89:6)
-- await --
test (testStepIntoAtReturn.js:82:14)
-- await --
(anonymous) (:0:0)
test (testStepIntoAtReturn.js:83:8)
-- await --
(anonymous) (:0:0)
test (testStepIntoAtReturn.js:84:6)
-- await --
(anonymous) (:0:0)
floodWithTimeouts (testStepIntoAtReturn.js:74:15)
-- setTimeout --
floodWithTimeouts (testStepIntoAtReturn.js:75:10)
-- setTimeout --
floodWithTimeouts (testStepIntoAtReturn.js:75:10)
test (testStepIntoAtReturn.js:80:8)
(anonymous) (:0:0)
Running test: testStepOverAtReturn
Check that stepOver at return go to resumed outer generator
bar (testStepIntoAtReturn.js:124:8)
-- await --
foo (testStepIntoAtReturn.js:119:14)
-- await --
test (testStepIntoAtReturn.js:113:14)
-- await --
(anonymous) (:0:0)
bar (testStepIntoAtReturn.js:125:6)
-- await --
foo (testStepIntoAtReturn.js:119:14)
-- await --
test (testStepIntoAtReturn.js:113:14)
-- await --
(anonymous) (:0:0)
foo (testStepIntoAtReturn.js:120:6)
-- await --
test (testStepIntoAtReturn.js:113:14)
-- await --
(anonymous) (:0:0)
test (testStepIntoAtReturn.js:114:8)
-- await --
(anonymous) (:0:0)
test (testStepIntoAtReturn.js:115:6)
-- await --
(anonymous) (:0:0)
floodWithTimeouts (testStepIntoAtReturn.js:105:15)
-- setTimeout --
floodWithTimeouts (testStepIntoAtReturn.js:106:10)
-- setTimeout --
floodWithTimeouts (testStepIntoAtReturn.js:106:10)
test (testStepIntoAtReturn.js:111:8)
(anonymous) (:0:0)
Running test: testStepOutFromNotAwaitedCall
Checks stepOut from not awaited call
bar (testStepIntoAtReturn.js:158:8)
-- await --
foo (testStepIntoAtReturn.js:152:8)
-- await --
test (testStepIntoAtReturn.js:144:14)
-- await --
(anonymous) (:0:0)
test (testStepIntoAtReturn.js:145:8)
-- await --
(anonymous) (:0:0)
floodWithTimeouts (testStepIntoAtReturn.js:136:15)
-- setTimeout --
floodWithTimeouts (testStepIntoAtReturn.js:137:10)
-- setTimeout --
floodWithTimeouts (testStepIntoAtReturn.js:137:10)
test (testStepIntoAtReturn.js:142:8)
(anonymous) (:0:0)

View File

@ -0,0 +1,185 @@
// Copyright 2018 the V8 project 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('stepOut async function');
session.setupScriptMap();
Protocol.Runtime.enable();
InspectorTest.runAsyncTestSuite([
async function testTrivial() {
InspectorTest.log('Check that we have proper async stack at return');
contextGroup.addInlineScript(`
async function test() {
await Promise.resolve();
await foo();
}
async function foo() {
await Promise.resolve();
await bar();
}
async function bar() {
await Promise.resolve();
debugger;
}`, 'testTrivial.js');
await runTestAndStepAction('stepOut');
},
async function testStepOutPrecision() {
InspectorTest.log('Check that stepOut go to resumed outer generator');
contextGroup.addInlineScript(`
function wait() {
return new Promise(resolve => setTimeout(resolve, 0));
}
function floodWithTimeouts(a) {
if (!a.stop)
setTimeout(floodWithTimeouts.bind(this, a), 0);
}
async function test() {
let a = {};
floodWithTimeouts(a)
await wait();
await foo();
await wait();
a.stop = true;
}
async function foo() {
await Promise.resolve();
await bar();
await wait();
}
async function bar() {
await Promise.resolve();
debugger;
await wait();
}`, 'testStepOutPrecision.js');
await runTestAndStepAction('stepOut');
},
async function testStepIntoAtReturn() {
InspectorTest.log('Check that stepInto at return go to resumed outer generator');
contextGroup.addInlineScript(`
function wait() {
return new Promise(resolve => setTimeout(resolve, 0));
}
function floodWithTimeouts(a) {
if (!a.stop)
setTimeout(floodWithTimeouts.bind(this, a), 0);
}
async function test() {
let a = {};
floodWithTimeouts(a)
await wait();
await foo();
a.stop = true;
}
async function foo() {
await Promise.resolve();
await bar();
}
async function bar() {
await Promise.resolve();
debugger;
}`, 'testStepIntoAtReturn.js');
await runTestAndStepAction('stepInto');
},
async function testStepOverAtReturn() {
InspectorTest.log('Check that stepOver at return go to resumed outer generator');
contextGroup.addInlineScript(`
function wait() {
return new Promise(resolve => setTimeout(resolve, 0));
}
function floodWithTimeouts(a) {
if (!a.stop)
setTimeout(floodWithTimeouts.bind(this, a), 0);
}
async function test() {
let a = {};
floodWithTimeouts(a)
await wait();
await foo();
a.stop = true;
}
async function foo() {
await Promise.resolve();
await bar();
}
async function bar() {
await Promise.resolve();
debugger;
}`, 'testStepIntoAtReturn.js');
await runTestAndStepAction('stepOver');
},
async function testStepOutFromNotAwaitedCall() {
InspectorTest.log('Checks stepOut from not awaited call');
contextGroup.addInlineScript(`
function wait() {
return new Promise(resolve => setTimeout(resolve, 0));
}
function floodWithTimeouts(a) {
if (!a.stop)
setTimeout(floodWithTimeouts.bind(this, a), 0);
}
async function test() {
let a = {};
floodWithTimeouts(a)
await wait();
await foo();
a.stop = true;
}
async function foo() {
let a = {};
floodWithTimeouts(a);
await Promise.resolve();
bar();
a.stop = true;
}
async function bar() {
await Promise.resolve();
debugger;
}`, 'testStepIntoAtReturn.js');
await runTestAndStepAction('stepOut');
}
]);
async function runTestAndStepAction(action) {
Protocol.Debugger.enable();
Protocol.Debugger.setAsyncCallStackDepth({maxDepth: 128});
let finished =
Protocol.Runtime.evaluate({expression: 'test()', awaitPromise: true})
.then(() => false);
while (true) {
const r = await Promise.race([finished, waitPauseAndDumpStack()]);
if (!r) break;
Protocol.Debugger[action]();
}
await Protocol.Debugger.disable();
}
async function waitPauseAndDumpStack() {
const {params} = await Protocol.Debugger.oncePaused();
session.logCallFrames(params.callFrames);
session.logAsyncStackTrace(params.asyncStackTrace);
InspectorTest.log('');
return true;
}

View File

@ -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.then --
test (test.js:19:14)
(anonymous) (expr1.js:0:0)
foo (test.js:12:2)
-- Promise.then --
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)

View File

@ -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.addInlineScript(
`
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;
}`,
'test.js');
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);
}
]);

View File

@ -0,0 +1,16 @@
Checks async stack for late .then handlers with gc
foo1 (test.js:11:2)
-- Promise.then --
test (test.js:18:14)
(anonymous) (expr.js:0:0)
foo1 (test.js:11:2)
-- Promise.then --
test (test.js:22:14)
(anonymous) (expr.js:0:0)
foo1 (test.js:11:2)
-- Promise.then --
test (test.js:24:14)
(anonymous) (expr.js:0:0)

View File

@ -0,0 +1,49 @@
// 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.addInlineScript(
`
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]);
}`,
'test.js');
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);

View File

@ -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)

View File

@ -0,0 +1,49 @@
// 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.addInlineScript(
`
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;
}`,
'test.js');
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);

View File

@ -0,0 +1,37 @@
Checks that async stacks works for async/await
foo2 (test.js:15:2)
-- await --
test (test.js:24:8)
(anonymous) (expr.js:0:0)
foo2 (test.js:17:2)
-- await --
test (test.js:24:8)
(anonymous) (expr.js:0:0)
foo1 (test.js:9:2)
foo2 (test.js:18:8)
-- await --
test (test.js:24:8)
(anonymous) (expr.js:0:0)
foo1 (test.js:9:2)
-- Promise.then --
foo2 (test.js:19:43)
-- await --
test (test.js:24:8)
(anonymous) (expr.js:0:0)
foo2 (test.js:20:2)
-- await --
test (test.js:24:8)
(anonymous) (expr.js:0:0)
{
id : <messageId>
result : {
result : {
type : undefined
}
}
}

View File

@ -0,0 +1,40 @@
// 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.addInlineScript(`
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();
}`, 'test.js');
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);

View File

@ -0,0 +1,91 @@
Checks created frame for async call chain
Running test: testPromise
foo1 (test.js:10:2)
-- Promise.then --
promise (test.js:20:14)
(anonymous) (expr.js:0:0)
Running test: testPromiseThen
foo1 (test.js:10:2)
-- Promise.then --
promiseThen (test.js:28:14)
(anonymous) (expr.js:0:0)
foo2 (test.js:14:2)
-- Promise.then --
promiseThen (test.js:29:14)
(anonymous) (expr.js:0:0)
Running test: testPromiseThenThen
foo1 (test.js:10:2)
-- Promise.then --
promiseThenThen (test.js:37:14)
(anonymous) (expr.js:0:0)
foo1 (test.js:10:2)
-- Promise.then --
promiseThenThen (test.js:38:14)
(anonymous) (expr.js:0:0)
foo2 (test.js:14:2)
-- Promise.then --
promiseThenThen (test.js:37:25)
(anonymous) (expr.js:0:0)
Running test: testPromiseResolve
foo1 (test.js:10:2)
-- Promise.then --
promiseResolve (test.js:44:27)
(anonymous) (expr.js:0:0)
Running test: testPromiseReject
foo1 (test.js:10:2)
-- Promise.catch --
promiseReject (test.js:48:31)
(anonymous) (expr.js:0:0)
Running test: testPromiseAll
foo1 (test.js:10:2)
-- Promise.then --
promiseAll (test.js:52:44)
(anonymous) (expr.js:0:0)
Running test: testPromiseRace
foo1 (test.js:10:2)
-- Promise.then --
promiseRace (test.js:56:45)
(anonymous) (expr.js:0:0)
Running test: testThenableJob1
foo1 (test.js:10:2)
-- Promise.then --
thenableJob1 (test.js:60:72)
(anonymous) (expr.js:0:0)
Running test: testThenableJob2
foo1 (test.js:10:2)
-- Promise.then --
thenableJob2 (test.js:64:57)
(anonymous) (expr.js:0:0)
Running test: testSetTimeouts
foo1 (test.js:10:2)
(anonymous) (test.js:72:25)
-- setTimeout --
(anonymous) (test.js:72:6)
-- setTimeout --
(anonymous) (test.js:71:4)
-- setTimeout --
setTimeouts (test.js:70:2)
(anonymous) (expr.js:0:0)

View File

@ -0,0 +1,177 @@
// 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.addInlineScript(
`
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;
}`,
'test.js');
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);
}
]);

View File

@ -0,0 +1,133 @@
Checks that async chains for promises are correct.
Running test: testPromise
foo1 (test.js:9:2)
-- Promise.then --
promise (test.js:19:14)
(anonymous) (testPromise.js:0:0)
Running test: testPromiseResolvedBySetTimeout
foo1 (test.js:9:2)
-- Promise.then --
promiseResolvedBySetTimeout (test.js:27:14)
(anonymous) (testPromiseResolvedBySetTimeout.js:0:0)
Running test: testPromiseAll
foo1 (test.js:9:2)
-- Promise.then --
promiseAll (test.js:37:35)
(anonymous) (testPromiseAll.js:0:0)
Running test: testPromiseAllReverseOrder
foo1 (test.js:9:2)
-- Promise.then --
promiseAllReverseOrder (test.js:48:35)
(anonymous) (testPromiseAllReverseOrder.js:0:0)
Running test: testPromiseRace
foo1 (test.js:9:2)
-- Promise.then --
promiseRace (test.js:59:36)
(anonymous) (testPromiseRace.js:0:0)
Running test: testTwoChainedCallbacks
foo1 (test.js:9:2)
-- Promise.then --
twoChainedCallbacks (test.js:68:14)
(anonymous) (testTwoChainedCallbacks.js:0:0)
foo2 (test.js:13:2)
-- Promise.then --
twoChainedCallbacks (test.js:68:25)
(anonymous) (testTwoChainedCallbacks.js:0:0)
Running test: testPromiseResolve
foo1 (test.js:9:2)
-- Promise.then --
promiseResolve (test.js:74:27)
(anonymous) (testPromiseResolve.js:0:0)
foo2 (test.js:13:2)
-- Promise.then --
promiseResolve (test.js:74:38)
(anonymous) (testPromiseResolve.js:0:0)
Running test: testThenableJobResolvedInSetTimeout
foo1 (test.js:9:2)
-- Promise.then --
thenableJobResolvedInSetTimeout (test.js:86:40)
(anonymous) (testThenableJobResolvedInSetTimeout.js:0:0)
Running test: testThenableJobResolvedInSetTimeoutWithStack
foo1 (test.js:9:2)
-- Promise.then --
thenableJobResolvedInSetTimeoutWithStack (test.js:104:40)
(anonymous) (testThenableJobResolvedInSetTimeoutWithStack.js:0:0)
Running test: testThenableJobResolvedByPromise
foo1 (test.js:9:2)
-- Promise.then --
thenableJobResolvedByPromise (test.js:118:40)
(anonymous) (testThenableJobResolvedByPromise.js:0:0)
Running test: testThenableJobResolvedByPromiseWithStack
foo1 (test.js:9:2)
-- Promise.then --
thenableJobResolvedByPromiseWithStack (test.js:136:40)
(anonymous) (testThenableJobResolvedByPromiseWithStack.js:0:0)
Running test: testLateThenCallback
foo1 (test.js:9:2)
-- Promise.then --
lateThenCallback (test.js:145:12)
(anonymous) (testLateThenCallback.js:0:0)
Running test: testComplex
inner1 (test.js:154:6)
foo1 (test.js:156:4)
-- Promise.then --
complex (test.js:202:5)
(anonymous) (testComplex.js:0:0)
(anonymous) (test.js:207:8)
-- Promise.then --
(anonymous) (test.js:206:8)
-- Promise.then --
(anonymous) (test.js:205:6)
-- setTimeout --
complex (test.js:204:2)
(anonymous) (testComplex.js:0:0)
Running test: testReject
foo1 (test.js:9:2)
-- Promise.catch --
reject (test.js:217:31)
(anonymous) (testReject.js:0:0)
Running test: testFinally1
foo1 (test.js:9:2)
-- Promise.finally --
finally1 (test.js:221:33)
(anonymous) (testFinally1.js:0:0)
Running test: testFinally2
foo1 (test.js:9:2)
-- Promise.finally --
finally2 (test.js:225:34)
(anonymous) (testFinally2.js:0:0)

View File

@ -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.addInlineScript(
`
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);
}
function finally1() {
return Promise.reject().finally(foo1);
}
function finally2() {
return Promise.resolve().finally(foo1);
}`,
'test.js');
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', 'finally1', 'finally2'
]
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);
}

View File

@ -0,0 +1,44 @@
Tests super long async stacks.
Running test: test
(anonymous) (expr.js:0:26)
callWithAsyncStack (utils.js:3:4)
call1 (wrapper.js:0:20)
--Promise.then--
callWithAsyncStack (utils.js:7:20)
call2 (wrapper.js:0:20)
--Promise.then--
callWithAsyncStack (utils.js:7:20)
call3 (wrapper.js:0:20)
--Promise.then--
callWithAsyncStack (utils.js:7:20)
call4 (wrapper.js:0:20)
--Promise.then--
callWithAsyncStack (utils.js:7:20)
call5 (wrapper.js:0:20)
(fetch parent..)
--Promise.then--
callWithAsyncStack (utils.js:7:20)
call6 (wrapper.js:0:20)
--Promise.then--
callWithAsyncStack (utils.js:7:20)
call7 (wrapper.js:0:20)
--Promise.then--
callWithAsyncStack (utils.js:7:20)
call8 (wrapper.js:0:20)
--Promise.then--
callWithAsyncStack (utils.js:7:20)
call9 (wrapper.js:0:20)
--Promise.then--
callWithAsyncStack (utils.js:7:20)
call10 (wrapper.js:0:21)
(fetch parent..)
--Promise.then--
callWithAsyncStack (utils.js:7:20)
call11 (wrapper.js:0:21)
--Promise.then--
callWithAsyncStack (utils.js:7:20)
call12 (wrapper.js:0:21)
--Promise.then--
callWithAsyncStack (utils.js:7:20)
(anonymous) (expr.js:0:0)

View File

@ -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('Tests super long async stacks.');
contextGroup.addScript(`
function callWithAsyncStack(f, depth) {
if (depth === 0) {
f();
return;
}
wrapper = eval('(function call' + depth + '() { callWithAsyncStack(f, depth - 1) }) //# sourceURL=wrapper.js');
Promise.resolve().then(wrapper);
}
//# sourceURL=utils.js`);
session.setupScriptMap();
InspectorTest.runAsyncTestSuite([async function test() {
Protocol.Debugger.enable();
Protocol.Debugger.setAsyncCallStackDepth({maxDepth: 4});
Protocol.Runtime.evaluate({
expression: 'callWithAsyncStack(() => {debugger}, 12)//# sourceURL=expr.js'
});
let {params} = await Protocol.Debugger.oncePaused();
let {callFrames, asyncStackTrace, externalAsyncStackTrace} = params;
while (true) {
session.logCallFrames(callFrames);
if (externalAsyncStackTrace) {
InspectorTest.log('(fetch parent..)');
asyncStackTrace = (await Protocol.Debugger.getStackTrace({
stackTraceId: externalAsyncStackTrace
})).result.stackTrace;
}
if (asyncStackTrace) {
InspectorTest.log('--' + asyncStackTrace.description + '--');
callFrames = asyncStackTrace.callFrames;
externalAsyncStackTrace = asyncStackTrace.parentId;
asyncStackTrace = asyncStackTrace.parent;
} else {
break;
}
}
}]);

View File

@ -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() {}

View File

@ -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();
}

View File

@ -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:4:36)
for (let x = 0; x < 1; ++x) await x;
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:4:36)
for (let x = 0; x < 1; ++x) await x;
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:4:36)
for (let x = 0; x < 1; ++x) await x;
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:4:36)
for (let x = 0; x < 1; ++x) await x;
return await Promise.resolve(2);#
}
(anonymous) (test.js:10:27)
await f1();
await f1().then(x => x #* 2);
await [1].map(x => Promise.resolve(x))[0];
(anonymous) (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);
(anonymous) (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);
(anonymous) (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:15:13)
await p;
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:15:13)
await p;
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);
}

View File

@ -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 '|_|';
}

View File

@ -0,0 +1,200 @@
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:17:13)
let r = await Promise.resolve(42);
return r;#
})();
(anonymous) (test.js:4:64)
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);
(anonymous) (test.js:4:67)
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);
(anonymous) (test.js:5:50)
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);
(anonymous) (test.js:5:53)
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);
(anonymous) (test.js:6:60)
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;
(anonymous) (test.js:6:63)
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;
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; }
}

View File

@ -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);
}
}
]);

View File

@ -0,0 +1,200 @@
Tests for break on exception and stepping.
Running test: testStepThrougA
function a() { #n(); };
function b() { c(); };
Running test: testStepThrougB
paused on exception:
{
reasons : [
[0] : {
reason : step
}
[1] : {
reason : other
}
]
}
function a() { n(); };
function b() { #c(); };
function c() { n(); };
function b() { c(); };
function c() { #n(); };
function d() { x = 1; try { e(); } catch(x) { x = 2; } };
Running test: testStepThrougD
paused on exception:
{
reasons : [
[0] : {
reason : step
}
[1] : {
reason : other
}
]
}
function c() { n(); };
function d() { #x = 1; try { e(); } catch(x) { x = 2; } };
function e() { n(); };
function c() { n(); };
function d() { x = 1; try { #e(); } catch(x) { x = 2; } };
function e() { n(); };
function d() { x = 1; try { e(); } catch(x) { x = 2; } };
function e() { #n(); };
function f() { x = 1; try { g(); } catch(x) { x = 2; } };
function c() { n(); };
function d() { x = 1; try { e(); } catch(x) { #x = 2; } };
function e() { n(); };
function c() { n(); };
function d() { x = 1; try { e(); } catch(x) { x = 2; } #};
function e() { n(); };
Running test: testStepThrougDWithBreakOnAllExceptions
paused on exception:
{
reasons : [
[0] : {
reason : step
}
[1] : {
reason : other
}
]
}
function c() { n(); };
function d() { #x = 1; try { e(); } catch(x) { x = 2; } };
function e() { n(); };
function c() { n(); };
function d() { x = 1; try { #e(); } catch(x) { x = 2; } };
function e() { n(); };
function d() { x = 1; try { e(); } catch(x) { x = 2; } };
function e() { #n(); };
function f() { x = 1; try { g(); } catch(x) { x = 2; } };
paused on exception:
{
className : ReferenceError
description : ReferenceError: n is not defined at e (<anonymous>:6:16) at d (<anonymous>:5:29) at expr.js:1:1
objectId : <objectId>
subtype : error
type : object
uncaught : false
}
function d() { x = 1; try { e(); } catch(x) { x = 2; } };
function e() { #n(); };
function f() { x = 1; try { g(); } catch(x) { x = 2; } };
function c() { n(); };
function d() { x = 1; try { e(); } catch(x) { #x = 2; } };
function e() { n(); };
function c() { n(); };
function d() { x = 1; try { e(); } catch(x) { x = 2; } #};
function e() { n(); };
Running test: testStepThrougF
paused on exception:
{
reasons : [
[0] : {
reason : step
}
[1] : {
reason : other
}
]
}
function e() { n(); };
function f() { #x = 1; try { g(); } catch(x) { x = 2; } };
function g() { h(); };
function e() { n(); };
function f() { x = 1; try { #g(); } catch(x) { x = 2; } };
function g() { h(); };
function f() { x = 1; try { g(); } catch(x) { x = 2; } };
function g() { #h(); };
function h() { x = 1; throw 1; };
function g() { h(); };
function h() { #x = 1; throw 1; };
function g() { h(); };
function h() { x = 1; #throw 1; };
function e() { n(); };
function f() { x = 1; try { g(); } catch(x) { #x = 2; } };
function g() { h(); };
function e() { n(); };
function f() { x = 1; try { g(); } catch(x) { x = 2; } #};
function g() { h(); };
Running test: testStepThrougFWithBreakOnAllExceptions
paused on exception:
{
reasons : [
[0] : {
reason : step
}
[1] : {
reason : other
}
]
}
function e() { n(); };
function f() { #x = 1; try { g(); } catch(x) { x = 2; } };
function g() { h(); };
function e() { n(); };
function f() { x = 1; try { #g(); } catch(x) { x = 2; } };
function g() { h(); };
function f() { x = 1; try { g(); } catch(x) { x = 2; } };
function g() { #h(); };
function h() { x = 1; throw 1; };
function g() { h(); };
function h() { #x = 1; throw 1; };
function g() { h(); };
function h() { x = 1; #throw 1; };
paused on exception:
{
description : 1
type : number
uncaught : false
value : 1
}
function g() { h(); };
function h() { x = 1; #throw 1; };
function e() { n(); };
function f() { x = 1; try { g(); } catch(x) { #x = 2; } };
function g() { h(); };
function e() { n(); };
function f() { x = 1; try { g(); } catch(x) { x = 2; } #};
function g() { h(); };

View File

@ -0,0 +1,69 @@
// Copyright 2018 the V8 project 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 for break on exception and stepping.');
session.setupScriptMap();
Protocol.Debugger.enable();
Protocol.Debugger.setBlackboxPatterns({patterns: ['expr\.js']});
Protocol.Debugger.onPaused(async ({params:{callFrames:[topFrame], data}}) => {
if (data) {
InspectorTest.log('paused on exception:');
InspectorTest.logMessage(data);
}
await session.logSourceLocation(topFrame.location);
Protocol.Debugger.stepInto();
});
contextGroup.addScript(`
function a() { n(); };
function b() { c(); };
function c() { n(); };
function d() { x = 1; try { e(); } catch(x) { x = 2; } };
function e() { n(); };
function f() { x = 1; try { g(); } catch(x) { x = 2; } };
function g() { h(); };
function h() { x = 1; throw 1; };
`);
InspectorTest.runAsyncTestSuite([
async function testStepThrougA() {
Protocol.Debugger.pause();
await Protocol.Runtime.evaluate({expression: 'a()\n//# sourceURL=expr.js'});
},
async function testStepThrougB() {
Protocol.Debugger.pause();
await Protocol.Runtime.evaluate({expression: 'b()\n//# sourceURL=expr.js'});
},
async function testStepThrougD() {
await Protocol.Debugger.setPauseOnExceptions({state: 'uncaught'});
Protocol.Debugger.pause();
await Protocol.Runtime.evaluate({expression: 'd()\n//# sourceURL=expr.js'});
await Protocol.Debugger.setPauseOnExceptions({state: 'none'});
},
async function testStepThrougDWithBreakOnAllExceptions() {
await Protocol.Debugger.setPauseOnExceptions({state: 'all'});
Protocol.Debugger.pause();
await Protocol.Runtime.evaluate({expression: 'd()\n//# sourceURL=expr.js'});
await Protocol.Debugger.setPauseOnExceptions({state: 'none'});
},
async function testStepThrougF() {
await Protocol.Debugger.setPauseOnExceptions({state: 'uncaught'});
Protocol.Debugger.pause();
await Protocol.Runtime.evaluate({expression: 'f()\n//# sourceURL=expr.js'});
await Protocol.Debugger.setPauseOnExceptions({state: 'none'});
},
async function testStepThrougFWithBreakOnAllExceptions() {
await Protocol.Debugger.setPauseOnExceptions({state: 'all'});
Protocol.Debugger.pause();
await Protocol.Runtime.evaluate({expression: 'f()\n//# sourceURL=expr.js'});
await Protocol.Debugger.setPauseOnExceptions({state: 'none'});
}
]);

View File

@ -0,0 +1,56 @@
Check that "break on exceptions" works for async generators.
Running test: testSimpleGeneratorThrowCaught
Paused for CAUGHT exception.
Running test: testSimpleGeneratorThrowUncaught
Paused for UNCAUGHT exception.
Running test: testYieldBeforeThrowCaught
Paused for CAUGHT exception.
Running test: testYieldBeforeThrowUncaught
Paused for UNCAUGHT exception.
Running test: testAwaitBeforeThrowCaught
Paused for CAUGHT exception.
Running test: testAwaitBeforeThrowUncaught
Paused for UNCAUGHT exception.
Running test: testYieldBeforeThrowWithAwaitCaught
Paused for CAUGHT exception.
Running test: testYieldBeforeThrowWithAwaitUncaught
Paused for UNCAUGHT exception.
Running test: testAwaitBeforeThrowWithYieldCaught
Paused for CAUGHT exception.
Running test: testAwaitBeforeThrowWithYieldUncaught
Paused for UNCAUGHT exception.
Running test: testYieldThrowsCaught
Paused for CAUGHT exception.
Running test: testYieldThrowsUncaught
Paused for UNCAUGHT exception.
Running test: testYieldThrowsCaughtInGenerator
Paused for CAUGHT exception.
Paused for UNCAUGHT exception.
Running test: testAwaitThrowsCaught
Paused for CAUGHT exception.
Running test: testAwaitThrowsUncaught
Paused for UNCAUGHT exception.
Running test: testYieldThrowMethodCaught
Paused for CAUGHT exception.
Running test: testYieldThrowMethodUncaught
Paused for UNCAUGHT exception.
Running test: testYieldThrowMethodCaughtInGenerator
Paused for UNCAUGHT exception.

View File

@ -0,0 +1,153 @@
// Copyright 2023 the V8 project 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 "break on exceptions" works for async generators.');
contextGroup.addScript(`
async function* simpleThrow() {
throw new Error();
}
async function* yieldBeforeThrow() {
yield 1;
throw new Error();
}
async function* awaitBeforeThrow() {
await 1;
throw new Error();
}
async function* yieldBeforeThrowWithAwait() {
await 1;
yield 2;
throw new Error();
}
async function* awaitBeforeThrowWithYield() {
yield 1;
await 2;
throw new Error();
}
async function* yieldThrows() {
yield 1;
yield thrower();
}
async function* yieldThrowsCaughtInGenerator() {
try {
yield 1;
yield thrower();
} catch {
throw new Error();
}
}
async function* awaitThrows() {
yield 1;
await thrower();
}
async function runGenWithCatch(gen) {
try {
for await (const val of gen());
} catch {}
}
async function runGenWithoutCatch(gen) {
for await (const val of gen());
}
async function injectExceptionIntoGen(gen) {
const g = gen();
await gen.next();
await gen.throw(new Error());
}
async function injectExceptionIntoGenWithCatch(gen) {
try {
const g = gen();
await gen.next();
await gen.throw(new Error());
} catch {}
}
async function thrower() {
await 1; // Suspend once.
throw new Error();
}`);
Protocol.Debugger.onPaused(async ({ params: { data }}) => {
const caughtOrUncaught = data.uncaught ? 'UNCAUGHT' : 'CAUGHT';
InspectorTest.log(`Paused for ${caughtOrUncaught} exception.`);
await Protocol.Debugger.resume();
});
async function runTest(expression) {
await Promise.all([
Protocol.Debugger.enable(),
Protocol.Debugger.setPauseOnExceptions({state: 'all'}),
]);
await Protocol.Runtime.evaluate({ expression, awaitPromise: true });
await Protocol.Debugger.disable();
}
InspectorTest.runAsyncTestSuite([
async function testSimpleGeneratorThrowCaught() {
await runTest('runGenWithCatch(simpleThrow)');
},
async function testSimpleGeneratorThrowUncaught() {
await runTest('runGenWithoutCatch(simpleThrow)');
},
async function testYieldBeforeThrowCaught() {
await runTest('runGenWithCatch(yieldBeforeThrow)');
},
async function testYieldBeforeThrowUncaught() {
await runTest('runGenWithoutCatch(yieldBeforeThrow)');
},
async function testAwaitBeforeThrowCaught() {
await runTest('runGenWithCatch(awaitBeforeThrow)');
},
async function testAwaitBeforeThrowUncaught() {
await runTest('runGenWithoutCatch(awaitBeforeThrow)');
},
async function testYieldBeforeThrowWithAwaitCaught() {
await runTest('runGenWithCatch(yieldBeforeThrowWithAwait)');
},
async function testYieldBeforeThrowWithAwaitUncaught() {
await runTest('runGenWithoutCatch(yieldBeforeThrowWithAwait)');
},
async function testAwaitBeforeThrowWithYieldCaught() {
await runTest('runGenWithCatch(awaitBeforeThrowWithYield)');
},
async function testAwaitBeforeThrowWithYieldUncaught() {
await runTest('runGenWithoutCatch(awaitBeforeThrowWithYield)');
},
async function testYieldThrowsCaught() {
await runTest('runGenWithCatch(yieldThrows)');
},
async function testYieldThrowsUncaught() {
await runTest('runGenWithoutCatch(yieldThrows)');
},
async function testYieldThrowsCaughtInGenerator() {
await runTest('runGenWithoutCatch(yieldThrowsCaughtInGenerator)');
},
async function testAwaitThrowsCaught() {
await runTest('runGenWithCatch(awaitThrows)');
},
async function testAwaitThrowsUncaught() {
await runTest('runGenWithoutCatch(awaitThrows)');
},
async function testYieldThrowMethodCaught() {
await runTest('injectExceptionIntoGenWithCatch(yieldThrows)');
},
async function testYieldThrowMethodUncaught() {
await runTest('injectExceptionIntoGen(yieldThrows)');
},
async function testYieldThrowMethodCaughtInGenerator() {
await runTest('injectExceptionIntoGen(yieldThrowsCaughtInGenerator)');
},
]);

View File

@ -0,0 +1,91 @@
Break on exceptions from compiler errors.
Running test: testUnexpectedEndOfInput
Runs '+++'
Runtime.evaluate exceptionDetails:
{
columnNumber : 3
exception : {
className : SyntaxError
description : SyntaxError: Unexpected end of input
objectId : <objectId>
subtype : error
type : object
}
exceptionId : <exceptionId>
lineNumber : 0
scriptId : <scriptId>
text : Uncaught
}
Running test: testUnexpectedIdentifier
Runs 'x x'
Runtime.evaluate exceptionDetails:
{
columnNumber : 2
exception : {
className : SyntaxError
description : SyntaxError: Unexpected identifier 'x'
objectId : <objectId>
subtype : error
type : object
}
exceptionId : <exceptionId>
lineNumber : 0
scriptId : <scriptId>
text : Uncaught
}
Running test: testEvalUnexpectedEndOfInput
Runs eval('+++')
paused on exception:
{
className : SyntaxError
description : SyntaxError: Unexpected end of input at <anonymous>:1:1
objectId : <objectId>
subtype : error
type : object
uncaught : false
}
Runtime.evaluate exceptionDetails:
{
columnNumber : 3
exception : {
className : SyntaxError
description : SyntaxError: Unexpected end of input at <anonymous>:1:1
objectId : <objectId>
subtype : error
type : object
}
exceptionId : <exceptionId>
lineNumber : 0
scriptId : <scriptId>
text : Uncaught
}
Running test: testEvalUnexpectedIdentifier
Runs eval('x x')
paused on exception:
{
className : SyntaxError
description : SyntaxError: Unexpected identifier 'x' at <anonymous>:1:1
objectId : <objectId>
subtype : error
type : object
uncaught : false
}
Runtime.evaluate exceptionDetails:
{
columnNumber : 2
exception : {
className : SyntaxError
description : SyntaxError: Unexpected identifier 'x' at <anonymous>:1:1
objectId : <objectId>
subtype : error
type : object
}
exceptionId : <exceptionId>
lineNumber : 0
scriptId : <scriptId>
text : Uncaught
}

View File

@ -0,0 +1,52 @@
// Copyright 2018 the V8 project 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 on exceptions from compiler errors.');
Protocol.Debugger.enable();
Protocol.Debugger.setPauseOnExceptions({state: 'all'});
Protocol.Debugger.onPaused(({params:{data}}) => {
InspectorTest.log('paused on exception:');
InspectorTest.logMessage(data);
Protocol.Debugger.resume();
});
InspectorTest.runAsyncTestSuite([
async function testUnexpectedEndOfInput() {
InspectorTest.log(`Runs '+++'`);
let {result:{exceptionDetails}} = await Protocol.Runtime.evaluate({
expression: '+++'
});
InspectorTest.log('Runtime.evaluate exceptionDetails:');
InspectorTest.logMessage(exceptionDetails);
},
async function testUnexpectedIdentifier() {
InspectorTest.log(`Runs 'x x'`);
let {result:{exceptionDetails}} = await Protocol.Runtime.evaluate({
expression: 'x x'
});
InspectorTest.log('Runtime.evaluate exceptionDetails:');
InspectorTest.logMessage(exceptionDetails);
},
async function testEvalUnexpectedEndOfInput() {
InspectorTest.log(`Runs eval('+++')`);
let {result:{exceptionDetails}} = await Protocol.Runtime.evaluate({
expression: `eval('+++')`
});
InspectorTest.log('Runtime.evaluate exceptionDetails:');
InspectorTest.logMessage(exceptionDetails);
},
async function testEvalUnexpectedIdentifier() {
InspectorTest.log(`Runs eval('x x')`);
let {result:{exceptionDetails}} = await Protocol.Runtime.evaluate({
expression: `eval('x x')`
});
InspectorTest.log('Runtime.evaluate exceptionDetails:');
InspectorTest.logMessage(exceptionDetails);
}
]);

View File

@ -0,0 +1,175 @@
Tests for break on exception.
Running test: testPauseOnInitialState
evaluate 'caught()'..
evaluate 'uncaught()'..
evaluate 'uncaughtFinally()'..
evaluate 'caughtFinally()'..
Running test: testPauseOnExceptionOff
evaluate 'caught()'..
evaluate 'uncaught()'..
evaluate 'uncaughtFinally()'..
evaluate 'caughtFinally()'..
Running test: testBreakOnCaughtException
evaluate 'caught()'..
paused on exception:
{
description : 1
type : number
uncaught : false
value : 1
}
evaluate 'uncaught()'..
evaluate 'uncaughtFinally()'..
evaluate 'caughtFinally()'..
Running test: testBreakOnUncaughtException
evaluate 'caught()'..
evaluate 'uncaught()'..
paused on exception:
{
description : 1
type : number
uncaught : true
value : 1
}
evaluate 'uncaughtFinally()'..
paused on exception:
{
description : 1
type : number
uncaught : true
value : 1
}
evaluate 'caughtFinally()'..
paused on exception:
{
description : 1
type : number
uncaught : true
value : 1
}
Running test: testBreakOnAll
evaluate 'caught()'..
paused on exception:
{
description : 1
type : number
uncaught : false
value : 1
}
evaluate 'uncaught()'..
paused on exception:
{
description : 1
type : number
uncaught : true
value : 1
}
evaluate 'uncaughtFinally()'..
paused on exception:
{
description : 1
type : number
uncaught : true
value : 1
}
evaluate 'caughtFinally()'..
paused on exception:
{
description : 1
type : number
uncaught : true
value : 1
}
Running test: testTryFinallyOriginalMessage
evaluate '
try {
throw 1;
} finally {
}
'..
paused on exception:
{
description : 1
type : number
uncaught : true
value : 1
}
Running test: testPromiseRejectedByCallback
evaluate '
function fun() { eval("throw 'rejection';") }
var p = new Promise(function(res, rej) { fun(); res(); });
var r;
p.then(() => { r = 'resolved'; }, (e) => { r = 'rejected' + e; });
'..
paused on exception:
{
type : string
uncaught : true
value : rejection
}
r =
{
type : string
value : rejectedrejection
}
Running test: testBreakOnExceptionAfterReconnect
evaluate 'f()'..
paused on exception:
{
className : Error
description : Error at f (<anonymous>:115:153) at <anonymous>:146:163
objectId : <objectId>
subtype : error
type : object
uncaught : true
}
reconnect..
evaluate 'f()'..
paused on exception:
{
className : Error
description : Error at f (<anonymous>:115:153) at <anonymous>:146:163
objectId : <objectId>
subtype : error
type : object
uncaught : true
}
Running test: testBreakOnExceptionInSilentMode
evaluate 'caught()'
evaluate 'uncaught()'
evaluate 'uncaughtFinally()'
evaluate 'caughtFinally()'

View File

@ -0,0 +1,191 @@
Checks if catch prediction works on new `using` and `await using` syntax.
Running test: testPauseOnInitialState
evaluate 'disposalUncaughtUsingSyntax()'..
evaluate 'disposalUncaughtAwaitUsingSyntax()'..
evaluate 'disposalUncaughtSuppressedError()'..
evaluate 'disposalCaughtUsingSyntax()'..
evaluate 'disposalCaughtAwaitUsingSyntax()'..
evaluate 'disposalCaughtSuppressedError()'..
Running test: testPauseOnExceptionOff
evaluate 'disposalUncaughtUsingSyntax()'..
evaluate 'disposalUncaughtAwaitUsingSyntax()'..
evaluate 'disposalUncaughtSuppressedError()'..
evaluate 'disposalCaughtUsingSyntax()'..
evaluate 'disposalCaughtAwaitUsingSyntax()'..
evaluate 'disposalCaughtSuppressedError()'..
Running test: testBreakOnCaughtException
evaluate 'disposalUncaughtUsingSyntax()'..
evaluate 'disposalUncaughtAwaitUsingSyntax()'..
evaluate 'disposalUncaughtSuppressedError()'..
evaluate 'disposalCaughtUsingSyntax()'..
paused on exception:
{
description : 5
type : number
uncaught : false
value : 5
}
evaluate 'disposalCaughtAwaitUsingSyntax()'..
paused on exception:
{
description : 6
type : number
uncaught : false
value : 6
}
evaluate 'disposalCaughtSuppressedError()'..
paused on exception:
{
description : 8
type : number
uncaught : false
value : 8
}
paused on exception:
{
description : 7
type : number
uncaught : false
value : 7
}
Running test: testBreakOnUncaughtException
evaluate 'disposalUncaughtUsingSyntax()'..
paused on exception:
{
description : 1
type : number
uncaught : true
value : 1
}
evaluate 'disposalUncaughtAwaitUsingSyntax()'..
paused on exception:
{
description : 2
type : number
uncaught : true
value : 2
}
evaluate 'disposalUncaughtSuppressedError()'..
paused on exception:
{
description : 4
type : number
uncaught : true
value : 4
}
paused on exception:
{
description : 3
type : number
uncaught : true
value : 3
}
evaluate 'disposalCaughtUsingSyntax()'..
evaluate 'disposalCaughtAwaitUsingSyntax()'..
evaluate 'disposalCaughtSuppressedError()'..
Running test: testBreakOnAll
evaluate 'disposalUncaughtUsingSyntax()'..
paused on exception:
{
description : 1
type : number
uncaught : true
value : 1
}
evaluate 'disposalUncaughtAwaitUsingSyntax()'..
paused on exception:
{
description : 2
type : number
uncaught : true
value : 2
}
evaluate 'disposalUncaughtSuppressedError()'..
paused on exception:
{
description : 4
type : number
uncaught : true
value : 4
}
paused on exception:
{
description : 3
type : number
uncaught : true
value : 3
}
evaluate 'disposalCaughtUsingSyntax()'..
paused on exception:
{
description : 5
type : number
uncaught : false
value : 5
}
evaluate 'disposalCaughtAwaitUsingSyntax()'..
paused on exception:
{
description : 6
type : number
uncaught : false
value : 6
}
evaluate 'disposalCaughtSuppressedError()'..
paused on exception:
{
description : 8
type : number
uncaught : false
value : 8
}
paused on exception:
{
description : 7
type : number
uncaught : false
value : 7
}
Running test: testBreakOnExceptionInSilentMode
evaluate 'disposalUncaughtUsingSyntax()'
evaluate 'disposalUncaughtAwaitUsingSyntax()'
evaluate 'disposalUncaughtSuppressedError()'
evaluate 'disposalCaughtUsingSyntax()'
evaluate 'disposalCaughtAwaitUsingSyntax()'
evaluate 'disposalCaughtSuppressedError()'

View File

@ -0,0 +1,178 @@
// Copyright 2024 the V8 project 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: --js-staging
let {session, contextGroup, Protocol} = InspectorTest.start(
'Checks if catch prediction works on new `using` and `await using` syntax.');
Protocol.Debugger.enable();
Protocol.Debugger.onPaused(({params: {data}}) => {
InspectorTest.log('paused on exception:');
InspectorTest.logMessage(data);
Protocol.Debugger.resume();
});
contextGroup.addInlineScript(
`
function disposalUncaughtUsingSyntax() {
using x = {
value: 1,
[Symbol.dispose]() {
throw 1;
}
};
}
async function disposalUncaughtAwaitUsingSyntax() {
await using y = {
value: 2,
[Symbol.asyncDispose]() {
throw 2;
}
};
}
function disposalUncaughtSuppressedError() {
using x = {
value: 1,
[Symbol.dispose]() {
throw 3;
}
};
using y = {
value: 2,
[Symbol.dispose]() {
throw 4;
}
};
}
function disposalCaughtUsingSyntax() {
try {
using x = {
value: 1,
[Symbol.dispose]() {
throw 5;
}
};
} catch (e) {
}
}
async function disposalCaughtAwaitUsingSyntax() {
try {
await using y = {
value: 2,
[Symbol.asyncDispose]() {
throw 6;
}
};
} catch (e) {
}
}
function disposalCaughtSuppressedError() {
try {
using x = {
value: 1,
[Symbol.dispose]() {
throw 7;
}
};
using y = {
value: 2,
[Symbol.dispose]() {
throw 8;
}
};
} catch (e) {
}
}
`,
'test.js');
InspectorTest.runAsyncTestSuite([
async function testPauseOnInitialState() {
await evaluate('disposalUncaughtUsingSyntax()');
await evaluate('disposalUncaughtAwaitUsingSyntax()');
await evaluate('disposalUncaughtSuppressedError()');
await evaluate('disposalCaughtUsingSyntax()');
await evaluate('disposalCaughtAwaitUsingSyntax()');
await evaluate('disposalCaughtSuppressedError()');
},
async function testPauseOnExceptionOff() {
await Protocol.Debugger.setPauseOnExceptions({state: 'none'});
await evaluate('disposalUncaughtUsingSyntax()');
await evaluate('disposalUncaughtAwaitUsingSyntax()');
await evaluate('disposalUncaughtSuppressedError()');
await evaluate('disposalCaughtUsingSyntax()');
await evaluate('disposalCaughtAwaitUsingSyntax()');
await evaluate('disposalCaughtSuppressedError()');
await Protocol.Debugger.setPauseOnExceptions({state: 'none'});
},
async function testBreakOnCaughtException() {
await Protocol.Debugger.setPauseOnExceptions({state: 'caught'});
await evaluate('disposalUncaughtUsingSyntax()');
await evaluate('disposalUncaughtAwaitUsingSyntax()');
await evaluate('disposalUncaughtSuppressedError()');
await evaluate('disposalCaughtUsingSyntax()');
await evaluate('disposalCaughtAwaitUsingSyntax()');
await evaluate('disposalCaughtSuppressedError()');
await Protocol.Debugger.setPauseOnExceptions({state: 'none'});
},
async function testBreakOnUncaughtException() {
await Protocol.Debugger.setPauseOnExceptions({state: 'uncaught'});
await evaluate('disposalUncaughtUsingSyntax()');
await evaluate('disposalUncaughtAwaitUsingSyntax()');
await evaluate('disposalUncaughtSuppressedError()');
await evaluate('disposalCaughtUsingSyntax()');
await evaluate('disposalCaughtAwaitUsingSyntax()');
await evaluate('disposalCaughtSuppressedError()');
await Protocol.Debugger.setPauseOnExceptions({state: 'none'});
},
async function testBreakOnAll() {
await Protocol.Debugger.setPauseOnExceptions({state: 'all'});
await evaluate('disposalUncaughtUsingSyntax()');
await evaluate('disposalUncaughtAwaitUsingSyntax()');
await evaluate('disposalUncaughtSuppressedError()');
await evaluate('disposalCaughtUsingSyntax()');
await evaluate('disposalCaughtAwaitUsingSyntax()');
await evaluate('disposalCaughtSuppressedError()');
await Protocol.Debugger.setPauseOnExceptions({state: 'none'});
},
async function testBreakOnExceptionInSilentMode(next) {
await Protocol.Debugger.setPauseOnExceptions({state: 'all'});
InspectorTest.log(`evaluate 'disposalUncaughtUsingSyntax()'`);
await Protocol.Runtime.evaluate(
{expression: 'disposalUncaughtUsingSyntax()', silent: true});
InspectorTest.log(`evaluate 'disposalUncaughtAwaitUsingSyntax()'`);
await Protocol.Runtime.evaluate(
{expression: 'disposalUncaughtAwaitUsingSyntax()', silent: true});
InspectorTest.log(`evaluate 'disposalUncaughtSuppressedError()'`);
await Protocol.Runtime.evaluate(
{expression: 'disposalUncaughtSuppressedError()', silent: true});
InspectorTest.log(`evaluate 'disposalCaughtUsingSyntax()'`);
await Protocol.Runtime.evaluate(
{expression: 'disposalCaughtUsingSyntax()', silent: true});
InspectorTest.log(`evaluate 'disposalCaughtAwaitUsingSyntax()'`);
await Protocol.Runtime.evaluate(
{expression: 'disposalCaughtAwaitUsingSyntax()', silent: true});
InspectorTest.log(`evaluate 'disposalCaughtSuppressedError()'`);
await Protocol.Runtime.evaluate(
{expression: 'disposalCaughtSuppressedError()', silent: true});
await Protocol.Debugger.setPauseOnExceptions({state: 'none'});
}
]);
async function evaluate(expression) {
InspectorTest.log(`\nevaluate '${expression}'..`);
contextGroup.addInlineScript(expression);
await InspectorTest.waitForPendingTasks();
}

View File

@ -0,0 +1,481 @@
Checks that exceptions in framework code have correct stopping behavior.
Running test: testCase
> Running scenario throwUncaughtError, breaking on caught exceptions:
Uncaught exception: Uncaught Error
-- <empty> --
throwUncaughtError (framework.js:10:8)
runWithResolution (framework.js:53:12)
-- setTimeout --
(anonymous) (framework.js:62:31)
testWrapper (framework.js:62:8)
(anonymous) (test_framework.js:0:0)
Running test: testCase
> Running scenario throwUncaughtError, breaking on uncaught exceptions:
Uncaught exception: Uncaught Error
-- <empty> --
throwUncaughtError (framework.js:10:8)
runWithResolution (framework.js:53:12)
-- setTimeout --
(anonymous) (framework.js:62:31)
testWrapper (framework.js:62:8)
(anonymous) (test_framework.js:0:0)
Running test: testCase
> Running scenario throwCaughtError, breaking on caught exceptions:
console: Caught at Error
at throwCaughtError (framework.js:16:11)
at runWithResolution (framework.js:54:13)
console: finished without error
Running test: testCase
> Running scenario throwCaughtError, breaking on uncaught exceptions:
console: Caught at Error
at throwCaughtError (framework.js:16:11)
at runWithResolution (framework.js:54:13)
console: finished without error
Running test: testCase
> Running scenario catchErrorInFramework, breaking on caught exceptions:
console: Caught at Error
at throwUncaughtError (framework.js:11:9)
at wrapErrorHandler (framework.js:42:5)
at catchErrorInFramework (framework.js:23:3)
at runWithResolution (framework.js:54:13)
console: finished without error
Running test: testCase
> Running scenario catchErrorInFramework, breaking on uncaught exceptions:
console: Caught at Error
at throwUncaughtError (framework.js:11:9)
at wrapErrorHandler (framework.js:42:5)
at catchErrorInFramework (framework.js:23:3)
at runWithResolution (framework.js:54:13)
console: finished without error
Running test: testCase
> Running scenario frameworkFinallyMethod, breaking on caught exceptions:
console: finally in framework code
Uncaught exception: Uncaught Error
-- <empty> --
throwUncaughtError (framework.js:10:8)
uncaughtAsync (framework.js:32:2)
-- await --
frameworkFinallyMethod (framework.js:26:9)
runWithResolution (framework.js:53:12)
-- setTimeout --
(anonymous) (framework.js:62:31)
testWrapper (framework.js:62:8)
(anonymous) (test_framework.js:0:0)
Exception revoked for reason: Handler added to rejected promise
Uncaught exception: Uncaught Error
-- <empty> --
throwUncaughtError (framework.js:10:8)
uncaughtAsync (framework.js:32:2)
-- await --
frameworkFinallyMethod (framework.js:26:9)
runWithResolution (framework.js:53:12)
-- setTimeout --
(anonymous) (framework.js:62:31)
testWrapper (framework.js:62:8)
(anonymous) (test_framework.js:0:0)
Running test: testCase
> Running scenario frameworkFinallyMethod, breaking on uncaught exceptions:
console: finally in framework code
Uncaught exception: Uncaught Error
-- <empty> --
throwUncaughtError (framework.js:10:8)
uncaughtAsync (framework.js:32:2)
-- await --
frameworkFinallyMethod (framework.js:26:9)
runWithResolution (framework.js:53:12)
-- setTimeout --
(anonymous) (framework.js:62:31)
testWrapper (framework.js:62:8)
(anonymous) (test_framework.js:0:0)
Exception revoked for reason: Handler added to rejected promise
Uncaught exception: Uncaught Error
-- <empty> --
throwUncaughtError (framework.js:10:8)
uncaughtAsync (framework.js:32:2)
-- await --
frameworkFinallyMethod (framework.js:26:9)
runWithResolution (framework.js:53:12)
-- setTimeout --
(anonymous) (framework.js:62:31)
testWrapper (framework.js:62:8)
(anonymous) (test_framework.js:0:0)
Running test: testCase
> Running scenario catchErrorInUserCode, breaking on caught exceptions:
Paused
throwUncaughtError (framework.js:10:2)
catchErrorInUserCode (user.js:70:4)
runWithResolution (framework.js:53:12)
-- setTimeout --
(anonymous) (framework.js:62:31)
testWrapper (framework.js:62:8)
(anonymous) (test_framework.js:0:0)
console: Caught at Error
at throwUncaughtError (framework.js:11:9)
at catchErrorInUserCode (user.js:71:5)
at runWithResolution (framework.js:54:13)
console: finished without error
Running test: testCase
> Running scenario catchErrorInUserCode, breaking on uncaught exceptions:
console: Caught at Error
at throwUncaughtError (framework.js:11:9)
at catchErrorInUserCode (user.js:71:5)
at runWithResolution (framework.js:54:13)
console: finished without error
Running test: testCase
> Running scenario passErrorThroughUserCode, breaking on caught exceptions:
Uncaught exception: Uncaught Error
-- <empty> --
throwUncaughtError (framework.js:10:8)
passErrorThroughUserCode (user.js:77:2)
runWithResolution (framework.js:53:12)
-- setTimeout --
(anonymous) (framework.js:62:31)
testWrapper (framework.js:62:8)
(anonymous) (test_framework.js:0:0)
Running test: testCase
> Running scenario passErrorThroughUserCode, breaking on uncaught exceptions:
Paused
throwUncaughtError (framework.js:10:2)
passErrorThroughUserCode (user.js:77:2)
runWithResolution (framework.js:53:12)
-- setTimeout --
(anonymous) (framework.js:62:31)
testWrapper (framework.js:62:8)
(anonymous) (test_framework.js:0:0)
Uncaught exception: Uncaught Error
-- <empty> --
throwUncaughtError (framework.js:10:8)
passErrorThroughUserCode (user.js:77:2)
runWithResolution (framework.js:53:12)
-- setTimeout --
(anonymous) (framework.js:62:31)
testWrapper (framework.js:62:8)
(anonymous) (test_framework.js:0:0)
Running test: testCase
> Running scenario notAffectingUserCode, breaking on caught exceptions:
console: Caught at Error
at throwUncaughtError (framework.js:11:9)
at wrapErrorHandler (framework.js:42:5)
at catchErrorInFramework (framework.js:23:3)
at notAffectingUserCode (user.js:82:3)
at runWithResolution (framework.js:54:13)
console: finished without error
Running test: testCase
> Running scenario notAffectingUserCode, breaking on uncaught exceptions:
console: Caught at Error
at throwUncaughtError (framework.js:11:9)
at wrapErrorHandler (framework.js:42:5)
at catchErrorInFramework (framework.js:23:3)
at notAffectingUserCode (user.js:82:3)
at runWithResolution (framework.js:54:13)
console: finished without error
Running test: testCase
> Running scenario uncaughtWithAsyncUserCode, breaking on caught exceptions:
Uncaught exception: Uncaught Error
-- <empty> --
throwUncaughtError (framework.js:10:8)
uncaughtAsync (framework.js:32:2)
-- await --
uncaughtWithAsyncUserCode (user.js:85:8)
runWithResolution (framework.js:53:12)
-- setTimeout --
(anonymous) (framework.js:62:31)
testWrapper (framework.js:62:8)
(anonymous) (test_framework.js:0:0)
Running test: testCase
> Running scenario uncaughtWithAsyncUserCode, breaking on uncaught exceptions:
Paused
throwUncaughtError (framework.js:10:2)
uncaughtAsync (framework.js:32:2)
-- await --
uncaughtWithAsyncUserCode (user.js:85:8)
runWithResolution (framework.js:53:12)
-- setTimeout --
(anonymous) (framework.js:62:31)
testWrapper (framework.js:62:8)
(anonymous) (test_framework.js:0:0)
Uncaught exception: Uncaught Error
-- <empty> --
throwUncaughtError (framework.js:10:8)
uncaughtAsync (framework.js:32:2)
-- await --
uncaughtWithAsyncUserCode (user.js:85:8)
runWithResolution (framework.js:53:12)
-- setTimeout --
(anonymous) (framework.js:62:31)
testWrapper (framework.js:62:8)
(anonymous) (test_framework.js:0:0)
Running test: testCase
> Running scenario uncaughtWithAsyncUserCodeAndDelay, breaking on caught exceptions:
Uncaught exception: Uncaught Error
-- <empty> --
throwUncaughtError (framework.js:10:8)
uncaughtWithAsyncUserCodeAndDelay (user.js:90:2)
-- await --
runWithResolution (framework.js:53:12)
-- setTimeout --
(anonymous) (framework.js:62:31)
testWrapper (framework.js:62:8)
(anonymous) (test_framework.js:0:0)
Running test: testCase
> Running scenario uncaughtWithAsyncUserCodeAndDelay, breaking on uncaught exceptions:
Paused
throwUncaughtError (framework.js:10:2)
uncaughtWithAsyncUserCodeAndDelay (user.js:90:2)
-- await --
runWithResolution (framework.js:53:12)
-- setTimeout --
(anonymous) (framework.js:62:31)
testWrapper (framework.js:62:8)
(anonymous) (test_framework.js:0:0)
Uncaught exception: Uncaught Error
-- <empty> --
throwUncaughtError (framework.js:10:8)
uncaughtWithAsyncUserCodeAndDelay (user.js:90:2)
-- await --
runWithResolution (framework.js:53:12)
-- setTimeout --
(anonymous) (framework.js:62:31)
testWrapper (framework.js:62:8)
(anonymous) (test_framework.js:0:0)
Running test: testCase
> Running scenario uncaughtWithAsyncUserCodeMissingAwait, breaking on caught exceptions:
Paused
throwUncaughtError (framework.js:10:2)
uncaughtWithAsyncUserCodeAndDelay (user.js:90:2)
-- await --
uncaughtWithAsyncUserCodeMissingAwait (user.js:94:9)
runWithResolution (framework.js:53:12)
-- setTimeout --
(anonymous) (framework.js:62:31)
testWrapper (framework.js:62:8)
(anonymous) (test_framework.js:0:0)
Uncaught exception: Uncaught Error
-- <empty> --
throwUncaughtError (framework.js:10:8)
uncaughtWithAsyncUserCodeAndDelay (user.js:90:2)
-- await --
uncaughtWithAsyncUserCodeMissingAwait (user.js:94:9)
runWithResolution (framework.js:53:12)
-- setTimeout --
(anonymous) (framework.js:62:31)
testWrapper (framework.js:62:8)
(anonymous) (test_framework.js:0:0)
Running test: testCase
> Running scenario uncaughtWithAsyncUserCodeMissingAwait, breaking on uncaught exceptions:
Uncaught exception: Uncaught Error
-- <empty> --
throwUncaughtError (framework.js:10:8)
uncaughtWithAsyncUserCodeAndDelay (user.js:90:2)
-- await --
uncaughtWithAsyncUserCodeMissingAwait (user.js:94:9)
runWithResolution (framework.js:53:12)
-- setTimeout --
(anonymous) (framework.js:62:31)
testWrapper (framework.js:62:8)
(anonymous) (test_framework.js:0:0)
Running test: testCase
> Running scenario catchPassingThroughUserCode, breaking on caught exceptions:
Paused
throwUncaughtError (framework.js:10:2)
passErrorThroughUserCode (user.js:77:2)
wrapErrorHandler (framework.js:41:4)
catchPassingThroughUserCode (user.js:98:2)
runWithResolution (framework.js:53:12)
-- setTimeout --
(anonymous) (framework.js:62:31)
testWrapper (framework.js:62:8)
(anonymous) (test_framework.js:0:0)
console: Caught at Error
at throwUncaughtError (framework.js:11:9)
at passErrorThroughUserCode (user.js:78:3)
at wrapErrorHandler (framework.js:42:5)
at catchPassingThroughUserCode (user.js:99:3)
at runWithResolution (framework.js:54:13)
console: finished without error
Running test: testCase
> Running scenario catchPassingThroughUserCode, breaking on uncaught exceptions:
console: Caught at Error
at throwUncaughtError (framework.js:11:9)
at passErrorThroughUserCode (user.js:78:3)
at wrapErrorHandler (framework.js:42:5)
at catchPassingThroughUserCode (user.js:99:3)
at runWithResolution (framework.js:54:13)
console: finished without error
Running test: testCase
> Running scenario userException, breaking on caught exceptions:
Uncaught exception: Uncaught Error
-- <empty> --
userException (user.js:102:8)
runWithResolution (framework.js:53:12)
-- setTimeout --
(anonymous) (framework.js:62:31)
testWrapper (framework.js:62:8)
(anonymous) (test_framework.js:0:0)
Running test: testCase
> Running scenario userException, breaking on uncaught exceptions:
Paused
userException (user.js:102:2)
runWithResolution (framework.js:53:12)
-- setTimeout --
(anonymous) (framework.js:62:31)
testWrapper (framework.js:62:8)
(anonymous) (test_framework.js:0:0)
Uncaught exception: Uncaught Error
-- <empty> --
userException (user.js:102:8)
runWithResolution (framework.js:53:12)
-- setTimeout --
(anonymous) (framework.js:62:31)
testWrapper (framework.js:62:8)
(anonymous) (test_framework.js:0:0)
Running test: testCase
> Running scenario catchUserException, breaking on caught exceptions:
Paused
userException (user.js:102:2)
wrapErrorHandler (framework.js:41:4)
catchUserException (user.js:106:2)
runWithResolution (framework.js:53:12)
-- setTimeout --
(anonymous) (framework.js:62:31)
testWrapper (framework.js:62:8)
(anonymous) (test_framework.js:0:0)
console: Caught at Error
at userException (user.js:103:9)
at wrapErrorHandler (framework.js:42:5)
at catchUserException (user.js:107:3)
at runWithResolution (framework.js:54:13)
console: finished without error
Running test: testCase
> Running scenario catchUserException, breaking on uncaught exceptions:
console: Caught at Error
at userException (user.js:103:9)
at wrapErrorHandler (framework.js:42:5)
at catchUserException (user.js:107:3)
at runWithResolution (framework.js:54:13)
console: finished without error
Running test: testCase
> Running scenario nowhereToStop, breaking on caught exceptions:
console: finished without error
Uncaught exception: Uncaught SyntaxError: Unexpected token 'p', "ping" is not valid JSON
-- <empty> --
-- setTimeout --
nowhereToStop (user.js:110:2)
runWithResolution (framework.js:53:12)
-- setTimeout --
(anonymous) (framework.js:62:31)
testWrapper (framework.js:62:8)
(anonymous) (test_framework.js:0:0)
Running test: testCase
> Running scenario nowhereToStop, breaking on uncaught exceptions:
console: finished without error
Uncaught exception: Uncaught SyntaxError: Unexpected token 'p', "ping" is not valid JSON
-- <empty> --
-- setTimeout --
nowhereToStop (user.js:110:2)
runWithResolution (framework.js:53:12)
-- setTimeout --
(anonymous) (framework.js:62:31)
testWrapper (framework.js:62:8)
(anonymous) (test_framework.js:0:0)
Running test: testCase
> Running scenario userFinallyMethod, breaking on caught exceptions:
console: finally in user code
Uncaught exception: Uncaught Error
-- <empty> --
throwUncaughtError (framework.js:10:8)
uncaughtAsync (framework.js:32:2)
-- await --
userFinallyMethod (user.js:114:9)
runWithResolution (framework.js:53:12)
-- setTimeout --
(anonymous) (framework.js:62:31)
testWrapper (framework.js:62:8)
(anonymous) (test_framework.js:0:0)
Exception revoked for reason: Handler added to rejected promise
Uncaught exception: Uncaught Error
-- <empty> --
throwUncaughtError (framework.js:10:8)
uncaughtAsync (framework.js:32:2)
-- await --
userFinallyMethod (user.js:114:9)
runWithResolution (framework.js:53:12)
-- setTimeout --
(anonymous) (framework.js:62:31)
testWrapper (framework.js:62:8)
(anonymous) (test_framework.js:0:0)
Running test: testCase
> Running scenario userFinallyMethod, breaking on uncaught exceptions:
Paused
throwUncaughtError (framework.js:10:2)
uncaughtAsync (framework.js:32:2)
-- await --
userFinallyMethod (user.js:114:9)
runWithResolution (framework.js:53:12)
-- setTimeout --
(anonymous) (framework.js:62:31)
testWrapper (framework.js:62:8)
(anonymous) (test_framework.js:0:0)
console: finally in user code
Uncaught exception: Uncaught Error
-- <empty> --
throwUncaughtError (framework.js:10:8)
uncaughtAsync (framework.js:32:2)
-- await --
userFinallyMethod (user.js:114:9)
runWithResolution (framework.js:53:12)
-- setTimeout --
(anonymous) (framework.js:62:31)
testWrapper (framework.js:62:8)
(anonymous) (test_framework.js:0:0)
Exception revoked for reason: Handler added to rejected promise
Uncaught exception: Uncaught Error
-- <empty> --
throwUncaughtError (framework.js:10:8)
uncaughtAsync (framework.js:32:2)
-- await --
userFinallyMethod (user.js:114:9)
runWithResolution (framework.js:53:12)
-- setTimeout --
(anonymous) (framework.js:62:31)
testWrapper (framework.js:62:8)
(anonymous) (test_framework.js:0:0)

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,156 @@
// Copyright 2023 the V8 project 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 exceptions in framework code have correct stopping behavior.');
// framework.js
async function frameworkUncaught() {
await complicatedThrow(false);
}
async function frameworkCaught() {
await complicatedThrow(true);
}
async function uncaughtAsync() {
await delay();
throw new Error('Failed');
}
function delay() {
return new Promise(resolve => setTimeout(resolve, 0));
}
function branchPromise(func, branchCatches) {
const newPromise = func().then(()=>console.log('Will not print'));
if (branchCatches) {
newPromise.catch((e)=>console.error('Caught at ' + e.stack));
} else {
newPromise.then(()=>console.log('Also will not print'));
}
return newPromise;
}
async function frameworkAsync(func) {
await func();
}
function complicatedThrow(catches) {
return frameworkAsync(branchPromise.bind(null, frameworkAsync.bind(null, branchPromise.bind(null, uncaughtAsync, false)), catches));
}
async function testWrapper(testFunc) {
// testWrapper runs testFunc and completes successfully when testFunc
// completes, but does so in a setTimeout so that it doesn't catch any
// exceptions thrown by testFunc.
async function runWithResolution(resolve) {
try {
await testFunc();
console.log('finished without error');
} finally {
// Leave exceptions uncaught, but the testWrapper continues normally
// anyway. Needs to be in a setTimeout so that uncaught exceptions
// are handled before the test is complete.
setTimeout(resolve, 0);
}
}
await new Promise(resolve => setTimeout(runWithResolution.bind(null, resolve), 0));
}
// user.js
async function caughtInUser() {
try {
await complicatedThrow(false);
} catch (e) {
console.log('Caught in user code at ' + e.stack);
}
}
async function caughtInUserAndFramework() {
try {
await complicatedThrow(true);
} catch (e) {
console.log('Caught in user code at ' + e.stack);
}
}
async function uncaughtInUser() {
await complicatedThrow(false);
}
async function uncaughtInUserCaughtInFramework() {
await complicatedThrow(true);
}
function branchInUser() {
const p = complicatedThrow(false);
p.catch((e)=>console.error('Caught in user code at ' + e.stack));
return p;
}
// -------------------------------------
// Order of functions should match above so that line numbers match
const files = [
{
name: 'framework.js',
scenarios: [frameworkUncaught, frameworkCaught],
helpers: [uncaughtAsync, delay, branchPromise, frameworkAsync, complicatedThrow, testWrapper],
startLine: 9,
}, {
name: 'user.js',
scenarios: [caughtInUser, caughtInUserAndFramework, uncaughtInUser, uncaughtInUserCaughtInFramework, branchInUser],
helpers: [],
startLine: 64,
}
];
const allScenarios = [];
for (const {name, scenarios, helpers, startLine} of files) {
allScenarios.push(...scenarios);
const file = [...scenarios, ...helpers].join('\n\n');
contextGroup.addScript(file, startLine, 0, name);
}
session.setupScriptMap();
Protocol.Debugger.onPaused(message => {
InspectorTest.log('Paused');
session.logCallFrames(message.params.callFrames);
session.logAsyncStackTrace(message.params.asyncStackTrace);
InspectorTest.log('');
Protocol.Debugger.resume();
});
Protocol.Console.onMessageAdded(event => InspectorTest.log('console: ' + event.params.message.text));
Protocol.Debugger.enable();
Protocol.Debugger.setAsyncCallStackDepth({maxDepth: 6});
Protocol.Console.enable();
Protocol.Runtime.onExceptionRevoked(event => InspectorTest.log('Exception revoked for reason: ' + event.params.reason));
Protocol.Runtime.onExceptionThrown(event => {
InspectorTest.log(`Uncaught exception: ${event.params.exceptionDetails.text}`);
session.logAsyncStackTrace(event.params.exceptionDetails.stackTrace);
});
Protocol.Runtime.enable();
const testFunctions = [];
for (const scenario of allScenarios) {
for (const state of ['caught', 'uncaught']) {
for (const ignoreList of [true, false]) {
const patterns = ignoreList ? ['framework\.js'] : [];
testFunctions.push(async function testCase() {
InspectorTest.log(`> Running scenario ${scenario.name}, breaking on ${state} exceptions, ignore listing ${ignoreList ? 'on' : 'off'}:`);
await Protocol.Debugger.setPauseOnExceptions({state});
await Protocol.Debugger.setBlackboxPatterns({patterns});
await Protocol.Runtime.evaluate({expression: `testWrapper(${scenario.name})//# sourceURL=test_framework.js`, awaitPromise: true});
});
}
}
}
InspectorTest.runAsyncTestSuite(testFunctions);

View File

@ -0,0 +1,199 @@
// Copyright 2023 the V8 project 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 exceptions in framework code have correct stopping behavior.');
// framework.js
function throwUncaughtError() {
throw new Error();
}
function throwCaughtError() {
try {
throw new Error();
} catch (e) {
console.log('Caught at ' + e.stack);
}
}
function catchErrorInFramework() {
wrapErrorHandler(throwUncaughtError);
}
function frameworkFinallyMethod() {
return uncaughtAsync().finally(
() => console.log('finally in framework code'));
}
async function uncaughtAsync() {
await delay();
throwUncaughtError();
}
function delay() {
return new Promise(resolve => setTimeout(resolve, 0));
}
function wrapErrorHandler(errorFunc) {
try {
errorFunc();
} catch (e) {
console.log('Caught at ' + e.stack);
}
}
async function testWrapper(testFunc) {
// testWrapper runs testFunc and completes successfully when testFunc
// completes, but does so in a setTimeout so that it doesn't catch any
// exceptions thrown by testFunc.
async function runWithResolution(resolve) {
try {
await testFunc();
console.log('finished without error');
} finally {
// Leave exceptions uncaught, but the testWrapper continues normally
// anyway. Needs to be in a setTimeout so that uncaught exceptions
// are handled before the test is complete.
setTimeout(resolve, 0);
}
}
await new Promise(resolve => setTimeout(runWithResolution.bind(null, resolve),
0));
}
// user.js
function catchErrorInUserCode() {
try {
throwUncaughtError();
} catch (e) {
console.log('Caught at ' + e.stack);
}
}
function passErrorThroughUserCode() {
throwUncaughtError();
}
function notAffectingUserCode() {
catchErrorInFramework();
}
async function uncaughtWithAsyncUserCode() {
await uncaughtAsync();
}
async function uncaughtWithAsyncUserCodeAndDelay() {
await delay();
throwUncaughtError();
}
async function uncaughtWithAsyncUserCodeMissingAwait() {
return uncaughtWithAsyncUserCodeAndDelay();
}
function catchPassingThroughUserCode() {
wrapErrorHandler(passErrorThroughUserCode);
}
function userException() {
throw new Error();
}
function catchUserException() {
wrapErrorHandler(userException);
}
function nowhereToStop() {
setTimeout(JSON.parse.bind(null, 'ping'), 0);
}
function userFinallyMethod() {
return uncaughtAsync().finally(() => console.log('finally in user code'));
}
// -------------------------------------
// Order of functions should match above so that line numbers match
const files = [
{
name: 'framework.js',
scenarios: [
throwUncaughtError,
throwCaughtError,
catchErrorInFramework,
frameworkFinallyMethod
],
helpers: [uncaughtAsync, delay, wrapErrorHandler, testWrapper],
startLine: 9,
}, {
name: 'user.js',
scenarios: [
catchErrorInUserCode,
passErrorThroughUserCode,
notAffectingUserCode,
uncaughtWithAsyncUserCode,
uncaughtWithAsyncUserCodeAndDelay,
uncaughtWithAsyncUserCodeMissingAwait,
catchPassingThroughUserCode,
userException,
catchUserException,
nowhereToStop,
userFinallyMethod
],
helpers: [],
startLine: 68,
}
];
const allScenarios = [];
for (const {name, scenarios, helpers, startLine} of files) {
allScenarios.push(...scenarios);
const file = [...scenarios, ...helpers].join('\n\n');
contextGroup.addScript(file, startLine, 0, name);
}
session.setupScriptMap();
Protocol.Debugger.onPaused(message => {
InspectorTest.log('Paused');
session.logCallFrames(message.params.callFrames);
session.logAsyncStackTrace(message.params.asyncStackTrace);
InspectorTest.log('');
Protocol.Debugger.resume();
});
Protocol.Console.onMessageAdded(
event => InspectorTest.log('console: ' + event.params.message.text));
Protocol.Debugger.enable();
Protocol.Debugger.setAsyncCallStackDepth({maxDepth: 6});
Protocol.Console.enable();
Protocol.Debugger.setBlackboxPatterns({patterns: ['framework\.js']});
Protocol.Runtime.onExceptionRevoked(event => InspectorTest.log(
'Exception revoked for reason: ' + event.params.reason));
Protocol.Runtime.onExceptionThrown(event => {
InspectorTest.log(
`Uncaught exception: ${event.params.exceptionDetails.text}`);
session.logAsyncStackTrace(event.params.exceptionDetails.stackTrace);
});
Protocol.Runtime.enable();
const testFunctions = [];
for (const scenario of allScenarios) {
for (const state of ['caught', 'uncaught']) {
testFunctions.push(async function testCase() {
InspectorTest.log(`> Running scenario ${scenario.name}, breaking on ${state} exceptions:`);
await Protocol.Debugger.setPauseOnExceptions({state});
await Protocol.Runtime.evaluate({
expression: `testWrapper(${scenario.name})//# sourceURL=test_framework.js`,
awaitPromise: true
});
});
}
}
InspectorTest.runAsyncTestSuite(testFunctions);

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,633 @@
// Copyright 2023 the V8 project 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: --js-staging
let {session, contextGroup, Protocol} = InspectorTest.start('Checks when promise rejections are predicted to be caught.');
// catch-prediction.js
function rejectAfterDelayInPromiseConstructor() {
return new Promise((pass, reject) => setTimeout(() => reject(new Error('fail')), 0));
}
function promiseReject() {
return Promise.reject(new Error('fail'));
}
function throwInPromiseConstructor() {
return new Promise(() => {throw new Error('fail');});
}
function rejectInPromiseConstructor() {
return new Promise((pass, reject) => {
reject(new Error('fail'));
console.log('after reject');
});
}
function rejectAfterDelayInTryInPromiseConstructor() {
return new Promise((pass, reject) => setTimeout(() => {
try {
reject(new Error('fail'));
} catch(e) {
console.log('fake'); // Won't be hit
}
}, 0));
}
function rejectBindAfterDelay() {
// Unbreakable location because there will be nothing on the callstack
return new Promise((pass, reject) => setTimeout(reject.bind(null, new Error('fail')), 0));
}
function throwInPromiseTryCallback() {
return Promise.try(() => { throw new Error('fail'); });
}
async function throwFromAsync() {
throw new Error('fail');
}
async function throwFromAsyncAfterDelay() {
await delay();
throw new Error('fail');
}
function customRejectingThenable() {
// JS supports awaiting on user defined promise-like objects
return {
then(onFulfilled, onRejected) {
onRejected(new Error('fail'));
}
}
}
function customRejectingThenableAfterDelay() {
// JS supports awaiting on user defined promise-like objects
return {
then(onFulfilled, onRejected) {
setTimeout(() => onRejected(new Error('fail')), 0);
}
}
}
function exceptionInThen() {
return Promise.resolve().then(() => {throw new Error('fail');});
}
function exceptionInCatch() {
return Promise.reject(new Error('will catch')).catch(() => {
console.log('throwing again');
throw new Error('fail');
});
}
async function exceptionInAsyncGenerator() {
async function* gen() {
yield 1;
throw new Error('fail');
}
for await(const x of gen()) {}
}
async function rejectInGenerator() {
function* gen() {
yield promiseReject();
}
for await(const x of gen()) {}
}
async function rejectAfterDelayInGenerator() {
function* gen() {
yield rejectAfterDelayInPromiseConstructor();
}
for await(const x of gen()) {}
}
async function rejectInAsyncGenerator() {
async function* gen() {
yield promiseReject();
}
for await(const x of gen()) {}
}
async function rejectAfterDelayInAsyncGenerator() {
async function* gen() {
yield rejectAfterDelayInPromiseConstructor();
}
for await(const x of gen()) {}
}
async function asyncGeneratorThrowMethod() {
async function* gen() {
yield 1;
}
const g = gen();
await g.next();
await g.throw(new Error('fail'));
}
async function asyncCatchingGeneratorThrowMethod() {
async function* gen() {
try {
yield 1;
} catch (e) {
console.log('caught by generator');
}
}
const g = gen();
await g.next();
await g.throw(new Error('fail'));
}
async function throwInAsyncGenerator() {
async function* gen() {
yield 1;
throw new Error('fail');
}
for await(const x of gen()) {}
}
function promiseRejectInTry() {
// A synchronous try can't catch a promise rejection.
try {
return Promise.reject(new Error('fail'));
} catch (e) {
console.log('fake'); // Will not catch
}
}
function rejectAfterFulfillInPromiseConstructor() {
return new Promise((pass, reject) => {
pass('ok');
console.log('after pass');
reject(new Error('fail'));
console.log('after reject');
});
}
function rejectAfterDelayAfterFulfillInPromiseConstructor() {
return new Promise((pass, reject) => {
pass('ok');
setTimeout(() => reject(new Error('fail')), 0);
});
}
function throwAfterFulfillInPromiseConstructor() {
return new Promise((pass, reject) => {
pass('ok');
console.log('after pass');
throw new Error('fail');
});
}
async function throwInAsyncDisposeFormSync() {
await using x = {
value: 1,
[Symbol.dispose]() {
throw new Error('fail');
}
};
}
async function dontHandleAsync(fn) {
// Unhandled exception that is trivial to predict,
// for comparison.
await fn();
}
async function awaitAndCreateInTry(fn) {
try {
// The easy case to get right, for comparison.
await fn();
} catch(e) {
console.log('caught');
}
}
function catchMethod(fn) {
// Catch handler may not be attached at the time promise is rejected
fn().catch((e) => console.log('caught'));
}
function finallyMethod(fn) {
// Is a finally handler considered caught?
fn().finally(() => console.log('finally handler'));
}
function catchMethodInTry(fn) {
try {
fn().catch((e) => console.log('caught'));
} catch(e) {
console.log('fake'); // Won't be hit
}
}
async function awaitInTry(fn) {
// No handler when promise is created, but there is when it is awaited
const promise = fn();
try {
await promise;
} catch(e) {
console.log('caught');
}
}
async function awaitAndCreateInTryFinally(fn) {
try {
await fn();
} finally {
// Is finally handler treated as a catch?
console.log('finally handler');
}
}
async function createInTry(fn) {
let promise = null;
// In this test case we don't handle the exception,
// but first we try to convince JS we will.
try {
promise = fn();
} catch(e) {
console.log('fake'); // Won't be hit
}
if(promise) {
await promise;
}
}
function fireAndForgetInTry(fn) {
try {
// Unhandled exception, but will we mispredict as caught?
fn();
} catch(e) {
console.log('fake'); // Won't be hit
}
}
function finallyAndCatchMethod(fn) {
// Will we account for the catch method after the finally?
fn().finally(() => console.log('finally handler'))
.catch(() => console.log('caught'));
}
function thenMethod(fn) {
fn().then(() => console.log('not hit'));
}
function thenMethodWithTwoArgs(fn) {
fn().then(() => console.log('not hit'), () => console.log('caught'));
}
async function caughtPromiseRace(fn) {
try {
await Promise.race([fn()]);
} catch(e) {
console.log('caught');
}
}
async function caughtInTryPromiseRace(fn) {
const promise = fn();
try {
await Promise.race([promise]);
} catch(e) {
console.log('caught');
}
}
async function uncaughtPromiseRace(fn) {
await Promise.race([fn()]);
}
async function ignoredPromiseRace(fn) {
// Race will resolve to first promise, preventing exception from second
// from propagating. Is this caught or uncaught?
await Promise.race([Promise.resolve(), fn()]);
}
async function ignoredPromiseRaceInTry(fn) {
try {
// Race will resolve to first promise, preventing exception from second
// from propagating. Is this caught or uncaught?
await Promise.race([Promise.resolve(), fn()]);
} catch(e) {
console.log('caught');
}
}
async function caughtPromiseAll(fn) {
try {
await Promise.all([fn()]);
} catch(e) {
console.log('caught');
}
}
async function uncaughtPromiseAll(fn) {
await Promise.all([fn()]);
}
async function caughtPromiseAny(fn) {
try {
await Promise.any([fn()]);
} catch(e) {
console.log('caught');
}
}
async function uncaughtPromiseAny(fn) {
await Promise.any([fn()]);
}
async function ignoredPromiseAny(fn) {
// Any will resolve to first promise, preventing exception from second
// from propagating. Is this caught or uncaught?
await Promise.any([Promise.resolve(), fn()]);
}
async function ignoredPromiseAnyInTry(fn) {
try {
// Any will resolve to first promise, preventing exception from second
// from propagating. Is this caught or uncaught?
await Promise.any([Promise.resolve(), fn()]);
} catch(e) {
console.log('caught');
}
}
async function ignoredPromiseAnyWithIndirection(fn) {
// Similar to other ignored cases but we have to walk the promise tree to
// find the already fulfilled promise.
async function indirectThrow() {
await fn();
}
async function indirectAny() {
await Promise.any([Promise.resolve(), indirectThrow()]);
}
await indirectAny();
}
async function ignoredPromiseAnyWithIndirectionInTry(fn) {
async function indirectThrow() {
await fn();
}
try {
// Similar to other ignored cases but we have to walk the promise tree to
// find the already fulfilled promise.
await Promise.any([Promise.resolve(), indirectThrow()]);
} catch(e) {
console.log('caught');
}
}
async function awaitAfterDelayInTry(fn) {
try {
// Predicts correctly if thrown immediately but if not no handler will
// be attached when it throws.
const promise = fn();
console.log('sleeping');
await delay();
await delay();
console.log('awaiting');
await promise;
} catch(e) {
console.log('caught');
}
}
async function catchInAsyncGenerator(fn) {
async function* gen() {
try {
yield fn();
} catch (e) {
console.log('caught');
}
}
for await(const x of gen()) {}
}
async function catchInGenerator(fn) {
function* gen() {
try {
yield fn();
} catch (e) {
console.log('fake'); // Will not catch
}
}
for await(const x of gen()) {}
}
async function catchAndAlsoDont(fn) {
const uncaughtPromise = fn();
const caughtPromise = uncaughtPromise.catch(() => console.log('caught'));
await uncaughtPromise;
console.log('never reached');
}
function delay() {
return new Promise(resolve => setTimeout(resolve, 0));
}
async function testWrapper(throwFunc, handleFunc) {
// testWrapper runs testFunc and completes successfully when testFunc
// completes, but does so in a setTimeout so that it doesn't catch any
// exceptions thrown by testFunc.
async function runWithResolution(resolve) {
try {
const promise = handleFunc(throwFunc);
console.log('awaiting promise');
await promise;
console.log('finished without error');
} finally {
// Leave exceptions uncaught, but the testWrapper continues normally
// anyway. Needs to be in a setTimeout so that uncaught exceptions
// are handled before the test is complete.
setTimeout(resolve, 0);
}
}
await new Promise(resolve => setTimeout(runWithResolution.bind(null, resolve), 0));
}
// -------------------------------------
// Order of functions should match above so that line numbers match
const basicThrowFunctions = [rejectAfterDelayInPromiseConstructor, promiseReject];
const advancedThrowFunctions = [
throwInPromiseConstructor,
rejectInPromiseConstructor,
rejectAfterDelayInTryInPromiseConstructor,
rejectBindAfterDelay,
throwFromAsync,
throwFromAsyncAfterDelay,
customRejectingThenable,
customRejectingThenableAfterDelay,
exceptionInThen,
exceptionInCatch,
exceptionInAsyncGenerator,
rejectInGenerator,
rejectAfterDelayInGenerator,
rejectInAsyncGenerator,
rejectAfterDelayInAsyncGenerator,
asyncGeneratorThrowMethod,
asyncCatchingGeneratorThrowMethod,
throwInAsyncGenerator,
promiseRejectInTry,
rejectAfterFulfillInPromiseConstructor,
rejectAfterDelayAfterFulfillInPromiseConstructor,
throwAfterFulfillInPromiseConstructor,
throwInPromiseTryCallback,
throwInAsyncDisposeFormSync
];
const basicCatchFunctions = [dontHandleAsync, awaitAndCreateInTry];
const advancedCatchFunctions = [
catchMethod,
finallyMethod,
catchMethodInTry,
awaitInTry,
awaitAndCreateInTryFinally,
createInTry,
fireAndForgetInTry,
finallyAndCatchMethod,
thenMethod,
thenMethodWithTwoArgs,
caughtPromiseRace,
caughtInTryPromiseRace,
uncaughtPromiseRace,
ignoredPromiseRace,
ignoredPromiseRaceInTry,
caughtPromiseAll,
uncaughtPromiseAll,
caughtPromiseAny,
uncaughtPromiseAny,
ignoredPromiseAny,
ignoredPromiseAnyInTry,
ignoredPromiseAnyWithIndirection,
ignoredPromiseAnyWithIndirectionInTry,
awaitAfterDelayInTry,
catchInAsyncGenerator,
catchInGenerator,
catchAndAlsoDont,
];
const helpers = [delay, testWrapper];
const file = [...basicThrowFunctions, ...advancedThrowFunctions, ...basicCatchFunctions, ...advancedCatchFunctions, ...helpers].join('\n\n');
const startLine = 9; // Should match first line of first function
contextGroup.addScript(file, startLine, 0, 'catch-prediction.js');
session.setupScriptMap();
let pauseCount = 0
let uncaught = false;
let predictedUncaught = null;
let exceptionDetails = null;
let exceptionStackTrace = null;
let exceptionId = null;
function lazyLogException() {
if (exceptionDetails || exceptionStackTrace) {
InspectorTest.log(`Uncaught exception: ${exceptionDetails}`);
session.logAsyncStackTrace(exceptionStackTrace);
}
exceptionDetails = null;
exceptionStackTrace = null;
}
function uncaughtString(uncaught) {
return ((uncaught && 'uncaught') ?? '(undefined)') || 'caught';
}
Protocol.Debugger.onPaused(message => {
lazyLogException();
predictedUncaught = message.params.data?.uncaught;
InspectorTest.log(`Paused on ${uncaughtString(predictedUncaught)} ${message.params.reason}`);
session.logCallFrames(message.params.callFrames);
session.logAsyncStackTrace(message.params.asyncStackTrace);
InspectorTest.log('');
pauseCount++;
Protocol.Debugger.resume();
});
Protocol.Console.onMessageAdded(event => {
lazyLogException();
InspectorTest.log('console: ' + event.params.message.text);
});
Protocol.Debugger.enable();
Protocol.Debugger.setAsyncCallStackDepth({maxDepth: 6});
Protocol.Console.enable();
Protocol.Runtime.onExceptionRevoked(event => {
if (!uncaught) {
InspectorTest.log('ERROR: Revoked exception when none thrown');
} else if (!exceptionId) {
InspectorTest.log('ERROR: No exception id');
} else if (exceptionId !== event.params.exceptionId) {
InspectorTest.log('ERROR: exception id does not match');
}
exceptionId = null;
uncaught = false;
let message = 'Previously printed uncaught exception revoked';
if (exceptionDetails || exceptionStackTrace) {
message = 'Uncaught message immediately revoked';
exceptionDetails = null;
exceptionStackTrace = null;
}
InspectorTest.log(message + ' for reason: ' + event.params.reason)
});
Protocol.Runtime.onExceptionThrown(event => {
lazyLogException();
if (uncaught) {
InspectorTest.log('ERROR: Uncaught exception thrown twice');
}
uncaught = true;
// Save this info and lazily log it so we can not log it when it is
// immediately revoked.
exceptionDetails = event.params.exceptionDetails.text;
exceptionStackTrace = event.params.exceptionDetails.stackTrace;
exceptionId = event.params.exceptionDetails.exceptionId;
});
Protocol.Runtime.enable();
const testFunctions = [];
function addTestFunctionsFor(throwFunc, catchFunc) {
async function testCase(next) {
InspectorTest.log(`> Throwing from ${throwFunc.name}, handling with ${catchFunc.name}`);
await Protocol.Debugger.setPauseOnExceptions({state: 'all'});
uncaught = false;
pauseCount = 0;
predictedUncaught = null;
exceptionId = null;
await Protocol.Runtime.evaluate({expression: `testWrapper(${throwFunc.name}, ${catchFunc.name})//# sourceURL=test_framework.js`, awaitPromise: true});
lazyLogException();
InspectorTest.log('');
if (pauseCount !== 1) {
InspectorTest.log(`WARNING: Test paused ${pauseCount} times`);
}
if (pauseCount > 0) {
if (uncaught === predictedUncaught) {
InspectorTest.log('Correctly predicted as ' + uncaughtString(uncaught));
} else {
InspectorTest.log(`PREDICTION MISMATCH: Exception was ${uncaughtString(uncaught)} but was predicted to be ${uncaughtString(predictedUncaught)}`);
}
}
InspectorTest.log('------------------------------------------------------');
}
testFunctions.push(testCase);
}
for (const throwFunc of [...basicThrowFunctions, ...advancedThrowFunctions]) {
for (const catchFunc of basicCatchFunctions) {
addTestFunctionsFor(throwFunc, catchFunc);
}
}
for (const catchFunc of advancedCatchFunctions) {
for (const throwFunc of basicThrowFunctions) {
addTestFunctionsFor(throwFunc, catchFunc);
}
}
InspectorTest.runAsyncTestSuite(testFunctions);

View File

@ -0,0 +1,147 @@
// Copyright 2018 the V8 project 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 for break on exception.');
Protocol.Debugger.enable();
Protocol.Debugger.onPaused(({params:{data}}) => {
InspectorTest.log('paused on exception:');
InspectorTest.logMessage(data);
Protocol.Debugger.resume();
});
contextGroup.addInlineScript(`
function throws() {
throw 1;
}
function caught() {
try {
throws();
} catch (e) {
}
}
function uncaught() {
throws();
}
function uncaughtFinally() {
try {
throws();
} finally {
}
}
function caughtFinally() {
L: try {
throws();
} finally {
break L;
}
}
`, 'test.js');
InspectorTest.runAsyncTestSuite([
async function testPauseOnInitialState() {
await evaluate('caught()');
await evaluate('uncaught()');
await evaluate('uncaughtFinally()');
await evaluate('caughtFinally()');
},
async function testPauseOnExceptionOff() {
await Protocol.Debugger.setPauseOnExceptions({state: 'none'});
await evaluate('caught()');
await evaluate('uncaught()');
await evaluate('uncaughtFinally()');
await evaluate('caughtFinally()');
await Protocol.Debugger.setPauseOnExceptions({state: 'none'});
},
async function testBreakOnCaughtException() {
await Protocol.Debugger.setPauseOnExceptions({state: 'caught'});
await evaluate('caught()');
await evaluate('uncaught()');
await evaluate('uncaughtFinally()');
await evaluate('caughtFinally()');
await Protocol.Debugger.setPauseOnExceptions({state: 'none'});
},
async function testBreakOnUncaughtException() {
await Protocol.Debugger.setPauseOnExceptions({state: 'uncaught'});
await evaluate('caught()');
await evaluate('uncaught()');
await evaluate('uncaughtFinally()');
await evaluate('caughtFinally()');
await Protocol.Debugger.setPauseOnExceptions({state: 'none'});
},
async function testBreakOnAll() {
await Protocol.Debugger.setPauseOnExceptions({state: 'all'});
await evaluate('caught()');
await evaluate('uncaught()');
await evaluate('uncaughtFinally()');
await evaluate('caughtFinally()');
await Protocol.Debugger.setPauseOnExceptions({state: 'none'});
},
async function testTryFinallyOriginalMessage() {
await Protocol.Debugger.setPauseOnExceptions({state: 'all'});
await evaluate(`
try {
throw 1;
} finally {
}
`);
await Protocol.Debugger.setPauseOnExceptions({state: 'none'});
},
async function testPromiseRejectedByCallback() {
await Protocol.Debugger.setPauseOnExceptions({state: 'uncaught'});
await evaluate(`
function fun() { eval("throw 'rejection';") }
var p = new Promise(function(res, rej) { fun(); res(); });
var r;
p.then(() => { r = 'resolved'; }, (e) => { r = 'rejected' + e; });
`);
InspectorTest.log('r = ');
InspectorTest.logMessage((await Protocol.Runtime.evaluate({
expression: 'r'
})).result.result);
await Protocol.Debugger.setPauseOnExceptions({state: 'none'});
},
async function testBreakOnExceptionAfterReconnect() {
contextGroup.addInlineScript('function f() { throw new Error(); }');
await Protocol.Debugger.setPauseOnExceptions({state: 'uncaught'});
await evaluate('f()');
InspectorTest.log('\nreconnect..');
session.reconnect();
await evaluate('f()');
await Protocol.Debugger.setPauseOnExceptions({state: 'none'});
},
async function testBreakOnExceptionInSilentMode(next) {
await Protocol.Debugger.setPauseOnExceptions({ state: "all" });
InspectorTest.log(`evaluate 'caught()'`);
await Protocol.Runtime.evaluate({expression: 'caught()', silent: true});
InspectorTest.log(`evaluate 'uncaught()'`);
await Protocol.Runtime.evaluate({expression: 'uncaught()', silent: true});
InspectorTest.log(`evaluate 'uncaughtFinally()'`);
await Protocol.Runtime.evaluate({
expression: 'uncaughtFinally()',
silent: true
});
InspectorTest.log(`evaluate 'caughtFinally()'`);
await Protocol.Runtime.evaluate({
xpression: 'caughtFinally()',
silent: true
});
await Protocol.Debugger.setPauseOnExceptions({state: 'none'});
}
]);
async function evaluate(expression) {
InspectorTest.log(`\nevaluate '${expression}'..`);
contextGroup.addInlineScript(expression);
await InspectorTest.waitForPendingTasks();
}

View File

@ -0,0 +1,26 @@
Tests how breakpoints and side effects live together.
Test breakpoint, should pause inside foo:
foo (test.js:3:2)
(anonymous) (:0:0)
Run foo with no side effects:
{
className : EvalError
description : EvalError: Possible side-effect in debug-evaluate
objectId : <objectId>
subtype : error
type : object
}
Test breakpoint after run with side effect check:
foo (test.js:3:2)
(anonymous) (:0:0)
Run foo with no side effects after debugger disabled:
{
className : EvalError
description : EvalError: Possible side-effect in debug-evaluate
objectId : <objectId>
subtype : error
type : object
}

View File

@ -0,0 +1,58 @@
// Copyright 2018 the V8 project 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 how breakpoints and side effects live together.');
(async function main() {
session.setupScriptMap();
Protocol.Debugger.enable();
Protocol.Runtime.evaluate({expression: `
var a = 1;
function foo() {
a = 2;
}
//# sourceURL=test.js`});
Protocol.Debugger.setBreakpointByUrl({url: 'test.js', lineNumber: 3});
InspectorTest.log('Test breakpoint, should pause inside foo:');
{
const evaluatePromise = Protocol.Runtime.evaluate({expression: 'foo()'});
const {params:{callFrames}} = await Protocol.Debugger.oncePaused();
session.logCallFrames(callFrames);
Protocol.Debugger.resume();
await evaluatePromise;
}
InspectorTest.log('\nRun foo with no side effects:');
{
const {result:{result}} = await Protocol.Runtime.evaluate({
expression: 'foo()',
throwOnSideEffect: true
});
InspectorTest.logMessage(result);
}
InspectorTest.log('\nTest breakpoint after run with side effect check:');
{
const evaluatePromise = Protocol.Runtime.evaluate({expression: 'foo()'});
const {params:{callFrames}} = await Protocol.Debugger.oncePaused();
session.logCallFrames(callFrames);
Protocol.Debugger.resume();
await evaluatePromise;
}
await Protocol.Debugger.disable();
InspectorTest.log('\nRun foo with no side effects after debugger disabled:');
{
const {result:{result}} = await Protocol.Runtime.evaluate({
expression: 'foo()',
throwOnSideEffect: true
});
InspectorTest.logMessage(result);
}
InspectorTest.completeTest();
})();

View File

@ -0,0 +1,66 @@
Checks breakpoints.
Running test: testRemoveBreakpoint
Debugger.removeBreakpoint when agent is disabled:
{
error : {
code : -32000
message : Debugger agent is not enabled
}
id : <messageId>
}
Remove breakpoint with invalid breakpoint id:
{
id : <messageId>
result : {
}
}
{
id : <messageId>
result : {
}
}
Running test: testSetBreakpointByUrl
Adding conditional (arg === 1) breakpoint
evaluating foo1(0):
not paused
evaluating foo1(1):
hit expected breakpoint
Evaluating another script with the same url
evaluating foo2(0):
not paused
evaluating foo2(1):
hit expected breakpoint
Removing breakpoint
evaluating foo1(1):
not paused
evaluating foo2(1):
not paused
Adding breakpoint back
evaluating foo1(0):
not paused
evaluating foo1(1):
hit expected breakpoint
Disabling debugger agent
evaluating foo1(1):
not paused
evaluating foo2(1):
not paused
Enabling debugger agent
evaluating foo1(1):
not paused
evaluating foo2(1):
not paused
Running test: testSetBreakpointInScriptsWithDifferentOffsets
Adding breakpoint
evaluating foo1(0):
hit expected breakpoint
evaluating foo2(0):
hit expected breakpoint

View File

@ -0,0 +1,117 @@
// 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 breakpoints.');
session.setupScriptMap();
InspectorTest.runAsyncTestSuite([
async function testRemoveBreakpoint() {
InspectorTest.log('Debugger.removeBreakpoint when agent is disabled:');
InspectorTest.logMessage(await Protocol.Debugger.removeBreakpoint({
breakpointId: '1:test.js:0:0'
}));
Protocol.Debugger.enable();
InspectorTest.log('Remove breakpoint with invalid breakpoint id:')
InspectorTest.logMessage(await Protocol.Debugger.removeBreakpoint({
breakpointId: ''
}));
InspectorTest.logMessage(await Protocol.Debugger.removeBreakpoint({
breakpointId: ':::'
}));
await Protocol.Debugger.disable();
},
async function testSetBreakpointByUrl() {
await Protocol.Debugger.enable();
Protocol.Runtime.evaluate({expression: `
function foo1(arg) {
return arg;
}
//# sourceURL=testSetBreakpointByUrl.js`});
InspectorTest.log('Adding conditional (arg === 1) breakpoint');
let {result:{breakpointId}} = await Protocol.Debugger.setBreakpointByUrl({
lineNumber: 2,
url: 'testSetBreakpointByUrl.js',
columnNumber: 2,
condition: 'arg === 1'
});
await evaluate('foo1(0)');
await evaluate('foo1(1)', breakpointId);
InspectorTest.log('\nEvaluating another script with the same url')
Protocol.Runtime.evaluate({expression: `
function foo2(arg) {
return arg;
}
//# sourceURL=testSetBreakpointByUrl.js`});
await evaluate('foo2(0)');
await evaluate('foo2(1)', breakpointId);
InspectorTest.log('\nRemoving breakpoint');
await Protocol.Debugger.removeBreakpoint({breakpointId});
await evaluate('foo1(1)');
await evaluate('foo2(1)');
InspectorTest.log('\nAdding breakpoint back');
({result:{breakpointId}} = await Protocol.Debugger.setBreakpointByUrl({
lineNumber: 2,
url: 'testSetBreakpointByUrl.js',
columnNumber: 2,
condition: 'arg === 1'
}));
await evaluate('foo1(0)');
await evaluate('foo1(1)', breakpointId);
InspectorTest.log('\nDisabling debugger agent');
await Protocol.Debugger.disable();
await evaluate('foo1(1)');
await evaluate('foo2(1)');
InspectorTest.log('\nEnabling debugger agent');
await Protocol.Debugger.enable();
await evaluate('foo1(1)');
await evaluate('foo2(1)');
},
async function testSetBreakpointInScriptsWithDifferentOffsets() {
await Protocol.Debugger.enable();
InspectorTest.log('Adding breakpoint');
let {result:{breakpointId}} = await Protocol.Debugger.setBreakpointByUrl({
lineNumber: 2,
url: 'test2.js',
columnNumber: 2,
});
contextGroup.addScript(`
function foo1(arg) {
return arg;
}
//# sourceURL=test2.js`);
contextGroup.addScript(`
function foo2(arg) {
return arg;
}
//# sourceURL=test2.js`, 5);
await evaluate('foo1(0)', breakpointId);
await evaluate('foo2(0)', breakpointId);
}
]);
async function evaluate(expression, expectedBreakpoint) {
InspectorTest.log('evaluating ' + expression + ':');
let paused = Protocol.Debugger.oncePaused();
let evaluate = Protocol.Runtime.evaluate({expression});
let result = await Promise.race([paused, evaluate]);
if (result.method === 'Debugger.paused') {
if (result.params.hitBreakpoints) {
if (result.params.hitBreakpoints.find(b => b === expectedBreakpoint)) {
InspectorTest.log(' hit expected breakpoint')
} else {
InspectorTest.log(' hit unexpected breakpoint');
}
}
await Protocol.Debugger.resume();
} else {
InspectorTest.log(' not paused');
}
}

View File

@ -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}

View File

@ -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();
}

View File

@ -0,0 +1,15 @@
Tests url in Debugger.CallFrame.
[
[0] : {
url :
}
[1] : {
url :
}
[2] : {
url :
}
[3] : {
url :
}
]

View File

@ -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();
})();

View File

@ -0,0 +1,4 @@
Async caught exception prediction and blackboxing.
paused at:
#debugger;

View File

@ -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;
}

View File

@ -0,0 +1,13 @@
Check that inspector correctly passes caught/uncaught information.
paused in throwCaught
uncaught: false
paused in throwUncaught
uncaught: true
paused in throwInPromiseCaught
uncaught: false
paused in promiseUncaught
uncaught: true
paused in throwInMapConstructor
uncaught: true
paused in throwInAsyncIterator
uncaught: true

View File

@ -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("Check that inspector correctly passes caught/uncaught information.");
contextGroup.addScript(
`function throwCaught() { try { throw new Error(); } catch (_) {} }
function throwUncaught() { throw new Error(); }
function throwInPromiseCaught() {
var reject;
new Promise(function(res, rej) { reject = rej; }).catch(() => {});
reject();
}
function throwInPromiseUncaught() {
new Promise(function promiseUncaught() { throw new Error(); });
}
function throwInMapConstructor() { new Map('a'); }
function throwInAsyncIterator() {
let it = (async function*() {})();
it.next.call({});
}
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(() => Protocol.Runtime.evaluate(
{ "expression": "schedule(throwInPromiseCaught);"}))
.then(() => Protocol.Runtime.evaluate(
{ "expression": "schedule(throwInPromiseUncaught);"}))
.then(() => Protocol.Runtime.evaluate(
{ "expression": "schedule(throwInMapConstructor);"}))
.then(() => Protocol.Runtime.evaluate(
{ "expression": "schedule(throwInAsyncIterator);"}))
.then(() => InspectorTest.completeTest());

View File

@ -0,0 +1,35 @@
Checks that we can update return value on pause
Running test: testError
Set return value not at return position
{
error : {
code : -32000
message : Could not update return value at non-return position
}
id : <messageId>
}
Running test: testUndefined
Break at return position..
Update return value to 42..
Dump actual return value
{
result : {
description : 42
type : number
value : 42
}
}
Running test: testArrow
Break at return position..
Update return value to 239..
Dump actual return value
{
result : {
description : 239
type : number
value : 239
}
}

View File

@ -0,0 +1,68 @@
// 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 can update return value on pause');
InspectorTest.runAsyncTestSuite([
async function testError() {
Protocol.Debugger.enable();
let evaluation = Protocol.Runtime.evaluate({
expression: 'function foo() { debugger; } foo()',
returnByValue: true
});
let {params:{callFrames}} = await Protocol.Debugger.oncePaused();
InspectorTest.log('Set return value not at return position');
let result = await Protocol.Debugger.setReturnValue({
newValue: { value: 42 },
});
InspectorTest.logMessage(result);
await Protocol.Debugger.disable();
},
async function testUndefined() {
Protocol.Debugger.enable();
let evaluation = Protocol.Runtime.evaluate({
expression: 'function foo() { debugger; } foo()',
returnByValue: true
});
InspectorTest.log('Break at return position..');
await Protocol.Debugger.oncePaused();
Protocol.Debugger.stepInto();
let {params:{callFrames}} = await Protocol.Debugger.oncePaused();
InspectorTest.log('Update return value to 42..');
Protocol.Debugger.setReturnValue({
newValue: { value: 42 },
});
Protocol.Debugger.resume();
let {result} = await evaluation;
InspectorTest.log('Dump actual return value');
InspectorTest.logMessage(result);
await Protocol.Debugger.disable();
},
async function testArrow() {
Protocol.Debugger.enable();
Protocol.Debugger.pause();
let evaluation = Protocol.Runtime.evaluate({
expression: '(() => 42)()',
returnByValue: true
});
InspectorTest.log('Break at return position..');
await Protocol.Debugger.oncePaused();
Protocol.Debugger.stepInto();
await Protocol.Debugger.oncePaused();
Protocol.Debugger.stepInto();
let {params:{callFrames}} = await Protocol.Debugger.oncePaused();
InspectorTest.log('Update return value to 239..');
Protocol.Debugger.setReturnValue({
newValue: { value: 239 },
});
Protocol.Debugger.resume();
let {result} = await evaluation;
InspectorTest.log('Dump actual return value');
InspectorTest.logMessage(result);
await Protocol.Debugger.disable();
}
]);

File diff suppressed because it is too large Load Diff

View File

@ -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(
"Test class fields scopes"
);
contextGroup.addScript(`
function run() {
function foo() {
debugger;
return "foo";
}
function bar() {
return 3;
}
class X {
x = 1;
[foo()] = 2;
p = bar();
}
debugger;
new X;
}`);
InspectorTest.runAsyncTestSuite([
async function testScopesPaused() {
Protocol.Debugger.enable();
Protocol.Runtime.evaluate({ expression: "run()" });
let {
params: { callFrames: callFrames0 }
} = await Protocol.Debugger.oncePaused(); // inside foo()
InspectorTest.logMessage(callFrames0);
Protocol.Debugger.resume();
await Protocol.Debugger.oncePaused(); // at debugger;
Protocol.Debugger.stepOver(); // at debugger;
await Protocol.Debugger.oncePaused(); // at new X;
Protocol.Debugger.stepInto(); // step into initializer_function;
// at x = 1;
let {
params: { callFrames: callFrames1 }
} = await Protocol.Debugger.oncePaused();
InspectorTest.logMessage(callFrames1);
Protocol.Debugger.stepOver();
// at [foo()] = 2;
let {
params: { callFrames: callFrames2 }
} = await Protocol.Debugger.oncePaused();
InspectorTest.logMessage(callFrames2);
Protocol.Debugger.stepOver();
// at p = bar();
let {
params: { callFrames: callFrames3 }
} = await Protocol.Debugger.oncePaused();
InspectorTest.logMessage(callFrames3);
Protocol.Debugger.stepInto();
// inside bar();
let {
params: { callFrames: callFrames4 }
} = await Protocol.Debugger.oncePaused();
InspectorTest.logMessage(callFrames4);
Protocol.Debugger.resume();
Protocol.Debugger.disable();
}
]);

View File

@ -0,0 +1,65 @@
Test static private class accessors
Running test: testScopesPaused
private members on the base class
privateProperties from Runtime.getProperties()
[
[0] : {
name : #writeOnly
set : {
className : Function
description : set #writeOnly(val) { this.#field = val; }
objectId : <objectId>
type : function
}
}
[1] : {
get : {
className : Function
description : get #readOnly() { return this.#field; }
objectId : <objectId>
type : function
}
name : #readOnly
}
[2] : {
get : {
className : Function
description : get #accessor() { return this.#field; }
objectId : <objectId>
type : function
}
name : #accessor
set : {
className : Function
description : set #accessor(val) { this.#field = val; }
objectId : <objectId>
type : function
}
}
[3] : {
name : #field
value : {
description : 2
type : number
value : 2
}
}
]
[[PrivateMethods]] in internalProperties from Runtime.getProperties()
undefined
private members on the subclass
privateProperties from Runtime.getProperties()
[
[0] : {
get : {
className : Function
description : get #accessor() { return 'subclassAccessor'; }
objectId : <objectId>
type : function
}
name : #accessor
}
]
[[PrivateMethods]] in internalProperties from Runtime.getProperties()
undefined

View File

@ -0,0 +1,64 @@
// Copyright 2024 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
utils.load('test/inspector/private-class-member-inspector-test.js');
let {session, contextGroup, Protocol} =
InspectorTest.start('Test static private class accessors');
const script = `
function run() {
class A {
static test() {
debugger;
}
static #field = 2;
get #instanceAccessor() { return this.#field; } // should not show up
set #instanceAccessor(val) { this.#field = val; } // should not show up
static set #writeOnly(val) { this.#field = val; }
static get #readOnly() { return this.#field; }
static get #accessor() { return this.#field; }
static set #accessor(val) { this.#field = val; }
};
A.test();
class B extends A {
static get #accessor() { return 'subclassAccessor'; }
static test() {
debugger;
}
}
B.test();
}`;
contextGroup.addScript(script);
InspectorTest.runAsyncTestSuite([async function testScopesPaused() {
Protocol.Debugger.enable();
// Do not await here, instead oncePaused should be awaited.
Protocol.Runtime.evaluate({expression: 'run()'});
InspectorTest.log('private members on the base class');
let {params: {callFrames}} =
await Protocol.Debugger.oncePaused(); // inside A.test()
let frame = callFrames[0];
await printPrivateMembers(
Protocol, InspectorTest, {objectId: frame.this.objectId});
Protocol.Debugger.resume();
({params: {callFrames}} = await Protocol.Debugger.oncePaused()); // B.test();
frame = callFrames[0];
InspectorTest.log('private members on the subclass');
await printPrivateMembers(
Protocol, InspectorTest, {objectId: frame.this.objectId});
Protocol.Debugger.resume();
Protocol.Debugger.disable();
}]);

Some files were not shown because too many files have changed in this diff Show More