ad42f966a4
The "imports" and "exports" that were exposed on WebAssembly frames via Debug-Evaluate aren't useful for the DWARF C/C++ extension (and likely not for any other language extension), since they only expose static information that's easily available (upfront) by reading the Wasm wire bytes. In fact, there are already standardized functions in the WebAssembly specification, namely `WebAssembly.Module.imports(module)` and `WebAssembly.Module.exports(module)`, which yield static information about the imports and exports of a Wasm module. So instead of exposing special, non-standard "imports" and "exports", we now instead expose both the "instance" and the "module" objects via both the Debug Proxy and the Scope view, and also add internal [[Exports]] and [[Imports]] properties to WasmModuleObject, which under the hood use the standard methods mentioned above. Fixed: chromium:1162069 Bug: chromium:1071432, chromium:1083146 Screenshot: https://imgur.com/lcaW2jL.png Doc: https://docs.google.com/document/d/1rqbu0jKTl3q_xCxLnKzkjGXWEsHnJ9aERVhKV9RNDgE#bookmark=id.925bb2qgou38 Change-Id: Ie27e55bb08ea5f90493c57375bf2b48dfb11a4d2 Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2606050 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@{#71893}
105 lines
3.6 KiB
JavaScript
105 lines
3.6 KiB
JavaScript
// Copyright 2020 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/mjsunit/wasm/wasm-module-builder.js');
|
|
|
|
WasmInspectorTest = {}
|
|
InspectorTest.getWasmOpcodeName = getOpcodeName;
|
|
|
|
WasmInspectorTest.evalWithUrl = (code, url) =>
|
|
Protocol.Runtime
|
|
.evaluate({'expression': code + '\n//# sourceURL=v8://test/' + url})
|
|
.then(printIfFailure);
|
|
|
|
WasmInspectorTest.instantiateFromBuffer = function(bytes, imports) {
|
|
var buffer = new ArrayBuffer(bytes.length);
|
|
var view = new Uint8Array(buffer);
|
|
for (var i = 0; i < bytes.length; ++i) {
|
|
view[i] = bytes[i] | 0;
|
|
}
|
|
const module = new WebAssembly.Module(buffer);
|
|
return new WebAssembly.Instance(module, imports);
|
|
}
|
|
|
|
WasmInspectorTest.instantiate = async function(bytes, instance_name = 'instance') {
|
|
const instantiate_code = `var ${instance_name} = (${WasmInspectorTest.instantiateFromBuffer})(${JSON.stringify(bytes)});`;
|
|
await WasmInspectorTest.evalWithUrl(instantiate_code, 'instantiate');
|
|
}
|
|
|
|
WasmInspectorTest.dumpScopeProperties = async function(message) {
|
|
printIfFailure(message);
|
|
for (var value of message.result.result) {
|
|
var value_str = await getScopeValues(value.name, value.value);
|
|
InspectorTest.log(' ' + value.name + ': ' + value_str);
|
|
}
|
|
}
|
|
|
|
WasmInspectorTest.getWasmValue = function(wasmValue) {
|
|
return typeof (wasmValue.value) === 'undefined' ?
|
|
wasmValue.unserializableValue :
|
|
wasmValue.value;
|
|
}
|
|
|
|
function printIfFailure(message) {
|
|
if (!message.result) {
|
|
InspectorTest.logMessage(message);
|
|
}
|
|
return message;
|
|
}
|
|
|
|
async function getScopeValues(name, value) {
|
|
if (value.type == 'object') {
|
|
if (value.subtype === 'typedarray' || value.subtype == 'webassemblymemory') return value.description;
|
|
if (name === 'instance') return dumpInstanceProperties(value);
|
|
if (name === 'module') return value.description;
|
|
|
|
let msg = await Protocol.Runtime.getProperties({objectId: value.objectId});
|
|
printIfFailure(msg);
|
|
const printProperty = function(elem) {
|
|
const wasmValue = WasmInspectorTest.getWasmValue(elem.value);
|
|
return `"${elem.name}": ${wasmValue} (${elem.value.subtype})`;
|
|
}
|
|
return msg.result.result.map(printProperty).join(', ');
|
|
}
|
|
return WasmInspectorTest.getWasmValue(value) + ' (' + value.subtype + ')';
|
|
}
|
|
|
|
function recursiveGetPropertiesWrapper(value, depth) {
|
|
return recursiveGetProperties({result: {result: [value]}}, depth);
|
|
}
|
|
|
|
async function recursiveGetProperties(value, depth) {
|
|
if (depth > 0) {
|
|
const properties = await Promise.all(value.result.result.map(
|
|
x => {return Protocol.Runtime.getProperties({objectId: x.value.objectId});}));
|
|
const recursiveProperties = await Promise.all(properties.map(
|
|
x => {return recursiveGetProperties(x, depth - 1);}));
|
|
return recursiveProperties.flat();
|
|
}
|
|
return value;
|
|
}
|
|
|
|
async function dumpInstanceProperties(instanceObj) {
|
|
function invokeGetter(property) {
|
|
return this[JSON.parse(property)];
|
|
}
|
|
|
|
const exportsName = 'exports';
|
|
let exportsObj = await Protocol.Runtime.callFunctionOn(
|
|
{objectId: instanceObj.objectId,
|
|
functionDeclaration: invokeGetter.toString(),
|
|
arguments: [{value: JSON.stringify(exportsName)}]
|
|
});
|
|
printIfFailure(exportsObj);
|
|
let exports = await Protocol.Runtime.getProperties(
|
|
{objectId: exportsObj.result.result.objectId});
|
|
printIfFailure(exports);
|
|
|
|
const printExports = function(value) {
|
|
return `"${value.name}" (${value.value.className})`;
|
|
}
|
|
const formattedExports = exports.result.result.map(printExports).join(', ');
|
|
return `${exportsName}: ${formattedExports}`
|
|
}
|