[Author Prev][Author Next][Thread Prev][Thread Next][Author Index][Thread Index]

[tor-commits] [Git][tpo/applications/tor-browser][tor-browser-153.2.0esr-16.0-1] 5 commits: Bug 2045435 - Prune dying entries from wasm::Realm::instances_ during sweeping. r=jpages



Title: GitLab

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

Commits:

  • 3e75dcee
    by Yury Delendik at 2026-09-01T16:47:31+02:00
    Bug 2045435 - Prune dying entries from wasm::Realm::instances_ during sweeping. r=jpages
    
    wasm::Realm::instances_ is a weak list. Readers rely on the
    instances()[i]->object() read barrier, but that barrier is a no-op once the
    owning zone is being incrementally swept, and entries are otherwise only
    removed at Instance finalization (~Instance -> unregisterInstance). So between
    marking a zone's instance objects dead and finalizing them, the list could
    still hand an about-to-be-finalized instance to a reader.
    
    Prune such entries at the start of zone sweeping via a new
    wasm::Realm::traceWeakInstances(), called from beginSweepingSweepGroup
    alongside the other per-realm weak-collection sweeps. This makes instances_
    behave like the engine's other weak collections, so it never exposes an
    about-to-be-finalized instance to the mutator during sweep slices.
    
    Differential Revision: https://phabricator.services.mozilla.com/D314032
    
  • 3c493b1e
    by Ting-Yu Lin at 2026-09-01T16:47:32+02:00
    Bug 2053578 - Use static_cast in nsSplittableFrame::UpdateFirstContinuationAndFirstInFlowCache(). r=layout-reviewers,jfkthame
    
    `nsSplittableFrame` is a subclass of `nsIFrame`, it is sufficient to use
    `static_cast`.
    
    Differential Revision: https://phabricator.services.mozilla.com/D315157
    
  • a6141d0a
    by Ting-Yu Lin at 2026-09-01T16:47:32+02:00
    Bug 2053578 - Update first-in-flow cache when a continuation is changing from fluid to non-fluid. r=layout-reviewers,jfkthame
    
    The original case in bug 2053578 comment 5 can reproduce an ASAN
    use-after-poison with the patch bug 2053578 comment 6 applied. However, with
    unpatched code, the best we can do is using a DEBUG-only assertion to catch the
    error condition that detect a stale first-in-flow cache in next-in-flow.
    
    `bidi-inline-continuation-first-in-flow.html` is generated with the help of
    Claude code, and it can trigger the assertion without other fix in this patch.
    
    Differential Revision: https://phabricator.services.mozilla.com/D315158
    
  • 23f5704c
    by Iain Ireland at 2026-09-01T16:47:33+02:00
    Bug 2058626: Check for mutually exclusive flags when deserializing cloned RegExp r=spidermonkey-reviewers,jonco
    
    Differential Revision: https://phabricator.services.mozilla.com/D316904
    
  • b781a92b
    by Gela at 2026-09-01T16:47:34+02:00
    Bug 2053320 - Part 1: Don't tie Nimbus tooling to `HomeActivity` UI  a=RyanVM
    
    Original Revision: https://phabricator.services.mozilla.com/D319628
    
    Differential Revision: https://phabricator.services.mozilla.com/D320784
    

12 changed files:

