Commit 68af366f authored by Alexey Kozyatinskiy's avatar Alexey Kozyatinskiy Committed by Commit Bot

[inspector] report [[Scopes]] all the time

Before we used to require compiled debugger script to report Scopes.
After migration inspection to brand-new native API we can report
Scopes all the time and remove this hidden dependency.

R=dgozman@chromium.org

Bug: none
Cq-Include-Trybots: master.tryserver.blink:linux_trusty_blink_rel
Change-Id: I3530bc7ead691a51073e384aea4a4ef428dc94da
Reviewed-on: https://chromium-review.googlesource.com/662097
Commit-Queue: Aleksey Kozyatinskiy <kozyatinskiy@chromium.org>
Reviewed-by: 's avatarDmitry Gozman <dgozman@chromium.org>
Cr-Commit-Position: refs/heads/master@{#47982}
parent 90eb06b3
......@@ -563,9 +563,6 @@ std::shared_ptr<AsyncStackTrace> V8Debugger::currentAsyncCreation() {
v8::MaybeLocal<v8::Value> V8Debugger::getTargetScopes(
v8::Local<v8::Context> context, v8::Local<v8::Value> value,
ScopeTargetKind kind) {
if (!enabled()) {
UNREACHABLE();
}
v8::Local<v8::Value> scopesValue;
std::unique_ptr<v8::debug::ScopeIterator> iterator;
switch (kind) {
......@@ -664,7 +661,6 @@ v8::MaybeLocal<v8::Array> V8Debugger::internalProperties(
toV8StringInternalized(m_isolate, "[[GeneratorLocation]]"));
createDataProperty(context, properties, properties->Length(), location);
}
if (!enabled()) return properties;
v8::Local<v8::Value> scopes;
if (generatorScopes(context, value).ToLocal(&scopes)) {
createDataProperty(context, properties, properties->Length(),
......@@ -672,7 +668,6 @@ v8::MaybeLocal<v8::Array> V8Debugger::internalProperties(
createDataProperty(context, properties, properties->Length(), scopes);
}
}
if (!enabled()) return properties;
if (value->IsFunction()) {
v8::Local<v8::Function> function = value.As<v8::Function>();
v8::Local<v8::Value> boundFunction = function->GetBoundFunction();
......
Tests that suspended generators produce scopes
Running test: testScopesPaused
{
id : <messageId>
result : {
result : [
[0] : {
configurable : true
enumerable : true
isOwn : true
name : b
value : {
description : 42
type : number
value : 42
}
writable : true
}
[1] : {
configurable : true
enumerable : true
isOwn : true
name : a
value : {
description : 420
type : number
value : 420
}
writable : true
}
]
[
[0] : {
configurable : true
enumerable : true
isOwn : true
name : b
value : {
description : 42
type : number
value : 42
}
writable : true
}
}
[1] : {
configurable : true
enumerable : true
isOwn : true
name : a
value : {
description : 420
type : number
value : 420
}
writable : true
}
]
Running test: testScopesNonPaused
{
id : <messageId>
result : {
result : [
[0] : {
configurable : true
enumerable : true
isOwn : true
name : b
value : {
type : undefined
}
writable : true
}
[1] : {
configurable : true
enumerable : true
isOwn : true
name : a
value : {
description : 430
type : number
value : 430
}
writable : true
}
]
[
[0] : {
configurable : true
enumerable : true
isOwn : true
name : b
value : {
type : undefined
}
writable : true
}
[1] : {
configurable : true
enumerable : true
isOwn : true
name : a
value : {
description : 430
type : number
value : 430
}
writable : true
}
}
]
......@@ -4,78 +4,66 @@
let {session, contextGroup, Protocol} = InspectorTest.start('Tests that suspended generators produce scopes');
contextGroup.addScript(
`function *gen(a) {
contextGroup.addScript(`
function *gen(a) {
var b = 42;
yield a;
return b;
}
function testSuspendedGenerator()
{
function testSuspendedGenerator() {
var g = gen(420);
g.next();
debugger;
return g;
}`);
Protocol.Debugger.enable().then(testSuite);
function dumpInnermostScope(msg) {
var scopes = msg.result.result;
var inner_scope = scopes[0].value;
return Protocol.Runtime.getProperties({ objectId : inner_scope.objectId })
.then(InspectorTest.logMessage);
}
function dumpGeneratorScopes(msg)
{
var props = msg.result.internalProperties;
var promises = props
.filter(prop => prop.name == "[[Scopes]]")
.map(prop => prop.value.objectId)
.map(scopesId => Protocol.Runtime.getProperties({ objectId : scopesId })
.then(dumpInnermostScope));
return Promise.all(promises);
}
function fetchGeneratorProperties(objectId) {
return Protocol.Runtime.getProperties({ objectId : objectId });
}
InspectorTest.runAsyncTestSuite([
async function testScopesPaused() {
Protocol.Debugger.enable();
Protocol.Runtime.evaluate({expression: 'testSuspendedGenerator()'});
let {params:{callFrames:[callFrame]}} = await Protocol.Debugger.oncePaused();
// Current local scope.
let localScope = callFrame.scopeChain.find(scope => scope.type === 'local');
let variables = (await Protocol.Runtime.getProperties({
objectId: localScope.object.objectId
})).result.result;
let genObjectId =
variables.find(variable => variable.name === 'g').value.objectId;
let {result:{internalProperties}} = await Protocol.Runtime.getProperties({
objectId: genObjectId
});
// Generator [[Scopes]].
let scopes = internalProperties.find(prop => prop.name === '[[Scopes]]');
let {result:{result}} = await Protocol.Runtime.getProperties({
objectId: scopes.value.objectId
});
// Locals from generator.
let scope = result.find(scope => scope.value.description === 'Local (gen)');
({result:{result}} = await Protocol.Runtime.getProperties({
objectId: scope.value.objectId
}));
InspectorTest.logMessage(result);
await Protocol.Debugger.disable();
},
function extractGeneratorObjectFromScope(scopeId) {
return Protocol.Runtime.getProperties({ objectId : scopeId })
.then(msg => {
var generatorObjectId = msg.result.result[0].value.objectId;
return fetchGeneratorProperties(generatorObjectId);
});
}
function dumpGeneratorScopesOnPause(msg) {
var scopeChain = msg.params.callFrames[0].scopeChain;
var promises = scopeChain
.filter(scope => scope.type === "local")
.map(scope => scope.object.objectId)
.map(scopeId => extractGeneratorObjectFromScope(scopeId)
.then(dumpGeneratorScopes));
return Promise.all(promises).then(Protocol.Debugger.resume);
}
function testSuite() {
InspectorTest.runTestSuite([
function testScopesPaused(next) {
Protocol.Debugger.oncePaused()
.then(dumpGeneratorScopesOnPause)
.then(next);
Protocol.Runtime.evaluate({ expression : "testSuspendedGenerator()" });
},
function testScopesNonPaused(next) {
Protocol.Runtime.evaluate({ expression : "gen(430)"})
.then(msg => fetchGeneratorProperties(msg.result.result.objectId))
.then(dumpGeneratorScopes)
.then(next);
},
]);
}
async function testScopesNonPaused() {
let {result:{result:{objectId}}} = await Protocol.Runtime.evaluate({
expression: 'gen(430)'
});
let {result:{internalProperties}} = await Protocol.Runtime.getProperties({
objectId
});
// Generator [[Scopes]].
let scopes = internalProperties.find(prop => prop.name === '[[Scopes]]');
let {result:{result}} = await Protocol.Runtime.getProperties({
objectId: scopes.value.objectId
});
// Locals from generator.
let scope = result.find(scope => scope.value.description === 'Local (gen)');
({result:{result}} = await Protocol.Runtime.getProperties({
objectId: scope.value.objectId
}));
InspectorTest.logMessage(result);
}
]);
Checks [[Scopes]] for functions
Catch:
{
configurable : true
enumerable : true
isOwn : true
name : a
value : {
description : 1
type : number
value : 1
}
writable : true
}
With block:
{
configurable : true
enumerable : true
isOwn : true
name : b
value : {
description : 2
type : number
value : 2
}
writable : true
}
Closure (closure):
{
configurable : true
enumerable : true
isOwn : true
name : c
value : {
description : 3
type : number
value : 3
}
writable : true
}
Global:
{
configurable : false
enumerable : true
isOwn : true
name : e
value : {
description : 5
type : number
value : 5
}
writable : true
}
// Copyright 2017 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
let {session, contextGroup, Protocol} = InspectorTest.start('Checks [[Scopes]] for functions');
contextGroup.addScript(`
var f;
try {
throw 1;
} catch (a) {
with({b:2}) {
function closure() {
var c = 3;
function foo() {
var d = 4;
return a + b + c + d;
}
return foo;
}
f = closure;
}
}
var e = 5;
//# sourceURL=test.js`);
(async function test() {
let {result:{result:{objectId}}} = await Protocol.Runtime.evaluate({
expression: 'f()'
});
let {result:{internalProperties}} = await Protocol.Runtime.getProperties({
objectId
});
let scopes = internalProperties.find(prop => prop.name === '[[Scopes]]');
let {result:{result}} = await Protocol.Runtime.getProperties({
objectId: scopes.value.objectId
});
await Promise.all(result.map(async scope => {
scope.variables = (await Protocol.Runtime.getProperties({
objectId: scope.value.objectId
})).result.result;
}));
let catchScope = result.find(scope => scope.value.description === 'Catch');
InspectorTest.log('Catch:');
InspectorTest.logMessage(catchScope.variables.find(variable => variable.name === 'a'));
InspectorTest.log('With block:');
let withScope = result.find(scope => scope.value.description === 'With Block');
InspectorTest.logMessage(withScope.variables.find(variable => variable.name === 'b'));
InspectorTest.log('Closure (closure):');
let closureScope = result.find(scope => scope.value.description === 'Closure (closure)');
InspectorTest.logMessage(closureScope.variables.find(variable => variable.name === 'c'));
InspectorTest.log('Global:');
let globalScope = result.find(scope => scope.value.description === 'Global');
InspectorTest.logMessage(globalScope.variables.find(variable => variable.name === 'e'));
InspectorTest.completeTest();
})();
......@@ -387,6 +387,16 @@ expression: gen2
}
}
}
[4] : {
name : [[Scopes]]
value : {
className : Array
description : Scopes[2]
objectId : <objectId>
subtype : internal#scopeList
type : object
}
}
]
}
}
......@@ -433,6 +443,16 @@ expression: gen2.next();gen2
}
}
}
[4] : {
name : [[Scopes]]
value : {
className : Array
description : Scopes[2]
objectId : <objectId>
subtype : internal#scopeList
type : object
}
}
]
}
}
......
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