Commit 7a9cc704 authored by Alexey Kozyatinskiy's avatar Alexey Kozyatinskiy Committed by Commit Bot

[inspector] moved var initialization break location before init expression

This CL improves break locations for expressions like 'var a = <expr>'. Without CL we use <expr> position as break location for initialization statement, with this CL we use position of first character after '=' as position.
Benefits (see test for details):
- only one break in expressions which includes mix of property lookup and calls, e.g. var p = Promise.resolve().then(x => x * 2),
- removed redundant break location for expressions like: let { x, y } = { x: 1, y: 2}.

Bug: v8:5909
Change-Id: I039d911903a2826c9859710a63ab0462c992e11b
Reviewed-on: https://chromium-review.googlesource.com/513926
Commit-Queue: Aleksey Kozyatinskiy <kozyatinskiy@chromium.org>
Reviewed-by: 's avatarMarja Hölttä <marja@chromium.org>
Reviewed-by: 's avatarDmitry Gozman <dgozman@chromium.org>
Cr-Commit-Position: refs/heads/master@{#45530}
parent 1f068187
......@@ -576,6 +576,7 @@ class ParserBase {
ExpressionT pattern;
int initializer_position;
int value_beg_position = kNoSourcePosition;
ExpressionT initializer;
};
......@@ -3807,7 +3808,10 @@ typename ParserBase<Impl>::BlockT ParserBase<Impl>::ParseVariableDeclarations(
ExpressionT value = impl()->EmptyExpression();
int initializer_position = kNoSourcePosition;
int value_beg_position = kNoSourcePosition;
if (Check(Token::ASSIGN)) {
value_beg_position = peek_position();
ExpressionClassifier classifier(this);
value = ParseAssignmentExpression(var_context != kForStatement,
CHECK_OK_CUSTOM(NullBlock));
......@@ -3855,6 +3859,7 @@ typename ParserBase<Impl>::BlockT ParserBase<Impl>::ParseVariableDeclarations(
typename DeclarationParsingResult::Declaration decl(
pattern, initializer_position, value);
decl.value_beg_position = value_beg_position;
if (var_context == kForStatement) {
// Save the declaration for further handling in ParseForStatement.
parsing_result->declarations.Add(decl);
......
......@@ -458,6 +458,7 @@ class V8_EXPORT_PRIVATE Parser : public NON_EXPORTED_BASE(ParserBase<Parser>) {
PatternContext context_;
Expression* pattern_;
int initializer_position_;
int value_beg_position_;
Block* block_;
const DeclarationDescriptor* descriptor_;
ZoneList<const AstRawString*>* names_;
......
......@@ -26,6 +26,7 @@ void Parser::PatternRewriter::DeclareAndInitializeVariables(
rewriter.context_ = BINDING;
rewriter.pattern_ = declaration->pattern;
rewriter.initializer_position_ = declaration->initializer_position;
rewriter.value_beg_position_ = declaration->value_beg_position;
rewriter.block_ = block;
rewriter.descriptor_ = declaration_descriptor;
rewriter.names_ = names;
......@@ -236,7 +237,10 @@ void Parser::PatternRewriter::VisitVariableProxy(VariableProxy* pattern) {
DCHECK_NOT_NULL(proxy->var());
}
// Add break location for destructured sub-pattern.
int pos = IsSubPattern() ? pattern->position() : value->position();
int pos = value_beg_position_;
if (pos == kNoSourcePosition) {
pos = IsSubPattern() ? pattern->position() : value->position();
}
Assignment* assignment =
factory()->NewAssignment(Token::INIT, proxy, value, pos);
block_->statements()->Add(
......
......@@ -47,7 +47,7 @@ bytecodes: [
/* 30 E> */ B(StackCheck),
/* 42 S> */ B(LdaSmi), I8(55),
B(Star), R(0),
/* 57 S> */ B(LdaSmi), I8(100),
/* 54 S> */ B(LdaSmi), I8(100),
B(Star), R(0),
B(Star), R(1),
/* 65 S> */ B(Nop),
......@@ -133,7 +133,7 @@ bytecodes: [
/* 30 E> */ B(StackCheck),
/* 42 S> */ B(LdaSmi), I8(55),
B(Star), R(0),
/* 76 S> */ B(LdaSmi), I8(1),
/* 54 S> */ B(LdaSmi), I8(1),
B(Mov), R(0), R(2),
B(Star), R(0),
/* 56 E> */ B(Add), R(2), U8(3),
......@@ -167,7 +167,7 @@ bytecodes: [
/* 30 E> */ B(StackCheck),
/* 42 S> */ B(LdaSmi), I8(55),
B(Star), R(0),
/* 76 S> */ B(LdaSmi), I8(1),
/* 54 S> */ B(LdaSmi), I8(1),
B(Mov), R(0), R(1),
B(Star), R(0),
/* 56 E> */ B(Add), R(1), U8(3),
......
......@@ -54,7 +54,7 @@ bytecodes: [
B(LdaTheHole),
B(Star), R(0),
/* 30 E> */ B(StackCheck),
/* 48 S> */ B(LdaSmi), I8(20),
/* 44 S> */ B(LdaSmi), I8(20),
B(Star), R(1),
B(Ldar), R(0),
B(JumpIfNotHole), U8(11),
......
......@@ -72,7 +72,7 @@ bytecodes: [
B(CreateClosure), U8(0), U8(3), U8(2),
B(Star), R(0),
/* 30 E> */ B(StackCheck),
/* 47 S> */ B(LdaSmi), I8(20),
/* 44 S> */ B(LdaSmi), I8(20),
B(Star), R(2),
B(LdaCurrentContextSlot), U8(4),
B(JumpIfNotHole), U8(11),
......@@ -80,7 +80,7 @@ bytecodes: [
B(Star), R(3),
/* 47 E> */ B(CallRuntime), U16(Runtime::kThrowReferenceError), R(3), U8(1),
B(CallRuntime), U16(Runtime::kThrowConstAssignError), R(0), U8(0),
/* 47 E> */ B(StaCurrentContextSlot), U8(4),
/* 44 E> */ B(StaCurrentContextSlot), U8(4),
B(LdaUndefined),
/* 80 S> */ B(Return),
]
......
......@@ -531,7 +531,7 @@ bytecodes: [
B(Star), R(1),
/* 34 S> */ B(LdaNamedProperty), R(6), U8(6), U8(19),
B(Star), R(2),
/* 58 S> */ B(Ldar), R(2),
/* 56 S> */ B(Ldar), R(2),
/* 58 E> */ B(Add), R(1), U8(21),
B(Star), R(0),
B(LdaZero),
......@@ -540,7 +540,7 @@ bytecodes: [
B(Jump), U8(36),
B(Star), R(17),
B(Ldar), R(closure),
/* 58 E> */ B(CreateCatchContext), R(17), U8(7), U8(8),
/* 56 E> */ B(CreateCatchContext), R(17), U8(7), U8(8),
B(PushContext), R(17),
B(Star), R(16),
B(LdaSmi), I8(2),
......
......@@ -54,7 +54,7 @@ bytecodes: [
B(LdaTheHole),
B(Star), R(0),
/* 30 E> */ B(StackCheck),
/* 45 S> */ B(LdaSmi), I8(20),
/* 42 S> */ B(LdaSmi), I8(20),
B(Star), R(1),
B(Ldar), R(0),
B(JumpIfNotHole), U8(11),
......
......@@ -72,7 +72,7 @@ bytecodes: [
B(CreateClosure), U8(0), U8(3), U8(2),
B(Star), R(0),
/* 30 E> */ B(StackCheck),
/* 45 S> */ B(LdaSmi), I8(20),
/* 42 S> */ B(LdaSmi), I8(20),
B(Star), R(2),
B(LdaCurrentContextSlot), U8(4),
B(JumpIfNotHole), U8(11),
......@@ -81,7 +81,7 @@ bytecodes: [
/* 45 E> */ B(CallRuntime), U16(Runtime::kThrowReferenceError), R(3), U8(1),
B(Ldar), R(2),
B(StaCurrentContextSlot), U8(4),
/* 45 E> */ B(StaCurrentContextSlot), U8(4),
/* 42 E> */ B(StaCurrentContextSlot), U8(4),
B(LdaUndefined),
/* 78 S> */ B(Return),
]
......
......@@ -94,7 +94,7 @@ parameter count: 2
bytecode array length: 14
bytecodes: [
/* 10 E> */ B(StackCheck),
/* 25 S> */ B(Nop),
/* 24 S> */ B(Nop),
/* 25 E> */ B(LdaNamedProperty), R(arg0), U8(0), U8(3),
B(Star), R(0),
/* 32 S> */ B(LdaSmi), I8(-124),
......
......@@ -237,15 +237,15 @@ bytecodes: [
B(Star), R(5),
B(CallRuntime), U16(Runtime::kNewTypeError), R(4), U8(2),
B(Throw),
/* 28 S> */ B(LdaNamedProperty), R(3), U8(2), U8(6),
/* 37 S> */ B(LdaNamedProperty), R(3), U8(2), U8(6),
B(Star), R(1),
/* 31 S> */ B(LdaNamedProperty), R(3), U8(3), U8(8),
/* 37 S> */ B(LdaNamedProperty), R(3), U8(3), U8(8),
B(Star), R(2),
/* 55 S> */ B(LdaZero),
/* 55 E> */ B(TestGreaterThan), R(2), U8(10),
B(JumpIfFalse), U8(19),
/* 17 E> */ B(StackCheck),
/* 77 S> */ B(Ldar), R(2),
/* 75 S> */ B(Ldar), R(2),
/* 77 E> */ B(Add), R(1), U8(12),
B(Star), R(0),
/* 62 S> */ B(Ldar), R(2),
......
......@@ -98,12 +98,12 @@ function test() {
}
var {
x: a, // B46
y: b = 9 // B47
} = { x: 4 };
assertEquals([4, 9], [a, b]); // B48
} // B49
x: a,
y: b = 9
} = { x: 4 }; // B46
assertEquals([4, 9], [a, b]); // B47
} // B48
test();
Debug.setListener(null); // B50
Debug.setListener(null); // B49
assertNull(exception);
......@@ -24,7 +24,7 @@ Debug.setListener(listener);
var late_resolve;
function g() {
return new Promise( // B4 StepOut
return new Promise( // B5 StepOut
function(res, rej) {
late_resolve = res;
}
......@@ -35,15 +35,15 @@ async function f1() {
var a = 1;
debugger; // B0 StepNext
a += // B1 StepNext
await // B6 StepNext
await // B7 StepNext
f2(); // B2 StepIn
return a; // B7 StepNext
} // B8 Continue
return a; // B8 StepNext
} // B9 Continue
async function f2() {
var b =
await // B5 StepOut
g(); // B3 StepIn
var b = 0 + // B3 StepIn
await // B6 StepOut
g(); // B4 StepIn
return b;
}
......@@ -53,4 +53,4 @@ late_resolve(3);
%RunMicrotasks();
assertEquals(9, step_count);
assertEquals(10, step_count);
......@@ -50,7 +50,7 @@ Paused #2
- [0] {"functionName":"testFunction","function_lineNumber":0,"function_columnNumber":21,"lineNumber":18,"columnNumber":12}
- [1] {"functionName":"","function_lineNumber":0,"function_columnNumber":0,"lineNumber":0,"columnNumber":0}
Paused #3
- [0] {"functionName":"generateAsmJs","function_lineNumber":1,"function_columnNumber":24,"lineNumber":3,"columnNumber":30}
- [0] {"functionName":"generateAsmJs","function_lineNumber":1,"function_columnNumber":24,"lineNumber":3,"columnNumber":23}
- [1] {"functionName":"testFunction","function_lineNumber":0,"function_columnNumber":21,"lineNumber":18,"columnNumber":12}
- [2] {"functionName":"","function_lineNumber":0,"function_columnNumber":0,"lineNumber":0,"columnNumber":0}
Paused #4
......
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:10)
(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:16:26)
testFunction (test.js:18:4)
(anonymous) (expr.js:0:0)
(async function asyncF() {
let r = await Promise.#resolve(42);
return r;
asyncF (test.js:16:12)
testFunction (test.js:18:4)
(anonymous) (expr.js:0:0)
(async function asyncF() {
let r = #await Promise.resolve(42);
return r;
asyncF (test.js:17:4)
let r = await Promise.resolve(42);
#return r;
})();
asyncF (test.js:18:2)
return r;
#})();
return promise;
Running test: testStepIntoAfterBreakpoint
testFunction (test.js:10:10)
(anonymous) (expr.js:0:0)
var y = (a = 100);
var z = #x + (a = 1) + (a = 2) + (a = 3) + f();
function f() {
f (test.js:12:24)
testFunction (test.js:10:44)
(anonymous) (expr.js:0:0)
function f() {
for (let { x, y } = #{ x: 0, y: 1 }; y > 0; --y) { let z = x + y; }
}
// 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);
}
}
]);
......@@ -2,6 +2,8 @@ Tests breakable locations in for-of loops.
Running test: testBreakLocations
Running test: testStepInto
function testFunction() {
var obj = |_|{a : 1};
var arr = |_|[1];
......@@ -31,8 +33,6 @@ function testFunction() {
for (let |_|k of |_|iterable) { |_|all.|C|push(k); }
|R|}
Running test: testStepInto
(anonymous) (expr.js:0:0)
......
......@@ -45,7 +45,7 @@ InspectorTest.runAsyncTestSuite([
let {params:{scriptId}} = await Protocol.Debugger.onceScriptParsed();
let {result:{locations}} = await Protocol.Debugger.getPossibleBreakpoints({
start: {lineNumber: 0, columnNumber : 0, scriptId}});
dumpAllLocations(locations);
session.logBreakLocations(locations);
},
async function testStepInto() {
......@@ -80,25 +80,3 @@ InspectorTest.runAsyncTestSuite([
}
}
]);
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 '|_|';
}
......@@ -8,36 +8,10 @@ let {session, contextGroup, Protocol} = InspectorTest.start('Checks Debugger.get
var source = utils.read('test/inspector/debugger/resources/break-locations.js');
contextGroup.addScript(source);
session.setupScriptMap();
Protocol.Debugger.onceScriptParsed()
.then(message => Protocol.Debugger.getPossibleBreakpoints({ start: { lineNumber: 0, columnNumber : 0, scriptId: message.params.scriptId }}))
.then(dumpAllLocations)
.then(message => session.logBreakLocations(message.result.locations))
.then(InspectorTest.completeTest);
Protocol.Debugger.enable();
function dumpAllLocations(message) {
if (message.error) {
InspectorTest.logMessage(message);
return;
}
var lines = source.split('\n');
var locations = message.result.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'));
return message;
}
function locationMark(type) {
if (type === 'return') return '|R|';
if (type === 'call') return '|C|';
if (type === 'debuggerStatement') return '|D|';
return '|_|';
}
......@@ -26,31 +26,34 @@ Protocol.Debugger.onceScriptParsed().then(message => {
}).then(() => InspectorTest.runTestSuite(tests));
session.setupScriptMap();
Protocol.Debugger.onPaused(dumpBreakLocationInSourceAndResume);
Protocol.Debugger.onPaused(message => {
session.logSourceLocation(message.params.callFrames[0].location);
Protocol.Debugger.resume();
});
Protocol.Debugger.enable();
var tests = [
function testWholeFunction(next) {
Protocol.Debugger.getPossibleBreakpoints({ start: location(1, 18), ignoreNestedFunctions: false })
.then(dumpAllLocations)
.then(message => session.logBreakLocations(message.result.locations))
.then(next);
},
function testWholeFunctionWithoutNested(next) {
Protocol.Debugger.getPossibleBreakpoints({ start: location(1, 18), ignoreNestedFunctions: true })
.then(dumpAllLocations)
.then(message => session.logBreakLocations(message.result.locations))
.then(next);
},
function testPartOfFunctionWithoutNested(next) {
Protocol.Debugger.getPossibleBreakpoints({ start: location(1, 18), end: location(2, 18), ignoreNestedFunctions: true })
.then(dumpAllLocations)
.then(message => session.logBreakLocations(message.result.locations))
.then(next);
},
function testNestedFunction(next) {
Protocol.Debugger.getPossibleBreakpoints({ start: location(4, 0), ignoreNestedFunctions: true })
.then(dumpAllLocations)
.then(message => session.logBreakLocations(message.result.locations))
.then(setAllBreakpoints)
.then(() => InspectorTest.log('Run test() to check breakpoints..'))
.then(() => Protocol.Runtime.evaluate({ expression: 'test()' }))
......@@ -62,9 +65,9 @@ function location(lineNumber, columnNumber) {
return { lineNumber: lineNumber, columnNumber: columnNumber, scriptId: scriptId };
}
function setAllBreakpoints(message) {
function setAllBreakpoints(locations) {
var promises = [];
for (var location of message.result.locations)
for (var location of locations)
promises.push(Protocol.Debugger.setBreakpoint({ location: location }).then(checkBreakpoint));
return Promise.all(promises);
}
......@@ -80,41 +83,3 @@ function checkBreakpoint(message) {
InspectorTest.log('FAIL: possible breakpoint was resolved in another location');
}
}
function dumpAllLocations(message) {
if (message.error) {
InspectorTest.logMessage(message);
return;
}
var sourceLines = source.split('\n')
var lineOffsets = Array(sourceLines.length).fill(0);
for (var location of message.result.locations) {
var lineNumber = location.lineNumber;
var columnNumber = location.columnNumber;
var line = sourceLines[lineNumber] || '';
var offset = lineOffsets[lineNumber];
line = line.slice(0, columnNumber + offset) + '#' + line.slice(columnNumber + offset);
++lineOffsets[lineNumber];
sourceLines[lineNumber] = line;
}
InspectorTest.log(sourceLines.join('\n'));
return message;
}
function dumpBreakLocationInSourceAndResume(message) {
session.logCallFrames([ message.params.callFrames[0] ]);
var location = message.params.callFrames[0].location;
var sourceLines = source.split('\n')
var lineNumber = location.lineNumber
var columnNumber = location.columnNumber;
var line = sourceLines[lineNumber];
line = line.slice(0, columnNumber) + '^' + line.slice(columnNumber);
sourceLines[lineNumber] = line;
InspectorTest.log(sourceLines.join('\n'));
InspectorTest.log('');
Protocol.Debugger.resume();
}
......@@ -239,6 +239,35 @@ InspectorTest.Session = class {
return this.logSourceLocation(locations[0]).then(() => this.logSourceLocations(locations.splice(1)));
}
async logBreakLocations(locations) {
let scriptId = locations[0].scriptId;
let script = this._scriptMap.get(scriptId);
if (!script.scriptSource) {
let message = await this.Protocol.Debugger.getScriptSource({scriptId});
script.scriptSource = message.result.scriptSource;
}
let lines = script.scriptSource.split('\n');
locations = locations.sort((loc1, loc2) => {
if (loc2.lineNumber !== loc1.lineNumber) return loc2.lineNumber - loc1.lineNumber;
return loc2.columnNumber - loc1.columnNumber;
});
for (let location of locations) {
let line = lines[location.lineNumber];
line = line.slice(0, location.columnNumber) + locationMark(location.type) + line.slice(location.columnNumber);
lines[location.lineNumber] = line;
}
lines = lines.filter(line => line.indexOf('//# sourceURL=') === -1);
InspectorTest.log(lines.join('\n') + '\n');
return locations;
function locationMark(type) {
if (type === 'return') return '|R|';
if (type === 'call') return '|C|';
if (type === 'debuggerStatement') return '|D|';
return '|_|';
}
}
logAsyncStackTrace(asyncStackTrace) {
while (asyncStackTrace) {
if (asyncStackTrace.promiseCreationFrame) {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment