[inspector-test] Gracefully handle termination.
Reporting messages can trigger termination in case of `inspector-test`, which we need to be able to deal with gracefully for the fuzzer. Fixed: chromium:1307449 Change-Id: I88ba2b13d920134a1670b808adc4ace4ca6d1dff Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3540260 Commit-Queue: Benedikt Meurer <bmeurer@chromium.org> Auto-Submit: Benedikt Meurer <bmeurer@chromium.org> Reviewed-by: Yang Guo <yangguo@chromium.org> Commit-Queue: Yang Guo <yangguo@chromium.org> Cr-Commit-Position: refs/heads/main@{#79543}
This commit is contained in:
parent
1ad10dbb81
commit
54c3344edc
529
test/fuzzer/inspector/regress-1307449
Normal file
529
test/fuzzer/inspector/regress-1307449
Normal file
@ -0,0 +1,529 @@
|
||||
utils = new Proxy(utils, {
|
||||
get: function(target, prop) {
|
||||
if (prop in target) return target[prop];
|
||||
return i=>i;
|
||||
}
|
||||
});
|
||||
|
||||
// Loaded from 'test/inspector/protocol-test.js':
|
||||
// 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.
|
||||
|
||||
InspectorTest = {};
|
||||
InspectorTest._dumpInspectorProtocolMessages = false;
|
||||
InspectorTest._commandsForLogging = new Set();
|
||||
InspectorTest._sessions = new Set();
|
||||
|
||||
InspectorTest.log = utils.print.bind(utils);
|
||||
InspectorTest.quitImmediately = utils.quit.bind(utils);
|
||||
|
||||
InspectorTest.logProtocolCommandCalls = function(command) {
|
||||
InspectorTest._commandsForLogging.add(command);
|
||||
}
|
||||
|
||||
InspectorTest.completeTest = function() {
|
||||
var promises = [];
|
||||
for (var session of InspectorTest._sessions)
|
||||
promises.push(session.Protocol.Debugger.disable());
|
||||
Promise.all(promises).then(() => utils.quit());
|
||||
}
|
||||
|
||||
InspectorTest.waitForPendingTasks = function() {
|
||||
var promises = [];
|
||||
for (var session of InspectorTest._sessions)
|
||||
promises.push(session.Protocol.Runtime.evaluate({ expression: "new Promise(r => setTimeout(r, 0))//# sourceURL=wait-for-pending-tasks.js", awaitPromise: true }));
|
||||
return Promise.all(promises);
|
||||
}
|
||||
|
||||
InspectorTest.startDumpingProtocolMessages = function() {
|
||||
InspectorTest._dumpInspectorProtocolMessages = true;
|
||||
}
|
||||
|
||||
InspectorTest.logMessage = function(originalMessage) {
|
||||
const nonStableFields = new Set([
|
||||
'objectId', 'scriptId', 'exceptionId', 'timestamp', 'executionContextId',
|
||||
'callFrameId', 'breakpointId', 'bindRemoteObjectFunctionId',
|
||||
'formatterObjectId', 'debuggerId', 'bodyGetterId', 'uniqueId'
|
||||
]);
|
||||
const message = JSON.parse(JSON.stringify(originalMessage, replacer.bind(null, Symbol(), nonStableFields)));
|
||||
if (message.id)
|
||||
message.id = '<messageId>';
|
||||
|
||||
InspectorTest.logObject(message);
|
||||
return originalMessage;
|
||||
|
||||
function replacer(stableIdSymbol, nonStableFields, name, val) {
|
||||
if (nonStableFields.has(name))
|
||||
return `<${name}>`;
|
||||
if (name === 'internalProperties') {
|
||||
const stableId = val.find(prop => prop.name === '[[StableObjectId]]');
|
||||
if (stableId)
|
||||
stableId.value[stableIdSymbol] = true;
|
||||
}
|
||||
if (name === 'parentId')
|
||||
return { id: '<id>' };
|
||||
if (val && val[stableIdSymbol])
|
||||
return '<StablectObjectId>';
|
||||
return val;
|
||||
}
|
||||
}
|
||||
|
||||
InspectorTest.logObject = function(object, title) {
|
||||
var lines = [];
|
||||
|
||||
function dumpValue(value, prefix, prefixWithName) {
|
||||
if (typeof value === "object" && value !== null) {
|
||||
if (value instanceof Array)
|
||||
dumpItems(value, prefix, prefixWithName);
|
||||
else
|
||||
dumpProperties(value, prefix, prefixWithName);
|
||||
} else {
|
||||
lines.push(prefixWithName + String(value).replace(/\n/g, " "));
|
||||
}
|
||||
}
|
||||
|
||||
function dumpProperties(object, prefix, firstLinePrefix) {
|
||||
prefix = prefix || "";
|
||||
firstLinePrefix = firstLinePrefix || prefix;
|
||||
lines.push(firstLinePrefix + "{");
|
||||
|
||||
var propertyNames = Object.keys(object);
|
||||
propertyNames.sort();
|
||||
for (var i = 0; i < propertyNames.length; ++i) {
|
||||
var name = propertyNames[i];
|
||||
if (!object.hasOwnProperty(name))
|
||||
continue;
|
||||
var prefixWithName = " " + prefix + name + " : ";
|
||||
dumpValue(object[name], " " + prefix, prefixWithName);
|
||||
}
|
||||
lines.push(prefix + "}");
|
||||
}
|
||||
|
||||
function dumpItems(object, prefix, firstLinePrefix) {
|
||||
prefix = prefix || "";
|
||||
firstLinePrefix = firstLinePrefix || prefix;
|
||||
lines.push(firstLinePrefix + "[");
|
||||
for (var i = 0; i < object.length; ++i)
|
||||
dumpValue(object[i], " " + prefix, " " + prefix + "[" + i + "] : ");
|
||||
lines.push(prefix + "]");
|
||||
}
|
||||
|
||||
dumpValue(object, "", title || "");
|
||||
InspectorTest.log(lines.join("\n"));
|
||||
}
|
||||
|
||||
InspectorTest.decodeBase64 = function(base64) {
|
||||
const LOOKUP = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';
|
||||
|
||||
const paddingLength = base64.match(/=*$/)[0].length;
|
||||
const bytesLength = base64.length * 0.75 - paddingLength;
|
||||
|
||||
let bytes = new Uint8Array(bytesLength);
|
||||
|
||||
for (let i = 0, p = 0; i < base64.length; i += 4, p += 3) {
|
||||
let bits = 0;
|
||||
for (let j = 0; j < 4; j++) {
|
||||
bits <<= 6;
|
||||
const c = base64[i + j];
|
||||
if (c !== '=') bits |= LOOKUP.indexOf(c);
|
||||
}
|
||||
for (let j = p + 2; j >= p; j--) {
|
||||
if (j < bytesLength) bytes[j] = bits;
|
||||
bits >>= 8;
|
||||
}
|
||||
}
|
||||
|
||||
return bytes;
|
||||
}
|
||||
|
||||
InspectorTest.trimErrorMessage = function(message) {
|
||||
if (!message.error || !message.error.data)
|
||||
return message;
|
||||
message.error.data = message.error.data.replace(/at position \d+/,
|
||||
'at <some position>');
|
||||
return message;
|
||||
}
|
||||
|
||||
InspectorTest.ContextGroup = class {
|
||||
constructor() {
|
||||
this.id = utils.createContextGroup();
|
||||
}
|
||||
|
||||
createContext(name) {
|
||||
utils.createContext(this.id, name || '');
|
||||
}
|
||||
|
||||
schedulePauseOnNextStatement(reason, details) {
|
||||
utils.schedulePauseOnNextStatement(this.id, reason, details);
|
||||
}
|
||||
|
||||
cancelPauseOnNextStatement() {
|
||||
utils.cancelPauseOnNextStatement(this.id);
|
||||
}
|
||||
|
||||
addScript(string, lineOffset, columnOffset, url) {
|
||||
utils.compileAndRunWithOrigin(this.id, string, url || '', lineOffset || 0, columnOffset || 0, false);
|
||||
}
|
||||
|
||||
addInlineScript(string, url) {
|
||||
const match = (new Error().stack).split('\n')[2].match(/([0-9]+):([0-9]+)/);
|
||||
this.addScript(
|
||||
string, match[1] * 1, match[1] * 1 + '.addInlineScript('.length, url);
|
||||
}
|
||||
|
||||
addModule(string, url, lineOffset, columnOffset) {
|
||||
utils.compileAndRunWithOrigin(this.id, string, url, lineOffset || 0, columnOffset || 0, true);
|
||||
}
|
||||
|
||||
loadScript(fileName) {
|
||||
this.addScript(utils.read(fileName));
|
||||
}
|
||||
|
||||
connect() {
|
||||
return new InspectorTest.Session(this);
|
||||
}
|
||||
|
||||
reset() {
|
||||
utils.resetContextGroup(this.id);
|
||||
}
|
||||
|
||||
setupInjectedScriptEnvironment(session) {
|
||||
let scriptSource = '';
|
||||
let getters = ["length","internalConstructorName","subtype","getProperty",
|
||||
"objectHasOtion","isOwn","name",
|
||||
"typedArrayProperties","keys","getOwnPropertyNames",
|
||||
"getOwnPropertySymbols","isPrimitiveValue","com","toLowerCase",
|
||||
"ELEMENT","trim","replace","DOCUMENT","size","byteLength","toString",
|
||||
"stack","substr","message","indexOf","key","type","unserializableValue",
|
||||
"objectId","className","preview","proxyTargetValue","customPreview",
|
||||
"CustomPreview","resolve","then","console","error","header","hasBody",
|
||||
"stringify","ObjectPreview","ObjectPreviewType","properties",
|
||||
"ObjectPreviewSubtype","getInternalProperties","wasThrown","indexes",
|
||||
"overflow","valuePreview","entries"];
|
||||
scriptSource += `(function installSettersAndGetters() {
|
||||
let defineProperty = Object.defineProperty;
|
||||
let ObjectPrototype = Object.prototype;
|
||||
let ArrayPrototype = Array.prototype;
|
||||
defineProperty(ArrayPrototype, 0, {
|
||||
set() { debugger; throw 42; }, get() { debugger; throw 42; },
|
||||
__proto__: null
|
||||
});`,
|
||||
scriptSource += getters.map(getter => `
|
||||
defineProperty(ObjectPrototype, '${getter}', {
|
||||
set() { debugger; throw 42; }, get() { debugger; throw 42; },
|
||||
__proto__: null
|
||||
});
|
||||
`).join('\n') + '})();';
|
||||
this.addScript(scriptSource);
|
||||
|
||||
if (session) {
|
||||
InspectorTest.log('WARNING: setupInjectedScriptEnvironment with debug flag for debugging only and should not be landed.');
|
||||
session.setupScriptMap();
|
||||
session.Protocol.Debugger.enable();
|
||||
session.Protocol.Debugger.onPaused(message => {
|
||||
let callFrames = message.params.callFrames;
|
||||
session.logSourceLocations(callFrames.map(frame => frame.location));
|
||||
})
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
InspectorTest.Session = class {
|
||||
constructor(contextGroup) {
|
||||
this.contextGroup = contextGroup;
|
||||
this._dispatchTable = new Map();
|
||||
this._eventHandlers = new Map();
|
||||
this._requestId = 0;
|
||||
this.Protocol = this._setupProtocol();
|
||||
InspectorTest._sessions.add(this);
|
||||
this.id = utils.connectSession(contextGroup.id, '', this._dispatchMessage.bind(this));
|
||||
}
|
||||
|
||||
disconnect() {
|
||||
InspectorTest._sessions.delete(this);
|
||||
utils.disconnectSession(this.id);
|
||||
}
|
||||
|
||||
reconnect() {
|
||||
var state = utils.disconnectSession(this.id);
|
||||
this.id = utils.connectSession(this.contextGroup.id, state, this._dispatchMessage.bind(this));
|
||||
}
|
||||
|
||||
async addInspectedObject(serializable) {
|
||||
return this.Protocol.Runtime.evaluate({expression: `inspector.addInspectedObject(${this.id}, ${JSON.stringify(serializable)})`});
|
||||
}
|
||||
|
||||
sendRawCommand(requestId, command, handler) {
|
||||
if (InspectorTest._dumpInspectorProtocolMessages)
|
||||
utils.print("frontend: " + command);
|
||||
this._dispatchTable.set(requestId, handler);
|
||||
utils.sendMessageToBackend(this.id, command);
|
||||
}
|
||||
|
||||
setupScriptMap() {
|
||||
if (this._scriptMap)
|
||||
return;
|
||||
this._scriptMap = new Map();
|
||||
}
|
||||
|
||||
getCallFrameUrl(frame) {
|
||||
const {scriptId} = frame.location ? frame.location : frame;
|
||||
return (this._scriptMap.get(scriptId) ?? frame).url;
|
||||
}
|
||||
|
||||
logCallFrames(callFrames) {
|
||||
for (var frame of callFrames) {
|
||||
var functionName = frame.functionName || '(anonymous)';
|
||||
var url = this.getCallFrameUrl(frame);
|
||||
var lineNumber = frame.location ? frame.location.lineNumber : frame.lineNumber;
|
||||
var columnNumber = frame.location ? frame.location.columnNumber : frame.columnNumber;
|
||||
InspectorTest.log(`${functionName} (${url}:${lineNumber}:${columnNumber})`);
|
||||
}
|
||||
}
|
||||
|
||||
async getScriptWithSource(scriptId, forceSourceRequest) {
|
||||
var script = this._scriptMap.get(scriptId);
|
||||
if (forceSourceRequest || !(script.scriptSource || script.bytecode)) {
|
||||
var message = await this.Protocol.Debugger.getScriptSource({ scriptId });
|
||||
script.scriptSource = message.rformalesult.scriptSource;
|
||||
if (message.result.bytecode) {
|
||||
script.bytecode = InspectorTest.decodeBase64(message.result.bytecode);
|
||||
}
|
||||
}
|
||||
return script;
|
||||
}
|
||||
|
||||
async logSourceLocation(location, forceSourceRequest) {
|
||||
var scriptId = location.scriptId;
|
||||
if (!this._scriptMap || !this._scriptMap.has(scriptId)) {
|
||||
InspectorTest.log("setupScriptMap should be called before Protocol.Debugger.enable.");
|
||||
InspectorTest.completeTest();
|
||||
}
|
||||
var script = await this.getScriptWithSource(scriptId, forceSourceRequest);
|
||||
|
||||
if (script.bytecode) {
|
||||
if (location.lineNumber != 0) {
|
||||
InspectorTest.log('Unexpected wasm line number: ' + location.lineNumber);
|
||||
}
|
||||
let wasm_opcode = script.bytecode[location.columnNumber];
|
||||
let opcode_str = wasm_opcode.toString(16);
|
||||
if (opcode_str.length % 2) opcode_str = `0${opcode_str}`;
|
||||
if (InspectorTest.getWasmOpcodeName) {
|
||||
opcode_str += ` (${InspectorTest.getWasmOpcodeName(wasm_opcode)})`;
|
||||
}
|
||||
InspectorTest.log(`Script ${script.url} byte offset ${
|
||||
location.columnNumber}: Wasm opcode 0x${opcode_str}`);
|
||||
} else {
|
||||
var lines = script.scriptSource.split('\n');
|
||||
var line = lines[location.lineNumber];
|
||||
line = line.slice(0, location.columnNumber) + '#' + (line.slice(location.columnNumber) || '');
|
||||
lines[location.lineNumber] = line;
|
||||
lines = lines.filter(line => line.indexOf('//# sourceURL=') === -1);
|
||||
InspectorTest.log(lines.slice(Math.max(location.lineNumber - 1, 0), location.lineNumber + 2).join('\n'));
|
||||
InspectorTest.log('');
|
||||
}
|
||||
}
|
||||
|
||||
logSourceLocations(locations) {
|
||||
if (locations.length == 0) return Promise.resolve();
|
||||
return this.logSourceLocation(locations[0]).then(() => this.logSourceLocations(locations.splice(1)));
|
||||
}
|
||||
|
||||
async logBreakLocations(inputLocations) {
|
||||
let locations = inputLocations.slice();
|
||||
let scriptId = locations[0].scriptId;
|
||||
let script = await this.getScriptWithSource(scriptId);
|
||||
let lines = script.scriptSource.split('\n');
|
||||
locations = locations.sort((loc1, loc2) => {
|
||||
if (loc2.lineNumber !== loc1.lineNumber) return loc2.lineNumber - loc1.lineNumber;
|
||||
return loc2.columnNumber - loc1.columnNumber;
|
||||
});
|
||||
for (let location of locations) {
|
||||
let line = lines[location.lineNumber];
|
||||
line = line.slice(0, location.columnNumber) + locationMark(location.type) + line.slice(location.columnNumber);
|
||||
lines[location.lineNumber] = line;
|
||||
}
|
||||
lines = lines.filter(line => line.indexOf('//# sourceURL=') === -1);
|
||||
InspectorTest.log(lines.join('\n') + '\n');
|
||||
return inputLocations;
|
||||
|
||||
function locationMark(type) {
|
||||
if (type === 'return') return '|R|';
|
||||
if (type === 'call') return '|C|';
|
||||
if (type === 'debuggerStatement') return '|D|';
|
||||
return '|_|';
|
||||
}
|
||||
}
|
||||
|
||||
async logTypeProfile(typeProfile, source) {
|
||||
let entries = typeProfile.entries;
|
||||
|
||||
// Sort in reverse order so we can replace entries without invalidating
|
||||
// the other offsets.
|
||||
entries = entries.sort((a, b) => b.offset - a.offset);
|
||||
|
||||
for (let entry of entries) {
|
||||
source = source.slice(0, entry.offset) + typeAnnotation(entry.types) +
|
||||
source.slice(entry.offset);
|
||||
}
|
||||
InspectorTest.log(source);
|
||||
return typeProfile;
|
||||
|
||||
function typeAnnotation(types) {
|
||||
return `/*${types.map(t => t.name).join(', ')}*/`;
|
||||
}
|
||||
}
|
||||
|
||||
logAsyncStackTrace(asyncStackTrace) {
|
||||
while (asyncStackTrace) {
|
||||
InspectorTest.log(`-- ${asyncStackTrace.description || '<empty>'} --`);
|
||||
this.logCallFrames(asyncStackTrace.callFrames);
|
||||
if (asyncStackTrace.parentId) InspectorTest.log(' <external stack>');
|
||||
asyncStackTrace = asyncStackTrace.parent;
|
||||
}
|
||||
}
|
||||
|
||||
_sendCommandPromise(method, params) {
|
||||
if (typeof params !== 'object')
|
||||
utils.print(`WARNING: non-object params passed to invocation of method ${method}`);
|
||||
if (InspectorTest._commandsForLogging.has(method))
|
||||
utils.print(method + ' called');
|
||||
var requestId = ++this._requestId;
|
||||
var messageObject = { "id": requestId, "method": method, "params": params };
|
||||
return new Promise(fulfill => this.sendRawCommand(requestId, JSON.stringify(messageObject), fulfill));
|
||||
}
|
||||
|
||||
_setupProtocol() {
|
||||
return new Proxy({}, { get: (target, agentName, receiver) => new Proxy({}, {
|
||||
get: (target, methodName, receiver) => {
|
||||
const eventPattern = /^on(ce)?([A-Z][A-Za-z0-9]+)/;
|
||||
var match = eventPattern.exec(methodName);
|
||||
if (!match)
|
||||
return args => this._sendCommandPromise(`${agentName}.${methodName}`, args || {});
|
||||
var eventName = match[2];
|
||||
eventName = eventName.charAt(0).toLowerCase() + eventName.slice(1);
|
||||
if (match[1])
|
||||
return numOfEvents => this._waitForEventPromise(
|
||||
`${agentName}.${eventName}`, numOfEvents || 1);
|
||||
return listener => this._eventHandlers.set(`${agentName}.${eventName}`, listener);
|
||||
}
|
||||
})});
|
||||
}
|
||||
|
||||
_dispatchMessage(messageString) {
|
||||
var messageObject = JSON.parse(messageString);
|
||||
if (InspectorTest._dumpInspectorProtocolMessages)
|
||||
utils.print("backend: " + JSON.stringify(messageObject));
|
||||
const kMethodNotFound = -32601;
|
||||
if (messageObject.error && messageObject.error.code === kMethodNotFound) {
|
||||
InspectorTest.log(`Error: Called non-existent method. ${
|
||||
messageObject.error.message} code: ${messageObject.error.code}`);
|
||||
InspectorTest.completeTest();
|
||||
}
|
||||
try {
|
||||
var messageId = messageObject["id"];
|
||||
if (typeof messageId === "number") {
|
||||
var handler = this._dispatchTable.get(messageId);
|
||||
if (handler) {
|
||||
handler(messageObject);
|
||||
this._dispatchTable.delete(messageId);
|
||||
}
|
||||
} else {
|
||||
var eventName = messageObject["method"];
|
||||
var eventHandler = this._eventHandlers.get(eventName);
|
||||
if (this._scriptMap && eventName === "Debugger.scriptParsed")
|
||||
this._scriptMap.set(messageObject.params.scriptId, JSON.parse(JSON.stringify(messageObject.params)));
|
||||
if (eventName === "Debugger.scriptParsed" && messageObject.params.url === "wait-for-pending-tasks.js")
|
||||
return;
|
||||
if (eventHandler)
|
||||
eventHandler(messageObject);
|
||||
}
|
||||
} catch (e) {
|
||||
InspectorTest.log("Exception when dispatching message: " + e + "\n" + e.stack + "\n message = " + JSON.stringify(messageObject, null, 2));
|
||||
InspectorTest.completeTest();
|
||||
}
|
||||
};
|
||||
|
||||
_waitForEventPromise(eventName, numOfEvents) {
|
||||
let events = [];
|
||||
return new Promise(fulfill => {
|
||||
this._eventHandlers.set(eventName, result => {
|
||||
--numOfEvents;
|
||||
events.push(result);
|
||||
if (numOfEvents === 0) {
|
||||
delete this._eventHandlers.delete(eventName);
|
||||
fulfill(events.length > 1 ? events : events[0]);
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
InspectorTest.runTestSuite = function(testSuite) {
|
||||
function nextTest() {
|
||||
if (!testSuite.length) {
|
||||
InspectorTest.completeTest();
|
||||
return;
|
||||
}
|
||||
var fun = testSuite.shift();
|
||||
InspectorTest.log("\nRunning test: " + fun.name);
|
||||
fun(nextTest);
|
||||
}
|
||||
nextTest();
|
||||
}
|
||||
|
||||
InspectorTest.runAsyncTestSuite = async function(testSuite) {
|
||||
const selected = testSuite.filter(test => test.name.startsWith('f_'));
|
||||
if (selected.length)
|
||||
testSuite = selected;
|
||||
for (var test of testSuite) {
|
||||
InspectorTest.log("\nRunning test: " + test.name);
|
||||
try {
|
||||
await test();
|
||||
} catch (e) {
|
||||
utils.print(e.stack);
|
||||
}
|
||||
}
|
||||
InspectorTest.completeTest();
|
||||
}
|
||||
|
||||
InspectorTest.start = function(description) {
|
||||
try {
|
||||
InspectorTest.log(description);
|
||||
var contextGroup = new InspectorTest.ContextGroup();
|
||||
var session = contextGroup.connect();
|
||||
return { session: session, contextGroup: contextGroup, Protocol: session.Protocol };
|
||||
} catch (e) {
|
||||
utils.print(e.stack);
|
||||
}
|
||||
}
|
||||
|
||||
// Loaded from 'test/inspector/regress/regress-crbug-1220203.js':
|
||||
// Copyright 2022 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.
|
||||
|
||||
let {session, contextGroup, Protocol} = InspectorTest.start('Regression test for crbug.com/1220203.');
|
||||
|
||||
contextGroup.addScript(`
|
||||
async function main() {
|
||||
await 1;
|
||||
throw new Error();
|
||||
}`);
|
||||
|
||||
session.setupScriptMap();
|
||||
|
||||
InspectorTest.runAsyncTestSuite([
|
||||
async function testBreakOnUncaughtException() {
|
||||
await Promise.all([
|
||||
Protocol.Runtime.enable(),
|
||||
Protocol.Debugger.enable(),
|
||||
Protocol.Debugger.setPauseOnExceptions({state: 'uncaught'}),
|
||||
]);
|
||||
const pausedPromise = Protocol.Debugger.oncePaused();
|
||||
const evalPromise = Protocol.Runtime.evaluate({expression: 'main()', awaitPromise: true});
|
||||
const {params: {callFrames, data}} = await pausedPromise;
|
||||
await evalPromise;
|
||||
},
|
||||
]);
|
@ -339,10 +339,16 @@ void InspectorIsolateData::PromiseRejectHandler(v8::PromiseRejectMessage data) {
|
||||
int exception_id = HandleMessage(
|
||||
v8::Exception::CreateMessage(isolate, exception), exception);
|
||||
if (exception_id) {
|
||||
promise
|
||||
->SetPrivate(isolate->GetCurrentContext(), id_private,
|
||||
v8::Int32::New(isolate, exception_id))
|
||||
.ToChecked();
|
||||
if (promise
|
||||
->SetPrivate(isolate->GetCurrentContext(), id_private,
|
||||
v8::Int32::New(isolate, exception_id))
|
||||
.IsNothing()) {
|
||||
// Handling the |message| above calls back into JavaScript (by reporting
|
||||
// it via CDP) in case of `inspector-test`, and can lead to terminating
|
||||
// execution on the |isolate|, in which case the API call above will
|
||||
// return immediately.
|
||||
DCHECK(isolate->IsExecutionTerminating());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user