Compare commits
No commits in common. "ecne" and "ecne/140.8.0-2gnu1" have entirely different histories.
ecne
...
ecne/140.8
2373 changed files with 38198 additions and 92775 deletions
|
|
@ -85,9 +85,9 @@ git = "https://github.com/mozilla/audioipc"
|
|||
rev = "e6f44a2bd1e57d11dfc737632a9e849077632330"
|
||||
replace-with = "vendored-sources"
|
||||
|
||||
[source."git+https://github.com/mozilla/cubeb-coreaudio-rs?rev=bebaa23317332c95734df76e25193c24a83a6840"]
|
||||
[source."git+https://github.com/mozilla/cubeb-coreaudio-rs?rev=2407441a2f67341a0e13b4ba6547555e387c671c"]
|
||||
git = "https://github.com/mozilla/cubeb-coreaudio-rs"
|
||||
rev = "bebaa23317332c95734df76e25193c24a83a6840"
|
||||
rev = "2407441a2f67341a0e13b4ba6547555e387c671c"
|
||||
replace-with = "vendored-sources"
|
||||
|
||||
[source."git+https://github.com/mozilla/cubeb-pulse-rs?rev=8678dcab1c287de79c4c184ccc2e065bc62b70e2"]
|
||||
|
|
|
|||
|
|
@ -263,7 +263,8 @@ jobs:
|
|||
- mozilla-release
|
||||
- mozilla-esr140
|
||||
when:
|
||||
- {weekday: 'Monday', hour: 5, minute: 0}
|
||||
- {weekday: 'Monday', hour: 8, minute: 0}
|
||||
- {weekday: 'Thursday', hour: 8, minute: 0}
|
||||
|
||||
- name: daily-beta-perf
|
||||
job:
|
||||
|
|
|
|||
3
icecat/.gitignore
vendored
3
icecat/.gitignore
vendored
|
|
@ -373,6 +373,3 @@ toolkit/crashreporter/minidump-analyzer/analyzer-test/target/
|
|||
|
||||
# Ignore mozperftest artifacts folder
|
||||
/artifacts/
|
||||
|
||||
# Ignore personal preferences files
|
||||
CLAUDE.local.md
|
||||
|
|
|
|||
|
|
@ -22,4 +22,4 @@
|
|||
# changes to stick? As of bug 928195, this shouldn't be necessary! Please
|
||||
# don't change CLOBBER for WebIDL changes any more.
|
||||
|
||||
Merge day clobber 2026-03-23
|
||||
Merge day clobber 2026-01-12
|
||||
4
icecat/Cargo.lock
generated
4
icecat/Cargo.lock
generated
|
|
@ -1086,7 +1086,7 @@ dependencies = [
|
|||
[[package]]
|
||||
name = "coreaudio-sys-utils"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/mozilla/cubeb-coreaudio-rs?rev=bebaa23317332c95734df76e25193c24a83a6840#bebaa23317332c95734df76e25193c24a83a6840"
|
||||
source = "git+https://github.com/mozilla/cubeb-coreaudio-rs?rev=2407441a2f67341a0e13b4ba6547555e387c671c#2407441a2f67341a0e13b4ba6547555e387c671c"
|
||||
dependencies = [
|
||||
"core-foundation-sys",
|
||||
"coreaudio-sys",
|
||||
|
|
@ -1398,7 +1398,7 @@ dependencies = [
|
|||
[[package]]
|
||||
name = "cubeb-coreaudio"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/mozilla/cubeb-coreaudio-rs?rev=bebaa23317332c95734df76e25193c24a83a6840#bebaa23317332c95734df76e25193c24a83a6840"
|
||||
source = "git+https://github.com/mozilla/cubeb-coreaudio-rs?rev=2407441a2f67341a0e13b4ba6547555e387c671c#2407441a2f67341a0e13b4ba6547555e387c671c"
|
||||
dependencies = [
|
||||
"atomic",
|
||||
"audio-mixer",
|
||||
|
|
|
|||
|
|
@ -23,7 +23,7 @@ using namespace mozilla::a11y;
|
|||
// AccIterator
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
AccIterator::AccIterator(LocalAccessible* aAccessible,
|
||||
AccIterator::AccIterator(const LocalAccessible* aAccessible,
|
||||
filters::FilterFuncPtr aFilterFunc)
|
||||
: mFilterFunc(aFilterFunc) {
|
||||
mState = new IteratorState(aAccessible);
|
||||
|
|
@ -63,7 +63,7 @@ LocalAccessible* AccIterator::Next() {
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
// nsAccIterator::IteratorState
|
||||
|
||||
AccIterator::IteratorState::IteratorState(LocalAccessible* aParent,
|
||||
AccIterator::IteratorState::IteratorState(const LocalAccessible* aParent,
|
||||
IteratorState* mParentState)
|
||||
: mParent(aParent), mIndex(0), mParentState(mParentState) {}
|
||||
|
||||
|
|
|
|||
|
|
@ -42,7 +42,7 @@ class AccIterable {
|
|||
*/
|
||||
class AccIterator : public AccIterable {
|
||||
public:
|
||||
AccIterator(LocalAccessible* aRoot, filters::FilterFuncPtr aFilterFunc);
|
||||
AccIterator(const LocalAccessible* aRoot, filters::FilterFuncPtr aFilterFunc);
|
||||
virtual ~AccIterator();
|
||||
|
||||
/**
|
||||
|
|
@ -57,10 +57,10 @@ class AccIterator : public AccIterable {
|
|||
AccIterator& operator=(const AccIterator&);
|
||||
|
||||
struct IteratorState {
|
||||
explicit IteratorState(LocalAccessible* aParent,
|
||||
explicit IteratorState(const LocalAccessible* aParent,
|
||||
IteratorState* mParentState = nullptr);
|
||||
|
||||
RefPtr<LocalAccessible> mParent;
|
||||
const LocalAccessible* mParent;
|
||||
int32_t mIndex;
|
||||
IteratorState* mParentState;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -71,14 +71,10 @@ void CachedTableAccessible::Invalidate(Accessible* aAcc) {
|
|||
return;
|
||||
}
|
||||
|
||||
Accessible* table = nsAccUtils::TableFor(aAcc);
|
||||
while (table && table->IsTable()) {
|
||||
if (Accessible* table = nsAccUtils::TableFor(aAcc)) {
|
||||
// Destroy the instance (if any). We'll create a new one the next time it
|
||||
// is requested. Climb up the heirarcy to invalidate parent tables as well.
|
||||
// is requested.
|
||||
sCachedTables->Remove(table);
|
||||
// The table may be a direct child of another table, invalidate that one as
|
||||
// well.
|
||||
table = table->Parent();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -536,7 +536,7 @@ static dom::Selection* GetDOMSelection(const nsIContent* aStartContent,
|
|||
return startFrameSel ? &startFrameSel->NormalSelection() : nullptr;
|
||||
}
|
||||
|
||||
std::pair<RefPtr<nsIContent>, uint32_t> TextLeafPoint::ToDOMPoint(
|
||||
std::pair<nsIContent*, uint32_t> TextLeafPoint::ToDOMPoint(
|
||||
bool aIncludeGenerated) const {
|
||||
if (!(*this) || !mAcc->IsLocal()) {
|
||||
MOZ_ASSERT_UNREACHABLE("Invalid point");
|
||||
|
|
|
|||
|
|
@ -188,7 +188,7 @@ class TextLeafPoint final {
|
|||
/**
|
||||
* Translate given TextLeafPoint into a DOM point.
|
||||
*/
|
||||
MOZ_CAN_RUN_SCRIPT std::pair<RefPtr<nsIContent>, uint32_t> ToDOMPoint(
|
||||
MOZ_CAN_RUN_SCRIPT std::pair<nsIContent*, uint32_t> ToDOMPoint(
|
||||
bool aIncludeGenerated = true) const;
|
||||
|
||||
private:
|
||||
|
|
|
|||
|
|
@ -1768,12 +1768,11 @@ void DocAccessible::DoInitialUpdate() {
|
|||
}
|
||||
#endif
|
||||
|
||||
// Fire a reorder event on the OuterDocAccessible after the document tree is
|
||||
// constructed. Note that since this reorder event is processed by the parent
|
||||
// document, events targeted to this child document may be fired prior to this
|
||||
// reorder event. We don't fire a reorder event for remote documents; the
|
||||
// parent process handles that.
|
||||
if (!IPCDoc() && !IsRoot()) {
|
||||
// Fire reorder event after the document tree is constructed. Note, since
|
||||
// this reorder event is processed by parent document then events targeted to
|
||||
// this document may be fired prior to this reorder event. If this is
|
||||
// a problem then consider to keep event processing per tab document.
|
||||
if (!IsRoot()) {
|
||||
RefPtr<AccReorderEvent> reorderEvent = new AccReorderEvent(LocalParent());
|
||||
ParentDocument()->FireDelayedEvent(reorderEvent);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -859,15 +859,16 @@ void HyperTextAccessible::ReplaceText(const nsAString& aText) {
|
|||
return;
|
||||
}
|
||||
|
||||
RefPtr<EditorBase> editorBase = GetEditor();
|
||||
|
||||
SetSelectionBoundsAt(TextLeafRange::kRemoveAllExistingSelectedRanges, 0,
|
||||
CharacterCount());
|
||||
|
||||
if (editorBase) {
|
||||
DebugOnly<nsresult> rv = editorBase->InsertTextAsAction(aText);
|
||||
NS_WARNING_ASSERTION(NS_SUCCEEDED(rv), "Failed to insert the new text");
|
||||
RefPtr<EditorBase> editorBase = GetEditor();
|
||||
if (!editorBase) {
|
||||
return;
|
||||
}
|
||||
|
||||
DebugOnly<nsresult> rv = editorBase->InsertTextAsAction(aText);
|
||||
NS_WARNING_ASSERTION(NS_SUCCEEDED(rv), "Failed to insert the new text");
|
||||
}
|
||||
|
||||
void HyperTextAccessible::InsertText(const nsAString& aText,
|
||||
|
|
|
|||
|
|
@ -50,7 +50,6 @@ DocAccessibleParent::DocAccessibleParent()
|
|||
mTopLevel(false),
|
||||
mTopLevelInContentProcess(false),
|
||||
mShutdown(false),
|
||||
mIsInitialTreeDone(false),
|
||||
mFocus(0),
|
||||
mCaretId(0),
|
||||
mCaretOffset(-1),
|
||||
|
|
@ -118,11 +117,6 @@ mozilla::ipc::IPCResult DocAccessibleParent::ProcessShowEvent(
|
|||
return IPC_OK();
|
||||
#endif
|
||||
}
|
||||
|
||||
if (parent->IsOuterDoc()) {
|
||||
return IPC_FAIL(this, "Cannot attach non-doc to OuterDoc");
|
||||
}
|
||||
|
||||
lastParent = parent;
|
||||
lastParentID = accData.ParentID();
|
||||
|
||||
|
|
@ -151,9 +145,7 @@ mozilla::ipc::IPCResult DocAccessibleParent::ProcessShowEvent(
|
|||
// Otherwise, clients might crawl the incomplete subtree and they won't get
|
||||
// mutation events for the remaining pieces.
|
||||
if (aComplete || root != child) {
|
||||
if (!AttachChild(parent, childIdx, child)) {
|
||||
return IPC_FAIL(this, "failed to attach child");
|
||||
}
|
||||
AttachChild(parent, childIdx, child);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -182,9 +174,7 @@ mozilla::ipc::IPCResult DocAccessibleParent::ProcessShowEvent(
|
|||
MOZ_ASSERT(rootParent);
|
||||
root = GetAccessible(mPendingShowChild);
|
||||
MOZ_ASSERT(root);
|
||||
if (!AttachChild(rootParent, mPendingShowIndex, root)) {
|
||||
return IPC_FAIL(this, "failed to attach pending show child");
|
||||
}
|
||||
AttachChild(rootParent, mPendingShowIndex, root);
|
||||
mPendingShowChild = 0;
|
||||
mPendingShowParent = 0;
|
||||
mPendingShowIndex = 0;
|
||||
|
|
@ -228,11 +218,6 @@ mozilla::ipc::IPCResult DocAccessibleParent::ProcessShowEvent(
|
|||
|
||||
RemoteAccessible* DocAccessibleParent::CreateAcc(
|
||||
const AccessibleData& aAccData) {
|
||||
if (aAccData.ID() == 0) {
|
||||
MOZ_ASSERT_UNREACHABLE("An ID of 0 is reserved for the document itself");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
RemoteAccessible* newProxy;
|
||||
if ((newProxy = GetAccessible(aAccData.ID()))) {
|
||||
// This is a move. Reuse the Accessible; don't destroy it.
|
||||
|
|
@ -249,11 +234,6 @@ RemoteAccessible* DocAccessibleParent::CreateAcc(
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
if (aAccData.GenericTypes() & eDocument) {
|
||||
MOZ_ASSERT_UNREACHABLE("Invalid acc type");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
newProxy = new RemoteAccessible(aAccData.ID(), this, aAccData.Role(),
|
||||
aAccData.Type(), aAccData.GenericTypes(),
|
||||
aAccData.RoleMapEntryIndex());
|
||||
|
|
@ -266,20 +246,9 @@ RemoteAccessible* DocAccessibleParent::CreateAcc(
|
|||
return newProxy;
|
||||
}
|
||||
|
||||
bool DocAccessibleParent::AttachChild(RemoteAccessible* aParent,
|
||||
void DocAccessibleParent::AttachChild(RemoteAccessible* aParent,
|
||||
uint32_t aIndex,
|
||||
RemoteAccessible* aChild) {
|
||||
if (aChild->RemoteParent()) {
|
||||
MOZ_ASSERT_UNREACHABLE(
|
||||
"Attempt to attach child which already has a parent!");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (aParent == aChild) {
|
||||
MOZ_ASSERT_UNREACHABLE("Attempt to make an accessible its own child!");
|
||||
return false;
|
||||
}
|
||||
|
||||
aParent->AddChildAt(aIndex, aChild);
|
||||
aChild->SetParent(aParent);
|
||||
// ProxyCreated might have already been called if aChild is being moved.
|
||||
|
|
@ -300,16 +269,11 @@ bool DocAccessibleParent::AttachChild(RemoteAccessible* aParent,
|
|||
}
|
||||
MOZ_ASSERT(bridge->GetEmbedderAccessibleDoc() == this);
|
||||
if (DocAccessibleParent* childDoc = bridge->GetDocAccessibleParent()) {
|
||||
MOZ_DIAGNOSTIC_ASSERT(!childDoc->RemoteParent(),
|
||||
"Pending OOP child doc shouldn't have parent "
|
||||
"once new OuterDoc is attached");
|
||||
AddChildDoc(childDoc, aChild->ID(), false);
|
||||
}
|
||||
return true;
|
||||
});
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void DocAccessibleParent::ShutdownOrPrepareForMove(RemoteAccessible* aAcc) {
|
||||
|
|
@ -322,10 +286,6 @@ void DocAccessibleParent::ShutdownOrPrepareForMove(RemoteAccessible* aAcc) {
|
|||
// the show event. For now, clear all of them by moving them to a temporary.
|
||||
auto children{std::move(aAcc->mChildren)};
|
||||
for (RemoteAccessible* child : children) {
|
||||
if (child == aAcc) {
|
||||
MOZ_ASSERT_UNREACHABLE(
|
||||
"Somehow an accessible got added as a child of itself!");
|
||||
}
|
||||
ShutdownOrPrepareForMove(child);
|
||||
}
|
||||
}
|
||||
|
|
@ -643,18 +603,6 @@ mozilla::ipc::IPCResult DocAccessibleParent::RecvMutationEvents(
|
|||
|
||||
mozilla::ipc::IPCResult DocAccessibleParent::RecvRequestAckMutationEvents() {
|
||||
if (!mShutdown) {
|
||||
if (!mIsInitialTreeDone) {
|
||||
// This is the first request for an ACK, which means we now have the
|
||||
// initial tree.
|
||||
mIsInitialTreeDone = true;
|
||||
// If this document is already bound to its embedder, fire a reorder event
|
||||
// to notify the client that the embedded document is available. If not,
|
||||
// this will be handled when this document is bound in AddChildDoc.
|
||||
if (RemoteAccessible* parent = RemoteParent()) {
|
||||
parent->Document()->FireEvent(parent,
|
||||
nsIAccessibleEvent::EVENT_REORDER);
|
||||
}
|
||||
}
|
||||
Unused << SendAckMutationEvents();
|
||||
}
|
||||
return IPC_OK();
|
||||
|
|
@ -916,10 +864,7 @@ mozilla::ipc::IPCResult DocAccessibleParent::RecvBindChildDoc(
|
|||
MOZ_ASSERT(CheckDocTree());
|
||||
|
||||
auto childDoc = static_cast<DocAccessibleParent*>(aChildDoc.get());
|
||||
if (childDoc->IsShutdown()) {
|
||||
return IPC_FAIL(this, "Attempt to bind a shutdown child doc");
|
||||
}
|
||||
|
||||
childDoc->Unbind();
|
||||
ipc::IPCResult result = AddChildDoc(childDoc, aID, false);
|
||||
MOZ_ASSERT(result);
|
||||
MOZ_ASSERT(CheckDocTree());
|
||||
|
|
@ -937,15 +882,6 @@ mozilla::ipc::IPCResult DocAccessibleParent::RecvBindChildDoc(
|
|||
ipc::IPCResult DocAccessibleParent::AddChildDoc(DocAccessibleParent* aChildDoc,
|
||||
uint64_t aParentID,
|
||||
bool aCreating) {
|
||||
if (aChildDoc->RemoteParent()) {
|
||||
return IPC_FAIL(this,
|
||||
"Attempt to add child doc which already has a parent");
|
||||
}
|
||||
|
||||
if (aChildDoc->IsShutdown()) {
|
||||
return IPC_FAIL(this, "Attempt to add a shutdown child doc");
|
||||
}
|
||||
|
||||
// We do not use GetAccessible here because we want to be sure to not get the
|
||||
// document it self.
|
||||
ProxyEntry* e = mAccessibles.GetEntry(aParentID);
|
||||
|
|
@ -994,20 +930,11 @@ ipc::IPCResult DocAccessibleParent::AddChildDoc(DocAccessibleParent* aChildDoc,
|
|||
aChildDoc->SetEmulatedWindowHandle(mEmulatedWindowHandle);
|
||||
}
|
||||
#endif // defined(XP_WIN)
|
||||
}
|
||||
// We need to fire a reorder event on the embedder. We do this here rather
|
||||
// than in the content process for two reasons:
|
||||
// 1. It isn't possible for the content process to fire a reorder event on the
|
||||
// embedder when the embedded document is in a different process to its
|
||||
// embedder.
|
||||
// 2. Doing it here ensures that the event is fired after the child document
|
||||
// is bound. Otherwise, there could be a short period where the content
|
||||
// process has fired the reorder event, but the child document isn't bound
|
||||
// yet.
|
||||
// However, if the initial tree hasn't been received yet, we don't want to
|
||||
// fire the reorder event yet. That gets handled in
|
||||
// RecvRequestAckMutationEvents.
|
||||
if (aChildDoc->mIsInitialTreeDone) {
|
||||
// We need to fire a reorder event on the outer doc accessible.
|
||||
// For same-process documents, this is fired by the content process, but
|
||||
// this isn't possible when the document is in a different process to its
|
||||
// embedder.
|
||||
// FireEvent fires both OS and XPCOM events.
|
||||
FireEvent(outerDoc, nsIAccessibleEvent::EVENT_REORDER);
|
||||
}
|
||||
|
||||
|
|
@ -1048,9 +975,6 @@ void DocAccessibleParent::Destroy() {
|
|||
// If we are already shutdown that is because our containing tab parent is
|
||||
// shutting down in which case we don't need to do anything.
|
||||
if (mShutdown) {
|
||||
// Just in case there is a cycle in the document heirarchy.
|
||||
mParent = nullptr;
|
||||
mIndexInParent = -1;
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -1088,8 +1012,6 @@ void DocAccessibleParent::Destroy() {
|
|||
RemoteAccessible* acc = iter.Get()->mProxy;
|
||||
MOZ_ASSERT(acc != this);
|
||||
if (acc->IsTable()) {
|
||||
// Prevents the invalidation code from trying to walk up the tree.
|
||||
acc->SetParent(nullptr);
|
||||
CachedTableAccessible::Invalidate(acc);
|
||||
}
|
||||
ProxyDestroyed(acc);
|
||||
|
|
@ -1135,9 +1057,6 @@ void DocAccessibleParent::ActorDestroy(ActorDestroyReason aWhy) {
|
|||
if (!mShutdown) {
|
||||
ACQUIRE_ANDROID_LOCK
|
||||
Destroy();
|
||||
} else if (RemoteParent()) {
|
||||
ACQUIRE_ANDROID_LOCK
|
||||
Unbind();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -325,14 +325,11 @@ class DocAccessibleParent : public RemoteAccessible,
|
|||
};
|
||||
|
||||
RemoteAccessible* CreateAcc(const AccessibleData& aAccData);
|
||||
bool AttachChild(RemoteAccessible* aParent, uint32_t aIndex,
|
||||
void AttachChild(RemoteAccessible* aParent, uint32_t aIndex,
|
||||
RemoteAccessible* aChild);
|
||||
[[nodiscard]] bool CheckDocTree() const;
|
||||
xpcAccessibleGeneric* GetXPCAccessible(RemoteAccessible* aProxy);
|
||||
|
||||
/**
|
||||
* Fire an event to both OS and XPCOM consumers.
|
||||
*/
|
||||
void FireEvent(RemoteAccessible* aAcc, const uint32_t& aType);
|
||||
|
||||
/**
|
||||
|
|
@ -368,10 +365,9 @@ class DocAccessibleParent : public RemoteAccessible,
|
|||
uint32_t mPendingShowIndex = 0;
|
||||
nsTHashSet<uint64_t> mMovingIDs;
|
||||
uint64_t mActorID;
|
||||
bool mTopLevel : 1;
|
||||
bool mTopLevelInContentProcess : 1;
|
||||
bool mShutdown : 1;
|
||||
bool mIsInitialTreeDone : 1;
|
||||
bool mTopLevel;
|
||||
bool mTopLevelInContentProcess;
|
||||
bool mShutdown;
|
||||
RefPtr<dom::CanonicalBrowsingContext> mBrowsingContext;
|
||||
|
||||
nsTHashSet<RefPtr<dom::BrowserBridgeParent>> mPendingOOPChildDocs;
|
||||
|
|
|
|||
|
|
@ -11,8 +11,6 @@ support-files = [
|
|||
["browser_hidden_iframe.js"]
|
||||
https_first_disabled = true
|
||||
|
||||
["browser_iframe_recreation.js"]
|
||||
|
||||
["browser_nested_iframe.js"]
|
||||
|
||||
["browser_reframe_root.js"]
|
||||
|
|
|
|||
|
|
@ -1,29 +0,0 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
"use strict";
|
||||
|
||||
addAccessibleTask(
|
||||
`test`,
|
||||
async function testRecreation(browser, iframeDocAcc, topDocAcc) {
|
||||
let iframe = findAccessibleChildByID(topDocAcc, DEFAULT_IFRAME_ID);
|
||||
is(iframeDocAcc.parent, iframe, "iframe doc's parent is iframe");
|
||||
// The ARIA role currently causes re-creation. If that ever changes, we'll
|
||||
// need to switch to another technique here.
|
||||
info("Change iframe's role to recreate it");
|
||||
let shown = waitForEvent(EVENT_SHOW, DEFAULT_IFRAME_ID);
|
||||
let reordered = waitForEvent(EVENT_REORDER, DEFAULT_IFRAME_ID);
|
||||
await SpecialPowers.spawn(
|
||||
topDocAcc.browsingContext,
|
||||
[DEFAULT_IFRAME_ID],
|
||||
id => {
|
||||
content.document.getElementById(id).role = "foo";
|
||||
}
|
||||
);
|
||||
iframe = (await shown).accessible;
|
||||
await reordered;
|
||||
is(iframeDocAcc.parent, iframe, "iframe doc's parent is iframe");
|
||||
},
|
||||
{ chrome: false, topLevel: false, iframe: true, remoteIframe: true }
|
||||
);
|
||||
|
|
@ -16,9 +16,25 @@ function getSiteBlockedErrorDetails(docShell) {
|
|||
Ci.nsIClassifiedChannel
|
||||
);
|
||||
if (classifiedChannel) {
|
||||
let httpChannel = docShell.failedChannel.QueryInterface(
|
||||
Ci.nsIHttpChannel
|
||||
);
|
||||
|
||||
let reportUri = httpChannel.URI;
|
||||
|
||||
// Remove the query to avoid leaking sensitive data
|
||||
if (reportUri instanceof Ci.nsIURL) {
|
||||
reportUri = reportUri.mutate().setQuery("").finalize();
|
||||
}
|
||||
|
||||
let triggeringPrincipal = docShell.failedChannel.loadInfo
|
||||
? docShell.failedChannel.loadInfo.triggeringPrincipal
|
||||
: null;
|
||||
blockedInfo = {
|
||||
list: classifiedChannel.matchedList,
|
||||
triggeringPrincipal,
|
||||
provider: classifiedChannel.matchedProvider,
|
||||
uri: reportUri.asciiSpec,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -177,11 +177,8 @@ export class BlockedSiteParent extends EscapablePageParent {
|
|||
// site, so that they don't lose track after, e.g., tab switching.
|
||||
// We can't use browser.contentPrincipal which is principal of about:blocked
|
||||
// Create one from uri with current principal origin attributes
|
||||
|
||||
// Remove the query to avoid leaking sensitive data
|
||||
let uri = browsingContext.currentURI.mutate().setQuery("").finalize();
|
||||
let principal = Services.scriptSecurityManager.createContentPrincipal(
|
||||
uri,
|
||||
Services.io.newURI(blockedInfo.uri),
|
||||
browsingContext.currentWindowGlobal.documentPrincipal.originAttributes
|
||||
);
|
||||
Services.perms.addFromPrincipal(
|
||||
|
|
@ -209,10 +206,10 @@ export class BlockedSiteParent extends EscapablePageParent {
|
|||
let title;
|
||||
let chromeWin = browsingContext.topChromeWindow;
|
||||
if (reason === "malware") {
|
||||
let reportUrl = lazy.SafeBrowsing.getReportURL("MalwareMistake", {
|
||||
...blockedInfo,
|
||||
uri: uri.asciiSpec,
|
||||
});
|
||||
let reportUrl = lazy.SafeBrowsing.getReportURL(
|
||||
"MalwareMistake",
|
||||
blockedInfo
|
||||
);
|
||||
title = lazy.browserBundle.GetStringFromName(
|
||||
"safebrowsing.reportedAttackSite"
|
||||
);
|
||||
|
|
@ -236,10 +233,10 @@ export class BlockedSiteParent extends EscapablePageParent {
|
|||
};
|
||||
}
|
||||
} else if (reason === "phishing") {
|
||||
let reportUrl = lazy.SafeBrowsing.getReportURL("PhishMistake", {
|
||||
...blockedInfo,
|
||||
uri: uri.asciiSpec,
|
||||
});
|
||||
let reportUrl = lazy.SafeBrowsing.getReportURL(
|
||||
"PhishMistake",
|
||||
blockedInfo
|
||||
);
|
||||
title = lazy.browserBundle.GetStringFromName(
|
||||
"safebrowsing.deceptiveSite"
|
||||
);
|
||||
|
|
@ -284,15 +281,16 @@ export class BlockedSiteParent extends EscapablePageParent {
|
|||
buttons
|
||||
);
|
||||
|
||||
let activeSHEntry = browsingContext.activeSessionHistoryEntry;
|
||||
if (!activeSHEntry) {
|
||||
console.error("No active session history entry found");
|
||||
return;
|
||||
}
|
||||
|
||||
// Allow users to override and continue through to the site.
|
||||
browsingContext.loadURI(uri, {
|
||||
triggeringPrincipal: activeSHEntry.triggeringPrincipal,
|
||||
// Note that we have to use the passed URI info and can't just
|
||||
// rely on the document URI, because the latter contains
|
||||
// additional query parameters that should be stripped.
|
||||
let triggeringPrincipal =
|
||||
blockedInfo.triggeringPrincipal ||
|
||||
Services.scriptSecurityManager.createNullPrincipal({});
|
||||
|
||||
browsingContext.fixupAndLoadURIString(blockedInfo.uri, {
|
||||
triggeringPrincipal,
|
||||
loadFlags: Ci.nsIWebNavigation.LOAD_FLAGS_BYPASS_CLASSIFIER,
|
||||
});
|
||||
}
|
||||
|
|
|
|||
|
|
@ -142,7 +142,9 @@ export class DOMFullscreenParent extends JSWindowActorParent {
|
|||
case "DOMFullscreen:NewOrigin": {
|
||||
// Don't show the warning if we've already exited fullscreen.
|
||||
if (window.document.fullscreen) {
|
||||
window.PointerlockFsWarning.showFullScreen(topBrowsingContext);
|
||||
window.PointerlockFsWarning.showFullScreen(
|
||||
aMessage.data.originNoSuffix
|
||||
);
|
||||
}
|
||||
this.updateFullscreenWindowReference(window);
|
||||
break;
|
||||
|
|
@ -220,7 +222,7 @@ export class DOMFullscreenParent extends JSWindowActorParent {
|
|||
|
||||
if (!this.hasBeenDestroyed() && this.requestOrigin) {
|
||||
window.PointerlockFsWarning.showFullScreen(
|
||||
this.requestOrigin.browsingContext
|
||||
this.requestOrigin.manager.documentPrincipal.originNoSuffix
|
||||
);
|
||||
}
|
||||
break;
|
||||
|
|
|
|||
|
|
@ -49,16 +49,10 @@ var PointerlockFsWarning = {
|
|||
}
|
||||
},
|
||||
|
||||
// Show info that top level has entered fullscreen. Ultimately, it is always
|
||||
// ancestors who are in control and can with various means make the user believe
|
||||
// a site has entered fullscreen while displaying it's own content.
|
||||
// We try to make it clear to the user that it's the top level that is actually in fullscreen
|
||||
showFullScreen(browsingContext) {
|
||||
const origin =
|
||||
browsingContext.top.currentWindowGlobal.documentPrincipal.originNoSuffix;
|
||||
showFullScreen(aOrigin) {
|
||||
let timeout = Services.prefs.getIntPref("full-screen-api.warning.timeout");
|
||||
let delay = Services.prefs.getIntPref("full-screen-api.warning.delay");
|
||||
this.show(origin, "fullscreen-warning", timeout, delay);
|
||||
this.show(aOrigin, "fullscreen-warning", timeout, delay);
|
||||
},
|
||||
|
||||
// Shows a warning that the site has entered fullscreen or
|
||||
|
|
|
|||
|
|
@ -60,9 +60,6 @@ skip-if = [
|
|||
"os == 'linux' && os_version == '18.04' && processor == 'x86_64' && swgl", # Bug 1949995
|
||||
]
|
||||
|
||||
["browser_fullscreen_toplevel_warning.js"]
|
||||
support-files = ["fullscreen.html"]
|
||||
|
||||
["browser_fullscreen_warning.js"]
|
||||
support-files = ["fullscreen.html"]
|
||||
skip-if = [
|
||||
|
|
|
|||
|
|
@ -1,184 +0,0 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
"use strict";
|
||||
|
||||
const FULLSCREEN_PATH =
|
||||
"/browser/browser/base/content/test/fullscreen/fullscreen.html";
|
||||
|
||||
function getWarningDomain(warning) {
|
||||
let textElem = warning.querySelector(".pointerlockfswarning-domain-text");
|
||||
if (textElem.hidden) {
|
||||
return null;
|
||||
}
|
||||
let args = textElem.getAttribute("data-l10n-args");
|
||||
return args ? JSON.parse(args).domain : null;
|
||||
}
|
||||
|
||||
async function waitForWarningState(aWarningElement, aExpectedState) {
|
||||
await BrowserTestUtils.waitForAttribute(aExpectedState, aWarningElement, "");
|
||||
}
|
||||
|
||||
add_setup(async function init() {
|
||||
await SpecialPowers.pushPrefEnv({
|
||||
set: [
|
||||
["test.wait300msAfterTabSwitch", true],
|
||||
["full-screen-api.enabled", true],
|
||||
["full-screen-api.allow-trusted-requests-only", false],
|
||||
],
|
||||
});
|
||||
});
|
||||
|
||||
// Bug 2021080 - Verify the fullscreen warning always displays the top-level domain,
|
||||
// not the origin of the cross-origin frame that requested fullscreen.
|
||||
add_task(async function test_fullscreen_warning_cross_origin_shows_toplevel() {
|
||||
await BrowserTestUtils.withNewTab("https://example.com", async browser => {
|
||||
let warning = document.getElementById("fullscreen-warning");
|
||||
|
||||
await SpecialPowers.spawn(browser, [FULLSCREEN_PATH], async path => {
|
||||
let iframe = content.document.createElement("iframe");
|
||||
iframe.allow = "fullscreen";
|
||||
iframe.src = `https://example.org${path}`;
|
||||
let loaded = new Promise(r =>
|
||||
iframe.addEventListener("load", r, { once: true })
|
||||
);
|
||||
content.document.body.appendChild(iframe);
|
||||
await loaded;
|
||||
});
|
||||
|
||||
let warningShown = waitForWarningState(warning, "onscreen");
|
||||
await SpecialPowers.spawn(browser, [], async () => {
|
||||
let frame = content.document.querySelector("iframe");
|
||||
frame.focus();
|
||||
await SpecialPowers.spawn(frame, [], () => {
|
||||
content.document.getElementById("request").click();
|
||||
});
|
||||
});
|
||||
await warningShown;
|
||||
|
||||
let activeOrigin = await SpecialPowers.spawn(browser, [], async () => {
|
||||
let frame = content.document.querySelector("iframe");
|
||||
return SpecialPowers.spawn(frame, [], () => content.location.hostname);
|
||||
});
|
||||
is(
|
||||
activeOrigin,
|
||||
"example.org",
|
||||
"Cross-origin frame (example.org) is the active fullscreen document"
|
||||
);
|
||||
is(
|
||||
getWarningDomain(warning),
|
||||
"example.com",
|
||||
"Warning shows top-level domain, not the active fullscreen frame's domain"
|
||||
);
|
||||
|
||||
let warningHidden = waitForWarningState(warning, "hidden");
|
||||
let exitPromise = BrowserTestUtils.waitForEvent(
|
||||
document,
|
||||
"fullscreenchange",
|
||||
false,
|
||||
() => !document.fullscreenElement
|
||||
);
|
||||
document.getElementById("fullscreen-exit-button").click();
|
||||
await Promise.all([exitPromise, warningHidden]);
|
||||
});
|
||||
});
|
||||
|
||||
// Bug 2021080 - Verify the fullscreen warning shows the top-level domain when each
|
||||
// of three nested cross-origin frames (top, middle, inner) requests fullscreen.
|
||||
add_task(async function test_fullscreen_warning_three_nested_origins() {
|
||||
await BrowserTestUtils.withNewTab("https://example.com", async browser => {
|
||||
let warning = document.getElementById("fullscreen-warning");
|
||||
|
||||
// Build a 3-level nested structure:
|
||||
// example.com (div > iframe[example.org (div > iframe[example.net])])
|
||||
await SpecialPowers.spawn(browser, [FULLSCREEN_PATH], async path => {
|
||||
let topDiv = content.document.createElement("div");
|
||||
content.document.body.appendChild(topDiv);
|
||||
|
||||
let middleFrame = content.document.createElement("iframe");
|
||||
middleFrame.allow = "fullscreen";
|
||||
middleFrame.src = `https://example.org${path}`;
|
||||
let loaded = new Promise(r =>
|
||||
middleFrame.addEventListener("load", r, { once: true })
|
||||
);
|
||||
topDiv.appendChild(middleFrame);
|
||||
await loaded;
|
||||
|
||||
await SpecialPowers.spawn(middleFrame, [path], async innerPath => {
|
||||
let middleDiv = content.document.createElement("div");
|
||||
content.document.body.appendChild(middleDiv);
|
||||
|
||||
let innerFrame = content.document.createElement("iframe");
|
||||
innerFrame.allow = "fullscreen";
|
||||
innerFrame.src = `https://example.net${innerPath}`;
|
||||
let innerLoaded = new Promise(r =>
|
||||
innerFrame.addEventListener("load", r, { once: true })
|
||||
);
|
||||
middleDiv.appendChild(innerFrame);
|
||||
await innerLoaded;
|
||||
});
|
||||
});
|
||||
|
||||
async function exitFullscreen() {
|
||||
let warningHidden = waitForWarningState(warning, "hidden");
|
||||
let exitPromise = BrowserTestUtils.waitForEvent(
|
||||
document,
|
||||
"fullscreenchange",
|
||||
false,
|
||||
() => !document.fullscreenElement
|
||||
);
|
||||
document.getElementById("fullscreen-exit-button").click();
|
||||
await Promise.all([exitPromise, warningHidden]);
|
||||
}
|
||||
|
||||
// Step 1: Top-level (example.com) requests fullscreen on its div.
|
||||
let warningShown = waitForWarningState(warning, "onscreen");
|
||||
await SpecialPowers.spawn(browser, [], () => {
|
||||
content.document.querySelector("div").requestFullscreen();
|
||||
});
|
||||
await warningShown;
|
||||
is(
|
||||
getWarningDomain(warning),
|
||||
"example.com",
|
||||
"Top-level fullscreen: warning shows top-level domain"
|
||||
);
|
||||
await exitFullscreen();
|
||||
|
||||
// Step 2: Middle frame (example.org) requests fullscreen on its div.
|
||||
warningShown = waitForWarningState(warning, "onscreen");
|
||||
await SpecialPowers.spawn(browser, [], async () => {
|
||||
let middleFrame = content.document.querySelector("iframe");
|
||||
middleFrame.focus();
|
||||
await SpecialPowers.spawn(middleFrame, [], () => {
|
||||
content.document.querySelector("div").requestFullscreen();
|
||||
});
|
||||
});
|
||||
await warningShown;
|
||||
is(
|
||||
getWarningDomain(warning),
|
||||
"example.com",
|
||||
"Middle frame fullscreen: warning shows top-level domain"
|
||||
);
|
||||
await exitFullscreen();
|
||||
|
||||
// Step 3: Inner frame (example.net) requests fullscreen on an element.
|
||||
warningShown = waitForWarningState(warning, "onscreen");
|
||||
await SpecialPowers.spawn(browser, [], async () => {
|
||||
let middleFrame = content.document.querySelector("iframe");
|
||||
await SpecialPowers.spawn(middleFrame, [], async () => {
|
||||
let innerFrame = content.document.querySelector("iframe");
|
||||
innerFrame.focus();
|
||||
await SpecialPowers.spawn(innerFrame, [], () => {
|
||||
content.document.getElementById("request").click();
|
||||
});
|
||||
});
|
||||
});
|
||||
await warningShown;
|
||||
is(
|
||||
getWarningDomain(warning),
|
||||
"example.com",
|
||||
"Inner frame fullscreen: warning shows top-level domain"
|
||||
);
|
||||
await exitFullscreen();
|
||||
});
|
||||
});
|
||||
|
|
@ -551,8 +551,11 @@ async function getAutofillRecords(data) {
|
|||
// JSActors, but that would import a lot of code for a targeting attribute.
|
||||
return 0;
|
||||
}
|
||||
let records = await actor?.getRecords(data);
|
||||
return records?.length ?? 0;
|
||||
let records = await actor?.receiveMessage({
|
||||
name: "FormAutofill:GetRecords",
|
||||
data,
|
||||
});
|
||||
return records?.records?.length ?? 0;
|
||||
}
|
||||
|
||||
// Attribution data can be encoded multiple times so we need this function to
|
||||
|
|
|
|||
|
|
@ -1418,10 +1418,15 @@ add_task(async function test_creditCardsSaved() {
|
|||
gBrowser.selectedBrowser.browsingContext.currentWindowGlobal.getActor(
|
||||
"FormAutofill"
|
||||
),
|
||||
"getRecords"
|
||||
"receiveMessage"
|
||||
)
|
||||
.withArgs(sandbox.match({ collectionName: "creditCards" }))
|
||||
.resolves([creditcard])
|
||||
.withArgs(
|
||||
sandbox.match({
|
||||
name: "FormAutofill:GetRecords",
|
||||
data: { collectionName: "creditCards" },
|
||||
})
|
||||
)
|
||||
.resolves({ records: [creditcard] })
|
||||
.callThrough();
|
||||
|
||||
is(
|
||||
|
|
@ -1430,8 +1435,8 @@ add_task(async function test_creditCardsSaved() {
|
|||
"Should return 1 when 1 credit card is saved"
|
||||
);
|
||||
ok(
|
||||
stub.calledWithMatch({ collectionName: "creditCards" }),
|
||||
"Targeting called getRecords"
|
||||
stub.calledWithMatch({ name: "FormAutofill:GetRecords" }),
|
||||
"Targeting called FormAutofill:GetRecords"
|
||||
);
|
||||
|
||||
sandbox.restore();
|
||||
|
|
|
|||
|
|
@ -60,5 +60,5 @@
|
|||
}
|
||||
}
|
||||
},
|
||||
"required": ["providerId", "searchPageRegexp"]
|
||||
"required": ["providerId", "searchPageRegexp", "includeParams"]
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1 +1 @@
|
|||
140.10.1
|
||||
140.8.0
|
||||
|
|
|
|||
|
|
@ -1 +1 @@
|
|||
140.10.1esr
|
||||
140.8.0esr
|
||||
|
|
|
|||
|
|
@ -13,5 +13,5 @@ MOZ_BRANDING_DIRECTORY=browser/branding/unofficial
|
|||
MOZ_OFFICIAL_BRANDING_DIRECTORY=browser/branding/official
|
||||
# IceCat settings
|
||||
MOZ_APP_BASENAME=IceCat
|
||||
MOZ_APP_VERSION=140.10.1
|
||||
MOZ_APP_VERSION=140.8.0
|
||||
MOZ_DATA_REPORTING=0
|
||||
|
|
|
|||
|
|
@ -10,4 +10,4 @@
|
|||
# hardcoded milestones in the tree from these two files.
|
||||
#--------------------------------------------------------
|
||||
|
||||
140.10.1
|
||||
140.8.0
|
||||
|
|
|
|||
|
|
@ -1,21 +1,3 @@
|
|||
icecat (140.10.1-1gnu1+build1-0.12.0) ecne; urgency=medium
|
||||
|
||||
* New upstream stable release (icecat-140.10.1-1gnu1)
|
||||
|
||||
-- Capitulo Mexicano de Software Libre <devel@cmxsl.org> Mon, 04 May 2026 16:44:54 -0600
|
||||
|
||||
icecat (140.10.0-1gnu1+build1-0.12.0) ecne; urgency=medium
|
||||
|
||||
* New upstream stable release (icecat-140.10.0-1gnu1)
|
||||
|
||||
-- Capitulo Mexicano de Software Libre <devel@cmxsl.org> Tue, 28 Apr 2026 03:08:30 -0600
|
||||
|
||||
icecat (140.9.0-1gnu1+build1-0.12.0) ecne; urgency=medium
|
||||
|
||||
* New upstream stable release (icecat-140.9.0-1gnu1)
|
||||
|
||||
-- Capitulo Mexicano de Software Libre <devel@cmxsl.org> Sat, 28 Mar 2026 01:16:35 -0600
|
||||
|
||||
icecat (140.8.0-2gnu1+build1-0.12.0) ecne; urgency=medium
|
||||
|
||||
* New upstream stable release (icecat-140.8.0-2gnu1)
|
||||
|
|
|
|||
|
|
@ -190,7 +190,6 @@ fail-if = ["a11y_checks"] # Bug 1849028 clicked element may not be focusable and
|
|||
|
||||
["browser_aboutdebugging_serviceworker_start.js"]
|
||||
skip-if = [
|
||||
"os == 'linux' && os_version == '18.04' && processor == 'x86_64' && tsan", # Bug 1947358, Bug 2030884
|
||||
"os == 'linux' && os_version == '24.04' && processor == 'x86_64' && display == 'x11' && tsan", # Bug 1947358
|
||||
]
|
||||
|
||||
|
|
|
|||
|
|
@ -96,11 +96,8 @@ fail-if = ["a11y_checks"] # Bug 1849028 clicked element may not be focusable and
|
|||
["browser_application_panel_start-service-worker.js"]
|
||||
fail-if = ["a11y_checks"] # Bug 1849028 clicked element may not be focusable and/or labeled
|
||||
skip-if = [
|
||||
"os == 'linux' && processor == 'x86_64' && tsan", # Bug 1608640, Bug 2030884
|
||||
"os == 'linux' && processor == 'x86_64' && asan", # Bug 1781479, Bug 2030884
|
||||
"os == 'mac' && os_version == '14.70' && processor == 'x86_64'", # Bug 1980084, Bug 2030884
|
||||
"os == 'win' && os_version == '11.26100' && processor == 'x86_64' && asan", # Bug 1781479, Bug 2030884
|
||||
"os == 'win' && os_version == '11.26200' && processor == 'x86_64' && asan", # Bug 1781479, Bug 2030884
|
||||
"os == 'linux' && os_version == '18.04' && processor == 'x86_64' && tsan", # Bug 1608640
|
||||
"os == 'linux' && os_version == '24.04' && processor == 'x86_64' && display == 'x11' && tsan", # Bug 1608640
|
||||
]
|
||||
|
||||
["browser_application_panel_target-switching.js"]
|
||||
|
|
|
|||
|
|
@ -47,8 +47,6 @@ export default [
|
|||
process: true,
|
||||
global: true,
|
||||
L10N: true,
|
||||
// TODO: Add this to the main ESlint globals Bug 2025542
|
||||
Sanitizer: true,
|
||||
},
|
||||
},
|
||||
rules: {
|
||||
|
|
|
|||
|
|
@ -2,12 +2,11 @@
|
|||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at <http://mozilla.org/MPL/2.0/>. */
|
||||
|
||||
import React, {
|
||||
Component,
|
||||
createRef,
|
||||
} from "devtools/client/shared/vendor/react";
|
||||
import React, { Component } from "devtools/client/shared/vendor/react";
|
||||
import { div } from "devtools/client/shared/vendor/react-dom-factories";
|
||||
import PropTypes from "devtools/client/shared/vendor/react-prop-types";
|
||||
import { connect } from "devtools/client/shared/vendor/react-redux";
|
||||
import { basename } from "../utils/path";
|
||||
import { createLocation } from "../utils/location";
|
||||
|
||||
const fuzzyAldrin = require("resource://devtools/client/shared/vendor/fuzzaldrin-plus.js");
|
||||
|
|
@ -60,7 +59,6 @@ export class QuickOpenModal extends Component {
|
|||
constructor(props) {
|
||||
super(props);
|
||||
this.state = { results: null, selectedIndex: 0 };
|
||||
this.resultListRef = createRef();
|
||||
}
|
||||
|
||||
static get propTypes() {
|
||||
|
|
@ -225,14 +223,20 @@ export class QuickOpenModal extends Component {
|
|||
|
||||
if (query == "" && !this.isShortcutQuery()) {
|
||||
this.showTopSources();
|
||||
} else if (this.isSymbolSearch()) {
|
||||
await this.searchSymbols(query);
|
||||
} else if (this.isShortcutQuery()) {
|
||||
this.searchShortcuts(query);
|
||||
} else {
|
||||
this.searchSources(query);
|
||||
return;
|
||||
}
|
||||
this.highlightQueryMatches(this.props.query);
|
||||
|
||||
if (this.isSymbolSearch()) {
|
||||
await this.searchSymbols(query);
|
||||
return;
|
||||
}
|
||||
|
||||
if (this.isShortcutQuery()) {
|
||||
this.searchShortcuts(query);
|
||||
return;
|
||||
}
|
||||
|
||||
this.searchSources(query);
|
||||
} catch (e) {
|
||||
// Due to throttling this might get scheduled after the component and the
|
||||
// toolbox are destroyed.
|
||||
|
|
@ -390,35 +394,23 @@ export class QuickOpenModal extends Component {
|
|||
isSourcesQuery = () => this.props.searchType === "sources";
|
||||
isSourceSearch = () => this.isSourcesQuery() || this.isGotoSourceQuery();
|
||||
|
||||
highlightQueryMatches(query) {
|
||||
/* eslint-disable react/no-danger */
|
||||
renderHighlight(candidateString, query) {
|
||||
const options = {
|
||||
wrap: {
|
||||
tagOpen: '<mark class="highlight">',
|
||||
tagClose: "</mark>",
|
||||
},
|
||||
};
|
||||
if (this.resultListRef.current) {
|
||||
const domEl = this.resultListRef.current.ref.current;
|
||||
for (const titleNode of domEl.querySelectorAll(".title")) {
|
||||
const htmlString = fuzzyAldrin.wrap(
|
||||
titleNode.innerText,
|
||||
query,
|
||||
options
|
||||
);
|
||||
// Sanitizer API not supported in ESR 140
|
||||
// Should remove at ESR 153
|
||||
if ("Sanitizer" in window) {
|
||||
const sanitizer = new Sanitizer({
|
||||
elements: ["mark"],
|
||||
attributes: ["class"],
|
||||
});
|
||||
titleNode.setHTML(htmlString, { sanitizer });
|
||||
}
|
||||
}
|
||||
}
|
||||
const html = fuzzyAldrin.wrap(candidateString, query, options);
|
||||
return div({
|
||||
dangerouslySetInnerHTML: {
|
||||
__html: html,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
renderResults = (query, results) => {
|
||||
highlightMatching = (query, results) => {
|
||||
let newQuery = query;
|
||||
if (newQuery === "") {
|
||||
return results;
|
||||
|
|
@ -429,7 +421,11 @@ export class QuickOpenModal extends Component {
|
|||
if (typeof result.title == "string") {
|
||||
return {
|
||||
...result,
|
||||
title: result.title,
|
||||
title: this.renderHighlight(
|
||||
result.title,
|
||||
basename(newQuery),
|
||||
"title"
|
||||
),
|
||||
};
|
||||
}
|
||||
return result;
|
||||
|
|
@ -458,7 +454,7 @@ export class QuickOpenModal extends Component {
|
|||
const { query } = this.props;
|
||||
const { selectedIndex, results } = this.state;
|
||||
|
||||
const items = this.renderResults(query, results || []);
|
||||
const items = this.highlightMatching(query, results || []);
|
||||
const expanded = !!items && !!items.length;
|
||||
return React.createElement(
|
||||
Modal,
|
||||
|
|
@ -491,7 +487,7 @@ export class QuickOpenModal extends Component {
|
|||
items,
|
||||
selected: selectedIndex,
|
||||
selectItem: this.selectResultItem,
|
||||
ref: this.resultListRef,
|
||||
ref: "resultList",
|
||||
expanded,
|
||||
...(this.isSourceSearch() ? SIZE_BIG : SIZE_DEFAULT),
|
||||
})
|
||||
|
|
|
|||
|
|
@ -115,9 +115,6 @@ skip-if = [
|
|||
["browser_dbg-call-stack.js"]
|
||||
|
||||
["browser_dbg-chrome-create.js"]
|
||||
skip-if = [
|
||||
"os == 'linux' && os_version == '18.04' && processor == 'x86_64' && asan", # Bug 2030884
|
||||
]
|
||||
|
||||
["browser_dbg-console-async.js"]
|
||||
|
||||
|
|
@ -289,7 +286,6 @@ skip-if = [
|
|||
["browser_dbg-javascript-tracer-values-preview.js"]
|
||||
skip-if = [
|
||||
"os == 'linux' && os_version == '18.04' && processor == 'x86_64' && opt && a11y_checks", # Bug The tracer tree isn't yet accessible
|
||||
"os == 'linux' && os_version == '18.04' && processor == 'x86_64' && tsan", # Bug 1959018, Bug 2030884
|
||||
"os == 'linux' && os_version == '24.04' && processor == 'x86_64' && display == 'x11' && opt && a11y_checks", # Bug The tracer tree isn't yet accessible
|
||||
]
|
||||
|
||||
|
|
|
|||
|
|
@ -94,18 +94,6 @@ add_task(async function () {
|
|||
pressKey(dbg, "Escape");
|
||||
assertQuickOpenDisabled(dbg);
|
||||
|
||||
info("Test that the highlighted result matches match the query");
|
||||
await quickOpen(dbg, "sw");
|
||||
await waitForResults(dbg, [
|
||||
"script-switching-01.js",
|
||||
"script-switching-02.js",
|
||||
]);
|
||||
await assertHighlightMatches(dbg, 1, "sw");
|
||||
await assertHighlightMatches(dbg, 2, "sw");
|
||||
EventUtils.sendString("i");
|
||||
await assertHighlightMatches(dbg, 1, "swi");
|
||||
pressKey(dbg, "Escape");
|
||||
|
||||
info("Testing goto line:column");
|
||||
assertLine(dbg, 0);
|
||||
assertColumn(dbg, 1);
|
||||
|
|
@ -182,19 +170,3 @@ async function assertResultIsTab(dbg, index) {
|
|||
"Result should be a tab"
|
||||
);
|
||||
}
|
||||
|
||||
async function assertHighlightMatches(dbg, resultIndex, expectedMatchText) {
|
||||
// Sanitizer API not supported in ESR 140
|
||||
// Should remove at ESR 153
|
||||
if ("Sanitizer" in dbg.win) {
|
||||
const el = await findResultEl(dbg, resultIndex);
|
||||
const highlight = await waitForElementWithSelector(dbg, "mark.highlight");
|
||||
ok(el && !!highlight, "The query match is highlighted");
|
||||
await waitUntil(
|
||||
() => el.querySelector("mark.highlight").innerText == expectedMatchText
|
||||
);
|
||||
ok(true, "The highlighted text matches the query text");
|
||||
} else {
|
||||
ok(true, "The text is not highlighted");
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -112,12 +112,6 @@ skip-if = [
|
|||
["browser_tab_commands_factory.js"]
|
||||
|
||||
["browser_tab_descriptor_fission.js"]
|
||||
skip-if = [
|
||||
"os == 'linux' && processor == 'x86_64' && asan", # Bug 1966872, Bug 2030884
|
||||
"os == 'linux' && processor == 'x86_64' && tsan", # Bug 1966872, Bug 2030884
|
||||
"os == 'win' && os_version == '11.26100' && processor == 'x86_64' && asan", # Bug 1966872, Bug 2030884
|
||||
"os == 'win' && os_version == '11.26200' && processor == 'x86_64' && asan", # Bug 1966872, Bug 2030884
|
||||
]
|
||||
|
||||
["browser_target_cached-front.js"]
|
||||
|
||||
|
|
@ -297,9 +291,6 @@ fail-if = ["a11y_checks"] # Bug 1849028 clicked element may not be focusable and
|
|||
["browser_toolbox_watchedByDevTools.js"]
|
||||
|
||||
["browser_toolbox_window_global_debugging.js"]
|
||||
skip-if = [
|
||||
"os == 'linux' && processor == 'x86_64' && tsan", # Bug 1950845, Bug 2030884
|
||||
]
|
||||
|
||||
["browser_toolbox_window_reload_target.js"]
|
||||
|
||||
|
|
|
|||
|
|
@ -150,11 +150,8 @@ fail-if = ["a11y_checks"] # Bug 1849028 clicked element may not be focusable and
|
|||
|
||||
["browser_animation_logic_mutations_fast.js"]
|
||||
skip-if = [
|
||||
"os == 'linux' && processor == 'x86_64' && asan", # Bug 1980142, Bug 2030884
|
||||
"os == 'linux' && processor == 'x86_64' && debug", # Bug 1567800, Bug 2030884
|
||||
"os == 'linux' && processor == 'x86_64' && tsan", # Bug 1980142, Bug 2030884
|
||||
"os == 'win' && os_version == '11.26100' && processor == 'x86_64' && debug", # Bug 1980142, Bug 2030884
|
||||
"os == 'win' && os_version == '11.26200' && processor == 'x86_64' && debug", # Bug 1980142, Bug 2030884
|
||||
"os == 'linux' && os_version == '18.04' && processor == 'x86_64' && debug", # Bug 1567800
|
||||
"os == 'linux' && os_version == '24.04' && processor == 'x86_64' && display == 'x11' && debug", # Bug 1567800
|
||||
]
|
||||
|
||||
["browser_animation_logic_mutations_properties.js"]
|
||||
|
|
|
|||
|
|
@ -746,7 +746,7 @@ class RequestListContextMenu {
|
|||
};
|
||||
|
||||
const options = JSON.stringify(fetchOptions, null, 4);
|
||||
const fetchString = `await fetch(${JSON.stringify(url)}, ${options});`;
|
||||
const fetchString = `await fetch("${url}", ${options});`;
|
||||
return fetchString;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -50,11 +50,10 @@ add_task(async function () {
|
|||
const types = ["end", "response", "duration", "latency"];
|
||||
|
||||
for (const t of types) {
|
||||
info("Check the timing column for type: " + t);
|
||||
await waitUntil(() => {
|
||||
const node = item.querySelector(".requests-list-" + t + "-time");
|
||||
const value = parseInt(node.textContent, 10);
|
||||
return value >= 0;
|
||||
return value > 0;
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@
|
|||
* Tests if Copy as Fetch works.
|
||||
*/
|
||||
|
||||
add_task(async function testBasicCopyAsFetch() {
|
||||
add_task(async function () {
|
||||
const { tab, monitor } = await initNetMonitor(HTTPS_CURL_URL, {
|
||||
requestCount: 1,
|
||||
});
|
||||
|
|
@ -15,9 +15,7 @@ add_task(async function testBasicCopyAsFetch() {
|
|||
|
||||
// GET request, no cookies (first request)
|
||||
await performRequest("GET");
|
||||
await testClipboardContent(
|
||||
monitor,
|
||||
`await fetch("https://example.com/browser/devtools/client/netmonitor/test/sjs_simple-test-server.sjs", {
|
||||
await testClipboardContent(`await fetch("https://example.com/browser/devtools/client/netmonitor/test/sjs_simple-test-server.sjs", {
|
||||
"credentials": "omit",
|
||||
"headers": {
|
||||
"User-Agent": "${navigator.userAgent}",
|
||||
|
|
@ -35,8 +33,7 @@ add_task(async function testBasicCopyAsFetch() {
|
|||
"referrer": "https://example.com/browser/devtools/client/netmonitor/test/html_copy-as-curl.html",
|
||||
"method": "GET",
|
||||
"mode": "cors"
|
||||
});`
|
||||
);
|
||||
});`);
|
||||
|
||||
await teardown(monitor);
|
||||
|
||||
|
|
@ -57,71 +54,39 @@ add_task(async function testBasicCopyAsFetch() {
|
|||
);
|
||||
await waitRequest;
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* Tests for Url escaping of copy as Fetch
|
||||
*/
|
||||
add_task(async function testUrlEscapeOfCopyAsFetch() {
|
||||
const { monitor } = await initNetMonitor(HTTPS_CURL_URL, {
|
||||
requestCount: 1,
|
||||
});
|
||||
info("Starting test... ");
|
||||
async function testClipboardContent(expectedResult) {
|
||||
const { document } = monitor.panelWin;
|
||||
|
||||
const waitRequest = waitForNetworkEvents(monitor, 1);
|
||||
await SpecialPowers.spawn(
|
||||
gBrowser.selectedBrowser,
|
||||
['data:text/html,"+alert(document.domain)+"'],
|
||||
url => {
|
||||
content.fetch(url);
|
||||
}
|
||||
);
|
||||
await waitRequest;
|
||||
const items = document.querySelectorAll(".request-list-item");
|
||||
EventUtils.sendMouseEvent({ type: "mousedown" }, items[items.length - 1]);
|
||||
EventUtils.sendMouseEvent(
|
||||
{ type: "contextmenu" },
|
||||
document.querySelectorAll(".request-list-item")[0]
|
||||
);
|
||||
|
||||
await testClipboardContent(
|
||||
monitor,
|
||||
`await fetch("data:text/html,\\"+alert(document.domain)+\\"", {
|
||||
"credentials": "omit",
|
||||
"headers": {},
|
||||
"method": "GET",
|
||||
"mode": "cors"
|
||||
});`
|
||||
);
|
||||
/* Ensure that the copy as fetch option is always visible */
|
||||
is(
|
||||
!!getContextMenuItem(monitor, "request-list-context-copy-as-fetch"),
|
||||
true,
|
||||
'The "Copy as Fetch" context menu item should not be hidden.'
|
||||
);
|
||||
|
||||
await teardown(monitor);
|
||||
});
|
||||
|
||||
async function testClipboardContent(monitor, expectedResult) {
|
||||
const { document } = monitor.panelWin;
|
||||
|
||||
const items = document.querySelectorAll(".request-list-item");
|
||||
EventUtils.sendMouseEvent({ type: "mousedown" }, items[items.length - 1]);
|
||||
EventUtils.sendMouseEvent(
|
||||
{ type: "contextmenu" },
|
||||
document.querySelectorAll(".request-list-item")[0]
|
||||
);
|
||||
|
||||
/* Ensure that the copy as fetch option is always visible */
|
||||
is(
|
||||
!!getContextMenuItem(monitor, "request-list-context-copy-as-fetch"),
|
||||
true,
|
||||
'The "Copy as Fetch" context menu item should not be hidden.'
|
||||
);
|
||||
|
||||
await waitForClipboardPromise(
|
||||
async function setup() {
|
||||
await selectContextMenuItem(
|
||||
monitor,
|
||||
"request-list-context-copy-as-fetch"
|
||||
);
|
||||
},
|
||||
function validate(result) {
|
||||
if (typeof result !== "string") {
|
||||
return false;
|
||||
await waitForClipboardPromise(
|
||||
async function setup() {
|
||||
await selectContextMenuItem(
|
||||
monitor,
|
||||
"request-list-context-copy-as-fetch"
|
||||
);
|
||||
},
|
||||
function validate(result) {
|
||||
if (typeof result !== "string") {
|
||||
return false;
|
||||
}
|
||||
return expectedResult === result;
|
||||
}
|
||||
return expectedResult === result;
|
||||
}
|
||||
);
|
||||
);
|
||||
|
||||
info("Clipboard contains a fetch command for item " + (items.length - 1));
|
||||
}
|
||||
info("Clipboard contains a fetch command for item " + (items.length - 1));
|
||||
}
|
||||
});
|
||||
|
|
|
|||
|
|
@ -10,13 +10,15 @@ const DEFAULT_DPPX = window.devicePixelRatio;
|
|||
|
||||
/* eslint-disable max-len */
|
||||
const TEST_DEVICE = {
|
||||
name: "iPhone 17 / 17 Pro",
|
||||
width: 402,
|
||||
height: 874,
|
||||
pixelRatio: 3,
|
||||
name: "iPhone 6/7/8",
|
||||
width: 375,
|
||||
height: 667,
|
||||
pixelRatio: 2,
|
||||
userAgent:
|
||||
"Mozilla/5.0 (iPhone; CPU iPhone OS 18_6 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/26.0 Mobile/15E148 Safari/604.1",
|
||||
"Mozilla/5.0 (iPhone; CPU iPhone OS 11_0 like Mac OS X) AppleWebKit/604.1.38 (KHTML, like Gecko) Version/11.0 Mobile/15A372 Safari/604.1",
|
||||
touch: true,
|
||||
icecatOS: false,
|
||||
os: "iOS",
|
||||
featured: true,
|
||||
};
|
||||
/* eslint-enable max-len */
|
||||
|
|
|
|||
|
|
@ -587,9 +587,7 @@ support-files = ["browser_webconsole_object_inspector_entries.snapshot.mjs"]
|
|||
https_first_disabled = true # JS HttpServer doesn't support https
|
||||
skip-if = [
|
||||
"http3", # JS HttpServer doesn't support http3
|
||||
"os == 'linux' && os_version == '18.04' && processor == 'x86_64' && opt", # Bug 1965340, Bug 2030884
|
||||
"os == 'linux' && os_version == '24.04' && processor == 'x86_64' && display == 'x11' && opt", # Bug 1965340
|
||||
"os == 'mac' && os_version == '14.70' && processor == 'x86_64'", # Bug 1965340, Bug 2030884
|
||||
]
|
||||
|
||||
["browser_webconsole_object_inspector_getters.js"]
|
||||
|
|
|
|||
|
|
@ -179,17 +179,17 @@ function getCleanedPacket(key, packet) {
|
|||
res.startedDateTime = existingPacket.startedDateTime;
|
||||
}
|
||||
|
||||
if (res.totalTime && existingPacket.totalTime) {
|
||||
res.totalTime = existingPacket.totalTime;
|
||||
}
|
||||
|
||||
if (res.securityState && existingPacket.securityState) {
|
||||
res.securityState = existingPacket.securityState;
|
||||
}
|
||||
|
||||
// totalTime and waitingTime can be very small and rounded to 0. However this
|
||||
// is still a valid time value, so check isNaN instead of a simple truthy check.
|
||||
if (!isNaN(res.totalTime) && !isNaN(existingPacket.totalTime)) {
|
||||
res.totalTime = existingPacket.totalTime;
|
||||
}
|
||||
|
||||
if (!isNaN(res.waitingTime) && !isNaN(existingPacket.waitingTime)) {
|
||||
// waitingTime can be very small and rounded to 0. However this is still a
|
||||
// valid waiting time, so check isNaN instead of a simple truthy check.
|
||||
if (!isNaN(res.waitingTime) && existingPacket.waitingTime) {
|
||||
res.waitingTime = existingPacket.waitingTime;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1937,19 +1937,6 @@ NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_THIS_BEGIN(BrowsingContext)
|
|||
return IsCertainlyAliveForCC(tmp);
|
||||
NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_THIS_END
|
||||
|
||||
/* static */
|
||||
void BrowsingContext::SweepWindowProxies(JSTracer* aTrc) {
|
||||
if (!sBrowsingContexts) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (BrowsingContext* bc : sBrowsingContexts->Values()) {
|
||||
if (bc->mWindowProxy) {
|
||||
JS_UpdateWeakPointerAfterGC(aTrc, &bc->mWindowProxy);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class RemoteLocationProxy
|
||||
: public RemoteObjectProxy<BrowsingContext::LocationProxy,
|
||||
Location_Binding::sCrossOriginProperties> {
|
||||
|
|
@ -2799,11 +2786,6 @@ void BrowsingContext::DidSet(FieldIndex<IDX_ExplicitActive>,
|
|||
});
|
||||
}
|
||||
|
||||
bool BrowsingContext::CanSet(FieldIndex<IDX_InRDMPane>, const bool&,
|
||||
ContentParent* aSource) {
|
||||
return XRE_IsParentProcess() && IsTop() && !aSource;
|
||||
}
|
||||
|
||||
void BrowsingContext::DidSet(FieldIndex<IDX_InRDMPane>, bool aOldValue) {
|
||||
MOZ_ASSERT(IsTop(),
|
||||
"Should only set InRDMPane in the top-level browsing context");
|
||||
|
|
|
|||
|
|
@ -734,9 +734,6 @@ class BrowsingContext : public nsILoadContext, public nsWrapperCache {
|
|||
mWindowProxy = aWindowProxy;
|
||||
}
|
||||
|
||||
// Since mWindowProxy is a weak pointer it has to be updated during sweeping.
|
||||
static void SweepWindowProxies(JSTracer* aTrc);
|
||||
|
||||
Nullable<WindowProxyHolder> GetWindow();
|
||||
|
||||
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
|
||||
|
|
@ -1139,7 +1136,6 @@ class BrowsingContext : public nsILoadContext, public nsWrapperCache {
|
|||
return IsTop();
|
||||
}
|
||||
|
||||
bool CanSet(FieldIndex<IDX_InRDMPane>, const bool&, ContentParent* aSource);
|
||||
void DidSet(FieldIndex<IDX_InRDMPane>, bool aOldValue);
|
||||
MOZ_CAN_RUN_SCRIPT_BOUNDARY void DidSet(FieldIndex<IDX_ForceDesktopViewport>,
|
||||
bool aOldValue);
|
||||
|
|
@ -1381,8 +1377,10 @@ class BrowsingContext : public nsILoadContext, public nsWrapperCache {
|
|||
|
||||
RefPtr<nsGeolocationService> mGeolocationServiceOverride;
|
||||
|
||||
// This is a weak reference. It will be updated automatically during sweeping
|
||||
// by SweepWindowProxies.
|
||||
// This is not a strong reference, but using a JS::Heap for that should be
|
||||
// fine. The JSObject stored in here should be a proxy with a
|
||||
// nsOuterWindowProxy handler, which will update the pointer from its
|
||||
// objectMoved hook and clear it from its finalize hook.
|
||||
JS::Heap<JSObject*> mWindowProxy;
|
||||
LocationProxy mLocation;
|
||||
|
||||
|
|
|
|||
|
|
@ -38,11 +38,6 @@ void AbortSignalImpl::GetReason(JSContext* aCx,
|
|||
}
|
||||
MaybeAssignAbortError(aCx);
|
||||
aReason.set(mReason);
|
||||
if (NS_WARN_IF(!JS_WrapValue(aCx, aReason))) {
|
||||
aReason.setUndefined();
|
||||
// TODO(Bug 2026137) - AbortSignalImpl::GetReason should be made fallible
|
||||
JS_ClearPendingException(aCx);
|
||||
}
|
||||
}
|
||||
|
||||
JS::Value AbortSignalImpl::RawReason() const { return mReason.get(); }
|
||||
|
|
@ -80,7 +75,7 @@ void AbortSignalImpl::RunAbortSteps() {
|
|||
// https://dom.spec.whatwg.org/#abortsignal-remove could be invoked in an
|
||||
// earlier algorithm to remove a later algorithm, so |mFollowers| must be a
|
||||
// |nsTObserverArray| to defend against mutation.
|
||||
for (RefPtr<AbortFollower> follower : mFollowers.ForwardRange()) {
|
||||
for (RefPtr<AbortFollower>& follower : mFollowers.ForwardRange()) {
|
||||
MOZ_ASSERT(follower->mFollowingSignal == this);
|
||||
follower->RunAbortAlgorithm();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -386,9 +386,11 @@ void Animation::SetStartTime(const Nullable<TimeDuration>& aNewStartTime) {
|
|||
}
|
||||
|
||||
CancelPendingTasks();
|
||||
// We may have already resolved mReady, but in that case calling
|
||||
// MaybeResolve is a no-op, so that's okay.
|
||||
MaybeResolvePromiseWithThis(mReady);
|
||||
if (mReady) {
|
||||
// We may have already resolved mReady, but in that case calling
|
||||
// MaybeResolve is a no-op, so that's okay.
|
||||
mReady->MaybeResolve(this);
|
||||
}
|
||||
|
||||
UpdateTiming(SeekFlag::DidSeek, SyncNotifyFlag::Async);
|
||||
if (IsRelevant()) {
|
||||
|
|
@ -447,7 +449,9 @@ void Animation::SetCurrentTimeNoUpdate(const TimeDuration& aSeekTime) {
|
|||
ApplyPendingPlaybackRate();
|
||||
mStartTime.SetNull();
|
||||
|
||||
MaybeResolvePromiseWithThis(mReady);
|
||||
if (mReady) {
|
||||
mReady->MaybeResolve(this);
|
||||
}
|
||||
CancelPendingTasks();
|
||||
}
|
||||
|
||||
|
|
@ -604,25 +608,11 @@ Promise* Animation::GetReady(ErrorResult& aRv) {
|
|||
return nullptr;
|
||||
}
|
||||
if (!Pending()) {
|
||||
MaybeResolvePromiseWithThis(mReady);
|
||||
mReady->MaybeResolve(this);
|
||||
}
|
||||
return mReady;
|
||||
}
|
||||
|
||||
void Animation::MaybeResolvePromiseWithThis(Promise* aPromise) {
|
||||
if (!aPromise) {
|
||||
return;
|
||||
}
|
||||
if (!nsContentUtils::IsSafeToRunScript()) {
|
||||
nsContentUtils::AddScriptRunner(NewRunnableMethod<RefPtr<Promise>>(
|
||||
"MaybeResolvePromiseWithThis", this,
|
||||
&Animation::MaybeResolvePromiseWithThis, aPromise));
|
||||
return;
|
||||
}
|
||||
RefPtr promise = aPromise;
|
||||
promise->MaybeResolve(this);
|
||||
}
|
||||
|
||||
Promise* Animation::GetFinished(ErrorResult& aRv) {
|
||||
nsCOMPtr<nsIGlobalObject> global = GetOwnerGlobal();
|
||||
if (!mFinished && global) {
|
||||
|
|
@ -724,7 +714,9 @@ void Animation::Finish(ErrorResult& aRv) {
|
|||
}
|
||||
CancelPendingTasks();
|
||||
didChange = true;
|
||||
MaybeResolvePromiseWithThis(mReady);
|
||||
if (mReady) {
|
||||
mReady->MaybeResolve(this);
|
||||
}
|
||||
}
|
||||
UpdateTiming(SeekFlag::DidSeek, SyncNotifyFlag::Sync);
|
||||
if (didChange && IsRelevant()) {
|
||||
|
|
@ -1615,7 +1607,9 @@ void Animation::ResumeAt(const TimeDuration& aReadyTime) {
|
|||
MutationObservers::NotifyAnimationChanged(this);
|
||||
}
|
||||
|
||||
MaybeResolvePromiseWithThis(mReady);
|
||||
if (mReady) {
|
||||
mReady->MaybeResolve(this);
|
||||
}
|
||||
}
|
||||
|
||||
void Animation::PauseAt(const TimeDuration& aReadyTime) {
|
||||
|
|
@ -1632,7 +1626,9 @@ void Animation::PauseAt(const TimeDuration& aReadyTime) {
|
|||
|
||||
UpdateTiming(SeekFlag::NoSeek, SyncNotifyFlag::Async);
|
||||
|
||||
MaybeResolvePromiseWithThis(mReady);
|
||||
if (mReady) {
|
||||
mReady->MaybeResolve(this);
|
||||
}
|
||||
}
|
||||
|
||||
void Animation::UpdateTiming(SeekFlag aSeekFlag,
|
||||
|
|
@ -1881,8 +1877,10 @@ void Animation::ResetFinishedPromise() {
|
|||
}
|
||||
|
||||
void Animation::MaybeResolveFinishedPromise() {
|
||||
if (mFinished) {
|
||||
mFinished->MaybeResolve(this);
|
||||
}
|
||||
mFinishedIsResolved = true;
|
||||
MaybeResolvePromiseWithThis(mFinished);
|
||||
}
|
||||
|
||||
void Animation::DoFinishNotificationImmediately(MicroTaskRunnable* aAsync) {
|
||||
|
|
|
|||
|
|
@ -466,7 +466,6 @@ class Animation : public DOMEventTargetHelper,
|
|||
friend class AsyncFinishNotification;
|
||||
void DoFinishNotificationImmediately(MicroTaskRunnable* aAsync = nullptr);
|
||||
void QueuePlaybackEvent(nsAtom* aOnEvent, TimeStamp&& aScheduledEventTime);
|
||||
void MaybeResolvePromiseWithThis(Promise*);
|
||||
|
||||
/**
|
||||
* Remove this animation from the pending animation tracker and reset
|
||||
|
|
|
|||
|
|
@ -10664,25 +10664,23 @@ void nsDOMAttributeMap::BlastSubtreeToPieces(nsINode* aNode) {
|
|||
|
||||
mozilla::DebugOnly<nsresult> rv =
|
||||
element->UnsetAttr(attr->NodeInfo()->NamespaceID(),
|
||||
attr->NodeInfo()->NameAtom(), true);
|
||||
attr->NodeInfo()->NameAtom(), false);
|
||||
|
||||
// XXX Should we abort here?
|
||||
NS_ASSERTION(NS_SUCCEEDED(rv), "Uh-oh, UnsetAttr shouldn't fail!");
|
||||
}
|
||||
}
|
||||
|
||||
// Hold the strong reference to be sure, since we may notify
|
||||
if (RefPtr<mozilla::dom::ShadowRoot> shadow = element->GetShadowRoot()) {
|
||||
if (mozilla::dom::ShadowRoot* shadow = element->GetShadowRoot()) {
|
||||
BlastSubtreeToPieces(shadow);
|
||||
element->UnattachShadow();
|
||||
}
|
||||
}
|
||||
|
||||
while (aNode->HasChildren()) {
|
||||
// Hold the strong reference to be sure, since we are notifying.
|
||||
nsCOMPtr<nsIContent> node = aNode->GetFirstChild();
|
||||
nsIContent* node = aNode->GetFirstChild();
|
||||
BlastSubtreeToPieces(node);
|
||||
aNode->RemoveChildNode(node, true);
|
||||
aNode->RemoveChildNode(node, false);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -16277,16 +16275,11 @@ void Document::RequestFullscreenInParentProcess(
|
|||
|
||||
/* static */
|
||||
bool Document::HandlePendingFullscreenRequests(Document* aDoc) {
|
||||
AutoTArray<UniquePtr<FullscreenRequest>, 1> requests;
|
||||
{
|
||||
PendingFullscreenChangeList::Iterator<FullscreenRequest> iter(
|
||||
aDoc, PendingFullscreenChangeList::eDocumentsWithSameRoot);
|
||||
while (!iter.AtEnd()) {
|
||||
requests.AppendElement(iter.TakeAndNext());
|
||||
}
|
||||
}
|
||||
bool handled = false;
|
||||
for (UniquePtr<FullscreenRequest>& request : requests) {
|
||||
PendingFullscreenChangeList::Iterator<FullscreenRequest> iter(
|
||||
aDoc, PendingFullscreenChangeList::eDocumentsWithSameRoot);
|
||||
while (!iter.AtEnd()) {
|
||||
UniquePtr<FullscreenRequest> request = iter.TakeAndNext();
|
||||
Document* doc = request->Document();
|
||||
if (doc->ApplyFullscreen(std::move(request))) {
|
||||
handled = true;
|
||||
|
|
|
|||
|
|
@ -5732,7 +5732,7 @@ class MOZ_RAII IgnoreOpensDuringUnload final {
|
|||
}
|
||||
|
||||
private:
|
||||
RefPtr<Document> mDoc;
|
||||
Document* mDoc;
|
||||
};
|
||||
|
||||
bool IsInFocusedTab(Document* aDoc);
|
||||
|
|
|
|||
|
|
@ -7,7 +7,6 @@
|
|||
#include "DocumentOrShadowRoot.h"
|
||||
#include "mozilla/AnimationComparator.h"
|
||||
#include "mozilla/EventStateManager.h"
|
||||
#include "mozilla/Likely.h"
|
||||
#include "mozilla/PointerLockManager.h"
|
||||
#include "mozilla/PresShell.h"
|
||||
#include "mozilla/StyleSheet.h"
|
||||
|
|
@ -113,10 +112,6 @@ void DocumentOrShadowRoot::RemoveSheetFromStylesIfApplicable(
|
|||
void DocumentOrShadowRoot::OnSetAdoptedStyleSheets(StyleSheet& aSheet,
|
||||
uint32_t aIndex,
|
||||
ErrorResult& aRv) {
|
||||
if (MOZ_UNLIKELY(aIndex > mAdoptedStyleSheets.Length())) {
|
||||
MOZ_ASSERT_UNREACHABLE("Out of sync proxy");
|
||||
return;
|
||||
}
|
||||
Document& doc = *AsNode().OwnerDoc();
|
||||
// 1. If value’s constructed flag is not set, or its constructor document is
|
||||
// not equal to this DocumentOrShadowRoot's node document, throw a
|
||||
|
|
@ -169,10 +164,7 @@ void DocumentOrShadowRoot::OnSetAdoptedStyleSheets(StyleSheet& aSheet,
|
|||
void DocumentOrShadowRoot::OnDeleteAdoptedStyleSheets(StyleSheet& aSheet,
|
||||
uint32_t aIndex,
|
||||
ErrorResult&) {
|
||||
if (MOZ_UNLIKELY(mAdoptedStyleSheets.ElementAt(aIndex) != &aSheet)) {
|
||||
MOZ_ASSERT_UNREACHABLE("Out of sync proxy");
|
||||
return;
|
||||
}
|
||||
MOZ_ASSERT(mAdoptedStyleSheets.ElementAt(aIndex) == &aSheet);
|
||||
mAdoptedStyleSheets.RemoveElementAt(aIndex);
|
||||
auto existingIndex = mAdoptedStyleSheets.LastIndexOf(&aSheet);
|
||||
if (existingIndex != mAdoptedStyleSheets.NoIndex && existingIndex >= aIndex) {
|
||||
|
|
|
|||
|
|
@ -279,9 +279,8 @@ nsIFrame* nsIContent::GetPrimaryFrame(mozilla::FlushType aType) {
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
RefPtr<mozilla::PresShell> presShell = frame->PresShell();
|
||||
if (aType == mozilla::FlushType::Layout) {
|
||||
presShell->EnsureReflowIfFrameHasHiddenContent(frame);
|
||||
frame->PresShell()->EnsureReflowIfFrameHasHiddenContent(frame);
|
||||
frame = GetPrimaryFrame();
|
||||
}
|
||||
|
||||
|
|
@ -2808,7 +2807,6 @@ bool Element::OnlyNotifySameValueSet(int32_t aNamespaceID, nsAtom* aName,
|
|||
}
|
||||
|
||||
nsAutoScriptBlocker scriptBlocker;
|
||||
OnAttrSetButNotChanged(aNamespaceID, aName, aValue, aNotify);
|
||||
MutationObservers::NotifyAttributeSetToCurrentValue(this, aNamespaceID,
|
||||
aName);
|
||||
return true;
|
||||
|
|
@ -2858,6 +2856,7 @@ nsresult Element::SetAttr(int32_t aNamespaceID, nsAtom* aName, nsAtom* aPrefix,
|
|||
if (OnlyNotifySameValueSet(aNamespaceID, aName, aPrefix, value, aNotify,
|
||||
oldValue, &modType, &hasListeners,
|
||||
&oldValueSet)) {
|
||||
OnAttrSetButNotChanged(aNamespaceID, aName, value, aNotify);
|
||||
return NS_OK;
|
||||
}
|
||||
}
|
||||
|
|
@ -2907,6 +2906,7 @@ nsresult Element::SetParsedAttr(int32_t aNamespaceID, nsAtom* aName,
|
|||
if (OnlyNotifySameValueSet(aNamespaceID, aName, aPrefix, value, aNotify,
|
||||
oldValue, &modType, &hasListeners,
|
||||
&oldValueSet)) {
|
||||
OnAttrSetButNotChanged(aNamespaceID, aName, value, aNotify);
|
||||
return NS_OK;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -341,8 +341,8 @@ nsresult ImageEncoder::ExtractDataInternal(
|
|||
return NS_ERROR_INVALID_ARG;
|
||||
}
|
||||
auto size = data->GetSize();
|
||||
rv = aEncoder->InitFromData(map.mData, map.mStride * size.height,
|
||||
size.width, size.height, map.mStride,
|
||||
rv = aEncoder->InitFromData(map.mData, size.width * size.height * 4,
|
||||
size.width, size.height, size.width * 4,
|
||||
imgIEncoder::INPUT_FORMAT_HOSTARGB, aOptions);
|
||||
data->Unmap();
|
||||
}
|
||||
|
|
@ -374,8 +374,8 @@ nsresult ImageEncoder::ExtractDataInternal(
|
|||
}
|
||||
|
||||
rv = aEncoder->InitFromData(data.Elements(),
|
||||
length, aSize.width,
|
||||
aSize.height, stride,
|
||||
aSize.width * aSize.height * 4, aSize.width,
|
||||
aSize.height, aSize.width * 4,
|
||||
imgIEncoder::INPUT_FORMAT_HOSTARGB, aOptions);
|
||||
} else {
|
||||
if (BufferSizeFromDimensions(aSize.width, aSize.height, 4) == 0) {
|
||||
|
|
@ -391,8 +391,8 @@ nsresult ImageEncoder::ExtractDataInternal(
|
|||
return NS_ERROR_INVALID_ARG;
|
||||
}
|
||||
auto size = dataSurface->GetSize();
|
||||
rv = aEncoder->InitFromData(map.mData, map.mStride * size.height,
|
||||
size.width, size.height, map.mStride,
|
||||
rv = aEncoder->InitFromData(map.mData, size.width * size.height * 4,
|
||||
size.width, size.height, size.width * 4,
|
||||
imgIEncoder::INPUT_FORMAT_HOSTARGB, aOptions);
|
||||
dataSurface->Unmap();
|
||||
}
|
||||
|
|
@ -421,13 +421,13 @@ nsresult ImageEncoder::ExtractDataInternal(
|
|||
if (!emptyCanvas->Map(DataSourceSurface::MapType::WRITE, &map)) {
|
||||
return NS_ERROR_INVALID_ARG;
|
||||
}
|
||||
auto size = map.mStride * aSize.height;
|
||||
if (aUsePlaceholder) {
|
||||
auto size = 4 * aSize.width * aSize.height;
|
||||
auto* data = map.mData;
|
||||
GeneratePlaceholderCanvasData(size, data);
|
||||
}
|
||||
rv = aEncoder->InitFromData(map.mData, size, aSize.width, aSize.height,
|
||||
map.mStride,
|
||||
rv = aEncoder->InitFromData(map.mData, aSize.width * aSize.height * 4,
|
||||
aSize.width, aSize.height, aSize.width * 4,
|
||||
imgIEncoder::INPUT_FORMAT_HOSTARGB, aOptions);
|
||||
emptyCanvas->Unmap();
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
|
|
|
|||
|
|
@ -271,7 +271,6 @@ template <typename char_type>
|
|||
const nsTSubstring<char_type>& aMimeType,
|
||||
nsTSubstring<char_type>& aOutEssence,
|
||||
nsTSubstring<char_type>& aOutCharset) {
|
||||
// https://fetch.spec.whatwg.org/#concept-header-extract-mime-type
|
||||
static char_type kCHARSET[] = {'c', 'h', 'a', 'r', 's', 'e', 't'};
|
||||
static nsTDependentSubstring<char_type> kCharset(kCHARSET, 7);
|
||||
|
||||
|
|
@ -279,8 +278,8 @@ template <typename char_type>
|
|||
nsTAutoString<char_type> prevContentType;
|
||||
nsTAutoString<char_type> prevCharset;
|
||||
|
||||
aOutEssence.Truncate();
|
||||
aOutCharset.Truncate();
|
||||
prevContentType.Assign(aOutEssence);
|
||||
prevCharset.Assign(aOutCharset);
|
||||
|
||||
nsTArray<nsTDependentSubstring<char_type>> mimeTypeParts =
|
||||
SplitMimetype(aMimeType);
|
||||
|
|
@ -293,7 +292,9 @@ template <typename char_type>
|
|||
parsed = Parse(mimeTypeString);
|
||||
|
||||
if (!parsed) {
|
||||
continue;
|
||||
aOutEssence.Truncate();
|
||||
aOutCharset.Truncate();
|
||||
return false;
|
||||
}
|
||||
|
||||
parsed->GetEssence(aOutEssence);
|
||||
|
|
@ -321,10 +322,6 @@ template <typename char_type>
|
|||
}
|
||||
}
|
||||
|
||||
if (aOutEssence.IsEmpty()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -70,24 +70,15 @@ ScreenOrientation::ScreenOrientation(nsPIDOMWindowInner* aWindow,
|
|||
: DOMEventTargetHelper(aWindow), mScreen(aScreen) {
|
||||
MOZ_ASSERT(aWindow);
|
||||
MOZ_ASSERT(aScreen);
|
||||
}
|
||||
|
||||
/* static */ already_AddRefed<ScreenOrientation> ScreenOrientation::Create(
|
||||
nsPIDOMWindowInner* aWindow, nsScreen* aScreen) {
|
||||
RefPtr screenOrientation = new ScreenOrientation(aWindow, aScreen);
|
||||
mAngle = aScreen->GetOrientationAngle();
|
||||
mType = InternalOrientationToType(aScreen->GetOrientationType());
|
||||
|
||||
screenOrientation->mAngle = aScreen->GetOrientationAngle();
|
||||
screenOrientation->mType =
|
||||
InternalOrientationToType(aScreen->GetOrientationType());
|
||||
|
||||
Document* doc = screenOrientation->GetResponsibleDocument();
|
||||
Document* doc = GetResponsibleDocument();
|
||||
BrowsingContext* bc = doc ? doc->GetBrowsingContext() : nullptr;
|
||||
if (bc && !bc->IsDiscarded() && !bc->InRDMPane()) {
|
||||
MOZ_ALWAYS_SUCCEEDS(bc->SetCurrentOrientation(screenOrientation->mType,
|
||||
screenOrientation->mAngle));
|
||||
MOZ_ALWAYS_SUCCEEDS(bc->SetCurrentOrientation(mType, mAngle));
|
||||
}
|
||||
|
||||
return screenOrientation.forget();
|
||||
}
|
||||
|
||||
ScreenOrientation::~ScreenOrientation() {
|
||||
|
|
|
|||
|
|
@ -33,13 +33,8 @@ class ScreenOrientation final : public DOMEventTargetHelper {
|
|||
// Called when the orientation may have changed.
|
||||
void MaybeChanged();
|
||||
|
||||
private:
|
||||
ScreenOrientation(nsPIDOMWindowInner* aWindow, nsScreen* aScreen);
|
||||
|
||||
public:
|
||||
static already_AddRefed<ScreenOrientation> Create(nsPIDOMWindowInner* aWindow,
|
||||
nsScreen* aScreen);
|
||||
|
||||
already_AddRefed<Promise> Lock(OrientationLockType aOrientation,
|
||||
ErrorResult& aRv);
|
||||
|
||||
|
|
@ -112,8 +107,8 @@ class ScreenOrientation final : public DOMEventTargetHelper {
|
|||
RefPtr<nsScreen> mScreen;
|
||||
RefPtr<FullscreenEventListener> mFullscreenListener;
|
||||
RefPtr<VisibleEventListener> mVisibleListener;
|
||||
OrientationType mType{};
|
||||
uint16_t mAngle{};
|
||||
OrientationType mType;
|
||||
uint16_t mAngle;
|
||||
// Whether we've tried to call into hal to lock the device orientation. This
|
||||
// is needed because you don't want calling UnlockDeviceOrientation() during
|
||||
// shutdown to initialize PHal if it hasn't been initialized earlier. Also,
|
||||
|
|
|
|||
|
|
@ -213,7 +213,7 @@ void ShadowRoot::Unattach() {
|
|||
|
||||
void ShadowRoot::InvalidateStyleAndLayoutOnSubtree(Element* aElement) {
|
||||
MOZ_ASSERT(aElement);
|
||||
Document* doc = aElement->GetComposedDoc();
|
||||
Document* doc = GetComposedDoc();
|
||||
if (!doc) {
|
||||
return;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -136,7 +136,7 @@ class ShadowRoot final : public DocumentFragment, public DocumentOrShadowRoot {
|
|||
* It is important that this runs _before_ actually shuffling the flat tree
|
||||
* around, so that layout knows the actual tree that it needs to invalidate.
|
||||
*/
|
||||
static void InvalidateStyleAndLayoutOnSubtree(Element*);
|
||||
void InvalidateStyleAndLayoutOnSubtree(Element*);
|
||||
|
||||
private:
|
||||
void InsertSheetIntoAuthorData(size_t aIndex, StyleSheet&,
|
||||
|
|
|
|||
|
|
@ -15,7 +15,6 @@
|
|||
#include "js/Wrapper.h"
|
||||
#include "jsapi.h"
|
||||
#include "mozilla/Assertions.h"
|
||||
#include "mozilla/CheckedInt.h"
|
||||
#include "mozilla/ErrorResult.h"
|
||||
#include "mozilla/Maybe.h"
|
||||
#include "mozilla/Span.h"
|
||||
|
|
@ -215,13 +214,8 @@ bool StructuredCloneBlob::WriteStructuredClone(JSContext* aCx,
|
|||
bool StructuredCloneBlob::Holder::WriteStructuredClone(
|
||||
JSContext* aCx, JSStructuredCloneWriter* aWriter,
|
||||
StructuredCloneHolder* aHolder) {
|
||||
const auto& data = mBuffer->data();
|
||||
CheckedUint32 dataSize(data.Size());
|
||||
if (!dataSize.isValid()) {
|
||||
return false;
|
||||
}
|
||||
if (!JS_WriteUint32Pair(aWriter, dataSize.value(),
|
||||
JS_STRUCTURED_CLONE_VERSION) ||
|
||||
auto& data = mBuffer->data();
|
||||
if (!JS_WriteUint32Pair(aWriter, data.Size(), JS_STRUCTURED_CLONE_VERSION) ||
|
||||
!JS_WriteUint32Pair(aWriter, aHolder->BlobImpls().Length(),
|
||||
BlobImpls().Length())) {
|
||||
return false;
|
||||
|
|
|
|||
|
|
@ -938,8 +938,9 @@ TextInputProcessor::NotifyIME(TextEventDispatcher* aTextEventDispatcher,
|
|||
NS_IMETHODIMP_(IMENotificationRequests)
|
||||
TextInputProcessor::GetIMENotificationRequests() {
|
||||
// TextInputProcessor should support all change notifications.
|
||||
return {IMENotificationRequest::TextChange,
|
||||
IMENotificationRequest::PositionChange};
|
||||
return IMENotificationRequests(
|
||||
IMENotificationRequests::NOTIFY_TEXT_CHANGE |
|
||||
IMENotificationRequests::NOTIFY_POSITION_CHANGE);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP_(void)
|
||||
|
|
|
|||
|
|
@ -27,10 +27,9 @@ class KeyboardEvent;
|
|||
|
||||
class TextInputProcessor final : public nsITextInputProcessor,
|
||||
public widget::TextEventDispatcherListener {
|
||||
using IMENotification = mozilla::widget::IMENotification;
|
||||
using IMENotificationRequest = mozilla::widget::IMENotificationRequest;
|
||||
using IMENotificationRequests = mozilla::widget::IMENotificationRequests;
|
||||
using TextEventDispatcher = mozilla::widget::TextEventDispatcher;
|
||||
typedef mozilla::widget::IMENotification IMENotification;
|
||||
typedef mozilla::widget::IMENotificationRequests IMENotificationRequests;
|
||||
typedef mozilla::widget::TextEventDispatcher TextEventDispatcher;
|
||||
|
||||
public:
|
||||
TextInputProcessor();
|
||||
|
|
|
|||
|
|
@ -1333,11 +1333,7 @@ void nsAttrValue::ParseAtom(const nsAString& aValue) {
|
|||
void nsAttrValue::ParseAtomArray(nsAtom* aValue) {
|
||||
if (MiscContainer* cont = AtomArrayCache::Lookup(aValue)) {
|
||||
// Set our MiscContainer to the cached one.
|
||||
// AddRef must happen before ResetIfSet: the cache does not hold a strong
|
||||
// reference, and ResetIfSet could release the last reference to cont if
|
||||
// this nsAttrValue is already holding it.
|
||||
NS_ADDREF(cont);
|
||||
ResetIfSet();
|
||||
SetPtrValueAndType(cont, eOtherBase);
|
||||
return;
|
||||
}
|
||||
|
|
@ -1937,11 +1933,7 @@ bool nsAttrValue::ParseStyleAttribute(const nsAString& aString,
|
|||
if (cachingAllowed) {
|
||||
if (MiscContainer* cont = attrStyles->LookupStyleAttr(aString)) {
|
||||
// Set our MiscContainer to the cached one.
|
||||
// AddRef must happen before ResetIfSet: the cache does not hold a strong
|
||||
// reference, and ResetIfSet could release the last reference to cont if
|
||||
// this nsAttrValue is already holding it.
|
||||
NS_ADDREF(cont);
|
||||
ResetIfSet();
|
||||
SetPtrValueAndType(cont, eOtherBase);
|
||||
return true;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -592,8 +592,7 @@ Element* nsContentList::NamedItem(const nsAString& aName, bool aDoFlush) {
|
|||
return mNamedItemsCache->Get(name);
|
||||
}
|
||||
|
||||
void nsContentList::GetSupportedNames(nsTArray<nsString>& aNames,
|
||||
FilterElementWithName aFilter) {
|
||||
void nsContentList::GetSupportedNames(nsTArray<nsString>& aNames) {
|
||||
BringSelfUpToDate(true);
|
||||
|
||||
AutoTArray<nsAtom*, 8> atoms;
|
||||
|
|
@ -607,14 +606,14 @@ void nsContentList::GetSupportedNames(nsTArray<nsString>& aNames,
|
|||
}
|
||||
}
|
||||
|
||||
if (nsGenericHTMLElement* el = nsGenericHTMLElement::FromNode(content)) {
|
||||
nsGenericHTMLElement* el = nsGenericHTMLElement::FromNode(content);
|
||||
if (el) {
|
||||
// XXXbz should we be checking for particular tags here? How
|
||||
// stable is this part of the spec?
|
||||
// Note: nsINode::HasName means the name is exposed on the document,
|
||||
// which is false for options, so we don't check it here.
|
||||
const nsAttrValue* val = el->GetParsedAttr(nsGkAtoms::name);
|
||||
if (val && val->Type() == nsAttrValue::eAtom &&
|
||||
(!aFilter || aFilter(el))) {
|
||||
if (val && val->Type() == nsAttrValue::eAtom) {
|
||||
nsAtom* name = val->GetAtomValue();
|
||||
MOZ_ASSERT(name != nsGkAtoms::_empty, "Empty names don't get atomized");
|
||||
if (!atoms.Contains(name)) {
|
||||
|
|
|
|||
|
|
@ -296,21 +296,13 @@ class nsContentList : public nsBaseContentList,
|
|||
aFound = !!item;
|
||||
return item;
|
||||
}
|
||||
void GetSupportedNames(nsTArray<nsString>& aNames) override {
|
||||
GetSupportedNames(aNames, nullptr);
|
||||
}
|
||||
void GetSupportedNames(nsTArray<nsString>& aNames) override;
|
||||
|
||||
// nsContentList public methods
|
||||
uint32_t Length(bool aDoFlush);
|
||||
nsIContent* Item(uint32_t aIndex, bool aDoFlush);
|
||||
Element* NamedItem(const nsAString& aName, bool aDoFlush);
|
||||
|
||||
// Used by HTMLAllCollection to limit the elements whose name attribute is
|
||||
// considered. The filter MUST NOT cause any flushes.
|
||||
using FilterElementWithName = bool (*)(nsIContent*);
|
||||
void GetSupportedNames(nsTArray<nsString>& aNames,
|
||||
FilterElementWithName aFilter);
|
||||
|
||||
// nsIMutationObserver
|
||||
NS_DECL_NSIMUTATIONOBSERVER_ATTRIBUTECHANGED
|
||||
NS_DECL_NSIMUTATIONOBSERVER_CONTENTAPPENDED
|
||||
|
|
|
|||
|
|
@ -44,15 +44,12 @@ class ContentPermissionRequestParent : public PContentPermissionRequestParent {
|
|||
// @param aIsRequestDelegatedToUnsafeThirdParty see
|
||||
// mIsRequestDelegatedToUnsafeThirdParty.
|
||||
ContentPermissionRequestParent(
|
||||
Element* aElement, nsIPrincipal* aPrincipal,
|
||||
nsIPrincipal* aTopLevelPrincipal,
|
||||
const nsTArray<PermissionRequest>& aRequests, Element* aElement,
|
||||
nsIPrincipal* aPrincipal, nsIPrincipal* aTopLevelPrincipal,
|
||||
const bool aHasValidTransientUserGestureActivation,
|
||||
const bool aIsRequestDelegatedToUnsafeThirdParty);
|
||||
virtual ~ContentPermissionRequestParent();
|
||||
|
||||
MOZ_CAN_RUN_SCRIPT_BOUNDARY
|
||||
void Init(nsTArray<PermissionRequest>&& aRequests);
|
||||
|
||||
bool IsBeingDestroyed();
|
||||
|
||||
nsCOMPtr<nsIPrincipal> mPrincipal;
|
||||
|
|
@ -67,13 +64,16 @@ class ContentPermissionRequestParent : public PContentPermissionRequestParent {
|
|||
nsTArray<PermissionRequest> mRequests;
|
||||
|
||||
private:
|
||||
// Not MOZ_CAN_RUN_SCRIPT because we can't annotate the thing we override yet.
|
||||
MOZ_CAN_RUN_SCRIPT_BOUNDARY
|
||||
virtual mozilla::ipc::IPCResult Recvprompt() override;
|
||||
virtual mozilla::ipc::IPCResult RecvDestroy() override;
|
||||
virtual void ActorDestroy(ActorDestroyReason why) override;
|
||||
};
|
||||
|
||||
ContentPermissionRequestParent::ContentPermissionRequestParent(
|
||||
Element* aElement, nsIPrincipal* aPrincipal,
|
||||
nsIPrincipal* aTopLevelPrincipal,
|
||||
const nsTArray<PermissionRequest>& aRequests, Element* aElement,
|
||||
nsIPrincipal* aPrincipal, nsIPrincipal* aTopLevelPrincipal,
|
||||
const bool aHasValidTransientUserGestureActivation,
|
||||
const bool aIsRequestDelegatedToUnsafeThirdParty) {
|
||||
MOZ_COUNT_CTOR(ContentPermissionRequestParent);
|
||||
|
|
@ -81,6 +81,7 @@ ContentPermissionRequestParent::ContentPermissionRequestParent(
|
|||
mPrincipal = aPrincipal;
|
||||
mTopLevelPrincipal = aTopLevelPrincipal;
|
||||
mElement = aElement;
|
||||
mRequests = aRequests.Clone();
|
||||
mHasValidTransientUserGestureActivation =
|
||||
aHasValidTransientUserGestureActivation;
|
||||
mIsRequestDelegatedToUnsafeThirdParty = aIsRequestDelegatedToUnsafeThirdParty;
|
||||
|
|
@ -90,14 +91,13 @@ ContentPermissionRequestParent::~ContentPermissionRequestParent() {
|
|||
MOZ_COUNT_DTOR(ContentPermissionRequestParent);
|
||||
}
|
||||
|
||||
void ContentPermissionRequestParent::Init(
|
||||
nsTArray<PermissionRequest>&& aRequests) {
|
||||
mRequests = std::move(aRequests);
|
||||
mozilla::ipc::IPCResult ContentPermissionRequestParent::Recvprompt() {
|
||||
mProxy = new nsContentPermissionRequestProxy(this);
|
||||
if (NS_FAILED(mProxy->Init(mRequests))) {
|
||||
RefPtr<nsContentPermissionRequestProxy> proxy(mProxy);
|
||||
proxy->Cancel();
|
||||
}
|
||||
return IPC_OK();
|
||||
}
|
||||
|
||||
mozilla::ipc::IPCResult ContentPermissionRequestParent::RecvDestroy() {
|
||||
|
|
@ -239,12 +239,12 @@ nsresult nsContentPermissionUtils::CreatePermissionArray(
|
|||
/* static */
|
||||
PContentPermissionRequestParent*
|
||||
nsContentPermissionUtils::CreateContentPermissionRequestParent(
|
||||
Element* aElement, nsIPrincipal* aPrincipal,
|
||||
nsIPrincipal* aTopLevelPrincipal,
|
||||
const nsTArray<PermissionRequest>& aRequests, Element* aElement,
|
||||
nsIPrincipal* aPrincipal, nsIPrincipal* aTopLevelPrincipal,
|
||||
const bool aHasValidTransientUserGestureActivation,
|
||||
const bool aIsRequestDelegatedToUnsafeThirdParty, const TabId& aTabId) {
|
||||
PContentPermissionRequestParent* parent = new ContentPermissionRequestParent(
|
||||
aElement, aPrincipal, aTopLevelPrincipal,
|
||||
aRequests, aElement, aPrincipal, aTopLevelPrincipal,
|
||||
aHasValidTransientUserGestureActivation,
|
||||
aIsRequestDelegatedToUnsafeThirdParty);
|
||||
ContentPermissionRequestParentMap()[parent] = aTabId;
|
||||
|
|
@ -252,14 +252,6 @@ nsContentPermissionUtils::CreateContentPermissionRequestParent(
|
|||
return parent;
|
||||
}
|
||||
|
||||
/* static */
|
||||
void nsContentPermissionUtils::InitContentPermissionRequestParent(
|
||||
PContentPermissionRequestParent* aActor,
|
||||
nsTArray<PermissionRequest>&& aRequests) {
|
||||
static_cast<ContentPermissionRequestParent*>(aActor)->Init(
|
||||
std::move(aRequests));
|
||||
}
|
||||
|
||||
/* static */
|
||||
nsresult nsContentPermissionUtils::AskPermission(
|
||||
nsIContentPermissionRequest* aRequest, nsPIDOMWindowInner* aWindow) {
|
||||
|
|
@ -309,6 +301,7 @@ nsresult nsContentPermissionUtils::AskPermission(
|
|||
}
|
||||
ContentPermissionRequestChildMap()[req.get()] = child->GetTabId();
|
||||
|
||||
req->Sendprompt();
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -63,15 +63,11 @@ class nsContentPermissionUtils {
|
|||
// @param aIsRequestDelegatedToUnsafeThirdParty see
|
||||
// ContentPermissionRequestParent.
|
||||
static PContentPermissionRequestParent* CreateContentPermissionRequestParent(
|
||||
Element* aElement, nsIPrincipal* aPrincipal,
|
||||
nsIPrincipal* aTopLevelPrincipal,
|
||||
const nsTArray<PermissionRequest>& aRequests, Element* aElement,
|
||||
nsIPrincipal* aPrincipal, nsIPrincipal* aTopLevelPrincipal,
|
||||
const bool aHasValidTransientUserGestureActivation,
|
||||
const bool aIsRequestDelegatedToUnsafeThirdParty, const TabId& aTabId);
|
||||
|
||||
static void InitContentPermissionRequestParent(
|
||||
PContentPermissionRequestParent* aActor,
|
||||
nsTArray<PermissionRequest>&& aRequests);
|
||||
|
||||
static nsresult AskPermission(nsIContentPermissionRequest* aRequest,
|
||||
nsPIDOMWindowInner* aWindow);
|
||||
|
||||
|
|
|
|||
|
|
@ -4533,9 +4533,10 @@ nsDOMWindowUtils::WrCapture() {
|
|||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDOMWindowUtils::WrStartCaptureSequence(uint32_t aFlags) {
|
||||
nsDOMWindowUtils::WrStartCaptureSequence(const nsACString& aPath,
|
||||
uint32_t aFlags) {
|
||||
if (WebRenderBridgeChild* wrbc = GetWebRenderBridge()) {
|
||||
wrbc->StartCaptureSequence(aFlags);
|
||||
wrbc->StartCaptureSequence(nsCString(aPath), aFlags);
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -105,7 +105,7 @@ void nsFrameLoaderOwner::ChangeRemotenessCommon(
|
|||
// no other blockers. Since we're going to be adding a new blocker as soon as
|
||||
// we recreate the frame loader, this is not what we want, so add our own
|
||||
// blocker until the process is complete.
|
||||
RefPtr<Document> doc = owner->OwnerDoc();
|
||||
Document* doc = owner->OwnerDoc();
|
||||
doc->BlockOnload();
|
||||
auto cleanup = MakeScopeExit([&]() { doc->UnblockOnload(false); });
|
||||
|
||||
|
|
|
|||
|
|
@ -2459,7 +2459,7 @@ VisualViewport* nsGlobalWindowInner::VisualViewport() {
|
|||
|
||||
nsScreen* nsGlobalWindowInner::Screen() {
|
||||
if (!mScreen) {
|
||||
mScreen = nsScreen::Create(this);
|
||||
mScreen = new nsScreen(this);
|
||||
}
|
||||
return mScreen;
|
||||
}
|
||||
|
|
@ -2535,10 +2535,6 @@ Maybe<ServiceWorkerDescriptor> nsPIDOMWindowInner::GetController() const {
|
|||
return nsGlobalWindowInner::Cast(this)->GetController();
|
||||
}
|
||||
|
||||
ClientSource* nsPIDOMWindowInner::GetClientSource() const {
|
||||
return nsGlobalWindowInner::Cast(this)->GetClientSource();
|
||||
}
|
||||
|
||||
void nsPIDOMWindowInner::SetCsp(nsIContentSecurityPolicy* aCsp) {
|
||||
return nsGlobalWindowInner::Cast(this)->SetCsp(aCsp);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1286,10 +1286,6 @@ class nsGlobalWindowInner final : public mozilla::dom::EventTarget,
|
|||
void SetCurrentPasteDataTransfer(mozilla::dom::DataTransfer* aDataTransfer);
|
||||
mozilla::dom::DataTransfer* GetCurrentPasteDataTransfer() const;
|
||||
|
||||
mozilla::dom::ClientSource* GetClientSource() const {
|
||||
return mClientSource.get();
|
||||
}
|
||||
|
||||
private:
|
||||
RefPtr<mozilla::dom::ContentMediaController> mContentMediaController;
|
||||
|
||||
|
|
|
|||
|
|
@ -1105,7 +1105,11 @@ void nsINode::Normalize() {
|
|||
const nsTextFragment* text = node->GetText();
|
||||
if (text->GetLength()) {
|
||||
nsIContent* target = node->GetPreviousSibling();
|
||||
if (target && target->NodeType() == TEXT_NODE) {
|
||||
NS_ASSERTION(
|
||||
(target && target->NodeType() == TEXT_NODE) || hasRemoveListeners,
|
||||
"Should always have a previous text sibling unless "
|
||||
"mutation events messed us up");
|
||||
if (!hasRemoveListeners || (target && target->NodeType() == TEXT_NODE)) {
|
||||
nsTextNode* t = static_cast<nsTextNode*>(target);
|
||||
if (text->Is2b()) {
|
||||
t->AppendTextForNormalize(text->Get2b(), text->GetLength(), true,
|
||||
|
|
@ -3717,10 +3721,8 @@ already_AddRefed<nsINode> nsINode::CloneAndAdopt(
|
|||
JSAutoRealm ar(cx, wrapper);
|
||||
UpdateReflectorGlobal(cx, wrapper, aError);
|
||||
if (aError.Failed()) {
|
||||
bool needsRollBack = false;
|
||||
if (wasRegistered) {
|
||||
needsRollBack =
|
||||
newDoc->UnregisterActivityObserver(aNode->AsElement());
|
||||
newDoc->UnregisterActivityObserver(aNode->AsElement());
|
||||
}
|
||||
if (hadProperties) {
|
||||
// NOTE: When it fails it removes all properties for the node
|
||||
|
|
@ -3730,7 +3732,7 @@ already_AddRefed<nsINode> nsINode::CloneAndAdopt(
|
|||
}
|
||||
aNode->mNodeInfo.swap(newNodeInfo);
|
||||
aNode->NodeInfoChanged(newDoc);
|
||||
if (needsRollBack) {
|
||||
if (wasRegistered) {
|
||||
oldDoc->RegisterActivityObserver(aNode->AsElement());
|
||||
}
|
||||
return nullptr;
|
||||
|
|
|
|||
|
|
@ -214,8 +214,8 @@ already_AddRefed<nsIDocShell> nsObjectLoadingContent::SetupDocShell(
|
|||
}
|
||||
|
||||
if (!docShell) {
|
||||
RefPtr<nsFrameLoader> loader = std::move(mFrameLoader);
|
||||
loader->Destroy();
|
||||
mFrameLoader->Destroy();
|
||||
mFrameLoader = nullptr;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
|
@ -1284,8 +1284,8 @@ nsresult nsObjectLoadingContent::LoadObject(bool aNotify, bool aForceLoad,
|
|||
nsCOMPtr<nsIURILoader> uriLoader(components::URILoader::Service());
|
||||
if (NS_WARN_IF(!uriLoader)) {
|
||||
MOZ_ASSERT_UNREACHABLE("Failed to get uriLoader service");
|
||||
RefPtr<nsFrameLoader> loader = std::move(mFrameLoader);
|
||||
loader->Destroy();
|
||||
mFrameLoader->Destroy();
|
||||
mFrameLoader = nullptr;
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
@ -1591,6 +1591,11 @@ uint32_t nsObjectLoadingContent::GetCapabilities() const {
|
|||
}
|
||||
|
||||
void nsObjectLoadingContent::Destroy() {
|
||||
if (mFrameLoader) {
|
||||
mFrameLoader->Destroy();
|
||||
mFrameLoader = nullptr;
|
||||
}
|
||||
|
||||
// Reset state so that if the element is re-appended to tree again (e.g.
|
||||
// adopting to another document), it will reload resource again.
|
||||
UnloadObject();
|
||||
|
|
@ -1614,8 +1619,8 @@ void nsObjectLoadingContent::Unlink(nsObjectLoadingContent* tmp) {
|
|||
|
||||
void nsObjectLoadingContent::UnloadObject(bool aResetState) {
|
||||
if (mFrameLoader) {
|
||||
RefPtr<nsFrameLoader> loader = std::move(mFrameLoader);
|
||||
loader->Destroy();
|
||||
mFrameLoader->Destroy();
|
||||
mFrameLoader = nullptr;
|
||||
}
|
||||
|
||||
if (aResetState) {
|
||||
|
|
@ -1713,30 +1718,23 @@ void nsObjectLoadingContent::TriggerInnerFallbackLoads() {
|
|||
}
|
||||
// Do a depth-first traverse of node tree with the current element as root,
|
||||
// looking for non-<param> elements. If we find some then we have an HTML
|
||||
// fallback for this element
|
||||
AutoTArray<RefPtr<nsIContent>, 4> targets;
|
||||
// fallback for this element.
|
||||
for (nsIContent* child = el->GetFirstChild(); child;) {
|
||||
// <object> and <embed> elements in the fallback need to StartObjectLoad.
|
||||
// Their children should be ignored since they are part of those element's
|
||||
// fallback.
|
||||
if (child->IsAnyOfHTMLElements(nsGkAtoms::embed, nsGkAtoms::object)) {
|
||||
targets.AppendElement(child);
|
||||
if (auto* embed = HTMLEmbedElement::FromNode(child)) {
|
||||
embed->StartObjectLoad(true, true);
|
||||
// Skip the children
|
||||
child = child->GetNextNonChildNode(el);
|
||||
} else if (auto* object = HTMLObjectElement::FromNode(child)) {
|
||||
object->StartObjectLoad(true, true);
|
||||
// Skip the children
|
||||
child = child->GetNextNonChildNode(el);
|
||||
} else {
|
||||
child = child->GetNextNode(el);
|
||||
}
|
||||
}
|
||||
|
||||
for (RefPtr<nsIContent>& target : targets) {
|
||||
if (!target->IsInclusiveDescendantOf(el)) {
|
||||
continue;
|
||||
}
|
||||
if (auto* embed = HTMLEmbedElement::FromNode(target)) {
|
||||
embed->StartObjectLoad(true, true);
|
||||
} else if (auto* object = HTMLObjectElement::FromNode(target)) {
|
||||
object->StartObjectLoad(true, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
|
|
|
|||
|
|
@ -366,7 +366,6 @@ class nsPIDOMWindowInner : public mozIDOMWindow {
|
|||
mozilla::Maybe<mozilla::dom::ClientInfo> GetClientInfo() const;
|
||||
mozilla::Maybe<mozilla::dom::ClientState> GetClientState() const;
|
||||
mozilla::Maybe<mozilla::dom::ServiceWorkerDescriptor> GetController() const;
|
||||
mozilla::dom::ClientSource* GetClientSource() const;
|
||||
|
||||
void SetCsp(nsIContentSecurityPolicy* aCsp);
|
||||
void SetPreloadCsp(nsIContentSecurityPolicy* aPreloadCsp);
|
||||
|
|
|
|||
|
|
@ -2829,6 +2829,20 @@ static nsTextFrame* GetTextFrameForContent(nsIContent* aContent,
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
// Try to un-suppress whitespace if needed, but only if we'll be able to flush
|
||||
// to immediately see the results of the un-suppression. If we can't flush
|
||||
// here, then calling EnsureFrameForTextNodeIsCreatedAfterFlush would be
|
||||
// pointless anyway.
|
||||
if (aFlushLayout) {
|
||||
const bool frameWillBeUnsuppressed =
|
||||
presShell->FrameConstructor()
|
||||
->EnsureFrameForTextNodeIsCreatedAfterFlush(
|
||||
static_cast<CharacterData*>(aContent));
|
||||
if (frameWillBeUnsuppressed) {
|
||||
doc->FlushPendingNotifications(FlushType::Layout);
|
||||
}
|
||||
}
|
||||
|
||||
nsIFrame* frame = aContent->GetPrimaryFrame();
|
||||
if (!frame || !frame->IsTextFrame()) {
|
||||
return nullptr;
|
||||
|
|
|
|||
|
|
@ -23,14 +23,8 @@ using namespace mozilla;
|
|||
using namespace mozilla::dom;
|
||||
|
||||
nsScreen::nsScreen(nsPIDOMWindowInner* aWindow)
|
||||
: DOMEventTargetHelper(aWindow) {}
|
||||
|
||||
/* static */ already_AddRefed<nsScreen> nsScreen::Create(
|
||||
nsPIDOMWindowInner* aWindow) {
|
||||
RefPtr screen = new nsScreen(aWindow);
|
||||
screen->mScreenOrientation = ScreenOrientation::Create(aWindow, screen);
|
||||
return screen.forget();
|
||||
}
|
||||
: DOMEventTargetHelper(aWindow),
|
||||
mScreenOrientation(new ScreenOrientation(aWindow, this)) {}
|
||||
|
||||
nsScreen::~nsScreen() = default;
|
||||
|
||||
|
|
|
|||
|
|
@ -21,11 +21,8 @@ enum class RFPTarget : uint64_t;
|
|||
|
||||
// Script "screen" object
|
||||
class nsScreen : public mozilla::DOMEventTargetHelper {
|
||||
private:
|
||||
explicit nsScreen(nsPIDOMWindowInner* aWindow);
|
||||
|
||||
public:
|
||||
static already_AddRefed<nsScreen> Create(nsPIDOMWindowInner* aWindow);
|
||||
explicit nsScreen(nsPIDOMWindowInner* aWindow);
|
||||
|
||||
NS_DECL_ISUPPORTS_INHERITED
|
||||
NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(nsScreen,
|
||||
|
|
|
|||
|
|
@ -47,13 +47,6 @@ void nsWrapperCache::SetWrapperJSObject(JSObject* aNewWrapper) {
|
|||
}
|
||||
}
|
||||
|
||||
void nsWrapperCache::ClearWrapperOnWrapFailure() {
|
||||
if (IsNurseryWrapper(mWrapper)) {
|
||||
CycleCollectedJSRuntime::Get()->NurseryWrapperRemovedSlow(this);
|
||||
}
|
||||
ClearWrapper();
|
||||
}
|
||||
|
||||
void nsWrapperCache::ReleaseWrapper(void* aScriptObjectHolder) {
|
||||
// If the behavior here changes in a substantive way, you may need
|
||||
// to update css::Rule::UnlinkDeclarationWrapper as well.
|
||||
|
|
|
|||
|
|
@ -170,8 +170,6 @@ class JS_HAZ_ROOTED nsWrapperCache {
|
|||
}
|
||||
}
|
||||
|
||||
void ClearWrapperOnWrapFailure();
|
||||
|
||||
/**
|
||||
* Update the wrapper when the object moves between globals.
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -86,18 +86,12 @@ inline void nsWrapperCache::UpdateWrapperForNewGlobal(T* aScriptObjectHolder,
|
|||
SetPreservingWrapper(false);
|
||||
}
|
||||
|
||||
JSObject* oldWrapper = mWrapper;
|
||||
SetWrapper(aNewWrapper);
|
||||
|
||||
if (zoneChanged) {
|
||||
PreserveWrapper(aScriptObjectHolder);
|
||||
} else if (preserving) {
|
||||
SetPreservingWrapper(true);
|
||||
if (!JS::ObjectIsTenured(mWrapper)) {
|
||||
// SetWrapper doesn't fire a write barrier; add one so minor GC can
|
||||
// update mWrapper if the new wrapper is tenured.
|
||||
JS::HeapObjectPostWriteBarrier(&mWrapper, oldWrapper, mWrapper);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -821,8 +821,8 @@ TEST(MimeTypeParsing, contentTypes1)
|
|||
|
||||
bool parsed = CMimeType::Parse(val, contentType, contentCharset);
|
||||
|
||||
ASSERT_TRUE(parsed);
|
||||
ASSERT_TRUE(contentType.EqualsLiteral("text/plain"));
|
||||
ASSERT_FALSE(parsed);
|
||||
ASSERT_TRUE(contentType.EqualsLiteral(""));
|
||||
ASSERT_TRUE(contentCharset.EqualsLiteral(""));
|
||||
}
|
||||
|
||||
|
|
@ -1074,43 +1074,3 @@ TEST(MimeTypeParsing, contentTypes20)
|
|||
ASSERT_TRUE(contentType.EqualsLiteral("text/plain"));
|
||||
ASSERT_TRUE(contentCharset.EqualsLiteral(""));
|
||||
}
|
||||
|
||||
// U+002F(/) is not a valid HTTP token code point
|
||||
// https://mimesniff.spec.whatwg.org/#http-token-code-point
|
||||
TEST(MimeTypeParsing, invalidSubtype1)
|
||||
{
|
||||
const nsAutoCString val("text/json/");
|
||||
RefPtr<CMimeType> parsed = CMimeType::Parse(val);
|
||||
ASSERT_TRUE(!parsed);
|
||||
}
|
||||
|
||||
TEST(MimeTypeParsing, invalidSubtype2)
|
||||
{
|
||||
const nsAutoCString val("text/json/bad");
|
||||
RefPtr<CMimeType> parsed = CMimeType::Parse(val);
|
||||
ASSERT_TRUE(!parsed);
|
||||
}
|
||||
|
||||
TEST(MimeTypeParsing, EmptyParsing)
|
||||
{
|
||||
constexpr nsLiteralCString val("");
|
||||
nsCString contentType;
|
||||
nsCString contentCharset;
|
||||
bool parsed = CMimeType::Parse(val, contentType, contentCharset);
|
||||
|
||||
ASSERT_FALSE(parsed);
|
||||
ASSERT_TRUE(contentType.EqualsLiteral(""));
|
||||
ASSERT_TRUE(contentCharset.EqualsLiteral(""));
|
||||
}
|
||||
|
||||
TEST(MimeTypeParsing, EmptySubtype)
|
||||
{
|
||||
constexpr nsLiteralCString val("audio/");
|
||||
nsCString contentType;
|
||||
nsCString contentCharset;
|
||||
bool parsed = CMimeType::Parse(val, contentType, contentCharset);
|
||||
|
||||
ASSERT_FALSE(parsed);
|
||||
ASSERT_TRUE(contentType.EqualsLiteral(""));
|
||||
ASSERT_TRUE(contentCharset.EqualsLiteral(""));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,3 @@
|
|||
[DEFAULT]
|
||||
|
||||
["test_bug_2027541.html"]
|
||||
|
||||
["test_nested_modules.html"]
|
||||
|
|
|
|||
|
|
@ -1,47 +0,0 @@
|
|||
<!DOCTYPE html>
|
||||
<head>
|
||||
<meta charset=utf-8>
|
||||
<title>Call import.meta.resolve after iframe removal</title>
|
||||
</head>
|
||||
<body>
|
||||
<script src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<script>
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
window.stolenResolve = null;
|
||||
|
||||
async function runTest() {
|
||||
const iframe = document.createElement("iframe");
|
||||
iframe.srcdoc = `<!DOCTYPE html><html><body>
|
||||
<script type="module">
|
||||
window.parent.stolenResolve = import.meta.resolve;
|
||||
window.parent.postMessage("ready", "*");
|
||||
<\/script>
|
||||
</body></html>`;
|
||||
|
||||
const ready = new Promise(resolve => {
|
||||
window.addEventListener("message", () => resolve(), { once: true });
|
||||
});
|
||||
document.body.appendChild(iframe);
|
||||
await ready;
|
||||
|
||||
ok(typeof window.stolenResolve === "function",
|
||||
"Got import.meta.resolve from inline iframe module");
|
||||
|
||||
iframe.remove();
|
||||
|
||||
SpecialPowers.forceGC();
|
||||
SpecialPowers.forceCC();
|
||||
await new Promise(r => requestAnimationFrame(r));
|
||||
|
||||
let result = window.stolenResolve("https://example.com/");
|
||||
is(result, "https://example.com/",
|
||||
"import.meta.resolve returns correct result after iframe removal and GC");
|
||||
|
||||
window.stolenResolve = null;
|
||||
SimpleTest.finish();
|
||||
}
|
||||
|
||||
runTest();
|
||||
</script>
|
||||
</body>
|
||||
|
|
@ -259,6 +259,39 @@ nsTArray<nsCString>& TErrorResult<CleanupPolicy>::CreateErrorMessageHelper(
|
|||
return message->mArgs;
|
||||
}
|
||||
|
||||
template <typename CleanupPolicy>
|
||||
void TErrorResult<CleanupPolicy>::SerializeMessage(
|
||||
IPC::MessageWriter* aWriter) const {
|
||||
using namespace IPC;
|
||||
AssertInOwningThread();
|
||||
MOZ_ASSERT(mUnionState == HasMessage);
|
||||
MOZ_ASSERT(mExtra.mMessage);
|
||||
WriteParam(aWriter, mExtra.mMessage->mArgs);
|
||||
WriteParam(aWriter, mExtra.mMessage->mErrorNumber);
|
||||
}
|
||||
|
||||
template <typename CleanupPolicy>
|
||||
bool TErrorResult<CleanupPolicy>::DeserializeMessage(
|
||||
IPC::MessageReader* aReader) {
|
||||
using namespace IPC;
|
||||
AssertInOwningThread();
|
||||
auto readMessage = MakeUnique<Message>();
|
||||
if (!ReadParam(aReader, &readMessage->mArgs) ||
|
||||
!ReadParam(aReader, &readMessage->mErrorNumber)) {
|
||||
return false;
|
||||
}
|
||||
if (!readMessage->HasCorrectNumberOfArguments()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
MOZ_ASSERT(mUnionState == HasNothing);
|
||||
InitMessage(readMessage.release());
|
||||
#ifdef DEBUG
|
||||
mUnionState = HasMessage;
|
||||
#endif // DEBUG
|
||||
return true;
|
||||
}
|
||||
|
||||
template <typename CleanupPolicy>
|
||||
void TErrorResult<CleanupPolicy>::SetPendingExceptionWithMessage(
|
||||
JSContext* aCx, const char* context) {
|
||||
|
|
@ -368,106 +401,34 @@ struct TErrorResult<CleanupPolicy>::DOMExceptionInfo {
|
|||
};
|
||||
|
||||
template <typename CleanupPolicy>
|
||||
void TErrorResult<CleanupPolicy>::SerializeErrorResult(
|
||||
void TErrorResult<CleanupPolicy>::SerializeDOMExceptionInfo(
|
||||
IPC::MessageWriter* aWriter) const {
|
||||
using namespace IPC;
|
||||
AssertInOwningThread();
|
||||
|
||||
// It should be the case that mMightHaveUnreportedJSException can only be
|
||||
// true when we're expecting a JS exception. We cannot send such messages
|
||||
// over the IPC channel since there is no sane way of transferring the JS
|
||||
// value over to the other side. Callers should never do that.
|
||||
MOZ_ASSERT(!mMightHaveUnreportedJSException);
|
||||
if (IsJSException() || IsJSContextException()) {
|
||||
MOZ_CRASH(
|
||||
"Cannot serialize an ErrorResult representing a Javascript exception");
|
||||
}
|
||||
|
||||
WriteParam(aWriter, mResult);
|
||||
if (IsErrorWithMessage()) {
|
||||
MOZ_ASSERT(mResult == NS_ERROR_INTERNAL_ERRORRESULT_TYPEERROR ||
|
||||
mResult == NS_ERROR_INTERNAL_ERRORRESULT_RANGEERROR);
|
||||
MOZ_ASSERT(mUnionState == HasMessage);
|
||||
MOZ_ASSERT(mExtra.mMessage);
|
||||
|
||||
WriteParam(aWriter, mExtra.mMessage->mArgs);
|
||||
WriteParam(aWriter, mExtra.mMessage->mErrorNumber);
|
||||
} else if (IsDOMException()) {
|
||||
MOZ_ASSERT(mResult == NS_ERROR_INTERNAL_ERRORRESULT_DOMEXCEPTION);
|
||||
MOZ_ASSERT(mUnionState == HasDOMExceptionInfo);
|
||||
MOZ_ASSERT(mExtra.mDOMExceptionInfo);
|
||||
|
||||
WriteParam(aWriter, mExtra.mDOMExceptionInfo->mMessage);
|
||||
WriteParam(aWriter, mExtra.mDOMExceptionInfo->mRv);
|
||||
} else {
|
||||
MOZ_ASSERT(mUnionState == HasNothing);
|
||||
}
|
||||
MOZ_ASSERT(mUnionState == HasDOMExceptionInfo);
|
||||
MOZ_ASSERT(mExtra.mDOMExceptionInfo);
|
||||
WriteParam(aWriter, mExtra.mDOMExceptionInfo->mMessage);
|
||||
WriteParam(aWriter, mExtra.mDOMExceptionInfo->mRv);
|
||||
}
|
||||
|
||||
template <typename CleanupPolicy>
|
||||
bool TErrorResult<CleanupPolicy>::DeserializeErrorResult(
|
||||
bool TErrorResult<CleanupPolicy>::DeserializeDOMExceptionInfo(
|
||||
IPC::MessageReader* aReader) {
|
||||
using namespace IPC;
|
||||
AssertInOwningThread();
|
||||
|
||||
nsresult result;
|
||||
if (!ReadParam(aReader, &result)) {
|
||||
nsCString message;
|
||||
nsresult rv;
|
||||
if (!ReadParam(aReader, &message) || !ReadParam(aReader, &rv)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
switch (result) {
|
||||
case NS_ERROR_INTERNAL_ERRORRESULT_JS_EXCEPTION:
|
||||
case NS_ERROR_INTERNAL_ERRORRESULT_EXCEPTION_ON_JSCONTEXT:
|
||||
// JS exceptions can not be serialized.
|
||||
return false;
|
||||
|
||||
case NS_ERROR_INTERNAL_ERRORRESULT_TYPEERROR:
|
||||
case NS_ERROR_INTERNAL_ERRORRESULT_RANGEERROR: {
|
||||
nsTArray<nsCString> args;
|
||||
dom::ErrNum errorNumber;
|
||||
if (!ReadParam(aReader, &args) || !ReadParam(aReader, &errorNumber)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (GetErrorArgCount(errorNumber) != args.Length()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for (nsCString& arg : args) {
|
||||
if (Utf8ValidUpTo(arg) != arg.Length()) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
ClearUnionData();
|
||||
|
||||
nsTArray<nsCString>& messageArgsArray =
|
||||
CreateErrorMessageHelper(errorNumber, result);
|
||||
messageArgsArray = std::move(args);
|
||||
MOZ_ASSERT(mExtra.mMessage->HasCorrectNumberOfArguments(),
|
||||
"validated earlier");
|
||||
MOZ_ASSERT(mUnionState == HasNothing);
|
||||
MOZ_ASSERT(IsDOMException());
|
||||
InitDOMExceptionInfo(new DOMExceptionInfo(rv, message));
|
||||
#ifdef DEBUG
|
||||
mUnionState = HasMessage;
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
|
||||
case NS_ERROR_INTERNAL_ERRORRESULT_DOMEXCEPTION: {
|
||||
nsCString message;
|
||||
nsresult rv;
|
||||
if (!ReadParam(aReader, &message) || !ReadParam(aReader, &rv)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
ThrowDOMException(rv, message);
|
||||
return true;
|
||||
}
|
||||
|
||||
default:
|
||||
ClearUnionData();
|
||||
AssignErrorCode(result);
|
||||
return true;
|
||||
}
|
||||
mUnionState = HasDOMExceptionInfo;
|
||||
#endif // DEBUG
|
||||
return true;
|
||||
}
|
||||
|
||||
template <typename CleanupPolicy>
|
||||
|
|
@ -2473,7 +2434,8 @@ void UpdateReflectorGlobal(JSContext* aCx, JS::Handle<JSObject*> aObjArg,
|
|||
}
|
||||
|
||||
// We've set up |newobj|, so we make it own the native by setting its reserved
|
||||
// slot and nulling out the reserved slot of |obj|.
|
||||
// slot and nulling out the reserved slot of |obj|. Update the wrapper cache
|
||||
// to keep everything consistent in case GC moves newobj.
|
||||
//
|
||||
// NB: It's important to do this _after_ copying the properties to
|
||||
// propertyHolder. Otherwise, an object with |foo.x === foo| will
|
||||
|
|
@ -2482,37 +2444,18 @@ void UpdateReflectorGlobal(JSContext* aCx, JS::Handle<JSObject*> aObjArg,
|
|||
JS::SetReservedSlot(newobj, DOM_OBJECT_SLOT,
|
||||
JS::GetReservedSlot(aObj, DOM_OBJECT_SLOT));
|
||||
JS::SetReservedSlot(aObj, DOM_OBJECT_SLOT, JS::PrivateValue(nullptr));
|
||||
size_t nslots = JSCLASS_RESERVED_SLOTS(JS::GetClass(aObj));
|
||||
for (size_t slot = DOM_INSTANCE_RESERVED_SLOTS; slot < nslots; ++slot) {
|
||||
const JS::Value& slotValue = JS::GetReservedSlot(aObj, slot);
|
||||
if (slotValue.isObject()) {
|
||||
JSObject* slotObj = &slotValue.toObject();
|
||||
if (IsObservableArrayProxy(slotObj)) {
|
||||
JS::SetReservedSlot(newobj, slot, slotValue);
|
||||
JS::SetReservedSlot(aObj, slot, JS::UndefinedValue());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
nsWrapperCache* cache = nullptr;
|
||||
CallQueryInterface(native, &cache);
|
||||
|
||||
// For preserved wrappers the store buffer keeps mWrapper consistent across
|
||||
// the transplant. For non-preserved wrappers clear mWrapper so that
|
||||
// JSObjectsTenured doesn't follow a stale pointer if nursery GC fires.
|
||||
bool preserving = cache->PreservingWrapper();
|
||||
if (preserving) {
|
||||
cache->UpdateWrapperForNewGlobal(native, newobj);
|
||||
} else {
|
||||
cache->ClearWrapper();
|
||||
}
|
||||
cache->UpdateWrapperForNewGlobal(native, newobj);
|
||||
|
||||
aObj = xpc::TransplantObjectRetainingXrayExpandos(aCx, aObj, newobj);
|
||||
if (!aObj) {
|
||||
MOZ_CRASH();
|
||||
}
|
||||
|
||||
if (!preserving || aObj != newobj) {
|
||||
// Update the wrapper cache again if transplanting didn't use newobj but
|
||||
// returned some other object.
|
||||
if (aObj != newobj) {
|
||||
MOZ_ASSERT(UnwrapDOMObjectToISupports(aObj) == native);
|
||||
cache->UpdateWrapperForNewGlobal(native, aObj);
|
||||
}
|
||||
|
|
@ -3573,7 +3516,6 @@ static bool GetBackingObject(JSContext* aCx, JS::Handle<JSObject*> aObj,
|
|||
? aObj
|
||||
: js::UncheckedUnwrap(aObj,
|
||||
/* stopAtWindowProxy = */ false);
|
||||
MOZ_ASSERT(aSlotIndex < JSCLASS_RESERVED_SLOTS(JS::GetClass(reflector)));
|
||||
|
||||
// Retrieve the backing object from the reserved slot on the maplike/setlike
|
||||
// object. If it doesn't exist yet, create it.
|
||||
|
|
|
|||
|
|
@ -4683,7 +4683,7 @@ class CGWrapWithCacheMethod(CGAbstractMethod):
|
|||
failureCode = dedent(
|
||||
"""
|
||||
aCache->ReleaseWrapper(aObject);
|
||||
aCache->ClearWrapperOnWrapFailure();
|
||||
aCache->ClearWrapper();
|
||||
return false;
|
||||
"""
|
||||
)
|
||||
|
|
@ -23213,9 +23213,7 @@ class CGIterableMethodGenerator(CGGeneric):
|
|||
CGGeneric.__init__(self, createIterator)
|
||||
|
||||
|
||||
def getObservableArrayBackingObject(
|
||||
descriptor, attr, objName="obj", errorReturn="return false;\n"
|
||||
):
|
||||
def getObservableArrayBackingObject(descriptor, attr, errorReturn="return false;\n"):
|
||||
"""
|
||||
Generate code to get/create a JS backing list for an observableArray attribute
|
||||
from the declaration slot.
|
||||
|
|
@ -23230,7 +23228,7 @@ def getObservableArrayBackingObject(
|
|||
"""
|
||||
JS::Rooted<JSObject*> backingObj(cx);
|
||||
bool created = false;
|
||||
if (!GetObservableArrayBackingObject(cx, ${objName}, ${slot},
|
||||
if (!GetObservableArrayBackingObject(cx, obj, ${slot},
|
||||
&backingObj, &created, ${namespace}::ObservableArrayProxyHandler::getInstance(),
|
||||
self)) {
|
||||
$*{errorReturn}
|
||||
|
|
@ -23239,9 +23237,8 @@ def getObservableArrayBackingObject(
|
|||
PreserveWrapper(self);
|
||||
}
|
||||
""",
|
||||
objName=objName,
|
||||
slot=memberReservedSlot(attr, descriptor),
|
||||
namespace=toBindingNamespace(MakeNativeName(attr.identifier.name)),
|
||||
slot=memberReservedSlot(attr, descriptor),
|
||||
errorReturn=errorReturn,
|
||||
selfType=descriptor.nativeType,
|
||||
)
|
||||
|
|
@ -23353,18 +23350,12 @@ class CGObservableArrayProxyHandler_callback(ClassMethod):
|
|||
$*{convertType}
|
||||
|
||||
$*{preCallback}
|
||||
const JS::Value& val = js::GetProxyReservedSlot(aProxy, OBSERVABLE_ARRAY_DOM_INTERFACE_SLOT);
|
||||
if (MOZ_LIKELY(!val.isUndefined())) {
|
||||
auto* interface = static_cast<${ifaceType}*>(val.toPrivate());
|
||||
MOZ_ASSERT(interface);
|
||||
|
||||
ErrorResult rv;
|
||||
MOZ_KnownLive(interface)->${methodName}(${callbackArgs});
|
||||
if (rv.MaybeSetPendingException(cx)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
JS::Value val = js::GetProxyReservedSlot(aProxy, OBSERVABLE_ARRAY_DOM_INTERFACE_SLOT);
|
||||
auto* interface = static_cast<${ifaceType}*>(val.toPrivate());
|
||||
MOZ_ASSERT(interface);
|
||||
|
||||
ErrorResult rv;
|
||||
MOZ_KnownLive(interface)->${methodName}(${callbackArgs});
|
||||
$*{postCallback}
|
||||
""",
|
||||
preConversion=self.preConversion(),
|
||||
|
|
@ -23408,7 +23399,7 @@ class CGObservableArrayProxyHandler_OnDeleteItem(
|
|||
def postCallback(self):
|
||||
return dedent(
|
||||
"""
|
||||
return true;
|
||||
return !rv.MaybeSetPendingException(cx);
|
||||
"""
|
||||
)
|
||||
|
||||
|
|
@ -23473,6 +23464,10 @@ class CGObservableArrayProxyHandler_SetIndexedValue(
|
|||
def postCallback(self):
|
||||
return dedent(
|
||||
"""
|
||||
if (rv.MaybeSetPendingException(cx)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!JS_SetElement(aCx, aBackingList, aIndex, aValue)) {
|
||||
return false;
|
||||
}
|
||||
|
|
@ -23535,9 +23530,7 @@ class CGObservableArraySetterGenerator(CGGeneric):
|
|||
def __init__(self, descriptor, attr):
|
||||
assert attr.isAttr()
|
||||
assert attr.type.isObservableArray()
|
||||
getBackingObject = getObservableArrayBackingObject(
|
||||
descriptor, attr, objName="unwrappedObj"
|
||||
)
|
||||
getBackingObject = getObservableArrayBackingObject(descriptor, attr)
|
||||
setElement = dedent(
|
||||
"""
|
||||
if (!JS_SetElement(cx, backingObj, i, val)) {
|
||||
|
|
@ -23564,22 +23557,15 @@ class CGObservableArraySetterGenerator(CGGeneric):
|
|||
return false;
|
||||
}
|
||||
|
||||
JS::Rooted<JSObject*> unwrappedObj(cx, js::UncheckedUnwrap(obj, /* stopAtWindowProxy = */ false));
|
||||
MOZ_ASSERT(IsDOMObject(unwrappedObj));
|
||||
{
|
||||
JSAutoRealm ar(cx, unwrappedObj);
|
||||
${getBackingObject}
|
||||
const ObservableArrayProxyHandler* handler = GetObservableArrayProxyHandler(backingObj);
|
||||
if (!handler->SetLength(cx, backingObj, 0)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$*{getBackingObject}
|
||||
|
||||
const ObservableArrayProxyHandler* handler = GetObservableArrayProxyHandler(backingObj);
|
||||
if (!handler->SetLength(cx, backingObj, 0)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
JS::Rooted<JS::Value> val(cx);
|
||||
for (size_t i = 0; i < arg0.Length(); i++) {
|
||||
$*{conversion}
|
||||
}
|
||||
JS::Rooted<JS::Value> val(cx);
|
||||
for (size_t i = 0; i < arg0.Length(); i++) {
|
||||
$*{conversion}
|
||||
}
|
||||
""",
|
||||
conversion=conversion,
|
||||
|
|
@ -23625,7 +23611,7 @@ class CGObservableArrayHelperFunctionGenerator(CGHelperFunctionGenerator):
|
|||
getObservableArrayBackingObject(
|
||||
descriptor,
|
||||
attr,
|
||||
errorReturn=dedent(
|
||||
dedent(
|
||||
"""
|
||||
aRv.Throw(NS_ERROR_UNEXPECTED);
|
||||
return%s;
|
||||
|
|
|
|||
|
|
@ -7,8 +7,11 @@
|
|||
#ifndef IPC_ErrorIPCUtils_h
|
||||
#define IPC_ErrorIPCUtils_h
|
||||
|
||||
#include <utility>
|
||||
|
||||
#include "ipc/EnumSerializer.h"
|
||||
#include "ipc/IPCMessageUtils.h"
|
||||
#include "mozilla/Assertions.h"
|
||||
#include "mozilla/ErrorResult.h"
|
||||
|
||||
namespace IPC {
|
||||
|
|
@ -21,18 +24,64 @@ struct ParamTraits<mozilla::dom::ErrNum>
|
|||
|
||||
template <>
|
||||
struct ParamTraits<mozilla::ErrorResult> {
|
||||
static void Write(MessageWriter* aWriter,
|
||||
const mozilla::ErrorResult& aParam) {
|
||||
aParam.SerializeErrorResult(aWriter);
|
||||
typedef mozilla::ErrorResult paramType;
|
||||
|
||||
static void Write(MessageWriter* aWriter, const paramType& aParam) {
|
||||
// It should be the case that mMightHaveUnreportedJSException can only be
|
||||
// true when we're expecting a JS exception. We cannot send such messages
|
||||
// over the IPC channel since there is no sane way of transferring the JS
|
||||
// value over to the other side. Callers should never do that.
|
||||
MOZ_ASSERT_IF(aParam.IsJSException(),
|
||||
aParam.mMightHaveUnreportedJSException);
|
||||
if (aParam.IsJSException()
|
||||
#ifdef DEBUG
|
||||
|| aParam.mMightHaveUnreportedJSException
|
||||
#endif
|
||||
) {
|
||||
MOZ_CRASH(
|
||||
"Cannot encode an ErrorResult representing a Javascript exception");
|
||||
}
|
||||
|
||||
WriteParam(aWriter, aParam.mResult);
|
||||
WriteParam(aWriter, aParam.IsErrorWithMessage());
|
||||
WriteParam(aWriter, aParam.IsDOMException());
|
||||
if (aParam.IsErrorWithMessage()) {
|
||||
aParam.SerializeMessage(aWriter);
|
||||
} else if (aParam.IsDOMException()) {
|
||||
aParam.SerializeDOMExceptionInfo(aWriter);
|
||||
}
|
||||
}
|
||||
|
||||
static void Write(MessageWriter* aWriter, mozilla::ErrorResult&& aParam) {
|
||||
aParam.SerializeErrorResult(aWriter);
|
||||
static void Write(MessageWriter* aWriter, paramType&& aParam) {
|
||||
Write(aWriter, static_cast<const paramType&>(aParam));
|
||||
aParam.SuppressException();
|
||||
}
|
||||
|
||||
static bool Read(MessageReader* aReader, mozilla::ErrorResult* aResult) {
|
||||
return aResult->DeserializeErrorResult(aReader);
|
||||
static bool Read(MessageReader* aReader, paramType* aResult) {
|
||||
paramType readValue;
|
||||
if (!ReadParam(aReader, &readValue.mResult)) {
|
||||
return false;
|
||||
}
|
||||
bool hasMessage = false;
|
||||
if (!ReadParam(aReader, &hasMessage)) {
|
||||
return false;
|
||||
}
|
||||
bool hasDOMExceptionInfo = false;
|
||||
if (!ReadParam(aReader, &hasDOMExceptionInfo)) {
|
||||
return false;
|
||||
}
|
||||
if (hasMessage && hasDOMExceptionInfo) {
|
||||
// Shouldn't have both!
|
||||
return false;
|
||||
}
|
||||
if (hasMessage && !readValue.DeserializeMessage(aReader)) {
|
||||
return false;
|
||||
} else if (hasDOMExceptionInfo &&
|
||||
!readValue.DeserializeDOMExceptionInfo(aReader)) {
|
||||
return false;
|
||||
}
|
||||
*aResult = std::move(readValue);
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -41,11 +90,14 @@ struct ParamTraits<mozilla::CopyableErrorResult> {
|
|||
typedef mozilla::CopyableErrorResult paramType;
|
||||
|
||||
static void Write(MessageWriter* aWriter, const paramType& aParam) {
|
||||
aParam.SerializeErrorResult(aWriter);
|
||||
ParamTraits<mozilla::ErrorResult>::Write(aWriter, aParam);
|
||||
}
|
||||
|
||||
static bool Read(MessageReader* aReader, paramType* aResult) {
|
||||
return aResult->DeserializeErrorResult(aReader);
|
||||
// We can't cast *aResult to ErrorResult&, so cheat and just cast
|
||||
// to ErrorResult*.
|
||||
return ParamTraits<mozilla::ErrorResult>::Read(
|
||||
aReader, reinterpret_cast<mozilla::ErrorResult*>(aResult));
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -215,7 +215,6 @@ class TErrorResult {
|
|||
// informative message and calling the relevant Throw*Error.
|
||||
void MOZ_MUST_RETURN_FROM_CALLER_IF_THIS_IS_ARG Throw(nsresult rv) {
|
||||
MOZ_ASSERT(NS_FAILED(rv), "Please don't try throwing success");
|
||||
ClearUnionData();
|
||||
AssignErrorCode(rv);
|
||||
}
|
||||
|
||||
|
|
@ -402,7 +401,7 @@ class TErrorResult {
|
|||
|
||||
// Check whether the TErrorResult says to just throw whatever is on
|
||||
// the JSContext already.
|
||||
bool IsJSContextException() const {
|
||||
bool IsJSContextException() {
|
||||
return ErrorCode() == NS_ERROR_INTERNAL_ERRORRESULT_EXCEPTION_ON_JSCONTEXT;
|
||||
}
|
||||
|
||||
|
|
@ -432,10 +431,7 @@ class TErrorResult {
|
|||
// Backwards-compat to make conversion simpler. We don't call
|
||||
// Throw() here because people can easily pass success codes to
|
||||
// this. This operator is deprecated and ideally shouldn't be used.
|
||||
void operator=(nsresult rv) {
|
||||
ClearUnionData();
|
||||
AssignErrorCode(rv);
|
||||
}
|
||||
void operator=(nsresult rv) { AssignErrorCode(rv); }
|
||||
|
||||
bool Failed() const { return NS_FAILED(mResult); }
|
||||
|
||||
|
|
@ -485,10 +481,11 @@ class TErrorResult {
|
|||
|
||||
friend struct IPC::ParamTraits<TErrorResult>;
|
||||
friend struct IPC::ParamTraits<ErrorResult>;
|
||||
friend struct IPC::ParamTraits<CopyableErrorResult>;
|
||||
void SerializeMessage(IPC::MessageWriter* aWriter) const;
|
||||
bool DeserializeMessage(IPC::MessageReader* aReader);
|
||||
|
||||
void SerializeErrorResult(IPC::MessageWriter* aWriter) const;
|
||||
bool DeserializeErrorResult(IPC::MessageReader* aReader);
|
||||
void SerializeDOMExceptionInfo(IPC::MessageWriter* aWriter) const;
|
||||
bool DeserializeDOMExceptionInfo(IPC::MessageReader* aReader);
|
||||
|
||||
// Helper method that creates a new Message for this TErrorResult,
|
||||
// and returns the arguments array from that Message.
|
||||
|
|
@ -546,7 +543,6 @@ class TErrorResult {
|
|||
}
|
||||
|
||||
void AssignErrorCode(nsresult aRv) {
|
||||
MOZ_ASSERT(mUnionState == HasNothing);
|
||||
MOZ_ASSERT(aRv != NS_ERROR_INTERNAL_ERRORRESULT_TYPEERROR,
|
||||
"Use ThrowTypeError()");
|
||||
MOZ_ASSERT(aRv != NS_ERROR_INTERNAL_ERRORRESULT_RANGEERROR,
|
||||
|
|
|
|||
|
|
@ -277,9 +277,6 @@ bool ObservableArrayProxyHandler::GetBackingListObject(
|
|||
if (NS_WARN_IF(!newBackingListObj)) {
|
||||
return false;
|
||||
}
|
||||
if (NS_WARN_IF(!JS_SetPrototype(aCx, newBackingListObj, nullptr))) {
|
||||
return false;
|
||||
}
|
||||
slotValue = JS::ObjectValue(*newBackingListObj);
|
||||
js::SetProxyReservedSlot(aProxy, OBSERVABLE_ARRAY_BACKING_LIST_OBJECT_SLOT,
|
||||
slotValue);
|
||||
|
|
|
|||
12
icecat/dom/cache/Manager.cpp
vendored
12
icecat/dom/cache/Manager.cpp
vendored
|
|
@ -658,8 +658,7 @@ class Manager::CacheMatchAction final : public Manager::BaseAction {
|
|||
|
||||
// If we entered shutdown on the main thread while we were doing IO,
|
||||
// bail out now.
|
||||
if (IsCanceled() ||
|
||||
AppShutdown::IsInOrBeyond(ShutdownPhase::AppShutdownQM)) {
|
||||
if (AppShutdown::IsInOrBeyond(ShutdownPhase::AppShutdownQM)) {
|
||||
if (stream) {
|
||||
stream->Close();
|
||||
}
|
||||
|
|
@ -735,8 +734,7 @@ class Manager::CacheMatchAllAction final : public Manager::BaseAction {
|
|||
|
||||
// If we entered shutdown on the main thread while we were doing IO,
|
||||
// bail out now.
|
||||
if (IsCanceled() ||
|
||||
AppShutdown::IsInOrBeyond(ShutdownPhase::AppShutdownQM)) {
|
||||
if (AppShutdown::IsInOrBeyond(ShutdownPhase::AppShutdownQM)) {
|
||||
if (stream) {
|
||||
stream->Close();
|
||||
}
|
||||
|
|
@ -1291,8 +1289,7 @@ class Manager::CacheKeysAction final : public Manager::BaseAction {
|
|||
|
||||
// If we entered shutdown on the main thread while we were doing IO,
|
||||
// bail out now.
|
||||
if (IsCanceled() ||
|
||||
AppShutdown::IsInOrBeyond(ShutdownPhase::AppShutdownQM)) {
|
||||
if (AppShutdown::IsInOrBeyond(ShutdownPhase::AppShutdownQM)) {
|
||||
if (stream) {
|
||||
stream->Close();
|
||||
}
|
||||
|
|
@ -1371,8 +1368,7 @@ class Manager::StorageMatchAction final : public Manager::BaseAction {
|
|||
|
||||
// If we entered shutdown on the main thread while we were doing IO,
|
||||
// bail out now.
|
||||
if (IsCanceled() ||
|
||||
AppShutdown::IsInOrBeyond(ShutdownPhase::AppShutdownQM)) {
|
||||
if (AppShutdown::IsInOrBeyond(ShutdownPhase::AppShutdownQM)) {
|
||||
if (stream) {
|
||||
stream->Close();
|
||||
}
|
||||
|
|
|
|||
7
icecat/dom/cache/StreamList.cpp
vendored
7
icecat/dom/cache/StreamList.cpp
vendored
|
|
@ -30,6 +30,7 @@ StreamList::StreamList(SafeRefPtr<Manager> aManager,
|
|||
mStreamControl(nullptr),
|
||||
mActivated(false) {
|
||||
MOZ_DIAGNOSTIC_ASSERT(mManager);
|
||||
mContext->AddActivity(*this);
|
||||
}
|
||||
|
||||
Manager& StreamList::GetManager() const {
|
||||
|
|
@ -72,9 +73,6 @@ void StreamList::Activate(CacheId aCacheId) {
|
|||
MOZ_DIAGNOSTIC_ASSERT(mCacheId == INVALID_CACHE_ID);
|
||||
mActivated = true;
|
||||
mCacheId = aCacheId;
|
||||
|
||||
mContext->AddActivity(*this);
|
||||
|
||||
mManager->AddRefCacheId(mCacheId);
|
||||
mManager->AddStreamList(*this);
|
||||
|
||||
|
|
@ -136,7 +134,6 @@ void StreamList::NoteClosedAll() {
|
|||
|
||||
void StreamList::CloseAll() {
|
||||
NS_ASSERT_OWNINGTHREAD(StreamList);
|
||||
SafeRefPtr<StreamList> kungFuDeathGrip = SafeRefPtrFromThis();
|
||||
|
||||
if (mStreamControl && mStreamControl->CanSend()) {
|
||||
// CloseAll will kick off everything needed for shutdown.
|
||||
|
|
@ -195,13 +192,13 @@ StreamList::~StreamList() {
|
|||
NS_ASSERT_OWNINGTHREAD(StreamList);
|
||||
MOZ_DIAGNOSTIC_ASSERT(!mStreamControl);
|
||||
if (mActivated) {
|
||||
mContext->RemoveActivity(*this);
|
||||
mManager->RemoveStreamList(*this);
|
||||
for (uint32_t i = 0; i < mList.Length(); ++i) {
|
||||
mManager->ReleaseBodyId(mList[i].mId);
|
||||
}
|
||||
mManager->ReleaseCacheId(mCacheId);
|
||||
}
|
||||
mContext->RemoveActivity(*this);
|
||||
}
|
||||
|
||||
} // namespace mozilla::dom::cache
|
||||
|
|
|
|||
|
|
@ -880,8 +880,6 @@ NS_IMPL_CYCLE_COLLECTING_RELEASE(CanvasRenderingContext2D)
|
|||
NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE_CLASS(CanvasRenderingContext2D)
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(CanvasRenderingContext2D)
|
||||
tmp->RemoveShutdownObserver();
|
||||
tmp->OnShutdown();
|
||||
// Make sure we remove ourselves from the list of demotable contexts (raw
|
||||
// pointers), since we're logically destructed at this point.
|
||||
NS_IMPL_CYCLE_COLLECTION_UNLINK(mCanvasElement)
|
||||
|
|
@ -2890,12 +2888,8 @@ void CanvasRenderingContext2D::GetLetterSpacing(nsACString& aLetterSpacing) {
|
|||
|
||||
void CanvasRenderingContext2D::SetLetterSpacing(
|
||||
const nsACString& aLetterSpacing) {
|
||||
nsAutoCString normalized;
|
||||
Maybe<float> value = ParseSpacing(aLetterSpacing, normalized);
|
||||
if (value) {
|
||||
CurrentState().letterSpacing = *value;
|
||||
CurrentState().letterSpacingStr = normalized;
|
||||
}
|
||||
ParseSpacing(aLetterSpacing, &CurrentState().letterSpacing,
|
||||
CurrentState().letterSpacingStr);
|
||||
}
|
||||
|
||||
void CanvasRenderingContext2D::GetWordSpacing(nsACString& aWordSpacing) {
|
||||
|
|
@ -2907,12 +2901,8 @@ void CanvasRenderingContext2D::GetWordSpacing(nsACString& aWordSpacing) {
|
|||
}
|
||||
|
||||
void CanvasRenderingContext2D::SetWordSpacing(const nsACString& aWordSpacing) {
|
||||
nsAutoCString normalized;
|
||||
Maybe<float> value = ParseSpacing(aWordSpacing, normalized);
|
||||
if (value) {
|
||||
CurrentState().wordSpacing = *value;
|
||||
CurrentState().wordSpacingStr = normalized;
|
||||
}
|
||||
ParseSpacing(aWordSpacing, &CurrentState().wordSpacing,
|
||||
CurrentState().wordSpacingStr);
|
||||
}
|
||||
|
||||
static GeckoFontMetrics GetFontMetricsFromCanvas(void* aContext) {
|
||||
|
|
@ -2943,8 +2933,9 @@ static GeckoFontMetrics GetFontMetricsFromCanvas(void* aContext) {
|
|||
0.0f};
|
||||
}
|
||||
|
||||
Maybe<float> CanvasRenderingContext2D::ParseSpacing(const nsACString& aSpacing,
|
||||
nsACString& aNormalized) {
|
||||
void CanvasRenderingContext2D::ParseSpacing(const nsACString& aSpacing,
|
||||
float* aValue,
|
||||
nsACString& aNormalized) {
|
||||
// Normalize whitespace in the string before trying to parse it, as we want
|
||||
// to store it in normalized form, and this allows a simple check against the
|
||||
// 'normal' keyword, which is not accepted.
|
||||
|
|
@ -2952,28 +2943,28 @@ Maybe<float> CanvasRenderingContext2D::ParseSpacing(const nsACString& aSpacing,
|
|||
normalized.CompressWhitespace(true, true);
|
||||
ToLowerCase(normalized);
|
||||
if (normalized.EqualsLiteral("normal")) {
|
||||
return Nothing();
|
||||
return;
|
||||
}
|
||||
float value;
|
||||
if (!Servo_ParseLengthWithoutStyleContext(&normalized, &value,
|
||||
GetFontMetricsFromCanvas, this)) {
|
||||
if (!GetPresShell()) {
|
||||
return Nothing();
|
||||
return;
|
||||
}
|
||||
// This will parse aSpacing as a <length-percentage>...
|
||||
RefPtr<const ComputedStyle> style =
|
||||
ResolveStyleForProperty(eCSSProperty_letter_spacing, aSpacing);
|
||||
if (!style) {
|
||||
return Nothing();
|
||||
return;
|
||||
}
|
||||
// ...but only <length> is allowed according to the canvas spec.
|
||||
if (!style->StyleText()->mLetterSpacing.IsLength()) {
|
||||
return Nothing();
|
||||
return;
|
||||
}
|
||||
value = style->StyleText()->mLetterSpacing.AsLength().ToCSSPixels();
|
||||
}
|
||||
aNormalized = normalized;
|
||||
return Some(value);
|
||||
*aValue = value;
|
||||
}
|
||||
|
||||
class CanvasUserSpaceMetrics final : public UserSpaceMetricsWithSize {
|
||||
|
|
@ -3443,11 +3434,6 @@ void CanvasRenderingContext2D::StrokeImpl(const gfx::Path& aPath) {
|
|||
return;
|
||||
}
|
||||
|
||||
const bool needBounds = NeedToCalculateBounds();
|
||||
if (!IsTargetValid()) {
|
||||
return;
|
||||
}
|
||||
|
||||
const ContextState* state = &CurrentState();
|
||||
StrokeOptions strokeOptions(state->lineWidth, CanvasToGfx(state->lineJoin),
|
||||
CanvasToGfx(state->lineCap), state->miterLimit,
|
||||
|
|
@ -3455,6 +3441,10 @@ void CanvasRenderingContext2D::StrokeImpl(const gfx::Path& aPath) {
|
|||
state->dashOffset);
|
||||
state = nullptr;
|
||||
|
||||
const bool needBounds = NeedToCalculateBounds();
|
||||
if (!IsTargetValid()) {
|
||||
return;
|
||||
}
|
||||
gfx::Rect bounds;
|
||||
if (needBounds) {
|
||||
bounds = aPath.GetStrokedBounds(strokeOptions, mTarget->GetTransform());
|
||||
|
|
@ -4705,7 +4695,6 @@ struct MOZ_STACK_CLASS CanvasBidiProcessor final
|
|||
}
|
||||
|
||||
mCtx->EnsureTarget();
|
||||
const bool needBounds = mCtx->NeedToCalculateBounds();
|
||||
if (!mCtx->IsTargetValid()) {
|
||||
return;
|
||||
}
|
||||
|
|
@ -4720,7 +4709,7 @@ struct MOZ_STACK_CLASS CanvasBidiProcessor final
|
|||
const ContextState& state = mCtx->CurrentState();
|
||||
|
||||
gfx::Rect bounds;
|
||||
if (needBounds) {
|
||||
if (mCtx->NeedToCalculateBounds()) {
|
||||
bounds = ToRect(mBoundingBox);
|
||||
bounds.MoveBy(mPt / mAppUnitsPerDevPixel);
|
||||
if (style == Style::STROKE) {
|
||||
|
|
@ -4868,9 +4857,6 @@ UniquePtr<TextMetrics> CanvasRenderingContext2D::DrawOrMeasureText(
|
|||
canvasStyle = nsComputedDOMStyle::GetComputedStyle(mCanvasElement);
|
||||
}
|
||||
|
||||
// This is only needed to know if we can know the drawing bounding box easily.
|
||||
const bool doCalculateBounds = NeedToCalculateBounds();
|
||||
|
||||
// Get text direction, either from the property or inherited from context.
|
||||
const ContextState& state = CurrentState();
|
||||
bool isRTL;
|
||||
|
|
@ -4896,6 +4882,8 @@ UniquePtr<TextMetrics> CanvasRenderingContext2D::DrawOrMeasureText(
|
|||
MOZ_CRASH("unknown direction!");
|
||||
}
|
||||
|
||||
// This is only needed to know if we can know the drawing bounding box easily.
|
||||
const bool doCalculateBounds = NeedToCalculateBounds();
|
||||
if (presShell && presShell->IsDestroying()) {
|
||||
aError = NS_ERROR_FAILURE;
|
||||
return nullptr;
|
||||
|
|
@ -5175,54 +5163,50 @@ gfxFontGroup* CanvasRenderingContext2D::GetCurrentFontStyle() {
|
|||
nsPresContext* presContext =
|
||||
presShell ? presShell->GetPresContext() : nullptr;
|
||||
|
||||
{
|
||||
// If we have a cached fontGroup, check that it is valid for the current
|
||||
// prescontext; if not, we need to discard and re-create it.
|
||||
RefPtr<gfxFontGroup>& fontGroup = CurrentState().fontGroup;
|
||||
if (fontGroup) {
|
||||
if (fontGroup->GetPresContext() != presContext) {
|
||||
fontGroup = nullptr;
|
||||
// If we have a cached fontGroup, check that it is valid for the current
|
||||
// prescontext; if not, we need to discard and re-create it.
|
||||
RefPtr<gfxFontGroup>& fontGroup = CurrentState().fontGroup;
|
||||
if (fontGroup) {
|
||||
if (fontGroup->GetPresContext() != presContext) {
|
||||
fontGroup = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
if (!fontGroup) {
|
||||
ErrorResult err;
|
||||
constexpr auto kDefaultFontStyle = "10px sans-serif"_ns;
|
||||
const float kDefaultFontSize = 10.0;
|
||||
// If the font has already been set, we're re-creating the fontGroup
|
||||
// and should re-use the existing font attribute; if not, we initialize
|
||||
// it to the canvas default.
|
||||
const nsCString& currentFont = CurrentState().font;
|
||||
bool fontUpdated = SetFontInternal(
|
||||
currentFont.IsEmpty() ? kDefaultFontStyle : currentFont, err);
|
||||
if (err.Failed() || !fontUpdated) {
|
||||
err.SuppressException();
|
||||
// XXX Should we get a default lang from the prescontext or something?
|
||||
nsAtom* language = nsGkAtoms::x_western;
|
||||
bool explicitLanguage = false;
|
||||
gfxFontStyle style;
|
||||
style.size = kDefaultFontSize;
|
||||
int32_t perDevPixel, perCSSPixel;
|
||||
GetAppUnitsValues(&perDevPixel, &perCSSPixel);
|
||||
gfxFloat devToCssSize = gfxFloat(perDevPixel) / gfxFloat(perCSSPixel);
|
||||
const auto* sans =
|
||||
Servo_FontFamily_Generic(StyleGenericFontFamily::SansSerif);
|
||||
fontGroup = new gfxFontGroup(
|
||||
presContext, sans->families, &style, language, explicitLanguage,
|
||||
presContext ? presContext->GetTextPerfMetrics() : nullptr, nullptr,
|
||||
devToCssSize, StyleFontVariantEmoji::Normal);
|
||||
if (fontGroup) {
|
||||
CurrentState().font = kDefaultFontStyle;
|
||||
} else {
|
||||
return fontGroup;
|
||||
NS_ERROR("Default canvas font is invalid");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ErrorResult err;
|
||||
constexpr auto kDefaultFontStyle = "10px sans-serif"_ns;
|
||||
const float kDefaultFontSize = 10.0;
|
||||
// If the font has already been set, we're re-creating the fontGroup
|
||||
// and should re-use the existing font attribute; if not, we initialize
|
||||
// it to the canvas default.
|
||||
nsAutoCString currentFont(CurrentState().font);
|
||||
if (currentFont.IsEmpty()) {
|
||||
currentFont = kDefaultFontStyle;
|
||||
}
|
||||
bool fontUpdated = SetFontInternal(currentFont, err);
|
||||
if (err.Failed() || !fontUpdated) {
|
||||
err.SuppressException();
|
||||
// XXX Should we get a default lang from the prescontext or something?
|
||||
nsAtom* language = nsGkAtoms::x_western;
|
||||
bool explicitLanguage = false;
|
||||
gfxFontStyle style;
|
||||
style.size = kDefaultFontSize;
|
||||
int32_t perDevPixel, perCSSPixel;
|
||||
GetAppUnitsValues(&perDevPixel, &perCSSPixel);
|
||||
gfxFloat devToCssSize = gfxFloat(perDevPixel) / gfxFloat(perCSSPixel);
|
||||
const auto* sans =
|
||||
Servo_FontFamily_Generic(StyleGenericFontFamily::SansSerif);
|
||||
CurrentState().fontGroup = new gfxFontGroup(
|
||||
presContext, sans->families, &style, language, explicitLanguage,
|
||||
presContext ? presContext->GetTextPerfMetrics() : nullptr, nullptr,
|
||||
devToCssSize, StyleFontVariantEmoji::Normal);
|
||||
if (CurrentState().fontGroup) {
|
||||
CurrentState().font = kDefaultFontStyle;
|
||||
} else {
|
||||
NS_ERROR("Default canvas font is invalid");
|
||||
}
|
||||
}
|
||||
|
||||
return CurrentState().fontGroup;
|
||||
return fontGroup;
|
||||
}
|
||||
|
||||
//
|
||||
|
|
@ -5727,7 +5711,7 @@ void CanvasRenderingContext2D::DrawImage(const CanvasImageSource& aImage,
|
|||
HTMLVideoElement* video = HTMLVideoElement::FromNodeOrNull(element);
|
||||
if (video && mBufferProvider->IsAccelerated() &&
|
||||
mTarget->IsRecording() &&
|
||||
!(NeedToApplyFilter() || NeedToDrawShadow())) {
|
||||
!(!NeedToApplyFilter() && NeedToDrawShadow())) {
|
||||
res = nsLayoutUtils::SurfaceFromElement(
|
||||
video, sfeFlags, mTarget, /* aOptimizeSourceSurface */ false);
|
||||
surfaceDescriptor = MaybeGetSurfaceDescriptorForRemoteCanvas(res);
|
||||
|
|
|
|||
|
|
@ -613,13 +613,11 @@ class CanvasRenderingContext2D : public nsICanvasRenderingContextInternal,
|
|||
protected:
|
||||
/**
|
||||
* Helper to parse a value for the letterSpacing or wordSpacing attribute.
|
||||
* If the string can be parsed, returns Some(value) and sets aNormalized to
|
||||
* the normalized form of the specified string. If it cannot be parsed as a
|
||||
* spacing value, returns Nothing, and aNormalized is untouched.
|
||||
* Note that ParseSpacing may flush style (to resolve font-relative units).
|
||||
* If successful, returns the result in aValue, and the whitespace-normalized
|
||||
* value string in aNormalized; if unsuccessful these are left untouched.
|
||||
*/
|
||||
mozilla::Maybe<float> ParseSpacing(const nsACString& aSpacing,
|
||||
nsACString& aNormalized);
|
||||
void ParseSpacing(const nsACString& aSpacing, float* aValue,
|
||||
nsACString& aNormalized);
|
||||
|
||||
already_AddRefed<const ComputedStyle> ResolveStyleForProperty(
|
||||
nsCSSPropertyID aProperty, const nsACString& aValue);
|
||||
|
|
@ -1002,14 +1000,10 @@ class CanvasRenderingContext2D : public nsICanvasRenderingContextInternal,
|
|||
* last call to UpdateFilter and now.
|
||||
*/
|
||||
const gfx::FilterDescription& EnsureUpdatedFilter() {
|
||||
bool isWriteOnly = IsWriteOnly() ||
|
||||
(mCanvasElement && mCanvasElement->IsWriteOnly()) ||
|
||||
(mOffscreenCanvas && mOffscreenCanvas->IsWriteOnly());
|
||||
bool isWriteOnly = mCanvasElement && mCanvasElement->IsWriteOnly();
|
||||
if (CurrentState().filterSourceGraphicTainted != isWriteOnly) {
|
||||
// Do not flush here: this runs inside drawing operations that hold raw
|
||||
// references to mPath/state, and a flush can run script that resets the
|
||||
// context, leading to UAF. Flush already happened at SetFilter() time.
|
||||
UpdateFilter(/* aFlushIfNeeded = */ false);
|
||||
UpdateFilter(/* aFlushIfNeeded = */ true);
|
||||
EnsureTarget();
|
||||
}
|
||||
MOZ_ASSERT(CurrentState().filterSourceGraphicTainted == isWriteOnly);
|
||||
return CurrentState().filter;
|
||||
|
|
|
|||
|
|
@ -198,18 +198,7 @@ ClientWebGLContext::ClientWebGLContext(const bool webgl2)
|
|||
: mIsWebGL2(webgl2),
|
||||
mExtLoseContext(new ClientWebGLExtensionLoseContext(*this)) {}
|
||||
|
||||
static inline void SafeReleaseNotLostData(std::shared_ptr<webgl::NotLostData>& notLost) {
|
||||
if (notLost) {
|
||||
const auto keepAlive = std::move(notLost);
|
||||
keepAlive->extensions = {};
|
||||
keepAlive->state = {};
|
||||
}
|
||||
}
|
||||
|
||||
ClientWebGLContext::~ClientWebGLContext() {
|
||||
RemovePostRefreshObserver();
|
||||
SafeReleaseNotLostData(mNotLost);
|
||||
}
|
||||
ClientWebGLContext::~ClientWebGLContext() { RemovePostRefreshObserver(); }
|
||||
|
||||
void ClientWebGLContext::JsWarning(const std::string& utf8) const {
|
||||
nsIGlobalObject* global = nullptr;
|
||||
|
|
@ -4522,14 +4511,6 @@ void ClientWebGLContext::TexImage(uint8_t funcDims, GLenum imageTarget,
|
|||
std::string{"gpuProcessTextureId works only in GPU process."});
|
||||
}
|
||||
} break;
|
||||
case layers::SurfaceDescriptor::TSurfaceDescriptorDXGIYCbCr: {
|
||||
MOZ_ASSERT(desc->image);
|
||||
keepAliveImage = desc->image;
|
||||
} break;
|
||||
case layers::SurfaceDescriptor::TSurfaceDescriptorMacIOSurface: {
|
||||
MOZ_ASSERT(desc->image);
|
||||
keepAliveImage = desc->image;
|
||||
} break;
|
||||
case layers::SurfaceDescriptor::TSurfaceDescriptorGPUVideo: {
|
||||
const auto& inProcess = mNotLost->inProcess;
|
||||
MOZ_ASSERT(desc->image);
|
||||
|
|
@ -7023,7 +7004,11 @@ void ImplCycleCollectionTraverse(
|
|||
}
|
||||
|
||||
void ImplCycleCollectionUnlink(std::shared_ptr<webgl::NotLostData>& field) {
|
||||
SafeReleaseNotLostData(field);
|
||||
if (!field) return;
|
||||
const auto keepAlive = field;
|
||||
keepAlive->extensions = {};
|
||||
keepAlive->state = {};
|
||||
field = nullptr;
|
||||
}
|
||||
|
||||
// -----------------------------------------------------
|
||||
|
|
|
|||
|
|
@ -21,6 +21,7 @@
|
|||
#include "mozilla/gfx/Swizzle.h"
|
||||
#include "mozilla/layers/ImageDataSerializer.h"
|
||||
#include "mozilla/layers/RemoteTextureMap.h"
|
||||
#include "mozilla/widget/ScreenManager.h"
|
||||
#include "skia/include/core/SkPixmap.h"
|
||||
#include "nsContentUtils.h"
|
||||
#include "nsIMemoryReporter.h"
|
||||
|
|
@ -816,7 +817,7 @@ bool DrawTargetWebgl::GenerateComplexClipMask() {
|
|||
return !!data;
|
||||
}
|
||||
|
||||
Maybe<Rect> DrawTargetWebgl::ComputeSimpleClipRect() const {
|
||||
bool DrawTargetWebgl::SetSimpleClipRect() {
|
||||
// Determine whether the clipping rectangle is simple enough to accelerate.
|
||||
// Check if there is a device space clip rectangle available from the Skia
|
||||
// target.
|
||||
|
|
@ -828,7 +829,9 @@ Maybe<Rect> DrawTargetWebgl::ComputeSimpleClipRect() const {
|
|||
if (!clip->IsEmpty() && clip->Contains(GetRect())) {
|
||||
clip = Some(GetRect());
|
||||
}
|
||||
return Some(Rect(*clip));
|
||||
mSharedContext->SetClipRect(*clip);
|
||||
mSharedContext->SetNoClipMask();
|
||||
return true;
|
||||
}
|
||||
|
||||
// There was no pixel-aligned clip rect available, so check the clip stack to
|
||||
|
|
@ -839,22 +842,15 @@ Maybe<Rect> DrawTargetWebgl::ComputeSimpleClipRect() const {
|
|||
// complex.
|
||||
if (clipStack.mPath ||
|
||||
!clipStack.mTransform.PreservesAxisAlignedRectangles()) {
|
||||
return Nothing();
|
||||
return false;
|
||||
}
|
||||
// Transform the rect and intersect it with the current clip.
|
||||
rect =
|
||||
clipStack.mTransform.TransformBounds(clipStack.mRect).Intersect(rect);
|
||||
}
|
||||
return Some(rect);
|
||||
}
|
||||
|
||||
bool DrawTargetWebgl::SetSimpleClipRect() {
|
||||
if (Maybe<Rect> rect = ComputeSimpleClipRect()) {
|
||||
mSharedContext->SetClipRect(*rect);
|
||||
mSharedContext->SetNoClipMask();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
mSharedContext->SetClipRect(rect);
|
||||
mSharedContext->SetNoClipMask();
|
||||
return true;
|
||||
}
|
||||
|
||||
// Installs the Skia clip rectangle, if applicable, onto the shared WebGL
|
||||
|
|
@ -878,21 +874,6 @@ bool DrawTargetWebgl::PrepareContext(bool aClipped) {
|
|||
return mSharedContext->SetTarget(this);
|
||||
}
|
||||
|
||||
// Whether clipping may be necessary for the operation. This tries to avoid
|
||||
// generating a complex clip mask in case the current target is not active
|
||||
// or not using WebGL. If there is only a simple clip mask and its bounds
|
||||
// encompass the viewport, then no clipping is required.
|
||||
bool DrawTargetWebgl::ShouldClip() {
|
||||
if (mSharedContext->IsCurrentTarget(this) && !mRefreshClipState) {
|
||||
return mSharedContext->HasClipMask() ||
|
||||
!mSharedContext->mClipAARect.Contains(Rect(GetRect()));
|
||||
}
|
||||
if (Maybe<Rect> rect = ComputeSimpleClipRect()) {
|
||||
return !rect->Contains(Rect(GetRect()));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool SharedContextWebgl::IsContextLost() const {
|
||||
return !mWebgl || mWebgl->IsContextLost();
|
||||
}
|
||||
|
|
@ -924,12 +905,29 @@ bool DrawTargetWebgl::CanCreate(const IntSize& aSize, SurfaceFormat aFormat) {
|
|||
return false;
|
||||
}
|
||||
|
||||
// Maximum pref allows 2 different options:
|
||||
// <= 0 means unlimited size,
|
||||
// Maximum pref allows 3 different options:
|
||||
// 0 means unlimited size,
|
||||
// > 0 means use value as an absolute threshold,
|
||||
// < 0 means use the number of screen pixels as a threshold.
|
||||
int32_t maxSize = StaticPrefs::gfx_canvas_accelerated_max_size();
|
||||
if (maxSize > 0 && std::max(aSize.width, aSize.height) > maxSize) {
|
||||
return false;
|
||||
if (maxSize > 0) {
|
||||
if (std::max(aSize.width, aSize.height) > maxSize) {
|
||||
return false;
|
||||
}
|
||||
} else if (maxSize < 0) {
|
||||
// Default to historical mobile screen size of 980x480, like FishIEtank.
|
||||
// In addition, allow acceleration up to this size even if the screen is
|
||||
// smaller. A lot content expects this size to work well. See Bug 999841
|
||||
static const int32_t kScreenPixels = 980 * 480;
|
||||
|
||||
if (RefPtr<widget::Screen> screen =
|
||||
widget::ScreenManager::GetSingleton().GetPrimaryScreen()) {
|
||||
LayoutDeviceIntSize screenSize = screen->GetRect().Size();
|
||||
if (aSize.width * aSize.height >
|
||||
std::max(screenSize.width * screenSize.height, kScreenPixels)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
|
|
@ -1647,7 +1645,9 @@ void DrawTargetWebgl::ClearRect(const Rect& aRect) {
|
|||
|
||||
// If the clear rectangle encompasses the entire viewport and is not clipped,
|
||||
// then mark the target as entirely clear.
|
||||
if (containsViewport && !ShouldClip()) {
|
||||
if (containsViewport && mSharedContext->IsCurrentTarget(this) &&
|
||||
!mSharedContext->HasClipMask() &&
|
||||
mSharedContext->mClipAARect.Contains(Rect(GetRect()))) {
|
||||
mIsClear = true;
|
||||
}
|
||||
}
|
||||
|
|
@ -2038,7 +2038,6 @@ bool SharedContextWebgl::UploadSurface(DataSourceSurface* aData,
|
|||
if (srcRect.IsEmpty()) {
|
||||
return true;
|
||||
}
|
||||
Maybe<DataSourceSurface::ScopedMap> map;
|
||||
if (aData) {
|
||||
// If the source rect could not possibly overlap the surface, then it is
|
||||
// effectively empty with nothing to upload.
|
||||
|
|
@ -2059,15 +2058,15 @@ bool SharedContextWebgl::UploadSurface(DataSourceSurface* aData,
|
|||
// The surface needs to be uploaded to its backing texture either to
|
||||
// initialize or update the texture handle contents. Map the data
|
||||
// contents of the surface so it can be read.
|
||||
map.emplace(aData, DataSourceSurface::READ);
|
||||
if (!map->IsMapped()) {
|
||||
DataSourceSurface::ScopedMap map(aData, DataSourceSurface::READ);
|
||||
if (!map.IsMapped()) {
|
||||
return false;
|
||||
}
|
||||
int32_t stride = map->GetStride();
|
||||
int32_t stride = map.GetStride();
|
||||
// Get the data pointer range considering the sampling rect offset and
|
||||
// size.
|
||||
Span<const uint8_t> range(
|
||||
map->GetData() + srcRect.y * size_t(stride) + srcRect.x * bpp,
|
||||
map.GetData() + srcRect.y * size_t(stride) + srcRect.x * bpp,
|
||||
std::max(srcRect.height - 1, 0) * size_t(stride) + srcRect.width * bpp);
|
||||
texDesc.cpuData = Some(range);
|
||||
// If the stride happens to be 4 byte aligned, assume that is the
|
||||
|
|
|
|||
|
|
@ -617,11 +617,9 @@ class DrawTargetWebgl : public DrawTarget, public SupportsWeakPtr {
|
|||
return mSharedContext->SupportsPattern(aPattern);
|
||||
}
|
||||
|
||||
Maybe<Rect> ComputeSimpleClipRect() const;
|
||||
bool SetSimpleClipRect();
|
||||
bool GenerateComplexClipMask();
|
||||
bool PrepareContext(bool aClipped = true);
|
||||
bool ShouldClip();
|
||||
|
||||
void DrawRectFallback(const Rect& aRect, const Pattern& aPattern,
|
||||
const DrawOptions& aOptions,
|
||||
|
|
|
|||
|
|
@ -146,29 +146,10 @@ already_AddRefed<ImageData> ImageData::ReadStructuredClone(
|
|||
!JS_ReadTypedArray(aReader, &dataArray)) {
|
||||
return nullptr;
|
||||
}
|
||||
MOZ_ASSERT(dataArray.isObject());
|
||||
|
||||
JS::Rooted<JSObject*> dataObj(aCx, &dataArray.toObject());
|
||||
RootedSpiderMonkeyInterface<Uint8ClampedArray> data(aCx);
|
||||
if (!data.Init(dataObj)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
Maybe<size_t> maybeLength = data.ProcessData(
|
||||
[&](const Span<uint8_t>& aData, JS::AutoCheckCannotGC&& nogc) {
|
||||
return Some(aData.Length());
|
||||
});
|
||||
if (maybeLength.isNothing()) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
CheckedInt<uint32_t> calculatedLength =
|
||||
CheckedInt<uint32_t>(width) * height * 4;
|
||||
if (!calculatedLength.isValid() ||
|
||||
size_t(calculatedLength.value()) != maybeLength.value()) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
RefPtr<ImageData> imageData = new ImageData(aGlobal, width, height, dataObj);
|
||||
JS::Rooted<JSObject*> arrayObj(aCx, &dataArray.toObject());
|
||||
RefPtr<ImageData> imageData = new ImageData(aGlobal, width, height, arrayObj);
|
||||
return imageData.forget();
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -391,8 +391,8 @@ static bool HasColorAndAlpha(const WebGLTexelFormat format) {
|
|||
}
|
||||
|
||||
bool TexUnpackBlob::ConvertIfNeeded(
|
||||
const WebGLContext* const webgl, const size_t rowLength,
|
||||
const size_t rowCount, WebGLTexelFormat srcFormat,
|
||||
const WebGLContext* const webgl, const uint32_t rowLength,
|
||||
const uint32_t rowCount, WebGLTexelFormat srcFormat,
|
||||
const uint8_t* const srcBegin, const ptrdiff_t srcStride,
|
||||
WebGLTexelFormat dstFormat, const ptrdiff_t dstStride,
|
||||
const uint8_t** const out_begin,
|
||||
|
|
@ -469,7 +469,7 @@ bool TexUnpackBlob::ConvertIfNeeded(
|
|||
|
||||
////
|
||||
|
||||
const auto dstTotalBytes = CheckedInt<size_t>(rowCount) * dstStride;
|
||||
const auto dstTotalBytes = CheckedUint32(rowCount) * dstStride;
|
||||
if (!dstTotalBytes.isValid()) {
|
||||
webgl->ErrorOutOfMemory("Calculation failed.");
|
||||
return false;
|
||||
|
|
@ -855,14 +855,9 @@ bool TexUnpackImage::TexOrSubImage(bool isSubImage, bool needsRespec,
|
|||
: dom::PredefinedColorSpace::Srgb;
|
||||
bool sameColorSpace = (srcColorSpace == dstColorSpace);
|
||||
|
||||
Maybe<std::string> reason;
|
||||
if (!webgl->IsUploadableSdType(sd)) {
|
||||
reason = Some(std::string("Unsupported surface descriptor type"));
|
||||
} else {
|
||||
reason = BlitPreventReason(
|
||||
const auto reason = BlitPreventReason(
|
||||
level, {xOffset, yOffset, zOffset}, dui->internalFormat, pi, mDesc,
|
||||
webgl->mOptionalRenderableFormatBits, sameColorSpace);
|
||||
}
|
||||
if (reason) {
|
||||
webgl->GeneratePerfWarning(
|
||||
"Failed to hit GPU-copy fast-path."
|
||||
|
|
@ -1115,6 +1110,10 @@ bool TexUnpackSurface::TexOrSubImage(bool isSubImage, bool needsRespec,
|
|||
////
|
||||
|
||||
const auto surfSize = surf->GetSize();
|
||||
if (uint32_t(surfSize.width) < size.x || uint32_t(surfSize.height) < size.y) {
|
||||
gfxCriticalError() << "Source surface size too small for upload.";
|
||||
return false;
|
||||
}
|
||||
|
||||
WebGLTexelFormat srcFormat;
|
||||
uint8_t srcBPP;
|
||||
|
|
@ -1166,12 +1165,6 @@ bool TexUnpackSurface::TexOrSubImage(bool isSubImage, bool needsRespec,
|
|||
const auto& dstUnpacking = dstUnpackingRes.inspect();
|
||||
MOZ_ASSERT(dstUnpacking.metrics.bytesPerRowStride == dstStride);
|
||||
|
||||
if (uint32_t(surfSize.width) < dstUnpacking.metrics.usedPixelsPerRow ||
|
||||
uint32_t(surfSize.height) < dstUnpacking.metrics.totalRows) {
|
||||
gfxCriticalError() << "Source surface size too small for upload.";
|
||||
return false;
|
||||
}
|
||||
|
||||
// -
|
||||
|
||||
const uint8_t* dstBegin = srcBegin;
|
||||
|
|
|
|||
|
|
@ -65,8 +65,8 @@ class TexUnpackBlob {
|
|||
virtual ~TexUnpackBlob() = default;
|
||||
|
||||
protected:
|
||||
bool ConvertIfNeeded(const WebGLContext*, const size_t rowLength,
|
||||
const size_t rowCount, WebGLTexelFormat srcFormat,
|
||||
bool ConvertIfNeeded(const WebGLContext*, const uint32_t rowLength,
|
||||
const uint32_t rowCount, WebGLTexelFormat srcFormat,
|
||||
const uint8_t* const srcBegin, const ptrdiff_t srcStride,
|
||||
WebGLTexelFormat dstFormat, const ptrdiff_t dstStride,
|
||||
|
||||
|
|
|
|||
|
|
@ -630,6 +630,50 @@ RefPtr<WebGLContext> WebGLContext::Create(HostWebGLContext* host,
|
|||
|
||||
// -
|
||||
|
||||
const auto UploadableSdTypes = [&]() {
|
||||
webgl::EnumMask<layers::SurfaceDescriptor::Type> types;
|
||||
types[layers::SurfaceDescriptor::TSurfaceDescriptorBuffer] = true;
|
||||
// Only support canvas surface interchange if using AC2D. This guarantees
|
||||
// that WebGL and AC2D commands are sequenced and processed on the same
|
||||
// thread, so that there is no mal-ordering between AC2D and WebGL
|
||||
// processing. We can flush out AC2D commands to produce a surface in time
|
||||
// for WebGL to use without requiring any blocking to occur.
|
||||
types[layers::SurfaceDescriptor::TSurfaceDescriptorCanvasSurface] =
|
||||
gfx::gfxVars::UseAcceleratedCanvas2D();
|
||||
// This is conditional on not using the Compositor thread because we may
|
||||
// need to synchronize with the RDD process over the PVideoBridge protocol
|
||||
// to wait for the texture to be available in the compositor process. We
|
||||
// cannot block on the Compositor thread, so in that configuration, we would
|
||||
// prefer to do the readback from the RDD which is guaranteed to work, and
|
||||
// only block the owning thread for WebGL.
|
||||
const bool offCompositorThread = gfx::gfxVars::UseCanvasRenderThread() ||
|
||||
!gfx::gfxVars::SupportsThreadsafeGL();
|
||||
types[layers::SurfaceDescriptor::TSurfaceDescriptorGPUVideo] =
|
||||
offCompositorThread;
|
||||
// Similarly to the PVideoBridge protocol, we may need to synchronize with
|
||||
// the content process over the PCompositorManager protocol to wait for the
|
||||
// shared surface to be available in the compositor process, and we cannot
|
||||
// block on the Compositor thread.
|
||||
types[layers::SurfaceDescriptor::TSurfaceDescriptorExternalImage] =
|
||||
offCompositorThread;
|
||||
if (webgl->gl->IsANGLE()) {
|
||||
types[layers::SurfaceDescriptor::TSurfaceDescriptorD3D10] = true;
|
||||
types[layers::SurfaceDescriptor::TSurfaceDescriptorDXGIYCbCr] = true;
|
||||
}
|
||||
if (kIsMacOS) {
|
||||
types[layers::SurfaceDescriptor::TSurfaceDescriptorMacIOSurface] = true;
|
||||
}
|
||||
if (kIsAndroid) {
|
||||
types[layers::SurfaceDescriptor::TSurfaceTextureDescriptor] = true;
|
||||
}
|
||||
if (kIsLinux) {
|
||||
types[layers::SurfaceDescriptor::TSurfaceDescriptorDMABuf] = true;
|
||||
}
|
||||
return types;
|
||||
};
|
||||
|
||||
// -
|
||||
|
||||
constexpr GLenum SHADER_TYPES[] = {
|
||||
LOCAL_GL_VERTEX_SHADER,
|
||||
LOCAL_GL_FRAGMENT_SHADER,
|
||||
|
|
@ -665,7 +709,7 @@ RefPtr<WebGLContext> WebGLContext::Create(HostWebGLContext* host,
|
|||
|
||||
out->options = webgl->mOptions;
|
||||
out->limits = *webgl->mLimits;
|
||||
out->uploadableSdTypes = webgl->mUploadableSdTypes;
|
||||
out->uploadableSdTypes = UploadableSdTypes();
|
||||
out->vendor = webgl->gl->Vendor();
|
||||
out->optionalRenderableFormatBits = webgl->mOptionalRenderableFormatBits;
|
||||
|
||||
|
|
@ -767,58 +811,6 @@ void WebGLContext::FinishInit() {
|
|||
|
||||
gl->ResetSyncCallCount("WebGLContext Initialization");
|
||||
LoseLruContextIfLimitExceeded();
|
||||
|
||||
InitUploadableSdTypes();
|
||||
}
|
||||
|
||||
void WebGLContext::InitUploadableSdTypes() {
|
||||
webgl::EnumMask<layers::SurfaceDescriptor::Type> types;
|
||||
types[layers::SurfaceDescriptor::TSurfaceDescriptorBuffer] = true;
|
||||
// Only support canvas surface interchange if using AC2D. This guarantees
|
||||
// that WebGL and AC2D commands are sequenced and processed on the same
|
||||
// thread, so that there is no mal-ordering between AC2D and WebGL
|
||||
// processing. We can flush out AC2D commands to produce a surface in time
|
||||
// for WebGL to use without requiring any blocking to occur.
|
||||
types[layers::SurfaceDescriptor::TSurfaceDescriptorCanvasSurface] =
|
||||
gfx::gfxVars::UseAcceleratedCanvas2D();
|
||||
// This is conditional on not using the Compositor thread because we may
|
||||
// need to synchronize with the RDD process over the PVideoBridge protocol
|
||||
// to wait for the texture to be available in the compositor process. We
|
||||
// cannot block on the Compositor thread, so in that configuration, we would
|
||||
// prefer to do the readback from the RDD which is guaranteed to work, and
|
||||
// only block the owning thread for WebGL.
|
||||
const bool offCompositorThread = gfx::gfxVars::UseCanvasRenderThread() ||
|
||||
!gfx::gfxVars::SupportsThreadsafeGL();
|
||||
types[layers::SurfaceDescriptor::TSurfaceDescriptorGPUVideo] =
|
||||
offCompositorThread;
|
||||
// Similarly to the PVideoBridge protocol, we may need to synchronize with
|
||||
// the content process over the PCompositorManager protocol to wait for the
|
||||
// shared surface to be available in the compositor process, and we cannot
|
||||
// block on the Compositor thread.
|
||||
types[layers::SurfaceDescriptor::TSurfaceDescriptorExternalImage] =
|
||||
offCompositorThread;
|
||||
if (gl->IsANGLE()) {
|
||||
types[layers::SurfaceDescriptor::TSurfaceDescriptorD3D10] = true;
|
||||
types[layers::SurfaceDescriptor::TSurfaceDescriptorDXGIYCbCr] = true;
|
||||
}
|
||||
if (kIsMacOS) {
|
||||
types[layers::SurfaceDescriptor::TSurfaceDescriptorMacIOSurface] = true;
|
||||
}
|
||||
if (kIsAndroid) {
|
||||
types[layers::SurfaceDescriptor::TSurfaceTextureDescriptor] = true;
|
||||
}
|
||||
if (kIsLinux) {
|
||||
types[layers::SurfaceDescriptor::TSurfaceDescriptorDMABuf] = true;
|
||||
}
|
||||
|
||||
mUploadableSdTypes = types;
|
||||
}
|
||||
|
||||
bool WebGLContext::IsUploadableSdType(
|
||||
const layers::SurfaceDescriptor& sd) const {
|
||||
// If the WebGLContext is remote, then validate that the SD is an allowed
|
||||
// type.
|
||||
return !bool(mHost) || mUploadableSdTypes[sd.type()];
|
||||
}
|
||||
|
||||
void WebGLContext::SetCompositableHost(
|
||||
|
|
@ -2795,23 +2787,6 @@ webgl::ExplicitPixelPackingState::ForUseWith(
|
|||
const Maybe<size_t> bytesPerRowStrideOverride) {
|
||||
auto state = stateOrZero;
|
||||
|
||||
// Enforce the GLES alignmentInTypeElems invariant. ElemsPerRowStride below
|
||||
// assumes a in {1,2,4,8}. Callers at IPC entry points validate this but
|
||||
// alignmentInTypeElems is deserialized from IPC, so guard it here too.
|
||||
switch (state.alignmentInTypeElems) {
|
||||
case 1:
|
||||
case 2:
|
||||
case 4:
|
||||
case 8:
|
||||
break;
|
||||
default: {
|
||||
const auto text = nsPrintfCString(
|
||||
"PACK/UNPACK_ALIGNMENT must be one of [1,2,4,8], was %u.",
|
||||
state.alignmentInTypeElems);
|
||||
return Err(mozilla::ToString(text));
|
||||
}
|
||||
}
|
||||
|
||||
if (!IsTexTarget3D(target)) {
|
||||
state.skipImages = 0;
|
||||
state.imageHeight = 0;
|
||||
|
|
@ -2917,9 +2892,7 @@ webgl::ExplicitPixelPackingState::ForUseWith(
|
|||
|
||||
const auto elemsPerRowStride = ElemsPerRowStride();
|
||||
const auto bytesPerRowStride = pii.bytesPerElement * elemsPerRowStride;
|
||||
const auto maxBytesPerRow = StaticPrefs::webgl_max_bytes_per_row();
|
||||
if (!bytesPerRowStride.isValid() ||
|
||||
(maxBytesPerRow > 0 && bytesPerRowStride.value() > maxBytesPerRow)) {
|
||||
if (!bytesPerRowStride.isValid()) {
|
||||
return Err("ROW_LENGTH or width too large for packing.");
|
||||
}
|
||||
metrics.bytesPerRowStride = bytesPerRowStride.value();
|
||||
|
|
|
|||
|
|
@ -292,7 +292,6 @@ class WebGLContext : public VRefCounted, public SupportsWeakPtr {
|
|||
WebGLContextOptions mOptions;
|
||||
const uint32_t mPrincipalKey;
|
||||
Maybe<webgl::Limits> mLimits;
|
||||
webgl::EnumMask<layers::SurfaceDescriptor::Type> mUploadableSdTypes;
|
||||
const uint32_t mMaxVertIdsPerDraw =
|
||||
StaticPrefs::webgl_max_vert_ids_per_draw();
|
||||
|
||||
|
|
@ -341,7 +340,6 @@ class WebGLContext : public VRefCounted, public SupportsWeakPtr {
|
|||
webgl::OptionalRenderableFormatBits mOptionalRenderableFormatBits =
|
||||
webgl::OptionalRenderableFormatBits{0};
|
||||
void FinishInit();
|
||||
void InitUploadableSdTypes();
|
||||
|
||||
protected:
|
||||
WebGLContext(HostWebGLContext*, const webgl::InitContextDesc&);
|
||||
|
|
@ -997,8 +995,6 @@ class WebGLContext : public VRefCounted, public SupportsWeakPtr {
|
|||
|
||||
bool IsFormatValidForFB(TexInternalFormat format) const;
|
||||
|
||||
bool IsUploadableSdType(const layers::SurfaceDescriptor& sd) const;
|
||||
|
||||
protected:
|
||||
// -------------------------------------------------------------------------
|
||||
// WebGL extensions (implemented in WebGLContextExtensions.cpp)
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue