2017-01-27 07:20:09 +00:00
|
|
|
// 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
|
|
|
|
|
2017-05-19 00:35:45 +00:00
|
|
|
let {session, contextGroup, Protocol} = InspectorTest.start('Tests breakable locations in wasm');
|
|
|
|
|
2017-02-28 20:22:24 +00:00
|
|
|
utils.load('test/mjsunit/wasm/wasm-module-builder.js');
|
2017-01-27 07:20:09 +00:00
|
|
|
|
|
|
|
var builder = new WasmModuleBuilder();
|
|
|
|
|
|
|
|
// clang-format off
|
|
|
|
var func_idx = builder.addFunction('helper', kSig_v_v)
|
|
|
|
.addLocals({i32_count: 1})
|
|
|
|
.addBody([
|
|
|
|
kExprNop,
|
|
|
|
kExprI32Const, 12,
|
|
|
|
kExprSetLocal, 0,
|
|
|
|
]).index;
|
|
|
|
|
|
|
|
builder.addFunction('main', kSig_v_i)
|
|
|
|
.addBody([
|
|
|
|
kExprGetLocal, 0,
|
|
|
|
kExprIf, kWasmStmt,
|
|
|
|
kExprBlock, kWasmStmt,
|
|
|
|
kExprCallFunction, func_idx,
|
|
|
|
kExprEnd,
|
|
|
|
kExprEnd
|
|
|
|
]).exportAs('main');
|
|
|
|
// clang-format on
|
|
|
|
|
|
|
|
var module_bytes = builder.toArray();
|
|
|
|
|
|
|
|
function testFunction(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;
|
|
|
|
}
|
|
|
|
|
|
|
|
var module = new WebAssembly.Module(buffer);
|
|
|
|
// Set global variable.
|
|
|
|
instance = new WebAssembly.Instance(module);
|
|
|
|
}
|
|
|
|
|
|
|
|
var evalWithUrl = (code, url) => Protocol.Runtime.evaluate(
|
|
|
|
{'expression': code + '\n//# sourceURL=v8://test/' + url});
|
|
|
|
|
|
|
|
var setupCode = testFunction.toString() + ';\nvar module_bytes = ' +
|
|
|
|
JSON.stringify(module_bytes) + ';\nvar instance;';
|
|
|
|
|
|
|
|
Protocol.Debugger.enable();
|
|
|
|
Protocol.Debugger.onScriptParsed(handleScriptParsed);
|
|
|
|
InspectorTest.log('Running testFunction...');
|
|
|
|
evalWithUrl(setupCode, 'setup')
|
|
|
|
.then(() => evalWithUrl('testFunction(module_bytes)', 'runTestFunction'))
|
|
|
|
.then(getBreakableLocationsForAllWasmScripts)
|
|
|
|
.then(setAllBreakableLocations)
|
|
|
|
.then(() => InspectorTest.log('Running wasm code...'))
|
|
|
|
.then(() => (evalWithUrl('instance.exports.main(1)', 'runWasm'), 0))
|
|
|
|
.then(waitForAllPauses)
|
|
|
|
.then(() => InspectorTest.log('Finished!'))
|
|
|
|
.then(InspectorTest.completeTest);
|
|
|
|
|
|
|
|
var allBreakableLocations = [];
|
|
|
|
|
|
|
|
var urls = {};
|
|
|
|
var numScripts = 0;
|
|
|
|
var wasmScripts = [];
|
|
|
|
function handleScriptParsed(messageObject) {
|
|
|
|
var scriptId = messageObject.params.scriptId;
|
|
|
|
var url = messageObject.params.url;
|
|
|
|
urls[scriptId] = url;
|
|
|
|
InspectorTest.log('Script nr ' + numScripts + ' parsed. URL: ' + url);
|
|
|
|
++numScripts;
|
|
|
|
|
|
|
|
if (url.startsWith('wasm://')) {
|
|
|
|
InspectorTest.log('This is a wasm script (nr ' + wasmScripts.length + ').');
|
|
|
|
wasmScripts.push(scriptId);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
function printFailure(message) {
|
|
|
|
if (!message.result) {
|
|
|
|
InspectorTest.logMessage(message);
|
|
|
|
}
|
|
|
|
return message;
|
|
|
|
}
|
|
|
|
|
|
|
|
function printBreakableLocations(message, expectedScriptId, source) {
|
|
|
|
var lines = source.split('\n');
|
|
|
|
var locations = message.result.locations;
|
|
|
|
InspectorTest.log(locations.length + ' breakable location(s):');
|
|
|
|
for (var i = 0; i < locations.length; ++i) {
|
|
|
|
if (locations[i].scriptId != expectedScriptId) {
|
|
|
|
InspectorTest.log(
|
|
|
|
'SCRIPT ID MISMATCH!! ' + locations[i].scriptId + ' != ' +
|
|
|
|
expectedScriptId);
|
|
|
|
}
|
|
|
|
var line = '<illegal line number>';
|
|
|
|
if (locations[i].lineNumber < lines.length) {
|
|
|
|
line = lines[locations[i].lineNumber];
|
|
|
|
if (locations[i].columnNumber < line.length) {
|
|
|
|
line = line.substr(0, locations[i].columnNumber) + '>' +
|
|
|
|
line.substr(locations[i].columnNumber);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
InspectorTest.log(
|
|
|
|
'[' + i + '] ' + locations[i].lineNumber + ':' +
|
|
|
|
locations[i].columnNumber + ' || ' + line);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
function checkGetBreakableLocations(wasmScriptNr) {
|
|
|
|
InspectorTest.log(
|
|
|
|
'Requesting all breakable locations in wasm script ' + wasmScriptNr);
|
|
|
|
var scriptId = wasmScripts[wasmScriptNr];
|
|
|
|
var source;
|
|
|
|
return Protocol.Debugger.getScriptSource({scriptId: scriptId})
|
|
|
|
.then(msg => source = msg.result.scriptSource)
|
|
|
|
.then(
|
|
|
|
() => Protocol.Debugger.getPossibleBreakpoints(
|
|
|
|
{start: {lineNumber: 0, columnNumber: 0, scriptId: scriptId}}))
|
|
|
|
.then(printFailure)
|
|
|
|
.then(msg => (allBreakableLocations.push(...msg.result.locations), msg))
|
|
|
|
.then(msg => printBreakableLocations(msg, scriptId, source))
|
|
|
|
.then(
|
|
|
|
() => InspectorTest.log(
|
|
|
|
'Requesting breakable locations in lines [0,3)'))
|
|
|
|
.then(() => Protocol.Debugger.getPossibleBreakpoints({
|
|
|
|
start: {lineNumber: 0, columnNumber: 0, scriptId: scriptId},
|
|
|
|
end: {lineNumber: 3, columnNumber: 0, scriptId: scriptId}
|
|
|
|
}))
|
|
|
|
.then(printFailure)
|
|
|
|
.then(msg => printBreakableLocations(msg, scriptId, source))
|
|
|
|
.then(
|
|
|
|
() => InspectorTest.log(
|
|
|
|
'Requesting breakable locations in lines [4,6)'))
|
|
|
|
.then(() => Protocol.Debugger.getPossibleBreakpoints({
|
|
|
|
start: {lineNumber: 4, columnNumber: 0, scriptId: scriptId},
|
|
|
|
end: {lineNumber: 6, columnNumber: 0, scriptId: scriptId}
|
|
|
|
}))
|
|
|
|
.then(printFailure)
|
|
|
|
.then(msg => printBreakableLocations(msg, scriptId, source));
|
|
|
|
}
|
|
|
|
|
|
|
|
function getBreakableLocationsForAllWasmScripts() {
|
|
|
|
InspectorTest.log('Querying breakable locations for all wasm scripts now...');
|
|
|
|
var promise = Promise.resolve();
|
|
|
|
for (var wasmScriptNr = 0; wasmScriptNr < wasmScripts.length;
|
|
|
|
++wasmScriptNr) {
|
|
|
|
promise = promise.then(checkGetBreakableLocations.bind(null, wasmScriptNr));
|
|
|
|
}
|
|
|
|
return promise;
|
|
|
|
}
|
|
|
|
|
|
|
|
function locationMatches(loc1, loc2) {
|
|
|
|
return loc1.scriptId == loc2.scriptId && loc1.lineNumber == loc2.lineNumber &&
|
|
|
|
loc1.columnNumber == loc2.columnNumber;
|
|
|
|
}
|
|
|
|
|
|
|
|
function locationStr(loc) {
|
|
|
|
return urls[loc.scriptId] + ':' + loc.lineNumber + ':' + loc.columnNumber;
|
|
|
|
}
|
|
|
|
|
|
|
|
function setBreakpoint(loc) {
|
|
|
|
InspectorTest.log('Setting at ' + locationStr(loc));
|
|
|
|
function check(msg) {
|
|
|
|
if (locationMatches(loc, msg.result.actualLocation)) {
|
|
|
|
InspectorTest.log("Success!");
|
|
|
|
} else {
|
|
|
|
InspectorTest.log("Mismatch!");
|
|
|
|
InspectorTest.logMessage(msg);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return Protocol.Debugger.setBreakpoint({'location': loc})
|
|
|
|
.then(printFailure)
|
|
|
|
.then(check);
|
|
|
|
}
|
|
|
|
|
|
|
|
function setAllBreakableLocations() {
|
|
|
|
InspectorTest.log('Setting a breakpoint on each breakable location...');
|
|
|
|
var promise = Promise.resolve();
|
|
|
|
for (var loc of allBreakableLocations) {
|
|
|
|
promise = promise.then(setBreakpoint.bind(null, loc));
|
|
|
|
}
|
|
|
|
return promise;
|
|
|
|
}
|
|
|
|
|
|
|
|
function removePausedLocation(msg) {
|
|
|
|
var topLocation = msg.params.callFrames[0].location;
|
|
|
|
InspectorTest.log('Stopped at ' + locationStr(topLocation));
|
|
|
|
for (var i = 0; i < allBreakableLocations.length; ++i) {
|
|
|
|
if (locationMatches(topLocation, allBreakableLocations[i])) {
|
|
|
|
allBreakableLocations.splice(i, 1);
|
|
|
|
--i;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
function waitForAllPauses() {
|
|
|
|
InspectorTest.log('Missing breakpoints: ' + allBreakableLocations.length);
|
|
|
|
if (allBreakableLocations.length == 0) return;
|
|
|
|
return Protocol.Debugger.oncePaused()
|
|
|
|
.then(removePausedLocation)
|
|
|
|
.then(Protocol.Debugger.resume())
|
|
|
|
.then(waitForAllPauses);
|
|
|
|
}
|