Merge "AccountUpdate: Test case for unsetting string values using empty strings" into stable-3.11
diff --git a/Documentation/config-gerrit.txt b/Documentation/config-gerrit.txt
index 9af1df8..8e9e1a93 100644
--- a/Documentation/config-gerrit.txt
+++ b/Documentation/config-gerrit.txt
@@ -3684,9 +3684,67 @@
 +
 Defaults to `false`.
 
+[[scheduledIndexer]]
+=== Section scheduledIndexer
+
+This section configures periodic indexing. Periodic indexing can be run
+on both primaries and replicas.
+
+
+[[scheduledIndexer.groups]]
+==== Subsection scheduledIndexer.groups
+
+Periodic groups reindexing will be scheduled by default on replicas if there is
+no explicit `scheduledIndexer.groups` configuration.
+
+Replication to replicas happens on Git level so that Gerrit is not aware
+of incoming replication events. But replicas need an updated group index
+to resolve memberships of users for ACL validation. To keep the group
+index in replicas up-to-date the Gerrit replica periodically scans the
+group refs in the All-Users repository to reindex groups if they are
+stale.
+
+[[scheduledIndexer.groups.runOnStartup]]scheduledIndexer.groups.runOnStartup::
++
+Whether the scheduled indexer should run once immediately on startup.
+If set to `true` the server startup is blocked until all stale groups
+were reindexed. Enabling this allows to prevent that servers that were
+offline for a longer period of time run with outdated group information
+until the first scheduled indexing is done.
++
+Defaults to `true` for replicas, `false` for primaries.
+
+[[scheduledIndexer.groups.enabled]]scheduledIndexer.groups.enabled::
++
+Whether the scheduled indexer is enabled. If the scheduled indexer is disabled
+you may need to implement other means to keep the groups index on replicas
+up-to-date.
++
+Defaults to `true` for replicas, `false` for primaries.
+
+[[scheduledIndexer.groups.startTime]]groups.scheduledIndexer.startTime::
++
+The link:#schedule-configuration-startTime[start time] for running
+the scheduled indexer.
++
+Defaults to `00:00`.
+
+[[scheduledIndexer.groups.interval]]scheduledIndexer.groups.interval::
++
+The link:#schedule-configuration-interval[interval] for running
+the scheduled indexer.
++
+Defaults to `5m`.
+
+link:#schedule-configuration-examples[Schedule examples] can be found
+in the link:#schedule-configuration[Schedule Configuration] section.
+
+
 [[index.scheduledIndexer]]
 ==== Subsection index.scheduledIndexer
 
+*(DEPRECATED)* Use the link:#scheduledIndexer[scheduledIndexer section] instead.
+
 This section configures periodic indexing. Periodic indexing is
 intended to run only on replicas and only updates the group index.
 Replication to replicas happens on Git level so that Gerrit is not aware
diff --git a/Documentation/config-submit-requirements.txt b/Documentation/config-submit-requirements.txt
index 5ab1add..560c77f 100644
--- a/Documentation/config-submit-requirements.txt
+++ b/Documentation/config-submit-requirements.txt
@@ -473,6 +473,38 @@
 +
 `distinctvoters:[Code-Review,Trust,API-Review],count>2`
 
+[[operator_label_with_users_arg]]
+label:'<label><operator><value>,users=human_reviewers'::
++
+Extension of the link:user-search.html#labels[label] predicate that
+allows matching changes that have a matching vote from all human
+reviewers. Votes from service users (members of the
+link:access-control.html#service_users[Service Users] group) and the
+change owner are ignored.
++
+If link:config-project-config.html#reviewer.enableByEmail[reviewers by
+email] are present then "user=all_reviewers" doesn't match if the
+expected value is other than 0. Reviewers by email are reviewers that
+don't have a Gerrit account.  Without Gerrit account they cannot vote
+on the change, which means changes that have any such reviewers never
+match when a vote from all reviewers is expected.
++
+If a change has no human reviewers, this operator doesn't match
+(because a human review is required but no human reviewer is present).
++
+Examples:
+`label:Code-Review=MAX,users=human_reviewers`
++
+`label:Code-Review>=1,users=human_reviewers`
++
+The 'users' arg cannot be combined with other arguments ('count',
+'user', 'group').
++
+'label:Code-Review=MAX,users=human_reviewers' can be used to
+implement "Want-Code-Review-From-All" functionaly, see
+link#require-code-review-approvals-from-all-human-reviewers-example[examples
+below].
+
 [[operator_is_true]]
 is:true::
 +
@@ -557,7 +589,7 @@
 == Examples
 
 [[code-review-example]]
-=== Code-Review Example
+=== Require Code-Review approval from a non-uploader
 
 To define a submit requirement for code-review that requires a maximum vote for
 the “Code-Review” label from a non-uploader without a maximum negative vote:
@@ -571,7 +603,7 @@
 ----
 
 [[exempt-branch-example]]
-=== Exempt a branch Example
+=== Exempt a branch
 
 We could exempt a submit requirement from certain branches. For example,
 project owners might want to skip the 'Code-Style' requirement from the
@@ -602,7 +634,7 @@
 ----
 
 [[require-footer-example]]
-=== Require a footer Example
+=== Require a footer
 
 It's possible to use a submit requirement to require a footer to be present in
 the commit message.
@@ -614,6 +646,59 @@
   submittableIf = hasfooter:\"Bug\"
 ----
 
+[[require-code-review-approvals-from-all-human-reviewers-example]]
+=== Require Code-Review approvals from all human reviewers
+
+The following submit requirement requires a 'Code-Review' approval
+('Code-Review+1' or 'Code-Review+2') from all human reviewers of the
+change. Votes from service users (members of the
+link:access-control.html#service_users[Service Users] group) and the
+change owner are ignored.
+
+The 'applicableIf' condition makes this submit requirement show up in
+the UI only if it is not satisfied (to keep the submit requirement
+showing when it is satisfied omit the 'applicableIf' condition).
+
+If a change has no human reviewers, this submit requirement is
+unsatisfied (because a human review is required but no human reviewer
+is present).
+
+----
+[submit-requirement "Want-Code-Review-From-All"]
+  description = A 'Code-Review' vote is required from all human \
+                reviewers (service users that are reviewers are \
+                ignored).
+  applicableIf = -label:Code-Review>=1,users=human_reviewers
+  submittableIf = label:Code-Review>=1,users=human_reviewers
+----
+
+It is possible to configure the 'Want-Code-Review-From-All' submit
+requirement so that it only applies when a 'Want-Code-Review: all'
+footer is present in the commit message. This way users can enable
+this submit requirement on demand by including this footer into their
+commit messages.
+
+The 'applicableIf' condition checks for the 'Want-Code-Review: all'
+footer and makes this submit requirement show up in the UI only if it
+is not satisfied (to keep the submit requirement showing when it is
+satisfied omit the '-label:Code-Review>=1,users=human_reviewers'
+predicate from the 'applicableIf' condition).
+
+Note, the footer key cannot contain underscores (e.g. using
+'Want_Code_Review: all' as the footer does not work).
+
+----
+[submit-requirement "Want-Code-Review-From-All"]
+  description = A 'Code-Review' vote is required from all human \
+                reviewers (service users that are reviewers are \
+                ignored).
+  applicableIf = footer:\"Want-Code-Review: all\" -label:Code-Review>=1,users=human_reviewers
+  submittableIf = label:Code-Review>=1,users=human_reviewers
+----
+
+For more information about the "users=human_reviewers" arg see
+link:#operator_label_with_users_arg[above].
+
 GERRIT
 ------
 Part of link:index.html[Gerrit Code Review]
diff --git a/Documentation/rest-api-changes.txt b/Documentation/rest-api-changes.txt
index 0ed6b27..c199d82 100644
--- a/Documentation/rest-api-changes.txt
+++ b/Documentation/rest-api-changes.txt
@@ -2751,7 +2751,7 @@
   }
 ----
 
-[[set-work-in-pogress]]
+[[set-work-in-progress]]
 === Set Work-In-Progress
 --
 'POST /changes/link:#change-id[\{change-id\}]/wip'
diff --git a/java/com/google/gerrit/acceptance/GerritServer.java b/java/com/google/gerrit/acceptance/GerritServer.java
index 9d8674f..cf4cf2c 100644
--- a/java/com/google/gerrit/acceptance/GerritServer.java
+++ b/java/com/google/gerrit/acceptance/GerritServer.java
@@ -58,6 +58,7 @@
 import com.google.gerrit.lucene.LuceneIndexModule;
 import com.google.gerrit.pgm.Daemon;
 import com.google.gerrit.pgm.Init;
+import com.google.gerrit.server.config.GerritOptions;
 import com.google.gerrit.server.config.GerritRuntime;
 import com.google.gerrit.server.config.GerritServerConfig;
 import com.google.gerrit.server.config.SitePath;
@@ -525,6 +526,7 @@
             new AbstractModule() {
               @Override
               protected void configure() {
+                bind(GerritOptions.class).toInstance(GerritOptions.DEFAULT);
                 bind(GerritRuntime.class).toInstance(GerritRuntime.DAEMON);
               }
             },
diff --git a/java/com/google/gerrit/acceptance/InMemoryTestingDatabaseModule.java b/java/com/google/gerrit/acceptance/InMemoryTestingDatabaseModule.java
index 9a652e3..c313a06 100644
--- a/java/com/google/gerrit/acceptance/InMemoryTestingDatabaseModule.java
+++ b/java/com/google/gerrit/acceptance/InMemoryTestingDatabaseModule.java
@@ -25,6 +25,7 @@
 import com.google.gerrit.server.config.AllProjectsConfigProvider;
 import com.google.gerrit.server.config.FileBasedAllProjectsConfigProvider;
 import com.google.gerrit.server.config.FileBasedGlobalPluginConfigProvider;
+import com.google.gerrit.server.config.GerritIsReplica;
 import com.google.gerrit.server.config.GerritServerConfig;
 import com.google.gerrit.server.config.GlobalPluginConfigProvider;
 import com.google.gerrit.server.config.MetricsReservoirConfigImpl;
@@ -83,6 +84,8 @@
     install(new SchemaModule());
 
     install(new SshdModule());
+
+    bind(Boolean.class).annotatedWith(GerritIsReplica.class).toInstance(false);
   }
 
   static class CreateSchema implements LifecycleListener {
diff --git a/java/com/google/gerrit/entities/LabelType.java b/java/com/google/gerrit/entities/LabelType.java
index ff4b8f9..c491620 100644
--- a/java/com/google/gerrit/entities/LabelType.java
+++ b/java/com/google/gerrit/entities/LabelType.java
@@ -207,12 +207,52 @@
     public abstract Builder setDescription(Optional<String> description);
 
     /**
-     * @deprecated in favour of using submit requirements, except if it’s needed to set the value to
-     *     PatchSetLock
+     * @deprecated All label functions except {@code PATCH_SET_LOCK} are deprecated in favour of
+     *     using submit requirements. When submit requirements are used the label function needs to
+     *     be set to {@code NO_BLOCK} (or {@code NO_OP} which is semantically the same). This is to
+     *     override the default label function which is {@code MAX_WITH_BLOCK} and which should not
+     *     be used in combination with a submit requirement.
      */
     @Deprecated
     public abstract Builder setFunction(LabelFunction function);
 
+    /**
+     * Sets the label function to {@code NO_BLOCK}, e.g. to override the default label function
+     * which is {@code MAX_WITH_BLOCK} and which should not be used in combination with a submit
+     * requirement. .
+     *
+     * <p>In contrast to most other label functions {@code NO_BLOCK} is not deprecated.
+     *
+     * <p>Use this method to set the label function to {@code NO_BLOCK}, instead of calling {@code
+     * setFunction(NO_BLOCK)} which is deprecated.
+     *
+     * <p>Note, {@code NO_OP} is semantically the same as {@code NO_BLOCK}, hence this method should
+     * also be used, instead of calling {@code setFunction(NO_OP)}.
+     *
+     * @return the instance of this builder to allow chaining calls.
+     */
+    @CanIgnoreReturnValue
+    @SuppressWarnings("deprecation")
+    public Builder setNoBlockFunction() {
+      return setFunction(LabelFunction.NO_BLOCK);
+    }
+
+    /**
+     * Sets the label function to {@code PATCH_SET_LOCK}.
+     *
+     * <p>In contrast to most other label functions {@code PATCH_SET_LOCK} is not deprecated.
+     *
+     * <p>Use this method to set the label function to {@code PATCH_SET_LOCK}, instead of calling
+     * {@code setFunction(PATCH_SET_LOCK)} which is deprecated.
+     *
+     * @return the instance of this builder to allow chaining calls.
+     */
+    @CanIgnoreReturnValue
+    @SuppressWarnings("deprecation")
+    public Builder setPatchSetLockFunction() {
+      return setFunction(LabelFunction.PATCH_SET_LOCK);
+    }
+
     public abstract Builder setCanOverride(boolean canOverride);
 
     public abstract Builder setAllowPostSubmit(boolean allowPostSubmit);
diff --git a/java/com/google/gerrit/httpd/init/WebAppInitializer.java b/java/com/google/gerrit/httpd/init/WebAppInitializer.java
index 0e37684..c8dab81 100644
--- a/java/com/google/gerrit/httpd/init/WebAppInitializer.java
+++ b/java/com/google/gerrit/httpd/init/WebAppInitializer.java
@@ -362,7 +362,7 @@
         new AbstractModule() {
           @Override
           protected void configure() {
-            bind(GerritOptions.class).toInstance(new GerritOptions(false, false));
+            bind(GerritOptions.class).toInstance(GerritOptions.DEFAULT);
             bind(GerritRuntime.class).toInstance(GerritRuntime.DAEMON);
           }
         });
diff --git a/java/com/google/gerrit/pgm/Daemon.java b/java/com/google/gerrit/pgm/Daemon.java
index 574f68d..4a47e5ad 100644
--- a/java/com/google/gerrit/pgm/Daemon.java
+++ b/java/com/google/gerrit/pgm/Daemon.java
@@ -63,6 +63,7 @@
 import com.google.gerrit.server.account.AccountCacheImpl;
 import com.google.gerrit.server.account.AccountDeactivator.AccountDeactivatorModule;
 import com.google.gerrit.server.account.InternalAccountDirectory.InternalAccountDirectoryModule;
+import com.google.gerrit.server.account.externalids.storage.notedb.ExternalIdCacheImpl;
 import com.google.gerrit.server.account.externalids.storage.notedb.ExternalIdCaseSensitivityMigrator;
 import com.google.gerrit.server.account.storage.notedb.AccountNoteDbReadStorageModule;
 import com.google.gerrit.server.account.storage.notedb.AccountNoteDbWriteStorageModule;
@@ -92,12 +93,12 @@
 import com.google.gerrit.server.git.ChangesByProjectCache;
 import com.google.gerrit.server.git.GarbageCollectionModule;
 import com.google.gerrit.server.git.WorkQueue.WorkQueueModule;
-import com.google.gerrit.server.group.PeriodicGroupIndexer.PeriodicGroupIndexerModule;
 import com.google.gerrit.server.index.AbstractIndexModule;
 import com.google.gerrit.server.index.IndexModule;
 import com.google.gerrit.server.index.OnlineUpgrader.OnlineUpgraderModule;
 import com.google.gerrit.server.index.VersionManager;
 import com.google.gerrit.server.index.options.AutoFlush;
+import com.google.gerrit.server.index.scheduler.PeriodicIndexScheduler;
 import com.google.gerrit.server.mail.EmailModule;
 import com.google.gerrit.server.mail.SignedTokenEmailTokenVerifier.SignedTokenEmailTokenVerifierModule;
 import com.google.gerrit.server.mail.receive.MailReceiver.MailReceiverModule;
@@ -384,11 +385,11 @@
   @VisibleForTesting
   public void start() throws IOException {
     if (dbInjector == null) {
-      dbInjector = createDbInjector(true /* enableMetrics */);
+      dbInjector =
+          createDbInjector(true /* enableMetrics */, new GerritOptions(headless, replica, devCdn));
     }
     cfgInjector = createCfgInjector();
     config = cfgInjector.getInstance(Key.get(Config.class, GerritServerConfig.class));
-    config.setBoolean("container", null, "replica", replica);
     indexType = IndexModule.getIndexType(cfgInjector);
     sysInjector = createSysInjector();
     sysInjector.getInstance(PluginGuiceEnvironment.class).setDbCfgInjector(dbInjector, cfgInjector);
@@ -476,6 +477,8 @@
 
     modules.add(new AccountNoteDbWriteStorageModule());
     modules.add(new AccountNoteDbReadStorageModule());
+    modules.add(new ExternalIdCacheImpl.ExternalIdCacheModule());
+    modules.add(new ExternalIdCacheImpl.ExternalIdCacheBindingModule());
     modules.add(new RepoSequenceModule());
     modules.add(new FromAddressGeneratorProvider.UserAddressGenModule());
     modules.add(new NoteDbDraftCommentsModule());
@@ -545,7 +548,6 @@
         new AbstractModule() {
           @Override
           protected void configure() {
-            bind(GerritOptions.class).toInstance(new GerritOptions(headless, replica, devCdn));
             if (inMemoryTest) {
               bind(String.class)
                   .annotatedWith(SecureStoreClassName.class)
@@ -555,9 +557,8 @@
           }
         });
     modules.add(new GarbageCollectionModule());
-    if (replica) {
-      modules.add(new PeriodicGroupIndexerModule());
-    } else {
+    modules.add(new PeriodicIndexScheduler.Module());
+    if (!replica) {
       modules.add(new AccountDeactivatorModule());
       modules.add(new AttentionSetOwnerAdderModule());
       modules.add(new ChangeCleanupRunnerModule());
diff --git a/java/com/google/gerrit/pgm/Init.java b/java/com/google/gerrit/pgm/Init.java
index d3e9988..fc5a2c7 100644
--- a/java/com/google/gerrit/pgm/Init.java
+++ b/java/com/google/gerrit/pgm/Init.java
@@ -30,6 +30,7 @@
 import com.google.gerrit.pgm.init.InitPlugins;
 import com.google.gerrit.pgm.init.api.ConsoleUI;
 import com.google.gerrit.pgm.util.ErrorLogFile;
+import com.google.gerrit.server.config.GerritOptions;
 import com.google.gerrit.server.config.GerritServerConfigModule;
 import com.google.gerrit.server.config.SitePath;
 import com.google.gerrit.server.index.GerritIndexStatus;
@@ -159,6 +160,7 @@
             bind(String.class)
                 .annotatedWith(SecureStoreClassName.class)
                 .toProvider(Providers.of(getConfiguredSecureStoreClass()));
+            bind(GerritOptions.class).toInstance(GerritOptions.DEFAULT);
           }
         });
     modules.add(new GerritServerConfigModule());
diff --git a/java/com/google/gerrit/pgm/Reindex.java b/java/com/google/gerrit/pgm/Reindex.java
index d393a89..7424407 100644
--- a/java/com/google/gerrit/pgm/Reindex.java
+++ b/java/com/google/gerrit/pgm/Reindex.java
@@ -33,6 +33,7 @@
 import com.google.gerrit.pgm.util.SiteProgram;
 import com.google.gerrit.server.LibModuleLoader;
 import com.google.gerrit.server.ModuleOverloader;
+import com.google.gerrit.server.account.externalids.storage.notedb.ExternalIdCacheImpl;
 import com.google.gerrit.server.account.storage.notedb.AccountNoteDbReadStorageModule;
 import com.google.gerrit.server.account.storage.notedb.AccountNoteDbWriteStorageModule;
 import com.google.gerrit.server.cache.CacheDisplay;
@@ -243,6 +244,8 @@
         });
     modules.add(new AccountNoteDbWriteStorageModule());
     modules.add(new AccountNoteDbReadStorageModule());
+    modules.add(new ExternalIdCacheImpl.ExternalIdCacheModule());
+    modules.add(new ExternalIdCacheImpl.ExternalIdCacheBindingModule());
     modules.add(new RepoSequenceModule());
     modules.add(new NoteDbDraftCommentsModule());
     modules.add(new NoteDbStarredChangesModule());
diff --git a/java/com/google/gerrit/pgm/init/BaseInit.java b/java/com/google/gerrit/pgm/init/BaseInit.java
index 1f56512..e0eb773 100644
--- a/java/com/google/gerrit/pgm/init/BaseInit.java
+++ b/java/com/google/gerrit/pgm/init/BaseInit.java
@@ -36,6 +36,7 @@
 import com.google.gerrit.pgm.init.index.IndexModuleOnInit;
 import com.google.gerrit.pgm.init.index.lucene.LuceneIndexModuleOnInit;
 import com.google.gerrit.pgm.util.SiteProgram;
+import com.google.gerrit.server.config.GerritOptions;
 import com.google.gerrit.server.config.GerritServerConfigModule;
 import com.google.gerrit.server.config.SitePath;
 import com.google.gerrit.server.config.SitePaths;
@@ -275,6 +276,7 @@
             bind(Boolean.class).annotatedWith(LibraryDownload.class).toInstance(skipAllDownloads());
 
             bind(MetricMaker.class).to(DisabledMetricMaker.class);
+            bind(GerritOptions.class).toInstance(GerritOptions.DEFAULT);
           }
         });
 
diff --git a/java/com/google/gerrit/pgm/util/BatchProgramModule.java b/java/com/google/gerrit/pgm/util/BatchProgramModule.java
index f45f1be..f30efd4 100644
--- a/java/com/google/gerrit/pgm/util/BatchProgramModule.java
+++ b/java/com/google/gerrit/pgm/util/BatchProgramModule.java
@@ -42,7 +42,6 @@
 import com.google.gerrit.server.account.GroupIncludeCacheImpl;
 import com.google.gerrit.server.account.Realm;
 import com.google.gerrit.server.account.ServiceUserClassifierImpl;
-import com.google.gerrit.server.account.externalids.storage.notedb.ExternalIdCacheModule;
 import com.google.gerrit.server.cache.CacheRemovalListener;
 import com.google.gerrit.server.cache.h2.H2CacheModule;
 import com.google.gerrit.server.cache.mem.DefaultMemoryCacheModule;
@@ -99,6 +98,7 @@
 import com.google.gerrit.server.submitrequirement.predicate.DistinctVotersPredicate;
 import com.google.gerrit.server.submitrequirement.predicate.FileEditsPredicate;
 import com.google.gerrit.server.submitrequirement.predicate.HasSubmoduleUpdatePredicate;
+import com.google.gerrit.server.submitrequirement.predicate.SubmitRequirementLabelExtensionPredicate;
 import com.google.gerrit.server.update.BatchUpdate;
 import com.google.inject.Injector;
 import com.google.inject.Key;
@@ -181,7 +181,6 @@
     modules.add(new DefaultPermissionBackendModule());
     modules.add(new DefaultMemoryCacheModule());
     modules.add(new H2CacheModule());
-    modules.add(new ExternalIdCacheModule());
     modules.add(new GroupModule());
     modules.add(new NoteDbModule());
     modules.add(AccountCacheImpl.module());
@@ -203,6 +202,7 @@
     factory(ChangeData.AssistedFactory.class);
     factory(ChangeIsVisibleToPredicate.Factory.class);
     factory(DistinctVotersPredicate.Factory.class);
+    factory(SubmitRequirementLabelExtensionPredicate.Factory.class);
     factory(HasSubmoduleUpdatePredicate.Factory.class);
     factory(ProjectState.Factory.class);
 
diff --git a/java/com/google/gerrit/pgm/util/SiteProgram.java b/java/com/google/gerrit/pgm/util/SiteProgram.java
index aeaa1d6..ddf62fe 100644
--- a/java/com/google/gerrit/pgm/util/SiteProgram.java
+++ b/java/com/google/gerrit/pgm/util/SiteProgram.java
@@ -25,6 +25,7 @@
 import com.google.gerrit.server.LibModuleLoader;
 import com.google.gerrit.server.LibModuleType;
 import com.google.gerrit.server.ModuleOverloader;
+import com.google.gerrit.server.config.GerritOptions;
 import com.google.gerrit.server.config.GerritRuntime;
 import com.google.gerrit.server.config.GerritServerConfigModule;
 import com.google.gerrit.server.config.SitePath;
@@ -77,11 +78,11 @@
 
   /** Provides database connectivity and site path. */
   protected Injector createDbInjector() {
-    return createDbInjector(false);
+    return createDbInjector(false, GerritOptions.DEFAULT);
   }
 
   /** Provides database connectivity and site path. */
-  protected Injector createDbInjector(boolean enableMetrics) {
+  protected Injector createDbInjector(boolean enableMetrics, GerritOptions options) {
     List<Module> modules = new ArrayList<>();
 
     Module sitePathModule =
@@ -124,7 +125,15 @@
             bind(GerritRuntime.class).toInstance(getGerritRuntime());
           }
         });
-    Injector cfgInjector = Guice.createInjector(sitePathModule, configModule);
+    Module gerritOptionsModule =
+        new AbstractModule() {
+          @Override
+          protected void configure() {
+            bind(GerritOptions.class).toInstance(options);
+          }
+        };
+    modules.add(gerritOptionsModule);
+    Injector cfgInjector = Guice.createInjector(sitePathModule, configModule, gerritOptionsModule);
 
     modules.add(new SchemaModule());
     modules.add(cfgInjector.getInstance(GitRepositoryManagerModule.class));
diff --git a/java/com/google/gerrit/server/account/externalids/ExternalIdCache.java b/java/com/google/gerrit/server/account/externalids/ExternalIdCache.java
index a23e7bc..886fe70 100644
--- a/java/com/google/gerrit/server/account/externalids/ExternalIdCache.java
+++ b/java/com/google/gerrit/server/account/externalids/ExternalIdCache.java
@@ -28,6 +28,12 @@
  * cache is up to date.
  *
  * <p>All returned collections are unmodifiable.
+ *
+ * <p>NOTE: Modules which bind {@link ExternalIdCache} by using modules other than {@link
+ * com.google.gerrit.server.account.externalids.storage.notedb.ExternalIdCacheImpl.ExternalIdCacheBindingModule},
+ * should also provide an {@code Optional<}{@link
+ * com.google.gerrit.server.account.externalids.storage.notedb.ExternalIdCacheImpl}{@code >}
+ * binding.
  */
 public interface ExternalIdCache {
   Optional<ExternalId> byKey(ExternalId.Key key) throws IOException;
diff --git a/java/com/google/gerrit/server/account/externalids/storage/notedb/DisabledExternalIdCache.java b/java/com/google/gerrit/server/account/externalids/storage/notedb/DisabledExternalIdCache.java
index 8e53277..fd19fcc 100644
--- a/java/com/google/gerrit/server/account/externalids/storage/notedb/DisabledExternalIdCache.java
+++ b/java/com/google/gerrit/server/account/externalids/storage/notedb/DisabledExternalIdCache.java
@@ -21,6 +21,8 @@
 import com.google.gerrit.server.account.externalids.ExternalIdCache;
 import com.google.inject.AbstractModule;
 import com.google.inject.Module;
+import com.google.inject.Provides;
+import com.google.inject.Singleton;
 import java.io.IOException;
 import java.util.Optional;
 
@@ -32,6 +34,12 @@
       protected void configure() {
         bind(ExternalIdCache.class).to(DisabledExternalIdCache.class);
       }
+
+      @Provides
+      @Singleton
+      Optional<ExternalIdCacheImpl> provideNoteDbExternalIdCacheImpl() {
+        return Optional.empty();
+      }
     };
   }
 
diff --git a/java/com/google/gerrit/server/account/externalids/storage/notedb/ExternalIdCacheImpl.java b/java/com/google/gerrit/server/account/externalids/storage/notedb/ExternalIdCacheImpl.java
index dbfe205..20c94eb 100644
--- a/java/com/google/gerrit/server/account/externalids/storage/notedb/ExternalIdCacheImpl.java
+++ b/java/com/google/gerrit/server/account/externalids/storage/notedb/ExternalIdCacheImpl.java
@@ -14,27 +14,86 @@
 
 package com.google.gerrit.server.account.externalids.storage.notedb;
 
+import static com.google.inject.Scopes.SINGLETON;
+
 import com.google.common.cache.Cache;
 import com.google.common.collect.ImmutableSet;
 import com.google.common.collect.ImmutableSetMultimap;
 import com.google.gerrit.entities.Account;
 import com.google.gerrit.server.account.externalids.ExternalId;
 import com.google.gerrit.server.account.externalids.ExternalIdCache;
+import com.google.gerrit.server.cache.CacheModule;
+import com.google.gerrit.server.cache.serialize.ObjectIdCacheSerializer;
+import com.google.inject.AbstractModule;
 import com.google.inject.Inject;
+import com.google.inject.Provides;
 import com.google.inject.Singleton;
+import com.google.inject.TypeLiteral;
 import com.google.inject.name.Named;
 import java.io.IOException;
+import java.time.Duration;
 import java.util.Optional;
 import java.util.concurrent.locks.Lock;
 import java.util.concurrent.locks.ReentrantLock;
 import org.eclipse.jgit.errors.ConfigInvalidException;
 import org.eclipse.jgit.lib.ObjectId;
 
-/** Caches external IDs of all accounts. The external IDs are always loaded from NoteDb. */
-@Singleton
-class ExternalIdCacheImpl implements ExternalIdCache {
+/**
+ * Caches external IDs of all accounts. The external IDs are always loaded from NoteDb. *
+ *
+ * <p>This class should be bounded as a Singleton. However, due to internal limitations in Google,
+ * it cannot be marked as a singleton. The common installation pattern should therefore be:
+ *
+ * <pre>{@code
+ * * install(new ExternalIdCacheModule());
+ * * install(new ExternalIdCacheBindingModule());
+ * *
+ * }</pre>
+ */
+public class ExternalIdCacheImpl implements ExternalIdCache {
   public static final String CACHE_NAME = "external_ids_map";
 
+  public static class ExternalIdCacheModule extends CacheModule {
+    @Override
+    protected void configure() {
+      persist(CACHE_NAME, ObjectId.class, new TypeLiteral<AllExternalIds>() {})
+          // The cached data is potentially pretty large and we are always only interested
+          // in the latest value. However, due to a race condition, it is possible for different
+          // threads to observe different values of the meta ref, and hence request different keys
+          // from the cache. Extend the cache size by 1 to cover this case, but expire the extra
+          // object after a short period of time, since it may be a potentially large amount of
+          // memory.
+          // When loading a new value because the primary data advanced, we want to leverage the old
+          // cache state to recompute only what changed. This doesn't affect cache size though as
+          // Guava calls the loader first and evicts later on.
+          .maximumWeight(2)
+          .expireFromMemoryAfterAccess(Duration.ofMinutes(1))
+          .diskLimit(-1)
+          .version(1)
+          .keySerializer(ObjectIdCacheSerializer.INSTANCE)
+          .valueSerializer(AllExternalIds.Serializer.INSTANCE);
+    }
+  }
+
+  public static class ExternalIdCacheBindingModule extends AbstractModule {
+    @Override
+    protected void configure() {
+      bind(ExternalIdCache.class).to(ExternalIdCacheImpl.class).in(SINGLETON);
+    }
+
+    /**
+     * Used by {@link ExternalIdsNoteDbImpl}. Modules which bind {@link ExternalIdCache} by using
+     * modules other than {@link ExternalIdCacheBindingModule}, should also provide an {@code
+     * Optional<ExternalIdCacheImpl>} binding.
+     */
+    @Provides
+    @Singleton
+    Optional<ExternalIdCacheImpl> provideNoteDbExternalIdCacheImpl(
+        ExternalIdCacheImpl externalIdCache) {
+      return Optional.of(externalIdCache);
+    }
+  }
+
   private final Cache<ObjectId, AllExternalIds> extIdsByAccount;
   private final ExternalIdReader externalIdReader;
   private final ExternalIdCacheLoader externalIdCacheLoader;
diff --git a/java/com/google/gerrit/server/account/externalids/storage/notedb/ExternalIdCacheModule.java b/java/com/google/gerrit/server/account/externalids/storage/notedb/ExternalIdCacheModule.java
deleted file mode 100644
index aca0e1a..0000000
--- a/java/com/google/gerrit/server/account/externalids/storage/notedb/ExternalIdCacheModule.java
+++ /dev/null
@@ -1,47 +0,0 @@
-// Copyright (C) 2017 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.server.account.externalids.storage.notedb;
-
-import com.google.gerrit.server.account.externalids.ExternalIdCache;
-import com.google.gerrit.server.cache.CacheModule;
-import com.google.gerrit.server.cache.serialize.ObjectIdCacheSerializer;
-import com.google.inject.TypeLiteral;
-import java.time.Duration;
-import org.eclipse.jgit.lib.ObjectId;
-
-public class ExternalIdCacheModule extends CacheModule {
-  @Override
-  protected void configure() {
-    persist(ExternalIdCacheImpl.CACHE_NAME, ObjectId.class, new TypeLiteral<AllExternalIds>() {})
-        // The cached data is potentially pretty large and we are always only interested
-        // in the latest value. However, due to a race condition, it is possible for different
-        // threads to observe different values of the meta ref, and hence request different keys
-        // from the cache. Extend the cache size by 1 to cover this case, but expire the extra
-        // object after a short period of time, since it may be a potentially large amount of
-        // memory.
-        // When loading a new value because the primary data advanced, we want to leverage the old
-        // cache state to recompute only what changed. This doesn't affect cache size though as
-        // Guava calls the loader first and evicts later on.
-        .maximumWeight(2)
-        .expireFromMemoryAfterAccess(Duration.ofMinutes(1))
-        .diskLimit(-1)
-        .version(1)
-        .keySerializer(ObjectIdCacheSerializer.INSTANCE)
-        .valueSerializer(AllExternalIds.Serializer.INSTANCE);
-
-    bind(ExternalIdCacheImpl.class);
-    bind(ExternalIdCache.class).to(ExternalIdCacheImpl.class);
-  }
-}
diff --git a/java/com/google/gerrit/server/account/externalids/storage/notedb/ExternalIdsNoteDbImpl.java b/java/com/google/gerrit/server/account/externalids/storage/notedb/ExternalIdsNoteDbImpl.java
index 7a2945c..4c26442 100644
--- a/java/com/google/gerrit/server/account/externalids/storage/notedb/ExternalIdsNoteDbImpl.java
+++ b/java/com/google/gerrit/server/account/externalids/storage/notedb/ExternalIdsNoteDbImpl.java
@@ -21,7 +21,6 @@
 import com.google.gerrit.common.Nullable;
 import com.google.gerrit.entities.Account;
 import com.google.gerrit.server.account.externalids.ExternalId;
-import com.google.gerrit.server.account.externalids.ExternalIdCache;
 import com.google.gerrit.server.account.externalids.ExternalIdKeyFactory;
 import com.google.gerrit.server.account.externalids.ExternalIds;
 import com.google.gerrit.server.config.AuthConfig;
@@ -47,21 +46,15 @@
   @Inject
   ExternalIdsNoteDbImpl(
       ExternalIdReader externalIdReader,
-      ExternalIdCache externalIdCache,
+      Optional<ExternalIdCacheImpl> externalIdCacheImpl,
       ExternalIdKeyFactory externalIdKeyFactory,
       AuthConfig authConfig) {
     this.externalIdReader = externalIdReader;
-    if (externalIdCache instanceof ExternalIdCacheImpl) {
-      this.externalIdCache = (ExternalIdCacheImpl) externalIdCache;
-    } else if (externalIdCache instanceof DisabledExternalIdCache) {
-      // Supported case for testing only. Non of the disabled cache methods should be called, so
-      // it's safe to not assign the var.
-      this.externalIdCache = null;
-    } else {
-      throw new IllegalStateException(
-          "The cache provided in ExternalIdsNoteDbImpl should be either ExternalIdCacheImpl or"
-              + " DisabledExternalIdCache");
-    }
+    this.externalIdCache =
+        externalIdCacheImpl.orElse(
+            // Supported case for tests or Google implementation. None of the disabled cache methods
+            // should be called from these flows, so it's safe to not assign the var.
+            null);
     this.externalIdKeyFactory = externalIdKeyFactory;
     this.authConfig = authConfig;
   }
diff --git a/java/com/google/gerrit/server/config/GerritGlobalModule.java b/java/com/google/gerrit/server/config/GerritGlobalModule.java
index 2dbe45e..1f0bd6e 100644
--- a/java/com/google/gerrit/server/config/GerritGlobalModule.java
+++ b/java/com/google/gerrit/server/config/GerritGlobalModule.java
@@ -109,7 +109,6 @@
 import com.google.gerrit.server.account.ServiceUserClassifierImpl;
 import com.google.gerrit.server.account.VersionedAuthorizedKeys;
 import com.google.gerrit.server.account.externalids.ExternalIdModule;
-import com.google.gerrit.server.account.externalids.storage.notedb.ExternalIdCacheModule;
 import com.google.gerrit.server.approval.ApprovalsUtil;
 import com.google.gerrit.server.auth.AuthBackend;
 import com.google.gerrit.server.auth.UniversalAuthBackend;
@@ -219,6 +218,7 @@
 import com.google.gerrit.server.submitrequirement.predicate.DistinctVotersPredicate;
 import com.google.gerrit.server.submitrequirement.predicate.FileEditsPredicate;
 import com.google.gerrit.server.submitrequirement.predicate.HasSubmoduleUpdatePredicate;
+import com.google.gerrit.server.submitrequirement.predicate.SubmitRequirementLabelExtensionPredicate;
 import com.google.gerrit.server.tools.ToolsCatalog;
 import com.google.gerrit.server.update.BatchUpdate;
 import com.google.gerrit.server.util.IdGenerator;
@@ -279,7 +279,6 @@
     install(new AccessControlModule());
     install(new AccountModule());
     install(new CmdLineParserModule());
-    install(new ExternalIdCacheModule());
     install(new ExternalIdModule());
     install(new GitModule());
     install(new GroupDbModule());
@@ -303,6 +302,7 @@
     factory(ChangeJson.AssistedFactory.class);
     factory(ChangeIsVisibleToPredicate.Factory.class);
     factory(DistinctVotersPredicate.Factory.class);
+    factory(SubmitRequirementLabelExtensionPredicate.Factory.class);
     factory(HasSubmoduleUpdatePredicate.Factory.class);
     factory(DeadlineChecker.Factory.class);
     factory(EmailNewPatchSet.Factory.class);
diff --git a/java/com/google/gerrit/server/config/GerritIsReplicaProvider.java b/java/com/google/gerrit/server/config/GerritIsReplicaProvider.java
index f242a50..f53d718 100644
--- a/java/com/google/gerrit/server/config/GerritIsReplicaProvider.java
+++ b/java/com/google/gerrit/server/config/GerritIsReplicaProvider.java
@@ -26,14 +26,16 @@
  */
 public final class GerritIsReplicaProvider implements Provider<Boolean> {
   private final Config config;
+  private final boolean replicaOption;
 
   @Inject
-  public GerritIsReplicaProvider(@GerritServerConfig Config config) {
+  public GerritIsReplicaProvider(@GerritServerConfig Config config, GerritOptions opts) {
     this.config = config;
+    this.replicaOption = opts.replica();
   }
 
   @Override
   public Boolean get() {
-    return ReplicaUtil.isReplica(config);
+    return replicaOption || ReplicaUtil.isReplica(config);
   }
 }
diff --git a/java/com/google/gerrit/server/config/GerritOptions.java b/java/com/google/gerrit/server/config/GerritOptions.java
index 0390620..30633a5 100644
--- a/java/com/google/gerrit/server/config/GerritOptions.java
+++ b/java/com/google/gerrit/server/config/GerritOptions.java
@@ -20,16 +20,18 @@
 
 public class GerritOptions {
   private final boolean headless;
-  private final boolean slave;
+  private final boolean replica;
   private final Optional<String> devCdn;
 
-  public GerritOptions(boolean headless, boolean slave) {
-    this(headless, slave, null);
+  public static GerritOptions DEFAULT = new GerritOptions(false, false);
+
+  public GerritOptions(boolean headless, boolean replica) {
+    this(headless, replica, null);
   }
 
-  public GerritOptions(boolean headless, boolean slave, @Nullable String devCdn) {
+  public GerritOptions(boolean headless, boolean replica, @Nullable String devCdn) {
     this.headless = headless;
-    this.slave = slave;
+    this.replica = replica;
     this.devCdn = headless ? Optional.empty() : Optional.ofNullable(Strings.emptyToNull(devCdn));
   }
 
@@ -37,8 +39,12 @@
     return headless;
   }
 
+  public boolean replica() {
+    return replica;
+  }
+
   public boolean enableMasterFeatures() {
-    return !slave;
+    return !replica;
   }
 
   public Optional<String> devCdn() {
diff --git a/java/com/google/gerrit/server/group/PeriodicGroupIndexer.java b/java/com/google/gerrit/server/group/PeriodicGroupIndexer.java
index 72e15ee..d466041 100644
--- a/java/com/google/gerrit/server/group/PeriodicGroupIndexer.java
+++ b/java/com/google/gerrit/server/group/PeriodicGroupIndexer.java
@@ -21,20 +21,12 @@
 import com.google.common.flogger.FluentLogger;
 import com.google.gerrit.entities.AccountGroup;
 import com.google.gerrit.entities.GroupReference;
-import com.google.gerrit.extensions.events.LifecycleListener;
-import com.google.gerrit.lifecycle.LifecycleModule;
 import com.google.gerrit.server.config.AllUsersName;
-import com.google.gerrit.server.config.GerritServerConfig;
-import com.google.gerrit.server.config.ScheduleConfig;
-import com.google.gerrit.server.config.ScheduleConfig.Schedule;
 import com.google.gerrit.server.git.GitRepositoryManager;
-import com.google.gerrit.server.git.WorkQueue;
 import com.google.gerrit.server.group.db.GroupNameNotes;
 import com.google.gerrit.server.index.group.GroupIndexer;
 import com.google.inject.Inject;
 import com.google.inject.Provider;
-import java.util.concurrent.TimeUnit;
-import org.eclipse.jgit.lib.Config;
 import org.eclipse.jgit.lib.Repository;
 
 /**
@@ -59,52 +51,6 @@
 public class PeriodicGroupIndexer implements Runnable {
   private static final FluentLogger logger = FluentLogger.forEnclosingClass();
 
-  public static class PeriodicGroupIndexerModule extends LifecycleModule {
-    @Override
-    protected void configure() {
-      listener().to(Lifecycle.class);
-    }
-  }
-
-  private static class Lifecycle implements LifecycleListener {
-    private final Config cfg;
-    private final WorkQueue queue;
-    private final PeriodicGroupIndexer runner;
-
-    @Inject
-    Lifecycle(@GerritServerConfig Config cfg, WorkQueue queue, PeriodicGroupIndexer runner) {
-      this.cfg = cfg;
-      this.queue = queue;
-      this.runner = runner;
-    }
-
-    @Override
-    public void start() {
-      boolean runOnStartup = cfg.getBoolean("index", "scheduledIndexer", "runOnStartup", true);
-      if (runOnStartup) {
-        runner.run();
-      }
-
-      boolean isEnabled = cfg.getBoolean("index", "scheduledIndexer", "enabled", true);
-      if (!isEnabled) {
-        logger.atWarning().log("index.scheduledIndexer is disabled");
-        return;
-      }
-
-      Schedule schedule =
-          ScheduleConfig.builder(cfg, "index")
-              .setSubsection("scheduledIndexer")
-              .buildSchedule()
-              .orElseGet(() -> Schedule.createOrFail(TimeUnit.MINUTES.toMillis(5), "00:00"));
-      queue.scheduleAtFixedRate(runner, schedule);
-    }
-
-    @Override
-    public void stop() {
-      // handled by WorkQueue.stop() already
-    }
-  }
-
   private final AllUsersName allUsersName;
   private final GitRepositoryManager repoManager;
   private final Provider<GroupIndexer> groupIndexerProvider;
diff --git a/java/com/google/gerrit/server/index/scheduler/PeriodicIndexScheduler.java b/java/com/google/gerrit/server/index/scheduler/PeriodicIndexScheduler.java
new file mode 100644
index 0000000..ab4b8fc
--- /dev/null
+++ b/java/com/google/gerrit/server/index/scheduler/PeriodicIndexScheduler.java
@@ -0,0 +1,102 @@
+// Copyright (C) 2024 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package com.google.gerrit.server.index.scheduler;
+
+import com.google.common.flogger.FluentLogger;
+import com.google.gerrit.extensions.events.LifecycleListener;
+import com.google.gerrit.lifecycle.LifecycleModule;
+import com.google.gerrit.server.config.GerritIsReplica;
+import com.google.gerrit.server.config.GerritServerConfig;
+import com.google.gerrit.server.config.ScheduleConfig;
+import com.google.gerrit.server.config.ScheduleConfig.Schedule;
+import com.google.gerrit.server.git.WorkQueue;
+import com.google.gerrit.server.group.PeriodicGroupIndexer;
+import com.google.inject.Inject;
+import java.util.Set;
+import java.util.concurrent.TimeUnit;
+import org.eclipse.jgit.lib.Config;
+
+public class PeriodicIndexScheduler implements LifecycleListener {
+  private static final FluentLogger logger = FluentLogger.forEnclosingClass();
+
+  public static class Module extends LifecycleModule {
+    @Override
+    protected void configure() {
+      listener().to(PeriodicIndexScheduler.class);
+    }
+  }
+
+  private final Config cfg;
+  private final WorkQueue queue;
+  private final PeriodicGroupIndexer groupIndexer;
+  private final boolean isReplica;
+
+  @Inject
+  PeriodicIndexScheduler(
+      @GerritServerConfig Config cfg,
+      WorkQueue queue,
+      PeriodicGroupIndexer groupIndexer,
+      @GerritIsReplica boolean isReplica) {
+    this.cfg = cfg;
+    this.queue = queue;
+    this.groupIndexer = groupIndexer;
+    this.isReplica = isReplica;
+  }
+
+  @Override
+  public void start() {
+    Subsection s = determineConfigSubsection();
+    boolean runOnStartup = cfg.getBoolean(s.section, s.subsection, "runOnStartup", isReplica);
+    if (runOnStartup) {
+      groupIndexer.run();
+    }
+
+    boolean isEnabled = cfg.getBoolean(s.section, s.subsection, "enabled", isReplica);
+    if (!isEnabled) {
+      logger.atWarning().log("index.scheduledIndexer is disabled");
+      return;
+    }
+
+    Schedule schedule =
+        ScheduleConfig.builder(cfg, s.section)
+            .setSubsection(s.subsection)
+            .buildSchedule()
+            .orElseGet(() -> Schedule.createOrFail(TimeUnit.MINUTES.toMillis(5), "00:00"));
+    queue.scheduleAtFixedRate(groupIndexer, schedule);
+  }
+
+  private Subsection determineConfigSubsection() {
+    Set<String> scheduledIndexerConfig = cfg.getSubsections("scheduledIndexer");
+    if (scheduledIndexerConfig.contains("groups")) {
+      return new Subsection("scheduledIndexer", "groups");
+    }
+    return new Subsection("index", "scheduledIndexer");
+  }
+
+  private static class Subsection {
+    final String section;
+    final String subsection;
+
+    Subsection(String section, String subsection) {
+      this.section = section;
+      this.subsection = subsection;
+    }
+  }
+
+  @Override
+  public void stop() {
+    // handled by WorkQueue.stop() already
+  }
+}
diff --git a/java/com/google/gerrit/server/project/testing/TestLabels.java b/java/com/google/gerrit/server/project/testing/TestLabels.java
index 32b87ec..989b354 100644
--- a/java/com/google/gerrit/server/project/testing/TestLabels.java
+++ b/java/com/google/gerrit/server/project/testing/TestLabels.java
@@ -14,7 +14,6 @@
 
 package com.google.gerrit.server.project.testing;
 
-import com.google.gerrit.entities.LabelFunction;
 import com.google.gerrit.entities.LabelId;
 import com.google.gerrit.entities.LabelType;
 import com.google.gerrit.entities.LabelValue;
@@ -49,7 +48,7 @@
     LabelType.Builder label =
         labelBuilder(
             "Patch-Set-Lock", value(1, "Patch Set Locked"), value(0, "Patch Set Unlocked"));
-    label.setFunction(LabelFunction.PATCH_SET_LOCK);
+    label.setPatchSetLockFunction();
     return label.build();
   }
 
diff --git a/java/com/google/gerrit/server/query/change/ChangeQueryBuilder.java b/java/com/google/gerrit/server/query/change/ChangeQueryBuilder.java
index d598739..9b85582 100644
--- a/java/com/google/gerrit/server/query/change/ChangeQueryBuilder.java
+++ b/java/com/google/gerrit/server/query/change/ChangeQueryBuilder.java
@@ -236,6 +236,7 @@
   public static final String ARG_ID_NON_UPLOADER = "non_uploader";
   public static final String ARG_ID_NON_CONTRIBUTOR = "non_contributor";
   public static final String ARG_COUNT = "count";
+  public static final String ARG_USERS = "users";
   public static final Account.Id OWNER_ACCOUNT_ID = Account.id(0);
   public static final Account.Id NON_UPLOADER_ACCOUNT_ID = Account.id(-1);
   public static final Account.Id NON_CONTRIBUTOR_ACCOUNT_ID = Account.id(-2);
@@ -1108,6 +1109,9 @@
                     "count=%d is not allowed. Maximum allowed value for count is %d.",
                     count, LabelPredicate.MAX_COUNT));
           }
+        } else if (key.equalsIgnoreCase(ARG_USERS)) {
+          throw new QueryParseException(
+              String.format("Cannot use the '%s' argument in search", ARG_USERS));
         } else {
           throw new QueryParseException("Invalid argument identifier '" + pair.getKey() + "'");
         }
diff --git a/java/com/google/gerrit/server/query/change/SubmitRequirementChangeQueryBuilder.java b/java/com/google/gerrit/server/query/change/SubmitRequirementChangeQueryBuilder.java
index cb92ddd..55d3505 100644
--- a/java/com/google/gerrit/server/query/change/SubmitRequirementChangeQueryBuilder.java
+++ b/java/com/google/gerrit/server/query/change/SubmitRequirementChangeQueryBuilder.java
@@ -28,13 +28,16 @@
 import com.google.gerrit.server.submitrequirement.predicate.RegexAuthorEmailPredicate;
 import com.google.gerrit.server.submitrequirement.predicate.RegexCommitterEmailPredicate;
 import com.google.gerrit.server.submitrequirement.predicate.RegexUploaderEmailPredicateFactory;
+import com.google.gerrit.server.submitrequirement.predicate.SubmitRequirementLabelExtensionPredicate;
 import com.google.inject.Inject;
+import java.io.IOException;
 import java.util.List;
 import java.util.Locale;
 import java.util.Set;
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
 import java.util.regex.PatternSyntaxException;
+import org.eclipse.jgit.errors.ConfigInvalidException;
 
 /**
  * A query builder for submit requirement expressions that includes all {@link ChangeQueryBuilder}
@@ -48,6 +51,8 @@
       new QueryBuilder.Definition<>(SubmitRequirementChangeQueryBuilder.class);
 
   private final DistinctVotersPredicate.Factory distinctVotersPredicateFactory;
+  private final SubmitRequirementLabelExtensionPredicate.Factory
+      submitRequirementLabelExtensionPredicateFactory;
   private final HasSubmoduleUpdatePredicate.Factory hasSubmoduleUpdateFactory;
 
   /**
@@ -70,11 +75,15 @@
   SubmitRequirementChangeQueryBuilder(
       Arguments args,
       DistinctVotersPredicate.Factory distinctVotersPredicateFactory,
+      SubmitRequirementLabelExtensionPredicate.Factory
+          submitRequirementLabelExtensionPredicateFactory,
       FileEditsPredicate.Factory fileEditsPredicateFactory,
       HasSubmoduleUpdatePredicate.Factory hasSubmoduleUpdateFactory,
       RegexUploaderEmailPredicateFactory regexUploaderEmailPredicateFactory) {
     super(def, args);
     this.distinctVotersPredicateFactory = distinctVotersPredicateFactory;
+    this.submitRequirementLabelExtensionPredicateFactory =
+        submitRequirementLabelExtensionPredicateFactory;
     this.fileEditsPredicateFactory = fileEditsPredicateFactory;
     this.hasSubmoduleUpdateFactory = hasSubmoduleUpdateFactory;
     this.regexUploaderEmailPredicateFactory = regexUploaderEmailPredicateFactory;
@@ -150,6 +159,16 @@
     return distinctVotersPredicateFactory.create(value);
   }
 
+  @Override
+  public Predicate<ChangeData> label(String value)
+      throws QueryParseException, IOException, ConfigInvalidException {
+    if (SubmitRequirementLabelExtensionPredicate.matches(value)) {
+      return submitRequirementLabelExtensionPredicateFactory.create(value);
+    }
+    SubmitRequirementLabelExtensionPredicate.validateIfNoMatch(value);
+    return super.label(value);
+  }
+
   /**
    * A SR operator that can match with file path and content pattern. The value should be of the
    * form:
diff --git a/java/com/google/gerrit/server/restapi/change/ReplyAttentionSetUpdates.java b/java/com/google/gerrit/server/restapi/change/ReplyAttentionSetUpdates.java
index bc47adc..2803c0e 100644
--- a/java/com/google/gerrit/server/restapi/change/ReplyAttentionSetUpdates.java
+++ b/java/com/google/gerrit/server/restapi/change/ReplyAttentionSetUpdates.java
@@ -14,9 +14,11 @@
 
 package com.google.gerrit.server.restapi.change;
 
+import static com.google.common.collect.ImmutableList.toImmutableList;
 import static com.google.common.collect.ImmutableSet.toImmutableSet;
 import static java.util.Objects.requireNonNull;
 
+import com.google.common.collect.ImmutableList;
 import com.google.common.collect.ImmutableSet;
 import com.google.common.collect.Sets;
 import com.google.common.collect.Sets.SetView;
@@ -25,6 +27,8 @@
 import com.google.gerrit.entities.Account;
 import com.google.gerrit.entities.AttentionSetUpdate;
 import com.google.gerrit.entities.HumanComment;
+import com.google.gerrit.entities.LabelId;
+import com.google.gerrit.entities.LabelValue;
 import com.google.gerrit.entities.PatchSet;
 import com.google.gerrit.extensions.api.changes.AttentionSetInput;
 import com.google.gerrit.extensions.api.changes.ReviewInput;
@@ -48,15 +52,17 @@
 import com.google.gerrit.server.permissions.ChangePermission;
 import com.google.gerrit.server.permissions.PermissionBackend;
 import com.google.gerrit.server.permissions.PermissionBackendException;
+import com.google.gerrit.server.project.ProjectCache;
 import com.google.gerrit.server.update.BatchUpdate;
 import com.google.gerrit.server.util.AttentionSetUtil;
 import com.google.gerrit.server.util.time.TimeUtil;
 import com.google.inject.Inject;
 import java.io.IOException;
 import java.util.ArrayList;
-import java.util.Collection;
 import java.util.HashSet;
+import java.util.LinkedHashSet;
 import java.util.List;
+import java.util.Optional;
 import java.util.Set;
 import java.util.stream.Collectors;
 import java.util.stream.Stream;
@@ -76,6 +82,7 @@
   private final ServiceUserClassifier serviceUserClassifier;
   private final CommentsUtil commentsUtil;
   private final DraftCommentsReader draftCommentsReader;
+  private final ProjectCache projectCache;
 
   @Inject
   ReplyAttentionSetUpdates(
@@ -86,7 +93,8 @@
       AccountResolver accountResolver,
       ServiceUserClassifier serviceUserClassifier,
       CommentsUtil commentsUtil,
-      DraftCommentsReader draftCommentsReader) {
+      DraftCommentsReader draftCommentsReader,
+      ProjectCache projectCache) {
     this.permissionBackend = permissionBackend;
     this.addToAttentionSetOpFactory = addToAttentionSetOpFactory;
     this.removeFromAttentionSetOpFactory = removeFromAttentionSetOpFactory;
@@ -95,6 +103,7 @@
     this.serviceUserClassifier = serviceUserClassifier;
     this.commentsUtil = commentsUtil;
     this.draftCommentsReader = draftCommentsReader;
+    this.projectCache = projectCache;
   }
 
   /** Adjusts the attention set but only based on the automatic rules. */
@@ -235,7 +244,7 @@
 
     addOwnerAndUploaderToAttentionSetIfSomeoneElseReplied(
         bu, postReviewOp, changeNotes, currentUser, readyForReview, allNewComments);
-    addAllAuthorsOfCommentThreads(bu, changeNotes, allNewComments);
+    addAllAuthorsOfCommentThreads(bu, changeNotes, allNewComments, currentUser);
   }
 
   /**
@@ -329,17 +338,71 @@
 
   /** Adds all authors of all comment threads that received a reply during this update */
   private void addAllAuthorsOfCommentThreads(
-      BatchUpdate bu, ChangeNotes changeNotes, ImmutableSet<HumanComment> allNewComments) {
-    List<HumanComment> publishedComments = commentsUtil.publishedHumanCommentsByChange(changeNotes);
-    ImmutableSet<CommentThread<HumanComment>> repliedToCommentThreads =
-        CommentThreads.forComments(publishedComments).getThreadsForChildren(allNewComments);
+      BatchUpdate bu,
+      ChangeNotes changeNotes,
+      ImmutableSet<HumanComment> allNewComments,
+      CurrentUser currentUser) {
+    boolean isOwnerOrUploader =
+        currentUser.getAccountId().equals(changeNotes.getChange().getOwner())
+            || currentUser.getAccountId().equals(changeNotes.getCurrentPatchSet().uploader());
 
-    ImmutableSet<Account.Id> repliedToUsers =
-        repliedToCommentThreads.stream()
-            .map(CommentThread::comments)
-            .flatMap(Collection::stream)
-            .map(comment -> comment.author.getId())
-            .collect(toImmutableSet());
+    boolean noCRLabel = false;
+    Optional<LabelValue> maxCRValue =
+        projectCache
+            .get(changeNotes.getChange().getProject())
+            .orElseThrow(
+                () ->
+                    new IllegalStateException(
+                        String.format(
+                            "Couldn't find project \"%s\" for a change \"%s\"",
+                            changeNotes.getChange().getProject(), changeNotes.getChangeId())))
+            .getLabelTypes(changeNotes)
+            .byLabel(LabelId.CODE_REVIEW)
+            .map(l -> l.getMax());
+
+    ImmutableSet<Account.Id> maxCrApprovers;
+    if (maxCRValue.isPresent()) {
+      maxCrApprovers =
+          changeNotes.getApprovals().all().get(changeNotes.getCurrentPatchSet().id()).stream()
+              .filter(
+                  a ->
+                      a.label().equals(LabelId.CODE_REVIEW)
+                          && a.value() == maxCRValue.get().getValue())
+              .map(a -> a.accountId())
+              .collect(toImmutableSet());
+    } else {
+      noCRLabel = true;
+      maxCrApprovers = ImmutableSet.of();
+    }
+
+    // Include newly published comments, when building threads.
+    ImmutableList<HumanComment> relevantComments =
+        Stream.concat(
+                commentsUtil.publishedHumanCommentsByChange(changeNotes).stream(),
+                allNewComments.stream())
+            .collect(toImmutableList());
+    ImmutableSet<CommentThread<HumanComment>> repliedToCommentThreads =
+        CommentThreads.forComments(relevantComments).getThreadsForChildren(allNewComments);
+
+    LinkedHashSet<Account.Id> repliedToUsers = new LinkedHashSet<>();
+    for (CommentThread<HumanComment> thread : repliedToCommentThreads) {
+      // If thread is resolved, we only bring back the commenters who have not yet left max
+      // Code-Review vote.
+      // If Owner replied but didn't resolve, we assume clarification was asked add everyone on the
+      // thread to attention set.
+      boolean ignoreVoteCheck = noCRLabel || (thread.unresolved() && isOwnerOrUploader);
+      if (thread.unresolved() && !isOwnerOrUploader) {
+        // Reviewer replied. Owner is still the one to act. No need to add commenters.
+        continue;
+      }
+      thread.comments().stream()
+          .map(comment -> comment.author.getId())
+          .filter(
+              a ->
+                  !a.equals(currentUser.getAccountId())
+                      && (ignoreVoteCheck || !maxCrApprovers.contains(a)))
+          .forEach(repliedToUsers::add);
+    }
     ImmutableSet<Account.Id> possibleUsersToAdd = approvalsUtil.getReviewers(changeNotes).all();
     SetView<Account.Id> usersToAdd = Sets.intersection(possibleUsersToAdd, repliedToUsers);
 
diff --git a/java/com/google/gerrit/server/submitrequirement/predicate/SubmitRequirementLabelExtensionPredicate.java b/java/com/google/gerrit/server/submitrequirement/predicate/SubmitRequirementLabelExtensionPredicate.java
new file mode 100644
index 0000000..389c7f4
--- /dev/null
+++ b/java/com/google/gerrit/server/submitrequirement/predicate/SubmitRequirementLabelExtensionPredicate.java
@@ -0,0 +1,213 @@
+// Copyright (C) 2024 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package com.google.gerrit.server.submitrequirement.predicate;
+
+import static com.google.common.collect.ImmutableSet.toImmutableSet;
+
+import com.google.common.base.Enums;
+import com.google.common.collect.ImmutableSet;
+import com.google.common.flogger.FluentLogger;
+import com.google.common.primitives.Ints;
+import com.google.errorprone.annotations.CanIgnoreReturnValue;
+import com.google.gerrit.entities.Account;
+import com.google.gerrit.entities.SubmitRecord;
+import com.google.gerrit.index.query.QueryParseException;
+import com.google.gerrit.server.account.ServiceUserClassifier;
+import com.google.gerrit.server.notedb.ReviewerStateInternal;
+import com.google.gerrit.server.query.change.ChangeData;
+import com.google.gerrit.server.query.change.ChangeQueryBuilder.Arguments;
+import com.google.gerrit.server.query.change.LabelPredicate;
+import com.google.gerrit.server.query.change.SubmitRequirementPredicate;
+import com.google.inject.Inject;
+import com.google.inject.assistedinject.Assisted;
+import java.util.Locale;
+import java.util.Optional;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+/**
+ * Extensions of the {@link LabelPredicate} that are only available for submit requirement
+ * expressions, but not for search.
+ *
+ * <p>Supported extensions:
+ *
+ * <ul>
+ *   <li>"users=human_reviewers" arg, e.g. "label:Code-Review=MAX,users=human_reviewers" matches
+ *       changes where all human reviewers have approved the change with Code-Review=MAX
+ * </ul>
+ */
+public class SubmitRequirementLabelExtensionPredicate extends SubmitRequirementPredicate {
+  private static final FluentLogger logger = FluentLogger.forEnclosingClass();
+
+  public interface Factory {
+    SubmitRequirementLabelExtensionPredicate create(String value) throws QueryParseException;
+  }
+
+  private static final Pattern PATTERN = Pattern.compile("(?<label>[^,]*),users=human_reviewers$");
+  private static final Pattern PATTERN_LABEL =
+      Pattern.compile("(?<label>[^,<>=]*)(?<op>=|<=|>=|<|>)(?<value>[^,]*)");
+
+  public static boolean matches(String value) {
+    return PATTERN.matcher(value).matches();
+  }
+
+  public static void validateIfNoMatch(String value) throws QueryParseException {
+    if (value.contains(",users=")) {
+      throw new QueryParseException(
+          "Cannot use the 'users' argument in conjunction with other arguments ('count', 'user',"
+              + " group')");
+    }
+  }
+
+  private final Arguments args;
+  private final ServiceUserClassifier serviceUserClassifier;
+  private final String label;
+
+  @Inject
+  SubmitRequirementLabelExtensionPredicate(
+      Arguments args, ServiceUserClassifier serviceUserClassifier, @Assisted String value)
+      throws QueryParseException {
+    super("label", value);
+    this.args = args;
+    this.serviceUserClassifier = serviceUserClassifier;
+
+    Matcher m = PATTERN.matcher(value);
+    if (!m.matches()) {
+      throw new QueryParseException(
+          String.format("invalid value for '%s': %s", getOperator(), value));
+    }
+    this.label = validateLabel(m.group("label"));
+  }
+
+  @CanIgnoreReturnValue
+  private String validateLabel(String label) throws QueryParseException {
+    int eq = label.indexOf('=');
+
+    if (eq <= 0) {
+      return label;
+    }
+
+    String statusName = label.substring(eq + 1).toUpperCase(Locale.US);
+    SubmitRecord.Label.Status status =
+        Enums.getIfPresent(SubmitRecord.Label.Status.class, statusName).orNull();
+    if (status != null) {
+      // We would need to use SubmitRecordPredicate but can't because it doesn't implement
+      // Matchable.
+      throw new QueryParseException(
+          "Cannot use the 'users=human_reviewers' argument in conjunction with a submit record"
+              + " label status");
+    }
+    return label;
+  }
+
+  @Override
+  public boolean match(ChangeData cd) {
+    if (!cd.reviewersByEmail().byState(ReviewerStateInternal.REVIEWER).isEmpty()
+        && !matchZeroVotes(label)) {
+      // Reviewers by email are reviewers that don't have a Gerrit account. Without Gerrit
+      // account they cannot vote on the change, which means changes that have any such
+      // reviewers never match when we expect a vote != 0 from all reviewers.
+      logger.atFine().log(
+          "change %s doesn't match since there are reviewers by email"
+              + " (that don't have a matching approval): %s",
+          cd.change().getChangeId(), cd.reviewersByEmail().byState(ReviewerStateInternal.REVIEWER));
+      return false;
+    }
+
+    ImmutableSet<Account.Id> humanReviewers =
+        cd.reviewers().byState(ReviewerStateInternal.REVIEWER).stream()
+            // Ignore the change owner (if the change owner voted on their own change they are
+            // technically a reviewer).
+            .filter(accountId -> !accountId.equals(cd.change().getOwner()))
+            // Ignore reviewers that are service users.
+            .filter(accountId -> !serviceUserClassifier.isServiceUser(accountId))
+            .collect(toImmutableSet());
+
+    if (humanReviewers.isEmpty()) {
+      // a review from human reviewers is required, but no human reviewers are present
+      return false;
+    }
+
+    for (Account.Id reviewer : humanReviewers) {
+      if (!new LabelPredicate(
+              args,
+              label,
+              ImmutableSet.of(reviewer),
+              /* group= */ null,
+              /* count= */ null,
+              /* countOp= */ null)
+          .match(cd)) {
+        logger.atFine().log(
+            "change %s doesn't match because it misses matching approvals from: %s",
+            cd.change().getChangeId(), reviewer);
+        return false;
+      }
+    }
+
+    logger.atFine().log(
+        "change %s matches because it has matching approvals from all human reviewers: %s",
+        cd.change().getChangeId(), humanReviewers);
+    return true;
+  }
+
+  private boolean matchZeroVotes(String label) {
+    Matcher m = PATTERN_LABEL.matcher(label);
+    if (!m.matches()) {
+      return false;
+    }
+
+    String op = m.group("op");
+    String value = m.group("value");
+
+    Optional<Integer> intValue = Optional.ofNullable(Ints.tryParse(value));
+
+    if (op.equals("=") && (intValue.isPresent() && intValue.get() == 0)) {
+      return true;
+    } else if (op.equals("<=")) {
+      if (intValue.isPresent() && intValue.get() >= 0) {
+        return true;
+      } else if (value.equals("MAX")) {
+        return true;
+      }
+      return false;
+    } else if (op.equals("<")) {
+      if (intValue.isPresent() && intValue.get() > 0) {
+        return true;
+      } else if (value.equals("MAX")) {
+        return true;
+      }
+    } else if (op.equals(">=")) {
+      if (intValue.isPresent() && intValue.get() <= 0) {
+        return true;
+      } else if (value.equals("MIN")) {
+        return true;
+      }
+      return false;
+    } else if (op.equals(">")) {
+      if (intValue.isPresent() && intValue.get() < 0) {
+        return true;
+      } else if (value.equals("MIN")) {
+        return true;
+      }
+    }
+
+    return false;
+  }
+
+  @Override
+  public int getCost() {
+    return 1;
+  }
+}
diff --git a/java/com/google/gerrit/testing/InMemoryModule.java b/java/com/google/gerrit/testing/InMemoryModule.java
index c1192f6..789655f 100644
--- a/java/com/google/gerrit/testing/InMemoryModule.java
+++ b/java/com/google/gerrit/testing/InMemoryModule.java
@@ -49,6 +49,7 @@
 import com.google.gerrit.server.Sequence.LightweightGroups;
 import com.google.gerrit.server.account.AccountCacheImpl;
 import com.google.gerrit.server.account.GroupBackend;
+import com.google.gerrit.server.account.externalids.storage.notedb.ExternalIdCacheImpl;
 import com.google.gerrit.server.account.storage.notedb.AccountNoteDbReadStorageModule;
 import com.google.gerrit.server.account.storage.notedb.AccountNoteDbWriteStorageModule;
 import com.google.gerrit.server.api.GerritApiModule;
@@ -208,6 +209,8 @@
     install(cfgInjector.getInstance(GerritGlobalModule.class));
     install(new AccountNoteDbWriteStorageModule());
     install(new AccountNoteDbReadStorageModule());
+    install(new ExternalIdCacheImpl.ExternalIdCacheModule());
+    install(new ExternalIdCacheImpl.ExternalIdCacheBindingModule());
     install(new RepoSequenceModule());
     install(new FromAddressGeneratorProvider.UserAddressGenModule());
     install(new NoteDbDraftCommentsModule());
diff --git a/javatests/com/google/gerrit/acceptance/api/change/PostReviewIT.java b/javatests/com/google/gerrit/acceptance/api/change/PostReviewIT.java
index bbe7cc3..56910e2 100644
--- a/javatests/com/google/gerrit/acceptance/api/change/PostReviewIT.java
+++ b/javatests/com/google/gerrit/acceptance/api/change/PostReviewIT.java
@@ -46,7 +46,6 @@
 import com.google.gerrit.entities.Account;
 import com.google.gerrit.entities.AttentionSetUpdate;
 import com.google.gerrit.entities.Change;
-import com.google.gerrit.entities.LabelFunction;
 import com.google.gerrit.entities.LabelId;
 import com.google.gerrit.entities.LabelType;
 import com.google.gerrit.entities.PatchSet;
@@ -618,7 +617,7 @@
       LabelType.Builder verified =
           labelBuilder(
                   LabelId.VERIFIED, value(1, "Passes"), value(0, "No score"), value(-1, "Failed"))
-              .setFunction(LabelFunction.NO_BLOCK);
+              .setNoBlockFunction();
       u.getConfig().upsertLabelType(verified.build());
       u.save();
     }
diff --git a/javatests/com/google/gerrit/acceptance/api/change/StickyApprovalsIT.java b/javatests/com/google/gerrit/acceptance/api/change/StickyApprovalsIT.java
index 2cc2798..6dea5be 100644
--- a/javatests/com/google/gerrit/acceptance/api/change/StickyApprovalsIT.java
+++ b/javatests/com/google/gerrit/acceptance/api/change/StickyApprovalsIT.java
@@ -52,7 +52,6 @@
 import com.google.gerrit.common.RawInputUtil;
 import com.google.gerrit.entities.Account;
 import com.google.gerrit.entities.Change;
-import com.google.gerrit.entities.LabelFunction;
 import com.google.gerrit.entities.LabelId;
 import com.google.gerrit.entities.LabelType;
 import com.google.gerrit.entities.PatchSet;
@@ -1233,10 +1232,9 @@
         .contains("Code-Review+1 by User");
   }
 
-  @SuppressWarnings("deprecation")
   @Test
   public void sticky_copiedToLatestPatchSetFromSubmitRecords() throws Exception {
-    updateVerifiedLabel(b -> b.setFunction(LabelFunction.NO_BLOCK));
+    updateVerifiedLabel(b -> b.setNoBlockFunction());
 
     // This test is covering the backfilling logic for changes which have been submitted, based on
     // copied approvals, before Gerrit persisted copied votes as Copied-Label footers in NoteDb. It
diff --git a/javatests/com/google/gerrit/acceptance/api/change/SubmitRequirementIT.java b/javatests/com/google/gerrit/acceptance/api/change/SubmitRequirementIT.java
index a5d86ce..44b0179 100644
--- a/javatests/com/google/gerrit/acceptance/api/change/SubmitRequirementIT.java
+++ b/javatests/com/google/gerrit/acceptance/api/change/SubmitRequirementIT.java
@@ -637,6 +637,252 @@
   }
 
   @Test
+  public void submitRequirement_wantCodeReviewFromHumanReviewers() throws Exception {
+    projectOperations
+        .project(project)
+        .forUpdate()
+        .add(allowLabel("Code-Review").ref("refs/*").group(REGISTERED_USERS).range(-2, 2))
+        .update();
+
+    configSubmitRequirement(
+        project,
+        SubmitRequirement.builder()
+            .setName("Code-Review")
+            .setSubmittabilityExpression(
+                SubmitRequirementExpression.create("label:Code-Review=MAX"))
+            .setAllowOverrideInChildProjects(false)
+            .build());
+    configSubmitRequirement(
+        project,
+        SubmitRequirement.builder()
+            .setName("Want-Code-Review-From-All")
+            .setApplicabilityExpression(
+                Optional.of(
+                    SubmitRequirementExpression.create(
+                        "-label:Code-Review>=1,users=human_reviewers")))
+            .setSubmittabilityExpression(
+                SubmitRequirementExpression.create("label:Code-Review>=1,users=human_reviewers"))
+            .setAllowOverrideInChildProjects(false)
+            .build());
+
+    PushOneCommit.Result r = createChange();
+    String changeId = r.getChangeId();
+
+    // Code-Review is unsatisfied because there is no Code-Review+2 approval.
+    assertSubmitRequirementStatus(
+        gApi.changes().id(changeId).get().submitRequirements,
+        "Code-Review",
+        Status.UNSATISFIED,
+        /* isLegacy= */ false);
+
+    // Want-Code-Review-From-All is unsatisfied (since a review from reviewers is required but no
+    // reviewer is present on the change).
+    assertSubmitRequirementStatus(
+        gApi.changes().id(changeId).get().submitRequirements,
+        "Want-Code-Review-From-All",
+        Status.UNSATISFIED,
+        /* isLegacy= */ false);
+
+    // Add some reviewers
+    TestAccount reviewer1 = accountCreator.create("reviewer1");
+    gApi.changes().id(changeId).addReviewer("reviewer1");
+    TestAccount reviewer2 = accountCreator.create("reviewer2");
+    gApi.changes().id(changeId).addReviewer("reviewer2");
+
+    // Code-Review is unsatisfied because there is no Code-Review+2 approval.
+    assertSubmitRequirementStatus(
+        gApi.changes().id(changeId).get().submitRequirements,
+        "Code-Review",
+        Status.UNSATISFIED,
+        /* isLegacy= */ false);
+
+    // Want-Code-Review-From-All is unsatisfied since there are reviewers on the change that
+    // didn't approve it yet.
+    assertSubmitRequirementStatus(
+        gApi.changes().id(changeId).get().submitRequirements,
+        "Want-Code-Review-From-All",
+        Status.UNSATISFIED,
+        /* isLegacy= */ false);
+
+    requestScopeOperations.setApiUser(reviewer1.id());
+    voteLabel(changeId, "Code-Review", 2);
+
+    // Code-Review is satisfied because there is Code-Review+2 approval from reviewer1.
+    assertSubmitRequirementStatus(
+        gApi.changes().id(changeId).get().submitRequirements,
+        "Code-Review",
+        Status.SATISFIED,
+        /* isLegacy= */ false);
+
+    // Want-Code-Review-From-All is unsatisfied since there is no approval from reviewer2.
+    assertSubmitRequirementStatus(
+        gApi.changes().id(changeId).get().submitRequirements,
+        "Want-Code-Review-From-All",
+        Status.UNSATISFIED,
+        /* isLegacy= */ false);
+
+    requestScopeOperations.setApiUser(reviewer2.id());
+    voteLabel(changeId, "Code-Review", 2);
+
+    // Code-Review is satisfied because there are Code-Review+2 approvals from reviewer1 and
+    // reviewer2.
+    assertSubmitRequirementStatus(
+        gApi.changes().id(changeId).get().submitRequirements,
+        "Code-Review",
+        Status.SATISFIED,
+        /* isLegacy= */ false);
+
+    // Want-Code-Review-From-All is not applicable since there are approval from all reviewers
+    // (reviewer1 and reviewer2) which makes "label:Code-Review=MAX,users=human_reviewers"
+    // satisfied.
+    assertSubmitRequirementStatus(
+        gApi.changes().id(changeId).get().submitRequirements,
+        "Want-Code-Review-From-All",
+        Status.NOT_APPLICABLE,
+        /* isLegacy= */ false);
+
+    // Add another reviewer
+    TestAccount reviewer3 = accountCreator.create("reviewer3");
+    gApi.changes().id(changeId).addReviewer("reviewer3");
+
+    // Want-Code-Review-From-All is unsatisfied because reviewer3 didn't vote yet.
+    assertSubmitRequirementStatus(
+        gApi.changes().id(changeId).get().submitRequirements,
+        "Want-Code-Review-From-All",
+        Status.UNSATISFIED,
+        /* isLegacy= */ false);
+
+    // Vote with Code-Review+1 by reviewer3.
+    requestScopeOperations.setApiUser(reviewer3.id());
+    voteLabel(changeId, "Code-Review", 1);
+
+    // Want-Code-Review-From-All is not applicable because all reviewers voted with Code-Review >=
+    // 1.
+    assertSubmitRequirementStatus(
+        gApi.changes().id(changeId).get().submitRequirements,
+        "Want-Code-Review-From-All",
+        Status.NOT_APPLICABLE,
+        /* isLegacy= */ false);
+  }
+
+  @Test
+  public void submitRequirement_wantCodeReviewFromHumanReviewers_enabledByFooter()
+      throws Exception {
+    projectOperations
+        .project(project)
+        .forUpdate()
+        .add(allowLabel("Code-Review").ref("refs/*").group(REGISTERED_USERS).range(-2, 2))
+        .update();
+
+    configSubmitRequirement(
+        project,
+        SubmitRequirement.builder()
+            .setName("Code-Review")
+            .setSubmittabilityExpression(
+                SubmitRequirementExpression.create("label:Code-Review=MAX"))
+            .setAllowOverrideInChildProjects(false)
+            .build());
+    configSubmitRequirement(
+        project,
+        SubmitRequirement.builder()
+            .setName("Want-Code-Review-From-All")
+            .setApplicabilityExpression(
+                Optional.of(
+                    SubmitRequirementExpression.create(
+                        "footer:\"Want-Code-Review: all\" -label:Code-Review>=1,users=human_reviewers")))
+            .setSubmittabilityExpression(
+                SubmitRequirementExpression.create("label:Code-Review>=1,users=human_reviewers"))
+            .setAllowOverrideInChildProjects(false)
+            .build());
+
+    PushOneCommit.Result r = createChange();
+    String changeId = r.getChangeId();
+
+    // Add some reviewers
+    TestAccount reviewer1 = accountCreator.create("reviewer1");
+    gApi.changes().id(changeId).addReviewer("reviewer1");
+    TestAccount reviewer2 = accountCreator.create("reviewer2");
+    gApi.changes().id(changeId).addReviewer("reviewer2");
+
+    // Approve by one reviewer
+    requestScopeOperations.setApiUser(reviewer1.id());
+    voteLabel(changeId, "Code-Review", 2);
+
+    // Code-Review is satisfied because there is Code-Review+2 approval from reviewer1.
+    assertSubmitRequirementStatus(
+        gApi.changes().id(changeId).get().submitRequirements,
+        "Code-Review",
+        Status.SATISFIED,
+        /* isLegacy= */ false);
+
+    // Want-Code-Review-From-All is not applicable since the commit message doesn't contain a
+    // "Want-Code-Review: all" footer.
+    assertSubmitRequirementStatus(
+        gApi.changes().id(changeId).get().submitRequirements,
+        "Want-Code-Review-From-All",
+        Status.NOT_APPLICABLE,
+        /* isLegacy= */ false);
+
+    // Amend the change to add a "Want-Code-Review: all" footer.
+    amendChange(
+        changeId,
+        PushOneCommit.SUBJECT
+            + "\n\nSome Description\n\nChange-Id: "
+            + changeId
+            + "\nWant-Code-Review: all\n",
+        PushOneCommit.FILE_NAME,
+        "content");
+
+    // Re-Approve by reviewer1.
+    requestScopeOperations.setApiUser(reviewer1.id());
+    voteLabel(changeId, "Code-Review", 2);
+
+    // Want-Code-Review-From-All is applicable since there is a "Want-Code-Review: all" footer and
+    // it is unsatisfied since there is no approval from reviewer2.
+    assertSubmitRequirementStatus(
+        gApi.changes().id(changeId).get().submitRequirements,
+        "Want-Code-Review-From-All",
+        Status.UNSATISFIED,
+        /* isLegacy= */ false);
+
+    // Approve by reviewer2.
+    requestScopeOperations.setApiUser(reviewer2.id());
+    voteLabel(changeId, "Code-Review", 2);
+
+    // Want-Code-Review-From-All is not applicable since there are approval from all reviewers
+    // (reviewer1 and reviewer2) which makes "label:Code-Review=MAX,users=human_reviewers"
+    // satisfied.
+    assertSubmitRequirementStatus(
+        gApi.changes().id(changeId).get().submitRequirements,
+        "Want-Code-Review-From-All",
+        Status.NOT_APPLICABLE,
+        /* isLegacy= */ false);
+
+    // Add another reviewer
+    TestAccount reviewer3 = accountCreator.create("reviewer3");
+    gApi.changes().id(changeId).addReviewer("reviewer3");
+
+    // Want-Code-Review-From-All is unsatisfied because reviewer3 didn't vote yet.
+    assertSubmitRequirementStatus(
+        gApi.changes().id(changeId).get().submitRequirements,
+        "Want-Code-Review-From-All",
+        Status.UNSATISFIED,
+        /* isLegacy= */ false);
+
+    // Vote with Code-Review+1 by reviewer3.
+    requestScopeOperations.setApiUser(reviewer3.id());
+    voteLabel(changeId, "Code-Review", 1);
+
+    // Want-Code-Review-From-All is not applicable because all reviewers voted with Code-Review >=
+    // 1.
+    assertSubmitRequirementStatus(
+        gApi.changes().id(changeId).get().submitRequirements,
+        "Want-Code-Review-From-All",
+        Status.NOT_APPLICABLE,
+        /* isLegacy= */ false);
+  }
+
+  @Test
   public void submitRequirementIsSatisfied_whenSubmittabilityExpressionIsFulfilled()
       throws Exception {
     configSubmitRequirement(
@@ -1603,9 +1849,7 @@
 
       // Clear SRs for the project and update code-review label to be non-blocking.
       clearSubmitRequirements(project);
-      @SuppressWarnings("deprecation")
-      LabelType cr =
-          TestLabels.codeReview().toBuilder().setFunction(LabelFunction.NO_BLOCK).build();
+      LabelType cr = TestLabels.codeReview().toBuilder().setNoBlockFunction().build();
       try (ProjectConfigUpdate u = updateProject(project)) {
         u.getConfig().upsertLabelType(cr);
         u.save();
@@ -1650,9 +1894,7 @@
 
       // Clear SRs for the project and update code-review label to be non-blocking.
       clearSubmitRequirements(project);
-      @SuppressWarnings("deprecation")
-      LabelType cr =
-          TestLabels.codeReview().toBuilder().setFunction(LabelFunction.NO_BLOCK).build();
+      LabelType cr = TestLabels.codeReview().toBuilder().setNoBlockFunction().build();
       try (ProjectConfigUpdate u = updateProject(project)) {
         u.getConfig().upsertLabelType(cr);
         u.save();
@@ -2865,8 +3107,7 @@
             .setAllowOverrideInChildProjects(true)
             .build());
 
-    @SuppressWarnings("deprecation")
-    LabelType cr = TestLabels.codeReview().toBuilder().setFunction(LabelFunction.NO_BLOCK).build();
+    LabelType cr = TestLabels.codeReview().toBuilder().setNoBlockFunction().build();
     try (ProjectConfigUpdate u = updateProject(project)) {
       u.getConfig().upsertLabelType(cr);
       u.save();
diff --git a/javatests/com/google/gerrit/acceptance/api/change/SubmitRequirementPredicateIT.java b/javatests/com/google/gerrit/acceptance/api/change/SubmitRequirementPredicateIT.java
index 8643489..61a06a3 100644
--- a/javatests/com/google/gerrit/acceptance/api/change/SubmitRequirementPredicateIT.java
+++ b/javatests/com/google/gerrit/acceptance/api/change/SubmitRequirementPredicateIT.java
@@ -15,6 +15,7 @@
 package com.google.gerrit.acceptance.api.change;
 
 import static com.google.common.truth.Truth.assertThat;
+import static com.google.common.truth.Truth.assertWithMessage;
 import static com.google.gerrit.acceptance.testsuite.project.TestProjectUpdate.allowLabel;
 import static com.google.gerrit.server.group.SystemGroupBackend.ANONYMOUS_USERS;
 import static com.google.gerrit.server.group.SystemGroupBackend.REGISTERED_USERS;
@@ -39,13 +40,19 @@
 import com.google.gerrit.common.Nullable;
 import com.google.gerrit.entities.Account;
 import com.google.gerrit.entities.AccountGroup;
+import com.google.gerrit.entities.BooleanProjectConfig;
 import com.google.gerrit.entities.Change;
 import com.google.gerrit.entities.LabelType;
+import com.google.gerrit.entities.Project;
 import com.google.gerrit.entities.RefNames;
 import com.google.gerrit.entities.SubmitRequirementExpression;
 import com.google.gerrit.entities.SubmitRequirementExpressionResult;
 import com.google.gerrit.extensions.api.changes.ReviewInput;
+import com.google.gerrit.extensions.client.InheritableBoolean;
 import com.google.gerrit.extensions.common.ChangeInfo;
+import com.google.gerrit.server.account.ServiceUserClassifier;
+import com.google.gerrit.server.git.meta.MetaDataUpdate;
+import com.google.gerrit.server.project.ProjectConfig;
 import com.google.gerrit.server.project.SubmitRequirementsEvaluatorImpl;
 import com.google.gerrit.server.query.change.ChangeData;
 import com.google.inject.Inject;
@@ -467,6 +474,373 @@
     assertMatching("label:Code-Review=+2,user=non_contributor", r1.getChange().getId());
   }
 
+  @Test
+  public void label_requireVoteFromHumanReviewers() throws Exception {
+    projectOperations
+        .project(project)
+        .forUpdate()
+        .add(allowLabel("Code-Review").ref("refs/*").group(REGISTERED_USERS).range(-2, 2))
+        .update();
+
+    Account.Id owner = accountCreator.create("owner").id();
+    Account.Id reviewer1 = accountCreator.create("reviewer1").id();
+    Account.Id reviewer2 = accountCreator.create("reviewer2").id();
+    Account.Id reviewer3 = accountCreator.create("reviewer3").id();
+
+    Account.Id serviceUser = accountCreator.create("serviceUser").id();
+    gApi.groups().id(ServiceUserClassifier.SERVICE_USERS).addMembers(serviceUser.toString());
+
+    Change.Id changeApprovedByAllReviewers =
+        changeOperations.newChange().project(project).owner(owner).create();
+    addReviewers(project, changeApprovedByAllReviewers, reviewer1, reviewer2, reviewer3);
+    addReviews(
+        project,
+        changeApprovedByAllReviewers,
+        ReviewInput.approve(),
+        reviewer1,
+        reviewer2,
+        reviewer3);
+
+    Change.Id changeApprovedBySomeReviewers =
+        changeOperations.newChange().project(project).owner(owner).create();
+    addReviewers(project, changeApprovedBySomeReviewers, reviewer1, reviewer2, reviewer3);
+    addReviews(project, changeApprovedBySomeReviewers, ReviewInput.approve(), reviewer1, reviewer2);
+
+    Change.Id changeRecommendedByAllReviewers =
+        changeOperations.newChange().project(project).owner(owner).create();
+    addReviewers(project, changeRecommendedByAllReviewers, reviewer1, reviewer2, reviewer3);
+    addReviews(
+        project,
+        changeRecommendedByAllReviewers,
+        ReviewInput.recommend(),
+        reviewer1,
+        reviewer2,
+        reviewer3);
+
+    Change.Id changeRecommendedBySomeReviewers =
+        changeOperations.newChange().project(project).owner(owner).create();
+    addReviewers(project, changeRecommendedBySomeReviewers, reviewer1, reviewer2, reviewer3);
+    addReviews(
+        project, changeRecommendedBySomeReviewers, ReviewInput.recommend(), reviewer1, reviewer2);
+
+    Change.Id changeNoVotesByReviewers =
+        changeOperations.newChange().project(project).owner(owner).create();
+    addReviewers(project, changeNoVotesByReviewers, reviewer1, reviewer2, reviewer3);
+
+    Change.Id changeWithoutReviewers =
+        changeOperations.newChange().project(project).owner(owner).create();
+
+    requestScopeOperations.setApiUser(user.id());
+
+    // change without reviewers doesn't match
+    assertNotMatching("label:Code-Review=MAX,users=human_reviewers", changeWithoutReviewers);
+
+    // match changes where all reviewers have the same vote
+    assertRequirement(
+        "label:Code-Review=MAX,users=human_reviewers",
+        ImmutableList.of(changeApprovedByAllReviewers),
+        ImmutableList.of(
+            changeApprovedBySomeReviewers,
+            changeRecommendedByAllReviewers,
+            changeRecommendedBySomeReviewers,
+            changeNoVotesByReviewers));
+    assertRequirement(
+        "label:Code-Review=2,users=human_reviewers",
+        ImmutableList.of(changeApprovedByAllReviewers),
+        ImmutableList.of(
+            changeApprovedBySomeReviewers,
+            changeRecommendedByAllReviewers,
+            changeRecommendedBySomeReviewers,
+            changeNoVotesByReviewers));
+    assertRequirement(
+        "label:Code-Review=1,users=human_reviewers",
+        ImmutableList.of(changeRecommendedByAllReviewers),
+        ImmutableList.of(
+            changeApprovedBySomeReviewers,
+            changeApprovedByAllReviewers,
+            changeRecommendedBySomeReviewers,
+            changeNoVotesByReviewers));
+
+    // match changes where no reviewer voted (same as "label:Code-Review=0")
+    assertRequirement(
+        "label:Code-Review=0,users=human_reviewers",
+        ImmutableList.of(changeNoVotesByReviewers),
+        ImmutableList.of(
+            changeApprovedByAllReviewers,
+            changeApprovedBySomeReviewers,
+            changeRecommendedByAllReviewers,
+            changeRecommendedBySomeReviewers));
+
+    // match changes where all reviewers have a vote <=, >=, < or >
+    assertRequirement(
+        "label:Code-Review<=2,users=human_reviewers",
+        ImmutableList.of(
+            changeApprovedByAllReviewers,
+            changeApprovedBySomeReviewers,
+            changeRecommendedByAllReviewers,
+            changeRecommendedBySomeReviewers,
+            changeNoVotesByReviewers),
+        ImmutableList.of());
+    assertRequirement(
+        "label:Code-Review<=1,users=human_reviewers",
+        ImmutableList.of(
+            changeRecommendedByAllReviewers,
+            changeRecommendedByAllReviewers,
+            changeRecommendedBySomeReviewers,
+            changeNoVotesByReviewers),
+        ImmutableList.of(changeApprovedByAllReviewers));
+    assertRequirement(
+        "label:Code-Review>=1,users=human_reviewers",
+        ImmutableList.of(changeApprovedByAllReviewers, changeRecommendedByAllReviewers),
+        ImmutableList.of(
+            changeApprovedBySomeReviewers,
+            changeRecommendedBySomeReviewers,
+            changeNoVotesByReviewers));
+    assertRequirement(
+        "label:Code-Review<1,users=human_reviewers",
+        ImmutableList.of(changeNoVotesByReviewers),
+        ImmutableList.of(
+            changeApprovedByAllReviewers,
+            changeApprovedBySomeReviewers,
+            changeRecommendedByAllReviewers,
+            changeRecommendedBySomeReviewers));
+    assertRequirement(
+        "label:Code-Review>1,users=human_reviewers",
+        ImmutableList.of(changeApprovedByAllReviewers),
+        ImmutableList.of(
+            changeApprovedBySomeReviewers,
+            changeRecommendedByAllReviewers,
+            changeRecommendedBySomeReviewers,
+            changeNoVotesByReviewers));
+
+    // match changes where all reviewers have any (non-zero) vote
+    assertRequirement(
+        "label:Code-Review=ANY,users=human_reviewers",
+        ImmutableList.of(changeApprovedByAllReviewers, changeRecommendedByAllReviewers),
+        ImmutableList.of(
+            changeApprovedBySomeReviewers,
+            changeRecommendedBySomeReviewers,
+            changeNoVotesByReviewers));
+
+    // votes of the change owners are ignored (as the change owner is not considered as a reviewer)
+    addReviews(project, changeApprovedByAllReviewers, ReviewInput.dislike(), owner);
+    assertRequirement(
+        "label:Code-Review=MAX,users=human_reviewers",
+        ImmutableList.of(changeApprovedByAllReviewers),
+        ImmutableList.of(
+            changeApprovedBySomeReviewers,
+            changeRecommendedByAllReviewers,
+            changeRecommendedBySomeReviewers,
+            changeNoVotesByReviewers));
+
+    // missing votes from service users are fine
+    addReviewers(project, changeApprovedByAllReviewers, serviceUser);
+    assertRequirement(
+        "label:Code-Review=MAX,users=human_reviewers",
+        ImmutableList.of(changeApprovedByAllReviewers),
+        ImmutableList.of(
+            changeApprovedBySomeReviewers,
+            changeRecommendedByAllReviewers,
+            changeRecommendedBySomeReviewers,
+            changeNoVotesByReviewers));
+
+    // votes from service users are ignored
+    addReviews(project, changeApprovedByAllReviewers, ReviewInput.dislike(), serviceUser);
+    assertRequirement(
+        "label:Code-Review=MAX,users=human_reviewers",
+        ImmutableList.of(changeApprovedByAllReviewers),
+        ImmutableList.of(
+            changeApprovedBySomeReviewers,
+            changeRecommendedByAllReviewers,
+            changeRecommendedBySomeReviewers,
+            changeNoVotesByReviewers));
+
+    // when reviewers by email are present changes do not match, unless the expected value is 0
+    try (MetaDataUpdate md = metaDataUpdateFactory.create(project)) {
+      ProjectConfig cfg = projectConfigFactory.create(project);
+      cfg.load(md);
+      cfg.updateProject(
+          update ->
+              update.setBooleanConfig(
+                  BooleanProjectConfig.ENABLE_REVIEWER_BY_EMAIL, InheritableBoolean.TRUE));
+      cfg.commit(md);
+    }
+    projectCache.evictAndReindex(project);
+    Change.Id changeRecommendedByAllReviewersWithReviewersByEmail =
+        changeOperations.newChange().project(project).owner(owner).create();
+    addReviewers(
+        project,
+        changeRecommendedByAllReviewersWithReviewersByEmail,
+        reviewer1,
+        reviewer2,
+        reviewer3);
+    addReviews(
+        project,
+        changeRecommendedByAllReviewersWithReviewersByEmail,
+        ReviewInput.recommend(),
+        reviewer1,
+        reviewer2,
+        reviewer3);
+    addReviewer(
+        project,
+        changeRecommendedByAllReviewersWithReviewersByEmail,
+        "email-without-account@example.com");
+    Change.Id changeNoVotesByReviewersWithReviewersByEmail =
+        changeOperations.newChange().project(project).owner(owner).create();
+    addReviewers(
+        project, changeNoVotesByReviewersWithReviewersByEmail, reviewer1, reviewer2, reviewer3);
+    addReviewer(
+        project, changeNoVotesByReviewersWithReviewersByEmail, "email-without-account@example.com");
+    assertRequirement(
+        "label:Code-Review=MAX,users=human_reviewers",
+        ImmutableList.of(),
+        ImmutableList.of(
+            changeRecommendedByAllReviewersWithReviewersByEmail,
+            changeNoVotesByReviewersWithReviewersByEmail));
+    assertRequirement(
+        "label:Code-Review=2,users=human_reviewers",
+        ImmutableList.of(),
+        ImmutableList.of(
+            changeRecommendedByAllReviewersWithReviewersByEmail,
+            changeNoVotesByReviewersWithReviewersByEmail));
+    assertRequirement(
+        "label:Code-Review=ANY,users=human_reviewers",
+        ImmutableList.of(),
+        ImmutableList.of(
+            changeRecommendedByAllReviewersWithReviewersByEmail,
+            changeNoVotesByReviewersWithReviewersByEmail));
+    assertRequirement(
+        "label:Code-Review=0,users=human_reviewers",
+        ImmutableList.of(changeNoVotesByReviewersWithReviewersByEmail),
+        ImmutableList.of(changeRecommendedByAllReviewersWithReviewersByEmail));
+    assertRequirement(
+        "label:Code-Review<=2,users=human_reviewers",
+        ImmutableList.of(
+            changeRecommendedByAllReviewersWithReviewersByEmail,
+            changeNoVotesByReviewersWithReviewersByEmail),
+        ImmutableList.of());
+    assertRequirement(
+        "label:Code-Review<=0,users=human_reviewers",
+        ImmutableList.of(changeNoVotesByReviewersWithReviewersByEmail),
+        ImmutableList.of(changeRecommendedByAllReviewersWithReviewersByEmail));
+    assertRequirement(
+        "label:Code-Review<=-1,users=human_reviewers",
+        ImmutableList.of(),
+        ImmutableList.of(
+            changeRecommendedByAllReviewersWithReviewersByEmail,
+            changeNoVotesByReviewersWithReviewersByEmail));
+    assertRequirement(
+        "label:Code-Review<2,users=human_reviewers",
+        ImmutableList.of(
+            changeRecommendedByAllReviewersWithReviewersByEmail,
+            changeNoVotesByReviewersWithReviewersByEmail),
+        ImmutableList.of());
+    assertRequirement(
+        "label:Code-Review<1,users=human_reviewers",
+        ImmutableList.of(changeNoVotesByReviewersWithReviewersByEmail),
+        ImmutableList.of(changeRecommendedByAllReviewersWithReviewersByEmail));
+    assertRequirement(
+        "label:Code-Review<0,users=human_reviewers",
+        ImmutableList.of(),
+        ImmutableList.of(
+            changeRecommendedByAllReviewersWithReviewersByEmail,
+            changeNoVotesByReviewersWithReviewersByEmail));
+    assertRequirement(
+        "label:Code-Review>=0,users=human_reviewers",
+        ImmutableList.of(
+            changeRecommendedByAllReviewersWithReviewersByEmail,
+            changeNoVotesByReviewersWithReviewersByEmail),
+        ImmutableList.of());
+    assertRequirement(
+        "label:Code-Review>=1,users=human_reviewers",
+        ImmutableList.of(),
+        ImmutableList.of(
+            changeRecommendedByAllReviewersWithReviewersByEmail,
+            changeNoVotesByReviewersWithReviewersByEmail));
+    assertRequirement(
+        "label:Code-Review>-1,users=human_reviewers",
+        ImmutableList.of(
+            changeRecommendedByAllReviewersWithReviewersByEmail,
+            changeNoVotesByReviewersWithReviewersByEmail),
+        ImmutableList.of());
+    assertRequirement(
+        "label:Code-Review>0,users=human_reviewers",
+        ImmutableList.of(),
+        ImmutableList.of(
+            changeRecommendedByAllReviewersWithReviewersByEmail,
+            changeNoVotesByReviewersWithReviewersByEmail));
+
+    // cannot combine users=human_reviewers" with submit record status
+    assertError(
+        "label:Code-Review=ok,users=human_reviewers",
+        changeApprovedByAllReviewers,
+        "Cannot use the 'users=human_reviewers' argument in conjunction with a submit record label"
+            + " status");
+
+    // cannot combine "users" arg with a "user" arg
+    assertError(
+        "label:Code-Review=MAX,users=human_reviewers,user=reviewer1",
+        changeApprovedByAllReviewers,
+        "Cannot use the 'users' argument in conjunction with other arguments ('count', 'user',"
+            + " group')");
+
+    // cannot combine "users" arg with a "group" arg
+    assertError(
+        "label:Code-Review=MAX,users=human_reviewers,group=foo",
+        changeApprovedByAllReviewers,
+        "Cannot use the 'users' argument in conjunction with other arguments ('count', 'user',"
+            + " group')");
+
+    // cannot combine "users" arg with a positional arg
+    assertError(
+        "label:Code-Review=MAX,users=human_reviewers,reviewer1",
+        changeApprovedByAllReviewers,
+        "Cannot use the 'users' argument in conjunction with other arguments ('count', 'user',"
+            + " group')");
+    assertError(
+        "label:Code-Review=MAX,reviewer1,users=human_reviewers",
+        changeApprovedByAllReviewers,
+        "Cannot use the 'users' argument in conjunction with other arguments ('count', 'user',"
+            + " group')");
+
+    // label without "users=human_reviewers" still works
+    assertRequirement(
+        "label:Code-Review=MAX,user=reviewer1",
+        ImmutableList.of(changeApprovedByAllReviewers, changeApprovedBySomeReviewers),
+        ImmutableList.of(
+            changeRecommendedByAllReviewers,
+            changeRecommendedBySomeReviewers,
+            changeNoVotesByReviewers));
+    assertRequirement(
+        "label:Code-Review=MAX,reviewer1",
+        ImmutableList.of(changeApprovedByAllReviewers, changeApprovedBySomeReviewers),
+        ImmutableList.of(
+            changeRecommendedByAllReviewers,
+            changeRecommendedBySomeReviewers,
+            changeNoVotesByReviewers));
+  }
+
+  private void addReviewers(Project.NameKey project, Change.Id changeId, Account.Id... reviewers)
+      throws Exception {
+    for (Account.Id reviewer : reviewers) {
+      addReviewer(project, changeId, reviewer.toString());
+    }
+  }
+
+  private void addReviewer(Project.NameKey project, Change.Id changeId, String reviewer)
+      throws Exception {
+    gApi.changes().id(project.get(), changeId.get()).addReviewer(reviewer);
+  }
+
+  private void addReviews(
+      Project.NameKey project, Change.Id changeId, ReviewInput reviewInput, Account.Id... reviewers)
+      throws Exception {
+    for (Account.Id reviewer : reviewers) {
+      requestScopeOperations.setApiUser(reviewer);
+      gApi.changes().id(project.get(), changeId.get()).current().review(reviewInput);
+    }
+  }
+
   private void approveAsUser(String changeId, Account.Id userId) throws Exception {
     requestScopeOperations.setApiUser(userId);
     approve(changeId);
@@ -540,13 +914,28 @@
     return threeWayMerger.getResultTreeId();
   }
 
+  private void assertRequirement(
+      String requirement,
+      ImmutableList<Change.Id> matchingChanges,
+      ImmutableList<Change.Id> nonMatchingChanges) {
+    for (Change.Id matchingChange : matchingChanges) {
+      assertMatching(requirement, matchingChange);
+    }
+
+    for (Change.Id nonMatchingChange : nonMatchingChanges) {
+      assertNotMatching(requirement, nonMatchingChange);
+    }
+  }
+
   private void assertMatching(String requirement, Change.Id change) {
-    assertThat(evaluate(requirement, change).status())
+    assertWithMessage("requirement \"%s\" doesn't match change %s", requirement, change)
+        .that(evaluate(requirement, change).status())
         .isEqualTo(SubmitRequirementExpressionResult.Status.PASS);
   }
 
   private void assertNotMatching(String requirement, Change.Id change) {
-    assertThat(evaluate(requirement, change).status())
+    assertWithMessage("requirement \"%s\" matches change %s", requirement, change)
+        .that(evaluate(requirement, change).status())
         .isEqualTo(SubmitRequirementExpressionResult.Status.FAIL);
   }
 
diff --git a/javatests/com/google/gerrit/acceptance/api/change/SubmitWithStickyApprovalDiffIT.java b/javatests/com/google/gerrit/acceptance/api/change/SubmitWithStickyApprovalDiffIT.java
index b0d39d5..625a00e 100644
--- a/javatests/com/google/gerrit/acceptance/api/change/SubmitWithStickyApprovalDiffIT.java
+++ b/javatests/com/google/gerrit/acceptance/api/change/SubmitWithStickyApprovalDiffIT.java
@@ -16,7 +16,6 @@
 
 import static com.google.common.truth.Truth.assertThat;
 import static com.google.gerrit.acceptance.testsuite.project.TestProjectUpdate.allowLabel;
-import static com.google.gerrit.entities.LabelFunction.NO_BLOCK;
 import static com.google.gerrit.server.group.SystemGroupBackend.REGISTERED_USERS;
 import static com.google.gerrit.server.project.testing.TestLabels.label;
 import static com.google.gerrit.server.project.testing.TestLabels.labelBuilder;
@@ -603,7 +602,7 @@
                       value(0, "No score"),
                       value(-1, "Negative"))
                   .toBuilder()
-                  .setFunction(NO_BLOCK)
+                  .setNoBlockFunction()
                   .build());
       u.save();
     }
diff --git a/javatests/com/google/gerrit/acceptance/rest/change/AttentionSetIT.java b/javatests/com/google/gerrit/acceptance/rest/change/AttentionSetIT.java
index 92da64e..0f245bd 100644
--- a/javatests/com/google/gerrit/acceptance/rest/change/AttentionSetIT.java
+++ b/javatests/com/google/gerrit/acceptance/rest/change/AttentionSetIT.java
@@ -130,6 +130,11 @@
   @Before
   public void setUp() {
     TimeUtil.setCurrentMillisSupplier(fakeClock);
+    projectOperations
+        .project(allProjects)
+        .forUpdate()
+        .add(allowLabel("Code-Review").ref("refs/heads/*").group(REGISTERED_USERS).range(-2, 2))
+        .update();
   }
 
   @Test
@@ -1402,10 +1407,51 @@
   }
 
   @Test
-  public void reviewAddsAllUsersInCommentThread() throws Exception {
+  public void ownerReplyResolvedAddsNonVotedInCommentThread() throws Exception {
     PushOneCommit.Result r = createChange();
     requestScopeOperations.setApiUser(user.id());
-    change(r).current().review(reviewWithComment());
+    ReviewInput ri = reviewWithComment();
+    ri.label("Code-Review", 2);
+    change(r).current().review(ri);
+
+    TestAccount user2 = accountCreator.user2();
+
+    requestScopeOperations.setApiUser(user2.id());
+    change(r)
+        .current()
+        .review(
+            reviewInReplyToComment(
+                Iterables.getOnlyElement(
+                        gApi.changes().id(r.getChangeId()).current().commentsAsList())
+                    .id));
+
+    change(r).attention(user.email()).remove(new AttentionSetInput("removal"));
+    requestScopeOperations.setApiUser(admin.id());
+    ri =
+        reviewInReplyToComment(
+            gApi.changes().id(r.getChangeId()).current().commentsAsList().get(1).id);
+    ri.comments.get(Patch.COMMIT_MSG).get(0).unresolved = false;
+    change(r).current().review(ri);
+
+    // First user already voted, no need to bring them back.
+    assertThat(getAttentionSetUpdatesForUser(r, user)).isEmpty();
+
+    AttentionSetUpdate attentionSet =
+        Iterables.getOnlyElement(getAttentionSetUpdatesForUser(r, user2));
+    assertThat(attentionSet).hasAccountIdThat().isEqualTo(user2.id());
+    assertThat(attentionSet).hasOperationThat().isEqualTo(AttentionSetUpdate.Operation.ADD);
+    assertThat(attentionSet)
+        .hasReasonThat()
+        .isEqualTo("Someone else replied on a comment you posted");
+  }
+
+  @Test
+  public void ownerReplyUnresolvedAddsAllUsersInCommentThread() throws Exception {
+    PushOneCommit.Result r = createChange();
+    requestScopeOperations.setApiUser(user.id());
+    ReviewInput ri = reviewWithComment();
+    ri.label("Code-Review", 2);
+    change(r).current().review(ri);
 
     TestAccount user2 = accountCreator.user2();
 
@@ -1443,6 +1489,71 @@
   }
 
   @Test
+  public void reviewerReplyUnresolvedAddsOnlyOwner() throws Exception {
+    PushOneCommit.Result r = createChange();
+    requestScopeOperations.setApiUser(user.id());
+    change(r).current().review(reviewWithComment());
+
+    TestAccount user2 = accountCreator.user2();
+    change(r).attention(admin.email()).remove(new AttentionSetInput("removal"));
+    requestScopeOperations.setApiUser(user2.id());
+    change(r)
+        .current()
+        .review(
+            reviewInReplyToComment(
+                Iterables.getOnlyElement(
+                        gApi.changes().id(r.getChangeId()).current().commentsAsList())
+                    .id));
+
+    // First user is not needed, owner haven't addressed their comment yet.
+    assertThat(getAttentionSetUpdatesForUser(r, user)).isEmpty();
+
+    AttentionSetUpdate attentionSet =
+        Iterables.getOnlyElement(getAttentionSetUpdatesForUser(r, admin));
+    assertThat(attentionSet).hasAccountIdThat().isEqualTo(admin.id());
+    assertThat(attentionSet).hasOperationThat().isEqualTo(AttentionSetUpdate.Operation.ADD);
+    assertThat(attentionSet).hasReasonThat().isEqualTo("Someone else replied on the change");
+  }
+
+  @Test
+  public void reviewerReplyResolvedAddsNonVotedInCommentThread() throws Exception {
+    PushOneCommit.Result r = createChange();
+    requestScopeOperations.setApiUser(user.id());
+    ReviewInput ri = reviewWithComment();
+    ri.label("Code-Review", 2);
+    change(r).current().review(ri);
+
+    TestAccount user2 = accountCreator.user2();
+    requestScopeOperations.setApiUser(user2.id());
+    change(r)
+        .current()
+        .review(
+            reviewInReplyToComment(
+                Iterables.getOnlyElement(
+                        gApi.changes().id(r.getChangeId()).current().commentsAsList())
+                    .id));
+
+    TestAccount user3 = accountCreator.create("user3", "user3@example.com", "User3", null);
+    requestScopeOperations.setApiUser(user3.id());
+    ri =
+        reviewInReplyToComment(
+            gApi.changes().id(r.getChangeId()).current().commentsAsList().get(1).id);
+    ri.comments.get(Patch.COMMIT_MSG).get(0).unresolved = false;
+    change(r).current().review(ri);
+
+    // First user already voted, no need to bring them back.
+    assertThat(getAttentionSetUpdatesForUser(r, user)).isEmpty();
+
+    AttentionSetUpdate attentionSet =
+        Iterables.getOnlyElement(getAttentionSetUpdatesForUser(r, user2));
+    assertThat(attentionSet).hasAccountIdThat().isEqualTo(user2.id());
+    assertThat(attentionSet).hasOperationThat().isEqualTo(AttentionSetUpdate.Operation.ADD);
+    assertThat(attentionSet)
+        .hasReasonThat()
+        .isEqualTo("Someone else replied on a comment you posted");
+  }
+
+  @Test
   public void reviewAddsAllUsersInCommentThreadWhenOriginalCommentIsARobotComment()
       throws Exception {
     PushOneCommit.Result result = createChange();
@@ -3278,6 +3389,7 @@
     comment.message = "comment";
     comment.setUpdated(TimeUtil.now());
     comment.inReplyTo = id;
+    comment.unresolved = true;
     ReviewInput reviewInput = new ReviewInput();
     reviewInput.comments = ImmutableMap.of(Patch.COMMIT_MSG, ImmutableList.of(comment));
     return reviewInput;
diff --git a/javatests/com/google/gerrit/acceptance/server/project/CustomLabelIT.java b/javatests/com/google/gerrit/acceptance/server/project/CustomLabelIT.java
index 7ffc0a4..2a210af 100644
--- a/javatests/com/google/gerrit/acceptance/server/project/CustomLabelIT.java
+++ b/javatests/com/google/gerrit/acceptance/server/project/CustomLabelIT.java
@@ -20,8 +20,6 @@
 import static com.google.gerrit.entities.LabelFunction.ANY_WITH_BLOCK;
 import static com.google.gerrit.entities.LabelFunction.MAX_NO_BLOCK;
 import static com.google.gerrit.entities.LabelFunction.MAX_WITH_BLOCK;
-import static com.google.gerrit.entities.LabelFunction.NO_BLOCK;
-import static com.google.gerrit.entities.LabelFunction.NO_OP;
 import static com.google.gerrit.extensions.client.ListChangesOption.DETAILED_LABELS;
 import static com.google.gerrit.extensions.client.ListChangesOption.LABELS;
 import static com.google.gerrit.extensions.client.ListChangesOption.SUBMITTABLE;
@@ -76,10 +74,9 @@
         .update();
   }
 
-  @SuppressWarnings("deprecation")
   @Test
   public void customLabelNoOp_NegativeVoteNotBlock() throws Exception {
-    saveLabelConfig(LABEL.toBuilder().setFunction(NO_OP));
+    saveLabelConfig(LABEL.toBuilder().setNoBlockFunction());
     PushOneCommit.Result r = createChange();
     revision(r).review(new ReviewInput().label(LABEL_NAME, -1));
     ChangeInfo c = getWithLabels(r);
@@ -92,10 +89,9 @@
     assertThat(q.blocking).isNull();
   }
 
-  @SuppressWarnings("deprecation")
   @Test
   public void customLabelNoBlock_NegativeVoteNotBlock() throws Exception {
-    saveLabelConfig(LABEL.toBuilder().setFunction(NO_BLOCK));
+    saveLabelConfig(LABEL.toBuilder().setNoBlockFunction());
     PushOneCommit.Result r = createChange();
     revision(r).review(new ReviewInput().label(LABEL_NAME, -1));
     ChangeInfo c = getWithLabels(r);
@@ -127,7 +123,8 @@
   @SuppressWarnings("deprecation")
   @Test
   public void customLabelMaxNoBlock_MaxVoteSubmittable() throws Exception {
-    saveLabelConfig(LABEL.toBuilder().setFunction(MAX_NO_BLOCK), P.toBuilder().setFunction(NO_OP));
+    saveLabelConfig(
+        LABEL.toBuilder().setFunction(MAX_NO_BLOCK), P.toBuilder().setNoBlockFunction());
     PushOneCommit.Result r = createChange();
     assertThat(info(r.getChangeId()).submittable).isNull();
     revision(r).review(ReviewInput.approve().label(LABEL_NAME, 1));
@@ -239,7 +236,7 @@
   @Test
   public void customLabelMaxWithBlock_MaxVoteSubmittable() throws Exception {
     saveLabelConfig(
-        LABEL.toBuilder().setFunction(MAX_WITH_BLOCK), P.toBuilder().setFunction(NO_OP));
+        LABEL.toBuilder().setFunction(MAX_WITH_BLOCK), P.toBuilder().setNoBlockFunction());
     PushOneCommit.Result r = createChange();
     assertThat(info(r.getChangeId()).submittable).isNull();
     revision(r).review(ReviewInput.approve().label(LABEL_NAME, 1));
@@ -272,12 +269,11 @@
     assertThat(q.blocking).isTrue();
   }
 
-  @SuppressWarnings("deprecation")
   @Test
   public void customLabel_DisallowPostSubmit() throws Exception {
     saveLabelConfig(
-        LABEL.toBuilder().setFunction(NO_OP).setAllowPostSubmit(false),
-        P.toBuilder().setFunction(NO_OP));
+        LABEL.toBuilder().setNoBlockFunction().setAllowPostSubmit(false),
+        P.toBuilder().setNoBlockFunction());
 
     PushOneCommit.Result r = createChange();
     revision(r).review(ReviewInput.approve());
diff --git a/javatests/com/google/gerrit/server/query/change/AbstractQueryChangesTest.java b/javatests/com/google/gerrit/server/query/change/AbstractQueryChangesTest.java
index a0aad96..1a546fa 100644
--- a/javatests/com/google/gerrit/server/query/change/AbstractQueryChangesTest.java
+++ b/javatests/com/google/gerrit/server/query/change/AbstractQueryChangesTest.java
@@ -1552,6 +1552,12 @@
   }
 
   @Test
+  public void cannotUseUsersArgWithLabel() throws Exception {
+    assertFailingQuery(
+        "label:Code-Review=MAX,users=human_reviewers", "Cannot use the 'users' argument in search");
+  }
+
+  @Test
   public void byLabelMulti() throws Exception {
     Project.NameKey project = Project.nameKey("repo");
     repo = createAndOpenProject(project);
diff --git a/modules/jgit b/modules/jgit
index 3a7a9cb..d34f8b5 160000
--- a/modules/jgit
+++ b/modules/jgit
@@ -1 +1 @@
-Subproject commit 3a7a9cb0e89de263d0a5133949c9c9bed5141916
+Subproject commit d34f8b523638fc95b2e7006d02c9f6a756cbba85
diff --git a/package.json b/package.json
index 136b73b..8d6206e 100644
--- a/package.json
+++ b/package.json
@@ -15,12 +15,12 @@
     "@typescript-eslint/eslint-plugin": "^5.62.0",
     "@web/dev-server": "^0.1.38",
     "@web/dev-server-esbuild": "^0.3.6",
-    "eslint": "^8.57.0",
+    "eslint": "^8.57.1",
     "eslint-config-google": "^0.14.0",
     "eslint-plugin-html": "^7.1.0",
-    "eslint-plugin-import": "^2.29.1",
+    "eslint-plugin-import": "^2.31.0",
     "eslint-plugin-jsdoc": "^44.2.7",
-    "eslint-plugin-lit": "^1.14.0",
+    "eslint-plugin-lit": "^1.15.0",
     "eslint-plugin-node": "^11.1.0",
     "eslint-plugin-prettier": "^4.2.1",
     "eslint-plugin-regex": "^1.10.0",
@@ -28,7 +28,7 @@
     "lit-analyzer": "^1.2.1",
     "npm-run-all": "^4.1.5",
     "prettier": "^2.8.8",
-    "rollup": "^2.79.1",
+    "rollup": "^2.79.2",
     "terser": "~5.8.0",
     "ts-lit-plugin": "^1.2.1",
     "typescript": "^4.9.5"
@@ -60,10 +60,10 @@
     "url": "https://gerrit.googlesource.com/gerrit"
   },
   "resolutions": {
-    "eslint": "^8.57.0",
+    "eslint": "^8.57.1",
     "@typescript-eslint/eslint-plugin": "^5.62.0",
     "@typescript-eslint/parser": "^5.62.0"
   },
   "author": "",
   "license": "Apache-2.0"
-}
+}
\ No newline at end of file
diff --git a/plugins/package.json b/plugins/package.json
index 3da1b7a..0091b48 100644
--- a/plugins/package.json
+++ b/plugins/package.json
@@ -3,42 +3,49 @@
   "description": "Gerrit Code Review - frontend plugin dependencies, each plugin may depend on a subset of these",
   "browser": true,
   "dependencies": {
-    "@codemirror/autocomplete": "^6.17.0",
-    "@codemirror/commands": "^6.6.0",
+    "@codemirror/autocomplete": "^6.18.2",
+    "@codemirror/commands": "^6.7.1",
     "@codemirror/lang-cpp": "^6.0.2",
-    "@codemirror/lang-css": "^6.2.1",
+    "@codemirror/lang-css": "^6.3.0",
     "@codemirror/lang-go": "^6.0.1",
     "@codemirror/lang-html": "^6.4.9",
     "@codemirror/lang-java": "^6.0.1",
     "@codemirror/lang-javascript": "^6.2.2",
     "@codemirror/lang-json": "^6.0.1",
     "@codemirror/lang-less": "^6.0.2",
-    "@codemirror/lang-markdown": "^6.2.5",
+    "@codemirror/lang-markdown": "^6.3.1",
     "@codemirror/lang-php": "^6.0.1",
     "@codemirror/lang-python": "^6.1.6",
     "@codemirror/lang-rust": "^6.0.1",
     "@codemirror/lang-sass": "^6.0.2",
-    "@codemirror/lang-sql": "^6.7.0",
+    "@codemirror/lang-sql": "^6.8.0",
     "@codemirror/lang-vue": "^0.1.3",
     "@codemirror/lang-xml": "^6.1.0",
     "@codemirror/lang-yaml": "^6.1.1",
-    "@codemirror/language": "^6.10.2",
+    "@codemirror/language": "^6.10.3",
     "@codemirror/language-data": "^6.5.1",
-    "@codemirror/legacy-modes": "^6.4.0",
-    "@codemirror/lint": "^6.8.1",
-    "@codemirror/search": "^6.5.6",
+    "@codemirror/legacy-modes": "^6.4.2",
+    "@codemirror/lint": "^6.8.2",
+    "@codemirror/search": "^6.5.7",
     "@codemirror/state": "^6.4.1",
-    "@codemirror/view": "^6.29.1",
+    "@codemirror/view": "^6.34.2",
     "@gerritcodereview/typescript-api": "3.10.0",
     "@open-wc/testing": "^3.2.2",
     "@polymer/decorators": "^3.0.0",
-    "@polymer/polymer": "^3.5.1",
+    "@polymer/polymer": "3.5.1",
     "@web/dev-server-esbuild": "^0.3.6",
     "@web/test-runner": "^0.15.3",
-    "lit": "^3.1.4",
+    "lit": "^3.2.1",
     "rxjs": "^6.6.7",
     "sinon": "^13.0.2"
   },
+  "dependencies // comments": {
+    "@polymer/polymer": [
+      "There is a an issue with release 3.5.2. Tests are failing with:",
+      "NotSupportedError: Failed to execute 'define' on 'CustomElementRegistry':",
+      "the name 'dom-module' has already been used with this registry at ..."
+    ]
+  },
   "license": "Apache-2.0",
   "private": true
-}
+}
\ No newline at end of file
diff --git a/plugins/yarn.lock b/plugins/yarn.lock
index c6d2b18..2d7bd33 100644
--- a/plugins/yarn.lock
+++ b/plugins/yarn.lock
@@ -25,7 +25,17 @@
     js-tokens "^4.0.0"
     picocolors "^1.0.0"
 
-"@codemirror/autocomplete@^6.0.0", "@codemirror/autocomplete@^6.17.0", "@codemirror/autocomplete@^6.3.2", "@codemirror/autocomplete@^6.7.1":
+"@codemirror/autocomplete@^6.0.0", "@codemirror/autocomplete@^6.18.2", "@codemirror/autocomplete@^6.7.1":
+  version "6.18.2"
+  resolved "https://registry.yarnpkg.com/@codemirror/autocomplete/-/autocomplete-6.18.2.tgz#bf3f15f1bf0fdfa3b4fac560e419adae1ece8a94"
+  integrity sha512-wJGylKtMFR/Ds6Gh01+OovXE/pncPiKZNNBKuC39pKnH+XK5d9+WsNqcrdxPjFPFTigRBqse0rfxw9UxrfyhPg==
+  dependencies:
+    "@codemirror/language" "^6.0.0"
+    "@codemirror/state" "^6.0.0"
+    "@codemirror/view" "^6.17.0"
+    "@lezer/common" "^1.0.0"
+
+"@codemirror/autocomplete@^6.3.2":
   version "6.17.0"
   resolved "https://registry.yarnpkg.com/@codemirror/autocomplete/-/autocomplete-6.17.0.tgz#24ff5fc37fd91f6439df6f4ff9c8e910cde1b053"
   integrity sha512-fdfj6e6ZxZf8yrkMHUSJJir7OJkHkZKaOZGzLWIYp2PZ3jd+d+UjG8zVPqJF6d3bKxkhvXTPan/UZ1t7Bqm0gA==