Changes:

  • js/src/gc/GCRuntime.h
    ... ... @@ -999,6 +999,7 @@ class GCRuntime {
    999 999
       void updateAtomsBitmap();
    
    1000 1000
       void sweepCCWrappers();
    
    1001 1001
       void sweepRealmGlobals();
    
    1002
    +  void sweepWasmInstances();
    
    1002 1003
       void sweepEmbeddingWeakPointers(JS::GCContext* gcx);
    
    1003 1004
       void sweepMisc();
    
    1004 1005
       void sweepCompressionTasks();
    

  • js/src/gc/Sweeping.cpp
    ... ... @@ -1387,6 +1387,13 @@ void GCRuntime::sweepRealmGlobals() {
    1387 1387
       }
    
    1388 1388
     }
    
    1389 1389
     
    
    1390
    +void GCRuntime::sweepWasmInstances() {
    
    1391
    +  for (SweepGroupRealmsIter r(this); !r.done(); r.next()) {
    
    1392
    +    AutoSetThreadIsSweeping threadIsSweeping(r->zone());
    
    1393
    +    r->wasm.traceWeakInstances();
    
    1394
    +  }
    
    1395
    +}
    
    1396
    +
    
    1390 1397
     void GCRuntime::sweepMisc() {
    
    1391 1398
       SweepingTracer trc(rt);
    
    1392 1399
       for (SweepGroupRealmsIter r(this); !r.done(); r.next()) {
    
    ... ... @@ -1743,6 +1750,11 @@ IncrementalProgress GCRuntime::beginSweepingSweepGroup(JS::GCContext* gcx,
    1743 1750
       // This must happen before updating embedding weak pointers.
    
    1744 1751
       sweepRealmGlobals();
    
    1745 1752
     
    
    1753
    +  // Prune dying wasm instances from each realm's weak instance list now, at the
    
    1754
    +  // start of sweeping, before the mutator can observe them via the (now no-op)
    
    1755
    +  // instances() read barrier during later incremental slices.
    
    1756
    +  sweepWasmInstances();
    
    1757
    +
    
    1746 1758
       sweepEmbeddingWeakPointers(gcx);
    
    1747 1759
     
    
    1748 1760
       maybeWriteCoverageAndSpew();
    

  • js/src/jit-test/tests/structured-clone/bug2058626.js
    1
    +function forge(pattern, srcFlags, flagsByte) {
    
    2
    +  var cb = serialize(new RegExp(pattern, srcFlags), undefined, { scope: "DifferentProcess" });
    
    3
    +  var u8 = new Uint8Array(cb.arraybuffer);
    
    4
    +  for (var i = 0; i + 8 <= u8.length; i += 4) {
    
    5
    +    var tag = u8[i+4] | (u8[i+5] << 8) | (u8[i+6] << 16) | (u8[i+7] << 24);
    
    6
    +    if ((tag >>> 0) === 0xFFFF0006) { u8[i] = flagsByte; break; }
    
    7
    +  }
    
    8
    +  cb.clonebuffer = u8.buffer;
    
    9
    +  return deserialize(cb, { scope: "DifferentProcess" });
    
    10
    +}
    
    11
    +try {
    
    12
    +  var forged = forge("[\\q{abc|de}]", "v", 0x90);
    
    13
    +  var bad = new RegExp(forged, "u");
    
    14
    +  try { bad.exec("abc"); } catch {}
    
    15
    +  var good = new RegExp("[\\q{abc|de}]", "u");
    
    16
    +} catch {}

  • js/src/vm/StructuredClone.cpp
    ... ... @@ -3234,7 +3234,9 @@ bool JSStructuredCloneReader::startReadUnchecked(
    3234 3234
         }
    
    3235 3235
     
    
    3236 3236
         case SCTAG_REGEXP_OBJECT: {
    
    3237
    -      if ((data & RegExpFlag::AllFlags) != data) {
    
    3237
    +      // Reject invalid flags. /u and /v are mutually exclusive.
    
    3238
    +      if ((data & RegExpFlag::AllFlags) != data ||
    
    3239
    +          ((data & RegExpFlag::Unicode) && (data & RegExpFlag::UnicodeSets))) {
    
    3238 3240
             JS_ReportErrorNumberASCII(context(), GetErrorMessage, nullptr,
    
    3239 3241
                                       JSMSG_SC_BAD_SERIALIZED_DATA, "regexp");
    
    3240 3242
             return false;
    

  • js/src/wasm/WasmRealm.cpp
    ... ... @@ -16,6 +16,7 @@
    16 16
     
    
    17 17
     #include "wasm/WasmRealm.h"
    
    18 18
     
    
    19
    +#include "gc/Marking.h"
    
    19 20
     #include "vm/GlobalObject.h"
    
    20 21
     #include "vm/Realm.h"
    
    21 22
     #include "wasm/WasmDebug.h"
    
    ... ... @@ -111,6 +112,19 @@ void wasm::Realm::unregisterInstance(Instance& instance) {
    111 112
       }
    
    112 113
     }
    
    113 114
     
    
    115
    +void wasm::Realm::traceWeakInstances() {
    
    116
    +  // Registration/unregistration of instances_ is tied to Instance lifetime, so
    
    117
    +  // an instance whose owning object is about to be finalized is still present
    
    118
    +  // here until ~Instance runs. Remove such entries now, at the start of zone
    
    119
    +  // sweeping, because the instances() read barrier that otherwise protects
    
    120
    +  // readers is a no-op once the zone is being swept. erase order is preserved,
    
    121
    +  // so the pointer-sorted invariant used by BinarySearchIf holds.
    
    122
    +  instances_.eraseIf([](Instance* instance) {
    
    123
    +    return js::gc::IsAboutToBeFinalizedUnbarriered(
    
    124
    +        instance->objectUnbarriered());
    
    125
    +  });
    
    126
    +}
    
    127
    +
    
    114 128
     void wasm::Realm::ensureProfilingLabels(bool profilingEnabled) {
    
    115 129
       for (Instance* instance : instances_) {
    
    116 130
         instance->ensureProfilingLabels(profilingEnabled);
    

  • js/src/wasm/WasmRealm.h
    ... ... @@ -51,10 +51,17 @@ class Realm {
    51 51
       // Return a vector of all live instances in the realm. The lifetime of
    
    52 52
       // these Instances is determined by their owning WasmInstanceObject.
    
    53 53
       // Note that accessing instances()[i]->object() triggers a read barrier
    
    54
    -  // since instances() is effectively a weak list.
    
    54
    +  // since instances() is effectively a weak list. This read barrier is only
    
    55
    +  // effective while the owning zone is being marked; traceWeakInstances()
    
    56
    +  // prunes dying entries at the start of sweeping so that the list never
    
    57
    +  // exposes an about-to-be-finalized instance to the mutator.
    
    55 58
     
    
    56 59
       const InstanceVector& instances() const { return instances_; }
    
    57 60
     
    
    61
    +  // Remove instances whose owning object is about to be finalized. Called at
    
    62
    +  // the start of zone sweeping, when the instances() read barrier is a no-op.
    
    63
    +  void traceWeakInstances();
    
    64
    +
    
    58 65
       // Ensure all Instances in this Realm have profiling labels created.
    
    59 66
     
    
    60 67
       void ensureProfilingLabels(bool profilingEnabled);
    

  • layout/generic/nsSplittableFrame.cpp
    ... ... @@ -9,6 +9,7 @@
    9 9
     
    
    10 10
     #include "nsSplittableFrame.h"
    
    11 11
     
    
    12
    +#include "mozilla/DebugOnly.h"
    
    12 13
     #include "mozilla/ReflowInput.h"
    
    13 14
     #include "nsContainerFrame.h"
    
    14 15
     #include "nsFieldSetFrame.h"
    
    ... ... @@ -214,7 +215,7 @@ void nsSplittableFrame::UpdateFirstContinuationAndFirstInFlowCache() {
    214 215
         if (oldCachedFirstContinuation != newFirstContinuation) {
    
    215 216
           // Update the first-continuation cache for us and our next-continuations.
    
    216 217
           for (nsSplittableFrame* f = this; f;
    
    217
    -           f = reinterpret_cast<nsSplittableFrame*>(f->GetNextContinuation())) {
    
    218
    +           f = static_cast<nsSplittableFrame*>(f->GetNextContinuation())) {
    
    218 219
             f->mFirstContinuation = newFirstContinuation;
    
    219 220
           }
    
    220 221
         }
    
    ... ... @@ -227,7 +228,7 @@ void nsSplittableFrame::UpdateFirstContinuationAndFirstInFlowCache() {
    227 228
           // behavior when a frame list is destroyed from the front. To avoid that
    
    228 229
           // pathological behavior, we simply purge the cached values.
    
    229 230
           for (nsSplittableFrame* f = this; f;
    
    230
    -           f = reinterpret_cast<nsSplittableFrame*>(f->GetNextContinuation())) {
    
    231
    +           f = static_cast<nsSplittableFrame*>(f->GetNextContinuation())) {
    
    231 232
             f->mFirstContinuation = nullptr;
    
    232 233
           }
    
    233 234
         }
    
    ... ... @@ -239,22 +240,41 @@ void nsSplittableFrame::UpdateFirstContinuationAndFirstInFlowCache() {
    239 240
         if (oldCachedFirstInFlow != newFirstInFlow) {
    
    240 241
           // Update the first-in-flow cache for us and our next-in-flows.
    
    241 242
           for (nsSplittableFrame* f = this; f;
    
    242
    -           f = reinterpret_cast<nsSplittableFrame*>(f->GetNextInFlow())) {
    
    243
    +           f = static_cast<nsSplittableFrame*>(f->GetNextInFlow())) {
    
    243 244
             f->mFirstInFlow = newFirstInFlow;
    
    244 245
           }
    
    245 246
         }
    
    246 247
       } else {
    
    247
    -    // We become the new first-in-flow due to our prev-in-flow being removed.
    
    248
    -    if (oldCachedFirstInFlow) {
    
    249
    -      // It's tempting to update the first-in-flow cache for our
    
    250
    -      // next-in-flows here, but that would result in overall O(n^2)
    
    251
    -      // behavior when a frame list is destroyed from the front. To avoid that
    
    252
    -      // pathological behavior, we simply purge the cached values.
    
    248
    +    if (GetPrevContinuation()) {
    
    249
    +      // We become the new first-in-flow after changing from fluid to non-fluid.
    
    250
    +      // Update the stale first-in-flow cache for us and all next-in-flows.
    
    251
    +      //
    
    252
    +      // Note that this has no counterpart in the above mFirstContinuation cache
    
    253
    +      // since GetPrevContinuation() does not depend on the
    
    254
    +      // NS_FRAME_IS_FLUID_CONTINUATION bit.
    
    253 255
           for (nsSplittableFrame* f = this; f;
    
    254
    -           f = reinterpret_cast<nsSplittableFrame*>(f->GetNextInFlow())) {
    
    255
    -        f->mFirstInFlow = nullptr;
    
    256
    +           f = static_cast<nsSplittableFrame*>(f->GetNextInFlow())) {
    
    257
    +        f->mFirstInFlow = this;
    
    258
    +      }
    
    259
    +    } else {
    
    260
    +      // We become the new first-in-flow due to our prev-in-flow being removed.
    
    261
    +      if (oldCachedFirstInFlow) {
    
    262
    +        // It's tempting to update the first-in-flow cache for our
    
    263
    +        // next-in-flows here, but that would result in overall O(n^2)
    
    264
    +        // behavior when a frame list is destroyed from the front. To avoid that
    
    265
    +        // pathological behavior, we simply purge the cached values.
    
    266
    +        for (nsSplittableFrame* f = this; f;
    
    267
    +             f = static_cast<nsSplittableFrame*>(f->GetNextInFlow())) {
    
    268
    +          f->mFirstInFlow = nullptr;
    
    269
    +        }
    
    256 270
           }
    
    257 271
         }
    
    272
    +
    
    273
    +    DebugOnly<nsSplittableFrame*> nextInFlow =
    
    274
    +        static_cast<nsSplittableFrame*>(GetNextInFlow());
    
    275
    +    MOZ_ASSERT(!nextInFlow || !nextInFlow->mFirstInFlow ||
    
    276
    +                   nextInFlow->mFirstInFlow == this,
    
    277
    +               "Our next-in-flow caches a stale first-in-flow!");
    
    258 278
       }
    
    259 279
     }
    
    260 280
     
    

  • mobile/android/fenix/app/src/main/AndroidManifest.xml
    ... ... @@ -820,6 +820,16 @@
    820 820
                 <action android:name="org.mozilla.fenix.TRIGGER_MESSAGE_WORKER" />
    
    821 821
               </intent-filter>
    
    822 822
             </receiver>
    
    823
    +
    
    824
    +        <receiver
    
    825
    +          android:name="org.mozilla.fenix.experiments.QANimbusToolingReceiver"
    
    826
    +          android:exported="true"
    
    827
    +          android:enabled="true"
    
    828
    +          android:permission="android.permission.DUMP">
    
    829
    +          <intent-filter>
    
    830
    +            <action android:name="org.mozilla.fenix.NIMBUS_TOOLING" />
    
    831
    +          </intent-filter>
    
    832
    +        </receiver>
    
    823 833
         </application>
    
    824 834
     
    
    825 835
     </manifest>

  • mobile/android/fenix/app/src/main/java/org/mozilla/fenix/HomeActivity.kt
    ... ... @@ -99,7 +99,6 @@ import mozilla.components.support.utils.toSafeIntent
    99 99
     import mozilla.components.support.webextensions.WebExtensionOptionsPageObserver
    
    100 100
     import mozilla.components.support.webextensions.WebExtensionPopupObserver
    
    101 101
     import mozilla.telemetry.glean.private.NoExtras
    
    102
    -import org.mozilla.experiments.nimbus.initializeTooling
    
    103 102
     import org.mozilla.fenix.GleanMetrics.AppIcon
    
    104 103
     import org.mozilla.fenix.GleanMetrics.Events
    
    105 104
     import org.mozilla.fenix.GleanMetrics.Metrics
    
    ... ... @@ -463,9 +462,6 @@ open class HomeActivity : LocaleAwareAppCompatActivity(), NavHostActivity, Crash
    463 462
                     }
    
    464 463
                 }
    
    465 464
             }
    
    466
    -
    
    467
    -        // Setup nimbus-cli tooling. This is a NOOP when launching normally.
    
    468
    -        components.nimbus.sdk.initializeTooling(applicationContext, intent)
    
    469 465
             components.strictMode.attachListenerToDisablePenaltyDeath(supportFragmentManager)
    
    470 466
             MarkersFragmentLifecycleCallbacks.register(supportFragmentManager, components.core.engine)
    
    471 467
     
    

  • mobile/android/fenix/app/src/main/java/org/mozilla/fenix/experiments/QANimbusToolingReceiver.kt
    1
    +/* This Source Code Form is subject to the terms of the Mozilla Public
    
    2
    + * License, v. 2.0. If a copy of the MPL was not distributed with this
    
    3
    + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
    
    4
    +
    
    5
    +package org.mozilla.fenix.experiments
    
    6
    +
    
    7
    +import android.content.BroadcastReceiver
    
    8
    +import android.content.Context
    
    9
    +import android.content.Intent
    
    10
    +import kotlinx.coroutines.CoroutineDispatcher
    
    11
    +import kotlinx.coroutines.CoroutineScope
    
    12
    +import kotlinx.coroutines.Dispatchers
    
    13
    +import kotlinx.coroutines.launch
    
    14
    +import mozilla.components.support.base.log.logger.Logger
    
    15
    +import org.mozilla.experiments.nimbus.initializeTooling
    
    16
    +import org.mozilla.fenix.ext.components
    
    17
    +
    
    18
    +private val logger = Logger("QANimbusToolingReceiver")
    
    19
    +
    
    20
    +/**
    
    21
    + * Receiver triggered on demand via `nimbus-cli` to manually enroll into Nimbus experiments.
    
    22
    + *
    
    23
    + * ```
    
    24
    + *   adb shell am broadcast -a org.mozilla.fenix.NIMBUS_TOOLING \
    
    25
    + *       -p org.mozilla.fenix
    
    26
    + * ```
    
    27
    + *
    
    28
    + * `-p org.mozilla.fenix` is the package name, so adjust that value for release/beta/nightly/debug.
    
    29
    + *
    
    30
    + * @param dispatcher the [CoroutineDispatcher] the tooling commands are applied on.
    
    31
    + */
    
    32
    +class QANimbusToolingReceiver(private val dispatcher: CoroutineDispatcher = Dispatchers.IO) : BroadcastReceiver() {
    
    33
    +    override fun onReceive(context: Context, intent: Intent) {
    
    34
    +        if (intent.action != ACTION_NIMBUS_TOOLING) return
    
    35
    +
    
    36
    +        logger.info("Enqueueing QANimbusToolingReceiver via debug trigger")
    
    37
    +
    
    38
    +        val applicationContext = context.applicationContext
    
    39
    +
    
    40
    +        val pendingResult: PendingResult? = goAsync()
    
    41
    +        CoroutineScope(dispatcher).launch {
    
    42
    +            try {
    
    43
    +                applicationContext.components.nimbus.sdk.initializeTooling(
    
    44
    +                    applicationContext,
    
    45
    +                    intent,
    
    46
    +                )
    
    47
    +            } finally {
    
    48
    +                logger.info("Nimbus tooling command processed")
    
    49
    +                pendingResult?.finish()
    
    50
    +            }
    
    51
    +        }
    
    52
    +    }
    
    53
    +
    
    54
    +    companion object {
    
    55
    +        const val ACTION_NIMBUS_TOOLING = "org.mozilla.fenix.NIMBUS_TOOLING"
    
    56
    +    }
    
    57
    +}

  • mobile/android/fenix/app/src/test/java/org/mozilla/fenix/experiments/QANimbusToolingReceiverTest.kt
    1
    +/* This Source Code Form is subject to the terms of the Mozilla Public
    
    2
    + * License, v. 2.0. If a copy of the MPL was not distributed with this
    
    3
    + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
    
    4
    +
    
    5
    +package org.mozilla.fenix.experiments
    
    6
    +
    
    7
    +import android.content.Context
    
    8
    +import android.content.Intent
    
    9
    +import io.mockk.every
    
    10
    +import kotlinx.coroutines.ExperimentalCoroutinesApi
    
    11
    +import kotlinx.coroutines.Job
    
    12
    +import kotlinx.coroutines.test.UnconfinedTestDispatcher
    
    13
    +import mozilla.components.support.test.robolectric.testContext
    
    14
    +import org.junit.Assert.assertEquals
    
    15
    +import org.junit.Assert.assertFalse
    
    16
    +import org.junit.Assert.assertNull
    
    17
    +import org.junit.Assert.assertTrue
    
    18
    +import org.junit.Before
    
    19
    +import org.junit.Test
    
    20
    +import org.junit.runner.RunWith
    
    21
    +import org.mozilla.fenix.experiments.QANimbusToolingReceiver.Companion.ACTION_NIMBUS_TOOLING
    
    22
    +import org.mozilla.fenix.ext.components
    
    23
    +import org.mozilla.fenix.nimbus.TestNimbusApi
    
    24
    +import org.robolectric.RobolectricTestRunner
    
    25
    +
    
    26
    +@OptIn(ExperimentalCoroutinesApi::class)
    
    27
    +@RunWith(RobolectricTestRunner::class)
    
    28
    +class QANimbusToolingReceiverTest {
    
    29
    +
    
    30
    +    private val nimbusApi = FakeNimbusApi(testContext)
    
    31
    +    private val receiver = QANimbusToolingReceiver(UnconfinedTestDispatcher())
    
    32
    +
    
    33
    +    @Before
    
    34
    +    fun setUp() {
    
    35
    +        every { testContext.components.nimbus.sdk } returns nimbusApi
    
    36
    +    }
    
    37
    +
    
    38
    +    @Test
    
    39
    +    fun `GIVEN a tooling command WHEN the tooling action is received THEN the command is applied`() {
    
    40
    +        receiver.onReceive(testContext, toolingIntent(ACTION_NIMBUS_TOOLING))
    
    41
    +
    
    42
    +        assertEquals(EXPERIMENTS, nimbusApi.appliedExperiments)
    
    43
    +        assertEquals(false, nimbusApi.fetchEnabled)
    
    44
    +        assertTrue(nimbusApi.databaseReset)
    
    45
    +        assertTrue(nimbusApi.stateDumped)
    
    46
    +    }
    
    47
    +
    
    48
    +    @Test
    
    49
    +    fun `GIVEN a tooling command WHEN another action is received THEN the command is ignored`() {
    
    50
    +        receiver.onReceive(testContext, toolingIntent("org.mozilla.fenix.ACTION_PRINT"))
    
    51
    +
    
    52
    +        assertNull(nimbusApi.appliedExperiments)
    
    53
    +        assertNull(nimbusApi.fetchEnabled)
    
    54
    +        assertFalse(nimbusApi.databaseReset)
    
    55
    +        assertFalse(nimbusApi.stateDumped)
    
    56
    +    }
    
    57
    +
    
    58
    +    @Test
    
    59
    +    fun `GIVEN no tooling command WHEN the tooling action is received THEN nothing is applied`() {
    
    60
    +        receiver.onReceive(testContext, Intent(ACTION_NIMBUS_TOOLING))
    
    61
    +
    
    62
    +        assertNull(nimbusApi.appliedExperiments)
    
    63
    +        assertNull(nimbusApi.fetchEnabled)
    
    64
    +        assertFalse(nimbusApi.databaseReset)
    
    65
    +        assertFalse(nimbusApi.stateDumped)
    
    66
    +    }
    
    67
    +
    
    68
    +    @Test
    
    69
    +    fun `GIVEN a tooling command without the version extra WHEN the tooling action is received THEN nothing is applied`() {
    
    70
    +        val intent = toolingIntent(ACTION_NIMBUS_TOOLING).apply { removeExtra("version") }
    
    71
    +
    
    72
    +        receiver.onReceive(testContext, intent)
    
    73
    +
    
    74
    +        assertNull(nimbusApi.appliedExperiments)
    
    75
    +        assertFalse(nimbusApi.stateDumped)
    
    76
    +    }
    
    77
    +
    
    78
    +    private fun toolingIntent(action: String) =
    
    79
    +        Intent(action).apply {
    
    80
    +            putExtra("nimbus-cli", null as String?)
    
    81
    +            putExtra("version", 1)
    
    82
    +            putExtra("experiments", EXPERIMENTS)
    
    83
    +            putExtra("reset-db", true)
    
    84
    +            putExtra("log-state", true)
    
    85
    +        }
    
    86
    +
    
    87
    +    private class FakeNimbusApi(context: Context) : TestNimbusApi(context) {
    
    88
    +        var appliedExperiments: String? = null
    
    89
    +        var fetchEnabled: Boolean? = null
    
    90
    +        var databaseReset = false
    
    91
    +        var stateDumped = false
    
    92
    +
    
    93
    +        override fun applyLocalExperiments(experimentsJson: String): Job {
    
    94
    +            appliedExperiments = experimentsJson
    
    95
    +            return completedJob()
    
    96
    +        }
    
    97
    +
    
    98
    +        override fun resetEnrollmentsDatabase(): Job {
    
    99
    +            databaseReset = true
    
    100
    +            return completedJob()
    
    101
    +        }
    
    102
    +
    
    103
    +        override fun setFetchEnabled(enabled: Boolean) {
    
    104
    +            fetchEnabled = enabled
    
    105
    +        }
    
    106
    +
    
    107
    +        override fun dumpStateToLog() {
    
    108
    +            stateDumped = true
    
    109
    +        }
    
    110
    +
    
    111
    +        private fun completedJob() = Job().apply { complete() }
    
    112
    +    }
    
    113
    +
    
    114
    +    companion object {
    
    115
    +        private const val EXPERIMENTS = """{"data":[]}"""
    
    116
    +    }
    
    117
    +}

  • testing/web-platform/tests/css/css-writing-modes/crashtests/bidi-inline-continuation-first-in-flow.html
    1
    +<!DOCTYPE html>
    
    2
    +<meta charset="utf-8">
    
    3
    +<link rel="author" title="Ting-Yu Lin" href="">"mailto:tlin@xxxxxxxxxxx">
    
    4
    +<link rel="help" href="">"https://bugzilla.mozilla.org/show_bug.cgi?id=2053578">
    
    5
    +
    
    6
    +<!-- The operations in <script> are generated from one of the runs from
    
    7
    +     the original testcase (Bug 2053578 Comment 5) that triggers
    
    8
    +     the assertion. -->
    
    9
    +
    
    10
    +<body></body>
    
    11
    +
    
    12
    +<script>
    
    13
    +var n1 = document.createElement("div");
    
    14
    +n1.style.width = "50px";
    
    15
    +var n2 = document.createElement("bdo");
    
    16
    +n2.setAttribute("dir", "rtl");
    
    17
    +var n3 = document.createTextNode("كلمة");
    
    18
    +n2.appendChild(n3);
    
    19
    +n1.appendChild(n2);
    
    20
    +var n4 = document.createElement("em");
    
    21
    +var n5 = document.createElement("span");
    
    22
    +var n6 = document.createElement("bdo");
    
    23
    +var n7 = document.createTextNode("word m mix");
    
    24
    +n6.appendChild(n7);
    
    25
    +n5.appendChild(n6);
    
    26
    +var n8 = document.createTextNode("מלל");
    
    27
    +n5.appendChild(n8);
    
    28
    +var n9 = document.createElement("b");
    
    29
    +n9.setAttribute("dir", "ltr");
    
    30
    +n9.style.unicodeBidi = "bidi-override";
    
    31
    +var n10 = document.createTextNode("alpha");
    
    32
    +n9.appendChild(n10);
    
    33
    +var n11 = document.createTextNode("نص مرحبا كلمة");
    
    34
    +n9.appendChild(n11);
    
    35
    +var n12 = document.createTextNode("مرحبا نص نص");
    
    36
    +n9.appendChild(n12);
    
    37
    +n5.appendChild(n9);
    
    38
    +n4.appendChild(n5);
    
    39
    +var n13 = document.createElement("span");
    
    40
    +n13.style.unicodeBidi = "bidi-override";
    
    41
    +var n14 = document.createElement("bdi");
    
    42
    +var n15 = document.createTextNode("اختبار");
    
    43
    +n14.appendChild(n15);
    
    44
    +n13.appendChild(n14);
    
    45
    +var n16 = document.createElement("em");
    
    46
    +var n17 = document.createTextNode("בדיקה מלל m نص");
    
    47
    +n16.appendChild(n17);
    
    48
    +var n18 = document.createTextNode("كلمة");
    
    49
    +n16.appendChild(n18);
    
    50
    +var n19 = document.createTextNode("نص مرحبا كلمة");
    
    51
    +n16.appendChild(n19);
    
    52
    +n13.appendChild(n16);
    
    53
    +var n20 = document.createElement("span");
    
    54
    +var n21 = document.createTextNode("שלום מלל בדיקה שלום");
    
    55
    +n20.appendChild(n21);
    
    56
    +n13.appendChild(n20);
    
    57
    +n4.appendChild(n13);
    
    58
    +n1.appendChild(n4);
    
    59
    +document.body.appendChild(n1);
    
    60
    +var n22 = document.createElement("bdo");
    
    61
    +n22.style.unicodeBidi = "plaintext";
    
    62
    +var n23 = document.createElement("span");
    
    63
    +var n24 = document.createTextNode("עברית שלום مرحبا alpha");
    
    64
    +n23.appendChild(n24);
    
    65
    +n22.appendChild(n23);
    
    66
    +n14.style.direction = "ltr";
    
    67
    +var n25 = document.createTextNode("كلمة שלום");
    
    68
    +n2.insertBefore(n25, n3);
    
    69
    +n21.remove();
    
    70
    +n9.setAttribute("dir", "ltr");
    
    71
    +var n26 = document.createTextNode("בדיקה mm");
    
    72
    +n4.appendChild(n26);
    
    73
    +n12.data = "שלום עברית שלום עברית";
    
    74
    +n7.remove();
    
    75
    +n2.style.direction = "ltr";
    
    76
    +n1.style.width = "102px";
    
    77
    +var n27 = document.createTextNode("עברית mm m");
    
    78
    +n22.appendChild(n27);
    
    79
    +n22.setAttribute("dir", "rtl");
    
    80
    +n4.style.direction = "";
    
    81
    +n14.style.direction = "rtl";
    
    82
    +n22.insertBefore(n9, n23);
    
    83
    +var n28 = document.createElement("br");
    
    84
    +n9.insertBefore(n28, n12);
    
    85
    +n14.style.unicodeBidi = "embed";
    
    86
    +n5.insertBefore(n22, n6);
    
    87
    +n9.style.direction = "";
    
    88
    +n9.style.unicodeBidi = "bidi-override";
    
    89
    +n22.remove();
    
    90
    +var n29 = document.createTextNode("עברית שלום");
    
    91
    +n5.insertBefore(n29, n6);
    
    92
    +n18.data = "mix";
    
    93
    +n19.data = "alpha m word";
    
    94
    +n20.style.direction = "ltr";
    
    95
    +var n30 = document.createTextNode("mm עברית עברית نص");
    
    96
    +n6.appendChild(n30);
    
    97
    +n6.style.unicodeBidi = "isolate";
    
    98
    +n20.style.unicodeBidi = "embed";
    
    99
    +n16.setAttribute("dir", "rtl");
    
    100
    +n2.insertBefore(n20, n25);
    
    101
    +var n31 = document.createTextNode("שלום مرحبا mix mm");
    
    102
    +n2.insertBefore(n31, n20);
    
    103
    +var n32 = document.createTextNode("m בדיקה word mix");
    
    104
    +n20.appendChild(n32);
    
    105
    +n16.removeAttribute("dir");
    
    106
    +n16.setAttribute("dir", "auto");
    
    107
    +n5.remove();
    
    108
    +n17.remove();
    
    109
    +n31.data = "בדיקה mm";
    
    110
    +n14.style.unicodeBidi = "isolate";
    
    111
    +n4.remove();
    
    112
    +n20.style.direction = "";
    
    113
    +n20.style.direction = "rtl";
    
    114
    +n3.data = "בדיקה שלום word";
    
    115
    +n25.data = "mm";
    
    116
    +n25.data = "m mix word";
    
    117
    +n1.style.direction = "rtl";
    
    118
    +n31.data = "كلمة اختبار";
    
    119
    +n20.remove();
    
    120
    +n3.data = "שלום نص";
    
    121
    +n31.remove();
    
    122
    +n2.setAttribute("dir", "ltr");
    
    123
    +n2.removeAttribute("dir");
    
    124
    +n1.insertBefore(n4, n2);
    
    125
    +n19.data = "מלל word";
    
    126
    +n15.remove();
    
    127
    +n13.setAttribute("dir", "ltr");
    
    128
    +n25.remove();
    
    129
    +n2.setAttribute("dir", "ltr");
    
    130
    +n14.appendChild(n2);
    
    131
    +n3.data = "مرحبا اختبار مرحبا";
    
    132
    +n18.data = "שלום";
    
    133
    +n16.insertBefore(n20, n18);
    
    134
    +var n33 = document.createTextNode("كلمة نص mm");
    
    135
    +n2.appendChild(n33);
    
    136
    +n19.data = "اختبار مرحبا كلمة كلمة";
    
    137
    +n18.data = "mm mix mix";
    
    138
    +var n34 = document.createElement("br");
    
    139
    +n4.insertBefore(n34, n13);
    
    140
    +n13.style.unicodeBidi = "isolate-override";
    
    141
    +n13.remove();
    
    142
    +n34.remove();
    
    143
    +n26.data = "كلمة كلمة مرحبا";
    
    144
    +n4.setAttribute("dir", "rtl");
    
    145
    +n26.data = "mm word m mm";
    
    146
    +n26.data = "اختبار نص";
    
    147
    +n4.setAttribute("dir", "auto");
    
    148
    +var n35 = document.createTextNode("مرحبا מלל كلمة שלום");
    
    149
    +n4.insertBefore(n35, n26);
    
    150
    +n4.style.unicodeBidi = "embed";
    
    151
    +n4.style.direction = "";
    
    152
    +var n36 = document.createTextNode("كلمة mix בדיקה نص");
    
    153
    +n4.insertBefore(n36, n35);
    
    154
    +n36.remove();
    
    155
    +n4.removeAttribute("dir");
    
    156
    +n4.style.unicodeBidi = "";
    
    157
    +n1.style.width = "87px";
    
    158
    +n26.data = "שלום מלל מלל עברית";
    
    159
    +var n37 = document.createElement("br");
    
    160
    +n4.insertBefore(n37, n35);
    
    161
    +n35.data = "مرحبا نص اختبار";
    
    162
    +n4.setAttribute("dir", "rtl");
    
    163
    +n33.data = "word alpha mm";
    
    164
    +var n38 = document.createTextNode("שלום word");
    
    165
    +n16.insertBefore(n38, n20);
    
    166
    +n2.setAttribute("dir", "auto");
    
    167
    +n2.remove();
    
    168
    +n37.remove();
    
    169
    +var n39 = document.createTextNode("עברית اختبار בדיקה");
    
    170
    +n13.appendChild(n39);
    
    171
    +var n40 = document.createTextNode("בדיקה m نص نص");
    
    172
    +n13.insertBefore(n40, n14);
    
    173
    +var n41 = document.createElement("br");
    
    174
    +n20.appendChild(n41);
    
    175
    +n35.data = "alpha";
    
    176
    +n16.remove();
    
    177
    +n39.data = "نص mm בדיקה اختبار";
    
    178
    +n40.data = "mix mix word m";
    
    179
    +n35.data = "שלום בדיקה";
    
    180
    +n35.data = "m mix mm m";
    
    181
    +n40.data = "مرحبا اختبار";
    
    182
    +n13.style.unicodeBidi = "embed";
    
    183
    +n4.insertBefore(n16, n26);
    
    184
    +var n42 = document.createTextNode("نص");
    
    185
    +n13.insertBefore(n42, n40);
    
    186
    +n41.remove();
    
    187
    +n20.insertBefore(n2, n32);
    
    188
    +document.body.offsetHeight;
    
    189
    +n39.data = "مرحبا alpha עברית word";
    
    190
    +n18.data = "שלום";
    
    191
    +n2.setAttribute("dir", "auto");
    
    192
    +document.body.offsetHeight;
    
    193
    +n20.style.direction = "ltr";
    
    194
    +</script>

  • _______________________________________________
    tor-commits mailing list -- tor-commits@xxxxxxxxxxxxxxxxxxxx
    To unsubscribe send an email to tor-commits-leave@xxxxxxxxxxxxxxxxxxxx