v8/test/inspector/runtime/custom-preview.js
Dmitry Gozman 66725a537e [inspector] Prepend isolateId to remoteObjectId
This changes remoteObjectId format from
"{injectedScriptId:123,id:456}" to "<isolateId>.<contextId>.<id>".

Prepending isolateId fixes the problem that
remote object ids clash between processes. This is especially
troubling during cross-process navigation in Chromium, see bug.

We also stop producing and parsing unnecessary json for object ids.

Drive-by: fixed some tests dumping object ids. Most tests avoid
dumping unstable values like ids, but there were few that still did.

BUG=chromium:1137143

Change-Id: Ia019757fb95704ccb718d3ea6cc54bde1a133382
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2461731
Commit-Queue: Dmitry Gozman <dgozman@chromium.org>
Reviewed-by: Yang Guo <yangguo@chromium.org>
Cr-Commit-Position: refs/heads/master@{#70592}
2020-10-18 10:39:57 +00:00

136 lines
5.4 KiB
JavaScript

// Copyright 2018 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.
const {session, contextGroup, Protocol} =
InspectorTest.start('RemoteObject.CustomPreview');
(async function test() {
contextGroup.addScript(`
var a = {name: 'a'};
var b = {name: 'b'};
var c = {name: 'c'};
a.formattableBy1 = true;
b.formattableBy2 = true;
c.formattableBy1 = true;
c.formattableBy2 = true;
var formatter1 = {
header: (x) => x.formattableBy1 ? ['span', {}, 'Header formatted by 1 ', x.name] : null,
hasBody: () => true,
body: (x) => ['span', {}, 'Body formatted by 1 ', x.name, ['object', {object: {}}]]
};
var formatter2 = {
header: (x) => x.formattableBy2 ? ['span', {}, 'Header formatted by 2 ', x.name] : null,
hasBody: (x) => true,
body: (x) => ['span', {}, 'Body formatted by 2 ', x.name]
};
var configTest = {};
var formatterWithConfig1 = {
header: function(x, config) {
if (x !== configTest || config)
return null;
return ['span', {}, 'Formatter with config ', ['object', {'object': x, 'config': {'info': 'additional info'}}]];
},
hasBody: (x) => false,
body: (x) => { throw 'Unreachable'; }
}
var formatterWithConfig2 = {
header: function(x, config) {
if (x !== configTest || !config)
return null;
return ['span', {}, 'Header ', 'info: ', config.info];
},
hasBody: (x, config) => config && config.info,
body: (x, config) => ['span', {}, 'body', 'info: ', config.info]
}
this.devtoolsFormatters = [formatter1, formatter2, formatterWithConfig1, formatterWithConfig2];
`);
Protocol.Runtime.enable();
Protocol.Runtime.setCustomObjectFormatterEnabled({enabled: true});
Protocol.Runtime.onConsoleAPICalled(m => InspectorTest.logMessage(m));
InspectorTest.log('Dump custom previews..');
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 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({
expression: `Object.defineProperty(this, 'devtoolsFormatters', {
get: () => { throw 1; },
configurable: true
})`
});
Protocol.Runtime.evaluate({ expression: '({})', generatePreview: true });
InspectorTest.logMessage(await Protocol.Runtime.onceConsoleAPICalled());
await Protocol.Runtime.evaluate({
expression: `Object.defineProperty(this, 'devtoolsFormatters', {
get: () => {
const arr = [1];
Object.defineProperty(arr, 0, { get: () => { throw 2; }});
return arr;
},
configurable: true
})`
});
Protocol.Runtime.evaluate({ expression: '({})', generatePreview: true });
InspectorTest.logMessage(await Protocol.Runtime.onceConsoleAPICalled());
await Protocol.Runtime.evaluate({
expression: `Object.defineProperty(this, 'devtoolsFormatters', {
get: () => [{get header() { throw 3; }}],
configurable: true
})`
});
Protocol.Runtime.evaluate({ expression: '({})', generatePreview: true });
InspectorTest.logMessage(await Protocol.Runtime.onceConsoleAPICalled());
await Protocol.Runtime.evaluate({
expression: `Object.defineProperty(this, 'devtoolsFormatters', {
get: () => [{header: () => { throw 4; }}],
configurable: true
})`
});
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;
if (customPreview.header)
customPreview.header = JSON.parse(customPreview.header);
InspectorTest.logMessage(customPreview);
if (customPreview.bodyGetterId) {
const body = await Protocol.Runtime.callFunctionOn({
objectId,
functionDeclaration: 'function(bodyGetter) { return bodyGetter.call(this); }',
arguments: [ { objectId: customPreview.bodyGetterId } ],
returnByValue: true
});
InspectorTest.logMessage(body);
}
}