[inspector] filter useless in preview internal properties
Only subset of internal properties can be useful in preview, report only them. BUG=chromium:653610 R=dgozman@chromium.org Review-Url: https://codereview.chromium.org/2399003003 Cr-Commit-Position: refs/heads/master@{#40064}
This commit is contained in:
parent
b1fb83d58a
commit
fac3b6fa46
@ -166,12 +166,69 @@ void V8InjectedScriptHost::subtypeCallback(
|
||||
void V8InjectedScriptHost::getInternalPropertiesCallback(
|
||||
const v8::FunctionCallbackInfo<v8::Value>& info) {
|
||||
if (info.Length() < 1) return;
|
||||
v8::Local<v8::Array> properties;
|
||||
if (unwrapInspector(info)
|
||||
->debugger()
|
||||
->internalProperties(info.GetIsolate()->GetCurrentContext(), info[0])
|
||||
.ToLocal(&properties))
|
||||
|
||||
std::unordered_set<String16> allowedProperties;
|
||||
if (info[0]->IsBooleanObject() || info[0]->IsNumberObject() ||
|
||||
info[0]->IsStringObject() || info[0]->IsSymbolObject()) {
|
||||
allowedProperties.insert(String16("[[PrimitiveValue]]"));
|
||||
} else if (info[0]->IsPromise()) {
|
||||
allowedProperties.insert(String16("[[PromiseStatus]]"));
|
||||
allowedProperties.insert(String16("[[PromiseValue]]"));
|
||||
} else if (info[0]->IsGeneratorObject()) {
|
||||
allowedProperties.insert(String16("[[GeneratorStatus]]"));
|
||||
} else if (info[0]->IsMapIterator() || info[0]->IsSetIterator()) {
|
||||
allowedProperties.insert(String16("[[IteratorHasMore]]"));
|
||||
allowedProperties.insert(String16("[[IteratorIndex]]"));
|
||||
allowedProperties.insert(String16("[[IteratorKind]]"));
|
||||
allowedProperties.insert(String16("[[Entries]]"));
|
||||
} else if (info[0]->IsMap() || info[0]->IsWeakMap() || info[0]->IsSet() ||
|
||||
info[0]->IsWeakSet()) {
|
||||
allowedProperties.insert(String16("[[Entries]]"));
|
||||
}
|
||||
if (!allowedProperties.size()) return;
|
||||
|
||||
v8::Isolate* isolate = info.GetIsolate();
|
||||
v8::Local<v8::Array> allProperties;
|
||||
if (!unwrapInspector(info)
|
||||
->debugger()
|
||||
->internalProperties(isolate->GetCurrentContext(), info[0])
|
||||
.ToLocal(&allProperties) ||
|
||||
!allProperties->IsArray() || allProperties->Length() % 2 != 0)
|
||||
return;
|
||||
|
||||
{
|
||||
v8::Local<v8::Context> context = isolate->GetCurrentContext();
|
||||
v8::TryCatch tryCatch(isolate);
|
||||
v8::Isolate::DisallowJavascriptExecutionScope throwJs(
|
||||
isolate,
|
||||
v8::Isolate::DisallowJavascriptExecutionScope::THROW_ON_FAILURE);
|
||||
|
||||
v8::Local<v8::Array> properties = v8::Array::New(isolate);
|
||||
if (tryCatch.HasCaught()) return;
|
||||
|
||||
uint32_t outputIndex = 0;
|
||||
for (uint32_t i = 0; i < allProperties->Length(); i += 2) {
|
||||
v8::Local<v8::Value> key;
|
||||
if (!allProperties->Get(context, i).ToLocal(&key)) continue;
|
||||
if (tryCatch.HasCaught()) {
|
||||
tryCatch.Reset();
|
||||
continue;
|
||||
}
|
||||
String16 keyString = toProtocolStringWithTypeCheck(key);
|
||||
if (keyString.isEmpty() ||
|
||||
allowedProperties.find(keyString) == allowedProperties.end())
|
||||
continue;
|
||||
v8::Local<v8::Value> value;
|
||||
if (!allProperties->Get(context, i + 1).ToLocal(&value)) continue;
|
||||
if (tryCatch.HasCaught()) {
|
||||
tryCatch.Reset();
|
||||
continue;
|
||||
}
|
||||
createDataProperty(context, properties, outputIndex++, key);
|
||||
createDataProperty(context, properties, outputIndex++, value);
|
||||
}
|
||||
info.GetReturnValue().Set(properties);
|
||||
}
|
||||
}
|
||||
|
||||
void V8InjectedScriptHost::objectHasOwnPropertyCallback(
|
||||
|
@ -0,0 +1,253 @@
|
||||
Check internal properties reported in object preview.
|
||||
|
||||
Running test: boxedObjects
|
||||
expression: new Number(239)
|
||||
{
|
||||
name : [[PrimitiveValue]]
|
||||
type : number
|
||||
value : 239
|
||||
}
|
||||
|
||||
expression: new Boolean(false)
|
||||
{
|
||||
name : [[PrimitiveValue]]
|
||||
type : boolean
|
||||
value : false
|
||||
}
|
||||
|
||||
expression: new String("abc")
|
||||
{
|
||||
name : [[PrimitiveValue]]
|
||||
type : string
|
||||
value : abc
|
||||
}
|
||||
|
||||
expression: Object(Symbol(42))
|
||||
{
|
||||
name : [[PrimitiveValue]]
|
||||
type : symbol
|
||||
valuePreview : {
|
||||
description : Symbol
|
||||
overflow : false
|
||||
properties : [
|
||||
]
|
||||
type : object
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Running test: promise
|
||||
expression: Promise.resolve(42)
|
||||
{
|
||||
name : [[PromiseStatus]]
|
||||
type : string
|
||||
value : resolved
|
||||
}
|
||||
{
|
||||
name : [[PromiseValue]]
|
||||
type : number
|
||||
value : 42
|
||||
}
|
||||
|
||||
expression: new Promise(() => undefined)
|
||||
{
|
||||
name : [[PromiseStatus]]
|
||||
type : string
|
||||
value : pending
|
||||
}
|
||||
{
|
||||
name : [[PromiseValue]]
|
||||
type : undefined
|
||||
value : undefined
|
||||
}
|
||||
|
||||
|
||||
Running test: generatorObject
|
||||
expression: (function* foo() { yield 1 })()
|
||||
{
|
||||
name : [[GeneratorStatus]]
|
||||
type : string
|
||||
value : suspended
|
||||
}
|
||||
|
||||
|
||||
Running test: entriesInMapAndSet
|
||||
expression: new Map([[1,2]])
|
||||
[[Entries]]:
|
||||
[
|
||||
[0] : {
|
||||
key : {
|
||||
description : 1
|
||||
overflow : false
|
||||
properties : [
|
||||
]
|
||||
type : number
|
||||
}
|
||||
value : {
|
||||
description : 2
|
||||
overflow : false
|
||||
properties : [
|
||||
]
|
||||
type : number
|
||||
}
|
||||
}
|
||||
]
|
||||
|
||||
expression: new Set([1])
|
||||
[[Entries]]:
|
||||
[
|
||||
[0] : {
|
||||
value : {
|
||||
description : 1
|
||||
overflow : false
|
||||
properties : [
|
||||
]
|
||||
type : number
|
||||
}
|
||||
}
|
||||
]
|
||||
|
||||
expression: new WeakMap([[{}, 42]])
|
||||
[[Entries]]:
|
||||
[
|
||||
[0] : {
|
||||
key : {
|
||||
description : Object
|
||||
overflow : false
|
||||
properties : [
|
||||
]
|
||||
type : object
|
||||
}
|
||||
value : {
|
||||
description : 42
|
||||
overflow : false
|
||||
properties : [
|
||||
]
|
||||
type : number
|
||||
}
|
||||
}
|
||||
]
|
||||
|
||||
expression: new WeakSet([{}])
|
||||
[[Entries]]:
|
||||
[
|
||||
[0] : {
|
||||
value : {
|
||||
description : Object
|
||||
overflow : false
|
||||
properties : [
|
||||
]
|
||||
type : object
|
||||
}
|
||||
}
|
||||
]
|
||||
|
||||
|
||||
Running test: iteratorObject
|
||||
expression: (new Map([[1,2]])).entries()
|
||||
{
|
||||
name : [[IteratorHasMore]]
|
||||
type : boolean
|
||||
value : true
|
||||
}
|
||||
{
|
||||
name : [[IteratorIndex]]
|
||||
type : number
|
||||
value : 0
|
||||
}
|
||||
{
|
||||
name : [[IteratorKind]]
|
||||
type : string
|
||||
value : entries
|
||||
}
|
||||
[[Entries]]:
|
||||
[
|
||||
[0] : {
|
||||
value : {
|
||||
description : Array[2]
|
||||
overflow : false
|
||||
properties : [
|
||||
[0] : {
|
||||
name : 0
|
||||
type : number
|
||||
value : 1
|
||||
}
|
||||
[1] : {
|
||||
name : 1
|
||||
type : number
|
||||
value : 2
|
||||
}
|
||||
]
|
||||
subtype : array
|
||||
type : object
|
||||
}
|
||||
}
|
||||
]
|
||||
|
||||
expression: (new Set([[1,2]])).entries()
|
||||
{
|
||||
name : [[IteratorHasMore]]
|
||||
type : boolean
|
||||
value : true
|
||||
}
|
||||
{
|
||||
name : [[IteratorIndex]]
|
||||
type : number
|
||||
value : 0
|
||||
}
|
||||
{
|
||||
name : [[IteratorKind]]
|
||||
type : string
|
||||
value : entries
|
||||
}
|
||||
[[Entries]]:
|
||||
[
|
||||
[0] : {
|
||||
value : {
|
||||
description : Array[2]
|
||||
overflow : false
|
||||
properties : [
|
||||
[0] : {
|
||||
name : 0
|
||||
subtype : array
|
||||
type : object
|
||||
value : Array[2]
|
||||
}
|
||||
[1] : {
|
||||
name : 1
|
||||
subtype : array
|
||||
type : object
|
||||
value : Array[2]
|
||||
}
|
||||
]
|
||||
subtype : array
|
||||
type : object
|
||||
}
|
||||
}
|
||||
]
|
||||
|
||||
|
||||
Running test: noPreviewForFunctionObject
|
||||
(function foo(){})
|
||||
{
|
||||
id : <messageId>
|
||||
result : {
|
||||
result : {
|
||||
className : Function
|
||||
description : function foo(){}
|
||||
objectId : <objectId>
|
||||
type : function
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Running test: otherObjects
|
||||
expression: [1,2,3]
|
||||
|
||||
expression: /123/
|
||||
|
||||
expression: ({})
|
||||
|
||||
|
||||
Running test: overridenArrayGetter
|
||||
expression: Promise.resolve(42)
|
107
test/inspector/debugger/object-preview-internal-properties.js
Normal file
107
test/inspector/debugger/object-preview-internal-properties.js
Normal file
@ -0,0 +1,107 @@
|
||||
// Copyright 2016 the V8 project authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
print("Check internal properties reported in object preview.");
|
||||
|
||||
Protocol.Debugger.enable();
|
||||
Protocol.Runtime.enable();
|
||||
Protocol.Runtime.onConsoleAPICalled(dumpInternalPropertiesAndEntries);
|
||||
|
||||
InspectorTest.runTestSuite([
|
||||
function boxedObjects(next)
|
||||
{
|
||||
checkExpression("new Number(239)")
|
||||
.then(() => checkExpression("new Boolean(false)"))
|
||||
.then(() => checkExpression("new String(\"abc\")"))
|
||||
.then(() => checkExpression("Object(Symbol(42))"))
|
||||
.then(next);
|
||||
},
|
||||
|
||||
function promise(next)
|
||||
{
|
||||
checkExpression("Promise.resolve(42)")
|
||||
.then(() => checkExpression("new Promise(() => undefined)"))
|
||||
.then(next);
|
||||
},
|
||||
|
||||
function generatorObject(next)
|
||||
{
|
||||
checkExpression("(function* foo() { yield 1 })()")
|
||||
.then(next);
|
||||
},
|
||||
|
||||
function entriesInMapAndSet(next)
|
||||
{
|
||||
checkExpression("new Map([[1,2]])")
|
||||
.then(() => checkExpression("new Set([1])"))
|
||||
.then(() => checkExpression("new WeakMap([[{}, 42]])"))
|
||||
.then(() => checkExpression("new WeakSet([{}])"))
|
||||
.then(next);
|
||||
},
|
||||
|
||||
function iteratorObject(next)
|
||||
{
|
||||
checkExpression("(new Map([[1,2]])).entries()")
|
||||
.then(() => checkExpression("(new Set([[1,2]])).entries()"))
|
||||
.then(next);
|
||||
},
|
||||
|
||||
function noPreviewForFunctionObject(next)
|
||||
{
|
||||
var expression = "(function foo(){})";
|
||||
InspectorTest.log(expression);
|
||||
Protocol.Runtime.evaluate({ expression: expression, generatePreview: true})
|
||||
.then(message => InspectorTest.logMessage(message))
|
||||
.then(next);
|
||||
},
|
||||
|
||||
function otherObjects(next)
|
||||
{
|
||||
checkExpression("[1,2,3]")
|
||||
.then(() => checkExpression("/123/"))
|
||||
.then(() => checkExpression("({})"))
|
||||
.then(next);
|
||||
},
|
||||
|
||||
function overridenArrayGetter(next)
|
||||
{
|
||||
Protocol.Runtime.evaluate({ expression: "Array.prototype.__defineGetter__(\"0\",() => { throw new Error() }) "})
|
||||
.then(() => checkExpression("Promise.resolve(42)"))
|
||||
.then(next);
|
||||
}
|
||||
]);
|
||||
|
||||
function checkExpression(expression)
|
||||
{
|
||||
InspectorTest.log(`expression: ${expression}`);
|
||||
// console.table has higher limits for internal properties amount in preview.
|
||||
return Protocol.Runtime.evaluate({ expression: `console.table(${expression})`, generatePreview: true });
|
||||
}
|
||||
|
||||
function dumpInternalPropertiesAndEntries(message)
|
||||
{
|
||||
var properties;
|
||||
var entries;
|
||||
try {
|
||||
var preview = message.params.args[0].preview;
|
||||
properties = preview.properties;
|
||||
entries = preview.entries;
|
||||
} catch (e) {
|
||||
InspectorTest.logMessage(message);
|
||||
return;
|
||||
}
|
||||
if (!properties) {
|
||||
InspectorTest.logMessage(message);
|
||||
return;
|
||||
}
|
||||
for (var property of properties) {
|
||||
if (property.name.startsWith("[["))
|
||||
InspectorTest.logMessage(property);
|
||||
}
|
||||
if (entries) {
|
||||
InspectorTest.log("[[Entries]]:");
|
||||
InspectorTest.logMessage(entries);
|
||||
}
|
||||
InspectorTest.log("");
|
||||
}
|
Loading…
Reference in New Issue
Block a user