| // 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. |
| |
| let {session, contextGroup, Protocol} = InspectorTest.start( |
| 'Tests that stepOver and stepInto correctly handle skipLists.'); |
| |
| function test(input) { |
| debugger; |
| var a = 4; |
| var sum = 0; |
| if (input > 0) { |
| sum = a + input; |
| } |
| var b = 5; |
| sum = add(sum, b); |
| return sum; |
| } |
| |
| function add(a, b) { |
| var res = a + b; |
| return res; |
| } |
| |
| contextGroup.addScript(`${test} //# sourceURL=test.js`); |
| contextGroup.addScript(`${add}`); |
| |
| const first_non_debug_line_offset = 2; |
| const last_line_line_offset = 9; |
| const function_call_line_offset = 8; |
| const function_call_column_offset = 2; |
| const if_case_line_offset = 4; |
| |
| const add_first_line_line_offset = 1; |
| const add_last_line_line_offset = 2; |
| const add_last_line_column_offset = 13; |
| |
| Protocol.Debugger.enable(); |
| runTest() |
| .catch(reason => InspectorTest.log(`Failed: ${reason}`)) |
| .then(InspectorTest.completeTest); |
| |
| async function runTest() { |
| const response = await Protocol.Debugger.onceScriptParsed(2); |
| const scriptIds = response.map(msg => msg.params.scriptId); |
| |
| await checkValidSkipLists(scriptIds[0], scriptIds[1]); |
| await checkInvalidSkipLists(scriptIds[0]); |
| } |
| |
| async function checkInvalidSkipLists(scriptId) { |
| const actions = ['stepOver', 'stepInto']; |
| for (let action of actions) { |
| InspectorTest.log('Test: start position has invalid column number'); |
| let skipList = [createLocationRange( |
| scriptId, first_non_debug_line_offset, -1, last_line_line_offset, 0)]; |
| await testStep(skipList, action); |
| |
| InspectorTest.log('Test: start position has invalid line number'); |
| skipList = |
| [createLocationRange(scriptId, -1, 0, first_non_debug_line_offset, 0)]; |
| await testStep(skipList, action); |
| |
| InspectorTest.log('Test: end position smaller than start position'); |
| skipList = [createLocationRange( |
| scriptId, if_case_line_offset, 0, first_non_debug_line_offset, 0)]; |
| await testStep(skipList, action); |
| |
| InspectorTest.log('Test: skip list is not maximally merged'); |
| skipList = [ |
| createLocationRange( |
| scriptId, first_non_debug_line_offset, 0, if_case_line_offset, 0), |
| createLocationRange( |
| scriptId, if_case_line_offset, 0, last_line_line_offset, 0) |
| ]; |
| await testStep(skipList, action); |
| |
| InspectorTest.log('Test: skip list is not sorted'); |
| skipList = [ |
| createLocationRange( |
| scriptId, function_call_line_offset, 0, last_line_line_offset, 0), |
| createLocationRange( |
| scriptId, first_non_debug_line_offset, 0, if_case_line_offset, 0) |
| ]; |
| await testStep(skipList, action); |
| } |
| } |
| |
| async function checkValidSkipLists(testScriptId, addScriptId) { |
| InspectorTest.log('Test: Stepping over without skip list'); |
| await testStep([], 'stepOver'); |
| |
| InspectorTest.log('Test: Stepping over with skip list'); |
| let skipList = [ |
| createLocationRange( |
| testScriptId, first_non_debug_line_offset, 0, if_case_line_offset, 0), |
| createLocationRange( |
| testScriptId, function_call_line_offset, 0, last_line_line_offset, 0) |
| ]; |
| await testStep(skipList, 'stepOver'); |
| |
| InspectorTest.log('Test: Stepping over start location is inclusive'); |
| skipList = [createLocationRange( |
| testScriptId, function_call_line_offset, function_call_column_offset, |
| last_line_line_offset, 0)]; |
| await testStep(skipList, 'stepOver'); |
| |
| InspectorTest.log('Test: Stepping over end location is exclusive'); |
| skipList = [createLocationRange( |
| testScriptId, first_non_debug_line_offset, 0, function_call_line_offset, |
| function_call_column_offset)]; |
| await testStep(skipList, 'stepOver'); |
| |
| InspectorTest.log('Test: Stepping into without skip list'); |
| skipList = []; |
| await testStep(skipList, 'stepInto'); |
| |
| InspectorTest.log( |
| 'Test: Stepping into with skip list, while call itself is skipped'); |
| skipList = [ |
| createLocationRange( |
| addScriptId, add_first_line_line_offset, 0, add_last_line_line_offset, |
| 0), |
| createLocationRange( |
| testScriptId, first_non_debug_line_offset, 0, |
| function_call_line_offset + 1, 0), |
| ]; |
| await testStep(skipList, 'stepInto'); |
| |
| InspectorTest.log('Test: Stepping into start location is inclusive'); |
| skipList = [ |
| createLocationRange( |
| addScriptId, add_last_line_line_offset, add_last_line_column_offset, |
| add_last_line_line_offset + 1, 0), |
| ]; |
| await testStep(skipList, 'stepInto'); |
| |
| InspectorTest.log('Test: Stepping into end location is exclusive'); |
| skipList = [ |
| createLocationRange( |
| addScriptId, add_last_line_line_offset - 1, 0, |
| add_last_line_line_offset, add_last_line_column_offset), |
| ]; |
| await testStep(skipList, 'stepInto'); |
| } |
| |
| async function testStep(skipList, stepAction) { |
| InspectorTest.log( |
| `Testing ${stepAction} with skipList: ${JSON.stringify(skipList)}`); |
| Protocol.Runtime.evaluate({expression: 'test(5);'}); |
| while (true) { |
| const pausedMsg = await Protocol.Debugger.oncePaused(); |
| const topCallFrame = pausedMsg.params.callFrames[0]; |
| printCallFrame(topCallFrame); |
| if (topCallFrame.location.lineNumber == last_line_line_offset) break; |
| |
| const stepOverMsg = await Protocol.Debugger[stepAction]({skipList}); |
| if (stepOverMsg.error) { |
| InspectorTest.log(stepOverMsg.error.message); |
| Protocol.Debugger.resume(); |
| return; |
| } |
| } |
| await Protocol.Debugger.resume(); |
| } |
| |
| function createLocationRange( |
| scriptId, startLine, startColumn, endLine, endColumn) { |
| return { |
| scriptId: scriptId, |
| start: {lineNumber: startLine, columnNumber: startColumn}, |
| end: {lineNumber: endLine, columnNumber: endColumn} |
| } |
| } |
| |
| function printCallFrame(frame) { |
| InspectorTest.log( |
| frame.functionName + ': ' + frame.location.lineNumber + ':' + |
| frame.location.columnNumber); |
| } |