@@ -35,10 +45,10 @@
     "@codemirror/view" "^6.17.0"
     "@lezer/common" "^1.0.0"
 
-"@codemirror/commands@^6.6.0":
-  version "6.6.0"
-  resolved "https://registry.yarnpkg.com/@codemirror/commands/-/commands-6.6.0.tgz#d308f143fe1b8896ca25fdb855f66acdaf019dd4"
-  integrity sha512-qnY+b7j1UNcTS31Eenuc/5YJB6gQOzkUoNmJQc0rznwqSRpeaWWpjkWy2C/MPTcePpsKJEM26hXrOXl1+nceXg==
+"@codemirror/commands@^6.7.1":
+  version "6.7.1"
+  resolved "https://registry.yarnpkg.com/@codemirror/commands/-/commands-6.7.1.tgz#04561e95bc0779eaa49efd63e916c4efb3bbf6d6"
+  integrity sha512-llTrboQYw5H4THfhN4U3qCnSZ1SOJ60ohhz+SzU0ADGtwlc533DtklQP0vSFaQuCPDn3BPpOd1GbbnUtwNjsrw==
   dependencies:
     "@codemirror/language" "^6.0.0"
     "@codemirror/state" "^6.4.0"
@@ -65,7 +75,18 @@
     "@codemirror/language" "^6.0.0"
     "@lezer/cpp" "^1.0.0"
 
-"@codemirror/lang-css@^6.0.0", "@codemirror/lang-css@^6.2.0", "@codemirror/lang-css@^6.2.1":
+"@codemirror/lang-css@^6.0.0", "@codemirror/lang-css@^6.3.0":
+  version "6.3.0"
+  resolved "https://registry.yarnpkg.com/@codemirror/lang-css/-/lang-css-6.3.0.tgz#607628559f2471b385c6070ec795072a55cffc0b"
+  integrity sha512-CyR4rUNG9OYcXDZwMPvJdtb6PHbBDKUc/6Na2BIwZ6dKab1JQqKa4di+RNRY9Myn7JB81vayKwJeQ7jEdmNVDA==
+  dependencies:
+    "@codemirror/autocomplete" "^6.0.0"
+    "@codemirror/language" "^6.0.0"
+    "@codemirror/state" "^6.0.0"
+    "@lezer/common" "^1.0.2"
+    "@lezer/css" "^1.1.7"
+
+"@codemirror/lang-css@^6.2.0":
   version "6.2.1"
   resolved "https://registry.yarnpkg.com/@codemirror/lang-css/-/lang-css-6.2.1.tgz#5dc0a43b8e3c31f6af7aabd55ff07fe9aef2a227"
   integrity sha512-/UNWDNV5Viwi/1lpr/dIXJNWiwDxpw13I4pTUAsNxZdg6E0mI2kTQb0P2iHczg1Tu+H4EBgJR+hYhKiHKko7qg==
