diff --git a/devtools/client/webconsole/test/browser/browser_console_error_source_click.js b/devtools/client/webconsole/test/browser/browser_console_error_source_click.js index a34fc63ae3a5..ffe3060841e1 100644 --- a/devtools/client/webconsole/test/browser/browser_console_error_source_click.js +++ b/devtools/client/webconsole/test/browser/browser_console_error_source_click.js @@ -36,10 +36,7 @@ add_task(async function() { }); async function waitForMessageAndViewSource(hud, message) { - const msg = await waitFor( - () => findMessage(hud, message), - `Message "${message}" wasn't found` - ); + const msg = await waitFor(() => findMessage(hud, message)); ok(msg, `Message found: "${message}"`); const locationNode = msg.querySelector( diff --git a/devtools/client/webconsole/test/node/fixtures/stubs/pageError.js b/devtools/client/webconsole/test/node/fixtures/stubs/pageError.js index 75ed1a3fb47b..46c63853a212 100644 --- a/devtools/client/webconsole/test/node/fixtures/stubs/pageError.js +++ b/devtools/client/webconsole/test/node/fixtures/stubs/pageError.js @@ -82,6 +82,7 @@ rawPackets.set(`ReferenceError: asdf is not defined`, { ], "notes": null, "chromeContext": false, + "cssSelectors": "", "isPromiseRejection": false, "isForwardedFromContentProcess": false, "exception": { @@ -163,6 +164,7 @@ rawPackets.set(`SyntaxError: redeclaration of let a`, { } ], "chromeContext": false, + "cssSelectors": "", "isPromiseRejection": false, "isForwardedFromContentProcess": false, "exception": { @@ -248,6 +250,7 @@ rawPackets.set(`TypeError longString message`, { ], "notes": null, "chromeContext": false, + "cssSelectors": "", "isPromiseRejection": false, "isForwardedFromContentProcess": false, "exception": { @@ -333,6 +336,7 @@ rawPackets.set(`throw string with URL`, { ], "notes": null, "chromeContext": false, + "cssSelectors": "", "isPromiseRejection": false, "isForwardedFromContentProcess": false, "exception": "“https://evil.com/?aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa“ is evil and “https://not-so-evil.com/?aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa“ is not good either", @@ -390,6 +394,7 @@ rawPackets.set(`throw ""`, { ], "notes": null, "chromeContext": false, + "cssSelectors": "", "isPromiseRejection": false, "isForwardedFromContentProcess": false, "exception": "", @@ -447,6 +452,7 @@ rawPackets.set(`throw "tomato"`, { ], "notes": null, "chromeContext": false, + "cssSelectors": "", "isPromiseRejection": false, "isForwardedFromContentProcess": false, "exception": "tomato", @@ -504,6 +510,7 @@ rawPackets.set(`throw false`, { ], "notes": null, "chromeContext": false, + "cssSelectors": "", "isPromiseRejection": false, "isForwardedFromContentProcess": false, "exception": false, @@ -561,6 +568,7 @@ rawPackets.set(`throw 0`, { ], "notes": null, "chromeContext": false, + "cssSelectors": "", "isPromiseRejection": false, "isForwardedFromContentProcess": false, "exception": 0, @@ -618,6 +626,7 @@ rawPackets.set(`throw null`, { ], "notes": null, "chromeContext": false, + "cssSelectors": "", "isPromiseRejection": false, "isForwardedFromContentProcess": false, "exception": { @@ -677,6 +686,7 @@ rawPackets.set(`throw undefined`, { ], "notes": null, "chromeContext": false, + "cssSelectors": "", "isPromiseRejection": false, "isForwardedFromContentProcess": false, "exception": { @@ -736,6 +746,7 @@ rawPackets.set(`throw Symbol`, { ], "notes": null, "chromeContext": false, + "cssSelectors": "", "isPromiseRejection": false, "isForwardedFromContentProcess": false, "exception": { @@ -797,6 +808,7 @@ rawPackets.set(`throw Object`, { ], "notes": null, "chromeContext": false, + "cssSelectors": "", "isPromiseRejection": false, "isForwardedFromContentProcess": false, "exception": { @@ -880,6 +892,7 @@ rawPackets.set(`throw Error Object`, { ], "notes": null, "chromeContext": false, + "cssSelectors": "", "isPromiseRejection": false, "isForwardedFromContentProcess": false, "exception": { @@ -957,6 +970,7 @@ rawPackets.set(`throw Error Object with custom name`, { ], "notes": null, "chromeContext": false, + "cssSelectors": "", "isPromiseRejection": false, "isForwardedFromContentProcess": false, "exception": { @@ -1034,6 +1048,7 @@ rawPackets.set(`Promise reject ""`, { ], "notes": null, "chromeContext": false, + "cssSelectors": "", "isPromiseRejection": true, "isForwardedFromContentProcess": false, "exception": "", @@ -1091,6 +1106,7 @@ rawPackets.set(`Promise reject "tomato"`, { ], "notes": null, "chromeContext": false, + "cssSelectors": "", "isPromiseRejection": true, "isForwardedFromContentProcess": false, "exception": "tomato", @@ -1148,6 +1164,7 @@ rawPackets.set(`Promise reject false`, { ], "notes": null, "chromeContext": false, + "cssSelectors": "", "isPromiseRejection": true, "isForwardedFromContentProcess": false, "exception": false, @@ -1205,6 +1222,7 @@ rawPackets.set(`Promise reject 0`, { ], "notes": null, "chromeContext": false, + "cssSelectors": "", "isPromiseRejection": true, "isForwardedFromContentProcess": false, "exception": 0, @@ -1262,6 +1280,7 @@ rawPackets.set(`Promise reject null`, { ], "notes": null, "chromeContext": false, + "cssSelectors": "", "isPromiseRejection": true, "isForwardedFromContentProcess": false, "exception": { @@ -1321,6 +1340,7 @@ rawPackets.set(`Promise reject undefined`, { ], "notes": null, "chromeContext": false, + "cssSelectors": "", "isPromiseRejection": true, "isForwardedFromContentProcess": false, "exception": { @@ -1380,6 +1400,7 @@ rawPackets.set(`Promise reject Symbol`, { ], "notes": null, "chromeContext": false, + "cssSelectors": "", "isPromiseRejection": true, "isForwardedFromContentProcess": false, "exception": { @@ -1441,6 +1462,7 @@ rawPackets.set(`Promise reject Object`, { ], "notes": null, "chromeContext": false, + "cssSelectors": "", "isPromiseRejection": true, "isForwardedFromContentProcess": false, "exception": { @@ -1524,6 +1546,7 @@ rawPackets.set(`Promise reject Error Object`, { ], "notes": null, "chromeContext": false, + "cssSelectors": "", "isPromiseRejection": true, "isForwardedFromContentProcess": false, "exception": { @@ -1601,6 +1624,7 @@ rawPackets.set(`Promise reject Error Object with custom name`, { ], "notes": null, "chromeContext": false, + "cssSelectors": "", "isPromiseRejection": true, "isForwardedFromContentProcess": false, "exception": { diff --git a/devtools/server/actors/descriptors/watcher/watcher.js b/devtools/server/actors/descriptors/watcher/watcher.js index 4a116086c5cb..343803b04e35 100644 --- a/devtools/server/actors/descriptors/watcher/watcher.js +++ b/devtools/server/actors/descriptors/watcher/watcher.js @@ -88,16 +88,13 @@ exports.WatcherActor = protocol.ActorClassWithSpec(watcherSpec, { false ); - const hasBrowserElement = !!this.browserElement; - return { actor: this.actorID, traits: { // FF77+ supports frames in Watcher actor frame: true, resources: { - // FF79+ supports console and platform messages, FF80+ supports error messages, - // but this isn't enabled yet. + // FF79+ supports console messages and platform messages, but this isn't enabled yet. // We will implement a few other resources before enabling it in bug 1642295. // This is to prevent having to handle backward compat if we have to change Watcher // Actor API while implementing other resources. @@ -105,9 +102,7 @@ exports.WatcherActor = protocol.ActorClassWithSpec(watcherSpec, { // content process targets yet. Bug 1620248 should help supporting them and enable // this more broadly. [Resources.TYPES.CONSOLE_MESSAGE]: - enableServerWatcher && hasBrowserElement, - [Resources.TYPES.ERROR_MESSAGE]: - enableServerWatcher && hasBrowserElement, + enableServerWatcher && !!this.browserElement, [Resources.TYPES.PLATFORM_MESSAGE]: enableServerWatcher, }, }, diff --git a/devtools/server/actors/resources/error-messages.js b/devtools/server/actors/resources/error-messages.js deleted file mode 100644 index 74250cb5ff43..000000000000 --- a/devtools/server/actors/resources/error-messages.js +++ /dev/null @@ -1,275 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -"use strict"; - -const { Ci, Cu } = require("chrome"); -const Services = require("Services"); -const ChromeUtils = require("ChromeUtils"); -const { DevToolsServer } = require("devtools/server/devtools-server"); -const ErrorDocs = require("devtools/server/actors/errordocs"); -const { - createStringGrip, - makeDebuggeeValue, - createValueGripForTarget, -} = require("devtools/server/actors/object/utils"); - -const { - getActorIdForInternalSourceId, -} = require("devtools/server/actors/utils/dbg-source"); - -const { - TYPES: { ERROR_MESSAGE }, -} = require("devtools/server/actors/resources/index"); - -class ErrorMessageWatcher { - /** - * Start watching for all error messages related to a given Target Actor. - * This will notify about existing console messages, but also the one created in future. - * - * @param TargetActor targetActor - * The target actor from which we should observe console messages - * @param Object options - * Dictionary object with following attributes: - * - onAvailable: mandatory function - * This will be called for each resource. - */ - constructor(targetActor, { onAvailable }) { - // The following code expects the ThreadActor to be instantiated, via: - // buildPageErrorResource > TabSources.getActorIdForInternalSourceId - // The Thread Actor is instantiated via Target.attach, but we should - // probably review this and only instantiate the actor instead of attaching the target. - targetActor.attach(); - - // Create the consoleListener. - const listener = { - QueryInterface: ChromeUtils.generateQI(["nsIConsoleListener"]), - observe(message) { - if (!shouldHandleMessage(targetActor, message)) { - return; - } - - onAvailable([buildPageErrorResource(targetActor, message)]); - }, - }; - - // Retrieve the cached messages just before registering the listener, so we don't get - // duplicated messages. - const cachedMessages = Services.console.getMessageArray() || []; - Services.console.registerListener(listener); - this.listener = listener; - - // Remove unwanted cache messages and send an array of resources. - const messages = []; - for (const message of cachedMessages) { - if (!shouldHandleMessage(targetActor, message)) { - continue; - } - - messages.push(buildPageErrorResource(targetActor, message)); - } - onAvailable(messages); - } - - /** - * Stop watching for console messages. - */ - destroy() { - if (this.listener) { - Services.console.unregisterListener(this.listener); - } - } -} -module.exports = ErrorMessageWatcher; - -/** - * Returns true if the message is considered an error message, and as a result, should - * be sent to the client. - * - * @param {nsIConsoleMessage|nsIScriptError} message - */ -function shouldHandleMessage(targetActor, message) { - // The listener we use can be called either with a nsIConsoleMessage or a nsIScriptError. - // In this file, we only want to handle nsIScriptError. - if ( - // We only care about nsIScriptError - !(message instanceof Ci.nsIScriptError) || - !isCategoryAllowed(targetActor, message.category) || - // Block any error that was triggered by eager evaluation - message.sourceName === "debugger eager eval code" || - // In Process targets don't include messages from private window - (isProcessTarget(targetActor) && message.isFromPrivateWindow) - ) { - return false; - } - - // Process targets listen for everything - if (isProcessTarget(targetActor)) { - return true; - } - - if (!message.innerWindowID) { - return false; - } - - const { window } = targetActor.window; - const win = window?.WindowGlobalChild?.getByInnerWindowId( - message.innerWindowID - ); - return targetActor.browserId === win?.browsingContext?.browserId; -} - -const PLATFORM_SPECIFIC_CATEGORIES = [ - "XPConnect JavaScript", - "component javascript", - "chrome javascript", - "chrome registration", -]; - -/** - * Check if the given message category is allowed to be tracked or not. - * We ignore chrome-originating errors as we only care about content. - * - * @param string category - * The message category you want to check. - * @return boolean - * True if the category is allowed to be logged, false otherwise. - */ -function isCategoryAllowed(targetActor, category) { - // CSS Parser errors will be handled by the CSSMessageWatcher. - if (!category || category === "CSS Parser") { - return false; - } - - // We listen for everything on Process targets - if (isProcessTarget(targetActor)) { - return true; - } - - // For non-process targets, we filter-out platform-specific errors. - return !PLATFORM_SPECIFIC_CATEGORIES.includes(category); -} - -function isProcessTarget(targetActor) { - const { typeName } = targetActor; - return ( - typeName === "parentProcessTarget" || typeName === "contentProcessTarget" - ); -} - -/** - * Prepare an nsIScriptError to be sent to the client. - * - * @param nsIScriptError error - * The page error we need to send to the client. - * @return object - * The object you can send to the remote client. - */ -function buildPageErrorResource(targetActor, error) { - const stack = prepareStackForRemote(targetActor, error.stack); - let lineText = error.sourceLine; - if (lineText && lineText.length > DevToolsServer.LONG_STRING_INITIAL_LENGTH) { - lineText = lineText.substr(0, DevToolsServer.LONG_STRING_INITIAL_LENGTH); - } - - let notesArray = null; - const notes = error.notes; - if (notes?.length) { - notesArray = []; - for (let i = 0, len = notes.length; i < len; i++) { - const note = notes.queryElementAt(i, Ci.nsIScriptErrorNote); - notesArray.push({ - messageBody: createStringGrip(targetActor, note.errorMessage), - frame: { - source: note.sourceName, - sourceId: getActorIdForInternalSourceId(targetActor, note.sourceId), - line: note.lineNumber, - column: note.columnNumber, - }, - }); - } - } - - // If there is no location information in the error but we have a stack, - // fill in the location with the first frame on the stack. - let { sourceName, sourceId, lineNumber, columnNumber } = error; - if (!sourceName && !sourceId && !lineNumber && !columnNumber && stack) { - sourceName = stack[0].filename; - sourceId = stack[0].sourceId; - lineNumber = stack[0].lineNumber; - columnNumber = stack[0].columnNumber; - } - - const pageError = { - errorMessage: createStringGrip(targetActor, error.errorMessage), - errorMessageName: error.errorMessageName, - exceptionDocURL: ErrorDocs.GetURL(error), - sourceName, - sourceId: getActorIdForInternalSourceId(targetActor, sourceId), - lineText, - lineNumber, - columnNumber, - category: error.category, - innerWindowID: error.innerWindowID, - timeStamp: error.timeStamp, - warning: !!(error.flags & error.warningFlag), - error: !(error.flags & (error.warningFlag | error.infoFlag)), - info: !!(error.flags & error.infoFlag), - private: error.isFromPrivateWindow, - stacktrace: stack, - notes: notesArray, - chromeContext: error.isFromChromeContext, - isPromiseRejection: error.isPromiseRejection, - isForwardedFromContentProcess: error.isForwardedFromContentProcess, - }; - - // If the pageError does have an exception object, we want to return the grip for it, - // but only if we do manage to get the grip, as we're checking the property on the - // client to render things differently. - if (error.hasException) { - try { - const obj = makeDebuggeeValue(targetActor, error.exception); - if (obj?.class !== "DeadObject") { - pageError.exception = createValueGripForTarget(targetActor, obj); - pageError.hasException = true; - } - } catch (e) {} - } - - return { - pageError, - resourceType: ERROR_MESSAGE, - }; -} - -/** - * Prepare a SavedFrame stack to be sent to the client. - * - * @param SavedFrame errorStack - * Stack for an error we need to send to the client. - * @return object - * The object you can send to the remote client. - */ -function prepareStackForRemote(targetActor, errorStack) { - // Convert stack objects to the JSON attributes expected by client code - // Bug 1348885: If the global from which this error came from has been - // nuked, stack is going to be a dead wrapper. - if (!errorStack || (Cu && Cu.isDeadWrapper(errorStack))) { - return null; - } - const stack = []; - let s = errorStack; - while (s) { - stack.push({ - filename: s.source, - sourceId: getActorIdForInternalSourceId(targetActor, s.sourceId), - lineNumber: s.line, - columnNumber: s.column, - functionName: s.functionDisplayName, - asyncCause: s.asyncCause ? s.asyncCause : undefined, - }); - s = s.parent || s.asyncParent; - } - return stack; -} diff --git a/devtools/server/actors/resources/index.js b/devtools/server/actors/resources/index.js index f19b98a7b86c..fe4abb6b7a6c 100644 --- a/devtools/server/actors/resources/index.js +++ b/devtools/server/actors/resources/index.js @@ -6,7 +6,6 @@ const TYPES = { CONSOLE_MESSAGE: "console-message", - ERROR_MESSAGE: "error-message", PLATFORM_MESSAGE: "platform-message", }; exports.TYPES = TYPES; @@ -25,9 +24,6 @@ const Resources = { [TYPES.CONSOLE_MESSAGE]: { path: "devtools/server/actors/resources/console-messages", }, - [TYPES.ERROR_MESSAGE]: { - path: "devtools/server/actors/resources/error-messages", - }, [TYPES.PLATFORM_MESSAGE]: { path: "devtools/server/actors/resources/platform-messages", }, diff --git a/devtools/server/actors/resources/moz.build b/devtools/server/actors/resources/moz.build index 5bf8276a06d7..b08ee66beaae 100644 --- a/devtools/server/actors/resources/moz.build +++ b/devtools/server/actors/resources/moz.build @@ -6,7 +6,6 @@ DevToolsModules( 'console-messages.js', - 'error-messages.js', 'index.js', 'platform-messages.js', ) diff --git a/devtools/server/actors/resources/platform-messages.js b/devtools/server/actors/resources/platform-messages.js index 2bd0136dd9b3..3b52cd5fa18f 100644 --- a/devtools/server/actors/resources/platform-messages.js +++ b/devtools/server/actors/resources/platform-messages.js @@ -17,7 +17,7 @@ const { LongStringActor } = require("devtools/server/actors/string"); class PlatformMessageWatcher { /** - * Start watching for all platform messages related to a given Target Actor. + * Start watching for all console messages related to a given Target Actor. * This will notify about existing console messages, but also the one created in future. * * @param TargetActor targetActor diff --git a/devtools/shared/resources/resource-watcher.js b/devtools/shared/resources/resource-watcher.js index 135b4c54a379..3377d1d47ba5 100644 --- a/devtools/shared/resources/resource-watcher.js +++ b/devtools/shared/resources/resource-watcher.js @@ -503,6 +503,4 @@ const LegacyListeners = { const ResourceTransformers = { [ResourceWatcher.TYPES .CONSOLE_MESSAGE]: require("devtools/shared/resources/transformers/console-messages"), - [ResourceWatcher.TYPES - .ERROR_MESSAGE]: require("devtools/shared/resources/transformers/error-messages"), }; diff --git a/devtools/shared/resources/tests/browser_resources_console_messages.js b/devtools/shared/resources/tests/browser_resources_console_messages.js index 85231990961c..144a8f13368f 100644 --- a/devtools/shared/resources/tests/browser_resources_console_messages.js +++ b/devtools/shared/resources/tests/browser_resources_console_messages.js @@ -154,43 +154,26 @@ function logExistingMessages(browser) { content.console.warn("foobarBaz-warn", content.document.body); }); } - -const NUMBER_REGEX = /^\d+$/; - -const defaultStackFrames = [ - { - filename: "resource://testing-common/content-task.js", - lineNumber: NUMBER_REGEX, - columnNumber: NUMBER_REGEX, - }, - { - filename: "resource://testing-common/content-task.js", - lineNumber: NUMBER_REGEX, - columnNumber: NUMBER_REGEX, - asyncCause: "MessageListener.receiveMessage", - }, -]; - const expectedExistingConsoleCalls = [ { level: "log", filename: EXPECTED_FILENAME, functionName: EXPECTED_FUNCTION_NAME, - timeStamp: NUMBER_REGEX, + timeStamp: /^\d+$/, arguments: ["foobarBaz-log", { type: "undefined" }], }, { level: "info", filename: EXPECTED_FILENAME, functionName: EXPECTED_FUNCTION_NAME, - timeStamp: NUMBER_REGEX, + timeStamp: /^\d+$/, arguments: ["foobarBaz-info", { type: "null" }], }, { level: "warn", filename: EXPECTED_FILENAME, functionName: EXPECTED_FUNCTION_NAME, - timeStamp: NUMBER_REGEX, + timeStamp: /^\d+$/, arguments: ["foobarBaz-warn", { type: "object", actor: /[a-z]/ }], }, ]; @@ -201,7 +184,7 @@ const expectedRuntimeConsoleCalls = [ level: "log", filename: EXPECTED_FILENAME, functionName: EXPECTED_FUNCTION_NAME, - timeStamp: NUMBER_REGEX, + timeStamp: /^\d+$/, arguments: ["foobarBaz-log", { type: "undefined" }], }, { @@ -220,41 +203,40 @@ const expectedRuntimeConsoleCalls = [ level: "info", filename: EXPECTED_FILENAME, functionName: EXPECTED_FUNCTION_NAME, - timeStamp: NUMBER_REGEX, + timeStamp: /^\d+$/, arguments: ["foobarBaz-info", { type: "null" }], }, { level: "warn", filename: EXPECTED_FILENAME, functionName: EXPECTED_FUNCTION_NAME, - timeStamp: NUMBER_REGEX, + timeStamp: /^\d+$/, arguments: ["foobarBaz-warn", { type: "object", actor: /[a-z]/ }], }, { level: "debug", filename: EXPECTED_FILENAME, functionName: EXPECTED_FUNCTION_NAME, - timeStamp: NUMBER_REGEX, + timeStamp: /^\d+$/, arguments: [{ type: "null" }], }, { level: "trace", filename: EXPECTED_FILENAME, functionName: EXPECTED_FUNCTION_NAME, - timeStamp: NUMBER_REGEX, + timeStamp: /^\d+$/, stacktrace: [ { filename: EXPECTED_FILENAME, functionName: EXPECTED_FUNCTION_NAME, }, - ...defaultStackFrames, ], }, { level: "dir", filename: EXPECTED_FILENAME, functionName: EXPECTED_FUNCTION_NAME, - timeStamp: NUMBER_REGEX, + timeStamp: /^\d+$/, arguments: [ { type: "object", @@ -272,7 +254,7 @@ const expectedRuntimeConsoleCalls = [ level: "log", filename: EXPECTED_FILENAME, functionName: EXPECTED_FUNCTION_NAME, - timeStamp: NUMBER_REGEX, + timeStamp: /^\d+$/, arguments: [ "foo", { @@ -290,7 +272,7 @@ const expectedRuntimeConsoleCalls = [ level: "log", filename: EXPECTED_FILENAME, functionName: EXPECTED_FUNCTION_NAME, - timeStamp: NUMBER_REGEX, + timeStamp: /^\d+$/, arguments: [ { type: "object", @@ -303,7 +285,7 @@ const expectedRuntimeConsoleCalls = [ level: "error", filename: EXPECTED_FILENAME, functionName: "fromAsmJS", - timeStamp: NUMBER_REGEX, + timeStamp: /^\d+$/, arguments: ["foobarBaz-asmjs-error", { type: "undefined" }], stacktrace: [ @@ -323,7 +305,6 @@ const expectedRuntimeConsoleCalls = [ filename: EXPECTED_FILENAME, functionName: EXPECTED_FUNCTION_NAME, }, - ...defaultStackFrames, ], }, ]; diff --git a/devtools/shared/resources/tests/browser_resources_error_messages.js b/devtools/shared/resources/tests/browser_resources_error_messages.js index 65fca0deb271..299a846f5da1 100644 --- a/devtools/shared/resources/tests/browser_resources_error_messages.js +++ b/devtools/shared/resources/tests/browser_resources_error_messages.js @@ -24,18 +24,6 @@ add_task(async function() { // which forces the emission of RDP requests we aren't correctly waiting for. await pushPref("dom.ipc.processPrelaunch.enabled", false); - info("Test error messages legacy listener"); - await testErrorMessagesResources(); - await testErrorMessagesResourcesWithIgnoreExistingResources(); - - info("Test error messages server listener"); - await pushPref("devtools.testing.enableServerWatcherSupport", true); - await testErrorMessagesResources(); - await testErrorMessagesResourcesWithIgnoreExistingResources(); - await pushPref("devtools.testing.enableServerWatcherSupport", false); -}); - -async function testErrorMessagesResources() { // Open a test tab const tab = await addTab(TEST_URI); @@ -105,10 +93,15 @@ async function testErrorMessagesResources() { Services.console.reset(); targetList.stopListening(); await client.close(); -} +}); -async function testErrorMessagesResourcesWithIgnoreExistingResources() { +add_task(async function() { info("Test ignoreExistingResources option for ERROR_MESSAGE"); + + // Disable the preloaded process as it creates processes intermittently + // which forces the emission of RDP requests we aren't correctly waiting for. + await pushPref("dom.ipc.processPrelaunch.enabled", false); + const tab = await addTab(TEST_URI); const { @@ -149,7 +142,7 @@ async function testErrorMessagesResourcesWithIgnoreExistingResources() { Services.console.reset(); await targetList.stopListening(); await client.close(); -} +}); /** * Triggers all the errors in the content page. @@ -181,31 +174,6 @@ async function triggerErrors(tab) { } const noUncaughtException = Symbol(); -const NUMBER_REGEX = /^\d+$/; - -const mdnUrl = path => - `https://developer.mozilla.org/${path}?utm_source=mozilla&utm_medium=firefox-console-errors&utm_campaign=default`; -const defaultStackFrames = [ - { - filename: /resource:\/\/testing-common\/content-task.js/, - lineNumber: NUMBER_REGEX, - columnNumber: NUMBER_REGEX, - functionName: "frameScript", - }, - { - filename: "resource://testing-common/content-task.js", - lineNumber: NUMBER_REGEX, - columnNumber: NUMBER_REGEX, - functionName: null, - }, - { - filename: "resource://testing-common/content-task.js", - lineNumber: NUMBER_REGEX, - columnNumber: NUMBER_REGEX, - functionName: null, - asyncCause: "MessageListener.receiveMessage", - }, -]; const expectedPageErrors = new Map([ [ @@ -215,33 +183,9 @@ const expectedPageErrors = new Map([ errorMessageName: undefined, sourceName: /test_page_errors/, category: "content javascript", - timeStamp: NUMBER_REGEX, + timeStamp: /^\d+$/, error: true, warning: false, - info: false, - sourceId: null, - lineText: "", - lineNumber: NUMBER_REGEX, - columnNumber: NUMBER_REGEX, - exceptionDocURL: mdnUrl( - "docs/Web/JavaScript/Reference/Errors/Not_a_function" - ), - innerWindowID: NUMBER_REGEX, - private: false, - stacktrace: [ - { - filename: /test_page_errors\.html/, - sourceId: null, - lineNumber: 1, - columnNumber: 10, - functionName: null, - }, - ...defaultStackFrames, - ], - notes: null, - chromeContext: false, - isPromiseRejection: false, - isForwardedFromContentProcess: false, }, ], [ @@ -251,31 +195,9 @@ const expectedPageErrors = new Map([ errorMessageName: "JSMSG_BAD_RADIX", sourceName: /test_page_errors/, category: "content javascript", - timeStamp: NUMBER_REGEX, + timeStamp: /^\d+$/, error: true, warning: false, - info: false, - sourceId: null, - lineText: "", - lineNumber: NUMBER_REGEX, - columnNumber: NUMBER_REGEX, - exceptionDocURL: mdnUrl("docs/Web/JavaScript/Reference/Errors/Bad_radix"), - innerWindowID: NUMBER_REGEX, - private: false, - stacktrace: [ - { - filename: /test_page_errors\.html/, - sourceId: null, - lineNumber: 1, - columnNumber: 6, - functionName: null, - }, - ...defaultStackFrames, - ], - notes: null, - chromeContext: false, - isPromiseRejection: false, - isForwardedFromContentProcess: false, }, ], [ @@ -285,31 +207,9 @@ const expectedPageErrors = new Map([ errorMessageName: "JSMSG_READ_ONLY", sourceName: /test_page_errors/, category: "content javascript", - timeStamp: NUMBER_REGEX, + timeStamp: /^\d+$/, error: true, warning: false, - info: false, - sourceId: null, - lineText: "", - lineNumber: NUMBER_REGEX, - columnNumber: NUMBER_REGEX, - exceptionDocURL: mdnUrl("docs/Web/JavaScript/Reference/Errors/Read-only"), - innerWindowID: NUMBER_REGEX, - private: false, - stacktrace: [ - { - filename: /test_page_errors\.html/, - sourceId: null, - lineNumber: 1, - columnNumber: 23, - functionName: null, - }, - ...defaultStackFrames, - ], - notes: null, - chromeContext: false, - isPromiseRejection: false, - isForwardedFromContentProcess: false, }, ], [ @@ -319,33 +219,9 @@ const expectedPageErrors = new Map([ errorMessageName: "JSMSG_BAD_ARRAY_LENGTH", sourceName: /test_page_errors/, category: "content javascript", - timeStamp: NUMBER_REGEX, + timeStamp: /^\d+$/, error: true, warning: false, - info: false, - sourceId: null, - lineText: "", - lineNumber: NUMBER_REGEX, - columnNumber: NUMBER_REGEX, - exceptionDocURL: mdnUrl( - "docs/Web/JavaScript/Reference/Errors/Invalid_array_length" - ), - innerWindowID: NUMBER_REGEX, - private: false, - stacktrace: [ - { - filename: /test_page_errors\.html/, - sourceId: null, - lineNumber: 1, - columnNumber: 2, - functionName: null, - }, - ...defaultStackFrames, - ], - notes: null, - chromeContext: false, - isPromiseRejection: false, - isForwardedFromContentProcess: false, }, ], [ @@ -355,40 +231,9 @@ const expectedPageErrors = new Map([ errorMessageName: "JSMSG_NEGATIVE_REPETITION_COUNT", sourceName: /test_page_errors/, category: "content javascript", - timeStamp: NUMBER_REGEX, + timeStamp: /^\d+$/, error: true, warning: false, - info: false, - sourceId: null, - lineText: "", - lineNumber: NUMBER_REGEX, - columnNumber: NUMBER_REGEX, - exceptionDocURL: mdnUrl( - "docs/Web/JavaScript/Reference/Errors/Negative_repetition_count" - ), - innerWindowID: NUMBER_REGEX, - private: false, - stacktrace: [ - { - filename: "self-hosted", - sourceId: null, - lineNumber: NUMBER_REGEX, - columnNumber: 1, - functionName: "repeat", - }, - { - filename: /test_page_errors\.html/, - sourceId: null, - lineNumber: 1, - columnNumber: 7, - functionName: null, - }, - ...defaultStackFrames, - ], - notes: null, - chromeContext: false, - isPromiseRejection: false, - isForwardedFromContentProcess: false, }, ], [ @@ -398,40 +243,9 @@ const expectedPageErrors = new Map([ errorMessageName: "JSMSG_RESULTING_STRING_TOO_LARGE", sourceName: /test_page_errors/, category: "content javascript", - timeStamp: NUMBER_REGEX, + timeStamp: /^\d+$/, error: true, warning: false, - info: false, - sourceId: null, - lineText: "", - lineNumber: NUMBER_REGEX, - columnNumber: NUMBER_REGEX, - exceptionDocURL: mdnUrl( - "docs/Web/JavaScript/Reference/Errors/Resulting_string_too_large" - ), - innerWindowID: NUMBER_REGEX, - private: false, - stacktrace: [ - { - filename: "self-hosted", - sourceId: null, - lineNumber: NUMBER_REGEX, - columnNumber: 1, - functionName: "repeat", - }, - { - filename: /test_page_errors\.html/, - sourceId: null, - lineNumber: 1, - columnNumber: 5, - functionName: null, - }, - ...defaultStackFrames, - ], - notes: null, - chromeContext: false, - isPromiseRejection: false, - isForwardedFromContentProcess: false, }, ], [ @@ -441,33 +255,9 @@ const expectedPageErrors = new Map([ errorMessageName: "JSMSG_PRECISION_RANGE", sourceName: /test_page_errors/, category: "content javascript", - timeStamp: NUMBER_REGEX, + timeStamp: /^\d+$/, error: true, warning: false, - info: false, - sourceId: null, - lineText: "", - lineNumber: NUMBER_REGEX, - columnNumber: NUMBER_REGEX, - exceptionDocURL: mdnUrl( - "docs/Web/JavaScript/Reference/Errors/Precision_range" - ), - innerWindowID: NUMBER_REGEX, - private: false, - stacktrace: [ - { - filename: /test_page_errors\.html/, - sourceId: null, - lineNumber: 1, - columnNumber: 9, - functionName: null, - }, - ...defaultStackFrames, - ], - notes: null, - chromeContext: false, - isPromiseRejection: false, - isForwardedFromContentProcess: false, }, ], [ @@ -477,24 +267,9 @@ const expectedPageErrors = new Map([ errorMessageName: "JSMSG_STMT_AFTER_RETURN", sourceName: /test_page_errors/, category: "content javascript", - timeStamp: NUMBER_REGEX, + timeStamp: /^\d+$/, error: false, warning: true, - info: false, - sourceId: null, - lineText: "function a() { return; 1 + 1; }", - lineNumber: NUMBER_REGEX, - columnNumber: NUMBER_REGEX, - exceptionDocURL: mdnUrl( - "docs/Web/JavaScript/Reference/Errors/Stmt_after_return" - ), - innerWindowID: NUMBER_REGEX, - private: false, - stacktrace: null, - notes: null, - chromeContext: false, - isPromiseRejection: false, - isForwardedFromContentProcess: false, }, ], [ @@ -504,23 +279,9 @@ const expectedPageErrors = new Map([ errorMessageName: "JSMSG_REDECLARED_VAR", sourceName: /test_page_errors/, category: "content javascript", - timeStamp: NUMBER_REGEX, + timeStamp: /^\d+$/, error: true, warning: false, - info: false, - sourceId: null, - lineText: "{let a, a;}", - lineNumber: NUMBER_REGEX, - columnNumber: NUMBER_REGEX, - exceptionDocURL: mdnUrl( - "docs/Web/JavaScript/Reference/Errors/Redeclared_parameter" - ), - innerWindowID: NUMBER_REGEX, - private: false, - stacktrace: defaultStackFrames, - chromeContext: false, - isPromiseRejection: false, - isForwardedFromContentProcess: false, notes: [ { messageBody: /Previously declared at line/, @@ -541,31 +302,9 @@ const expectedPageErrors = new Map([ errorMessageName: "", sourceName: /test_page_errors/, category: "content javascript", - timeStamp: NUMBER_REGEX, + timeStamp: /^\d+$/, error: true, warning: false, - info: false, - sourceId: null, - lineText: "", - lineNumber: NUMBER_REGEX, - columnNumber: NUMBER_REGEX, - exceptionDocURL: mdnUrl("docs/Web/JavaScript/Reference/Errors/Read-only"), - innerWindowID: NUMBER_REGEX, - private: false, - stacktrace: [ - { - filename: /test_page_errors\.html/, - sourceId: null, - lineNumber: 1, - columnNumber: 13, - functionName: null, - }, - ...defaultStackFrames, - ], - notes: null, - chromeContext: false, - isPromiseRejection: false, - isForwardedFromContentProcess: false, }, ], [ @@ -575,79 +314,24 @@ const expectedPageErrors = new Map([ errorMessageName: "MSG_METHOD_THIS_DOES_NOT_IMPLEMENT_INTERFACE", sourceName: /test_page_errors/, category: "content javascript", - timeStamp: NUMBER_REGEX, + timeStamp: /^\d+$/, error: true, warning: false, - info: false, - sourceId: null, - lineText: "", - lineNumber: NUMBER_REGEX, - columnNumber: NUMBER_REGEX, - exceptionDocURL: mdnUrl("docs/Web/JavaScript/Reference/Errors/Read-only"), - innerWindowID: NUMBER_REGEX, - private: false, - stacktrace: [ - { - filename: /test_page_errors\.html/, - sourceId: null, - lineNumber: 1, - columnNumber: 33, - functionName: null, - }, - ...defaultStackFrames, - ], - notes: null, - chromeContext: false, - isPromiseRejection: false, - isForwardedFromContentProcess: false, }, ], [ - ` - function promiseThrow() { - var error2 = new TypeError("abc"); - error2.name = "MyPromiseError"; - error2.message = "here2"; - return Promise.reject(error2); - } - promiseThrow()`, + `var error2 = new TypeError("abc"); + error2.name = "MyPromiseError"; + error2.message = "here2"; + Promise.reject(error2)`, { errorMessage: /MyPromiseError: here2/, errorMessageName: "", sourceName: /test_page_errors/, category: "content javascript", - timeStamp: NUMBER_REGEX, + timeStamp: /^\d+$/, error: true, warning: false, - info: false, - sourceId: null, - lineText: "", - lineNumber: NUMBER_REGEX, - columnNumber: NUMBER_REGEX, - exceptionDocURL: mdnUrl("docs/Web/JavaScript/Reference/Errors/Read-only"), - innerWindowID: NUMBER_REGEX, - private: false, - stacktrace: [ - { - filename: /test_page_errors\.html/, - sourceId: null, - lineNumber: 6, - columnNumber: 24, - functionName: "promiseThrow", - }, - { - filename: /test_page_errors\.html/, - sourceId: null, - lineNumber: 8, - columnNumber: 7, - functionName: null, - }, - ...defaultStackFrames, - ], - notes: null, - chromeContext: false, - isPromiseRejection: true, - isForwardedFromContentProcess: false, [noUncaughtException]: true, }, ], diff --git a/devtools/shared/resources/tests/head.js b/devtools/shared/resources/tests/head.js index 9cced7af0daf..c1db7cffd286 100644 --- a/devtools/shared/resources/tests/head.js +++ b/devtools/shared/resources/tests/head.js @@ -69,11 +69,11 @@ function checkObject(object, expected) { function checkValue(name, value, expected) { if (expected === null) { - is(value, null, `'${name}' is null`); + ok(!value, "'" + name + "' is null"); } else if (value === undefined) { - is(value, undefined, `'${name}' is undefined`); + ok(false, "'" + name + "' is undefined"); } else if (value === null) { - is(value, expected, `'${name}' has expected value`); + ok(false, "'" + name + "' is null"); } else if ( typeof expected == "string" || typeof expected == "number" || @@ -84,14 +84,7 @@ function checkValue(name, value, expected) { ok(expected.test(value), name + ": " + expected + " matched " + value); } else if (Array.isArray(expected)) { info("checking array for property '" + name + "'"); - ok(Array.isArray(value), `property '${name}' is an array`); - - is(value.length, expected.length, "Array has expected length"); - if (value.length !== expected.length) { - is(JSON.stringify(value, null, 2), JSON.stringify(expected, null, 2)); - } else { - checkObject(value, expected); - } + checkObject(value, expected); } else if (typeof expected == "object") { info("checking object for property '" + name + "'"); checkObject(value, expected); diff --git a/devtools/shared/resources/transformers/error-messages.js b/devtools/shared/resources/transformers/error-messages.js deleted file mode 100644 index 8d6e2b821e7b..000000000000 --- a/devtools/shared/resources/transformers/error-messages.js +++ /dev/null @@ -1,31 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ - -"use strict"; - -// eslint-disable-next-line mozilla/reject-some-requires -loader.lazyRequireGetter( - this, - "getAdHocFrontOrPrimitiveGrip", - "devtools/client/fronts/object", - true -); - -module.exports = function({ resource, targetFront }) { - if (resource?.pageError?.errorMessage) { - resource.pageError.errorMessage = getAdHocFrontOrPrimitiveGrip( - resource.pageError.errorMessage, - targetFront - ); - } - - if (resource?.pageError?.exception) { - resource.pageError.exception = getAdHocFrontOrPrimitiveGrip( - resource.pageError.exception, - targetFront - ); - } - - return resource; -}; diff --git a/devtools/shared/resources/transformers/moz.build b/devtools/shared/resources/transformers/moz.build index 4e835bf376d5..7761df34b483 100644 --- a/devtools/shared/resources/transformers/moz.build +++ b/devtools/shared/resources/transformers/moz.build @@ -3,6 +3,5 @@ # file, You can obtain one at http://mozilla.org/MPL/2.0/. DevToolsModules( - 'console-messages.js', - 'error-messages.js', + 'console-messages.js' )