Skip to content

Commit 50f7455

Browse files
alexkozyCommit Bot
authored andcommitted
[inspector] added Runtime.globalLexicalScopeNames method
The method returns names for all available top-level scope variables in giving context. [email protected],[email protected] Bug: chromium:681333 Cq-Include-Trybots: master.tryserver.blink:linux_trusty_blink_rel Change-Id: I2d0b600e1afbfef9087f53ea9c26abe1e112047c Reviewed-on: https://chromium-review.googlesource.com/719409 Commit-Queue: Aleksey Kozyatinskiy <[email protected]> Reviewed-by: Yang Guo <[email protected]> Reviewed-by: Jakob Gruber <[email protected]> Reviewed-by: Dmitry Gozman <[email protected]> Cr-Commit-Position: refs/heads/master@{#48618}
1 parent c97d869 commit 50f7455

8 files changed

Lines changed: 181 additions & 1 deletion

src/api.cc

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10166,6 +10166,25 @@ void debug::QueryObjects(v8::Local<v8::Context> v8_context,
1016610166
predicate, objects);
1016710167
}
1016810168

10169+
void debug::GlobalLexicalScopeNames(
10170+
v8::Local<v8::Context> v8_context,
10171+
v8::PersistentValueVector<v8::String>* names) {
10172+
i::Handle<i::Context> context = Utils::OpenHandle(*v8_context);
10173+
i::Handle<i::ScriptContextTable> table(
10174+
context->global_object()->native_context()->script_context_table());
10175+
for (int i = 0; i < table->used(); i++) {
10176+
i::Handle<i::Context> context = i::ScriptContextTable::GetContext(table, i);
10177+
DCHECK(context->IsScriptContext());
10178+
i::Handle<i::ScopeInfo> scope_info(context->scope_info());
10179+
int local_count = scope_info->ContextLocalCount();
10180+
for (int j = 0; j < local_count; ++j) {
10181+
i::String* name = scope_info->ContextLocalName(j);
10182+
if (i::ScopeInfo::VariableIsSynthetic(name)) continue;
10183+
names->Append(Utils::ToLocal(handle(name)));
10184+
}
10185+
}
10186+
}
10187+
1016910188
Local<String> CpuProfileNode::GetFunctionName() const {
1017010189
const i::ProfileNode* node = reinterpret_cast<const i::ProfileNode*>(this);
1017110190
i::Isolate* isolate = node->isolate();

src/debug/debug-interface.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -482,6 +482,9 @@ void QueryObjects(v8::Local<v8::Context> context,
482482
QueryObjectPredicate* predicate,
483483
v8::PersistentValueVector<v8::Object>* objects);
484484

485+
void GlobalLexicalScopeNames(v8::Local<v8::Context> context,
486+
v8::PersistentValueVector<v8::String>* names);
487+
485488
} // namespace debug
486489
} // namespace v8
487490

src/inspector/js_protocol.json

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -355,6 +355,17 @@
355355
{ "name": "objects", "$ref": "RemoteObject", "description": "Array with objects." }
356356
],
357357
"experimental": true
358+
},
359+
{
360+
"name": "globalLexicalScopeNames",
361+
"parameters": [
362+
{ "name": "executionContextId", "$ref": "ExecutionContextId", "optional": true, "description": "Specifies in which execution context to lookup global scope variables." }
363+
],
364+
"returns": [
365+
{ "name": "names", "type": "array", "items": { "type": "string" } }
366+
],
367+
"description": "Returns all let, const and class variables from global scope.",
368+
"experimental": true
358369
}
359370
],
360371
"events": [

src/inspector/v8-runtime-agent-impl.cc

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -586,6 +586,27 @@ Response V8RuntimeAgentImpl::queryObjects(
586586
resultArray, scope.objectGroupName(), false, false, objects);
587587
}
588588