@@ -156,7 +177,7 @@
     "@lezer/highlight" "^1.0.0"
     "@lezer/lr" "^1.3.1"
 
-"@codemirror/lang-markdown@^6.0.0", "@codemirror/lang-markdown@^6.2.5":
+"@codemirror/lang-markdown@^6.0.0":
   version "6.2.5"
   resolved "https://registry.yarnpkg.com/@codemirror/lang-markdown/-/lang-markdown-6.2.5.tgz#451941bf743d3788e73598f1aedb71cbeb6f71ba"
   integrity sha512-Hgke565YcO4fd9pe2uLYxnMufHO5rQwRr+AAhFq8ABuhkrjyX8R5p5s+hZUTdV60O0dMRjxKhBLxz8pu/MkUVA==
@@ -169,6 +190,19 @@
     "@lezer/common" "^1.2.1"
     "@lezer/markdown" "^1.0.0"
 
+"@codemirror/lang-markdown@^6.3.1":
+  version "6.3.1"
+  resolved "https://registry.yarnpkg.com/@codemirror/lang-markdown/-/lang-markdown-6.3.1.tgz#067e4e18993fa3520e2a980d2dce5fe23dd245a0"
+  integrity sha512-y3sSPuQjBKZQbQwe3ZJKrSW6Silyl9PnrU/Mf0m2OQgIlPoSYTtOvEL7xs94SVMkb8f4x+SQFnzXPdX4Wk2lsg==
+  dependencies:
+    "@codemirror/autocomplete" "^6.7.1"
+    "@codemirror/lang-html" "^6.0.0"
+    "@codemirror/language" "^6.3.0"
+    "@codemirror/state" "^6.0.0"
+    "@codemirror/view" "^6.0.0"
+    "@lezer/common" "^1.2.1"
+    "@lezer/markdown" "^1.0.0"
+
 "@codemirror/lang-php@^6.0.0", "@codemirror/lang-php@^6.0.1":
   version "6.0.1"
   resolved "https://registry.yarnpkg.com/@codemirror/lang-php/-/lang-php-6.0.1.tgz#fa34cc75562178325861a5731f79bd621f57ffaa"
@@ -210,7 +244,7 @@
     "@lezer/common" "^1.0.2"
     "@lezer/sass" "^1.0.0"
 
-"@codemirror/lang-sql@^6.0.0", "@codemirror/lang-sql@^6.7.0":
+"@codemirror/lang-sql@^6.0.0":
   version "6.7.0"
   resolved "https://registry.yarnpkg.com/@codemirror/lang-sql/-/lang-sql-6.7.0.tgz#a87fb9b458ae0ad1d8647c0234accca0ef11bb78"
   integrity sha512-KMXp6rtyPYz6RaElvkh/77ClEAoQoHRPZo0zutRRialeFs/B/X8YaUJBCnAV2zqyeJPLZ4hgo48mG8TKoNXfZA==
@@ -222,6 +256,18 @@
     "@lezer/highlight" "^1.0.0"
     "@lezer/lr" "^1.0.0"
 
+"@codemirror/lang-sql@^6.8.0":
+  version "6.8.0"
+  resolved "https://registry.yarnpkg.com/@codemirror/lang-sql/-/lang-sql-6.8.0.tgz#1ae68ad49f378605ff88a4cc428ba667ce056068"
+  integrity sha512-aGLmY4OwGqN3TdSx3h6QeA1NrvaYtF7kkoWR/+W7/JzB0gQtJ+VJxewlnE3+VImhA4WVlhmkJr109PefOOhjLg==
+  dependencies:
+    "@codemirror/autocomplete" "^6.0.0"
+    "@codemirror/language" "^6.0.0"
+    "@codemirror/state" "^6.0.0"
+    "@lezer/common" "^1.2.0"
+    "@lezer/highlight" "^1.0.0"
+    "@lezer/lr" "^1.0.0"
+
 "@codemirror/lang-vue@^0.1.1", "@codemirror/lang-vue@^0.1.3":
   version "0.1.3"
   resolved "https://registry.yarnpkg.com/@codemirror/lang-vue/-/lang-vue-0.1.3.tgz#bf79b9152cc18b4903d64c1f67e186ae045c8a97"
@@ -296,7 +342,19 @@
     "@codemirror/language" "^6.0.0"
     "@codemirror/legacy-modes" "^6.4.0"
 
-"@codemirror/language@^6.0.0", "@codemirror/language@^6.10.2", "@codemirror/language@^6.3.0", "@codemirror/language@^6.4.0", "@codemirror/language@^6.6.0", "@codemirror/language@^6.8.0":
+"@codemirror/language@^6.0.0", "@codemirror/language@^6.10.3", "@codemirror/language@^6.3.0", "@codemirror/language@^6.4.0", "@codemirror/language@^6.6.0":
+  version "6.10.3"
+  resolved "https://registry.yarnpkg.com/@codemirror/language/-/language-6.10.3.tgz#eb25fc5ade19032e7bf1dcaa957804e5f1660585"
+  integrity sha512-kDqEU5sCP55Oabl6E7m5N+vZRoc0iWqgDVhEKifcHzPzjqCegcO4amfrYVL9PmPZpl4G0yjkpTpUO/Ui8CzO8A==
+  dependencies:
+    "@codemirror/state" "^6.0.0"
+    "@codemirror/view" "^6.23.0"
+    "@lezer/common" "^1.1.0"
+    "@lezer/highlight" "^1.0.0"
+    "@lezer/lr" "^1.0.0"
+    style-mod "^4.0.0"
+
+"@codemirror/language@^6.8.0":
   version "6.10.2"
   resolved "https://registry.yarnpkg.com/@codemirror/language/-/language-6.10.2.tgz#4056dc219619627ffe995832eeb09cea6060be61"
   integrity sha512-kgbTYTo0Au6dCSc/TFy7fK3fpJmgHDv1sG1KNQKJXVi+xBTEeBPY/M30YXiU6mMXeH+YIDLsbrT4ZwNRdtF+SA==
@@ -308,26 +366,26 @@
     "@lezer/lr" "^1.0.0"
     style-mod "^4.0.0"
 
-"@codemirror/legacy-modes@^6.4.0":
-  version "6.4.0"
-  resolved "https://registry.yarnpkg.com/@codemirror/legacy-modes/-/legacy-modes-6.4.0.tgz#3cf7a863da5deebbd7bf9a90f12f89f06cca6d46"
-  integrity sha512-5m/K+1A6gYR0e+h/dEde7LoGimMjRtWXZFg4Lo70cc8HzjSdHe3fLwjWMR0VRl5KFT1SxalSap7uMgPKF28wBA==
+"@codemirror/legacy-modes@^6.4.0", "@codemirror/legacy-modes@^6.4.2":
+  version "6.4.2"
+  resolved "https://registry.yarnpkg.com/@codemirror/legacy-modes/-/legacy-modes-6.4.2.tgz#723a55aae21304d4c112575943d3467c9040d217"
+  integrity sha512-HsvWu08gOIIk303eZQCal4H4t65O/qp1V4ul4zVa3MHK5FJ0gz3qz3O55FIkm+aQUcshUOjBx38t2hPiJwW5/g==
   dependencies:
     "@codemirror/language" "^6.0.0"
 
-"@codemirror/lint@^6.0.0", "@codemirror/lint@^6.8.1":
-  version "6.8.1"
-  resolved "https://registry.yarnpkg.com/@codemirror/lint/-/lint-6.8.1.tgz#6427848815baaf68c08e98c7673b804d3d8c0e7f"
-  integrity sha512-IZ0Y7S4/bpaunwggW2jYqwLuHj0QtESf5xcROewY6+lDNwZ/NzvR4t+vpYgg9m7V8UXLPYqG+lu3DF470E5Oxg==
+"@codemirror/lint@^6.0.0", "@codemirror/lint@^6.8.2":
+  version "6.8.2"
+  resolved "https://registry.yarnpkg.com/@codemirror/lint/-/lint-6.8.2.tgz#7864b03583e9efd18554cff1dd4504da10338ab1"
+  integrity sha512-PDFG5DjHxSEjOXk9TQYYVjZDqlZTFaDBfhQixHnQOEVDDNHUbEh/hstAjcQJaA6FQdZTD1hquXTK0rVBLADR1g==
   dependencies:
     "@codemirror/state" "^6.0.0"
     "@codemirror/view" "^6.0.0"
     crelt "^1.0.5"
 
-"@codemirror/search@^6.5.6":
-  version "6.5.6"
-  resolved "https://registry.yarnpkg.com/@codemirror/search/-/search-6.5.6.tgz#8f858b9e678d675869112e475f082d1e8488db93"
-  integrity sha512-rpMgcsh7o0GuCDUXKPvww+muLA1pDJaFrpq/CCHtpQJYz8xopu4D1hPcKRoDD0YlF8gZaqTNIRa4VRBWyhyy7Q==
+"@codemirror/search@^6.5.7":
+  version "6.5.7"
+  resolved "https://registry.yarnpkg.com/@codemirror/search/-/search-6.5.7.tgz#fb60f6637437a8264f86079621a56290dc3814c4"
+  integrity sha512-6+iLsXvITWKHYlkgHPCs/qiX4dNzn8N78YfhOFvPtPYCkuXqZq10rAfsUMhOq7O/1VjJqdXRflyExlfVcu/9VQ==
   dependencies:
     "@codemirror/state" "^6.0.0"
     "@codemirror/view" "^6.0.0"
@@ -338,10 +396,10 @@
   resolved "https://registry.yarnpkg.com/@codemirror/state/-/state-6.4.1.tgz#da57143695c056d9a3c38705ed34136e2b68171b"
   integrity sha512-QkEyUiLhsJoZkbumGZlswmAhA7CBU02Wrz7zvH4SrcifbsqwlXShVXg65f3v/ts57W3dqyamEriMhij1Z3Zz4A==
 
-"@codemirror/view@^6.0.0", "@codemirror/view@^6.17.0", "@codemirror/view@^6.23.0", "@codemirror/view@^6.27.0", "@codemirror/view@^6.29.1":
-  version "6.29.1"
-  resolved "https://registry.yarnpkg.com/@codemirror/view/-/view-6.29.1.tgz#9c6c6f8a15e12df1b7e9d136dcbf4ff90b81ef71"
-  integrity sha512-7r+DlO/QFwPqKp73uq5mmrS4TuLPUVotbNOKYzN3OLP5ScrOVXcm4g13/48b6ZXGhdmzMinzFYqH0vo+qihIkQ==
+"@codemirror/view@^6.0.0", "@codemirror/view@^6.17.0", "@codemirror/view@^6.23.0", "@codemirror/view@^6.27.0", "@codemirror/view@^6.34.2":
+  version "6.34.2"
+  resolved "https://registry.yarnpkg.com/@codemirror/view/-/view-6.34.2.tgz#c6cc1387be217f448af585f05f23e681f76aeda7"
+  integrity sha512-d6n0WFvL970A9Z+l9N2dO+Hk9ev4hDYQzIx+B9tCyBP0W5wPEszi1rhuyFesNSkLZzXbQE5FPH7F/z/TMJfoPA==
   dependencies:
     "@codemirror/state" "^6.4.0"
     style-mod "^4.1.0"
@@ -493,9 +551,9 @@
     "@jridgewell/sourcemap-codec" "^1.4.14"
 
 "@lezer/common@^1.0.0", "@lezer/common@^1.0.2", "@lezer/common@^1.1.0", "@lezer/common@^1.2.0", "@lezer/common@^1.2.1":
-  version "1.2.1"
-  resolved "https://registry.yarnpkg.com/@lezer/common/-/common-1.2.1.tgz#198b278b7869668e1bebbe687586e12a42731049"
-  integrity sha512-yemX0ZD2xS/73llMZIK6KplkjIjf2EvAHcinDi/TfJ9hS25G0388+ClHt6/3but0oOxinTcQHJLDXh6w1crzFQ==
+  version "1.2.3"
+  resolved "https://registry.yarnpkg.com/@lezer/common/-/common-1.2.3.tgz#138fcddab157d83da557554851017c6c1e5667fd"
+  integrity sha512-w7ojc8ejBqr2REPsWxJjrMFsA/ysDCFICn8zEOR9mrqzOu2amhITYuLD8ag6XZf0CFXDrhKqw7+tW8cX66NaDA==
 
 "@lezer/cpp@^1.0.0":
   version "1.1.2"
@@ -506,10 +564,10 @@
     "@lezer/highlight" "^1.0.0"
     "@lezer/lr" "^1.0.0"
 
-"@lezer/css@^1.0.0", "@lezer/css@^1.1.0":
-  version "1.1.8"
-  resolved "https://registry.yarnpkg.com/@lezer/css/-/css-1.1.8.tgz#11fd456dac53bc899b266778794ed4ca9576a5a4"
-  integrity sha512-7JhxupKuMBaWQKjQoLtzhGj83DdnZY9MckEOG5+/iLKNK2ZJqKc6hf6uc0HjwCX7Qlok44jBNqZhHKDhEhZYLA==
+"@lezer/css@^1.0.0", "@lezer/css@^1.1.0", "@lezer/css@^1.1.7":
+  version "1.1.9"
+  resolved "https://registry.yarnpkg.com/@lezer/css/-/css-1.1.9.tgz#404563d361422c5a1fe917295f1527ee94845ed1"
+  integrity sha512-TYwgljcDv+YrV0MZFFvYFQHCfGgbPMR6nuqLabBdmZoFH3EP1gvw8t0vae326Ne3PszQkbXfVBjCnf3ZVCr0bA==
   dependencies:
     "@lezer/common" "^1.2.0"
     "@lezer/highlight" "^1.0.0"
@@ -524,7 +582,14 @@
     "@lezer/highlight" "^1.0.0"
     "@lezer/lr" "^1.0.0"
 
-"@lezer/highlight@^1.0.0", "@lezer/highlight@^1.1.3", "@lezer/highlight@^1.2.0":
+"@lezer/highlight@^1.0.0", "@lezer/highlight@^1.1.3":
+  version "1.2.1"
+  resolved "https://registry.yarnpkg.com/@lezer/highlight/-/highlight-1.2.1.tgz#596fa8f9aeb58a608be0a563e960c373cbf23f8b"
+  integrity sha512-Z5duk4RN/3zuVO7Jq0pGLJ3qynpxUVsh7IbUbGj88+uV2ApSAn6kWg2au3iJb+0Zi7kKtqffIESgNcRXWZWmSA==
+  dependencies:
+    "@lezer/common" "^1.0.0"
+
+"@lezer/highlight@^1.2.0":
   version "1.2.0"
   resolved "https://registry.yarnpkg.com/@lezer/highlight/-/highlight-1.2.0.tgz#e5898c3644208b4b589084089dceeea2966f7780"
   integrity sha512-WrS5Mw51sGrpqjlh3d4/fOwpEV2Hd3YOkp9DBt4k8XZQcoTHZFB7sx030A6OcahF4J1nDQAa3jXlTVVYH50IFA==
@@ -550,9 +615,9 @@
     "@lezer/lr" "^1.0.0"
 
 "@lezer/javascript@^1.0.0":
-  version "1.4.17"
-  resolved "https://registry.yarnpkg.com/@lezer/javascript/-/javascript-1.4.17.tgz#8456e369f960c328b9e823342d0c72d704238c31"
-  integrity sha512-bYW4ctpyGK+JMumDApeUzuIezX01H76R1foD6LcRX224FWfyYit/HYxiPGDjXXe/wQWASjCvVGoukTH68+0HIA==
+  version "1.4.19"
+  resolved "https://registry.yarnpkg.com/@lezer/javascript/-/javascript-1.4.19.tgz#7c8c8e5052537d8c8ddcae428e270227aadbddc9"
+  integrity sha512-j44kbR1QL26l6dMunZ1uhKBFteVGLVCBGNUD2sUaMnic+rbTviVuoK0CD1l9FTW31EueWvFFswCKMH7Z+M3JRA==
   dependencies:
     "@lezer/common" "^1.2.0"
     "@lezer/highlight" "^1.1.3"
@@ -575,9 +640,9 @@
     "@lezer/common" "^1.0.0"
 
 "@lezer/markdown@^1.0.0":
-  version "1.3.0"
-  resolved "https://registry.yarnpkg.com/@lezer/markdown/-/markdown-1.3.0.tgz#a954d48aa3256d07173353f80086f1a3bc6f965f"
-  integrity sha512-ErbEQ15eowmJUyT095e9NJc3BI9yZ894fjSDtHftD0InkfUBGgnKSU6dvan9jqsZuNHg2+ag/1oyDRxNsENupQ==
+  version "1.3.2"
+  resolved "https://registry.yarnpkg.com/@lezer/markdown/-/markdown-1.3.2.tgz#9d648b2a6cb47523f3d7ab494eee8c7be4f1ea9e"
+  integrity sha512-Wu7B6VnrKTbBEohqa63h5vxXjiC4pO5ZQJ/TDbhJxPQaaIoRD/6UVDhSDtVsCwVZV12vvN9KxuLL3ATMnlG0oQ==
   dependencies:
     "@lezer/common" "^1.0.0"
     "@lezer/highlight" "^1.0.0"
@@ -637,9 +702,9 @@
     "@lezer/lr" "^1.4.0"
 
 "@lit-labs/ssr-dom-shim@^1.2.0":
-  version "1.2.0"
-  resolved "https://registry.yarnpkg.com/@lit-labs/ssr-dom-shim/-/ssr-dom-shim-1.2.0.tgz#353ce4a76c83fadec272ea5674ede767650762fd"
-  integrity sha512-yWJKmpGE6lUURKAaIltoPIE/wrbY3TEkqQt+X0m+7fQNnAv0keydnYvbiJFP1PnMhizmIWRWOG5KLhYyc/xl+g==
+  version "1.2.1"
+  resolved "https://registry.yarnpkg.com/@lit-labs/ssr-dom-shim/-/ssr-dom-shim-1.2.1.tgz#2f3a8f1d688935c704dbc89132394a41029acbb8"
+  integrity sha512-wx4aBmgeGvFmOKucFKY+8VFJSYZxs9poN3SDNQFF6lT6NrQUnHiPB2PWz2sc4ieEcAaYYzN+1uWahEeTq2aRIQ==
 
 "@lit/reactive-element@^1.0.0 || ^2.0.0", "@lit/reactive-element@^2.0.4":
   version "2.0.4"
@@ -723,7 +788,7 @@
   dependencies:
     "@polymer/polymer" "^3.0.5"
 
-"@polymer/polymer@^3.0.5", "@polymer/polymer@^3.5.1":
+"@polymer/polymer@3.5.1", "@polymer/polymer@^3.0.5":
   version "3.5.1"
   resolved "https://registry.yarnpkg.com/@polymer/polymer/-/polymer-3.5.1.tgz#4b5234e43b8876441022bcb91313ab3c4a29f0c8"
   integrity sha512-JlAHuy+1qIC6hL1ojEUfIVD58fzTpJAoCxFwV5yr0mYTXV1H8bz5zy0+rC963Cgr9iNXQ4T9ncSjC2fkF9BQfw==
@@ -2376,23 +2441,30 @@
     debug "^2.6.9"
     marky "^1.2.2"
 
-lit-element@^4.0.4:
-  version "4.0.6"
-  resolved "https://registry.yarnpkg.com/lit-element/-/lit-element-4.0.6.tgz#b9f5b5d68f30636be1314ec76c9a73a6405f04dc"
-  integrity sha512-U4sdJ3CSQip7sLGZ/uJskO5hGiqtlpxndsLr6mt3IQIjheg93UKYeGQjWMRql1s/cXNOaRrCzC2FQwjIwSUqkg==
+lit-element@^4.0.4, lit-element@^4.1.0:
+  version "4.1.1"
+  resolved "https://registry.yarnpkg.com/lit-element/-/lit-element-4.1.1.tgz#07905992815076e388cf6f1faffc7d6866c82007"
+  integrity sha512-HO9Tkkh34QkTeUmEdNYhMT8hzLid7YlMlATSi1q4q17HE5d9mrrEHJ/o8O2D0cMi182zK1F3v7x0PWFjrhXFew==
   dependencies:
     "@lit-labs/ssr-dom-shim" "^1.2.0"
     "@lit/reactive-element" "^2.0.4"
-    lit-html "^3.1.2"
+    lit-html "^3.2.0"
 
-"lit-html@^2.0.0 || ^3.0.0", lit-html@^3.1.2:
+"lit-html@^2.0.0 || ^3.0.0":
   version "3.1.4"
   resolved "https://registry.yarnpkg.com/lit-html/-/lit-html-3.1.4.tgz#30ad4f11467a61e2f08856de170e343184e9034e"
   integrity sha512-yKKO2uVv7zYFHlWMfZmqc+4hkmSbFp8jgjdZY9vvR9jr4J8fH6FUMXhr+ljfELgmjpvlF7Z1SJ5n5/Jeqtc9YA==
   dependencies:
     "@types/trusted-types" "^2.0.2"
 
-"lit@^2.0.0 || ^3.0.0", lit@^3.1.4:
+lit-html@^3.1.2, lit-html@^3.2.0:
+  version "3.2.1"
+  resolved "https://registry.yarnpkg.com/lit-html/-/lit-html-3.2.1.tgz#8fc49e3531ee5947e4d93e8a5aa642ab1649833b"
+  integrity sha512-qI/3lziaPMSKsrwlxH/xMgikhQ0EGOX2ICU73Bi/YHFvz2j/yMCIrw4+puF2IpQ4+upd3EWbvnHM9+PnJn48YA==
+  dependencies:
+    "@types/trusted-types" "^2.0.2"
+
+"lit@^2.0.0 || ^3.0.0":
   version "3.1.4"
   resolved "https://registry.yarnpkg.com/lit/-/lit-3.1.4.tgz#03a72e9f0b1f5da317bf49b1ab579a7132e73d7a"
   integrity sha512-q6qKnKXHy2g1kjBaNfcoLlgbI3+aSOZ9Q4tiGa9bGYXq5RBXxkVTqTIVmP2VWMp29L4GyvCFm8ZQ2o56eUAMyA==
@@ -2401,6 +2473,15 @@
     lit-element "^4.0.4"
     lit-html "^3.1.2"
 
+lit@^3.2.1:
+  version "3.2.1"
+  resolved "https://registry.yarnpkg.com/lit/-/lit-3.2.1.tgz#d6dd15eac20db3a098e81e2c85f70a751ff55592"
+  integrity sha512-1BBa1E/z0O9ye5fZprPtdqnc0BFzxIxTTOO/tQFmyC/hj1O3jL4TfmLBw0WEwjAokdLwpclkvGgDJwTIh0/22w==
+  dependencies:
+    "@lit/reactive-element" "^2.0.4"
+    lit-element "^4.1.0"
+    lit-html "^3.2.0"
+
 lodash.camelcase@^4.3.0:
   version "4.3.0"
   resolved "https://registry.yarnpkg.com/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz#b28aa6288a2b9fc651035c7711f65ab6190331a6"
diff --git a/polygerrit-ui/app/elements/shared/gr-formatted-text/gr-formatted-text.ts b/polygerrit-ui/app/elements/shared/gr-formatted-text/gr-formatted-text.ts
index 900e9ed..fa2a4ff 100644
--- a/polygerrit-ui/app/elements/shared/gr-formatted-text/gr-formatted-text.ts
+++ b/polygerrit-ui/app/elements/shared/gr-formatted-text/gr-formatted-text.ts
@@ -68,7 +68,8 @@
         p:last-child,
         ul:last-child,
         blockquote:last-child,
-        pre:last-child {
+        pre:last-child,
+        pre.plaintext {
           margin: 0;
         }
         blockquote {
diff --git a/polygerrit-ui/app/elements/shared/gr-js-api-interface/gr-api-utils.ts b/polygerrit-ui/app/elements/shared/gr-js-api-interface/gr-api-utils.ts
index a1d2dcb..1396157 100644
--- a/polygerrit-ui/app/elements/shared/gr-js-api-interface/gr-api-utils.ts
+++ b/polygerrit-ui/app/elements/shared/gr-js-api-interface/gr-api-utils.ts
@@ -4,10 +4,6 @@
  * SPDX-License-Identifier: Apache-2.0
  */
 import {getBaseUrl} from '../../../utils/url-util';
-import {HttpMethod} from '../../../constants/constants';
-import {RequestPayload} from '../../../types/common';
-import {RestApiService} from '../../../services/gr-rest-api/gr-rest-api';
-import {readJSONResponsePayload} from '../gr-rest-api-interface/gr-rest-apis/gr-rest-api-helper';
 
 export const PLUGIN_LOADING_TIMEOUT_MS = 10000;
 
@@ -56,33 +52,3 @@
   // TODO(taoalpha): guard with a regex
   return pathname.split('/')[2].split('.')[0];
 }
-
-export function send(
-  restApiService: RestApiService,
-  method: HttpMethod,
-  url: string,
-  callback?: (response: unknown) => void,
-  payload?: RequestPayload
-) {
-  return restApiService
-    .send(method, url, payload)
-    .then(response => {
-      if (response.status < 200 || response.status >= 300) {
-        return response.text().then((text: string | undefined) => {
-          if (text) {
-            return Promise.reject(new Error(text));
-          } else {
-            return Promise.reject(new Error(`${response.status}`));
-          }
-        });
-      } else {
-        return readJSONResponsePayload(response).then(obj => obj.parsed);
-      }
-    })
-    .then(response => {
-      if (callback) {
-        callback(response);
-      }
-      return response;
-    });
-}
diff --git a/polygerrit-ui/app/elements/shared/gr-js-api-interface/gr-js-api-interface_test.ts b/polygerrit-ui/app/elements/shared/gr-js-api-interface/gr-js-api-interface_test.ts
index a21ddc3..d57c4f4 100644
--- a/polygerrit-ui/app/elements/shared/gr-js-api-interface/gr-js-api-interface_test.ts
+++ b/polygerrit-ui/app/elements/shared/gr-js-api-interface/gr-js-api-interface_test.ts
@@ -13,7 +13,6 @@
   stubBaseUrl,
   waitEventLoop,
   waitUntilCalled,
-  assertFails,
 } from '../../../test/test-utils';
 import {assert} from '@open-wc/testing';
 import {testResolver} from '../../../test/common-test-setup';
@@ -23,7 +22,6 @@
 import {Plugin} from './gr-public-js-api';
 import {
   ChangeInfo,
-  HttpMethod,
   NumericChangeId,
   PatchSetNum,
   RevisionPatchSetNum,
@@ -43,7 +41,6 @@
   let errorStub: SinonStub;
   let pluginLoader: PluginLoader;
 
-  let sendStub: SinonStub;
   let clock: SinonFakeTimers;
 
   const throwErrFn = function () {
@@ -57,9 +54,6 @@
       name: 'Judy Hopps',
       registered_on: '' as Timestamp,
     });
-    sendStub = stubRestApi('send').resolves(
-      new Response(undefined, {status: 200})
-    );
     pluginLoader = testResolver(pluginLoaderToken);
 
     // We are using the jsApiService as the implementation class rather than the
@@ -91,28 +85,6 @@
     );
   });
 
-  test('_send on failure rejects with response text', async () => {
-    sendStub.resolves({
-      status: 400,
-      text() {
-        return Promise.resolve('text');
-      },
-    });
-    const error = await assertFails<Error>(plugin._send(HttpMethod.POST, ''));
-    assert.equal(error.message, 'text');
-  });
-
-  test('_send on failure without text rejects with code', async () => {
-    sendStub.resolves({
-      status: 400,
-      text() {
-        return Promise.resolve(null);
-      },
-    });
-    const error = await assertFails<Error>(plugin._send(HttpMethod.POST, ''));
-    assert.equal(error.message, '400');
-  });
-
   test('showchange event', async () => {
     const showChangeStub = stub();
     const testChange: ParsedChangeInfo = {
diff --git a/polygerrit-ui/app/elements/shared/gr-js-api-interface/gr-public-js-api.ts b/polygerrit-ui/app/elements/shared/gr-js-api-interface/gr-public-js-api.ts
index d3dea78..b076373 100644
--- a/polygerrit-ui/app/elements/shared/gr-js-api-interface/gr-public-js-api.ts
+++ b/polygerrit-ui/app/elements/shared/gr-js-api-interface/gr-public-js-api.ts
@@ -14,11 +14,9 @@
 import {GrEventHelper} from '../../plugins/gr-event-helper/gr-event-helper';
 import {GrPluginRestApi} from './gr-plugin-rest-api';
 import {EndpointType, GrPluginEndpoints} from './gr-plugin-endpoints';
-import {getPluginNameFromUrl, send} from './gr-api-utils';
+import {getPluginNameFromUrl} from './gr-api-utils';
 import {GrReportingJsApi} from './gr-reporting-js-api';
 import {EventType, PluginApi, TargetElement} from '../../../api/plugin';
-import {RequestPayload} from '../../../types/common';
-import {HttpMethod} from '../../../constants/constants';
 import {GrChangeActions} from '../../change/gr-change-actions/gr-change-actions';
 import {GrChecksApi} from '../../plugins/gr-checks-api/gr-checks-api';
 import {AdminPluginApi} from '../../../api/admin';
@@ -180,15 +178,6 @@
     return `${origin}${base}/x/${this.getPluginName()}${tokenPart}`;
   }
 
-  _send(
-    method: HttpMethod,
-    url: string,
-    callback?: SendCallback,
-    payload?: RequestPayload
-  ) {
-    return send(this.restApiService, method, this.url(url), callback, payload);
-  }
-
   annotationApi(): AnnotationPluginApi {
     return new GrAnnotationActionsInterface(
       this.report,
diff --git a/polygerrit-ui/app/embed/diff/gr-diff-processor/gr-diff-processor.ts b/polygerrit-ui/app/embed/diff/gr-diff-processor/gr-diff-processor.ts
index d138414..89bb49e 100644
--- a/polygerrit-ui/app/embed/diff/gr-diff-processor/gr-diff-processor.ts
+++ b/polygerrit-ui/app/embed/diff/gr-diff-processor/gr-diff-processor.ts
@@ -181,18 +181,29 @@
     return chunkIndex;
   }
 
+  /**
+   * Check if a chunk is collapsible.
+   *
+   * A chunk is collapsible if it is either common or skippable, and it is not
+   * a key location, or it is outside of the focus range.
+   *
+   * @param chunk The chunk to check.
+   * @param offsetLeft The offset of the left side of the chunk.
+   * @param offsetRight The offset of the right side of the chunk.
+   * @return True if the chunk is collapsible, false otherwise.
+   */
   private isCollapsibleChunk(
     chunk: DiffContent,
     offsetLeft: number,
     offsetRight: number
   ) {
-    return (
-      (chunk.ab ||
-        chunk.common ||
-        chunk.skip ||
-        this.isChunkOutsideOfFocusRange(chunk, offsetLeft, offsetRight)) &&
-      !chunk.keyLocation
+    const isCommonOrSkip = chunk.ab || chunk.common || chunk.skip;
+    const isOutsideOfFocusRange = this.isChunkOutsideOfFocusRange(
+      chunk,
+      offsetLeft,
+      offsetRight
     );
+    return (isCommonOrSkip && !chunk.keyLocation) || isOutsideOfFocusRange;
   }
 
   private isChunkOutsideOfFocusRange(
diff --git a/polygerrit-ui/app/embed/diff/gr-diff-processor/gr-diff-processor_test.ts b/polygerrit-ui/app/embed/diff/gr-diff-processor/gr-diff-processor_test.ts
index 3f01096..19a687e 100644
--- a/polygerrit-ui/app/embed/diff/gr-diff-processor/gr-diff-processor_test.ts
+++ b/polygerrit-ui/app/embed/diff/gr-diff-processor/gr-diff-processor_test.ts
@@ -1054,6 +1054,32 @@
           assert.equal(result.groups[0].lines.length, 5);
           assert.equal(result.groups[1].type, GrDiffGroupType.DELTA);
         });
+
+        test('collapse chunks with key locations if out of focus range', () => {
+          const keyLocationLineText = 'key location behind a context group';
+          state = {
+            lineNums: {left: 7, right: 6},
+            chunkIndex: 4,
+          };
+          const result = processor.processNext(state, [
+            ...chunks,
+            {
+              ab: Array.from<string>({length: 2}).fill(
+                'all work and no play make jill a dull boy'
+              ),
+              keyLocation: false,
+            },
+            {
+              ab: Array.from<string>({length: 5}).fill(keyLocationLineText),
+              keyLocation: true,
+            },
+          ]);
+          assert.equal(result.groups.length, 3);
+          assert.equal(
+            result.groups[2].contextGroups[0].lines[0].text,
+            keyLocationLineText
+          );
+        });
       });
     });
 
