| Index: test/inspector/debugger/wasm-get-breakable-locations.js
|
| diff --git a/test/inspector/debugger/wasm-get-breakable-locations.js b/test/inspector/debugger/wasm-get-breakable-locations.js
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..f947161b5ec1d8dd2da2f49b38b76699524afe0b
|
| --- /dev/null
|
| +++ b/test/inspector/debugger/wasm-get-breakable-locations.js
|
| @@ -0,0 +1,208 @@
|
| +// 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
|
| +
|
| +load('test/mjsunit/wasm/wasm-constants.js');
|
| +load('test/mjsunit/wasm/wasm-module-builder.js');
|
| +
|
| +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);
|
| +}
|
|
|