ma1 pushed to branch mullvad-browser-115.16.0esr-13.5-1 at The Tor Project / Applications / Mullvad Browser
Commits:
-
eafe617f
by Nika Layzell at 2024-10-01T00:57:18+02:00
-
db726edf
by Paul Zuehlcke at 2024-10-01T00:57:20+02:00
-
be142b0d
by André Bargull at 2024-10-01T00:57:21+02:00
-
bfc54ed4
by Emilio Cobos Álvarez at 2024-10-01T00:57:23+02:00
-
cb01df5c
by Steve Fink at 2024-10-01T00:57:25+02:00
-
84dc8a8a
by Nika Layzell at 2024-10-01T00:57:26+02:00
-
0fe417ba
by Kershaw Chang at 2024-10-01T00:57:28+02:00
22 changed files:
- browser/base/content/test/tabPrompts/browser_confirmFolderUpload.js
- browser/components/prompts/PromptCollection.sys.mjs
- docshell/base/BrowsingContext.cpp
- docshell/base/BrowsingContext.h
- docshell/base/nsDocShell.cpp
- docshell/base/nsDocShell.h
- dom/base/Document.cpp
- dom/base/Document.h
- dom/base/ShadowRoot.cpp
- dom/base/ShadowRoot.h
- dom/filesystem/tests/script_promptHandler.js
- js/public/StructuredClone.h
- js/public/friend/ErrorNumbers.msg
- js/src/jit-test/tests/structured-clone/transferable-cleanup.js
- js/src/jit/IonAnalysis.cpp
- js/src/vm/StructuredClone.cpp
- layout/style/ServoStyleSet.cpp
- layout/style/ServoStyleSet.h
- layout/style/StyleSheet.cpp
- netwerk/ipc/DocumentLoadListener.cpp
- netwerk/protocol/webtransport/WebTransportSessionProxy.cpp
- + testing/web-platform/tests/css/cssom/insertRule-import-trailing-garbage-crash.html
Changes:
... | ... | @@ -101,8 +101,29 @@ async function testUploadPrompt(confirmUpload) { |
101 | 101 | // Wait for confirmation prompt
|
102 | 102 | let prompt = await promptPromise;
|
103 | 103 | ok(prompt, "Shown upload confirmation prompt");
|
104 | + |
|
104 | 105 | is(prompt.ui.button0.label, "Upload", "Accept button label");
|
106 | + ok(
|
|
107 | + prompt.ui.button0.disabled,
|
|
108 | + "Accept button should be disabled by the security delay initially."
|
|
109 | + );
|
|
110 | + |
|
105 | 111 | ok(prompt.ui.button1.hasAttribute("default"), "Cancel is default button");
|
112 | + ok(
|
|
113 | + !prompt.ui.button1.disabled,
|
|
114 | + "Cancel button should not be disabled by the security delay."
|
|
115 | + );
|
|
116 | + |
|
117 | + info("Wait for the security delay to pass.");
|
|
118 | + let delayTime = Services.prefs.getIntPref("security.dialog_enable_delay");
|
|
119 | + // eslint-disable-next-line mozilla/no-arbitrary-setTimeout
|
|
120 | + await new Promise(resolve => setTimeout(resolve, delayTime + 100));
|
|
121 | + |
|
122 | + ok(
|
|
123 | + !prompt.ui.button0.disabled,
|
|
124 | + "Accept button should no longer be disabled."
|
|
125 | + );
|
|
126 | + ok(!prompt.ui.button1.disabled, "Cancel button should remain enabled.");
|
|
106 | 127 | |
107 | 128 | // Close confirmation prompt
|
108 | 129 | await PromptTestUtils.handlePrompt(prompt, {
|
... | ... | @@ -156,7 +156,7 @@ export class PromptCollection { |
156 | 156 | Services.prompt.MODAL_TYPE_TAB,
|
157 | 157 | title,
|
158 | 158 | message,
|
159 | - buttonFlags,
|
|
159 | + buttonFlags | Ci.nsIPrompt.BUTTON_DELAY_ENABLE,
|
|
160 | 160 | acceptLabel,
|
161 | 161 | null,
|
162 | 162 | null,
|
... | ... | @@ -572,9 +572,19 @@ mozilla::ipc::IPCResult BrowsingContext::CreateFromIPC( |
572 | 572 | context->mRequestContextId = aInit.mRequestContextId;
|
573 | 573 | // NOTE: Private browsing ID is set by `SetOriginAttributes`.
|
574 | 574 | |
575 | + if (const char* failure =
|
|
576 | + context->BrowsingContextCoherencyChecks(aOriginProcess)) {
|
|
577 | + mozilla::ipc::IProtocol* actor = aOriginProcess;
|
|
578 | + if (!actor) {
|
|
579 | + actor = ContentChild::GetSingleton();
|
|
580 | + }
|
|
581 | + return IPC_FAIL(actor, "Incoherent BrowsingContext");
|
|
582 | + }
|
|
583 | + |
|
575 | 584 | Register(context);
|
576 | 585 | |
577 | - return context->Attach(/* aFromIPC */ true, aOriginProcess);
|
|
586 | + context->Attach(/* aFromIPC */ true, aOriginProcess);
|
|
587 | + return IPC_OK();
|
|
578 | 588 | }
|
579 | 589 | |
580 | 590 | BrowsingContext::BrowsingContext(WindowContext* aParentWindow,
|
... | ... | @@ -786,8 +796,64 @@ void BrowsingContext::Embed() { |
786 | 796 | }
|
787 | 797 | }
|
788 | 798 | |
789 | -mozilla::ipc::IPCResult BrowsingContext::Attach(bool aFromIPC,
|
|
790 | - ContentParent* aOriginProcess) {
|
|
799 | +const char* BrowsingContext::BrowsingContextCoherencyChecks(
|
|
800 | + ContentParent* aOriginProcess) {
|
|
801 | +#define COHERENCY_ASSERT(condition) \
|
|
802 | + if (!(condition)) return "Assertion " #condition " failed";
|
|
803 | + |
|
804 | + if (mGroup->IsPotentiallyCrossOriginIsolated() !=
|
|
805 | + (Top()->GetOpenerPolicy() ==
|
|
806 | + nsILoadInfo::OPENER_POLICY_SAME_ORIGIN_EMBEDDER_POLICY_REQUIRE_CORP)) {
|
|
807 | + return "Invalid CrossOriginIsolated state";
|
|
808 | + }
|
|
809 | + |
|
810 | + if (aOriginProcess && !IsContent()) {
|
|
811 | + return "Content cannot create chrome BCs";
|
|
812 | + }
|
|
813 | + |
|
814 | + // LoadContext should generally match our opener or parent.
|
|
815 | + if (IsContent()) {
|
|
816 | + if (RefPtr<BrowsingContext> opener = GetOpener()) {
|
|
817 | + COHERENCY_ASSERT(opener->mType == mType);
|
|
818 | + COHERENCY_ASSERT(opener->mGroup == mGroup);
|
|
819 | + COHERENCY_ASSERT(opener->mUseRemoteTabs == mUseRemoteTabs);
|
|
820 | + COHERENCY_ASSERT(opener->mUseRemoteSubframes == mUseRemoteSubframes);
|
|
821 | + COHERENCY_ASSERT(opener->mPrivateBrowsingId == mPrivateBrowsingId);
|
|
822 | + COHERENCY_ASSERT(
|
|
823 | + opener->mOriginAttributes.EqualsIgnoringFPD(mOriginAttributes));
|
|
824 | + }
|
|
825 | + }
|
|
826 | + if (RefPtr<BrowsingContext> parent = GetParent()) {
|
|
827 | + COHERENCY_ASSERT(parent->mType == mType);
|
|
828 | + COHERENCY_ASSERT(parent->mGroup == mGroup);
|
|
829 | + COHERENCY_ASSERT(parent->mUseRemoteTabs == mUseRemoteTabs);
|
|
830 | + COHERENCY_ASSERT(parent->mUseRemoteSubframes == mUseRemoteSubframes);
|
|
831 | + COHERENCY_ASSERT(parent->mPrivateBrowsingId == mPrivateBrowsingId);
|
|
832 | + COHERENCY_ASSERT(
|
|
833 | + parent->mOriginAttributes.EqualsIgnoringFPD(mOriginAttributes));
|
|
834 | + }
|
|
835 | + |
|
836 | + // UseRemoteSubframes and UseRemoteTabs must match.
|
|
837 | + if (mUseRemoteSubframes && !mUseRemoteTabs) {
|
|
838 | + return "Cannot set useRemoteSubframes without also setting useRemoteTabs";
|
|
839 | + }
|
|
840 | + |
|
841 | + // Double-check OriginAttributes/Private Browsing
|
|
842 | + // Chrome browsing contexts must not have a private browsing OriginAttribute
|
|
843 | + // Content browsing contexts must maintain the equality:
|
|
844 | + // mOriginAttributes.mPrivateBrowsingId == mPrivateBrowsingId
|
|
845 | + if (IsChrome()) {
|
|
846 | + COHERENCY_ASSERT(mOriginAttributes.mPrivateBrowsingId == 0);
|
|
847 | + } else {
|
|
848 | + COHERENCY_ASSERT(mOriginAttributes.mPrivateBrowsingId ==
|
|
849 | + mPrivateBrowsingId);
|
|
850 | + }
|
|
851 | +#undef COHERENCY_ASSERT
|
|
852 | + |
|
853 | + return nullptr;
|
|
854 | +}
|
|
855 | + |
|
856 | +void BrowsingContext::Attach(bool aFromIPC, ContentParent* aOriginProcess) {
|
|
791 | 857 | MOZ_DIAGNOSTIC_ASSERT(!mEverAttached);
|
792 | 858 | MOZ_DIAGNOSTIC_ASSERT_IF(aFromIPC, aOriginProcess || XRE_IsContentProcess());
|
793 | 859 | mEverAttached = true;
|
... | ... | @@ -806,25 +872,15 @@ mozilla::ipc::IPCResult BrowsingContext::Attach(bool aFromIPC, |
806 | 872 | MOZ_DIAGNOSTIC_ASSERT(mGroup);
|
807 | 873 | MOZ_DIAGNOSTIC_ASSERT(!mIsDiscarded);
|
808 | 874 | |
809 | - if (mGroup->IsPotentiallyCrossOriginIsolated() !=
|
|
810 | - (Top()->GetOpenerPolicy() ==
|
|
811 | - nsILoadInfo::OPENER_POLICY_SAME_ORIGIN_EMBEDDER_POLICY_REQUIRE_CORP)) {
|
|
812 | - MOZ_DIAGNOSTIC_ASSERT(aFromIPC);
|
|
813 | - if (aFromIPC) {
|
|
814 | - auto* actor = aOriginProcess
|
|
815 | - ? static_cast<mozilla::ipc::IProtocol*>(aOriginProcess)
|
|
816 | - : static_cast<mozilla::ipc::IProtocol*>(
|
|
817 | - ContentChild::GetSingleton());
|
|
818 | - return IPC_FAIL(
|
|
819 | - actor,
|
|
820 | - "Invalid CrossOriginIsolated state in BrowsingContext::Attach call");
|
|
821 | - } else {
|
|
822 | - MOZ_CRASH(
|
|
823 | - "Invalid CrossOriginIsolated state in BrowsingContext::Attach call");
|
|
875 | +#ifdef MOZ_DIAGNOSTIC_ASSERT_ENABLED
|
|
876 | + // We'll already have checked this if `aFromIPC` is set before calling this
|
|
877 | + // function.
|
|
878 | + if (!aFromIPC) {
|
|
879 | + if (const char* failure = BrowsingContextCoherencyChecks(aOriginProcess)) {
|
|
880 | + MOZ_CRASH_UNSAFE_PRINTF("Incoherent BrowsingContext: %s", failure);
|
|
824 | 881 | }
|
825 | 882 | }
|
826 | - |
|
827 | - AssertCoherentLoadContext();
|
|
883 | +#endif
|
|
828 | 884 | |
829 | 885 | // Add ourselves either to our parent or BrowsingContextGroup's child list.
|
830 | 886 | // Important: We shouldn't return IPC_FAIL after this point, since the
|
... | ... | @@ -906,7 +962,6 @@ mozilla::ipc::IPCResult BrowsingContext::Attach(bool aFromIPC, |
906 | 962 | if (XRE_IsParentProcess()) {
|
907 | 963 | Canonical()->CanonicalAttach();
|
908 | 964 | }
|
909 | - return IPC_OK();
|
|
910 | 965 | }
|
911 | 966 | |
912 | 967 | void BrowsingContext::Detach(bool aFromIPC) {
|
... | ... | @@ -1743,40 +1798,6 @@ nsresult BrowsingContext::SetOriginAttributes(const OriginAttributes& aAttrs) { |
1743 | 1798 | return NS_OK;
|
1744 | 1799 | }
|
1745 | 1800 | |
1746 | -void BrowsingContext::AssertCoherentLoadContext() {
|
|
1747 | -#ifdef MOZ_DIAGNOSTIC_ASSERT_ENABLED
|
|
1748 | - // LoadContext should generally match our opener or parent.
|
|
1749 | - if (IsContent()) {
|
|
1750 | - if (RefPtr<BrowsingContext> opener = GetOpener()) {
|
|
1751 | - MOZ_DIAGNOSTIC_ASSERT(opener->mType == mType);
|
|
1752 | - MOZ_DIAGNOSTIC_ASSERT(opener->mGroup == mGroup);
|
|
1753 | - MOZ_DIAGNOSTIC_ASSERT(opener->mUseRemoteTabs == mUseRemoteTabs);
|
|
1754 | - MOZ_DIAGNOSTIC_ASSERT(opener->mUseRemoteSubframes == mUseRemoteSubframes);
|
|
1755 | - MOZ_DIAGNOSTIC_ASSERT(opener->mPrivateBrowsingId == mPrivateBrowsingId);
|
|
1756 | - MOZ_DIAGNOSTIC_ASSERT(
|
|
1757 | - opener->mOriginAttributes.EqualsIgnoringFPD(mOriginAttributes));
|
|
1758 | - }
|
|
1759 | - }
|
|
1760 | - if (RefPtr<BrowsingContext> parent = GetParent()) {
|
|
1761 | - MOZ_DIAGNOSTIC_ASSERT(parent->mType == mType);
|
|
1762 | - MOZ_DIAGNOSTIC_ASSERT(parent->mGroup == mGroup);
|
|
1763 | - MOZ_DIAGNOSTIC_ASSERT(parent->mUseRemoteTabs == mUseRemoteTabs);
|
|
1764 | - MOZ_DIAGNOSTIC_ASSERT(parent->mUseRemoteSubframes == mUseRemoteSubframes);
|
|
1765 | - MOZ_DIAGNOSTIC_ASSERT(parent->mPrivateBrowsingId == mPrivateBrowsingId);
|
|
1766 | - MOZ_DIAGNOSTIC_ASSERT(
|
|
1767 | - parent->mOriginAttributes.EqualsIgnoringFPD(mOriginAttributes));
|
|
1768 | - }
|
|
1769 | - |
|
1770 | - // UseRemoteSubframes and UseRemoteTabs must match.
|
|
1771 | - MOZ_DIAGNOSTIC_ASSERT(
|
|
1772 | - !mUseRemoteSubframes || mUseRemoteTabs,
|
|
1773 | - "Cannot set useRemoteSubframes without also setting useRemoteTabs");
|
|
1774 | - |
|
1775 | - // Double-check OriginAttributes/Private Browsing
|
|
1776 | - AssertOriginAttributesMatchPrivateBrowsing();
|
|
1777 | -#endif
|
|
1778 | -}
|
|
1779 | - |
|
1780 | 1801 | void BrowsingContext::AssertOriginAttributesMatchPrivateBrowsing() {
|
1781 | 1802 | // Chrome browsing contexts must not have a private browsing OriginAttribute
|
1782 | 1803 | // Content browsing contexts must maintain the equality:
|
... | ... | @@ -971,7 +971,18 @@ class BrowsingContext : public nsILoadContext, public nsWrapperCache { |
971 | 971 | bool aHasPostData);
|
972 | 972 | |
973 | 973 | private:
|
974 | - mozilla::ipc::IPCResult Attach(bool aFromIPC, ContentParent* aOriginProcess);
|
|
974 | + // Assert that this BrowsingContext is coherent relative to related
|
|
975 | + // BrowsingContexts. This will be run before the BrowsingContext is attached.
|
|
976 | + //
|
|
977 | + // A non-null string return value indicates that there was a coherency check
|
|
978 | + // failure, which will be handled with either a crash or IPC failure.
|
|
979 | + //
|
|
980 | + // If provided, `aOriginProcess` is the process which is responsible for the
|
|
981 | + // creation of this BrowsingContext.
|
|
982 | + [[nodiscard]] const char* BrowsingContextCoherencyChecks(
|
|
983 | + ContentParent* aOriginProcess);
|
|
984 | + |
|
985 | + void Attach(bool aFromIPC, ContentParent* aOriginProcess);
|
|
975 | 986 | |
976 | 987 | // Recomputes whether we can execute scripts in this BrowsingContext based on
|
977 | 988 | // the value of AllowJavascript() and whether scripts are allowed in the
|
... | ... | @@ -985,10 +996,6 @@ class BrowsingContext : public nsILoadContext, public nsWrapperCache { |
985 | 996 | |
986 | 997 | void AssertOriginAttributesMatchPrivateBrowsing();
|
987 | 998 | |
988 | - // Assert that the BrowsingContext's LoadContext flags appear coherent
|
|
989 | - // relative to related BrowsingContexts.
|
|
990 | - void AssertCoherentLoadContext();
|
|
991 | - |
|
992 | 999 | friend class ::nsOuterWindowProxy;
|
993 | 1000 | friend class ::nsGlobalWindowOuter;
|
994 | 1001 | friend class WindowContext;
|
... | ... | @@ -6254,7 +6254,7 @@ already_AddRefed<nsIURI> nsDocShell::AttemptURIFixup( |
6254 | 6254 | |
6255 | 6255 | nsresult nsDocShell::FilterStatusForErrorPage(
|
6256 | 6256 | nsresult aStatus, nsIChannel* aChannel, uint32_t aLoadType,
|
6257 | - bool aIsTopFrame, bool aUseErrorPages, bool aIsInitialDocument,
|
|
6257 | + bool aIsTopFrame, bool aUseErrorPages,
|
|
6258 | 6258 | bool* aSkippedUnknownProtocolNavigation) {
|
6259 | 6259 | // Errors to be shown only on top-level frames
|
6260 | 6260 | if ((aStatus == NS_ERROR_UNKNOWN_HOST ||
|
... | ... | @@ -6298,18 +6298,10 @@ nsresult nsDocShell::FilterStatusForErrorPage( |
6298 | 6298 | |
6299 | 6299 | if (aStatus == NS_ERROR_UNKNOWN_PROTOCOL) {
|
6300 | 6300 | // For unknown protocols we only display an error if the load is triggered
|
6301 | - // by the browser itself, or we're replacing the initial document (and
|
|
6302 | - // nothing else). Showing the error for page-triggered navigations causes
|
|
6303 | - // annoying behavior for users, see bug 1528305.
|
|
6304 | - //
|
|
6305 | - // We could, maybe, try to detect if this is in response to some user
|
|
6306 | - // interaction (like clicking a link, or something else) and maybe show
|
|
6307 | - // the error page in that case. But this allows for ctrl+clicking and such
|
|
6308 | - // to see the error page.
|
|
6301 | + // by the browser itself. Showing the error for page-triggered navigations
|
|
6302 | + // causes annoying behavior for users, see bug 1528305.
|
|
6309 | 6303 | nsCOMPtr<nsILoadInfo> info = aChannel->LoadInfo();
|
6310 | - if (!info->TriggeringPrincipal()->IsSystemPrincipal() &&
|
|
6311 | - StaticPrefs::dom_no_unknown_protocol_error_enabled() &&
|
|
6312 | - !aIsInitialDocument) {
|
|
6304 | + if (!info->TriggeringPrincipal()->IsSystemPrincipal()) {
|
|
6313 | 6305 | if (aSkippedUnknownProtocolNavigation) {
|
6314 | 6306 | *aSkippedUnknownProtocolNavigation = true;
|
6315 | 6307 | }
|
... | ... | @@ -6459,12 +6451,9 @@ nsresult nsDocShell::EndPageLoad(nsIWebProgress* aProgress, |
6459 | 6451 | aStatus == NS_ERROR_CONTENT_BLOCKED);
|
6460 | 6452 | UnblockEmbedderLoadEventForFailure(fireFrameErrorEvent);
|
6461 | 6453 | |
6462 | - bool isInitialDocument =
|
|
6463 | - !GetExtantDocument() || GetExtantDocument()->IsInitialDocument();
|
|
6464 | 6454 | bool skippedUnknownProtocolNavigation = false;
|
6465 | 6455 | aStatus = FilterStatusForErrorPage(aStatus, aChannel, mLoadType, isTopFrame,
|
6466 | 6456 | mBrowsingContext->GetUseErrorPages(),
|
6467 | - isInitialDocument,
|
|
6468 | 6457 | &skippedUnknownProtocolNavigation);
|
6469 | 6458 | hadErrorStatus = true;
|
6470 | 6459 | if (NS_FAILED(aStatus)) {
|
... | ... | @@ -464,7 +464,7 @@ class nsDocShell final : public nsDocLoader, |
464 | 464 | // navigation.
|
465 | 465 | static nsresult FilterStatusForErrorPage(
|
466 | 466 | nsresult aStatus, nsIChannel* aChannel, uint32_t aLoadType,
|
467 | - bool aIsTopFrame, bool aUseErrorPages, bool aIsInitialDocument,
|
|
467 | + bool aIsTopFrame, bool aUseErrorPages,
|
|
468 | 468 | bool* aSkippedUnknownProtocolNavigation = nullptr);
|
469 | 469 | |
470 | 470 | // Notify consumers of a search being loaded through the observer service:
|
... | ... | @@ -8266,7 +8266,7 @@ void Document::RuleAdded(StyleSheet& aSheet, css::Rule& aRule) { |
8266 | 8266 | }
|
8267 | 8267 | }
|
8268 | 8268 | |
8269 | -void Document::ImportRuleLoaded(dom::CSSImportRule& aRule, StyleSheet& aSheet) {
|
|
8269 | +void Document::ImportRuleLoaded(StyleSheet& aSheet) {
|
|
8270 | 8270 | if (aSheet.IsApplicable()) {
|
8271 | 8271 | ApplicableStylesChanged();
|
8272 | 8272 | }
|
... | ... | @@ -2135,7 +2135,7 @@ class Document : public nsINode, |
2135 | 2135 | void RuleAdded(StyleSheet&, css::Rule&);
|
2136 | 2136 | void RuleRemoved(StyleSheet&, css::Rule&);
|
2137 | 2137 | void SheetCloned(StyleSheet&) {}
|
2138 | - void ImportRuleLoaded(CSSImportRule&, StyleSheet&);
|
|
2138 | + void ImportRuleLoaded(StyleSheet&);
|
|
2139 | 2139 | |
2140 | 2140 | /**
|
2141 | 2141 | * Flush notifications for this document and its parent documents
|
... | ... | @@ -412,7 +412,7 @@ void ShadowRoot::RuleChanged(StyleSheet& aSheet, css::Rule*, |
412 | 412 | ApplicableRulesChanged();
|
413 | 413 | }
|
414 | 414 | |
415 | -void ShadowRoot::ImportRuleLoaded(CSSImportRule&, StyleSheet& aSheet) {
|
|
415 | +void ShadowRoot::ImportRuleLoaded(StyleSheet& aSheet) {
|
|
416 | 416 | if (mStyleRuleMap) {
|
417 | 417 | mStyleRuleMap->SheetAdded(aSheet);
|
418 | 418 | }
|
... | ... | @@ -86,7 +86,7 @@ class ShadowRoot final : public DocumentFragment, |
86 | 86 | void RuleAdded(StyleSheet&, css::Rule&);
|
87 | 87 | void RuleRemoved(StyleSheet&, css::Rule&);
|
88 | 88 | void RuleChanged(StyleSheet&, css::Rule*, StyleRuleChangeKind);
|
89 | - void ImportRuleLoaded(CSSImportRule&, StyleSheet&);
|
|
89 | + void ImportRuleLoaded(StyleSheet&);
|
|
90 | 90 | void SheetCloned(StyleSheet&);
|
91 | 91 | void StyleSheetApplicableStateChanged(StyleSheet&);
|
92 | 92 |
... | ... | @@ -2,7 +2,45 @@ |
2 | 2 | |
3 | 3 | let dialogObserverTopic = "common-dialog-loaded";
|
4 | 4 | |
5 | -function dialogObserver(subj, topic, data) {
|
|
5 | +function waitForButtonEnabledState(button) {
|
|
6 | + return new Promise(resolve => {
|
|
7 | + // Check if the button is already enabled (not disabled)
|
|
8 | + if (!button.disabled) {
|
|
9 | + resolve();
|
|
10 | + return;
|
|
11 | + }
|
|
12 | + |
|
13 | + // Create a MutationObserver instance
|
|
14 | + let win = button.ownerGlobal;
|
|
15 | + let { MutationObserver } = win;
|
|
16 | + const observer = new MutationObserver(mutationsList => {
|
|
17 | + for (const mutation of mutationsList) {
|
|
18 | + if (
|
|
19 | + mutation.type === "attributes" &&
|
|
20 | + mutation.attributeName === "disabled"
|
|
21 | + ) {
|
|
22 | + if (!button.disabled) {
|
|
23 | + // Resolve the promise when the button is enabled
|
|
24 | + observer.disconnect(); // Stop observing
|
|
25 | + resolve();
|
|
26 | + }
|
|
27 | + }
|
|
28 | + }
|
|
29 | + });
|
|
30 | + |
|
31 | + // Start observing the button for changes to the 'disabled' attribute
|
|
32 | + observer.observe(button, {
|
|
33 | + attributes: true,
|
|
34 | + attributeFilter: ["disabled"],
|
|
35 | + });
|
|
36 | + });
|
|
37 | +}
|
|
38 | + |
|
39 | +async function dialogObserver(subj) {
|
|
40 | + let dialog = subj.document.querySelector("dialog");
|
|
41 | + let acceptButton = dialog.getButton("accept");
|
|
42 | + await waitForButtonEnabledState(acceptButton);
|
|
43 | + |
|
6 | 44 | subj.document.querySelector("dialog").acceptDialog();
|
7 | 45 | sendAsyncMessage("promptAccepted");
|
8 | 46 | }
|
... | ... | @@ -744,6 +744,7 @@ class JS_PUBLIC_API JSAutoStructuredCloneBuffer { |
744 | 744 | #define JS_SCERR_WASM_NO_TRANSFER 6
|
745 | 745 | #define JS_SCERR_NOT_CLONABLE 7
|
746 | 746 | #define JS_SCERR_NOT_CLONABLE_WITH_COOP_COEP 8
|
747 | +#define JS_SCERR_TRANSFERABLE_TWICE 9
|
|
747 | 748 | |
748 | 749 | JS_PUBLIC_API bool JS_ReadUint32Pair(JSStructuredCloneReader* r, uint32_t* p1,
|
749 | 750 | uint32_t* p2);
|
... | ... | @@ -527,6 +527,7 @@ MSG_DEF(JSMSG_SC_BAD_CLONE_VERSION, 0, JSEXN_ERR, "unsupported structured clo |
527 | 527 | MSG_DEF(JSMSG_SC_BAD_SERIALIZED_DATA, 1, JSEXN_INTERNALERR, "bad serialized structured data ({0})")
|
528 | 528 | MSG_DEF(JSMSG_SC_DUP_TRANSFERABLE, 0, JSEXN_TYPEERR, "duplicate transferable for structured clone")
|
529 | 529 | MSG_DEF(JSMSG_SC_NOT_TRANSFERABLE, 0, JSEXN_TYPEERR, "invalid transferable array for structured clone")
|
530 | +MSG_DEF(JSMSG_SC_TRANSFERABLE_TWICE, 0, JSEXN_TYPEERR, "structured clone cannot transfer twice")
|
|
530 | 531 | MSG_DEF(JSMSG_SC_UNSUPPORTED_TYPE, 0, JSEXN_TYPEERR, "unsupported type for structured data")
|
531 | 532 | MSG_DEF(JSMSG_SC_NOT_CLONABLE, 1, JSEXN_TYPEERR, "The {0} object cannot be serialized. The Cross-Origin-Opener-Policy and Cross-Origin-Embedder-Policy HTTP headers will enable this in the future.")
|
532 | 533 | MSG_DEF(JSMSG_SC_NOT_CLONABLE_WITH_COOP_COEP, 1, JSEXN_TYPEERR, "The {0} object cannot be serialized. The Cross-Origin-Opener-Policy and Cross-Origin-Embedder-Policy HTTP headers can be used to enable this.")
|
... | ... | @@ -160,6 +160,15 @@ function testMultiWithDeserializeReadTransferErrorHelper(g, BASE, desc) { |
160 | 160 | } catch (e) {
|
161 | 161 | assertEq(e.message.includes("invalid transferable"), true);
|
162 | 162 | }
|
163 | + |
|
164 | + try {
|
|
165 | + // This fails without logging anything, since the re-transfer will be caught
|
|
166 | + // by looking at its header before calling any callbacks.
|
|
167 | + let clone = deserialize(s);
|
|
168 | + } catch (e) {
|
|
169 | + assertEq(e.message.includes("cannot transfer twice"), true);
|
|
170 | + }
|
|
171 | + |
|
163 | 172 | s = null;
|
164 | 173 | gc();
|
165 | 174 | printTrace(arguments.callee.name, g, BASE, obj.log, "deserialize");
|
... | ... | @@ -170,6 +179,7 @@ function testMultiWithDeserializeReadTransferErrorHelper(g, BASE, desc) { |
170 | 179 | // which comes before the main reading. obj transfer data is now owned by its
|
171 | 180 | // clone. obj3 transfer data was not successfully handed over to a new object,
|
172 | 181 | // so it is still owned by the clone buffer and must be discarded with freeTransfer.
|
182 | + // 'F' means the data is freed.
|
|
173 | 183 | BASE + 3, "F",
|
174 | 184 | ], "deserialize " + desc);
|
175 | 185 | obj.log = null;
|
... | ... | @@ -29,8 +29,9 @@ using MPhiUseIteratorStack = |
29 | 29 | |
30 | 30 | // Look for Phi uses with a depth-first search. If any uses are found the stack
|
31 | 31 | // of MPhi instructions is returned in the |worklist| argument.
|
32 | -static bool DepthFirstSearchUse(MIRGenerator* mir,
|
|
33 | - MPhiUseIteratorStack& worklist, MPhi* phi) {
|
|
32 | +[[nodiscard]] static bool DepthFirstSearchUse(MIRGenerator* mir,
|
|
33 | + MPhiUseIteratorStack& worklist,
|
|
34 | + MPhi* phi) {
|
|
34 | 35 | // Push a Phi and the next use to iterate over in the worklist.
|
35 | 36 | auto push = [&worklist](MPhi* phi, MUseIterator use) -> bool {
|
36 | 37 | phi->setInWorklist();
|
... | ... | @@ -131,9 +132,9 @@ static bool DepthFirstSearchUse(MIRGenerator* mir, |
131 | 132 | return true;
|
132 | 133 | }
|
133 | 134 | |
134 | -static bool FlagPhiInputsAsImplicitlyUsed(MIRGenerator* mir, MBasicBlock* block,
|
|
135 | - MBasicBlock* succ,
|
|
136 | - MPhiUseIteratorStack& worklist) {
|
|
135 | +[[nodiscard]] static bool FlagPhiInputsAsImplicitlyUsed(
|
|
136 | + MIRGenerator* mir, MBasicBlock* block, MBasicBlock* succ,
|
|
137 | + MPhiUseIteratorStack& worklist) {
|
|
137 | 138 | // When removing an edge between 2 blocks, we might remove the ability of
|
138 | 139 | // later phases to figure out that the uses of a Phi should be considered as
|
139 | 140 | // a use of all its inputs. Thus we need to mark the Phi inputs as being
|
... | ... | @@ -265,7 +266,7 @@ static MInstructionIterator FindFirstInstructionAfterBail(MBasicBlock* block) { |
265 | 266 | |
266 | 267 | // Given an iterator pointing to the first removed instruction, mark
|
267 | 268 | // the operands of each removed instruction as having implicit uses.
|
268 | -static bool FlagOperandsAsImplicitlyUsedAfter(
|
|
269 | +[[nodiscard]] static bool FlagOperandsAsImplicitlyUsedAfter(
|
|
269 | 270 | MIRGenerator* mir, MBasicBlock* block, MInstructionIterator firstRemoved) {
|
270 | 271 | MOZ_ASSERT(firstRemoved->block() == block);
|
271 | 272 | |
... | ... | @@ -312,8 +313,8 @@ static bool FlagOperandsAsImplicitlyUsedAfter( |
312 | 313 | return true;
|
313 | 314 | }
|
314 | 315 | |
315 | -static bool FlagEntryResumePointOperands(MIRGenerator* mir,
|
|
316 | - MBasicBlock* block) {
|
|
316 | +[[nodiscard]] static bool FlagEntryResumePointOperands(MIRGenerator* mir,
|
|
317 | + MBasicBlock* block) {
|
|
317 | 318 | // Flag observable operands of the entry resume point as having implicit uses.
|
318 | 319 | MResumePoint* rp = block->entryResumePoint();
|
319 | 320 | while (rp) {
|
... | ... | @@ -334,8 +335,8 @@ static bool FlagEntryResumePointOperands(MIRGenerator* mir, |
334 | 335 | return true;
|
335 | 336 | }
|
336 | 337 | |
337 | -static bool FlagAllOperandsAsImplicitlyUsed(MIRGenerator* mir,
|
|
338 | - MBasicBlock* block) {
|
|
338 | +[[nodiscard]] static bool FlagAllOperandsAsImplicitlyUsed(MIRGenerator* mir,
|
|
339 | + MBasicBlock* block) {
|
|
339 | 340 | return FlagEntryResumePointOperands(mir, block) &&
|
340 | 341 | FlagOperandsAsImplicitlyUsedAfter(mir, block, block->begin());
|
341 | 342 | }
|
... | ... | @@ -420,12 +421,16 @@ bool jit::PruneUnusedBranches(MIRGenerator* mir, MIRGraph& graph) { |
420 | 421 | if (!block->isMarked()) {
|
421 | 422 | // If we are removing the block entirely, mark the operands of every
|
422 | 423 | // instruction as being implicitly used.
|
423 | - FlagAllOperandsAsImplicitlyUsed(mir, block);
|
|
424 | + if (!FlagAllOperandsAsImplicitlyUsed(mir, block)) {
|
|
425 | + return false;
|
|
426 | + }
|
|
424 | 427 | } else if (block->alwaysBails()) {
|
425 | 428 | // If we are only trimming instructions after a bail, only mark operands
|
426 | 429 | // of removed instructions.
|
427 | 430 | MInstructionIterator firstRemoved = FindFirstInstructionAfterBail(block);
|
428 | - FlagOperandsAsImplicitlyUsedAfter(mir, block, firstRemoved);
|
|
431 | + if (!FlagOperandsAsImplicitlyUsedAfter(mir, block, firstRemoved)) {
|
|
432 | + return false;
|
|
433 | + }
|
|
429 | 434 | }
|
430 | 435 | }
|
431 | 436 | |
... | ... | @@ -503,7 +508,8 @@ bool jit::PruneUnusedBranches(MIRGenerator* mir, MIRGraph& graph) { |
503 | 508 | return true;
|
504 | 509 | }
|
505 | 510 | |
506 | -static bool SplitCriticalEdgesForBlock(MIRGraph& graph, MBasicBlock* block) {
|
|
511 | +[[nodiscard]] static bool SplitCriticalEdgesForBlock(MIRGraph& graph,
|
|
512 | + MBasicBlock* block) {
|
|
507 | 513 | if (block->numSuccessors() < 2) {
|
508 | 514 | return true;
|
509 | 515 | }
|
... | ... | @@ -767,8 +773,8 @@ static bool IsDiamondPattern(MBasicBlock* initialBlock) { |
767 | 773 | return true;
|
768 | 774 | }
|
769 | 775 | |
770 | -static bool MaybeFoldDiamondConditionBlock(MIRGraph& graph,
|
|
771 | - MBasicBlock* initialBlock) {
|
|
776 | +[[nodiscard]] static bool MaybeFoldDiamondConditionBlock(
|
|
777 | + MIRGraph& graph, MBasicBlock* initialBlock) {
|
|
772 | 778 | MOZ_ASSERT(IsDiamondPattern(initialBlock));
|
773 | 779 | |
774 | 780 | // Optimize the MIR graph to improve the code generated for conditional
|
... | ... | @@ -936,8 +942,8 @@ static bool IsTrianglePattern(MBasicBlock* initialBlock) { |
936 | 942 | return false;
|
937 | 943 | }
|
938 | 944 | |
939 | -static bool MaybeFoldTriangleConditionBlock(MIRGraph& graph,
|
|
940 | - MBasicBlock* initialBlock) {
|
|
945 | +[[nodiscard]] static bool MaybeFoldTriangleConditionBlock(
|
|
946 | + MIRGraph& graph, MBasicBlock* initialBlock) {
|
|
941 | 947 | MOZ_ASSERT(IsTrianglePattern(initialBlock));
|
942 | 948 | |
943 | 949 | // Optimize the MIR graph to improve the code generated for boolean
|
... | ... | @@ -1089,8 +1095,8 @@ static bool MaybeFoldTriangleConditionBlock(MIRGraph& graph, |
1089 | 1095 | return true;
|
1090 | 1096 | }
|
1091 | 1097 | |
1092 | -static bool MaybeFoldConditionBlock(MIRGraph& graph,
|
|
1093 | - MBasicBlock* initialBlock) {
|
|
1098 | +[[nodiscard]] static bool MaybeFoldConditionBlock(MIRGraph& graph,
|
|
1099 | + MBasicBlock* initialBlock) {
|
|
1094 | 1100 | if (IsDiamondPattern(initialBlock)) {
|
1095 | 1101 | return MaybeFoldDiamondConditionBlock(graph, initialBlock);
|
1096 | 1102 | }
|
... | ... | @@ -1100,7 +1106,8 @@ static bool MaybeFoldConditionBlock(MIRGraph& graph, |
1100 | 1106 | return true;
|
1101 | 1107 | }
|
1102 | 1108 | |
1103 | -static bool MaybeFoldTestBlock(MIRGraph& graph, MBasicBlock* initialBlock) {
|
|
1109 | +[[nodiscard]] static bool MaybeFoldTestBlock(MIRGraph& graph,
|
|
1110 | + MBasicBlock* initialBlock) {
|
|
1104 | 1111 | // Handle test expressions on more than two inputs. For example
|
1105 | 1112 | // |if ((x > 10) && (y > 20) && (z > 30)) { ... }|, which results in the below
|
1106 | 1113 | // pattern.
|
... | ... | @@ -2752,7 +2759,9 @@ bool jit::RemoveUnmarkedBlocks(MIRGenerator* mir, MIRGraph& graph, |
2752 | 2759 | continue;
|
2753 | 2760 | }
|
2754 | 2761 | |
2755 | - FlagAllOperandsAsImplicitlyUsed(mir, block);
|
|
2762 | + if (!FlagAllOperandsAsImplicitlyUsed(mir, block)) {
|
|
2763 | + return false;
|
|
2764 | + }
|
|
2756 | 2765 | }
|
2757 | 2766 | |
2758 | 2767 | // Find unmarked blocks and remove them.
|
... | ... | @@ -4003,8 +4012,8 @@ bool jit::EliminateRedundantShapeGuards(MIRGraph& graph) { |
4003 | 4012 | return true;
|
4004 | 4013 | }
|
4005 | 4014 | |
4006 | -static bool TryEliminateGCBarriersForAllocation(TempAllocator& alloc,
|
|
4007 | - MInstruction* allocation) {
|
|
4015 | +[[nodiscard]] static bool TryEliminateGCBarriersForAllocation(
|
|
4016 | + TempAllocator& alloc, MInstruction* allocation) {
|
|
4008 | 4017 | MOZ_ASSERT(allocation->type() == MIRType::Object);
|
4009 | 4018 | |
4010 | 4019 | JitSpew(JitSpew_RedundantGCBarriers, "Analyzing allocation %s",
|
... | ... | @@ -172,17 +172,25 @@ enum StructuredDataType : uint32_t { |
172 | 172 | |
173 | 173 | /*
|
174 | 174 | * Format of transfer map:
|
175 | - * <SCTAG_TRANSFER_MAP_HEADER, TransferableMapHeader(UNREAD|TRANSFERRED)>
|
|
176 | - * numTransferables (64 bits)
|
|
177 | - * array of:
|
|
178 | - * <SCTAG_TRANSFER_MAP_*, TransferableOwnership>
|
|
179 | - * pointer (64 bits)
|
|
180 | - * extraData (64 bits), eg byte length for ArrayBuffers
|
|
175 | + * - <SCTAG_TRANSFER_MAP_HEADER, UNREAD|TRANSFERRING|TRANSFERRED>
|
|
176 | + * - numTransferables (64 bits)
|
|
177 | + * - array of:
|
|
178 | + * - <SCTAG_TRANSFER_MAP_*, TransferableOwnership> pointer (64
|
|
179 | + * bits)
|
|
180 | + * - extraData (64 bits), eg byte length for ArrayBuffers
|
|
181 | + * - any data written for custom transferables
|
|
181 | 182 | */
|
182 | 183 | |
183 | 184 | // Data associated with an SCTAG_TRANSFER_MAP_HEADER that tells whether the
|
184 | -// contents have been read out yet or not.
|
|
185 | -enum TransferableMapHeader { SCTAG_TM_UNREAD = 0, SCTAG_TM_TRANSFERRED };
|
|
185 | +// contents have been read out yet or not. TRANSFERRING is for the case where we
|
|
186 | +// have started but not completed reading, which due to errors could mean that
|
|
187 | +// there are things still owned by the clone buffer that need to be released, so
|
|
188 | +// discarding should not just be skipped.
|
|
189 | +enum TransferableMapHeader {
|
|
190 | + SCTAG_TM_UNREAD = 0,
|
|
191 | + SCTAG_TM_TRANSFERRING,
|
|
192 | + SCTAG_TM_TRANSFERRED
|
|
193 | +};
|
|
186 | 194 | |
187 | 195 | static inline uint64_t PairToUInt64(uint32_t tag, uint32_t data) {
|
188 | 196 | return uint64_t(data) | (uint64_t(tag) << 32);
|
... | ... | @@ -693,6 +701,10 @@ static void ReportDataCloneError(JSContext* cx, |
693 | 701 | errorNumber = JSMSG_SC_SHMEM_TRANSFERABLE;
|
694 | 702 | break;
|
695 | 703 | |
704 | + case JS_SCERR_TRANSFERABLE_TWICE:
|
|
705 | + errorNumber = JSMSG_SC_TRANSFERABLE_TWICE;
|
|
706 | + break;
|
|
707 | + |
|
696 | 708 | case JS_SCERR_TYPED_ARRAY_DETACHED:
|
697 | 709 | errorNumber = JSMSG_TYPED_ARRAY_DETACHED;
|
698 | 710 | break;
|
... | ... | @@ -3209,11 +3221,21 @@ bool JSStructuredCloneReader::readTransferMap() { |
3209 | 3221 | return in.reportTruncated();
|
3210 | 3222 | }
|
3211 | 3223 | |
3224 | + auto transferState = static_cast<TransferableMapHeader>(data);
|
|
3225 | + |
|
3212 | 3226 | if (tag != SCTAG_TRANSFER_MAP_HEADER ||
|
3213 | - TransferableMapHeader(data) == SCTAG_TM_TRANSFERRED) {
|
|
3227 | + transferState == SCTAG_TM_TRANSFERRED) {
|
|
3214 | 3228 | return true;
|
3215 | 3229 | }
|
3216 | 3230 | |
3231 | + if (transferState == SCTAG_TM_TRANSFERRING) {
|
|
3232 | + ReportDataCloneError(cx, callbacks, JS_SCERR_TRANSFERABLE_TWICE, closure);
|
|
3233 | + return false;
|
|
3234 | + }
|
|
3235 | + |
|
3236 | + headerPos.write(
|
|
3237 | + PairToUInt64(SCTAG_TRANSFER_MAP_HEADER, SCTAG_TM_TRANSFERRING));
|
|
3238 | + |
|
3217 | 3239 | uint64_t numTransferables;
|
3218 | 3240 | MOZ_ALWAYS_TRUE(in.readPair(&tag, &data));
|
3219 | 3241 | if (!in.read(&numTransferables)) {
|
... | ... | @@ -3329,7 +3351,7 @@ bool JSStructuredCloneReader::readTransferMap() { |
3329 | 3351 | #ifdef DEBUG
|
3330 | 3352 | SCInput::getPair(headerPos.peek(), &tag, &data);
|
3331 | 3353 | MOZ_ASSERT(tag == SCTAG_TRANSFER_MAP_HEADER);
|
3332 | - MOZ_ASSERT(TransferableMapHeader(data) != SCTAG_TM_TRANSFERRED);
|
|
3354 | + MOZ_ASSERT(TransferableMapHeader(data) == SCTAG_TM_TRANSFERRING);
|
|
3333 | 3355 | #endif
|
3334 | 3356 | headerPos.write(
|
3335 | 3357 | PairToUInt64(SCTAG_TRANSFER_MAP_HEADER, SCTAG_TM_TRANSFERRED));
|
... | ... | @@ -954,7 +954,7 @@ static OriginFlags ToOriginFlags(StyleOrigin aOrigin) { |
954 | 954 | }
|
955 | 955 | }
|
956 | 956 | |
957 | -void ServoStyleSet::ImportRuleLoaded(dom::CSSImportRule&, StyleSheet& aSheet) {
|
|
957 | +void ServoStyleSet::ImportRuleLoaded(StyleSheet& aSheet) {
|
|
958 | 958 | if (mStyleRuleMap) {
|
959 | 959 | mStyleRuleMap->SheetAdded(aSheet);
|
960 | 960 | }
|
... | ... | @@ -133,7 +133,7 @@ class ServoStyleSet { |
133 | 133 | void RuleRemoved(StyleSheet&, css::Rule&);
|
134 | 134 | void RuleChanged(StyleSheet&, css::Rule*, StyleRuleChangeKind);
|
135 | 135 | void SheetCloned(StyleSheet&);
|
136 | - void ImportRuleLoaded(dom::CSSImportRule&, StyleSheet&);
|
|
136 | + void ImportRuleLoaded(StyleSheet&);
|
|
137 | 137 | |
138 | 138 | // Runs style invalidation due to document state changes.
|
139 | 139 | void InvalidateStyleForDocumentStateChanges(
|
... | ... | @@ -836,15 +836,19 @@ StyleSheet::StyleSheetLoaded(StyleSheet* aSheet, bool aWasDeferred, |
836 | 836 | if (!aSheet->GetParentSheet()) {
|
837 | 837 | return NS_OK; // ignore if sheet has been detached already
|
838 | 838 | }
|
839 | - MOZ_ASSERT(this == aSheet->GetParentSheet(),
|
|
840 | - "We are being notified of a sheet load for a sheet that is not "
|
|
841 | - "our child!");
|
|
839 | + MOZ_DIAGNOSTIC_ASSERT(this == aSheet->GetParentSheet(),
|
|
840 | + "We are being notified of a sheet load for a sheet "
|
|
841 | + "that is not our child!");
|
|
842 | 842 | if (NS_FAILED(aStatus)) {
|
843 | 843 | return NS_OK;
|
844 | 844 | }
|
845 | - |
|
846 | - MOZ_ASSERT(aSheet->GetOwnerRule());
|
|
847 | - NOTIFY(ImportRuleLoaded, (*aSheet->GetOwnerRule(), *aSheet));
|
|
845 | + // The assert below should hold if we stop triggering import loads for invalid
|
|
846 | + // insertRule() calls, see bug 1914106.
|
|
847 | + // MOZ_ASSERT(aSheet->GetOwnerRule());
|
|
848 | + if (!aSheet->GetOwnerRule()) {
|
|
849 | + return NS_OK;
|
|
850 | + }
|
|
851 | + NOTIFY(ImportRuleLoaded, (*aSheet));
|
|
848 | 852 | return NS_OK;
|
849 | 853 | }
|
850 | 854 |
... | ... | @@ -2316,15 +2316,9 @@ bool DocumentLoadListener::DocShellWillDisplayContent(nsresult aStatus) { |
2316 | 2316 | |
2317 | 2317 | auto* loadingContext = GetLoadingBrowsingContext();
|
2318 | 2318 | |
2319 | - bool isInitialDocument = true;
|
|
2320 | - if (WindowGlobalParent* currentWindow =
|
|
2321 | - loadingContext->GetCurrentWindowGlobal()) {
|
|
2322 | - isInitialDocument = currentWindow->IsInitialDocument();
|
|
2323 | - }
|
|
2324 | - |
|
2325 | 2319 | nsresult rv = nsDocShell::FilterStatusForErrorPage(
|
2326 | 2320 | aStatus, mChannel, mLoadStateLoadType, loadingContext->IsTop(),
|
2327 | - loadingContext->GetUseErrorPages(), isInitialDocument, nullptr);
|
|
2321 | + loadingContext->GetUseErrorPages(), nullptr);
|
|
2328 | 2322 | |
2329 | 2323 | if (NS_SUCCEEDED(rv)) {
|
2330 | 2324 | MOZ_LOG(gProcessIsolationLog, LogLevel::Verbose,
|
... | ... | @@ -1042,15 +1042,6 @@ void WebTransportSessionProxy::NotifyDatagramReceived( |
1042 | 1042 | MutexAutoLock lock(mMutex);
|
1043 | 1043 | MOZ_ASSERT(mTarget->IsOnCurrentThread());
|
1044 | 1044 | |
1045 | - if (!mStopRequestCalled) {
|
|
1046 | - CopyableTArray<uint8_t> copied(aData);
|
|
1047 | - mPendingEvents.AppendElement(
|
|
1048 | - [self = RefPtr{this}, data = std::move(copied)]() mutable {
|
|
1049 | - self->NotifyDatagramReceived(std::move(data));
|
|
1050 | - });
|
|
1051 | - return;
|
|
1052 | - }
|
|
1053 | - |
|
1054 | 1045 | if (mState != WebTransportSessionProxyState::ACTIVE || !mListener) {
|
1055 | 1046 | return;
|
1056 | 1047 | }
|
... | ... | @@ -1066,6 +1057,15 @@ NS_IMETHODIMP WebTransportSessionProxy::OnDatagramReceivedInternal( |
1066 | 1057 | |
1067 | 1058 | {
|
1068 | 1059 | MutexAutoLock lock(mMutex);
|
1060 | + if (!mStopRequestCalled) {
|
|
1061 | + CopyableTArray<uint8_t> copied(aData);
|
|
1062 | + mPendingEvents.AppendElement(
|
|
1063 | + [self = RefPtr{this}, data = std::move(copied)]() mutable {
|
|
1064 | + self->OnDatagramReceivedInternal(std::move(data));
|
|
1065 | + });
|
|
1066 | + return NS_OK;
|
|
1067 | + }
|
|
1068 | + |
|
1069 | 1069 | if (!mTarget->IsOnCurrentThread()) {
|
1070 | 1070 | return mTarget->Dispatch(NS_NewRunnableFunction(
|
1071 | 1071 | "WebTransportSessionProxy::OnDatagramReceived",
|
1 | +<!doctype html>
|
|
2 | +<link rel="help" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1914106">
|
|
3 | +<style></style>
|
|
4 | +<script>
|
|
5 | +document.querySelector("style").sheet.insertRule("@import url('data:text/css,:root{background:red}');html,body{/* random garbage */}");
|
|
6 | +</script> |