diff --git a/polygerrit-ui/app/embed/diff/gr-diff/gr-diff-styles.ts b/polygerrit-ui/app/embed/diff/gr-diff/gr-diff-styles.ts
index 98a2093..2913fc8 100644
--- a/polygerrit-ui/app/embed/diff/gr-diff/gr-diff-styles.ts
+++ b/polygerrit-ui/app/embed/diff/gr-diff/gr-diff-styles.ts
@@ -369,6 +369,9 @@
     background-color: var(--dark-add-highlight-color);
     &:has(.is-out-of-focus-range) {
       background-color: transparent;
+      .intraline {
+        background-color: transparent;
+      }
     }
   }
   gr-diff-row td.content.add div.contentText,
@@ -376,6 +379,9 @@
     background-color: var(--light-add-highlight-color);
     &:has(.is-out-of-focus-range) {
       background-color: transparent;
+      .intraline {
+        background-color: transparent;
+      }
     }
   }
   /* If there are no intraline info, consider everything changed */
diff --git a/polygerrit-ui/app/package.json b/polygerrit-ui/app/package.json
index 850a97aa..d2b5283 100644
--- a/polygerrit-ui/app/package.json
+++ b/polygerrit-ui/app/package.json
@@ -29,7 +29,7 @@
     "@polymer/paper-tabs": "^3.1.0",
     "@polymer/paper-toggle-button": "^3.0.1",
     "@polymer/paper-tooltip": "^3.0.1",
-    "@polymer/polymer": "^3.5.1",
+    "@polymer/polymer": "3.5.1",
     "@types/resemblejs": "^4.1.3",
     "@types/resize-observer-browser": "^0.1.11",
     "@webcomponents/shadycss": "^1.11.2",
@@ -39,7 +39,7 @@
     "highlightjs-epp": "https://github.com/highlightjs/highlightjs-epp#9f9e1a92f37c217c68899c7d3bdccb4d134681b9",
     "highlightjs-structured-text": "https://github.com/highlightjs/highlightjs-structured-text#e68dd7aa829529fb6c40d6287585f43273605a9e",
     "immer": "^9.0.21",
-    "lit": "^3.1.4",
+    "lit": "^3.2.1",
     "polymer-bridges": "file:../../polymer-bridges",
     "polymer-resin": "^2.0.1",
     "resemblejs": "^5.0.0",
@@ -52,8 +52,13 @@
       "There is a an issue with release 0.3.2, which exposes both an ESM and a CommonJS module:",
       "https://github.com/google/safevalues/commit/16aa2567dc303759841b097b1901d1d6ff4e083e",
       "That causes tests to fail claiming that 'sanitizeHtml' is not exported from safevalues."
+    ],
+    "@polymer/polymer": [
+      "There is a an issue with release 3.5.2. Tests are failing with:",
+      "NotSupportedError: Failed to execute 'define' on 'CustomElementRegistry':",
+      "the name 'dom-module' has already been used with this registry at ..."
     ]
   },
   "license": "Apache-2.0",
   "private": true
-}
+}
\ No newline at end of file
diff --git a/polygerrit-ui/app/services/gr-rest-api/gr-rest-api-impl.ts b/polygerrit-ui/app/services/gr-rest-api/gr-rest-api-impl.ts
index a65eddc..5180d93 100644
--- a/polygerrit-ui/app/services/gr-rest-api/gr-rest-api-impl.ts
+++ b/polygerrit-ui/app/services/gr-rest-api/gr-rest-api-impl.ts
@@ -1328,6 +1328,10 @@
     if (window.DEFAULT_DETAIL_HEXES && window.DEFAULT_DETAIL_HEXES.changePage) {
       return window.DEFAULT_DETAIL_HEXES.changePage;
     }
+    // Kept as a fallback in case DEFAULT_DETAIL_HEXES is not set in index file
+    // (e.g PolyGerritIndexHtml.soy)
+    // We expect that DEFAULT_DETAIL_HEXES is always set and we are
+    // using same hex as preloaded queries
     return listChangesOptionsToHex(...(await this.getChangeOptions()));
   }
 
diff --git a/polygerrit-ui/app/yarn.lock b/polygerrit-ui/app/yarn.lock
index d863af3..80ab2ec 100644
--- a/polygerrit-ui/app/yarn.lock
+++ b/polygerrit-ui/app/yarn.lock
@@ -423,7 +423,7 @@
     "@polymer/paper-styles" "^3.0.0-pre.26"
     "@polymer/polymer" "^3.0.0"
 
-"@polymer/polymer@^3.0.0", "@polymer/polymer@^3.0.2", "@polymer/polymer@^3.0.5", "@polymer/polymer@^3.3.1", "@polymer/polymer@^3.5.1":
+"@polymer/polymer@3.5.1", "@polymer/polymer@^3.0.0", "@polymer/polymer@^3.0.2", "@polymer/polymer@^3.0.5", "@polymer/polymer@^3.3.1":
   version "3.5.1"
   resolved "https://registry.yarnpkg.com/@polymer/polymer/-/polymer-3.5.1.tgz#4b5234e43b8876441022bcb91313ab3c4a29f0c8"
   integrity sha512-JlAHuy+1qIC6hL1ojEUfIVD58fzTpJAoCxFwV5yr0mYTXV1H8bz5zy0+rC963Cgr9iNXQ4T9ncSjC2fkF9BQfw==
@@ -669,30 +669,30 @@
   resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz#f116f8064fe90b3f7844a38997c0b75051269f1d"
   integrity sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==
 
-lit-element@^4.0.4:
-  version "4.0.6"
-  resolved "https://registry.yarnpkg.com/lit-element/-/lit-element-4.0.6.tgz#b9f5b5d68f30636be1314ec76c9a73a6405f04dc"
-  integrity sha512-U4sdJ3CSQip7sLGZ/uJskO5hGiqtlpxndsLr6mt3IQIjheg93UKYeGQjWMRql1s/cXNOaRrCzC2FQwjIwSUqkg==
+lit-element@^4.1.0:
+  version "4.1.1"
+  resolved "https://registry.yarnpkg.com/lit-element/-/lit-element-4.1.1.tgz#07905992815076e388cf6f1faffc7d6866c82007"
+  integrity sha512-HO9Tkkh34QkTeUmEdNYhMT8hzLid7YlMlATSi1q4q17HE5d9mrrEHJ/o8O2D0cMi182zK1F3v7x0PWFjrhXFew==
   dependencies:
     "@lit-labs/ssr-dom-shim" "^1.2.0"
     "@lit/reactive-element" "^2.0.4"
-    lit-html "^3.1.2"
+    lit-html "^3.2.0"
 
-lit-html@^3.1.2:
-  version "3.1.4"
-  resolved "https://registry.yarnpkg.com/lit-html/-/lit-html-3.1.4.tgz#30ad4f11467a61e2f08856de170e343184e9034e"
-  integrity sha512-yKKO2uVv7zYFHlWMfZmqc+4hkmSbFp8jgjdZY9vvR9jr4J8fH6FUMXhr+ljfELgmjpvlF7Z1SJ5n5/Jeqtc9YA==
+lit-html@^3.2.0:
+  version "3.2.1"
+  resolved "https://registry.yarnpkg.com/lit-html/-/lit-html-3.2.1.tgz#8fc49e3531ee5947e4d93e8a5aa642ab1649833b"
+  integrity sha512-qI/3lziaPMSKsrwlxH/xMgikhQ0EGOX2ICU73Bi/YHFvz2j/yMCIrw4+puF2IpQ4+upd3EWbvnHM9+PnJn48YA==
   dependencies:
     "@types/trusted-types" "^2.0.2"
 
-lit@^3.1.4:
-  version "3.1.4"
-  resolved "https://registry.yarnpkg.com/lit/-/lit-3.1.4.tgz#03a72e9f0b1f5da317bf49b1ab579a7132e73d7a"
-  integrity sha512-q6qKnKXHy2g1kjBaNfcoLlgbI3+aSOZ9Q4tiGa9bGYXq5RBXxkVTqTIVmP2VWMp29L4GyvCFm8ZQ2o56eUAMyA==
+lit@^3.2.1:
+  version "3.2.1"
+  resolved "https://registry.yarnpkg.com/lit/-/lit-3.2.1.tgz#d6dd15eac20db3a098e81e2c85f70a751ff55592"
+  integrity sha512-1BBa1E/z0O9ye5fZprPtdqnc0BFzxIxTTOO/tQFmyC/hj1O3jL4TfmLBw0WEwjAokdLwpclkvGgDJwTIh0/22w==
   dependencies:
     "@lit/reactive-element" "^2.0.4"
-    lit-element "^4.0.4"
-    lit-html "^3.1.2"
+    lit-element "^4.1.0"
+    lit-html "^3.2.0"
 
 lru-cache@^6.0.0:
   version "6.0.0"
diff --git a/yarn.lock b/yarn.lock
index 328680b..8a5d986 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -10,11 +10,6 @@
     lodash.assignwith "^4.2.0"
     typical "^7.1.1"
 
-"@aashutoshrathi/word-wrap@^1.2.3":
-  version "1.2.6"
-  resolved "https://registry.yarnpkg.com/@aashutoshrathi/word-wrap/-/word-wrap-1.2.6.tgz#bd9154aec9983f77b3a034ecaa015c2e4201f6cf"
-  integrity sha512-1Yjs2SvM8TflER/OD3cOjhWWOZb58A2t7wpE2S9XfBYTiIl+XFhQG2bjy4Pu1I+EAlCNUzRDYDdFwFYUKvXcIA==
-
 "@babel/code-frame@^7.0.0", "@babel/code-frame@^7.12.11":
   version "7.23.5"
   resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.23.5.tgz#9009b69a8c602293476ad598ff53e4562e15c244"
@@ -202,17 +197,22 @@
   integrity sha512-lAhycmKnVOuRYNtRtatQR1LPQf2oYCkRGkSFnseDAKPl8lu5SOsK/e1sXe5a0Pc5kHIHe6P2I/ilntNv2xf3cA==
 
 "@eslint-community/eslint-utils@^4.2.0":
-  version "4.4.0"
-  resolved "https://registry.yarnpkg.com/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz#a23514e8fb9af1269d5f7788aa556798d61c6b59"
-  integrity sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==
+  version "4.4.1"
+  resolved "https://registry.yarnpkg.com/@eslint-community/eslint-utils/-/eslint-utils-4.4.1.tgz#d1145bf2c20132d6400495d6df4bf59362fd9d56"
+  integrity sha512-s3O3waFUrMV8P/XaF/+ZTp1X9XBZW1a4B97ZnjQF2KYWaFD2A8KyFBsrsfSjEmjn3RGWAIuvlneuZm3CUK3jbA==
   dependencies:
-    eslint-visitor-keys "^3.3.0"
+    eslint-visitor-keys "^3.4.3"
 
-"@eslint-community/regexpp@^4.4.0", "@eslint-community/regexpp@^4.6.1":
+"@eslint-community/regexpp@^4.4.0":
   version "4.10.0"
   resolved "https://registry.yarnpkg.com/@eslint-community/regexpp/-/regexpp-4.10.0.tgz#548f6de556857c8bb73bbee70c35dc82a2e74d63"
   integrity sha512-Cu96Sd2By9mCNTx2iyKOmq10v22jUVQv0lQnlGNy16oE9589yE+QADPbrMGCkA51cKZSg3Pu/aTJVTGfL/qjUA==
 
+"@eslint-community/regexpp@^4.6.1":
+  version "4.12.1"
+  resolved "https://registry.yarnpkg.com/@eslint-community/regexpp/-/regexpp-4.12.1.tgz#cfc6cffe39df390a3841cde2abccf92eaa7ae0e0"
+  integrity sha512-CCZCDJuduB9OUkFkY2IgppNZMi2lBQgD2qzwXkEia16cge2pijY/aXi96CJMquDMn3nJdlPV1A5KrJEXwfLNzQ==
+
 "@eslint/eslintrc@^2.1.4":
   version "2.1.4"
   resolved "https://registry.yarnpkg.com/@eslint/eslintrc/-/eslintrc-2.1.4.tgz#388a269f0f25c1b6adc317b5a2c55714894c70ad"
@@ -228,17 +228,17 @@
     minimatch "^3.1.2"
     strip-json-comments "^3.1.1"
 
-"@eslint/js@8.57.0":
-  version "8.57.0"
-  resolved "https://registry.yarnpkg.com/@eslint/js/-/js-8.57.0.tgz#a5417ae8427873f1dd08b70b3574b453e67b5f7f"
-  integrity sha512-Ys+3g2TaW7gADOJzPt83SJtCDhMjndcDMFVQ/Tj9iA1BfJzFKD9mAUXT3OenpuPHbI6P/myECxRJrofUsDx/5g==
+"@eslint/js@8.57.1":
+  version "8.57.1"
+  resolved "https://registry.yarnpkg.com/@eslint/js/-/js-8.57.1.tgz#de633db3ec2ef6a3c89e2f19038063e8a122e2c2"
+  integrity sha512-d9zaMRSTIKDLhctzH12MtXvJKSSUhaHcjV+2Z+GK+EEY7XKpP5yR4x+N3TAcHTcu963nIr+TMcCb4DBCYX1z6Q==
 
-"@humanwhocodes/config-array@^0.11.14":
-  version "0.11.14"
-  resolved "https://registry.yarnpkg.com/@humanwhocodes/config-array/-/config-array-0.11.14.tgz#d78e481a039f7566ecc9660b4ea7fe6b1fec442b"
-  integrity sha512-3T8LkOmg45BV5FICb15QQMsyUSWrQ8AygVfC7ZG32zOalnqrilm018ZVCw0eapXux8FtA33q8PSRSstjee3jSg==
+"@humanwhocodes/config-array@^0.13.0":
+  version "0.13.0"
+  resolved "https://registry.yarnpkg.com/@humanwhocodes/config-array/-/config-array-0.13.0.tgz#fb907624df3256d04b9aa2df50d7aa97ec648748"
+  integrity sha512-DZLEEqFWQFiyK6h5YIeynKx7JlvCYWL0cImfSRXZ9l4Sg2efkFGTuFf6vzXjK1cq6IYkU+Eg/JizXw+TD2vRNw==
   dependencies:
-    "@humanwhocodes/object-schema" "^2.0.2"
+    "@humanwhocodes/object-schema" "^2.0.3"
     debug "^4.3.1"
     minimatch "^3.0.5"
 
@@ -247,7 +247,7 @@
   resolved "https://registry.yarnpkg.com/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz#af5b2691a22b44be847b0ca81641c5fb6ad0172c"
   integrity sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==
 
-"@humanwhocodes/object-schema@^2.0.2":
+"@humanwhocodes/object-schema@^2.0.3":
   version "2.0.3"
   resolved "https://registry.yarnpkg.com/@humanwhocodes/object-schema/-/object-schema-2.0.3.tgz#4a2868d75d6d6963e423bcf90b7fd1be343409d3"
   integrity sha512-93zYdMES/c1D69yZiKDBj0V24vqNzB/koF26KPaagAfd3P/4gUlh3Dys5ogAK+Exi9QyzlD8x/08Zt7wIKcDcA==
@@ -372,6 +372,11 @@
     estree-walker "^1.0.1"
     picomatch "^2.2.2"
 
+"@rtsao/scc@^1.1.0":
+  version "1.1.0"
+  resolved "https://registry.yarnpkg.com/@rtsao/scc/-/scc-1.1.0.tgz#927dd2fae9bc3361403ac2c7a00c32ddce9ad7e8"
+  integrity sha512-zt6OdqaDoOnJ1ZYsCYGt9YmWzDXl4vQdKTyJev62gFhRGKdx7mcT54V9KIjg+d2wi9EXsPvAPKe7i7WjfVWB8g==
+
 "@types/accepts@*":
   version "1.3.7"
   resolved "https://registry.yarnpkg.com/@types/accepts/-/accepts-1.3.7.tgz#3b98b1889d2b2386604c2bbbe62e4fb51e95b265"
@@ -763,9 +768,9 @@
   integrity sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==
 
 acorn@^8.9.0:
-  version "8.11.3"
-  resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.11.3.tgz#71e0b14e13a4ec160724b38fb7b0f233b1b81d7a"
-  integrity sha512-Y9rRfJG5jcKOE0CLisYbojUjIrIEE7AGMzA/Sm4BslANhbS+cDMpgBdcPT91oJ7OuJ9hYJBx59RjbhxVnrF8Xg==
+  version "8.14.0"
+  resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.14.0.tgz#063e2c70cac5fb4f6467f0b11152e04c682795b0"
+  integrity sha512-cl669nCJTZBsL97OF4kUQm5g5hC2uihk0NxY3WENAC0TYdILVkAyHymAntgxGkl7K+t0cXIrH5siy5S4XkFycA==
 
 ajv@^6.12.4:
   version "6.12.6"
@@ -846,23 +851,24 @@
   resolved "https://registry.yarnpkg.com/array-back/-/array-back-6.2.2.tgz#f567d99e9af88a6d3d2f9dfcc21db6f9ba9fd157"
   integrity sha512-gUAZ7HPyb4SJczXAMUXMGAvI976JoK3qEx9v1FTmeYuJj0IBiaKttG1ydtGKdkfqWkIkouke7nG8ufGy77+Cvw==
 
-array-buffer-byte-length@^1.0.0:
-  version "1.0.0"
-  resolved "https://registry.yarnpkg.com/array-buffer-byte-length/-/array-buffer-byte-length-1.0.0.tgz#fabe8bc193fea865f317fe7807085ee0dee5aead"
-  integrity sha512-LPuwb2P+NrQw3XhxGc36+XSvuBPopovXYTR9Ew++Du9Yb/bx5AzBfrIsBoj0EZUifjQU+sHL21sseZ3jerWO/A==
+array-buffer-byte-length@^1.0.1:
+  version "1.0.1"
+  resolved "https://registry.yarnpkg.com/array-buffer-byte-length/-/array-buffer-byte-length-1.0.1.tgz#1e5583ec16763540a27ae52eed99ff899223568f"
+  integrity sha512-ahC5W1xgou+KTXix4sAO8Ki12Q+jf4i0+tmk3sC+zgcynshkHxzpXdImBehiUYKKKDwvfFiJl1tZt6ewscS1Mg==
   dependencies:
-    call-bind "^1.0.2"
-    is-array-buffer "^3.0.1"
+    call-bind "^1.0.5"
+    is-array-buffer "^3.0.4"
 
-array-includes@^3.1.7:
-  version "3.1.7"
-  resolved "https://registry.yarnpkg.com/array-includes/-/array-includes-3.1.7.tgz#8cd2e01b26f7a3086cbc87271593fe921c62abda"
-  integrity sha512-dlcsNBIiWhPkHdOEEKnehA+RNUWDc4UqFtnIXU4uuYDPtA4LDkr7qip2p0VvFAEXNDr0yWZ9PJyIRiGjRLQzwQ==
+array-includes@^3.1.8:
+  version "3.1.8"
+  resolved "https://registry.yarnpkg.com/array-includes/-/array-includes-3.1.8.tgz#5e370cbe172fdd5dd6530c1d4aadda25281ba97d"
+  integrity sha512-itaWrbYbqpGXkGhZPGUulwnhVf5Hpy1xiCFsGqyIGglbBxmG5vSjxQen3/WGOjPpNEv1RtBLKxbmVXm8HpJStQ==
   dependencies:
-    call-bind "^1.0.2"
-    define-properties "^1.2.0"
-    es-abstract "^1.22.1"
-    get-intrinsic "^1.2.1"
+    call-bind "^1.0.7"
+    define-properties "^1.2.1"
+    es-abstract "^1.23.2"
+    es-object-atoms "^1.0.0"
+    get-intrinsic "^1.2.4"
     is-string "^1.0.7"
 
 array-union@^2.1.0:
@@ -875,16 +881,17 @@
   resolved "https://registry.yarnpkg.com/array-unique/-/array-unique-0.3.2.tgz#a894b75d4bc4f6cd679ef3244a9fd8f46ae2d428"
   integrity sha512-SleRWjh9JUud2wH1hPs9rZBZ33H6T9HOiL0uwGnGx9FpE6wKGyfWugmbkEOIs6qWrZhg0LWeLziLrEwQJhs5mQ==
 
-array.prototype.findlastindex@^1.2.3:
-  version "1.2.3"
-  resolved "https://registry.yarnpkg.com/array.prototype.findlastindex/-/array.prototype.findlastindex-1.2.3.tgz#b37598438f97b579166940814e2c0493a4f50207"
-  integrity sha512-LzLoiOMAxvy+Gd3BAq3B7VeIgPdo+Q8hthvKtXybMvRV0jrXfJM/t8mw7nNlpEcVlVUnCnM2KSX4XU5HmpodOA==
+array.prototype.findlastindex@^1.2.5:
+  version "1.2.5"
+  resolved "https://registry.yarnpkg.com/array.prototype.findlastindex/-/array.prototype.findlastindex-1.2.5.tgz#8c35a755c72908719453f87145ca011e39334d0d"
+  integrity sha512-zfETvRFA8o7EiNn++N5f/kaCw221hrpGsDmcpndVupkPzEc1Wuf3VgC0qby1BbHs7f5DVYjgtEU2LLh5bqeGfQ==
   dependencies:
-    call-bind "^1.0.2"
-    define-properties "^1.2.0"
-    es-abstract "^1.22.1"
-    es-shim-unscopables "^1.0.0"
-    get-intrinsic "^1.2.1"
+    call-bind "^1.0.7"
+    define-properties "^1.2.1"
+    es-abstract "^1.23.2"
+    es-errors "^1.3.0"
+    es-object-atoms "^1.0.0"
+    es-shim-unscopables "^1.0.2"
 
 array.prototype.flat@^1.3.2:
   version "1.3.2"
@@ -906,17 +913,18 @@
     es-abstract "^1.22.1"
     es-shim-unscopables "^1.0.0"
 
-arraybuffer.prototype.slice@^1.0.2:
-  version "1.0.2"
-  resolved "https://registry.yarnpkg.com/arraybuffer.prototype.slice/-/arraybuffer.prototype.slice-1.0.2.tgz#98bd561953e3e74bb34938e77647179dfe6e9f12"
-  integrity sha512-yMBKppFur/fbHu9/6USUe03bZ4knMYiwFBcyiaXB8Go0qNehwX6inYPzK9U0NeQvGxKthcmHcaR8P5MStSRBAw==
+arraybuffer.prototype.slice@^1.0.3:
+  version "1.0.3"
+  resolved "https://registry.yarnpkg.com/arraybuffer.prototype.slice/-/arraybuffer.prototype.slice-1.0.3.tgz#097972f4255e41bc3425e37dc3f6421cf9aefde6"
+  integrity sha512-bMxMKAjg13EBSVscxTaYA4mRc5t1UAXa2kXiGTNfZ079HIWXEkKmkgFrh/nJqamaLSrXO5H4WFFkPEaLJWbs3A==
   dependencies:
-    array-buffer-byte-length "^1.0.0"
-    call-bind "^1.0.2"
-    define-properties "^1.2.0"
-    es-abstract "^1.22.1"
-    get-intrinsic "^1.2.1"
-    is-array-buffer "^3.0.2"
+    array-buffer-byte-length "^1.0.1"
+    call-bind "^1.0.5"
+    define-properties "^1.2.1"
+    es-abstract "^1.22.3"
+    es-errors "^1.2.1"
+    get-intrinsic "^1.2.3"
+    is-array-buffer "^3.0.4"
     is-shared-array-buffer "^1.0.2"
 
 arrify@^1.0.1:
@@ -941,10 +949,12 @@
   resolved "https://registry.yarnpkg.com/atob/-/atob-2.1.2.tgz#6d9517eb9e030d2436666651e86bd9f6f13533c9"
   integrity sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==
 
-available-typed-arrays@^1.0.5:
-  version "1.0.5"
-  resolved "https://registry.yarnpkg.com/available-typed-arrays/-/available-typed-arrays-1.0.5.tgz#92f95616501069d07d10edb2fc37d3e1c65123b7"
-  integrity sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw==
+available-typed-arrays@^1.0.7:
+  version "1.0.7"
+  resolved "https://registry.yarnpkg.com/available-typed-arrays/-/available-typed-arrays-1.0.7.tgz#a5cc375d6a03c2efc87a553f3e0b1522def14846"
+  integrity sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==
+  dependencies:
+    possible-typed-array-names "^1.0.0"
 
 balanced-match@^1.0.0:
   version "1.0.2"
@@ -1033,14 +1043,16 @@
     mime-types "^2.1.18"
     ylru "^1.2.0"
 
-call-bind@^1.0.0, call-bind@^1.0.2, call-bind@^1.0.4, call-bind@^1.0.5:
-  version "1.0.5"
-  resolved "https://registry.yarnpkg.com/call-bind/-/call-bind-1.0.5.tgz#6fa2b7845ce0ea49bf4d8b9ef64727a2c2e2e513"
-  integrity sha512-C3nQxfFZxFRVoJoGKKI8y3MOEo129NQ+FgQ08iye+Mk4zNZZGdjfs06bVTr+DBSlA66Q2VEcMki/cUCP4SercQ==
+call-bind@^1.0.2, call-bind@^1.0.5, call-bind@^1.0.6, call-bind@^1.0.7:
+  version "1.0.7"
+  resolved "https://registry.yarnpkg.com/call-bind/-/call-bind-1.0.7.tgz#06016599c40c56498c18769d2730be242b6fa3b9"
+  integrity sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==
   dependencies:
+    es-define-property "^1.0.0"
+    es-errors "^1.3.0"
     function-bind "^1.1.2"
-    get-intrinsic "^1.2.1"
-    set-function-length "^1.1.1"
+    get-intrinsic "^1.2.4"
+    set-function-length "^1.2.1"
 
 call-me-maybe@^1.0.1:
   version "1.0.2"
@@ -1273,6 +1285,33 @@
     shebang-command "^2.0.0"
     which "^2.0.1"
 
+data-view-buffer@^1.0.1:
+  version "1.0.1"
+  resolved "https://registry.yarnpkg.com/data-view-buffer/-/data-view-buffer-1.0.1.tgz#8ea6326efec17a2e42620696e671d7d5a8bc66b2"
+  integrity sha512-0lht7OugA5x3iJLOWFhWK/5ehONdprk0ISXqVFn/NFrDu+cuc8iADFrGQz5BnRK7LLU3JmkbXSxaqX+/mXYtUA==
+  dependencies:
+    call-bind "^1.0.6"
+    es-errors "^1.3.0"
+    is-data-view "^1.0.1"
+
+data-view-byte-length@^1.0.1:
+  version "1.0.1"
+  resolved "https://registry.yarnpkg.com/data-view-byte-length/-/data-view-byte-length-1.0.1.tgz#90721ca95ff280677eb793749fce1011347669e2"
+  integrity sha512-4J7wRJD3ABAzr8wP+OcIcqq2dlUKp4DVflx++hs5h5ZKydWMI6/D/fAot+yh6g2tHh8fLFTvNOaVN357NvSrOQ==
+  dependencies:
+    call-bind "^1.0.7"
+    es-errors "^1.3.0"
+    is-data-view "^1.0.1"
+
+data-view-byte-offset@^1.0.0:
+  version "1.0.0"
+  resolved "https://registry.yarnpkg.com/data-view-byte-offset/-/data-view-byte-offset-1.0.0.tgz#5e0bbfb4828ed2d1b9b400cd8a7d119bca0ff18a"
+  integrity sha512-t/Ygsytq+R995EJ5PZlD4Cu56sWa8InXySaViRzw9apusqsOO2bQP+SbYzAhR0pFKoB+43lYy8rWban9JSuXnA==
+  dependencies:
+    call-bind "^1.0.6"
+    es-errors "^1.3.0"
+    is-data-view "^1.0.1"
+
 debounce@^1.2.0:
   version "1.2.1"
   resolved "https://registry.yarnpkg.com/debounce/-/debounce-1.2.1.tgz#38881d8f4166a5c5848020c11827b834bcb3e0a5"
@@ -1292,13 +1331,20 @@
   dependencies:
     ms "^2.1.1"
 
-debug@^4.1.1, debug@^4.3.1, debug@^4.3.2, debug@^4.3.4:
+debug@^4.1.1, debug@^4.3.4:
   version "4.3.4"
   resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.4.tgz#1319f6579357f2338d3337d2cdd4914bb5dcc865"
   integrity sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==
   dependencies:
     ms "2.1.2"
 
+debug@^4.3.1, debug@^4.3.2:
+  version "4.3.7"
+  resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.7.tgz#87945b4151a011d76d95a198d7111c865c360a52"
+  integrity sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==
+  dependencies:
+    ms "^2.1.3"
+
 decamelize-keys@^1.1.0:
   version "1.1.1"
   resolved "https://registry.yarnpkg.com/decamelize-keys/-/decamelize-keys-1.1.1.tgz#04a2d523b2f18d80d0158a43b895d56dff8d19d8"
@@ -1332,21 +1378,21 @@
   resolved "https://registry.yarnpkg.com/deepmerge/-/deepmerge-4.3.1.tgz#44b5f2147cd3b00d4b56137685966f26fd25dd4a"
   integrity sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==
 
-define-data-property@^1.0.1, define-data-property@^1.1.1:
-  version "1.1.1"
-  resolved "https://registry.yarnpkg.com/define-data-property/-/define-data-property-1.1.1.tgz#c35f7cd0ab09883480d12ac5cb213715587800b3"
-  integrity sha512-E7uGkTzkk1d0ByLeSc6ZsFS79Axg+m1P/VsgYsxHgiuc3tFSj+MjMIwe90FC4lOAZzNBdY7kkO2P2wKdsQ1vgQ==
+define-data-property@^1.0.1, define-data-property@^1.1.4:
+  version "1.1.4"
+  resolved "https://registry.yarnpkg.com/define-data-property/-/define-data-property-1.1.4.tgz#894dc141bb7d3060ae4366f6a0107e68fbe48c5e"
+  integrity sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==
   dependencies:
-    get-intrinsic "^1.2.1"
+    es-define-property "^1.0.0"
+    es-errors "^1.3.0"
     gopd "^1.0.1"
