mirror of
https://github.com/react/react-native-devtools-frontend.git
synced 2026-10-10 21:54:47 +08:00
Network should not be intsrumented with JavaScript AsyncTask instrumentation since it does not trigger JS execution explicitly. R=pfeldman@chromium.org Bug: chromium:840502 Change-Id: I07a939b7f583b0330fa40afb0326a40e58918547 Reviewed-on: https://chromium-review.googlesource.com/1049107 Commit-Queue: Aleksey Kozyatinskiy <kozyatinskiy@chromium.org> Commit-Queue: Pavel Feldman <pfeldman@chromium.org> Reviewed-by: Pavel Feldman <pfeldman@chromium.org> Cr-Original-Commit-Position: refs/heads/master@{#556673} Cr-Mirrored-From: https://chromium.googlesource.com/chromium/src Cr-Mirrored-Commit: af27f53e066caf431f7999c9069aca1c4f374f62
781 lines
27 KiB
JavaScript
781 lines
27 KiB
JavaScript
// Copyright 2017 The Chromium Authors. All
|
|
// Use of this source code is governed by a BSD-style license that can be
|
|
// found in the LICENSE file.
|
|
|
|
/**
|
|
* @fileoverview using private properties isn't a Closure violation in tests.
|
|
* @suppress {accessControls}
|
|
*/
|
|
|
|
SourcesTestRunner.startDebuggerTest = function(callback, quiet) {
|
|
console.assert(TestRunner.debuggerModel.debuggerEnabled(), 'Debugger has to be enabled');
|
|
|
|
if (quiet !== undefined)
|
|
SourcesTestRunner._quiet = quiet;
|
|
|
|
UI.viewManager.showView('sources');
|
|
TestRunner.addSniffer(SDK.DebuggerModel.prototype, '_pausedScript', SourcesTestRunner._pausedScript, true);
|
|
TestRunner.addSniffer(SDK.DebuggerModel.prototype, '_resumedScript', SourcesTestRunner._resumedScript, true);
|
|
TestRunner.safeWrap(callback)();
|
|
};
|
|
|
|
SourcesTestRunner.startDebuggerTestPromise = function(quiet) {
|
|
let cb;
|
|
const p = new Promise(fullfill => cb = fullfill);
|
|
SourcesTestRunner.startDebuggerTest(cb, quiet);
|
|
return p;
|
|
};
|
|
|
|
SourcesTestRunner.completeDebuggerTest = function() {
|
|
Common.moduleSetting('breakpointsActive').set(true);
|
|
SourcesTestRunner.resumeExecution(TestRunner.completeTest.bind(TestRunner));
|
|
};
|
|
|
|
(function() {
|
|
const origThen = Promise.prototype.then;
|
|
const origCatch = Promise.prototype.catch;
|
|
|
|
Promise.prototype.then = function() {
|
|
const result = origThen.apply(this, arguments);
|
|
origThen.call(result, undefined, onUncaughtPromiseReject.bind(null, new Error().stack));
|
|
return result;
|
|
};
|
|
|
|
Promise.prototype.catch = function() {
|
|
const result = origCatch.apply(this, arguments);
|
|
origThen.call(result, undefined, onUncaughtPromiseReject.bind(null, new Error().stack));
|
|
return result;
|
|
};
|
|
|
|
function onUncaughtPromiseReject(stack, e) {
|
|
const message = typeof e === 'object' && e.stack || e;
|
|
TestRunner.addResult('FAIL: Uncaught exception in promise: ' + message + ' ' + stack);
|
|
SourcesTestRunner.completeDebuggerTest();
|
|
}
|
|
})();
|
|
|
|
SourcesTestRunner.runDebuggerTestSuite = function(testSuite) {
|
|
const testSuiteTests = testSuite.slice();
|
|
|
|
function runner() {
|
|
if (!testSuiteTests.length) {
|
|
SourcesTestRunner.completeDebuggerTest();
|
|
return;
|
|
}
|
|
|
|
const nextTest = testSuiteTests.shift();
|
|
TestRunner.addResult('');
|
|
TestRunner.addResult(
|
|
'Running: ' +
|
|
/function\s([^(]*)/.exec(nextTest)[1]);
|
|
TestRunner.safeWrap(nextTest)(runner, runner);
|
|
}
|
|
|
|
SourcesTestRunner.startDebuggerTest(runner);
|
|
};
|
|
|
|
SourcesTestRunner.runTestFunction = function() {
|
|
TestRunner.evaluateInPageAnonymously('scheduleTestFunction()');
|
|
TestRunner.addResult('Set timer for test function.');
|
|
};
|
|
|
|
SourcesTestRunner.runTestFunctionAndWaitUntilPaused = function(callback) {
|
|
SourcesTestRunner.runTestFunction();
|
|
SourcesTestRunner.waitUntilPaused(callback);
|
|
};
|
|
|
|
SourcesTestRunner.runTestFunctionAndWaitUntilPausedPromise = function() {
|
|
return new Promise(SourcesTestRunner.runTestFunctionAndWaitUntilPaused);
|
|
};
|
|
|
|
SourcesTestRunner.runAsyncCallStacksTest = function(totalDebuggerStatements, maxAsyncCallStackDepth) {
|
|
const defaultMaxAsyncCallStackDepth = 32;
|
|
SourcesTestRunner.setQuiet(true);
|
|
SourcesTestRunner.startDebuggerTest(step1);
|
|
|
|
async function step1() {
|
|
await TestRunner.DebuggerAgent.setAsyncCallStackDepth(maxAsyncCallStackDepth || defaultMaxAsyncCallStackDepth);
|
|
SourcesTestRunner.runTestFunctionAndWaitUntilPaused(didPause);
|
|
}
|
|
|
|
let step = 0;
|
|
const callStacksOutput = [];
|
|
|
|
function didPause(callFrames, reason, breakpointIds, asyncStackTrace) {
|
|
++step;
|
|
callStacksOutput.push(SourcesTestRunner.captureStackTraceIntoString(callFrames, asyncStackTrace) + '\n');
|
|
|
|
if (step < totalDebuggerStatements) {
|
|
SourcesTestRunner.resumeExecution(SourcesTestRunner.waitUntilPaused.bind(SourcesTestRunner, didPause));
|
|
} else {
|
|
TestRunner.addResult('Captured call stacks in no particular order:');
|
|
callStacksOutput.sort();
|
|
TestRunner.addResults(callStacksOutput);
|
|
SourcesTestRunner.completeDebuggerTest();
|
|
}
|
|
}
|
|
};
|
|
|
|
SourcesTestRunner.dumpSourceFrameMessages = function(sourceFrame, dumpFullURL) {
|
|
const messages = [];
|
|
|
|
for (const bucket of sourceFrame._rowMessageBuckets.values()) {
|
|
for (const rowMessage of bucket._messages) {
|
|
const message = rowMessage.message();
|
|
messages.push(String.sprintf(
|
|
' %d:%d [%s] %s', message.lineNumber(), message.columnNumber(), message.level(), message.text()));
|
|
}
|
|
}
|
|
|
|
const name = (dumpFullURL ? sourceFrame.uiSourceCode().url() : sourceFrame.uiSourceCode().displayName());
|
|
TestRunner.addResult('SourceFrame ' + name + ': ' + messages.length + ' message(s)');
|
|
TestRunner.addResult(messages.join('\n'));
|
|
};
|
|
|
|
SourcesTestRunner.waitUntilPausedNextTime = function(callback) {
|
|
SourcesTestRunner._waitUntilPausedCallback = TestRunner.safeWrap(callback);
|
|
};
|
|
|
|
SourcesTestRunner.waitUntilPaused = function(callback) {
|
|
callback = TestRunner.safeWrap(callback);
|
|
|
|
if (SourcesTestRunner._pausedScriptArguments)
|
|
callback.apply(callback, SourcesTestRunner._pausedScriptArguments);
|
|
else
|
|
SourcesTestRunner._waitUntilPausedCallback = callback;
|
|
};
|
|
|
|
SourcesTestRunner.waitUntilPausedPromise = function() {
|
|
return new Promise(resolve => SourcesTestRunner.waitUntilPaused(resolve));
|
|
};
|
|
|
|
SourcesTestRunner.waitUntilResumedNextTime = function(callback) {
|
|
SourcesTestRunner._waitUntilResumedCallback = TestRunner.safeWrap(callback);
|
|
};
|
|
|
|
SourcesTestRunner.waitUntilResumed = function(callback) {
|
|
callback = TestRunner.safeWrap(callback);
|
|
|
|
if (!SourcesTestRunner._pausedScriptArguments)
|
|
callback();
|
|
else
|
|
SourcesTestRunner._waitUntilResumedCallback = callback;
|
|
};
|
|
|
|
SourcesTestRunner.waitUntilResumedPromise = function() {
|
|
return new Promise(resolve => SourcesTestRunner.waitUntilResumed(resolve));
|
|
};
|
|
|
|
SourcesTestRunner.resumeExecution = function(callback) {
|
|
if (UI.panels.sources.paused())
|
|
UI.panels.sources._togglePause();
|
|
|
|
SourcesTestRunner.waitUntilResumed(callback);
|
|
};
|
|
|
|
SourcesTestRunner.waitUntilPausedAndDumpStackAndResume = function(callback, options) {
|
|
SourcesTestRunner.waitUntilPaused(paused);
|
|
TestRunner.addSniffer(Sources.SourcesPanel.prototype, '_updateDebuggerButtonsAndStatusForTest', setStatus);
|
|
let caption;
|
|
let callFrames;
|
|
let asyncStackTrace;
|
|
|
|
function setStatus() {
|
|
const statusElement = this.element.querySelector('.paused-message');
|
|
caption = statusElement.deepTextContent();
|
|
|
|
if (callFrames)
|
|
step1();
|
|
}
|
|
|
|
function paused(frames, reason, breakpointIds, async) {
|
|
callFrames = frames;
|
|
asyncStackTrace = async;
|
|
|
|
if (typeof caption === 'string')
|
|
step1();
|
|
}
|
|
|
|
function step1() {
|
|
SourcesTestRunner.captureStackTrace(callFrames, asyncStackTrace, options);
|
|
TestRunner.addResult(TestRunner.clearSpecificInfoFromStackFrames(caption));
|
|
TestRunner.deprecatedRunAfterPendingDispatches(step2);
|
|
}
|
|
|
|
function step2() {
|
|
SourcesTestRunner.resumeExecution(TestRunner.safeWrap(callback));
|
|
}
|
|
};
|
|
|
|
SourcesTestRunner.stepOver = function() {
|
|
Promise.resolve().then(function() {
|
|
UI.panels.sources._stepOver();
|
|
});
|
|
};
|
|
|
|
SourcesTestRunner.stepInto = function() {
|
|
Promise.resolve().then(function() {
|
|
UI.panels.sources._stepInto();
|
|
});
|
|
};
|
|
|
|
SourcesTestRunner.stepIntoAsync = function() {
|
|
Promise.resolve().then(function() {
|
|
UI.panels.sources._stepIntoAsync();
|
|
});
|
|
};
|
|
|
|
SourcesTestRunner.stepOut = function() {
|
|
Promise.resolve().then(function() {
|
|
UI.panels.sources._stepOut();
|
|
});
|
|
};
|
|
|
|
SourcesTestRunner.togglePause = function() {
|
|
Promise.resolve().then(function() {
|
|
UI.panels.sources._togglePause();
|
|
});
|
|
};
|
|
|
|
SourcesTestRunner.waitUntilPausedAndPerformSteppingActions = function(actions, callback) {
|
|
callback = TestRunner.safeWrap(callback);
|
|
SourcesTestRunner.waitUntilPaused(didPause);
|
|
|
|
function didPause(callFrames, reason, breakpointIds, asyncStackTrace) {
|
|
let action = actions.shift();
|
|
|
|
if (action === 'Print') {
|
|
SourcesTestRunner.captureStackTrace(callFrames, asyncStackTrace);
|
|
TestRunner.addResult('');
|
|
|
|
while (action === 'Print')
|
|
action = actions.shift();
|
|
}
|
|
|
|
if (!action) {
|
|
callback();
|
|
return;
|
|
}
|
|
|
|
TestRunner.addResult('Executing ' + action + '...');
|
|
|
|
switch (action) {
|
|
case 'StepInto':
|
|
SourcesTestRunner.stepInto();
|
|
break;
|
|
case 'StepOver':
|
|
SourcesTestRunner.stepOver();
|
|
break;
|
|
case 'StepOut':
|
|
SourcesTestRunner.stepOut();
|
|
break;
|
|
case 'Resume':
|
|
SourcesTestRunner.togglePause();
|
|
break;
|
|
default:
|
|
TestRunner.addResult('FAIL: Unknown action: ' + action);
|
|
callback();
|
|
return;
|
|
}
|
|
|
|
SourcesTestRunner.waitUntilResumed(
|
|
(actions.length ? SourcesTestRunner.waitUntilPaused.bind(SourcesTestRunner, didPause) : callback));
|
|
}
|
|
};
|
|
|
|
SourcesTestRunner.captureStackTrace = function(callFrames, asyncStackTrace, options) {
|
|
TestRunner.addResult(SourcesTestRunner.captureStackTraceIntoString(callFrames, asyncStackTrace, options));
|
|
};
|
|
|
|
SourcesTestRunner.captureStackTraceIntoString = function(callFrames, asyncStackTrace, options) {
|
|
const results = [];
|
|
options = options || {};
|
|
|
|
function printCallFrames(callFrames, locationFunction, returnValueFunction) {
|
|
let printed = 0;
|
|
|
|
for (let i = 0; i < callFrames.length; i++) {
|
|
const frame = callFrames[i];
|
|
const location = locationFunction.call(frame);
|
|
const script = location.script();
|
|
const uiLocation = Bindings.debuggerWorkspaceBinding.rawLocationToUILocation(location);
|
|
const isFramework = Bindings.blackboxManager.isBlackboxedRawLocation(location);
|
|
|
|
if (options.dropFrameworkCallFrames && isFramework)
|
|
continue;
|
|
|
|
let url;
|
|
let lineNumber;
|
|
|
|
if (uiLocation && uiLocation.uiSourceCode.project().type() !== Workspace.projectTypes.Debugger) {
|
|
url = uiLocation.uiSourceCode.name();
|
|
lineNumber = uiLocation.lineNumber + 1;
|
|
} else {
|
|
url = Bindings.displayNameForURL(script.sourceURL);
|
|
lineNumber = location.lineNumber + 1;
|
|
}
|
|
|
|
let s = ((isFramework ? ' * ' : ' ')) + printed++ + ') ' + frame.functionName + ' (' + url +
|
|
((options.dropLineNumbers ? '' : ':' + lineNumber)) + ')';
|
|
s = s.replace(/scheduleTestFunction.+$/, 'scheduleTestFunction <omitted>');
|
|
results.push(s);
|
|
|
|
if (options.printReturnValue && returnValueFunction && returnValueFunction.call(frame))
|
|
results.push(' <return>: ' + returnValueFunction.call(frame).description);
|
|
|
|
if (frame.functionName === 'scheduleTestFunction') {
|
|
const remainingFrames = callFrames.length - 1 - i;
|
|
|
|
if (remainingFrames)
|
|
results.push(' <... skipped remaining frames ...>');
|
|
|
|
break;
|
|
}
|
|
}
|
|
|
|
return printed;
|
|
}
|
|
|
|
function runtimeCallFramePosition() {
|
|
return new SDK.DebuggerModel.Location(TestRunner.debuggerModel, this.scriptId, this.lineNumber, this.columnNumber);
|
|
}
|
|
|
|
results.push('Call stack:');
|
|
printCallFrames(
|
|
callFrames, SDK.DebuggerModel.CallFrame.prototype.location, SDK.DebuggerModel.CallFrame.prototype.returnValue);
|
|
|
|
while (asyncStackTrace) {
|
|
results.push(' [' + (asyncStackTrace.description || 'Async Call') + ']');
|
|
const printed = printCallFrames(asyncStackTrace.callFrames, runtimeCallFramePosition);
|
|
|
|
if (!printed)
|
|
results.pop();
|
|
|
|
asyncStackTrace = asyncStackTrace.parent;
|
|
}
|
|
|
|
return results.join('\n');
|
|
};
|
|
|
|
SourcesTestRunner.dumpSourceFrameContents = function(sourceFrame) {
|
|
TestRunner.addResult('==Source frame contents start==');
|
|
const textEditor = sourceFrame._textEditor;
|
|
|
|
for (let i = 0; i < textEditor.linesCount; ++i)
|
|
TestRunner.addResult(textEditor.line(i));
|
|
|
|
TestRunner.addResult('==Source frame contents end==');
|
|
};
|
|
|
|
SourcesTestRunner._pausedScript = function(callFrames, reason, auxData, breakpointIds, asyncStackTrace) {
|
|
if (!SourcesTestRunner._quiet)
|
|
TestRunner.addResult('Script execution paused.');
|
|
|
|
const debuggerModel = this.target().model(SDK.DebuggerModel);
|
|
SourcesTestRunner._pausedScriptArguments = [
|
|
SDK.DebuggerModel.CallFrame.fromPayloadArray(debuggerModel, callFrames), reason, breakpointIds, asyncStackTrace,
|
|
auxData
|
|
];
|
|
|
|
if (SourcesTestRunner._waitUntilPausedCallback) {
|
|
const callback = SourcesTestRunner._waitUntilPausedCallback;
|
|
delete SourcesTestRunner._waitUntilPausedCallback;
|
|
setTimeout(() => callback.apply(callback, SourcesTestRunner._pausedScriptArguments));
|
|
}
|
|
};
|
|
|
|
SourcesTestRunner._resumedScript = function() {
|
|
if (!SourcesTestRunner._quiet)
|
|
TestRunner.addResult('Script execution resumed.');
|
|
|
|
delete SourcesTestRunner._pausedScriptArguments;
|
|
|
|
if (SourcesTestRunner._waitUntilResumedCallback) {
|
|
const callback = SourcesTestRunner._waitUntilResumedCallback;
|
|
delete SourcesTestRunner._waitUntilResumedCallback;
|
|
callback();
|
|
}
|
|
};
|
|
|
|
SourcesTestRunner.showUISourceCode = function(uiSourceCode, callback) {
|
|
const panel = UI.panels.sources;
|
|
panel.showUISourceCode(uiSourceCode);
|
|
const sourceFrame = panel.visibleView;
|
|
|
|
if (sourceFrame.loaded)
|
|
callback(sourceFrame);
|
|
else
|
|
TestRunner.addSniffer(sourceFrame, 'setContent', callback && callback.bind(null, sourceFrame));
|
|
};
|
|
|
|
SourcesTestRunner.showUISourceCodePromise = function(uiSourceCode) {
|
|
let fulfill;
|
|
const promise = new Promise(x => fulfill = x);
|
|
SourcesTestRunner.showUISourceCode(uiSourceCode, fulfill);
|
|
return promise;
|
|
};
|
|
|
|
SourcesTestRunner.showScriptSource = function(scriptName, callback) {
|
|
SourcesTestRunner.waitForScriptSource(scriptName, onScriptSource);
|
|
|
|
function onScriptSource(uiSourceCode) {
|
|
SourcesTestRunner.showUISourceCode(uiSourceCode, callback);
|
|
}
|
|
};
|
|
|
|
SourcesTestRunner.showScriptSourcePromise = function(scriptName) {
|
|
return new Promise(resolve => SourcesTestRunner.showScriptSource(scriptName, resolve));
|
|
};
|
|
|
|
SourcesTestRunner.waitForScriptSource = function(scriptName, callback) {
|
|
const panel = UI.panels.sources;
|
|
const uiSourceCodes = panel._workspace.uiSourceCodes();
|
|
|
|
for (let i = 0; i < uiSourceCodes.length; ++i) {
|
|
if (uiSourceCodes[i].project().type() === Workspace.projectTypes.Service)
|
|
continue;
|
|
|
|
if (uiSourceCodes[i].name() === scriptName) {
|
|
callback(uiSourceCodes[i]);
|
|
return;
|
|
}
|
|
}
|
|
|
|
TestRunner.addSniffer(
|
|
Sources.SourcesView.prototype, '_addUISourceCode',
|
|
SourcesTestRunner.waitForScriptSource.bind(SourcesTestRunner, scriptName, callback));
|
|
};
|
|
|
|
SourcesTestRunner.setBreakpoint = function(sourceFrame, lineNumber, condition, enabled) {
|
|
const debuggerPlugin = SourcesTestRunner.debuggerPlugin(sourceFrame);
|
|
if (!debuggerPlugin._muted)
|
|
debuggerPlugin._setBreakpoint(lineNumber, 0, condition, enabled);
|
|
};
|
|
|
|
SourcesTestRunner.removeBreakpoint = function(sourceFrame, lineNumber) {
|
|
const debuggerPlugin = SourcesTestRunner.debuggerPlugin(sourceFrame);
|
|
debuggerPlugin._breakpointManager.findBreakpoints(sourceFrame._uiSourceCode, lineNumber)[0].remove();
|
|
};
|
|
|
|
SourcesTestRunner.createNewBreakpoint = function(sourceFrame, lineNumber, condition, enabled) {
|
|
const debuggerPlugin = SourcesTestRunner.debuggerPlugin(sourceFrame);
|
|
const promise =
|
|
new Promise(resolve => TestRunner.addSniffer(debuggerPlugin.__proto__, '_breakpointWasSetForTest', resolve));
|
|
debuggerPlugin._createNewBreakpoint(lineNumber, condition, enabled);
|
|
return promise;
|
|
};
|
|
|
|
SourcesTestRunner.toggleBreakpoint = function(sourceFrame, lineNumber, disableOnly) {
|
|
const debuggerPlugin = SourcesTestRunner.debuggerPlugin(sourceFrame);
|
|
if (!debuggerPlugin._muted)
|
|
debuggerPlugin._toggleBreakpoint(lineNumber, disableOnly);
|
|
};
|
|
|
|
SourcesTestRunner.waitBreakpointSidebarPane = function(waitUntilResolved) {
|
|
return new Promise(
|
|
resolve => TestRunner.addSniffer(
|
|
Sources.JavaScriptBreakpointsSidebarPane.prototype, '_didUpdateForTest', resolve))
|
|
.then(checkIfReady);
|
|
|
|
function checkIfReady() {
|
|
if (!waitUntilResolved)
|
|
return;
|
|
|
|
for (const breakpoint of Bindings.breakpointManager._allBreakpoints()) {
|
|
if (breakpoint._fakePrimaryLocation && breakpoint.enabled())
|
|
return SourcesTestRunner.waitBreakpointSidebarPane();
|
|
}
|
|
}
|
|
};
|
|
|
|
SourcesTestRunner.breakpointsSidebarPaneContent = function() {
|
|
const paneElement = self.runtime.sharedInstance(Sources.JavaScriptBreakpointsSidebarPane).contentElement;
|
|
const empty = paneElement.querySelector('.gray-info-message');
|
|
|
|
if (empty)
|
|
return TestRunner.textContentWithLineBreaks(empty);
|
|
|
|
const entries = Array.from(paneElement.querySelectorAll('.breakpoint-entry'));
|
|
return entries.map(TestRunner.textContentWithLineBreaks).join('\n');
|
|
};
|
|
|
|
SourcesTestRunner.dumpBreakpointSidebarPane = function(title) {
|
|
TestRunner.addResult('Breakpoint sidebar pane ' + (title || ''));
|
|
TestRunner.addResult(SourcesTestRunner.breakpointsSidebarPaneContent());
|
|
};
|
|
|
|
SourcesTestRunner.dumpScopeVariablesSidebarPane = function() {
|
|
TestRunner.addResult('Scope variables sidebar pane:');
|
|
const sections = SourcesTestRunner.scopeChainSections();
|
|
|
|
for (let i = 0; i < sections.length; ++i) {
|
|
const textContent = TestRunner.textContentWithLineBreaks(sections[i].element);
|
|
const text = TestRunner.clearSpecificInfoFromStackFrames(textContent);
|
|
|
|
if (text.length > 0)
|
|
TestRunner.addResult(text);
|
|
|
|
if (!sections[i].objectTreeElement().expanded)
|
|
TestRunner.addResult(' <section collapsed>');
|
|
}
|
|
};
|
|
|
|
SourcesTestRunner.scopeChainSections = function() {
|
|
const children = self.runtime.sharedInstance(Sources.ScopeChainSidebarPane).contentElement.children;
|
|
const sections = [];
|
|
|
|
for (let i = 0; i < children.length; ++i)
|
|
sections.push(children[i]._section);
|
|
|
|
return sections;
|
|
};
|
|
|
|
SourcesTestRunner.expandScopeVariablesSidebarPane = function(callback) {
|
|
const sections = SourcesTestRunner.scopeChainSections();
|
|
|
|
for (let i = 0; i < sections.length - 1; ++i)
|
|
sections[i].expand();
|
|
|
|
TestRunner.deprecatedRunAfterPendingDispatches(callback);
|
|
};
|
|
|
|
SourcesTestRunner.expandProperties = function(properties, callback) {
|
|
let index = 0;
|
|
|
|
function expandNextPath() {
|
|
if (index === properties.length) {
|
|
TestRunner.safeWrap(callback)();
|
|
return;
|
|
}
|
|
|
|
const parentTreeElement = properties[index++];
|
|
const path = properties[index++];
|
|
SourcesTestRunner._expandProperty(parentTreeElement, path, 0, expandNextPath);
|
|
}
|
|
|
|
TestRunner.deprecatedRunAfterPendingDispatches(expandNextPath);
|
|
};
|
|
|
|
SourcesTestRunner._expandProperty = function(parentTreeElement, path, pathIndex, callback) {
|
|
if (pathIndex === path.length) {
|
|
TestRunner.addResult('Expanded property: ' + path.join('.'));
|
|
callback();
|
|
return;
|
|
}
|
|
|
|
const name = path[pathIndex++];
|
|
const propertyTreeElement = SourcesTestRunner._findChildPropertyTreeElement(parentTreeElement, name);
|
|
|
|
if (!propertyTreeElement) {
|
|
TestRunner.addResult('Failed to expand property: ' + path.slice(0, pathIndex).join('.'));
|
|
SourcesTestRunner.completeDebuggerTest();
|
|
return;
|
|
}
|
|
|
|
propertyTreeElement.expand();
|
|
TestRunner.deprecatedRunAfterPendingDispatches(
|
|
SourcesTestRunner._expandProperty.bind(SourcesTestRunner, propertyTreeElement, path, pathIndex, callback));
|
|
};
|
|
|
|
SourcesTestRunner._findChildPropertyTreeElement = function(parent, childName) {
|
|
const children = parent.children();
|
|
|
|
for (let i = 0; i < children.length; i++) {
|
|
const treeElement = children[i];
|
|
const property = treeElement.property;
|
|
|
|
if (property.name === childName)
|
|
return treeElement;
|
|
}
|
|
};
|
|
|
|
SourcesTestRunner.setQuiet = function(quiet) {
|
|
SourcesTestRunner._quiet = quiet;
|
|
};
|
|
|
|
SourcesTestRunner.queryScripts = function(filter) {
|
|
const scripts = TestRunner.debuggerModel.scripts();
|
|
return (filter ? scripts.filter(filter) : scripts);
|
|
};
|
|
|
|
SourcesTestRunner.createScriptMock = function(
|
|
url, startLine, startColumn, isContentScript, source, target, preRegisterCallback) {
|
|
target = target || SDK.targetManager.mainTarget();
|
|
const debuggerModel = target.model(SDK.DebuggerModel);
|
|
const scriptId = ++SourcesTestRunner._lastScriptId + '';
|
|
const lineCount = source.computeLineEndings().length;
|
|
const endLine = startLine + lineCount - 1;
|
|
const endColumn =
|
|
(lineCount === 1 ? startColumn + source.length : source.length - source.computeLineEndings()[lineCount - 2]);
|
|
const hasSourceURL =
|
|
!!source.match(/\/\/#\ssourceURL=\s*(\S*?)\s*$/m) || !!source.match(/\/\/@\ssourceURL=\s*(\S*?)\s*$/m);
|
|
|
|
const script = new SDK.Script(
|
|
debuggerModel, scriptId, url, startLine, startColumn, endLine, endColumn, 0, '', isContentScript, false,
|
|
undefined, hasSourceURL, source.length);
|
|
|
|
script.requestContent = function() {
|
|
const trimmedSource = SDK.Script._trimSourceURLComment(source);
|
|
return Promise.resolve(trimmedSource);
|
|
};
|
|
|
|
if (preRegisterCallback)
|
|
preRegisterCallback(script);
|
|
|
|
debuggerModel._registerScript(script);
|
|
return script;
|
|
};
|
|
|
|
SourcesTestRunner._lastScriptId = 0;
|
|
|
|
SourcesTestRunner.checkRawLocation = function(script, lineNumber, columnNumber, location) {
|
|
TestRunner.assertEquals(script.scriptId, location.scriptId, 'Incorrect scriptId');
|
|
TestRunner.assertEquals(lineNumber, location.lineNumber, 'Incorrect lineNumber');
|
|
TestRunner.assertEquals(columnNumber, location.columnNumber, 'Incorrect columnNumber');
|
|
};
|
|
|
|
SourcesTestRunner.checkUILocation = function(uiSourceCode, lineNumber, columnNumber, location) {
|
|
TestRunner.assertEquals(
|
|
uiSourceCode, location.uiSourceCode,
|
|
'Incorrect uiSourceCode, expected \'' + ((uiSourceCode ? uiSourceCode.url() : null)) + '\',' +
|
|
' but got \'' + ((location.uiSourceCode ? location.uiSourceCode.url() : null)) + '\'');
|
|
|
|
TestRunner.assertEquals(
|
|
lineNumber, location.lineNumber,
|
|
'Incorrect lineNumber, expected \'' + lineNumber + '\', but got \'' + location.lineNumber + '\'');
|
|
|
|
TestRunner.assertEquals(
|
|
columnNumber, location.columnNumber,
|
|
'Incorrect columnNumber, expected \'' + columnNumber + '\', but got \'' + location.columnNumber + '\'');
|
|
};
|
|
|
|
SourcesTestRunner.scriptFormatter = function() {
|
|
return self.runtime.allInstances(Sources.SourcesView.EditorAction).then(function(editorActions) {
|
|
for (let i = 0; i < editorActions.length; ++i) {
|
|
if (editorActions[i] instanceof Sources.ScriptFormatterEditorAction)
|
|
return editorActions[i];
|
|
}
|
|
|
|
return null;
|
|
});
|
|
};
|
|
|
|
SourcesTestRunner.waitForExecutionContextInTarget = function(target, callback) {
|
|
const runtimeModel = target.model(SDK.RuntimeModel);
|
|
|
|
if (runtimeModel.executionContexts().length) {
|
|
callback(runtimeModel.executionContexts()[0]);
|
|
return;
|
|
}
|
|
|
|
runtimeModel.addEventListener(SDK.RuntimeModel.Events.ExecutionContextCreated, contextCreated);
|
|
|
|
function contextCreated() {
|
|
runtimeModel.removeEventListener(SDK.RuntimeModel.Events.ExecutionContextCreated, contextCreated);
|
|
callback(runtimeModel.executionContexts()[0]);
|
|
}
|
|
};
|
|
|
|
SourcesTestRunner.selectThread = function(target) {
|
|
const threadsPane = self.runtime.sharedInstance(Sources.ThreadsSidebarPane);
|
|
threadsPane._list.selectItem(target.model(SDK.DebuggerModel));
|
|
};
|
|
|
|
SourcesTestRunner.evaluateOnCurrentCallFrame = function(code) {
|
|
return TestRunner.debuggerModel.evaluateOnSelectedCallFrame({expression: code, objectGroup: 'console'});
|
|
};
|
|
|
|
SourcesTestRunner.waitDebuggerPluginBreakpoints = function(sourceFrame) {
|
|
return waitUpdate().then(checkIfReady);
|
|
|
|
async function waitUpdate() {
|
|
await TestRunner.addSnifferPromise(Sources.DebuggerPlugin.prototype, '_breakpointDecorationsUpdatedForTest');
|
|
}
|
|
|
|
function checkIfReady() {
|
|
for (const breakpoint of Bindings.breakpointManager._allBreakpoints()) {
|
|
if (breakpoint._fakePrimaryLocation && breakpoint.enabled())
|
|
return waitUpdate().then(checkIfReady);
|
|
}
|
|
|
|
return Promise.resolve();
|
|
}
|
|
};
|
|
|
|
SourcesTestRunner.dumpDebuggerPluginBreakpoints = function(sourceFrame) {
|
|
const textEditor = sourceFrame._textEditor;
|
|
|
|
for (let lineNumber = 0; lineNumber < textEditor.linesCount; ++lineNumber) {
|
|
if (!textEditor.hasLineClass(lineNumber, 'cm-breakpoint'))
|
|
continue;
|
|
|
|
const disabled = textEditor.hasLineClass(lineNumber, 'cm-breakpoint-disabled');
|
|
const conditional = textEditor.hasLineClass(lineNumber, 'cm-breakpoint-conditional');
|
|
TestRunner.addResult(
|
|
'breakpoint at ' + lineNumber + ((disabled ? ' disabled' : '')) + ((conditional ? ' conditional' : '')));
|
|
const range = new TextUtils.TextRange(lineNumber, 0, lineNumber, textEditor.line(lineNumber).length);
|
|
let bookmarks = textEditor.bookmarks(range, Sources.DebuggerPlugin.BreakpointDecoration._bookmarkSymbol);
|
|
bookmarks = bookmarks.filter(bookmark => !!bookmark.position());
|
|
bookmarks.sort((bookmark1, bookmark2) => bookmark1.position().startColumn - bookmark2.position().startColumn);
|
|
|
|
for (const bookmark of bookmarks) {
|
|
const position = bookmark.position();
|
|
const element = bookmark[Sources.DebuggerPlugin.BreakpointDecoration._elementSymbolForTest];
|
|
const disabled = element.classList.contains('cm-inline-disabled');
|
|
const conditional = element.classList.contains('cm-inline-conditional');
|
|
|
|
TestRunner.addResult(
|
|
' inline breakpoint at (' + position.startLine + ', ' + position.startColumn + ')' +
|
|
((disabled ? ' disabled' : '')) + ((conditional ? ' conditional' : '')));
|
|
}
|
|
}
|
|
};
|
|
|
|
SourcesTestRunner.clickDebuggerPluginBreakpoint = function(sourceFrame, lineNumber, index, next) {
|
|
const textEditor = sourceFrame._textEditor;
|
|
const lineLength = textEditor.line(lineNumber).length;
|
|
const lineRange = new TextUtils.TextRange(lineNumber, 0, lineNumber, lineLength);
|
|
const bookmarks = textEditor.bookmarks(lineRange, Sources.DebuggerPlugin.BreakpointDecoration._bookmarkSymbol);
|
|
bookmarks.sort((bookmark1, bookmark2) => bookmark1.position().startColumn - bookmark2.position().startColumn);
|
|
const bookmark = bookmarks[index];
|
|
|
|
if (bookmark) {
|
|
bookmark[Sources.DebuggerPlugin.BreakpointDecoration._elementSymbolForTest].click();
|
|
} else {
|
|
TestRunner.addResult(`Could not click on Javascript breakpoint - lineNumber: ${lineNumber}, index: ${index}`);
|
|
next();
|
|
}
|
|
};
|
|
|
|
SourcesTestRunner.debuggerPlugin = function(sourceFrame) {
|
|
return sourceFrame._plugins.find(plugin => plugin instanceof Sources.DebuggerPlugin);
|
|
};
|
|
|
|
SourcesTestRunner.waitUntilDebuggerPluginLoaded = async function(sourceFrame) {
|
|
while (!SourcesTestRunner.debuggerPlugin(sourceFrame))
|
|
await TestRunner.addSnifferPromise(sourceFrame, '_ensurePluginsLoaded');
|
|
return SourcesTestRunner.debuggerPlugin(sourceFrame);
|
|
};
|
|
|
|
SourcesTestRunner.setEventListenerBreakpoint = function(id, enabled, targetName) {
|
|
const pane = self.runtime.sharedInstance(BrowserDebugger.EventListenerBreakpointsSidebarPane);
|
|
|
|
const auxData = {'eventName': id};
|
|
|
|
if (targetName)
|
|
auxData.targetName = targetName;
|
|
|
|
const breakpoint = SDK.domDebuggerManager.resolveEventListenerBreakpoint(auxData);
|
|
|
|
if (breakpoint.enabled() !== enabled) {
|
|
pane._breakpoints.get(breakpoint).checkbox.checked = enabled;
|
|
pane._breakpointCheckboxClicked(breakpoint);
|
|
}
|
|
};
|
|
|
|
TestRunner.deprecatedInitAsync(`
|
|
function scheduleTestFunction() {
|
|
setTimeout(testFunction, 0);
|
|
}
|
|
`);
|