UNPKG

@dcloudio/uni-debugger

Version:

uni-app debugger

781 lines (616 loc) 27.2 kB
// 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); } `);