Merge inbound to m-c a=merge

MozReview-Commit-ID: 6viJ4wRxLa8
This commit is contained in:
Wes Kocher 2017-09-26 15:54:51 -07:00
commit 22a72df7fe
177 changed files with 2135 additions and 2306 deletions

View file

@ -313,24 +313,12 @@ nsAccessibilityService::ListenersChanged(nsIArray* aEventChanges)
if (!node || !node->IsHTMLElement()) { if (!node || !node->IsHTMLElement()) {
continue; continue;
} }
nsCOMPtr<nsIArray> listenerNames;
change->GetChangedListenerNames(getter_AddRefs(listenerNames));
uint32_t changeCount; uint32_t changeCount;
rv = listenerNames->GetLength(&changeCount); change->GetCountOfEventListenerChangesAffectingAccessibility(&changeCount);
NS_ENSURE_SUCCESS(rv, rv); NS_ENSURE_SUCCESS(rv, rv);
for (uint32_t i = 0 ; i < changeCount ; i++) { for (uint32_t i = 0 ; i < changeCount ; i++) {
nsCOMPtr<nsIAtom> listenerName = do_QueryElementAt(listenerNames, i);
// We are only interested in event listener changes which may
// make an element accessible or inaccessible.
if (listenerName != nsGkAtoms::onclick &&
listenerName != nsGkAtoms::onmousedown &&
listenerName != nsGkAtoms::onmouseup) {
continue;
}
nsIDocument* ownerDoc = node->OwnerDoc(); nsIDocument* ownerDoc = node->OwnerDoc();
DocAccessible* document = GetExistingDocAccessible(ownerDoc); DocAccessible* document = GetExistingDocAccessible(ownerDoc);

View file

@ -849,6 +849,9 @@ function makePreview(row) {
var physWidth = 0, physHeight = 0; var physWidth = 0, physHeight = 0;
var width = 0, height = 0; var width = 0, height = 0;
let serial = Components.classes["@mozilla.org/network/serialization-helper;1"]
.getService(Components.interfaces.nsISerializationHelper);
let loadingPrincipalStr = serial.serializeToString(gDocInfo.principal);
if ((item.HTMLLinkElement || item.HTMLInputElement || if ((item.HTMLLinkElement || item.HTMLInputElement ||
item.HTMLImageElement || item.SVGImageElement || item.HTMLImageElement || item.SVGImageElement ||
(item.HTMLObjectElement && mimeType && mimeType.startsWith("image/")) || (item.HTMLObjectElement && mimeType && mimeType.startsWith("image/")) ||
@ -907,12 +910,14 @@ function makePreview(row) {
setItemValue("imagedimensiontext", imageSize); setItemValue("imagedimensiontext", imageSize);
}, {once: true}); }, {once: true});
newImage.setAttribute("loadingprincipal", loadingPrincipalStr);
newImage.setAttribute("src", url); newImage.setAttribute("src", url);
} else { } else {
// Handle the case where newImage is not used for width & height // Handle the case where newImage is not used for width & height
if (item.HTMLVideoElement && isProtocolAllowed) { if (item.HTMLVideoElement && isProtocolAllowed) {
newImage = document.createElementNS("http://www.w3.org/1999/xhtml", "video"); newImage = document.createElementNS("http://www.w3.org/1999/xhtml", "video");
newImage.id = "thepreviewimage"; newImage.id = "thepreviewimage";
newImage.setAttribute("loadingprincipal", loadingPrincipalStr);
newImage.src = url; newImage.src = url;
newImage.controls = true; newImage.controls = true;
width = physWidth = item.videoWidth; width = physWidth = item.videoWidth;
@ -923,6 +928,7 @@ function makePreview(row) {
} else if (item.HTMLAudioElement && isProtocolAllowed) { } else if (item.HTMLAudioElement && isProtocolAllowed) {
newImage = new Audio; newImage = new Audio;
newImage.id = "thepreviewimage"; newImage.id = "thepreviewimage";
newImage.setAttribute("loadingprincipal", loadingPrincipalStr);
newImage.src = url; newImage.src = url;
newImage.controls = true; newImage.controls = true;
isAudio = true; isAudio = true;

View file

@ -3,6 +3,12 @@
[browser_pageInfo.js] [browser_pageInfo.js]
support-files = support-files =
../general/feed_tab.html ../general/feed_tab.html
[browser_pageinfo_firstPartyIsolation.js]
support-files =
image.html
../general/audio.ogg
../general/moz.png
../general/video.ogg
[browser_pageinfo_images.js] [browser_pageinfo_images.js]
[browser_pageinfo_image_info.js] [browser_pageinfo_image_info.js]
skip-if = (os == 'linux' && e10s) # bug 1161699 skip-if = (os == 'linux' && e10s) # bug 1161699

View file

@ -0,0 +1,89 @@
const {classes: Cc, interfaces: Ci, manager: Cm} = Components;
function waitForEvent(elem, event) {
return new Promise(resolve => {
elem.addEventListener(event, resolve, {capture: true, once: true});
});
}
function testFirstPartyDomain(pageInfo) {
return new Promise(resolve => {
const EXPECTED_DOMAIN = "example.com";
info("pageInfo load");
pageInfo.onFinished.push(async function() {
info("pageInfo onfinished");
let tree = pageInfo.document.getElementById("imagetree");
Assert.ok(!!tree, "should have imagetree element");
// i=0: <img>
// i=1: <video>
// i=2: <audio>
for (let i = 0; i < 3; i++) {
info("imagetree select " + i);
tree.view.selection.select(i);
tree.treeBoxObject.ensureRowIsVisible(i);
tree.focus();
let preview = pageInfo.document.getElementById("thepreviewimage");
info("preview.src=" + preview.src);
// For <img>, we will query imgIRequest.imagePrincipal later, so we wait
// for loadend event. For <audio> and <video>, so far we only can get
// the loadingprincipal attribute on the node, so we simply wait for
// loadstart.
if (i == 0) {
await waitForEvent(preview, "loadend");
} else {
await waitForEvent(preview, "loadstart");
}
info("preview load " + i);
// Originally thepreviewimage is loaded with SystemPrincipal, therefore
// it won't have origin attributes, now we've changed to loadingPrincipal
// to the content in bug 1376971, it should have firstPartyDomain set.
if (i == 0) {
let req = preview.getRequest(Ci.nsIImageLoadingContent.CURRENT_REQUEST);
Assert.equal(req.imagePrincipal.originAttributes.firstPartyDomain, EXPECTED_DOMAIN,
"imagePrincipal should have firstPartyDomain set to " + EXPECTED_DOMAIN);
}
// Check the node has the attribute 'loadingprincipal'.
let serial = Components.classes["@mozilla.org/network/serialization-helper;1"]
.getService(Components.interfaces.nsISerializationHelper);
let loadingPrincipalStr = preview.getAttribute("loadingprincipal");
let loadingPrincipal = serial.deserializeObject(loadingPrincipalStr);
Assert.equal(loadingPrincipal.originAttributes.firstPartyDomain, EXPECTED_DOMAIN,
"loadingPrincipal should have firstPartyDomain set to " + EXPECTED_DOMAIN);
}
resolve();
});
});
}
async function test() {
waitForExplicitFinish();
Services.prefs.setBoolPref("privacy.firstparty.isolate", true);
registerCleanupFunction(function() {
Services.prefs.clearUserPref("privacy.firstparty.isolate");
});
gBrowser.selectedTab = BrowserTestUtils.addTab(gBrowser);
content.location = "https://example.com/browser/browser/base/content/test/pageinfo/image.html";
await waitForEvent(gBrowser.selectedBrowser, "load");
let spec = gBrowser.selectedBrowser.currentURI.spec;
let pageInfo = BrowserPageInfo(spec, "mediaTab");
info("waitForEvent pageInfo");
await waitForEvent(pageInfo, "load");
info("calling testFirstPartyDomain");
await testFirstPartyDomain(pageInfo);
pageInfo.close();
gBrowser.removeCurrentTab();
finish();
}

View file

@ -0,0 +1,5 @@
<html>
<img src='moz.png' height=100 width=150 id='test-image'>
<video src='video.ogg' id='test-video'></video>
<audio src='audio.ogg' id='test-audio'></audio>
</html>

View file

@ -53,7 +53,8 @@ NS_IMETHODIMP
BasePrincipal::GetOriginNoSuffix(nsACString& aOrigin) BasePrincipal::GetOriginNoSuffix(nsACString& aOrigin)
{ {
MOZ_ASSERT(mInitialized); MOZ_ASSERT(mInitialized);
return mOriginNoSuffix->ToUTF8String(aOrigin); mOriginNoSuffix->ToUTF8String(aOrigin);
return NS_OK;
} }
bool bool
@ -293,7 +294,8 @@ NS_IMETHODIMP
BasePrincipal::GetOriginSuffix(nsACString& aOriginAttributes) BasePrincipal::GetOriginSuffix(nsACString& aOriginAttributes)
{ {
MOZ_ASSERT(mOriginSuffix); MOZ_ASSERT(mOriginSuffix);
return mOriginSuffix->ToUTF8String(aOriginAttributes); mOriginSuffix->ToUTF8String(aOriginAttributes);
return NS_OK;
} }
NS_IMETHODIMP NS_IMETHODIMP

View file

@ -453,13 +453,12 @@ Toolbox.prototype = {
if (e.originalTarget.closest("input[type=text]") || if (e.originalTarget.closest("input[type=text]") ||
e.originalTarget.closest("input[type=search]") || e.originalTarget.closest("input[type=search]") ||
e.originalTarget.closest("input:not([type])") || e.originalTarget.closest("input:not([type])") ||
e.originalTarget.closest("textarea") e.originalTarget.closest("textarea")) {
) {
e.stopPropagation(); e.stopPropagation();
e.preventDefault(); e.preventDefault();
this.openTextBoxContextMenu(e.screenX, e.screenY); this.openTextBoxContextMenu(e.screenX, e.screenY);
} }
}, true); });
this.shortcuts = new KeyShortcuts({ this.shortcuts = new KeyShortcuts({
window: this.doc.defaultView window: this.doc.defaultView

View file

@ -1124,7 +1124,15 @@ Inspector.prototype = {
}, },
_onContextMenu: function (e) { _onContextMenu: function (e) {
if (e.originalTarget.closest("input[type=text]") ||
e.originalTarget.closest("input:not([type])") ||
e.originalTarget.closest("textarea")) {
return;
}
e.stopPropagation();
e.preventDefault(); e.preventDefault();
this._openMenu({ this._openMenu({
screenX: e.screenX, screenX: e.screenX,
screenY: e.screenY, screenY: e.screenY,

View file

@ -397,6 +397,15 @@ CssRuleView.prototype = {
* Context menu handler. * Context menu handler.
*/ */
_onContextMenu: function (event) { _onContextMenu: function (event) {
if (event.originalTarget.closest("input[type=text]") ||
event.originalTarget.closest("input:not([type])") ||
event.originalTarget.closest("textarea")) {
return;
}
event.stopPropagation();
event.preventDefault();
this._contextmenu.show(event); this._contextmenu.show(event);
}, },

View file

@ -26,10 +26,19 @@ add_task(function* () {
let [, win, doc] = yield createHost("bottom", TEST_URI); let [, win, doc] = yield createHost("bottom", TEST_URI);
info("Resizing window to have some space below the window."); info("Resize and move the window to have space below.");
let originalWidth = win.top.outerWidth; let originalWidth = win.top.outerWidth;
let originalHeight = win.top.outerHeight; let originalHeight = win.top.outerHeight;
win.top.resizeBy(0, -100); win.top.resizeBy(-100, -200);
let originalTop = win.top.screenTop;
let originalLeft = win.top.screenLeft;
win.top.moveTo(100, 100);
registerCleanupFunction(() => {
info("Restore original window dimensions and position.");
win.top.resizeTo(originalWidth, originalHeight);
win.top.moveTo(originalTop, originalLeft);
});
info("Create HTML tooltip"); info("Create HTML tooltip");
let tooltip = new HTMLTooltip(doc, {useXulWrapper: true}); let tooltip = new HTMLTooltip(doc, {useXulWrapper: true});
@ -55,9 +64,6 @@ add_task(function* () {
is(tooltip.isVisible(), false, "Tooltip is not visible"); is(tooltip.isVisible(), false, "Tooltip is not visible");
tooltip.destroy(); tooltip.destroy();
info("Restore original window dimensions.");
win.top.resizeTo(originalWidth, originalHeight);
}); });
function checkTooltip(tooltip, position, height) { function checkTooltip(tooltip, position, height) {

View file

@ -356,12 +356,13 @@ Editor.prototype = {
}); });
cm.getWrapperElement().addEventListener("contextmenu", ev => { cm.getWrapperElement().addEventListener("contextmenu", ev => {
ev.preventDefault();
if (!this.config.contextMenu) { if (!this.config.contextMenu) {
return; return;
} }
ev.stopPropagation();
ev.preventDefault();
let popup = this.config.contextMenu; let popup = this.config.contextMenu;
if (typeof popup == "string") { if (typeof popup == "string") {
popup = doc.getElementById(this.config.contextMenu); popup = doc.getElementById(this.config.contextMenu);

View file

@ -3,14 +3,10 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
:root { :root {
--markup-hidden-attr-color: var(--theme-comment);
--markup-hidden-tag-color: #A1A1A4;
--markup-outline: var(--theme-splitter-color); --markup-outline: var(--theme-splitter-color);
} }
.theme-dark:root { .theme-dark:root {
--markup-hidden-attr-color: var(--theme-body-color-inactive);
--markup-hidden-tag-color: var(--theme-content-color1);
--markup-outline: var(--theme-selection-background); --markup-outline: var(--theme-selection-background);
} }
@ -336,16 +332,6 @@ ul.children + .tag-line::before {
z-index: 1; z-index: 1;
} }
.not-displayed .attr-name,
.not-displayed .attr-value {
color: var(--markup-hidden-attr-color);
}
.not-displayed .theme-fg-color3 {
color: var(--markup-hidden-tag-color);
}
/* Firebug Theme */ /* Firebug Theme */
.theme-firebug .theme-fg-color3 { .theme-firebug .theme-fg-color3 {
@ -367,12 +353,6 @@ ul.children + .tag-line::before {
font-size: var(--theme-toolbar-font-size); font-size: var(--theme-toolbar-font-size);
} }
/* In case a node isn't displayed in the page, we fade the syntax highlighting */
.theme-firebug .not-displayed .open,
.theme-firebug .not-displayed .close {
opacity: .5;
}
/* Selected nodes in the tree should have light selected text. /* Selected nodes in the tree should have light selected text.
theme-selected doesn't work in this case since the text is a theme-selected doesn't work in this case since the text is a
sibling of the class, not a child. */ sibling of the class, not a child. */
@ -403,6 +383,12 @@ ul.children + .tag-line::before {
color: #787878; color: #787878;
} }
/* In case a node isn't displayed in the page, we fade the syntax highlighting */
.not-displayed .open,
.not-displayed .close {
opacity: .5;
}
/* Events */ /* Events */
.markupview-events { .markupview-events {
font-size: 8px; font-size: 8px;

View file

@ -28,14 +28,13 @@ CustomElementCallback::Call()
mOwnerData->mElementIsBeingCreated = true; mOwnerData->mElementIsBeingCreated = true;
// The callback hasn't actually been invoked yet, but we need to flip // The callback hasn't actually been invoked yet, but we need to flip
// this now in order to enqueue the attached callback. This is a spec // this now in order to enqueue the connected callback. This is a spec
// bug (w3c bug 27437). // bug (w3c bug 27437).
mOwnerData->mCreatedCallbackInvoked = true; mOwnerData->mCreatedCallbackInvoked = true;
// If ELEMENT is in a document and this document has a browsing context, // If ELEMENT is connected, enqueue connected callback for ELEMENT.
// enqueue attached callback for ELEMENT.
nsIDocument* document = mThisObject->GetComposedDoc(); nsIDocument* document = mThisObject->GetComposedDoc();
if (document && document->GetDocShell()) { if (document) {
NodeInfo* ni = mThisObject->NodeInfo(); NodeInfo* ni = mThisObject->NodeInfo();
nsDependentAtomString extType(mOwnerData->mType); nsDependentAtomString extType(mOwnerData->mType);
@ -49,18 +48,18 @@ CustomElementCallback::Call()
extType.IsEmpty() ? nullptr : &extType); extType.IsEmpty() ? nullptr : &extType);
nsContentUtils::EnqueueLifecycleCallback( nsContentUtils::EnqueueLifecycleCallback(
document, nsIDocument::eAttached, mThisObject, nullptr, definition); nsIDocument::eConnected, mThisObject, nullptr, definition);
} }
static_cast<LifecycleCreatedCallback *>(mCallback.get())->Call(mThisObject, rv); static_cast<LifecycleCreatedCallback *>(mCallback.get())->Call(mThisObject, rv);
mOwnerData->mElementIsBeingCreated = false; mOwnerData->mElementIsBeingCreated = false;
break; break;
} }
case nsIDocument::eAttached: case nsIDocument::eConnected:
static_cast<LifecycleAttachedCallback *>(mCallback.get())->Call(mThisObject, rv); static_cast<LifecycleConnectedCallback *>(mCallback.get())->Call(mThisObject, rv);
break; break;
case nsIDocument::eDetached: case nsIDocument::eDisconnected:
static_cast<LifecycleDetachedCallback *>(mCallback.get())->Call(mThisObject, rv); static_cast<LifecycleDisconnectedCallback *>(mCallback.get())->Call(mThisObject, rv);
break; break;
case nsIDocument::eAttributeChanged: case nsIDocument::eAttributeChanged:
static_cast<LifecycleAttributeChangedCallback *>(mCallback.get())->Call(mThisObject, static_cast<LifecycleAttributeChangedCallback *>(mCallback.get())->Call(mThisObject,
@ -321,7 +320,7 @@ CustomElementRegistry::SetupCustomElement(Element* aElement,
SyncInvokeReactions(nsIDocument::eCreated, aElement, definition); SyncInvokeReactions(nsIDocument::eCreated, aElement, definition);
} }
UniquePtr<CustomElementCallback> /* static */ UniquePtr<CustomElementCallback>
CustomElementRegistry::CreateCustomElementCallback( CustomElementRegistry::CreateCustomElementCallback(
nsIDocument::ElementCallbackType aType, Element* aCustomElement, nsIDocument::ElementCallbackType aType, Element* aCustomElement,
LifecycleCallbackArgs* aArgs, CustomElementDefinition* aDefinition) LifecycleCallbackArgs* aArgs, CustomElementDefinition* aDefinition)
@ -340,15 +339,15 @@ CustomElementRegistry::CreateCustomElementCallback(
} }
break; break;
case nsIDocument::eAttached: case nsIDocument::eConnected:
if (aDefinition->mCallbacks->mAttachedCallback.WasPassed()) { if (aDefinition->mCallbacks->mConnectedCallback.WasPassed()) {
func = aDefinition->mCallbacks->mAttachedCallback.Value(); func = aDefinition->mCallbacks->mConnectedCallback.Value();
} }
break; break;
case nsIDocument::eDetached: case nsIDocument::eDisconnected:
if (aDefinition->mCallbacks->mDetachedCallback.WasPassed()) { if (aDefinition->mCallbacks->mDisconnectedCallback.WasPassed()) {
func = aDefinition->mCallbacks->mDetachedCallback.Value(); func = aDefinition->mCallbacks->mDisconnectedCallback.Value();
} }
break; break;
@ -395,7 +394,7 @@ CustomElementRegistry::SyncInvokeReactions(nsIDocument::ElementCallbackType aTyp
} }
UniquePtr<CustomElementReaction> reaction(Move( UniquePtr<CustomElementReaction> reaction(Move(
MakeUnique<CustomElementCallbackReaction>(this, aDefinition, MakeUnique<CustomElementCallbackReaction>(aDefinition,
Move(callback)))); Move(callback))));
RefPtr<SyncInvokeReactionRunnable> runnable = RefPtr<SyncInvokeReactionRunnable> runnable =
@ -404,7 +403,7 @@ CustomElementRegistry::SyncInvokeReactions(nsIDocument::ElementCallbackType aTyp
nsContentUtils::AddScriptRunner(runnable); nsContentUtils::AddScriptRunner(runnable);
} }
void /* static */ void
CustomElementRegistry::EnqueueLifecycleCallback(nsIDocument::ElementCallbackType aType, CustomElementRegistry::EnqueueLifecycleCallback(nsIDocument::ElementCallbackType aType,
Element* aCustomElement, Element* aCustomElement,
LifecycleCallbackArgs* aArgs, LifecycleCallbackArgs* aArgs,
@ -425,7 +424,7 @@ CustomElementRegistry::EnqueueLifecycleCallback(nsIDocument::ElementCallbackType
return; return;
} }
DocGroup* docGroup = mWindow->GetDocGroup(); DocGroup* docGroup = aCustomElement->OwnerDoc()->GetDocGroup();
if (!docGroup) { if (!docGroup) {
return; return;
} }
@ -440,7 +439,7 @@ CustomElementRegistry::EnqueueLifecycleCallback(nsIDocument::ElementCallbackType
CustomElementReactionsStack* reactionsStack = CustomElementReactionsStack* reactionsStack =
docGroup->CustomElementReactionsStack(); docGroup->CustomElementReactionsStack();
reactionsStack->EnqueueCallbackReaction(this, aCustomElement, definition, reactionsStack->EnqueueCallbackReaction(aCustomElement, definition,
Move(callback)); Move(callback));
} }
@ -480,7 +479,7 @@ CustomElementRegistry::UpgradeCandidates(nsIAtom* aKey,
continue; continue;
} }
reactionsStack->EnqueueUpgradeReaction(this, elem, aDefinition); reactionsStack->EnqueueUpgradeReaction(elem, aDefinition);
} }
} }
} }
@ -934,8 +933,7 @@ CustomElementRegistry::Upgrade(Element* aElement,
(attrValue.IsEmpty() ? VoidString() : attrValue), (attrValue.IsEmpty() ? VoidString() : attrValue),
(namespaceURI.IsEmpty() ? VoidString() : namespaceURI) (namespaceURI.IsEmpty() ? VoidString() : namespaceURI)
}; };
nsContentUtils::EnqueueLifecycleCallback(aElement->OwnerDoc(), nsContentUtils::EnqueueLifecycleCallback(nsIDocument::eAttributeChanged,
nsIDocument::eAttributeChanged,
aElement, aElement,
&args, aDefinition); &args, aDefinition);
} }
@ -943,7 +941,10 @@ CustomElementRegistry::Upgrade(Element* aElement,
} }
// Step 4. // Step 4.
// TODO: Bug 1334043 - Implement connected lifecycle callbacks for custom elements if (aElement->IsInComposedDoc()) {
nsContentUtils::EnqueueLifecycleCallback(nsIDocument::eConnected, aElement,
nullptr, aDefinition);
}
// Step 5. // Step 5.
AutoConstructionStackEntry acs(aDefinition->mConstructionStack, AutoConstructionStackEntry acs(aDefinition->mConstructionStack,
@ -965,8 +966,7 @@ CustomElementRegistry::Upgrade(Element* aElement,
aElement->SetCustomElementDefinition(aDefinition); aElement->SetCustomElementDefinition(aDefinition);
// This is for old spec. // This is for old spec.
nsContentUtils::EnqueueLifecycleCallback(aElement->OwnerDoc(), nsContentUtils::EnqueueLifecycleCallback(nsIDocument::eCreated,
nsIDocument::eCreated,
aElement, nullptr, aDefinition); aElement, nullptr, aDefinition);
} }
@ -1010,20 +1010,18 @@ CustomElementReactionsStack::PopAndInvokeElementQueue()
} }
void void
CustomElementReactionsStack::EnqueueUpgradeReaction(CustomElementRegistry* aRegistry, CustomElementReactionsStack::EnqueueUpgradeReaction(Element* aElement,
Element* aElement,
CustomElementDefinition* aDefinition) CustomElementDefinition* aDefinition)
{ {
Enqueue(aElement, new CustomElementUpgradeReaction(aRegistry, aDefinition)); Enqueue(aElement, new CustomElementUpgradeReaction(aDefinition));
} }
void void
CustomElementReactionsStack::EnqueueCallbackReaction(CustomElementRegistry* aRegistry, CustomElementReactionsStack::EnqueueCallbackReaction(Element* aElement,
Element* aElement,
CustomElementDefinition* aDefinition, CustomElementDefinition* aDefinition,
UniquePtr<CustomElementCallback> aCustomElementCallback) UniquePtr<CustomElementCallback> aCustomElementCallback)
{ {
Enqueue(aElement, new CustomElementCallbackReaction(aRegistry, aDefinition, Enqueue(aElement, new CustomElementCallbackReaction(aDefinition,
Move(aCustomElementCallback))); Move(aCustomElementCallback)));
} }
@ -1036,14 +1034,14 @@ CustomElementReactionsStack::Enqueue(Element* aElement,
// Add element to the current element queue. // Add element to the current element queue.
if (!mReactionsStack.IsEmpty()) { if (!mReactionsStack.IsEmpty()) {
mReactionsStack.LastElement()->AppendElement(do_GetWeakReference(aElement)); mReactionsStack.LastElement()->AppendElement(aElement);
elementData->mReactionQueue.AppendElement(aReaction); elementData->mReactionQueue.AppendElement(aReaction);
return; return;
} }
// If the custom element reactions stack is empty, then: // If the custom element reactions stack is empty, then:
// Add element to the backup element queue. // Add element to the backup element queue.
mBackupQueue.AppendElement(do_GetWeakReference(aElement)); mBackupQueue.AppendElement(aElement);
elementData->mReactionQueue.AppendElement(aReaction); elementData->mReactionQueue.AppendElement(aReaction);
if (mIsBackupQueueProcessing) { if (mIsBackupQueueProcessing) {
@ -1081,14 +1079,18 @@ CustomElementReactionsStack::InvokeReactions(ElementQueue* aElementQueue,
// Note: It's possible to re-enter this method. // Note: It's possible to re-enter this method.
for (uint32_t i = 0; i < aElementQueue->Length(); ++i) { for (uint32_t i = 0; i < aElementQueue->Length(); ++i) {
nsCOMPtr<Element> element = do_QueryReferent(aElementQueue->ElementAt(i)); Element* element = aElementQueue->ElementAt(i);
if (!element) { if (!element) {
continue; continue;
} }
RefPtr<CustomElementData> elementData = element->GetCustomElementData(); RefPtr<CustomElementData> elementData = element->GetCustomElementData();
MOZ_ASSERT(elementData, "CustomElementData should exist"); if (!elementData) {
// This happens when the document is destroyed and the element is already
// unlinked, no need to fire the callbacks in this case.
return;
}
auto& reactions = elementData->mReactionQueue; auto& reactions = elementData->mReactionQueue;
for (uint32_t j = 0; j < reactions.Length(); ++j) { for (uint32_t j = 0; j < reactions.Length(); ++j) {
@ -1138,14 +1140,14 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(CustomElementDefinition)
cb.NoteXPCOMChild(callbacks->mCreatedCallback.Value()); cb.NoteXPCOMChild(callbacks->mCreatedCallback.Value());
} }
if (callbacks->mAttachedCallback.WasPassed()) { if (callbacks->mConnectedCallback.WasPassed()) {
NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb, "mCallbacks->mAttachedCallback"); NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb, "mCallbacks->mConnectedCallback");
cb.NoteXPCOMChild(callbacks->mAttachedCallback.Value()); cb.NoteXPCOMChild(callbacks->mConnectedCallback.Value());
} }
if (callbacks->mDetachedCallback.WasPassed()) { if (callbacks->mDisconnectedCallback.WasPassed()) {
NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb, "mCallbacks->mDetachedCallback"); NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb, "mCallbacks->mDisconnectedCallback");
cb.NoteXPCOMChild(callbacks->mDetachedCallback.Value()); cb.NoteXPCOMChild(callbacks->mDisconnectedCallback.Value());
} }
NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb, "mConstructor"); NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb, "mConstructor");
@ -1184,7 +1186,7 @@ CustomElementDefinition::CustomElementDefinition(nsIAtom* aType,
/* virtual */ void /* virtual */ void
CustomElementUpgradeReaction::Invoke(Element* aElement, ErrorResult& aRv) CustomElementUpgradeReaction::Invoke(Element* aElement, ErrorResult& aRv)
{ {
mRegistry->Upgrade(aElement, mDefinition, aRv); CustomElementRegistry::Upgrade(aElement, mDefinition, aRv);
} }
//----------------------------------------------------- //-----------------------------------------------------

View file

@ -200,10 +200,8 @@ private:
class CustomElementReaction class CustomElementReaction
{ {
public: public:
explicit CustomElementReaction(CustomElementRegistry* aRegistry, explicit CustomElementReaction(CustomElementDefinition* aDefinition)
CustomElementDefinition* aDefinition) : mDefinition(aDefinition)
: mRegistry(aRegistry)
, mDefinition(aDefinition)
{ {
} }
@ -214,16 +212,14 @@ public:
} }
protected: protected:
CustomElementRegistry* mRegistry;
CustomElementDefinition* mDefinition; CustomElementDefinition* mDefinition;
}; };
class CustomElementUpgradeReaction final : public CustomElementReaction class CustomElementUpgradeReaction final : public CustomElementReaction
{ {
public: public:
explicit CustomElementUpgradeReaction(CustomElementRegistry* aRegistry, explicit CustomElementUpgradeReaction(CustomElementDefinition* aDefinition)
CustomElementDefinition* aDefinition) : CustomElementReaction(aDefinition)
: CustomElementReaction(aRegistry, aDefinition)
{ {
} }
@ -234,10 +230,9 @@ private:
class CustomElementCallbackReaction final : public CustomElementReaction class CustomElementCallbackReaction final : public CustomElementReaction
{ {
public: public:
CustomElementCallbackReaction(CustomElementRegistry* aRegistry, CustomElementCallbackReaction(CustomElementDefinition* aDefinition,
CustomElementDefinition* aDefinition,
UniquePtr<CustomElementCallback> aCustomElementCallback) UniquePtr<CustomElementCallback> aCustomElementCallback)
: CustomElementReaction(aRegistry, aDefinition) : CustomElementReaction(aDefinition)
, mCustomElementCallback(Move(aCustomElementCallback)) , mCustomElementCallback(Move(aCustomElementCallback))
{ {
} }
@ -263,26 +258,25 @@ public:
{ {
} }
// nsWeakPtr is a weak pointer of Element // Hold a strong reference of Element so that it does not get cycle collected
// before the reactions in its reaction queue are invoked.
// The element reaction queues are stored in CustomElementData. // The element reaction queues are stored in CustomElementData.
// We need to lookup ElementReactionQueueMap again to get relevant reaction queue. // We need to lookup ElementReactionQueueMap again to get relevant reaction queue.
// The choice of 1 for the auto size here is based on gut feeling. // The choice of 1 for the auto size here is based on gut feeling.
typedef AutoTArray<nsWeakPtr, 1> ElementQueue; typedef AutoTArray<RefPtr<Element>, 1> ElementQueue;
/** /**
* Enqueue a custom element upgrade reaction * Enqueue a custom element upgrade reaction
* https://html.spec.whatwg.org/multipage/scripting.html#enqueue-a-custom-element-upgrade-reaction * https://html.spec.whatwg.org/multipage/scripting.html#enqueue-a-custom-element-upgrade-reaction
*/ */
void EnqueueUpgradeReaction(CustomElementRegistry* aRegistry, void EnqueueUpgradeReaction(Element* aElement,
Element* aElement,
CustomElementDefinition* aDefinition); CustomElementDefinition* aDefinition);
/** /**
* Enqueue a custom element callback reaction * Enqueue a custom element callback reaction
* https://html.spec.whatwg.org/multipage/scripting.html#enqueue-a-custom-element-callback-reaction * https://html.spec.whatwg.org/multipage/scripting.html#enqueue-a-custom-element-callback-reaction
*/ */
void EnqueueCallbackReaction(CustomElementRegistry* aRegistry, void EnqueueCallbackReaction(Element* aElement,
Element* aElement,
CustomElementDefinition* aDefinition, CustomElementDefinition* aDefinition,
UniquePtr<CustomElementCallback> aCustomElementCallback); UniquePtr<CustomElementCallback> aCustomElementCallback);
@ -377,10 +371,10 @@ public:
*/ */
void SetupCustomElement(Element* aElement, const nsAString* aTypeExtension); void SetupCustomElement(Element* aElement, const nsAString* aTypeExtension);
void EnqueueLifecycleCallback(nsIDocument::ElementCallbackType aType, static void EnqueueLifecycleCallback(nsIDocument::ElementCallbackType aType,
Element* aCustomElement, Element* aCustomElement,
LifecycleCallbackArgs* aArgs, LifecycleCallbackArgs* aArgs,
CustomElementDefinition* aDefinition); CustomElementDefinition* aDefinition);
void GetCustomPrototype(nsIAtom* aAtom, void GetCustomPrototype(nsIAtom* aAtom,
JS::MutableHandle<JSObject*> aPrototype); JS::MutableHandle<JSObject*> aPrototype);
@ -398,7 +392,7 @@ public:
private: private:
~CustomElementRegistry(); ~CustomElementRegistry();
UniquePtr<CustomElementCallback> CreateCustomElementCallback( static UniquePtr<CustomElementCallback> CreateCustomElementCallback(
nsIDocument::ElementCallbackType aType, Element* aCustomElement, nsIDocument::ElementCallbackType aType, Element* aCustomElement,
LifecycleCallbackArgs* aArgs, CustomElementDefinition* aDefinition); LifecycleCallbackArgs* aArgs, CustomElementDefinition* aDefinition);

View file

@ -1620,14 +1620,11 @@ Element::BindToTree(nsIDocument* aDocument, nsIContent* aParent,
SetSubtreeRootPointer(aParent->SubtreeRoot()); SetSubtreeRootPointer(aParent->SubtreeRoot());
} }
nsIDocument* composedDoc = GetComposedDoc(); if (CustomElementRegistry::IsCustomElementEnabled() && IsInComposedDoc()) {
if (composedDoc) { // Connected callback must be enqueued whenever a custom element becomes
// Attached callback must be enqueued whenever custom element is inserted into a // connected.
// document and this document has a browsing context. if (GetCustomElementData()) {
if (GetCustomElementData() && composedDoc->GetDocShell()) { nsContentUtils::EnqueueLifecycleCallback(nsIDocument::eConnected, this);
// Enqueue an attached callback for the custom element.
nsContentUtils::EnqueueLifecycleCallback(
composedDoc, nsIDocument::eAttached, this);
} }
} }
@ -1951,12 +1948,12 @@ Element::UnbindFromTree(bool aDeep, bool aNullParent)
document->ClearBoxObjectFor(this); document->ClearBoxObjectFor(this);
// Detached must be enqueued whenever custom element is removed from // Disconnected must be enqueued whenever a connected custom element becomes
// the document and this document has a browsing context. // disconnected.
if (GetCustomElementData() && document->GetDocShell()) { if (CustomElementRegistry::IsCustomElementEnabled() &&
// Enqueue a detached callback for the custom element. GetCustomElementData()) {
nsContentUtils::EnqueueLifecycleCallback( nsContentUtils::EnqueueLifecycleCallback(nsIDocument::eDisconnected,
document, nsIDocument::eDetached, this); this);
} }
} }
@ -2625,7 +2622,7 @@ Element::SetAttrAndNotify(int32_t aNamespaceID,
} }
} }
if (nsContentUtils::IsWebComponentsEnabled()) { if (CustomElementRegistry::IsCustomElementEnabled()) {
if (CustomElementData* data = GetCustomElementData()) { if (CustomElementData* data = GetCustomElementData()) {
if (CustomElementDefinition* definition = if (CustomElementDefinition* definition =
nsContentUtils::GetElementDefinitionIfObservingAttr(this, nsContentUtils::GetElementDefinitionIfObservingAttr(this,
@ -2652,7 +2649,7 @@ Element::SetAttrAndNotify(int32_t aNamespaceID,
}; };
nsContentUtils::EnqueueLifecycleCallback( nsContentUtils::EnqueueLifecycleCallback(
OwnerDoc(), nsIDocument::eAttributeChanged, this, &args, definition); nsIDocument::eAttributeChanged, this, &args, definition);
} }
} }
} }
@ -2929,7 +2926,7 @@ Element::UnsetAttr(int32_t aNameSpaceID, nsIAtom* aName,
} }
} }
if (nsContentUtils::IsWebComponentsEnabled()) { if (CustomElementRegistry::IsCustomElementEnabled()) {
if (CustomElementData* data = GetCustomElementData()) { if (CustomElementData* data = GetCustomElementData()) {
if (CustomElementDefinition* definition = if (CustomElementDefinition* definition =
nsContentUtils::GetElementDefinitionIfObservingAttr(this, nsContentUtils::GetElementDefinitionIfObservingAttr(this,
@ -2947,7 +2944,7 @@ Element::UnsetAttr(int32_t aNameSpaceID, nsIAtom* aName,
}; };
nsContentUtils::EnqueueLifecycleCallback( nsContentUtils::EnqueueLifecycleCallback(
OwnerDoc(), nsIDocument::eAttributeChanged, this, &args, definition); nsIDocument::eAttributeChanged, this, &args, definition);
} }
} }
} }

View file

@ -10162,45 +10162,30 @@ nsContentUtils::EnqueueUpgradeReaction(Element* aElement,
MOZ_ASSERT(aElement); MOZ_ASSERT(aElement);
nsIDocument* doc = aElement->OwnerDoc(); nsIDocument* doc = aElement->OwnerDoc();
nsPIDOMWindowInner* window(doc->GetInnerWindow());
if (!window) {
return;
}
RefPtr<CustomElementRegistry> registry(window->CustomElements()); // No DocGroup means no custom element reactions stack.
if (!registry) { if (!doc->GetDocGroup()) {
return; return;
} }
CustomElementReactionsStack* stack = CustomElementReactionsStack* stack =
doc->GetDocGroup()->CustomElementReactionsStack(); doc->GetDocGroup()->CustomElementReactionsStack();
stack->EnqueueUpgradeReaction(registry, aElement, aDefinition); stack->EnqueueUpgradeReaction(aElement, aDefinition);
} }
/* static */ void /* static */ void
nsContentUtils::EnqueueLifecycleCallback(nsIDocument* aDoc, nsContentUtils::EnqueueLifecycleCallback(nsIDocument::ElementCallbackType aType,
nsIDocument::ElementCallbackType aType,
Element* aCustomElement, Element* aCustomElement,
LifecycleCallbackArgs* aArgs, LifecycleCallbackArgs* aArgs,
CustomElementDefinition* aDefinition) CustomElementDefinition* aDefinition)
{ {
MOZ_ASSERT(aDoc); // No DocGroup means no custom element reactions stack.
if (!aCustomElement->OwnerDoc()->GetDocGroup()) {
if (!aDoc->GetDocShell()) {
return; return;
} }
nsCOMPtr<nsPIDOMWindowInner> window(aDoc->GetInnerWindow()); CustomElementRegistry::EnqueueLifecycleCallback(aType, aCustomElement, aArgs,
if (!window) { aDefinition);
return;
}
RefPtr<CustomElementRegistry> registry(window->CustomElements());
if (!registry) {
return;
}
registry->EnqueueLifecycleCallback(aType, aCustomElement, aArgs, aDefinition);
} }
/* static */ void /* static */ void
@ -10444,6 +10429,44 @@ nsContentUtils::AppendNativeAnonymousChildren(
} }
} }
/* static */ bool
nsContentUtils::GetLoadingPrincipalForXULNode(nsIContent* aLoadingNode,
nsIPrincipal** aLoadingPrincipal)
{
MOZ_ASSERT(aLoadingNode);
MOZ_ASSERT(aLoadingPrincipal);
bool result = false;
nsCOMPtr<nsIPrincipal> loadingPrincipal = aLoadingNode->NodePrincipal();
nsAutoString loadingStr;
aLoadingNode->GetAttr(kNameSpaceID_None, nsGkAtoms::loadingprincipal,
loadingStr);
if (loadingStr.IsEmpty()) {
// Fall back to mContent's principal (SystemPrincipal) if 'loadingprincipal'
// isn't specified.
loadingPrincipal.forget(aLoadingPrincipal);
return result;
}
nsCOMPtr<nsISupports> serializedPrincipal;
NS_DeserializeObject(NS_ConvertUTF16toUTF8(loadingStr),
getter_AddRefs(serializedPrincipal));
loadingPrincipal = do_QueryInterface(serializedPrincipal);
if (loadingPrincipal) {
// We only allow specifying loadingprincipal attribute on a node loaded by
// SystemPrincipal.
MOZ_ASSERT(nsContentUtils::IsSystemPrincipal(aLoadingNode->NodePrincipal()),
"aLoadingNode Should be loaded with SystemPrincipal");
result = true;
} else {
// Fallback if the deserialization is failed.
loadingPrincipal = aLoadingNode->NodePrincipal();
}
loadingPrincipal.forget(aLoadingPrincipal);
return result;
}
/* static */ void /* static */ void
nsContentUtils::GetContentPolicyTypeForUIImageLoading(nsIContent* aLoadingNode, nsContentUtils::GetContentPolicyTypeForUIImageLoading(nsIContent* aLoadingNode,
@ -10453,38 +10476,23 @@ nsContentUtils::GetContentPolicyTypeForUIImageLoading(nsIContent* aLoadingNode,
{ {
MOZ_ASSERT(aRequestContextID); MOZ_ASSERT(aRequestContextID);
// Use the serialized loadingPrincipal from the image element. Fall back bool result = GetLoadingPrincipalForXULNode(aLoadingNode, aLoadingPrincipal);
// to mContent's principal (SystemPrincipal) if not available. if (result) {
aContentPolicyType = nsIContentPolicy::TYPE_INTERNAL_IMAGE; // Set the content policy type to TYPE_INTERNAL_IMAGE_FAVICON for
nsCOMPtr<nsIPrincipal> loadingPrincipal = aLoadingNode->NodePrincipal(); // indicating it's a favicon loading.
nsAutoString imageLoadingPrincipal; aContentPolicyType = nsIContentPolicy::TYPE_INTERNAL_IMAGE_FAVICON;
aLoadingNode->GetAttr(kNameSpaceID_None, nsGkAtoms::loadingprincipal,
imageLoadingPrincipal);
if (!imageLoadingPrincipal.IsEmpty()) {
nsCOMPtr<nsISupports> serializedPrincipal;
NS_DeserializeObject(NS_ConvertUTF16toUTF8(imageLoadingPrincipal),
getter_AddRefs(serializedPrincipal));
loadingPrincipal = do_QueryInterface(serializedPrincipal);
if (loadingPrincipal) { nsAutoString requestContextID;
// Set the content policy type to TYPE_INTERNAL_IMAGE_FAVICON for aLoadingNode->GetAttr(kNameSpaceID_None, nsGkAtoms::requestcontextid,
// indicating it's a favicon loading. requestContextID);
aContentPolicyType = nsIContentPolicy::TYPE_INTERNAL_IMAGE_FAVICON; nsresult rv;
int64_t val = requestContextID.ToInteger64(&rv);
nsAutoString requestContextID; *aRequestContextID = NS_SUCCEEDED(rv)
aLoadingNode->GetAttr(kNameSpaceID_None, nsGkAtoms::requestcontextid, ? val
requestContextID); : 0;
nsresult rv; } else {
int64_t val = requestContextID.ToInteger64(&rv); aContentPolicyType = nsIContentPolicy::TYPE_INTERNAL_IMAGE;
*aRequestContextID = NS_SUCCEEDED(rv)
? val
: 0;
} else {
// Fallback if the deserialization is failed.
loadingPrincipal = aLoadingNode->NodePrincipal();
}
} }
loadingPrincipal.forget(aLoadingPrincipal);
} }
/* static */ nsresult /* static */ nsresult

View file

@ -3005,8 +3005,7 @@ public:
static void EnqueueUpgradeReaction(Element* aElement, static void EnqueueUpgradeReaction(Element* aElement,
mozilla::dom::CustomElementDefinition* aDefinition); mozilla::dom::CustomElementDefinition* aDefinition);
static void EnqueueLifecycleCallback(nsIDocument* aDoc, static void EnqueueLifecycleCallback(nsIDocument::ElementCallbackType aType,
nsIDocument::ElementCallbackType aType,
Element* aCustomElement, Element* aCustomElement,
mozilla::dom::LifecycleCallbackArgs* aArgs = nullptr, mozilla::dom::LifecycleCallbackArgs* aArgs = nullptr,
mozilla::dom::CustomElementDefinition* aDefinition = nullptr); mozilla::dom::CustomElementDefinition* aDefinition = nullptr);
@ -3038,6 +3037,19 @@ public:
nsTArray<nsIContent*>& aKids, nsTArray<nsIContent*>& aKids,
uint32_t aFlags); uint32_t aFlags);
/**
* Query loadingPrincipal if it is specified as 'loadingprincipal' attribute on
* aLoadingNode, otherwise the NodePrincipal of aLoadingNode is returned
* (which is System Principal).
*
* Return true if aLoadingPrincipal has 'loadingprincipal' attributes, and
* the value 'loadingprincipal' is also successfully deserialized, otherwise
* return false.
*/
static bool
GetLoadingPrincipalForXULNode(nsIContent* aLoadingNode,
nsIPrincipal** aLoadingPrincipal);
/** /**
* Returns the content policy type that should be used for loading images * Returns the content policy type that should be used for loading images
* for displaying in the UI. The sources of such images can be <xul:image>, * for displaying in the UI. The sources of such images can be <xul:image>,

View file

@ -361,31 +361,6 @@ static uint32_t gThrottledIdlePeriodLength;
} \ } \
PR_END_MACRO PR_END_MACRO
#define FORWARD_TO_OUTER_CHROME(method, args, err_rval) \
PR_BEGIN_MACRO \
if (IsInnerWindow()) { \
nsGlobalWindow *outer = GetOuterWindowInternal(); \
if (!AsInner()->HasActiveDocument()) { \
NS_WARNING(outer ? \
"Inner window does not have active document." : \
"No outer window available!"); \
return err_rval; \
} \
return ((nsGlobalChromeWindow *)outer)->method args; \
} \
PR_END_MACRO
#define FORWARD_TO_INNER_CHROME(method, args, err_rval) \
PR_BEGIN_MACRO \
if (IsOuterWindow()) { \
if (!mInnerWindow) { \
NS_WARNING("No inner window available!"); \
return err_rval; \
} \
return ((nsGlobalChromeWindow *)nsGlobalWindow::Cast(mInnerWindow))->method args; \
} \
PR_END_MACRO
#define FORWARD_TO_OUTER_MODAL_CONTENT_WINDOW(method, args, err_rval) \ #define FORWARD_TO_OUTER_MODAL_CONTENT_WINDOW(method, args, err_rval) \
PR_BEGIN_MACRO \ PR_BEGIN_MACRO \
if (IsInnerWindow()) { \ if (IsInnerWindow()) { \
@ -1753,6 +1728,20 @@ nsGlobalWindow::~nsGlobalWindow()
{ {
AssertIsOnMainThread(); AssertIsOnMainThread();
if (IsChromeWindow()) {
MOZ_ASSERT(mCleanMessageManager,
"chrome windows may always disconnect the msg manager");
DisconnectAndClearGroupMessageManagers();
if (mChromeFields.mMessageManager) {
static_cast<nsFrameMessageManager *>(
mChromeFields.mMessageManager.get())->Disconnect();
}
mCleanMessageManager = false;
}
DisconnectEventTargetObjects(); DisconnectEventTargetObjects();
// We have to check if sWindowsById isn't null because ::Shutdown might have // We have to check if sWindowsById isn't null because ::Shutdown might have
@ -2040,10 +2029,9 @@ nsGlobalWindow::CleanUp()
if (mCleanMessageManager) { if (mCleanMessageManager) {
MOZ_ASSERT(mIsChrome, "only chrome should have msg manager cleaned"); MOZ_ASSERT(mIsChrome, "only chrome should have msg manager cleaned");
nsGlobalChromeWindow *asChrome = static_cast<nsGlobalChromeWindow*>(this); if (mChromeFields.mMessageManager) {
if (asChrome->mMessageManager) {
static_cast<nsFrameMessageManager*>( static_cast<nsFrameMessageManager*>(
asChrome->mMessageManager.get())->Disconnect(); mChromeFields.mMessageManager.get())->Disconnect();
} }
} }
@ -2215,6 +2203,9 @@ NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsGlobalWindow)
if (aIID.Equals(NS_GET_IID(mozIDOMWindowProxy)) && IsOuterWindow()) { if (aIID.Equals(NS_GET_IID(mozIDOMWindowProxy)) && IsOuterWindow()) {
foundInterface = AsOuter(); foundInterface = AsOuter();
} else } else
if (aIID.Equals(NS_GET_IID(nsIDOMChromeWindow)) && IsChromeWindow()) {
foundInterface = static_cast<nsIDOMChromeWindow*>(this);
} else
NS_INTERFACE_MAP_ENTRY(nsISupportsWeakReference) NS_INTERFACE_MAP_ENTRY(nsISupportsWeakReference)
NS_INTERFACE_MAP_ENTRY(nsIInterfaceRequestor) NS_INTERFACE_MAP_ENTRY(nsIInterfaceRequestor)
NS_INTERFACE_MAP_END NS_INTERFACE_MAP_END
@ -2355,6 +2346,11 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INTERNAL(nsGlobalWindow)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mIntlUtils) NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mIntlUtils)
tmp->TraverseHostObjectURIs(cb); tmp->TraverseHostObjectURIs(cb);
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mChromeFields.mBrowserDOMWindow)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mChromeFields.mMessageManager)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mChromeFields.mGroupMessageManagers)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mChromeFields.mOpenerForInitialContentBrowser)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsGlobalWindow) NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsGlobalWindow)
@ -2437,6 +2433,18 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsGlobalWindow)
NS_IMPL_CYCLE_COLLECTION_UNLINK(mIdleRequestExecutor) NS_IMPL_CYCLE_COLLECTION_UNLINK(mIdleRequestExecutor)
tmp->DisableIdleCallbackRequests(); tmp->DisableIdleCallbackRequests();
if (tmp->IsChromeWindow()) {
NS_IMPL_CYCLE_COLLECTION_UNLINK(mChromeFields.mBrowserDOMWindow)
if (tmp->mChromeFields.mMessageManager) {
static_cast<nsFrameMessageManager*>(
tmp->mChromeFields.mMessageManager.get())->Disconnect();
NS_IMPL_CYCLE_COLLECTION_UNLINK(mChromeFields.mMessageManager)
}
tmp->DisconnectAndClearGroupMessageManagers();
NS_IMPL_CYCLE_COLLECTION_UNLINK(mChromeFields.mGroupMessageManagers)
NS_IMPL_CYCLE_COLLECTION_UNLINK(mChromeFields.mOpenerForInitialContentBrowser)
}
NS_IMPL_CYCLE_COLLECTION_UNLINK_PRESERVED_WRAPPER NS_IMPL_CYCLE_COLLECTION_UNLINK_PRESERVED_WRAPPER
NS_IMPL_CYCLE_COLLECTION_UNLINK_END NS_IMPL_CYCLE_COLLECTION_UNLINK_END
@ -3125,7 +3133,7 @@ nsGlobalWindow::SetNewDocument(nsIDocument* aDocument,
newInnerGlobal = newInnerWindow->GetWrapperPreserveColor(); newInnerGlobal = newInnerWindow->GetWrapperPreserveColor();
} else { } else {
if (thisChrome) { if (thisChrome) {
newInnerWindow = nsGlobalChromeWindow::Create(this); newInnerWindow = nsGlobalWindow::CreateChrome(this);
} else { } else {
newInnerWindow = nsGlobalWindow::Create(this); newInnerWindow = nsGlobalWindow::Create(this);
} }
@ -7309,12 +7317,11 @@ nsGlobalWindow::SetWidgetFullscreen(FullscreenReason aReason, bool aIsFullscreen
MOZ_ASSERT(XRE_GetProcessType() == GeckoProcessType_Default); MOZ_ASSERT(XRE_GetProcessType() == GeckoProcessType_Default);
if (!NS_WARN_IF(!IsChromeWindow())) { if (!NS_WARN_IF(!IsChromeWindow())) {
auto chromeWin = static_cast<nsGlobalChromeWindow*>(this); if (!NS_WARN_IF(mChromeFields.mFullscreenPresShell)) {
if (!NS_WARN_IF(chromeWin->mFullscreenPresShell)) {
if (nsIPresShell* shell = mDocShell->GetPresShell()) { if (nsIPresShell* shell = mDocShell->GetPresShell()) {
if (nsRefreshDriver* rd = shell->GetRefreshDriver()) { if (nsRefreshDriver* rd = shell->GetRefreshDriver()) {
chromeWin->mFullscreenPresShell = do_GetWeakReference(shell); mChromeFields.mFullscreenPresShell = do_GetWeakReference(shell);
MOZ_ASSERT(chromeWin->mFullscreenPresShell); MOZ_ASSERT(mChromeFields.mFullscreenPresShell);
rd->SetIsResizeSuppressed(); rd->SetIsResizeSuppressed();
rd->Freeze(); rd->Freeze();
} }
@ -7362,13 +7369,12 @@ nsGlobalWindow::FinishFullscreenChange(bool aIsFullscreen)
DispatchCustomEvent(NS_LITERAL_STRING("fullscreen")); DispatchCustomEvent(NS_LITERAL_STRING("fullscreen"));
if (!NS_WARN_IF(!IsChromeWindow())) { if (!NS_WARN_IF(!IsChromeWindow())) {
auto chromeWin = static_cast<nsGlobalChromeWindow*>(this);
if (nsCOMPtr<nsIPresShell> shell = if (nsCOMPtr<nsIPresShell> shell =
do_QueryReferent(chromeWin->mFullscreenPresShell)) { do_QueryReferent(mChromeFields.mFullscreenPresShell)) {
if (nsRefreshDriver* rd = shell->GetRefreshDriver()) { if (nsRefreshDriver* rd = shell->GetRefreshDriver()) {
rd->Thaw(); rd->Thaw();
} }
chromeWin->mFullscreenPresShell = nullptr; mChromeFields.mFullscreenPresShell = nullptr;
} }
} }
@ -9362,8 +9368,7 @@ nsGlobalWindow::CanClose()
if (mIsChrome) { if (mIsChrome) {
nsCOMPtr<nsIBrowserDOMWindow> bwin; nsCOMPtr<nsIBrowserDOMWindow> bwin;
nsIDOMChromeWindow* chromeWin = static_cast<nsGlobalChromeWindow*>(this); GetBrowserDOMWindow(getter_AddRefs(bwin));
chromeWin->GetBrowserDOMWindow(getter_AddRefs(bwin));
bool canClose = true; bool canClose = true;
if (bwin && NS_SUCCEEDED(bwin->CanClose(&canClose))) { if (bwin && NS_SUCCEEDED(bwin->CanClose(&canClose))) {
@ -14015,44 +14020,13 @@ nsGlobalWindow::DispatchVRDisplayPresentChange(uint32_t aDisplayID)
} }
} }
// nsGlobalChromeWindow implementation /* static */ already_AddRefed<nsGlobalWindow>
nsGlobalWindow::CreateChrome(nsGlobalWindow *aOuterWindow)
NS_IMPL_CYCLE_COLLECTION_CLASS(nsGlobalChromeWindow)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(nsGlobalChromeWindow,
nsGlobalWindow)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mBrowserDOMWindow)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mMessageManager)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mGroupMessageManagers)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mOpenerForInitialContentBrowser)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(nsGlobalChromeWindow,
nsGlobalWindow)
NS_IMPL_CYCLE_COLLECTION_UNLINK(mBrowserDOMWindow)
if (tmp->mMessageManager) {
static_cast<nsFrameMessageManager*>(
tmp->mMessageManager.get())->Disconnect();
NS_IMPL_CYCLE_COLLECTION_UNLINK(mMessageManager)
}
tmp->DisconnectAndClearGroupMessageManagers();
NS_IMPL_CYCLE_COLLECTION_UNLINK(mGroupMessageManagers)
NS_IMPL_CYCLE_COLLECTION_UNLINK(mOpenerForInitialContentBrowser)
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
// QueryInterface implementation for nsGlobalChromeWindow
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsGlobalChromeWindow)
NS_INTERFACE_MAP_ENTRY(nsIDOMChromeWindow)
NS_INTERFACE_MAP_END_INHERITING(nsGlobalWindow)
NS_IMPL_ADDREF_INHERITED(nsGlobalChromeWindow, nsGlobalWindow)
NS_IMPL_RELEASE_INHERITED(nsGlobalChromeWindow, nsGlobalWindow)
/* static */ already_AddRefed<nsGlobalChromeWindow>
nsGlobalChromeWindow::Create(nsGlobalWindow *aOuterWindow)
{ {
RefPtr<nsGlobalChromeWindow> window = new nsGlobalChromeWindow(aOuterWindow); RefPtr<nsGlobalWindow> window = new nsGlobalWindow(aOuterWindow);
window->mIsChrome = true;
window->mCleanMessageManager = true;
window->InitWasOffline(); window->InitWasOffline();
return window.forget(); return window.forget();
} }
@ -14102,7 +14076,7 @@ nsGlobalWindow::IsFullyOccluded()
void void
nsGlobalWindow::Maximize() nsGlobalWindow::Maximize()
{ {
MOZ_ASSERT(IsInnerWindow()); MOZ_RELEASE_ASSERT(IsInnerWindow());
nsCOMPtr<nsIWidget> widget = GetMainWidget(); nsCOMPtr<nsIWidget> widget = GetMainWidget();
@ -14114,7 +14088,7 @@ nsGlobalWindow::Maximize()
void void
nsGlobalWindow::Minimize() nsGlobalWindow::Minimize()
{ {
MOZ_ASSERT(IsInnerWindow()); MOZ_RELEASE_ASSERT(IsInnerWindow());
nsCOMPtr<nsIWidget> widget = GetMainWidget(); nsCOMPtr<nsIWidget> widget = GetMainWidget();
@ -14126,7 +14100,7 @@ nsGlobalWindow::Minimize()
void void
nsGlobalWindow::Restore() nsGlobalWindow::Restore()
{ {
MOZ_ASSERT(IsInnerWindow()); MOZ_RELEASE_ASSERT(IsInnerWindow());
nsCOMPtr<nsIWidget> widget = GetMainWidget(); nsCOMPtr<nsIWidget> widget = GetMainWidget();
@ -14271,9 +14245,10 @@ nsGlobalWindow::SetCursor(const nsAString& aCursor, ErrorResult& aError)
} }
NS_IMETHODIMP NS_IMETHODIMP
nsGlobalChromeWindow::GetBrowserDOMWindow(nsIBrowserDOMWindow **aBrowserWindow) nsGlobalWindow::GetBrowserDOMWindow(nsIBrowserDOMWindow **aBrowserWindow)
{ {
FORWARD_TO_INNER_CHROME(GetBrowserDOMWindow, (aBrowserWindow), NS_ERROR_UNEXPECTED); MOZ_RELEASE_ASSERT(IsChromeWindow());
FORWARD_TO_INNER(GetBrowserDOMWindow, (aBrowserWindow), NS_ERROR_UNEXPECTED);
ErrorResult rv; ErrorResult rv;
NS_IF_ADDREF(*aBrowserWindow = GetBrowserDOMWindow(rv)); NS_IF_ADDREF(*aBrowserWindow = GetBrowserDOMWindow(rv));
@ -14285,7 +14260,7 @@ nsGlobalWindow::GetBrowserDOMWindowOuter()
{ {
MOZ_RELEASE_ASSERT(IsOuterWindow()); MOZ_RELEASE_ASSERT(IsOuterWindow());
MOZ_ASSERT(IsChromeWindow()); MOZ_ASSERT(IsChromeWindow());
return static_cast<nsGlobalChromeWindow*>(this)->mBrowserDOMWindow; return mChromeFields.mBrowserDOMWindow;
} }
nsIBrowserDOMWindow* nsIBrowserDOMWindow*
@ -14299,7 +14274,7 @@ nsGlobalWindow::SetBrowserDOMWindowOuter(nsIBrowserDOMWindow* aBrowserWindow)
{ {
MOZ_RELEASE_ASSERT(IsOuterWindow()); MOZ_RELEASE_ASSERT(IsOuterWindow());
MOZ_ASSERT(IsChromeWindow()); MOZ_ASSERT(IsChromeWindow());
static_cast<nsGlobalChromeWindow*>(this)->mBrowserDOMWindow = aBrowserWindow; mChromeFields.mBrowserDOMWindow = aBrowserWindow;
} }
void void
@ -14359,9 +14334,9 @@ nsGlobalWindow::NotifyDefaultButtonLoaded(Element& aDefaultButton,
} }
NS_IMETHODIMP NS_IMETHODIMP
nsGlobalChromeWindow::GetMessageManager(nsIMessageBroadcaster** aManager) nsGlobalWindow::GetMessageManager(nsIMessageBroadcaster** aManager)
{ {
FORWARD_TO_INNER_CHROME(GetMessageManager, (aManager), NS_ERROR_UNEXPECTED); FORWARD_TO_INNER(GetMessageManager, (aManager), NS_ERROR_UNEXPECTED);
ErrorResult rv; ErrorResult rv;
NS_IF_ADDREF(*aManager = GetMessageManager(rv)); NS_IF_ADDREF(*aManager = GetMessageManager(rv));
@ -14373,23 +14348,23 @@ nsGlobalWindow::GetMessageManager(ErrorResult& aError)
{ {
MOZ_ASSERT(IsChromeWindow()); MOZ_ASSERT(IsChromeWindow());
MOZ_RELEASE_ASSERT(IsInnerWindow()); MOZ_RELEASE_ASSERT(IsInnerWindow());
nsGlobalChromeWindow* myself = static_cast<nsGlobalChromeWindow*>(this); if (!mChromeFields.mMessageManager) {
if (!myself->mMessageManager) {
nsCOMPtr<nsIMessageBroadcaster> globalMM = nsCOMPtr<nsIMessageBroadcaster> globalMM =
do_GetService("@mozilla.org/globalmessagemanager;1"); do_GetService("@mozilla.org/globalmessagemanager;1");
myself->mMessageManager = mChromeFields.mMessageManager =
new nsFrameMessageManager(nullptr, new nsFrameMessageManager(nullptr,
static_cast<nsFrameMessageManager*>(globalMM.get()), static_cast<nsFrameMessageManager*>(globalMM.get()),
MM_CHROME | MM_BROADCASTER); MM_CHROME | MM_BROADCASTER);
} }
return myself->mMessageManager; return mChromeFields.mMessageManager;
} }
NS_IMETHODIMP NS_IMETHODIMP
nsGlobalChromeWindow::GetGroupMessageManager(const nsAString& aGroup, nsGlobalWindow::GetGroupMessageManager(const nsAString& aGroup,
nsIMessageBroadcaster** aManager) nsIMessageBroadcaster** aManager)
{ {
FORWARD_TO_INNER_CHROME(GetGroupMessageManager, (aGroup, aManager), NS_ERROR_UNEXPECTED); MOZ_RELEASE_ASSERT(IsChromeWindow());
FORWARD_TO_INNER(GetGroupMessageManager, (aGroup, aManager), NS_ERROR_UNEXPECTED);
ErrorResult rv; ErrorResult rv;
NS_IF_ADDREF(*aManager = GetGroupMessageManager(aGroup, rv)); NS_IF_ADDREF(*aManager = GetGroupMessageManager(aGroup, rv));
@ -14403,9 +14378,8 @@ nsGlobalWindow::GetGroupMessageManager(const nsAString& aGroup,
MOZ_ASSERT(IsChromeWindow()); MOZ_ASSERT(IsChromeWindow());
MOZ_RELEASE_ASSERT(IsInnerWindow()); MOZ_RELEASE_ASSERT(IsInnerWindow());
nsGlobalChromeWindow* myself = static_cast<nsGlobalChromeWindow*>(this);
nsCOMPtr<nsIMessageBroadcaster> messageManager = nsCOMPtr<nsIMessageBroadcaster> messageManager =
myself->mGroupMessageManagers.LookupForAdd(aGroup).OrInsert( mChromeFields.mGroupMessageManagers.LookupForAdd(aGroup).OrInsert(
[this, &aError] () { [this, &aError] () {
nsFrameMessageManager* parent = nsFrameMessageManager* parent =
static_cast<nsFrameMessageManager*>(GetMessageManager(aError)); static_cast<nsFrameMessageManager*>(GetMessageManager(aError));
@ -14418,20 +14392,22 @@ nsGlobalWindow::GetGroupMessageManager(const nsAString& aGroup,
} }
nsresult nsresult
nsGlobalChromeWindow::SetOpenerForInitialContentBrowser(mozIDOMWindowProxy* aOpenerWindow) nsGlobalWindow::SetOpenerForInitialContentBrowser(mozIDOMWindowProxy* aOpenerWindow)
{ {
MOZ_RELEASE_ASSERT(IsChromeWindow());
MOZ_RELEASE_ASSERT(IsOuterWindow()); MOZ_RELEASE_ASSERT(IsOuterWindow());
MOZ_ASSERT(!mOpenerForInitialContentBrowser); MOZ_ASSERT(!mChromeFields.mOpenerForInitialContentBrowser);
mOpenerForInitialContentBrowser = aOpenerWindow; mChromeFields.mOpenerForInitialContentBrowser = aOpenerWindow;
return NS_OK; return NS_OK;
} }
nsresult nsresult
nsGlobalChromeWindow::TakeOpenerForInitialContentBrowser(mozIDOMWindowProxy** aOpenerWindow) nsGlobalWindow::TakeOpenerForInitialContentBrowser(mozIDOMWindowProxy** aOpenerWindow)
{ {
MOZ_RELEASE_ASSERT(IsChromeWindow());
MOZ_RELEASE_ASSERT(IsOuterWindow()); MOZ_RELEASE_ASSERT(IsOuterWindow());
// Intentionally forget our own member // Intentionally forget our own member
mOpenerForInitialContentBrowser.forget(aOpenerWindow); mChromeFields.mOpenerForInitialContentBrowser.forget(aOpenerWindow);
return NS_OK; return NS_OK;
} }

View file

@ -260,6 +260,9 @@ private:
class nsGlobalWindow : public mozilla::dom::EventTarget, class nsGlobalWindow : public mozilla::dom::EventTarget,
public nsPIDOMWindow<nsISupports>, public nsPIDOMWindow<nsISupports>,
private nsIDOMWindow, private nsIDOMWindow,
// NOTE: This interface is private, as it's only
// implemented on chrome windows.
private nsIDOMChromeWindow,
public nsIScriptGlobalObject, public nsIScriptGlobalObject,
public nsIScriptObjectPrincipal, public nsIScriptObjectPrincipal,
public nsSupportsWeakReference, public nsSupportsWeakReference,
@ -342,6 +345,9 @@ public:
// nsIDOMWindow // nsIDOMWindow
NS_DECL_NSIDOMWINDOW NS_DECL_NSIDOMWINDOW
// nsIDOMChromeWindow (only implemented on chrome windows)
NS_DECL_NSIDOMCHROMEWINDOW
nsresult nsresult
OpenJS(const nsAString& aUrl, const nsAString& aName, OpenJS(const nsAString& aUrl, const nsAString& aName,
const nsAString& aOptions, nsPIDOMWindowOuter **_retval); const nsAString& aOptions, nsPIDOMWindowOuter **_retval);
@ -486,6 +492,7 @@ public:
// Object Management // Object Management
static already_AddRefed<nsGlobalWindow> Create(nsGlobalWindow *aOuterWindow); static already_AddRefed<nsGlobalWindow> Create(nsGlobalWindow *aOuterWindow);
static already_AddRefed<nsGlobalWindow> CreateChrome(nsGlobalWindow *aOuterWindow);
static nsGlobalWindow *FromSupports(nsISupports *supports) static nsGlobalWindow *FromSupports(nsISupports *supports)
{ {
@ -1251,7 +1258,7 @@ public:
// ChromeWindow bits. Do NOT call these unless your window is in // ChromeWindow bits. Do NOT call these unless your window is in
// fact an nsGlobalChromeWindow. // fact chrome.
uint16_t WindowState(); uint16_t WindowState();
bool IsFullyOccluded(); bool IsFullyOccluded();
nsIBrowserDOMWindow* GetBrowserDOMWindowOuter(); nsIBrowserDOMWindow* GetBrowserDOMWindowOuter();
@ -1783,6 +1790,19 @@ private:
void SetIsBackgroundInternal(bool aIsBackground); void SetIsBackgroundInternal(bool aIsBackground);
// NOTE: Chrome Only
void DisconnectAndClearGroupMessageManagers()
{
MOZ_RELEASE_ASSERT(IsChromeWindow());
for (auto iter = mChromeFields.mGroupMessageManagers.Iter(); !iter.Done(); iter.Next()) {
nsIMessageBroadcaster* mm = iter.UserData();
if (mm) {
static_cast<nsFrameMessageManager*>(mm)->Disconnect();
}
}
mChromeFields.mGroupMessageManagers.Clear();
}
public: public:
// Dispatch a runnable related to the global. // Dispatch a runnable related to the global.
virtual nsresult Dispatch(mozilla::TaskCategory aCategory, virtual nsresult Dispatch(mozilla::TaskCategory aCategory,
@ -2025,6 +2045,23 @@ protected:
RefPtr<mozilla::dom::IntlUtils> mIntlUtils; RefPtr<mozilla::dom::IntlUtils> mIntlUtils;
// Members in the mChromeFields member should only be used in chrome windows.
// All accesses to this field should be guarded by a check of mIsChrome.
struct ChromeFields {
ChromeFields()
: mGroupMessageManagers(1)
{}
nsCOMPtr<nsIBrowserDOMWindow> mBrowserDOMWindow;
nsCOMPtr<nsIMessageBroadcaster> mMessageManager;
nsInterfaceHashtable<nsStringHashKey, nsIMessageBroadcaster> mGroupMessageManagers;
// A weak pointer to the nsPresShell that we are doing fullscreen for.
// The pointer being set indicates we've set the IsInFullscreenChange
// flag on this pres shell.
nsWeakPtr mFullscreenPresShell;
nsCOMPtr<mozIDOMWindowProxy> mOpenerForInitialContentBrowser;
} mChromeFields;
friend class nsDOMScriptableHelper; friend class nsDOMScriptableHelper;
friend class nsDOMWindowUtils; friend class nsDOMWindowUtils;
friend class mozilla::dom::PostMessageEvent; friend class mozilla::dom::PostMessageEvent;
@ -2047,84 +2084,6 @@ ToCanonicalSupports(nsGlobalWindow *p)
return static_cast<nsIDOMEventTarget*>(p); return static_cast<nsIDOMEventTarget*>(p);
} }
/*
* nsGlobalChromeWindow inherits from nsGlobalWindow. It is the global
* object created for a Chrome Window only.
*/
class nsGlobalChromeWindow : public nsGlobalWindow,
public nsIDOMChromeWindow
{
public:
// nsISupports
NS_DECL_ISUPPORTS_INHERITED
// nsIDOMChromeWindow interface
NS_DECL_NSIDOMCHROMEWINDOW
static already_AddRefed<nsGlobalChromeWindow> Create(nsGlobalWindow *aOuterWindow);
void DisconnectAndClearGroupMessageManagers()
{
for (auto iter = mGroupMessageManagers.Iter(); !iter.Done(); iter.Next()) {
nsIMessageBroadcaster* mm = iter.UserData();
if (mm) {
static_cast<nsFrameMessageManager*>(mm)->Disconnect();
}
}
mGroupMessageManagers.Clear();
}
protected:
explicit nsGlobalChromeWindow(nsGlobalWindow *aOuterWindow)
: nsGlobalWindow(aOuterWindow),
mGroupMessageManagers(1)
{
mIsChrome = true;
mCleanMessageManager = true;
}
~nsGlobalChromeWindow()
{
MOZ_ASSERT(mCleanMessageManager,
"chrome windows may always disconnect the msg manager");
DisconnectAndClearGroupMessageManagers();
if (mMessageManager) {
static_cast<nsFrameMessageManager *>(
mMessageManager.get())->Disconnect();
}
mCleanMessageManager = false;
}
public:
NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(nsGlobalChromeWindow,
nsGlobalWindow)
using nsGlobalWindow::GetBrowserDOMWindow;
using nsGlobalWindow::SetBrowserDOMWindow;
using nsGlobalWindow::GetAttention;
using nsGlobalWindow::GetAttentionWithCycleCount;
using nsGlobalWindow::SetCursor;
using nsGlobalWindow::Maximize;
using nsGlobalWindow::Minimize;
using nsGlobalWindow::Restore;
using nsGlobalWindow::NotifyDefaultButtonLoaded;
using nsGlobalWindow::GetMessageManager;
using nsGlobalWindow::GetGroupMessageManager;
using nsGlobalWindow::BeginWindowMove;
nsCOMPtr<nsIBrowserDOMWindow> mBrowserDOMWindow;
nsCOMPtr<nsIMessageBroadcaster> mMessageManager;
nsInterfaceHashtable<nsStringHashKey, nsIMessageBroadcaster> mGroupMessageManagers;
// A weak pointer to the nsPresShell that we are doing fullscreen for.
// The pointer being set indicates we've set the IsInFullscreenChange
// flag on this pres shell.
nsWeakPtr mFullscreenPresShell;
nsCOMPtr<mozIDOMWindowProxy> mOpenerForInitialContentBrowser;
};
/* factory function */ /* factory function */
inline already_AddRefed<nsGlobalWindow> inline already_AddRefed<nsGlobalWindow>
NS_NewScriptGlobalObject(bool aIsChrome) NS_NewScriptGlobalObject(bool aIsChrome)
@ -2132,7 +2091,7 @@ NS_NewScriptGlobalObject(bool aIsChrome)
RefPtr<nsGlobalWindow> global; RefPtr<nsGlobalWindow> global;
if (aIsChrome) { if (aIsChrome) {
global = nsGlobalChromeWindow::Create(nullptr); global = nsGlobalWindow::CreateChrome(nullptr);
} else { } else {
global = nsGlobalWindow::Create(nullptr); global = nsGlobalWindow::Create(nullptr);
} }

View file

@ -2742,8 +2742,8 @@ public:
enum ElementCallbackType { enum ElementCallbackType {
eCreated, eCreated,
eAttached, eConnected,
eDetached, eDisconnected,
eAttributeChanged eAttributeChanged
}; };

View file

@ -1018,8 +1018,6 @@ nsImageLoadingContent::LoadImage(nsIURI* aNewURI,
"Principal mismatch?"); "Principal mismatch?");
#endif #endif
nsContentPolicyType policyType = PolicyTypeForLoad(aImageLoadType);
nsLoadFlags loadFlags = aLoadFlags; nsLoadFlags loadFlags = aLoadFlags;
int32_t corsmode = GetCORSMode(); int32_t corsmode = GetCORSMode();
if (corsmode == CORS_ANONYMOUS) { if (corsmode == CORS_ANONYMOUS) {
@ -1040,12 +1038,24 @@ nsImageLoadingContent::LoadImage(nsIURI* aNewURI,
RefPtr<imgRequestProxy>& req = PrepareNextRequest(aImageLoadType); RefPtr<imgRequestProxy>& req = PrepareNextRequest(aImageLoadType);
nsCOMPtr<nsIContent> content = nsCOMPtr<nsIContent> content =
do_QueryInterface(static_cast<nsIImageLoadingContent*>(this)); do_QueryInterface(static_cast<nsIImageLoadingContent*>(this));
nsCOMPtr<nsIPrincipal> loadingPrincipal;
bool result =
nsContentUtils::GetLoadingPrincipalForXULNode(content,
getter_AddRefs(loadingPrincipal));
// If result is true, which means this node has specified 'loadingprincipal'
// attribute on it, so we use favicon as the policy type.
nsContentPolicyType policyType = result ?
nsIContentPolicy::TYPE_INTERNAL_IMAGE_FAVICON:
PolicyTypeForLoad(aImageLoadType);
nsCOMPtr<nsINode> thisNode = nsCOMPtr<nsINode> thisNode =
do_QueryInterface(static_cast<nsIImageLoadingContent*>(this)); do_QueryInterface(static_cast<nsIImageLoadingContent*>(this));
nsresult rv = nsContentUtils::LoadImage(aNewURI, nsresult rv = nsContentUtils::LoadImage(aNewURI,
thisNode, thisNode,
aDocument, aDocument,
aDocument->NodePrincipal(), loadingPrincipal,
0, 0,
aDocument->GetDocumentURI(), aDocument->GetDocumentURI(),
referrerPolicy, referrerPolicy,

View file

@ -2732,8 +2732,7 @@ class AttrDefiner(PropertyDefiner):
def flags(attr): def flags(attr):
unforgeable = " | JSPROP_PERMANENT" if self.unforgeable else "" unforgeable = " | JSPROP_PERMANENT" if self.unforgeable else ""
enumerable = " | %s" % EnumerabilityFlags(attr) return EnumerabilityFlags(attr) + unforgeable
return ("JSPROP_SHARED" + enumerable + unforgeable)
def getter(attr): def getter(attr):
if self.static: if self.static:

View file

@ -2399,7 +2399,6 @@ WebGLContext::StartVRPresentation()
gl::GLScreenBuffer::CreateFactory(gl, gl::GLScreenBuffer::CreateFactory(gl,
caps, caps,
vrmc, vrmc,
vrmc->GetBackendType(),
TextureFlags::ORIGIN_BOTTOM_LEFT); TextureFlags::ORIGIN_BOTTOM_LEFT);
if (factory) { if (factory) {

View file

@ -1660,7 +1660,7 @@ Console::PopulateConsoleNotificationInTheTargetScope(JSContext* aCx,
if (NS_WARN_IF(!JS_DefineProperty(aCx, eventObj, "stacktrace", if (NS_WARN_IF(!JS_DefineProperty(aCx, eventObj, "stacktrace",
JS_DATA_TO_FUNC_PTR(JSNative, funObj.get()), JS_DATA_TO_FUNC_PTR(JSNative, funObj.get()),
nullptr, nullptr,
JSPROP_ENUMERATE | JSPROP_SHARED | JSPROP_ENUMERATE |
JSPROP_GETTER | JSPROP_SETTER))) { JSPROP_GETTER | JSPROP_SETTER))) {
return false; return false;
} }

View file

@ -10,6 +10,7 @@
#include "mozilla/EventListenerManager.h" #include "mozilla/EventListenerManager.h"
#include "mozilla/JSEventHandler.h" #include "mozilla/JSEventHandler.h"
#include "mozilla/Maybe.h" #include "mozilla/Maybe.h"
#include "nsArrayUtils.h"
#include "nsCOMArray.h" #include "nsCOMArray.h"
#include "nsDOMClassInfoID.h" #include "nsDOMClassInfoID.h"
#include "nsIXPConnect.h" #include "nsIXPConnect.h"
@ -54,10 +55,28 @@ EventListenerChange::GetTarget(nsIDOMEventTarget** aTarget)
} }
NS_IMETHODIMP NS_IMETHODIMP
EventListenerChange::GetChangedListenerNames(nsIArray** aEventNames) EventListenerChange::GetCountOfEventListenerChangesAffectingAccessibility(
uint32_t* aCount)
{ {
NS_ENSURE_ARG_POINTER(aEventNames); *aCount = 0;
NS_ADDREF(*aEventNames = mChangedListenerNames);
uint32_t length;
nsresult rv = mChangedListenerNames->GetLength(&length);
NS_ENSURE_SUCCESS(rv, rv);
for (size_t i = 0; i < length; i++) {
nsCOMPtr<nsIAtom> listenerName =
do_QueryElementAt(mChangedListenerNames, i);
// These are the event listener changes which may make an element
// accessible or inaccessible.
if (listenerName == nsGkAtoms::onclick ||
listenerName == nsGkAtoms::onmousedown ||
listenerName == nsGkAtoms::onmouseup) {
*aCount += 1;
}
}
return NS_OK; return NS_OK;
} }

View file

@ -10,14 +10,16 @@ interface nsIDOMEventTarget;
interface nsIArray; interface nsIArray;
/** /**
* Contains an event target along with an array of nsIAtom in form "oneventname" * Contains an event target along with a count of event listener changes
* representing changed event listener names. * affecting accessibility.
*/ */
[scriptable, uuid(07222b02-da12-4cf4-b2f7-761da007a8d8)] [scriptable, uuid(07222b02-da12-4cf4-b2f7-761da007a8d8)]
interface nsIEventListenerChange : nsISupports interface nsIEventListenerChange : nsISupports
{ {
readonly attribute nsIDOMEventTarget target; readonly attribute nsIDOMEventTarget target;
[noscript] readonly attribute nsIArray changedListenerNames;
[noscript]
readonly attribute uint32_t countOfEventListenerChangesAffectingAccessibility;
}; };
[scriptable, function, uuid(aa7c95f6-d3b5-44b3-9597-1d9f19b9c5f2)] [scriptable, function, uuid(aa7c95f6-d3b5-44b3-9597-1d9f19b9c5f2)]

View file

@ -472,7 +472,7 @@ FetchBodyConsumer<Derived>::BeginConsumeBodyMainThread()
nsCOMPtr<nsIInputStreamPump> pump; nsCOMPtr<nsIInputStreamPump> pump;
nsresult rv = NS_NewInputStreamPump(getter_AddRefs(pump), nsresult rv = NS_NewInputStreamPump(getter_AddRefs(pump),
mBodyStream, -1, -1, 0, 0, false, mBodyStream, 0, 0, false,
mMainThreadEventTarget); mMainThreadEventTarget);
if (NS_WARN_IF(NS_FAILED(rv))) { if (NS_WARN_IF(NS_FAILED(rv))) {
return; return;

View file

@ -224,8 +224,6 @@ FetchStream::RequestDataCallback(JSContext* aCx,
nsCOMPtr<nsITransport> transport; nsCOMPtr<nsITransport> transport;
rv = sts->CreateInputTransport(stream->mOriginalInputStream, rv = sts->CreateInputTransport(stream->mOriginalInputStream,
/* aStartOffset */ 0,
/* aReadLimit */ -1,
/* aCloseWhenDone */ true, /* aCloseWhenDone */ true,
getter_AddRefs(transport)); getter_AddRefs(transport));
if (NS_WARN_IF(NS_FAILED(rv))) { if (NS_WARN_IF(NS_FAILED(rv))) {

View file

@ -400,8 +400,6 @@ FileReader::ReadFileContent(Blob& aBlob,
nsCOMPtr<nsITransport> transport; nsCOMPtr<nsITransport> transport;
aRv = sts->CreateInputTransport(stream, aRv = sts->CreateInputTransport(stream,
/* aStartOffset */ 0,
/* aReadLimit */ -1,
/* aCloseWhenDone */ true, /* aCloseWhenDone */ true,
getter_AddRefs(transport)); getter_AddRefs(transport));
if (NS_WARN_IF(aRv.Failed())) { if (NS_WARN_IF(aRv.Failed())) {

View file

@ -651,8 +651,6 @@ IPCBlobInputStream::EnsureAsyncRemoteStream()
nsCOMPtr<nsITransport> transport; nsCOMPtr<nsITransport> transport;
rv = sts->CreateInputTransport(mRemoteStream, rv = sts->CreateInputTransport(mRemoteStream,
/* aStartOffset */ 0,
/* aReadLimit */ -1,
/* aCloseWhenDone */ true, /* aCloseWhenDone */ true,
getter_AddRefs(transport)); getter_AddRefs(transport));
if (NS_WARN_IF(NS_FAILED(rv))) { if (NS_WARN_IF(NS_FAILED(rv))) {

View file

@ -1191,19 +1191,31 @@ public:
? nsIContentPolicy::TYPE_INTERNAL_AUDIO : ? nsIContentPolicy::TYPE_INTERNAL_AUDIO :
nsIContentPolicy::TYPE_INTERNAL_VIDEO; nsIContentPolicy::TYPE_INTERNAL_VIDEO;
// If aElement has 'loadingprincipal' attribute, we will use the value as
// loadingPrincipal for the channel, otherwise it will default to use
// aElement->NodePrincipal().
// This function returns true when aElement has 'loadingprincipal', so if
// setAttrs is true we will override the origin attributes on the channel
// later.
nsCOMPtr<nsIPrincipal> loadingPrincipal;
bool setAttrs = nsContentUtils::GetLoadingPrincipalForXULNode(aElement,
getter_AddRefs(loadingPrincipal));
nsCOMPtr<nsILoadGroup> loadGroup = aElement->GetDocumentLoadGroup(); nsCOMPtr<nsILoadGroup> loadGroup = aElement->GetDocumentLoadGroup();
nsCOMPtr<nsIChannel> channel; nsCOMPtr<nsIChannel> channel;
nsresult rv = NS_NewChannel(getter_AddRefs(channel), nsresult rv =
aElement->mLoadingSrc, NS_NewChannelWithTriggeringPrincipal(getter_AddRefs(channel),
static_cast<Element*>(aElement), aElement->mLoadingSrc,
securityFlags, static_cast<Element*>(aElement),
contentPolicyType, loadingPrincipal,
loadGroup, securityFlags,
nullptr, // aCallbacks contentPolicyType,
nsICachingChannel::LOAD_BYPASS_LOCAL_CACHE_IF_BUSY | loadGroup,
nsIChannel::LOAD_MEDIA_SNIFFER_OVERRIDES_CONTENT_TYPE | nullptr, // aCallbacks
nsIChannel::LOAD_CLASSIFY_URI | nsICachingChannel::LOAD_BYPASS_LOCAL_CACHE_IF_BUSY |
nsIChannel::LOAD_CALL_CONTENT_SNIFFERS); nsIChannel::LOAD_MEDIA_SNIFFER_OVERRIDES_CONTENT_TYPE |
nsIChannel::LOAD_CLASSIFY_URI |
nsIChannel::LOAD_CALL_CONTENT_SNIFFERS);
if (NS_FAILED(rv)) { if (NS_FAILED(rv)) {
// Notify load error so the element will try next resource candidate. // Notify load error so the element will try next resource candidate.
@ -1211,6 +1223,14 @@ public:
return; return;
} }
if (setAttrs) {
nsCOMPtr<nsILoadInfo> loadInfo = channel->GetLoadInfo();
if (loadInfo) {
// The function simply returns NS_OK, so we ignore the return value.
Unused << loadInfo->SetOriginAttributes(loadingPrincipal->OriginAttributesRef());
}
}
nsCOMPtr<nsIClassOfService> cos(do_QueryInterface(channel)); nsCOMPtr<nsIClassOfService> cos(do_QueryInterface(channel));
if (cos) { if (cos) {
if (aElement->mUseUrgentStartForChannel) { if (aElement->mUseUrgentStartForChannel) {

View file

@ -317,7 +317,7 @@ nsGenericHTMLElement::GetOffsetRect(CSSIntRect& aRect)
// Add the parent's origin to our own to get to the // Add the parent's origin to our own to get to the
// right coordinate system. // right coordinate system.
const bool isOffsetParent = !isPositioned && IsOffsetParent(parent); const bool isOffsetParent = !isPositioned && IsOffsetParent(parent);
if (!isAbsolutelyPositioned && !isOffsetParent) { if (!isOffsetParent) {
origin += parent->GetPositionIgnoringScrolling(); origin += parent->GetPositionIgnoringScrolling();
} }

View file

@ -88,8 +88,10 @@
#include "nsIXULRuntime.h" #include "nsIXULRuntime.h"
#include "nsPIDOMWindow.h" #include "nsPIDOMWindow.h"
#include "nsPIWindowRoot.h" #include "nsPIWindowRoot.h"
#include "nsPointerHashKeys.h"
#include "nsLayoutUtils.h" #include "nsLayoutUtils.h"
#include "nsPrintfCString.h" #include "nsPrintfCString.h"
#include "nsTHashtable.h"
#include "nsThreadManager.h" #include "nsThreadManager.h"
#include "nsThreadUtils.h" #include "nsThreadUtils.h"
#include "nsViewManager.h" #include "nsViewManager.h"
@ -164,7 +166,7 @@ NS_IMPL_ISUPPORTS(TabChildSHistoryListener,
static const char BEFORE_FIRST_PAINT[] = "before-first-paint"; static const char BEFORE_FIRST_PAINT[] = "before-first-paint";
nsTArray<TabChild*>* TabChild::sActiveTabs; nsTHashtable<nsPtrHashKey<TabChild>>* TabChild::sActiveTabs;
typedef nsDataHashtable<nsUint64HashKey, TabChild*> TabChildMap; typedef nsDataHashtable<nsUint64HashKey, TabChild*> TabChildMap;
static TabChildMap* sTabChildren; static TabChildMap* sTabChildren;
@ -1120,7 +1122,7 @@ TabChild::ActorDestroy(ActorDestroyReason why)
TabChild::~TabChild() TabChild::~TabChild()
{ {
if (sActiveTabs) { if (sActiveTabs) {
sActiveTabs->RemoveElement(this); sActiveTabs->RemoveEntry(this);
if (sActiveTabs->IsEmpty()) { if (sActiveTabs->IsEmpty()) {
delete sActiveTabs; delete sActiveTabs;
sActiveTabs = nullptr; sActiveTabs = nullptr;
@ -2589,12 +2591,12 @@ TabChild::InternalSetDocShellIsActive(bool aIsActive, bool aPreserveLayers)
if (aIsActive) { if (aIsActive) {
if (!sActiveTabs) { if (!sActiveTabs) {
sActiveTabs = new nsTArray<TabChild*>(); sActiveTabs = new nsTHashtable<nsPtrHashKey<TabChild>>();
} }
sActiveTabs->AppendElement(this); sActiveTabs->PutEntry(this);
} else { } else {
if (sActiveTabs) { if (sActiveTabs) {
sActiveTabs->RemoveElement(this); sActiveTabs->RemoveEntry(this);
// We don't delete sActiveTabs here when it's empty since that // We don't delete sActiveTabs here when it's empty since that
// could cause a lot of churn. Instead, we wait until ~TabChild. // could cause a lot of churn. Instead, we wait until ~TabChild.
} }

View file

@ -48,6 +48,9 @@ class nsIDOMWindowUtils;
class nsIHttpChannel; class nsIHttpChannel;
class nsISerialEventTarget; class nsISerialEventTarget;
template<typename T> class nsTHashtable;
template<typename T> class nsPtrHashKey;
namespace mozilla { namespace mozilla {
class AbstractThread; class AbstractThread;
namespace layout { namespace layout {
@ -762,7 +765,7 @@ public:
// open. There can also be zero foreground TabChilds if the foreground tab is // open. There can also be zero foreground TabChilds if the foreground tab is
// in a different content process. Note that this function should only be // in a different content process. Note that this function should only be
// called if HasActiveTabs() returns true. // called if HasActiveTabs() returns true.
static const nsTArray<TabChild*>& GetActiveTabs() static const nsTHashtable<nsPtrHashKey<TabChild>>& GetActiveTabs()
{ {
MOZ_ASSERT(HasActiveTabs()); MOZ_ASSERT(HasActiveTabs());
return *sActiveTabs; return *sActiveTabs;
@ -964,7 +967,7 @@ private:
// the foreground). There may be more than one if there are multiple browser // the foreground). There may be more than one if there are multiple browser
// windows open. There may be none if this process does not host any // windows open. There may be none if this process does not host any
// foreground tabs. // foreground tabs.
static nsTArray<TabChild*>* sActiveTabs; static nsTHashtable<nsPtrHashKey<TabChild>>* sActiveTabs;
DISALLOW_EVIL_CONSTRUCTORS(TabChild); DISALLOW_EVIL_CONSTRUCTORS(TabChild);
}; };

View file

@ -750,16 +750,36 @@ ChannelMediaResource::RecreateChannel()
nsContentPolicyType contentPolicyType = element->IsHTMLElement(nsGkAtoms::audio) ? nsContentPolicyType contentPolicyType = element->IsHTMLElement(nsGkAtoms::audio) ?
nsIContentPolicy::TYPE_INTERNAL_AUDIO : nsIContentPolicy::TYPE_INTERNAL_VIDEO; nsIContentPolicy::TYPE_INTERNAL_AUDIO : nsIContentPolicy::TYPE_INTERNAL_VIDEO;
nsresult rv = NS_NewChannel(getter_AddRefs(mChannel), // If element has 'loadingprincipal' attribute, we will use the value as
mURI, // loadingPrincipal for the channel, otherwise it will default to use
element, // aElement->NodePrincipal().
securityFlags, // This function returns true when element has 'loadingprincipal', so if
contentPolicyType, // setAttrs is true we will override the origin attributes on the channel
loadGroup, // later.
nullptr, // aCallbacks nsCOMPtr<nsIPrincipal> loadingPrincipal;
loadFlags); bool setAttrs =
nsContentUtils::GetLoadingPrincipalForXULNode(element,
getter_AddRefs(loadingPrincipal));
nsresult rv = NS_NewChannelWithTriggeringPrincipal(getter_AddRefs(mChannel),
mURI,
element,
loadingPrincipal,
securityFlags,
contentPolicyType,
loadGroup,
nullptr, // aCallbacks
loadFlags);
NS_ENSURE_SUCCESS(rv, rv); NS_ENSURE_SUCCESS(rv, rv);
if (setAttrs) {
nsCOMPtr<nsILoadInfo> loadInfo = mChannel->GetLoadInfo();
if (loadInfo) {
// The function simply returns NS_OK, so we ignore the return value.
Unused << loadInfo->SetOriginAttributes(loadingPrincipal->OriginAttributesRef());
}
}
nsCOMPtr<nsIClassOfService> cos(do_QueryInterface(mChannel)); nsCOMPtr<nsIClassOfService> cos(do_QueryInterface(mChannel));
if (cos) { if (cos) {
// Unconditionally disable throttling since we want the media to fluently // Unconditionally disable throttling since we want the media to fluently

View file

@ -991,7 +991,7 @@ TCPSocket::CreateInputStreamPump()
mInputStreamPump = do_CreateInstance("@mozilla.org/network/input-stream-pump;1", &rv); mInputStreamPump = do_CreateInstance("@mozilla.org/network/input-stream-pump;1", &rv);
NS_ENSURE_SUCCESS(rv, rv); NS_ENSURE_SUCCESS(rv, rv);
rv = mInputStreamPump->Init(mSocketInputStream, -1, -1, 0, 0, false, nullptr); rv = mInputStreamPump->Init(mSocketInputStream, 0, 0, false, nullptr);
NS_ENSURE_SUCCESS(rv, rv); NS_ENSURE_SUCCESS(rv, rv);
uint64_t suspendCount = mSuspendCount; uint64_t suspendCount = mSuspendCount;

View file

@ -282,7 +282,7 @@ PresentationTCPSessionTransport::CreateInputStreamPump()
return rv; return rv;
} }
rv = mInputStreamPump->Init(mSocketInputStream, -1, -1, 0, 0, false, nullptr); rv = mInputStreamPump->Init(mSocketInputStream, 0, 0, false, nullptr);
if (NS_WARN_IF(NS_FAILED(rv))) { if (NS_WARN_IF(NS_FAILED(rv))) {
return rv; return rv;
} }

View file

@ -663,7 +663,7 @@ TCPControlChannel.prototype = {
this._direction); // jshint ignore:line this._direction); // jshint ignore:line
this._pump = Cc["@mozilla.org/network/input-stream-pump;1"]. this._pump = Cc["@mozilla.org/network/input-stream-pump;1"].
createInstance(Ci.nsIInputStreamPump); createInstance(Ci.nsIInputStreamPump);
this._pump.init(this._input, -1, -1, 0, 0, false); this._pump.init(this._input, 0, 0, false);
this._pump.asyncRead(this, null); this._pump.asyncRead(this, null);
this._stateMachine.onChannelReady(); this._stateMachine.onChannelReady();
}, },

View file

@ -54,7 +54,7 @@ function getInLAProc(aBrowser) {
async function largeAllocSuccessTests() { async function largeAllocSuccessTests() {
// I'm terrible and put this set of tests into a single file, so I need a longer timeout // I'm terrible and put this set of tests into a single file, so I need a longer timeout
requestLongerTimeout(2); requestLongerTimeout(4);
// Check if we are on win32 // Check if we are on win32
let isWin32 = /Windows/.test(navigator.userAgent) && !/x64/.test(navigator.userAgent); let isWin32 = /Windows/.test(navigator.userAgent) && !/x64/.test(navigator.userAgent);

View file

@ -16,7 +16,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=1102502
SimpleTest.waitForExplicitFinish(); SimpleTest.waitForExplicitFinish();
var attachedCallbackCount = 0; var connectedCallbackCount = 0;
var p = Object.create(HTMLElement.prototype); var p = Object.create(HTMLElement.prototype);
@ -24,12 +24,12 @@ p.createdCallback = function() {
ok(true, "createdCallback called."); ok(true, "createdCallback called.");
}; };
p.attachedCallback = function() { p.connectedCallback = function() {
ok(true, "attachedCallback should be called when the parser creates an element in the document."); ok(true, "connectedCallback should be called when the parser creates an element in the document.");
attachedCallbackCount++; connectedCallbackCount++;
// attachedCallback should be called twice, once for the element created for innerHTML and // connectedCallback should be called twice, once for the element created for innerHTML and
// once for the element created in this document. // once for the element created in this document.
if (attachedCallbackCount == 2) { if (connectedCallbackCount == 2) {
SimpleTest.finish(); SimpleTest.finish();
} }
} }

View file

@ -11,8 +11,8 @@
*/ */
callback LifecycleCreatedCallback = void(); callback LifecycleCreatedCallback = void();
callback LifecycleAttachedCallback = void(); callback LifecycleConnectedCallback = void();
callback LifecycleDetachedCallback = void(); callback LifecycleDisconnectedCallback = void();
callback LifecycleAttributeChangedCallback = void(DOMString attrName, callback LifecycleAttributeChangedCallback = void(DOMString attrName,
DOMString? oldValue, DOMString? oldValue,
DOMString? newValue, DOMString? newValue,
@ -20,8 +20,8 @@ callback LifecycleAttributeChangedCallback = void(DOMString attrName,
dictionary LifecycleCallbacks { dictionary LifecycleCallbacks {
LifecycleCreatedCallback? createdCallback; LifecycleCreatedCallback? createdCallback;
LifecycleAttachedCallback? attachedCallback; LifecycleConnectedCallback? connectedCallback;
LifecycleDetachedCallback? detachedCallback; LifecycleDisconnectedCallback? disconnectedCallback;
LifecycleAttributeChangedCallback? attributeChangedCallback; LifecycleAttributeChangedCallback? attributeChangedCallback;
}; };

View file

@ -1725,8 +1725,6 @@ CacheScriptLoader::ResolvedCallback(JSContext* aCx,
MOZ_ASSERT(!mPump); MOZ_ASSERT(!mPump);
rv = NS_NewInputStreamPump(getter_AddRefs(mPump), rv = NS_NewInputStreamPump(getter_AddRefs(mPump),
inputStream, inputStream,
-1, /* default streamPos */
-1, /* default streamLen */
0, /* default segsize */ 0, /* default segsize */
0, /* default segcount */ 0, /* default segcount */
false, /* default closeWhenDone */ false, /* default closeWhenDone */

View file

@ -1159,8 +1159,6 @@ CompareCache::ManageValueResult(JSContext* aCx, JS::Handle<JS::Value> aValue)
MOZ_ASSERT(!mPump); MOZ_ASSERT(!mPump);
rv = NS_NewInputStreamPump(getter_AddRefs(mPump), rv = NS_NewInputStreamPump(getter_AddRefs(mPump),
inputStream, inputStream,
-1, /* default streamPos */
-1, /* default streamLen */
0, /* default segsize */ 0, /* default segsize */
0, /* default segcount */ 0, /* default segcount */
false, /* default closeWhenDone */ false, /* default closeWhenDone */

View file

@ -45,7 +45,7 @@ public:
const char16_t* GetName() const { return mName; } const char16_t* GetName() const { return mName; }
unsigned AccessorAttributes() const { unsigned AccessorAttributes() const {
return JSPROP_SHARED | JSPROP_GETTER | JSPROP_SETTER | return JSPROP_GETTER | JSPROP_SETTER |
(mJSAttributes & (JSPROP_ENUMERATE | JSPROP_PERMANENT)); (mJSAttributes & (JSPROP_ENUMERATE | JSPROP_PERMANENT));
} }

View file

@ -213,7 +213,7 @@ nsXBLProtoImplProperty::CompileMember(AutoJSAPI& jsapi, const nsString& aClassSt
mGetter.SetJSFunction(getterObject); mGetter.SetJSFunction(getterObject);
if (mGetter.GetJSFunction() && NS_SUCCEEDED(rv)) { if (mGetter.GetJSFunction() && NS_SUCCEEDED(rv)) {
mJSAttributes |= JSPROP_GETTER | JSPROP_SHARED; mJSAttributes |= JSPROP_GETTER;
} }
if (NS_FAILED(rv)) { if (NS_FAILED(rv)) {
mGetter.SetJSFunction(nullptr); mGetter.SetJSFunction(nullptr);
@ -259,7 +259,7 @@ nsXBLProtoImplProperty::CompileMember(AutoJSAPI& jsapi, const nsString& aClassSt
mSetter.SetJSFunction(setterObject); mSetter.SetJSFunction(setterObject);
if (mSetter.GetJSFunction() && NS_SUCCEEDED(rv)) { if (mSetter.GetJSFunction() && NS_SUCCEEDED(rv)) {
mJSAttributes |= JSPROP_SETTER | JSPROP_SHARED; mJSAttributes |= JSPROP_SETTER;
} }
if (NS_FAILED(rv)) { if (NS_FAILED(rv)) {
mSetter.SetJSFunction(nullptr); mSetter.SetJSFunction(nullptr);
@ -308,7 +308,7 @@ nsXBLProtoImplProperty::Read(nsIObjectInputStream* aStream,
nsresult rv = XBL_DeserializeFunction(aStream, &getterObject); nsresult rv = XBL_DeserializeFunction(aStream, &getterObject);
NS_ENSURE_SUCCESS(rv, rv); NS_ENSURE_SUCCESS(rv, rv);
mJSAttributes |= JSPROP_GETTER | JSPROP_SHARED; mJSAttributes |= JSPROP_GETTER;
} }
mGetter.SetJSFunction(getterObject); mGetter.SetJSFunction(getterObject);
@ -318,7 +318,7 @@ nsXBLProtoImplProperty::Read(nsIObjectInputStream* aStream,
nsresult rv = XBL_DeserializeFunction(aStream, &setterObject); nsresult rv = XBL_DeserializeFunction(aStream, &setterObject);
NS_ENSURE_SUCCESS(rv, rv); NS_ENSURE_SUCCESS(rv, rv);
mJSAttributes |= JSPROP_SETTER | JSPROP_SHARED; mJSAttributes |= JSPROP_SETTER;
} }
mSetter.SetJSFunction(setterObject); mSetter.SetJSFunction(setterObject);

View file

@ -68,72 +68,63 @@ GLScreenBuffer::CreateFactory(GLContext* gl,
KnowsCompositor* compositorConnection, KnowsCompositor* compositorConnection,
const layers::TextureFlags& flags) const layers::TextureFlags& flags)
{ {
return CreateFactory(gl, caps, compositorConnection->GetTextureForwarder(), LayersIPCChannel* ipcChannel = compositorConnection->GetTextureForwarder();
compositorConnection->GetCompositorBackendType(), flags); const layers::LayersBackend backend = compositorConnection->GetCompositorBackendType();
} const bool useANGLE = compositorConnection->GetCompositorUseANGLE();
const bool useGl = !gfxPrefs::WebGLForceLayersReadback() &&
(backend == layers::LayersBackend::LAYERS_OPENGL ||
(backend == layers::LayersBackend::LAYERS_WR && !useANGLE));
const bool useD3D = !gfxPrefs::WebGLForceLayersReadback() &&
(backend == layers::LayersBackend::LAYERS_D3D11 ||
(backend == layers::LayersBackend::LAYERS_WR && useANGLE));
/* static */ UniquePtr<SurfaceFactory>
GLScreenBuffer::CreateFactory(GLContext* gl,
const SurfaceCaps& caps,
LayersIPCChannel* ipcChannel,
const mozilla::layers::LayersBackend backend,
const layers::TextureFlags& flags)
{
UniquePtr<SurfaceFactory> factory = nullptr; UniquePtr<SurfaceFactory> factory = nullptr;
if (!gfxPrefs::WebGLForceLayersReadback()) { if (useGl) {
switch (backend) {
case mozilla::layers::LayersBackend::LAYERS_OPENGL: {
#if defined(XP_MACOSX) #if defined(XP_MACOSX)
factory = SurfaceFactory_IOSurface::Create(gl, caps, ipcChannel, flags); factory = SurfaceFactory_IOSurface::Create(gl, caps, ipcChannel, flags);
#elif defined(GL_PROVIDER_GLX) #elif defined(GL_PROVIDER_GLX)
if (sGLXLibrary.UseTextureFromPixmap()) if (sGLXLibrary.UseTextureFromPixmap())
factory = SurfaceFactory_GLXDrawable::Create(gl, caps, ipcChannel, flags); factory = SurfaceFactory_GLXDrawable::Create(gl, caps, ipcChannel, flags);
#elif defined(MOZ_WIDGET_UIKIT) #elif defined(MOZ_WIDGET_UIKIT)
factory = MakeUnique<SurfaceFactory_GLTexture>(mGLContext, caps, ipcChannel, mFlags); factory = MakeUnique<SurfaceFactory_GLTexture>(mGLContext, caps, ipcChannel, mFlags);
#elif defined(MOZ_WIDGET_ANDROID) #elif defined(MOZ_WIDGET_ANDROID)
if (XRE_IsParentProcess() && !gfxPrefs::WebGLSurfaceTextureEnabled()) { if (XRE_IsParentProcess() && !gfxPrefs::WebGLSurfaceTextureEnabled()) {
factory = SurfaceFactory_EGLImage::Create(gl, caps, ipcChannel, flags); factory = SurfaceFactory_EGLImage::Create(gl, caps, ipcChannel, flags);
} else { } else {
factory = SurfaceFactory_SurfaceTexture::Create(gl, caps, ipcChannel, flags); factory = SurfaceFactory_SurfaceTexture::Create(gl, caps, ipcChannel, flags);
} }
#else #else
if (gl->GetContextType() == GLContextType::EGL) { if (gl->GetContextType() == GLContextType::EGL) {
if (XRE_IsParentProcess()) { if (XRE_IsParentProcess()) {
factory = SurfaceFactory_EGLImage::Create(gl, caps, ipcChannel, flags); factory = SurfaceFactory_EGLImage::Create(gl, caps, ipcChannel, flags);
}
}
#endif
break;
} }
case mozilla::layers::LayersBackend::LAYERS_D3D11: { }
#endif
} else if (useD3D) {
#ifdef XP_WIN #ifdef XP_WIN
// Enable surface sharing only if ANGLE and compositing devices // Enable surface sharing only if ANGLE and compositing devices
// are both WARP or both not WARP // are both WARP or both not WARP
gfx::DeviceManagerDx* dm = gfx::DeviceManagerDx::Get(); gfx::DeviceManagerDx* dm = gfx::DeviceManagerDx::Get();
if (gl->IsANGLE() && if (gl->IsANGLE() &&
(gl->IsWARP() == dm->IsWARP()) && (gl->IsWARP() == dm->IsWARP()) &&
dm->TextureSharingWorks()) dm->TextureSharingWorks())
{ {
factory = SurfaceFactory_ANGLEShareHandle::Create(gl, caps, ipcChannel, flags); factory = SurfaceFactory_ANGLEShareHandle::Create(gl, caps, ipcChannel, flags);
}
if (!factory && gfxPrefs::WebGLDXGLEnabled()) {
factory = SurfaceFactory_D3D11Interop::Create(gl, caps, ipcChannel, flags);
}
#endif
break;
}
default:
break;
} }
#ifdef GL_PROVIDER_GLX if (!factory && gfxPrefs::WebGLDXGLEnabled()) {
if (!factory && sGLXLibrary.UseTextureFromPixmap()) { factory = SurfaceFactory_D3D11Interop::Create(gl, caps, ipcChannel, flags);
factory = SurfaceFactory_GLXDrawable::Create(gl, caps, ipcChannel, flags);
} }
#endif #endif
} }
#ifdef GL_PROVIDER_GLX
if (!factory && sGLXLibrary.UseTextureFromPixmap()) {
factory = SurfaceFactory_GLXDrawable::Create(gl, caps, ipcChannel, flags);
}
#endif
return factory; return factory;
} }

View file

@ -140,12 +140,6 @@ public:
const SurfaceCaps& caps, const SurfaceCaps& caps,
layers::KnowsCompositor* compositorConnection, layers::KnowsCompositor* compositorConnection,
const layers::TextureFlags& flags); const layers::TextureFlags& flags);
static UniquePtr<SurfaceFactory>
CreateFactory(GLContext* gl,
const SurfaceCaps& caps,
layers::LayersIPCChannel* ipcChannel,
const mozilla::layers::LayersBackend backend,
const layers::TextureFlags& flags);
protected: protected:
GLContext* const mGL; // Owns us. GLContext* const mGL; // Owns us.

View file

@ -93,6 +93,11 @@ GPUParent::Init(base::ProcessId aParentPid,
nsDebugImpl::SetMultiprocessMode("GPU"); nsDebugImpl::SetMultiprocessMode("GPU");
// This must be sent before any IPDL message, which may hit sentinel
// errors due to parent and content processes having different
// versions.
GetIPCChannel()->SendBuildID();
#ifdef MOZ_CRASHREPORTER #ifdef MOZ_CRASHREPORTER
// Init crash reporter support. // Init crash reporter support.
CrashReporterClient::InitSingleton(this); CrashReporterClient::InitSingleton(this);

View file

@ -225,16 +225,13 @@ GPUProcessManager::EnsureProtocolsReady()
void void
GPUProcessManager::EnsureCompositorManagerChild() GPUProcessManager::EnsureCompositorManagerChild()
{ {
base::ProcessId gpuPid = EnsureGPUReady() bool gpuReady = EnsureGPUReady();
? mGPUChild->OtherPid() if (CompositorManagerChild::IsInitialized(mProcessToken)) {
: base::GetCurrentProcId();
if (CompositorManagerChild::IsInitialized(gpuPid)) {
return; return;
} }
if (!EnsureGPUReady()) { if (!gpuReady) {
CompositorManagerChild::InitSameProcess(AllocateNamespace()); CompositorManagerChild::InitSameProcess(AllocateNamespace(), mProcessToken);
return; return;
} }
@ -251,7 +248,8 @@ GPUProcessManager::EnsureCompositorManagerChild()
} }
mGPUChild->SendInitCompositorManager(Move(parentPipe)); mGPUChild->SendInitCompositorManager(Move(parentPipe));
CompositorManagerChild::Init(Move(childPipe), AllocateNamespace()); CompositorManagerChild::Init(Move(childPipe), AllocateNamespace(),
mProcessToken);
} }
void void
@ -523,7 +521,7 @@ GPUProcessManager::OnProcessUnexpectedShutdown(GPUProcessHost* aHost)
{ {
MOZ_ASSERT(mProcess && mProcess == aHost); MOZ_ASSERT(mProcess && mProcess == aHost);
CompositorManagerChild::OnGPUProcessLost(); CompositorManagerChild::OnGPUProcessLost(aHost->GetProcessToken());
DestroyProcess(); DestroyProcess();
if (mNumProcessAttempts > uint32_t(gfxPrefs::GPUProcessMaxRestarts())) { if (mNumProcessAttempts > uint32_t(gfxPrefs::GPUProcessMaxRestarts())) {

View file

@ -111,37 +111,34 @@ GPUVideoTextureHost::CreateRenderTexture(const wr::ExternalImageId& aExternalIma
mWrappedTextureHost->CreateRenderTexture(aExternalImageId); mWrappedTextureHost->CreateRenderTexture(aExternalImageId);
} }
void uint32_t
GPUVideoTextureHost::GetWRImageKeys(nsTArray<wr::ImageKey>& aImageKeys, GPUVideoTextureHost::NumSubTextures() const
const std::function<wr::ImageKey()>& aImageKeyAllocator)
{ {
MOZ_ASSERT(mWrappedTextureHost); MOZ_ASSERT(mWrappedTextureHost);
MOZ_ASSERT(aImageKeys.IsEmpty()); return mWrappedTextureHost->NumSubTextures();
mWrappedTextureHost->GetWRImageKeys(aImageKeys, aImageKeyAllocator);
} }
void void
GPUVideoTextureHost::AddWRImage(wr::ResourceUpdateQueue& aResources, GPUVideoTextureHost::PushResourceUpdates(wr::ResourceUpdateQueue& aResources,
Range<const wr::ImageKey>& aImageKeys, ResourceUpdateOp aOp,
const wr::ExternalImageId& aExtID) const Range<wr::ImageKey>& aImageKeys,
const wr::ExternalImageId& aExtID)
{ {
MOZ_ASSERT(mWrappedTextureHost); MOZ_ASSERT(mWrappedTextureHost);
mWrappedTextureHost->PushResourceUpdates(aResources, aOp, aImageKeys, aExtID);
mWrappedTextureHost->AddWRImage(aResources, aImageKeys, aExtID);
} }
void void
GPUVideoTextureHost::PushExternalImage(wr::DisplayListBuilder& aBuilder, GPUVideoTextureHost::PushDisplayItems(wr::DisplayListBuilder& aBuilder,
const wr::LayoutRect& aBounds, const wr::LayoutRect& aBounds,
const wr::LayoutRect& aClip, const wr::LayoutRect& aClip,
wr::ImageRendering aFilter, wr::ImageRendering aFilter,
Range<const wr::ImageKey>& aImageKeys) const Range<wr::ImageKey>& aImageKeys)
{ {
MOZ_ASSERT(mWrappedTextureHost); MOZ_ASSERT(mWrappedTextureHost);
MOZ_ASSERT(aImageKeys.length() > 0); MOZ_ASSERT(aImageKeys.length() > 0);
mWrappedTextureHost->PushExternalImage(aBuilder, mWrappedTextureHost->PushDisplayItems(aBuilder,
aBounds, aBounds,
aClip, aClip,
aFilter, aFilter,

View file

@ -48,18 +48,18 @@ public:
virtual void CreateRenderTexture(const wr::ExternalImageId& aExternalImageId) override; virtual void CreateRenderTexture(const wr::ExternalImageId& aExternalImageId) override;
virtual void GetWRImageKeys(nsTArray<wr::ImageKey>& aImageKeys, virtual uint32_t NumSubTextures() const override;
const std::function<wr::ImageKey()>& aImageKeyAllocator) override;
virtual void AddWRImage(wr::ResourceUpdateQueue& aResources, virtual void PushResourceUpdates(wr::ResourceUpdateQueue& aResources,
Range<const wr::ImageKey>& aImageKeys, ResourceUpdateOp aOp,
const wr::ExternalImageId& aExtID) override; const Range<wr::ImageKey>& aImageKeys,
const wr::ExternalImageId& aExtID) override;
virtual void PushExternalImage(wr::DisplayListBuilder& aBuilder, virtual void PushDisplayItems(wr::DisplayListBuilder& aBuilder,
const wr::LayoutRect& aBounds, const wr::LayoutRect& aBounds,
const wr::LayoutRect& aClip, const wr::LayoutRect& aClip,
wr::ImageRendering aFilter, wr::ImageRendering aFilter,
Range<const wr::ImageKey>& aImageKeys) override; const Range<wr::ImageKey>& aImageKeys) override;
protected: protected:
RefPtr<TextureHost> mWrappedTextureHost; RefPtr<TextureHost> mWrappedTextureHost;

View file

@ -566,67 +566,51 @@ BufferTextureHost::CreateRenderTexture(const wr::ExternalImageId& aExternalImage
wr::RenderThread::Get()->RegisterExternalImage(wr::AsUint64(aExternalImageId), texture.forget()); wr::RenderThread::Get()->RegisterExternalImage(wr::AsUint64(aExternalImageId), texture.forget());
} }
void uint32_t
BufferTextureHost::GetWRImageKeys(nsTArray<wr::ImageKey>& aImageKeys, BufferTextureHost::NumSubTextures() const
const std::function<wr::ImageKey()>& aImageKeyAllocator)
{ {
MOZ_ASSERT(aImageKeys.IsEmpty()); if (GetFormat() == gfx::SurfaceFormat::YUV) {
return 3;
if (GetFormat() != gfx::SurfaceFormat::YUV) {
// 1 image key
aImageKeys.AppendElement(aImageKeyAllocator());
MOZ_ASSERT(aImageKeys.Length() == 1);
} else {
// 3 image key
aImageKeys.AppendElement(aImageKeyAllocator());
aImageKeys.AppendElement(aImageKeyAllocator());
aImageKeys.AppendElement(aImageKeyAllocator());
MOZ_ASSERT(aImageKeys.Length() == 3);
} }
return 1;
} }
void void
BufferTextureHost::AddWRImage(wr::ResourceUpdateQueue& aResources, BufferTextureHost::PushResourceUpdates(wr::ResourceUpdateQueue& aResources,
Range<const wr::ImageKey>& aImageKeys, ResourceUpdateOp aOp,
const wr::ExternalImageId& aExtID) const Range<wr::ImageKey>& aImageKeys,
const wr::ExternalImageId& aExtID)
{ {
auto method = aOp == TextureHost::ADD_IMAGE ? &wr::ResourceUpdateQueue::AddExternalImage
: &wr::ResourceUpdateQueue::UpdateExternalImage;
auto bufferType = wr::WrExternalImageBufferType::ExternalBuffer;
if (GetFormat() != gfx::SurfaceFormat::YUV) { if (GetFormat() != gfx::SurfaceFormat::YUV) {
MOZ_ASSERT(aImageKeys.length() == 1); MOZ_ASSERT(aImageKeys.length() == 1);
wr::ImageDescriptor descriptor(GetSize(), wr::ImageDescriptor descriptor(GetSize(),
ImageDataSerializer::ComputeRGBStride(GetFormat(), GetSize().width), ImageDataSerializer::ComputeRGBStride(GetFormat(), GetSize().width),
GetFormat()); GetFormat());
aResources.AddExternalImageBuffer(aImageKeys[0], descriptor, aExtID); (aResources.*method)(aImageKeys[0], descriptor, aExtID, bufferType, 0);
} else { } else {
MOZ_ASSERT(aImageKeys.length() == 3); MOZ_ASSERT(aImageKeys.length() == 3);
const layers::YCbCrDescriptor& desc = mDescriptor.get_YCbCrDescriptor(); const layers::YCbCrDescriptor& desc = mDescriptor.get_YCbCrDescriptor();
wr::ImageDescriptor yDescriptor(desc.ySize(), desc.ySize().width, gfx::SurfaceFormat::A8); wr::ImageDescriptor yDescriptor(desc.ySize(), desc.ySize().width, gfx::SurfaceFormat::A8);
wr::ImageDescriptor cbcrDescriptor(desc.cbCrSize(), desc.cbCrSize().width, gfx::SurfaceFormat::A8); wr::ImageDescriptor cbcrDescriptor(desc.cbCrSize(), desc.cbCrSize().width, gfx::SurfaceFormat::A8);
aResources.AddExternalImage(aImageKeys[0], (aResources.*method)(aImageKeys[0], yDescriptor, aExtID, bufferType, 0);
yDescriptor, (aResources.*method)(aImageKeys[1], cbcrDescriptor, aExtID, bufferType, 1);
aExtID, (aResources.*method)(aImageKeys[2], cbcrDescriptor, aExtID, bufferType, 2);
wr::WrExternalImageBufferType::ExternalBuffer,
0);
aResources.AddExternalImage(aImageKeys[1],
cbcrDescriptor,
aExtID,
wr::WrExternalImageBufferType::ExternalBuffer,
1);
aResources.AddExternalImage(aImageKeys[2],
cbcrDescriptor,
aExtID,
wr::WrExternalImageBufferType::ExternalBuffer,
2);
} }
} }
void void
BufferTextureHost::PushExternalImage(wr::DisplayListBuilder& aBuilder, BufferTextureHost::PushDisplayItems(wr::DisplayListBuilder& aBuilder,
const wr::LayoutRect& aBounds, const wr::LayoutRect& aBounds,
const wr::LayoutRect& aClip, const wr::LayoutRect& aClip,
wr::ImageRendering aFilter, wr::ImageRendering aFilter,
Range<const wr::ImageKey>& aImageKeys) const Range<wr::ImageKey>& aImageKeys)
{ {
if (GetFormat() != gfx::SurfaceFormat::YUV) { if (GetFormat() != gfx::SurfaceFormat::YUV) {
MOZ_ASSERT(aImageKeys.length() == 1); MOZ_ASSERT(aImageKeys.length() == 1);

View file

@ -621,35 +621,32 @@ public:
MOZ_RELEASE_ASSERT(false, "No CreateRenderTexture() implementation for this TextureHost type."); MOZ_RELEASE_ASSERT(false, "No CreateRenderTexture() implementation for this TextureHost type.");
} }
// Create all necessary image keys for this textureHost rendering. /// Returns the number of actual textures that will be used to render this.
// @param aImageKeys - [out] The set of ImageKeys used for this textureHost /// For example in a lot of YUV cases it will be 3
// composing. virtual uint32_t NumSubTextures() const { return 1; }
// @param aImageKeyAllocator - [in] The function which is used for creating
// the new ImageKey. enum ResourceUpdateOp {
virtual void GetWRImageKeys(nsTArray<wr::ImageKey>& aImageKeys, ADD_IMAGE,
const std::function<wr::ImageKey()>& aImageKeyAllocator) UPDATE_IMAGE,
{ };
MOZ_ASSERT(aImageKeys.IsEmpty());
MOZ_ASSERT_UNREACHABLE("No GetWRImageKeys() implementation for this TextureHost type.");
}
// Add all necessary TextureHost informations to the resource update queue. // Add all necessary TextureHost informations to the resource update queue.
// Then, WR will use this informations to read from the TextureHost. virtual void PushResourceUpdates(wr::ResourceUpdateQueue& aResources,
virtual void AddWRImage(wr::ResourceUpdateQueue& aResources, ResourceUpdateOp aOp,
Range<const wr::ImageKey>& aImageKeys, const Range<wr::ImageKey>& aImageKeys,
const wr::ExternalImageId& aExtID) const wr::ExternalImageId& aExtID)
{ {
MOZ_ASSERT_UNREACHABLE("No AddWRImage() implementation for this TextureHost type."); MOZ_ASSERT_UNREACHABLE("Unimplemented");
} }
// Put all necessary WR commands into DisplayListBuilder for this textureHost rendering. // Put all necessary WR commands into DisplayListBuilder for this textureHost rendering.
virtual void PushExternalImage(wr::DisplayListBuilder& aBuilder, virtual void PushDisplayItems(wr::DisplayListBuilder& aBuilder,
const wr::LayoutRect& aBounds, const wr::LayoutRect& aBounds,
const wr::LayoutRect& aClip, const wr::LayoutRect& aClip,
wr::ImageRendering aFilter, wr::ImageRendering aFilter,
Range<const wr::ImageKey>& aKeys) const Range<wr::ImageKey>& aKeys)
{ {
MOZ_ASSERT_UNREACHABLE("No PushExternalImage() implementation for this TextureHost type."); MOZ_ASSERT_UNREACHABLE("No PushDisplayItems() implementation for this TextureHost type.");
} }
/** /**
@ -747,18 +744,18 @@ public:
virtual void CreateRenderTexture(const wr::ExternalImageId& aExternalImageId) override; virtual void CreateRenderTexture(const wr::ExternalImageId& aExternalImageId) override;
virtual void GetWRImageKeys(nsTArray<wr::ImageKey>& aImageKeys, virtual uint32_t NumSubTextures() const override;
const std::function<wr::ImageKey()>& aImageKeyAllocator) override;
virtual void AddWRImage(wr::ResourceUpdateQueue& aResources, virtual void PushResourceUpdates(wr::ResourceUpdateQueue& aResources,
Range<const wr::ImageKey>& aImageKeys, ResourceUpdateOp aOp,
const wr::ExternalImageId& aExtID) override; const Range<wr::ImageKey>& aImageKeys,
const wr::ExternalImageId& aExtID) override;
virtual void PushExternalImage(wr::DisplayListBuilder& aBuilder, virtual void PushDisplayItems(wr::DisplayListBuilder& aBuilder,
const wr::LayoutRect& aBounds, const wr::LayoutRect& aBounds,
const wr::LayoutRect& aClip, const wr::LayoutRect& aClip,
wr::ImageRendering aFilter, wr::ImageRendering aFilter,
Range<const wr::ImageKey>& aImageKeys) override; const Range<wr::ImageKey>& aImageKeys) override;
protected: protected:
bool Upload(nsIntRegion *aRegion = nullptr); bool Upload(nsIntRegion *aRegion = nullptr);

View file

@ -1042,41 +1042,36 @@ DXGITextureHostD3D11::CreateRenderTexture(const wr::ExternalImageId& aExternalIm
wr::RenderThread::Get()->RegisterExternalImage(wr::AsUint64(aExternalImageId), texture.forget()); wr::RenderThread::Get()->RegisterExternalImage(wr::AsUint64(aExternalImageId), texture.forget());
} }
void uint32_t
DXGITextureHostD3D11::GetWRImageKeys(nsTArray<wr::ImageKey>& aImageKeys, DXGITextureHostD3D11::NumSubTextures() const
const std::function<wr::ImageKey()>& aImageKeyAllocator)
{ {
MOZ_ASSERT(aImageKeys.IsEmpty());
switch (GetFormat()) { switch (GetFormat()) {
case gfx::SurfaceFormat::R8G8B8X8: case gfx::SurfaceFormat::R8G8B8X8:
case gfx::SurfaceFormat::R8G8B8A8: case gfx::SurfaceFormat::R8G8B8A8:
case gfx::SurfaceFormat::B8G8R8A8: case gfx::SurfaceFormat::B8G8R8A8:
case gfx::SurfaceFormat::B8G8R8X8: { case gfx::SurfaceFormat::B8G8R8X8: {
// 1 image key return 1;
aImageKeys.AppendElement(aImageKeyAllocator());
MOZ_ASSERT(aImageKeys.Length() == 1);
break;
} }
case gfx::SurfaceFormat::NV12: { case gfx::SurfaceFormat::NV12: {
// 2 image key return 2;
aImageKeys.AppendElement(aImageKeyAllocator());
aImageKeys.AppendElement(aImageKeyAllocator());
MOZ_ASSERT(aImageKeys.Length() == 2);
break;
} }
default: { default: {
MOZ_ASSERT_UNREACHABLE("unexpected to be called"); MOZ_ASSERT_UNREACHABLE("unexpected format");
return 1;
} }
} }
} }
void void
DXGITextureHostD3D11::AddWRImage(wr::ResourceUpdateQueue& aResources, DXGITextureHostD3D11::PushResourceUpdates(wr::ResourceUpdateQueue& aResources,
Range<const wr::ImageKey>& aImageKeys, ResourceUpdateOp aOp,
const wr::ExternalImageId& aExtID) const Range<wr::ImageKey>& aImageKeys,
const wr::ExternalImageId& aExtID)
{ {
MOZ_ASSERT(mHandle); MOZ_ASSERT(mHandle);
auto method = aOp == TextureHost::ADD_IMAGE ? &wr::ResourceUpdateQueue::AddExternalImage
: &wr::ResourceUpdateQueue::UpdateExternalImage;
auto bufferType = wr::WrExternalImageBufferType::TextureExternalHandle;
switch (mFormat) { switch (mFormat) {
case gfx::SurfaceFormat::R8G8B8X8: case gfx::SurfaceFormat::R8G8B8X8:
@ -1086,11 +1081,7 @@ DXGITextureHostD3D11::AddWRImage(wr::ResourceUpdateQueue& aResources,
MOZ_ASSERT(aImageKeys.length() == 1); MOZ_ASSERT(aImageKeys.length() == 1);
wr::ImageDescriptor descriptor(GetSize(), GetFormat()); wr::ImageDescriptor descriptor(GetSize(), GetFormat());
aResources.AddExternalImage(aImageKeys[0], (aResources.*method)(aImageKeys[0], descriptor, aExtID, bufferType, 0);
descriptor,
aExtID,
wr::WrExternalImageBufferType::Texture2DHandle,
0);
break; break;
} }
case gfx::SurfaceFormat::NV12: { case gfx::SurfaceFormat::NV12: {
@ -1098,16 +1089,8 @@ DXGITextureHostD3D11::AddWRImage(wr::ResourceUpdateQueue& aResources,
wr::ImageDescriptor descriptor0(GetSize(), gfx::SurfaceFormat::A8); wr::ImageDescriptor descriptor0(GetSize(), gfx::SurfaceFormat::A8);
wr::ImageDescriptor descriptor1(GetSize() / 2, gfx::SurfaceFormat::R8G8); wr::ImageDescriptor descriptor1(GetSize() / 2, gfx::SurfaceFormat::R8G8);
aResources.AddExternalImage(aImageKeys[0], (aResources.*method)(aImageKeys[0], descriptor0, aExtID, bufferType, 0);
descriptor0, (aResources.*method)(aImageKeys[1], descriptor1, aExtID, bufferType, 1);
aExtID,
wr::WrExternalImageBufferType::TextureExternalHandle,
0);
aResources.AddExternalImage(aImageKeys[1],
descriptor1,
aExtID,
wr::WrExternalImageBufferType::TextureExternalHandle,
1);
break; break;
} }
default: { default: {
@ -1117,11 +1100,11 @@ DXGITextureHostD3D11::AddWRImage(wr::ResourceUpdateQueue& aResources,
} }
void void
DXGITextureHostD3D11::PushExternalImage(wr::DisplayListBuilder& aBuilder, DXGITextureHostD3D11::PushDisplayItems(wr::DisplayListBuilder& aBuilder,
const wr::LayoutRect& aBounds, const wr::LayoutRect& aBounds,
const wr::LayoutRect& aClip, const wr::LayoutRect& aClip,
wr::ImageRendering aFilter, wr::ImageRendering aFilter,
Range<const wr::ImageKey>& aImageKeys) const Range<wr::ImageKey>& aImageKeys)
{ {
switch (GetFormat()) { switch (GetFormat()) {
case gfx::SurfaceFormat::R8G8B8X8: case gfx::SurfaceFormat::R8G8B8X8:
@ -1312,20 +1295,10 @@ DXGIYCbCrTextureHostD3D11::CreateRenderTexture(const wr::ExternalImageId& aExter
} }
void void
DXGIYCbCrTextureHostD3D11::GetWRImageKeys(nsTArray<wr::ImageKey>& aImageKeys, DXGIYCbCrTextureHostD3D11::PushResourceUpdates(wr::ResourceUpdateQueue& aResources,
const std::function<wr::ImageKey()>& aImageKeyAllocator) ResourceUpdateOp aOp,
{ const Range<wr::ImageKey>& aImageKeys,
MOZ_ASSERT(aImageKeys.IsEmpty()); const wr::ExternalImageId& aExtID)
// 1 image key
aImageKeys.AppendElement(aImageKeyAllocator());
MOZ_ASSERT(aImageKeys.Length() == 1);
}
void
DXGIYCbCrTextureHostD3D11::AddWRImage(wr::ResourceUpdateQueue& aResources,
Range<const wr::ImageKey>& aImageKeys,
const wr::ExternalImageId& aExtID)
{ {
// TODO - This implementation is very slow (read-back, copy on the copy and re-upload). // TODO - This implementation is very slow (read-back, copy on the copy and re-upload).
@ -1351,17 +1324,21 @@ DXGIYCbCrTextureHostD3D11::AddWRImage(wr::ResourceUpdateQueue& aResources,
wr::ImageDescriptor descriptor(size, map.mStride, dataSourceSurface->GetFormat()); wr::ImageDescriptor descriptor(size, map.mStride, dataSourceSurface->GetFormat());
wr::Vec_u8 imgBytes; wr::Vec_u8 imgBytes;
imgBytes.PushBytes(Range<uint8_t>(map.mData, size.height * map.mStride)); imgBytes.PushBytes(Range<uint8_t>(map.mData, size.height * map.mStride));
aResources.AddImage(aImageKeys[0], descriptor, imgBytes); if (aOp == TextureHost::ADD_IMAGE) {
aResources.AddImage(aImageKeys[0], descriptor, imgBytes);
} else {
aResources.UpdateImageBuffer(aImageKeys[0], descriptor, imgBytes);
}
dataSourceSurface->Unmap(); dataSourceSurface->Unmap();
} }
void void
DXGIYCbCrTextureHostD3D11::PushExternalImage(wr::DisplayListBuilder& aBuilder, DXGIYCbCrTextureHostD3D11::PushDisplayItems(wr::DisplayListBuilder& aBuilder,
const wr::LayoutRect& aBounds, const wr::LayoutRect& aBounds,
const wr::LayoutRect& aClip, const wr::LayoutRect& aClip,
wr::ImageRendering aFilter, wr::ImageRendering aFilter,
Range<const wr::ImageKey>& aImageKeys) const Range<wr::ImageKey>& aImageKeys)
{ {
// 1 image key // 1 image key
MOZ_ASSERT(aImageKeys.length() == 1); MOZ_ASSERT(aImageKeys.length() == 1);

View file

@ -335,18 +335,18 @@ public:
virtual void CreateRenderTexture(const wr::ExternalImageId& aExternalImageId) override; virtual void CreateRenderTexture(const wr::ExternalImageId& aExternalImageId) override;
virtual void GetWRImageKeys(nsTArray<wr::ImageKey>& aImageKeys, virtual uint32_t NumSubTextures() const override;
const std::function<wr::ImageKey()>& aImageKeyAllocator) override;
virtual void AddWRImage(wr::ResourceUpdateQueue& aAPI, virtual void PushResourceUpdates(wr::ResourceUpdateQueue& aResources,
Range<const wr::ImageKey>& aImageKeys, ResourceUpdateOp aOp,
const wr::ExternalImageId& aExtID) override; const Range<wr::ImageKey>& aImageKeys,
const wr::ExternalImageId& aExtID) override;
virtual void PushExternalImage(wr::DisplayListBuilder& aBuilder, virtual void PushDisplayItems(wr::DisplayListBuilder& aBuilder,
const wr::LayoutRect& aBounds, const wr::LayoutRect& aBounds,
const wr::LayoutRect& aClip, const wr::LayoutRect& aClip,
wr::ImageRendering aFilter, wr::ImageRendering aFilter,
Range<const wr::ImageKey>& aImageKeys) override; const Range<wr::ImageKey>& aImageKeys) override;
protected: protected:
bool LockInternal(); bool LockInternal();
@ -398,18 +398,16 @@ public:
virtual void CreateRenderTexture(const wr::ExternalImageId& aExternalImageId) override; virtual void CreateRenderTexture(const wr::ExternalImageId& aExternalImageId) override;
virtual void GetWRImageKeys(nsTArray<wr::ImageKey>& aImageKeys, virtual void PushResourceUpdates(wr::ResourceUpdateQueue& aResources,
const std::function<wr::ImageKey()>& aImageKeyAllocator) override; ResourceUpdateOp aOp,
const Range<wr::ImageKey>& aImageKeys,
const wr::ExternalImageId& aExtID) override;
virtual void AddWRImage(wr::ResourceUpdateQueue& aResources, virtual void PushDisplayItems(wr::DisplayListBuilder& aBuilder,
Range<const wr::ImageKey>& aImageKeys, const wr::LayoutRect& aBounds,
const wr::ExternalImageId& aExtID) override; const wr::LayoutRect& aClip,
wr::ImageRendering aFilter,
virtual void PushExternalImage(wr::DisplayListBuilder& aBuilder, const Range<wr::ImageKey>& aImageKeys) override;
const wr::LayoutRect& aBounds,
const wr::LayoutRect& aClip,
wr::ImageRendering aFilter,
Range<const wr::ImageKey>& aImageKeys) override;
private: private:
bool EnsureTextureSource(); bool EnsureTextureSource();

View file

@ -24,37 +24,48 @@ using gfx::GPUProcessManager;
StaticRefPtr<CompositorManagerChild> CompositorManagerChild::sInstance; StaticRefPtr<CompositorManagerChild> CompositorManagerChild::sInstance;
/* static */ bool /* static */ bool
CompositorManagerChild::IsInitialized(base::ProcessId aGPUPid) CompositorManagerChild::IsInitialized(uint64_t aProcessToken)
{ {
MOZ_ASSERT(NS_IsMainThread()); MOZ_ASSERT(NS_IsMainThread());
return sInstance && sInstance->CanSend() && sInstance->OtherPid() == aGPUPid; return sInstance && sInstance->CanSend() &&
sInstance->mProcessToken == aProcessToken;
} }
/* static */ bool /* static */ void
CompositorManagerChild::InitSameProcess(uint32_t aNamespace) CompositorManagerChild::InitSameProcess(uint32_t aNamespace,
uint64_t aProcessToken)
{ {
MOZ_ASSERT(NS_IsMainThread()); MOZ_ASSERT(NS_IsMainThread());
if (NS_WARN_IF(IsInitialized(base::GetCurrentProcId()))) { if (NS_WARN_IF(IsInitialized(base::GetCurrentProcId()))) {
MOZ_ASSERT_UNREACHABLE("Already initialized same process"); MOZ_ASSERT_UNREACHABLE("Already initialized same process");
return false; return;
} }
RefPtr<CompositorManagerParent> parent = RefPtr<CompositorManagerParent> parent =
CompositorManagerParent::CreateSameProcess(); CompositorManagerParent::CreateSameProcess();
sInstance = new CompositorManagerChild(parent, aNamespace); RefPtr<CompositorManagerChild> child =
return true; new CompositorManagerChild(parent, aProcessToken, aNamespace);
if (NS_WARN_IF(!child->CanSend())) {
MOZ_DIAGNOSTIC_ASSERT(false, "Failed to open same process protocol");
return;
}
parent->BindComplete();
sInstance = child.forget();
} }
/* static */ bool /* static */ bool
CompositorManagerChild::Init(Endpoint<PCompositorManagerChild>&& aEndpoint, CompositorManagerChild::Init(Endpoint<PCompositorManagerChild>&& aEndpoint,
uint32_t aNamespace) uint32_t aNamespace,
uint64_t aProcessToken /* = 0 */)
{ {
MOZ_ASSERT(NS_IsMainThread()); MOZ_ASSERT(NS_IsMainThread());
if (sInstance) { if (sInstance) {
MOZ_ASSERT(sInstance->mNamespace != aNamespace); MOZ_ASSERT(sInstance->mNamespace != aNamespace);
} }
sInstance = new CompositorManagerChild(Move(aEndpoint), aNamespace); sInstance = new CompositorManagerChild(Move(aEndpoint), aProcessToken,
aNamespace);
return sInstance->CanSend(); return sInstance->CanSend();
} }
@ -73,14 +84,14 @@ CompositorManagerChild::Shutdown()
} }
/* static */ void /* static */ void
CompositorManagerChild::OnGPUProcessLost() CompositorManagerChild::OnGPUProcessLost(uint64_t aProcessToken)
{ {
MOZ_ASSERT(NS_IsMainThread()); MOZ_ASSERT(NS_IsMainThread());
// Since GPUChild and CompositorManagerChild will race on ActorDestroy, we // Since GPUChild and CompositorManagerChild will race on ActorDestroy, we
// cannot know if the CompositorManagerChild is about to be released but has // cannot know if the CompositorManagerChild is about to be released but has
// yet to be. As such, we want to pre-emptively set mCanSend to false. // yet to be. As such, we want to pre-emptively set mCanSend to false.
if (sInstance) { if (sInstance && sInstance->mProcessToken == aProcessToken) {
sInstance->mCanSend = false; sInstance->mCanSend = false;
} }
} }
@ -162,10 +173,12 @@ CompositorManagerChild::CreateSameProcessWidgetCompositorBridge(LayerManager* aL
} }
CompositorManagerChild::CompositorManagerChild(CompositorManagerParent* aParent, CompositorManagerChild::CompositorManagerChild(CompositorManagerParent* aParent,
uint64_t aProcessToken,
uint32_t aNamespace) uint32_t aNamespace)
: mCanSend(false) : mProcessToken(aProcessToken)
, mNamespace(aNamespace) , mNamespace(aNamespace)
, mResourceId(0) , mResourceId(0)
, mCanSend(false)
{ {
MOZ_ASSERT(aParent); MOZ_ASSERT(aParent);
@ -182,10 +195,12 @@ CompositorManagerChild::CompositorManagerChild(CompositorManagerParent* aParent,
} }
CompositorManagerChild::CompositorManagerChild(Endpoint<PCompositorManagerChild>&& aEndpoint, CompositorManagerChild::CompositorManagerChild(Endpoint<PCompositorManagerChild>&& aEndpoint,
uint64_t aProcessToken,
uint32_t aNamespace) uint32_t aNamespace)
: mCanSend(false) : mProcessToken(aProcessToken)
, mNamespace(aNamespace) , mNamespace(aNamespace)
, mResourceId(0) , mResourceId(0)
, mCanSend(false)
{ {
if (NS_WARN_IF(!aEndpoint.Bind(this))) { if (NS_WARN_IF(!aEndpoint.Bind(this))) {
return; return;

View file

@ -24,12 +24,13 @@ class CompositorManagerChild : public PCompositorManagerChild
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(CompositorManagerChild) NS_INLINE_DECL_THREADSAFE_REFCOUNTING(CompositorManagerChild)
public: public:
static bool IsInitialized(base::ProcessId aPid); static bool IsInitialized(uint64_t aProcessToken);
static bool InitSameProcess(uint32_t aNamespace); static void InitSameProcess(uint32_t aNamespace, uint64_t aProcessToken);
static bool Init(Endpoint<PCompositorManagerChild>&& aEndpoint, static bool Init(Endpoint<PCompositorManagerChild>&& aEndpoint,
uint32_t aNamespace); uint32_t aNamespace,
uint64_t aProcessToken = 0);
static void Shutdown(); static void Shutdown();
static void OnGPUProcessLost(); static void OnGPUProcessLost(uint64_t aProcessToken);
static bool static bool
CreateContentCompositorBridge(uint32_t aNamespace); CreateContentCompositorBridge(uint32_t aNamespace);
@ -73,9 +74,11 @@ private:
static StaticRefPtr<CompositorManagerChild> sInstance; static StaticRefPtr<CompositorManagerChild> sInstance;
CompositorManagerChild(CompositorManagerParent* aParent, CompositorManagerChild(CompositorManagerParent* aParent,
uint64_t aProcessToken,
uint32_t aNamespace); uint32_t aNamespace);
CompositorManagerChild(Endpoint<PCompositorManagerChild>&& aEndpoint, CompositorManagerChild(Endpoint<PCompositorManagerChild>&& aEndpoint,
uint64_t aProcessToken,
uint32_t aNamespace); uint32_t aNamespace);
~CompositorManagerChild() override ~CompositorManagerChild() override
@ -95,9 +98,10 @@ private:
void SetReplyTimeout(); void SetReplyTimeout();
bool mCanSend; uint64_t mProcessToken;
uint32_t mNamespace; uint32_t mNamespace;
uint32_t mResourceId; uint32_t mResourceId;
bool mCanSend;
}; };
} // namespace layers } // namespace layers

View file

@ -42,18 +42,6 @@ CompositorManagerParent::CreateSameProcess()
// on the main thread and complete before we return the manager handles. // on the main thread and complete before we return the manager handles.
RefPtr<CompositorManagerParent> parent = new CompositorManagerParent(); RefPtr<CompositorManagerParent> parent = new CompositorManagerParent();
parent->SetOtherProcessId(base::GetCurrentProcId()); parent->SetOtherProcessId(base::GetCurrentProcId());
// CompositorManagerParent::Bind would normally add a reference for IPDL but
// we don't use that in the same process case.
parent.get()->AddRef();
sInstance = parent;
#ifdef COMPOSITOR_MANAGER_PARENT_EXPLICIT_SHUTDOWN
if (!sActiveActors) {
sActiveActors = new nsTArray<CompositorManagerParent*>();
}
sActiveActors->AppendElement(parent);
#endif
return parent.forget(); return parent.forget();
} }
@ -133,12 +121,22 @@ CompositorManagerParent::Bind(Endpoint<PCompositorManagerParent>&& aEndpoint)
return; return;
} }
BindComplete();
}
void
CompositorManagerParent::BindComplete()
{
// Add the IPDL reference to ourself, so we can't get freed until IPDL is // Add the IPDL reference to ourself, so we can't get freed until IPDL is
// done with us. // done with us.
AddRef(); AddRef();
#ifdef COMPOSITOR_MANAGER_PARENT_EXPLICIT_SHUTDOWN
StaticMutexAutoLock lock(sMutex); StaticMutexAutoLock lock(sMutex);
if (OtherPid() == base::GetCurrentProcId()) {
sInstance = this;
}
#ifdef COMPOSITOR_MANAGER_PARENT_EXPLICIT_SHUTDOWN
if (!sActiveActors) { if (!sActiveActors) {
sActiveActors = new nsTArray<CompositorManagerParent*>(); sActiveActors = new nsTArray<CompositorManagerParent*>();
} }

View file

@ -39,6 +39,7 @@ public:
bool aUseExternalSurfaceSize, bool aUseExternalSurfaceSize,
const gfx::IntSize& aSurfaceSize); const gfx::IntSize& aSurfaceSize);
void BindComplete();
void ActorDestroy(ActorDestroyReason aReason) override; void ActorDestroy(ActorDestroyReason aReason) override;
bool DeallocPCompositorBridgeParent(PCompositorBridgeParent* aActor) override; bool DeallocPCompositorBridgeParent(PCompositorBridgeParent* aActor) override;

View file

@ -22,9 +22,6 @@ namespace layers {
static StaticRefPtr<CompositorThreadHolder> sCompositorThreadHolder; static StaticRefPtr<CompositorThreadHolder> sCompositorThreadHolder;
static bool sFinishedCompositorShutDown = false; static bool sFinishedCompositorShutDown = false;
// See ImageBridgeChild.cpp
void ReleaseImageBridgeParentSingleton();
CompositorThreadHolder* GetCompositorThreadHolder() CompositorThreadHolder* GetCompositorThreadHolder()
{ {
return sCompositorThreadHolder; return sCompositorThreadHolder;
@ -126,7 +123,7 @@ CompositorThreadHolder::Shutdown()
MOZ_ASSERT(NS_IsMainThread(), "Should be on the main Thread!"); MOZ_ASSERT(NS_IsMainThread(), "Should be on the main Thread!");
MOZ_ASSERT(sCompositorThreadHolder, "The compositor thread has already been shut down!"); MOZ_ASSERT(sCompositorThreadHolder, "The compositor thread has already been shut down!");
ReleaseImageBridgeParentSingleton(); ImageBridgeParent::Shutdown();
gfx::ReleaseVRManagerParentSingleton(); gfx::ReleaseVRManagerParentSingleton();
MediaSystemResourceService::Shutdown(); MediaSystemResourceService::Shutdown();
CompositorManagerParent::Shutdown(); CompositorManagerParent::Shutdown();

View file

@ -240,13 +240,16 @@ ImageBridgeChild::ShutdownStep2(SynchronousTask* aTask)
MOZ_ASSERT(InImageBridgeChildThread(), MOZ_ASSERT(InImageBridgeChildThread(),
"Should be in ImageBridgeChild thread."); "Should be in ImageBridgeChild thread.");
Close(); if (!mDestroyed) {
Close();
}
} }
void void
ImageBridgeChild::ActorDestroy(ActorDestroyReason aWhy) ImageBridgeChild::ActorDestroy(ActorDestroyReason aWhy)
{ {
mCanSend = false; mCanSend = false;
mDestroyed = true;
{ {
MutexAutoLock lock(mContainerMapLock); MutexAutoLock lock(mContainerMapLock);
mImageContainerListeners.Clear(); mImageContainerListeners.Clear();
@ -650,8 +653,6 @@ ImageBridgeChild::WillShutdown()
task.Wait(); task.Wait();
} }
mDestroyed = true;
} }
void void

View file

@ -46,6 +46,8 @@ std::map<base::ProcessId, ImageBridgeParent*> ImageBridgeParent::sImageBridges;
StaticAutoPtr<mozilla::Monitor> sImageBridgesLock; StaticAutoPtr<mozilla::Monitor> sImageBridgesLock;
static StaticRefPtr<ImageBridgeParent> sImageBridgeParentSingleton;
// defined in CompositorBridgeParent.cpp // defined in CompositorBridgeParent.cpp
CompositorThreadHolder* GetCompositorThreadHolder(); CompositorThreadHolder* GetCompositorThreadHolder();
@ -81,12 +83,6 @@ ImageBridgeParent::~ImageBridgeParent()
{ {
} }
static StaticRefPtr<ImageBridgeParent> sImageBridgeParentSingleton;
void ReleaseImageBridgeParentSingleton() {
sImageBridgeParentSingleton = nullptr;
}
/* static */ ImageBridgeParent* /* static */ ImageBridgeParent*
ImageBridgeParent::CreateSameProcess() ImageBridgeParent::CreateSameProcess()
{ {
@ -116,6 +112,36 @@ ImageBridgeParent::CreateForGPUProcess(Endpoint<PImageBridgeParent>&& aEndpoint)
return true; return true;
} }
/* static */ void
ImageBridgeParent::ShutdownInternal()
{
// We make a copy because we don't want to hold the lock while closing and we
// don't want the object to get freed underneath us.
nsTArray<RefPtr<ImageBridgeParent>> actors;
{
MonitorAutoLock lock(*sImageBridgesLock);
for (const auto& iter : sImageBridges) {
actors.AppendElement(iter.second);
}
}
for (auto const& actor : actors) {
MOZ_RELEASE_ASSERT(!actor->mClosed);
actor->Close();
}
sImageBridgeParentSingleton = nullptr;
}
/* static */ void
ImageBridgeParent::Shutdown()
{
CompositorThreadHolder::Loop()->PostTask(
NS_NewRunnableFunction("ImageBridgeParent::Shutdown", []() -> void {
ImageBridgeParent::ShutdownInternal();
}));
}
void void
ImageBridgeParent::ActorDestroy(ActorDestroyReason aWhy) ImageBridgeParent::ActorDestroy(ActorDestroyReason aWhy)
{ {

View file

@ -58,6 +58,7 @@ public:
static ImageBridgeParent* CreateSameProcess(); static ImageBridgeParent* CreateSameProcess();
static bool CreateForGPUProcess(Endpoint<PImageBridgeParent>&& aEndpoint); static bool CreateForGPUProcess(Endpoint<PImageBridgeParent>&& aEndpoint);
static bool CreateForContent(Endpoint<PImageBridgeParent>&& aEndpoint); static bool CreateForContent(Endpoint<PImageBridgeParent>&& aEndpoint);
static void Shutdown();
virtual ShmemAllocator* AsShmemAllocator() override { return this; } virtual ShmemAllocator* AsShmemAllocator() override { return this; }
@ -125,6 +126,8 @@ protected:
void Bind(Endpoint<PImageBridgeParent>&& aEndpoint); void Bind(Endpoint<PImageBridgeParent>&& aEndpoint);
private: private:
static void ShutdownInternal();
void DeferredDestroy(); void DeferredDestroy();
MessageLoop* mMessageLoop; MessageLoop* mMessageLoop;
// This keeps us alive until ActorDestroy(), at which point we do a // This keeps us alive until ActorDestroy(), at which point we do a

View file

@ -125,48 +125,39 @@ MacIOSurfaceTextureHostOGL::CreateRenderTexture(const wr::ExternalImageId& aExte
wr::RenderThread::Get()->RegisterExternalImage(wr::AsUint64(aExternalImageId), texture.forget()); wr::RenderThread::Get()->RegisterExternalImage(wr::AsUint64(aExternalImageId), texture.forget());
} }
void uint32_t
MacIOSurfaceTextureHostOGL::GetWRImageKeys(nsTArray<wr::ImageKey>& aImageKeys, MacIOSurfaceTextureHostOGL::NumSubTextures() const
const std::function<wr::ImageKey()>& aImageKeyAllocator)
{ {
MOZ_ASSERT(aImageKeys.IsEmpty());
switch (GetFormat()) { switch (GetFormat()) {
case gfx::SurfaceFormat::R8G8B8X8: case gfx::SurfaceFormat::R8G8B8X8:
case gfx::SurfaceFormat::R8G8B8A8: case gfx::SurfaceFormat::R8G8B8A8:
case gfx::SurfaceFormat::B8G8R8A8: case gfx::SurfaceFormat::B8G8R8A8:
case gfx::SurfaceFormat::B8G8R8X8: { case gfx::SurfaceFormat::B8G8R8X8:
// 1 image key
aImageKeys.AppendElement(aImageKeyAllocator());
MOZ_ASSERT(aImageKeys.Length() == 1);
break;
}
case gfx::SurfaceFormat::YUV422: { case gfx::SurfaceFormat::YUV422: {
// 1 image key return 1;
aImageKeys.AppendElement(aImageKeyAllocator());
MOZ_ASSERT(aImageKeys.Length() == 1);
break;
} }
case gfx::SurfaceFormat::NV12: { case gfx::SurfaceFormat::NV12: {
// 2 image key return 2;
aImageKeys.AppendElement(aImageKeyAllocator());
aImageKeys.AppendElement(aImageKeyAllocator());
MOZ_ASSERT(aImageKeys.Length() == 2);
break;
} }
default: { default: {
MOZ_ASSERT_UNREACHABLE("unexpected to be called"); MOZ_ASSERT_UNREACHABLE("unexpected format");
return 1;
} }
} }
} }
void void
MacIOSurfaceTextureHostOGL::AddWRImage(wr::ResourceUpdateQueue& aResources, MacIOSurfaceTextureHostOGL::PushResourceUpdates(wr::ResourceUpdateQueue& aResources,
Range<const wr::ImageKey>& aImageKeys, ResourceUpdateOp aOp,
const wr::ExternalImageId& aExtID) const Range<wr::ImageKey>& aImageKeys,
const wr::ExternalImageId& aExtID)
{ {
MOZ_ASSERT(mSurface); MOZ_ASSERT(mSurface);
auto method = aOp == TextureHost::ADD_IMAGE ? &wr::ResourceUpdateQueue::AddExternalImage
: &wr::ResourceUpdateQueue::UpdateExternalImage;
auto bufferType = wr::WrExternalImageBufferType::TextureRectHandle;
switch (GetFormat()) { switch (GetFormat()) {
case gfx::SurfaceFormat::R8G8B8X8: case gfx::SurfaceFormat::R8G8B8X8:
case gfx::SurfaceFormat::R8G8B8A8: case gfx::SurfaceFormat::R8G8B8A8:
@ -175,11 +166,7 @@ MacIOSurfaceTextureHostOGL::AddWRImage(wr::ResourceUpdateQueue& aResources,
MOZ_ASSERT(aImageKeys.length() == 1); MOZ_ASSERT(aImageKeys.length() == 1);
MOZ_ASSERT(mSurface->GetPlaneCount() == 0); MOZ_ASSERT(mSurface->GetPlaneCount() == 0);
wr::ImageDescriptor descriptor(GetSize(), GetFormat()); wr::ImageDescriptor descriptor(GetSize(), GetFormat());
aResources.AddExternalImage(aImageKeys[0], (aResources.*method)(aImageKeys[0], descriptor, aExtID, bufferType, 0);
descriptor,
aExtID,
wr::WrExternalImageBufferType::TextureRectHandle,
0);
break; break;
} }
case gfx::SurfaceFormat::YUV422: { case gfx::SurfaceFormat::YUV422: {
@ -190,11 +177,7 @@ MacIOSurfaceTextureHostOGL::AddWRImage(wr::ResourceUpdateQueue& aResources,
MOZ_ASSERT(aImageKeys.length() == 1); MOZ_ASSERT(aImageKeys.length() == 1);
MOZ_ASSERT(mSurface->GetPlaneCount() == 0); MOZ_ASSERT(mSurface->GetPlaneCount() == 0);
wr::ImageDescriptor descriptor(GetSize(), gfx::SurfaceFormat::R8G8B8X8); wr::ImageDescriptor descriptor(GetSize(), gfx::SurfaceFormat::R8G8B8X8);
aResources.AddExternalImage(aImageKeys[0], (aResources.*method)(aImageKeys[0], descriptor, aExtID, bufferType, 0);
descriptor,
aExtID,
wr::WrExternalImageBufferType::TextureRectHandle,
0);
break; break;
} }
case gfx::SurfaceFormat::NV12: { case gfx::SurfaceFormat::NV12: {
@ -204,16 +187,8 @@ MacIOSurfaceTextureHostOGL::AddWRImage(wr::ResourceUpdateQueue& aResources,
gfx::SurfaceFormat::A8); gfx::SurfaceFormat::A8);
wr::ImageDescriptor descriptor1(gfx::IntSize(mSurface->GetDevicePixelWidth(1), mSurface->GetDevicePixelHeight(1)), wr::ImageDescriptor descriptor1(gfx::IntSize(mSurface->GetDevicePixelWidth(1), mSurface->GetDevicePixelHeight(1)),
gfx::SurfaceFormat::R8G8); gfx::SurfaceFormat::R8G8);
aResources.AddExternalImage(aImageKeys[0], (aResources.*method)(aImageKeys[0], descriptor0, aExtID, bufferType, 0);
descriptor0, (aResources.*method)(aImageKeys[1], descriptor1, aExtID, bufferType, 1);
aExtID,
wr::WrExternalImageBufferType::TextureRectHandle,
0);
aResources.AddExternalImage(aImageKeys[1],
descriptor1,
aExtID,
wr::WrExternalImageBufferType::TextureRectHandle,
1);
break; break;
} }
default: { default: {
@ -223,11 +198,11 @@ MacIOSurfaceTextureHostOGL::AddWRImage(wr::ResourceUpdateQueue& aResources,
} }
void void
MacIOSurfaceTextureHostOGL::PushExternalImage(wr::DisplayListBuilder& aBuilder, MacIOSurfaceTextureHostOGL::PushDisplayItems(wr::DisplayListBuilder& aBuilder,
const wr::LayoutRect& aBounds, const wr::LayoutRect& aBounds,
const wr::LayoutRect& aClip, const wr::LayoutRect& aClip,
wr::ImageRendering aFilter, wr::ImageRendering aFilter,
Range<const wr::ImageKey>& aImageKeys) const Range<wr::ImageKey>& aImageKeys)
{ {
switch (GetFormat()) { switch (GetFormat()) {
case gfx::SurfaceFormat::R8G8B8X8: case gfx::SurfaceFormat::R8G8B8X8:

View file

@ -64,18 +64,18 @@ public:
virtual void CreateRenderTexture(const wr::ExternalImageId& aExternalImageId) override; virtual void CreateRenderTexture(const wr::ExternalImageId& aExternalImageId) override;
virtual void GetWRImageKeys(nsTArray<wr::ImageKey>& aImageKeys, virtual uint32_t NumSubTextures() const override;
const std::function<wr::ImageKey()>& aImageKeyAllocator) override;
virtual void AddWRImage(wr::ResourceUpdateQueue& aResources, virtual void PushResourceUpdates(wr::ResourceUpdateQueue& aResources,
Range<const wr::ImageKey>& aImageKeys, ResourceUpdateOp aOp,
const wr::ExternalImageId& aExtID) override; const Range<wr::ImageKey>& aImageKeys,
const wr::ExternalImageId& aExtID) override;
virtual void PushExternalImage(wr::DisplayListBuilder& aBuilder, virtual void PushDisplayItems(wr::DisplayListBuilder& aBuilder,
const wr::LayoutRect& aBounds, const wr::LayoutRect& aBounds,
const wr::LayoutRect& aClip, const wr::LayoutRect& aClip,
wr::ImageRendering aFilter, wr::ImageRendering aFilter,
Range<const wr::ImageKey>& aImageKeys) override; const Range<wr::ImageKey>& aImageKeys) override;
protected: protected:
GLTextureSource* CreateTextureSourceForPlane(size_t aPlane); GLTextureSource* CreateTextureSourceForPlane(size_t aPlane);

View file

@ -11,6 +11,7 @@
#include "mozilla/layers/WebRenderImageHost.h" #include "mozilla/layers/WebRenderImageHost.h"
#include "mozilla/layers/WebRenderTextureHost.h" #include "mozilla/layers/WebRenderTextureHost.h"
#include "mozilla/webrender/WebRenderAPI.h" #include "mozilla/webrender/WebRenderAPI.h"
#include "mozilla/webrender/WebRenderTypes.h"
namespace mozilla { namespace mozilla {
namespace layers { namespace layers {
@ -42,29 +43,10 @@ void
AsyncImagePipelineManager::Destroy() AsyncImagePipelineManager::Destroy()
{ {
MOZ_ASSERT(!mDestroyed); MOZ_ASSERT(!mDestroyed);
DeleteOldAsyncImages();
mApi = nullptr; mApi = nullptr;
mDestroyed = true; mDestroyed = true;
} }
bool
AsyncImagePipelineManager::HasKeysToDelete()
{
return !mKeysToDelete.IsEmpty();
}
void
AsyncImagePipelineManager::DeleteOldAsyncImages()
{
MOZ_ASSERT(!mDestroyed);
wr::ResourceUpdateQueue resources;
for (wr::ImageKey key : mKeysToDelete) {
resources.DeleteImage(key);
}
mApi->UpdateResources(resources);
mKeysToDelete.Clear();
}
void void
AsyncImagePipelineManager::AddPipeline(const wr::PipelineId& aPipelineId) AsyncImagePipelineManager::AddPipeline(const wr::PipelineId& aPipelineId)
{ {
@ -162,91 +144,108 @@ AsyncImagePipelineManager::UpdateAsyncImagePipeline(const wr::PipelineId& aPipel
pipeline->mMixBlendMode = aMixBlendMode; pipeline->mMixBlendMode = aMixBlendMode;
} }
bool Maybe<TextureHost::ResourceUpdateOp>
AsyncImagePipelineManager::GenerateImageKeyForTextureHost(wr::ResourceUpdateQueue& aResources, AsyncImagePipelineManager::UpdateImageKeys(wr::ResourceUpdateQueue& aResources,
TextureHost* aTexture, AsyncImagePipeline* aPipeline,
nsTArray<wr::ImageKey>& aKeys) nsTArray<wr::ImageKey>& aKeys)
{ {
MOZ_ASSERT(aKeys.IsEmpty()); MOZ_ASSERT(aKeys.IsEmpty());
MOZ_ASSERT(aTexture); MOZ_ASSERT(aPipeline);
if (!aPipeline->mInitialised) {
WebRenderTextureHost* wrTexture = aTexture->AsWebRenderTextureHost(); return Nothing();
if (!gfxEnv::EnableWebRenderRecording() && wrTexture) {
wrTexture->GetWRImageKeys(aKeys, std::bind(&AsyncImagePipelineManager::GenerateImageKey, this));
MOZ_ASSERT(!aKeys.IsEmpty());
Range<const wr::ImageKey> keys(&aKeys[0], aKeys.Length());
wrTexture->AddWRImage(aResources, keys, wrTexture->GetExternalImageKey());
return true;
} else {
RefPtr<gfx::DataSourceSurface> dSurf = aTexture->GetAsSurface();
if (!dSurf) {
NS_ERROR("TextureHost does not return DataSourceSurface");
return false;
}
gfx::DataSourceSurface::MappedSurface map;
if (!dSurf->Map(gfx::DataSourceSurface::MapType::READ, &map)) {
NS_ERROR("DataSourceSurface failed to map");
return false;
}
gfx::IntSize size = dSurf->GetSize();
wr::Vec_u8 imgBytes;
imgBytes.PushBytes(Range<uint8_t>(map.mData, size.height * map.mStride));
wr::ImageDescriptor descriptor(size, map.mStride, dSurf->GetFormat());
wr::ImageKey key = GenerateImageKey();
aKeys.AppendElement(key);
aResources.AddImage(key, descriptor, imgBytes);
dSurf->Unmap();
} }
return false;
TextureHost* texture = aPipeline->mImageHost->GetAsTextureHostForComposite();
TextureHost* previousTexture = aPipeline->mCurrentTexture.get();
if (!aPipeline->mIsChanged && texture == previousTexture) {
// The texture has not changed, just reuse previous ImageKeys.
// No need to update DisplayList.
return Nothing();
}
if (!texture) {
// We don't have a new texture, there isn't much we can do.
return Nothing();
}
aPipeline->mIsChanged = false;
aPipeline->mCurrentTexture = texture;
WebRenderTextureHost* wrTexture = texture->AsWebRenderTextureHost();
bool useExternalImage = !gfxEnv::EnableWebRenderRecording() && wrTexture;
aPipeline->mUseExternalImage = useExternalImage;
// The non-external image code path falls back to converting the texture into
// an rgb image.
auto numKeys = useExternalImage ? texture->NumSubTextures() : 1;
// If we already had a texture and the format hasn't changed, better to reuse the image keys
// than create new ones.
bool canUpdate = !!previousTexture
&& previousTexture->GetFormat() == texture->GetFormat()
&& aPipeline->mKeys.Length() == numKeys;
if (!canUpdate) {
for (auto key : aPipeline->mKeys) {
aResources.DeleteImage(key);
}
aPipeline->mKeys.Clear();
for (uint32_t i = 0; i < numKeys; ++i) {
aPipeline->mKeys.AppendElement(GenerateImageKey());
}
}
aKeys = aPipeline->mKeys;
auto op = canUpdate ? TextureHost::UPDATE_IMAGE : TextureHost::ADD_IMAGE;
if (!useExternalImage) {
return UpdateWithoutExternalImage(aResources, texture, aKeys[0], op);
}
Range<wr::ImageKey> keys(&aKeys[0], aKeys.Length());
wrTexture->PushResourceUpdates(aResources, op, keys, wrTexture->GetExternalImageKey());
return Some(op);
} }
bool Maybe<TextureHost::ResourceUpdateOp>
AsyncImagePipelineManager::UpdateImageKeys(wr::ResourceUpdateQueue& aResources, AsyncImagePipelineManager::UpdateWithoutExternalImage(wr::ResourceUpdateQueue& aResources,
bool& aUseExternalImage, TextureHost* aTexture,
AsyncImagePipeline* aImageMgr, wr::ImageKey aKey,
nsTArray<wr::ImageKey>& aKeys, TextureHost::ResourceUpdateOp aOp)
nsTArray<wr::ImageKey>& aKeysToDelete)
{ {
MOZ_ASSERT(aKeys.IsEmpty()); MOZ_ASSERT(aTexture);
MOZ_ASSERT(aImageMgr);
TextureHost* texture = aImageMgr->mImageHost->GetAsTextureHostForComposite();
if (!aImageMgr->mInitialised) { RefPtr<gfx::DataSourceSurface> dSurf = aTexture->GetAsSurface();
return false; if (!dSurf) {
NS_ERROR("TextureHost does not return DataSourceSurface");
return Nothing();
}
gfx::DataSourceSurface::MappedSurface map;
if (!dSurf->Map(gfx::DataSourceSurface::MapType::READ, &map)) {
NS_ERROR("DataSourceSurface failed to map");
return Nothing();
} }
// No change gfx::IntSize size = dSurf->GetSize();
if (!aImageMgr->mIsChanged && texture == aImageMgr->mCurrentTexture) { wr::ImageDescriptor descriptor(size, map.mStride, dSurf->GetFormat());
// No need to update DisplayList.
return false; // Costly copy right here...
wr::Vec_u8 bytes;
bytes.PushBytes(Range<uint8_t>(map.mData, size.height * map.mStride));
if (aOp == TextureHost::UPDATE_IMAGE) {
aResources.UpdateImageBuffer(aKey, descriptor, bytes);
} else {
aResources.AddImage(aKey, descriptor, bytes);
} }
aImageMgr->mIsChanged = false; dSurf->Unmap();
if (texture == aImageMgr->mCurrentTexture) { return Some(aOp);
// Reuse previous ImageKeys.
aKeys.AppendElements(aImageMgr->mKeys);
aUseExternalImage = aImageMgr->mUseExternalImage;
return true;
}
// Delete old ImageKeys
aKeysToDelete.AppendElements(aImageMgr->mKeys);
aImageMgr->mKeys.Clear();
aImageMgr->mCurrentTexture = nullptr;
// No txture to render
if (!texture) {
return true;
}
aUseExternalImage = aImageMgr->mUseExternalImage = GenerateImageKeyForTextureHost(aResources, texture, aKeys);
MOZ_ASSERT(!aKeys.IsEmpty());
aImageMgr->mKeys.AppendElements(aKeys);
aImageMgr->mCurrentTexture = texture;
return true;
} }
void void
@ -258,67 +257,66 @@ AsyncImagePipelineManager::ApplyAsyncImages()
++mAsyncImageEpoch; // Update webrender epoch ++mAsyncImageEpoch; // Update webrender epoch
wr::Epoch epoch = wr::NewEpoch(mAsyncImageEpoch); wr::Epoch epoch = wr::NewEpoch(mAsyncImageEpoch);
nsTArray<wr::ImageKey> keysToDelete;
wr::ResourceUpdateQueue resourceUpdates;
// We use a pipeline with a very small display list for each video element.
// Update each of them if needed.
for (auto iter = mAsyncImagePipelines.Iter(); !iter.Done(); iter.Next()) { for (auto iter = mAsyncImagePipelines.Iter(); !iter.Done(); iter.Next()) {
wr::ResourceUpdateQueue resourceUpdates;
wr::PipelineId pipelineId = wr::AsPipelineId(iter.Key()); wr::PipelineId pipelineId = wr::AsPipelineId(iter.Key());
AsyncImagePipeline* pipeline = iter.Data(); AsyncImagePipeline* pipeline = iter.Data();
nsTArray<wr::ImageKey> keys; nsTArray<wr::ImageKey> keys;
bool useExternalImage = false; auto op = UpdateImageKeys(resourceUpdates, pipeline, keys);
bool updateDisplayList = UpdateImageKeys(resourceUpdates,
useExternalImage, if (op != Some(TextureHost::ADD_IMAGE)) {
pipeline, // We don't need to update the display list, either because we can't or because
keys, // the previous one is still up to date.
keysToDelete); // We may, however, have updated some resources.
if (!updateDisplayList) { mApi->UpdateResources(resourceUpdates);
continue; continue;
} }
wr::LayoutSize contentSize { pipeline->mScBounds.Width(), pipeline->mScBounds.Height() }; wr::LayoutSize contentSize { pipeline->mScBounds.Width(), pipeline->mScBounds.Height() };
wr::DisplayListBuilder builder(pipelineId, contentSize); wr::DisplayListBuilder builder(pipelineId, contentSize);
if (!keys.IsEmpty()) { MOZ_ASSERT(!keys.IsEmpty());
MOZ_ASSERT(pipeline->mCurrentTexture.get()); MOZ_ASSERT(pipeline->mCurrentTexture.get());
float opacity = 1.0f; float opacity = 1.0f;
builder.PushStackingContext(wr::ToLayoutRect(pipeline->mScBounds), builder.PushStackingContext(wr::ToLayoutRect(pipeline->mScBounds),
0, 0,
&opacity, &opacity,
pipeline->mScTransform.IsIdentity() ? nullptr : &pipeline->mScTransform, pipeline->mScTransform.IsIdentity() ? nullptr : &pipeline->mScTransform,
wr::TransformStyle::Flat, wr::TransformStyle::Flat,
nullptr, nullptr,
pipeline->mMixBlendMode, pipeline->mMixBlendMode,
nsTArray<wr::WrFilterOp>(), nsTArray<wr::WrFilterOp>(),
true); true);
LayerRect rect(0, 0, pipeline->mCurrentTexture->GetSize().width, pipeline->mCurrentTexture->GetSize().height); LayerRect rect(0, 0, pipeline->mCurrentTexture->GetSize().width, pipeline->mCurrentTexture->GetSize().height);
if (pipeline->mScaleToSize.isSome()) { if (pipeline->mScaleToSize.isSome()) {
rect = LayerRect(0, 0, pipeline->mScaleToSize.value().width, pipeline->mScaleToSize.value().height); rect = LayerRect(0, 0, pipeline->mScaleToSize.value().width, pipeline->mScaleToSize.value().height);
}
if (useExternalImage) {
MOZ_ASSERT(pipeline->mCurrentTexture->AsWebRenderTextureHost());
Range<const wr::ImageKey> range_keys(&keys[0], keys.Length());
pipeline->mCurrentTexture->PushExternalImage(builder,
wr::ToLayoutRect(rect),
wr::ToLayoutRect(rect),
pipeline->mFilter,
range_keys);
HoldExternalImage(pipelineId, epoch, pipeline->mCurrentTexture->AsWebRenderTextureHost());
} else {
MOZ_ASSERT(keys.Length() == 1);
builder.PushImage(wr::ToLayoutRect(rect),
wr::ToLayoutRect(rect),
true,
pipeline->mFilter,
keys[0]);
}
builder.PopStackingContext();
} }
if (pipeline->mUseExternalImage) {
MOZ_ASSERT(pipeline->mCurrentTexture->AsWebRenderTextureHost());
Range<wr::ImageKey> range_keys(&keys[0], keys.Length());
pipeline->mCurrentTexture->PushDisplayItems(builder,
wr::ToLayoutRect(rect),
wr::ToLayoutRect(rect),
pipeline->mFilter,
range_keys);
HoldExternalImage(pipelineId, epoch, pipeline->mCurrentTexture->AsWebRenderTextureHost());
} else {
MOZ_ASSERT(keys.Length() == 1);
builder.PushImage(wr::ToLayoutRect(rect),
wr::ToLayoutRect(rect),
true,
pipeline->mFilter,
keys[0]);
}
builder.PopStackingContext();
wr::BuiltDisplayList dl; wr::BuiltDisplayList dl;
wr::LayoutSize builderContentSize; wr::LayoutSize builderContentSize;
builder.Finalize(builderContentSize, dl); builder.Finalize(builderContentSize, dl);
@ -327,8 +325,6 @@ AsyncImagePipelineManager::ApplyAsyncImages()
dl.dl_desc, dl.dl.inner.data, dl.dl.inner.length, dl.dl_desc, dl.dl.inner.data, dl.dl.inner.length,
resourceUpdates); resourceUpdates);
} }
DeleteOldAsyncImages();
mKeysToDelete.SwapElements(keysToDelete);
} }
void void

View file

@ -42,7 +42,6 @@ protected:
public: public:
void Destroy(); void Destroy();
bool HasKeysToDelete();
void AddPipeline(const wr::PipelineId& aPipelineId); void AddPipeline(const wr::PipelineId& aPipelineId);
void RemovePipeline(const wr::PipelineId& aPipelineId, const wr::Epoch& aEpoch); void RemovePipeline(const wr::PipelineId& aPipelineId, const wr::Epoch& aEpoch);
@ -92,7 +91,6 @@ public:
} }
private: private:
void DeleteOldAsyncImages();
uint32_t GetNextResourceId() { return ++mResourceId; } uint32_t GetNextResourceId() { return ++mResourceId; }
wr::IdNamespace GetNamespace() { return mIdNamespace; } wr::IdNamespace GetNamespace() { return mIdNamespace; }
@ -103,9 +101,6 @@ private:
key.mHandle = GetNextResourceId(); key.mHandle = GetNextResourceId();
return key; return key;
} }
bool GenerateImageKeyForTextureHost(wr::ResourceUpdateQueue& aResources,
TextureHost* aTexture,
nsTArray<wr::ImageKey>& aKeys);
struct ForwardingTextureHost { struct ForwardingTextureHost {
ForwardingTextureHost(const wr::Epoch& aEpoch, TextureHost* aTexture) ForwardingTextureHost(const wr::Epoch& aEpoch, TextureHost* aTexture)
@ -138,11 +133,15 @@ private:
nsTArray<wr::ImageKey> mKeys; nsTArray<wr::ImageKey> mKeys;
}; };
bool UpdateImageKeys(wr::ResourceUpdateQueue& aResourceUpdates, Maybe<TextureHost::ResourceUpdateOp>
bool& aUseExternalImage, UpdateImageKeys(wr::ResourceUpdateQueue& aResourceUpdates,
AsyncImagePipeline* aImageMgr, AsyncImagePipeline* aPipeline,
nsTArray<wr::ImageKey>& aKeys, nsTArray<wr::ImageKey>& aKeys);
nsTArray<wr::ImageKey>& aKeysToDelete); Maybe<TextureHost::ResourceUpdateOp>
UpdateWithoutExternalImage(wr::ResourceUpdateQueue& aResources,
TextureHost* aTexture,
wr::ImageKey aKey,
TextureHost::ResourceUpdateOp);
RefPtr<wr::WebRenderAPI> mApi; RefPtr<wr::WebRenderAPI> mApi;
wr::IdNamespace mIdNamespace; wr::IdNamespace mIdNamespace;
@ -151,7 +150,6 @@ private:
nsClassHashtable<nsUint64HashKey, PipelineTexturesHolder> mPipelineTexturesHolders; nsClassHashtable<nsUint64HashKey, PipelineTexturesHolder> mPipelineTexturesHolders;
nsClassHashtable<nsUint64HashKey, AsyncImagePipeline> mAsyncImagePipelines; nsClassHashtable<nsUint64HashKey, AsyncImagePipeline> mAsyncImagePipelines;
uint32_t mAsyncImageEpoch; uint32_t mAsyncImageEpoch;
nsTArray<wr::ImageKey> mKeysToDelete;
bool mDestroyed; bool mDestroyed;
// Render time for the current composition. // Render time for the current composition.

View file

@ -334,7 +334,7 @@ bool
WebRenderBridgeParent::AddExternalImage(wr::ExternalImageId aExtId, wr::ImageKey aKey, WebRenderBridgeParent::AddExternalImage(wr::ExternalImageId aExtId, wr::ImageKey aKey,
wr::ResourceUpdateQueue& aResources) wr::ResourceUpdateQueue& aResources)
{ {
Range<const wr::ImageKey> keys(&aKey, 1); Range<wr::ImageKey> keys(&aKey, 1);
// Check if key is obsoleted. // Check if key is obsoleted.
if (keys[0].mNamespace != mIdNamespace) { if (keys[0].mNamespace != mIdNamespace) {
return true; return true;
@ -354,7 +354,8 @@ WebRenderBridgeParent::AddExternalImage(wr::ExternalImageId aExtId, wr::ImageKey
} }
WebRenderTextureHost* wrTexture = texture->AsWebRenderTextureHost(); WebRenderTextureHost* wrTexture = texture->AsWebRenderTextureHost();
if (wrTexture) { if (wrTexture) {
wrTexture->AddWRImage(aResources, keys, wrTexture->GetExternalImageKey()); wrTexture->PushResourceUpdates(aResources, TextureHost::ADD_IMAGE, keys,
wrTexture->GetExternalImageKey());
return true; return true;
} }
} }

View file

@ -24,16 +24,6 @@ void
WebRenderCanvasRenderer::Initialize(const CanvasInitializeData& aData) WebRenderCanvasRenderer::Initialize(const CanvasInitializeData& aData)
{ {
ShareableCanvasRenderer::Initialize(aData); ShareableCanvasRenderer::Initialize(aData);
// XXX: Use basic surface factory until we support shared surface.
if (!mGLContext || mGLFrontbuffer)
return;
gl::GLScreenBuffer* screen = mGLContext->Screen();
auto factory = MakeUnique<gl::SurfaceFactory_Basic>(mGLContext,
screen->mCaps,
mFlags);
screen->Morph(Move(factory));
} }
WebRenderCanvasRendererSync::~WebRenderCanvasRendererSync() WebRenderCanvasRendererSync::~WebRenderCanvasRendererSync()

View file

@ -134,38 +134,36 @@ WebRenderTextureHost::GetRGBStride()
return ImageDataSerializer::ComputeRGBStride(format, GetSize().width); return ImageDataSerializer::ComputeRGBStride(format, GetSize().width);
} }
void uint32_t
WebRenderTextureHost::GetWRImageKeys(nsTArray<wr::ImageKey>& aImageKeys, WebRenderTextureHost::NumSubTextures() const
const std::function<wr::ImageKey()>& aImageKeyAllocator)
{ {
MOZ_ASSERT(mWrappedTextureHost); MOZ_ASSERT(mWrappedTextureHost);
MOZ_ASSERT(aImageKeys.IsEmpty()); return mWrappedTextureHost->NumSubTextures();
mWrappedTextureHost->GetWRImageKeys(aImageKeys, aImageKeyAllocator);
} }
void void
WebRenderTextureHost::AddWRImage(wr::ResourceUpdateQueue& aResources, WebRenderTextureHost::PushResourceUpdates(wr::ResourceUpdateQueue& aResources,
Range<const wr::ImageKey>& aImageKeys, ResourceUpdateOp aOp,
const wr::ExternalImageId& aExtID) const Range<wr::ImageKey>& aImageKeys,
const wr::ExternalImageId& aExtID)
{ {
MOZ_ASSERT(mWrappedTextureHost); MOZ_ASSERT(mWrappedTextureHost);
MOZ_ASSERT(mExternalImageId == aExtID); MOZ_ASSERT(mExternalImageId == aExtID);
mWrappedTextureHost->AddWRImage(aResources, aImageKeys, aExtID); mWrappedTextureHost->PushResourceUpdates(aResources, aOp, aImageKeys, aExtID);
} }
void void
WebRenderTextureHost::PushExternalImage(wr::DisplayListBuilder& aBuilder, WebRenderTextureHost::PushDisplayItems(wr::DisplayListBuilder& aBuilder,
const wr::LayoutRect& aBounds, const wr::LayoutRect& aBounds,
const wr::LayoutRect& aClip, const wr::LayoutRect& aClip,
wr::ImageRendering aFilter, wr::ImageRendering aFilter,
Range<const wr::ImageKey>& aImageKeys) const Range<wr::ImageKey>& aImageKeys)
{ {
MOZ_ASSERT(mWrappedTextureHost); MOZ_ASSERT(mWrappedTextureHost);
MOZ_ASSERT(aImageKeys.length() > 0); MOZ_ASSERT(aImageKeys.length() > 0);
mWrappedTextureHost->PushExternalImage(aBuilder, mWrappedTextureHost->PushDisplayItems(aBuilder,
aBounds, aBounds,
aClip, aClip,
aFilter, aFilter,

View file

@ -63,18 +63,18 @@ public:
int32_t GetRGBStride(); int32_t GetRGBStride();
virtual void GetWRImageKeys(nsTArray<wr::ImageKey>& aImageKeys, virtual uint32_t NumSubTextures() const override;
const std::function<wr::ImageKey()>& aImageKeyAllocator) override;
virtual void AddWRImage(wr::ResourceUpdateQueue& aResources, virtual void PushResourceUpdates(wr::ResourceUpdateQueue& aResources,
Range<const wr::ImageKey>& aImageKeys, ResourceUpdateOp aOp,
const wr::ExternalImageId& aExtID) override; const Range<wr::ImageKey>& aImageKeys,
const wr::ExternalImageId& aExtID) override;
virtual void PushExternalImage(wr::DisplayListBuilder& aBuilder, virtual void PushDisplayItems(wr::DisplayListBuilder& aBuilder,
const wr::LayoutRect& aBounds, const wr::LayoutRect& aBounds,
const wr::LayoutRect& aClip, const wr::LayoutRect& aClip,
wr::ImageRendering aFilter, wr::ImageRendering aFilter,
Range<const wr::ImageKey>& aImageKeys) override; const Range<wr::ImageKey>& aImageKeys) override;
protected: protected:
void CreateRenderTextureHost(const SurfaceDescriptor& aDesc, TextureHost* aTexture); void CreateRenderTextureHost(const SurfaceDescriptor& aDesc, TextureHost* aTexture);

View file

@ -241,7 +241,7 @@ nsIconChannel::AsyncOpen(nsIStreamListener* aListener,
nsCOMPtr<nsIEventTarget> target = nsCOMPtr<nsIEventTarget> target =
nsContentUtils::GetEventTargetByLoadInfo(mLoadInfo, nsContentUtils::GetEventTargetByLoadInfo(mLoadInfo,
mozilla::TaskCategory::Other); mozilla::TaskCategory::Other);
rv = mPump->Init(inStream, int64_t(-1), int64_t(-1), 0, 0, false, target); rv = mPump->Init(inStream, 0, 0, false, target);
if (NS_FAILED(rv)) { if (NS_FAILED(rv)) {
mCallbacks = nullptr; mCallbacks = nullptr;
return rv; return rv;

View file

@ -256,7 +256,7 @@ nsIconChannel::AsyncOpen(nsIStreamListener* aListener,
nsCOMPtr<nsIEventTarget> target = nsCOMPtr<nsIEventTarget> target =
nsContentUtils::GetEventTargetByLoadInfo(mLoadInfo, nsContentUtils::GetEventTargetByLoadInfo(mLoadInfo,
mozilla::TaskCategory::Other); mozilla::TaskCategory::Other);
rv = mPump->Init(inStream, int64_t(-1), int64_t(-1), 0, 0, false, target); rv = mPump->Init(inStream, 0, 0, false, target);
if (NS_FAILED(rv)) { if (NS_FAILED(rv)) {
mCallbacks = nullptr; mCallbacks = nullptr;
return rv; return rv;

View file

@ -628,14 +628,15 @@ BackgroundChildImpl::RecvDispatchLocalStorageChange(
} }
bool bool
BackgroundChildImpl::GetMessageSchedulerGroups(const Message& aMsg, nsTArray<RefPtr<SchedulerGroup>>& aGroups) BackgroundChildImpl::GetMessageSchedulerGroups(const Message& aMsg, SchedulerGroupSet& aGroups)
{ {
if (aMsg.type() == layout::PVsync::MessageType::Msg_Notify__ID) { if (aMsg.type() == layout::PVsync::MessageType::Msg_Notify__ID) {
MOZ_ASSERT(NS_IsMainThread()); MOZ_ASSERT(NS_IsMainThread());
aGroups.Clear(); aGroups.Clear();
if (dom::TabChild::HasActiveTabs()) { if (dom::TabChild::HasActiveTabs()) {
for (dom::TabChild* tabChild : dom::TabChild::GetActiveTabs()) { for (auto iter = dom::TabChild::GetActiveTabs().ConstIter();
aGroups.AppendElement(tabChild->TabGroup()); !iter.Done(); iter.Next()) {
aGroups.Put(iter.Get()->GetKey()->TabGroup());
} }
} }
return true; return true;

View file

@ -224,7 +224,7 @@ protected:
const bool& aIsPrivate) override; const bool& aIsPrivate) override;
bool bool
GetMessageSchedulerGroups(const Message& aMsg, nsTArray<RefPtr<SchedulerGroup>>& aGroups) override; GetMessageSchedulerGroups(const Message& aMsg, SchedulerGroupSet& aGroups) override;
}; };
class BackgroundChildImpl::ThreadLocal final class BackgroundChildImpl::ThreadLocal final

View file

@ -1018,7 +1018,7 @@ MessageChannel::SendBuildID()
MonitorAutoLock lock(*mMonitor); MonitorAutoLock lock(*mMonitor);
if (!Connected()) { if (!Connected()) {
ReportConnectionError("MessageChannel", msg); ReportConnectionError("MessageChannel", msg);
MOZ_CRASH(); return;
} }
mLink->SendMessage(msg.forget()); mLink->SendMessage(msg.forget());
} }
@ -2002,7 +2002,7 @@ MessageChannel::MessageTask::GetPriority(uint32_t* aPriority)
} }
bool bool
MessageChannel::MessageTask::GetAffectedSchedulerGroups(nsTArray<RefPtr<SchedulerGroup>>& aGroups) MessageChannel::MessageTask::GetAffectedSchedulerGroups(SchedulerGroupSet& aGroups)
{ {
if (!mChannel) { if (!mChannel) {
return false; return false;

View file

@ -564,7 +564,7 @@ class MessageChannel : HasResultCodes, MessageLoop::DestructionObserver
Message& Msg() { return mMessage; } Message& Msg() { return mMessage; }
const Message& Msg() const { return mMessage; } const Message& Msg() const { return mMessage; }
bool GetAffectedSchedulerGroups(nsTArray<RefPtr<SchedulerGroup>>& aGroups) override; bool GetAffectedSchedulerGroups(SchedulerGroupSet& aGroups) override;
private: private:
MessageTask() = delete; MessageTask() = delete;

View file

@ -29,6 +29,7 @@
#include "mozilla/NotNull.h" #include "mozilla/NotNull.h"
#include "mozilla/UniquePtr.h" #include "mozilla/UniquePtr.h"
#include "MainThreadUtils.h" #include "MainThreadUtils.h"
#include "nsILabelableRunnable.h"
#if defined(ANDROID) && defined(DEBUG) #if defined(ANDROID) && defined(DEBUG)
#include <android/log.h> #include <android/log.h>
@ -268,6 +269,8 @@ protected:
~IToplevelProtocol(); ~IToplevelProtocol();
public: public:
using SchedulerGroupSet = nsILabelableRunnable::SchedulerGroupSet;
void SetTransport(UniquePtr<Transport> aTrans) void SetTransport(UniquePtr<Transport> aTrans)
{ {
mTrans = Move(aTrans); mTrans = Move(aTrans);
@ -388,7 +391,7 @@ public:
// when it's difficult to determine an EventTarget ahead of time. See the // when it's difficult to determine an EventTarget ahead of time. See the
// comment in nsILabelableRunnable.h for more information. // comment in nsILabelableRunnable.h for more information.
virtual bool virtual bool
GetMessageSchedulerGroups(const Message& aMsg, nsTArray<RefPtr<SchedulerGroup>>& aGroups) GetMessageSchedulerGroups(const Message& aMsg, SchedulerGroupSet& aGroups)
{ {
return false; return false;
} }

View file

@ -131,7 +131,7 @@ struct GCPointerPolicy
return false; return false;
} }
static bool isValid(T v) { static bool isValid(T v) {
return js::gc::IsCellPointerValid(v); return js::gc::IsCellPointerValidOrNull(v);
} }
}; };
template <> struct GCPolicy<JS::Symbol*> : public GCPointerPolicy<JS::Symbol*> {}; template <> struct GCPolicy<JS::Symbol*> : public GCPointerPolicy<JS::Symbol*> {};

View file

@ -406,8 +406,6 @@ IsInsideNursery(const js::gc::Cell* cell)
MOZ_ALWAYS_INLINE bool MOZ_ALWAYS_INLINE bool
IsCellPointerValid(const void* cell) IsCellPointerValid(const void* cell)
{ {
if (!cell)
return true;
auto addr = uintptr_t(cell); auto addr = uintptr_t(cell);
if (addr < ChunkSize || addr % CellAlignBytes != 0) if (addr < ChunkSize || addr % CellAlignBytes != 0)
return false; return false;
@ -419,6 +417,14 @@ IsCellPointerValid(const void* cell)
return false; return false;
} }
MOZ_ALWAYS_INLINE bool
IsCellPointerValidOrNull(const void* cell)
{
if (!cell)
return true;
return IsCellPointerValid(cell);
}
} /* namespace gc */ } /* namespace gc */
} /* namespace js */ } /* namespace js */

View file

@ -402,7 +402,7 @@ class TenuredHeap : public js::HeapBase<T, TenuredHeap<T>>
void setPtr(T newPtr) { void setPtr(T newPtr) {
MOZ_ASSERT((reinterpret_cast<uintptr_t>(newPtr) & flagsMask) == 0); MOZ_ASSERT((reinterpret_cast<uintptr_t>(newPtr) & flagsMask) == 0);
MOZ_ASSERT(js::gc::IsCellPointerValid(newPtr)); MOZ_ASSERT(js::gc::IsCellPointerValidOrNull(newPtr));
if (newPtr) if (newPtr)
AssertGCThingMustBeTenured(newPtr); AssertGCThingMustBeTenured(newPtr);
bits = (bits & flagsMask) | reinterpret_cast<uintptr_t>(newPtr); bits = (bits & flagsMask) | reinterpret_cast<uintptr_t>(newPtr);

View file

@ -317,9 +317,8 @@ function ModuleInstantiate()
if (stack.length === 0 && if (stack.length === 0 &&
typeof(UnsafeGetReservedSlot(module, MODULE_OBJECT_ERROR_SLOT)) === "undefined") typeof(UnsafeGetReservedSlot(module, MODULE_OBJECT_ERROR_SLOT)) === "undefined")
{ {
// This can happen due to OOM when appending to the stack. // This can happen due to OOM when appending to the stack or
assert(error === "out of memory", // over-recursion errors.
"Stack must contain module unless we hit OOM");
RecordModuleError(module, error); RecordModuleError(module, error);
} }
@ -542,9 +541,8 @@ function ModuleEvaluate()
if (stack.length === 0 && if (stack.length === 0 &&
typeof(UnsafeGetReservedSlot(module, MODULE_OBJECT_ERROR_SLOT)) === "undefined") typeof(UnsafeGetReservedSlot(module, MODULE_OBJECT_ERROR_SLOT)) === "undefined")
{ {
// This can happen due to OOM when appending to the stack. // This can happen due to OOM when appending to the stack or
assert(error === "out of memory", // over-recursion errors.
"Stack must contain module unless we hit OOM");
RecordModuleError(module, error); RecordModuleError(module, error);
} }

View file

@ -6,6 +6,8 @@
#include "builtin/ModuleObject.h" #include "builtin/ModuleObject.h"
#include "mozilla/EnumSet.h"
#include "builtin/SelfHostingDefines.h" #include "builtin/SelfHostingDefines.h"
#include "frontend/ParseNode.h" #include "frontend/ParseNode.h"
#include "frontend/SharedContext.h" #include "frontend/SharedContext.h"
@ -889,29 +891,41 @@ ModuleObject::Freeze(JSContext* cx, HandleModuleObject self)
#ifdef DEBUG #ifdef DEBUG
static inline bool static inline bool
IsObjectFrozen(JSContext* cx, HandleObject obj) CheckObjectFrozen(JSContext* cx, HandleObject obj, bool* result)
{ {
bool frozen = false; return TestIntegrityLevel(cx, obj, IntegrityLevel::Frozen, result);
MOZ_ALWAYS_TRUE(TestIntegrityLevel(cx, obj, IntegrityLevel::Frozen, &frozen));
return frozen;
} }
static inline bool static inline bool
IsObjectPropertyFrozen(JSContext* cx, HandleNativeObject obj, uint32_t slot) CheckObjectPropertyFrozen(JSContext* cx, HandleNativeObject obj, uint32_t slot, bool* result)
{ {
RootedObject property(cx, &obj->getSlot(slot).toObject()); RootedObject property(cx, &obj->getSlot(slot).toObject());
return IsObjectFrozen(cx, property); return CheckObjectFrozen(cx, property, result);
} }
/* static */ inline bool /* static */ inline bool
ModuleObject::IsFrozen(JSContext* cx, HandleModuleObject self) ModuleObject::AssertFrozen(JSContext* cx, HandleModuleObject self)
{ {
return IsObjectPropertyFrozen(cx, self, RequestedModulesSlot) && static const mozilla::EnumSet<ModuleSlot> slotsToCheck = {
IsObjectPropertyFrozen(cx, self, ImportEntriesSlot) && RequestedModulesSlot,
IsObjectPropertyFrozen(cx, self, LocalExportEntriesSlot) && ImportEntriesSlot,
IsObjectPropertyFrozen(cx, self, IndirectExportEntriesSlot) && LocalExportEntriesSlot,
IsObjectPropertyFrozen(cx, self, StarExportEntriesSlot) && IndirectExportEntriesSlot,
IsObjectFrozen(cx, self); StarExportEntriesSlot
};
bool frozen = false;
for (auto slot : slotsToCheck) {
if (!CheckObjectPropertyFrozen(cx, self, slot, &frozen))
return false;
MOZ_ASSERT(frozen);
}
if (!CheckObjectFrozen(cx, self, &frozen))
return false;
MOZ_ASSERT(frozen);
return true;
} }
#endif #endif
@ -1034,7 +1048,10 @@ ModuleObject::noteFunctionDeclaration(JSContext* cx, HandleAtom name, HandleFunc
/* static */ bool /* static */ bool
ModuleObject::instantiateFunctionDeclarations(JSContext* cx, HandleModuleObject self) ModuleObject::instantiateFunctionDeclarations(JSContext* cx, HandleModuleObject self)
{ {
MOZ_ASSERT(IsFrozen(cx, self)); #ifdef DEBUG
if (!AssertFrozen(cx, self))
return false;
#endif
FunctionDeclarationVector* funDecls = self->functionDeclarations(); FunctionDeclarationVector* funDecls = self->functionDeclarations();
if (!funDecls) { if (!funDecls) {
@ -1061,6 +1078,9 @@ ModuleObject::instantiateFunctionDeclarations(JSContext* cx, HandleModuleObject
} }
} }
if (!obj)
return false;
value = ObjectValue(*obj); value = ObjectValue(*obj);
if (!SetProperty(cx, env, funDecl.name->asPropertyName(), value)) if (!SetProperty(cx, env, funDecl.name->asPropertyName(), value))
return false; return false;
@ -1074,7 +1094,10 @@ ModuleObject::instantiateFunctionDeclarations(JSContext* cx, HandleModuleObject
/* static */ bool /* static */ bool
ModuleObject::execute(JSContext* cx, HandleModuleObject self, MutableHandleValue rval) ModuleObject::execute(JSContext* cx, HandleModuleObject self, MutableHandleValue rval)
{ {
MOZ_ASSERT(IsFrozen(cx, self)); #ifdef DEBUG
if (!AssertFrozen(cx, self))
return false;
#endif
RootedScript script(cx, self->script()); RootedScript script(cx, self->script());
RootedModuleEnvironmentObject scope(cx, self->environment()); RootedModuleEnvironmentObject scope(cx, self->environment());

View file

@ -236,7 +236,7 @@ using ModuleStatus = int32_t;
class ModuleObject : public NativeObject class ModuleObject : public NativeObject
{ {
public: public:
enum enum ModuleSlot
{ {
ScriptSlot = 0, ScriptSlot = 0,
InitialEnvironmentSlot, InitialEnvironmentSlot,
@ -284,7 +284,7 @@ class ModuleObject : public NativeObject
HandleArrayObject starExportEntries); HandleArrayObject starExportEntries);
static bool Freeze(JSContext* cx, HandleModuleObject self); static bool Freeze(JSContext* cx, HandleModuleObject self);
#ifdef DEBUG #ifdef DEBUG
static bool IsFrozen(JSContext* cx, HandleModuleObject self); static bool AssertFrozen(JSContext* cx, HandleModuleObject self);
#endif #endif
void fixEnvironmentsAfterCompartmentMerge(); void fixEnvironmentsAfterCompartmentMerge();

View file

@ -6120,7 +6120,7 @@ StructType::DefineInternal(JSContext* cx, JSObject* typeObj_, JSObject* fieldsOb
nameChars.twoByteChars(), name->length(), nameChars.twoByteChars(), name->length(),
JS_DATA_TO_FUNC_PTR(JSNative, getterObj.get()), JS_DATA_TO_FUNC_PTR(JSNative, getterObj.get()),
JS_DATA_TO_FUNC_PTR(JSNative, setterObj.get()), JS_DATA_TO_FUNC_PTR(JSNative, setterObj.get()),
JSPROP_SHARED | JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_GETTER | JSPROP_SETTER)) JSPROP_ENUMERATE | JSPROP_PERMANENT | JSPROP_GETTER | JSPROP_SETTER))
{ {
return false; return false;
} }

View file

@ -127,7 +127,7 @@ struct InternalGCPointerPolicy {
TraceManuallyBarrieredEdge(trc, vp, name); TraceManuallyBarrieredEdge(trc, vp, name);
} }
static bool isValid(T v) { static bool isValid(T v) {
return gc::IsCellPointerValid(v); return gc::IsCellPointerValidOrNull(v);
} }
}; };

View file

@ -65,7 +65,7 @@ ZoneGroup::enter(JSContext* cx)
if (ownerContext().context() == cx) { if (ownerContext().context() == cx) {
MOZ_ASSERT(enterCount); MOZ_ASSERT(enterCount);
} else { } else {
if (useExclusiveLocking) { if (useExclusiveLocking()) {
MOZ_ASSERT(!usedByHelperThread()); MOZ_ASSERT(!usedByHelperThread());
while (ownerContext().context() != nullptr) { while (ownerContext().context() != nullptr) {
cx->yieldToEmbedding(); cx->yieldToEmbedding();

View file

@ -43,7 +43,7 @@ class ZoneGroup
// If this flag is true, then we may need to block before entering this zone // If this flag is true, then we may need to block before entering this zone
// group. Blocking happens using JSContext::yieldToEmbedding. // group. Blocking happens using JSContext::yieldToEmbedding.
UnprotectedData<bool> useExclusiveLocking; UnprotectedData<bool> useExclusiveLocking_;
public: public:
CooperatingContext& ownerContext() { return ownerContext_.ref(); } CooperatingContext& ownerContext() { return ownerContext_.ref(); }
@ -102,8 +102,9 @@ class ZoneGroup
inline bool isCollecting(); inline bool isCollecting();
inline bool isGCScheduled(); inline bool isGCScheduled();
// See the useExclusiveLocking field above. // See the useExclusiveLocking_ field above.
void setUseExclusiveLocking() { useExclusiveLocking = true; } void setUseExclusiveLocking() { useExclusiveLocking_ = true; }
bool useExclusiveLocking() { return useExclusiveLocking_; }
// Delete an empty zone after its contents have been merged. // Delete an empty zone after its contents have been merged.
void deleteEmptyZone(Zone* zone); void deleteEmptyZone(Zone* zone);

View file

@ -0,0 +1,7 @@
if (!('stackTest' in this))
quit();
stackTest(function() {
let m = parseModule(``);
m.declarationInstantiation();
});

View file

@ -0,0 +1,15 @@
if (!('oomTest' in this))
quit();
loadFile(`
function parseAndEvaluate(source) {
let m = parseModule(source);
m.declarationInstantiation();
}
parseAndEvaluate("async function a() { await 2 + 3; }")
`);
function loadFile(lfVarx) {
oomTest(function() {
eval(lfVarx);
});
}

View file

@ -36,12 +36,12 @@ BEGIN_TEST(testDefineGetterSetterNonEnumerable)
CHECK(JS_DefineProperty(cx, vObject, PROPERTY_NAME, CHECK(JS_DefineProperty(cx, vObject, PROPERTY_NAME,
JS_DATA_TO_FUNC_PTR(JSNative, (JSObject*) funGetObj), JS_DATA_TO_FUNC_PTR(JSNative, (JSObject*) funGetObj),
JS_DATA_TO_FUNC_PTR(JSNative, (JSObject*) funSetObj), JS_DATA_TO_FUNC_PTR(JSNative, (JSObject*) funSetObj),
JSPROP_GETTER | JSPROP_SETTER | JSPROP_SHARED | JSPROP_ENUMERATE)); JSPROP_GETTER | JSPROP_SETTER | JSPROP_ENUMERATE));
CHECK(JS_DefineProperty(cx, vObject, PROPERTY_NAME, CHECK(JS_DefineProperty(cx, vObject, PROPERTY_NAME,
JS_DATA_TO_FUNC_PTR(JSNative, (JSObject*) funGetObj), JS_DATA_TO_FUNC_PTR(JSNative, (JSObject*) funGetObj),
JS_DATA_TO_FUNC_PTR(JSNative, (JSObject*) funSetObj), JS_DATA_TO_FUNC_PTR(JSNative, (JSObject*) funSetObj),
JSPROP_GETTER | JSPROP_SETTER | JSPROP_SHARED | JSPROP_PERMANENT)); JSPROP_GETTER | JSPROP_SETTER | JSPROP_PERMANENT));
JS::Rooted<JS::PropertyDescriptor> desc(cx); JS::Rooted<JS::PropertyDescriptor> desc(cx);
CHECK(JS_GetOwnPropertyDescriptor(cx, vObject, PROPERTY_NAME, &desc)); CHECK(JS_GetOwnPropertyDescriptor(cx, vObject, PROPERTY_NAME, &desc));

View file

@ -17,7 +17,7 @@ BEGIN_TEST(testDefineProperty_bug564344)
JS::RootedObject obj(cx, x.toObjectOrNull()); JS::RootedObject obj(cx, x.toObjectOrNull());
for (int i = 0; i < 2; i++) for (int i = 0; i < 2; i++)
CHECK(JS_DefineProperty(cx, obj, "q", JS::UndefinedHandleValue, JSPROP_SHARED)); CHECK(JS_DefineProperty(cx, obj, "q", JS::UndefinedHandleValue, 0));
return true; return true;
} }
END_TEST(testDefineProperty_bug564344) END_TEST(testDefineProperty_bug564344)

View file

@ -47,7 +47,7 @@ BEGIN_TEST(testDefinePropertyIgnoredAttributes)
// aren't passing it. // aren't passing it.
CHECK(JS_DefineProperty(cx, obj, "foo", CHECK(JS_DefineProperty(cx, obj, "foo",
Getter, nullptr, Getter, nullptr,
JSPROP_IGNORE_ENUMERATE | JSPROP_IGNORE_PERMANENT | JSPROP_SHARED)); JSPROP_IGNORE_ENUMERATE | JSPROP_IGNORE_PERMANENT));
CHECK(JS_GetOwnPropertyDescriptor(cx, obj, "foo", &desc)); CHECK(JS_GetOwnPropertyDescriptor(cx, obj, "foo", &desc));
@ -57,7 +57,7 @@ BEGIN_TEST(testDefinePropertyIgnoredAttributes)
// Install another configurable property, so we can futz with it. // Install another configurable property, so we can futz with it.
CHECK(JS_DefineProperty(cx, obj, "bar", CHECK(JS_DefineProperty(cx, obj, "bar",
Getter, nullptr, Getter, nullptr,
JSPROP_IGNORE_ENUMERATE | JSPROP_SHARED)); JSPROP_IGNORE_ENUMERATE));
CHECK(JS_GetOwnPropertyDescriptor(cx, obj, "bar", &desc)); CHECK(JS_GetOwnPropertyDescriptor(cx, obj, "bar", &desc));
CHECK(CheckDescriptor(desc, AccessorDescriptor, false, true, true)); CHECK(CheckDescriptor(desc, AccessorDescriptor, false, true, true));
@ -65,7 +65,7 @@ BEGIN_TEST(testDefinePropertyIgnoredAttributes)
// unchanged. // unchanged.
CHECK(JS_DefineProperty(cx, obj, "bar", CHECK(JS_DefineProperty(cx, obj, "bar",
Getter, nullptr, Getter, nullptr,
JSPROP_IGNORE_PERMANENT | JSPROP_ENUMERATE | JSPROP_SHARED)); JSPROP_IGNORE_PERMANENT | JSPROP_ENUMERATE));
CHECK(JS_GetOwnPropertyDescriptor(cx, obj, "bar", &desc)); CHECK(JS_GetOwnPropertyDescriptor(cx, obj, "bar", &desc));
CHECK(CheckDescriptor(desc, AccessorDescriptor, true, true, true)); CHECK(CheckDescriptor(desc, AccessorDescriptor, true, true, true));

View file

@ -16,7 +16,7 @@ BEGIN_TEST(testSetProperty_NativeGetterStubSetter)
CHECK(JS_DefineProperty(cx, obj, "prop", CHECK(JS_DefineProperty(cx, obj, "prop",
JS_PROPERTYOP_GETTER(NativeGet), nullptr, JS_PROPERTYOP_GETTER(NativeGet), nullptr,
JSPROP_SHARED | JSPROP_PROPOP_ACCESSORS)); JSPROP_PROPOP_ACCESSORS));
EXEC("'use strict'; \n" EXEC("'use strict'; \n"
"var error, passed = false; \n" "var error, passed = false; \n"

View file

@ -875,11 +875,6 @@ static const uint8_t JSPROP_GETTER = 0x10;
/* property holds setter function */ /* property holds setter function */
static const uint8_t JSPROP_SETTER = 0x20; static const uint8_t JSPROP_SETTER = 0x20;
/* don't allocate a value slot for this property; don't copy the property on set
of the same-named property in an object that delegates to a prototype
containing this property */
static const uint8_t JSPROP_SHARED = 0x40;
/* internal JS engine use only */ /* internal JS engine use only */
static const uint8_t JSPROP_INTERNAL_USE_BIT = 0x80; static const uint8_t JSPROP_INTERNAL_USE_BIT = 0x80;
@ -2278,23 +2273,23 @@ inline int CheckIsSetterOp(JSSetterOp op);
*/ */
#define JS_PSG(name, getter, flags) \ #define JS_PSG(name, getter, flags) \
JS_PS_ACCESSOR_SPEC(name, JSNATIVE_WRAPPER(getter), JSNATIVE_WRAPPER(nullptr), flags, \ JS_PS_ACCESSOR_SPEC(name, JSNATIVE_WRAPPER(getter), JSNATIVE_WRAPPER(nullptr), flags, \
JSPROP_SHARED) 0)
#define JS_PSGS(name, getter, setter, flags) \ #define JS_PSGS(name, getter, setter, flags) \
JS_PS_ACCESSOR_SPEC(name, JSNATIVE_WRAPPER(getter), JSNATIVE_WRAPPER(setter), flags, \ JS_PS_ACCESSOR_SPEC(name, JSNATIVE_WRAPPER(getter), JSNATIVE_WRAPPER(setter), flags, \
JSPROP_SHARED) 0)
#define JS_SYM_GET(symbol, getter, flags) \ #define JS_SYM_GET(symbol, getter, flags) \
JS_PS_ACCESSOR_SPEC(reinterpret_cast<const char*>(uint32_t(::JS::SymbolCode::symbol) + 1), \ JS_PS_ACCESSOR_SPEC(reinterpret_cast<const char*>(uint32_t(::JS::SymbolCode::symbol) + 1), \
JSNATIVE_WRAPPER(getter), JSNATIVE_WRAPPER(nullptr), flags, JSPROP_SHARED) JSNATIVE_WRAPPER(getter), JSNATIVE_WRAPPER(nullptr), flags, 0)
#define JS_SELF_HOSTED_GET(name, getterName, flags) \ #define JS_SELF_HOSTED_GET(name, getterName, flags) \
JS_PS_ACCESSOR_SPEC(name, SELFHOSTED_WRAPPER(getterName), JSNATIVE_WRAPPER(nullptr), flags, \ JS_PS_ACCESSOR_SPEC(name, SELFHOSTED_WRAPPER(getterName), JSNATIVE_WRAPPER(nullptr), flags, \
JSPROP_SHARED | JSPROP_GETTER) JSPROP_GETTER)
#define JS_SELF_HOSTED_GETSET(name, getterName, setterName, flags) \ #define JS_SELF_HOSTED_GETSET(name, getterName, setterName, flags) \
JS_PS_ACCESSOR_SPEC(name, SELFHOSTED_WRAPPER(getterName), SELFHOSTED_WRAPPER(setterName), \ JS_PS_ACCESSOR_SPEC(name, SELFHOSTED_WRAPPER(getterName), SELFHOSTED_WRAPPER(setterName), \
flags, JSPROP_SHARED | JSPROP_GETTER | JSPROP_SETTER) flags, JSPROP_GETTER | JSPROP_SETTER)
#define JS_SELF_HOSTED_SYM_GET(symbol, getterName, flags) \ #define JS_SELF_HOSTED_SYM_GET(symbol, getterName, flags) \
JS_PS_ACCESSOR_SPEC(reinterpret_cast<const char*>(uint32_t(::JS::SymbolCode::symbol) + 1), \ JS_PS_ACCESSOR_SPEC(reinterpret_cast<const char*>(uint32_t(::JS::SymbolCode::symbol) + 1), \
SELFHOSTED_WRAPPER(getterName), JSNATIVE_WRAPPER(nullptr), flags, \ SELFHOSTED_WRAPPER(getterName), JSNATIVE_WRAPPER(nullptr), flags, \
JSPROP_SHARED | JSPROP_GETTER) JSPROP_GETTER)
#define JS_STRING_PS(name, string, flags) \ #define JS_STRING_PS(name, string, flags) \
JS_PS_VALUE_SPEC(name, STRINGVALUE_WRAPPER(string), flags) JS_PS_VALUE_SPEC(name, STRINGVALUE_WRAPPER(string), flags)
#define JS_STRING_SYM_PS(symbol, string, flags) \ #define JS_STRING_SYM_PS(symbol, string, flags) \
@ -2864,7 +2859,6 @@ class WrappedPtrOperations<JS::PropertyDescriptor, Wrapper>
} }
bool hasGetterOrSetter() const { return desc().getter || desc().setter; } bool hasGetterOrSetter() const { return desc().getter || desc().setter; }
bool isShared() const { return has(JSPROP_SHARED); }
JS::HandleObject object() const { JS::HandleObject object() const {
return JS::HandleObject::fromMarkedLocation(&desc().obj); return JS::HandleObject::fromMarkedLocation(&desc().obj);
@ -2881,14 +2875,12 @@ class WrappedPtrOperations<JS::PropertyDescriptor, Wrapper>
JSPROP_IGNORE_VALUE | JSPROP_IGNORE_VALUE |
JSPROP_GETTER | JSPROP_GETTER |
JSPROP_SETTER | JSPROP_SETTER |
JSPROP_SHARED |
JSPROP_REDEFINE_NONCONFIGURABLE | JSPROP_REDEFINE_NONCONFIGURABLE |
JSPROP_RESOLVING | JSPROP_RESOLVING |
SHADOWABLE)) == 0); SHADOWABLE)) == 0);
MOZ_ASSERT(!hasAll(JSPROP_IGNORE_ENUMERATE | JSPROP_ENUMERATE)); MOZ_ASSERT(!hasAll(JSPROP_IGNORE_ENUMERATE | JSPROP_ENUMERATE));
MOZ_ASSERT(!hasAll(JSPROP_IGNORE_PERMANENT | JSPROP_PERMANENT)); MOZ_ASSERT(!hasAll(JSPROP_IGNORE_PERMANENT | JSPROP_PERMANENT));
if (isAccessorDescriptor()) { if (isAccessorDescriptor()) {
MOZ_ASSERT(has(JSPROP_SHARED));
MOZ_ASSERT(!has(JSPROP_READONLY)); MOZ_ASSERT(!has(JSPROP_READONLY));
MOZ_ASSERT(!has(JSPROP_IGNORE_READONLY)); MOZ_ASSERT(!has(JSPROP_IGNORE_READONLY));
MOZ_ASSERT(!has(JSPROP_IGNORE_VALUE)); MOZ_ASSERT(!has(JSPROP_IGNORE_VALUE));
@ -2917,7 +2909,6 @@ class WrappedPtrOperations<JS::PropertyDescriptor, Wrapper>
JSPROP_READONLY | JSPROP_READONLY |
JSPROP_GETTER | JSPROP_GETTER |
JSPROP_SETTER | JSPROP_SETTER |
JSPROP_SHARED |
JSPROP_REDEFINE_NONCONFIGURABLE | JSPROP_REDEFINE_NONCONFIGURABLE |
JSPROP_RESOLVING | JSPROP_RESOLVING |
SHADOWABLE)) == 0); SHADOWABLE)) == 0);
@ -3018,12 +3009,12 @@ class MutableWrappedPtrOperations<JS::PropertyDescriptor, Wrapper>
void setGetterObject(JSObject* obj) { void setGetterObject(JSObject* obj) {
desc().getter = reinterpret_cast<JSGetterOp>(obj); desc().getter = reinterpret_cast<JSGetterOp>(obj);
desc().attrs &= ~(JSPROP_IGNORE_VALUE | JSPROP_IGNORE_READONLY | JSPROP_READONLY); desc().attrs &= ~(JSPROP_IGNORE_VALUE | JSPROP_IGNORE_READONLY | JSPROP_READONLY);
desc().attrs |= JSPROP_GETTER | JSPROP_SHARED; desc().attrs |= JSPROP_GETTER;
} }
void setSetterObject(JSObject* obj) { void setSetterObject(JSObject* obj) {
desc().setter = reinterpret_cast<JSSetterOp>(obj); desc().setter = reinterpret_cast<JSSetterOp>(obj);
desc().attrs &= ~(JSPROP_IGNORE_VALUE | JSPROP_IGNORE_READONLY | JSPROP_READONLY); desc().attrs &= ~(JSPROP_IGNORE_VALUE | JSPROP_IGNORE_READONLY | JSPROP_READONLY);
desc().attrs |= JSPROP_SETTER | JSPROP_SHARED; desc().attrs |= JSPROP_SETTER;
} }
JS::MutableHandleObject getterObject() { JS::MutableHandleObject getterObject() {

View file

@ -1047,7 +1047,7 @@ AddLengthProperty(JSContext* cx, HandleArrayObject obj)
return NativeObject::addProperty(cx, obj, lengthId, array_length_getter, array_length_setter, return NativeObject::addProperty(cx, obj, lengthId, array_length_getter, array_length_setter,
SHAPE_INVALID_SLOT, SHAPE_INVALID_SLOT,
JSPROP_PERMANENT | JSPROP_SHARED | JSPROP_SHADOWABLE, JSPROP_PERMANENT | JSPROP_SHADOWABLE,
0, /* allowDictionary = */ false); 0, /* allowDictionary = */ false);
} }

View file

@ -8081,13 +8081,19 @@ JS::AssertGCThingIsNotAnObjectSubclass(Cell* cell)
JS_FRIEND_API(void) JS_FRIEND_API(void)
js::gc::AssertGCThingHasType(js::gc::Cell* cell, JS::TraceKind kind) js::gc::AssertGCThingHasType(js::gc::Cell* cell, JS::TraceKind kind)
{ {
MOZ_ASSERT(IsCellPointerValid(cell)); if (!cell) {
if (!cell)
MOZ_ASSERT(kind == JS::TraceKind::Null); MOZ_ASSERT(kind == JS::TraceKind::Null);
else if (IsInsideNursery(cell)) return;
}
MOZ_ASSERT(IsCellPointerValid(cell));
if (IsInsideNursery(cell)) {
MOZ_ASSERT(kind == JS::TraceKind::Object); MOZ_ASSERT(kind == JS::TraceKind::Object);
else return;
MOZ_ASSERT(MapAllocToTraceKind(cell->asTenured().getAllocKind()) == kind); }
MOZ_ASSERT(MapAllocToTraceKind(cell->asTenured().getAllocKind()) == kind);
} }
#endif #endif
@ -8651,7 +8657,7 @@ NewMemoryInfoObject(JSContext* cx)
#endif #endif
if (!JS_DefineProperty(cx, obj, pair.name, if (!JS_DefineProperty(cx, obj, pair.name,
getter, nullptr, getter, nullptr,
JSPROP_ENUMERATE | JSPROP_SHARED)) JSPROP_ENUMERATE))
{ {
return nullptr; return nullptr;
} }
@ -8686,7 +8692,7 @@ NewMemoryInfoObject(JSContext* cx)
#endif #endif
if (!JS_DefineProperty(cx, zoneObj, pair.name, if (!JS_DefineProperty(cx, zoneObj, pair.name,
getter, nullptr, getter, nullptr,
JSPROP_ENUMERATE | JSPROP_SHARED)) JSPROP_ENUMERATE))
{ {
return nullptr; return nullptr;
} }

View file

@ -361,7 +361,7 @@ js::ToPropertyDescriptor(JSContext* cx, HandleValue descval, bool checkAccessors
js_getter_str); js_getter_str);
return false; return false;
} }
attrs |= JSPROP_GETTER | JSPROP_SHARED; attrs |= JSPROP_GETTER;
} }
// step 9 // step 9
@ -379,7 +379,7 @@ js::ToPropertyDescriptor(JSContext* cx, HandleValue descval, bool checkAccessors
js_setter_str); js_setter_str);
return false; return false;
} }
attrs |= JSPROP_SETTER | JSPROP_SHARED; attrs |= JSPROP_SETTER;
} }
// step 10 // step 10
@ -395,7 +395,6 @@ js::ToPropertyDescriptor(JSContext* cx, HandleValue descval, bool checkAccessors
desc.setAttributes(attrs); desc.setAttributes(attrs);
MOZ_ASSERT_IF(attrs & JSPROP_READONLY, !(attrs & (JSPROP_GETTER | JSPROP_SETTER))); MOZ_ASSERT_IF(attrs & JSPROP_READONLY, !(attrs & (JSPROP_GETTER | JSPROP_SETTER)));
MOZ_ASSERT_IF(attrs & (JSPROP_GETTER | JSPROP_SETTER), attrs & JSPROP_SHARED);
return true; return true;
} }
@ -425,7 +424,7 @@ js::CompletePropertyDescriptor(MutableHandle<PropertyDescriptor> desc)
desc.setGetterObject(nullptr); desc.setGetterObject(nullptr);
if (!desc.hasSetterObject()) if (!desc.hasSetterObject())
desc.setSetterObject(nullptr); desc.setSetterObject(nullptr);
desc.attributesRef() |= JSPROP_GETTER | JSPROP_SETTER | JSPROP_SHARED; desc.attributesRef() |= JSPROP_GETTER | JSPROP_SETTER;
} }
if (!desc.hasConfigurable()) if (!desc.hasConfigurable())
desc.attributesRef() |= JSPROP_PERMANENT; desc.attributesRef() |= JSPROP_PERMANENT;
@ -3526,7 +3525,6 @@ DumpProperty(const NativeObject* obj, Shape& shape, js::GenericPrinter& out)
if (attrs & JSPROP_ENUMERATE) out.put("enumerate "); if (attrs & JSPROP_ENUMERATE) out.put("enumerate ");
if (attrs & JSPROP_READONLY) out.put("readonly "); if (attrs & JSPROP_READONLY) out.put("readonly ");
if (attrs & JSPROP_PERMANENT) out.put("permanent "); if (attrs & JSPROP_PERMANENT) out.put("permanent ");
if (attrs & JSPROP_SHARED) out.put("shared ");
if (shape.hasGetterValue()) if (shape.hasGetterValue())
out.printf("getterValue=%p ", (void*) shape.getterObject()); out.printf("getterValue=%p ", (void*) shape.getterObject());

View file

@ -1447,6 +1447,9 @@ ConvertTranscodeResultToJSException(JSContext* cx, JS::TranscodeResult rv)
} }
} }
static bool
CooperativeThreadMayYield(JSContext* cx);
static bool static bool
Evaluate(JSContext* cx, unsigned argc, Value* vp) Evaluate(JSContext* cx, unsigned argc, Value* vp)
{ {
@ -1538,14 +1541,25 @@ Evaluate(JSContext* cx, unsigned argc, Value* vp)
return false; return false;
} }
// Find all eligible globals to execute in: any global in another // Find all eligible globals to execute in.
// zone group which has not been entered by a cooperative thread.
JS::AutoObjectVector eligibleGlobals(cx); JS::AutoObjectVector eligibleGlobals(cx);
for (CompartmentsIter c(cx->runtime(), SkipAtoms); !c.done(); c.next()) { for (CompartmentsIter c(cx->runtime(), SkipAtoms); !c.done(); c.next()) {
if (!c->zone()->group()->ownerContext().context() && // Compartments without globals and the self hosting global may
c->maybeGlobal() && // not be entered.
!cx->runtime()->isSelfHostingGlobal(c->maybeGlobal())) if (!c->maybeGlobal() || cx->runtime()->isSelfHostingGlobal(c->maybeGlobal()))
{ continue;
// Globals in zone groups which are not in use by a cooperative
// thread may be entered.
if (!c->zone()->group()->ownerContext().context()) {
if (!eligibleGlobals.append(c->maybeGlobal()))
return false;
}
// Globals in zone groups which use exclusive locking may be
// entered, in which case this thread will yield until the zone
// group is available.
if (c->zone()->group()->useExclusiveLocking() && CooperativeThreadMayYield(cx)) {
if (!eligibleGlobals.append(c->maybeGlobal())) if (!eligibleGlobals.append(c->maybeGlobal()))
return false; return false;
} }
@ -3337,24 +3351,16 @@ CooperativeYield()
} }
static bool static bool
CooperativeYieldThread(JSContext* cx, unsigned argc, Value* vp) CooperativeThreadMayYield(JSContext* cx)
{ {
CallArgs args = CallArgsFromVp(argc, vp); if (!cx->runtime()->gc.canChangeActiveContext(cx))
if (!cx->runtime()->gc.canChangeActiveContext(cx)) {
JS_ReportErrorASCII(cx, "Cooperating multithreading context switches are not currently allowed");
return false; return false;
}
if (GetShellContext(cx)->isWorker) { if (GetShellContext(cx)->isWorker)
JS_ReportErrorASCII(cx, "Worker threads cannot yield");
return false; return false;
}
if (cooperationState->singleThreaded) { if (cooperationState->singleThreaded)
JS_ReportErrorASCII(cx, "Yielding is not allowed while single threaded");
return false; return false;
}
// To avoid contention issues between threads, yields are not allowed while // To avoid contention issues between threads, yields are not allowed while
// a thread has access to zone groups other than its original one, i.e. if // a thread has access to zone groups other than its original one, i.e. if
@ -3364,10 +3370,30 @@ CooperativeYieldThread(JSContext* cx, unsigned argc, Value* vp)
// threads, whereas the browser has more control over which threads are // threads, whereas the browser has more control over which threads are
// running at different times. // running at different times.
for (ZoneGroupsIter group(cx->runtime()); !group.done(); group.next()) { for (ZoneGroupsIter group(cx->runtime()); !group.done(); group.next()) {
if (group->ownerContext().context() == cx && group != cx->zone()->group()) { if (group->ownerContext().context() == cx && group != cx->zone()->group())
JS_ReportErrorASCII(cx, "Yielding is not allowed while owning multiple zone groups");
return false; return false;
} }
return true;
}
static void
CooperativeYieldCallback(JSContext* cx)
{
MOZ_ASSERT(CooperativeThreadMayYield(cx));
CooperativeBeginWait(cx);
CooperativeYield();
CooperativeEndWait(cx);
}
static bool
CooperativeYieldThread(JSContext* cx, unsigned argc, Value* vp)
{
CallArgs args = CallArgsFromVp(argc, vp);
if (!CooperativeThreadMayYield(cx)) {
JS_ReportErrorASCII(cx, "Yielding is not currently allowed");
return false;
} }
{ {
@ -3467,6 +3493,8 @@ WorkerMain(void* arg)
if (!cx) if (!cx)
return; return;
SetCooperativeYieldCallback(cx, CooperativeYieldCallback);
UniquePtr<ShellContext> sc = MakeUnique<ShellContext>(cx); UniquePtr<ShellContext> sc = MakeUnique<ShellContext>(cx);
if (!sc) if (!sc)
return; return;
@ -7273,7 +7301,7 @@ static const JSJitInfo doFoo_methodinfo = {
static const JSPropertySpec dom_props[] = { static const JSPropertySpec dom_props[] = {
{"x", {"x",
JSPROP_SHARED | JSPROP_ENUMERATE, JSPROP_ENUMERATE,
{ { { {
{ { dom_genericGetter, &dom_x_getterinfo } }, { { dom_genericGetter, &dom_x_getterinfo } },
{ { dom_genericSetter, &dom_x_setterinfo } } { { dom_genericSetter, &dom_x_setterinfo } }
@ -8645,6 +8673,7 @@ main(int argc, char** argv, char** envp)
JS::SetSingleThreadedExecutionCallbacks(cx, JS::SetSingleThreadedExecutionCallbacks(cx,
CooperativeBeginSingleThreadedExecution, CooperativeBeginSingleThreadedExecution,
CooperativeEndSingleThreadedExecution); CooperativeEndSingleThreadedExecution);
SetCooperativeYieldCallback(cx, CooperativeYieldCallback);
result = Shell(cx, &op, envp); result = Shell(cx, &op, envp);

View file

@ -576,7 +576,7 @@ MappedArgumentsObject::obj_resolve(JSContext* cx, HandleObject obj, HandleId id,
return true; return true;
} }
unsigned attrs = JSPROP_SHARED | JSPROP_SHADOWABLE | JSPROP_RESOLVING; unsigned attrs = JSPROP_SHADOWABLE | JSPROP_RESOLVING;
if (JSID_IS_INT(id)) { if (JSID_IS_INT(id)) {
uint32_t arg = uint32_t(JSID_TO_INT(id)); uint32_t arg = uint32_t(JSID_TO_INT(id));
if (arg >= argsobj->initialLength() || argsobj->isElementDeleted(arg)) if (arg >= argsobj->initialLength() || argsobj->isElementDeleted(arg))
@ -776,7 +776,7 @@ UnmappedArgumentsObject::obj_resolve(JSContext* cx, HandleObject obj, HandleId i
return true; return true;
} }
unsigned attrs = JSPROP_SHARED | JSPROP_SHADOWABLE; unsigned attrs = JSPROP_SHADOWABLE;
GetterOp getter = UnmappedArgGetter; GetterOp getter = UnmappedArgGetter;
SetterOp setter = UnmappedArgSetter; SetterOp setter = UnmappedArgSetter;
@ -793,7 +793,7 @@ UnmappedArgumentsObject::obj_resolve(JSContext* cx, HandleObject obj, HandleId i
if (!JSID_IS_ATOM(id, cx->names().callee)) if (!JSID_IS_ATOM(id, cx->names().callee))
return true; return true;
attrs = JSPROP_PERMANENT | JSPROP_GETTER | JSPROP_SETTER | JSPROP_SHARED; attrs = JSPROP_PERMANENT | JSPROP_GETTER | JSPROP_SETTER;
getter = CastAsGetterOp(argsobj->global().getThrowTypeError()); getter = CastAsGetterOp(argsobj->global().getThrowTypeError());
setter = CastAsSetterOp(argsobj->global().getThrowTypeError()); setter = CastAsSetterOp(argsobj->global().getThrowTypeError());
} }

Some files were not shown because too many files have changed in this diff Show more