From 4fe1cbf23e29406837ed968cbcd4f0bdf8a69aa2 Mon Sep 17 00:00:00 2001 From: Nicolas Chevobbe Date: Fri, 23 May 2025 14:35:15 +0000 Subject: [PATCH] Bug 1967673 - [devtools] Don't omit valid safe getter undefined values in _findSafeGetterValues. r=devtools-reviewers,jdescottes Differential Revision: https://phabricator.services.mozilla.com/D250613 --- .../webconsole/test/browser/_webconsole.toml | 2 + .../browser_webconsole_previewers_https.js | 56 +++++++++++++++++++ devtools/server/actors/object.js | 8 ++- .../tests/objects/AllJavascriptTypes.mjs | 4 +- 4 files changed, 65 insertions(+), 5 deletions(-) create mode 100644 devtools/client/webconsole/test/browser/browser_webconsole_previewers_https.js diff --git a/devtools/client/webconsole/test/browser/_webconsole.toml b/devtools/client/webconsole/test/browser/_webconsole.toml index 649706df7377..9ee0a08b7e79 100644 --- a/devtools/client/webconsole/test/browser/_webconsole.toml +++ b/devtools/client/webconsole/test/browser/_webconsole.toml @@ -588,6 +588,8 @@ fail-if = ["a11y_checks"] # Bug 1849028 clicked element may not be focusable and ["browser_webconsole_persist.js"] skip-if = ["os == 'linux' && os_version == '18.04' && processor == 'x86_64' && debug && http3"] # Bug 1829298 +["browser_webconsole_previewers_https.js"] + ["browser_webconsole_previewers.js"] support-files = ["browser_webconsole_previewers.snapshot.mjs"] https_first_disabled = true # JS HttpServer doesn't support https diff --git a/devtools/client/webconsole/test/browser/browser_webconsole_previewers_https.js b/devtools/client/webconsole/test/browser/browser_webconsole_previewers_https.js new file mode 100644 index 000000000000..471aab6f2baf --- /dev/null +++ b/devtools/client/webconsole/test/browser/browser_webconsole_previewers_https.js @@ -0,0 +1,56 @@ +/* Any copyright is dedicated to the Public Domain. + * http://creativecommons.org/publicdomain/zero/1.0/ */ + +"use strict"; + +// Those cases should be added into AllJavascriptTypes.mjs (so they can be consumed in +// browser_webconsole_previewers.js) when Bug 1967917 is resolved (so we can have a secure context) + +add_task(async function () { + const hud = await openNewTabAndConsole(URL_ROOT_COM_SSL + "test-blank.html"); + + SpecialPowers.spawn(gBrowser.selectedBrowser, [], function () { + const openReq = content.indexedDB.open("idb-bug-demo", 1); + openReq.onupgradeneeded = e => { + e.target.result.createObjectStore("demo", { + keyPath: "id", + }); + }; + openReq.onsuccess = e => { + const db = e.target.result; + const store = db.transaction(["demo"], "readonly").objectStore("demo"); + + const idbRequest = store.get("unknown"); + idbRequest.onsuccess = () => { + content.console.log(idbRequest); + db.close(); + }; + }; + }); + + const message = await waitForMessageByType(hud, "IDBRequest", ".console-api"); + is( + message.node.querySelector(".message-body").innerText.trim(), + 'IDBRequest { result: undefined, error: null, source: IDBObjectStore, transaction: IDBTransaction, readyState: "done", onsuccess: Restricted, onerror: null }', + "Got expected IDBRequest object, with undefined result property" + ); + + const oi = message.node.querySelector(".tree"); + // Expand the root node + await expandObjectInspectorNode(oi.querySelector(".tree-node")); + const resultPropertyTreeItemEl = Array.from( + oi.querySelectorAll(".object-node") + ).find(el => el.querySelector(".object-label")?.innerText === "result"); + is( + resultPropertyTreeItemEl.innerText, + "result: undefined", + "Got expected result property in the object inspector for the IDBRequest" + ); + + // This can't be placed in a registerCleanupFunction because it throws (The operation is insecure) + await SpecialPowers.spawn(gBrowser.selectedBrowser, [], async function () { + const { promise, resolve } = content.Promise.withResolvers(); + content.indexedDB.deleteDatabase("idb-bug-demo").onsuccess = resolve; + await promise; + }); +}); diff --git a/devtools/server/actors/object.js b/devtools/server/actors/object.js index 0cf14d017be5..5dc6709719e4 100644 --- a/devtools/server/actors/object.js +++ b/devtools/server/actors/object.js @@ -478,7 +478,7 @@ class ObjectActor extends Actor { } const getterValue = this._evaluateGetter(desc.get); - if (getterValue === undefined) { + if (getterValue === this._evaluateGetterNoResult) { continue; } @@ -516,6 +516,8 @@ class ObjectActor extends Actor { return safeGetterValues; } + _evaluateGetterNoResult = Symbol(); + /** * Evaluate the getter function |desc.get|. * @param {Object} getter @@ -523,10 +525,10 @@ class ObjectActor extends Actor { _evaluateGetter(getter) { const result = getter.call(this.obj); if (!result || "throw" in result) { - return undefined; + return this._evaluateGetterNoResult; } - let getterValue = undefined; + let getterValue = this._evaluateGetterNoResult; if ("return" in result) { getterValue = result.return; } else if ("yield" in result) { diff --git a/devtools/shared/tests/objects/AllJavascriptTypes.mjs b/devtools/shared/tests/objects/AllJavascriptTypes.mjs index 88935c6d03c3..4fb5d7b2fa92 100644 --- a/devtools/shared/tests/objects/AllJavascriptTypes.mjs +++ b/devtools/shared/tests/objects/AllJavascriptTypes.mjs @@ -227,7 +227,7 @@ const DOMAPIs = [ expression: `myPolicy.createHTML("hello")`, prefs: [["dom.security.trusted_types.enabled", true]], }, - { + { context: CONTEXTS.PAGE, expression: `myPolicy.createScript("const hello = 'world'")` }, @@ -246,7 +246,7 @@ const DOMAPIs = [ formData; `, }, - /* midi API requires https + /* midi API requires https (See Bug 1967917) { context: CONTEXTS.PAGE, expression: `