From 1ee5e178966c1d2e367f9074dc93be15e73b7ff9 Mon Sep 17 00:00:00 2001
From: NullVoxPopuli <199018+NullVoxPopuli@users.noreply.github.com>
Date: Thu, 21 Aug 2025 14:34:24 -0400
Subject: [PATCH 1/2] Move the reactive collections to
@ember/reactive/collections
---
packages/@ember/reactive/collections.ts | 262 ++++++++++++++++++++++++
packages/@ember/reactive/index.ts | 257 +----------------------
tests/docs/expected.js | 1 +
type-tests/@ember/reactive-test.ts | 2 +-
4 files changed, 266 insertions(+), 256 deletions(-)
create mode 100644 packages/@ember/reactive/collections.ts
diff --git a/packages/@ember/reactive/collections.ts b/packages/@ember/reactive/collections.ts
new file mode 100644
index 00000000000..e64b1bd4a1e
--- /dev/null
+++ b/packages/@ember/reactive/collections.ts
@@ -0,0 +1,262 @@
+/**
+ * The `@ember/reactive/collections` module contains reactive data structures that fall under the "Collections" category.
+ *
+ * @module @ember/reactive/collections
+ * @public
+ */
+
+/**
+ * A utility for creating tracked arrays, copying the original data so that
+ * mutations to the tracked data don't mutate the original untracked data.
+ *
+ * `trackedArray` can be used in templates and in JavaScript via import.
+ * All property accesses entangle with that property, all property sets dirty
+ * that property, and changes to the collection only render what changed
+ * without causing unneeded renders.
+ *
+ * See [MDN for more information](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array)
+ *
+ * @example
+ * ```javascript
+ * import { trackedArray } from '@ember/reactive';
+ * import { on } from '@ember/modifier';
+ * import { fn } from '@ember/helper';
+ *
+ * const nonTrackedArray = [1, 2, 3];
+ * const addTo = (arr) => arr.push(Math.random());
+ *
+ *
+ * {{#let (trackedArray nonTrackedArray) as |arr|}}
+ * {{#each arr as |datum|}}
+ * {{datum}}
+ * {{/each}}
+ *
+ *
+ * {{/let}}
+ *
+ * ```
+ *
+ * @method trackedArray
+ * @static
+ * @for @ember/reactive/collections
+ * @param {Array} [data] The initial array data to track
+ * @param {Object} [options] Optional configuration
+ * @param {Function} [options.equals] Custom equality function (defaults to Object.is)
+ * @param {String} [options.description] Description for debugging purposes
+ * @returns {Array} A tracked array that updates reactively
+ * @public
+ */
+export { trackedArray } from '@glimmer/validator';
+
+/**
+ * A utility for creating tracked objects, copying the original data so that
+ * mutations to the tracked data don't mutate the original untracked data.
+ *
+ * `trackedObject` can be used in templates and in JavaScript via import.
+ * All property accesses entangle with that property, all property sets dirty
+ * that property, and changes to the collection only render what changed
+ * without causing unneeded renders.
+ *
+ * See [MDN for more information](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object)
+ *
+ * @example
+ * ```gjs
+ * import { trackedObject } from '@ember/reactive';
+ * import { on } from '@ember/modifier';
+ * import { fn } from '@ember/helper';
+ *
+ * const nonTrackedObject = { a: 1 };
+ * const addTo = (obj) => obj[Math.random()] = Math.random();
+ *
+ *
+ * {{#let (trackedObject nonTrackedObject) as |obj|}}
+ * {{#each-in obj as |key value|}}
+ * {{key}} => {{value}}
+ * {{/each-in}}
+ *
+ *
+ * {{/let}}
+ *
+ * ```
+ *
+ * @method trackedObject
+ * @static
+ * @for @ember/reactive/collections
+ * @param {Object} [data] The initial object data to track
+ * @param {Object} [options] Optional configuration
+ * @param {Function} [options.equals] Custom equality function (defaults to Object.is)
+ * @param {String} [options.description] Description for debugging purposes
+ * @returns {Object} A tracked object that updates reactively
+ * @public
+ */
+export { trackedObject } from '@glimmer/validator';
+
+/**
+ * A utility for creating tracked sets, copying the original data so that
+ * mutations to the tracked data don't mutate the original untracked data.
+ *
+ * `trackedSet` can be used in templates and in JavaScript via import.
+ * All property accesses entangle with that property, all property sets dirty
+ * that property, and changes to the collection only render what changed
+ * without causing unneeded renders.
+ *
+ * See [MDN for more information](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Set)
+ *
+ * @example
+ * ```gjs
+ * import { trackedSet } from '@ember/reactive';
+ * import { on } from '@ember/modifier';
+ * import { fn } from '@ember/helper';
+ *
+ * const nonTrackedSet = new Set();
+ * nonTrackedSet.add(1);
+ * const addTo = (set) => set.add(Math.random());
+ *
+ *
+ * {{#let (trackedSet nonTrackedSet) as |set|}}
+ * {{#each set as |value|}}
+ * {{value}}
+ * {{/each}}
+ *
+ *
+ * {{/let}}
+ *
+ * ```
+ *
+ * @method trackedSet
+ * @static
+ * @for @ember/reactive/collections
+ * @param {Set} [data] The initial Set data to track
+ * @param {Object} [options] Optional configuration
+ * @param {Function} [options.equals] Custom equality function (defaults to Object.is)
+ * @param {String} [options.description] Description for debugging purposes
+ * @returns {Set} A tracked Set that updates reactively
+ * @public
+ */
+export { trackedSet } from '@glimmer/validator';
+
+/**
+ * A utility for creating tracked weak sets, copying the original data so that
+ * mutations to the tracked data don't mutate the original untracked data.
+ *
+ * `trackedWeakSet` can be used in templates and in JavaScript via import.
+ * All property accesses entangle with that property, all property sets dirty
+ * that property, and changes to the collection only render what changed
+ * without causing unneeded renders.
+ *
+ * WeakSets hold weak references to their values, allowing garbage collection
+ * when objects are no longer referenced elsewhere.
+ *
+ * See [MDN for more information](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/WeakSet)
+ *
+ * @example
+ * ```gjs
+ * import { trackedWeakSet } from '@ember/reactive';
+ * import { on } from '@ember/modifier';
+ * import { fn } from '@ember/helper';
+ *
+ * const nonTrackedWeakSet = new WeakSet();
+ *
+ *
+ * {{#let (trackedWeakSet nonTrackedWeakSet) as |weakSet|}}
+ * {{log weakSet}}
+ * {{/let}}
+ *
+ * ```
+ *
+ * @method trackedWeakSet
+ * @static
+ * @for @ember/reactive/collections
+ * @param {WeakSet} [data] The initial WeakSet data to track
+ * @param {Object} [options] Optional configuration
+ * @param {Function} [options.equals] Custom equality function (defaults to Object.is)
+ * @param {String} [options.description] Description for debugging purposes
+ * @returns {WeakSet} A tracked WeakSet that updates reactively
+ * @public
+ */
+export { trackedWeakSet } from '@glimmer/validator';
+
+/**
+ * A utility for creating tracked maps, copying the original data so that
+ * mutations to the tracked data don't mutate the original untracked data.
+ *
+ * `trackedMap` can be used in templates and in JavaScript via import.
+ * All property accesses entangle with that property, all property sets dirty
+ * that property, and changes to the collection only render what changed
+ * without causing unneeded renders.
+ *
+ * See [MDN for more information](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map)
+ *
+ * @example
+ * ```gjs
+ * import { trackedMap } from '@ember/reactive';
+ * import { on } from '@ember/modifier';
+ * import { fn } from '@ember/helper';
+ *
+ * const nonTrackedMap = new Map();
+ * nonTrackedMap.set('a', 1);
+ * const addTo = (map) => map.set(Math.random(), Math.random());
+ *
+ *
+ * {{#let (trackedMap nonTrackedMap) as |map|}}
+ * {{#each-in map as |key value|}}
+ * {{key}} => {{value}}
+ * {{/each-in}}
+ *
+ *
+ * {{/let}}
+ *
+ * ```
+ *
+ * @method trackedMap
+ * @static
+ * @for @ember/reactive/collections
+ * @param {Map} [data] The initial Map data to track
+ * @param {Object} [options] Optional configuration
+ * @param {Function} [options.equals] Custom equality function (defaults to Object.is)
+ * @param {String} [options.description] Description for debugging purposes
+ * @returns {Map} A tracked Map that updates reactively
+ * @public
+ */
+export { trackedMap } from '@glimmer/validator';
+
+/**
+ * A utility for creating tracked weak maps, copying the original data so that
+ * mutations to the tracked data don't mutate the original untracked data.
+ *
+ * `trackedWeakMap` can be used in templates and in JavaScript via import.
+ * All property accesses entangle with that property, all property sets dirty
+ * that property, and changes to the collection only render what changed
+ * without causing unneeded renders.
+ *
+ * WeakMaps hold weak references to their keys, allowing garbage collection
+ * when key objects are no longer referenced elsewhere.
+ *
+ * See [MDN for more information](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/WeakMap)
+ *
+ * @example
+ * ```gjs
+ * import { trackedWeakMap } from '@ember/reactive';
+ * import { on } from '@ember/modifier';
+ * import { fn } from '@ember/helper';
+ *
+ * const nonTrackedWeakMap = new WeakMap();
+ *
+ *
+ * {{#let (trackedWeakMap nonTrackedWeakMap) as |weakMap|}}
+ * {{log weakMap}}
+ * {{/let}}
+ *
+ * ```
+ *
+ * @method trackedWeakMap
+ * @static
+ * @for @ember/reactive/collections
+ * @param {WeakMap} [data] The initial WeakMap data to track
+ * @param {Object} [options] Optional configuration
+ * @param {Function} [options.equals] Custom equality function (defaults to Object.is)
+ * @param {String} [options.description] Description for debugging purposes
+ * @returns {WeakMap} A tracked WeakMap that updates reactively
+ * @public
+ */
+export { trackedWeakMap } from '@glimmer/validator';
diff --git a/packages/@ember/reactive/index.ts b/packages/@ember/reactive/index.ts
index a58df2aac94..3664f60e67f 100644
--- a/packages/@ember/reactive/index.ts
+++ b/packages/@ember/reactive/index.ts
@@ -6,258 +6,5 @@
* @public
*/
-/**
- * A utility for creating tracked arrays, copying the original data so that
- * mutations to the tracked data don't mutate the original untracked data.
- *
- * `trackedArray` can be used in templates and in JavaScript via import.
- * All property accesses entangle with that property, all property sets dirty
- * that property, and changes to the collection only render what changed
- * without causing unneeded renders.
- *
- * See [MDN for more information](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array)
- *
- * @example
- * ```javascript
- * import { trackedArray } from '@ember/reactive';
- * import { on } from '@ember/modifier';
- * import { fn } from '@ember/helper';
- *
- * const nonTrackedArray = [1, 2, 3];
- * const addTo = (arr) => arr.push(Math.random());
- *
- *
- * {{#let (trackedArray nonTrackedArray) as |arr|}}
- * {{#each arr as |datum|}}
- * {{datum}}
- * {{/each}}
- *
- *
- * {{/let}}
- *
- * ```
- *
- * @method trackedArray
- * @static
- * @for @ember/reactive
- * @param {Array} [data] The initial array data to track
- * @param {Object} [options] Optional configuration
- * @param {Function} [options.equals] Custom equality function (defaults to Object.is)
- * @param {String} [options.description] Description for debugging purposes
- * @returns {Array} A tracked array that updates reactively
- * @public
- */
-export { trackedArray } from '@glimmer/validator';
-
-/**
- * A utility for creating tracked objects, copying the original data so that
- * mutations to the tracked data don't mutate the original untracked data.
- *
- * `trackedObject` can be used in templates and in JavaScript via import.
- * All property accesses entangle with that property, all property sets dirty
- * that property, and changes to the collection only render what changed
- * without causing unneeded renders.
- *
- * See [MDN for more information](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object)
- *
- * @example
- * ```gjs
- * import { trackedObject } from '@ember/reactive';
- * import { on } from '@ember/modifier';
- * import { fn } from '@ember/helper';
- *
- * const nonTrackedObject = { a: 1 };
- * const addTo = (obj) => obj[Math.random()] = Math.random();
- *
- *
- * {{#let (trackedObject nonTrackedObject) as |obj|}}
- * {{#each-in obj as |key value|}}
- * {{key}} => {{value}}
- * {{/each-in}}
- *
- *
- * {{/let}}
- *
- * ```
- *
- * @method trackedObject
- * @static
- * @for @ember/reactive
- * @param {Object} [data] The initial object data to track
- * @param {Object} [options] Optional configuration
- * @param {Function} [options.equals] Custom equality function (defaults to Object.is)
- * @param {String} [options.description] Description for debugging purposes
- * @returns {Object} A tracked object that updates reactively
- * @public
- */
-export { trackedObject } from '@glimmer/validator';
-
-/**
- * A utility for creating tracked sets, copying the original data so that
- * mutations to the tracked data don't mutate the original untracked data.
- *
- * `trackedSet` can be used in templates and in JavaScript via import.
- * All property accesses entangle with that property, all property sets dirty
- * that property, and changes to the collection only render what changed
- * without causing unneeded renders.
- *
- * See [MDN for more information](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Set)
- *
- * @example
- * ```gjs
- * import { trackedSet } from '@ember/reactive';
- * import { on } from '@ember/modifier';
- * import { fn } from '@ember/helper';
- *
- * const nonTrackedSet = new Set();
- * nonTrackedSet.add(1);
- * const addTo = (set) => set.add(Math.random());
- *
- *
- * {{#let (trackedSet nonTrackedSet) as |set|}}
- * {{#each set as |value|}}
- * {{value}}
- * {{/each}}
- *
- *
- * {{/let}}
- *
- * ```
- *
- * @method trackedSet
- * @static
- * @for @ember/reactive
- * @param {Set} [data] The initial Set data to track
- * @param {Object} [options] Optional configuration
- * @param {Function} [options.equals] Custom equality function (defaults to Object.is)
- * @param {String} [options.description] Description for debugging purposes
- * @returns {Set} A tracked Set that updates reactively
- * @public
- */
-export { trackedSet } from '@glimmer/validator';
-
-/**
- * A utility for creating tracked weak sets, copying the original data so that
- * mutations to the tracked data don't mutate the original untracked data.
- *
- * `trackedWeakSet` can be used in templates and in JavaScript via import.
- * All property accesses entangle with that property, all property sets dirty
- * that property, and changes to the collection only render what changed
- * without causing unneeded renders.
- *
- * WeakSets hold weak references to their values, allowing garbage collection
- * when objects are no longer referenced elsewhere.
- *
- * See [MDN for more information](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/WeakSet)
- *
- * @example
- * ```gjs
- * import { trackedWeakSet } from '@ember/reactive';
- * import { on } from '@ember/modifier';
- * import { fn } from '@ember/helper';
- *
- * const nonTrackedWeakSet = new WeakSet();
- *
- *
- * {{#let (trackedWeakSet nonTrackedWeakSet) as |weakSet|}}
- * {{log weakSet}}
- * {{/let}}
- *
- * ```
- *
- * @method trackedWeakSet
- * @static
- * @for @ember/reactive
- * @param {WeakSet} [data] The initial WeakSet data to track
- * @param {Object} [options] Optional configuration
- * @param {Function} [options.equals] Custom equality function (defaults to Object.is)
- * @param {String} [options.description] Description for debugging purposes
- * @returns {WeakSet} A tracked WeakSet that updates reactively
- * @public
- */
-export { trackedWeakSet } from '@glimmer/validator';
-
-/**
- * A utility for creating tracked maps, copying the original data so that
- * mutations to the tracked data don't mutate the original untracked data.
- *
- * `trackedMap` can be used in templates and in JavaScript via import.
- * All property accesses entangle with that property, all property sets dirty
- * that property, and changes to the collection only render what changed
- * without causing unneeded renders.
- *
- * See [MDN for more information](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map)
- *
- * @example
- * ```gjs
- * import { trackedMap } from '@ember/reactive';
- * import { on } from '@ember/modifier';
- * import { fn } from '@ember/helper';
- *
- * const nonTrackedMap = new Map();
- * nonTrackedMap.set('a', 1);
- * const addTo = (map) => map.set(Math.random(), Math.random());
- *
- *
- * {{#let (trackedMap nonTrackedMap) as |map|}}
- * {{#each-in map as |key value|}}
- * {{key}} => {{value}}
- * {{/each-in}}
- *
- *
- * {{/let}}
- *
- * ```
- *
- * @method trackedMap
- * @static
- * @for @ember/reactive
- * @param {Map} [data] The initial Map data to track
- * @param {Object} [options] Optional configuration
- * @param {Function} [options.equals] Custom equality function (defaults to Object.is)
- * @param {String} [options.description] Description for debugging purposes
- * @returns {Map} A tracked Map that updates reactively
- * @public
- */
-export { trackedMap } from '@glimmer/validator';
-
-/**
- * A utility for creating tracked weak maps, copying the original data so that
- * mutations to the tracked data don't mutate the original untracked data.
- *
- * `trackedWeakMap` can be used in templates and in JavaScript via import.
- * All property accesses entangle with that property, all property sets dirty
- * that property, and changes to the collection only render what changed
- * without causing unneeded renders.
- *
- * WeakMaps hold weak references to their keys, allowing garbage collection
- * when key objects are no longer referenced elsewhere.
- *
- * See [MDN for more information](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/WeakMap)
- *
- * @example
- * ```gjs
- * import { trackedWeakMap } from '@ember/reactive';
- * import { on } from '@ember/modifier';
- * import { fn } from '@ember/helper';
- *
- * const nonTrackedWeakMap = new WeakMap();
- *
- *
- * {{#let (trackedWeakMap nonTrackedWeakMap) as |weakMap|}}
- * {{log weakMap}}
- * {{/let}}
- *
- * ```
- *
- * @method trackedWeakMap
- * @static
- * @for @ember/reactive
- * @param {WeakMap} [data] The initial WeakMap data to track
- * @param {Object} [options] Optional configuration
- * @param {Function} [options.equals] Custom equality function (defaults to Object.is)
- * @param {String} [options.description] Description for debugging purposes
- * @returns {WeakMap} A tracked WeakMap that updates reactively
- * @public
- */
-export { trackedWeakMap } from '@glimmer/validator';
+// empty module (for now)
+export default {};
diff --git a/tests/docs/expected.js b/tests/docs/expected.js
index 291736c703d..d0f65de0483 100644
--- a/tests/docs/expected.js
+++ b/tests/docs/expected.js
@@ -634,6 +634,7 @@ module.exports = {
'@ember/object/proxy',
'@ember/owner',
'@ember/reactive',
+ '@ember/reactive/collections',
'@ember/renderer',
'@ember/routing',
'@ember/routing/hash-location',
diff --git a/type-tests/@ember/reactive-test.ts b/type-tests/@ember/reactive-test.ts
index fd138b6bca1..94f7bf3accf 100644
--- a/type-tests/@ember/reactive-test.ts
+++ b/type-tests/@ember/reactive-test.ts
@@ -1,4 +1,4 @@
-import { trackedArray, trackedObject, trackedWeakSet, trackedSet, trackedMap, trackedWeakMap } from '@ember/reactive';
+import { trackedArray, trackedObject, trackedWeakSet, trackedSet, trackedMap, trackedWeakMap } from '@ember/reactive/collections';
import { expectTypeOf } from 'expect-type';
From d078d163242bc9c39fa8ff86d054fedae5ceead4 Mon Sep 17 00:00:00 2001
From: NullVoxPopuli <199018+NullVoxPopuli@users.noreply.github.com>
Date: Thu, 21 Aug 2025 14:42:34 -0400
Subject: [PATCH 2/2] Update package.json
---
package.json | 1 +
1 file changed, 1 insertion(+)
diff --git a/package.json b/package.json
index 8bba9d782e8..e26b0460d2b 100644
--- a/package.json
+++ b/package.json
@@ -281,6 +281,7 @@
"@ember/object/promise-proxy-mixin.js": "ember-source/@ember/object/promise-proxy-mixin.js",
"@ember/object/proxy.js": "ember-source/@ember/object/proxy.js",
"@ember/owner/index.js": "ember-source/@ember/owner/index.js",
+ "@ember/reactive/collections.js": "ember-source/@ember/reactive/collections.js",
"@ember/reactive/index.js": "ember-source/@ember/reactive/index.js",
"@ember/renderer/index.js": "ember-source/@ember/renderer/index.js",
"@ember/routing/-internals.js": "ember-source/@ember/routing/-internals.js",