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); |
+} |