40a156813e
The wrapper obects for the debugger displayed e.g. in dev tools contain a proper `null` value already. Note: This only affects the printing of wasm tables in the test. Change-Id: I3c2e9580b0a3983b66b9c3e2e16e5a2b322a9ff7 Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/4020261 Auto-Submit: Matthias Liedtke <mliedtke@chromium.org> Commit-Queue: Manos Koukoutos <manoskouk@chromium.org> Reviewed-by: Manos Koukoutos <manoskouk@chromium.org> Cr-Commit-Position: refs/heads/main@{#84201}
177 lines
6.4 KiB
JavaScript
177 lines
6.4 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 = async function(expression, url) {
|
|
const sourceURL = `v8://test/${url}`;
|
|
const {result: {scriptId}} = await Protocol.Runtime.compileScript({
|
|
expression, sourceURL, persistScript: true}).then(printIfFailure);
|
|
return await Protocol.Runtime
|
|
.runScript({scriptId})
|
|
.then(printIfFailure);
|
|
};
|
|
|
|
WasmInspectorTest.compileFromBuffer = (function(bytes) {
|
|
var buffer = new ArrayBuffer(bytes.length);
|
|
var view = new Uint8Array(buffer);
|
|
for (var i = 0; i < bytes.length; ++i) {
|
|
view[i] = bytes[i] | 0;
|
|
}
|
|
return new WebAssembly.Module(buffer);
|
|
}).toString();
|
|
|
|
WasmInspectorTest.instantiateFromBuffer =
|
|
(function(bytes, imports) {
|
|
return new WebAssembly.Instance(compileFromBuffer(bytes), imports);
|
|
})
|
|
.toString()
|
|
.replace('compileFromBuffer', WasmInspectorTest.compileFromBuffer);
|
|
|
|
WasmInspectorTest.compile = async function(bytes, module_name = 'module') {
|
|
const compile_code = `var ${module_name} = (${
|
|
WasmInspectorTest.compileFromBuffer})(${JSON.stringify(bytes)});`;
|
|
await WasmInspectorTest.evalWithUrl(compile_code, 'compile_module');
|
|
};
|
|
|
|
WasmInspectorTest.instantiate =
|
|
async function(bytes, instance_name = 'instance', imports) {
|
|
const instantiate_code = `var ${instance_name} = (${
|
|
WasmInspectorTest.instantiateFromBuffer})(${JSON.stringify(bytes)},
|
|
${imports});`;
|
|
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 = async function(value) {
|
|
let msg = await Protocol.Runtime.getProperties({ objectId: value.objectId });
|
|
printIfFailure(msg);
|
|
const value_type = msg.result.result.find(({name}) => name === 'type');
|
|
const value_value = msg.result.result.find(({name}) => name === 'value');
|
|
return `${
|
|
value_value.value.unserializableValue ??
|
|
value_value.value.description ??
|
|
value_value.value.value} (${value_type.value.value})`;
|
|
};
|
|
|
|
function printIfFailure(message) {
|
|
if (!message.result || message.result.exceptionDetails) {
|
|
InspectorTest.logMessage(message);
|
|
}
|
|
return message;
|
|
}
|
|
|
|
async function getScopeValues(name, value) {
|
|
async function printValue(value) {
|
|
if (value.type === 'object' && value.subtype === 'wasmvalue') {
|
|
return await WasmInspectorTest.getWasmValue(value);
|
|
} else if ('className' in value) {
|
|
return `(${value.className})`;
|
|
}
|
|
return `${value.unserializableValue ?? value.value} (${
|
|
value.subtype ?? value.type})`;
|
|
}
|
|
if (value.type === 'object' && value.subtype !== 'wasmvalue') {
|
|
if (value.subtype === 'typedarray' || value.subtype == 'webassemblymemory')
|
|
return value.description;
|
|
if (name === 'instance') return dumpInstanceProperties(value);
|
|
if (name === 'module') return value.description;
|
|
if (name === 'tables') return dumpTables(value);
|
|
|
|
let msg = await Protocol.Runtime.getProperties({objectId: value.objectId});
|
|
printIfFailure(msg);
|
|
async function printProperty({name, value}) {
|
|
return `"${name}": ${await printValue(value)}`;
|
|
}
|
|
return (await Promise.all(msg.result.result.map(printProperty))).join(', ');
|
|
}
|
|
return await printValue(value);
|
|
}
|
|
|
|
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);
|
|
|
|
function printExports(value) {
|
|
return `"${value.name}" (${value.value.className})`;
|
|
}
|
|
const formattedExports = exports.result.result.map(printExports).join(', ');
|
|
return `${exportsName}: ${formattedExports}`
|
|
}
|
|
|
|
async function dumpTables(tablesObj) {
|
|
let msg =
|
|
await Protocol.Runtime.getProperties({objectId: tablesObj.objectId});
|
|
let tables_str = [];
|
|
for (let table of msg.result.result) {
|
|
let table_content =
|
|
await Protocol.Runtime.getProperties({objectId: table.value.objectId});
|
|
|
|
let entries_object = table_content.result.internalProperties.filter(
|
|
p => p.name === '[[Entries]]')[0];
|
|
entries = await Protocol.Runtime.getProperties(
|
|
{objectId: entries_object.value.objectId});
|
|
let functions = [];
|
|
for (let entry of entries.result.result) {
|
|
if (entry.name === 'length') continue;
|
|
let description = entry.value.description;
|
|
// For tables containing references, explore one level into the ref.
|
|
if (entry.value.objectId != null) {
|
|
let referencedObj = await Protocol.Runtime.getProperties(
|
|
{objectId: entry.value.objectId});
|
|
let value = referencedObj.result.result
|
|
.filter(prop => prop.name == "value")[0].value;
|
|
// If the value doesn't have a description, fall back to its value
|
|
// property. (For null this makes sure to print "null", as the null
|
|
// value doesn't have a description.)
|
|
value = value.description ?? value.value;
|
|
description = `${value} (${description})`;
|
|
}
|
|
functions.push(`${entry.name}: ${description}`);
|
|
}
|
|
const functions_str = functions.join(', ');
|
|
tables_str.push(` ${table.name}: ${functions_str}`);
|
|
}
|
|
return '\n' + tables_str.join('\n');
|
|
}
|