// 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. let {session, contextGroup, Protocol} = InspectorTest.start('Tests Debugger.setScriptSource'); contextGroup.addScript( `function TestExpression(a, b) { return a + b; }`); // A general-purpose engine for sending a sequence of protocol commands. // The clients provide requests and response handlers, while the engine catches // errors and makes sure that once there's nothing to do completeTest() is called. // @param step is an object with command, params and callback fields function runRequestSeries(step) { processStep(step); function processStep(currentStep) { try { processStepOrFail(currentStep); } catch (e) { InspectorTest.log(e.stack); InspectorTest.completeTest(); } } function processStepOrFail(currentStep) { if (!currentStep) { InspectorTest.completeTest(); return; } if (!currentStep.command) { // A simple loopback step. var next = currentStep.callback(); processStep(next); return; } var innerCallback = function(response) { var next; if ("error" in response) { if (!("errorHandler" in currentStep)) { // Error message is not logged intentionally, it may be platform-specific. InspectorTest.log("Protocol command '" + currentStep.command + "' failed"); InspectorTest.completeTest(); return; } try { next = currentStep.errorHandler(response.error); } catch (e) { InspectorTest.log(e.stack); InspectorTest.completeTest(); return; } } else { try { next = currentStep.callback(response.result); } catch (e) { InspectorTest.log(e.stack); InspectorTest.completeTest(); return; } } processStep(next); } var command = currentStep.command.split("."); Protocol[command[0]][command[1]](currentStep.params).then(innerCallback); } } function logEqualsCheck(actual, expected) { if (actual === expected) { InspectorTest.log("PASS, result value: " + actual); } else { InspectorTest.log("FAIL, actual value: " + actual + ", expected: " + expected); } } function logCheck(description, success) { InspectorTest.log(description + ": " + (success ? "PASS" : "FAIL")); } var firstStep = { callback: enableDebugger }; runRequestSeries(firstStep); function enableDebugger() { return { command: "Debugger.enable", params: {}, callback: evalFunction }; } function evalFunction(response) { var expression = "TestExpression(2, 4)"; return { command: "Runtime.evaluate", params: { expression: expression }, callback: callbackEvalFunction }; } function callbackEvalFunction(result) { InspectorTest.log("Function evaluate: " + JSON.stringify(result.result)); logEqualsCheck(result.result.value, 6); return { command: "Runtime.evaluate", params: { expression: "TestExpression" }, callback: callbackEvalFunctionObject }; } function callbackEvalFunctionObject(result) { return { command: "Runtime.getProperties", params: { objectId: result.result.objectId }, callback: callbackFunctionDetails }; } function callbackFunctionDetails(result) { var scriptId; for (var prop of result.internalProperties) { if (prop.name === "[[FunctionLocation]]") scriptId = prop.value.value.scriptId; } return createScriptManipulationArc(scriptId, null); } // Several steps with scriptId in context. function createScriptManipulationArc(scriptId, next) { return { command: "Debugger.getScriptSource", params: { scriptId: scriptId }, callback: callbackGetScriptSource }; var originalText; function callbackGetScriptSource(result) { originalText = result.scriptSource; var patched = originalText.replace("a + b", "a * b"); return { command: "Debugger.setScriptSource", params: { scriptId: scriptId, scriptSource: patched }, callback: callbackSetScriptSource }; } function callbackSetScriptSource(result) { var expression = "TestExpression(2, 4)"; return { command: "Runtime.evaluate", params: { expression: expression }, callback: callbackEvalFunction2 }; } function callbackEvalFunction2(result) { InspectorTest.log("Function evaluate: " + JSON.stringify(result.result)); logEqualsCheck(result.result.value, 8); var patched = originalText.replace("a + b", "a # b"); return { command: "Debugger.setScriptSource", params: { scriptId: scriptId, scriptSource: patched }, callback: errorCallbackSetScriptSource2 }; } function errorCallbackSetScriptSource2(result) { var exceptionDetails = result.exceptionDetails; logCheck("Has error reported", !!exceptionDetails); logCheck("Reported error is a compile error", !!exceptionDetails); if (exceptionDetails) logEqualsCheck(exceptionDetails.lineNumber, 1); return next; } }