[inspector] Add Wasm test coverage for evaluateOnCallFrame().
Drive-by-fix: Handle duplicate globals names correctly in the scope exposed module object. Bug: chromium:1127914, chromium:1071432 Change-Id: I697256642c5ddbc13f86ff25ab012c53537b9c88 Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2609416 Commit-Queue: Benedikt Meurer <bmeurer@chromium.org> Commit-Queue: Yang Guo <yangguo@chromium.org> Auto-Submit: Benedikt Meurer <bmeurer@chromium.org> Reviewed-by: Yang Guo <yangguo@chromium.org> Cr-Commit-Position: refs/heads/master@{#71910}
This commit is contained in:
parent
adea008b75
commit
d09b35f3b1
src/wasm
test/inspector/debugger
@ -241,7 +241,9 @@ Handle<JSObject> GetModuleScopeObject(Handle<WasmInstanceObject> instance) {
|
|||||||
WasmValue value =
|
WasmValue value =
|
||||||
WasmInstanceObject::GetGlobalValue(instance, globals[i]);
|
WasmInstanceObject::GetGlobalValue(instance, globals[i]);
|
||||||
Handle<Object> value_obj = WasmValueToValueObject(isolate, value);
|
Handle<Object> value_obj = WasmValueToValueObject(isolate, value);
|
||||||
JSObject::AddProperty(isolate, globals_obj, name, value_obj, NONE);
|
LookupIterator it(isolate, globals_obj, name, globals_obj,
|
||||||
|
LookupIterator::OWN_SKIP_INTERCEPTOR);
|
||||||
|
JSObject::CreateDataProperty(&it, value_obj).Check();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return module_scope_object;
|
return module_scope_object;
|
||||||
|
109
test/inspector/debugger/wasm-evaluate-on-call-frame-expected.txt
Normal file
109
test/inspector/debugger/wasm-evaluate-on-call-frame-expected.txt
Normal file
@ -0,0 +1,109 @@
|
|||||||
|
Test wasm debug evaluate
|
||||||
|
|
||||||
|
Running test: testInstanceAndModule
|
||||||
|
Compile module.
|
||||||
|
Set breakpoint in main.
|
||||||
|
Instantiate module.
|
||||||
|
Call main.
|
||||||
|
Debugger paused in main.
|
||||||
|
> instance = Instance
|
||||||
|
> module = Module
|
||||||
|
|
||||||
|
Running test: testGlobals
|
||||||
|
Compile module.
|
||||||
|
Set breakpoint in main.
|
||||||
|
Instantiate module.
|
||||||
|
Call main.
|
||||||
|
Debugger paused in main.
|
||||||
|
> typeof globals = "object"
|
||||||
|
> globals[0] = 0
|
||||||
|
> globals[1] = 1
|
||||||
|
> globals[2] = 2n
|
||||||
|
> globals[3] = 3n
|
||||||
|
> globals["$global0"] = 1
|
||||||
|
> $global0 = 1
|
||||||
|
> globals["$global3"] = 3n
|
||||||
|
> $global3 = 3n
|
||||||
|
Stepping twice in main.
|
||||||
|
Debugger paused in main.
|
||||||
|
> globals[0] = 0
|
||||||
|
> globals[1] = 1
|
||||||
|
> globals[2] = 2n
|
||||||
|
> globals[3] = 42n
|
||||||
|
> globals["$global0"] = 1
|
||||||
|
> $global0 = 1
|
||||||
|
> globals["$global3"] = 42n
|
||||||
|
> $global3 = 42n
|
||||||
|
Changing global from JavaScript.
|
||||||
|
> globals[0] = 0
|
||||||
|
> globals[1] = 21
|
||||||
|
> globals[2] = 2n
|
||||||
|
> globals[3] = 42n
|
||||||
|
> globals["$global0"] = 21
|
||||||
|
> $global0 = 21
|
||||||
|
> globals["$global3"] = 42n
|
||||||
|
> $global3 = 42n
|
||||||
|
|
||||||
|
Running test: testFunctions
|
||||||
|
Compile module.
|
||||||
|
Set breakpoint in main.
|
||||||
|
Instantiate module.
|
||||||
|
Call main.
|
||||||
|
Debugger paused in main.
|
||||||
|
> typeof functions = "object"
|
||||||
|
> functions[0] = function 0() { [native code] }
|
||||||
|
> functions[1] = function 1() { [native code] }
|
||||||
|
> functions[2] = function 2() { [native code] }
|
||||||
|
> functions[3] = function 3() { [native code] }
|
||||||
|
> functions["$main"] = function 0() { [native code] }
|
||||||
|
> $main = function 0() { [native code] }
|
||||||
|
> functions["$func1"] = function 2() { [native code] }
|
||||||
|
> $func1 = function 2() { [native code] }
|
||||||
|
> functions["$func3"] = function 3() { [native code] }
|
||||||
|
> $func3 = function 3() { [native code] }
|
||||||
|
|
||||||
|
Running test: testLocals
|
||||||
|
Compile module.
|
||||||
|
Set breakpoint in main.
|
||||||
|
Instantiate module.
|
||||||
|
Call main.
|
||||||
|
Debugger paused in main.
|
||||||
|
> typeof locals = "object"
|
||||||
|
> locals[0] = 3
|
||||||
|
> locals[1] = 6
|
||||||
|
> locals[2] = 0
|
||||||
|
> locals["$x"] = 6
|
||||||
|
> $x = 6
|
||||||
|
> locals["$var2"] = 0
|
||||||
|
> $var2 = 0
|
||||||
|
Stepping twice in main.
|
||||||
|
Debugger paused in main.
|
||||||
|
> locals[0] = 3
|
||||||
|
> locals[1] = 6
|
||||||
|
> locals[2] = 42
|
||||||
|
> locals["$x"] = 6
|
||||||
|
> $x = 6
|
||||||
|
> locals["$var2"] = 42
|
||||||
|
> $var2 = 42
|
||||||
|
|
||||||
|
Running test: testMemories
|
||||||
|
Compile module.
|
||||||
|
Set breakpoint in main.
|
||||||
|
Instantiate module.
|
||||||
|
Call main.
|
||||||
|
Debugger paused in main.
|
||||||
|
> typeof memories = "object"
|
||||||
|
> memories[0] = Memory(1)
|
||||||
|
> memories["$foo"] = Memory(1)
|
||||||
|
> $foo = Memory(1)
|
||||||
|
|
||||||
|
Running test: testTables
|
||||||
|
Compile module.
|
||||||
|
Set breakpoint in main.
|
||||||
|
Instantiate module.
|
||||||
|
Call main.
|
||||||
|
Debugger paused in main.
|
||||||
|
> typeof tables = "object"
|
||||||
|
> tables[0] = Table
|
||||||
|
> tables["$bar"] = Table
|
||||||
|
> $bar = Table
|
290
test/inspector/debugger/wasm-evaluate-on-call-frame.js
Normal file
290
test/inspector/debugger/wasm-evaluate-on-call-frame.js
Normal file
@ -0,0 +1,290 @@
|
|||||||
|
// 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];
|
||||||
|
}
|
||||||
|
|
||||||
|
async function instantiateModule({objectId}) {
|
||||||
|
const {result: {result}} = await Protocol.Runtime.callFunctionOn({
|
||||||
|
functionDeclaration: 'function() { return new WebAssembly.Instance(this); }',
|
||||||
|
objectId
|
||||||
|
});
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
async function dumpOnCallFrame(callFrameId, expression) {
|
||||||
|
const {result: {result}} = await Protocol.Debugger.evaluateOnCallFrame({
|
||||||
|
callFrameId, expression
|
||||||
|
});
|
||||||
|
if ('description' in result) {
|
||||||
|
InspectorTest.log(`> ${expression} = ${result.description}`);
|
||||||
|
} else {
|
||||||
|
InspectorTest.log(`> ${expression} = ${JSON.stringify(result.value)}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function dumpKeysOnCallFrame(callFrameId, object, keys) {
|
||||||
|
for (const key of keys) {
|
||||||
|
await dumpOnCallFrame(callFrameId, `${object}[${JSON.stringify(key)}]`);
|
||||||
|
if (typeof key === 'string') {
|
||||||
|
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();
|
||||||
|
await dumpOnCallFrame(callFrameId, `typeof globals`);
|
||||||
|
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();
|
||||||
|
const main = builder.addFunction('main', kSig_i_v)
|
||||||
|
.addBody([
|
||||||
|
kExprI32Const, 0,
|
||||||
|
]).exportFunc();
|
||||||
|
builder.addFunction('func1', kSig_i_v)
|
||||||
|
.addBody([
|
||||||
|
kExprI32Const, 1,
|
||||||
|
]);
|
||||||
|
builder.addFunction(undefined, kSig_i_v)
|
||||||
|
.addBody([
|
||||||
|
kExprI32Const, 2,
|
||||||
|
]).exportAs('func1');
|
||||||
|
builder.addFunction(undefined, kSig_i_v)
|
||||||
|
.addBody([
|
||||||
|
kExprI32Const, 3,
|
||||||
|
]);
|
||||||
|
const KEYS = [0, 1, 2, 3, '$main', '$func1', '$func3'];
|
||||||
|
|
||||||
|
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();
|
||||||
|
await dumpOnCallFrame(callFrameId, `typeof functions`);
|
||||||
|
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();
|
||||||
|
await dumpOnCallFrame(callFrameId, `typeof locals`);
|
||||||
|
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();
|
||||||
|
await dumpOnCallFrame(callFrameId, `typeof memories`);
|
||||||
|
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();
|
||||||
|
await dumpOnCallFrame(callFrameId, `typeof tables`);
|
||||||
|
await dumpKeysOnCallFrame(callFrameId, "tables", KEYS);
|
||||||
|
await Protocol.Debugger.resume();
|
||||||
|
await callMainPromise;
|
||||||
|
}
|
||||||
|
]);
|
Loading…
Reference in New Issue
Block a user