author | Csoregi Natalia <ncsoregi@mozilla.com> |
Wed, 07 Nov 2018 11:52:57 +0200 | |
changeset 501234 | 070757a0160c8e6156cf6d8d567a0af280dc33e8 |
parent 501205 | bc83ec5a338dd6070dc14d6f08efd208fc1c69b0 (current diff) |
parent 501233 | 274f95b85267d07ae0d2eceb95c683dda098ce82 (diff) |
child 501248 | 4de987e47323c74954cef79540e5a0bbe887c232 |
child 501278 | 64e32a13c4826d10460564ee555cf8e956a7891d |
push id | 10290 |
push user | ffxbld-merge |
push date | Mon, 03 Dec 2018 16:23:23 +0000 |
treeherder | mozilla-beta@700bed2445e6 [default view] [failures only] |
perfherder | [talos] [build metrics] [platform microbench] (compared to previous push) |
reviewers | merge |
milestone | 65.0a1 |
first release with | nightly linux32
070757a0160c
/
65.0a1
/
20181107100135
/
files
nightly linux64
070757a0160c
/
65.0a1
/
20181107100135
/
files
nightly mac
070757a0160c
/
65.0a1
/
20181107100135
/
files
nightly win32
070757a0160c
/
65.0a1
/
20181107100135
/
files
nightly win64
070757a0160c
/
65.0a1
/
20181107100135
/
files
|
last release without | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
releases | nightly linux32
65.0a1
/
20181107100135
/
pushlog to previous
nightly linux64
65.0a1
/
20181107100135
/
pushlog to previous
nightly mac
65.0a1
/
20181107100135
/
pushlog to previous
nightly win32
65.0a1
/
20181107100135
/
pushlog to previous
nightly win64
65.0a1
/
20181107100135
/
pushlog to previous
|
dom/base/nsFrameLoader.cpp | file | annotate | diff | comparison | revisions | |
dom/ipc/ContentChild.cpp | file | annotate | diff | comparison | revisions | |
dom/ipc/ContentParent.cpp | file | annotate | diff | comparison | revisions | |
gfx/2d/2D.h | file | annotate | diff | comparison | revisions | |
layout/ipc/PRenderFrame.ipdl | file | annotate | diff | comparison | revisions | |
layout/ipc/RenderFrameChild.cpp | file | annotate | diff | comparison | revisions | |
layout/ipc/RenderFrameChild.h | file | annotate | diff | comparison | revisions | |
layout/ipc/RenderFrameParent.cpp | file | annotate | diff | comparison | revisions | |
layout/ipc/RenderFrameParent.h | file | annotate | diff | comparison | revisions | |
modules/libpref/init/StaticPrefList.h | file | annotate | diff | comparison | revisions | |
mozilla-config.h.in | file | annotate | diff | comparison | revisions |
--- a/browser/components/downloads/test/browser/browser.ini +++ b/browser/components/downloads/test/browser/browser.ini @@ -5,13 +5,14 @@ support-files = head.js [browser_first_download_panel.js] skip-if = os == "linux" # Bug 949434 [browser_overflow_anchor.js] skip-if = os == "linux" # Bug 952422 [browser_confirm_unblock_download.js] [browser_iframe_gone_mid_download.js] [browser_indicatorDrop.js] [browser_libraryDrop.js] +skip-if = (os == 'win' && os_version == '10.0' && ccov) # Bug 1306510 [browser_library_clearall.js] [browser_downloads_panel_block.js] skip-if = true # Bug 1352792 [browser_downloads_panel_height.js] [browser_downloads_autohide.js]
--- a/devtools/server/actors/replay/graphics.js +++ b/devtools/server/actors/replay/graphics.js @@ -20,18 +20,17 @@ const CC = Components.Constructor; const sandbox = Cu.Sandbox(CC("@mozilla.org/systemprincipal;1", "nsIPrincipal")()); Cu.evalInSandbox( "Components.utils.import('resource://gre/modules/jsdebugger.jsm');" + "addDebuggerToGlobal(this);", sandbox ); // Windows in the middleman process are initially set up as about:blank pages. -// This method fills them in with a canvas filling the tab, and an overlay that -// can be displayed over that canvas. +// This method fills them in with a canvas filling the tab. function setupContents(window) { // The middlemanCanvas element fills the tab's contents. const canvas = window.middlemanCanvas = window.document.createElement("canvas"); canvas.style.position = "absolute"; window.document.body.style.margin = "0px"; window.document.body.prepend(canvas); } @@ -86,18 +85,12 @@ function UpdateCanvas(buffer, width, hei for (const window of Services.ww.getWindowEnumerator()) { updateWindowCanvas(window, buffer, width, height, hadFailure); } } catch (e) { dump("Middleman Graphics UpdateCanvas Exception: " + e + "\n"); } } -// Entry point for when we need to update the overlay's contents or visibility. -// eslint-disable-next-line no-unused-vars -function UpdateOverlay() { -} - // eslint-disable-next-line no-unused-vars var EXPORTED_SYMBOLS = [ "UpdateCanvas", - "UpdateOverlay", ];
--- a/dom/base/nsFrameLoader.cpp +++ b/dom/base/nsFrameLoader.cpp @@ -77,17 +77,17 @@ #include "mozilla/NullPrincipal.h" #include "mozilla/Preferences.h" #include "mozilla/Unused.h" #include "mozilla/dom/ChromeMessageSender.h" #include "mozilla/dom/Element.h" #include "mozilla/dom/FrameLoaderBinding.h" #include "mozilla/gfx/CrossProcessPaint.h" #include "mozilla/jsipc/CrossProcessObjectWrappers.h" -#include "mozilla/layout/RenderFrameParent.h" +#include "mozilla/layout/RenderFrame.h" #include "mozilla/ServoCSSParser.h" #include "mozilla/ServoStyleSet.h" #include "nsGenericHTMLFrameElement.h" #include "GeckoProfiler.h" #include "jsapi.h" #include "mozilla/dom/HTMLIFrameElement.h" #include "nsSandboxFlags.h" @@ -848,22 +848,22 @@ nsFrameLoader::ShowRemoteFrame(const Scr } // We never want to host remote frameloaders in simple popups, like menus. nsIWidget* widget = nsContentUtils::WidgetForContent(mOwnerContent); if (!widget || static_cast<nsBaseWidget*>(widget)->IsSmallPopup()) { return false; } - RenderFrameParent* rfp = GetCurrentRenderFrame(); - if (!rfp) { + RenderFrame* rf = GetCurrentRenderFrame(); + if (!rf) { return false; } - if (!rfp->AttachLayerManager()) { + if (!rf->AttachLayerManager()) { // This is just not going to work. return false; } mRemoteBrowser->Show(size, ParentWindowIsActive(mOwnerContent->OwnerDoc())); mRemoteBrowserShown = true; nsCOMPtr<nsIObserverService> os = services::GetObserverService(); @@ -1801,17 +1801,17 @@ nsFrameLoader::SetOwnerContent(Element* JS::RootedObject wrapper(jsapi.cx(), GetWrapper()); if (wrapper) { JSAutoRealm ar(jsapi.cx(), wrapper); IgnoredErrorResult rv; ReparentWrapper(jsapi.cx(), wrapper, rv); Unused << NS_WARN_IF(rv.Failed()); } - if (RenderFrameParent* rfp = GetCurrentRenderFrame()) { + if (RenderFrame* rfp = GetCurrentRenderFrame()) { rfp->OwnerContentChanged(aContent); } } bool nsFrameLoader::OwnerIsMozBrowserFrame() { nsCOMPtr<nsIMozBrowserFrame> browserFrame = do_QueryInterface(mOwnerContent); @@ -2611,18 +2611,18 @@ nsFrameLoader::TryRemoteBrowser() nsCOMPtr<Element> ownerElement = mOwnerContent; mRemoteBrowser = ContentParent::CreateBrowser(context, ownerElement, openerContentParent, sameTabGroupAs, nextTabParentId); if (!mRemoteBrowser) { return false; } - // Now that mRemoteBrowser is set, we can initialize the RenderFrameParent - mRemoteBrowser->InitRenderFrame(); + // Now that mRemoteBrowser is set, we can initialize the RenderFrame + mRemoteBrowser->InitRendering(); MaybeUpdatePrimaryTabParent(eTabParentChanged); mChildID = mRemoteBrowser->Manager()->ChildID(); nsCOMPtr<nsIDocShellTreeItem> rootItem; parentDocShell->GetRootTreeItem(getter_AddRefs(rootItem)); nsCOMPtr<nsPIDOMWindowOuter> rootWin = rootItem->GetWindow(); @@ -2665,17 +2665,17 @@ nsFrameLoader::TryRemoteBrowser() } mozilla::dom::PBrowserParent* nsFrameLoader::GetRemoteBrowser() const { return mRemoteBrowser; } -RenderFrameParent* +RenderFrame* nsFrameLoader::GetCurrentRenderFrame() const { if (mRemoteBrowser) { return mRemoteBrowser->GetRenderFrame(); } return nullptr; } @@ -2936,16 +2936,17 @@ nsFrameLoader::SetRemoteBrowser(nsITabPa { MOZ_ASSERT(!mRemoteBrowser); mRemoteFrame = true; mRemoteBrowser = TabParent::GetFrom(aTabParent); mChildID = mRemoteBrowser ? mRemoteBrowser->Manager()->ChildID() : 0; MaybeUpdatePrimaryTabParent(eTabParentChanged); ReallyLoadFrameScripts(); InitializeBrowserAPI(); + mRemoteBrowser->InitRendering(); ShowRemoteFrame(ScreenIntSize(0, 0)); } void nsFrameLoader::SetDetachedSubdocFrame(nsIFrame* aDetachedFrame, nsIDocument* aContainerDoc) { mDetachedSubdocFrame = aDetachedFrame;
--- a/dom/base/nsFrameLoader.h +++ b/dom/base/nsFrameLoader.h @@ -60,17 +60,17 @@ class MutableTabContext; namespace ipc { class StructuredCloneData; } // namespace ipc } // namespace dom namespace layout { -class RenderFrameParent; +class RenderFrame; } // namespace layout } // namespace mozilla #if defined(MOZ_WIDGET_GTK) typedef struct _GtkWidget GtkWidget; #endif // IID for nsFrameLoader, because some places want to QI to it. @@ -81,17 +81,17 @@ typedef struct _GtkWidget GtkWidget; class nsFrameLoader final : public nsStubMutationObserver, public mozilla::dom::ipc::MessageManagerCallback, public nsWrapperCache { friend class AutoResetInShow; friend class AutoResetInFrameSwap; typedef mozilla::dom::PBrowserParent PBrowserParent; typedef mozilla::dom::TabParent TabParent; - typedef mozilla::layout::RenderFrameParent RenderFrameParent; + typedef mozilla::layout::RenderFrame RenderFrame; public: static nsFrameLoader* Create(mozilla::dom::Element* aOwner, nsPIDOMWindowOuter* aOpener, bool aNetworkCreated, int32_t aJSPluginID = nsFakePluginTag::NOT_JSPLUGIN); NS_DECLARE_STATIC_IID_ACCESSOR(NS_FRAMELOADER_IID) @@ -291,17 +291,17 @@ public: * * Note that the returned render frame might not be a frame * constructed for this->GetURL(). This can happen, e.g., if the * <browser> was just navigated to a new URL, but hasn't painted the * new page yet. A render frame for the previous page may be * returned. (In-process <browser> behaves similarly, and this * behavior seems desirable.) */ - RenderFrameParent* GetCurrentRenderFrame() const; + RenderFrame* GetCurrentRenderFrame() const; mozilla::dom::ChromeMessageSender* GetFrameMessageManager() { return mMessageManager; } mozilla::dom::Element* GetOwnerContent() { return mOwnerContent; } bool ShouldClipSubdocument() { return mClipSubdocument; } bool ShouldClampScrollPosition() { return mClampScrollPosition; }
--- a/dom/base/nsGlobalWindowOuter.cpp +++ b/dom/base/nsGlobalWindowOuter.cpp @@ -5473,16 +5473,24 @@ nsGlobalWindowOuter::RevisePopupAbuseLev if (abuse == openAbused || abuse == openBlocked || abuse == openControlled) { int32_t popupMax = Preferences::GetInt("dom.popup_maximum", -1); if (popupMax >= 0 && gOpenPopupSpamCount >= popupMax) abuse = openOverridden; } + // If this popup is allowed, let's block any other for this event, forcing + // openBlocked state. + if ((abuse == openAllowed || abuse == openControlled) && + StaticPrefs::dom_block_multiple_popups() && + !PopupWhitelisted()) { + nsContentUtils::PushPopupControlState(openBlocked, true); + } + return abuse; } /* If a window open is blocked, fire the appropriate DOM events. */ void nsGlobalWindowOuter::FireAbuseEvents(const nsAString &aPopupURL, const nsAString &aPopupWindowName, const nsAString &aPopupWindowFeatures) @@ -5509,17 +5517,17 @@ nsGlobalWindowOuter::FireAbuseEvents(con baseURL = doc->GetDocBaseURI(); // use the base URI to build what would have been the popup's URI nsCOMPtr<nsIIOService> ios(do_GetService(NS_IOSERVICE_CONTRACTID)); if (ios) ios->NewURI(NS_ConvertUTF16toUTF8(aPopupURL), nullptr, baseURL, getter_AddRefs(popupURI)); - // fire an event chock full of informative URIs + // fire an event block full of informative URIs FirePopupBlockedEvent(topDoc, popupURI, aPopupWindowName, aPopupWindowFeatures); } already_AddRefed<nsPIDOMWindowOuter> nsGlobalWindowOuter::OpenOuter(const nsAString& aUrl, const nsAString& aName, const nsAString& aOptions, ErrorResult& aError) {
--- a/dom/base/test/browser.ini +++ b/dom/base/test/browser.ini @@ -52,8 +52,10 @@ skip-if = e10s # this tests non-e10s beh [browser_promiseDocumentFlushed.js] [browser_state_notifications.js] skip-if = true # Bug 1271028 [browser_use_counters.js] skip-if = verify [browser_timeout_throttling_with_audio_playback.js] [browser_bug1303838.js] [browser_inputStream_structuredClone.js] +[browser_multiple_popups.js] +support-files = browser_multiple_popups.html
new file mode 100644 --- /dev/null +++ b/dom/base/test/browser_multiple_popups.html @@ -0,0 +1,54 @@ +<!DOCTYPE html> +<html> +<body> + <button onclick="openPopups();" id="openPopups">open popups</button> + <button onclick="openNestedPopups();" id="openNestedPopups">open tested popups</button> + <button onclick="openPopupAndClick();" id="openPopupAndClick">open popups and click</button> + <button onclick="closeAllWindows();" id="closeAllWindows">close all windows</button> + <input type="text" id="input" /> + <script> +let windows = []; + +function openPopups() { + windows.push(window.open('empty.html', '_blank', 'width=100,height=100')); + windows.push(window.open('empty.html', '_blank', 'width=100,height=100')); +} + +function openNestedPopups() { + var w = window.open('empty.html', '_blank', 'width=100,height=100'); + windows.push(w); + windows.push(w.open('empty.html', '_blank', 'width=100,height=100')); +} + +var recursion = false; +function openPopupAndClick() { + windows.push(window.open('empty.html', '_blank', 'width=100,height=100')); + if (!recursion) { + recursion = true; + document.getElementById("openPopupAndClick").click(); + } +} + +function closeAllWindows() { + windows.forEach(w => { + try { + w.close(); + } catch(e) {} + }); +} + +if (location.search.includes("openPopups")) { + let id = setInterval(() => { + if (document.getElementById('start')) { + clearInterval(id); + openPopups(); + } + }, 500); +} + +document.getElementById("input").onmouseup = _ => { + openPopups(); +} + </script> +</body> +</html>
new file mode 100644 --- /dev/null +++ b/dom/base/test/browser_multiple_popups.js @@ -0,0 +1,362 @@ +/** + * In this test, we check that the content can't open more than one popup at a + * time (depending on "dom.allow_mulitple_popups" preference value). + */ + +const TEST_DOMAIN = "http://example.net"; +const TEST_PATH = "/browser/dom/base/test/"; +const CHROME_DOMAIN = "chrome://mochitests/content"; + +requestLongerTimeout(2); + +function WindowObserver(count) { + return new Promise(resolve => { + let windowObserver = function(aSubject, aTopic, aData) { + if (aTopic != "domwindowopened") { + return; + } + + if (--count == 0) { + Services.ww.unregisterNotification(windowObserver); + resolve(); + } + } + Services.ww.registerNotification(windowObserver); + }); +} + +add_task(async _ => { + info("All opened if the pref is off"); + + await SpecialPowers.pushPrefEnv({"set": [ + ["dom.block_multiple_popups", false], + ["dom.disable_open_during_load", true], + ]}); + + let tab = BrowserTestUtils.addTab(gBrowser, TEST_DOMAIN + TEST_PATH + "browser_multiple_popups.html") + gBrowser.selectedTab = tab; + + let browser = gBrowser.getBrowserForTab(tab); + await BrowserTestUtils.browserLoaded(browser); + + let obs = new WindowObserver(2); + + await BrowserTestUtils.synthesizeMouseAtCenter("#openPopups", {}, tab.linkedBrowser); + + await obs; + ok(true, "We had 2 windows."); + + await BrowserTestUtils.synthesizeMouseAtCenter("#closeAllWindows", {}, tab.linkedBrowser); + + BrowserTestUtils.removeTab(tab); +}); + +add_task(async _ => { + info("2 window.open()s in a click event allowed because whitelisted domain."); + + await SpecialPowers.pushPrefEnv({"set": [ + ["dom.block_multiple_popups", true], + ["dom.disable_open_during_load", true], + ]}); + + const uri = Services.io.newURI(TEST_DOMAIN); + const principal = Services.scriptSecurityManager.createCodebasePrincipal(uri, {}); + + Services.perms.addFromPrincipal(principal, "popup", Services.perms.ALLOW_ACTION); + + let tab = BrowserTestUtils.addTab(gBrowser, TEST_DOMAIN + TEST_PATH + "browser_multiple_popups.html") + gBrowser.selectedTab = tab; + + let browser = gBrowser.getBrowserForTab(tab); + await BrowserTestUtils.browserLoaded(browser); + + let obs = new WindowObserver(2); + + await BrowserTestUtils.synthesizeMouseAtCenter("#openPopups", {}, tab.linkedBrowser); + + await obs; + ok(true, "We had 2 windows."); + + await BrowserTestUtils.synthesizeMouseAtCenter("#closeAllWindows", {}, tab.linkedBrowser); + + BrowserTestUtils.removeTab(tab); + + await new Promise(aResolve => { + Services.clearData.deleteData(Ci.nsIClearDataService.CLEAR_PERMISSIONS, value => { + Assert.equal(value, 0); + aResolve(); + }); + }); +}); + +add_task(async _ => { + info("2 window.open()s in a mouseup event allowed because whitelisted domain."); + + await SpecialPowers.pushPrefEnv({"set": [ + ["dom.block_multiple_popups", true], + ["dom.disable_open_during_load", true], + ]}); + + const uri = Services.io.newURI(TEST_DOMAIN); + const principal = Services.scriptSecurityManager.createCodebasePrincipal(uri, {}); + + Services.perms.addFromPrincipal(principal, "popup", Services.perms.ALLOW_ACTION); + + let tab = BrowserTestUtils.addTab(gBrowser, TEST_DOMAIN + TEST_PATH + "browser_multiple_popups.html") + gBrowser.selectedTab = tab; + + let browser = gBrowser.getBrowserForTab(tab); + await BrowserTestUtils.browserLoaded(browser); + + let obs = new WindowObserver(2); + + await BrowserTestUtils.synthesizeMouseAtCenter("#input", { type: "mouseup" }, tab.linkedBrowser); + + await obs; + ok(true, "We had 2 windows."); + + await BrowserTestUtils.synthesizeMouseAtCenter("#closeAllWindows", {}, tab.linkedBrowser); + + BrowserTestUtils.removeTab(tab); + + await new Promise(aResolve => { + Services.clearData.deleteData(Ci.nsIClearDataService.CLEAR_PERMISSIONS, value => { + Assert.equal(value, 0); + aResolve(); + }); + }); +}); + +add_task(async _ => { + info("2 window.open()s in a single click event: only the first one is allowed."); + + await SpecialPowers.pushPrefEnv({"set": [ + ["dom.block_multiple_popups", true], + ["dom.disable_open_during_load", true], + ]}); + + let tab = BrowserTestUtils.addTab(gBrowser, TEST_DOMAIN + TEST_PATH + "browser_multiple_popups.html") + gBrowser.selectedTab = tab; + + let browser = gBrowser.getBrowserForTab(tab); + await BrowserTestUtils.browserLoaded(browser); + + let p = ContentTask.spawn(browser, null, () => { + return new content.Promise(resolve => { + content.addEventListener("DOMPopupBlocked", () => { + ok(true, "The popup has been blocked"); + resolve(); + }, {once:true}); + }); + }); + + let obs = new WindowObserver(1); + + await BrowserTestUtils.synthesizeMouseAtCenter("#openPopups", {}, tab.linkedBrowser); + + await p; + await obs; + ok(true, "We had only 1 window."); + + await BrowserTestUtils.synthesizeMouseAtCenter("#closeAllWindows", {}, tab.linkedBrowser); + + BrowserTestUtils.removeTab(tab); +}); + +add_task(async _ => { + info("2 window.open()s in a single mouseup event: only the first one is allowed."); + + await SpecialPowers.pushPrefEnv({"set": [ + ["dom.block_multiple_popups", true], + ["dom.disable_open_during_load", true], + ]}); + + let tab = BrowserTestUtils.addTab(gBrowser, TEST_DOMAIN + TEST_PATH + "browser_multiple_popups.html") + gBrowser.selectedTab = tab; + + let browser = gBrowser.getBrowserForTab(tab); + await BrowserTestUtils.browserLoaded(browser); + + let p = ContentTask.spawn(browser, null, () => { + return new content.Promise(resolve => { + content.addEventListener("DOMPopupBlocked", () => { + ok(true, "The popup has been blocked"); + resolve(); + }, {once:true}); + }); + }); + + let obs = new WindowObserver(1); + + await BrowserTestUtils.synthesizeMouseAtCenter("#input", { type: "mouseup" }, tab.linkedBrowser); + + await p; + await obs; + ok(true, "We had only 1 window."); + + await BrowserTestUtils.synthesizeMouseAtCenter("#closeAllWindows", {}, tab.linkedBrowser); + + BrowserTestUtils.removeTab(tab); +}); + +add_task(async _ => { + info("2 window.open()s by non-event code: no windows allowed."); + + await SpecialPowers.pushPrefEnv({"set": [ + ["dom.block_multiple_popups", true], + ["dom.disable_open_during_load", true], + ]}); + + let tab = BrowserTestUtils.addTab(gBrowser, TEST_DOMAIN + TEST_PATH + "browser_multiple_popups.html?openPopups") + gBrowser.selectedTab = tab; + + let browser = gBrowser.getBrowserForTab(tab); + await BrowserTestUtils.browserLoaded(browser); + + await ContentTask.spawn(browser, null, () => { + return new content.Promise(resolve => { + let count = 0; + content.addEventListener("DOMPopupBlocked", function cb() { + if (++count == 2) { + content.removeEventListener("DOMPopupBlocked", cb); + ok(true, "The popup has been blocked"); + resolve(); + } + }); + + let p = content.document.createElement("p"); + p.setAttribute('id', 'start'); + content.document.body.appendChild(p); + }); + }); + + ok(true, "We had 0 windows."); + + await BrowserTestUtils.synthesizeMouseAtCenter("#closeAllWindows", {}, tab.linkedBrowser); + + BrowserTestUtils.removeTab(tab); +}); + +add_task(async _ => { + info("2 window.open()s by non-event code allowed by permission"); + + await SpecialPowers.pushPrefEnv({"set": [ + ["dom.block_multiple_popups", true], + ["dom.disable_open_during_load", true], + ]}); + + const uri = Services.io.newURI(TEST_DOMAIN); + const principal = Services.scriptSecurityManager.createCodebasePrincipal(uri, {}); + + Services.perms.addFromPrincipal(principal, "popup", Services.perms.ALLOW_ACTION); + + let obs = new WindowObserver(2); + + let tab = BrowserTestUtils.addTab(gBrowser, TEST_DOMAIN + TEST_PATH + "browser_multiple_popups.html?openPopups") + gBrowser.selectedTab = tab; + + let browser = gBrowser.getBrowserForTab(tab); + await BrowserTestUtils.browserLoaded(browser); + + ok(true, "We had 2 windows."); + + await BrowserTestUtils.synthesizeMouseAtCenter("#closeAllWindows", {}, tab.linkedBrowser); + + BrowserTestUtils.removeTab(tab); + + await new Promise(aResolve => { + Services.clearData.deleteData(Ci.nsIClearDataService.CLEAR_PERMISSIONS, value => { + Assert.equal(value, 0); + aResolve(); + }); + }); +}); + +add_task(async _ => { + info("1 window.open() executing another window.open(): only the first one is allowed."); + + await SpecialPowers.pushPrefEnv({"set": [ + ["dom.block_multiple_popups", true], + ["dom.disable_open_during_load", true], + ]}); + + let tab = BrowserTestUtils.addTab(gBrowser, TEST_DOMAIN + TEST_PATH + "browser_multiple_popups.html") + gBrowser.selectedTab = tab; + + let browser = gBrowser.getBrowserForTab(tab); + await BrowserTestUtils.browserLoaded(browser); + + // We don't receive DOMPopupBlocked for nested windows. Let's use just the observer. + let obs = new WindowObserver(1); + + await BrowserTestUtils.synthesizeMouseAtCenter("#openNestedPopups", {}, tab.linkedBrowser); + + await obs; + ok(true, "We had 1 window."); + + await BrowserTestUtils.synthesizeMouseAtCenter("#closeAllWindows", {}, tab.linkedBrowser); + + BrowserTestUtils.removeTab(tab); +}); + +add_task(async _ => { + info("window.open() and .click() on the element opening the window."); + + await SpecialPowers.pushPrefEnv({"set": [ + ["dom.block_multiple_popups", true], + ["dom.disable_open_during_load", true], + ]}); + + let tab = BrowserTestUtils.addTab(gBrowser, TEST_DOMAIN + TEST_PATH + "browser_multiple_popups.html") + gBrowser.selectedTab = tab; + + let browser = gBrowser.getBrowserForTab(tab); + await BrowserTestUtils.browserLoaded(browser); + + let p = ContentTask.spawn(browser, null, () => { + return new content.Promise(resolve => { + content.addEventListener("DOMPopupBlocked", () => { + ok(true, "The popup has been blocked"); + resolve(); + }, {once:true}); + }); + }); + + let obs = new WindowObserver(1); + + await BrowserTestUtils.synthesizeMouseAtCenter("#openPopupAndClick", {}, tab.linkedBrowser); + + await p; + await obs; + ok(true, "We had only 1 window."); + + await BrowserTestUtils.synthesizeMouseAtCenter("#closeAllWindows", {}, tab.linkedBrowser); + + BrowserTestUtils.removeTab(tab); +}); + +add_task(async _ => { + info("All opened from chrome."); + + await SpecialPowers.pushPrefEnv({"set": [ + ["dom.block_multiple_popups", true], + ["dom.disable_open_during_load", true], + ]}); + + let tab = BrowserTestUtils.addTab(gBrowser, CHROME_DOMAIN + TEST_PATH + "browser_multiple_popups.html") + gBrowser.selectedTab = tab; + + let browser = gBrowser.getBrowserForTab(tab); + await BrowserTestUtils.browserLoaded(browser); + + let obs = new WindowObserver(2); + + await BrowserTestUtils.synthesizeMouseAtCenter("#openPopups", {}, tab.linkedBrowser); + + await obs; + ok(true, "We had 2 windows."); + + await BrowserTestUtils.synthesizeMouseAtCenter("#closeAllWindows", {}, tab.linkedBrowser); + + BrowserTestUtils.removeTab(tab); +});
--- a/dom/browser-element/BrowserElementParent.cpp +++ b/dom/browser-element/BrowserElementParent.cpp @@ -17,17 +17,16 @@ #include "BrowserElementParent.h" #include "mozilla/EventDispatcher.h" #include "mozilla/dom/HTMLIFrameElement.h" #include "mozilla/dom/ToJSValue.h" #include "nsIInterfaceRequestorUtils.h" #include "nsVariant.h" #include "mozilla/dom/BrowserElementDictionariesBinding.h" #include "mozilla/dom/CustomEvent.h" -#include "mozilla/layout/RenderFrameParent.h" using namespace mozilla; using namespace mozilla::dom; using namespace mozilla::layers; using namespace mozilla::layout; namespace { @@ -172,22 +171,19 @@ BrowserElementParent::DispatchOpenWindow return BrowserElementParent::OPEN_WINDOW_IGNORED; } /*static*/ BrowserElementParent::OpenWindowResult BrowserElementParent::OpenWindowOOP(TabParent* aOpenerTabParent, TabParent* aPopupTabParent, - PRenderFrameParent* aRenderFrame, const nsAString& aURL, const nsAString& aName, - const nsAString& aFeatures, - TextureFactoryIdentifier* aTextureFactoryIdentifier, - layers::LayersId* aLayersId) + const nsAString& aFeatures) { // Create an iframe owned by the same document which owns openerFrameElement. nsCOMPtr<Element> openerFrameElement = aOpenerTabParent->GetOwnerElement(); NS_ENSURE_TRUE(openerFrameElement, BrowserElementParent::OPEN_WINDOW_IGNORED); RefPtr<HTMLIFrameElement> popupFrameElement = CreateIframe(openerFrameElement, aName, /* aRemote = */ true); @@ -212,22 +208,16 @@ BrowserElementParent::OpenWindowOOP(TabP } // The popup was not blocked, so hook up the frame element and the popup tab // parent, and return success. aPopupTabParent->SetOwnerElement(popupFrameElement); popupFrameElement->AllowCreateFrameLoader(); popupFrameElement->CreateRemoteFrameLoader(aPopupTabParent); - RenderFrameParent* rfp = static_cast<RenderFrameParent*>(aRenderFrame); - if (!aPopupTabParent->SetRenderFrame(rfp) || - !aPopupTabParent->GetRenderFrameInfo(aTextureFactoryIdentifier, aLayersId)) { - return BrowserElementParent::OPEN_WINDOW_IGNORED; - } - return opened; } /* static */ BrowserElementParent::OpenWindowResult BrowserElementParent::OpenWindowInProcess(nsPIDOMWindowOuter* aOpenerWindow, nsIURI* aURI, const nsAString& aName,
--- a/dom/browser-element/BrowserElementParent.h +++ b/dom/browser-element/BrowserElementParent.h @@ -17,24 +17,16 @@ class nsIDOMWindow; class nsIURI; namespace mozilla { namespace dom { class TabParent; } // namespace dom -namespace layers { -struct TextureFactoryIdentifier; -} // namespace layers - -namespace layout { -class PRenderFrameParent; -} // namespace layout - /** * BrowserElementParent implements a portion of the parent-process side of * <iframe mozbrowser>. * * Most of the parent-process side of <iframe mozbrowser> is implemented in * BrowserElementParent.js. This file implements the few parts of this * functionality which must be written in C++. * @@ -90,22 +82,19 @@ public: * live. * @return an OpenWindowresult that describes whether the embedder added the * frame to a document and whether it called preventDefault to prevent * the platform from handling the open request. */ static OpenWindowResult OpenWindowOOP(dom::TabParent* aOpenerTabParent, dom::TabParent* aPopupTabParent, - layout::PRenderFrameParent* aRenderFrame, const nsAString& aURL, const nsAString& aName, - const nsAString& aFeatures, - layers::TextureFactoryIdentifier* aTextureFactoryIdentifier, - layers::LayersId* aLayersId); + const nsAString& aFeatures); /** * Handle a window.open call from an in-process <iframe mozbrowser>. * * (These parameter types are silly, but they match what our caller has in * hand. Feel free to add an override, if they are inconvenient to you.) * * @param aURI the URI the new window should load. May be null.
--- a/dom/canvas/CanvasRenderingContext2D.cpp +++ b/dom/canvas/CanvasRenderingContext2D.cpp @@ -1074,16 +1074,17 @@ CanvasRenderingContext2D::CanvasRenderin , mIsSkiaGL(false) , mHasPendingStableStateCallback(false) , mDrawObserver(nullptr) , mIsEntireFrameInvalid(false) , mPredictManyRedrawCalls(false) , mIsCapturedFrameInvalid(false) , mPathTransformWillUpdate(false) , mInvalidateCount(0) + , mWriteOnly(false) { if (!sMaxContextsInitialized) { sMaxContexts = gfxPrefs::CanvasAzureAcceleratedLimit(); sMaxContextsInitialized = true; } sNumLivingContexts++; @@ -2560,17 +2561,18 @@ CanvasRenderingContext2D::CreatePattern( aError.Throw(NS_ERROR_DOM_INVALID_STATE_ERR); return nullptr; } // An ImageBitmap never taints others so we set principalForSecurityCheck to // nullptr and set CORSUsed to true for passing the security check in // CanvasUtils::DoDrawImageSecurityCheck(). RefPtr<CanvasPattern> pat = - new CanvasPattern(this, srcSurf, repeatMode, nullptr, false, true); + new CanvasPattern(this, srcSurf, repeatMode, nullptr, + imgBitmap.IsWriteOnly(), true); return pat.forget(); } EnsureTarget(); if (!IsTargetValid()) { aError.Throw(NS_ERROR_DOM_INVALID_STATE_ERR); return nullptr; @@ -4915,24 +4917,32 @@ CanvasRenderingContext2D::DrawImage(cons if (aImage.IsHTMLCanvasElement()) { HTMLCanvasElement* canvas = &aImage.GetAsHTMLCanvasElement(); element = canvas; nsIntSize size = canvas->GetSize(); if (size.width == 0 || size.height == 0) { aError.Throw(NS_ERROR_DOM_INVALID_STATE_ERR); return; } + + if (canvas->IsWriteOnly()) { + SetWriteOnly(); + } } else if (aImage.IsImageBitmap()) { ImageBitmap& imageBitmap = aImage.GetAsImageBitmap(); srcSurf = imageBitmap.PrepareForDrawTarget(mTarget); if (!srcSurf) { return; } + if (imageBitmap.IsWriteOnly()) { + SetWriteOnly(); + } + imgSize = gfx::IntSize(imageBitmap.Width(), imageBitmap.Height()); } else { if (aImage.IsHTMLImageElement()) { HTMLImageElement* img = &aImage.GetAsHTMLImageElement(); element = img; } else if (aImage.IsSVGImageElement()) { SVGImageElement* img = &aImage.GetAsSVGImageElement(); @@ -5443,17 +5453,18 @@ CanvasRenderingContext2D::GetImageData(J if (!mCanvasElement && !mDocShell) { NS_ERROR("No canvas element and no docshell in GetImageData!!!"); aError.Throw(NS_ERROR_DOM_SECURITY_ERR); return nullptr; } // Check only if we have a canvas element; if we were created with a docshell, // then it's special internal use. - if (mCanvasElement && !mCanvasElement->CallerCanRead(aCx)) { + if (IsWriteOnly() || + (mCanvasElement && !mCanvasElement->CallerCanRead(aCx))) { // XXX ERRMSG we need to report an error to developers here! (bug 329026) aError.Throw(NS_ERROR_DOM_SECURITY_ERR); return nullptr; } if (!IsFinite(aSx) || !IsFinite(aSy) || !IsFinite(aSw) || !IsFinite(aSh)) { aError.Throw(NS_ERROR_DOM_NOT_SUPPORTED_ERR);
--- a/dom/canvas/CanvasRenderingContext2D.h +++ b/dom/canvas/CanvasRenderingContext2D.h @@ -36,16 +36,17 @@ class nsXULElement; namespace mozilla { namespace gl { class SourceSurface; } // namespace gl namespace dom { class HTMLImageElementOrSVGImageElementOrHTMLCanvasElementOrHTMLVideoElementOrImageBitmap; typedef HTMLImageElementOrSVGImageElementOrHTMLCanvasElementOrHTMLVideoElementOrImageBitmap CanvasImageSource; +class ImageBitmap; class ImageData; class StringOrCanvasGradientOrCanvasPattern; class OwningStringOrCanvasGradientOrCanvasPattern; class TextMetrics; class CanvasPath; extern const mozilla::gfx::Float SIGMA_MAX; @@ -1187,16 +1188,29 @@ protected: if (aPerDevPixel) *aPerDevPixel = devPixel; if (aPerCSSPixel) *aPerCSSPixel = cssPixel; } friend struct CanvasBidiProcessor; friend class CanvasDrawObserver; + friend class ImageBitmap; + + void SetWriteOnly() + { + mWriteOnly = true; + } + + bool IsWriteOnly() const + { + return mWriteOnly; + } + + bool mWriteOnly; }; size_t BindingJSObjectMallocBytes(CanvasRenderingContext2D* aContext); } // namespace dom } // namespace mozilla #endif /* CanvasRenderingContext2D_h */
--- a/dom/canvas/ImageBitmap.cpp +++ b/dom/canvas/ImageBitmap.cpp @@ -466,46 +466,45 @@ CheckSecurityForElements(const nsLayoutU } /* * A wrapper to the nsLayoutUtils::SurfaceFromElement() function followed by the * security checking. */ template<class ElementType> static already_AddRefed<SourceSurface> -GetSurfaceFromElement(nsIGlobalObject* aGlobal, ElementType& aElement, ErrorResult& aRv) +GetSurfaceFromElement(nsIGlobalObject* aGlobal, ElementType& aElement, + bool* aWriteOnly, ErrorResult& aRv) { nsLayoutUtils::SurfaceFromElementResult res = nsLayoutUtils::SurfaceFromElement(&aElement, nsLayoutUtils::SFE_WANT_FIRST_FRAME_IF_IMAGE); RefPtr<SourceSurface> surface = res.GetSourceSurface(); if (NS_WARN_IF(!surface)) { aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR); return nullptr; } - // check origin-clean - if (!CheckSecurityForElements(res)) { - aRv.Throw(NS_ERROR_DOM_SECURITY_ERR); - return nullptr; - } + // check write-only mode + *aWriteOnly = !CheckSecurityForElements(res); return surface.forget(); } ImageBitmap::ImageBitmap(nsIGlobalObject* aGlobal, layers::Image* aData, - gfxAlphaType aAlphaType) + bool aWriteOnly, gfxAlphaType aAlphaType) : mParent(aGlobal) , mData(aData) , mSurface(nullptr) , mDataWrapper(new ImageUtils(mData)) , mPictureRect(0, 0, aData->GetSize().width, aData->GetSize().height) , mAlphaType(aAlphaType) , mAllocatedImageData(false) + , mWriteOnly(aWriteOnly) { MOZ_ASSERT(aData, "aData is null in ImageBitmap constructor."); mShutdownObserver = new ImageBitmapShutdownObserver(this); mShutdownObserver->RegisterObserver(); } ImageBitmap::~ImageBitmap() @@ -758,135 +757,141 @@ ImageBitmap::ToCloneData() const } UniquePtr<ImageBitmapCloneData> result(new ImageBitmapCloneData()); result->mPictureRect = mPictureRect; result->mAlphaType = mAlphaType; RefPtr<SourceSurface> surface = mData->GetAsSourceSurface(); result->mSurface = surface->GetDataSurface(); MOZ_ASSERT(result->mSurface); + result->mWriteOnly = mWriteOnly; return result; } /* static */ already_AddRefed<ImageBitmap> ImageBitmap::CreateFromSourceSurface(nsIGlobalObject* aGlobal, gfx::SourceSurface* aSource, ErrorResult& aRv) { RefPtr<layers::Image> data = CreateImageFromSurface(aSource); - RefPtr<ImageBitmap> ret = new ImageBitmap(aGlobal, data); + RefPtr<ImageBitmap> ret = new ImageBitmap(aGlobal, data, + false /* writeOnly */); ret->mAllocatedImageData = true; return ret.forget(); } /* static */ already_AddRefed<ImageBitmap> ImageBitmap::CreateFromCloneData(nsIGlobalObject* aGlobal, ImageBitmapCloneData* aData) { RefPtr<layers::Image> data = CreateImageFromSurface(aData->mSurface); - RefPtr<ImageBitmap> ret = new ImageBitmap(aGlobal, data, aData->mAlphaType); + RefPtr<ImageBitmap> ret = + new ImageBitmap(aGlobal, data, aData->mWriteOnly, aData->mAlphaType); ret->mAllocatedImageData = true; ErrorResult rv; ret->SetPictureRect(aData->mPictureRect, rv); return ret.forget(); } /* static */ already_AddRefed<ImageBitmap> ImageBitmap::CreateFromOffscreenCanvas(nsIGlobalObject* aGlobal, OffscreenCanvas& aOffscreenCanvas, ErrorResult& aRv) { - // Check origin-clean. - if (aOffscreenCanvas.IsWriteOnly()) { - aRv.Throw(NS_ERROR_DOM_SECURITY_ERR); - return nullptr; - } + // Check write-only mode. + bool writeOnly = aOffscreenCanvas.IsWriteOnly(); nsLayoutUtils::SurfaceFromElementResult res = nsLayoutUtils::SurfaceFromOffscreenCanvas(&aOffscreenCanvas, nsLayoutUtils::SFE_WANT_FIRST_FRAME_IF_IMAGE); RefPtr<SourceSurface> surface = res.GetSourceSurface(); if (NS_WARN_IF(!surface)) { aRv.Throw(NS_ERROR_NOT_AVAILABLE); return nullptr; } RefPtr<layers::Image> data = CreateImageFromSurface(surface); - RefPtr<ImageBitmap> ret = new ImageBitmap(aGlobal, data); + RefPtr<ImageBitmap> ret = new ImageBitmap(aGlobal, data, writeOnly); ret->mAllocatedImageData = true; return ret.forget(); } /* static */ already_AddRefed<ImageBitmap> ImageBitmap::CreateInternal(nsIGlobalObject* aGlobal, HTMLImageElement& aImageEl, const Maybe<IntRect>& aCropRect, ErrorResult& aRv) { // Check if the image element is completely available or not. if (!aImageEl.Complete()) { aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR); return nullptr; } + bool writeOnly = true; + // Get the SourceSurface out from the image element and then do security // checking. - RefPtr<SourceSurface> surface = GetSurfaceFromElement(aGlobal, aImageEl, aRv); + RefPtr<SourceSurface> surface = GetSurfaceFromElement(aGlobal, aImageEl, + &writeOnly, aRv); if (NS_WARN_IF(aRv.Failed())) { return nullptr; } // Create ImageBitmap. RefPtr<layers::Image> data = CreateImageFromSurface(surface); if (NS_WARN_IF(!data)) { aRv.Throw(NS_ERROR_NOT_AVAILABLE); return nullptr; } - RefPtr<ImageBitmap> ret = new ImageBitmap(aGlobal, data); + RefPtr<ImageBitmap> ret = new ImageBitmap(aGlobal, data, writeOnly); // Set the picture rectangle. if (ret && aCropRect.isSome()) { ret->SetPictureRect(aCropRect.ref(), aRv); } return ret.forget(); } /* static */ already_AddRefed<ImageBitmap> ImageBitmap::CreateInternal(nsIGlobalObject* aGlobal, SVGImageElement& aImageEl, const Maybe<IntRect>& aCropRect, ErrorResult& aRv) { + bool writeOnly = true; + // Get the SourceSurface out from the image element and then do security // checking. - RefPtr<SourceSurface> surface = GetSurfaceFromElement(aGlobal, aImageEl, aRv); + RefPtr<SourceSurface> surface = GetSurfaceFromElement(aGlobal, aImageEl, + &writeOnly, aRv); if (NS_WARN_IF(aRv.Failed())) { return nullptr; } // Create ImageBitmap. RefPtr<layers::Image> data = CreateImageFromSurface(surface); if (NS_WARN_IF(!data)) { aRv.Throw(NS_ERROR_NOT_AVAILABLE); return nullptr; } - RefPtr<ImageBitmap> ret = new ImageBitmap(aGlobal, data); + RefPtr<ImageBitmap> ret = new ImageBitmap(aGlobal, data, writeOnly); // Set the picture rectangle. if (ret && aCropRect.isSome()) { ret->SetPictureRect(aCropRect.ref(), aRv); } return ret.forget(); } @@ -908,28 +913,25 @@ ImageBitmap::CreateInternal(nsIGlobalObj if (aVideoEl.ReadyState() <= HAVE_METADATA) { aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR); return nullptr; } // Check security. nsCOMPtr<nsIPrincipal> principal = aVideoEl.GetCurrentVideoPrincipal(); bool CORSUsed = aVideoEl.GetCORSMode() != CORS_NONE; - if (!CheckSecurityForElements(false, CORSUsed, principal)) { - aRv.Throw(NS_ERROR_DOM_SECURITY_ERR); - return nullptr; - } + bool writeOnly = !CheckSecurityForElements(false, CORSUsed, principal); // Create ImageBitmap. RefPtr<layers::Image> data = aVideoEl.GetCurrentImage(); if (!data) { aRv.Throw(NS_ERROR_NOT_AVAILABLE); return nullptr; } - RefPtr<ImageBitmap> ret = new ImageBitmap(aGlobal, data); + RefPtr<ImageBitmap> ret = new ImageBitmap(aGlobal, data, writeOnly); // Set the picture rectangle. if (ret && aCropRect.isSome()) { ret->SetPictureRect(aCropRect.ref(), aRv); } return ret.forget(); } @@ -938,22 +940,28 @@ ImageBitmap::CreateInternal(nsIGlobalObj ImageBitmap::CreateInternal(nsIGlobalObject* aGlobal, HTMLCanvasElement& aCanvasEl, const Maybe<IntRect>& aCropRect, ErrorResult& aRv) { if (aCanvasEl.Width() == 0 || aCanvasEl.Height() == 0) { aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR); return nullptr; } - RefPtr<SourceSurface> surface = GetSurfaceFromElement(aGlobal, aCanvasEl, aRv); + bool writeOnly = true; + RefPtr<SourceSurface> surface = GetSurfaceFromElement(aGlobal, aCanvasEl, + &writeOnly, aRv); if (NS_WARN_IF(aRv.Failed())) { return nullptr; } + if (!writeOnly) { + writeOnly = aCanvasEl.IsWriteOnly(); + } + // Crop the source surface if needed. RefPtr<SourceSurface> croppedSurface; IntRect cropRect = aCropRect.valueOr(IntRect()); // If the HTMLCanvasElement's rendering context is WebGL, then the snapshot // we got from the HTMLCanvasElement is a DataSourceSurface which is a copy // of the rendering context. We handle cropping in this case. bool needToReportMemoryAllocation = false; @@ -977,17 +985,17 @@ ImageBitmap::CreateInternal(nsIGlobalObj // Create an Image from the SourceSurface. RefPtr<layers::Image> data = CreateImageFromSurface(croppedSurface); if (NS_WARN_IF(!data)) { aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR); return nullptr; } - RefPtr<ImageBitmap> ret = new ImageBitmap(aGlobal, data); + RefPtr<ImageBitmap> ret = new ImageBitmap(aGlobal, data, writeOnly); if (needToReportMemoryAllocation) { ret->mAllocatedImageData = true; } // Set the picture rectangle. if (ret && aCropRect.isSome()) { ret->SetPictureRect(cropRect, aRv); @@ -1042,17 +1050,18 @@ ImageBitmap::CreateInternal(nsIGlobalObj } if (NS_WARN_IF(!data)) { aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR); return nullptr; } // Create an ImageBimtap. - RefPtr<ImageBitmap> ret = new ImageBitmap(aGlobal, data, alphaType); + RefPtr<ImageBitmap> ret = + new ImageBitmap(aGlobal, data, false /* write-only */, alphaType); ret->mAllocatedImageData = true; // The cropping information has been handled in the CreateImageFromRawData() // function. return ret.forget(); } @@ -1065,21 +1074,18 @@ ImageBitmap::CreateInternal(nsIGlobalObj nsGlobalWindowInner* window = nsGlobalWindowInner::Cast(win); if (NS_WARN_IF(!window) || !window->GetExtantDoc()) { aRv.Throw(NS_ERROR_DOM_SECURITY_ERR); return nullptr; } window->GetExtantDoc()->WarnOnceAbout(nsIDocument::eCreateImageBitmapCanvasRenderingContext2D); - // Check origin-clean. - if (aCanvasCtx.GetCanvas()->IsWriteOnly()) { - aRv.Throw(NS_ERROR_DOM_SECURITY_ERR); - return nullptr; - } + // Check write-only mode. + bool writeOnly = aCanvasCtx.GetCanvas()->IsWriteOnly() || aCanvasCtx.IsWriteOnly(); RefPtr<SourceSurface> surface = aCanvasCtx.GetSurfaceSnapshot(); if (NS_WARN_IF(!surface)) { aRv.Throw(NS_ERROR_NOT_AVAILABLE); return nullptr; } @@ -1091,17 +1097,18 @@ ImageBitmap::CreateInternal(nsIGlobalObj RefPtr<layers::Image> data = CreateImageFromSurface(surface); if (NS_WARN_IF(!data)) { aRv.Throw(NS_ERROR_NOT_AVAILABLE); return nullptr; } - RefPtr<ImageBitmap> ret = new ImageBitmap(aGlobal, data); + RefPtr<ImageBitmap> ret = + new ImageBitmap(aGlobal, data, writeOnly); ret->mAllocatedImageData = true; // Set the picture rectangle. if (ret && aCropRect.isSome()) { ret->SetPictureRect(aCropRect.ref(), aRv); } @@ -1113,17 +1120,19 @@ ImageBitmap::CreateInternal(nsIGlobalObj const Maybe<IntRect>& aCropRect, ErrorResult& aRv) { if (!aImageBitmap.mData) { aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR); return nullptr; } RefPtr<layers::Image> data = aImageBitmap.mData; - RefPtr<ImageBitmap> ret = new ImageBitmap(aGlobal, data, aImageBitmap.mAlphaType); + RefPtr<ImageBitmap> ret = + new ImageBitmap(aGlobal, data, aImageBitmap.mWriteOnly, + aImageBitmap.mAlphaType); // Set the picture rectangle. if (ret && aCropRect.isSome()) { ret->SetPictureRect(aCropRect.ref(), aRv); } return ret.forget(); } @@ -1427,26 +1436,24 @@ ImageBitmap::ReadStructuredClone(JSConte MOZ_ASSERT(aReader); // aParent might be null. uint32_t picRectX_; uint32_t picRectY_; uint32_t picRectWidth_; uint32_t picRectHeight_; uint32_t alphaType_; - uint32_t dummy; + uint32_t writeOnly; if (!JS_ReadUint32Pair(aReader, &picRectX_, &picRectY_) || !JS_ReadUint32Pair(aReader, &picRectWidth_, &picRectHeight_) || - !JS_ReadUint32Pair(aReader, &alphaType_, &dummy)) { + !JS_ReadUint32Pair(aReader, &alphaType_, &writeOnly)) { return nullptr; } - MOZ_ASSERT(dummy == 0); - int32_t picRectX = BitwiseCast<int32_t>(picRectX_); int32_t picRectY = BitwiseCast<int32_t>(picRectY_); int32_t picRectWidth = BitwiseCast<int32_t>(picRectWidth_); int32_t picRectHeight = BitwiseCast<int32_t>(picRectHeight_); const auto alphaType = BitwiseCast<gfxAlphaType>(alphaType_); // Create a new ImageBitmap. MOZ_ASSERT(!aClonedSurfaces.IsEmpty()); @@ -1460,17 +1467,18 @@ ImageBitmap::ReadStructuredClone(JSConte JS::Rooted<JS::Value> value(aCx); { #ifdef FUZZING if (aIndex >= aClonedSurfaces.Length()) { return nullptr; } #endif RefPtr<layers::Image> img = CreateImageFromSurface(aClonedSurfaces[aIndex]); - RefPtr<ImageBitmap> imageBitmap = new ImageBitmap(aParent, img, alphaType); + RefPtr<ImageBitmap> imageBitmap = + new ImageBitmap(aParent, img, !!writeOnly, alphaType); ErrorResult error; imageBitmap->SetPictureRect(IntRect(picRectX, picRectY, picRectWidth, picRectHeight), error); if (NS_WARN_IF(error.Failed())) { error.SuppressException(); return nullptr; } @@ -1500,17 +1508,17 @@ ImageBitmap::WriteStructuredClone(JSStru const uint32_t alphaType = BitwiseCast<uint32_t>(aImageBitmap->mAlphaType); // Indexing the cloned surfaces and send the index to the receiver. uint32_t index = aClonedSurfaces.Length(); if (NS_WARN_IF(!JS_WriteUint32Pair(aWriter, SCTAG_DOM_IMAGEBITMAP, index)) || NS_WARN_IF(!JS_WriteUint32Pair(aWriter, picRectX, picRectY)) || NS_WARN_IF(!JS_WriteUint32Pair(aWriter, picRectWidth, picRectHeight)) || - NS_WARN_IF(!JS_WriteUint32Pair(aWriter, alphaType, 0))) { + NS_WARN_IF(!JS_WriteUint32Pair(aWriter, alphaType, aImageBitmap->mWriteOnly))) { return false; } RefPtr<SourceSurface> surface = aImageBitmap->mData->GetAsSourceSurface(); RefPtr<DataSourceSurface> snapshot = surface->GetDataSurface(); RefPtr<DataSourceSurface> dstDataSurface; { @@ -1834,17 +1842,18 @@ CreateImageBitmapFromBlob::MimeTypeAndDe }); if (NS_WARN_IF(NS_FAILED(aStatus))) { mPromise->MaybeReject(NS_ERROR_DOM_INVALID_STATE_ERR); return; } // Create ImageBitmap object. - RefPtr<ImageBitmap> imageBitmap = new ImageBitmap(mGlobalObject, aImage); + RefPtr<ImageBitmap> imageBitmap = + new ImageBitmap(mGlobalObject, aImage, false /* write-only */); if (mCropRect.isSome()) { ErrorResult rv; imageBitmap->SetPictureRect(mCropRect.ref(), rv); if (rv.Failed()) { mPromise->MaybeReject(rv); return;
--- a/dom/canvas/ImageBitmap.h +++ b/dom/canvas/ImageBitmap.h @@ -55,16 +55,17 @@ class Promise; class PostMessageEvent; // For StructuredClone between windows. class SVGImageElement; struct ImageBitmapCloneData final { RefPtr<gfx::DataSourceSurface> mSurface; gfx::IntRect mPictureRect; gfxAlphaType mAlphaType; + bool mWriteOnly; }; /* * ImageBitmap is an opaque handler to several kinds of image-like objects from * HTMLImageElement, HTMLVideoElement, HTMLCanvasElement, ImageData to * CanvasRenderingContext2D and Image Blob. * * An ImageBitmap could be painted to a canvas element. @@ -147,16 +148,21 @@ public: friend CreateImageBitmapFromBlob; friend CreateImageBitmapFromBlobTask; friend CreateImageBitmapFromBlobWorkerTask; size_t GetAllocatedSize() const; void OnShutdown(); + bool IsWriteOnly() const + { + return mWriteOnly; + } + protected: /* * The default value of aIsPremultipliedAlpha is TRUE because that the * data stored in HTMLImageElement, HTMLVideoElement, HTMLCanvasElement, * CanvasRenderingContext2D are alpha-premultiplied in default. * * Actually, if one HTMLCanvasElement's rendering context is WebGLContext, it @@ -169,16 +175,17 @@ protected: * re-decoding if the original decoded data is alpha-premultiplied) and * 2) while decoding a blob. But we do not do it in both code path too. * * ImageData's underlying data is triggered as non-premultipliedAlpha, so set * the aIsPremultipliedAlpha to be false in the * CreateInternal(from ImageData) method. */ ImageBitmap(nsIGlobalObject* aGlobal, layers::Image* aData, + bool aWriteOnly, gfxAlphaType aAlphaType = gfxAlphaType::Premult); virtual ~ImageBitmap(); void SetPictureRect(const gfx::IntRect& aRect, ErrorResult& aRv); static already_AddRefed<ImageBitmap> CreateInternal(nsIGlobalObject* aGlobal, HTMLImageElement& aImageEl, @@ -250,16 +257,23 @@ protected: const gfxAlphaType mAlphaType; RefPtr<ImageBitmapShutdownObserver> mShutdownObserver; /* * Whether this object allocated allocated and owns the image data. */ bool mAllocatedImageData; + + /* + * Write-Only flag is set to true if this image has been generated from a + * cross-origin source. This is the opposite of what is called 'origin-clean' + * in the spec. + */ + bool mWriteOnly; }; } // namespace dom } // namespace mozilla #endif // mozilla_dom_ImageBitmap_h
--- a/dom/canvas/WebGLContext.h +++ b/dom/canvas/WebGLContext.h @@ -240,18 +240,21 @@ struct TexImageSourceAdapter final : pub TexImageSourceAdapter(const WebGLsizeiptr* pboOffset, GLuint ignored1, GLuint ignored2 = 0) { mPboOffset = pboOffset; } TexImageSourceAdapter(const WebGLsizeiptr* pboOffset, ErrorResult* ignored) { mPboOffset = pboOffset; } - TexImageSourceAdapter(const dom::ImageBitmap* imageBitmap, ErrorResult*) { + TexImageSourceAdapter(const dom::ImageBitmap* imageBitmap, + ErrorResult* out_error) + { mImageBitmap = imageBitmap; + mOut_error = out_error; } TexImageSourceAdapter(const dom::ImageData* imageData, ErrorResult*) { mImageData = imageData; } TexImageSourceAdapter(const dom::Element* domElem, ErrorResult* const out_error) { mDomElem = domElem;
--- a/dom/canvas/WebGLTextureUpload.cpp +++ b/dom/canvas/WebGLTextureUpload.cpp @@ -7,16 +7,17 @@ #include <algorithm> #include "CanvasUtils.h" #include "gfxPrefs.h" #include "GLBlitHelper.h" #include "GLContext.h" #include "mozilla/gfx/2D.h" +#include "mozilla/dom/HTMLCanvasElement.h" #include "mozilla/dom/HTMLVideoElement.h" #include "mozilla/dom/ImageBitmap.h" #include "mozilla/dom/ImageData.h" #include "mozilla/MathAlgorithms.h" #include "mozilla/Scoped.h" #include "mozilla/Unused.h" #include "ScopedGLHelpers.h" #include "TexUnpackBlob.h" @@ -217,21 +218,26 @@ FromPboOffset(WebGLContext* webgl, TexIm const auto ptr = (const uint8_t*)pboOffset; return MakeUnique<webgl::TexUnpackBytes>(webgl, target, width, height, depth, isClientData, ptr, availBufferBytes); } static UniquePtr<webgl::TexUnpackBlob> FromImageBitmap(WebGLContext* webgl, TexImageTarget target, uint32_t width, uint32_t height, uint32_t depth, - const dom::ImageBitmap& imageBitmap) + const dom::ImageBitmap& imageBitmap, ErrorResult* aRv) { + if (imageBitmap.IsWriteOnly()) { + aRv->Throw(NS_ERROR_DOM_SECURITY_ERR); + return nullptr; + } + UniquePtr<dom::ImageBitmapCloneData> cloneData = imageBitmap.ToCloneData(); if (!cloneData) { - return nullptr; + return nullptr; } const RefPtr<gfx::DataSourceSurface> surf = cloneData->mSurface; if (!width) { width = surf->GetSize().width; } @@ -295,16 +301,24 @@ FromImageData(WebGLContext* webgl, TexIm alphaType); } UniquePtr<webgl::TexUnpackBlob> WebGLContext::FromDomElem(TexImageTarget target, uint32_t width, uint32_t height, uint32_t depth, const dom::Element& elem, ErrorResult* const out_error) { + if (elem.IsHTMLElement(nsGkAtoms::canvas)) { + const dom::HTMLCanvasElement* canvas = static_cast<const dom::HTMLCanvasElement*>(&elem); + if (canvas->IsWriteOnly()) { + out_error->Throw(NS_ERROR_DOM_SECURITY_ERR); + return nullptr; + } + } + // The canvas spec says that drawImage should draw the first frame of // animated images. The webgl spec doesn't mention the issue, so we do the // same as drawImage. uint32_t flags = nsLayoutUtils::SFE_WANT_FIRST_FRAME_IF_IMAGE | nsLayoutUtils::SFE_WANT_IMAGE_SURFACE | nsLayoutUtils::SFE_USE_ELEMENT_SIZE_IF_VECTOR; if (mPixelStore_ColorspaceConversion == LOCAL_GL_NONE) @@ -416,17 +430,17 @@ WebGLContext::From(TexImageTarget target if (mBoundPixelUnpackBuffer) { ErrorInvalidOperation("PIXEL_UNPACK_BUFFER must be null."); return nullptr; } if (src.mImageBitmap) { return FromImageBitmap(this, target, width, height, depth, - *(src.mImageBitmap)); + *(src.mImageBitmap), src.mOut_error); } if (src.mImageData) { return FromImageData(this, target, width, height, depth, *(src.mImageData), scopedArr); } if (src.mDomElem) {
--- a/dom/canvas/test/test_imagebitmap.html +++ b/dom/canvas/test/test_imagebitmap.html @@ -265,23 +265,32 @@ function testSecurityErrors() { reject(); } uncleanImage.src = "http://example.com/tests/dom/canvas/test/crossorigin/image.png"; }); } function checkPromiseFailedWithSecurityError(p) { - return p.then( function(reason) { ok(false, "Did not get SecurityError with unclean source. ImageBitmap was created successfully."); }, - function(reason) { if (reason == "SecurityError: The operation is insecure.") { - ok(true, reason); - } - else { - ok(false, "Did not get SecurityError with unclean source. Error Message: " + reason); - }}); + return p.then(imageBitmap => { + ok(!!imageBitmap, "ImageBitmaps are always created"); + const context = document.createElement("canvas").getContext("2d"); + context.drawImage(imageBitmap, 0, 0); + try { + context.getImageData(0, 0, 1, 1); + ok(false, "Did not get SecurityError with unclean source. ImageBitmap was created successfully."); + } catch (ex) { + if (ex == "SecurityError: The operation is insecure.") { + ok(true, ex); + } + else { + ok(false, "Did not get SecurityError with unclean source. Error Message: " + ex); + } + } + }); } return Promise.all([ checkPromiseFailedWithSecurityError(getUncleanImagePromise()), checkPromiseFailedWithSecurityError(getUncleanVideoPromise()), checkPromiseFailedWithSecurityError(getTaintedCanvasPromise()), checkPromiseFailedWithSecurityError(getTaintedCanvasRenderingContex2dPromise()), ]);
--- a/dom/html/HTMLCanvasElement.cpp +++ b/dom/html/HTMLCanvasElement.cpp @@ -1078,17 +1078,17 @@ HTMLCanvasElement::MozGetIPCContext(cons nsIntSize HTMLCanvasElement::GetSize() { return GetWidthHeight(); } bool -HTMLCanvasElement::IsWriteOnly() +HTMLCanvasElement::IsWriteOnly() const { return mWriteOnly; } void HTMLCanvasElement::SetWriteOnly() { mExpandedReader = nullptr;
--- a/dom/html/HTMLCanvasElement.h +++ b/dom/html/HTMLCanvasElement.h @@ -218,17 +218,17 @@ public: /** * Get the size in pixels of this canvas element */ nsIntSize GetSize(); /** * Determine whether the canvas is write-only. */ - bool IsWriteOnly(); + bool IsWriteOnly() const; /** * Force the canvas to be write-only. */ void SetWriteOnly(); /** * Force the canvas to be write-only, except for readers from
--- a/dom/ipc/ContentChild.cpp +++ b/dom/ipc/ContentChild.cpp @@ -63,17 +63,16 @@ #include "mozilla/intl/LocaleService.h" #include "mozilla/ipc/TestShellChild.h" #include "mozilla/jsipc/CrossProcessObjectWrappers.h" #include "mozilla/jsipc/PJavaScript.h" #include "mozilla/layers/APZChild.h" #include "mozilla/layers/CompositorManagerChild.h" #include "mozilla/layers/ContentProcessController.h" #include "mozilla/layers/ImageBridgeChild.h" -#include "mozilla/layout/RenderFrameChild.h" #include "mozilla/loader/ScriptCacheActors.h" #include "mozilla/net/NeckoChild.h" #include "mozilla/net/CookieServiceChild.h" #include "mozilla/net/CaptivePortalService.h" #include "mozilla/PerformanceMetricsCollector.h" #include "mozilla/PerformanceUtils.h" #include "mozilla/plugins/PluginInstanceParent.h" #include "mozilla/plugins/PluginModuleParent.h" @@ -967,19 +966,16 @@ ContentChild::ProvideWindowCommon(TabChi SetEventTargetForActor(newChild, target); Unused << SendPBrowserConstructor( // We release this ref in DeallocPBrowserChild RefPtr<TabChild>(newChild).forget().take(), tabId, TabId(0), *ipcContext, aChromeFlags, GetID(), IsForBrowser()); - - PRenderFrameChild* renderFrame = newChild->SendPRenderFrameConstructor(); - nsCOMPtr<nsPIDOMWindowInner> parentTopInnerWindow; if (aParent) { nsCOMPtr<nsPIDOMWindowOuter> parentTopWindow = nsPIDOMWindowOuter::From(aParent)->GetTop(); if (parentTopWindow) { parentTopInnerWindow = parentTopWindow->GetCurrentInnerWindow(); } } @@ -990,19 +986,16 @@ ContentChild::ProvideWindowCommon(TabChi // NOTE: Capturing by reference here is safe, as this function won't return // until one of these callbacks is called. auto resolve = [&] (const CreatedWindowInfo& info) { MOZ_RELEASE_ASSERT(NS_IsMainThread()); rv = info.rv(); *aWindowIsNew = info.windowOpened(); nsTArray<FrameScriptInfo> frameScripts(info.frameScripts()); nsCString urlToLoad = info.urlToLoad(); - TextureFactoryIdentifier textureFactoryIdentifier = info.textureFactoryIdentifier(); - layers::LayersId layersId = info.layersId(); - CompositorOptions compositorOptions = info.compositorOptions(); uint32_t maxTouchPoints = info.maxTouchPoints(); DimensionInfo dimensionInfo = info.dimensions(); bool hasSiblings = info.hasSiblings(); // Once this function exits, we should try to exit the nested event loop. ready = true; // NOTE: We have to handle this immediately in the resolve callback in order @@ -1021,20 +1014,16 @@ ContentChild::ProvideWindowCommon(TabChi } // If the TabChild has been torn down, we don't need to do this anymore. if (NS_WARN_IF(!newChild->IPCOpen() || newChild->IsDestroyed())) { rv = NS_ERROR_ABORT; return; } - if (!layersId.IsValid()) { // if renderFrame is invalid. - renderFrame = nullptr; - } - ShowInfo showInfo(EmptyString(), false, false, true, false, 0, 0, 0); auto* opener = nsPIDOMWindowOuter::From(aParent); nsIDocShell* openerShell; if (opener && (openerShell = opener->GetDocShell())) { nsCOMPtr<nsILoadContext> context = do_QueryInterface(openerShell); showInfo = ShowInfo(EmptyString(), false, context->UsePrivateBrowsing(), true, false, aTabOpener->WebWidget()->GetDPI(), @@ -1053,18 +1042,17 @@ ContentChild::ProvideWindowCommon(TabChi if (!aForceNoOpener && windowProxy && aParent) { nsPIDOMWindowOuter* outer = nsPIDOMWindowOuter::From(windowProxy); nsPIDOMWindowOuter* parent = nsPIDOMWindowOuter::From(aParent); outer->SetOpenerWindow(parent, *aWindowIsNew); } // Unfortunately we don't get a window unless we've shown the frame. That's // pretty bogus; see bug 763602. - newChild->DoFakeShow(textureFactoryIdentifier, layersId, compositorOptions, - renderFrame, showInfo); + newChild->DoFakeShow(showInfo); newChild->RecvUpdateDimensions(dimensionInfo); for (size_t i = 0; i < frameScripts.Length(); i++) { FrameScriptInfo& info = frameScripts[i]; if (!newChild->RecvLoadRemoteScript(info.url(), info.runInGlobalScope())) { MOZ_CRASH(); } @@ -1097,17 +1085,17 @@ ContentChild::ProvideWindowCommon(TabChi // We can't actually send a nullptr up as the URI, since IPDL doesn't let us // send nullptr's for primitives. We indicate that the nsString for the URI // should be converted to a nullptr by voiding the string. url.SetIsVoid(true); } // NOTE: BrowserFrameOpenWindowPromise is the same type as // CreateWindowPromise, and this code depends on that fact. - newChild->SendBrowserFrameOpenWindow(aTabOpener, renderFrame, + newChild->SendBrowserFrameOpenWindow(aTabOpener, NS_ConvertUTF8toUTF16(url), name, NS_ConvertUTF8toUTF16(features), std::move(resolve), std::move(reject)); } else { nsAutoCString baseURIString; float fullZoom; nsCOMPtr<nsIPrincipal> triggeringPrincipal; uint32_t referrerPolicy = mozilla::net::RP_Unset; @@ -1120,17 +1108,17 @@ ContentChild::ProvideWindowCommon(TabChi OptionalURIParams uriToLoad; if (aURI) { SerializeURI(aURI, uriToLoad); } else { uriToLoad = mozilla::void_t(); } - SendCreateWindow(aTabOpener, newChild, renderFrame, + SendCreateWindow(aTabOpener, newChild, aChromeFlags, aCalledFromJS, aPositionSpecified, aSizeSpecified, uriToLoad, features, baseURIString, fullZoom, Principal(triggeringPrincipal), referrerPolicy, std::move(resolve), std::move(reject)); } // ======================= // Begin Nested Event Loop
--- a/dom/ipc/ContentParent.cpp +++ b/dom/ipc/ContentParent.cpp @@ -78,17 +78,16 @@ #include "mozilla/ipc/TestShellParent.h" #include "mozilla/ipc/IPCStreamUtils.h" #include "mozilla/intl/LocaleService.h" #include "mozilla/jsipc/CrossProcessObjectWrappers.h" #include "mozilla/layers/PAPZParent.h" #include "mozilla/layers/CompositorThread.h" #include "mozilla/layers/ImageBridgeParent.h" #include "mozilla/layers/LayerTreeOwnerTracker.h" -#include "mozilla/layout/RenderFrameParent.h" #include "mozilla/loader/ScriptCacheActors.h" #include "mozilla/LoginReputationIPC.h" #include "mozilla/LookAndFeel.h" #include "mozilla/media/MediaParent.h" #include "mozilla/Move.h" #include "mozilla/net/NeckoParent.h" #include "mozilla/net/CookieServiceParent.h" #include "mozilla/net/PCookieServiceParent.h" @@ -1256,17 +1255,16 @@ ContentParent::CreateBrowser(const TabCo chromeFlags |= nsIWebBrowserChrome::CHROME_PRIVATE_LIFETIME; } if (tabId == 0) { return nullptr; } RefPtr<TabParent> tp(new TabParent(constructorSender, tabId, aContext, chromeFlags)); - tp->SetInitedByParent(); PBrowserParent* browser = constructorSender->SendPBrowserConstructor( // DeallocPBrowserParent() releases this ref. tp.forget().take(), tabId, aSameTabGroupAs ? aSameTabGroupAs->GetTabId() : TabId(0), aContext.AsIPCTabContext(), chromeFlags, @@ -1652,91 +1650,16 @@ ContentParent::ProcessingError(Result aC return; } #ifndef FUZZING // Other errors are big deals. KillHard(aReason); #endif } -/* static */ -bool -ContentParent::AllocateLayerTreeId(TabParent* aTabParent, layers::LayersId* aId) -{ - return AllocateLayerTreeId(aTabParent->Manager()->AsContentParent(), - aTabParent, aTabParent->GetTabId(), aId); -} - -/* static */ -bool -ContentParent::AllocateLayerTreeId(ContentParent* aContent, - TabParent* aTopLevel, const TabId& aTabId, - layers::LayersId* aId) -{ - GPUProcessManager* gpu = GPUProcessManager::Get(); - - *aId = gpu->AllocateLayerTreeId(); - - if (!aContent || !aTopLevel) { - return false; - } - - gpu->MapLayerTreeId(*aId, aContent->OtherPid()); - - return true; -} - -mozilla::ipc::IPCResult -ContentParent::RecvAllocateLayerTreeId(const ContentParentId& aCpId, - const TabId& aTabId, layers::LayersId* aId) -{ - // Protect against spoofing by a compromised child. aCpId must either - // correspond to the process that this ContentParent represents or be a - // child of it. - ContentProcessManager* cpm = ContentProcessManager::GetSingleton(); - RefPtr<ContentParent> contentParent = cpm->GetContentProcessById(aCpId); - if (!contentParent || - (ChildID() != aCpId && !contentParent->CanCommunicateWith(ChildID()))) { - return IPC_FAIL_NO_REASON(this); - } - - // GetTopLevelTabParentByProcessAndTabId will make sure that aTabId - // lives in the process for aCpId. - RefPtr<TabParent> browserParent = - cpm->GetTopLevelTabParentByProcessAndTabId(aCpId, aTabId); - MOZ_ASSERT(contentParent && browserParent); - - if (!AllocateLayerTreeId(contentParent, browserParent, aTabId, aId)) { - return IPC_FAIL_NO_REASON(this); - } - return IPC_OK(); -} - -mozilla::ipc::IPCResult -ContentParent::RecvDeallocateLayerTreeId(const ContentParentId& aCpId, - const layers::LayersId& aId) -{ - GPUProcessManager* gpu = GPUProcessManager::Get(); - - ContentProcessManager* cpm = ContentProcessManager::GetSingleton(); - RefPtr<ContentParent> contentParent = cpm->GetContentProcessById(aCpId); - if (!contentParent || !contentParent->CanCommunicateWith(ChildID())) { - return IPC_FAIL(this, "Spoofed DeallocateLayerTreeId call"); - } - - if (!gpu->IsLayerTreeIdMapped(aId, contentParent->OtherPid())) { - // You can't deallocate layer tree ids that you didn't allocate - KillHard("DeallocateLayerTreeId"); - } - - gpu->UnmapLayerTreeId(aId, contentParent->OtherPid()); - - return IPC_OK(); -} - namespace { void DelayedDeleteSubprocess(GeckoChildProcessHost* aSubprocess) { RefPtr<DeleteTask<GeckoChildProcessHost>> task = new DeleteTask<GeckoChildProcessHost>(aSubprocess); XRE_GetIOMessageLoop()->PostTask(task.forget()); } @@ -5156,17 +5079,16 @@ ContentParent::CommonCreateWindow(PBrows } return IPC_OK(); } mozilla::ipc::IPCResult ContentParent::RecvCreateWindow(PBrowserParent* aThisTab, PBrowserParent* aNewTab, - PRenderFrameParent* aRenderFrame, const uint32_t& aChromeFlags, const bool& aCalledFromJS, const bool& aPositionSpecified, const bool& aSizeSpecified, const OptionalURIParams& aURIToLoad, const nsCString& aFeatures, const nsCString& aBaseURI, const float& aFullZoom, @@ -5174,17 +5096,16 @@ ContentParent::RecvCreateWindow(PBrowser const uint32_t& aReferrerPolicy, CreateWindowResolver&& aResolve) { nsresult rv = NS_OK; CreatedWindowInfo cwi; // We always expect to open a new window here. If we don't, it's an error. cwi.windowOpened() = true; - cwi.layersId() = LayersId{0}; cwi.maxTouchPoints() = 0; cwi.hasSiblings() = false; // Make sure to resolve the resolver when this function exits, even if we // failed to generate a valid response. auto resolveOnExit = MakeScopeExit([&] { // Copy over the nsresult, and then resolve. cwi.rv() = rv; @@ -5232,23 +5153,17 @@ ContentParent::RecvCreateWindow(PBrowser } if (sNextTabParents.GetAndRemove(nextTabParentId).valueOr(nullptr)) { cwi.windowOpened() = false; } MOZ_ASSERT(TabParent::GetFrom(newRemoteTab) == newTab); newTab->SwapFrameScriptsFrom(cwi.frameScripts()); - - RenderFrameParent* rfp = static_cast<RenderFrameParent*>(aRenderFrame); - if (!newTab->SetRenderFrame(rfp) || - !newTab->GetRenderFrameInfo(&cwi.textureFactoryIdentifier(), &cwi.layersId())) { - rv = NS_ERROR_FAILURE; - } - cwi.compositorOptions() = rfp->GetCompositorOptions(); + newTab->MaybeShowFrame(); nsCOMPtr<nsIWidget> widget = newTab->GetWidget(); if (widget) { cwi.maxTouchPoints() = widget->GetMaxTouchPoints(); cwi.dimensions() = newTab->GetDimensionInfo(); } cwi.hasSiblings() = (openLocation == nsIBrowserDOMWindow::OPEN_NEWTAB);
--- a/dom/ipc/ContentParent.h +++ b/dom/ipc/ContentParent.h @@ -87,20 +87,16 @@ class ProtocolFuzzerHelper; namespace jsipc { class PJavaScriptParent; } // namespace jsipc namespace layers { struct TextureFactoryIdentifier; } // namespace layers -namespace layout { -class PRenderFrameParent; -} // namespace layout - namespace dom { class Element; class TabParent; class ClonedMessageData; class MemoryReport; class TabContext; class ContentBridgeParent; @@ -538,17 +534,16 @@ public: virtual bool HandleWindowsMessages(const Message& aMsg) const override; void ForkNewProcess(bool aBlocking); virtual mozilla::ipc::IPCResult RecvCreateWindow(PBrowserParent* aThisTabParent, PBrowserParent* aNewTab, - layout::PRenderFrameParent* aRenderFrame, const uint32_t& aChromeFlags, const bool& aCalledFromJS, const bool& aPositionSpecified, const bool& aSizeSpecified, const OptionalURIParams& aURIToLoad, const nsCString& aFeatures, const nsCString& aBaseURI, const float& aFullZoom, @@ -565,18 +560,16 @@ public: const OptionalURIParams& aURIToLoad, const nsCString& aFeatures, const nsCString& aBaseURI, const float& aFullZoom, const nsString& aName, const IPC::Principal& aTriggeringPrincipal, const uint32_t& aReferrerPolicy) override; - static bool AllocateLayerTreeId(TabParent* aTabParent, layers::LayersId* aId); - static void BroadcastBlobURLRegistration(const nsACString& aURI, BlobImpl* aBlobImpl, nsIPrincipal* aPrincipal, ContentParent* aIgnoreThisCP = nullptr); static void BroadcastBlobURLUnregistration(const nsACString& aURI, @@ -865,20 +858,16 @@ private: // content process. // // See nsIPermissionManager::GetPermissionsForKey for more information on // these keys. void EnsurePermissionsByKey(const nsCString& aKey); static void ForceKillTimerCallback(nsITimer* aTimer, void* aClosure); - static bool AllocateLayerTreeId(ContentParent* aContent, - TabParent* aTopLevel, const TabId& aTabId, - layers::LayersId* aId); - /** * Get or create the corresponding content parent array to |aContentProcessType|. */ static nsTArray<ContentParent*>& GetOrCreatePool(const nsAString& aContentProcessType); virtual mozilla::ipc::IPCResult RecvInitBackground(Endpoint<mozilla::ipc::PBackgroundParent>&& aEndpoint) override; mozilla::ipc::IPCResult RecvAddMemoryReport(const MemoryReport& aReport) override; @@ -1135,23 +1124,16 @@ public: virtual mozilla::ipc::IPCResult RecvCopyFavicon(const URIParams& aOldURI, const URIParams& aNewURI, const IPC::Principal& aLoadingPrincipal, const bool& aInPrivateBrowsing) override; virtual void ProcessingError(Result aCode, const char* aMsgName) override; - virtual mozilla::ipc::IPCResult RecvAllocateLayerTreeId(const ContentParentId& aCpId, - const TabId& aTabId, - layers::LayersId* aId) override; - - virtual mozilla::ipc::IPCResult RecvDeallocateLayerTreeId(const ContentParentId& aCpId, - const layers::LayersId& aId) override; - virtual mozilla::ipc::IPCResult RecvGraphicsError(const nsCString& aError) override; virtual mozilla::ipc::IPCResult RecvBeginDriverCrashGuard(const uint32_t& aGuardType, bool* aOutCrashed) override; virtual mozilla::ipc::IPCResult RecvEndDriverCrashGuard(const uint32_t& aGuardType) override;
--- a/dom/ipc/DOMTypes.ipdlh +++ b/dom/ipc/DOMTypes.ipdlh @@ -20,19 +20,16 @@ using struct mozilla::SerializedStructur using LayoutDeviceIntRect from "Units.h"; using DesktopIntRect from "Units.h"; using DesktopToLayoutDeviceScale from "Units.h"; using CSSToLayoutDeviceScale from "Units.h"; using CSSRect from "Units.h"; using CSSSize from "Units.h"; using mozilla::LayoutDeviceIntPoint from "Units.h"; using hal::ScreenOrientation from "mozilla/HalScreenConfiguration.h"; -using struct mozilla::layers::TextureFactoryIdentifier from "mozilla/layers/CompositorTypes.h"; -using mozilla::layers::CompositorOptions from "mozilla/layers/CompositorOptions.h"; -using mozilla::layers::LayersId from "mozilla/layers/LayersTypes.h"; using mozilla::gfx::SurfaceFormat from "mozilla/gfx/Types.h"; namespace mozilla { namespace dom { struct MessagePortIdentifier { @@ -115,19 +112,16 @@ struct FrameScriptInfo * The information required to complete a window creation request. */ struct CreatedWindowInfo { nsresult rv; bool windowOpened; FrameScriptInfo[] frameScripts; nsCString urlToLoad; - TextureFactoryIdentifier textureFactoryIdentifier; - LayersId layersId; - CompositorOptions compositorOptions; uint32_t maxTouchPoints; DimensionInfo dimensions; bool hasSiblings; }; /** * PerformanceInfo is used to pass performance info stored
--- a/dom/ipc/PBrowser.ipdl +++ b/dom/ipc/PBrowser.ipdl @@ -6,17 +6,16 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ include protocol PColorPicker; include protocol PContent; include protocol PContentBridge; include protocol PDocAccessible; include protocol PFilePicker; include protocol PIndexedDBPermissionRequest; -include protocol PRenderFrame; include protocol PPluginWidget; include protocol PRemotePrintJob; include protocol PChildToParentStream; include protocol PParentToChildStream; include protocol PFileDescriptorSet; include protocol PIPCBlobInputStream; include protocol PPaymentRequest; @@ -112,30 +111,23 @@ union OptionalShmem nested(upto inside_cpow) sync protocol PBrowser { manager PContent or PContentBridge; manages PColorPicker; manages PDocAccessible; manages PFilePicker; manages PIndexedDBPermissionRequest; - manages PRenderFrame; manages PPluginWidget; manages PPaymentRequest; both: async AsyncMessage(nsString aMessage, CpowEntry[] aCpows, Principal aPrincipal, ClonedMessageData aData); - /** - * Create a layout frame (encapsulating a remote layer tree) for - * the page that is currently loaded in the <browser>. - */ - async PRenderFrame(); - parent: /** * Tell the parent process a new accessible document has been created. * aParentDoc is the accessible document it was created in if any, and * aParentAcc is the id of the accessible in that document the new document * is a child of. aMsaaID is the MSAA id for this content process, and * is only valid on Windows. Set to 0 on other platforms. aDocCOMProxy * is also Windows-specific and should be set to 0 on other platforms. @@ -434,17 +426,17 @@ parent: * process), then calls BrowserFrameOpenWindow on it. * * The parent process gets a chance to accept or reject the window.open * call, and windowOpened is set to true if we ended up going through with * the window.open. * * @param opener the PBrowser whose content called window.open. */ - async BrowserFrameOpenWindow(PBrowser opener, PRenderFrame renderFrame, + async BrowserFrameOpenWindow(PBrowser opener, nsString aURL, nsString aName, nsString aFeatures) returns (CreatedWindowInfo window); /** * Tells the containing widget whether the given input block results in a * swipe. Should be called in response to a WidgetWheelEvent that has * mFlags.mCanTriggerSwipe set on it. */ @@ -530,16 +522,21 @@ parent: * compositing. This is sent when all pending changes have been * sent to the compositor and are ready to be shown on the next composite. * @see PCompositor * @see RequestNotifyAfterRemotePaint */ async RemotePaintIsReady(); /** + * Child informs the parent that a compositor transaction has ocurred. + */ + async NotifyCompositorTransaction(); + + /** * Child informs the parent that the content is ready to handle input * events. This is sent when the TabChild is created. */ async RemoteIsReadyToHandleInputEvents(); /** * Child informs the parent that the layer tree is already available. */ @@ -595,18 +592,17 @@ child: async Show(ScreenIntSize size, ShowInfo info, bool parentIsActive, nsSizeMode sizeMode); async InitRendering(TextureFactoryIdentifier textureFactoryIdentifier, LayersId layersId, CompositorOptions compositorOptions, - bool layersConnected, - nullable PRenderFrame renderFrame); + bool layersConnected); async LoadURL(nsCString uri, ShowInfo info); async UpdateDimensions(DimensionInfo dimensions) compressall; async SizeModeChanged(nsSizeMode sizeMode); async ParentActivated(bool aActivated);
--- a/dom/ipc/PContent.ipdl +++ b/dom/ipc/PContent.ipdl @@ -27,17 +27,16 @@ include protocol PStreamFilter; include protocol PGMPContent; include protocol PGMPService; include protocol PPluginModule; include protocol PGMP; include protocol PPrinting; include protocol PChildToParentStream; include protocol PParentToChildStream; include protocol POfflineCacheUpdate; -include protocol PRenderFrame; include protocol PSpeechSynthesis; include protocol PTestShell; include protocol PJavaScript; include protocol PRemoteSpellcheckEngine; include protocol PWebBrowserPersistDocument; include protocol PWebrtcGlobal; include protocol PPresentation; include protocol PURLClassifier; @@ -908,21 +907,16 @@ parent: sync KeywordToURI(nsCString keyword) returns (nsString providerName, nsIInputStream postData, OptionalURIParams uri); sync NotifyKeywordSearchLoading(nsString providerName, nsString keyword); async CopyFavicon(URIParams oldURI, URIParams newURI, Principal aLoadingPrincipal, bool isPrivate); - // Tell the compositor to allocate a layer tree id for nested remote mozbrowsers. - sync AllocateLayerTreeId(ContentParentId cpId, TabId tabId) - returns (LayersId id); - async DeallocateLayerTreeId(ContentParentId cpId, LayersId id); - /** * Notifies the parent about a recording device is starting or shutdown. * @param recordingStatus starting or shutdown * @param pageURL URL that request that changing the recording status * @param isAudio recording start with microphone * @param isVideo recording start with camera */ async RecordingDeviceEvents(nsString recordingStatus, @@ -1049,17 +1043,16 @@ parent: /** * Request graphics initialization information from the parent. */ sync GetGraphicsDeviceInitData() returns (ContentDeviceData aData); async CreateWindow(nullable PBrowser aThisTab, PBrowser aNewTab, - PRenderFrame aRenderFrame, uint32_t aChromeFlags, bool aCalledFromJS, bool aPositionSpecified, bool aSizeSpecified, OptionalURIParams aURIToLoad, nsCString aFeatures, nsCString aBaseURI, float aFullZoom,
--- a/dom/ipc/TabChild.cpp +++ b/dom/ipc/TabChild.cpp @@ -37,18 +37,16 @@ #include "mozilla/layers/CompositorBridgeChild.h" #include "mozilla/layers/DoubleTapToZoom.h" #include "mozilla/layers/IAPZCTreeManager.h" #include "mozilla/layers/ImageBridgeChild.h" #include "mozilla/layers/InputAPZContext.h" #include "mozilla/layers/LayerTransactionChild.h" #include "mozilla/layers/ShadowLayers.h" #include "mozilla/layers/WebRenderLayerManager.h" -#include "mozilla/layout/RenderFrameChild.h" -#include "mozilla/layout/RenderFrameParent.h" #include "mozilla/plugins/PPluginWidgetChild.h" #include "mozilla/recordreplay/ParentIPC.h" #include "mozilla/LookAndFeel.h" #include "mozilla/MouseEvents.h" #include "mozilla/Move.h" #include "mozilla/PresShell.h" #include "mozilla/ProcessHangMonitor.h" #include "mozilla/ScopeExit.h" @@ -392,17 +390,16 @@ TabChild::Create(nsIContentChild* aManag TabChild::TabChild(nsIContentChild* aManager, const TabId& aTabId, dom::TabGroup* aTabGroup, const TabContext& aContext, uint32_t aChromeFlags) : TabContext(aContext) , mTabGroup(aTabGroup) - , mRemoteFrame(nullptr) , mManager(aManager) , mChromeFlags(aChromeFlags) , mMaxTouchPoints(0) , mLayersId{0} , mBeforeUnloadListeners(0) , mDidFakeShow(false) , mNotified(false) , mTriedBrowserInit(false) @@ -803,20 +800,20 @@ TabChild::IsWindowModal(bool* aRetVal) return NS_OK; } NS_IMETHODIMP TabChild::SetStatusWithContext(uint32_t aStatusType, const nsAString& aStatusText, nsISupports* aStatusContext) { - // We can only send the status after the ipc machinery is set up, - // mRemoteFrame is a good indicator. - if (mRemoteFrame) + // We can only send the status after the ipc machinery is set up + if (IPCOpen()) { SendSetStatus(aStatusType, nsString(aStatusText)); + } return NS_OK; } NS_IMETHODIMP TabChild::SetDimensions(uint32_t aFlags, int32_t aX, int32_t aY, int32_t aCx, int32_t aCy) { // The parent is in charge of the dimension changes. If JS code wants to @@ -1021,28 +1018,21 @@ TabChild::DestroyWindow() static_cast<CoalescedMouseData*>(mToBeDispatchedMouseData.PopFront())); data.reset(); } nsCOMPtr<nsIBaseWindow> baseWindow = do_QueryInterface(WebNavigation()); if (baseWindow) baseWindow->Destroy(); - // NB: the order of mPuppetWidget->Destroy() and mRemoteFrame->Destroy() - // is important: we want to kill off remote layers before their - // frames if (mPuppetWidget) { mPuppetWidget->Destroy(); } - if (mRemoteFrame) { - mRemoteFrame->Destroy(); - mRemoteFrame = nullptr; - } - + mLayersConnected = Nothing(); if (mLayersId.IsValid()) { StaticMutexAutoLock lock(sTabChildrenMutex); MOZ_ASSERT(sTabChildren); sTabChildren->Remove(uint64_t(mLayersId)); if (!sTabChildren->Count()) { delete sTabChildren; @@ -1124,23 +1114,18 @@ TabChild::RecvLoadURL(const nsCString& a } CrashReporter::AnnotateCrashReport(CrashReporter::Annotation::URL, aURI); return IPC_OK(); } void -TabChild::DoFakeShow(const TextureFactoryIdentifier& aTextureFactoryIdentifier, - const layers::LayersId& aLayersId, - const CompositorOptions& aCompositorOptions, - PRenderFrameChild* aRenderFrame, const ShowInfo& aShowInfo) +TabChild::DoFakeShow(const ShowInfo& aShowInfo) { - mLayersConnected = aRenderFrame ? Some(true) : Some(false); - InitRenderingState(aTextureFactoryIdentifier, aLayersId, aCompositorOptions, aRenderFrame); RecvShow(ScreenIntSize(0, 0), aShowInfo, mParentIsActive, nsSizeMode_Normal); mDidFakeShow = true; } void TabChild::ApplyShowInfo(const ShowInfo& aInfo) { // Even if we already set real show info, the dpi / rounding & scale may still @@ -1231,32 +1216,29 @@ TabChild::RecvShow(const ScreenIntSize& return IPC_OK(); } mozilla::ipc::IPCResult TabChild::RecvInitRendering(const TextureFactoryIdentifier& aTextureFactoryIdentifier, const layers::LayersId& aLayersId, const CompositorOptions& aCompositorOptions, - const bool& aLayersConnected, - PRenderFrameChild* aRenderFrame) + const bool& aLayersConnected) { - MOZ_ASSERT((!mDidFakeShow && aRenderFrame) || (mDidFakeShow && !aRenderFrame)); - mLayersConnected = Some(aLayersConnected); - InitRenderingState(aTextureFactoryIdentifier, aLayersId, aCompositorOptions, aRenderFrame); + InitRenderingState(aTextureFactoryIdentifier, aLayersId, aCompositorOptions); return IPC_OK(); } mozilla::ipc::IPCResult TabChild::RecvUpdateDimensions(const DimensionInfo& aDimensionInfo) { // When recording/replaying we need to make sure the dimensions are up to // date on the compositor used in this process. - if (!mRemoteFrame && !recordreplay::IsRecordingOrReplaying()) { + if (mLayersConnected.isNothing() && !recordreplay::IsRecordingOrReplaying()) { return IPC_OK(); } mUnscaledOuterRect = aDimensionInfo.rect(); mClientOffset = aDimensionInfo.clientOffset(); mChromeOffset = aDimensionInfo.chromeOffset(); mOrientation = aDimensionInfo.orientation(); @@ -2726,29 +2708,16 @@ TabChild::RecvHandledWindowedPluginKeyEv { if (NS_WARN_IF(!mPuppetWidget)) { return IPC_OK(); } mPuppetWidget->HandledWindowedPluginKeyEvent(aKeyEventData, aIsConsumed); return IPC_OK(); } -PRenderFrameChild* -TabChild::AllocPRenderFrameChild() -{ - return new RenderFrameChild(); -} - -bool -TabChild::DeallocPRenderFrameChild(PRenderFrameChild* aFrame) -{ - delete aFrame; - return true; -} - bool TabChild::InitTabChildMessageManager() { if (!mTabChildMessageManager) { nsCOMPtr<nsPIDOMWindowOuter> window = do_GetInterface(WebNavigation()); NS_ENSURE_TRUE(window, false); nsCOMPtr<EventTarget> chromeHandler = window->GetChromeEventHandler(); NS_ENSURE_TRUE(chromeHandler, false); @@ -2775,42 +2744,34 @@ TabChild::InitTabChildMessageManager() } return true; } void TabChild::InitRenderingState(const TextureFactoryIdentifier& aTextureFactoryIdentifier, const layers::LayersId& aLayersId, - const CompositorOptions& aCompositorOptions, - PRenderFrameChild* aRenderFrame) + const CompositorOptions& aCompositorOptions) { mPuppetWidget->InitIMEState(); - if (!aRenderFrame) { - mLayersConnected = Some(false); - NS_WARNING("failed to construct RenderFrame"); - return; - } - MOZ_ASSERT(aLayersId.IsValid()); mTextureFactoryIdentifier = aTextureFactoryIdentifier; // Pushing layers transactions directly to a separate // compositor context. PCompositorBridgeChild* compositorChild = CompositorBridgeChild::Get(); if (!compositorChild) { mLayersConnected = Some(false); NS_WARNING("failed to get CompositorBridgeChild instance"); return; } mCompositorOptions = Some(aCompositorOptions); - mRemoteFrame = static_cast<RenderFrameChild*>(aRenderFrame); if (aLayersId.IsValid()) { StaticMutexAutoLock lock(sTabChildrenMutex); if (!sTabChildren) { sTabChildren = new TabChildMap; } MOZ_ASSERT(!sTabChildren->Get(uint64_t(aLayersId))); sTabChildren->Put(uint64_t(aLayersId), this); @@ -2918,17 +2879,17 @@ TabChild::InitAPZState() } void TabChild::NotifyPainted() { if (!mNotified) { // Recording/replaying processes have a compositor but not a remote frame. if (!recordreplay::IsRecordingOrReplaying()) { - mRemoteFrame->SendNotifyCompositorTransaction(); + SendNotifyCompositorTransaction(); } mNotified = true; } } void TabChild::MakeVisible() { @@ -3297,17 +3258,17 @@ TabChild::OnHideTooltip() mozilla::ipc::IPCResult TabChild::RecvRequestNotifyAfterRemotePaint() { // Get the CompositorBridgeChild instance for this content thread. CompositorBridgeChild* compositor = CompositorBridgeChild::Get(); // Tell the CompositorBridgeChild that, when it gets a RemotePaintIsReady // message that it should forward it us so that we can bounce it to our - // RenderFrameParent. + // TabParent. compositor->RequestNotifyAfterRemotePaint(this); return IPC_OK(); } mozilla::ipc::IPCResult TabChild::RecvUIResolutionChanged(const float& aDpi, const int32_t& aRounding, const double& aScale)
--- a/dom/ipc/TabChild.h +++ b/dom/ipc/TabChild.h @@ -49,19 +49,16 @@ class nsIHttpChannel; class nsISerialEventTarget; class nsWebBrowser; template<typename T> class nsTHashtable; template<typename T> class nsPtrHashKey; namespace mozilla { class AbstractThread; -namespace layout { -class RenderFrameChild; -} // namespace layout namespace layers { class APZChild; class APZEventState; class AsyncDragMetrics; class IAPZCTreeManager; class ImageCompositeNotification; class PCompositorBridgeChild; @@ -206,17 +203,16 @@ class TabChild final : public TabChildBa public nsIObserver, public TabContext, public nsITooltipListener, public mozilla::ipc::IShmemAllocator { typedef mozilla::dom::ClonedMessageData ClonedMessageData; typedef mozilla::dom::CoalescedMouseData CoalescedMouseData; typedef mozilla::dom::CoalescedWheelData CoalescedWheelData; - typedef mozilla::layout::RenderFrameChild RenderFrameChild; typedef mozilla::layers::APZEventState APZEventState; typedef mozilla::layers::SetAllowedTouchBehaviorCallback SetAllowedTouchBehaviorCallback; typedef mozilla::layers::TouchBehaviorFlags TouchBehaviorFlags; public: /** * Find TabChild of aTabId in the same content process of the * caller. @@ -302,18 +298,17 @@ public: const ShowInfo& aInfo, const bool& aParentIsActive, const nsSizeMode& aSizeMode) override; virtual mozilla::ipc::IPCResult RecvInitRendering(const TextureFactoryIdentifier& aTextureFactoryIdentifier, const layers::LayersId& aLayersId, const mozilla::layers::CompositorOptions& aCompositorOptions, - const bool& aLayersConnected, - PRenderFrameChild* aRenderFrame) override; + const bool& aLayersConnected) override; virtual mozilla::ipc::IPCResult RecvUpdateDimensions(const mozilla::dom::DimensionInfo& aDimensionInfo) override; virtual mozilla::ipc::IPCResult RecvSizeModeChanged(const nsSizeMode& aSizeMode) override; mozilla::ipc::IPCResult RecvActivate(); @@ -601,21 +596,17 @@ public: } const mozilla::layers::CompositorOptions& GetCompositorOptions() const; bool AsyncPanZoomEnabled() const; virtual ScreenIntSize GetInnerSize() override; // Call RecvShow(nsIntSize(0, 0)) and block future calls to RecvShow(). - void DoFakeShow(const TextureFactoryIdentifier& aTextureFactoryIdentifier, - const layers::LayersId& aLayersId, - const mozilla::layers::CompositorOptions& aCompositorOptions, - PRenderFrameChild* aRenderFrame, - const ShowInfo& aShowInfo); + void DoFakeShow(const ShowInfo& aShowInfo); void ContentReceivedInputBlock(const ScrollableLayerGuid& aGuid, uint64_t aInputBlockId, bool aPreventDefault) const; void SetTargetAPZC(uint64_t aInputBlockId, const nsTArray<ScrollableLayerGuid>& aTargets) const; MOZ_CAN_RUN_SCRIPT mozilla::ipc::IPCResult RecvHandleTap(const layers::GeckoContentController::TapType& aType, @@ -709,20 +700,16 @@ public: { MOZ_ASSERT(HasVisibleTabs()); return *sVisibleTabs; } protected: virtual ~TabChild(); - virtual PRenderFrameChild* AllocPRenderFrameChild() override; - - virtual bool DeallocPRenderFrameChild(PRenderFrameChild* aFrame) override; - virtual mozilla::ipc::IPCResult RecvDestroy() override; virtual mozilla::ipc::IPCResult RecvSetDocShellIsActive(const bool& aIsActive) override; virtual mozilla::ipc::IPCResult RecvRenderLayers(const bool& aEnabled, const bool& aForce, const layers::LayersObserverEpoch& aEpoch) override; virtual mozilla::ipc::IPCResult RecvRequestRootPaint(const IntRect& aRect, const float& aScale, const nscolor& aBackgroundColor, RequestRootPaintResolver&& aResolve) override; @@ -770,18 +757,17 @@ private: void UpdateFrameType(); void ActorDestroy(ActorDestroyReason why) override; bool InitTabChildMessageManager(); void InitRenderingState(const TextureFactoryIdentifier& aTextureFactoryIdentifier, const layers::LayersId& aLayersId, - const mozilla::layers::CompositorOptions& aCompositorOptions, - PRenderFrameChild* aRenderFrame); + const mozilla::layers::CompositorOptions& aCompositorOptions); void InitAPZState(); void DestroyWindow(); void ApplyShowInfo(const ShowInfo& aInfo); bool HasValidInnerSize(); @@ -821,17 +807,16 @@ private: class DelayedDeleteRunnable; TextureFactoryIdentifier mTextureFactoryIdentifier; RefPtr<nsWebBrowser> mWebBrowser; nsCOMPtr<nsIWebNavigation> mWebNav; RefPtr<mozilla::dom::TabGroup> mTabGroup; RefPtr<PuppetWidget> mPuppetWidget; nsCOMPtr<nsIURI> mLastURI; - RenderFrameChild* mRemoteFrame; RefPtr<nsIContentChild> mManager; uint32_t mChromeFlags; uint32_t mMaxTouchPoints; layers::LayersId mLayersId; int64_t mBeforeUnloadListeners; CSSRect mUnscaledOuterRect; Maybe<bool> mLayersConnected; bool mDidFakeShow;
--- a/dom/ipc/TabParent.cpp +++ b/dom/ipc/TabParent.cpp @@ -26,17 +26,17 @@ #include "mozilla/gfx/2D.h" #include "mozilla/gfx/DataSurfaceHelpers.h" #include "mozilla/gfx/GPUProcessManager.h" #include "mozilla/Hal.h" #include "mozilla/IMEStateManager.h" #include "mozilla/jsipc/CrossProcessObjectWrappers.h" #include "mozilla/layers/AsyncDragMetrics.h" #include "mozilla/layers/InputAPZContext.h" -#include "mozilla/layout/RenderFrameParent.h" +#include "mozilla/layout/RenderFrame.h" #include "mozilla/plugins/PPluginWidgetParent.h" #include "mozilla/LookAndFeel.h" #include "mozilla/MouseEvents.h" #include "mozilla/net/NeckoChild.h" #include "mozilla/Preferences.h" #include "mozilla/PresShell.h" #include "mozilla/TextEvents.h" #include "mozilla/TouchEvents.h" @@ -151,17 +151,16 @@ TabParent::TabParent(nsIContentParent* a , mUpdatedDimensions(false) , mSizeMode(nsSizeMode_Normal) , mManager(aManager) , mDocShellIsActive(false) , mMarkedDestroying(false) , mIsDestroyed(false) , mChromeFlags(aChromeFlags) , mDragValid(false) - , mInitedByParent(false) , mTabId(aTabId) , mCreatingWindow(false) , mCursor(eCursorInvalid) , mCustomCursorHotspotX(0) , mCustomCursorHotspotY(0) , mTabSetsCursor(false) , mHasContentOpener(false) #ifdef DEBUG @@ -354,21 +353,16 @@ TabParent::DestroyInternal() } #endif // If this fails, it's most likely due to a content-process crash, // and auto-cleanup will kick in. Otherwise, the child side will // destroy itself and send back __delete__(). Unused << SendDestroy(); - if (RenderFrameParent* frame = GetRenderFrame()) { - RemoveTabParentFromTable(frame->GetLayersId()); - frame->Destroy(); - } - #ifdef XP_WIN // Let all PluginWidgets know we are tearing down. Prevents // these objects from sending async events after the child side // is shut down. const ManagedContainer<PPluginWidgetParent>& kids = ManagedPPluginWidgetParent(); for (auto iter = kids.ConstIter(); !iter.Done(); iter.Next()) { static_cast<mozilla::plugins::PluginWidgetParent*>( @@ -401,18 +395,18 @@ TabParent::Destroy() } mMarkedDestroying = true; } mozilla::ipc::IPCResult TabParent::RecvEnsureLayersConnected(CompositorOptions* aCompositorOptions) { - if (RenderFrameParent* frame = GetRenderFrame()) { - frame->EnsureLayersConnected(aCompositorOptions); + if (mRenderFrame.IsInitialized()) { + mRenderFrame.EnsureLayersConnected(aCompositorOptions); } return IPC_OK(); } mozilla::ipc::IPCResult TabParent::Recv__delete__() { if (XRE_IsParentProcess()) { @@ -428,16 +422,24 @@ TabParent::Recv__delete__() } return IPC_OK(); } void TabParent::ActorDestroy(ActorDestroyReason why) { + if (mRenderFrame.IsInitialized()) { + // It's important to unmap layers after the remote browser has been destroyed, + // otherwise it may still send messages to the compositor which will reject them, + // causing assertions. + RemoveTabParentFromTable(mRenderFrame.GetLayersId()); + mRenderFrame.Destroy(); + } + // Even though TabParent::Destroy calls this, we need to do it here too in // case of a crash. IMEStateManager::OnTabParentDestroying(this); // Prevent executing ContentParent::NotifyTabDestroying in // TabParent::Destroy() called by frameLoader->DestroyComplete() below // when tab crashes in contentprocess because ContentParent::ActorDestroy() // in main process will be triggered before this function @@ -625,56 +627,59 @@ TabParent::LoadURL(nsIURI* aURI) mDelayedURL = spec; return; } Unused << SendLoadURL(spec, GetShowInfo()); } void -TabParent::InitRenderFrame() +TabParent::InitRendering() { - if (IsInitedByParent()) { - // If TabParent is initialized by parent side then the RenderFrame must also - // be created here. If TabParent is initialized by child side, - // child side will create RenderFrame. - MOZ_ASSERT(!GetRenderFrame()); - RefPtr<nsFrameLoader> frameLoader = GetFrameLoader(); - MOZ_ASSERT(frameLoader); - if (frameLoader) { - RenderFrameParent* renderFrame = new RenderFrameParent(frameLoader); - MOZ_ASSERT(renderFrame->IsInitted()); - layers::LayersId layersId = renderFrame->GetLayersId(); - AddTabParentToTable(layersId, this); - if (!SendPRenderFrameConstructor(renderFrame)) { - return; - } - - TextureFactoryIdentifier textureFactoryIdentifier; - renderFrame->GetTextureFactoryIdentifier(&textureFactoryIdentifier); - Unused << SendInitRendering(textureFactoryIdentifier, layersId, - renderFrame->GetCompositorOptions(), - renderFrame->IsLayersConnected(), renderFrame); - } - } else { - // Otherwise, the child should have constructed the RenderFrame, - // and we should already know about it. - MOZ_ASSERT(GetRenderFrame()); + RefPtr<nsFrameLoader> frameLoader = GetFrameLoader(); + + MOZ_ASSERT(!mRenderFrame.IsInitialized()); + MOZ_ASSERT(frameLoader); + + if (!frameLoader) { + return; } + + mRenderFrame.Initialize(frameLoader); + MOZ_ASSERT(mRenderFrame.IsInitialized()); + + layers::LayersId layersId = mRenderFrame.GetLayersId(); + AddTabParentToTable(layersId, this); + + TextureFactoryIdentifier textureFactoryIdentifier; + mRenderFrame.GetTextureFactoryIdentifier(&textureFactoryIdentifier); + Unused << SendInitRendering(textureFactoryIdentifier, layersId, + mRenderFrame.GetCompositorOptions(), + mRenderFrame.IsLayersConnected()); +} + +void +TabParent::MaybeShowFrame() +{ + RefPtr<nsFrameLoader> frameLoader = GetFrameLoader(); + if (!frameLoader) { + return; + } + frameLoader->MaybeShowFrame(); } void TabParent::Show(const ScreenIntSize& size, bool aParentIsActive) { mDimensions = size; if (mIsDestroyed) { return; } - MOZ_ASSERT(GetRenderFrame()); + MOZ_ASSERT(mRenderFrame.IsInitialized()); nsCOMPtr<nsISupports> container = mFrameElement->OwnerDoc()->GetContainer(); nsCOMPtr<nsIBaseWindow> baseWindow = do_QueryInterface(container); nsCOMPtr<nsIWidget> mainWidget; baseWindow->GetMainWidget(getter_AddRefs(mainWidget)); mSizeMode = mainWidget ? mainWidget->SizeMode() : nsSizeMode_Normal; Unused << SendShow(size, GetShowInfo(), aParentIsActive, mSizeMode); @@ -1649,19 +1654,29 @@ TabParent::SendHandleTap(TapType aType, const LayoutDevicePoint& aPoint, Modifiers aModifiers, const ScrollableLayerGuid& aGuid, uint64_t aInputBlockId) { if (mIsDestroyed || !mIsReadyToHandleInputEvents) { return false; } - if ((aType == TapType::eSingleTap || aType == TapType::eSecondTap) && - GetRenderFrame()) { - GetRenderFrame()->TakeFocusForClickFromTap(); + if ((aType == TapType::eSingleTap || aType == TapType::eSecondTap)) { + nsIFocusManager* fm = nsFocusManager::GetFocusManager(); + if (fm) { + RefPtr<nsFrameLoader> frameLoader = GetFrameLoader(); + if (frameLoader) { + RefPtr<Element> element = frameLoader->GetOwnerContent(); + if (element) { + fm->SetFocus(element, nsIFocusManager::FLAG_BYMOUSE | + nsIFocusManager::FLAG_BYTOUCH | + nsIFocusManager::FLAG_NOSCROLL); + } + } + } } LayoutDeviceIntPoint offset = GetChildProcessOffset(); return Manager()->AsContentParent()->IsInputPriorityEventEnabled() ? PBrowserParent::SendHandleTap(aType, aPoint + offset, aModifiers, aGuid, aInputBlockId) : PBrowserParent::SendNormalPriorityHandleTap(aType, aPoint + offset, aModifiers, aGuid, aInputBlockId); @@ -2363,23 +2378,23 @@ TabParent::GetTabIdFrom(nsIDocShell *doc { nsCOMPtr<nsITabChild> tabChild(TabChild::GetFrom(docShell)); if (tabChild) { return static_cast<TabChild*>(tabChild.get())->GetTabId(); } return TabId(0); } -RenderFrameParent* +RenderFrame* TabParent::GetRenderFrame() { - PRenderFrameParent* p = LoneManagedOrNullAsserts(ManagedPRenderFrameParent()); - RenderFrameParent* frame = static_cast<RenderFrameParent*>(p); - - return frame; + if (!mRenderFrame.IsInitialized()) { + return nullptr; + } + return &mRenderFrame; } mozilla::ipc::IPCResult TabParent::RecvRequestIMEToCommitComposition(const bool& aCancel, bool* aIsCommitted, nsString* aCommittedString) { nsCOMPtr<nsIWidget> widget = GetWidget(); @@ -2592,78 +2607,16 @@ TabParent::AllocPColorPickerParent(const bool TabParent::DeallocPColorPickerParent(PColorPickerParent* actor) { delete actor; return true; } -PRenderFrameParent* -TabParent::AllocPRenderFrameParent() -{ - MOZ_ASSERT(ManagedPRenderFrameParent().IsEmpty()); - RefPtr<nsFrameLoader> frameLoader = GetFrameLoader(); - - RenderFrameParent* rfp = new RenderFrameParent(frameLoader); - if (rfp->IsInitted()) { - layers::LayersId layersId = rfp->GetLayersId(); - AddTabParentToTable(layersId, this); - } - return rfp; -} - -bool -TabParent::DeallocPRenderFrameParent(PRenderFrameParent* aFrame) -{ - delete aFrame; - return true; -} - -bool -TabParent::SetRenderFrame(PRenderFrameParent* aRFParent) -{ - if (IsInitedByParent()) { - return false; - } - - RefPtr<nsFrameLoader> frameLoader = GetFrameLoader(); - - if (!frameLoader) { - return false; - } - - RenderFrameParent* renderFrame = static_cast<RenderFrameParent*>(aRFParent); - bool success = renderFrame->Init(frameLoader); - if (!success) { - return false; - } - - frameLoader->MaybeShowFrame(); - - layers::LayersId layersId = renderFrame->GetLayersId(); - AddTabParentToTable(layersId, this); - - return true; -} - -bool -TabParent::GetRenderFrameInfo(TextureFactoryIdentifier* aTextureFactoryIdentifier, - layers::LayersId* aLayersId) -{ - RenderFrameParent* rfp = GetRenderFrame(); - if (!rfp) { - return false; - } - - *aLayersId = rfp->GetLayersId(); - rfp->GetTextureFactoryIdentifier(aTextureFactoryIdentifier); - return true; -} - already_AddRefed<nsFrameLoader> TabParent::GetFrameLoader(bool aUseCachedFrameLoaderAfterDestroy) const { if (mIsDestroyed && !aUseCachedFrameLoaderAfterDestroy) { return nullptr; } if (mFrameLoader) { @@ -2727,19 +2680,19 @@ TabParent::ApzAwareEventRoutingToChild(S if (aOutTargetGuid) { *aOutTargetGuid = InputAPZContext::GetTargetLayerGuid(); // There may be cases where the APZ hit-testing code came to a different // conclusion than the main-thread hit-testing code as to where the event // is destined. In such cases the layersId of the APZ result may not match // the layersId of this renderframe. In such cases the main-thread hit- // testing code "wins" so we need to update the guid to reflect this. - if (RenderFrameParent* rfp = GetRenderFrame()) { - if (aOutTargetGuid->mLayersId != rfp->GetLayersId()) { - *aOutTargetGuid = ScrollableLayerGuid(rfp->GetLayersId(), 0, ScrollableLayerGuid::NULL_SCROLL_ID); + if (mRenderFrame.IsInitialized()) { + if (aOutTargetGuid->mLayersId != mRenderFrame.GetLayersId()) { + *aOutTargetGuid = ScrollableLayerGuid(mRenderFrame.GetLayersId(), 0, ScrollableLayerGuid::NULL_SCROLL_ID); } } } if (aOutInputBlockId) { *aOutInputBlockId = InputAPZContext::GetInputBlockId(); } if (aOutApzResponse) { *aOutApzResponse = InputAPZContext::GetApzResponse(); @@ -2751,34 +2704,28 @@ TabParent::ApzAwareEventRoutingToChild(S if (aOutApzResponse) { *aOutApzResponse = nsEventStatus_eIgnore; } } } mozilla::ipc::IPCResult TabParent::RecvBrowserFrameOpenWindow(PBrowserParent* aOpener, - PRenderFrameParent* aRenderFrame, const nsString& aURL, const nsString& aName, const nsString& aFeatures, BrowserFrameOpenWindowResolver&& aResolve) { CreatedWindowInfo cwi; cwi.rv() = NS_OK; - cwi.layersId() = LayersId{0}; cwi.maxTouchPoints() = 0; BrowserElementParent::OpenWindowResult opened = BrowserElementParent::OpenWindowOOP(TabParent::GetFrom(aOpener), - this, aRenderFrame, aURL, aName, aFeatures, - &cwi.textureFactoryIdentifier(), - &cwi.layersId()); - cwi.compositorOptions() = - static_cast<RenderFrameParent*>(aRenderFrame)->GetCompositorOptions(); + this, aURL, aName, aFeatures); cwi.windowOpened() = (opened == BrowserElementParent::OPEN_WINDOW_ADDED); nsCOMPtr<nsIWidget> widget = GetWidget(); if (widget) { cwi.maxTouchPoints() = widget->GetMaxTouchPoints(); cwi.dimensions() = GetDimensionInfo(); } // Resolve the request with the information we collected. @@ -3180,16 +3127,40 @@ TabParent::RecvRemotePaintIsReady() event->InitEvent(NS_LITERAL_STRING("MozAfterRemotePaint"), false, false); event->SetTrusted(true); event->WidgetEventPtr()->mFlags.mOnlyChromeDispatch = true; mFrameElement->DispatchEvent(*event); return IPC_OK(); } mozilla::ipc::IPCResult +TabParent::RecvNotifyCompositorTransaction() +{ + RefPtr<nsFrameLoader> frameLoader = GetFrameLoader(); + + if (!frameLoader) { + return IPC_OK(); + } + + nsIFrame* docFrame = frameLoader->GetPrimaryFrameOfOwningContent(); + + if (!docFrame) { + // Bad, but nothing we can do about it (XXX/cjones: or is there? + // maybe bug 589337?). When the new frame is created, we'll + // probably still be the current render frame and will get to draw + // our content then. Or, we're shutting down and this update goes + // to /dev/null. + return IPC_OK(); + } + + docFrame->InvalidateLayer(DisplayItemType::TYPE_REMOTE); + return IPC_OK(); +} + +mozilla::ipc::IPCResult TabParent::RecvRemoteIsReadyToHandleInputEvents() { // When enabling input event prioritization, input events may preempt other // normal priority IPC messages. To prevent the input events preempt // PBrowserConstructor, we use an IPC 'RemoteIsReadyToHandleInputEvents' to // notify the parent that TabChild is created and ready to handle input // events. SetReadyToHandleInputEvents(); @@ -3550,18 +3521,18 @@ TabParent::StartApzAutoscroll(float aAnc bool* aOutRetval) { if (!AsyncPanZoomEnabled()) { *aOutRetval = false; return NS_OK; } bool success = false; - if (RenderFrameParent* renderFrame = GetRenderFrame()) { - layers::LayersId layersId = renderFrame->GetLayersId(); + if (mRenderFrame.IsInitialized()) { + layers::LayersId layersId = mRenderFrame.GetLayersId(); if (nsCOMPtr<nsIWidget> widget = GetWidget()) { ScrollableLayerGuid guid{layersId, aPresShellId, aScrollId}; // The anchor coordinates that are passed in are relative to the origin // of the screen, but we are sending them to APZ which only knows about // coordinates relative to the widget, so convert them accordingly. CSSPoint anchorCss{aAnchorX, aAnchorY}; LayoutDeviceIntPoint anchor = RoundedToInt(anchorCss * widget->GetDefaultScale()); @@ -3578,18 +3549,18 @@ TabParent::StartApzAutoscroll(float aAnc NS_IMETHODIMP TabParent::StopApzAutoscroll(nsViewID aScrollId, uint32_t aPresShellId) { if (!AsyncPanZoomEnabled()) { return NS_OK; } - if (RenderFrameParent* renderFrame = GetRenderFrame()) { - layers::LayersId layersId = renderFrame->GetLayersId(); + if (mRenderFrame.IsInitialized()) { + layers::LayersId layersId = mRenderFrame.GetLayersId(); if (nsCOMPtr<nsIWidget> widget = GetWidget()) { ScrollableLayerGuid guid{layersId, aPresShellId, aScrollId}; widget->StopAsyncAutoscroll(guid); } } return NS_OK; }
--- a/dom/ipc/TabParent.h +++ b/dom/ipc/TabParent.h @@ -14,16 +14,17 @@ #include "mozilla/dom/PBrowserParent.h" #include "mozilla/dom/PContent.h" #include "mozilla/dom/PFilePickerParent.h" #include "mozilla/dom/TabContext.h" #include "mozilla/EventForwards.h" #include "mozilla/dom/File.h" #include "mozilla/gfx/CrossProcessPaint.h" #include "mozilla/layers/CompositorBridgeParent.h" +#include "mozilla/layout/RenderFrame.h" #include "mozilla/RefPtr.h" #include "mozilla/Move.h" #include "nsCOMPtr.h" #include "nsIAuthPromptProvider.h" #include "nsIBrowserDOMWindow.h" #include "nsIDOMEventListener.h" #include "nsIKeyEventInPluginCallback.h" #include "nsITabParent.h" @@ -50,20 +51,16 @@ class DocAccessibleParent; namespace jsipc { class CpowHolder; } // namespace jsipc namespace layers { struct TextureFactoryIdentifier; } // namespace layers -namespace layout { -class RenderFrameParent; -} // namespace layout - namespace widget { struct IMENotification; } // namespace widget namespace gfx { class SourceSurface; class DataSourceSurface; } // namespace gfx @@ -157,17 +154,16 @@ public: virtual mozilla::ipc::IPCResult RecvAccessKeyNotHandled(const WidgetKeyboardEvent& aEvent) override; virtual mozilla::ipc::IPCResult RecvSetHasBeforeUnload(const bool& aHasBeforeUnload) override; virtual mozilla::ipc::IPCResult RecvBrowserFrameOpenWindow(PBrowserParent* aOpener, - PRenderFrameParent* aRenderFrame, const nsString& aURL, const nsString& aName, const nsString& aFeatures, BrowserFrameOpenWindowResolver&& aResolve) override; virtual mozilla::ipc::IPCResult RecvSyncMessage(const nsString& aMessage, const ClonedMessageData& aData, @@ -328,17 +324,18 @@ public: /** * Return the top level doc accessible parent for this tab. */ a11y::DocAccessibleParent* GetTopLevelDocAccessible() const; void LoadURL(nsIURI* aURI); - void InitRenderFrame(); + void InitRendering(); + void MaybeShowFrame(); // XXX/cjones: it's not clear what we gain by hiding these // message-sending functions under a layer of indirection and // eating the return values void Show(const ScreenIntSize& aSize, bool aParentIsActive); void UpdateDimensions(const nsIntRect& aRect, const ScreenIntSize& aSize); @@ -549,20 +546,16 @@ public: DeallocPPluginWidgetParent(PPluginWidgetParent* aActor) override; virtual PPaymentRequestParent* AllocPPaymentRequestParent() override; virtual bool DeallocPPaymentRequestParent(PPaymentRequestParent* aActor) override; - void SetInitedByParent() { mInitedByParent = true; } - - bool IsInitedByParent() const { return mInitedByParent; } - bool SendLoadRemoteScript(const nsString& aURL, const bool& aRunInGlobalScope); void LayerTreeUpdate(const LayersObserverEpoch& aEpoch, bool aActive); void RequestRootPaint(gfx::CrossProcessPaint* aPaint, IntRect aRect, float aScale, nscolor aBackgroundColor); void RequestSubPaint(gfx::CrossProcessPaint* aPaint, float aScale, nscolor aBackgroundColor); @@ -575,21 +568,17 @@ public: const nsCString& aPrincipalURISpec) override; void AddInitialDnDDataTo(DataTransfer* aDataTransfer, nsACString& aPrincipalURISpec); bool TakeDragVisualization(RefPtr<mozilla::gfx::SourceSurface>& aSurface, LayoutDeviceIntRect* aDragRect); - layout::RenderFrameParent* GetRenderFrame(); - - bool SetRenderFrame(PRenderFrameParent* aRFParent); - bool GetRenderFrameInfo(TextureFactoryIdentifier* aTextureFactoryIdentifier, - layers::LayersId* aLayersId); + layout::RenderFrame* GetRenderFrame(); mozilla::ipc::IPCResult RecvEnsureLayersConnected(CompositorOptions* aCompositorOptions) override; // LiveResizeListener implementation void LiveResizeStarted() override; void LiveResizeStopped() override; void SetReadyToHandleInputEvents() { mIsReadyToHandleInputEvents = true; } @@ -615,21 +604,19 @@ protected: virtual mozilla::ipc::IPCResult Recv__delete__() override; virtual void ActorDestroy(ActorDestroyReason why) override; Element* mFrameElement; nsCOMPtr<nsIBrowserDOMWindow> mBrowserDOMWindow; - virtual PRenderFrameParent* AllocPRenderFrameParent() override; + virtual mozilla::ipc::IPCResult RecvRemotePaintIsReady() override; - virtual bool DeallocPRenderFrameParent(PRenderFrameParent* aFrame) override; - - virtual mozilla::ipc::IPCResult RecvRemotePaintIsReady() override; + virtual mozilla::ipc::IPCResult RecvNotifyCompositorTransaction() override; virtual mozilla::ipc::IPCResult RecvRemoteIsReadyToHandleInputEvents() override; virtual mozilla::ipc::IPCResult RecvPaintWhileInterruptingJSNoOp(const LayersObserverEpoch& aEpoch) override; virtual mozilla::ipc::IPCResult RecvSetDimensions(const uint32_t& aFlags, const int32_t& aX, const int32_t& aY, const int32_t& aCx, const int32_t& aCy) override; @@ -692,20 +679,16 @@ private: nsTArray<nsTArray<IPCDataTransferItem>> mInitialDataTransferItems; RefPtr<gfx::DataSourceSurface> mDnDVisualization; bool mDragValid; LayoutDeviceIntRect mDragRect; nsCString mDragPrincipalURISpec; - // When true, the TabParent is initialized without child side's request. - // When false, the TabParent is initialized by window.open() from child side. - bool mInitedByParent; - nsCOMPtr<nsILoadContext> mLoadContext; // We keep a strong reference to the frameloader after we've sent the // Destroy message and before we've received __delete__. This allows us to // dispatch message manager messages during this time. RefPtr<nsFrameLoader> mFrameLoader; TabId mTabId; @@ -767,16 +750,17 @@ private: // to dispatch events. typedef nsDataHashtable<nsUint64HashKey, TabParent*> LayerToTabParentTable; static LayerToTabParentTable* sLayerToTabParentTable; static void AddTabParentToTable(layers::LayersId aLayersId, TabParent* aTabParent); static void RemoveTabParentFromTable(layers::LayersId aLayersId); + layout::RenderFrame mRenderFrame; LayersObserverEpoch mLayerTreeEpoch; // If this flag is set, then the tab's layers will be preserved even when // the tab's docshell is inactive. bool mPreserveLayers; // Holds the most recent value passed to the RenderLayers function. This // does not necessarily mean that the layers have finished rendering
--- a/gfx/2d/2D.h +++ b/gfx/2d/2D.h @@ -58,16 +58,17 @@ typedef FT_FaceRec_* FT_Face; typedef int FT_Error; struct ID3D11Texture2D; struct ID3D11Device; struct ID2D1Device; struct IDWriteFactory; struct IDWriteRenderingParams; struct IDWriteFontFace; +struct IDWriteFontCollection; class GrContext; class SkCanvas; struct gfxFontStyle; struct CGContext; typedef struct CGContext *CGContextRef; @@ -1855,19 +1856,19 @@ public: * Attempts to create and install a D2D1 device from the supplied Direct3D11 device. * Returns true on success, or false on failure and leaves the D2D1/Direct3D11 devices unset. */ static bool SetDirect3D11Device(ID3D11Device *aDevice); static RefPtr<ID3D11Device> GetDirect3D11Device(); static RefPtr<ID2D1Device> GetD2D1Device(uint32_t* aOutSeqNo = nullptr); static bool HasD2D1Device(); static RefPtr<IDWriteFactory> GetDWriteFactory(); - static bool SetDWriteFactory(IDWriteFactory *aFactory); static RefPtr<IDWriteFactory> EnsureDWriteFactory(); static bool SupportsD2D1(); + static RefPtr<IDWriteFontCollection> GetDWriteSystemFonts(bool aUpdate = false); static uint64_t GetD2DVRAMUsageDrawTarget(); static uint64_t GetD2DVRAMUsageSourceSurface(); static void D2DCleanup(); static already_AddRefed<ScaledFont> CreateScaledFontForDWriteFont(IDWriteFontFace* aFontFace, const gfxFontStyle* aStyle, @@ -1881,16 +1882,17 @@ public: static void SetSystemTextQuality(uint8_t aQuality); private: static StaticRefPtr<ID2D1Device> mD2D1Device; static StaticRefPtr<ID3D11Device> mD3D11Device; static StaticRefPtr<IDWriteFactory> mDWriteFactory; static bool mDWriteFactoryInitialized; + static StaticRefPtr<IDWriteFontCollection> mDWriteSystemFonts; protected: // This guards access to the singleton devices above, as well as the // singleton devices in DrawTargetD2D1. static StaticMutex mDeviceLock; // This synchronizes access between different D2D drawtargets and their // implied dependency graph. static StaticMutex mDTDependencyLock;
--- a/gfx/2d/Factory.cpp +++ b/gfx/2d/Factory.cpp @@ -224,16 +224,17 @@ Mutex* Factory::mFTLock = nullptr; #ifdef WIN32 // Note: mDeviceLock must be held when mutating these values. static uint32_t mDeviceSeq = 0; StaticRefPtr<ID3D11Device> Factory::mD3D11Device; StaticRefPtr<ID2D1Device> Factory::mD2D1Device; StaticRefPtr<IDWriteFactory> Factory::mDWriteFactory; bool Factory::mDWriteFactoryInitialized = false; +StaticRefPtr<IDWriteFontCollection> Factory::mDWriteSystemFonts; StaticMutex Factory::mDeviceLock; StaticMutex Factory::mDTDependencyLock; #endif DrawEventRecorder *Factory::mRecorder; mozilla::gfx::Config* Factory::sConfig = nullptr; @@ -946,16 +947,40 @@ Factory::EnsureDWriteFactory() if (FAILED(hr)) { gfxWarning() << "Failed to create DWrite Factory."; } return mDWriteFactory; } +RefPtr<IDWriteFontCollection> +Factory::GetDWriteSystemFonts(bool aUpdate) +{ + StaticMutexAutoLock lock(mDeviceLock); + + if (mDWriteSystemFonts && !aUpdate) { + return mDWriteSystemFonts; + } + + if (!mDWriteFactory) { + return nullptr; + } + + RefPtr<IDWriteFontCollection> systemFonts; + HRESULT hr = mDWriteFactory->GetSystemFontCollection(getter_AddRefs(systemFonts)); + if (FAILED(hr)) { + gfxWarning() << "Failed to create DWrite system font collection"; + return nullptr; + } + mDWriteSystemFonts = systemFonts; + + return mDWriteSystemFonts; +} + bool Factory::SupportsD2D1() { return !!D2DFactory(); } BYTE sSystemTextQuality = CLEARTYPE_QUALITY; void
--- a/gfx/2d/ScaledFontDWrite.cpp +++ b/gfx/2d/ScaledFontDWrite.cpp @@ -380,16 +380,28 @@ UnscaledFontDWrite::GetWRFontDescriptor( return false; } std::vector<WCHAR> familyName; if (!GetDWriteFamilyName(family, familyName)) { return false; } + RefPtr<IDWriteFontCollection> systemFonts = Factory::GetDWriteSystemFonts(); + if (!systemFonts) { + return false; + } + + UINT32 idx; + BOOL exists; + hr = systemFonts->FindFamilyName(familyName.data(), &idx, &exists); + if (FAILED(hr) || !exists) { + return false; + } + // The style information that identifies the font can be encoded easily in // less than 32 bits. Since the index is needed for font descriptors, only // the family name and style information, pass along the style in the index // data to avoid requiring a more complicated structure packing for it in // the data payload. uint32_t index = weight | (stretch << 16) | (style << 24); aCb(reinterpret_cast<const uint8_t*>(familyName.data()), (familyName.size() - 1) * sizeof(WCHAR),
--- a/gfx/ipc/GPUProcessManager.cpp +++ b/gfx/ipc/GPUProcessManager.cpp @@ -607,20 +607,20 @@ GPUProcessManager::HandleProcessLost() // // (7) In addition, each ContentChild will ask each of its TabChildren // to re-request association with the compositor for the window // owning the tab. The sequence of calls looks like: // (a) [CONTENT] ContentChild::RecvReinitRendering // (b) [CONTENT] TabChild::ReinitRendering // (c) [CONTENT] TabChild::SendEnsureLayersConnected // (d) [UI] TabParent::RecvEnsureLayersConnected - // (e) [UI] RenderFrameParent::EnsureLayersConnected + // (e) [UI] RenderFrame::EnsureLayersConnected // (f) [UI] CompositorBridgeChild::SendNotifyChildRecreated // - // Note that at step (e), RenderFrameParent will call GetLayerManager + // Note that at step (e), RenderFrame will call GetLayerManager // on the nsIWidget owning the tab. This step ensures that a compositor // exists for the window. If we decided to launch a new GPU Process, // at this point we block until the process has launched and we're // able to create a new window compositor. Otherwise, if compositing // is now in-process, this will simply create a new // CompositorBridgeParent in the UI process. If there are multiple tabs // in the same window, additional tabs will simply return the already- // established compositor.
--- a/gfx/layers/apz/src/FocusTarget.cpp +++ b/gfx/layers/apz/src/FocusTarget.cpp @@ -4,17 +4,17 @@ * 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/. */ #include "mozilla/layers/FocusTarget.h" #include "mozilla/dom/EventTarget.h" // for EventTarget #include "mozilla/dom/TabParent.h" // for TabParent #include "mozilla/EventDispatcher.h" // for EventDispatcher -#include "mozilla/layout/RenderFrameParent.h" // For RenderFrameParent +#include "mozilla/layout/RenderFrame.h" // For RenderFrame #include "nsIContentInlines.h" // for nsINode::IsEditable() #include "nsIPresShell.h" // for nsIPresShell #include "nsLayoutUtils.h" // for nsLayoutUtils #define ENABLE_FT_LOGGING 0 // #define ENABLE_FT_LOGGING 1 #if ENABLE_FT_LOGGING @@ -161,26 +161,26 @@ FocusTarget::FocusTarget(nsIPresShell* a aFocusSequenceNumber, static_cast<int>(mFocusHasKeyEventListeners)); return; } // Check if the key event target is a remote browser if (TabParent* browserParent = TabParent::GetFrom(keyEventTarget)) { - RenderFrameParent* rfp = browserParent->GetRenderFrame(); + RenderFrame* rf = browserParent->GetRenderFrame(); // The globally focused element for scrolling is in a remote layer tree - if (rfp) { + if (rf) { FT_LOG("Creating reflayer target with seq=%" PRIu64 ", kl=%d, lt=%" PRIu64 "\n", aFocusSequenceNumber, mFocusHasKeyEventListeners, - rfp->GetLayersId()); + rf->GetLayersId()); - mData = AsVariant<LayersId>(rfp->GetLayersId()); + mData = AsVariant<LayersId>(rf->GetLayersId()); return; } FT_LOG("Creating nil target with seq=%" PRIu64 ", kl=%d (remote browser missing layers id)\n", aFocusSequenceNumber, mFocusHasKeyEventListeners); return;
--- a/gfx/layers/ipc/CompositorBridgeParent.cpp +++ b/gfx/layers/ipc/CompositorBridgeParent.cpp @@ -58,17 +58,16 @@ #include "mozilla/layers/LayerManagerComposite.h" #include "mozilla/layers/LayerManagerMLGPU.h" #include "mozilla/layers/LayerTreeOwnerTracker.h" #include "mozilla/layers/LayersTypes.h" #include "mozilla/layers/PLayerTransactionParent.h" #include "mozilla/layers/RemoteContentController.h" #include "mozilla/layers/WebRenderBridgeParent.h" #include "mozilla/layers/AsyncImagePipelineManager.h" -#include "mozilla/layout/RenderFrameParent.h" #include "mozilla/webrender/WebRenderAPI.h" #include "mozilla/media/MediaSystemResourceService.h" // for MediaSystemResourceService #include "mozilla/mozalloc.h" // for operator new, etc #include "mozilla/Telemetry.h" #ifdef MOZ_WIDGET_GTK #include "basic/X11BasicCompositor.h" // for X11BasicCompositor #endif #include "nsCOMPtr.h" // for already_AddRefed
--- a/gfx/layers/ipc/LayerTransactionChild.h +++ b/gfx/layers/ipc/LayerTransactionChild.h @@ -10,20 +10,16 @@ #include <stdint.h> // for uint32_t #include "mozilla/Attributes.h" // for override #include "mozilla/ipc/ProtocolUtils.h" #include "mozilla/layers/PLayerTransactionChild.h" #include "mozilla/RefPtr.h" namespace mozilla { -namespace layout { -class RenderFrameChild; -} // namespace layout - namespace layers { class ShadowLayerForwarder; class LayerTransactionChild : public PLayerTransactionChild { public: NS_INLINE_DECL_THREADSAFE_REFCOUNTING(LayerTransactionChild) @@ -68,17 +64,16 @@ protected: AddRef(); } void ReleaseIPDLReference() { MOZ_ASSERT(mIPCOpen == true); mIPCOpen = false; Release(); } friend class CompositorBridgeChild; - friend class layout::RenderFrameChild; ShadowLayerForwarder* mForwarder; bool mIPCOpen; bool mDestroyed; LayersId mId; }; } // namespace layers
--- a/gfx/layers/ipc/LayerTransactionParent.cpp +++ b/gfx/layers/ipc/LayerTransactionParent.cpp @@ -34,18 +34,16 @@ #include "nsMathUtils.h" // for NS_round #include "nsPoint.h" // for nsPoint #include "nsTArray.h" // for nsTArray, nsTArray_Impl, etc #include "TreeTraversal.h" // for ForEachNode #include "GeckoProfiler.h" #include "mozilla/layers/TextureHost.h" #include "mozilla/layers/AsyncCompositionManager.h" -using mozilla::layout::RenderFrameParent; - namespace mozilla { namespace layers { //-------------------------------------------------- // LayerTransactionParent LayerTransactionParent::LayerTransactionParent(HostLayerManager* aManager, CompositorBridgeParentBase* aBridge, CompositorAnimationStorage* aAnimStorage,
--- a/gfx/layers/ipc/LayerTransactionParent.h +++ b/gfx/layers/ipc/LayerTransactionParent.h @@ -17,34 +17,29 @@ #include "nsTArrayForwardDeclare.h" // for InfallibleTArray namespace mozilla { namespace ipc { class Shmem; } // namespace ipc -namespace layout { -class RenderFrameParent; -} // namespace layout - namespace layers { class Layer; class HostLayerManager; class ShadowLayerParent; class CompositableParent; class CompositorAnimationStorage; class CompositorBridgeParentBase; class LayerTransactionParent final : public PLayerTransactionParent, public CompositableParentManager, public ShmemAllocator { - typedef mozilla::layout::RenderFrameParent RenderFrameParent; typedef InfallibleTArray<Edit> EditArray; typedef InfallibleTArray<OpDestroy> OpDestroyArray; typedef InfallibleTArray<PluginWindowData> PluginsArray; public: LayerTransactionParent(HostLayerManager* aManager, CompositorBridgeParentBase* aBridge, CompositorAnimationStorage* aAnimStorage, @@ -163,17 +158,16 @@ protected: } void ReleaseIPDLReference() { MOZ_ASSERT(mIPCOpen == true); mIPCOpen = false; Release(); } friend class CompositorBridgeParent; friend class CrossProcessCompositorBridgeParent; - friend class layout::RenderFrameParent; private: // This is a function so we can log or breakpoint on why hit // testing tree changes are made. void UpdateHitTestingTree(Layer* aLayer, const char* aWhy) { mUpdateHitTestingTree = true; }
--- a/gfx/layers/ipc/LayersMessages.ipdlh +++ b/gfx/layers/ipc/LayersMessages.ipdlh @@ -2,17 +2,16 @@ * vim: sw=2 ts=8 et : */ /* 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/. */ include LayersSurfaces; include protocol PCompositorBridge; -include protocol PRenderFrame; include protocol PTexture; include "gfxipc/ShadowLayerUtils.h"; include "mozilla/GfxMessageUtils.h"; include "ImageLayers.h"; using mozilla::gfx::Glyph from "mozilla/gfx/2D.h"; using mozilla::gfx::SamplingFilter from "mozilla/gfx/2D.h";
--- a/gfx/layers/ipc/PLayerTransaction.ipdl +++ b/gfx/layers/ipc/PLayerTransaction.ipdl @@ -3,17 +3,16 @@ */ /* 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/. */ include LayersSurfaces; include LayersMessages; include protocol PCompositorBridge; -include protocol PRenderFrame; include protocol PTexture; include "mozilla/GfxMessageUtils.h"; include "mozilla/layers/LayersMessageUtils.h"; using struct mozilla::layers::TextureInfo from "mozilla/layers/CompositorTypes.h"; using struct mozilla::void_t from "ipc/IPCMessageUtils.h"; using struct mozilla::null_t from "ipc/IPCMessageUtils.h";
--- a/gfx/layers/ipc/RemoteContentController.cpp +++ b/gfx/layers/ipc/RemoteContentController.cpp @@ -9,17 +9,16 @@ #include "base/message_loop.h" #include "base/task.h" #include "MainThreadUtils.h" #include "mozilla/dom/ContentParent.h" #include "mozilla/dom/TabParent.h" #include "mozilla/layers/APZCCallbackHelper.h" #include "mozilla/layers/APZCTreeManagerParent.h" // for APZCTreeManagerParent #include "mozilla/layers/APZThreadUtils.h" -#include "mozilla/layout/RenderFrameParent.h" #include "mozilla/gfx/GPUProcessManager.h" #include "mozilla/Unused.h" #include "Units.h" namespace mozilla { namespace layers { using namespace mozilla::gfx;
--- a/gfx/layers/wr/WebRenderScrollData.cpp +++ b/gfx/layers/wr/WebRenderScrollData.cpp @@ -4,17 +4,16 @@ * 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/. */ #include "mozilla/layers/WebRenderScrollData.h" #include "Layers.h" #include "LayersLogging.h" #include "mozilla/layers/WebRenderLayerManager.h" -#include "mozilla/layout/RenderFrameParent.h" #include "mozilla/Unused.h" #include "nsDisplayList.h" #include "nsTArray.h" #include "UnitTransforms.h" namespace mozilla { namespace layers {
--- a/gfx/thebes/gfxDWriteFontList.cpp +++ b/gfx/thebes/gfxDWriteFontList.cpp @@ -1052,31 +1052,30 @@ gfxDWriteFontList::InitFontListForPlatfo HRESULT hr; mGDIFontTableAccess = Preferences::GetBool("gfx.font_rendering.directwrite.use_gdi_table_loading", false); mFontSubstitutes.Clear(); mNonExistingFonts.Clear(); - hr = Factory::GetDWriteFactory()-> - GetGdiInterop(getter_AddRefs(mGDIInterop)); + RefPtr<IDWriteFactory> factory = + Factory::GetDWriteFactory(); + + hr = factory->GetGdiInterop(getter_AddRefs(mGDIInterop)); if (FAILED(hr)) { Telemetry::Accumulate(Telemetry::DWRITEFONT_INIT_PROBLEM, uint32_t(errGDIInterop)); return NS_ERROR_FAILURE; } QueryPerformanceCounter(&t2); // base-class/interop initialization - RefPtr<IDWriteFactory> factory = - Factory::GetDWriteFactory(); - - hr = factory->GetSystemFontCollection(getter_AddRefs(mSystemFonts)); - NS_ASSERTION(SUCCEEDED(hr), "GetSystemFontCollection failed!"); + mSystemFonts = Factory::GetDWriteSystemFonts(true); + NS_ASSERTION(mSystemFonts != nullptr, "GetSystemFontCollection failed!"); if (FAILED(hr)) { Telemetry::Accumulate(Telemetry::DWRITEFONT_INIT_PROBLEM, uint32_t(errSystemFontCollection)); return NS_ERROR_FAILURE; } QueryPerformanceCounter(&t3); // system font collection
--- a/ipc/ipdl/sync-messages.ini +++ b/ipc/ipdl/sync-messages.ini @@ -877,18 +877,16 @@ description = Retrieve supported clipboa [PContent::GetIconForExtension] description = [PContent::GetShowPasswordSetting] description = [PContent::KeywordToURI] description = [PContent::NotifyKeywordSearchLoading] description = -[PContent::AllocateLayerTreeId] -description = [PContent::BeginDriverCrashGuard] description = [PContent::EndDriverCrashGuard] description = [PContent::KeygenProcessValue] description = [PContent::KeygenProvideContent] description =
--- a/js/src/frontend/BinSource-auto.cpp +++ b/js/src/frontend/BinSource-auto.cpp @@ -131,106 +131,16 @@ BinASTParser<Tok>::parseSumAssignmentTar break; default: return raiseInvalidKind("AssignmentTarget", kind); } return result; } /* -AssignmentTargetOrAssignmentTargetWithInitializer ::= ArrayAssignmentTarget - AssignmentTargetIdentifier - AssignmentTargetWithInitializer - ComputedMemberAssignmentTarget - ObjectAssignmentTarget - StaticMemberAssignmentTarget -*/ -template<typename Tok> JS::Result<ParseNode*> -BinASTParser<Tok>::parseAssignmentTargetOrAssignmentTargetWithInitializer() -{ - BinKind kind; - BinFields fields(cx_); - AutoTaggedTuple guard(*tokenizer_); - const auto start = tokenizer_->offset(); - - MOZ_TRY(tokenizer_->enterTaggedTuple(kind, fields, guard)); - - BINJS_MOZ_TRY_DECL(result, parseSumAssignmentTargetOrAssignmentTargetWithInitializer(start, kind, fields)); - - MOZ_TRY(guard.done()); - return result; -} - -template<typename Tok> JS::Result<ParseNode*> -BinASTParser<Tok>::parseSumAssignmentTargetOrAssignmentTargetWithInitializer(const size_t start, const BinKind kind, const BinFields& fields) -{ - ParseNode* result; - switch (kind) { - case BinKind::ArrayAssignmentTarget: - MOZ_TRY_VAR(result, parseInterfaceArrayAssignmentTarget(start, kind, fields)); - break; - case BinKind::AssignmentTargetIdentifier: - MOZ_TRY_VAR(result, parseInterfaceAssignmentTargetIdentifier(start, kind, fields)); - break; - case BinKind::AssignmentTargetWithInitializer: - MOZ_TRY_VAR(result, parseInterfaceAssignmentTargetWithInitializer(start, kind, fields)); - break; - case BinKind::ComputedMemberAssignmentTarget: - MOZ_TRY_VAR(result, parseInterfaceComputedMemberAssignmentTarget(start, kind, fields)); - break; - case BinKind::ObjectAssignmentTarget: - MOZ_TRY_VAR(result, parseInterfaceObjectAssignmentTarget(start, kind, fields)); - break; - case BinKind::StaticMemberAssignmentTarget: - MOZ_TRY_VAR(result, parseInterfaceStaticMemberAssignmentTarget(start, kind, fields)); - break; - default: - return raiseInvalidKind("AssignmentTargetOrAssignmentTargetWithInitializer", kind); - } - return result; -} - -/* -AssignmentTargetProperty ::= AssignmentTargetPropertyIdentifier - AssignmentTargetPropertyProperty -*/ -template<typename Tok> JS::Result<ParseNode*> -BinASTParser<Tok>::parseAssignmentTargetProperty() -{ - BinKind kind; - BinFields fields(cx_); - AutoTaggedTuple guard(*tokenizer_); - const auto start = tokenizer_->offset(); - - MOZ_TRY(tokenizer_->enterTaggedTuple(kind, fields, guard)); - - BINJS_MOZ_TRY_DECL(result, parseSumAssignmentTargetProperty(start, kind, fields)); - - MOZ_TRY(guard.done()); - return result; -} - -template<typename Tok> JS::Result<ParseNode*> -BinASTParser<Tok>::parseSumAssignmentTargetProperty(const size_t start, const BinKind kind, const BinFields& fields) -{ - ParseNode* result; - switch (kind) { - case BinKind::AssignmentTargetPropertyIdentifier: - MOZ_TRY_VAR(result, parseInterfaceAssignmentTargetPropertyIdentifier(start, kind, fields)); - break; - case BinKind::AssignmentTargetPropertyProperty: - MOZ_TRY_VAR(result, parseInterfaceAssignmentTargetPropertyProperty(start, kind, fields)); - break; - default: - return raiseInvalidKind("AssignmentTargetProperty", kind); - } - return result; -} - -/* Binding ::= ArrayBinding BindingIdentifier ObjectBinding */ template<typename Tok> JS::Result<ParseNode*> BinASTParser<Tok>::parseBinding() { BinKind kind; @@ -262,98 +172,16 @@ BinASTParser<Tok>::parseSumBinding(const break; default: return raiseInvalidKind("Binding", kind); } return result; } /* -BindingOrBindingWithInitializer ::= ArrayBinding - BindingIdentifier - BindingWithInitializer - ObjectBinding -*/ -template<typename Tok> JS::Result<ParseNode*> -BinASTParser<Tok>::parseBindingOrBindingWithInitializer() -{ - BinKind kind; - BinFields fields(cx_); - AutoTaggedTuple guard(*tokenizer_); - const auto start = tokenizer_->offset(); - - MOZ_TRY(tokenizer_->enterTaggedTuple(kind, fields, guard)); - - BINJS_MOZ_TRY_DECL(result, parseSumBindingOrBindingWithInitializer(start, kind, fields)); - - MOZ_TRY(guard.done()); - return result; -} - -template<typename Tok> JS::Result<ParseNode*> -BinASTParser<Tok>::parseSumBindingOrBindingWithInitializer(const size_t start, const BinKind kind, const BinFields& fields) -{ - ParseNode* result; - switch (kind) { - case BinKind::ArrayBinding: - MOZ_TRY_VAR(result, parseInterfaceArrayBinding(start, kind, fields)); - break; - case BinKind::BindingIdentifier: - MOZ_TRY_VAR(result, parseInterfaceBindingIdentifier(start, kind, fields)); - break; - case BinKind::BindingWithInitializer: - MOZ_TRY_VAR(result, parseInterfaceBindingWithInitializer(start, kind, fields)); - break; - case BinKind::ObjectBinding: - MOZ_TRY_VAR(result, parseInterfaceObjectBinding(start, kind, fields)); - break; - default: - return raiseInvalidKind("BindingOrBindingWithInitializer", kind); - } - return result; -} - -/* -BindingProperty ::= BindingPropertyIdentifier - BindingPropertyProperty -*/ -template<typename Tok> JS::Result<ParseNode*> -BinASTParser<Tok>::parseBindingProperty() -{ - BinKind kind; - BinFields fields(cx_); - AutoTaggedTuple guard(*tokenizer_); - const auto start = tokenizer_->offset(); - - MOZ_TRY(tokenizer_->enterTaggedTuple(kind, fields, guard)); - - BINJS_MOZ_TRY_DECL(result, parseSumBindingProperty(start, kind, fields)); - - MOZ_TRY(guard.done()); - return result; -} - -template<typename Tok> JS::Result<ParseNode*> -BinASTParser<Tok>::parseSumBindingProperty(const size_t start, const BinKind kind, const BinFields& fields) -{ - ParseNode* result; - switch (kind) { - case BinKind::BindingPropertyIdentifier: - MOZ_TRY_VAR(result, parseInterfaceBindingPropertyIdentifier(start, kind, fields)); - break; - case BinKind::BindingPropertyProperty: - MOZ_TRY_VAR(result, parseInterfaceBindingPropertyProperty(start, kind, fields)); - break; - default: - return raiseInvalidKind("BindingProperty", kind); - } - return result; -} - -/* Expression ::= ArrayExpression AssignmentExpression AwaitExpression BinaryExpression CallExpression ClassExpression CompoundAssignmentExpression ComputedMemberExpression @@ -662,177 +490,16 @@ BinASTParser<Tok>::parseSumExpressionOrS break; default: return raiseInvalidKind("ExpressionOrSuper", kind); } return result; } /* -ExpressionOrTemplateElement ::= ArrayExpression - AssignmentExpression - AwaitExpression - BinaryExpression - CallExpression - ClassExpression - CompoundAssignmentExpression - ComputedMemberExpression - ConditionalExpression - EagerArrowExpressionWithExpression - EagerArrowExpressionWithFunctionBody - EagerFunctionExpression - IdentifierExpression - LazyArrowExpressionWithExpression - LazyArrowExpressionWithFunctionBody - LazyFunctionExpression - LiteralBooleanExpression - LiteralInfinityExpression - LiteralNullExpression - LiteralNumericExpression - LiteralRegExpExpression - LiteralStringExpression - NewExpression - NewTargetExpression - ObjectExpression - StaticMemberExpression - TemplateElement - TemplateExpression - ThisExpression - UnaryExpression - UpdateExpression - YieldExpression - YieldStarExpression -*/ -template<typename Tok> JS::Result<ParseNode*> -BinASTParser<Tok>::parseExpressionOrTemplateElement() -{ - BinKind kind; - BinFields fields(cx_); - AutoTaggedTuple guard(*tokenizer_); - const auto start = tokenizer_->offset(); - - MOZ_TRY(tokenizer_->enterTaggedTuple(kind, fields, guard)); - - BINJS_MOZ_TRY_DECL(result, parseSumExpressionOrTemplateElement(start, kind, fields)); - - MOZ_TRY(guard.done()); - return result; -} - -template<typename Tok> JS::Result<ParseNode*> -BinASTParser<Tok>::parseSumExpressionOrTemplateElement(const size_t start, const BinKind kind, const BinFields& fields) -{ - ParseNode* result; - switch (kind) { - case BinKind::ArrayExpression: - MOZ_TRY_VAR(result, parseInterfaceArrayExpression(start, kind, fields)); - break; - case BinKind::AssignmentExpression: - MOZ_TRY_VAR(result, parseInterfaceAssignmentExpression(start, kind, fields)); - break; - case BinKind::AwaitExpression: - MOZ_TRY_VAR(result, parseInterfaceAwaitExpression(start, kind, fields)); - break; - case BinKind::BinaryExpression: - MOZ_TRY_VAR(result, parseInterfaceBinaryExpression(start, kind, fields)); - break; - case BinKind::CallExpression: - MOZ_TRY_VAR(result, parseInterfaceCallExpression(start, kind, fields)); - break; - case BinKind::ClassExpression: - MOZ_TRY_VAR(result, parseInterfaceClassExpression(start, kind, fields)); - break; - case BinKind::CompoundAssignmentExpression: - MOZ_TRY_VAR(result, parseInterfaceCompoundAssignmentExpression(start, kind, fields)); - break; - case BinKind::ComputedMemberExpression: - MOZ_TRY_VAR(result, parseInterfaceComputedMemberExpression(start, kind, fields)); - break; - case BinKind::ConditionalExpression: - MOZ_TRY_VAR(result, parseInterfaceConditionalExpression(start, kind, fields)); - break; - case BinKind::EagerArrowExpressionWithExpression: - MOZ_TRY_VAR(result, parseInterfaceEagerArrowExpressionWithExpression(start, kind, fields)); - break; - case BinKind::EagerArrowExpressionWithFunctionBody: - MOZ_TRY_VAR(result, parseInterfaceEagerArrowExpressionWithFunctionBody(start, kind, fields)); - break; - case BinKind::EagerFunctionExpression: - MOZ_TRY_VAR(result, parseInterfaceEagerFunctionExpression(start, kind, fields)); - break; - case BinKind::IdentifierExpression: - MOZ_TRY_VAR(result, parseInterfaceIdentifierExpression(start, kind, fields)); - break; - case BinKind::LazyArrowExpressionWithExpression: - MOZ_TRY_VAR(result, parseInterfaceLazyArrowExpressionWithExpression(start, kind, fields)); - break; - case BinKind::LazyArrowExpressionWithFunctionBody: - MOZ_TRY_VAR(result, parseInterfaceLazyArrowExpressionWithFunctionBody(start, kind, fields)); - break; - case BinKind::LazyFunctionExpression: - MOZ_TRY_VAR(result, parseInterfaceLazyFunctionExpression(start, kind, fields)); - break; - case BinKind::LiteralBooleanExpression: - MOZ_TRY_VAR(result, parseInterfaceLiteralBooleanExpression(start, kind, fields)); - break; - case BinKind::LiteralInfinityExpression: - MOZ_TRY_VAR(result, parseInterfaceLiteralInfinityExpression(start, kind, fields)); - break; - case BinKind::LiteralNullExpression: - MOZ_TRY_VAR(result, parseInterfaceLiteralNullExpression(start, kind, fields)); - break; - case BinKind::LiteralNumericExpression: - MOZ_TRY_VAR(result, parseInterfaceLiteralNumericExpression(start, kind, fields)); - break; - case BinKind::LiteralRegExpExpression: - MOZ_TRY_VAR(result, parseInterfaceLiteralRegExpExpression(start, kind, fields)); - break; - case BinKind::LiteralStringExpression: - MOZ_TRY_VAR(result, parseInterfaceLiteralStringExpression(start, kind, fields)); - break; - case BinKind::NewExpression: - MOZ_TRY_VAR(result, parseInterfaceNewExpression(start, kind, fields)); - break; - case BinKind::NewTargetExpression: - MOZ_TRY_VAR(result, parseInterfaceNewTargetExpression(start, kind, fields)); - break; - case BinKind::ObjectExpression: - MOZ_TRY_VAR(result, parseInterfaceObjectExpression(start, kind, fields)); - break; - case BinKind::StaticMemberExpression: - MOZ_TRY_VAR(result, parseInterfaceStaticMemberExpression(start, kind, fields)); - break; - case BinKind::TemplateElement: - MOZ_TRY_VAR(result, parseInterfaceTemplateElement(start, kind, fields)); - break; - case BinKind::TemplateExpression: - MOZ_TRY_VAR(result, parseInterfaceTemplateExpression(start, kind, fields)); - break; - case BinKind::ThisExpression: - MOZ_TRY_VAR(result, parseInterfaceThisExpression(start, kind, fields)); - break; - case BinKind::UnaryExpression: - MOZ_TRY_VAR(result, parseInterfaceUnaryExpression(start, kind, fields)); - break; - case BinKind::UpdateExpression: - MOZ_TRY_VAR(result, parseInterfaceUpdateExpression(start, kind, fields)); - break; - case BinKind::YieldExpression: - MOZ_TRY_VAR(result, parseInterfaceYieldExpression(start, kind, fields)); - break; - case BinKind::YieldStarExpression: - MOZ_TRY_VAR(result, parseInterfaceYieldStarExpression(start, kind, fields)); - break; - default: - return raiseInvalidKind("ExpressionOrTemplateElement", kind); - } - return result; -} - -/* ForInOfBindingOrAssignmentTarget ::= ArrayAssignmentTarget AssignmentTargetIdentifier ComputedMemberAssignmentTarget ForInOfBinding ObjectAssignmentTarget StaticMemberAssignmentTarget */ template<typename Tok> JS::Result<ParseNode*> @@ -876,436 +543,16 @@ BinASTParser<Tok>::parseSumForInOfBindin break; default: return raiseInvalidKind("ForInOfBindingOrAssignmentTarget", kind); } return result; } /* -FunctionDeclarationOrClassDeclarationOrExpression ::= ArrayExpression - AssignmentExpression - AwaitExpression - BinaryExpression - CallExpression - ClassDeclaration - ClassExpression - CompoundAssignmentExpression - ComputedMemberExpression - ConditionalExpression - EagerArrowExpressionWithExpression - EagerArrowExpressionWithFunctionBody - EagerFunctionDeclaration - EagerFunctionExpression - IdentifierExpression - LazyArrowExpressionWithExpression - LazyArrowExpressionWithFunctionBody - LazyFunctionDeclaration - LazyFunctionExpression - LiteralBooleanExpression - LiteralInfinityExpression - LiteralNullExpression - LiteralNumericExpression - LiteralRegExpExpression - LiteralStringExpression - NewExpression - NewTargetExpression - ObjectExpression - StaticMemberExpression - TemplateExpression - ThisExpression - UnaryExpression - UpdateExpression - YieldExpression - YieldStarExpression -*/ -template<typename Tok> JS::Result<ParseNode*> -BinASTParser<Tok>::parseFunctionDeclarationOrClassDeclarationOrExpression() -{ - BinKind kind; - BinFields fields(cx_); - AutoTaggedTuple guard(*tokenizer_); - const auto start = tokenizer_->offset(); - - MOZ_TRY(tokenizer_->enterTaggedTuple(kind, fields, guard)); - - BINJS_MOZ_TRY_DECL(result, parseSumFunctionDeclarationOrClassDeclarationOrExpression(start, kind, fields)); - - MOZ_TRY(guard.done()); - return result; -} - -template<typename Tok> JS::Result<ParseNode*> -BinASTParser<Tok>::parseSumFunctionDeclarationOrClassDeclarationOrExpression(const size_t start, const BinKind kind, const BinFields& fields) -{ - ParseNode* result; - switch (kind) { - case BinKind::ArrayExpression: - MOZ_TRY_VAR(result, parseInterfaceArrayExpression(start, kind, fields)); - break; - case BinKind::AssignmentExpression: - MOZ_TRY_VAR(result, parseInterfaceAssignmentExpression(start, kind, fields)); - break; - case BinKind::AwaitExpression: - MOZ_TRY_VAR(result, parseInterfaceAwaitExpression(start, kind, fields)); - break; - case BinKind::BinaryExpression: - MOZ_TRY_VAR(result, parseInterfaceBinaryExpression(start, kind, fields)); - break; - case BinKind::CallExpression: - MOZ_TRY_VAR(result, parseInterfaceCallExpression(start, kind, fields)); - break; - case BinKind::ClassDeclaration: - MOZ_TRY_VAR(result, parseInterfaceClassDeclaration(start, kind, fields)); - break; - case BinKind::ClassExpression: - MOZ_TRY_VAR(result, parseInterfaceClassExpression(start, kind, fields)); - break; - case BinKind::CompoundAssignmentExpression: - MOZ_TRY_VAR(result, parseInterfaceCompoundAssignmentExpression(start, kind, fields)); - break; - case BinKind::ComputedMemberExpression: - MOZ_TRY_VAR(result, parseInterfaceComputedMemberExpression(start, kind, fields)); - break; - case BinKind::ConditionalExpression: - MOZ_TRY_VAR(result, parseInterfaceConditionalExpression(start, kind, fields)); - break; - case BinKind::EagerArrowExpressionWithExpression: - MOZ_TRY_VAR(result, parseInterfaceEagerArrowExpressionWithExpression(start, kind, fields)); - break; - case BinKind::EagerArrowExpressionWithFunctionBody: - MOZ_TRY_VAR(result, parseInterfaceEagerArrowExpressionWithFunctionBody(start, kind, fields)); - break; - case BinKind::EagerFunctionDeclaration: - MOZ_TRY_VAR(result, parseInterfaceEagerFunctionDeclaration(start, kind, fields)); - break; - case BinKind::EagerFunctionExpression: - MOZ_TRY_VAR(result, parseInterfaceEagerFunctionExpression(start, kind, fields)); - break; - case BinKind::IdentifierExpression: - MOZ_TRY_VAR(result, parseInterfaceIdentifierExpression(start, kind, fields)); - break; - case BinKind::LazyArrowExpressionWithExpression: - MOZ_TRY_VAR(result, parseInterfaceLazyArrowExpressionWithExpression(start, kind, fields)); - break; - case BinKind::LazyArrowExpressionWithFunctionBody: - MOZ_TRY_VAR(result, parseInterfaceLazyArrowExpressionWithFunctionBody(start, kind, fields)); - break; - case BinKind::LazyFunctionDeclaration: - MOZ_TRY_VAR(result, parseInterfaceLazyFunctionDeclaration(start, kind, fields)); - break; - case BinKind::LazyFunctionExpression: - MOZ_TRY_VAR(result, parseInterfaceLazyFunctionExpression(start, kind, fields)); - break; - case BinKind::LiteralBooleanExpression: - MOZ_TRY_VAR(result, parseInterfaceLiteralBooleanExpression(start, kind, fields)); - break; - case BinKind::LiteralInfinityExpression: - MOZ_TRY_VAR(result, parseInterfaceLiteralInfinityExpression(start, kind, fields)); - break; - case BinKind::LiteralNullExpression: - MOZ_TRY_VAR(result, parseInterfaceLiteralNullExpression(start, kind, fields)); - break; - case BinKind::LiteralNumericExpression: - MOZ_TRY_VAR(result, parseInterfaceLiteralNumericExpression(start, kind, fields)); - break; - case BinKind::LiteralRegExpExpression: - MOZ_TRY_VAR(result, parseInterfaceLiteralRegExpExpression(start, kind, fields)); - break; - case BinKind::LiteralStringExpression: - MOZ_TRY_VAR(result, parseInterfaceLiteralStringExpression(start, kind, fields)); - break; - case BinKind::NewExpression: - MOZ_TRY_VAR(result, parseInterfaceNewExpression(start, kind, fields)); - break; - case BinKind::NewTargetExpression: - MOZ_TRY_VAR(result, parseInterfaceNewTargetExpression(start, kind, fields)); - break; - case BinKind::ObjectExpression: - MOZ_TRY_VAR(result, parseInterfaceObjectExpression(start, kind, fields)); - break; - case BinKind::StaticMemberExpression: - MOZ_TRY_VAR(result, parseInterfaceStaticMemberExpression(start, kind, fields)); - break; - case BinKind::TemplateExpression: - MOZ_TRY_VAR(result, parseInterfaceTemplateExpression(start, kind, fields)); - break; - case BinKind::ThisExpression: - MOZ_TRY_VAR(result, parseInterfaceThisExpression(start, kind, fields)); - break; - case BinKind::UnaryExpression: - MOZ_TRY_VAR(result, parseInterfaceUnaryExpression(start, kind, fields)); - break; - case BinKind::UpdateExpression: - MOZ_TRY_VAR(result, parseInterfaceUpdateExpression(start, kind, fields)); - break; - case BinKind::YieldExpression: - MOZ_TRY_VAR(result, parseInterfaceYieldExpression(start, kind, fields)); - break; - case BinKind::YieldStarExpression: - MOZ_TRY_VAR(result, parseInterfaceYieldStarExpression(start, kind, fields)); - break; - default: - return raiseInvalidKind("FunctionDeclarationOrClassDeclarationOrExpression", kind); - } - return result; -} - -/* -FunctionDeclarationOrClassDeclarationOrVariableDeclaration ::= ClassDeclaration - EagerFunctionDeclaration - LazyFunctionDeclaration - VariableDeclaration -*/ -template<typename Tok> JS::Result<ParseNode*> -BinASTParser<Tok>::parseFunctionDeclarationOrClassDeclarationOrVariableDeclaration() -{ - BinKind kind; - BinFields fields(cx_); - AutoTaggedTuple guard(*tokenizer_); - const auto start = tokenizer_->offset(); - - MOZ_TRY(tokenizer_->enterTaggedTuple(kind, fields, guard)); - - BINJS_MOZ_TRY_DECL(result, parseSumFunctionDeclarationOrClassDeclarationOrVariableDeclaration(start, kind, fields)); - - MOZ_TRY(guard.done()); - return result; -} - -template<typename Tok> JS::Result<ParseNode*> -BinASTParser<Tok>::parseSumFunctionDeclarationOrClassDeclarationOrVariableDeclaration(const size_t start, const BinKind kind, const BinFields& fields) -{ - ParseNode* result; - switch (kind) { - case BinKind::ClassDeclaration: - MOZ_TRY_VAR(result, parseInterfaceClassDeclaration(start, kind, fields)); - break; - case BinKind::EagerFunctionDeclaration: - MOZ_TRY_VAR(result, parseInterfaceEagerFunctionDeclaration(start, kind, fields)); - break; - case BinKind::LazyFunctionDeclaration: - MOZ_TRY_VAR(result, parseInterfaceLazyFunctionDeclaration(start, kind, fields)); - break; - case BinKind::VariableDeclaration: - MOZ_TRY_VAR(result, parseInterfaceVariableDeclaration(start, kind, fields)); - break; - default: - return raiseInvalidKind("FunctionDeclarationOrClassDeclarationOrVariableDeclaration", kind); - } - return result; -} - -/* -ImportDeclarationOrExportDeclarationOrStatement ::= Block - BreakStatement - ClassDeclaration - ContinueStatement - DebuggerStatement - DoWhileStatement - EagerFunctionDeclaration - EmptyStatement - Export - ExportAllFrom - ExportDefault - ExportFrom - ExportLocals - ExpressionStatement - ForInStatement - ForOfStatement - ForStatement - IfStatement - Import - ImportNamespace - LabelledStatement - LazyFunctionDeclaration - ReturnStatement - SwitchStatement - SwitchStatementWithDefault - ThrowStatement - TryCatchStatement - TryFinallyStatement - VariableDeclaration - WhileStatement - WithStatement -*/ -template<typename Tok> JS::Result<ParseNode*> -BinASTParser<Tok>::parseImportDeclarationOrExportDeclarationOrStatement() -{ - BinKind kind; - BinFields fields(cx_); - AutoTaggedTuple guard(*tokenizer_); - const auto start = tokenizer_->offset(); - - MOZ_TRY(tokenizer_->enterTaggedTuple(kind, fields, guard)); - - BINJS_MOZ_TRY_DECL(result, parseSumImportDeclarationOrExportDeclarationOrStatement(start, kind, fields)); - - MOZ_TRY(guard.done()); - return result; -} - -template<typename Tok> JS::Result<ParseNode*> -BinASTParser<Tok>::parseSumImportDeclarationOrExportDeclarationOrStatement(const size_t start, const BinKind kind, const BinFields& fields) -{ - ParseNode* result; - switch (kind) { - case BinKind::Block: - MOZ_TRY_VAR(result, parseInterfaceBlock(start, kind, fields)); - break; - case BinKind::BreakStatement: - MOZ_TRY_VAR(result, parseInterfaceBreakStatement(start, kind, fields)); - break; - case BinKind::ClassDeclaration: - MOZ_TRY_VAR(result, parseInterfaceClassDeclaration(start, kind, fields)); - break; - case BinKind::ContinueStatement: - MOZ_TRY_VAR(result, parseInterfaceContinueStatement(start, kind, fields)); - break; - case BinKind::DebuggerStatement: - MOZ_TRY_VAR(result, parseInterfaceDebuggerStatement(start, kind, fields)); - break; - case BinKind::DoWhileStatement: - MOZ_TRY_VAR(result, parseInterfaceDoWhileStatement(start, kind, fields)); - break; - case BinKind::EagerFunctionDeclaration: - MOZ_TRY_VAR(result, parseInterfaceEagerFunctionDeclaration(start, kind, fields)); - break; - case BinKind::EmptyStatement: - MOZ_TRY_VAR(result, parseInterfaceEmptyStatement(start, kind, fields)); - break; - case BinKind::Export: - MOZ_TRY_VAR(result, parseInterfaceExport(start, kind, fields)); - break; - case BinKind::ExportAllFrom: - MOZ_TRY_VAR(result, parseInterfaceExportAllFrom(start, kind, fields)); - break; - case BinKind::ExportDefault: - MOZ_TRY_VAR(result, parseInterfaceExportDefault(start, kind, fields)); - break; - case BinKind::ExportFrom: - MOZ_TRY_VAR(result, parseInterfaceExportFrom(start, kind, fields)); - break; - case BinKind::ExportLocals: - MOZ_TRY_VAR(result, parseInterfaceExportLocals(start, kind, fields)); - break; - case BinKind::ExpressionStatement: - MOZ_TRY_VAR(result, parseInterfaceExpressionStatement(start, kind, fields)); - break; - case BinKind::ForInStatement: - MOZ_TRY_VAR(result, parseInterfaceForInStatement(start, kind, fields)); - break; - case BinKind::ForOfStatement: - MOZ_TRY_VAR(result, parseInterfaceForOfStatement(start, kind, fields)); - break; - case BinKind::ForStatement: - MOZ_TRY_VAR(result, parseInterfaceForStatement(start, kind, fields)); - break; - case BinKind::IfStatement: - MOZ_TRY_VAR(result, parseInterfaceIfStatement(start, kind, fields)); - break; - case BinKind::Import: - MOZ_TRY_VAR(result, parseInterfaceImport(start, kind, fields)); - break; - case BinKind::ImportNamespace: - MOZ_TRY_VAR(result, parseInterfaceImportNamespace(start, kind, fields)); - break; - case BinKind::LabelledStatement: - MOZ_TRY_VAR(result, parseInterfaceLabelledStatement(start, kind, fields)); - break; - case BinKind::LazyFunctionDeclaration: - MOZ_TRY_VAR(result, parseInterfaceLazyFunctionDeclaration(start, kind, fields)); - break; - case BinKind::ReturnStatement: - MOZ_TRY_VAR(result, parseInterfaceReturnStatement(start, kind, fields)); - break; - case BinKind::SwitchStatement: - MOZ_TRY_VAR(result, parseInterfaceSwitchStatement(start, kind, fields)); - break; - case BinKind::SwitchStatementWithDefault: - MOZ_TRY_VAR(result, parseInterfaceSwitchStatementWithDefault(start, kind, fields)); - break; - case BinKind::ThrowStatement: - MOZ_TRY_VAR(result, parseInterfaceThrowStatement(start, kind, fields)); - break; - case BinKind::TryCatchStatement: - MOZ_TRY_VAR(result, parseInterfaceTryCatchStatement(start, kind, fields)); - break; - case BinKind::TryFinallyStatement: - MOZ_TRY_VAR(result, parseInterfaceTryFinallyStatement(start, kind, fields)); - break; - case BinKind::VariableDeclaration: - MOZ_TRY_VAR(result, parseInterfaceVariableDeclaration(start, kind, fields)); - break; - case BinKind::WhileStatement: - MOZ_TRY_VAR(result, parseInterfaceWhileStatement(start, kind, fields)); - break; - case BinKind::WithStatement: - MOZ_TRY_VAR(result, parseInterfaceWithStatement(start, kind, fields)); - break; - default: - return raiseInvalidKind("ImportDeclarationOrExportDeclarationOrStatement", kind); - } - return result; -} - -/* -MethodDefinition ::= EagerGetter - EagerMethod - EagerSetter - LazyGetter - LazyMethod - LazySetter -*/ -template<typename Tok> JS::Result<ParseNode*> -BinASTParser<Tok>::parseMethodDefinition() -{ - BinKind kind; - BinFields fields(cx_); - AutoTaggedTuple guard(*tokenizer_); - const auto start = tokenizer_->offset(); - - MOZ_TRY(tokenizer_->enterTaggedTuple(kind, fields, guard)); - - BINJS_MOZ_TRY_DECL(result, parseSumMethodDefinition(start, kind, fields)); - - MOZ_TRY(guard.done()); - return result; -} - -template<typename Tok> JS::Result<ParseNode*> -BinASTParser<Tok>::parseSumMethodDefinition(const size_t start, const BinKind kind, const BinFields& fields) -{ - ParseNode* result; - switch (kind) { - case BinKind::EagerGetter: - MOZ_TRY_VAR(result, parseInterfaceEagerGetter(start, kind, fields)); - break; - case BinKind::EagerMethod: - MOZ_TRY_VAR(result, parseInterfaceEagerMethod(start, kind, fields)); - break; - case BinKind::EagerSetter: - MOZ_TRY_VAR(result, parseInterfaceEagerSetter(start, kind, fields)); - break; - case BinKind::LazyGetter: - MOZ_TRY_VAR(result, parseInterfaceLazyGetter(start, kind, fields)); - break; - case BinKind::LazyMethod: - MOZ_TRY_VAR(result, parseInterfaceLazyMethod(start, kind, fields)); - break; - case BinKind::LazySetter: - MOZ_TRY_VAR(result, parseInterfaceLazySetter(start, kind, fields)); - break; - default: - return raiseInvalidKind("MethodDefinition", kind); - } - return result; -} - -/* ObjectProperty ::= DataProperty EagerGetter EagerMethod EagerSetter LazyGetter LazyMethod LazySetter ShorthandProperty @@ -1957,82 +1204,16 @@ BinASTParser<Tok>::parseInterfaceArrayEx elements->setHasNonConstInitializer(); } auto result = elements; return result; } /* - interface ArrowExpressionContentsWithExpression : Node { - AssertedParameterScope parameterScope; - FormalParameters params; - AssertedVarScope bodyScope; - Expression body; - } -*/ -template<typename Tok> JS::Result<ParseNode*> -BinASTParser<Tok>::parseArrowExpressionContentsWithExpression() -{ - BinKind kind; - BinFields fields(cx_); - AutoTaggedTuple guard(*tokenizer_); - - MOZ_TRY(tokenizer_->enterTaggedTuple(kind, fields, guard)); - if (kind != BinKind::ArrowExpressionContentsWithExpression) { - return raiseInvalidKind("ArrowExpressionContentsWithExpression", kind); - } - const auto start = tokenizer_->offset(); - BINJS_MOZ_TRY_DECL(result, parseInterfaceArrowExpressionContentsWithExpression(start, kind, fields)); - MOZ_TRY(guard.done()); - - return result; -} - -template<typename Tok> JS::Result<ParseNode*> -BinASTParser<Tok>::parseInterfaceArrowExpressionContentsWithExpression(const size_t start, const BinKind kind, const BinFields& fields) -{ - return raiseError("FIXME: Not implemented yet in this preview release (ArrowExpressionContentsWithExpression)"); -} - - -/* - interface ArrowExpressionContentsWithFunctionBody : Node { - AssertedParameterScope parameterScope; - FormalParameters params; - AssertedVarScope bodyScope; - FunctionBody body; - } -*/ -template<typename Tok> JS::Result<ParseNode*> -BinASTParser<Tok>::parseArrowExpressionContentsWithFunctionBody() -{ - BinKind kind; - BinFields fields(cx_); - AutoTaggedTuple guard(*tokenizer_); - - MOZ_TRY(tokenizer_->enterTaggedTuple(kind, fields, guard)); - if (kind != BinKind::ArrowExpressionContentsWithFunctionBody) { - return raiseInvalidKind("ArrowExpressionContentsWithFunctionBody", kind); - } - const auto start = tokenizer_->offset(); - BINJS_MOZ_TRY_DECL(result, parseInterfaceArrowExpressionContentsWithFunctionBody(start, kind, fields)); - MOZ_TRY(guard.done()); - - return result; -} - -template<typename Tok> JS::Result<ParseNode*> -BinASTParser<Tok>::parseInterfaceArrowExpressionContentsWithFunctionBody(const size_t start, const BinKind kind, const BinFields& fields) -{ - return raiseError("FIXME: Not implemented yet in this preview release (ArrowExpressionContentsWithFunctionBody)"); -} - - -/* interface AssertedBlockScope : Node { FrozenArray<AssertedDeclaredName> declaredNames; bool hasDirectEval; } */ template<typename Tok> JS::Result<Ok> BinASTParser<Tok>::parseAssertedBlockScope() { @@ -2236,22 +1417,16 @@ BinASTParser<Tok>::parseInterfaceAsserte ParseContext::Scope* scope; DeclarationKind declKind; MOZ_TRY(getDeclaredScope(scopeKind, kind_, scope, declKind)); MOZ_TRY(addScopeName(scopeKind, name, scope, declKind, isCaptured, allowDuplicateName)); auto result = Ok(); return result; } -template<typename Tok> JS::Result<ParseNode*> -BinASTParser<Tok>::parseInterfaceAssertedParameterName(const size_t start, const BinKind kind, const BinFields& fields) -{ - return raiseError("FIXME: Not implemented yet in this preview release (AssertedParameterName)"); -} - /* interface AssertedParameterScope : Node { FrozenArray<AssertedMaybePositionalParameterName> paramNames; bool hasDirectEval; bool isSimpleParameterList; } */ @@ -2349,22 +1524,16 @@ BinASTParser<Tok>::parseInterfaceAsserte ParseContext::Scope* scope; DeclarationKind declKind; MOZ_TRY(getBoundScope(scopeKind, scope, declKind)); MOZ_TRY(addScopeName(scopeKind, name, scope, declKind, isCaptured, allowDuplicateName)); auto result = Ok(); return result; } -template<typename Tok> JS::Result<ParseNode*> -BinASTParser<Tok>::parseInterfaceAssertedRestParameterName(const size_t start, const BinKind kind, const BinFields& fields) -{ - return raiseError("FIXME: Not implemented yet in this preview release (AssertedRestParameterName)"); -} - /* interface AssertedScriptGlobalScope : Node { FrozenArray<AssertedDeclaredName> declaredNames; bool hasDirectEval; } */ template<typename Tok> JS::Result<Ok> @@ -2482,40 +1651,16 @@ BinASTParser<Tok>::parseInterfaceAssignm BINJS_MOZ_TRY_DECL(binding, parseAssignmentTarget()); BINJS_MOZ_TRY_DECL(expression, parseExpression()); BINJS_TRY_DECL(result, factory_.newAssignment(ParseNodeKind::Assign, binding, expression)); return result; } - -/* - interface AssignmentTargetIdentifier : Node { - [IdentifierName] string name; - } -*/ -template<typename Tok> JS::Result<ParseNode*> -BinASTParser<Tok>::parseAssignmentTargetIdentifier() -{ - BinKind kind; - BinFields fields(cx_); - AutoTaggedTuple guard(*tokenizer_); - - MOZ_TRY(tokenizer_->enterTaggedTuple(kind, fields, guard)); - if (kind != BinKind::AssignmentTargetIdentifier) { - return raiseInvalidKind("AssignmentTargetIdentifier", kind); - } - const auto start = tokenizer_->offset(); - BINJS_MOZ_TRY_DECL(result, parseInterfaceAssignmentTargetIdentifier(start, kind, fields)); - MOZ_TRY(guard.done()); - - return result; -} - template<typename Tok> JS::Result<ParseNode*> BinASTParser<Tok>::parseInterfaceAssignmentTargetIdentifier(const size_t start, const BinKind kind, const BinFields& fields) { MOZ_ASSERT(kind == BinKind::AssignmentTargetIdentifier); BINJS_TRY(CheckRecursionLimit(cx_)); #if defined(DEBUG) const BinField expected_fields[1] = { BinField::Name }; @@ -2529,34 +1674,16 @@ BinASTParser<Tok>::parseInterfaceAssignm return raiseError("Invalid identifier"); } BINJS_TRY(usedNames_.noteUse(cx_, name, parseContext_->scriptId(), parseContext_->innermostScope()->id())); BINJS_TRY_DECL(result, factory_.newName(name->asPropertyName(), tokenizer_->pos(start), cx_)); return result; } template<typename Tok> JS::Result<ParseNode*> -BinASTParser<Tok>::parseInterfaceAssignmentTargetPropertyIdentifier(const size_t start, const BinKind kind, const BinFields& fields) -{ - return raiseError("FIXME: Not implemented yet in this preview release (AssignmentTargetPropertyIdentifier)"); -} - -template<typename Tok> JS::Result<ParseNode*> -BinASTParser<Tok>::parseInterfaceAssignmentTargetPropertyProperty(const size_t start, const BinKind kind, const BinFields& fields) -{ - return raiseError("FIXME: Not implemented yet in this preview release (AssignmentTargetPropertyProperty)"); -} - -template<typename Tok> JS::Result<ParseNode*> -BinASTParser<Tok>::parseInterfaceAssignmentTargetWithInitializer(const size_t start, const BinKind kind, const BinFields& fields) -{ - return raiseError("FIXME: Not implemented yet in this preview release (AssignmentTargetWithInitializer)"); -} - -template<typename Tok> JS::Result<ParseNode*> BinASTParser<Tok>::parseInterfaceAwaitExpression(const size_t start, const BinKind kind, const BinFields& fields) { return raiseError("FIXME: Not implemented yet in this preview release (AwaitExpression)"); } template<typename Tok> JS::Result<ParseNode*> BinASTParser<Tok>::parseInterfaceBinaryExpression(const size_t start, const BinKind kind, const BinFields& fields) { @@ -2711,28 +1838,16 @@ BinASTParser<Tok>::parseInterfaceBinding if (!IsIdentifier(name)) { return raiseError("Invalid identifier"); } BINJS_TRY_DECL(result, factory_.newName(name->asPropertyName(), tokenizer_->pos(start), cx_)); return result; } template<typename Tok> JS::Result<ParseNode*> -BinASTParser<Tok>::parseInterfaceBindingPropertyIdentifier(const size_t start, const BinKind kind, const BinFields& fields) -{ - return raiseError("FIXME: Not implemented yet in this preview release (BindingPropertyIdentifier)"); -} - -template<typename Tok> JS::Result<ParseNode*> -BinASTParser<Tok>::parseInterfaceBindingPropertyProperty(const size_t start, const BinKind kind, const BinFields& fields) -{ - return raiseError("FIXME: Not implemented yet in this preview release (BindingPropertyProperty)"); -} - -template<typename Tok> JS::Result<ParseNode*> BinASTParser<Tok>::parseInterfaceBindingWithInitializer(const size_t start, const BinKind kind, const BinFields& fields) { return raiseError("FIXME: Not implemented yet in this preview release (BindingWithInitializer)"); } /* interface Block : Node { @@ -2916,47 +2031,16 @@ BinASTParser<Tok>::parseInterfaceCatchCl } template<typename Tok> JS::Result<ParseNode*> BinASTParser<Tok>::parseInterfaceClassDeclaration(const size_t start, const BinKind kind, const BinFields& fields) { return raiseError("FIXME: Not implemented yet in this preview release (ClassDeclaration)"); } - -/* - interface ClassElement : Node { - bool isStatic; - MethodDefinition method; - } -*/ -template<typename Tok> JS::Result<ParseNode*> -BinASTParser<Tok>::parseClassElement() -{ - BinKind kind; - BinFields fields(cx_); - AutoTaggedTuple guard(*tokenizer_); - - MOZ_TRY(tokenizer_->enterTaggedTuple(kind, fields, guard)); - if (kind != BinKind::ClassElement) { - return raiseInvalidKind("ClassElement", kind); - } - const auto start = tokenizer_->offset(); - BINJS_MOZ_TRY_DECL(result, parseInterfaceClassElement(start, kind, fields)); - MOZ_TRY(guard.done()); - - return result; -} - -template<typename Tok> JS::Result<ParseNode*> -BinASTParser<Tok>::parseInterfaceClassElement(const size_t start, const BinKind kind, const BinFields& fields) -{ - return raiseError("FIXME: Not implemented yet in this preview release (ClassElement)"); -} - template<typename Tok> JS::Result<ParseNode*> BinASTParser<Tok>::parseInterfaceClassExpression(const size_t start, const BinKind kind, const BinFields& fields) { return raiseError("FIXME: Not implemented yet in this preview release (ClassExpression)"); } template<typename Tok> JS::Result<ParseNode*> BinASTParser<Tok>::parseInterfaceCompoundAssignmentExpression(const size_t start, const BinKind kind, const BinFields& fields) @@ -3499,108 +2583,16 @@ BinASTParser<Tok>::parseInterfaceEmptySt BINJS_TRY(CheckRecursionLimit(cx_)); MOZ_TRY(tokenizer_->checkFields0(kind, fields)); BINJS_TRY_DECL(result, factory_.newEmptyStatement(tokenizer_->pos(start))); return result; } template<typename Tok> JS::Result<ParseNode*> -BinASTParser<Tok>::parseInterfaceExport(const size_t start, const BinKind kind, const BinFields& fields) -{ - return raiseError("FIXME: Not implemented yet in this preview release (Export)"); -} - -template<typename Tok> JS::Result<ParseNode*> -BinASTParser<Tok>::parseInterfaceExportAllFrom(const size_t start, const BinKind kind, const BinFields& fields) -{ - return raiseError("FIXME: Not implemented yet in this preview release (ExportAllFrom)"); -} - -template<typename Tok> JS::Result<ParseNode*> -BinASTParser<Tok>::parseInterfaceExportDefault(const size_t start, const BinKind kind, const BinFields& fields) -{ - return raiseError("FIXME: Not implemented yet in this preview release (ExportDefault)"); -} - -template<typename Tok> JS::Result<ParseNode*> -BinASTParser<Tok>::parseInterfaceExportFrom(const size_t start, const BinKind kind, const BinFields& fields) -{ - return raiseError("FIXME: Not implemented yet in this preview release (ExportFrom)"); -} - - -/* - interface ExportFromSpecifier : Node { - [IdentifierName] string name; - [IdentifierName] string? exportedName; - } -*/ -template<typename Tok> JS::Result<ParseNode*> -BinASTParser<Tok>::parseExportFromSpecifier() -{ - BinKind kind; - BinFields fields(cx_); - AutoTaggedTuple guard(*tokenizer_); - - MOZ_TRY(tokenizer_->enterTaggedTuple(kind, fields, guard)); - if (kind != BinKind::ExportFromSpecifier) { - return raiseInvalidKind("ExportFromSpecifier", kind); - } - const auto start = tokenizer_->offset(); - BINJS_MOZ_TRY_DECL(result, parseInterfaceExportFromSpecifier(start, kind, fields)); - MOZ_TRY(guard.done()); - - return result; -} - -template<typename Tok> JS::Result<ParseNode*> -BinASTParser<Tok>::parseInterfaceExportFromSpecifier(const size_t start, const BinKind kind, const BinFields& fields) -{ - return raiseError("FIXME: Not implemented yet in this preview release (ExportFromSpecifier)"); -} - - -/* - interface ExportLocalSpecifier : Node { - IdentifierExpression name; - [PropertyKey] string? exportedName; - } -*/ -template<typename Tok> JS::Result<ParseNode*> -BinASTParser<Tok>::parseExportLocalSpecifier() -{ - BinKind kind; - BinFields fields(cx_); - AutoTaggedTuple guard(*tokenizer_); - - MOZ_TRY(tokenizer_->enterTaggedTuple(kind, fields, guard)); - if (kind != BinKind::ExportLocalSpecifier) { - return raiseInvalidKind("ExportLocalSpecifier", kind); - } - const auto start = tokenizer_->offset(); - BINJS_MOZ_TRY_DECL(result, parseInterfaceExportLocalSpecifier(start, kind, fields)); - MOZ_TRY(guard.done()); - - return result; -} - -template<typename Tok> JS::Result<ParseNode*> -BinASTParser<Tok>::parseInterfaceExportLocalSpecifier(const size_t start, const BinKind kind, const BinFields& fields) -{ - return raiseError("FIXME: Not implemented yet in this preview release (ExportLocalSpecifier)"); -} - -template<typename Tok> JS::Result<ParseNode*> -BinASTParser<Tok>::parseInterfaceExportLocals(const size_t start, const BinKind kind, const BinFields& fields) -{ - return raiseError("FIXME: Not implemented yet in this preview release (ExportLocals)"); -} - -template<typename Tok> JS::Result<ParseNode*> BinASTParser<Tok>::parseInterfaceExpressionStatement(const size_t start, const BinKind kind, const BinFields& fields) { MOZ_ASSERT(kind == BinKind::ExpressionStatement); BINJS_TRY(CheckRecursionLimit(cx_)); #if defined(DEBUG) const BinField expected_fields[1] = { BinField::Expression }; MOZ_TRY(tokenizer_->checkFields(kind, fields, expected_fields)); @@ -4028,59 +3020,16 @@ BinASTParser<Tok>::parseInterfaceIfState BINJS_MOZ_TRY_DECL(alternate, parseOptionalStatement()); BINJS_TRY_DECL(result, factory_.newIfStatement(start, test, consequent, alternate)); return result; } template<typename Tok> JS::Result<ParseNode*> -BinASTParser<Tok>::parseInterfaceImport(const size_t start, const BinKind kind, const BinFields& fields) -{ - return raiseError("FIXME: Not implemented yet in this preview release (Import)"); -} - -template<typename Tok> JS::Result<ParseNode*> -BinASTParser<Tok>::parseInterfaceImportNamespace(const size_t start, const BinKind kind, const BinFields& fields) -{ - return raiseError("FIXME: Not implemented yet in this preview release (ImportNamespace)"); -} - - -/* - interface ImportSpecifier : Node { - [PropertyKey] string? name; - BindingIdentifier binding; - } -*/ -template<typename Tok> JS::Result<ParseNode*> -BinASTParser<Tok>::parseImportSpecifier() -{ - BinKind kind; - BinFields fields(cx_); - AutoTaggedTuple guard(*tokenizer_); - - MOZ_TRY(tokenizer_->enterTaggedTuple(kind, fields, guard)); - if (kind != BinKind::ImportSpecifier) { - return raiseInvalidKind("ImportSpecifier", kind); - } - const auto start = tokenizer_->offset(); - BINJS_MOZ_TRY_DECL(result, parseInterfaceImportSpecifier(start, kind, fields)); - MOZ_TRY(guard.done()); - - return result; -} - -template<typename Tok> JS::Result<ParseNode*> -BinASTParser<Tok>::parseInterfaceImportSpecifier(const size_t start, const BinKind kind, const BinFields& fields) -{ - return raiseError("FIXME: Not implemented yet in this preview release (ImportSpecifier)"); -} - -template<typename Tok> JS::Result<ParseNode*> BinASTParser<Tok>::parseInterfaceLabelledStatement(const size_t start, const BinKind kind, const BinFields& fields) { MOZ_ASSERT(kind == BinKind::LabelledStatement); BINJS_TRY(CheckRecursionLimit(cx_)); #if defined(DEBUG) const BinField expected_fields[2] = { BinField::Label, BinField::Body }; MOZ_TRY(tokenizer_->checkFields(kind, fields, expected_fields)); @@ -4770,22 +3719,16 @@ BinASTParser<Tok>::parseInterfaceSwitchS iter = next; } BINJS_TRY_DECL(scope, factory_.newLexicalScope(nullptr, cases)); BINJS_TRY_DECL(result, factory_.newSwitchStatement(start, discriminant, scope, true)); return result; } template<typename Tok> JS::Result<ParseNode*> -BinASTParser<Tok>::parseInterfaceTemplateElement(const size_t start, const BinKind kind, const BinFields& fields) -{ - return raiseError("FIXME: Not implemented yet in this preview release (TemplateElement)"); -} - -template<typename Tok> JS::Result<ParseNode*> BinASTParser<Tok>::parseInterfaceTemplateExpression(const size_t start, const BinKind kind, const BinFields& fields) { return raiseError("FIXME: Not implemented yet in this preview release (TemplateExpression)"); } template<typename Tok> JS::Result<ParseNode*> BinASTParser<Tok>::parseInterfaceThisExpression(const size_t start, const BinKind kind, const BinFields& fields) { @@ -5493,40 +4436,16 @@ BinASTParser<Tok>::parseListOfAssertedMa scopeKind, positionalParams)); // Nothing to do here. } MOZ_TRY(guard.done()); return result; } -template<typename Tok> JS::Result<ParseNode*> -BinASTParser<Tok>::parseListOfAssignmentTargetOrAssignmentTargetWithInitializer() -{ - return raiseError("FIXME: Not implemented yet in this preview release (ListOfAssignmentTargetOrAssignmentTargetWithInitializer)"); -} - -template<typename Tok> JS::Result<ParseNode*> -BinASTParser<Tok>::parseListOfAssignmentTargetProperty() -{ - return raiseError("FIXME: Not implemented yet in this preview release (ListOfAssignmentTargetProperty)"); -} - -template<typename Tok> JS::Result<ParseNode*> -BinASTParser<Tok>::parseListOfBindingProperty() -{ - return raiseError("FIXME: Not implemented yet in this preview release (ListOfBindingProperty)"); -} - -template<typename Tok> JS::Result<ParseNode*> -BinASTParser<Tok>::parseListOfClassElement() -{ - return raiseError("FIXME: Not implemented yet in this preview release (ListOfClassElement)"); -} - template<typename Tok> JS::Result<ListNode*> BinASTParser<Tok>::parseListOfDirective() { uint32_t length; AutoList guard(*tokenizer_); const auto start = tokenizer_->offset(); MOZ_TRY(tokenizer_->enterList(length, guard)); @@ -5536,46 +4455,16 @@ BinASTParser<Tok>::parseListOfDirective( BINJS_MOZ_TRY_DECL(item, parseDirective()); factory_.addStatementToList(result, item); } MOZ_TRY(guard.done()); return result; } -template<typename Tok> JS::Result<ParseNode*> -BinASTParser<Tok>::parseListOfExportFromSpecifier() -{ - return raiseError("FIXME: Not implemented yet in this preview release (ListOfExportFromSpecifier)"); -} - -template<typename Tok> JS::Result<ParseNode*> -BinASTParser<Tok>::parseListOfExportLocalSpecifier() -{ - return raiseError("FIXME: Not implemented yet in this preview release (ListOfExportLocalSpecifier)"); -} - -template<typename Tok> JS::Result<ParseNode*> -BinASTParser<Tok>::parseListOfExpressionOrTemplateElement() -{ - return raiseError("FIXME: Not implemented yet in this preview release (ListOfExpressionOrTemplateElement)"); -} - -template<typename Tok> JS::Result<ParseNode*> -BinASTParser<Tok>::parseListOfImportDeclarationOrExportDeclarationOrStatement() -{ - return raiseError("FIXME: Not implemented yet in this preview release (ListOfImportDeclarationOrExportDeclarationOrStatement)"); -} - -template<typename Tok> JS::Result<ParseNode*> -BinASTParser<Tok>::parseListOfImportSpecifier() -{ - return raiseError("FIXME: Not implemented yet in this preview release (ListOfImportSpecifier)"); -} - template<typename Tok> JS::Result<ListNode*> BinASTParser<Tok>::parseListOfObjectProperty() { uint32_t length; AutoList guard(*tokenizer_); const auto start = tokenizer_->offset(); MOZ_TRY(tokenizer_->enterList(length, guard)); @@ -5587,22 +4476,16 @@ BinASTParser<Tok>::parseListOfObjectProp result->setHasNonConstInitializer(); result->appendWithoutOrderAssumption(item); } MOZ_TRY(guard.done()); return result; } -template<typename Tok> JS::Result<ParseNode*> -BinASTParser<Tok>::parseListOfOptionalBindingOrBindingWithInitializer() -{ - return raiseError("FIXME: Not implemented yet in this preview release (ListOfOptionalBindingOrBindingWithInitializer)"); -} - template<typename Tok> JS::Result<ListNode*> BinASTParser<Tok>::parseListOfOptionalSpreadElementOrExpression() { uint32_t length; AutoList guard(*tokenizer_); const auto start = tokenizer_->offset(); MOZ_TRY(tokenizer_->enterList(length, guard)); @@ -5696,36 +4579,16 @@ BinASTParser<Tok>::parseListOfVariableDe MOZ_TRY(guard.done()); return result; } // ----- Default values (by lexicographical order) template<typename Tok> JS::Result<ParseNode*> -BinASTParser<Tok>::parseOptionalAssignmentTarget() -{ - BinKind kind; - BinFields fields(cx_); - AutoTaggedTuple guard(*tokenizer_); - - MOZ_TRY(tokenizer_->enterTaggedTuple(kind, fields, guard)); - ParseNode* result; - if (kind == BinKind::_Null) { - result = nullptr; - } else { - const auto start = tokenizer_->offset(); - MOZ_TRY_VAR(result, parseSumAssignmentTarget(start, kind, fields)); - } - MOZ_TRY(guard.done()); - - return result; -} - -template<typename Tok> JS::Result<ParseNode*> BinASTParser<Tok>::parseOptionalBinding() { BinKind kind; BinFields fields(cx_); AutoTaggedTuple guard(*tokenizer_); MOZ_TRY(tokenizer_->enterTaggedTuple(kind, fields, guard)); ParseNode* result; @@ -5757,36 +4620,16 @@ BinASTParser<Tok>::parseOptionalBindingI } else { return raiseInvalidKind("BindingIdentifier", kind); } MOZ_TRY(guard.done()); return result; } -template<typename Tok> JS::Result<ParseNode*> -BinASTParser<Tok>::parseOptionalBindingOrBindingWithInitializer() -{ - BinKind kind; - BinFields fields(cx_); - AutoTaggedTuple guard(*tokenizer_); - - MOZ_TRY(tokenizer_->enterTaggedTuple(kind, fields, guard)); - ParseNode* result; - if (kind == BinKind::_Null) { - result = nullptr; - } else { - const auto start = tokenizer_->offset(); - MOZ_TRY_VAR(result, parseSumBindingOrBindingWithInitializer(start, kind, fields)); - } - MOZ_TRY(guard.done()); - - return result; -} - template<typename Tok> JS::Result<LexicalScopeNode*> BinASTParser<Tok>::parseOptionalCatchClause() { BinKind kind; BinFields fields(cx_); AutoTaggedTuple guard(*tokenizer_); MOZ_TRY(tokenizer_->enterTaggedTuple(kind, fields, guard));
--- a/js/src/frontend/BinSource-auto.h +++ b/js/src/frontend/BinSource-auto.h @@ -88,145 +88,110 @@ enum class VariableDeclarationKind { // ----- Sums of interfaces (by lexicographical order) // Implementations are autogenerated // `ParseNode*` may never be nullptr JS::Result<Ok> parseAssertedMaybePositionalParameterName( AssertedScopeKind scopeKind, MutableHandle<GCVector<JSAtom*>> positionalParams); JS::Result<ParseNode*> parseAssignmentTarget(); -JS::Result<ParseNode*> parseAssignmentTargetOrAssignmentTargetWithInitializer(); -JS::Result<ParseNode*> parseAssignmentTargetProperty(); JS::Result<ParseNode*> parseBinding(); -JS::Result<ParseNode*> parseBindingOrBindingWithInitializer(); -JS::Result<ParseNode*> parseBindingProperty(); JS::Result<ParseNode*> parseExpression(); JS::Result<ParseNode*> parseExpressionOrSuper(); -JS::Result<ParseNode*> parseExpressionOrTemplateElement(); JS::Result<ParseNode*> parseForInOfBindingOrAssignmentTarget(); -JS::Result<ParseNode*> parseFunctionDeclarationOrClassDeclarationOrExpression(); -JS::Result<ParseNode*> parseFunctionDeclarationOrClassDeclarationOrVariableDeclaration(); -JS::Result<ParseNode*> parseImportDeclarationOrExportDeclarationOrStatement(); -JS::Result<ParseNode*> parseMethodDefinition(); JS::Result<ParseNode*> parseObjectProperty(); JS::Result<ParseNode*> parseParameter(); JS::Result<ParseNode*> parseProgram(); JS::Result<ParseNode*> parsePropertyName(); JS::Result<ParseNode*> parseSimpleAssignmentTarget(); JS::Result<ParseNode*> parseSpreadElementOrExpression(); JS::Result<ParseNode*> parseStatement(); JS::Result<Ok> parseSumAssertedMaybePositionalParameterName(const size_t start, const BinKind kind, const BinFields& fields, AssertedScopeKind scopeKind, MutableHandle<GCVector<JSAtom*>> positionalParams); JS::Result<ParseNode*> parseSumAssignmentTarget(const size_t start, const BinKind kind, const BinFields& fields); -JS::Result<ParseNode*> parseSumAssignmentTargetOrAssignmentTargetWithInitializer(const size_t start, const BinKind kind, const BinFields& fields); -JS::Result<ParseNode*> parseSumAssignmentTargetProperty(const size_t start, const BinKind kind, const BinFields& fields); JS::Result<ParseNode*> parseSumBinding(const size_t start, const BinKind kind, const BinFields& fields); -JS::Result<ParseNode*> parseSumBindingOrBindingWithInitializer(const size_t start, const BinKind kind, const BinFields& fields); -JS::Result<ParseNode*> parseSumBindingProperty(const size_t start, const BinKind kind, const BinFields& fields); JS::Result<ParseNode*> parseSumExpression(const size_t start, const BinKind kind, const BinFields& fields); JS::Result<ParseNode*> parseSumExpressionOrSuper(const size_t start, const BinKind kind, const BinFields& fields); -JS::Result<ParseNode*> parseSumExpressionOrTemplateElement(const size_t start, const BinKind kind, const BinFields& fields); JS::Result<ParseNode*> parseSumForInOfBindingOrAssignmentTarget(const size_t start, const BinKind kind, const BinFields& fields); -JS::Result<ParseNode*> parseSumFunctionDeclarationOrClassDeclarationOrExpression(const size_t start, const BinKind kind, const BinFields& fields); -JS::Result<ParseNode*> parseSumFunctionDeclarationOrClassDeclarationOrVariableDeclaration(const size_t start, const BinKind kind, const BinFields& fields); -JS::Result<ParseNode*> parseSumImportDeclarationOrExportDeclarationOrStatement(const size_t start, const BinKind kind, const BinFields& fields); -JS::Result<ParseNode*> parseSumMethodDefinition(const size_t start, const BinKind kind, const BinFields& fields); JS::Result<ParseNode*> parseSumObjectProperty(const size_t start, const BinKind kind, const BinFields& fields); JS::Result<ParseNode*> parseSumParameter(const size_t start, const BinKind kind, const BinFields& fields); JS::Result<ParseNode*> parseSumProgram(const size_t start, const BinKind kind, const BinFields& fields); JS::Result<ParseNode*> parseSumPropertyName(const size_t start, const BinKind kind, const BinFields& fields); JS::Result<ParseNode*> parseSumSimpleAssignmentTarget(const size_t start, const BinKind kind, const BinFields& fields); JS::Result<ParseNode*> parseSumSpreadElementOrExpression(const size_t start, const BinKind kind, const BinFields& fields); JS::Result<ParseNode*> parseSumStatement(const size_t start, const BinKind kind, const BinFields& fields); JS::Result<ParseNode*> parseSumVariableDeclarationOrExpression(const size_t start, const BinKind kind, const BinFields& fields); // ----- Interfaces (by lexicographical order) // Implementations are autogenerated // `ParseNode*` may never be nullptr -JS::Result<ParseNode*> parseArrowExpressionContentsWithExpression(); -JS::Result<ParseNode*> parseArrowExpressionContentsWithFunctionBody(); JS::Result<Ok> parseAssertedBlockScope(); JS::Result<Ok> parseAssertedBoundName( AssertedScopeKind scopeKind); JS::Result<Ok> parseAssertedBoundNamesScope(); JS::Result<Ok> parseAssertedDeclaredName( AssertedScopeKind scopeKind); JS::Result<Ok> parseAssertedParameterScope( MutableHandle<GCVector<JSAtom*>> positionalParams); JS::Result<Ok> parseAssertedScriptGlobalScope(); JS::Result<Ok> parseAssertedVarScope(); -JS::Result<ParseNode*> parseAssignmentTargetIdentifier(); JS::Result<ParseNode*> parseBindingIdentifier(); JS::Result<ParseNode*> parseBlock(); JS::Result<LexicalScopeNode*> parseCatchClause(); -JS::Result<ParseNode*> parseClassElement(); JS::Result<ParseNode*> parseDirective(); -JS::Result<ParseNode*> parseExportFromSpecifier(); -JS::Result<ParseNode*> parseExportLocalSpecifier(); JS::Result<ListNode*> parseFormalParameters(); JS::Result<Ok> parseFunctionExpressionContents( uint32_t funLength, ListNode** paramsOut, ListNode** bodyOut); JS::Result<Ok> parseFunctionOrMethodContents( uint32_t funLength, ListNode** paramsOut, ListNode** bodyOut); JS::Result<Ok> parseGetterContents( uint32_t funLength, ListNode** paramsOut, ListNode** bodyOut); JS::Result<ParseNode*> parseIdentifierExpression(); -JS::Result<ParseNode*> parseImportSpecifier(); JS::Result<Ok> parseSetterContents( uint32_t funLength, ListNode** paramsOut, ListNode** bodyOut); JS::Result<CaseClause*> parseSwitchCase(); JS::Result<ParseNode*> parseSwitchDefault(); JS::Result<ParseNode*> parseVariableDeclarator(); JS::Result<ParseNode*> parseInterfaceArrayAssignmentTarget(const size_t start, const BinKind kind, const BinFields& fields); JS::Result<ParseNode*> parseInterfaceArrayBinding(const size_t start, const BinKind kind, const BinFields& fields); JS::Result<ParseNode*> parseInterfaceArrayExpression(const size_t start, const BinKind kind, const BinFields& fields); -JS::Result<ParseNode*> parseInterfaceArrowExpressionContentsWithExpression(const size_t start, const BinKind kind, const BinFields& fields); -JS::Result<ParseNode*> parseInterfaceArrowExpressionContentsWithFunctionBody(const size_t start, const BinKind kind, const BinFields& fields); JS::Result<Ok> parseInterfaceAssertedBlockScope(const size_t start, const BinKind kind, const BinFields& fields); JS::Result<Ok> parseInterfaceAssertedBoundName(const size_t start, const BinKind kind, const BinFields& fields, AssertedScopeKind scopeKind); JS::Result<Ok> parseInterfaceAssertedBoundNamesScope(const size_t start, const BinKind kind, const BinFields& fields); JS::Result<Ok> parseInterfaceAssertedDeclaredName(const size_t start, const BinKind kind, const BinFields& fields, AssertedScopeKind scopeKind); -JS::Result<ParseNode*> parseInterfaceAssertedParameterName(const size_t start, const BinKind kind, const BinFields& fields); JS::Result<Ok> parseInterfaceAssertedParameterScope(const size_t start, const BinKind kind, const BinFields& fields, MutableHandle<GCVector<JSAtom*>> positionalParams); JS::Result<Ok> parseInterfaceAssertedPositionalParameterName(const size_t start, const BinKind kind, const BinFields& fields, AssertedScopeKind scopeKind, MutableHandle<GCVector<JSAtom*>> positionalParams); -JS::Result<ParseNode*> parseInterfaceAssertedRestParameterName(const size_t start, const BinKind kind, const BinFields& fields); JS::Result<Ok> parseInterfaceAssertedScriptGlobalScope(const size_t start, const BinKind kind, const BinFields& fields); JS::Result<Ok> parseInterfaceAssertedVarScope(const size_t start, const BinKind kind, const BinFields& fields); JS::Result<ParseNode*> parseInterfaceAssignmentExpression(const size_t start, const BinKind kind, const BinFields& fields); JS::Result<ParseNode*> parseInterfaceAssignmentTargetIdentifier(const size_t start, const BinKind kind, const BinFields& fields); -JS::Result<ParseNode*> parseInterfaceAssignmentTargetPropertyIdentifier(const size_t start, const BinKind kind, const BinFields& fields); -JS::Result<ParseNode*> parseInterfaceAssignmentTargetPropertyProperty(const size_t start, const BinKind kind, const BinFields& fields); -JS::Result<ParseNode*> parseInterfaceAssignmentTargetWithInitializer(const size_t start, const BinKind kind, const BinFields& fields); JS::Result<ParseNode*> parseInterfaceAwaitExpression(const size_t start, const BinKind kind, const BinFields& fields); JS::Result<ParseNode*> parseInterfaceBinaryExpression(const size_t start, const BinKind kind, const BinFields& fields); JS::Result<ParseNode*> parseInterfaceBindingIdentifier(const size_t start, const BinKind kind, const BinFields& fields); -JS::Result<ParseNode*> parseInterfaceBindingPropertyIdentifier(const size_t start, const BinKind kind, const BinFields& fields); -JS::Result<ParseNode*> parseInterfaceBindingPropertyProperty(const size_t start, const BinKind kind, const BinFields& fields); JS::Result<ParseNode*> parseInterfaceBindingWithInitializer(const size_t start, const BinKind kind, const BinFields& fields); JS::Result<ParseNode*> parseInterfaceBlock(const size_t start, const BinKind kind, const BinFields& fields); JS::Result<ParseNode*> parseInterfaceBreakStatement(const size_t start, const BinKind kind, const BinFields& fields); JS::Result<ParseNode*> parseInterfaceCallExpression(const size_t start, const BinKind kind, const BinFields& fields); JS::Result<LexicalScopeNode*> parseInterfaceCatchClause(const size_t start, const BinKind kind, const BinFields& fields); JS::Result<ParseNode*> parseInterfaceClassDeclaration(const size_t start, const BinKind kind, const BinFields& fields); -JS::Result<ParseNode*> parseInterfaceClassElement(const size_t start, const BinKind kind, const BinFields& fields); JS::Result<ParseNode*> parseInterfaceClassExpression(const size_t start, const BinKind kind, const BinFields& fields); JS::Result<ParseNode*> parseInterfaceCompoundAssignmentExpression(const size_t start, const BinKind kind, const BinFields& fields); JS::Result<ParseNode*> parseInterfaceComputedMemberAssignmentTarget(const size_t start, const BinKind kind, const BinFields& fields); JS::Result<ParseNode*> parseInterfaceComputedMemberExpression(const size_t start, const BinKind kind, const BinFields& fields); JS::Result<ParseNode*> parseInterfaceComputedPropertyName(const size_t start, const BinKind kind, const BinFields& fields); JS::Result<ParseNode*> parseInterfaceConditionalExpression(const size_t start, const BinKind kind, const BinFields& fields); JS::Result<ParseNode*> parseInterfaceContinueStatement(const size_t start, const BinKind kind, const BinFields& fields); JS::Result<ParseNode*> parseInterfaceDataProperty(const size_t start, const BinKind kind, const BinFields& fields); @@ -236,23 +201,16 @@ JS::Result<ParseNode*> parseInterfaceDoW JS::Result<ParseNode*> parseInterfaceEagerArrowExpressionWithExpression(const size_t start, const BinKind kind, const BinFields& fields); JS::Result<ParseNode*> parseInterfaceEagerArrowExpressionWithFunctionBody(const size_t start, const BinKind kind, const BinFields& fields); JS::Result<ParseNode*> parseInterfaceEagerFunctionDeclaration(const size_t start, const BinKind kind, const BinFields& fields); JS::Result<ParseNode*> parseInterfaceEagerFunctionExpression(const size_t start, const BinKind kind, const BinFields& fields); JS::Result<ParseNode*> parseInterfaceEagerGetter(const size_t start, const BinKind kind, const BinFields& fields); JS::Result<ParseNode*> parseInterfaceEagerMethod(const size_t start, const BinKind kind, const BinFields& fields); JS::Result<ParseNode*> parseInterfaceEagerSetter(const size_t start, const BinKind kind, const BinFields& fields); JS::Result<ParseNode*> parseInterfaceEmptyStatement(const size_t start, const BinKind kind, const BinFields& fields); -JS::Result<ParseNode*> parseInterfaceExport(const size_t start, const BinKind kind, const BinFields& fields); -JS::Result<ParseNode*> parseInterfaceExportAllFrom(const size_t start, const BinKind kind, const BinFields& fields); -JS::Result<ParseNode*> parseInterfaceExportDefault(const size_t start, const BinKind kind, const BinFields& fields); -JS::Result<ParseNode*> parseInterfaceExportFrom(const size_t start, const BinKind kind, const BinFields& fields); -JS::Result<ParseNode*> parseInterfaceExportFromSpecifier(const size_t start, const BinKind kind, const BinFields& fields); -JS::Result<ParseNode*> parseInterfaceExportLocalSpecifier(const size_t start, const BinKind kind, const BinFields& fields); -JS::Result<ParseNode*> parseInterfaceExportLocals(const size_t start, const BinKind kind, const BinFields& fields); JS::Result<ParseNode*> parseInterfaceExpressionStatement(const size_t start, const BinKind kind, const BinFields& fields); JS::Result<ParseNode*> parseInterfaceForInOfBinding(const size_t start, const BinKind kind, const BinFields& fields); JS::Result<ParseNode*> parseInterfaceForInStatement(const size_t start, const BinKind kind, const BinFields& fields); JS::Result<ParseNode*> parseInterfaceForOfStatement(const size_t start, const BinKind kind, const BinFields& fields); JS::Result<ParseNode*> parseInterfaceForStatement(const size_t start, const BinKind kind, const BinFields& fields); JS::Result<ListNode*> parseInterfaceFormalParameters(const size_t start, const BinKind kind, const BinFields& fields); JS::Result<Ok> parseInterfaceFunctionExpressionContents(const size_t start, const BinKind kind, const BinFields& fields, uint32_t funLength, @@ -263,19 +221,16 @@ JS::Result<Ok> parseInterfaceFunctionOrM ListNode** paramsOut, ListNode** bodyOut); JS::Result<Ok> parseInterfaceGetterContents(const size_t start, const BinKind kind, const BinFields& fields, uint32_t funLength, ListNode** paramsOut, ListNode** bodyOut); JS::Result<ParseNode*> parseInterfaceIdentifierExpression(const size_t start, const BinKind kind, const BinFields& fields); JS::Result<ParseNode*> parseInterfaceIfStatement(const size_t start, const BinKind kind, const BinFields& fields); -JS::Result<ParseNode*> parseInterfaceImport(const size_t start, const BinKind kind, const BinFields& fields); -JS::Result<ParseNode*> parseInterfaceImportNamespace(const size_t start, const BinKind kind, const BinFields& fields); -JS::Result<ParseNode*> parseInterfaceImportSpecifier(const size_t start, const BinKind kind, const BinFields& fields); JS::Result<ParseNode*> parseInterfaceLabelledStatement(const size_t start, const BinKind kind, const BinFields& fields); JS::Result<ParseNode*> parseInterfaceLazyArrowExpressionWithExpression(const size_t start, const BinKind kind, const BinFields& fields); JS::Result<ParseNode*> parseInterfaceLazyArrowExpressionWithFunctionBody(const size_t start, const BinKind kind, const BinFields& fields); JS::Result<ParseNode*> parseInterfaceLazyFunctionDeclaration(const size_t start, const BinKind kind, const BinFields& fields); JS::Result<ParseNode*> parseInterfaceLazyFunctionExpression(const size_t start, const BinKind kind, const BinFields& fields); JS::Result<ParseNode*> parseInterfaceLazyGetter(const size_t start, const BinKind kind, const BinFields& fields); JS::Result<ParseNode*> parseInterfaceLazyMethod(const size_t start, const BinKind kind, const BinFields& fields); JS::Result<ParseNode*> parseInterfaceLazySetter(const size_t start, const BinKind kind, const BinFields& fields); @@ -302,17 +257,16 @@ JS::Result<ParseNode*> parseInterfaceSho JS::Result<ParseNode*> parseInterfaceSpreadElement(const size_t start, const BinKind kind, const BinFields& fields); JS::Result<ParseNode*> parseInterfaceStaticMemberAssignmentTarget(const size_t start, const BinKind kind, const BinFields& fields); JS::Result<ParseNode*> parseInterfaceStaticMemberExpression(const size_t start, const BinKind kind, const BinFields& fields); JS::Result<ParseNode*> parseInterfaceSuper(const size_t start, const BinKind kind, const BinFields& fields); JS::Result<CaseClause*> parseInterfaceSwitchCase(const size_t start, const BinKind kind, const BinFields& fields); JS::Result<ParseNode*> parseInterfaceSwitchDefault(const size_t start, const BinKind kind, const BinFields& fields); JS::Result<ParseNode*> parseInterfaceSwitchStatement(const size_t start, const BinKind kind, const BinFields& fields); JS::Result<ParseNode*> parseInterfaceSwitchStatementWithDefault(const size_t start, const BinKind kind, const BinFields& fields); -JS::Result<ParseNode*> parseInterfaceTemplateElement(const size_t start, const BinKind kind, const BinFields& fields); JS::Result<ParseNode*> parseInterfaceTemplateExpression(const size_t start, const BinKind kind, const BinFields& fields); JS::Result<ParseNode*> parseInterfaceThisExpression(const size_t start, const BinKind kind, const BinFields& fields); JS::Result<ParseNode*> parseInterfaceThrowStatement(const size_t start, const BinKind kind, const BinFields& fields); JS::Result<ParseNode*> parseInterfaceTryCatchStatement(const size_t start, const BinKind kind, const BinFields& fields); JS::Result<ParseNode*> parseInterfaceTryFinallyStatement(const size_t start, const BinKind kind, const BinFields& fields); JS::Result<ParseNode*> parseInterfaceUnaryExpression(const size_t start, const BinKind kind, const BinFields& fields); JS::Result<ParseNode*> parseInterfaceUpdateExpression(const size_t start, const BinKind kind, const BinFields& fields); JS::Result<ParseNode*> parseInterfaceVariableDeclaration(const size_t start, const BinKind kind, const BinFields& fields); @@ -339,39 +293,27 @@ JS::Result<ParseNode*> parseArguments(); JS::Result<ListNode*> parseFunctionBody(); JS::Result<Ok> parseListOfAssertedBoundName( AssertedScopeKind scopeKind); JS::Result<Ok> parseListOfAssertedDeclaredName( AssertedScopeKind scopeKind); JS::Result<Ok> parseListOfAssertedMaybePositionalParameterName( AssertedScopeKind scopeKind, MutableHandle<GCVector<JSAtom*>> positionalParams); -JS::Result<ParseNode*> parseListOfAssignmentTargetOrAssignmentTargetWithInitializer(); -JS::Result<ParseNode*> parseListOfAssignmentTargetProperty(); -JS::Result<ParseNode*> parseListOfBindingProperty(); -JS::Result<ParseNode*> parseListOfClassElement(); JS::Result<ListNode*> parseListOfDirective(); -JS::Result<ParseNode*> parseListOfExportFromSpecifier(); -JS::Result<ParseNode*> parseListOfExportLocalSpecifier(); -JS::Result<ParseNode*> parseListOfExpressionOrTemplateElement(); -JS::Result<ParseNode*> parseListOfImportDeclarationOrExportDeclarationOrStatement(); -JS::Result<ParseNode*> parseListOfImportSpecifier(); JS::Result<ListNode*> parseListOfObjectProperty(); -JS::Result<ParseNode*> parseListOfOptionalBindingOrBindingWithInitializer(); JS::Result<ListNode*> parseListOfOptionalSpreadElementOrExpression(); JS::Result<ListNode*> parseListOfParameter(); JS::Result<ListNode*> parseListOfStatement(); JS::Result<ListNode*> parseListOfSwitchCase(); JS::Result<ListNode*> parseListOfVariableDeclarator(); // ----- Default values (by lexicographical order) // Implementations are autogenerated -JS::Result<ParseNode*> parseOptionalAssignmentTarget(); JS::Result<ParseNode*> parseOptionalBinding(); JS::Result<ParseNode*> parseOptionalBindingIdentifier(); -JS::Result<ParseNode*> parseOptionalBindingOrBindingWithInitializer(); JS::Result<LexicalScopeNode*> parseOptionalCatchClause(); JS::Result<ParseNode*> parseOptionalExpression(); JS::Result<ParseNode*> parseOptionalSpreadElementOrExpression(); JS::Result<ParseNode*> parseOptionalStatement(); JS::Result<ParseNode*> parseOptionalVariableDeclarationOrExpression();
--- a/js/src/frontend/binsource/src/main.rs +++ b/js/src/frontend/binsource/src/main.rs @@ -514,24 +514,16 @@ const INTERFACE_PARAMS: &str = /// Fixed arguments of interface method. const INTERFACE_ARGS: &str = "start, kind, fields"; /// The name of the toplevel interface for the script. const TOPLEVEL_INTERFACE: &str = "Program"; -/// Get Rc<String> from NodeName. -/// -/// FIXME: Do not clone the String itself, but just clone the Rc<String> inside -/// NodeName (Bug 1504597). -fn string_from_nodename(name: &NodeName) -> Rc<String> { - Rc::new(name.to_string().clone()) -} - /// The actual exporter. struct CPPExporter { /// The syntax to export. syntax: Spec, /// Rules, as specified in yaml. rules: GlobalRules, @@ -638,61 +630,95 @@ impl CPPExporter { let mut refgraph = ReferenceGraph::new(); // FIXME: Reflect `replace` rule in yaml file for each interface to // the reference (bug 1504595). // 1. Typesums let sums_of_interfaces = self.syntax.resolved_sums_of_interfaces_by_name(); for (name, nodes) in sums_of_interfaces { + let rules_for_this_sum = self.rules.get(name); + let mut edges: HashSet<Rc<String>> = HashSet::new(); edges.insert(Rc::new(format!("Sum{}", name))); - refgraph.insert(string_from_nodename(name), edges); + refgraph.insert(name.to_rc_string().clone(), edges); let mut sum_edges: HashSet<Rc<String>> = HashSet::new(); for node in nodes { + let rule_for_this_arm = rules_for_this_sum.by_sum.get(&node) + .cloned() + .unwrap_or_default(); + + // If this arm is disabled, we emit raiseError instead of + // call to parseInterface*. Do not add edge in that case. + if rule_for_this_arm.disabled { + continue; + } + sum_edges.insert(Rc::new(format!("Interface{}", node.to_string()))); } refgraph.insert(Rc::new(format!("Sum{}", name.to_string())), sum_edges); } // 2. Single interfaces let interfaces_by_name = self.syntax.interfaces_by_name(); for (name, interface) in interfaces_by_name { - let mut edges: HashSet<Rc<String>> = HashSet::new(); - edges.insert(Rc::new(format!("Interface{}", name))); - refgraph.insert(string_from_nodename(name), edges); + let rules_for_this_interface = self.rules.get(name); + let is_implemented = rules_for_this_interface.build_result.is_some(); + // If this interafce is not implemented, parse* method should + // not be called nor referenced in the graph. + if is_implemented { + let mut edges: HashSet<Rc<String>> = HashSet::new(); + edges.insert(Rc::new(format!("Interface{}", name))); + refgraph.insert(name.to_rc_string().clone(), edges); + } let mut interface_edges: HashSet<Rc<String>> = HashSet::new(); - for field in interface.contents().fields() { - match field.type_().get_primitive(&self.syntax) { - Some(IsNullable { is_nullable: _, content: Primitive::Interface(_) }) - | None => { - let typename = TypeName::type_(field.type_()); - interface_edges.insert(Rc::new(typename.to_string())); - }, + // If this interface is not implemented, we emit raiseError in + // parseInterface* method, instead of parse* for each fields. + // There can be reference to parseInterface* of this interface + // from sum interface, and this node needs to be represented in + // the reference graph. + if is_implemented { + for field in interface.contents().fields() { + match field.type_().get_primitive(&self.syntax) { + Some(IsNullable { is_nullable: _, content: Primitive::Interface(_) }) + | None => { + let typename = TypeName::type_(field.type_()); + interface_edges.insert(Rc::new(typename.to_string())); + }, - // Don't have to handle other type of fields (string, - // number, bool, etc). - _ => {} + // Don't have to handle other type of fields (string, + // number, bool, etc). + _ => {} + } } } refgraph.insert(Rc::new(format!("Interface{}", name)), interface_edges); } // 3. String Enums for (kind, _) in self.syntax.string_enums_by_name() { - refgraph.insert(string_from_nodename(kind), HashSet::new()); + refgraph.insert(kind.to_rc_string().clone(), HashSet::new()); } // 4. Lists for parser in &self.list_parsers_to_generate { + let name = &parser.name; + let rules_for_this_list = self.rules.get(name); + let is_implemented = rules_for_this_list.init.is_some(); + // If this list is not implemented, this method should not be + // called nor referenced in the graph. + if !is_implemented { + continue; + } + let mut edges: HashSet<Rc<String>> = HashSet::new(); - edges.insert(string_from_nodename(&parser.elements)); - refgraph.insert(string_from_nodename(&parser.name), edges); + edges.insert(parser.elements.to_rc_string().clone()); + refgraph.insert(name.to_rc_string().clone(), edges); } // 5. Optional values for parser in &self.option_parsers_to_generate { let mut edges: HashSet<Rc<String>> = HashSet::new(); let named_implementation = if let Some(NamedType::Typedef(ref typedef)) = self.syntax.get_type_by_name(&parser.name) { assert!(typedef.is_optional()); @@ -717,17 +743,17 @@ impl CPPExporter { &TypeSpec::TypeSum(_) => { edges.insert(Rc::new(format!("Sum{}", parser.elements.to_string()))); }, _ => {} } }, _ => {} } - refgraph.insert(string_from_nodename(&parser.name), edges); + refgraph.insert(parser.name.to_rc_string().clone(), edges); } // 6. Primitive values. refgraph.insert(Rc::new("IdentifierName".to_string()), HashSet::new()); refgraph.insert(Rc::new("PropertyKey".to_string()), HashSet::new()); self.refgraph = refgraph; } @@ -978,17 +1004,17 @@ enum class BinVariant { fn export_declare_sums_of_interface_methods(&self, buffer: &mut String) { let sums_of_interfaces = self.syntax.resolved_sums_of_interfaces_by_name() .iter() .sorted_by(|a, b| a.0.cmp(&b.0)); buffer.push_str("\n\n// ----- Sums of interfaces (by lexicographical order)\n"); buffer.push_str("// Implementations are autogenerated\n"); buffer.push_str("// `ParseNode*` may never be nullptr\n"); for &(ref name, _) in &sums_of_interfaces { - if !self.refgraph.is_used(string_from_nodename(&name)) { + if !self.refgraph.is_used(name.to_rc_string().clone()) { continue; } let rules_for_this_sum = self.rules.get(name); let extra_params = rules_for_this_sum.extra_params; let rendered = self.get_method_signature(name, "", "", &extra_params); buffer.push_str(&rendered.reindent("") @@ -1020,17 +1046,17 @@ enum class BinVariant { let mut outer_parsers = Vec::with_capacity(interfaces_by_name.len()); let mut inner_parsers = Vec::with_capacity(interfaces_by_name.len()); for &(name, _) in &interfaces_by_name { let rules_for_this_interface = self.rules.get(name); let extra_params = rules_for_this_interface.extra_params; - if self.refgraph.is_used(string_from_nodename(name)) { + if self.refgraph.is_used(name.to_rc_string().clone()) { let outer = self.get_method_signature(name, "", "", &extra_params); outer_parsers.push(outer.reindent("")); } let inner_prefix = "Interface"; if !self.refgraph.is_used(Rc::new(format!("{}{}", inner_prefix, name))) { continue; } @@ -1053,48 +1079,48 @@ enum class BinVariant { fn export_declare_string_enums_methods(&self, buffer: &mut String) { buffer.push_str("\n\n// ----- String enums (by lexicographical order)\n"); buffer.push_str("// Implementations are autogenerated\n"); let string_enums_by_name = self.syntax.string_enums_by_name() .iter() .sorted_by(|a, b| str::cmp(a.0.to_str(), b.0.to_str())); for (kind, _) in string_enums_by_name { - if !self.refgraph.is_used(string_from_nodename(kind)) { + if !self.refgraph.is_used(kind.to_rc_string().clone()) { continue; } let rendered = self.get_method_signature(kind, "", "", &None); buffer.push_str(&rendered.reindent("")); buffer.push_str("\n"); } } fn export_declare_list_methods(&self, buffer: &mut String) { buffer.push_str("\n\n// ----- Lists (by lexicographical order)\n"); buffer.push_str("// Implementations are autogenerated\n"); for parser in &self.list_parsers_to_generate { - if !self.refgraph.is_used(string_from_nodename(&parser.name)) { + if !self.refgraph.is_used(parser.name.to_rc_string().clone()) { continue; } let rules_for_this_node = self.rules.get(&parser.name); let extra_params = rules_for_this_node.extra_params; let rendered = self.get_method_signature(&parser.name, "", "", &extra_params); buffer.push_str(&rendered.reindent("")); buffer.push_str("\n"); } } fn export_declare_option_methods(&self, buffer: &mut String) { buffer.push_str("\n\n// ----- Default values (by lexicographical order)\n"); buffer.push_str("// Implementations are autogenerated\n"); for parser in &self.option_parsers_to_generate { - if !self.refgraph.is_used(string_from_nodename(&parser.name)) { + if !self.refgraph.is_used(parser.name.to_rc_string().clone()) { continue; } let rules_for_this_node = self.rules.get(&parser.name); let extra_params = rules_for_this_node.extra_params; let rendered = self.get_method_signature(&parser.name, "", "", &extra_params); buffer.push_str(&rendered.reindent("")); @@ -1146,17 +1172,17 @@ impl CPPExporter { // Generate comments (FIXME: We should use the actual webidl, not the resolved sum) let rules_for_this_sum = self.rules.get(name); let extra_params = rules_for_this_sum.extra_params; let extra_args = rules_for_this_sum.extra_args; let nodes = nodes.iter() .sorted(); let kind = name.to_class_cases(); - if self.refgraph.is_used(string_from_nodename(name)) { + if self.refgraph.is_used(name.to_rc_string().clone()) { let rendered_bnf = format!("/*\n{name} ::= {nodes}\n*/", nodes = nodes.iter() .format("\n "), name = name.to_str()); // Generate outer method buffer.push_str(&format!("{bnf} {first_line} @@ -1234,17 +1260,17 @@ impl CPPExporter { INTERFACE_PARAMS, &extra_params), type_ok = self.get_type_ok(name) )); } /// Generate the implementation of a single list parser fn generate_implement_list(&self, buffer: &mut String, parser: &ListParserData) { - if !self.refgraph.is_used(string_from_nodename(&parser.name)) { + if !self.refgraph.is_used(parser.name.to_rc_string().clone()) { return; } let rules_for_this_list = self.rules.get(&parser.name); let extra_params = rules_for_this_list.extra_params; let extra_args = rules_for_this_list.extra_args; // Warn if some rules are unused. @@ -1327,17 +1353,17 @@ impl CPPExporter { append = append); buffer.push_str(&rendered); } fn generate_implement_option(&self, buffer: &mut String, parser: &OptionParserData) { debug!(target: "generate_spidermonkey", "Implementing optional value {} backed by {}", parser.name.to_str(), parser.elements.to_str()); - if !self.refgraph.is_used(string_from_nodename(&parser.name)) { + if !self.refgraph.is_used(parser.name.to_rc_string().clone()) { return; } let rules_for_this_node = self.rules.get(&parser.name); let extra_params = rules_for_this_node.extra_params; let extra_args = rules_for_this_node.extra_args; // Warn if some rules are unused. @@ -1578,17 +1604,17 @@ impl CPPExporter { for &(condition, rule_name) in &[ (rules_for_this_interface.append.is_some(), "build:"), ] { if condition { warn!("In {}, rule `{}` was specified but is ignored.", name, rule_name); } } - if self.refgraph.is_used(string_from_nodename(name)) { + if self.refgraph.is_used(name.to_rc_string().clone()) { // Generate comments let comment = format!("\n/*\n{}*/\n", ToWebidl::interface(interface, "", " ")); buffer.push_str(&comment); // Generate public method buffer.push_str(&format!("{first_line} {{ BinKind kind; @@ -1860,17 +1886,17 @@ impl CPPExporter { // 3. String Enums buffer.push_str("\n\n// ----- String enums (autogenerated, by lexicographical order)\n"); { let string_enums_by_name = self.syntax.string_enums_by_name() .iter() .sorted_by(|a, b| str::cmp(a.0.to_str(), b.0.to_str())); for (kind, enum_) in string_enums_by_name { - if !self.refgraph.is_used(string_from_nodename(kind)) { + if !self.refgraph.is_used(kind.to_rc_string().clone()) { continue; } let convert = format!(" switch (variant) {{ {cases} default: return raiseInvalidVariant(\"{kind}\", variant); }}",
--- a/layout/generic/nsSubDocumentFrame.cpp +++ b/layout/generic/nsSubDocumentFrame.cpp @@ -8,17 +8,17 @@ * rendering object for replaced elements that contain a document, such * as <frame>, <iframe>, and some <object>s */ #include "nsSubDocumentFrame.h" #include "gfxPrefs.h" -#include "mozilla/layout/RenderFrameParent.h" +#include "mozilla/layout/RenderFrame.h" #include "nsCOMPtr.h" #include "nsGenericHTMLElement.h" #include "nsGenericHTMLFrameElement.h" #include "nsAttrValueInlines.h" #include "nsIDocShell.h" #include "nsIContentViewer.h" #include "nsIContentInlines.h" @@ -41,17 +41,17 @@ #include "nsContentUtils.h" #include "nsIPermissionManager.h" #include "nsServiceManagerUtils.h" #include "mozilla/Preferences.h" #include "mozilla/dom/HTMLFrameElement.h" #include "RetainedDisplayListBuilder.h" using namespace mozilla; -using mozilla::layout::RenderFrameParent; +using mozilla::layout::RenderFrame; static bool sShowPreviousPage = true; static nsIDocument* GetDocumentFromView(nsView* aView) { MOZ_ASSERT(aView, "null view"); @@ -328,28 +328,28 @@ WrapBackgroundColorInOwnLayer(nsDisplayL void nsSubDocumentFrame::BuildDisplayList(nsDisplayListBuilder* aBuilder, const nsDisplayListSet& aLists) { if (!IsVisibleForPainting(aBuilder)) return; nsFrameLoader* frameLoader = FrameLoader(); - RenderFrameParent* rfp = nullptr; + RenderFrame* rf = nullptr; if (frameLoader) { - rfp = frameLoader->GetCurrentRenderFrame(); + rf = frameLoader->GetCurrentRenderFrame(); } // If we are pointer-events:none then we don't need to HitTest background bool pointerEventsNone = StyleUI()->mPointerEvents == NS_STYLE_POINTER_EVENTS_NONE; if (!aBuilder->IsForEventDelivery() || !pointerEventsNone) { nsDisplayListCollection decorations(aBuilder); DisplayBorderBackgroundOutline(aBuilder, decorations); - if (rfp) { + if (rf) { // Wrap background colors of <iframe>s with remote subdocuments in their // own layer so we generate a ColorLayer. This is helpful for optimizing // compositing; we can skip compositing the ColorLayer when the // remote content is opaque. WrapBackgroundColorInOwnLayer(aBuilder, this, decorations.BorderBackground()); } decorations.MoveTo(aLists); } @@ -361,17 +361,17 @@ nsSubDocumentFrame::BuildDisplayList(nsD // If we're passing pointer events to children then we have to descend into // subdocuments no matter what, to determine which parts are transparent for // hit-testing or event regions. bool needToDescend = aBuilder->GetDescendIntoSubdocuments(); if (!mInnerView || !needToDescend) { return; } - if (rfp) { + if (rf) { // We're the subdoc for <browser remote="true"> and it has // painted content. Display its shadow layer tree. DisplayListClipState::AutoSaveRestore clipState(aBuilder); nsPoint offset = aBuilder->ToReferenceFrame(this); nsRect bounds = this->EnsureInnerView()->GetBounds() + offset; clipState.ClipContentDescendants(bounds); @@ -1076,18 +1076,18 @@ nsSubDocumentFrame::FrameLoader() const nsCOMPtr<nsIFrameLoaderOwner> loaderOwner = do_QueryInterface(content); if (loaderOwner) { mFrameLoader = loaderOwner->GetFrameLoader(); } } return mFrameLoader; } -mozilla::layout::RenderFrameParent* -nsSubDocumentFrame::GetRenderFrameParent() const +mozilla::layout::RenderFrame* +nsSubDocumentFrame::GetRenderFrame() const { return FrameLoader() ? FrameLoader()->GetCurrentRenderFrame() : nullptr; } // XXX this should be called ObtainDocShell or something like that, // to indicate that it could have side effects nsIDocShell* nsSubDocumentFrame::GetDocShell()
--- a/layout/generic/nsSubDocumentFrame.h +++ b/layout/generic/nsSubDocumentFrame.h @@ -10,17 +10,17 @@ #include "mozilla/Attributes.h" #include "nsAtomicContainerFrame.h" #include "nsIReflowCallback.h" #include "nsFrameLoader.h" #include "Units.h" namespace mozilla { namespace layout { -class RenderFrameParent; +class RenderFrame; } } /****************************************************************************** * nsSubDocumentFrame *****************************************************************************/ class nsSubDocumentFrame final : public nsAtomicContainerFrame @@ -135,17 +135,17 @@ public: void MaybeShowViewer() { if (!mDidCreateDoc && !mCallingShow) { ShowViewer(); } } - mozilla::layout::RenderFrameParent* GetRenderFrameParent() const; + mozilla::layout::RenderFrame* GetRenderFrame() const; protected: friend class AsyncFrameInit; // Helper method to look up the HTML marginwidth & marginheight attributes. mozilla::CSSIntSize GetMarginAttributes(); nsFrameLoader* FrameLoader() const;
deleted file mode 100644 --- a/layout/ipc/PRenderFrame.ipdl +++ /dev/null @@ -1,37 +0,0 @@ -/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- - * vim: sw=2 ts=8 et : - */ -/* 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/. */ - -include protocol PBrowser; -include protocol PLayerTransaction; - - -using class nsRegion from "nsRegion.h"; - -namespace mozilla { -namespace layout { - -/** - * PRenderFrame (in the layout sense of "frame") represents one web - * "page". It's used to graft content processes' layer trees into - * chrome's rendering path. The lifetime of a PRenderFrame is tied to - * its PresShell in the child process. - * - * The child process conceptually "owns" a PRenderFrame, because it - * only makes sense wrt documents loaded by the child. - */ -sync protocol PRenderFrame -{ - manager PBrowser; - -parent: - async NotifyCompositorTransaction(); - - async __delete__(); -}; - -} // namespace layout -} // namespace mozilla
rename from layout/ipc/RenderFrameParent.cpp rename to layout/ipc/RenderFrame.cpp --- a/layout/ipc/RenderFrameParent.cpp +++ b/layout/ipc/RenderFrame.cpp @@ -1,85 +1,38 @@ /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* vim: set ts=8 sts=2 et sw=2 tw=80: */ /* 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/. */ #include "base/basictypes.h" -#include "BasicLayers.h" -#include "gfxPrefs.h" -#include "mozilla/BrowserElementParent.h" -#include "mozilla/EventForwards.h" // for Modifiers -#include "mozilla/ViewportFrame.h" -#include "mozilla/dom/ContentChild.h" #include "mozilla/dom/ContentParent.h" -#include "mozilla/dom/Element.h" -#include "mozilla/dom/TabChild.h" #include "mozilla/dom/TabParent.h" #include "mozilla/layers/CompositorBridgeParent.h" +#include "mozilla/layers/CompositorTypes.h" #include "mozilla/layers/LayerTransactionParent.h" -#include "nsContentUtils.h" -#include "nsFocusManager.h" #include "nsFrameLoader.h" -#include "nsIObserver.h" #include "nsStyleStructInlines.h" #include "nsSubDocumentFrame.h" -#include "nsView.h" -#include "RenderFrameParent.h" +#include "RenderFrame.h" #include "mozilla/gfx/GPUProcessManager.h" -#include "mozilla/layers/LayerManagerComposite.h" #include "mozilla/layers/CompositorBridgeChild.h" #include "mozilla/layers/WebRenderLayerManager.h" #include "mozilla/layers/WebRenderScrollData.h" #include "mozilla/webrender/WebRenderAPI.h" -#include "ClientLayerManager.h" -#include "FrameLayerBuilder.h" using namespace mozilla::dom; using namespace mozilla::gfx; using namespace mozilla::layers; namespace mozilla { namespace layout { -typedef ScrollableLayerGuid::ViewID ViewID; - -/** - * Gets the layer-pixel offset of aContainerFrame's content rect top-left - * from the nearest display item reference frame (which we assume will be inducing - * a ContainerLayer). - */ -static LayoutDeviceIntPoint -GetContentRectLayerOffset(nsIFrame* aContainerFrame, nsDisplayListBuilder* aBuilder) -{ - nscoord auPerDevPixel = aContainerFrame->PresContext()->AppUnitsPerDevPixel(); - - // Offset to the content rect in case we have borders or padding - // Note that aContainerFrame could be a reference frame itself, so - // we need to be careful here to ensure that we call ToReferenceFrame - // on aContainerFrame and not its parent. - nsPoint frameOffset = aBuilder->ToReferenceFrame(aContainerFrame) + - aContainerFrame->GetContentRectRelativeToSelf().TopLeft(); - - return LayoutDeviceIntPoint::FromAppUnitsToNearest(frameOffset, auPerDevPixel); -} - -// Return true iff |aManager| is a "temporary layer manager". They're -// used for small software rendering tasks, like drawWindow. That's -// currently implemented by a BasicLayerManager without a backing -// widget, and hence in non-retained mode. -inline static bool -IsTempLayerManager(LayerManager* aManager) -{ - return (mozilla::layers::LayersBackend::LAYERS_BASIC == aManager->GetBackendType() && - !static_cast<BasicLayerManager*>(aManager)->IsRetained()); -} - static already_AddRefed<LayerManager> GetLayerManager(nsFrameLoader* aFrameLoader) { if (nsIContent* content = aFrameLoader->GetOwnerContent()) { RefPtr<LayerManager> lm = nsContentUtils::LayerManagerForContent(content); if (lm) { return lm.forget(); } @@ -87,134 +40,87 @@ GetLayerManager(nsFrameLoader* aFrameLoa nsIDocument* doc = aFrameLoader->GetOwnerDoc(); if (!doc) { return nullptr; } return nsContentUtils::LayerManagerForDocument(doc); } -RenderFrameParent::RenderFrameParent(nsFrameLoader* aFrameLoader) +RenderFrame::RenderFrame() : mLayersId{0} + , mFrameLoader(nullptr) + , mLayerManager(nullptr) + , mInitialized(false) , mLayersConnected(false) - , mFrameLoader(aFrameLoader) - , mFrameLoaderDestroyed(false) - , mAsyncPanZoomEnabled(false) - , mInitted(false) { - mInitted = Init(aFrameLoader); } -RenderFrameParent::~RenderFrameParent() -{} +RenderFrame::~RenderFrame() +{ +} bool -RenderFrameParent::Init(nsFrameLoader* aFrameLoader) +RenderFrame::Initialize(nsFrameLoader* aFrameLoader) { - if (mInitted || !aFrameLoader) { + if (mInitialized || !aFrameLoader) { return false; } mFrameLoader = aFrameLoader; - RefPtr<LayerManager> lm = GetLayerManager(mFrameLoader); - - mAsyncPanZoomEnabled = lm && lm->AsyncPanZoomEnabled(); + PCompositorBridgeChild* compositor = lm + ? lm->GetCompositorBridgeChild() + : nullptr; - TabParent* browser = TabParent::GetFrom(mFrameLoader); - if (XRE_IsParentProcess()) { - PCompositorBridgeChild* compositor = nullptr; - if (lm) { - compositor = lm->GetCompositorBridgeChild(); - } + TabParent* browser = TabParent::GetFrom(aFrameLoader); + mTabProcessId = browser->Manager()->AsContentParent()->OtherPid(); - // Our remote frame will push layers updates to the compositor, - // and we'll keep an indirect reference to that tree. - GPUProcessManager* gpm = GPUProcessManager::Get(); - mLayersConnected = gpm->AllocateAndConnectLayerTreeId( - compositor, - browser->Manager()->AsContentParent()->OtherPid(), - &mLayersId, - &mCompositorOptions); - } else if (XRE_IsContentProcess()) { - ContentChild::GetSingleton()->SendAllocateLayerTreeId(browser->Manager()->ChildID(), browser->GetTabId(), &mLayersId); - mLayersConnected = CompositorBridgeChild::Get()->SendNotifyChildCreated(mLayersId, &mCompositorOptions); - } + // Our remote frame will push layers updates to the compositor, + // and we'll keep an indirect reference to that tree. + GPUProcessManager* gpm = GPUProcessManager::Get(); + mLayersConnected = gpm->AllocateAndConnectLayerTreeId( + compositor, + mTabProcessId, + &mLayersId, + &mCompositorOptions); - mInitted = true; + mInitialized = true; return true; } -bool -RenderFrameParent::IsInitted() +void +RenderFrame::Destroy() { - return mInitted; -} + if (mLayersId.IsValid()) { + GPUProcessManager::Get()->UnmapLayerTreeId(mLayersId, mTabProcessId); + } -void -RenderFrameParent::Destroy() -{ - mFrameLoaderDestroyed = true; + mFrameLoader = nullptr; mLayerManager = nullptr; } -already_AddRefed<Layer> -RenderFrameParent::BuildLayer(nsDisplayListBuilder* aBuilder, - nsIFrame* aFrame, - LayerManager* aManager, - nsDisplayItem* aItem, - const ContainerLayerParameters& aContainerParameters) +void +RenderFrame::EnsureLayersConnected(CompositorOptions* aCompositorOptions) { - MOZ_ASSERT(aFrame, - "makes no sense to have a shadow tree without a frame"); - - if (IsTempLayerManager(aManager)) { - // This can happen if aManager is a "temporary" manager, or if the - // widget's layer manager changed out from under us. We need to - // FIXME handle the former case somehow, probably with an API to - // draw a manager's subtree. The latter is bad bad bad, but the the - // MOZ_ASSERT() above will flag it. Returning nullptr here will just - // cause the shadow subtree not to be rendered. - if (!aContainerParameters.mForEventsAndPluginsOnly) { - NS_WARNING("Remote iframe not rendered"); - } - return nullptr; + RefPtr<LayerManager> lm = GetLayerManager(mFrameLoader); + if (!lm) { + return; } - if (!mLayersId.IsValid()) { - return nullptr; + if (!lm->GetCompositorBridgeChild()) { + return; } - RefPtr<Layer> layer = - (aManager->GetLayerBuilder()->GetLeafLayerFor(aBuilder, aItem)); - if (!layer) { - layer = aManager->CreateRefLayer(); - } - if (!layer) { - // Probably a temporary layer manager that doesn't know how to - // use ref layers. - return nullptr; - } - static_cast<RefLayer*>(layer.get())->SetReferentId(mLayersId); - LayoutDeviceIntPoint offset = GetContentRectLayerOffset(aFrame, aBuilder); - // We can only have an offset if we're a child of an inactive - // container, but our display item is LAYER_ACTIVE_FORCE which - // forces all layers above to be active. - MOZ_ASSERT(aContainerParameters.mOffset == nsIntPoint()); - gfx::Matrix4x4 m = gfx::Matrix4x4::Translation(offset.x, offset.y, 0.0); - // Remote content can't be repainted by us, so we multiply down - // the resolution that our container expects onto our container. - m.PreScale(aContainerParameters.mXScale, aContainerParameters.mYScale, 1.0); - layer->SetBaseTransform(m); - - return layer.forget(); + mLayersConnected = lm->GetCompositorBridgeChild()->SendNotifyChildRecreated(mLayersId, &mCompositorOptions); + *aCompositorOptions = mCompositorOptions; } LayerManager* -RenderFrameParent::AttachLayerManager() +RenderFrame::AttachLayerManager() { RefPtr<LayerManager> lm; if (mFrameLoader) { lm = GetLayerManager(mFrameLoader); } // Perhaps the document containing this frame currently has no presentation? if (lm && lm->GetCompositorBridgeChild() && lm != mLayerManager) { @@ -222,167 +128,169 @@ RenderFrameParent::AttachLayerManager() FrameLayerBuilder::InvalidateAllLayers(lm); } mLayerManager = lm.forget(); return mLayerManager; } void -RenderFrameParent::OwnerContentChanged(nsIContent* aContent) +RenderFrame::OwnerContentChanged(nsIContent* aContent) { MOZ_ASSERT(!mFrameLoader || mFrameLoader->GetOwnerContent() == aContent, "Don't build new map if owner is same!"); Unused << AttachLayerManager(); } void -RenderFrameParent::ActorDestroy(ActorDestroyReason why) -{ - if (mLayersId.IsValid()) { - if (XRE_IsParentProcess()) { - GPUProcessManager::Get()->UnmapLayerTreeId(mLayersId, OtherPid()); - } else if (XRE_IsContentProcess()) { - TabParent* browser = TabParent::GetFrom(mFrameLoader); - ContentChild::GetSingleton()->SendDeallocateLayerTreeId(browser->Manager()->ChildID(), mLayersId); - } - } - - mFrameLoader = nullptr; - mLayerManager = nullptr; -} - -mozilla::ipc::IPCResult -RenderFrameParent::RecvNotifyCompositorTransaction() -{ - TriggerRepaint(); - return IPC_OK(); -} - -void -RenderFrameParent::TriggerRepaint() -{ - nsIFrame* docFrame = mFrameLoader->GetPrimaryFrameOfOwningContent(); - if (!docFrame) { - // Bad, but nothing we can do about it (XXX/cjones: or is there? - // maybe bug 589337?). When the new frame is created, we'll - // probably still be the current render frame and will get to draw - // our content then. Or, we're shutting down and this update goes - // to /dev/null. - return; - } - - docFrame->InvalidateLayer(DisplayItemType::TYPE_REMOTE); -} - -void -RenderFrameParent::GetTextureFactoryIdentifier(TextureFactoryIdentifier* aTextureFactoryIdentifier) +RenderFrame::GetTextureFactoryIdentifier(TextureFactoryIdentifier* aTextureFactoryIdentifier) const { RefPtr<LayerManager> lm = mFrameLoader ? GetLayerManager(mFrameLoader) : nullptr; // Perhaps the document containing this frame currently has no presentation? if (lm) { *aTextureFactoryIdentifier = lm->GetTextureFactoryIdentifier(); } else { *aTextureFactoryIdentifier = TextureFactoryIdentifier(); } } -void -RenderFrameParent::TakeFocusForClickFromTap() +} // namespace layout +} // namespace mozilla + +/** + * Gets the layer-pixel offset of aContainerFrame's content rect top-left + * from the nearest display item reference frame (which we assume will be inducing + * a ContainerLayer). + */ +static mozilla::LayoutDeviceIntPoint +GetContentRectLayerOffset(nsIFrame* aContainerFrame, nsDisplayListBuilder* aBuilder) { - nsIFocusManager* fm = nsFocusManager::GetFocusManager(); - if (!fm) { - return; - } - RefPtr<Element> element = mFrameLoader->GetOwnerContent(); - if (!element) { - return; - } - fm->SetFocus(element, nsIFocusManager::FLAG_BYMOUSE | - nsIFocusManager::FLAG_BYTOUCH | - nsIFocusManager::FLAG_NOSCROLL); + nscoord auPerDevPixel = aContainerFrame->PresContext()->AppUnitsPerDevPixel(); + + // Offset to the content rect in case we have borders or padding + // Note that aContainerFrame could be a reference frame itself, so + // we need to be careful here to ensure that we call ToReferenceFrame + // on aContainerFrame and not its parent. + nsPoint frameOffset = aBuilder->ToReferenceFrame(aContainerFrame) + + aContainerFrame->GetContentRectRelativeToSelf().TopLeft(); + + return mozilla::LayoutDeviceIntPoint::FromAppUnitsToNearest(frameOffset, auPerDevPixel); } -void -RenderFrameParent::EnsureLayersConnected(CompositorOptions* aCompositorOptions) +// Return true iff |aManager| is a "temporary layer manager". They're +// used for small software rendering tasks, like drawWindow. That's +// currently implemented by a BasicLayerManager without a backing +// widget, and hence in non-retained mode. +inline static bool +IsTempLayerManager(mozilla::layers::LayerManager* aManager) { - RefPtr<LayerManager> lm = GetLayerManager(mFrameLoader); - if (!lm) { - return; - } - - if (!lm->GetCompositorBridgeChild()) { - return; - } - - mLayersConnected = lm->GetCompositorBridgeChild()->SendNotifyChildRecreated(mLayersId, &mCompositorOptions); - *aCompositorOptions = mCompositorOptions; + return (mozilla::layers::LayersBackend::LAYERS_BASIC == aManager->GetBackendType() && + !static_cast<BasicLayerManager*>(aManager)->IsRetained()); } -} // namespace layout -} // namespace mozilla - nsDisplayRemote::nsDisplayRemote(nsDisplayListBuilder* aBuilder, nsSubDocumentFrame* aFrame) : nsDisplayItem(aBuilder, aFrame) , mTabId{0} , mEventRegionsOverride(EventRegionsOverride::NoOverride) { bool frameIsPointerEventsNone = aFrame->StyleUI()->GetEffectivePointerEvents(aFrame) == NS_STYLE_POINTER_EVENTS_NONE; if (aBuilder->IsInsidePointerEventsNoneDoc() || frameIsPointerEventsNone) { mEventRegionsOverride |= EventRegionsOverride::ForceEmptyHitRegion; } if (nsLayoutUtils::HasDocumentLevelListenersForApzAwareEvents(aFrame->PresShell())) { mEventRegionsOverride |= EventRegionsOverride::ForceDispatchToContent; } - nsFrameLoader* frameLoader = GetRenderFrameParent()->FrameLoader(); + nsFrameLoader* frameLoader = GetRenderFrame()->GetFrameLoader(); if (frameLoader) { TabParent* browser = TabParent::GetFrom(frameLoader); if (browser) { mTabId = browser->GetTabId(); } } } mozilla::LayerState nsDisplayRemote::GetLayerState(nsDisplayListBuilder* aBuilder, LayerManager* aManager, const ContainerLayerParameters& aParameters) { - if (mozilla::layout::IsTempLayerManager(aManager)) { + if (IsTempLayerManager(aManager)) { return mozilla::LAYER_NONE; } return mozilla::LAYER_ACTIVE_FORCE; } bool nsDisplayRemote::HasDeletedFrame() const { - // RenderFrameParent might change without invalidating nsSubDocumentFrame. - return !GetRenderFrameParent() || nsDisplayItem::HasDeletedFrame(); + // RenderFrame might change without invalidating nsSubDocumentFrame. + return !GetRenderFrame() || nsDisplayItem::HasDeletedFrame(); } already_AddRefed<Layer> nsDisplayRemote::BuildLayer(nsDisplayListBuilder* aBuilder, LayerManager* aManager, const ContainerLayerParameters& aContainerParameters) { - MOZ_ASSERT(GetRenderFrameParent()); + MOZ_ASSERT(GetRenderFrame()); + MOZ_ASSERT(mFrame, "Makes no sense to have a shadow tree without a frame"); + + if (IsTempLayerManager(aManager)) { + // This can happen if aManager is a "temporary" manager, or if the + // widget's layer manager changed out from under us. We need to + // FIXME handle the former case somehow, probably with an API to + // draw a manager's subtree. The latter is bad bad bad, but the the + // MOZ_ASSERT() above will flag it. Returning nullptr here will just + // cause the shadow subtree not to be rendered. + if (!aContainerParameters.mForEventsAndPluginsOnly) { + NS_WARNING("Remote iframe not rendered"); + } + return nullptr; + } + + LayersId remoteId = GetRenderFrame()->GetLayersId(); + + if (!remoteId.IsValid()) { + return nullptr; + } RefPtr<Layer> layer = - GetRenderFrameParent()->BuildLayer(aBuilder, mFrame, aManager, - this, aContainerParameters); + aManager->GetLayerBuilder()->GetLeafLayerFor(aBuilder, this); + + if (!layer) { + layer = aManager->CreateRefLayer(); + } + + if (!layer) { + // Probably a temporary layer manager that doesn't know how to + // use ref layers. + return nullptr; + } - if (layer && layer->AsRefLayer()) { + static_cast<RefLayer*>(layer.get())->SetReferentId(remoteId); + LayoutDeviceIntPoint offset = GetContentRectLayerOffset(Frame(), aBuilder); + // We can only have an offset if we're a child of an inactive + // container, but our display item is LAYER_ACTIVE_FORCE which + // forces all layers above to be active. + MOZ_ASSERT(aContainerParameters.mOffset == nsIntPoint()); + Matrix4x4 m = Matrix4x4::Translation(offset.x, offset.y, 0.0); + // Remote content can't be repainted by us, so we multiply down + // the resolution that our container expects onto our container. + m.PreScale(aContainerParameters.mXScale, aContainerParameters.mYScale, 1.0); + layer->SetBaseTransform(m); + + if (layer->AsRefLayer()) { layer->AsRefLayer()->SetEventRegionsOverride(mEventRegionsOverride); } + return layer.forget(); } void nsDisplayRemote::Paint(nsDisplayListBuilder* aBuilder, gfxContext* aCtx) { DrawTarget* target = aCtx->GetDrawTarget(); if (!target->IsRecording() || mTabId == 0) { @@ -398,19 +306,19 @@ nsDisplayRemote::Paint(nsDisplayListBuil bool nsDisplayRemote::CreateWebRenderCommands(mozilla::wr::DisplayListBuilder& aBuilder, mozilla::wr::IpcResourceUpdateQueue& aResources, const StackingContextHelper& aSc, mozilla::layers::WebRenderLayerManager* aManager, nsDisplayListBuilder* aDisplayListBuilder) { - mOffset = mozilla::layout::GetContentRectLayerOffset(mFrame, aDisplayListBuilder); + mOffset = GetContentRectLayerOffset(mFrame, aDisplayListBuilder); - mozilla::LayoutDeviceRect rect = mozilla::LayoutDeviceRect::FromAppUnits( + LayoutDeviceRect rect = LayoutDeviceRect::FromAppUnits( mFrame->GetContentRectRelativeToSelf(), mFrame->PresContext()->AppUnitsPerDevPixel()); rect += mOffset; aBuilder.PushIFrame(mozilla::wr::ToRoundedLayoutRect(rect), !BackfaceIsHidden(), mozilla::wr::AsPipelineId(GetRemoteLayersId()), /*ignoreMissingPipelines*/ true); @@ -427,19 +335,19 @@ nsDisplayRemote::UpdateScrollData(mozill aLayerData->SetEventRegionsOverride(mEventRegionsOverride); } return true; } LayersId nsDisplayRemote::GetRemoteLayersId() const { - MOZ_ASSERT(GetRenderFrameParent()); - return GetRenderFrameParent()->GetLayersId(); + MOZ_ASSERT(GetRenderFrame()); + return GetRenderFrame()->GetLayersId(); } -mozilla::layout::RenderFrameParent* -nsDisplayRemote::GetRenderFrameParent() const +mozilla::layout::RenderFrame* +nsDisplayRemote::GetRenderFrame() const { return mFrame - ? static_cast<nsSubDocumentFrame*>(mFrame)->GetRenderFrameParent() + ? static_cast<nsSubDocumentFrame*>(mFrame)->GetRenderFrame() : nullptr; }
rename from layout/ipc/RenderFrameParent.h rename to layout/ipc/RenderFrame.h --- a/layout/ipc/RenderFrameParent.h +++ b/layout/ipc/RenderFrame.h @@ -1,159 +1,105 @@ /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* vim: set ts=8 sts=2 et sw=2 tw=80: */ /* 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/. */ -#ifndef mozilla_layout_RenderFrameParent_h -#define mozilla_layout_RenderFrameParent_h +#ifndef mozilla_layout_RenderFrame_h +#define mozilla_layout_RenderFrame_h + +#include "base/process.h" #include "mozilla/Attributes.h" -#include <map> #include "mozilla/dom/ipc/IdType.h" -#include "mozilla/layers/APZUtils.h" #include "mozilla/layers/CompositorOptions.h" #include "mozilla/layers/LayersTypes.h" -#include "mozilla/layout/PRenderFrameParent.h" #include "nsDisplayList.h" class nsFrameLoader; class nsSubDocumentFrame; namespace mozilla { -class InputEvent; namespace layers { -class AsyncDragMetrics; -class TargetConfig; struct TextureFactoryIdentifier; -struct ScrollableLayerGuid; } // namespace layers namespace layout { -class RenderFrameParent final : public PRenderFrameParent +class RenderFrame final { - typedef mozilla::layers::AsyncDragMetrics AsyncDragMetrics; - typedef mozilla::layers::FrameMetrics FrameMetrics; typedef mozilla::layers::CompositorOptions CompositorOptions; - typedef mozilla::layers::ContainerLayer ContainerLayer; - typedef mozilla::layers::Layer Layer; typedef mozilla::layers::LayerManager LayerManager; typedef mozilla::layers::LayersId LayersId; - typedef mozilla::layers::TargetConfig TargetConfig; - typedef mozilla::ContainerLayerParameters ContainerLayerParameters; typedef mozilla::layers::TextureFactoryIdentifier TextureFactoryIdentifier; - typedef mozilla::layers::ScrollableLayerGuid ScrollableLayerGuid; - typedef mozilla::layers::TouchBehaviorFlags TouchBehaviorFlags; - typedef mozilla::layers::ZoomConstraints ZoomConstraints; - typedef ScrollableLayerGuid::ViewID ViewID; - public: + RenderFrame(); + virtual ~RenderFrame(); - /** - * Select the desired scrolling behavior. If ASYNC_PAN_ZOOM is - * chosen, then RenderFrameParent will watch input events and use - * them to asynchronously pan and zoom. - */ - explicit RenderFrameParent(nsFrameLoader* aFrameLoader); - virtual ~RenderFrameParent(); - - bool Init(nsFrameLoader* aFrameLoader); - bool IsInitted(); + bool Initialize(nsFrameLoader* aFrameLoader); void Destroy(); - - already_AddRefed<Layer> BuildLayer(nsDisplayListBuilder* aBuilder, - nsIFrame* aFrame, - LayerManager* aManager, - nsDisplayItem* aItem, - const ContainerLayerParameters& aContainerParameters); - + void EnsureLayersConnected(CompositorOptions* aCompositorOptions); + LayerManager* AttachLayerManager(); void OwnerContentChanged(nsIContent* aContent); - bool HitTest(const nsRect& aRect); - - void GetTextureFactoryIdentifier(TextureFactoryIdentifier* aTextureFactoryIdentifier); - - inline LayersId GetLayersId() const { return mLayersId; } - inline bool IsLayersConnected() const { return mLayersConnected; } - inline CompositorOptions GetCompositorOptions() const { return mCompositorOptions; } - - void TakeFocusForClickFromTap(); - - void EnsureLayersConnected(CompositorOptions* aCompositorOptions); + nsFrameLoader* GetFrameLoader() const { return mFrameLoader; } + LayersId GetLayersId() const { return mLayersId; } + CompositorOptions GetCompositorOptions() const { return mCompositorOptions; } - LayerManager* AttachLayerManager(); + void GetTextureFactoryIdentifier(TextureFactoryIdentifier* aTextureFactoryIdentifier) const; - nsFrameLoader* FrameLoader() const - { - return mFrameLoader; - } - -protected: - void ActorDestroy(ActorDestroyReason why) override; - - virtual mozilla::ipc::IPCResult RecvNotifyCompositorTransaction() override; + bool IsInitialized() const { return mInitialized; } + bool IsLayersConnected() const { return mLayersConnected; } private: - void TriggerRepaint(); - void DispatchEventForPanZoomController(const InputEvent& aEvent); - + base::ProcessId mTabProcessId; // When our child frame is pushing transactions directly to the // compositor, this is the ID of its layer tree in the compositor's // context. LayersId mLayersId; - // A flag that indicates whether or not the compositor knows about the - // layers id. In some cases this RenderFrameParent is not connected to the - // compositor and so this flag is false. - bool mLayersConnected; // The compositor options for this layers id. This is only meaningful if // the compositor actually knows about this layers id (i.e. when mLayersConnected // is true). CompositorOptions mCompositorOptions; RefPtr<nsFrameLoader> mFrameLoader; RefPtr<LayerManager> mLayerManager; - // True after Destroy() has been called, which is triggered - // originally by nsFrameLoader::Destroy(). After this point, we can - // no longer safely ask the frame loader to find its nearest layer - // manager, because it may have been disconnected from the DOM. - // It's still OK to *tell* the frame loader that we've painted after - // it's destroyed; it'll just ignore us, and we won't be able to - // find an nsIFrame to invalidate. See ShadowLayersUpdated(). - // - // Prefer the extra bit of state to null'ing out mFrameLoader in - // Destroy() so that less code needs to be special-cased for after - // Destroy(). - // - // It's possible for mFrameLoader==null and - // mFrameLoaderDestroyed==false. - bool mFrameLoaderDestroyed; - - bool mAsyncPanZoomEnabled; - bool mInitted; + bool mInitialized; + // A flag that indicates whether or not the compositor knows about the + // layers id. In some cases this RenderFrame is not connected to the + // compositor and so this flag is false. + bool mLayersConnected; }; } // namespace layout } // namespace mozilla /** * A DisplayRemote exists solely to graft a child process's shadow - * layer tree (for a given RenderFrameParent) into its parent + * layer tree (for a given RenderFrame) into its parent * process's layer tree. */ class nsDisplayRemote final : public nsDisplayItem { - typedef mozilla::layout::RenderFrameParent RenderFrameParent; + typedef mozilla::dom::TabId TabId; + typedef mozilla::gfx::Matrix4x4 Matrix4x4; + typedef mozilla::layers::EventRegionsOverride EventRegionsOverride; + typedef mozilla::layers::Layer Layer; + typedef mozilla::layers::LayersId LayersId; + typedef mozilla::layers::RefLayer RefLayer; + typedef mozilla::layout::RenderFrame RenderFrame; + typedef mozilla::LayoutDeviceRect LayoutDeviceRect; + typedef mozilla::LayoutDeviceIntPoint LayoutDeviceIntPoint; public: nsDisplayRemote(nsDisplayListBuilder* aBuilder, nsSubDocumentFrame* aFrame); bool HasDeletedFrame() const override; LayerState GetLayerState(nsDisplayListBuilder* aBuilder, @@ -172,18 +118,17 @@ public: mozilla::layers::WebRenderLayerManager* aManager, nsDisplayListBuilder* aDisplayListBuilder) override; bool UpdateScrollData(mozilla::layers::WebRenderScrollData* aData, mozilla::layers::WebRenderLayerScrollData* aLayerData) override; NS_DISPLAY_DECL_NAME("Remote", TYPE_REMOTE) private: - mozilla::layers::LayersId GetRemoteLayersId() const; - RenderFrameParent* GetRenderFrameParent() const; + LayersId GetRemoteLayersId() const; + RenderFrame* GetRenderFrame() const; - mozilla::dom::TabId mTabId; - mozilla::LayoutDeviceIntPoint mOffset; - mozilla::layers::EventRegionsOverride mEventRegionsOverride; + TabId mTabId; + LayoutDeviceIntPoint mOffset; + EventRegionsOverride mEventRegionsOverride; }; - -#endif // mozilla_layout_RenderFrameParent_h +#endif // mozilla_layout_RenderFrame_h
deleted file mode 100644 --- a/layout/ipc/RenderFrameChild.cpp +++ /dev/null @@ -1,34 +0,0 @@ -/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* vim: set ts=8 sts=2 et sw=2 tw=80: */ -/* 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/. */ - -#include "RenderFrameChild.h" -#include "mozilla/layers/LayerTransactionChild.h" - -using mozilla::layers::PLayerTransactionChild; -using mozilla::layers::LayerTransactionChild; - -namespace mozilla { -namespace layout { - -void -RenderFrameChild::ActorDestroy(ActorDestroyReason why) -{ - mWasDestroyed = true; -} - -void -RenderFrameChild::Destroy() -{ - if (mWasDestroyed) { - return; - } - - Send__delete__(this); - // WARNING: |this| is dead, hands off -} - -} // namespace layout -} // namespace mozilla
deleted file mode 100644 --- a/layout/ipc/RenderFrameChild.h +++ /dev/null @@ -1,32 +0,0 @@ -/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* vim: set ts=8 sts=2 et sw=2 tw=80: */ -/* 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/. */ - -#ifndef mozilla_dom_RenderFrameChild_h -#define mozilla_dom_RenderFrameChild_h - -#include "mozilla/layout/PRenderFrameChild.h" - -namespace mozilla { -namespace layout { - -class RenderFrameChild : public PRenderFrameChild -{ -public: - RenderFrameChild() : mWasDestroyed(false) {} - virtual ~RenderFrameChild() {} - - void ActorDestroy(ActorDestroyReason why) override; - - void Destroy(); - -private: - bool mWasDestroyed; -}; - -} // namespace layout -} // namespace mozilla - -#endif // mozilla_dom_RenderFrameChild_h
--- a/layout/ipc/moz.build +++ b/layout/ipc/moz.build @@ -3,34 +3,31 @@ # 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/. with Files('**'): BUG_COMPONENT = ('Core', 'Web Painting') EXPORTS.mozilla.layout += [ - 'RenderFrameChild.h', - 'RenderFrameParent.h', + 'RenderFrame.h', 'VsyncChild.h', 'VsyncParent.h', ] UNIFIED_SOURCES += [ - 'RenderFrameChild.cpp', - 'RenderFrameParent.cpp', + 'RenderFrame.cpp', ] SOURCES += [ 'VsyncChild.cpp', 'VsyncParent.cpp', ] IPDL_SOURCES = [ - 'PRenderFrame.ipdl', 'PVsync.ipdl', ] include('/ipc/chromium/chromium-config.mozbuild') FINAL_LIBRARY = 'xul' LOCAL_INCLUDES += [
--- a/modules/libpref/init/StaticPrefList.h +++ b/modules/libpref/init/StaticPrefList.h @@ -434,16 +434,23 @@ VARCACHE_PREF( // Enable content type normalization of XHR uploads via MIME Sniffing standard // Disabled for now in bz1499136 VARCACHE_PREF( "dom.xhr.standard_content_type_normalization", dom_xhr_standard_content_type_normalization, RelaxedAtomicBool, false ) +// Block multiple window.open() per single event. +VARCACHE_PREF( + "dom.block_multiple_popups", + dom_block_multiple_popups, + bool, true +) + //--------------------------------------------------------------------------- // Clear-Site-Data prefs //--------------------------------------------------------------------------- VARCACHE_PREF( "dom.clearSiteData.enabled", dom_clearSiteData_enabled, bool, true
old mode 100644 new mode 100755 --- a/mozilla-config.h.in +++ b/mozilla-config.h.in @@ -40,11 +40,26 @@ /* * Force-include sdkdecls.h for building the chromium sandbox code. * * CHROMIUM_SANDBOX_BUILD is defined in security/sandbox/moz.build. * Note that this include path relies on the LOCAL_INCLUDES in that file. */ #if defined(CHROMIUM_SANDBOX_BUILD) && defined(XP_WIN) #include "base/win/sdkdecls.h" + +#ifdef __MINGW32__ +/* + * MinGW doesn't support __try / __except. There are a few mechanisms available + * to hack around it and pseudo-support it, but these are untested in Firefox. + * What is tested (and works) is replacing them with if(true) and else. + */ +#define __try if(true) +#define __except(x) else +#ifdef GetExceptionCode +#undef GetExceptionCode +#endif +#define GetExceptionCode() 0 + +#endif /* __MINGW32__ */ #endif /* defined(CHROMIUM_SANDBOX_BUILD) && defined(XP_WIN) */ #endif /* MOZILLA_CONFIG_H */
new file mode 100644 --- /dev/null +++ b/security/sandbox/chromium-shim/patches/with_update/mingw_disable_one_try.patch @@ -0,0 +1,51 @@ +# HG changeset patch +# User Tom Ritter <tom@mozilla.com> +# Date 1516389982 21600 +# Fri Jan 19 13:26:22 2018 -0600 +# Node ID 3ca7306d73ebc1ce47ccdc62ee8cbb69a9bfbb2c +# Parent 6aa6c7d894609140ccde2e9e50eba8c25a9caeb5 +Bug 1431803 Disable a specific __try block on MinGW r?bobowen + +This function is a technique to name a thread for debugging purposes, +and it always throws an exception (and then continues). On MinGW +we don't want it to throw an exception, so we do nothing. + +This means on MinGW we won't get nice thread naming during debugging, +but we'll limp along. + +MozReview-Commit-ID: JRKY4wp7sdu + +diff --git a/security/sandbox/chromium/base/threading/platform_thread_win.cc b/security/sandbox/chromium/base/threading/platform_thread_win.cc +--- a/security/sandbox/chromium/base/threading/platform_thread_win.cc ++++ b/security/sandbox/chromium/base/threading/platform_thread_win.cc +@@ -32,27 +32,30 @@ typedef struct tagTHREADNAME_INFO { + } THREADNAME_INFO; + + // The SetThreadDescription API was brought in version 1607 of Windows 10. + typedef HRESULT(WINAPI* SetThreadDescription)(HANDLE hThread, + PCWSTR lpThreadDescription); + + // This function has try handling, so it is separated out of its caller. + void SetNameInternal(PlatformThreadId thread_id, const char* name) { ++ //This function is only used for debugging purposes, as you can find by its caller ++#ifndef __MINGW32__ + THREADNAME_INFO info; + info.dwType = 0x1000; + info.szName = name; + info.dwThreadID = thread_id; + info.dwFlags = 0; + + __try { + RaiseException(kVCThreadNameException, 0, sizeof(info)/sizeof(DWORD), + reinterpret_cast<DWORD_PTR*>(&info)); + } __except(EXCEPTION_CONTINUE_EXECUTION) { + } ++#endif + } + + struct ThreadParams { + PlatformThread::Delegate* delegate; + bool joinable; + ThreadPriority priority; + }; +
--- a/security/sandbox/chromium-shim/patches/with_update/patch_order.txt +++ b/security/sandbox/chromium-shim/patches/with_update/patch_order.txt @@ -12,9 +12,10 @@ fix_Wcomma_warning_in_time_cc.patch allow_read_only_all_paths_rule.patch revert_TargetNtSetInformationThread_change.patch mingw_base_win_get_caller.patch mingw_duplicate_instatinations.patch mingw_copy_s.patch mingw_operator_new.patch mingw_cast_getprocaddress.patch mingw_capitalization.patch +mingw_disable_one_try.patch mingw_offsetof.patch
--- a/security/sandbox/chromium/base/threading/platform_thread_win.cc +++ b/security/sandbox/chromium/base/threading/platform_thread_win.cc @@ -32,27 +32,30 @@ typedef struct tagTHREADNAME_INFO { } THREADNAME_INFO; // The SetThreadDescription API was brought in version 1607 of Windows 10. typedef HRESULT(WINAPI* SetThreadDescription)(HANDLE hThread, PCWSTR lpThreadDescription); // This function has try handling, so it is separated out of its caller. void SetNameInternal(PlatformThreadId thread_id, const char* name) { + //This function is only used for debugging purposes, as you can find by its caller +#ifndef __MINGW32__ THREADNAME_INFO info; info.dwType = 0x1000; info.szName = name; info.dwThreadID = thread_id; info.dwFlags = 0; __try { RaiseException(kVCThreadNameException, 0, sizeof(info)/sizeof(DWORD), reinterpret_cast<DWORD_PTR*>(&info)); } __except(EXCEPTION_CONTINUE_EXECUTION) { } +#endif } struct ThreadParams { PlatformThread::Delegate* delegate; bool joinable; ThreadPriority priority; };
--- a/testing/mozbase/mozrunner/mozrunner/base/device.py +++ b/testing/mozbase/mozrunner/mozrunner/base/device.py @@ -50,52 +50,45 @@ class DeviceRunner(BaseRunner): kwargs['process_args'] = process_args BaseRunner.__init__(self, **kwargs) device_args = device_args or {} self.device = device_class(**device_args) @property def command(self): - cmd = [self.app_ctx.adb] - if self.app_ctx.device_serial: - cmd.extend(['-s', self.app_ctx.device_serial]) - cmd.append('shell') - for k, v in self._device_env.iteritems(): - cmd.append('%s=%s' % (k, v)) - cmd.append(self.app_ctx.remote_binary) - return cmd + # command built by mozdevice -- see start() below + return None def start(self, *args, **kwargs): if isinstance(self.device, BaseEmulator) and not self.device.connected: self.device.start() self.device.connect() self.device.setup_profile(self.profile) - # TODO: this doesn't work well when the device is running but dropped - # wifi for some reason. It would be good to probe the state of the device - # to see if we have the homescreen running, or something, before waiting here - self.device.wait_for_net() - - if not self.device.wait_for_net(): - raise Exception("Network did not come up when starting device") - - pid = BaseRunner.start(self, *args, **kwargs) + app = self.app_ctx.remote_process + args = ["-no-remote", "-profile", self.app_ctx.remote_profile] + args.extend(self.cmdargs) + env = self._device_env + url = None + if 'geckoview' in app: + activity = "TestRunnerActivity" + self.app_ctx.device.launch_activity(app, activity, e10s=True, moz_env=env, + extra_args=args, url=url) + else: + self.app_ctx.device.launch_fennec( + app, moz_env=env, extra_args=args, url=url) timeout = 10 # seconds end_time = datetime.datetime.now() + datetime.timedelta(seconds=timeout) while not self.is_running() and datetime.datetime.now() < end_time: time.sleep(.1) if not self.is_running(): print("timed out waiting for '%s' process to start" % self.app_ctx.remote_process) - if not self.device.wait_for_net(): - raise Exception("Failed to get a network connection") - return pid - def stop(self, sig=None): if not sig and self.is_running(): self.app_ctx.stop_application() if self.is_running(): timeout = 10 self.app_ctx.device.pkill(self.app_ctx.remote_process, sig=sig) @@ -179,25 +172,8 @@ class DeviceRunner(BaseRunner): self.device.cleanup() class FennecRunner(DeviceRunner): def __init__(self, cmdargs=None, **kwargs): super(FennecRunner, self).__init__(**kwargs) self.cmdargs = cmdargs or [] - - @property - def command(self): - cmd = [self.app_ctx.adb] - if self.app_ctx.device_serial: - cmd.extend(["-s", self.app_ctx.device_serial]) - cmd.append("shell") - app = "%s/org.mozilla.gecko.BrowserApp" % self.app_ctx.remote_process - am_subcommand = ["am", "start", "-a", "android.activity.MAIN", "-n", app] - app_params = ["-no-remote", "-profile", self.app_ctx.remote_profile] - app_params.extend(self.cmdargs) - am_subcommand.extend(["--es", "args", "'%s'" % " ".join(app_params)]) - # Append env variables in the form |--es env0 MOZ_CRASHREPORTER=1| - for (count, (k, v)) in enumerate(self._device_env.iteritems()): - am_subcommand.extend(["--es", "env%d" % count, "%s=%s" % (k, v)]) - cmd.append("%s" % " ".join(am_subcommand)) - return cmd
--- a/testing/profiles/unittest/user.js +++ b/testing/profiles/unittest/user.js @@ -102,16 +102,17 @@ user_pref("dom.forms.datetime.others", t // Enable Gamepad user_pref("dom.gamepad.enabled", true); user_pref("dom.gamepad.non_standard_events.enabled", true); user_pref("dom.ipc.reportProcessHangs", false); // process hang monitor // Don't forceably kill content processes after a timeout user_pref("dom.ipc.tabs.shutdownTimeoutSecs", 0); user_pref("dom.min_background_timeout_value", 1000); user_pref("dom.popup_maximum", -1); +user_pref("dom.block_multiple_popups", false); user_pref("dom.presentation.testing.simulate-receiver", false); // Prevent connection to the push server for tests. user_pref("dom.push.connection.enabled", false); user_pref("dom.successive_dialog_time_limit", 0); // In the default configuration, we bypass XBL scopes (a security feature) for // domains whitelisted for remote XUL, so that intranet apps and such continue // to work without major rewrites. However, we also use the whitelist mechanism // to run our XBL tests in automation, in which case we really want to be testing
--- a/testing/web-platform/meta/2dcontext/imagebitmap/createImageBitmap-origin.sub.html.ini +++ b/testing/web-platform/meta/2dcontext/imagebitmap/createImageBitmap-origin.sub.html.ini @@ -1,23 +1,4 @@ [createImageBitmap-origin.sub.html] prefs: [network.http.send_window_size:0] - [cross-origin HTMLImageElement] - expected: FAIL - - [cross-origin SVGImageElement] - expected: FAIL - - [cross-origin HTMLVideoElement] - expected: FAIL - - [unclean HTMLCanvasElement] - expected: FAIL - - [unclean ImageBitmap] - expected: FAIL - - [redirected to cross-origin HTMLVideoElement] - expected: FAIL - [redirected to same-origin HTMLVideoElement] expected: FAIL -
--- a/testing/web-platform/tests/tools/wptrunner/wptrunner/browsers/fennec.py +++ b/testing/web-platform/tests/tools/wptrunner/wptrunner/browsers/fennec.py @@ -208,29 +208,29 @@ class FennecBrowser(FirefoxBrowser): env=env, symbols_path=self.symbols_path, serial=self.device_serial, # TODO - choose appropriate log dir logdir=os.getcwd(), process_class=ProcessHandler, process_args={"processOutputLine": [self.on_output]}) - self.logger.debug("Starting Fennec") + self.logger.debug("Starting %s" % self.package_name) # connect to a running emulator self.runner.device.connect() write_hosts_file(self.config, self.runner.device.device) self.runner.start(debug_args=debug_args, interactive=self.debug_info and self.debug_info.interactive) self.runner.device.device.forward( local="tcp:{}".format(self.marionette_port), remote="tcp:{}".format(self.marionette_port)) - self.logger.debug("Fennec Started") + self.logger.debug("%s Started" % self.package_name) def stop(self, force=False): if self.runner is not None: try: if self.runner.device.connected: if len(self.runner.device.device.list_forwards()) > 0: self.runner.device.device.remove_forwards( "tcp:{}".format(self.marionette_port))
--- a/testing/xpcshell/runxpcshelltests.py +++ b/testing/xpcshell/runxpcshelltests.py @@ -222,17 +222,19 @@ class XPCShellTestThread(Thread): with open(test_file + ".log", "w") as f: f.write(stdout) def getReturnCode(self, proc): """ Simple wrapper to get the return code for a given process. On a remote system we overload this to work with the remote process management. """ - return proc.returncode + if proc is not None and hasattr(proc, "returncode"): + return proc.returncode + return -1 def communicate(self, proc): """ Simple wrapper to communicate with a process. On a remote system, this is overloaded to handle remote process communication. """ # Processing of incremental output put here to # sidestep issues on remote platforms, where what we know @@ -279,17 +281,20 @@ class XPCShellTestThread(Thread): self.log.info("%s | current directory: %r" % (name, testdir)) # Show only those environment variables that are changed from # the ambient environment. changedEnv = (set("%s=%s" % i for i in self.env.iteritems()) - set("%s=%s" % i for i in os.environ.iteritems())) self.log.info("%s | environment: %s" % (name, list(changedEnv))) def killTimeout(self, proc): - mozcrash.kill_and_get_minidump(proc.pid, self.tempDir, utility_path=self.utility_path) + if proc is not None and hasattr(proc, "pid"): + mozcrash.kill_and_get_minidump(proc.pid, self.tempDir, utility_path=self.utility_path) + else: + self.log.info("not killing -- proc or pid unknown") def postCheck(self, proc): """Checks for a still-running test process, kills it and fails the test if found. We can sometimes get here before the process has terminated, which would cause removeDir() to fail - so check for the process and kill it if needed. """ if proc and self.poll(proc) is None: if HAVE_PSUTIL:
--- a/toolkit/recordreplay/Lock.cpp +++ b/toolkit/recordreplay/Lock.cpp @@ -142,17 +142,17 @@ Lock::Find(void* aNativeLock) Lock* lock = iter->second; if (AreThreadEventsPassedThrough()) { return nullptr; } if (HasDivergedFromRecording()) { // When diverged from the recording, don't allow uses of locks that are // held by idling threads that have not diverged from the recording. // This will cause the process to deadlock, so rewind instead. - if (lock->mOwner && Thread::GetById(lock->mOwner)->IsIdle()) { + if (lock->mOwner && Thread::GetById(lock->mOwner)->ShouldIdle()) { ex.reset(); EnsureNotDivergedFromRecording(); Unreachable(); } return nullptr; } return lock; }
--- a/toolkit/recordreplay/Thread.h +++ b/toolkit/recordreplay/Thread.h @@ -297,19 +297,19 @@ public: // After WaitForIdleThreads(), the main thread will call this to allow // other threads to resume execution. static void ResumeIdleThreads(); // Allow a single thread to resume execution. static void ResumeSingleIdleThread(size_t aId); - // Return whether this thread is in the idle state entered after + // Return whether this thread will remain in the idle state entered after // WaitForIdleThreads. - bool IsIdle() { return mIdle; } + bool ShouldIdle() { return mShouldIdle; } }; // This uses a stack pointer instead of TLS to make sure events are passed // through, for avoiding thorny reentrance issues. class AutoEnsurePassThroughThreadEventsUseStackPointer { Thread* mThread; bool mPassedThrough;
--- a/toolkit/recordreplay/ipc/Channel.cpp +++ b/toolkit/recordreplay/ipc/Channel.cpp @@ -146,16 +146,17 @@ Channel::ThreadMain(void* aChannelArg) channel->mHandler(msg); } } void Channel::SendMessage(const Message& aMsg) { MOZ_RELEASE_ASSERT(NS_IsMainThread() || + aMsg.mType == MessageType::BeginFatalError || aMsg.mType == MessageType::FatalError || aMsg.mType == MessageType::MiddlemanCallRequest); // Block until the channel is initialized. if (!mInitialized) { MonitorAutoLock lock(mMonitor); while (!mInitialized) { mMonitor.Wait();
--- a/toolkit/recordreplay/ipc/Channel.h +++ b/toolkit/recordreplay/ipc/Channel.h @@ -104,18 +104,23 @@ namespace recordreplay { /* Messages sent from the child process to the middleman. */ \ \ /* Sent in response to a FlushRecording, telling the middleman that the flush */ \ /* has finished. */ \ _Macro(RecordingFlushed) \ \ /* A critical error occurred and execution cannot continue. The child will */ \ /* stop executing after sending this message and will wait to be terminated. */ \ + /* A minidump for the child has been generated. */ \ _Macro(FatalError) \ \ + /* Sent when a fatal error has occurred, but before the minidump has been */ \ + /* generated. */ \ + _Macro(BeginFatalError) \ + \ /* The child's graphics were repainted. */ \ _Macro(Paint) \ \ /* Notify the middleman that a checkpoint or breakpoint was hit. */ \ /* The child will pause after sending these messages. */ \ _Macro(HitCheckpoint) \ _Macro(HitBreakpoint) \ \ @@ -366,16 +371,18 @@ struct FatalErrorMessage : public Messag { explicit FatalErrorMessage(uint32_t aSize) : Message(MessageType::FatalError, aSize) {} const char* Error() const { return Data<FatalErrorMessage, const char>(); } }; +typedef EmptyMessage<MessageType::BeginFatalError> BeginFatalErrorMessage; + // The format for graphics data which will be sent to the middleman process. // This needs to match the format expected for canvas image data, to avoid // transforming the data before rendering it in the middleman process. static const gfx::SurfaceFormat gSurfaceFormat = gfx::SurfaceFormat::R8G8B8X8; struct PaintMessage : public Message { // Checkpoint whose state is being painted.
--- a/toolkit/recordreplay/ipc/ChildIPC.cpp +++ b/toolkit/recordreplay/ipc/ChildIPC.cpp @@ -103,18 +103,19 @@ ChannelMessageHandler(Message* aMsg) // processes. When sent to a recording process (which the middleman manages // directly) they signal that a clean shutdown is needed, while when sent // to a replaying process (which the UI process manages) they signal that // the process should crash, since it seems to be hanged. if (IsRecording()) { PrintSpew("Terminate message received, exiting...\n"); _exit(0); } else { - MOZ_CRASH("Hanged replaying process"); + ReportFatalError(Nothing(), "Hung replaying process"); } + break; } case MessageType::SetIsActive: { const SetIsActiveMessage& nmsg = (const SetIsActiveMessage&) *aMsg; PauseMainThreadAndInvokeCallback([=]() { SetIsActiveChild(nmsg.mActive); }); break; } case MessageType::SetAllowIntentionalCrashes: { const SetAllowIntentionalCrashesMessage& nmsg = (const SetAllowIntentionalCrashesMessage&) *aMsg; @@ -345,16 +346,20 @@ CreateCheckpoint() if (!HasDivergedFromRecording()) { NewCheckpoint(/* aTemporary = */ false); } } void ReportFatalError(const Maybe<MinidumpInfo>& aMinidump, const char* aFormat, ...) { + // Notify the middleman that we are crashing and are going to try to write a + // minidump. + gChannel->SendMessage(BeginFatalErrorMessage()); + // Unprotect any memory which might be written while producing the minidump. UnrecoverableSnapshotFailure(); AutoEnsurePassThroughThreadEvents pt; #ifdef MOZ_CRASHREPORTER MinidumpInfo info = aMinidump.isSome() ? aMinidump.ref()
--- a/toolkit/recordreplay/ipc/ChildProcess.cpp +++ b/toolkit/recordreplay/ipc/ChildProcess.cpp @@ -35,16 +35,18 @@ ChildProcessInfo::ChildProcessInfo(Uniqu , mRecording(aRecordingProcessData.isSome()) , mRecoveryStage(RecoveryStage::None) , mPaused(false) , mPausedMessage(nullptr) , mLastCheckpoint(CheckpointId::Invalid) , mNumRecoveredMessages(0) , mRole(std::move(aRole)) , mPauseNeeded(false) + , mHasBegunFatalError(false) + , mHasFatalError(false) { MOZ_RELEASE_ASSERT(NS_IsMainThread()); static bool gFirst = false; if (!gFirst) { gFirst = true; gChildrenAreDebugging = !!getenv("WAIT_AT_START"); } @@ -194,17 +196,21 @@ ChildProcessInfo::OnIncomingMessage(size MOZ_RELEASE_ASSERT(NS_IsMainThread()); // Ignore messages from channels for subprocesses we terminated already. if (aChannelId != mChannel->GetId()) { return; } // Always handle fatal errors in the same way. - if (aMsg.mType == MessageType::FatalError) { + if (aMsg.mType == MessageType::BeginFatalError) { + mHasBegunFatalError = true; + return; + } else if (aMsg.mType == MessageType::FatalError) { + mHasFatalError = true; const FatalErrorMessage& nmsg = static_cast<const FatalErrorMessage&>(aMsg); OnCrash(nmsg.Error()); return; } mLastMessageTime = TimeStamp::Now(); if (IsRecovering()) { @@ -522,22 +528,33 @@ ChildProcessInfo::LaunchSubprocess(const SendMessage(*gIntroductionMessage); } void ChildProcessInfo::OnCrash(const char* aWhy) { MOZ_RELEASE_ASSERT(NS_IsMainThread()); - // If a child process crashes or hangs then annotate the crash report and - // shut down cleanly so that we don't mask the report with our own crash. - // We want the crash to happen quickly so the user doesn't get a hanged tab. + // If a child process crashes or hangs then annotate the crash report. CrashReporter::AnnotateCrashReport(CrashReporter::Annotation::RecordReplayError, nsAutoCString(aWhy)); - Shutdown(); + + // If we received a FatalError message then the child generated a minidump. + // Shut down cleanly so that we don't mask the report with our own crash. + if (mHasFatalError) { + Shutdown(); + } + + // Indicate when we crash if the child tried to send us a fatal error message + // but had a problem either unprotecting system memory or generating the + // minidump. + MOZ_RELEASE_ASSERT(!mHasBegunFatalError); + + // The child crashed without producing a minidump, produce one ourselves. + MOZ_CRASH("Unexpected child crash"); } /////////////////////////////////////////////////////////////////////////////// // Handling Channel Messages /////////////////////////////////////////////////////////////////////////////// // When messages are received from child processes, we want their handler to // execute on the main thread. The main thread might be blocked in WaitUntil, @@ -608,17 +625,17 @@ ChildProcessInfo::WaitUntil(const std::f // wait another HangSeconds before hitting the restart case below. // Use SendMessageRaw to avoid problems if we are recovering. CrashReporter::AnnotateCrashReport(CrashReporter::Annotation::RecordReplayHang, true); SendMessageRaw(TerminateMessage()); sentTerminateMessage = true; } else { // The child is still non-responsive after sending the terminate - // message, fail without producing a minidump. + // message. OnCrash("Child process non-responsive"); } } gMonitor->WaitUntil(deadline); } } } }
--- a/toolkit/recordreplay/ipc/ParentForwarding.cpp +++ b/toolkit/recordreplay/ipc/ParentForwarding.cpp @@ -33,17 +33,16 @@ HandleMessageInMiddleman(ipc::Side aSide type == dom::PContent::Msg_PBrowserConstructor__ID || type == dom::PContent::Msg_RegisterChrome__ID || type == dom::PContent::Msg_SetXPCOMProcessAttributes__ID || type == dom::PContent::Msg_UpdateSharedData__ID || type == dom::PContent::Msg_SetProcessSandbox__ID || // Graphics messages that affect both processes. type == dom::PBrowser::Msg_InitRendering__ID || type == dom::PBrowser::Msg_SetDocShellIsActive__ID || - type == dom::PBrowser::Msg_PRenderFrameConstructor__ID || type == dom::PBrowser::Msg_RenderLayers__ID || type == dom::PBrowser::Msg_UpdateDimensions__ID || // These messages perform some graphics related initialization. type == dom::PBrowser::Msg_LoadURL__ID || type == dom::PBrowser::Msg_Show__ID || // May be loading devtools code that runs in the middleman process. type == dom::PBrowser::Msg_LoadRemoteScript__ID || // May be sending a message for receipt by devtools code.
--- a/toolkit/recordreplay/ipc/ParentGraphics.cpp +++ b/toolkit/recordreplay/ipc/ParentGraphics.cpp @@ -196,33 +196,16 @@ UpdateGraphicsInUIProcess(const PaintMes // Call into the graphics module to update the canvas it manages. RootedValue rval(cx); if (!JS_CallFunctionName(cx, *gGraphicsSandbox, "UpdateCanvas", args, &rval)) { MOZ_CRASH("UpdateGraphicsInUIProcess"); } } -void -UpdateGraphicsOverlay() -{ - if (!gLastPaintWidth || !gLastPaintHeight) { - return; - } - - AutoSafeJSContext cx; - JSAutoRealm ar(cx, *gGraphicsSandbox); - - RootedValue rval(cx); - if (!JS_CallFunctionName(cx, *gGraphicsSandbox, "UpdateOverlay", - JS::HandleValueArray::empty(), &rval)) { - MOZ_CRASH("UpdateGraphicsOverlay"); - } -} - static void MaybeTriggerExplicitPaint() { if (gLastExplicitPaint && gLastExplicitPaint->mCheckpointId == gLastCheckpoint) { UpdateGraphicsInUIProcess(gLastExplicitPaint.get()); } }
--- a/toolkit/recordreplay/ipc/ParentIPC.cpp +++ b/toolkit/recordreplay/ipc/ParentIPC.cpp @@ -606,22 +606,16 @@ SwitchActiveChild(ChildProcessInfo* aChi } aChild->SetRole(MakeUnique<ChildRoleActive>()); if (oldActiveChild->IsRecording()) { oldActiveChild->SetRole(MakeUnique<ChildRoleInert>()); } else { oldActiveChild->RecoverToCheckpoint(oldActiveChild->MostRecentSavedCheckpoint()); oldActiveChild->SetRole(MakeUnique<ChildRoleStandby>()); } - - // The graphics overlay is affected when we switch between recording and - // replaying children. - if (aChild->IsRecording() != oldActiveChild->IsRecording()) { - UpdateGraphicsOverlay(); - } } /////////////////////////////////////////////////////////////////////////////// // Preferences /////////////////////////////////////////////////////////////////////////////// static bool gPreferencesLoaded; static bool gRewindingEnabled; @@ -1182,20 +1176,16 @@ ResumeBeforeWaitingForIPDLReply() } static void RecvHitCheckpoint(const HitCheckpointMessage& aMsg) { UpdateCheckpointTimes(aMsg); MaybeUpdateGraphicsAtCheckpoint(aMsg.mCheckpointId); - if (!gActiveChild->IsRecording()) { - UpdateGraphicsOverlay(); - } - // Resume either forwards or backwards. Break the resume off into a separate // runnable, to avoid starving any code already on the stack and waiting for // the process to pause. Immediately resume if the main thread is blocked. if (MainThreadIsWaitingForIPDLReply()) { MOZ_RELEASE_ASSERT(gChildExecuteForward); Resume(true); } else if (!gResumeForwardOrBackward) { gResumeForwardOrBackward = true;
--- a/toolkit/recordreplay/ipc/ParentInternal.h +++ b/toolkit/recordreplay/ipc/ParentInternal.h @@ -89,19 +89,16 @@ extern void* gGraphicsMemory; void InitializeGraphicsMemory(); void SendGraphicsMemoryToChild(); // Update the graphics painted in the UI process, per painting data received // from a child process, or null if a repaint was triggered and failed due to // an unhandled recording divergence. void UpdateGraphicsInUIProcess(const PaintMessage* aMsg); -// Update the overlay shown over the tab's graphics. -void UpdateGraphicsOverlay(); - // If necessary, update graphics after the active child sends a paint message // or reaches a checkpoint. void MaybeUpdateGraphicsAtPaint(const PaintMessage& aMsg); void MaybeUpdateGraphicsAtCheckpoint(size_t aCheckpointId); // ID for the mach message sent from a child process to the middleman to // request a port for the graphics shmem. static const int32_t GraphicsHandshakeMessageId = 42; @@ -269,16 +266,21 @@ class ChildProcessInfo InfallibleVector<size_t> mShouldSaveCheckpoints; // Sorted major checkpoints for this process. See ParentIPC.cpp. InfallibleVector<size_t> mMajorCheckpoints; // Whether we need this child to pause while the recording is updated. bool mPauseNeeded; + // Flags for whether we have received messages from the child indicating it + // is crashing. + bool mHasBegunFatalError; + bool mHasFatalError; + void OnIncomingMessage(size_t aChannelId, const Message& aMsg); void OnIncomingRecoveryMessage(const Message& aMsg); void SendNextRecoveryMessage(); void SendMessageRaw(const Message& aMsg); static void MaybeProcessPendingMessageRunnable(); void ReceiveChildMessageOnMainThread(size_t aChannelId, Message* aMsg);
--- a/xpcom/base/nsCycleCollector.cpp +++ b/xpcom/base/nsCycleCollector.cpp @@ -2753,19 +2753,22 @@ public: } aObject.mParticipant->DeleteCycleCollectable(aObject.mPointer); } } bool Visit(nsPurpleBuffer& aBuffer, nsPurpleBufferEntry* aEntry) { - // Ignore any slice budget we have when recording/replaying, as it behaves - // non-deterministically. - if (mBudget && !recordreplay::IsRecordingOrReplaying()) { + // The cycle collector does not collect anything when recording/replaying. + if (recordreplay::IsRecordingOrReplaying()) { + return true; + } + + if (mBudget) { if (mBudget->isOverBudget()) { return false; } mBudget->step(); } MOZ_ASSERT(aEntry->mObject, "Null object in purple buffer"); if (!aEntry->mRefCnt->get()) {