589+
Response V8RuntimeAgentImpl::globalLexicalScopeNames(
590+
Maybe<int> executionContextId,
591+
std::unique_ptr<protocol::Array<String16>>* outNames) {
592+
int contextId = 0;
593+
Response response = ensureContext(m_inspector, m_session->contextGroupId(),
594+
std::move(executionContextId), &contextId);
595+
if (!response.isSuccess()) return response;
596+
597+
InjectedScript::ContextScope scope(m_session, contextId);
598+
response = scope.initialize();
599+
if (!response.isSuccess()) return response;
600+
601+
v8::PersistentValueVector<v8::String> names(m_inspector->isolate());
602+
v8::debug::GlobalLexicalScopeNames(scope.context(), &names);
603+
*outNames = protocol::Array<String16>::create();
604+
for (size_t i = 0; i < names.Size(); ++i) {
605+
(*outNames)->addItem(toProtocolString(names.Get(i)));
606+
}
607+
return Response::OK();
608+
}
609+
589610
void V8RuntimeAgentImpl::restore() {
590611
if (!m_state->booleanProperty(V8RuntimeAgentImplState::runtimeEnabled, false))
591612
return;

src/inspector/v8-runtime-agent-impl.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,9 @@ class V8RuntimeAgentImpl : public protocol::Runtime::Backend {
101101
Response queryObjects(
102102
const String16& prototypeObjectId,
103103
std::unique_ptr<protocol::Runtime::RemoteObject>* objects) override;
104+
Response globalLexicalScopeNames(
105+
Maybe<int> executionContextId,
106+
std::unique_ptr<protocol::Array<String16>>* outNames) override;
104107

105108
void reset();
106109
void reportExecutionContextCreated(InspectedContext*);
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
Test for Runtime.globalLexicalScopeVariablesNames
2+
Running 'let a = 1'
3+
Values:
4+
a = 1
5+
6+
Running 'let b = 2'
7+
Values:
8+
a = 1
9+
b = 2
10+
11+
Running 'let b = 3'
12+
Values:
13+
a = 1
14+
b = 2
15+
16+
Running 'const c = 4'
17+
Values:
18+
a = 1
19+
b = 2
20+
c = 4
21+
22+
Running 'var d = 5'
23+
(should not be in list of scoped variables)
24+
Values:
25+
a = 1
26+
b = 2
27+
c = 4
28+
29+
Running 'class Foo{}'
30+
Values:
31+
a = 1
32+
b = 2
33+
c = 4
34+
Foo =
35+
{
36+
className : Function
37+
description : class Foo{}
38+
objectId : <objectId>
39+
type : function
40+
}
41+
42+
Adding script with scope variables
43+
Values:
44+
a = 1
45+
b = 2
46+
c = 4
47+
Foo =
48+
{
49+
className : Function
50+
description : class Foo{}
51+
objectId : <objectId>
52+
type : function
53+
}
54+
e = 1
55+
f = 2
56+
g = 3
57+
Boo =
58+
{
59+
className : Function
60+
description : class Boo {}
61+
objectId : <objectId>
62+
type : function
63+
}
64+
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
// Copyright 2017 the V8 project authors. All rights reserved.
2+
// Use of this source code is governed by a BSD-style license that can be
3+
// found in the LICENSE file.
4+
5+
let {session, contextGroup, Protocol} =
6+
InspectorTest.start('Test for Runtime.globalLexicalScopeVariablesNames');
7+
8+
(async function test() {
9+
InspectorTest.log('Running \'let a = 1\'');
10+
Protocol.Runtime.evaluate({expression: 'let a = 1'});
11+
await dumpGlobalScopeVariables();
12+
13+
InspectorTest.log('Running \'let b = 2\'');
14+
Protocol.Runtime.evaluate({expression: 'let b = 2'});
15+
await dumpGlobalScopeVariables();
16+
17+
InspectorTest.log('Running \'let b = 3\'');
18+
Protocol.Runtime.evaluate({expression: 'let b = 3'});
19+
await dumpGlobalScopeVariables();
20+
21+
InspectorTest.log('Running \'const c = 4\'');
22+
Protocol.Runtime.evaluate({expression: 'const c = 4'});
23+
await dumpGlobalScopeVariables();
24+
25+
InspectorTest.log('Running \'var d = 5\'');
26+
InspectorTest.log('(should not be in list of scoped variables)');
27+
Protocol.Runtime.evaluate({expression: 'var d = 5'});
28+
await dumpGlobalScopeVariables();
29+
30+
InspectorTest.log('Running \'class Foo{}\'');
31+
Protocol.Runtime.evaluate({expression: 'class Foo{}'});
32+
await dumpGlobalScopeVariables();
33+
34+
InspectorTest.log('Adding script with scope variables');
35+
contextGroup.addScript(`
36+
let e = 1;
37+
const f = 2;
38+
const g = 3;
39+
class Boo {};
40+
`);
41+
await dumpGlobalScopeVariables();
42+
InspectorTest.completeTest();
43+
})();
44+
45+
async function dumpGlobalScopeVariables() {
46+
let {result:{names}} =
47+
await Protocol.Runtime.globalLexicalScopeNames();
48+
InspectorTest.log('Values:');
49+
for (let name of names) {
50+
let {result:{result}} = await Protocol.Runtime.evaluate({expression: name});
51+
if (result.value) {
52+
InspectorTest.log(`${name} = ${result.value}`);
53+
} else {
54+
InspectorTest.log(`${name} =`);
55+
InspectorTest.logMessage(result);
56+
}
57+
}
58+
InspectorTest.log('');
59+
}

test/inspector/runtime/runtime-restore.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
// Copyright 2017 the V8 project authors. All rights reserved.
22
// Use of this source code is governed by a BSD-style license that can be
3-
// found in the LICENSE file.v8
3+
// found in the LICENSE file.
44

55
let {session, contextGroup, Protocol} = InspectorTest.start('Checks that Runtime agent correctly restore its state.');
66

0 commit comments

Comments
 (0)