[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:
kozyatinskiy 2016-10-06 18:16:10 -07:00 committed by Commit bot
parent b1fb83d58a
commit fac3b6fa46
3 changed files with 422 additions and 5 deletions

View File

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

View File

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

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