2021-01-05 07:42:18 +00:00
|
|
|
// Copyright 2021 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.
|
|
|
|
|
|
|
|
utils.load('test/inspector/wasm-inspector-test.js');
|
|
|
|
|
|
|
|
let {session, contextGroup, Protocol} =
|
|
|
|
InspectorTest.start('Test wasm debug evaluate');
|
|
|
|
|
|
|
|
Protocol.Debugger.enable();
|
|
|
|
Protocol.Runtime.enable();
|
|
|
|
|
|
|
|
async function compileModule(builder) {
|
|
|
|
const moduleBytes = JSON.stringify(builder.toArray());
|
|
|
|
const expression = `new WebAssembly.Module(new Uint8Array(${moduleBytes}).buffer);`;
|
|
|
|
const {result: {scriptId}} = await Protocol.Runtime.compileScript({expression, sourceURL: 'v8://test/compileModule', persistScript: true});
|
|
|
|
const [{params}, {result}] = await Promise.all([
|
|
|
|
Protocol.Debugger.onceScriptParsed(),
|
|
|
|
Protocol.Runtime.runScript({scriptId})
|
|
|
|
]);
|
|
|
|
return [result.result, params.scriptId];
|
|
|
|
}
|
|
|
|
|
2021-01-13 11:11:35 +00:00
|
|
|
async function instantiateModule({objectId}, importObject) {
|
2021-01-05 07:42:18 +00:00
|
|
|
const {result: {result}} = await Protocol.Runtime.callFunctionOn({
|
2021-01-13 11:11:35 +00:00
|
|
|
arguments: importObject ? [importObject] : [],
|
|
|
|
functionDeclaration: 'function(importObject) { return new WebAssembly.Instance(this, importObject); }',
|
2021-01-05 07:42:18 +00:00
|
|
|
objectId
|
|
|
|
});
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
async function dumpOnCallFrame(callFrameId, expression) {
|
2021-02-12 19:44:06 +00:00
|
|
|
const {result: {result: object}} = await Protocol.Debugger.evaluateOnCallFrame({
|
2021-01-05 07:42:18 +00:00
|
|
|
callFrameId, expression
|
|
|
|
});
|
2021-06-29 11:24:41 +00:00
|
|
|
if ('customPreview' in object) {
|
|
|
|
InspectorTest.log(
|
|
|
|
`> ${expression} = ${JSON.stringify(object.customPreview)}`);
|
|
|
|
} else if (object.type === 'object' && object.subtype === 'wasmvalue') {
|
2021-02-12 19:44:06 +00:00
|
|
|
const {result: {result: properties}} = await Protocol.Runtime.getProperties({objectId: object.objectId, ownProperties: true})
|
|
|
|
const valueProperty = properties.find(p => p.name === 'value');
|
|
|
|
InspectorTest.log(`> ${expression} = ${object.description} {${valueProperty.value.description}}`);
|
|
|
|
} else if ('description' in object) {
|
|
|
|
InspectorTest.log(`> ${expression} = ${object.description}`);
|
2021-01-05 07:42:18 +00:00
|
|
|
} else {
|
2021-02-12 19:44:06 +00:00
|
|
|
InspectorTest.log(`> ${expression} = ${JSON.stringify(object.value)}`);
|
2021-01-05 07:42:18 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
async function dumpKeysOnCallFrame(callFrameId, object, keys) {
|
|
|
|
for (const key of keys) {
|
|
|
|
await dumpOnCallFrame(callFrameId, `${object}[${JSON.stringify(key)}]`);
|
2021-01-13 11:11:35 +00:00
|
|
|
if (typeof key === 'string' && key.indexOf('.') < 0) {
|
2021-01-05 07:42:18 +00:00
|
|
|
await dumpOnCallFrame(callFrameId, `${key}`);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
async function waitForDebuggerPaused() {
|
|
|
|
const {params: {callFrames: [{callFrameId, functionName}]}} = await Protocol.Debugger.oncePaused();
|
|
|
|
InspectorTest.log(`Debugger paused in ${functionName}.`);
|
|
|
|
return callFrameId;
|
|
|
|
}
|
|
|
|
|
|
|
|
InspectorTest.runAsyncTestSuite([
|
|
|
|
async function testInstanceAndModule() {
|
|
|
|
const builder = new WasmModuleBuilder();
|
|
|
|
const main = builder.addFunction('main', kSig_v_v)
|
|
|
|
.addBody([]).exportFunc();
|
|
|
|
|
|
|
|
InspectorTest.log('Compile module.');
|
|
|
|
const [module, scriptId] = await compileModule(builder);
|
|
|
|
|
|
|
|
InspectorTest.log('Set breakpoint in main.');
|
|
|
|
await Protocol.Debugger.setBreakpoint({
|
|
|
|
location: {scriptId, lineNumber: 0, columnNumber: main.body_offset}
|
|
|
|
});
|
|
|
|
|
|
|
|
InspectorTest.log('Instantiate module.');
|
|
|
|
const instance = await instantiateModule(module);
|
|
|
|
|
|
|
|
InspectorTest.log('Call main.');
|
|
|
|
const callMainPromise = Protocol.Runtime.callFunctionOn({
|
|
|
|
functionDeclaration: `function() { return this.exports.main(); }`,
|
|
|
|
objectId: instance.objectId
|
|
|
|
});
|
|
|
|
const callFrameId = await waitForDebuggerPaused();
|
|
|
|
await dumpOnCallFrame(callFrameId, `instance`);
|
|
|
|
await dumpOnCallFrame(callFrameId, `module`);
|
|
|
|
await Protocol.Debugger.resume();
|
|
|
|
await callMainPromise;
|
|
|
|
},
|
|
|
|
|
|
|
|
async function testGlobals() {
|
|
|
|
const builder = new WasmModuleBuilder();
|
|
|
|
const global0 = builder.addGlobal(kWasmI32, true); // global0
|
|
|
|
const global1 = builder.addGlobal(kWasmI32, true).exportAs('global0');
|
|
|
|
const global2 = builder.addGlobal(kWasmI64, true).exportAs('global3');
|
|
|
|
const global3 = builder.addGlobal(kWasmI64, true); // global3
|
|
|
|
const main = builder.addFunction('main', kSig_v_v)
|
|
|
|
.addBody([
|
|
|
|
kExprI64Const, 42,
|
|
|
|
kExprGlobalSet, global3.index,
|
|
|
|
]).exportFunc();
|
|
|
|
const start = builder.addFunction('start', kSig_v_v)
|
|
|
|
.addBody([
|
|
|
|
kExprNop,
|
|
|
|
kExprI32Const, 0,
|
|
|
|
kExprGlobalSet, global0.index,
|
|
|
|
kExprI32Const, 1,
|
|
|
|
kExprGlobalSet, global1.index,
|
|
|
|
kExprI64Const, 2,
|
|
|
|
kExprGlobalSet, global2.index,
|
|
|
|
kExprI64Const, 3,
|
|
|
|
kExprGlobalSet, global3.index,
|
|
|
|
]);
|
|
|
|
builder.addStart(start.index);
|
|
|
|
const KEYS = [0, 1, 2, 3, '$global0', '$global3'];
|
|
|
|
|
|
|
|
InspectorTest.log('Compile module.');
|
|
|
|
const [module, scriptId] = await compileModule(builder);
|
|
|
|
|
|
|
|
InspectorTest.log('Set breakpoint in main.');
|
|
|
|
await Protocol.Debugger.setBreakpoint({
|
|
|
|
location: {scriptId, lineNumber: 0, columnNumber: main.body_offset}
|
|
|
|
});
|
|
|
|
|
|
|
|
InspectorTest.log('Instantiate module.');
|
|
|
|
const instance = await instantiateModule(module);
|
|
|
|
|
|
|
|
InspectorTest.log('Call main.');
|
|
|
|
const callMainPromise = Protocol.Runtime.callFunctionOn({
|
|
|
|
functionDeclaration: `function() { return this.exports.main(); }`,
|
|
|
|
objectId: instance.objectId
|
|
|
|
});
|
|
|
|
let callFrameId = await waitForDebuggerPaused();
|
[inspector] Implement Debug Proxy API via Interceptors.
Previously the Debug Proxy API that's exposed on Wasm frames by
Runtime.evaluateOnCallFrame() was implemented via actual JSProxy
instances. That means that all entities such as "memories", "tables",
"stack", "globals", etc. were JSProxy instances with "get" and "has"
traps. But that has a couple of down-sides:
1. In DevTools front-end, the proxies are shown as JSProxy, which is not
very useful to developers, since they cannot interact with them nor
can they inspect their contents. And the object preview also only
shows "Proxy {}" for them.
2. The performance doesn't scale well, which becomes a painful
bottleneck with larger Wasm modules that contain hundreds of
thousands of functions or globals.
3. We cannot use the JSProxy instances in the Scope view (for the
reasons outlined in 1.) and hence we have different logic to provide
Scope values than values in the rest of DevTools, which led to subtle
but annoying bugs and inconsistencies.
This also changes the "locals" implementation by querying the values
ahead of time, similar to the object exposed to the Scope view, instead
of on-demand, since the "locals" object might survive the current
debugger pause and peeking into the stack afterwards would read invalid
memory (and might even be a security issue). For being able to change
locals we need to look into a similar solution as what we have for
JavaScript locals already. The expression stack already works this way.
For performance reasons (especially scaling to huge, realistic Wasm
modules), we cache the per-instance proxies ("functions", "memories",
"tables" and "globals") on the WasmInstanceObject and reuse them (which
is safe since they have a `null` prototype and are non-extensible), and
we also cache the proxy maps (with the interceptors) on the
JSGlobalObject per native context.
Doc: http://bit.ly/devtools-wasm-entities
Bug: chromium:1127914, chromium:1159402, chromium:1071432, chromium:1164241
Change-Id: I6191035fdfd887835ae533fcdaabb5bbc8e661ae
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2606058
Commit-Queue: Benedikt Meurer <bmeurer@chromium.org>
Auto-Submit: Benedikt Meurer <bmeurer@chromium.org>
Reviewed-by: Yang Guo <yangguo@chromium.org>
Cr-Commit-Position: refs/heads/master@{#71981}
2021-01-08 14:35:58 +00:00
|
|
|
await dumpOnCallFrame(callFrameId, `globals`);
|
2021-01-05 07:42:18 +00:00
|
|
|
await dumpOnCallFrame(callFrameId, `typeof globals`);
|
[inspector] Implement Debug Proxy API via Interceptors.
Previously the Debug Proxy API that's exposed on Wasm frames by
Runtime.evaluateOnCallFrame() was implemented via actual JSProxy
instances. That means that all entities such as "memories", "tables",
"stack", "globals", etc. were JSProxy instances with "get" and "has"
traps. But that has a couple of down-sides:
1. In DevTools front-end, the proxies are shown as JSProxy, which is not
very useful to developers, since they cannot interact with them nor
can they inspect their contents. And the object preview also only
shows "Proxy {}" for them.
2. The performance doesn't scale well, which becomes a painful
bottleneck with larger Wasm modules that contain hundreds of
thousands of functions or globals.
3. We cannot use the JSProxy instances in the Scope view (for the
reasons outlined in 1.) and hence we have different logic to provide
Scope values than values in the rest of DevTools, which led to subtle
but annoying bugs and inconsistencies.
This also changes the "locals" implementation by querying the values
ahead of time, similar to the object exposed to the Scope view, instead
of on-demand, since the "locals" object might survive the current
debugger pause and peeking into the stack afterwards would read invalid
memory (and might even be a security issue). For being able to change
locals we need to look into a similar solution as what we have for
JavaScript locals already. The expression stack already works this way.
For performance reasons (especially scaling to huge, realistic Wasm
modules), we cache the per-instance proxies ("functions", "memories",
"tables" and "globals") on the WasmInstanceObject and reuse them (which
is safe since they have a `null` prototype and are non-extensible), and
we also cache the proxy maps (with the interceptors) on the
JSGlobalObject per native context.
Doc: http://bit.ly/devtools-wasm-entities
Bug: chromium:1127914, chromium:1159402, chromium:1071432, chromium:1164241
Change-Id: I6191035fdfd887835ae533fcdaabb5bbc8e661ae
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2606058
Commit-Queue: Benedikt Meurer <bmeurer@chromium.org>
Auto-Submit: Benedikt Meurer <bmeurer@chromium.org>
Reviewed-by: Yang Guo <yangguo@chromium.org>
Cr-Commit-Position: refs/heads/master@{#71981}
2021-01-08 14:35:58 +00:00
|
|
|
await dumpOnCallFrame(callFrameId, `Object.keys(globals)`);
|
2021-01-05 07:42:18 +00:00
|
|
|
await dumpKeysOnCallFrame(callFrameId, "globals", KEYS);
|
|
|
|
|
|
|
|
InspectorTest.log(`Stepping twice in main.`)
|
|
|
|
await Protocol.Debugger.stepOver(); // i32.const 42
|
|
|
|
await Protocol.Debugger.stepOver(); // global.set $global3
|
|
|
|
callFrameId = await waitForDebuggerPaused();
|
|
|
|
await dumpKeysOnCallFrame(callFrameId, "globals", KEYS);
|
|
|
|
|
|
|
|
InspectorTest.log('Changing global from JavaScript.')
|
|
|
|
await Protocol.Debugger.evaluateOnCallFrame({
|
|
|
|
callFrameId,
|
|
|
|
expression: `instance.exports.global0.value = 21`
|
|
|
|
});
|
|
|
|
await dumpKeysOnCallFrame(callFrameId, "globals", KEYS);
|
|
|
|
await Protocol.Debugger.resume();
|
|
|
|
await callMainPromise;
|
|
|
|
},
|
|
|
|
|
|
|
|
async function testFunctions() {
|
|
|
|
const builder = new WasmModuleBuilder();
|
2021-01-13 11:11:35 +00:00
|
|
|
builder.addImport('foo', 'bar', kSig_v_v);
|
2021-01-05 07:42:18 +00:00
|
|
|
const main = builder.addFunction('main', kSig_i_v)
|
|
|
|
.addBody([
|
|
|
|
kExprI32Const, 0,
|
|
|
|
]).exportFunc();
|
2021-01-13 11:11:35 +00:00
|
|
|
builder.addFunction('func2', kSig_i_v)
|
2021-01-05 07:42:18 +00:00
|
|
|
.addBody([
|
|
|
|
kExprI32Const, 1,
|
|
|
|
]);
|
|
|
|
builder.addFunction(undefined, kSig_i_v)
|
|
|
|
.addBody([
|
|
|
|
kExprI32Const, 2,
|
2021-01-13 11:11:35 +00:00
|
|
|
]).exportAs('func2');
|
2021-01-05 07:42:18 +00:00
|
|
|
builder.addFunction(undefined, kSig_i_v)
|
|
|
|
.addBody([
|
|
|
|
kExprI32Const, 3,
|
|
|
|
]);
|
2021-01-13 11:11:35 +00:00
|
|
|
const KEYS = [0, 1, 2, 3, 4, '$foo.bar', '$main', '$func2', '$func4'];
|
2021-01-05 07:42:18 +00:00
|
|
|
|
|
|
|
InspectorTest.log('Compile module.');
|
|
|
|
const [module, scriptId] = await compileModule(builder);
|
|
|
|
|
|
|
|
InspectorTest.log('Set breakpoint in main.');
|
|
|
|
await Protocol.Debugger.setBreakpoint({
|
|
|
|
location: {scriptId, lineNumber: 0, columnNumber: main.body_offset}
|
|
|
|
});
|
|
|
|
|
|
|
|
InspectorTest.log('Instantiate module.');
|
2021-01-13 11:11:35 +00:00
|
|
|
const {result: { result: importObject }} = await Protocol.Runtime.evaluate({
|
|
|
|
expression: `({foo: {bar() { }}})`
|
|
|
|
});
|
|
|
|
const instance = await instantiateModule(module, importObject);
|
2021-01-05 07:42:18 +00:00
|
|
|
|
|
|
|
InspectorTest.log('Call main.');
|
|
|
|
const callMainPromise = Protocol.Runtime.callFunctionOn({
|
|
|
|
functionDeclaration: `function() { return this.exports.main(); }`,
|
|
|
|
objectId: instance.objectId
|
|
|
|
});
|
|
|
|
let callFrameId = await waitForDebuggerPaused();
|
[inspector] Implement Debug Proxy API via Interceptors.
Previously the Debug Proxy API that's exposed on Wasm frames by
Runtime.evaluateOnCallFrame() was implemented via actual JSProxy
instances. That means that all entities such as "memories", "tables",
"stack", "globals", etc. were JSProxy instances with "get" and "has"
traps. But that has a couple of down-sides:
1. In DevTools front-end, the proxies are shown as JSProxy, which is not
very useful to developers, since they cannot interact with them nor
can they inspect their contents. And the object preview also only
shows "Proxy {}" for them.
2. The performance doesn't scale well, which becomes a painful
bottleneck with larger Wasm modules that contain hundreds of
thousands of functions or globals.
3. We cannot use the JSProxy instances in the Scope view (for the
reasons outlined in 1.) and hence we have different logic to provide
Scope values than values in the rest of DevTools, which led to subtle
but annoying bugs and inconsistencies.
This also changes the "locals" implementation by querying the values
ahead of time, similar to the object exposed to the Scope view, instead
of on-demand, since the "locals" object might survive the current
debugger pause and peeking into the stack afterwards would read invalid
memory (and might even be a security issue). For being able to change
locals we need to look into a similar solution as what we have for
JavaScript locals already. The expression stack already works this way.
For performance reasons (especially scaling to huge, realistic Wasm
modules), we cache the per-instance proxies ("functions", "memories",
"tables" and "globals") on the WasmInstanceObject and reuse them (which
is safe since they have a `null` prototype and are non-extensible), and
we also cache the proxy maps (with the interceptors) on the
JSGlobalObject per native context.
Doc: http://bit.ly/devtools-wasm-entities
Bug: chromium:1127914, chromium:1159402, chromium:1071432, chromium:1164241
Change-Id: I6191035fdfd887835ae533fcdaabb5bbc8e661ae
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2606058
Commit-Queue: Benedikt Meurer <bmeurer@chromium.org>
Auto-Submit: Benedikt Meurer <bmeurer@chromium.org>
Reviewed-by: Yang Guo <yangguo@chromium.org>
Cr-Commit-Position: refs/heads/master@{#71981}
2021-01-08 14:35:58 +00:00
|
|
|
await dumpOnCallFrame(callFrameId, `functions`);
|
2021-01-05 07:42:18 +00:00
|
|
|
await dumpOnCallFrame(callFrameId, `typeof functions`);
|
[inspector] Implement Debug Proxy API via Interceptors.
Previously the Debug Proxy API that's exposed on Wasm frames by
Runtime.evaluateOnCallFrame() was implemented via actual JSProxy
instances. That means that all entities such as "memories", "tables",
"stack", "globals", etc. were JSProxy instances with "get" and "has"
traps. But that has a couple of down-sides:
1. In DevTools front-end, the proxies are shown as JSProxy, which is not
very useful to developers, since they cannot interact with them nor
can they inspect their contents. And the object preview also only
shows "Proxy {}" for them.
2. The performance doesn't scale well, which becomes a painful
bottleneck with larger Wasm modules that contain hundreds of
thousands of functions or globals.
3. We cannot use the JSProxy instances in the Scope view (for the
reasons outlined in 1.) and hence we have different logic to provide
Scope values than values in the rest of DevTools, which led to subtle
but annoying bugs and inconsistencies.
This also changes the "locals" implementation by querying the values
ahead of time, similar to the object exposed to the Scope view, instead
of on-demand, since the "locals" object might survive the current
debugger pause and peeking into the stack afterwards would read invalid
memory (and might even be a security issue). For being able to change
locals we need to look into a similar solution as what we have for
JavaScript locals already. The expression stack already works this way.
For performance reasons (especially scaling to huge, realistic Wasm
modules), we cache the per-instance proxies ("functions", "memories",
"tables" and "globals") on the WasmInstanceObject and reuse them (which
is safe since they have a `null` prototype and are non-extensible), and
we also cache the proxy maps (with the interceptors) on the
JSGlobalObject per native context.
Doc: http://bit.ly/devtools-wasm-entities
Bug: chromium:1127914, chromium:1159402, chromium:1071432, chromium:1164241
Change-Id: I6191035fdfd887835ae533fcdaabb5bbc8e661ae
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2606058
Commit-Queue: Benedikt Meurer <bmeurer@chromium.org>
Auto-Submit: Benedikt Meurer <bmeurer@chromium.org>
Reviewed-by: Yang Guo <yangguo@chromium.org>
Cr-Commit-Position: refs/heads/master@{#71981}
2021-01-08 14:35:58 +00:00
|
|
|
await dumpOnCallFrame(callFrameId, `Object.keys(functions)`);
|
2021-01-05 07:42:18 +00:00
|
|
|
await dumpKeysOnCallFrame(callFrameId, "functions", KEYS);
|
|
|
|
await Protocol.Debugger.resume();
|
|
|
|
await callMainPromise;
|
|
|
|
},
|
|
|
|
|
|
|
|
async function testLocals() {
|
|
|
|
const builder = new WasmModuleBuilder();
|
|
|
|
const main = builder.addFunction('main', kSig_v_ii, ['x', 'x'])
|
|
|
|
.addLocals(kWasmI32, 1)
|
|
|
|
.addBody([
|
|
|
|
kExprI32Const, 42,
|
|
|
|
kExprLocalSet, 2
|
|
|
|
]).exportFunc();
|
|
|
|
const KEYS = [0, 1, 2, '$x', '$var2'];
|
|
|
|
|
|
|
|
InspectorTest.log('Compile module.');
|
|
|
|
const [module, scriptId] = await compileModule(builder);
|
|
|
|
|
|
|
|
InspectorTest.log('Set breakpoint in main.');
|
|
|
|
await Protocol.Debugger.setBreakpoint({
|
|
|
|
location: {scriptId, lineNumber: 0, columnNumber: main.body_offset}
|
|
|
|
});
|
|
|
|
|
|
|
|
InspectorTest.log('Instantiate module.');
|
|
|
|
const instance = await instantiateModule(module);
|
|
|
|
|
|
|
|
InspectorTest.log('Call main.');
|
|
|
|
const callMainPromise = Protocol.Runtime.callFunctionOn({
|
|
|
|
functionDeclaration: `function() { return this.exports.main(3, 6); }`,
|
|
|
|
objectId: instance.objectId
|
|
|
|
});
|
|
|
|
let callFrameId = await waitForDebuggerPaused();
|
[inspector] Implement Debug Proxy API via Interceptors.
Previously the Debug Proxy API that's exposed on Wasm frames by
Runtime.evaluateOnCallFrame() was implemented via actual JSProxy
instances. That means that all entities such as "memories", "tables",
"stack", "globals", etc. were JSProxy instances with "get" and "has"
traps. But that has a couple of down-sides:
1. In DevTools front-end, the proxies are shown as JSProxy, which is not
very useful to developers, since they cannot interact with them nor
can they inspect their contents. And the object preview also only
shows "Proxy {}" for them.
2. The performance doesn't scale well, which becomes a painful
bottleneck with larger Wasm modules that contain hundreds of
thousands of functions or globals.
3. We cannot use the JSProxy instances in the Scope view (for the
reasons outlined in 1.) and hence we have different logic to provide
Scope values than values in the rest of DevTools, which led to subtle
but annoying bugs and inconsistencies.
This also changes the "locals" implementation by querying the values
ahead of time, similar to the object exposed to the Scope view, instead
of on-demand, since the "locals" object might survive the current
debugger pause and peeking into the stack afterwards would read invalid
memory (and might even be a security issue). For being able to change
locals we need to look into a similar solution as what we have for
JavaScript locals already. The expression stack already works this way.
For performance reasons (especially scaling to huge, realistic Wasm
modules), we cache the per-instance proxies ("functions", "memories",
"tables" and "globals") on the WasmInstanceObject and reuse them (which
is safe since they have a `null` prototype and are non-extensible), and
we also cache the proxy maps (with the interceptors) on the
JSGlobalObject per native context.
Doc: http://bit.ly/devtools-wasm-entities
Bug: chromium:1127914, chromium:1159402, chromium:1071432, chromium:1164241
Change-Id: I6191035fdfd887835ae533fcdaabb5bbc8e661ae
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2606058
Commit-Queue: Benedikt Meurer <bmeurer@chromium.org>
Auto-Submit: Benedikt Meurer <bmeurer@chromium.org>
Reviewed-by: Yang Guo <yangguo@chromium.org>
Cr-Commit-Position: refs/heads/master@{#71981}
2021-01-08 14:35:58 +00:00
|
|
|
await dumpOnCallFrame(callFrameId, `locals`);
|
2021-01-05 07:42:18 +00:00
|
|
|
await dumpOnCallFrame(callFrameId, `typeof locals`);
|
[inspector] Implement Debug Proxy API via Interceptors.
Previously the Debug Proxy API that's exposed on Wasm frames by
Runtime.evaluateOnCallFrame() was implemented via actual JSProxy
instances. That means that all entities such as "memories", "tables",
"stack", "globals", etc. were JSProxy instances with "get" and "has"
traps. But that has a couple of down-sides:
1. In DevTools front-end, the proxies are shown as JSProxy, which is not
very useful to developers, since they cannot interact with them nor
can they inspect their contents. And the object preview also only
shows "Proxy {}" for them.
2. The performance doesn't scale well, which becomes a painful
bottleneck with larger Wasm modules that contain hundreds of
thousands of functions or globals.
3. We cannot use the JSProxy instances in the Scope view (for the
reasons outlined in 1.) and hence we have different logic to provide
Scope values than values in the rest of DevTools, which led to subtle
but annoying bugs and inconsistencies.
This also changes the "locals" implementation by querying the values
ahead of time, similar to the object exposed to the Scope view, instead
of on-demand, since the "locals" object might survive the current
debugger pause and peeking into the stack afterwards would read invalid
memory (and might even be a security issue). For being able to change
locals we need to look into a similar solution as what we have for
JavaScript locals already. The expression stack already works this way.
For performance reasons (especially scaling to huge, realistic Wasm
modules), we cache the per-instance proxies ("functions", "memories",
"tables" and "globals") on the WasmInstanceObject and reuse them (which
is safe since they have a `null` prototype and are non-extensible), and
we also cache the proxy maps (with the interceptors) on the
JSGlobalObject per native context.
Doc: http://bit.ly/devtools-wasm-entities
Bug: chromium:1127914, chromium:1159402, chromium:1071432, chromium:1164241
Change-Id: I6191035fdfd887835ae533fcdaabb5bbc8e661ae
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2606058
Commit-Queue: Benedikt Meurer <bmeurer@chromium.org>
Auto-Submit: Benedikt Meurer <bmeurer@chromium.org>
Reviewed-by: Yang Guo <yangguo@chromium.org>
Cr-Commit-Position: refs/heads/master@{#71981}
2021-01-08 14:35:58 +00:00
|
|
|
await dumpOnCallFrame(callFrameId, `Object.keys(locals)`);
|
2021-01-05 07:42:18 +00:00
|
|
|
await dumpKeysOnCallFrame(callFrameId, "locals", KEYS);
|
|
|
|
|
|
|
|
InspectorTest.log(`Stepping twice in main.`)
|
|
|
|
await Protocol.Debugger.stepOver(); // i32.const 42
|
|
|
|
await Protocol.Debugger.stepOver(); // local.set $var2
|
|
|
|
callFrameId = await waitForDebuggerPaused();
|
|
|
|
await dumpKeysOnCallFrame(callFrameId, "locals", KEYS);
|
|
|
|
await Protocol.Debugger.resume();
|
|
|
|
await callMainPromise;
|
|
|
|
},
|
|
|
|
|
|
|
|
async function testMemories() {
|
|
|
|
const builder = new WasmModuleBuilder();
|
|
|
|
builder.addMemory(1, 1).exportMemoryAs('foo');
|
|
|
|
const main = builder.addFunction('main', kSig_v_v)
|
|
|
|
.addBody([kExprNop]).exportFunc();
|
|
|
|
const KEYS = [0, '$foo'];
|
|
|
|
|
|
|
|
InspectorTest.log('Compile module.');
|
|
|
|
const [module, scriptId] = await compileModule(builder);
|
|
|
|
|
|
|
|
InspectorTest.log('Set breakpoint in main.');
|
|
|
|
await Protocol.Debugger.setBreakpoint({
|
|
|
|
location: {scriptId, lineNumber: 0, columnNumber: main.body_offset}
|
|
|
|
});
|
|
|
|
|
|
|
|
InspectorTest.log('Instantiate module.');
|
|
|
|
const instance = await instantiateModule(module);
|
|
|
|
|
|
|
|
InspectorTest.log('Call main.');
|
|
|
|
const callMainPromise = Protocol.Runtime.callFunctionOn({
|
|
|
|
functionDeclaration: `function() { return this.exports.main(); }`,
|
|
|
|
objectId: instance.objectId
|
|
|
|
});
|
|
|
|
let callFrameId = await waitForDebuggerPaused();
|
[inspector] Implement Debug Proxy API via Interceptors.
Previously the Debug Proxy API that's exposed on Wasm frames by
Runtime.evaluateOnCallFrame() was implemented via actual JSProxy
instances. That means that all entities such as "memories", "tables",
"stack", "globals", etc. were JSProxy instances with "get" and "has"
traps. But that has a couple of down-sides:
1. In DevTools front-end, the proxies are shown as JSProxy, which is not
very useful to developers, since they cannot interact with them nor
can they inspect their contents. And the object preview also only
shows "Proxy {}" for them.
2. The performance doesn't scale well, which becomes a painful
bottleneck with larger Wasm modules that contain hundreds of
thousands of functions or globals.
3. We cannot use the JSProxy instances in the Scope view (for the
reasons outlined in 1.) and hence we have different logic to provide
Scope values than values in the rest of DevTools, which led to subtle
but annoying bugs and inconsistencies.
This also changes the "locals" implementation by querying the values
ahead of time, similar to the object exposed to the Scope view, instead
of on-demand, since the "locals" object might survive the current
debugger pause and peeking into the stack afterwards would read invalid
memory (and might even be a security issue). For being able to change
locals we need to look into a similar solution as what we have for
JavaScript locals already. The expression stack already works this way.
For performance reasons (especially scaling to huge, realistic Wasm
modules), we cache the per-instance proxies ("functions", "memories",
"tables" and "globals") on the WasmInstanceObject and reuse them (which
is safe since they have a `null` prototype and are non-extensible), and
we also cache the proxy maps (with the interceptors) on the
JSGlobalObject per native context.
Doc: http://bit.ly/devtools-wasm-entities
Bug: chromium:1127914, chromium:1159402, chromium:1071432, chromium:1164241
Change-Id: I6191035fdfd887835ae533fcdaabb5bbc8e661ae
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2606058
Commit-Queue: Benedikt Meurer <bmeurer@chromium.org>
Auto-Submit: Benedikt Meurer <bmeurer@chromium.org>
Reviewed-by: Yang Guo <yangguo@chromium.org>
Cr-Commit-Position: refs/heads/master@{#71981}
2021-01-08 14:35:58 +00:00
|
|
|
await dumpOnCallFrame(callFrameId, `memories`);
|
2021-01-05 07:42:18 +00:00
|
|
|
await dumpOnCallFrame(callFrameId, `typeof memories`);
|
[inspector] Implement Debug Proxy API via Interceptors.
Previously the Debug Proxy API that's exposed on Wasm frames by
Runtime.evaluateOnCallFrame() was implemented via actual JSProxy
instances. That means that all entities such as "memories", "tables",
"stack", "globals", etc. were JSProxy instances with "get" and "has"
traps. But that has a couple of down-sides:
1. In DevTools front-end, the proxies are shown as JSProxy, which is not
very useful to developers, since they cannot interact with them nor
can they inspect their contents. And the object preview also only
shows "Proxy {}" for them.
2. The performance doesn't scale well, which becomes a painful
bottleneck with larger Wasm modules that contain hundreds of
thousands of functions or globals.
3. We cannot use the JSProxy instances in the Scope view (for the
reasons outlined in 1.) and hence we have different logic to provide
Scope values than values in the rest of DevTools, which led to subtle
but annoying bugs and inconsistencies.
This also changes the "locals" implementation by querying the values
ahead of time, similar to the object exposed to the Scope view, instead
of on-demand, since the "locals" object might survive the current
debugger pause and peeking into the stack afterwards would read invalid
memory (and might even be a security issue). For being able to change
locals we need to look into a similar solution as what we have for
JavaScript locals already. The expression stack already works this way.
For performance reasons (especially scaling to huge, realistic Wasm
modules), we cache the per-instance proxies ("functions", "memories",
"tables" and "globals") on the WasmInstanceObject and reuse them (which
is safe since they have a `null` prototype and are non-extensible), and
we also cache the proxy maps (with the interceptors) on the
JSGlobalObject per native context.
Doc: http://bit.ly/devtools-wasm-entities
Bug: chromium:1127914, chromium:1159402, chromium:1071432, chromium:1164241
Change-Id: I6191035fdfd887835ae533fcdaabb5bbc8e661ae
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2606058
Commit-Queue: Benedikt Meurer <bmeurer@chromium.org>
Auto-Submit: Benedikt Meurer <bmeurer@chromium.org>
Reviewed-by: Yang Guo <yangguo@chromium.org>
Cr-Commit-Position: refs/heads/master@{#71981}
2021-01-08 14:35:58 +00:00
|
|
|
await dumpOnCallFrame(callFrameId, `Object.keys(memories)`);
|
2021-01-05 07:42:18 +00:00
|
|
|
await dumpKeysOnCallFrame(callFrameId, "memories", KEYS);
|
|
|
|
await Protocol.Debugger.resume();
|
|
|
|
await callMainPromise;
|
|
|
|
},
|
|
|
|
|
|
|
|
async function testTables() {
|
|
|
|
const builder = new WasmModuleBuilder();
|
|
|
|
builder.addTable(kWasmFuncRef, 2).exportAs('bar');
|
|
|
|
const main = builder.addFunction('main', kSig_v_v)
|
|
|
|
.addBody([kExprNop]).exportFunc();
|
|
|
|
const KEYS = [0, '$bar'];
|
|
|
|
|
|
|
|
InspectorTest.log('Compile module.');
|
|
|
|
const [module, scriptId] = await compileModule(builder);
|
|
|
|
|
|
|
|
InspectorTest.log('Set breakpoint in main.');
|
|
|
|
await Protocol.Debugger.setBreakpoint({
|
|
|
|
location: {scriptId, lineNumber: 0, columnNumber: main.body_offset}
|
|
|
|
});
|
|
|
|
|
|
|
|
InspectorTest.log('Instantiate module.');
|
|
|
|
const instance = await instantiateModule(module);
|
|
|
|
|
|
|
|
InspectorTest.log('Call main.');
|
|
|
|
const callMainPromise = Protocol.Runtime.callFunctionOn({
|
|
|
|
functionDeclaration: `function() { return this.exports.main(); }`,
|
|
|
|
objectId: instance.objectId
|
|
|
|
});
|
|
|
|
let callFrameId = await waitForDebuggerPaused();
|
[inspector] Implement Debug Proxy API via Interceptors.
Previously the Debug Proxy API that's exposed on Wasm frames by
Runtime.evaluateOnCallFrame() was implemented via actual JSProxy
instances. That means that all entities such as "memories", "tables",
"stack", "globals", etc. were JSProxy instances with "get" and "has"
traps. But that has a couple of down-sides:
1. In DevTools front-end, the proxies are shown as JSProxy, which is not
very useful to developers, since they cannot interact with them nor
can they inspect their contents. And the object preview also only
shows "Proxy {}" for them.
2. The performance doesn't scale well, which becomes a painful
bottleneck with larger Wasm modules that contain hundreds of
thousands of functions or globals.
3. We cannot use the JSProxy instances in the Scope view (for the
reasons outlined in 1.) and hence we have different logic to provide
Scope values than values in the rest of DevTools, which led to subtle
but annoying bugs and inconsistencies.
This also changes the "locals" implementation by querying the values
ahead of time, similar to the object exposed to the Scope view, instead
of on-demand, since the "locals" object might survive the current
debugger pause and peeking into the stack afterwards would read invalid
memory (and might even be a security issue). For being able to change
locals we need to look into a similar solution as what we have for
JavaScript locals already. The expression stack already works this way.
For performance reasons (especially scaling to huge, realistic Wasm
modules), we cache the per-instance proxies ("functions", "memories",
"tables" and "globals") on the WasmInstanceObject and reuse them (which
is safe since they have a `null` prototype and are non-extensible), and
we also cache the proxy maps (with the interceptors) on the
JSGlobalObject per native context.
Doc: http://bit.ly/devtools-wasm-entities
Bug: chromium:1127914, chromium:1159402, chromium:1071432, chromium:1164241
Change-Id: I6191035fdfd887835ae533fcdaabb5bbc8e661ae
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2606058
Commit-Queue: Benedikt Meurer <bmeurer@chromium.org>
Auto-Submit: Benedikt Meurer <bmeurer@chromium.org>
Reviewed-by: Yang Guo <yangguo@chromium.org>
Cr-Commit-Position: refs/heads/master@{#71981}
2021-01-08 14:35:58 +00:00
|
|
|
await dumpOnCallFrame(callFrameId, `tables`);
|
2021-01-05 07:42:18 +00:00
|
|
|
await dumpOnCallFrame(callFrameId, `typeof tables`);
|
[inspector] Implement Debug Proxy API via Interceptors.
Previously the Debug Proxy API that's exposed on Wasm frames by
Runtime.evaluateOnCallFrame() was implemented via actual JSProxy
instances. That means that all entities such as "memories", "tables",
"stack", "globals", etc. were JSProxy instances with "get" and "has"
traps. But that has a couple of down-sides:
1. In DevTools front-end, the proxies are shown as JSProxy, which is not
very useful to developers, since they cannot interact with them nor
can they inspect their contents. And the object preview also only
shows "Proxy {}" for them.
2. The performance doesn't scale well, which becomes a painful
bottleneck with larger Wasm modules that contain hundreds of
thousands of functions or globals.
3. We cannot use the JSProxy instances in the Scope view (for the
reasons outlined in 1.) and hence we have different logic to provide
Scope values than values in the rest of DevTools, which led to subtle
but annoying bugs and inconsistencies.
This also changes the "locals" implementation by querying the values
ahead of time, similar to the object exposed to the Scope view, instead
of on-demand, since the "locals" object might survive the current
debugger pause and peeking into the stack afterwards would read invalid
memory (and might even be a security issue). For being able to change
locals we need to look into a similar solution as what we have for
JavaScript locals already. The expression stack already works this way.
For performance reasons (especially scaling to huge, realistic Wasm
modules), we cache the per-instance proxies ("functions", "memories",
"tables" and "globals") on the WasmInstanceObject and reuse them (which
is safe since they have a `null` prototype and are non-extensible), and
we also cache the proxy maps (with the interceptors) on the
JSGlobalObject per native context.
Doc: http://bit.ly/devtools-wasm-entities
Bug: chromium:1127914, chromium:1159402, chromium:1071432, chromium:1164241
Change-Id: I6191035fdfd887835ae533fcdaabb5bbc8e661ae
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2606058
Commit-Queue: Benedikt Meurer <bmeurer@chromium.org>
Auto-Submit: Benedikt Meurer <bmeurer@chromium.org>
Reviewed-by: Yang Guo <yangguo@chromium.org>
Cr-Commit-Position: refs/heads/master@{#71981}
2021-01-08 14:35:58 +00:00
|
|
|
await dumpOnCallFrame(callFrameId, `Object.keys(tables)`);
|
2021-01-05 07:42:18 +00:00
|
|
|
await dumpKeysOnCallFrame(callFrameId, "tables", KEYS);
|
|
|
|
await Protocol.Debugger.resume();
|
|
|
|
await callMainPromise;
|
[inspector] Implement Debug Proxy API via Interceptors.
Previously the Debug Proxy API that's exposed on Wasm frames by
Runtime.evaluateOnCallFrame() was implemented via actual JSProxy
instances. That means that all entities such as "memories", "tables",
"stack", "globals", etc. were JSProxy instances with "get" and "has"
traps. But that has a couple of down-sides:
1. In DevTools front-end, the proxies are shown as JSProxy, which is not
very useful to developers, since they cannot interact with them nor
can they inspect their contents. And the object preview also only
shows "Proxy {}" for them.
2. The performance doesn't scale well, which becomes a painful
bottleneck with larger Wasm modules that contain hundreds of
thousands of functions or globals.
3. We cannot use the JSProxy instances in the Scope view (for the
reasons outlined in 1.) and hence we have different logic to provide
Scope values than values in the rest of DevTools, which led to subtle
but annoying bugs and inconsistencies.
This also changes the "locals" implementation by querying the values
ahead of time, similar to the object exposed to the Scope view, instead
of on-demand, since the "locals" object might survive the current
debugger pause and peeking into the stack afterwards would read invalid
memory (and might even be a security issue). For being able to change
locals we need to look into a similar solution as what we have for
JavaScript locals already. The expression stack already works this way.
For performance reasons (especially scaling to huge, realistic Wasm
modules), we cache the per-instance proxies ("functions", "memories",
"tables" and "globals") on the WasmInstanceObject and reuse them (which
is safe since they have a `null` prototype and are non-extensible), and
we also cache the proxy maps (with the interceptors) on the
JSGlobalObject per native context.
Doc: http://bit.ly/devtools-wasm-entities
Bug: chromium:1127914, chromium:1159402, chromium:1071432, chromium:1164241
Change-Id: I6191035fdfd887835ae533fcdaabb5bbc8e661ae
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2606058
Commit-Queue: Benedikt Meurer <bmeurer@chromium.org>
Auto-Submit: Benedikt Meurer <bmeurer@chromium.org>
Reviewed-by: Yang Guo <yangguo@chromium.org>
Cr-Commit-Position: refs/heads/master@{#71981}
2021-01-08 14:35:58 +00:00
|
|
|
},
|
|
|
|
|
|
|
|
async function testStack() {
|
|
|
|
const builder = new WasmModuleBuilder();
|
|
|
|
const main = builder.addFunction('main', kSig_i_i)
|
|
|
|
.addBody([
|
|
|
|
kExprLocalGet, 0,
|
|
|
|
kExprI32Const, 42,
|
|
|
|
kExprI32Add,
|
|
|
|
]).exportFunc();
|
|
|
|
|
|
|
|
InspectorTest.log('Compile module.');
|
|
|
|
const [module, scriptId] = await compileModule(builder);
|
|
|
|
|
|
|
|
InspectorTest.log('Set breakpoint in main.');
|
|
|
|
await Protocol.Debugger.setBreakpoint({
|
|
|
|
location: {scriptId, lineNumber: 0, columnNumber: main.body_offset}
|
|
|
|
});
|
|
|
|
|
|
|
|
InspectorTest.log('Instantiate module.');
|
|
|
|
const instance = await instantiateModule(module);
|
|
|
|
|
|
|
|
InspectorTest.log('Call main.');
|
|
|
|
const callMainPromise = Protocol.Runtime.callFunctionOn({
|
|
|
|
functionDeclaration: `function() { return this.exports.main(5); }`,
|
|
|
|
objectId: instance.objectId
|
|
|
|
});
|
|
|
|
let callFrameId = await waitForDebuggerPaused();
|
|
|
|
await dumpOnCallFrame(callFrameId, `stack`);
|
|
|
|
await dumpOnCallFrame(callFrameId, `typeof stack`);
|
|
|
|
await dumpOnCallFrame(callFrameId, `Object.keys(stack)`);
|
|
|
|
|
|
|
|
InspectorTest.log(`Stepping twice in main.`)
|
|
|
|
await Protocol.Debugger.stepOver(); // local.get $var0
|
|
|
|
await Protocol.Debugger.stepOver(); // i32.const 42
|
|
|
|
callFrameId = await waitForDebuggerPaused();
|
|
|
|
await dumpOnCallFrame(callFrameId, `stack`);
|
|
|
|
await dumpOnCallFrame(callFrameId, `Object.keys(stack)`);
|
|
|
|
await dumpKeysOnCallFrame(callFrameId, "stack", [0, 1]);
|
2021-06-29 11:24:41 +00:00
|
|
|
await Protocol.Debugger.resume();
|
|
|
|
await callMainPromise;
|
|
|
|
},
|
|
|
|
|
|
|
|
async function testCustomFormatters() {
|
|
|
|
const builder = new WasmModuleBuilder();
|
|
|
|
const main = builder.addFunction('main', kSig_i_i, ['x'])
|
|
|
|
.addBody([
|
|
|
|
kExprLocalGet,
|
|
|
|
0,
|
|
|
|
])
|
|
|
|
.exportFunc();
|
|
|
|
|
|
|
|
InspectorTest.log('Compile module.');
|
|
|
|
const [module, scriptId] = await compileModule(builder);
|
|
|
|
|
|
|
|
await Protocol.Runtime.enable();
|
|
|
|
InspectorTest.log('Set breakpoint in main.');
|
|
|
|
await Protocol.Debugger.setBreakpoint(
|
|
|
|
{location: {scriptId, lineNumber: 0, columnNumber: main.body_offset}});
|
|
|
|
|
|
|
|
InspectorTest.log('Install custom formatter.');
|
|
|
|
await Protocol.Runtime.onConsoleAPICalled(m => InspectorTest.logMessage(m));
|
|
|
|
await Protocol.Runtime.setCustomObjectFormatterEnabled({enabled: true});
|
|
|
|
await Protocol.Runtime.evaluate({
|
|
|
|
expression: `this.devtoolsFormatters = [{
|
|
|
|
header: function(obj) { return ["div", {}, JSON.stringify(obj)]; },
|
|
|
|
hasBody: function() { return false; }
|
|
|
|
}]`
|
|
|
|
});
|
|
|
|
|
|
|
|
InspectorTest.log('Instantiate module.');
|
|
|
|
const instance = await instantiateModule(module);
|
|
|
|
|
|
|
|
InspectorTest.log('Call main.');
|
|
|
|
const callMainPromise = Protocol.Runtime.callFunctionOn({
|
|
|
|
functionDeclaration: `function() { return this.exports.main(5); }`,
|
|
|
|
objectId: instance.objectId
|
|
|
|
});
|
|
|
|
let callFrameId = await waitForDebuggerPaused();
|
|
|
|
await dumpOnCallFrame(callFrameId, `locals`);
|
|
|
|
await dumpOnCallFrame(callFrameId, `Object.keys(locals)`);
|
|
|
|
await dumpKeysOnCallFrame(callFrameId, 'locals', [0, '$x']);
|
|
|
|
|
[inspector] Implement Debug Proxy API via Interceptors.
Previously the Debug Proxy API that's exposed on Wasm frames by
Runtime.evaluateOnCallFrame() was implemented via actual JSProxy
instances. That means that all entities such as "memories", "tables",
"stack", "globals", etc. were JSProxy instances with "get" and "has"
traps. But that has a couple of down-sides:
1. In DevTools front-end, the proxies are shown as JSProxy, which is not
very useful to developers, since they cannot interact with them nor
can they inspect their contents. And the object preview also only
shows "Proxy {}" for them.
2. The performance doesn't scale well, which becomes a painful
bottleneck with larger Wasm modules that contain hundreds of
thousands of functions or globals.
3. We cannot use the JSProxy instances in the Scope view (for the
reasons outlined in 1.) and hence we have different logic to provide
Scope values than values in the rest of DevTools, which led to subtle
but annoying bugs and inconsistencies.
This also changes the "locals" implementation by querying the values
ahead of time, similar to the object exposed to the Scope view, instead
of on-demand, since the "locals" object might survive the current
debugger pause and peeking into the stack afterwards would read invalid
memory (and might even be a security issue). For being able to change
locals we need to look into a similar solution as what we have for
JavaScript locals already. The expression stack already works this way.
For performance reasons (especially scaling to huge, realistic Wasm
modules), we cache the per-instance proxies ("functions", "memories",
"tables" and "globals") on the WasmInstanceObject and reuse them (which
is safe since they have a `null` prototype and are non-extensible), and
we also cache the proxy maps (with the interceptors) on the
JSGlobalObject per native context.
Doc: http://bit.ly/devtools-wasm-entities
Bug: chromium:1127914, chromium:1159402, chromium:1071432, chromium:1164241
Change-Id: I6191035fdfd887835ae533fcdaabb5bbc8e661ae
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2606058
Commit-Queue: Benedikt Meurer <bmeurer@chromium.org>
Auto-Submit: Benedikt Meurer <bmeurer@chromium.org>
Reviewed-by: Yang Guo <yangguo@chromium.org>
Cr-Commit-Position: refs/heads/master@{#71981}
2021-01-08 14:35:58 +00:00
|
|
|
await Protocol.Debugger.resume();
|
|
|
|
await callMainPromise;
|
2021-01-05 07:42:18 +00:00
|
|
|
}
|
|
|
|
]);
|