-    has-property-descriptors "^1.0.0"
 
 define-lazy-prop@^2.0.0:
   version "2.0.0"
   resolved "https://registry.yarnpkg.com/define-lazy-prop/-/define-lazy-prop-2.0.0.tgz#3f7ae421129bcaaac9bc74905c98a0009ec9ee7f"
   integrity sha512-Ds09qNh8yw3khSjiJjiUInaGX9xlqZDY7JVryGxdxV7NPeuqQfplOpQ66yJFZut3jLa5zOwkXw1g9EI2uKh4Og==
 
-define-properties@^1.1.3, define-properties@^1.2.0, define-properties@^1.2.1:
+define-properties@^1.2.0, define-properties@^1.2.1:
   version "1.2.1"
   resolved "https://registry.yarnpkg.com/define-properties/-/define-properties-1.2.1.tgz#10781cc616eb951a80a034bafcaa7377f6af2b6c"
   integrity sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==
@@ -1484,66 +1530,92 @@
   dependencies:
     is-arrayish "^0.2.1"
 
-es-abstract@^1.22.1:
-  version "1.22.3"
-  resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.22.3.tgz#48e79f5573198de6dee3589195727f4f74bc4f32"
-  integrity sha512-eiiY8HQeYfYH2Con2berK+To6GrK2RxbPawDkGq4UiCQQfZHb6wX9qQqkbpPqaxQFcl8d9QzZqo0tGE0VcrdwA==
+es-abstract@^1.22.1, es-abstract@^1.22.3, es-abstract@^1.23.0, es-abstract@^1.23.2:
+  version "1.23.3"
+  resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.23.3.tgz#8f0c5a35cd215312573c5a27c87dfd6c881a0aa0"
+  integrity sha512-e+HfNH61Bj1X9/jLc5v1owaLYuHdeHHSQlkhCBiTK8rBvKaULl/beGMxwrMXjpYrv4pz22BlY570vVePA2ho4A==
   dependencies:
-    array-buffer-byte-length "^1.0.0"
-    arraybuffer.prototype.slice "^1.0.2"
-    available-typed-arrays "^1.0.5"
-    call-bind "^1.0.5"
-    es-set-tostringtag "^2.0.1"
+    array-buffer-byte-length "^1.0.1"
+    arraybuffer.prototype.slice "^1.0.3"
+    available-typed-arrays "^1.0.7"
+    call-bind "^1.0.7"
+    data-view-buffer "^1.0.1"
+    data-view-byte-length "^1.0.1"
+    data-view-byte-offset "^1.0.0"
+    es-define-property "^1.0.0"
+    es-errors "^1.3.0"
+    es-object-atoms "^1.0.0"
+    es-set-tostringtag "^2.0.3"
     es-to-primitive "^1.2.1"
     function.prototype.name "^1.1.6"
-    get-intrinsic "^1.2.2"
-    get-symbol-description "^1.0.0"
+    get-intrinsic "^1.2.4"
+    get-symbol-description "^1.0.2"
     globalthis "^1.0.3"
     gopd "^1.0.1"
-    has-property-descriptors "^1.0.0"
-    has-proto "^1.0.1"
+    has-property-descriptors "^1.0.2"
+    has-proto "^1.0.3"
     has-symbols "^1.0.3"
-    hasown "^2.0.0"
-    internal-slot "^1.0.5"
-    is-array-buffer "^3.0.2"
+    hasown "^2.0.2"
+    internal-slot "^1.0.7"
+    is-array-buffer "^3.0.4"
     is-callable "^1.2.7"
-    is-negative-zero "^2.0.2"
+    is-data-view "^1.0.1"
+    is-negative-zero "^2.0.3"
     is-regex "^1.1.4"
-    is-shared-array-buffer "^1.0.2"
+    is-shared-array-buffer "^1.0.3"
     is-string "^1.0.7"
-    is-typed-array "^1.1.12"
+    is-typed-array "^1.1.13"
     is-weakref "^1.0.2"
     object-inspect "^1.13.1"
     object-keys "^1.1.1"
-    object.assign "^4.1.4"
-    regexp.prototype.flags "^1.5.1"
-    safe-array-concat "^1.0.1"
-    safe-regex-test "^1.0.0"
-    string.prototype.trim "^1.2.8"
-    string.prototype.trimend "^1.0.7"
-    string.prototype.trimstart "^1.0.7"
-    typed-array-buffer "^1.0.0"
-    typed-array-byte-length "^1.0.0"
-    typed-array-byte-offset "^1.0.0"
-    typed-array-length "^1.0.4"
+    object.assign "^4.1.5"
+    regexp.prototype.flags "^1.5.2"
+    safe-array-concat "^1.1.2"
+    safe-regex-test "^1.0.3"
+    string.prototype.trim "^1.2.9"
+    string.prototype.trimend "^1.0.8"
+    string.prototype.trimstart "^1.0.8"
+    typed-array-buffer "^1.0.2"
+    typed-array-byte-length "^1.0.1"
+    typed-array-byte-offset "^1.0.2"
+    typed-array-length "^1.0.6"
     unbox-primitive "^1.0.2"
-    which-typed-array "^1.1.13"
+    which-typed-array "^1.1.15"
+
+es-define-property@^1.0.0:
+  version "1.0.0"
+  resolved "https://registry.yarnpkg.com/es-define-property/-/es-define-property-1.0.0.tgz#c7faefbdff8b2696cf5f46921edfb77cc4ba3845"
+  integrity sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ==
+  dependencies:
+    get-intrinsic "^1.2.4"
+
+es-errors@^1.2.1, es-errors@^1.3.0:
+  version "1.3.0"
+  resolved "https://registry.yarnpkg.com/es-errors/-/es-errors-1.3.0.tgz#05f75a25dab98e4fb1dcd5e1472c0546d5057c8f"
+  integrity sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==
 
 es-module-lexer@^1.0.0:
   version "1.4.1"
   resolved "https://registry.yarnpkg.com/es-module-lexer/-/es-module-lexer-1.4.1.tgz#41ea21b43908fe6a287ffcbe4300f790555331f5"
   integrity sha512-cXLGjP0c4T3flZJKQSuziYoq7MlT+rnvfZjfp7h+I7K9BNX54kP9nyWvdbwjQ4u1iWbOL4u96fgeZLToQlZC7w==
 
-es-set-tostringtag@^2.0.1:
-  version "2.0.2"
-  resolved "https://registry.yarnpkg.com/es-set-tostringtag/-/es-set-tostringtag-2.0.2.tgz#11f7cc9f63376930a5f20be4915834f4bc74f9c9"
-  integrity sha512-BuDyupZt65P9D2D2vA/zqcI3G5xRsklm5N3xCwuiy+/vKy8i0ifdsQP1sLgO4tZDSCaQUSnmC48khknGMV3D2Q==
+es-object-atoms@^1.0.0:
+  version "1.0.0"
+  resolved "https://registry.yarnpkg.com/es-object-atoms/-/es-object-atoms-1.0.0.tgz#ddb55cd47ac2e240701260bc2a8e31ecb643d941"
+  integrity sha512-MZ4iQ6JwHOBQjahnjwaC1ZtIBH+2ohjamzAO3oaHcXYup7qxjF2fixyH+Q71voWHeOkI2q/TnJao/KfXYIZWbw==
   dependencies:
-    get-intrinsic "^1.2.2"
-    has-tostringtag "^1.0.0"
-    hasown "^2.0.0"
+    es-errors "^1.3.0"
 
-es-shim-unscopables@^1.0.0:
+es-set-tostringtag@^2.0.3:
+  version "2.0.3"
+  resolved "https://registry.yarnpkg.com/es-set-tostringtag/-/es-set-tostringtag-2.0.3.tgz#8bb60f0a440c2e4281962428438d58545af39777"
+  integrity sha512-3T8uNMC3OQTHkFUsFq8r/BwAXLHvU/9O9mE0fBc/MY5iq/8H7ncvO947LmYA6ldWw9Uh8Yhf25zu6n7nML5QWQ==
+  dependencies:
+    get-intrinsic "^1.2.4"
+    has-tostringtag "^1.0.2"
+    hasown "^2.0.1"
+
+es-shim-unscopables@^1.0.0, es-shim-unscopables@^1.0.2:
   version "1.0.2"
   resolved "https://registry.yarnpkg.com/es-shim-unscopables/-/es-shim-unscopables-1.0.2.tgz#1f6942e71ecc7835ed1c8a83006d8771a63a3763"
   integrity sha512-J3yBRXCzDu4ULnQwxyToo/OjdMx6akgVC7K6few0a7F/0wLtmKKN7I73AH5T2836UuXRqN7Qg+IIUw/+YJksRw==
@@ -1621,10 +1693,10 @@
     is-core-module "^2.13.0"
     resolve "^1.22.4"
 
-eslint-module-utils@^2.8.0:
-  version "2.8.0"
-  resolved "https://registry.yarnpkg.com/eslint-module-utils/-/eslint-module-utils-2.8.0.tgz#e439fee65fc33f6bba630ff621efc38ec0375c49"
-  integrity sha512-aWajIYfsqCKRDgUfjEXNN/JlrzauMuSEy5sbd7WXbtW3EH6A6MpwEh42c7qD+MqQo9QMJ6fWLAeIJynx0g6OAw==
+eslint-module-utils@^2.12.0:
+  version "2.12.0"
+  resolved "https://registry.yarnpkg.com/eslint-module-utils/-/eslint-module-utils-2.12.0.tgz#fe4cfb948d61f49203d7b08871982b65b9af0b0b"
+  integrity sha512-wALZ0HFoytlyh/1+4wuZ9FJCD/leWHQzzrxJ8+rebyReSLk7LApMyd3WJaLVoN+D5+WIdJyDK1c6JnE65V4Zyg==
   dependencies:
     debug "^3.2.7"
 
@@ -1643,27 +1715,29 @@
   dependencies:
     htmlparser2 "^8.0.1"
 
-eslint-plugin-import@^2.29.1:
-  version "2.29.1"
-  resolved "https://registry.yarnpkg.com/eslint-plugin-import/-/eslint-plugin-import-2.29.1.tgz#d45b37b5ef5901d639c15270d74d46d161150643"
-  integrity sha512-BbPC0cuExzhiMo4Ff1BTVwHpjjv28C5R+btTOGaCRC7UEz801up0JadwkeSk5Ued6TG34uaczuVuH6qyy5YUxw==
+eslint-plugin-import@^2.31.0:
+  version "2.31.0"
+  resolved "https://registry.yarnpkg.com/eslint-plugin-import/-/eslint-plugin-import-2.31.0.tgz#310ce7e720ca1d9c0bb3f69adfd1c6bdd7d9e0e7"
+  integrity sha512-ixmkI62Rbc2/w8Vfxyh1jQRTdRTF52VxwRVHl/ykPAmqG+Nb7/kNn+byLP0LxPgI7zWA16Jt82SybJInmMia3A==
   dependencies:
-    array-includes "^3.1.7"
-    array.prototype.findlastindex "^1.2.3"
+    "@rtsao/scc" "^1.1.0"
+    array-includes "^3.1.8"
+    array.prototype.findlastindex "^1.2.5"
     array.prototype.flat "^1.3.2"
     array.prototype.flatmap "^1.3.2"
     debug "^3.2.7"
     doctrine "^2.1.0"
     eslint-import-resolver-node "^0.3.9"
-    eslint-module-utils "^2.8.0"
-    hasown "^2.0.0"
-    is-core-module "^2.13.1"
+    eslint-module-utils "^2.12.0"
+    hasown "^2.0.2"
+    is-core-module "^2.15.1"
     is-glob "^4.0.3"
     minimatch "^3.1.2"
-    object.fromentries "^2.0.7"
-    object.groupby "^1.0.1"
-    object.values "^1.1.7"
+    object.fromentries "^2.0.8"
+    object.groupby "^1.0.3"
+    object.values "^1.2.0"
     semver "^6.3.1"
+    string.prototype.trimend "^1.0.8"
     tsconfig-paths "^3.15.0"
 
 eslint-plugin-jsdoc@^44.2.7:
@@ -1680,10 +1754,10 @@
     semver "^7.5.1"
     spdx-expression-parse "^3.0.1"
 
-eslint-plugin-lit@^1.14.0:
-  version "1.14.0"
-  resolved "https://registry.yarnpkg.com/eslint-plugin-lit/-/eslint-plugin-lit-1.14.0.tgz#afd10b93dd6fed3dc851f9c375c3d7f6c32c59fa"
-  integrity sha512-J4w+CgO31621GreLFCdTUbTr5yeV2/RJ/M0myw0dykD5p9FGGIRLityQiNa6SG+JpVbmeQTQPJy4pNFmiurJ/w==
+eslint-plugin-lit@^1.15.0:
+  version "1.15.0"
+  resolved "https://registry.yarnpkg.com/eslint-plugin-lit/-/eslint-plugin-lit-1.15.0.tgz#b03728313cb12130f4d264c442bd9f5d4f407d14"
+  integrity sha512-Yhr2MYNz6Ln8megKcX503aVZQln8wsywCG49g0heiJ/Qr5UjkE4pGr4Usez2anNcc7NvlvHbQWMYwWcgH3XRKA==
   dependencies:
     parse5 "^6.0.1"
     parse5-htmlparser2-tree-adapter "^6.0.1"
@@ -1753,16 +1827,16 @@
   resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz#0cd72fe8550e3c2eae156a96a4dddcd1c8ac5800"
   integrity sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==
 
-eslint@^7.10.0, eslint@^8.57.0:
-  version "8.57.0"
-  resolved "https://registry.yarnpkg.com/eslint/-/eslint-8.57.0.tgz#c786a6fd0e0b68941aaf624596fb987089195668"
-  integrity sha512-dZ6+mexnaTIbSBZWgou51U6OmzIhYM2VcNdtiTtI7qPNZm35Akpr0f6vtw3w1Kmn5PYo+tZVfh13WrhpS6oLqQ==
+eslint@^7.10.0, eslint@^8.57.1:
+  version "8.57.1"
+  resolved "https://registry.yarnpkg.com/eslint/-/eslint-8.57.1.tgz#7df109654aba7e3bbe5c8eae533c5e461d3c6ca9"
+  integrity sha512-ypowyDxpVSYpkXr9WPv2PAZCtNip1Mv5KTW0SCurXv/9iOpcrH9PaqUElksqEB6pChqHGDRCFTyrZlGhnLNGiA==
   dependencies:
     "@eslint-community/eslint-utils" "^4.2.0"
     "@eslint-community/regexpp" "^4.6.1"
     "@eslint/eslintrc" "^2.1.4"
-    "@eslint/js" "8.57.0"
-    "@humanwhocodes/config-array" "^0.11.14"
+    "@eslint/js" "8.57.1"
+    "@humanwhocodes/config-array" "^0.13.0"
     "@humanwhocodes/module-importer" "^1.0.1"
     "@nodelib/fs.walk" "^1.2.8"
     "@ungap/structured-clone" "^1.2.0"
@@ -1806,7 +1880,14 @@
     acorn-jsx "^5.3.2"
     eslint-visitor-keys "^3.4.1"
 
-esquery@^1.4.2, esquery@^1.5.0:
+esquery@^1.4.2:
+  version "1.6.0"
+  resolved "https://registry.yarnpkg.com/esquery/-/esquery-1.6.0.tgz#91419234f804d852a82dceec3e16cdc22cf9dae7"
+  integrity sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg==
+  dependencies:
+    estraverse "^5.1.0"
+
+esquery@^1.5.0:
   version "1.5.0"
   resolved "https://registry.yarnpkg.com/esquery/-/esquery-1.5.0.tgz#6ce17738de8577694edd7361c57182ac8cb0db0b"
   integrity sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg==
@@ -1955,9 +2036,9 @@
   integrity sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==
 
 fastq@^1.6.0:
-  version "1.16.0"
-  resolved "https://registry.yarnpkg.com/fastq/-/fastq-1.16.0.tgz#83b9a9375692db77a822df081edb6a9cf6839320"
-  integrity sha512-ifCoaXsDrsdkWTtiNJX5uzHDsrck5TzfKKDcuFFTIrrc/BS076qgEIfoIy1VeZqViznfKiysPYTh/QeHtnIsYA==
+  version "1.17.1"
+  resolved "https://registry.yarnpkg.com/fastq/-/fastq-1.17.1.tgz#2a523f07a4e7b1e81a42b91b8bf2254107753b47"
+  integrity sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==
   dependencies:
     reusify "^1.0.4"
 
@@ -2025,9 +2106,9 @@
     rimraf "^3.0.2"
 
 flatted@^3.2.9:
-  version "3.2.9"
-  resolved "https://registry.yarnpkg.com/flatted/-/flatted-3.2.9.tgz#7eb4c67ca1ba34232ca9d2d93e9886e611ad7daf"
-  integrity sha512-36yxDn5H7OFZQla0/jFJmbIKTdZAQHngCedGxiMmpNfEZM0sdEeT+WczLQrjK6D7o2aiyLYDnkw0R3JK0Qv1RQ==
+  version "3.3.1"
+  resolved "https://registry.yarnpkg.com/flatted/-/flatted-3.3.1.tgz#21db470729a6734d4997002f439cb308987f567a"
+  integrity sha512-X8cqMLLie7KsNUDSdzeN8FYK9rEt4Dt67OsG/DNGnYTSDBG4uFAJFBnUeiV+zCVAvwFy56IjM9sH51jVaEhNxw==
 
 for-each@^0.3.3:
   version "0.3.3"
@@ -2088,11 +2169,12 @@
   resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-2.0.5.tgz#4f94412a82db32f36e3b0b9741f8a97feb031f7e"
   integrity sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==
 
-get-intrinsic@^1.0.2, get-intrinsic@^1.1.1, get-intrinsic@^1.1.3, get-intrinsic@^1.2.0, get-intrinsic@^1.2.1, get-intrinsic@^1.2.2:
-  version "1.2.2"
-  resolved "https://registry.yarnpkg.com/get-intrinsic/-/get-intrinsic-1.2.2.tgz#281b7622971123e1ef4b3c90fd7539306da93f3b"
-  integrity sha512-0gSo4ml/0j98Y3lngkFEot/zhiCeWsbYIlZ+uZOVgzLyLaUw7wxUL+nCTP0XJvJg1AXulJRI3UJi8GsbDuxdGA==
+get-intrinsic@^1.1.3, get-intrinsic@^1.2.1, get-intrinsic@^1.2.3, get-intrinsic@^1.2.4:
+  version "1.2.4"
+  resolved "https://registry.yarnpkg.com/get-intrinsic/-/get-intrinsic-1.2.4.tgz#e385f5a4b5227d449c3eabbad05494ef0abbeadd"
+  integrity sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==
   dependencies:
+    es-errors "^1.3.0"
     function-bind "^1.1.2"
     has-proto "^1.0.1"
     has-symbols "^1.0.3"
@@ -2103,13 +2185,14 @@
   resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-6.0.1.tgz#a262d8eef67aced57c2852ad6167526a43cbf7b7"
   integrity sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==
 
-get-symbol-description@^1.0.0:
-  version "1.0.0"
-  resolved "https://registry.yarnpkg.com/get-symbol-description/-/get-symbol-description-1.0.0.tgz#7fdb81c900101fbd564dd5f1a30af5aadc1e58d6"
-  integrity sha512-2EmdH1YvIQiZpltCNgkuiUnyukzxM/R6NDJX31Ke3BG1Nq5b0S2PhX59UKi9vZpPDQVdqn+1IcaAwnzTT5vCjw==
+get-symbol-description@^1.0.2:
+  version "1.0.2"
+  resolved "https://registry.yarnpkg.com/get-symbol-description/-/get-symbol-description-1.0.2.tgz#533744d5aa20aca4e079c8e5daf7fd44202821f5"
+  integrity sha512-g0QYk1dZBxGwk+Ngc+ltRH2IBp2f7zBkBMBJZCDerh6EhlhSR6+9irMCuT/09zD6qkarHUSn529sK/yL4S27mg==
   dependencies:
-    call-bind "^1.0.2"
-    get-intrinsic "^1.1.1"
+    call-bind "^1.0.5"
+    es-errors "^1.3.0"
+    get-intrinsic "^1.2.4"
 
 get-value@^2.0.3, get-value@^2.0.6:
   version "2.0.6"
@@ -2163,11 +2246,12 @@
     type-fest "^0.20.2"
 
 globalthis@^1.0.3:
-  version "1.0.3"
-  resolved "https://registry.yarnpkg.com/globalthis/-/globalthis-1.0.3.tgz#5852882a52b80dc301b0660273e1ed082f0b6ccf"
-  integrity sha512-sFdI5LyBiNTHjRd7cGPWapiHWMOXKyuBNX/cWJ3NfzrZQVa8GI/8cofCl74AOVqq9W5kNmguTIzJ/1s2gyI9wA==
+  version "1.0.4"
+  resolved "https://registry.yarnpkg.com/globalthis/-/globalthis-1.0.4.tgz#7430ed3a975d97bfb59bcce41f5cabbafa651236"
+  integrity sha512-DpLKbNU4WylpxJykQujfCcwYWiV/Jhm50Goo0wrVILAv5jOr9d+H+UR3PhSCD2rCCEIg0uc+G+muBTwD54JhDQ==
   dependencies:
-    define-properties "^1.1.3"
+    define-properties "^1.2.1"
+    gopd "^1.0.1"
 
 globby@^11.1.0:
   version "11.1.0"
@@ -2244,29 +2328,29 @@
   resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-4.0.0.tgz#944771fd9c81c81265c4d6941860da06bb59479b"
   integrity sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==
 
-has-property-descriptors@^1.0.0:
-  version "1.0.1"
-  resolved "https://registry.yarnpkg.com/has-property-descriptors/-/has-property-descriptors-1.0.1.tgz#52ba30b6c5ec87fd89fa574bc1c39125c6f65340"
-  integrity sha512-VsX8eaIewvas0xnvinAe9bw4WfIeODpGYikiWYLH+dma0Jw6KHYqWiWfhQlgOVK8D6PvjubK5Uc4P0iIhIcNVg==
+has-property-descriptors@^1.0.0, has-property-descriptors@^1.0.2:
+  version "1.0.2"
+  resolved "https://registry.yarnpkg.com/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz#963ed7d071dc7bf5f084c5bfbe0d1b6222586854"
+  integrity sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==
   dependencies:
-    get-intrinsic "^1.2.2"
+    es-define-property "^1.0.0"
 
-has-proto@^1.0.1:
-  version "1.0.1"
-  resolved "https://registry.yarnpkg.com/has-proto/-/has-proto-1.0.1.tgz#1885c1305538958aff469fef37937c22795408e0"
-  integrity sha512-7qE+iP+O+bgF9clE5+UoBFzE65mlBiVj3tKCrlNQ0Ogwm0BjpT/gK4SlLYDMybDh5I3TCTKnPPa0oMG7JDYrhg==
+has-proto@^1.0.1, has-proto@^1.0.3:
+  version "1.0.3"
+  resolved "https://registry.yarnpkg.com/has-proto/-/has-proto-1.0.3.tgz#b31ddfe9b0e6e9914536a6ab286426d0214f77fd"
+  integrity sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q==
 
 has-symbols@^1.0.2, has-symbols@^1.0.3:
   version "1.0.3"
   resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.3.tgz#bb7b2c4349251dce87b125f7bdf874aa7c8b39f8"
   integrity sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==
 
-has-tostringtag@^1.0.0:
-  version "1.0.0"
-  resolved "https://registry.yarnpkg.com/has-tostringtag/-/has-tostringtag-1.0.0.tgz#7e133818a7d394734f941e73c3d3f9291e658b25"
-  integrity sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ==
+has-tostringtag@^1.0.0, has-tostringtag@^1.0.2:
+  version "1.0.2"
+  resolved "https://registry.yarnpkg.com/has-tostringtag/-/has-tostringtag-1.0.2.tgz#2cdc42d40bef2e5b4eeab7c01a73c54ce7ab5abc"
+  integrity sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==
   dependencies:
-    has-symbols "^1.0.2"
+    has-symbols "^1.0.3"
 
 has-value@^0.3.1:
   version "0.3.1"
@@ -2299,10 +2383,10 @@
     is-number "^3.0.0"
     kind-of "^4.0.0"
 
-hasown@^2.0.0:
-  version "2.0.0"
-  resolved "https://registry.yarnpkg.com/hasown/-/hasown-2.0.0.tgz#f4c513d454a57b7c7e1650778de226b11700546c"
-  integrity sha512-vUptKVTpIJhcczKBbgnS+RtcuYMB8+oNzPK2/Hp3hanz8JmpATdmmgLgSaadVREkDm+e2giHwY3ZRkyjSIDDFA==
+hasown@^2.0.0, hasown@^2.0.1, hasown@^2.0.2:
+  version "2.0.2"
+  resolved "https://registry.yarnpkg.com/hasown/-/hasown-2.0.2.tgz#003eaf91be7adc372e84ec59dc37252cedb80003"
+  integrity sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==
   dependencies:
     function-bind "^1.1.2"
 
@@ -2369,11 +2453,16 @@
   dependencies:
     safer-buffer ">= 2.1.2 < 3"
 
-ignore@^5.1.1, ignore@^5.2.0:
+ignore@^5.1.1:
   version "5.3.0"
   resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.3.0.tgz#67418ae40d34d6999c95ff56016759c718c82f78"
   integrity sha512-g7dmpshy+gD7mh88OC9NwSGTKoc3kyLAZQRU1mt53Aw/vnvfXnbC+F/7F7QoYVKbV+KNvJx8wArewKy1vXMtlg==
 
+ignore@^5.2.0:
+  version "5.3.2"
+  resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.3.2.tgz#3cd40e729f3643fd87cb04e50bf0eb722bc596f5"
+  integrity sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==
+
 import-fresh@^3.2.1:
   version "3.3.0"
   resolved "https://registry.yarnpkg.com/import-fresh/-/import-fresh-3.3.0.tgz#37162c25fcb9ebaa2e6e53d5b4d88ce17d9e0c2b"
@@ -2429,12 +2518,12 @@
     strip-ansi "^6.0.0"
     through "^2.3.6"
 
-internal-slot@^1.0.5:
-  version "1.0.6"
-  resolved "https://registry.yarnpkg.com/internal-slot/-/internal-slot-1.0.6.tgz#37e756098c4911c5e912b8edbf71ed3aa116f930"
-  integrity sha512-Xj6dv+PsbtwyPpEflsejS+oIZxmMlV44zAhG479uYu89MsjcYOhCFnNyKrkJrihbsiasQyY0afoCl/9BLR65bg==
+internal-slot@^1.0.7:
+  version "1.0.7"
+  resolved "https://registry.yarnpkg.com/internal-slot/-/internal-slot-1.0.7.tgz#c06dcca3ed874249881007b0a5523b172a190802"
+  integrity sha512-NGnrKwXzSms2qUUih/ILZ5JBqNTSa1+ZmP6flaIp6KmSElgE9qdndzS3cqjrDovwFdmwsGsLdeFgB6suw+1e9g==
   dependencies:
-    get-intrinsic "^1.2.2"
+    es-errors "^1.3.0"
     hasown "^2.0.0"
     side-channel "^1.0.4"
 
@@ -2450,14 +2539,13 @@
   dependencies:
     hasown "^2.0.0"
 
-is-array-buffer@^3.0.1, is-array-buffer@^3.0.2:
-  version "3.0.2"
-  resolved "https://registry.yarnpkg.com/is-array-buffer/-/is-array-buffer-3.0.2.tgz#f2653ced8412081638ecb0ebbd0c41c6e0aecbbe"
-  integrity sha512-y+FyyR/w8vfIRq4eQcM1EYgSTnmHXPqaF+IgzgraytCFq5Xh8lllDVmAZolPJiZttZLeFSINPYMaEJ7/vWUa1w==
+is-array-buffer@^3.0.4:
+  version "3.0.4"
+  resolved "https://registry.yarnpkg.com/is-array-buffer/-/is-array-buffer-3.0.4.tgz#7a1f92b3d61edd2bc65d24f130530ea93d7fae98"
+  integrity sha512-wcjaerHw0ydZwfhiKbXJWLDY8A7yV7KhjQOpb83hGgGfId/aQa4TOvwyzn2PuswW2gPCYEL/nEAiSVpdOj1lXw==
   dependencies:
     call-bind "^1.0.2"
-    get-intrinsic "^1.2.0"
-    is-typed-array "^1.1.10"
+    get-intrinsic "^1.2.1"
 
 is-arrayish@^0.2.1:
   version "0.2.1"
@@ -2503,7 +2591,14 @@
   resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.2.7.tgz#3bc2a85ea742d9e36205dcacdd72ca1fdc51b055"
   integrity sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==
 
-is-core-module@^2.13.0, is-core-module@^2.13.1, is-core-module@^2.5.0:
+is-core-module@^2.13.0, is-core-module@^2.15.1:
+  version "2.15.1"
+  resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.15.1.tgz#a7363a25bee942fefab0de13bf6aa372c82dcc37"
+  integrity sha512-z0vtXSwucUJtANQWldhbtbt7BnL0vxiFjIdDLAatwhDYty2bad6s+rijD6Ri4YuYJubLzIJLUidCh09e1djEVQ==
+  dependencies:
+    hasown "^2.0.2"
+
+is-core-module@^2.5.0:
   version "2.13.1"
   resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.13.1.tgz#ad0d7532c6fea9da1ebdc82742d74525c6273384"
   integrity sha512-hHrIjvZsftOsvKSn2TRYl63zvxsgE0K+0mYMoH6gD4omR5IWB2KynivBQczo3+wF1cCkjzvptnI9Q0sPU66ilw==
@@ -2517,6 +2612,13 @@
   dependencies:
     hasown "^2.0.0"
 
+is-data-view@^1.0.1:
+  version "1.0.1"
+  resolved "https://registry.yarnpkg.com/is-data-view/-/is-data-view-1.0.1.tgz#4b4d3a511b70f3dc26d42c03ca9ca515d847759f"
+  integrity sha512-AHkaJrsUVW6wq6JS8y3JnM/GJF/9cf+k20+iDzlSaJrinEo5+7vRiteOSwBhHRiAyQATN1AmY4hwzxJKPmYf+w==
+  dependencies:
+    is-typed-array "^1.1.13"
+
 is-date-object@^1.0.1:
   version "1.0.5"
   resolved "https://registry.yarnpkg.com/is-date-object/-/is-date-object-1.0.5.tgz#0841d5536e724c25597bf6ea62e1bd38298df31f"
@@ -2593,10 +2695,10 @@
   resolved "https://registry.yarnpkg.com/is-module/-/is-module-1.0.0.tgz#3258fb69f78c14d5b815d664336b4cffb6441591"
   integrity sha512-51ypPSPCoTEIN9dy5Oy+h4pShgJmPCygKfyRCISBI+JoWT/2oJvK8QPxmwv7b/p239jXrm9M1mlQbyKJ5A152g==
 
-is-negative-zero@^2.0.2:
-  version "2.0.2"
-  resolved "https://registry.yarnpkg.com/is-negative-zero/-/is-negative-zero-2.0.2.tgz#7bf6f03a28003b8b3965de3ac26f664d765f3150"
-  integrity sha512-dqJvarLawXsFbNDeJW7zAz8ItJ9cd28YufuuFzh0G8pNHjJMnY08Dv7sYX2uF5UpQOwieAeOExEYAWWfu7ZZUA==
+is-negative-zero@^2.0.3:
+  version "2.0.3"
+  resolved "https://registry.yarnpkg.com/is-negative-zero/-/is-negative-zero-2.0.3.tgz#ced903a027aca6381b777a5743069d7376a49747"
+  integrity sha512-5KoIu2Ngpyek75jXodFvnafB6DJgr3u8uuK0LEZJjrU19DrMD3EVERaR8sjz8CCGgpZvxPl9SuE1GMVPFHx1mw==
 
 is-number-object@^1.0.4:
   version "1.0.7"
