blob: f2254d75820538dbfe296710eaae6afe3641858b [file] [log] [blame]
TestPage.registerInitializer(() => {
let lines = [];
let linesSourceCode = null;
function insertCaretIntoStringAtIndex(str, index, caret="|") {
return str.slice(0, index) + caret + str.slice(index);
}
window.findScript = function(regex) {
for (let resource of WI.networkManager.mainFrame.resourceCollection) {
if (regex.test(resource.url))
return resource.scripts[0];
}
return null;
}
window.findResource = function(regex) {
for (let frame of WI.networkManager.frames) {
if (regex.test(frame.mainResource.url))
return frame.mainResource;
for (let resource of frame.resourceCollection) {
if (regex.test(resource.url))
return resource;
}
}
return null;
}
window.loadLinesFromSourceCode = function(sourceCode) {
linesSourceCode = sourceCode;
return sourceCode.requestContent()
.then((content) => {
lines = sourceCode.content.split(/\n/);
return lines;
})
.catch(() => {
InspectorTest.fail("Failed to load script content.");
InspectorTest.completeTest();
});
}
window.loadMainPageContent = function() {
return loadLinesFromSourceCode(WI.networkManager.mainFrame.mainResource);
}
window.setBreakpointsOnLinesWithBreakpointComment = function(resource) {
if (!resource)
resource = WI.networkManager.mainFrame.mainResource;
function createLocation(resource, lineNumber, columnNumber) {
return {url: resource.url, lineNumber, columnNumber};
}
let promises = [];
for (let i = 0; i < lines.length; ++i) {
let line = lines[i];
if (/BREAKPOINT/.test(line)) {
let lastPathComponent = parseURL(resource.url).lastPathComponent;
InspectorTest.log(`Setting Breakpoint: ${lastPathComponent}:${i}:0`);
promises.push(DebuggerAgent.setBreakpointByUrl.invoke({url: resource.url, lineNumber: i, columnNumber: 0}));
}
}
return Promise.all(promises);
}
window.logResolvedBreakpointLinesWithContext = function(inputLocation, resolvedLocation, context) {
if (resolvedLocation.sourceCode !== linesSourceCode && !WI.networkManager.mainFrame.mainResource.scripts.includes(resolvedLocation.sourceCode)) {
InspectorTest.log("--- Source Unavailable ---");
return;
}
InspectorTest.assert(inputLocation.lineNumber <= resolvedLocation.lineNumber, "Input line number should always precede resolve location line number.");
InspectorTest.assert(inputLocation.lineNumber !== resolvedLocation.lineNumber || inputLocation.columnNumber <= resolvedLocation.columnNumber, "Input position should always precede resolve position.");
const inputCaret = "#";
const resolvedCaret = "|";
let startLine = inputLocation.lineNumber - context;
let endLine = resolvedLocation.lineNumber + context;
for (let lineNumber = startLine; lineNumber <= endLine; ++lineNumber) {
let lineContent = lines[lineNumber];
if (typeof lineContent !== "string")
continue;
let hasInputLocation = lineNumber === inputLocation.lineNumber;
let hasResolvedLocation = lineNumber === resolvedLocation.lineNumber;
let prefix = " ";
if (hasInputLocation && hasResolvedLocation) {
prefix = "-=> ";
lineContent = insertCaretIntoStringAtIndex(lineContent, resolvedLocation.columnNumber, resolvedCaret);
if (inputLocation.columnNumber !== resolvedLocation.columnNumber)
lineContent = insertCaretIntoStringAtIndex(lineContent, inputLocation.columnNumber, inputCaret);
} else if (hasInputLocation) {
prefix = " -> ";
lineContent = insertCaretIntoStringAtIndex(lineContent, inputLocation.columnNumber, inputCaret);
} else if (hasResolvedLocation) {
prefix = " => ";
lineContent = insertCaretIntoStringAtIndex(lineContent, resolvedLocation.columnNumber, resolvedCaret);
}
let number = lineNumber.toString().padStart(3);
InspectorTest.log(`${prefix}${number} ${lineContent}`);
}
}
window.logLinesWithContext = function(location, context) {
if (location.sourceCode !== linesSourceCode && !WI.networkManager.mainFrame.mainResource.scripts.includes(location.sourceCode)) {
InspectorTest.log("--- Source Unavailable ---");
return;
}
let startLine = location.lineNumber - context;
let endLine = location.lineNumber + context;
for (let lineNumber = startLine; lineNumber <= endLine; ++lineNumber) {
let lineContent = lines[lineNumber];
if (typeof lineContent !== "string")
continue;
let active = lineNumber === location.lineNumber;
let prefix = active ? " -> " : " ";
let number = lineNumber.toString().padStart(3);
lineContent = active ? insertCaretIntoStringAtIndex(lineContent, location.columnNumber) : lineContent;
InspectorTest.log(`${prefix}${number} ${lineContent}`);
}
}
window.logPauseLocation = function() {
let callFrame = WI.debuggerManager.activeCallFrame;
let name = callFrame.functionName || "<anonymous>";
let location = callFrame.sourceCodeLocation;
let line = location.lineNumber + 1;
let column = location.columnNumber + 1;
InspectorTest.log(`PAUSE AT ${name}:${line}:${column}`);
logLinesWithContext(location, 3);
InspectorTest.log("");
}
let suite;
let currentSteps = [];
window.step = function(type) {
switch (type) {
case "in":
InspectorTest.log("ACTION: step-in");
WI.debuggerManager.stepInto();
break;
case "over":
InspectorTest.log("ACTION: step-over");
WI.debuggerManager.stepOver();
break;
case "out":
InspectorTest.log("ACTION: step-out");
WI.debuggerManager.stepOut();
break;
case "next":
InspectorTest.log("ACTION: step-next");
WI.debuggerManager.stepNext();
break;
case "resume":
InspectorTest.log("ACTION: resume");
WI.debuggerManager.resume();
break;
default:
InspectorTest.fail("Unhandled step.");
WI.debuggerManager.resume();
break;
}
}
window.initializeSteppingTestSuite = function(testSuite) {
suite = testSuite;
WI.debuggerManager.addEventListener(WI.DebuggerManager.Event.CallFramesDidChange, (event) => {
if (!WI.debuggerManager.activeCallFrame)
return;
logPauseLocation();
step(currentSteps.shift());
});
}
window.addSteppingTestCase = function({name, description, expression, steps, pauseOnAllException, setup, teardown}) {
suite.addTestCase({
name, description, setup, teardown,
test(resolve, reject) {
// Setup.
currentSteps = steps;
InspectorTest.assert(steps[steps.length - 1] === "resume", "The test should always resume at the end to avoid timeouts.");
WI.debuggerManager.allExceptionsBreakpoint.disabled = pauseOnAllException ? false : true;
// Trigger entry and step through it.
InspectorTest.evaluateInPage(expression);
InspectorTest.log(`EXPRESSION: ${expression}`);
InspectorTest.log(`STEPS: ${steps.join(", ")}`);
WI.debuggerManager.singleFireEventListener(WI.DebuggerManager.Event.Paused, (event) => {
InspectorTest.log(`PAUSED (${WI.debuggerManager.dataForTarget(WI.debuggerManager.activeCallFrame.target).pauseReason})`);
});
WI.debuggerManager.singleFireEventListener(WI.DebuggerManager.Event.Resumed, (event) => {
InspectorTest.log("RESUMED");
InspectorTest.expectThat(steps.length === 0, "Should have used all steps.");
resolve();
});
}
});
}
});
if (!window.testRunner) {
window.addEventListener("load", () => {
for (let property in window) {
if (property.startsWith("entry")) {
let button = document.body.appendChild(document.createElement("button"));
button.textContent = property;
button.onclick = () => { setTimeout(window[property]); };
document.body.appendChild(document.createElement("br"));
}
}
});
}