[inspector] Make InjectedScript::getProperties respect custom formatters

BUG=chromium:917136

Change-Id: I02696a3315c22b34705bbc48cddaeb9e6c59fa9f
Reviewed-on: https://chromium-review.googlesource.com/c/1391749
Reviewed-by: Dmitry Gozman <dgozman@chromium.org>
Commit-Queue: Alexei Filippov <alph@chromium.org>
Cr-Commit-Position: refs/heads/master@{#58482}
This commit is contained in:
Alexei Filippov 2018-12-27 14:17:02 -08:00 committed by Commit Bot
parent 0d0f0c51c5
commit 4eae3bb140
6 changed files with 147 additions and 84 deletions

View File

@ -302,12 +302,9 @@ Response InjectedScript::getProperties(
Response response;
std::unique_ptr<RemoteObject> remoteObject;
if (mirror.value) {
response =
mirror.value->buildRemoteObject(context, wrapMode, &remoteObject);
if (!response.isSuccess()) return response;
response =
bindRemoteObjectIfNeeded(sessionId, context, mirror.value->v8Value(),
groupName, remoteObject.get());
response = wrapObjectMirror(*mirror.value, groupName, wrapMode,
v8::MaybeLocal<v8::Value>(),
kMaxCustomPreviewDepth, &remoteObject);
if (!response.isSuccess()) return response;
descriptor->setValue(std::move(remoteObject));
descriptor->setWritable(mirror.writable);
@ -411,12 +408,23 @@ Response InjectedScript::wrapObject(
std::unique_ptr<protocol::Runtime::RemoteObject>* result) {
v8::Local<v8::Context> context = m_context->context();
v8::Context::Scope contextScope(context);
std::unique_ptr<ValueMirror> mirror = ValueMirror::create(context, value);
if (!mirror) return Response::InternalError();
return wrapObjectMirror(*mirror, groupName, wrapMode, customPreviewConfig,
maxCustomPreviewDepth, result);
}
Response InjectedScript::wrapObjectMirror(
const ValueMirror& mirror, const String16& groupName, WrapMode wrapMode,
v8::MaybeLocal<v8::Value> customPreviewConfig, int maxCustomPreviewDepth,
std::unique_ptr<protocol::Runtime::RemoteObject>* result) {
int customPreviewEnabled = m_customPreviewEnabled;
int sessionId = m_sessionId;
auto obj = ValueMirror::create(m_context->context(), value);
if (!obj) return Response::InternalError();
Response response = obj->buildRemoteObject(context, wrapMode, result);
v8::Local<v8::Context> context = m_context->context();
v8::Context::Scope contextScope(context);
Response response = mirror.buildRemoteObject(context, wrapMode, result);
if (!response.isSuccess()) return response;
v8::Local<v8::Value> value = mirror.v8Value();
response = bindRemoteObjectIfNeeded(sessionId, context, value, groupName,
result->get());
if (!response.isSuccess()) return response;

View File

@ -48,6 +48,7 @@ namespace v8_inspector {
class RemoteObjectId;
class V8InspectorImpl;
class V8InspectorSessionImpl;
class ValueMirror;
enum class WrapMode;
using protocol::Maybe;
@ -93,6 +94,10 @@ class InjectedScript final {
v8::MaybeLocal<v8::Value> customPreviewConfig,
int maxCustomPreviewDepth,
std::unique_ptr<protocol::Runtime::RemoteObject>* result);
Response wrapObjectMirror(
const ValueMirror& mirror, const String16& groupName, WrapMode wrapMode,
v8::MaybeLocal<v8::Value> customPreviewConfig, int maxCustomPreviewDepth,
std::unique_ptr<protocol::Runtime::RemoteObject>* result);
std::unique_ptr<protocol::Runtime::RemoteObject> wrapTable(
v8::Local<v8::Object> table, v8::MaybeLocal<v8::Array> columns);

View File

@ -325,9 +325,10 @@ class PrimitiveValueMirror final : public ValueMirror {
PrimitiveValueMirror(v8::Local<v8::Value> value, const String16& type)
: m_value(value), m_type(type) {}
v8::Local<v8::Value> v8Value() override { return m_value; }
Response buildRemoteObject(v8::Local<v8::Context> context, WrapMode mode,
std::unique_ptr<RemoteObject>* result) override {
v8::Local<v8::Value> v8Value() const override { return m_value; }
Response buildRemoteObject(
v8::Local<v8::Context> context, WrapMode mode,
std::unique_ptr<RemoteObject>* result) const override {
std::unique_ptr<protocol::Value> protocolValue;
toProtocolValue(context, m_value, &protocolValue);
*result = RemoteObject::create()
@ -339,9 +340,9 @@ class PrimitiveValueMirror final : public ValueMirror {
return Response::OK();
}
void buildEntryPreview(v8::Local<v8::Context> context, int* nameLimit,
int* indexLimit,
std::unique_ptr<ObjectPreview>* preview) override {
void buildEntryPreview(
v8::Local<v8::Context> context, int* nameLimit, int* indexLimit,
std::unique_ptr<ObjectPreview>* preview) const override {
*preview =
ObjectPreview::create()
.setType(m_type)
@ -355,7 +356,7 @@ class PrimitiveValueMirror final : public ValueMirror {
void buildPropertyPreview(
v8::Local<v8::Context> context, const String16& name,
std::unique_ptr<PropertyPreview>* preview) override {
std::unique_ptr<PropertyPreview>* preview) const override {
*preview = PropertyPreview::create()
.setName(name)
.setValue(abbreviateString(
@ -375,10 +376,11 @@ class PrimitiveValueMirror final : public ValueMirror {
class NumberMirror final : public ValueMirror {
public:
explicit NumberMirror(v8::Local<v8::Number> value) : m_value(value) {}
v8::Local<v8::Value> v8Value() override { return m_value; }
v8::Local<v8::Value> v8Value() const override { return m_value; }
Response buildRemoteObject(v8::Local<v8::Context> context, WrapMode mode,
std::unique_ptr<RemoteObject>* result) override {
Response buildRemoteObject(
v8::Local<v8::Context> context, WrapMode mode,
std::unique_ptr<RemoteObject>* result) const override {
bool unserializable = false;
String16 descriptionValue = description(&unserializable);
*result = RemoteObject::create()
@ -392,9 +394,9 @@ class NumberMirror final : public ValueMirror {
}
return Response::OK();
}
void buildPropertyPreview(v8::Local<v8::Context> context,
const String16& name,
std::unique_ptr<PropertyPreview>* result) override {
void buildPropertyPreview(
v8::Local<v8::Context> context, const String16& name,
std::unique_ptr<PropertyPreview>* result) const override {
bool unserializable = false;
*result = PropertyPreview::create()
.setName(name)
@ -402,9 +404,9 @@ class NumberMirror final : public ValueMirror {
.setValue(description(&unserializable))
.build();
}
void buildEntryPreview(v8::Local<v8::Context> context, int* nameLimit,
int* indexLimit,
std::unique_ptr<ObjectPreview>* preview) override {
void buildEntryPreview(
v8::Local<v8::Context> context, int* nameLimit, int* indexLimit,
std::unique_ptr<ObjectPreview>* preview) const override {
bool unserializable = false;
*preview = ObjectPreview::create()
.setType(RemoteObject::TypeEnum::Number)
@ -415,7 +417,7 @@ class NumberMirror final : public ValueMirror {
}
private:
String16 description(bool* unserializable) {
String16 description(bool* unserializable) const {
*unserializable = true;
double rawValue = m_value->Value();
if (std::isnan(rawValue)) return "NaN";
@ -434,8 +436,9 @@ class BigIntMirror final : public ValueMirror {
public:
explicit BigIntMirror(v8::Local<v8::BigInt> value) : m_value(value) {}
Response buildRemoteObject(v8::Local<v8::Context> context, WrapMode mode,
std::unique_ptr<RemoteObject>* result) override {
Response buildRemoteObject(
v8::Local<v8::Context> context, WrapMode mode,
std::unique_ptr<RemoteObject>* result) const override {
String16 description = descriptionForBigInt(context, m_value);
*result = RemoteObject::create()
.setType(RemoteObject::TypeEnum::Bigint)
@ -445,9 +448,10 @@ class BigIntMirror final : public ValueMirror {
return Response::OK();
}
void buildPropertyPreview(
v8::Local<v8::Context> context, const String16& name,
std::unique_ptr<protocol::Runtime::PropertyPreview>* preview) override {
void buildPropertyPreview(v8::Local<v8::Context> context,
const String16& name,
std::unique_ptr<protocol::Runtime::PropertyPreview>*
preview) const override {
*preview = PropertyPreview::create()
.setName(name)
.setType(RemoteObject::TypeEnum::Bigint)
@ -456,9 +460,10 @@ class BigIntMirror final : public ValueMirror {
.build();
}
void buildEntryPreview(
v8::Local<v8::Context> context, int* nameLimit, int* indexLimit,
std::unique_ptr<protocol::Runtime::ObjectPreview>* preview) override {
void buildEntryPreview(v8::Local<v8::Context> context, int* nameLimit,
int* indexLimit,
std::unique_ptr<protocol::Runtime::ObjectPreview>*
preview) const override {
*preview = ObjectPreview::create()
.setType(RemoteObject::TypeEnum::Bigint)
.setDescription(descriptionForBigInt(context, m_value))
@ -467,7 +472,7 @@ class BigIntMirror final : public ValueMirror {
.build();
}
v8::Local<v8::Value> v8Value() override { return m_value; }
v8::Local<v8::Value> v8Value() const override { return m_value; }
private:
v8::Local<v8::BigInt> m_value;
@ -478,8 +483,9 @@ class SymbolMirror final : public ValueMirror {
explicit SymbolMirror(v8::Local<v8::Value> value)
: m_symbol(value.As<v8::Symbol>()) {}
Response buildRemoteObject(v8::Local<v8::Context> context, WrapMode mode,
std::unique_ptr<RemoteObject>* result) override {
Response buildRemoteObject(
v8::Local<v8::Context> context, WrapMode mode,
std::unique_ptr<RemoteObject>* result) const override {
if (mode == WrapMode::kForceValue) {
return Response::Error("Object couldn't be returned by value");
}
@ -490,9 +496,10 @@ class SymbolMirror final : public ValueMirror {
return Response::OK();
}
void buildPropertyPreview(
v8::Local<v8::Context> context, const String16& name,
std::unique_ptr<protocol::Runtime::PropertyPreview>* preview) override {
void buildPropertyPreview(v8::Local<v8::Context> context,
const String16& name,
std::unique_ptr<protocol::Runtime::PropertyPreview>*
preview) const override {
*preview = PropertyPreview::create()
.setName(name)
.setType(RemoteObject::TypeEnum::Symbol)
@ -501,7 +508,7 @@ class SymbolMirror final : public ValueMirror {
.build();
}
v8::Local<v8::Value> v8Value() override { return m_symbol; }
v8::Local<v8::Value> v8Value() const override { return m_symbol; }
private:
v8::Local<v8::Symbol> m_symbol;
@ -530,8 +537,9 @@ class LocationMirror final : public ValueMirror {
suspendedLocation.GetColumnNumber());
}
Response buildRemoteObject(v8::Local<v8::Context> context, WrapMode mode,
std::unique_ptr<RemoteObject>* result) override {
Response buildRemoteObject(
v8::Local<v8::Context> context, WrapMode mode,
std::unique_ptr<RemoteObject>* result) const override {
auto location = protocol::DictionaryValue::create();
location->setString("scriptId", String16::fromInteger(m_scriptId));
location->setInteger("lineNumber", m_lineNumber);
@ -544,7 +552,7 @@ class LocationMirror final : public ValueMirror {
.build();
return Response::OK();
}
v8::Local<v8::Value> v8Value() override { return m_value; }
v8::Local<v8::Value> v8Value() const override { return m_value; }
private:
static std::unique_ptr<LocationMirror> create(v8::Local<v8::Value> value,
@ -577,10 +585,11 @@ class FunctionMirror final : public ValueMirror {
explicit FunctionMirror(v8::Local<v8::Value> value)
: m_value(value.As<v8::Function>()) {}
v8::Local<v8::Value> v8Value() override { return m_value; }
v8::Local<v8::Value> v8Value() const override { return m_value; }
Response buildRemoteObject(v8::Local<v8::Context> context, WrapMode mode,
std::unique_ptr<RemoteObject>* result) override {
Response buildRemoteObject(
v8::Local<v8::Context> context, WrapMode mode,
std::unique_ptr<RemoteObject>* result) const override {
// TODO(alph): drop this functionality.
if (mode == WrapMode::kForceValue) {
std::unique_ptr<protocol::Value> protocolValue;
@ -601,18 +610,18 @@ class FunctionMirror final : public ValueMirror {
return Response::OK();
}
void buildPropertyPreview(v8::Local<v8::Context> context,
const String16& name,
std::unique_ptr<PropertyPreview>* result) override {
void buildPropertyPreview(
v8::Local<v8::Context> context, const String16& name,
std::unique_ptr<PropertyPreview>* result) const override {
*result = PropertyPreview::create()
.setName(name)
.setType(RemoteObject::TypeEnum::Function)
.setValue(String16())
.build();
}
void buildEntryPreview(v8::Local<v8::Context> context, int* nameLimit,
int* indexLimit,
std::unique_ptr<ObjectPreview>* preview) override {
void buildEntryPreview(
v8::Local<v8::Context> context, int* nameLimit, int* indexLimit,
std::unique_ptr<ObjectPreview>* preview) const override {
*preview = ObjectPreview::create()
.setType(RemoteObject::TypeEnum::Function)
.setDescription(descriptionForFunction(context, m_value))
@ -809,10 +818,11 @@ class ObjectMirror final : public ValueMirror {
m_hasSubtype(true),
m_subtype(subtype) {}
v8::Local<v8::Value> v8Value() override { return m_value; }
v8::Local<v8::Value> v8Value() const override { return m_value; }
Response buildRemoteObject(v8::Local<v8::Context> context, WrapMode mode,
std::unique_ptr<RemoteObject>* result) override {
Response buildRemoteObject(
v8::Local<v8::Context> context, WrapMode mode,
std::unique_ptr<RemoteObject>* result) const override {
if (mode == WrapMode::kForceValue) {
std::unique_ptr<protocol::Value> protocolValue;
Response response = toProtocolValue(context, m_value, &protocolValue);
@ -842,26 +852,26 @@ class ObjectMirror final : public ValueMirror {
return Response::OK();
}
void buildObjectPreview(v8::Local<v8::Context> context,
bool generatePreviewForTable, int* nameLimit,
int* indexLimit,
std::unique_ptr<ObjectPreview>* result) override {
void buildObjectPreview(
v8::Local<v8::Context> context, bool generatePreviewForTable,
int* nameLimit, int* indexLimit,
std::unique_ptr<ObjectPreview>* result) const override {
buildObjectPreviewInternal(context, false /* forEntry */,
generatePreviewForTable, nameLimit, indexLimit,
result);
}
void buildEntryPreview(v8::Local<v8::Context> context, int* nameLimit,
int* indexLimit,
std::unique_ptr<ObjectPreview>* result) override {
void buildEntryPreview(
v8::Local<v8::Context> context, int* nameLimit, int* indexLimit,
std::unique_ptr<ObjectPreview>* result) const override {
buildObjectPreviewInternal(context, true /* forEntry */,
false /* generatePreviewForTable */, nameLimit,
indexLimit, result);
}
void buildPropertyPreview(v8::Local<v8::Context> context,
const String16& name,
std::unique_ptr<PropertyPreview>* result) override {
void buildPropertyPreview(
v8::Local<v8::Context> context, const String16& name,
std::unique_ptr<PropertyPreview>* result) const override {
*result = PropertyPreview::create()
.setName(name)
.setType(RemoteObject::TypeEnum::Object)
@ -874,10 +884,10 @@ class ObjectMirror final : public ValueMirror {
}
private:
void buildObjectPreviewInternal(v8::Local<v8::Context> context, bool forEntry,
bool generatePreviewForTable, int* nameLimit,
int* indexLimit,
std::unique_ptr<ObjectPreview>* result) {
void buildObjectPreviewInternal(
v8::Local<v8::Context> context, bool forEntry,
bool generatePreviewForTable, int* nameLimit, int* indexLimit,
std::unique_ptr<ObjectPreview>* result) const {
std::unique_ptr<protocol::Array<PropertyPreview>> properties =
protocol::Array<PropertyPreview>::create();
std::unique_ptr<protocol::Array<EntryPreview>> entriesPreview;

View File

@ -47,18 +47,18 @@ class ValueMirror {
v8::Local<v8::Value> value);
virtual protocol::Response buildRemoteObject(
v8::Local<v8::Context> context, WrapMode mode,
std::unique_ptr<protocol::Runtime::RemoteObject>* result) = 0;
std::unique_ptr<protocol::Runtime::RemoteObject>* result) const = 0;
virtual void buildPropertyPreview(
v8::Local<v8::Context> context, const String16& name,
std::unique_ptr<protocol::Runtime::PropertyPreview>*) {}
std::unique_ptr<protocol::Runtime::PropertyPreview>*) const {}
virtual void buildObjectPreview(
v8::Local<v8::Context> context, bool generatePreviewForTable,
int* nameLimit, int* indexLimit,
std::unique_ptr<protocol::Runtime::ObjectPreview>*) {}
std::unique_ptr<protocol::Runtime::ObjectPreview>*) const {}
virtual void buildEntryPreview(
v8::Local<v8::Context> context, int* nameLimit, int* indexLimit,
std::unique_ptr<protocol::Runtime::ObjectPreview>*) {}
virtual v8::Local<v8::Value> v8Value() = 0;
std::unique_ptr<protocol::Runtime::ObjectPreview>*) const {}
virtual v8::Local<v8::Value> v8Value() const = 0;
class PropertyAccumulator {
public:

View File

@ -148,6 +148,35 @@ Change formatters order and dump again..
{
header : ["span",{},"Formatter with config ",["object",{"type":"object","className":"Object","description":"Object","objectId":"{\"injectedScriptId\":1,\"id\":21}","customPreview":{"header":"[\"span\",{},\"Header \",\"info: \",\"additional info\"]","bodyGetterId":"{\"injectedScriptId\":1,\"id\":22}"}}]]
}
Test Runtime.getProperties
{
bodyGetterId : <bodyGetterId>
header : ["span",{},"Header formatted by 1 ","a"]
}
{
id : <messageId>
result : {
result : {
type : object
value : [
[0] : span
[1] : {
}
[2] : Body formatted by 1
[3] : a
[4] : [
[0] : object
[1] : {
className : Object
description : Object
objectId : <objectId>
type : object
}
]
]
}
}
}
Try to break custom preview..
{
method : Runtime.consoleAPICalled

View File

@ -51,18 +51,24 @@ const {session, contextGroup, Protocol} =
Protocol.Runtime.onConsoleAPICalled(m => InspectorTest.logMessage(m));
InspectorTest.log('Dump custom previews..');
await dumpCustomPreview(await Protocol.Runtime.evaluate({expression: 'a'}));
await dumpCustomPreview(await Protocol.Runtime.evaluate({expression: 'b'}));
await dumpCustomPreview(await Protocol.Runtime.evaluate({expression: 'c'}));
await dumpCustomPreview(await Protocol.Runtime.evaluate({expression: 'configTest'}));
await dumpCustomPreviewForEvaluate(await Protocol.Runtime.evaluate({expression: 'a'}));
await dumpCustomPreviewForEvaluate(await Protocol.Runtime.evaluate({expression: 'b'}));
await dumpCustomPreviewForEvaluate(await Protocol.Runtime.evaluate({expression: 'c'}));
await dumpCustomPreviewForEvaluate(await Protocol.Runtime.evaluate({expression: 'configTest'}));
InspectorTest.log('Change formatters order and dump again..');
await Protocol.Runtime.evaluate({
expression: 'this.devtoolsFormatters = [formatter2, formatter1, formatterWithConfig1, formatterWithConfig2]'
});
await dumpCustomPreview(await Protocol.Runtime.evaluate({expression: 'a'}));
await dumpCustomPreview(await Protocol.Runtime.evaluate({expression: 'b'}));
await dumpCustomPreview(await Protocol.Runtime.evaluate({expression: 'c'}));
await dumpCustomPreview(await Protocol.Runtime.evaluate({expression: 'configTest'}));
await dumpCustomPreviewForEvaluate(await Protocol.Runtime.evaluate({expression: 'a'}));
await dumpCustomPreviewForEvaluate(await Protocol.Runtime.evaluate({expression: 'b'}));
await dumpCustomPreviewForEvaluate(await Protocol.Runtime.evaluate({expression: 'c'}));
await dumpCustomPreviewForEvaluate(await Protocol.Runtime.evaluate({expression: 'configTest'}));
InspectorTest.log('Test Runtime.getProperties');
const {result:{result:{objectId}}} = await Protocol.Runtime.evaluate({expression: '({a})'});
const {result:{result}} = await Protocol.Runtime.getProperties({
objectId, ownProperties: true, generatePreview: true});
await dumpCustomPreview(result.find(value => value.name === 'a').value);
InspectorTest.log('Try to break custom preview..');
await Protocol.Runtime.evaluate({
@ -104,11 +110,16 @@ const {session, contextGroup, Protocol} =
});
Protocol.Runtime.evaluate({ expression: '({})', generatePreview: true });
InspectorTest.logMessage(await Protocol.Runtime.onceConsoleAPICalled());
InspectorTest.completeTest();
})()
function dumpCustomPreviewForEvaluate(result) {
return dumpCustomPreview(result.result.result);
}
async function dumpCustomPreview(result) {
const { objectId, customPreview } = result.result.result;
const { objectId, customPreview } = result;
InspectorTest.logMessage(customPreview);
if (customPreview.bodyGetterId) {
const body = await Protocol.Runtime.callFunctionOn({