@@ -2642,12 +2744,12 @@
     call-bind "^1.0.2"
     has-tostringtag "^1.0.0"
 
-is-shared-array-buffer@^1.0.2:
-  version "1.0.2"
-  resolved "https://registry.yarnpkg.com/is-shared-array-buffer/-/is-shared-array-buffer-1.0.2.tgz#8f259c573b60b6a32d4058a1a07430c0a7344c79"
-  integrity sha512-sqN2UDu1/0y6uvXyStCOzyhAjCSlHceFoMKJW8W9EU9cvic/QdsZ0kEU93HEy3IUEFZIiH/3w+AH/UQbPHNdhA==
+is-shared-array-buffer@^1.0.2, is-shared-array-buffer@^1.0.3:
+  version "1.0.3"
+  resolved "https://registry.yarnpkg.com/is-shared-array-buffer/-/is-shared-array-buffer-1.0.3.tgz#1237f1cba059cdb62431d378dcc37d9680181688"
+  integrity sha512-nA2hv5XIhLR3uVzDDfCIknerhx8XUKnstuOERPNNIinXG7v9u+ohXF67vxm4TPTEPU6lm61ZkwP3c9PCB97rhg==
   dependencies:
-    call-bind "^1.0.2"
+    call-bind "^1.0.7"
 
 is-stream@^2.0.0:
   version "2.0.1"
@@ -2668,12 +2770,12 @@
   dependencies:
     has-symbols "^1.0.2"
 
-is-typed-array@^1.1.10, is-typed-array@^1.1.12, is-typed-array@^1.1.9:
-  version "1.1.12"
-  resolved "https://registry.yarnpkg.com/is-typed-array/-/is-typed-array-1.1.12.tgz#d0bab5686ef4a76f7a73097b95470ab199c57d4a"
-  integrity sha512-Z14TF2JNG8Lss5/HMqt0//T9JeHXttXy5pH/DBU4vi98ozO2btxzq9MwYDZYnKwU8nRsz/+GVFVRDq3DkVuSPg==
+is-typed-array@^1.1.13:
+  version "1.1.13"
+  resolved "https://registry.yarnpkg.com/is-typed-array/-/is-typed-array-1.1.13.tgz#d6c5ca56df62334959322d7d7dd1cca50debe229"
+  integrity sha512-uZ25/bUAlUY5fR4OKT4rZQEBrzQWYV9ZJYGGsUmEJ6thodVJ1HX64ePQ6Z0qPWP+m+Uq6e9UugrE38jeYsDSMw==
   dependencies:
-    which-typed-array "^1.1.11"
+    which-typed-array "^1.1.14"
 
 is-typedarray@^1.0.0:
   version "1.0.0"
@@ -3132,7 +3234,7 @@
   resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009"
   integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==
 
-ms@^2.1.1:
+ms@^2.1.1, ms@^2.1.3:
   version "2.1.3"
   resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2"
   integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==
@@ -3245,10 +3347,10 @@
     define-property "^0.2.5"
     kind-of "^3.0.3"
 
-object-inspect@^1.13.1, object-inspect@^1.9.0:
-  version "1.13.1"
-  resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.13.1.tgz#b96c6109324ccfef6b12216a956ca4dc2ff94bc2"
-  integrity sha512-5qoj1RUiKOMsCCNLV1CBiPYE10sziTsnmNxkAI/rZhiD63CF7IqdFGC/XzjWjpSgLf0LxXX3bDFIh0E18f6UhQ==
+object-inspect@^1.13.1:
+  version "1.13.2"
+  resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.13.2.tgz#dea0088467fb991e67af4058147a24824a3043ff"
+  integrity sha512-IRZSRuzJiynemAXPYtPe5BoI/RESNYR7TYm50MC5Mqbd3Jmw5y790sErYw3V6SryFJD64b74qQQs9wn5Bg/k3g==
 
 object-keys@^1.1.1:
   version "1.1.1"
@@ -3262,7 +3364,7 @@
   dependencies:
     isobject "^3.0.0"
 
-object.assign@^4.1.4:
+object.assign@^4.1.5:
   version "4.1.5"
   resolved "https://registry.yarnpkg.com/object.assign/-/object.assign-4.1.5.tgz#3a833f9ab7fdb80fc9e8d2300c803d216d8fdbb0"
   integrity sha512-byy+U7gp+FVwmyzKPYhW2h5l3crpmGsxl7X2s8y43IgxvG4g3QZ6CffDtsNQy1WsmZpQbO+ybo0AlW7TY6DcBQ==
@@ -3272,24 +3374,24 @@
     has-symbols "^1.0.3"
     object-keys "^1.1.1"
 
-object.fromentries@^2.0.7:
-  version "2.0.7"
-  resolved "https://registry.yarnpkg.com/object.fromentries/-/object.fromentries-2.0.7.tgz#71e95f441e9a0ea6baf682ecaaf37fa2a8d7e616"
-  integrity sha512-UPbPHML6sL8PI/mOqPwsH4G6iyXcCGzLin8KvEPenOZN5lpCNBZZQ+V62vdjB1mQHrmqGQt5/OJzemUA+KJmEA==
+object.fromentries@^2.0.8:
+  version "2.0.8"
+  resolved "https://registry.yarnpkg.com/object.fromentries/-/object.fromentries-2.0.8.tgz#f7195d8a9b97bd95cbc1999ea939ecd1a2b00c65"
+  integrity sha512-k6E21FzySsSK5a21KRADBd/NGneRegFO5pLHfdQLpRDETUNJueLXs3WCzyQ3tFRDYgbq3KHGXfTbi2bs8WQ6rQ==
   dependencies:
-    call-bind "^1.0.2"
-    define-properties "^1.2.0"
-    es-abstract "^1.22.1"
+    call-bind "^1.0.7"
+    define-properties "^1.2.1"
+    es-abstract "^1.23.2"
+    es-object-atoms "^1.0.0"
 
-object.groupby@^1.0.1:
-  version "1.0.1"
-  resolved "https://registry.yarnpkg.com/object.groupby/-/object.groupby-1.0.1.tgz#d41d9f3c8d6c778d9cbac86b4ee9f5af103152ee"
-  integrity sha512-HqaQtqLnp/8Bn4GL16cj+CUYbnpe1bh0TtEaWvybszDG4tgxCJuRpV8VGuvNaI1fAnI4lUJzDG55MXcOH4JZcQ==
+object.groupby@^1.0.3:
+  version "1.0.3"
+  resolved "https://registry.yarnpkg.com/object.groupby/-/object.groupby-1.0.3.tgz#9b125c36238129f6f7b61954a1e7176148d5002e"
+  integrity sha512-+Lhy3TQTuzXI5hevh8sBGqbmurHbbIjAi0Z4S63nthVLmLxfbj4T54a4CfZrXIrt9iP4mVAPYMo/v99taj3wjQ==
   dependencies:
-    call-bind "^1.0.2"
-    define-properties "^1.2.0"
-    es-abstract "^1.22.1"
-    get-intrinsic "^1.2.1"
+    call-bind "^1.0.7"
+    define-properties "^1.2.1"
+    es-abstract "^1.23.2"
 
 object.pick@^1.3.0:
   version "1.3.0"
@@ -3298,14 +3400,14 @@
   dependencies:
     isobject "^3.0.1"
 
-object.values@^1.1.7:
-  version "1.1.7"
-  resolved "https://registry.yarnpkg.com/object.values/-/object.values-1.1.7.tgz#617ed13272e7e1071b43973aa1655d9291b8442a"
-  integrity sha512-aU6xnDFYT3x17e/f0IiiwlGPTy2jzMySGfUB4fq6z7CV8l85CWHDk5ErhyhpfDHhrOMwGFhSQkhMGHaIotA6Ng==
+object.values@^1.2.0:
+  version "1.2.0"
+  resolved "https://registry.yarnpkg.com/object.values/-/object.values-1.2.0.tgz#65405a9d92cee68ac2d303002e0b8470a4d9ab1b"
+  integrity sha512-yBYjY9QX2hnRmZHAjG/f13MzmBzxzYgQhFrke06TTyKY5zSTEqkOeukBzIdVA3j3ulu8Qa3MbVFShV7T2RmGtQ==
   dependencies:
-    call-bind "^1.0.2"
-    define-properties "^1.2.0"
-    es-abstract "^1.22.1"
+    call-bind "^1.0.7"
+    define-properties "^1.2.1"
+    es-object-atoms "^1.0.0"
 
 on-finished@^2.3.0:
   version "2.4.1"
@@ -3343,16 +3445,16 @@
     is-wsl "^2.2.0"
 
 optionator@^0.9.3:
-  version "0.9.3"
-  resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.9.3.tgz#007397d44ed1872fdc6ed31360190f81814e2c64"
-  integrity sha512-JjCoypp+jKn1ttEFExxhetCKeJt9zhAgAve5FXHixTvFDW/5aEktX9bufBKLRRMdU7bNtpLfcGu94B3cdEJgjg==
+  version "0.9.4"
+  resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.9.4.tgz#7ea1c1a5d91d764fb282139c88fe11e182a3a734"
+  integrity sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==
   dependencies:
-    "@aashutoshrathi/word-wrap" "^1.2.3"
     deep-is "^0.1.3"
     fast-levenshtein "^2.0.6"
     levn "^0.4.1"
     prelude-ls "^1.2.1"
     type-check "^0.4.0"
+    word-wrap "^1.2.5"
 
 os-tmpdir@~1.0.2:
   version "1.0.2"
@@ -3515,6 +3617,11 @@
   resolved "https://registry.yarnpkg.com/posix-character-classes/-/posix-character-classes-0.1.1.tgz#01eac0fe3b5af71a2a6c02feabb8c1fef7e00eab"
   integrity sha512-xTgYBc3fuo7Yt7JbiuFxSYGToMoz8fLoE6TC9Wx1P/u+LfeThMOAqmuyECnlBaaJb+u1m9hHiXUEtwW4OzfUJg==
 
+possible-typed-array-names@^1.0.0:
+  version "1.0.0"
+  resolved "https://registry.yarnpkg.com/possible-typed-array-names/-/possible-typed-array-names-1.0.0.tgz#89bb63c6fada2c3e90adc4a647beeeb39cc7bf8f"
+  integrity sha512-d7Uw+eZoloe0EHDIYoe+bQ5WXnGMOpmiZFTuMWCwpjzzkL2nTjcKiAk4hh8TjnGye2TwWOk3UXucZ+3rbmBa8Q==
+
 prelude-ls@^1.2.1:
   version "1.2.1"
   resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.2.1.tgz#debc6489d7a6e6b0e7611888cec880337d316396"
@@ -3622,14 +3729,15 @@
     extend-shallow "^3.0.2"
     safe-regex "^1.1.0"
 
-regexp.prototype.flags@^1.5.1:
-  version "1.5.1"
-  resolved "https://registry.yarnpkg.com/regexp.prototype.flags/-/regexp.prototype.flags-1.5.1.tgz#90ce989138db209f81492edd734183ce99f9677e"
-  integrity sha512-sy6TXMN+hnP/wMy+ISxg3krXx7BAtWVO4UouuCN/ziM9UEne0euamVNafDfvC83bRNr95y0V5iijeDQFUNpvrg==
+regexp.prototype.flags@^1.5.2:
+  version "1.5.3"
+  resolved "https://registry.yarnpkg.com/regexp.prototype.flags/-/regexp.prototype.flags-1.5.3.tgz#b3ae40b1d2499b8350ab2c3fe6ef3845d3a96f42"
+  integrity sha512-vqlC04+RQoFalODCbCumG2xIOvapzVMHwsyIGM/SIE8fRhFFsXeH8/QQ+s0T0kDAhKc4k30s73/0ydkHQz6HlQ==
   dependencies:
-    call-bind "^1.0.2"
-    define-properties "^1.2.0"
-    set-function-name "^2.0.0"
+    call-bind "^1.0.7"
+    define-properties "^1.2.1"
+    es-errors "^1.3.0"
+    set-function-name "^2.0.2"
 
 regexpp@^3.0.0:
   version "3.2.0"
@@ -3713,13 +3821,20 @@
   dependencies:
     glob "^7.1.3"
 
-rollup@^2.67.0, rollup@^2.79.1:
+rollup@^2.67.0:
   version "2.79.1"
   resolved "https://registry.yarnpkg.com/rollup/-/rollup-2.79.1.tgz#bedee8faef7c9f93a2647ac0108748f497f081c7"
   integrity sha512-uKxbd0IhMZOhjAiD5oAFp7BqvkA4Dv47qpOCtaNvng4HBwdbWtdOh8f5nZNuk2rp51PMGk3bzfWu5oayNEuYnw==
   optionalDependencies:
     fsevents "~2.3.2"
 
+rollup@^2.79.2:
+  version "2.79.2"
+  resolved "https://registry.yarnpkg.com/rollup/-/rollup-2.79.2.tgz#f150e4a5db4b121a21a747d762f701e5e9f49090"
+  integrity sha512-fS6iqSPZDs3dr/y7Od6y5nha8dW1YnbgtsyotCVvoFGKbERG++CVRFv1meyGDE1SNItQA8BrnCw7ScdAhRJ3XQ==
+  optionalDependencies:
+    fsevents "~2.3.2"
+
 run-async@^2.4.0:
   version "2.4.1"
   resolved "https://registry.yarnpkg.com/run-async/-/run-async-2.4.1.tgz#8440eccf99ea3e70bd409d49aab88e10c189a455"
@@ -3739,13 +3854,13 @@
   dependencies:
     tslib "^1.9.0"
 
-safe-array-concat@^1.0.1:
-  version "1.0.1"
-  resolved "https://registry.yarnpkg.com/safe-array-concat/-/safe-array-concat-1.0.1.tgz#91686a63ce3adbea14d61b14c99572a8ff84754c"
-  integrity sha512-6XbUAseYE2KtOuGueyeobCySj9L4+66Tn6KQMOPQJrAJEowYKW/YR/MGJZl7FdydUdaFu4LYyDZjxf4/Nmo23Q==
+safe-array-concat@^1.1.2:
+  version "1.1.2"
+  resolved "https://registry.yarnpkg.com/safe-array-concat/-/safe-array-concat-1.1.2.tgz#81d77ee0c4e8b863635227c721278dd524c20edb"
+  integrity sha512-vj6RsCsWBCf19jIeHEfkRMw8DPiBb+DMXklQ/1SGDHOMlHdPUkZXFQ2YdplS23zESTijAcurb1aSgJA3AgMu1Q==
   dependencies:
-    call-bind "^1.0.2"
-    get-intrinsic "^1.2.1"
+    call-bind "^1.0.7"
+    get-intrinsic "^1.2.4"
     has-symbols "^1.0.3"
     isarray "^2.0.5"
 
@@ -3754,13 +3869,13 @@
   resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6"
   integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==
 
-safe-regex-test@^1.0.0:
-  version "1.0.0"
-  resolved "https://registry.yarnpkg.com/safe-regex-test/-/safe-regex-test-1.0.0.tgz#793b874d524eb3640d1873aad03596db2d4f2295"
-  integrity sha512-JBUUzyOgEwXQY1NuPtvcj/qcBDbDmEvWufhlnXZIm75DEHp+afM1r1ujJpJsV/gSM4t59tpDyPi1sd6ZaPFfsA==
+safe-regex-test@^1.0.3:
+  version "1.0.3"
+  resolved "https://registry.yarnpkg.com/safe-regex-test/-/safe-regex-test-1.0.3.tgz#a5b4c0f06e0ab50ea2c395c14d8371232924c377"
+  integrity sha512-CdASjNJPvRa7roO6Ra/gLYBTzYzzPyyBXxIMdGW3USQLyjWEls2RgW5UBTXaQVp+OrpeCK3bLem8smtmheoRuw==
   dependencies:
-    call-bind "^1.0.2"
-    get-intrinsic "^1.1.3"
+    call-bind "^1.0.6"
+    es-errors "^1.3.0"
     is-regex "^1.1.4"
 
 safe-regex@^1.1.0:
@@ -3802,24 +3917,27 @@
   resolved "https://registry.yarnpkg.com/set-blocking/-/set-blocking-2.0.0.tgz#045f9782d011ae9a6803ddd382b24392b3d890f7"
   integrity sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==
 
-set-function-length@^1.1.1:
-  version "1.1.1"
-  resolved "https://registry.yarnpkg.com/set-function-length/-/set-function-length-1.1.1.tgz#4bc39fafb0307224a33e106a7d35ca1218d659ed"
-  integrity sha512-VoaqjbBJKiWtg4yRcKBQ7g7wnGnLV3M8oLvVWwOk2PdYY6PEFegR1vezXR0tw6fZGF9csVakIRjrJiy2veSBFQ==
+set-function-length@^1.2.1:
+  version "1.2.2"
+  resolved "https://registry.yarnpkg.com/set-function-length/-/set-function-length-1.2.2.tgz#aac72314198eaed975cf77b2c3b6b880695e5449"
+  integrity sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==
   dependencies:
-    define-data-property "^1.1.1"
-    get-intrinsic "^1.2.1"
+    define-data-property "^1.1.4"
+    es-errors "^1.3.0"
+    function-bind "^1.1.2"
+    get-intrinsic "^1.2.4"
     gopd "^1.0.1"
-    has-property-descriptors "^1.0.0"
+    has-property-descriptors "^1.0.2"
 
-set-function-name@^2.0.0:
-  version "2.0.1"
-  resolved "https://registry.yarnpkg.com/set-function-name/-/set-function-name-2.0.1.tgz#12ce38b7954310b9f61faa12701620a0c882793a"
-  integrity sha512-tMNCiqYVkXIZgc2Hnoy2IvC/f8ezc5koaRFkCjrpWzGpCd3qbZXPzVy9MAZzK1ch/X0jvSkojys3oqJN0qCmdA==
+set-function-name@^2.0.2:
+  version "2.0.2"
+  resolved "https://registry.yarnpkg.com/set-function-name/-/set-function-name-2.0.2.tgz#16a705c5a0dc2f5e638ca96d8a8cd4e1c2b90985"
+  integrity sha512-7PGFlmtwsEADb0WYyvCMa1t+yke6daIG4Wirafur5kcf+MhUnPms1UeR0CKQdTZD81yESwMHbtn+TR+dMviakQ==
   dependencies:
-    define-data-property "^1.0.1"
+    define-data-property "^1.1.4"
+    es-errors "^1.3.0"
     functions-have-names "^1.2.3"
-    has-property-descriptors "^1.0.0"
+    has-property-descriptors "^1.0.2"
 
 set-value@^2.0.0, set-value@^2.0.1:
   version "2.0.1"
@@ -3871,13 +3989,14 @@
   integrity sha512-6j1W9l1iAs/4xYBI1SYOVZyFcCis9b4KCLQ8fgAGG07QvzaRLVVRQvAy85yNmmZSjYjg4MWh4gNvlPujU/5LpA==
 
 side-channel@^1.0.4:
-  version "1.0.4"
-  resolved "https://registry.yarnpkg.com/side-channel/-/side-channel-1.0.4.tgz#efce5c8fdc104ee751b25c58d4290011fa5ea2cf"
-  integrity sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==
+  version "1.0.6"
+  resolved "https://registry.yarnpkg.com/side-channel/-/side-channel-1.0.6.tgz#abd25fb7cd24baf45466406b1096b7831c9215f2"
+  integrity sha512-fDW/EZ6Q9RiO8eFG8Hj+7u/oW+XrPTIChwCOM2+th2A6OblDtYYIpve9m+KvI9Z4C9qSEXlaGR6bTEYHReuglA==
   dependencies:
-    call-bind "^1.0.0"
-    get-intrinsic "^1.0.2"
-    object-inspect "^1.9.0"
+    call-bind "^1.0.7"
+    es-errors "^1.3.0"
+    get-intrinsic "^1.2.4"
+    object-inspect "^1.13.1"
 
 signal-exit@^3.0.2, signal-exit@^3.0.3:
   version "3.0.7"
@@ -4035,32 +4154,33 @@
     define-properties "^1.2.0"
     es-abstract "^1.22.1"
 
-string.prototype.trim@^1.2.8:
-  version "1.2.8"
-  resolved "https://registry.yarnpkg.com/string.prototype.trim/-/string.prototype.trim-1.2.8.tgz#f9ac6f8af4bd55ddfa8895e6aea92a96395393bd"
-  integrity sha512-lfjY4HcixfQXOfaqCvcBuOIapyaroTXhbkfJN3gcB1OtyupngWK4sEET9Knd0cXd28kTUqu/kHoV4HKSJdnjiQ==
+string.prototype.trim@^1.2.9:
+  version "1.2.9"
+  resolved "https://registry.yarnpkg.com/string.prototype.trim/-/string.prototype.trim-1.2.9.tgz#b6fa326d72d2c78b6df02f7759c73f8f6274faa4"
+  integrity sha512-klHuCNxiMZ8MlsOihJhJEBJAiMVqU3Z2nEXWfWnIqjN0gEFS9J9+IxKozWWtQGcgoa1WUZzLjKPTr4ZHNFTFxw==
   dependencies:
-    call-bind "^1.0.2"
-    define-properties "^1.2.0"
-    es-abstract "^1.22.1"
+    call-bind "^1.0.7"
+    define-properties "^1.2.1"
+    es-abstract "^1.23.0"
+    es-object-atoms "^1.0.0"
 
-string.prototype.trimend@^1.0.7:
-  version "1.0.7"
-  resolved "https://registry.yarnpkg.com/string.prototype.trimend/-/string.prototype.trimend-1.0.7.tgz#1bb3afc5008661d73e2dc015cd4853732d6c471e"
-  integrity sha512-Ni79DqeB72ZFq1uH/L6zJ+DKZTkOtPIHovb3YZHQViE+HDouuU4mBrLOLDn5Dde3RF8qw5qVETEjhu9locMLvA==
+string.prototype.trimend@^1.0.8:
+  version "1.0.8"
+  resolved "https://registry.yarnpkg.com/string.prototype.trimend/-/string.prototype.trimend-1.0.8.tgz#3651b8513719e8a9f48de7f2f77640b26652b229"
+  integrity sha512-p73uL5VCHCO2BZZ6krwwQE3kCzM7NKmis8S//xEC6fQonchbum4eP6kR4DLEjQFO3Wnj3Fuo8NM0kOSjVdHjZQ==
   dependencies:
-    call-bind "^1.0.2"
-    define-properties "^1.2.0"
-    es-abstract "^1.22.1"
+    call-bind "^1.0.7"
+    define-properties "^1.2.1"
+    es-object-atoms "^1.0.0"
 
-string.prototype.trimstart@^1.0.7:
-  version "1.0.7"
-  resolved "https://registry.yarnpkg.com/string.prototype.trimstart/-/string.prototype.trimstart-1.0.7.tgz#d4cdb44b83a4737ffbac2d406e405d43d0184298"
-  integrity sha512-NGhtDFu3jCEm7B4Fy0DpLewdJQOZcQ0rGbwQ/+stjnrp2i+rlKeCvos9hOIeCmqwratM47OBxY7uFZzjxHXmrg==
+string.prototype.trimstart@^1.0.8:
+  version "1.0.8"
+  resolved "https://registry.yarnpkg.com/string.prototype.trimstart/-/string.prototype.trimstart-1.0.8.tgz#7ee834dda8c7c17eff3118472bb35bfedaa34dde"
+  integrity sha512-UXSH262CSZY1tfu3G3Secr6uGLCFVPMhIqHjlgCUtCCcgihYc/xKs9djMTMUOb2j1mVSeU8EU6NWc/iQKU6Gfg==
   dependencies:
-    call-bind "^1.0.2"
-    define-properties "^1.2.0"
-    es-abstract "^1.22.1"
+    call-bind "^1.0.7"
+    define-properties "^1.2.1"
+    es-object-atoms "^1.0.0"
 
 strip-ansi@^6.0.0, strip-ansi@^6.0.1:
   version "6.0.1"
@@ -4277,44 +4397,49 @@
     media-typer "0.3.0"
     mime-types "~2.1.24"
 
-typed-array-buffer@^1.0.0:
-  version "1.0.0"
-  resolved "https://registry.yarnpkg.com/typed-array-buffer/-/typed-array-buffer-1.0.0.tgz#18de3e7ed7974b0a729d3feecb94338d1472cd60"
-  integrity sha512-Y8KTSIglk9OZEr8zywiIHG/kmQ7KWyjseXs1CbSo8vC42w7hg2HgYTxSWwP0+is7bWDc1H+Fo026CpHFwm8tkw==
+typed-array-buffer@^1.0.2:
+  version "1.0.2"
+  resolved "https://registry.yarnpkg.com/typed-array-buffer/-/typed-array-buffer-1.0.2.tgz#1867c5d83b20fcb5ccf32649e5e2fc7424474ff3"
+  integrity sha512-gEymJYKZtKXzzBzM4jqa9w6Q1Jjm7x2d+sh19AdsD4wqnMPDYyvwpsIc2Q/835kHuo3BEQ7CjelGhfTsoBb2MQ==
   dependencies:
-    call-bind "^1.0.2"
-    get-intrinsic "^1.2.1"
-    is-typed-array "^1.1.10"
+    call-bind "^1.0.7"
+    es-errors "^1.3.0"
+    is-typed-array "^1.1.13"
 
-typed-array-byte-length@^1.0.0:
-  version "1.0.0"
-  resolved "https://registry.yarnpkg.com/typed-array-byte-length/-/typed-array-byte-length-1.0.0.tgz#d787a24a995711611fb2b87a4052799517b230d0"
-  integrity sha512-Or/+kvLxNpeQ9DtSydonMxCx+9ZXOswtwJn17SNLvhptaXYDJvkFFP5zbfU/uLmvnBJlI4yrnXRxpdWH/M5tNA==
+typed-array-byte-length@^1.0.1:
+  version "1.0.1"
+  resolved "https://registry.yarnpkg.com/typed-array-byte-length/-/typed-array-byte-length-1.0.1.tgz#d92972d3cff99a3fa2e765a28fcdc0f1d89dec67"
+  integrity sha512-3iMJ9q0ao7WE9tWcaYKIptkNBuOIcZCCT0d4MRvuuH88fEoEH62IuQe0OtraD3ebQEoTRk8XCBoknUNc1Y67pw==
   dependencies:
-    call-bind "^1.0.2"
+    call-bind "^1.0.7"
     for-each "^0.3.3"
-    has-proto "^1.0.1"
-    is-typed-array "^1.1.10"
+    gopd "^1.0.1"
+    has-proto "^1.0.3"
+    is-typed-array "^1.1.13"
 
-typed-array-byte-offset@^1.0.0:
-  version "1.0.0"
-  resolved "https://registry.yarnpkg.com/typed-array-byte-offset/-/typed-array-byte-offset-1.0.0.tgz#cbbe89b51fdef9cd6aaf07ad4707340abbc4ea0b"
-  integrity sha512-RD97prjEt9EL8YgAgpOkf3O4IF9lhJFr9g0htQkm0rchFp/Vx7LW5Q8fSXXub7BXAODyUQohRMyOc3faCPd0hg==
+typed-array-byte-offset@^1.0.2:
+  version "1.0.2"
+  resolved "https://registry.yarnpkg.com/typed-array-byte-offset/-/typed-array-byte-offset-1.0.2.tgz#f9ec1acb9259f395093e4567eb3c28a580d02063"
+  integrity sha512-Ous0vodHa56FviZucS2E63zkgtgrACj7omjwd/8lTEMEPFFyjfixMZ1ZXenpgCFBBt4EC1J2XsyVS2gkG0eTFA==
   dependencies:
-    available-typed-arrays "^1.0.5"
-    call-bind "^1.0.2"
+    available-typed-arrays "^1.0.7"
+    call-bind "^1.0.7"
     for-each "^0.3.3"
-    has-proto "^1.0.1"
-    is-typed-array "^1.1.10"
+    gopd "^1.0.1"
+    has-proto "^1.0.3"
+    is-typed-array "^1.1.13"
 
-typed-array-length@^1.0.4:
-  version "1.0.4"
-  resolved "https://registry.yarnpkg.com/typed-array-length/-/typed-array-length-1.0.4.tgz#89d83785e5c4098bec72e08b319651f0eac9c1bb"
-  integrity sha512-KjZypGq+I/H7HI5HlOoGHkWUUGq+Q0TPhQurLbyrVrvnKTBgzLhIJ7j6J/XTQOi0d1RjyZ0wdas8bKs2p0x3Ng==
+typed-array-length@^1.0.6:
+  version "1.0.6"
+  resolved "https://registry.yarnpkg.com/typed-array-length/-/typed-array-length-1.0.6.tgz#57155207c76e64a3457482dfdc1c9d1d3c4c73a3"
+  integrity sha512-/OxDN6OtAk5KBpGb28T+HZc2M+ADtvRxXrKKbUwtsLgdoxgX13hyy7ek6bFRl5+aBs2yZzB0c4CnQfAtVypW/g==
   dependencies:
-    call-bind "^1.0.2"
+    call-bind "^1.0.7"
     for-each "^0.3.3"
-    is-typed-array "^1.1.9"
+    gopd "^1.0.1"
+    has-proto "^1.0.3"
+    is-typed-array "^1.1.13"
+    possible-typed-array-names "^1.0.0"
 
 typedarray-to-buffer@^3.1.5:
   version "3.1.5"
@@ -4490,16 +4615,16 @@
   resolved "https://registry.yarnpkg.com/which-module/-/which-module-2.0.1.tgz#776b1fe35d90aebe99e8ac15eb24093389a4a409"
   integrity sha512-iBdZ57RDvnOR9AGBhML2vFZf7h8vmBjhoaZqODJBFWHVtKkDmKuHai3cx5PgVMrX5YDNp27AofYbAwctSS+vhQ==
 
-which-typed-array@^1.1.11, which-typed-array@^1.1.13:
-  version "1.1.13"
-  resolved "https://registry.yarnpkg.com/which-typed-array/-/which-typed-array-1.1.13.tgz#870cd5be06ddb616f504e7b039c4c24898184d36"
-  integrity sha512-P5Nra0qjSncduVPEAr7xhoF5guty49ArDTwzJ/yNuPIbZppyRxFQsRCWrocxIY+CnMVG+qfbU2FmDKyvSGClow==
+which-typed-array@^1.1.14, which-typed-array@^1.1.15:
+  version "1.1.15"
+  resolved "https://registry.yarnpkg.com/which-typed-array/-/which-typed-array-1.1.15.tgz#264859e9b11a649b388bfaaf4f767df1f779b38d"
+  integrity sha512-oV0jmFtUky6CXfkqehVvBP/LSWJ2sy4vWMioiENyJLePrBO/yKyV9OyJySfAKosh+RYkIl5zJCNZ8/4JncrpdA==
   dependencies:
-    available-typed-arrays "^1.0.5"
-    call-bind "^1.0.4"
+    available-typed-arrays "^1.0.7"
+    call-bind "^1.0.7"
     for-each "^0.3.3"
     gopd "^1.0.1"
-    has-tostringtag "^1.0.0"
+    has-tostringtag "^1.0.2"
 
 which@^1.2.9:
   version "1.3.1"
@@ -4515,6 +4640,11 @@
   dependencies:
     isexe "^2.0.0"
 
+word-wrap@^1.2.5:
+  version "1.2.5"
+  resolved "https://registry.yarnpkg.com/word-wrap/-/word-wrap-1.2.5.tgz#d2c45c6dd4fbce621a66f136cbe328afd0410b34"
+  integrity sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==
+
 wordwrapjs@^5.1.0:
   version "5.1.0"
   resolved "https://registry.yarnpkg.com/wordwrapjs/-/wordwrapjs-5.1.0.tgz#4c4d20446dcc670b14fa115ef4f8fd9947af2b3a"