ma1 pushed to branch tor-browser-115.1.0esr-13.0-1 at The Tor Project / Applications / Tor Browser

Commits:

12 changed files:

Changes:

  • accessible/android/SessionAccessibility.cpp
    ... ... @@ -269,12 +269,9 @@ RefPtr<SessionAccessibility> SessionAccessibility::GetInstanceFor(
    269 269
           return GetInstanceFor(doc->GetPresShell());
    
    270 270
         }
    
    271 271
       } else {
    
    272
    -    DocAccessibleParent* remoteDoc = aAccessible->AsRemote()->Document();
    
    273
    -    if (remoteDoc->mSessionAccessibility) {
    
    274
    -      return remoteDoc->mSessionAccessibility;
    
    275
    -    }
    
    276 272
         dom::CanonicalBrowsingContext* cbc =
    
    277
    -        static_cast<dom::BrowserParent*>(remoteDoc->Manager())
    
    273
    +        static_cast<dom::BrowserParent*>(
    
    274
    +            aAccessible->AsRemote()->Document()->Manager())
    
    278 275
                 ->GetBrowsingContext()
    
    279 276
                 ->Top();
    
    280 277
         dom::BrowserParent* bp = cbc->GetBrowserParent();
    
    ... ... @@ -285,10 +282,7 @@ RefPtr<SessionAccessibility> SessionAccessibility::GetInstanceFor(
    285 282
         if (auto element = bp->GetOwnerElement()) {
    
    286 283
           if (auto doc = element->OwnerDoc()) {
    
    287 284
             if (nsPresContext* presContext = doc->GetPresContext()) {
    
    288
    -          RefPtr<SessionAccessibility> sessionAcc =
    
    289
    -              GetInstanceFor(presContext->PresShell());
    
    290
    -          remoteDoc->mSessionAccessibility = sessionAcc;
    
    291
    -          return sessionAcc;
    
    285
    +          return GetInstanceFor(presContext->PresShell());
    
    292 286
             }
    
    293 287
           } else {
    
    294 288
             MOZ_ASSERT_UNREACHABLE(
    
    ... ... @@ -684,14 +678,7 @@ void SessionAccessibility::PopulateNodeInfo(
    684 678
     }
    
    685 679
     
    
    686 680
     Accessible* SessionAccessibility::GetAccessibleByID(int32_t aID) const {
    
    687
    -  Accessible* accessible = mIDToAccessibleMap.Get(aID);
    
    688
    -  if (accessible && accessible->IsLocal() &&
    
    689
    -      accessible->AsLocal()->IsDefunct()) {
    
    690
    -    MOZ_ASSERT_UNREACHABLE("Registered accessible is defunct!");
    
    691
    -    return nullptr;
    
    692
    -  }
    
    693
    -
    
    694
    -  return accessible;
    
    681
    +  return mIDToAccessibleMap.Get(aID);
    
    695 682
     }
    
    696 683
     
    
    697 684
     #ifdef DEBUG
    
    ... ... @@ -705,6 +692,58 @@ static bool IsDetachedDoc(Accessible* aAccessible) {
    705 692
     }
    
    706 693
     #endif
    
    707 694
     
    
    695
    +SessionAccessibility::IDMappingEntry::IDMappingEntry(Accessible* aAccessible)
    
    696
    +    : mInternalID(0) {
    
    697
    +  *this = aAccessible;
    
    698
    +}
    
    699
    +
    
    700
    +SessionAccessibility::IDMappingEntry&
    
    701
    +SessionAccessibility::IDMappingEntry::operator=(Accessible* aAccessible) {
    
    702
    +  mInternalID = aAccessible->ID();
    
    703
    +  MOZ_ASSERT(!(mInternalID & IS_REMOTE), "First bit is used in accessible ID!");
    
    704
    +  if (aAccessible->IsRemote()) {
    
    705
    +    mInternalID |= IS_REMOTE;
    
    706
    +  }
    
    707
    +
    
    708
    +  Accessible* docAcc = nsAccUtils::DocumentFor(aAccessible);
    
    709
    +  MOZ_ASSERT(docAcc);
    
    710
    +  if (docAcc) {
    
    711
    +    MOZ_ASSERT(docAcc->IsRemote() == aAccessible->IsRemote());
    
    712
    +    if (docAcc->IsRemote()) {
    
    713
    +      mDoc = docAcc->AsRemote()->AsDoc();
    
    714
    +    } else {
    
    715
    +      mDoc = docAcc->AsLocal();
    
    716
    +    }
    
    717
    +  }
    
    718
    +
    
    719
    +  return *this;
    
    720
    +}
    
    721
    +
    
    722
    +SessionAccessibility::IDMappingEntry::operator Accessible*() const {
    
    723
    +  if (mInternalID == 0) {
    
    724
    +    return static_cast<LocalAccessible*>(mDoc.get());
    
    725
    +  }
    
    726
    +
    
    727
    +  if (mInternalID == IS_REMOTE) {
    
    728
    +    return static_cast<DocAccessibleParent*>(mDoc.get());
    
    729
    +  }
    
    730
    +
    
    731
    +  if (mInternalID & IS_REMOTE) {
    
    732
    +    return static_cast<DocAccessibleParent*>(mDoc.get())
    
    733
    +        ->GetAccessible(mInternalID & ~IS_REMOTE);
    
    734
    +  }
    
    735
    +
    
    736
    +  Accessible* accessible =
    
    737
    +      static_cast<LocalAccessible*>(mDoc.get())
    
    738
    +          ->AsDoc()
    
    739
    +          ->GetAccessibleByUniqueID(reinterpret_cast<void*>(mInternalID));
    
    740
    +  // If the accessible is retrievable from the DocAccessible, it can't be
    
    741
    +  // defunct.
    
    742
    +  MOZ_ASSERT(!accessible->AsLocal()->IsDefunct());
    
    743
    +
    
    744
    +  return accessible;
    
    745
    +}
    
    746
    +
    
    708 747
     void SessionAccessibility::RegisterAccessible(Accessible* aAccessible) {
    
    709 748
       if (IPCAccessibilityActive()) {
    
    710 749
         // Don't register accessible in content process.
    
    ... ... @@ -766,7 +805,6 @@ void SessionAccessibility::UnregisterAccessible(Accessible* aAccessible) {
    766 805
       }
    
    767 806
     
    
    768 807
       RefPtr<SessionAccessibility> sessionAcc = GetInstanceFor(aAccessible);
    
    769
    -  MOZ_ASSERT(sessionAcc, "Need SessionAccessibility to unregister Accessible!");
    
    770 808
       if (sessionAcc) {
    
    771 809
         Accessible* registeredAcc =
    
    772 810
             sessionAcc->mIDToAccessibleMap.Get(virtualViewID);
    

  • accessible/android/SessionAccessibility.h
    ... ... @@ -110,10 +110,34 @@ class SessionAccessibility final
    110 110
       jni::NativeWeakPtr<widget::GeckoViewSupport> mWindow;  // Parent only
    
    111 111
       java::SessionAccessibility::NativeProvider::GlobalRef mSessionAccessibility;
    
    112 112
     
    
    113
    +  class IDMappingEntry {
    
    114
    +   public:
    
    115
    +    explicit IDMappingEntry(Accessible* aAccessible);
    
    116
    +
    
    117
    +    IDMappingEntry& operator=(Accessible* aAccessible);
    
    118
    +
    
    119
    +    operator Accessible*() const;
    
    120
    +
    
    121
    +   private:
    
    122
    +    // A strong reference to a DocAccessible or DocAccessibleParent. They don't
    
    123
    +    // share any useful base class except nsISupports, so we use that.
    
    124
    +    // When we retrieve the document from this reference we cast it to
    
    125
    +    // LocalAccessible in the DocAccessible case because DocAccessible has
    
    126
    +    // multiple inheritance paths for nsISupports.
    
    127
    +    RefPtr<nsISupports> mDoc;
    
    128
    +    // The ID of the accessible as used in the internal doc mapping.
    
    129
    +    // We rely on this ID being pointer derived and therefore divisible by two
    
    130
    +    // so we can use the first bit to mark if it is remote or not.
    
    131
    +    uint64_t mInternalID;
    
    132
    +
    
    133
    +    static const uintptr_t IS_REMOTE = 0x1;
    
    134
    +  };
    
    135
    +
    
    113 136
       /*
    
    114 137
        * This provides a mapping from 32 bit id to accessible objects.
    
    115 138
        */
    
    116
    -  nsTHashMap<nsUint32HashKey, Accessible*> mIDToAccessibleMap;
    
    139
    +  nsBaseHashtable<nsUint32HashKey, IDMappingEntry, Accessible*>
    
    140
    +      mIDToAccessibleMap;
    
    117 141
     };
    
    118 142
     
    
    119 143
     }  // namespace a11y
    

  • accessible/ipc/DocAccessibleParent.cpp
    ... ... @@ -29,7 +29,6 @@
    29 29
     #endif
    
    30 30
     
    
    31 31
     #if defined(ANDROID)
    
    32
    -#  include "mozilla/a11y/SessionAccessibility.h"
    
    33 32
     #  define ACQUIRE_ANDROID_LOCK \
    
    34 33
         MonitorAutoLock mal(nsAccessibilityService::GetAndroidMonitor());
    
    35 34
     #else
    

  • accessible/ipc/DocAccessibleParent.h
    ... ... @@ -29,10 +29,6 @@ class xpcAccessibleGeneric;
    29 29
     class DocAccessiblePlatformExtParent;
    
    30 30
     #endif
    
    31 31
     
    
    32
    -#ifdef ANDROID
    
    33
    -class SessionAccessibility;
    
    34
    -#endif
    
    35
    -
    
    36 32
     /*
    
    37 33
      * These objects live in the main process and comunicate with and represent
    
    38 34
      * an accessible document in a content process.
    
    ... ... @@ -348,10 +344,6 @@ class DocAccessibleParent : public RemoteAccessible,
    348 344
     
    
    349 345
       size_t SizeOfExcludingThis(MallocSizeOf aMallocSizeOf) override;
    
    350 346
     
    
    351
    -#ifdef ANDROID
    
    352
    -  RefPtr<SessionAccessibility> mSessionAccessibility;
    
    353
    -#endif
    
    354
    -
    
    355 347
      private:
    
    356 348
       ~DocAccessibleParent();
    
    357 349
     
    

  • accessible/ipc/moz.build
    ... ... @@ -24,11 +24,6 @@ else:
    24 24
             LOCAL_INCLUDES += [
    
    25 25
                 "/accessible/mac",
    
    26 26
             ]
    
    27
    -    elif CONFIG["MOZ_WIDGET_TOOLKIT"] == "android":
    
    28
    -        LOCAL_INCLUDES += [
    
    29
    -            "/accessible/android",
    
    30
    -            "/widget/android",
    
    31
    -        ]
    
    32 27
         else:
    
    33 28
             LOCAL_INCLUDES += [
    
    34 29
                 "/accessible/other",
    

  • browser/base/content/browser-fullScreenAndPointerLock.js
    ... ... @@ -62,9 +62,14 @@ var PointerlockFsWarning = {
    62 62
           this._element = document.getElementById(elementId);
    
    63 63
           // Setup event listeners
    
    64 64
           this._element.addEventListener("transitionend", this);
    
    65
    +      this._element.addEventListener("transitioncancel", this);
    
    65 66
           window.addEventListener("mousemove", this, true);
    
    67
    +      window.addEventListener("activate", this);
    
    68
    +      window.addEventListener("deactivate", this);
    
    66 69
           // The timeout to hide the warning box after a while.
    
    67 70
           this._timeoutHide = new this.Timeout(() => {
    
    71
    +        window.removeEventListener("activate", this);
    
    72
    +        window.removeEventListener("deactivate", this);
    
    68 73
             this._state = "hidden";
    
    69 74
           }, timeout);
    
    70 75
           // The timeout to show the warning box when the pointer is at the top
    
    ... ... @@ -116,11 +121,10 @@ var PointerlockFsWarning = {
    116 121
           return;
    
    117 122
         }
    
    118 123
     
    
    119
    -    // Explicitly set the last state to hidden to avoid the warning
    
    120
    -    // box being hidden immediately because of mousemove.
    
    121
    -    this._state = "onscreen";
    
    122
    -    this._lastState = "hidden";
    
    123
    -    this._timeoutHide.start();
    
    124
    +    if (Services.focus.activeWindow == window) {
    
    125
    +      this._state = "onscreen";
    
    126
    +      this._timeoutHide.start();
    
    127
    +    }
    
    124 128
       },
    
    125 129
     
    
    126 130
       /**
    
    ... ... @@ -148,7 +152,10 @@ var PointerlockFsWarning = {
    148 152
         this._element.hidden = true;
    
    149 153
         // Remove all event listeners
    
    150 154
         this._element.removeEventListener("transitionend", this);
    
    155
    +    this._element.removeEventListener("transitioncancel", this);
    
    151 156
         window.removeEventListener("mousemove", this, true);
    
    157
    +    window.removeEventListener("activate", this);
    
    158
    +    window.removeEventListener("deactivate", this);
    
    152 159
         // Clear fields
    
    153 160
         this._element = null;
    
    154 161
         this._timeoutHide = null;
    
    ... ... @@ -186,7 +193,7 @@ var PointerlockFsWarning = {
    186 193
         }
    
    187 194
         if (newState != "hidden") {
    
    188 195
           if (currentState != "hidden") {
    
    189
    -        this._element.setAttribute(newState, true);
    
    196
    +        this._element.setAttribute(newState, "");
    
    190 197
           } else {
    
    191 198
             // When the previous state is hidden, the display was none,
    
    192 199
             // thus no box was constructed. We need to wait for the new
    
    ... ... @@ -197,7 +204,7 @@ var PointerlockFsWarning = {
    197 204
             requestAnimationFrame(() => {
    
    198 205
               requestAnimationFrame(() => {
    
    199 206
                 if (this._element) {
    
    200
    -              this._element.setAttribute(newState, true);
    
    207
    +              this._element.setAttribute(newState, "");
    
    201 208
                 }
    
    202 209
               });
    
    203 210
             });
    
    ... ... @@ -217,7 +224,7 @@ var PointerlockFsWarning = {
    217 224
               } else if (this._timeoutShow.delay >= 0) {
    
    218 225
                 this._timeoutShow.start();
    
    219 226
               }
    
    220
    -        } else {
    
    227
    +        } else if (state != "onscreen") {
    
    221 228
               let elemRect = this._element.getBoundingClientRect();
    
    222 229
               if (state == "hiding" && this._lastState != "hidden") {
    
    223 230
                 // If we are on the hiding transition, and the pointer
    
    ... ... @@ -239,12 +246,23 @@ var PointerlockFsWarning = {
    239 246
             }
    
    240 247
             break;
    
    241 248
           }
    
    242
    -      case "transitionend": {
    
    249
    +      case "transitionend":
    
    250
    +      case "transitioncancel": {
    
    243 251
             if (this._state == "hiding") {
    
    244 252
               this._element.hidden = true;
    
    245 253
             }
    
    246 254
             break;
    
    247 255
           }
    
    256
    +      case "activate": {
    
    257
    +        this._state = "onscreen";
    
    258
    +        this._timeoutHide.start();
    
    259
    +        break;
    
    260
    +      }
    
    261
    +      case "deactivate": {
    
    262
    +        this._state = "hidden";
    
    263
    +        this._timeoutHide.cancel();
    
    264
    +        break;
    
    265
    +      }
    
    248 266
         }
    
    249 267
       },
    
    250 268
     };
    

  • browser/base/content/fullscreen-and-pointerlock.inc.xhtml
    ... ... @@ -3,7 +3,7 @@
    3 3
     # file, You can obtain one at http://mozilla.org/MPL/2.0/.
    
    4 4
     
    
    5 5
     <html:div id="fullscreen-and-pointerlock-wrapper">
    
    6
    -  <html:div id="fullscreen-warning" class="pointerlockfswarning" hidden="true">
    
    6
    +  <html:div id="fullscreen-warning" class="pointerlockfswarning" hidden="">
    
    7 7
         <html:div class="pointerlockfswarning-domain-text">
    
    8 8
           <html:span class="pointerlockfswarning-domain" data-l10n-name="domain"/>
    
    9 9
         </html:div>
    
    ... ... @@ -20,7 +20,7 @@
    20 20
         </html:button>
    
    21 21
       </html:div>
    
    22 22
     
    
    23
    -  <html:div id="pointerlock-warning" class="pointerlockfswarning" hidden="true">
    
    23
    +  <html:div id="pointerlock-warning" class="pointerlockfswarning" hidden="">
    
    24 24
         <html:div class="pointerlockfswarning-domain-text">
    
    25 25
           <html:span class="pointerlockfswarning-domain" data-l10n-name="domain"/>
    
    26 26
         </html:div>
    

  • browser/base/content/test/fullscreen/browser_fullscreen_warning.js
    ... ... @@ -3,14 +3,35 @@
    3 3
     
    
    4 4
     "use strict";
    
    5 5
     
    
    6
    -add_task(async function test_fullscreen_display_none() {
    
    6
    +function checkWarningState(aWarningElement, aExpectedState, aMsg) {
    
    7
    +  ["hidden", "ontop", "onscreen"].forEach(state => {
    
    8
    +    is(
    
    9
    +      aWarningElement.hasAttribute(state),
    
    10
    +      state == aExpectedState,
    
    11
    +      `${aMsg} - check ${state} attribute.`
    
    12
    +    );
    
    13
    +  });
    
    14
    +}
    
    15
    +
    
    16
    +async function waitForWarningState(aWarningElement, aExpectedState) {
    
    17
    +  await BrowserTestUtils.waitForAttribute(aExpectedState, aWarningElement, "");
    
    18
    +  checkWarningState(
    
    19
    +    aWarningElement,
    
    20
    +    aExpectedState,
    
    21
    +    `Wait for ${aExpectedState} state`
    
    22
    +  );
    
    23
    +}
    
    24
    +
    
    25
    +add_setup(async function init() {
    
    7 26
       await SpecialPowers.pushPrefEnv({
    
    8 27
         set: [
    
    9 28
           ["full-screen-api.enabled", true],
    
    10 29
           ["full-screen-api.allow-trusted-requests-only", false],
    
    11 30
         ],
    
    12 31
       });
    
    32
    +});
    
    13 33
     
    
    34
    +add_task(async function test_fullscreen_display_none() {
    
    14 35
       await BrowserTestUtils.withNewTab(
    
    15 36
         {
    
    16 37
           gBrowser,
    
    ... ... @@ -30,11 +51,13 @@ add_task(async function test_fullscreen_display_none() {
    30 51
         },
    
    31 52
         async function (browser) {
    
    32 53
           let warning = document.getElementById("fullscreen-warning");
    
    33
    -      let warningShownPromise = BrowserTestUtils.waitForAttribute(
    
    34
    -        "onscreen",
    
    54
    +      checkWarningState(
    
    35 55
             warning,
    
    36
    -        "true"
    
    56
    +        "hidden",
    
    57
    +        "Should not show full screen warning initially"
    
    37 58
           );
    
    59
    +
    
    60
    +      let warningShownPromise = waitForWarningState(warning, "onscreen");
    
    38 61
           // Enter fullscreen
    
    39 62
           await SpecialPowers.spawn(browser, [], async () => {
    
    40 63
             let frame = content.document.querySelector("iframe");
    
    ... ... @@ -54,39 +77,33 @@ add_task(async function test_fullscreen_display_none() {
    54 77
           );
    
    55 78
           document.getElementById("fullscreen-exit-button").click();
    
    56 79
           await exitFullscreenPromise;
    
    80
    +
    
    81
    +      checkWarningState(
    
    82
    +        warning,
    
    83
    +        "hidden",
    
    84
    +        "Should hide fullscreen warning after exiting fullscreen"
    
    85
    +      );
    
    57 86
         }
    
    58 87
       );
    
    59 88
     });
    
    60 89
     
    
    61 90
     add_task(async function test_fullscreen_pointerlock_conflict() {
    
    62
    -  await SpecialPowers.pushPrefEnv({
    
    63
    -    set: [
    
    64
    -      ["full-screen-api.enabled", true],
    
    65
    -      ["full-screen-api.allow-trusted-requests-only", false],
    
    66
    -    ],
    
    67
    -  });
    
    68
    -
    
    69 91
       await BrowserTestUtils.withNewTab("https://example.com", async browser => {
    
    70 92
         let fsWarning = document.getElementById("fullscreen-warning");
    
    71 93
         let plWarning = document.getElementById("pointerlock-warning");
    
    72 94
     
    
    73
    -    is(
    
    74
    -      fsWarning.getAttribute("onscreen"),
    
    75
    -      null,
    
    76
    -      "Should not show full screen warning initially."
    
    77
    -    );
    
    78
    -    is(
    
    79
    -      plWarning.getAttribute("onscreen"),
    
    80
    -      null,
    
    81
    -      "Should not show pointer lock warning initially."
    
    82
    -    );
    
    83
    -
    
    84
    -    let fsWarningShownPromise = BrowserTestUtils.waitForAttribute(
    
    85
    -      "onscreen",
    
    95
    +    checkWarningState(
    
    86 96
           fsWarning,
    
    87
    -      "true"
    
    97
    +      "hidden",
    
    98
    +      "Should not show full screen warning initially"
    
    99
    +    );
    
    100
    +    checkWarningState(
    
    101
    +      plWarning,
    
    102
    +      "hidden",
    
    103
    +      "Should not show pointer lock warning initially"
    
    88 104
         );
    
    89 105
     
    
    106
    +    let fsWarningShownPromise = waitForWarningState(fsWarning, "onscreen");
    
    90 107
         info("Entering full screen and pointer lock.");
    
    91 108
         await SpecialPowers.spawn(browser, [], async () => {
    
    92 109
           await content.document.body.requestFullscreen();
    
    ... ... @@ -94,15 +111,10 @@ add_task(async function test_fullscreen_pointerlock_conflict() {
    94 111
         });
    
    95 112
     
    
    96 113
         await fsWarningShownPromise;
    
    97
    -    is(
    
    98
    -      fsWarning.getAttribute("onscreen"),
    
    99
    -      "true",
    
    100
    -      "Should show full screen warning."
    
    101
    -    );
    
    102
    -    is(
    
    103
    -      plWarning.getAttribute("onscreen"),
    
    104
    -      null,
    
    105
    -      "Should not show pointer lock warning."
    
    114
    +    checkWarningState(
    
    115
    +      plWarning,
    
    116
    +      "hidden",
    
    117
    +      "Should not show pointer lock warning"
    
    106 118
         );
    
    107 119
     
    
    108 120
         info("Exiting pointerlock");
    
    ... ... @@ -110,18 +122,19 @@ add_task(async function test_fullscreen_pointerlock_conflict() {
    110 122
           await content.document.exitPointerLock();
    
    111 123
         });
    
    112 124
     
    
    113
    -    is(
    
    114
    -      fsWarning.getAttribute("onscreen"),
    
    115
    -      "true",
    
    116
    -      "Should still show full screen warning."
    
    125
    +    checkWarningState(
    
    126
    +      fsWarning,
    
    127
    +      "onscreen",
    
    128
    +      "Should still show full screen warning"
    
    117 129
         );
    
    118
    -    is(
    
    119
    -      plWarning.getAttribute("onscreen"),
    
    120
    -      null,
    
    121
    -      "Should not show pointer lock warning."
    
    130
    +    checkWarningState(
    
    131
    +      plWarning,
    
    132
    +      "hidden",
    
    133
    +      "Should not show pointer lock warning"
    
    122 134
         );
    
    123 135
     
    
    124 136
         // Cleanup
    
    137
    +    info("Exiting fullscreen");
    
    125 138
         await document.exitFullscreen();
    
    126 139
       });
    
    127 140
     });

  • dom/tests/browser/browser_pointerlock_warning.js
    ... ... @@ -15,6 +15,25 @@ const FRAME_TEST_URL =
    15 15
       encodeURI(BODY_URL) +
    
    16 16
       '"></iframe></body>';
    
    17 17
     
    
    18
    +function checkWarningState(aWarningElement, aExpectedState, aMsg) {
    
    19
    +  ["hidden", "ontop", "onscreen"].forEach(state => {
    
    20
    +    is(
    
    21
    +      aWarningElement.hasAttribute(state),
    
    22
    +      state == aExpectedState,
    
    23
    +      `${aMsg} - check ${state} attribute.`
    
    24
    +    );
    
    25
    +  });
    
    26
    +}
    
    27
    +
    
    28
    +async function waitForWarningState(aWarningElement, aExpectedState) {
    
    29
    +  await BrowserTestUtils.waitForAttribute(aExpectedState, aWarningElement, "");
    
    30
    +  checkWarningState(
    
    31
    +    aWarningElement,
    
    32
    +    aExpectedState,
    
    33
    +    `Wait for ${aExpectedState} state`
    
    34
    +  );
    
    35
    +}
    
    36
    +
    
    18 37
     // Make sure the pointerlock warning is shown and exited with the escape key
    
    19 38
     add_task(async function show_pointerlock_warning_escape() {
    
    20 39
       let urls = [TEST_URL, FRAME_TEST_URL];
    
    ... ... @@ -24,11 +43,7 @@ add_task(async function show_pointerlock_warning_escape() {
    24 43
         let tab = await BrowserTestUtils.openNewForegroundTab(gBrowser, url);
    
    25 44
     
    
    26 45
         let warning = document.getElementById("pointerlock-warning");
    
    27
    -    let warningShownPromise = BrowserTestUtils.waitForAttribute(
    
    28
    -      "onscreen",
    
    29
    -      warning,
    
    30
    -      "true"
    
    31
    -    );
    
    46
    +    let warningShownPromise = waitForWarningState(warning, "onscreen");
    
    32 47
     
    
    33 48
         let expectedWarningText;
    
    34 49
     
    
    ... ... @@ -49,11 +64,7 @@ add_task(async function show_pointerlock_warning_escape() {
    49 64
     
    
    50 65
         ok(true, "Pointerlock warning shown");
    
    51 66
     
    
    52
    -    let warningHiddenPromise = BrowserTestUtils.waitForAttribute(
    
    53
    -      "hidden",
    
    54
    -      warning,
    
    55
    -      ""
    
    56
    -    );
    
    67
    +    let warningHiddenPromise = waitForWarningState(warning, "hidden");
    
    57 68
     
    
    58 69
         await BrowserTestUtils.waitForCondition(
    
    59 70
           () => warning.innerText == expectedWarningText,
    

  • js/src/gc/GC.cpp
    ... ... @@ -1331,6 +1331,11 @@ void GCRuntime::assertNoMarkingWork() const {
    1331 1331
     }
    
    1332 1332
     #endif
    
    1333 1333
     
    
    1334
    +static size_t GetGCParallelThreadCount() {
    
    1335
    +  AutoLockHelperThreadState lock;
    
    1336
    +  return HelperThreadState().getGCParallelThreadCount(lock);
    
    1337
    +}
    
    1338
    +
    
    1334 1339
     bool GCRuntime::updateMarkersVector() {
    
    1335 1340
       MOZ_ASSERT(helperThreadCount >= 1,
    
    1336 1341
                  "There must always be at least one mark task");
    
    ... ... @@ -1339,8 +1344,8 @@ bool GCRuntime::updateMarkersVector() {
    1339 1344
     
    
    1340 1345
       // Limit worker count to number of GC parallel tasks that can run
    
    1341 1346
       // concurrently, otherwise one thread can deadlock waiting on another.
    
    1342
    -  size_t targetCount = std::min(markingWorkerCount(),
    
    1343
    -                                HelperThreadState().getGCParallelThreadCount());
    
    1347
    +  size_t targetCount =
    
    1348
    +      std::min(markingWorkerCount(), GetGCParallelThreadCount());
    
    1344 1349
     
    
    1345 1350
       if (markers.length() > targetCount) {
    
    1346 1351
         return markers.resize(targetCount);
    

  • js/src/gc/ParallelMarking.cpp
    ... ... @@ -103,6 +103,10 @@ bool ParallelMarker::markOneColor(MarkColor color, SliceBudget& sliceBudget) {
    103 103
       {
    
    104 104
         AutoLockHelperThreadState lock;
    
    105 105
     
    
    106
    +    // There should always be enough parallel tasks to run our marking work.
    
    107
    +    MOZ_RELEASE_ASSERT(HelperThreadState().getGCParallelThreadCount(lock) >=
    
    108
    +                       workerCount());
    
    109
    +
    
    106 110
         for (size_t i = 0; i < workerCount(); i++) {
    
    107 111
           gc->startTask(*tasks[i], lock);
    
    108 112
         }
    

  • js/src/vm/HelperThreadState.h
    ... ... @@ -333,9 +333,11 @@ class GlobalHelperThreadState {
    333 333
     
    
    334 334
       GCParallelTaskList& gcParallelWorklist() { return gcParallelWorklist_; }
    
    335 335
     
    
    336
    -  size_t getGCParallelThreadCount() const { return gcParallelThreadCount; }
    
    336
    +  size_t getGCParallelThreadCount(const AutoLockHelperThreadState& lock) const {
    
    337
    +    return gcParallelThreadCount;
    
    338
    +  }
    
    337 339
       void setGCParallelThreadCount(size_t count,
    
    338
    -                                const AutoLockHelperThreadState&) {
    
    340
    +                                const AutoLockHelperThreadState& lock) {
    
    339 341
         MOZ_ASSERT(count >= 1);
    
    340 342
         MOZ_ASSERT(count <= threadCount);
    
    341 343
         gcParallelThreadCount = count;