v8/test/inspector/debugger/wasm-scripts.js
Ingvar Stepanyan d8f95c4b79 [wasm] Prefer source map over DWARF info if present
Some tools that transform Wasm today, already support encoding the
transforms and correctly updating locations in source maps, but not yet
in DWARF (although this is being worked on).

Until they catch up, it's best to consistently prefer source maps over
DWARF when both are present, and not just rely on order of sections as
accidentally done in the previous CL that introduced DWARF info.

Ref: crrev.com/c/v8/v8/+/1834341
Bug: chromium:1016772
Change-Id: I769311e2096ae0e4ca304bef0a0453c7e0776aae
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/1888930
Commit-Queue: Ingvar Stepanyan <rreverser@google.com>
Reviewed-by: Clemens Backes <clemensb@chromium.org>
Cr-Commit-Position: refs/heads/master@{#64647}
2019-10-30 13:12:35 +00:00

144 lines
4.6 KiB
JavaScript

// 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.
// Flags: --expose-wasm
InspectorTest.log("Tests how wasm scripts are reported");
let contextGroup = new InspectorTest.ContextGroup();
let sessions = [
// Main session.
trackScripts(),
// Extra session to verify that all inspectors get same messages.
// See https://bugs.chromium.org/p/v8/issues/detail?id=9725.
trackScripts(),
];
utils.load('test/mjsunit/wasm/wasm-module-builder.js');
// Create module with given custom sections.
function createModule(...customSections) {
var builder = new WasmModuleBuilder();
builder.addFunction('nopFunction', kSig_v_v).addBody([kExprNop]);
builder.addFunction('main', kSig_v_v)
.addBody([kExprBlock, kWasmStmt, kExprI32Const, 2, kExprDrop, kExprEnd])
.exportAs('main');
for (var { name, value } of customSections) {
builder.addCustomSection(name, value);
}
return builder.toArray();
}
function testFunction(bytes) {
// Compilation triggers registration of wasm scripts.
new WebAssembly.Module(new Uint8Array(bytes));
}
contextGroup.addScript(testFunction.toString(), 0, 0, 'v8://test/testFunction');
InspectorTest.log(
'Check that each inspector gets two wasm scripts at module creation time.');
// Sample .debug_info section.
// Content doesn't matter, as we don't try to parse it in V8,
// but should be non-empty to check that we're skipping it correctly.
const dwarfSection = { name: '.debug_info', value: [1, 2, 3, 4, 5] };
// Sample sourceMappingURL section set to "abc".
const sourceMapSection = { name: 'sourceMappingURL', value: [3, 97, 98, 99] };
sessions[0].Protocol.Runtime
.evaluate({
'expression': `//# sourceURL=v8://test/runTestRunction
// no debug info
testFunction([${createModule()}]);
// DWARF
testFunction([${createModule(dwarfSection)}]);
// Source map
testFunction([${createModule(sourceMapSection)}]);
// DWARF + source map
testFunction([${createModule(dwarfSection, sourceMapSection)}]);
// Source map + DWARF (different order)
testFunction([${createModule(sourceMapSection, dwarfSection)}]);
`
})
.then(() => (
// At this point all scripts were parsed.
// Stop tracking and wait for script sources in each session.
Promise.all(sessions.map(session => session.getScripts()))
))
.catch(err => {
InspectorTest.log(err.stack);
})
.then(() => InspectorTest.completeTest());
function decodeBase64(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;
}
function trackScripts(debuggerParams) {
let {id: sessionId, Protocol} = contextGroup.connect();
let scripts = [];
Protocol.Debugger.enable(debuggerParams);
Protocol.Debugger.onScriptParsed(handleScriptParsed);
async function loadScript({url, scriptId, sourceMapURL}) {
InspectorTest.log(`Session #${sessionId}: Script #${scripts.length} parsed. URL: ${url}. Source map URL: ${sourceMapURL}`);
let scriptSource;
if (sourceMapURL) {
let {result: {bytecode}} = await Protocol.Debugger.getWasmBytecode({scriptId});
// Binary value is represented as base64 in JSON, decode it.
bytecode = decodeBase64(bytecode);
// Check that it can be parsed back to a WebAssembly module.
let module = new WebAssembly.Module(bytecode);
scriptSource = `
Raw: ${Array.from(bytecode, b => ('0' + b.toString(16)).slice(-2)).join(' ')}
Imports: [${WebAssembly.Module.imports(module).map(i => `${i.name}: ${i.kind} from "${i.module}"`).join(', ')}]
Exports: [${WebAssembly.Module.exports(module).map(e => `${e.name}: ${e.kind}`).join(', ')}]
`.trim();
} else {
({result: {scriptSource}} = await Protocol.Debugger.getScriptSource({scriptId}));
}
InspectorTest.log(`Session #${sessionId}: Source for ${url}:`);
InspectorTest.log(scriptSource);
}
function handleScriptParsed({params}) {
if (params.url.startsWith("wasm://")) {
scripts.push(loadScript(params));
}
}
return {
Protocol,
getScripts: () => Promise.all(scripts),
};
}