Create a variant of EnumSet that works when compiled to js
Fixed: 54468
Change-Id: I36d3b8789695ef6a74a32c6801ec5c8c19aae381
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/366822
Reviewed-by: Konstantin Shcheglov <scheglov@google.com>
Commit-Queue: Jonas Jensen <jonasfj@google.com>
diff --git a/pkg/analyzer/lib/src/generated/utilities_collection.dart b/pkg/analyzer/lib/src/generated/utilities_collection.dart
index 5725b73..4d20795 100644
--- a/pkg/analyzer/lib/src/generated/utilities_collection.dart
+++ b/pkg/analyzer/lib/src/generated/utilities_collection.dart
@@ -2,36 +2,6 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
-/// The set of [Enum] values, backed by [int].
-extension type EnumSet<T extends Enum>(int _bits) {
- EnumSet.empty() : this(0);
-
- /// Whether [constant] is present.
- bool operator [](T constant) {
- var index = constant.index;
- _checkIndex(index);
-
- var mask = 1 << index;
- return (_bits & mask) != 0;
- }
-
- /// Returns a new set, with presence of [constant] updated.
- EnumSet<T> updated(T constant, bool value) {
- var index = constant.index;
- _checkIndex(index);
-
- var mask = 1 << index;
- if (value) {
- return EnumSet<T>(_bits | mask);
- } else {
- return EnumSet<T>(_bits & ~mask);
- }
- }
-
- /// Throws an exception if the [index] does not fit [int].
- static void _checkIndex(int index) {
- if (index < 0 || index > 60) {
- throw RangeError("Index not between 0 and 60: $index");
- }
- }
-}
+// Export [EnumSet] depending on the compilation target.
+export 'utilities_collection_native.dart'
+ if (dart.library.js) 'utilities_collection_js.dart';
diff --git a/pkg/analyzer/lib/src/generated/utilities_collection_js.dart b/pkg/analyzer/lib/src/generated/utilities_collection_js.dart
new file mode 100644
index 0000000..ef81378
--- /dev/null
+++ b/pkg/analyzer/lib/src/generated/utilities_collection_js.dart
@@ -0,0 +1,51 @@
+// Copyright (c) 2024, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+/// Provides [EnumSet] which works when compiled to JS.
+library;
+
+/// The set of [Enum] values, up to `60` constants.
+extension type EnumSet<T extends Enum>((int, int) _bits) {
+ EnumSet.empty() : this((0, 0));
+
+ /// Whether [constant] is present.
+ bool operator [](T constant) {
+ var index = constant.index;
+ _checkIndex(index);
+
+ // In JavaScript bitwise operations are performed on 32-bit integers.
+ if (index <= 30) {
+ var mask = 1 << index;
+ return (_bits.$1 & mask) != 0;
+ } else {
+ var mask = 1 << (index - 30);
+ return (_bits.$2 & mask) != 0;
+ }
+ }
+
+ /// Returns a new set, with presence of [constant] updated.
+ EnumSet<T> updated(T constant, bool value) {
+ var index = constant.index;
+ _checkIndex(index);
+
+ if (index <= 30) {
+ var mask = 1 << index;
+ var field = _bits.$1;
+ var newField = value ? field | mask : field & ~mask;
+ return EnumSet<T>((newField, _bits.$2));
+ } else {
+ var mask = 1 << (index - 30);
+ var field = _bits.$2;
+ var newField = value ? field | mask : field & ~mask;
+ return EnumSet<T>((_bits.$1, newField));
+ }
+ }
+
+ /// Throws an exception if the [index] does not fit the storage.
+ static void _checkIndex(int index) {
+ if (index < 0 || index > 60) {
+ throw RangeError("Index not between 0 and 60: $index");
+ }
+ }
+}
diff --git a/pkg/analyzer/lib/src/generated/utilities_collection_native.dart b/pkg/analyzer/lib/src/generated/utilities_collection_native.dart
new file mode 100644
index 0000000..b30c0a6
--- /dev/null
+++ b/pkg/analyzer/lib/src/generated/utilities_collection_native.dart
@@ -0,0 +1,41 @@
+// Copyright (c) 2024, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+/// Provides efficient [EnumSet] which only works when 64 bit integers are
+/// available.
+library;
+
+/// The set of [Enum] values, backed by [int].
+extension type EnumSet<T extends Enum>(int _bits) {
+ EnumSet.empty() : this(0);
+
+ /// Whether [constant] is present.
+ bool operator [](T constant) {
+ var index = constant.index;
+ _checkIndex(index);
+
+ var mask = 1 << index;
+ return (_bits & mask) != 0;
+ }
+
+ /// Returns a new set, with presence of [constant] updated.
+ EnumSet<T> updated(T constant, bool value) {
+ var index = constant.index;
+ _checkIndex(index);
+
+ var mask = 1 << index;
+ if (value) {
+ return EnumSet<T>(_bits | mask);
+ } else {
+ return EnumSet<T>(_bits & ~mask);
+ }
+ }
+
+ /// Throws an exception if the [index] does not fit [int].
+ static void _checkIndex(int index) {
+ if (index < 0 || index > 60) {
+ throw RangeError("Index not between 0 and 60: $index");
+ }
+ }
+}