ember-source 7.3.0-alpha.1 → 7.3.0-alpha.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (102) hide show
  1. package/build-metadata.json +3 -3
  2. package/dist/dev/packages/@ember/-internals/glimmer/index.js +6 -6
  3. package/dist/dev/packages/@ember/-internals/metal/index.js +8 -8
  4. package/dist/dev/packages/@ember/-internals/runtime/lib/mixins/-proxy.js +2 -2
  5. package/dist/dev/packages/@ember/-internals/runtime/lib/mixins/target_action_support.js +1 -1
  6. package/dist/dev/packages/@ember/-internals/views/lib/system/event_dispatcher.js +1 -1
  7. package/dist/dev/packages/@ember/-internals/views/lib/views/core_view.js +1 -1
  8. package/dist/dev/packages/@ember/application/index.js +1 -1
  9. package/dist/dev/packages/@ember/application/instance.js +4 -4
  10. package/dist/dev/packages/@ember/array/index.js +3 -3
  11. package/dist/dev/packages/@ember/array/proxy.js +3 -3
  12. package/dist/dev/packages/@ember/component/index.js +2 -2
  13. package/dist/dev/packages/@ember/controller/index.js +2 -2
  14. package/dist/dev/packages/@ember/engine/index.js +2 -2
  15. package/dist/dev/packages/@ember/object/computed.js +2 -2
  16. package/dist/dev/packages/@ember/object/core.js +2 -2
  17. package/dist/dev/packages/@ember/object/index.js +4 -4
  18. package/dist/dev/packages/@ember/object/lib/computed/computed_macros.js +3 -3
  19. package/dist/dev/packages/@ember/object/lib/computed/reduce_computed_macros.js +1 -1
  20. package/dist/dev/packages/@ember/object/mixin.js +1 -1
  21. package/dist/dev/packages/@ember/object/observable.js +3 -3
  22. package/dist/dev/packages/@ember/object/promise-proxy-mixin.js +2 -2
  23. package/dist/dev/packages/@ember/renderer/index.js +1 -1
  24. package/dist/dev/packages/@ember/routing/route.js +3 -3
  25. package/dist/dev/packages/@ember/routing/router.js +2 -2
  26. package/dist/dev/packages/@ember/service/index.js +1 -1
  27. package/dist/dev/packages/@glimmer/node/index.js +2 -2
  28. package/dist/dev/packages/@glimmer/runtime/index.js +3 -3
  29. package/dist/dev/packages/@glimmer/tracking/index.js +1 -1
  30. package/dist/dev/packages/@glimmer/validator/index.js +1 -1
  31. package/dist/dev/packages/ember/version.js +1 -1
  32. package/dist/dev/packages/shared-chunks/{alias-DpqL1qx6.js → alias-CT_thCad.js} +2 -2
  33. package/dist/dev/packages/shared-chunks/{api-C0PAtEgQ.js → api-Dz70AUL_.js} +6 -4
  34. package/dist/dev/packages/shared-chunks/{array-CVEnNWng.js → array-DvaweI_T.js} +1 -1
  35. package/dist/dev/packages/shared-chunks/{computed-BPCtuOxQ.js → computed-DGxbeUbf.js} +1 -6
  36. package/dist/dev/packages/shared-chunks/{index-CCyXUNBa.js → index-D1AjYv31.js} +3 -3
  37. package/dist/dev/packages/shared-chunks/{injected_property-CbBLr5jt.js → injected_property-DbXd6Gax.js} +1 -1
  38. package/dist/dev/packages/shared-chunks/{property_set-qCUylPEK.js → property_set-CVlVgdor.js} +1 -1
  39. package/dist/dev/packages/shared-chunks/{rehydrate-builder-C6k1XhET.js → rehydrate-builder-CsnkZkur.js} +1 -1
  40. package/dist/dev/packages/shared-chunks/{render-87_sKZ_k.js → render-CtH73XOv.js} +10 -5
  41. package/dist/dev/packages/shared-chunks/{serialize-builder-BlxBjwO-.js → serialize-builder-D1oAeiyl.js} +1 -1
  42. package/dist/dev/packages/shared-chunks/{set_properties-C4TSebH6.js → set_properties-CEUT_EJn.js} +2 -2
  43. package/dist/dev/packages/shared-chunks/{setup-registry-BHdDJATP.js → setup-registry-DQ3c4Juo.js} +6 -6
  44. package/dist/dev/packages/shared-chunks/{textarea-C4lYkaHj.js → textarea-DEvw4ezm.js} +1 -1
  45. package/dist/dev/packages/shared-chunks/tracked-57EW14Ny.js +253 -0
  46. package/dist/dev/packages/shared-chunks/tracked-value-DhyJmrhG.js +115 -0
  47. package/dist/prod/packages/@ember/-internals/glimmer/index.js +6 -6
  48. package/dist/prod/packages/@ember/-internals/metal/index.js +8 -8
  49. package/dist/prod/packages/@ember/-internals/runtime/lib/mixins/-proxy.js +2 -2
  50. package/dist/prod/packages/@ember/-internals/runtime/lib/mixins/target_action_support.js +1 -1
  51. package/dist/prod/packages/@ember/-internals/views/lib/system/event_dispatcher.js +1 -1
  52. package/dist/prod/packages/@ember/-internals/views/lib/views/core_view.js +1 -1
  53. package/dist/prod/packages/@ember/application/index.js +1 -1
  54. package/dist/prod/packages/@ember/application/instance.js +3 -3
  55. package/dist/prod/packages/@ember/array/index.js +3 -3
  56. package/dist/prod/packages/@ember/array/proxy.js +3 -3
  57. package/dist/prod/packages/@ember/component/index.js +2 -2
  58. package/dist/prod/packages/@ember/controller/index.js +2 -2
  59. package/dist/prod/packages/@ember/engine/index.js +2 -2
  60. package/dist/prod/packages/@ember/object/computed.js +2 -2
  61. package/dist/prod/packages/@ember/object/index.js +4 -4
  62. package/dist/prod/packages/@ember/object/lib/computed/computed_macros.js +3 -3
  63. package/dist/prod/packages/@ember/object/lib/computed/reduce_computed_macros.js +1 -1
  64. package/dist/prod/packages/@ember/object/mixin.js +1 -1
  65. package/dist/prod/packages/@ember/object/observable.js +3 -3
  66. package/dist/prod/packages/@ember/object/promise-proxy-mixin.js +2 -2
  67. package/dist/prod/packages/@ember/renderer/index.js +1 -1
  68. package/dist/prod/packages/@ember/routing/route.js +3 -3
  69. package/dist/prod/packages/@ember/routing/router.js +2 -2
  70. package/dist/prod/packages/@ember/service/index.js +1 -1
  71. package/dist/prod/packages/@glimmer/node/index.js +2 -2
  72. package/dist/prod/packages/@glimmer/runtime/index.js +3 -3
  73. package/dist/prod/packages/@glimmer/tracking/index.js +1 -1
  74. package/dist/prod/packages/@glimmer/validator/index.js +1 -1
  75. package/dist/prod/packages/ember/version.js +1 -1
  76. package/dist/prod/packages/shared-chunks/{alias-Bod6qdNp.js → alias-CHHuE0LE.js} +2 -2
  77. package/dist/prod/packages/shared-chunks/{api-CQexacBn.js → api-DzOa0Acr.js} +6 -4
  78. package/dist/prod/packages/shared-chunks/{array-BzReKMeW.js → array-CnXdmzOG.js} +1 -1
  79. package/dist/prod/packages/shared-chunks/{computed-DtIStxvq.js → computed-BNdMwGhH.js} +1 -6
  80. package/dist/prod/packages/shared-chunks/{index-npr2B-vu.js → index-CvQQ6l11.js} +3 -3
  81. package/dist/prod/packages/shared-chunks/{injected_property-Y-FadDej.js → injected_property-DqQ0XV7k.js} +1 -1
  82. package/dist/prod/packages/shared-chunks/{property_set-BaQJdVfS.js → property_set-CkLe4ht8.js} +1 -1
  83. package/dist/prod/packages/shared-chunks/{rehydrate-builder-Blt1x9MP.js → rehydrate-builder-n_8RCUj9.js} +1 -1
  84. package/dist/prod/packages/shared-chunks/{render-Dx7lr1hR.js → render-Bf7GviCY.js} +10 -5
  85. package/dist/prod/packages/shared-chunks/{serialize-builder-BvAXYHTr.js → serialize-builder-CsG9WHVw.js} +1 -1
  86. package/dist/prod/packages/shared-chunks/{set_properties-Qxhw4qzw.js → set_properties-Cs3rVemD.js} +2 -2
  87. package/dist/prod/packages/shared-chunks/{setup-registry-Dfu8EyLU.js → setup-registry-kOGgOucf.js} +6 -6
  88. package/dist/prod/packages/shared-chunks/{textarea-DOmZ1x0E.js → textarea-DMmdvgk2.js} +1 -1
  89. package/dist/prod/packages/shared-chunks/tracked-DvOpYI0o.js +235 -0
  90. package/dist/prod/packages/shared-chunks/tracked-value-CR6kx-73.js +115 -0
  91. package/docs/data.json +149 -10
  92. package/package.json +1 -2
  93. package/types/stable/@ember/-internals/glimmer/lib/glimmer-tracking-docs.d.ts +68 -0
  94. package/types/stable/@ember/-internals/metal/lib/tracked.d.ts +53 -6
  95. package/types/stable/@glimmer/tracking/index.d.ts +70 -1
  96. package/types/stable/@glimmer/validator/index.d.ts +1 -0
  97. package/types/stable/@glimmer/validator/lib/tracked-value.d.ts +58 -0
  98. package/types/stable/index.d.ts +1 -0
  99. package/dist/dev/packages/shared-chunks/tracked-DEyf0T_X.js +0 -148
  100. package/dist/dev/packages/shared-chunks/tracked-data-DgqqRdYO.js +0 -31
  101. package/dist/prod/packages/shared-chunks/tracked-B9380JtC.js +0 -132
  102. package/dist/prod/packages/shared-chunks/tracked-data-CHq42QHb.js +0 -31
@@ -0,0 +1,115 @@
1
+ import { d as dirtyTagFor, t as tagFor } from './meta-BJtIZDir.js';
2
+ import { c as consumeTag, b as createUpdatableTag, D as DIRTY_TAG } from './cache-CofLhaS4.js';
3
+
4
+ function trackedData(key, initializer) {
5
+ let values = new WeakMap();
6
+ let hasInitializer = typeof initializer === 'function';
7
+ function getter(self) {
8
+ consumeTag(tagFor(self, key));
9
+ let value;
10
+
11
+ // If the field has never been initialized, we should initialize it
12
+ if (hasInitializer && !values.has(self)) {
13
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion -- @fixme
14
+ value = initializer.call(self);
15
+ values.set(self, value);
16
+ } else {
17
+ value = values.get(self);
18
+ }
19
+ return value;
20
+ }
21
+ function setter(self, value) {
22
+ dirtyTagFor(self, key);
23
+ values.set(self, value);
24
+ }
25
+ return {
26
+ getter,
27
+ setter
28
+ };
29
+ }
30
+
31
+ /**
32
+ * A mutable reactive value.
33
+ *
34
+ * Reading `value` consumes the underlying tag (entangling with any active
35
+ * tracking frame), and writing `value` dirties it.
36
+ */
37
+
38
+ /**
39
+ * A reactive value that can only be read.
40
+ */
41
+
42
+ class TrackedValue {
43
+ #isFrozen = false;
44
+ #value;
45
+ #options;
46
+ #tag;
47
+ constructor(value, options) {
48
+ this.#value = value;
49
+ this.#options = options;
50
+ this.#tag = createUpdatableTag();
51
+ }
52
+
53
+ /**
54
+ * The underlying value.
55
+ *
56
+ * Reading entangles with the current tracking frame, and writing notifies
57
+ * consumers (unless the configured `equals` deems the new value equal to
58
+ * the current one).
59
+ */
60
+ get value() {
61
+ consumeTag(this.#tag);
62
+ return this.#value;
63
+ }
64
+ set value(value) {
65
+ this.set(value);
66
+ }
67
+
68
+ /**
69
+ * Function short-hand for reading `value`.
70
+ */
71
+ get = () => {
72
+ return this.value;
73
+ };
74
+
75
+ /**
76
+ * Function short-hand for assigning `value`.
77
+ *
78
+ * Returns `true` if the value changed (and consumers were notified),
79
+ * `false` if the new value was equal to the current one.
80
+ */
81
+ set = value => {
82
+ if (this.#isFrozen) {
83
+ throw new Error(`Cannot update a frozen TrackedValue${this.#options.description ? ` (\`${this.#options.description}\`)` : ''}`);
84
+ }
85
+ if (this.#options.equals(this.#value, value)) {
86
+ return false;
87
+ }
88
+ this.#value = value;
89
+ DIRTY_TAG(this.#tag);
90
+ return true;
91
+ };
92
+
93
+ /**
94
+ * Update the value based on the current value, without consuming it.
95
+ */
96
+ update = updater => {
97
+ this.set(updater(this.#value));
98
+ };
99
+
100
+ /**
101
+ * Prevents further updates, making the TrackedValue behave as a
102
+ * ReadOnlyReactive.
103
+ */
104
+ freeze = () => {
105
+ this.#isFrozen = true;
106
+ };
107
+ }
108
+ function trackedValue(value, options) {
109
+ return new TrackedValue(value, {
110
+ equals: options?.equals ?? Object.is,
111
+ description: options?.description
112
+ });
113
+ }
114
+
115
+ export { TrackedValue as T, trackedData as a, trackedValue as t };
package/docs/data.json CHANGED
@@ -3,7 +3,7 @@
3
3
  "name": "The Ember API",
4
4
  "description": "The Ember API: a framework for building ambitious web applications",
5
5
  "url": "https://emberjs.com/",
6
- "version": "7.3.0-alpha.1"
6
+ "version": "7.3.0-alpha.3"
7
7
  },
8
8
  "files": {
9
9
  "node_modules/rsvp/lib/rsvp/promise/all.js": {
@@ -2532,6 +2532,13 @@
2532
2532
  "fors": {},
2533
2533
  "namespaces": {}
2534
2534
  },
2535
+ "packages/@glimmer/validator/lib/tracked-value.ts": {
2536
+ "name": "packages/@glimmer/validator/lib/tracked-value.ts",
2537
+ "modules": {},
2538
+ "classes": {},
2539
+ "fors": {},
2540
+ "namespaces": {}
2541
+ },
2535
2542
  "packages/@glimmer/validator/lib/tracking.ts": {
2536
2543
  "name": "packages/@glimmer/validator/lib/tracking.ts",
2537
2544
  "modules": {},
@@ -2774,7 +2781,7 @@
2774
2781
  "namespaces": {},
2775
2782
  "tag": "module",
2776
2783
  "file": "packages/@glimmer/tracking/index.ts",
2777
- "line": 4,
2784
+ "line": 10,
2778
2785
  "description": "In order to tell Ember a value might change, we need to mark it as trackable.\nTrackable values are values that:\n\n- Can change over their component’s lifetime and\n- Should cause Ember to rerender if and when they change\n\nWe can do this by marking the field with the `@tracked` decorator.",
2779
2786
  "access": "public",
2780
2787
  "tagname": ""
@@ -7896,7 +7903,7 @@
7896
7903
  {
7897
7904
  "file": "packages/@ember/-internals/glimmer/lib/glimmer-tracking-docs.ts",
7898
7905
  "line": 22,
7899
- "description": "Marks a property as tracked. By default, values that are rendered in Ember app\ntemplates are _static_, meaning that updates to them won't cause the\napplication to rerender. Marking a property as tracked means that when that\nproperty changes, any templates that used that property, directly or\nindirectly, will rerender. For instance, consider this component:\n\n```gjs\nimport Component from '@glimmer/component';\nimport { tracked } from '@glimmer/tracking';\nimport { action } from '@ember/object';\n\nexport default class CounterComponent extends Component {\n @tracked count = 0;\n\n get timesTen() {\n return this.count * 10;\n }\n\n @action\n plusOne() {\n this.count += 1;\n }\n \n <template>\n <div>Count: {{this.count}}</div>\n <div>Times Ten: {{this.timesTen}}</div>\n <div>\n <button {{on \"click\" this.plusOne}}>\n Plus One\n </button>\n </div>\n </template>\n}\n```\n\nBoth the `{{this.count}}` and the `{{this.timesTen}}` properties in the\ntemplate will update whenever the button is clicked. Any tracked properties\nthat are used in any way to calculate a value that is used in the template\nwill cause a rerender when updated - this includes through method calls and\nother means:\n\n```gjs\nimport Component from '@glimmer/component';\nimport { tracked } from '@glimmer/tracking';\n\nclass Entry {\n @tracked name;\n @tracked phoneNumber;\n\n constructor(name, phoneNumber) {\n this.name = name;\n this.phoneNumber = phoneNumber;\n }\n}\n\nexport default class PhoneBookComponent extends Component {\n entries = [\n new Entry('Pizza Palace', 5551234),\n new Entry('1st Street Cleaners', 5554321),\n new Entry('Plants R Us', 5552468),\n ];\n\n // Any usage of this property will update whenever any of the names in the\n // entries arrays are updated\n get names() {\n return this.entries.map(e => e.name);\n }\n\n // Any usage of this property will update whenever any of the numbers in the\n // entries arrays are updated\n get numbers() {\n return this.getFormattedNumbers();\n }\n\n getFormattedNumbers() {\n return this.entries\n .map(e => e.phoneNumber)\n .map(number => {\n let numberString = '' + number;\n\n return numberString.slice(0, 3) + '-' + numberString.slice(3);\n });\n }\n}\n```\n\nIt's important to note that setting tracked properties will always trigger an\nupdate, even if the property is set to the same value as it was before.\n\n```js\nlet entry = new Entry('Pizza Palace', 5551234);\n\n// if entry was used when rendering, this would cause a rerender, even though\n// the name is being set to the same value as it was before\nentry.name = entry.name;\n```\n\n`tracked` can also be used with the classic Ember object model in a similar\nmanner to classic computed properties:\n\n```javascript\nimport EmberObject from '@ember/object';\nimport { tracked } from '@glimmer/tracking';\n\nconst Entry = EmberObject.extend({\n name: tracked(),\n phoneNumber: tracked()\n});\n```\n\nOften this is unnecessary, but to ensure robust auto-tracking behavior it is\nadvisable to mark tracked state appropriately wherever possible.\n\nThis form of `tracked` also accepts an optional configuration object\ncontaining either an initial `value` or an `initializer` function (but not\nboth).\n\n```javascript\nimport EmberObject from '@ember/object';\nimport { tracked } from '@glimmer/tracking';\n\nconst Entry = EmberObject.extend({\n name: tracked({ value: 'Zoey' }),\n favoriteSongs: tracked({\n initializer: () => ['Raspberry Beret', 'Time After Time']\n })\n});\n```",
7906
+ "description": "Marks a property as tracked. By default, values that are rendered in Ember app\ntemplates are _static_, meaning that updates to them won't cause the\napplication to rerender. Marking a property as tracked means that when that\nproperty changes, any templates that used that property, directly or\nindirectly, will rerender. For instance, consider this component:\n\n```gjs\nimport Component from '@glimmer/component';\nimport { tracked } from '@glimmer/tracking';\nimport { action } from '@ember/object';\n\nexport default class CounterComponent extends Component {\n @tracked count = 0;\n\n get timesTen() {\n return this.count * 10;\n }\n\n @action\n plusOne() {\n this.count += 1;\n }\n \n <template>\n <div>Count: {{this.count}}</div>\n <div>Times Ten: {{this.timesTen}}</div>\n <div>\n <button {{on \"click\" this.plusOne}}>\n Plus One\n </button>\n </div>\n </template>\n}\n```\n\nBoth the `{{this.count}}` and the `{{this.timesTen}}` properties in the\ntemplate will update whenever the button is clicked. Any tracked properties\nthat are used in any way to calculate a value that is used in the template\nwill cause a rerender when updated - this includes through method calls and\nother means:\n\n```gjs\nimport Component from '@glimmer/component';\nimport { tracked } from '@glimmer/tracking';\n\nclass Entry {\n @tracked name;\n @tracked phoneNumber;\n\n constructor(name, phoneNumber) {\n this.name = name;\n this.phoneNumber = phoneNumber;\n }\n}\n\nexport default class PhoneBookComponent extends Component {\n entries = [\n new Entry('Pizza Palace', 5551234),\n new Entry('1st Street Cleaners', 5554321),\n new Entry('Plants R Us', 5552468),\n ];\n\n // Any usage of this property will update whenever any of the names in the\n // entries arrays are updated\n get names() {\n return this.entries.map(e => e.name);\n }\n\n // Any usage of this property will update whenever any of the numbers in the\n // entries arrays are updated\n get numbers() {\n return this.getFormattedNumbers();\n }\n\n getFormattedNumbers() {\n return this.entries\n .map(e => e.phoneNumber)\n .map(number => {\n let numberString = '' + number;\n\n return numberString.slice(0, 3) + '-' + numberString.slice(3);\n });\n }\n}\n```\n\nIt's important to note that setting tracked properties will always trigger an\nupdate, even if the property is set to the same value as it was before.\n\n```js\nlet entry = new Entry('Pizza Palace', 5551234);\n\n// if entry was used when rendering, this would cause a rerender, even though\n// the name is being set to the same value as it was before\nentry.name = entry.name;\n```\n\n`tracked` can also be used with the classic Ember object model in a similar\nmanner to classic computed properties:\n\n```javascript\nimport EmberObject from '@ember/object';\nimport { tracked } from '@glimmer/tracking';\n\nconst Entry = EmberObject.extend({\n name: tracked(),\n phoneNumber: tracked()\n});\n```\n\nOften this is unnecessary, but to ensure robust auto-tracking behavior it is\nadvisable to mark tracked state appropriately wherever possible.\n\nThis form of `tracked` also accepts an optional configuration object\ncontaining either an initial `value` or an `initializer` function (but not\nboth).\n\n```javascript\nimport EmberObject from '@ember/object';\nimport { tracked } from '@glimmer/tracking';\n\nconst Entry = EmberObject.extend({\n name: tracked({ value: 'Zoey' }),\n favoriteSongs: tracked({\n initializer: () => ['Raspberry Beret', 'Time After Time']\n })\n});\n```\n\nCalling `tracked` with an initial value creates a standalone reactive\nvalue, usable outside of classes:\n\n```js\nimport { tracked } from '@glimmer/tracking';\n\nconst count = tracked(0);\n\ncount.value; // read the value, entangling with any tracking context\ncount.value = 1; // write the value, notifying consumers\ncount.get(); // function shorthand for reading\ncount.set(2); // function shorthand for writing\ncount.update((n) => n + 1); // write based on the current value, without entangling\ncount.freeze(); // prevent all future writes\n```\n\nReading `value` in a template (or in a getter used by a template) will\nrerender just like a `@tracked` property:\n\n```gjs\nimport { tracked } from '@glimmer/tracking';\nimport { on } from '@ember/modifier';\n\nconst count = tracked(0);\nconst increment = () => count.value++;\n\n<template>\n Count is: {{count.value}}\n\n <button {{on \"click\" increment}}>add one</button>\n</template>\n```\n\nThis form accepts an options object containing an `equals` function, which\ndecides whether a written value should notify consumers (it defaults to\n`Object.is`), and a `description` used for debugging:\n\n```js\nconst count = tracked(0, { equals: (a, b) => a === b });\n\ncount.value = 0; // does not notify consumers, the value did not change\n```\n\nNote: when `tracked` is called with a single plain object whose keys are all\ndrawn from `value`, `initializer`, `equals`, and `description`, it is treated\nas the configuration object for a decorator (or classic-class field), not as a\nstandalone value wrapping that object. To create a standalone reactive value\naround such an object, pass it as an initial value and include a (possibly\nempty) options argument: `tracked({ value: 5 }, {})`.\n\nThe `@tracked` decorator accepts the same options. By default, setting a\n`@tracked` property always notifies consumers, even when setting the\nproperty to the same value; passing `equals` opts in to equality-based\nnotification instead:\n\n```js\nimport { tracked } from '@glimmer/tracking';\n\nclass Counter {\n @tracked({ equals: (a, b) => a === b }) count = 0;\n\n noop = () => {\n // does not notify consumers, the value did not change\n this.count = this.count;\n };\n}\n```",
7900
7907
  "itemtype": "method",
7901
7908
  "name": "tracked",
7902
7909
  "static": 1,
@@ -7907,7 +7914,7 @@
7907
7914
  },
7908
7915
  {
7909
7916
  "file": "packages/@ember/-internals/glimmer/lib/glimmer-tracking-docs.ts",
7910
- "line": 158,
7917
+ "line": 226,
7911
7918
  "description": "Gives the getter a caching behavior. The return value of the getter\nwill be cached until any of the properties it is entangled with\nare invalidated. This is useful when a getter is expensive and\nused very often.\n\nFor instance, in this `GuestList` class, we have the `sortedGuests`\ngetter that sorts the guests alphabetically:\n\n```javascript\n import { tracked } from '@glimmer/tracking';\n\n class GuestList {\n @tracked guests = ['Zoey', 'Tomster'];\n\n get sortedGuests() {\n return this.guests.slice().sort()\n }\n }\n```\n\nEvery time `sortedGuests` is accessed, a new array will be created and sorted,\nbecause JavaScript getters do not cache by default. When the guest list\nis small, like the one in the example, this is not a problem. However, if\nthe guest list were to grow very large, it would mean that we would be doing\na large amount of work each time we accessed `sortedGuests`. With `@cached`,\nwe can cache the value instead:\n\n```javascript\n import { tracked, cached } from '@glimmer/tracking';\n\n class GuestList {\n @tracked guests = ['Zoey', 'Tomster'];\n\n @cached\n get sortedGuests() {\n return this.guests.slice().sort()\n }\n }\n```\n\nNow the `sortedGuests` getter will be cached based on autotracking.\nIt will only rerun and create a new sorted array when the guests tracked\nproperty is updated.\n\n\n### Tradeoffs\n\nOveruse is discouraged.\n\nIn general, you should avoid using `@cached` unless you have confirmed that\nthe getter you are decorating is computationally expensive, since `@cached`\nadds a small amount of overhead to the getter.\nWhile the individual costs are small, a systematic use of the `@cached`\ndecorator can add up to a large impact overall in your app.\nMany getters and tracked properties are only accessed once during rendering,\nand then never rerendered, so adding `@cached` when unnecessary can\nnegatively impact performance.\n\nAlso, `@cached` may rerun even if the values themselves have not changed,\nsince tracked properties will always invalidate.\nFor example updating an integer value from `5` to an other `5` will trigger\na rerun of the cached properties building from this integer.\n\nAvoiding a cache invalidation in this case is not something that can\nbe achieved on the `@cached` decorator itself, but rather when updating\nthe underlying tracked values, by applying some diff checking mechanisms:\n\n```javascript\nif (nextValue !== this.trackedProp) {\n this.trackedProp = nextValue;\n}\n```\n\nHere equal values won't update the property, therefore not triggering\nthe subsequent cache invalidations of the `@cached` properties who were\nusing this `trackedProp`.\n\nRemember that setting tracked data should only be done during initialization,\nor as the result of a user action. Setting tracked data during render\n(such as in a getter), is not supported.",
7912
7919
  "itemtype": "method",
7913
7920
  "name": "cached",
@@ -9157,7 +9164,7 @@
9157
9164
  },
9158
9165
  {
9159
9166
  "file": "packages/@ember/-internals/metal/lib/tracked.ts",
9160
- "line": 14,
9167
+ "line": 15,
9161
9168
  "decorator": "",
9162
9169
  "access": "private",
9163
9170
  "tagname": "Marks a property as tracked.\n\nBy default, a component's properties are expected to be static,\nmeaning you are not able to update them and have the template update accordingly.\nMarking a property as tracked means that when that property changes,\na rerender of the component is scheduled so the template is kept up to date.\n\nThere are two usages for the `@tracked` decorator, shown below.",
@@ -9174,6 +9181,41 @@
9174
9181
  "class": "@ember/owner",
9175
9182
  "module": "@ember/object"
9176
9183
  },
9184
+ {
9185
+ "file": "packages/@ember/-internals/metal/lib/tracked.ts",
9186
+ "line": 77,
9187
+ "description": "Reactivity options for the standalone `tracked(value, options)` form.\n\n- `equals` decides whether writing a value notifies consumers; it defaults to\n `Object.is`.\n- `description` is used in development for debugging.\n\n`equals` is a function-typed property (rather than method syntax) on purpose:\nthis keeps its parameters checked strictly, so passing an `equals` typed for\nthe wrong value type is a type error instead of being silently accepted.",
9188
+ "class": "@ember/owner",
9189
+ "module": "@ember/object"
9190
+ },
9191
+ {
9192
+ "file": "packages/@ember/-internals/metal/lib/tracked.ts",
9193
+ "line": 93,
9194
+ "description": "Options for `tracked` used as a decorator, or as a field on a *classic* class\n(`EmberObject.extend({ foo: tracked({ value }) })`).\n\nAll properties are optional because this single shape backs several usages:\nclassic-field defaults (`tracked({ value })` / `tracked({ initializer })`) and\noptions-only native decorators (`@tracked({ equals })`). The mutually\nexclusive combinations (e.g. both `value` and `initializer`) and the\nclassic-only restriction on `value`/`initializer` are enforced at runtime via\nassertions rather than in the type, matching the runtime `isDecoratorOptions`\ncheck that accepts any object composed of these keys.\n\n- `value` / `initializer` supply a default value and are only valid on classic\n classes; native classes use class field initializers instead.\n- `equals` / `description` configure reactivity, mirroring\n {@link TrackedValueOptions}.",
9195
+ "class": "@ember/owner",
9196
+ "module": "@ember/object"
9197
+ },
9198
+ {
9199
+ "file": "packages/@ember/-internals/metal/lib/tracked.ts",
9200
+ "line": 124,
9201
+ "description": "`tracked` as a decorator factory: `@tracked({ equals })`, or on classic\nclasses `tracked({ value })` / `tracked({ initializer })`.",
9202
+ "class": "@ember/owner",
9203
+ "module": "@ember/object"
9204
+ },
9205
+ {
9206
+ "file": "packages/@ember/-internals/metal/lib/tracked.ts",
9207
+ "line": 129,
9208
+ "description": "`tracked` as a bare decorator: `@tracked foo = 1`.",
9209
+ "class": "@ember/owner",
9210
+ "module": "@ember/object"
9211
+ },
9212
+ {
9213
+ "file": "packages/@ember/-internals/metal/lib/tracked.ts",
9214
+ "line": 138,
9215
+ "description": "`tracked` as a standalone reactive value, usable outside of classes:\n`const count = tracked(0)`.",
9216
+ "class": "@ember/owner",
9217
+ "module": "@ember/object"
9218
+ },
9177
9219
  {
9178
9220
  "file": "packages/@ember/-internals/owner/index.ts",
9179
9221
  "line": 24,
@@ -24289,8 +24331,8 @@
24289
24331
  },
24290
24332
  {
24291
24333
  "file": "packages/@glimmer/tracking/index.ts",
24292
- "line": 17,
24293
- "description": "Marks a property as tracked. By default, values that are rendered in Ember app\ntemplates are _static_, meaning that updates to them won't cause the\napplication to rerender. Marking a property as tracked means that when that\nproperty changes, any templates that used that property, directly or\nindirectly, will rerender. For instance, consider this component:\n\n```gjs\nimport Component from '@glimmer/component';\nimport { tracked } from '@glimmer/tracking';\nimport { action } from '@ember/object';\n\nexport default class CounterComponent extends Component {\n @tracked count = 0;\n\n get timesTen() {\n return this.count * 10;\n }\n\n @action\n plusOne() {\n this.count += 1;\n }\n \n <template>\n <div>Count: {{this.count}}</div>\n <div>Times Ten: {{this.timesTen}}</div>\n <div>\n <button {{on \"click\" this.plusOne}}>\n Plus One\n </button>\n </div>\n </template>\n}\n```\n\nBoth the `{{this.count}}` and the `{{this.timesTen}}` properties in the\ntemplate will update whenever the button is clicked. Any tracked properties\nthat are used in any way to calculate a value that is used in the template\nwill cause a rerender when updated - this includes through method calls and\nother means:\n\n```gjs\nimport Component from '@glimmer/component';\nimport { tracked } from '@glimmer/tracking';\n\nclass Entry {\n @tracked name;\n @tracked phoneNumber;\n\n constructor(name, phoneNumber) {\n this.name = name;\n this.phoneNumber = phoneNumber;\n }\n}\n\nexport default class PhoneBookComponent extends Component {\n entries = [\n new Entry('Pizza Palace', 5551234),\n new Entry('1st Street Cleaners', 5554321),\n new Entry('Plants R Us', 5552468),\n ];\n\n // Any usage of this property will update whenever any of the names in the\n // entries arrays are updated\n get names() {\n return this.entries.map(e => e.name);\n }\n\n // Any usage of this property will update whenever any of the numbers in the\n // entries arrays are updated\n get numbers() {\n return this.getFormattedNumbers();\n }\n\n getFormattedNumbers() {\n return this.entries\n .map(e => e.phoneNumber)\n .map(number => {\n let numberString = '' + number;\n\n return numberString.slice(0, 3) + '-' + numberString.slice(3);\n });\n }\n}\n```\n\nIt's important to note that setting tracked properties will always trigger an\nupdate, even if the property is set to the same value as it was before.\n\n```js\nlet entry = new Entry('Pizza Palace', 5551234);\n// if entry was used when rendering, this would cause a rerender, even though\n// the name is being set to the same value as it was before\nentry.name = entry.name;\n```\n\n`tracked` can also be used with the classic Ember object model in a similar\nmanner to classic computed properties:\n\n```javascript\nimport EmberObject from '@ember/object';\nimport { tracked } from '@glimmer/tracking';\n\nconst Entry = EmberObject.extend({\n name: tracked(),\n phoneNumber: tracked()\n});\n```\n\nOften this is unnecessary, but to ensure robust auto-tracking behavior it is\nadvisable to mark tracked state appropriately wherever possible.\nThis form of `tracked` also accepts an optional configuration object\ncontaining either an initial `value` or an `initializer` function (but not\nboth).\n\n```javascript\nimport EmberObject from '@ember/object';\nimport { tracked } from '@glimmer/tracking';\n\nconst Entry = EmberObject.extend({\n name: tracked({ value: 'Zoey' }),\n favoriteSongs: tracked({\n initializer: () => ['Raspberry Beret', 'Time After Time']\n })\n});\n```",
24334
+ "line": 23,
24335
+ "description": "Marks a property as tracked. By default, values that are rendered in Ember app\ntemplates are _static_, meaning that updates to them won't cause the\napplication to rerender. Marking a property as tracked means that when that\nproperty changes, any templates that used that property, directly or\nindirectly, will rerender. For instance, consider this component:\n\n```gjs\nimport Component from '@glimmer/component';\nimport { tracked } from '@glimmer/tracking';\nimport { action } from '@ember/object';\n\nexport default class CounterComponent extends Component {\n @tracked count = 0;\n\n get timesTen() {\n return this.count * 10;\n }\n\n @action\n plusOne() {\n this.count += 1;\n }\n\n <template>\n <div>Count: {{this.count}}</div>\n <div>Times Ten: {{this.timesTen}}</div>\n <div>\n <button {{on \"click\" this.plusOne}}>\n Plus One\n </button>\n </div>\n </template>\n}\n```\n\nBoth the `{{this.count}}` and the `{{this.timesTen}}` properties in the\ntemplate will update whenever the button is clicked. Any tracked properties\nthat are used in any way to calculate a value that is used in the template\nwill cause a rerender when updated - this includes through method calls and\nother means:\n\n```gjs\nimport Component from '@glimmer/component';\nimport { tracked } from '@glimmer/tracking';\n\nclass Entry {\n @tracked name;\n @tracked phoneNumber;\n\n constructor(name, phoneNumber) {\n this.name = name;\n this.phoneNumber = phoneNumber;\n }\n}\n\nexport default class PhoneBookComponent extends Component {\n entries = [\n new Entry('Pizza Palace', 5551234),\n new Entry('1st Street Cleaners', 5554321),\n new Entry('Plants R Us', 5552468),\n ];\n\n // Any usage of this property will update whenever any of the names in the\n // entries arrays are updated\n get names() {\n return this.entries.map(e => e.name);\n }\n\n // Any usage of this property will update whenever any of the numbers in the\n // entries arrays are updated\n get numbers() {\n return this.getFormattedNumbers();\n }\n\n getFormattedNumbers() {\n return this.entries\n .map(e => e.phoneNumber)\n .map(number => {\n let numberString = '' + number;\n\n return numberString.slice(0, 3) + '-' + numberString.slice(3);\n });\n }\n}\n```\n\nIt's important to note that setting tracked properties will always trigger an\nupdate, even if the property is set to the same value as it was before.\n\n```js\nlet entry = new Entry('Pizza Palace', 5551234);\n// if entry was used when rendering, this would cause a rerender, even though\n// the name is being set to the same value as it was before\nentry.name = entry.name;\n```\n\n`tracked` can also be used with the classic Ember object model in a similar\nmanner to classic computed properties:\n\n```javascript\nimport EmberObject from '@ember/object';\nimport { tracked } from '@glimmer/tracking';\n\nconst Entry = EmberObject.extend({\n name: tracked(),\n phoneNumber: tracked()\n});\n```\n\nOften this is unnecessary, but to ensure robust auto-tracking behavior it is\nadvisable to mark tracked state appropriately wherever possible.\nThis form of `tracked` also accepts an optional configuration object\ncontaining either an initial `value` or an `initializer` function (but not\nboth).\n\n```javascript\nimport EmberObject from '@ember/object';\nimport { tracked } from '@glimmer/tracking';\n\nconst Entry = EmberObject.extend({\n name: tracked({ value: 'Zoey' }),\n favoriteSongs: tracked({\n initializer: () => ['Raspberry Beret', 'Time After Time']\n })\n});\n```\n\nCalling `tracked` with an initial value creates a standalone reactive\nvalue, usable outside of classes:\n\n```js\nimport { tracked } from '@glimmer/tracking';\n\nconst count = tracked(0);\n\ncount.value; // read the value, entangling with any tracking context\ncount.value = 1; // write the value, notifying consumers\ncount.get(); // function shorthand for reading\ncount.set(2); // function shorthand for writing\ncount.update((n) => n + 1); // write based on the current value, without entangling\ncount.freeze(); // prevent all future writes\n```\n\nReading `value` in a template (or in a getter used by a template) will\nrerender just like a `@tracked` property:\n\n```gjs\nimport { tracked } from '@glimmer/tracking';\nimport { on } from '@ember/modifier';\n\nconst count = tracked(0);\nconst increment = () => count.value++;\n\n<template>\n Count is: {{count.value}}\n\n <button {{on \"click\" increment}}>add one</button>\n</template>\n```\n\nThis form accepts an options object containing an `equals` function, which\ndecides whether a written value should notify consumers (it defaults to\n`Object.is`), and a `description` used for debugging:\n\n```js\nconst count = tracked(0, { equals: (a, b) => a === b });\n\ncount.value = 0; // does not notify consumers, the value did not change\n```\n\nNote: when `tracked` is called with a single plain object whose keys are all\ndrawn from `value`, `initializer`, `equals`, and `description`, it is treated\nas the configuration object for a decorator (or classic-class field), not as a\nstandalone value wrapping that object. To create a standalone reactive value\naround such an object, pass it as an initial value and include a (possibly\nempty) options argument: `tracked({ value: 5 }, {})`.\n\nThe `@tracked` decorator accepts the same options. By default, setting a\n`@tracked` property always notifies consumers, even when setting the\nproperty to the same value; passing `equals` opts in to equality-based\nnotification instead:\n\n```js\nimport { tracked } from '@glimmer/tracking';\n\nclass Counter {\n @tracked({ equals: (a, b) => a === b }) count = 0;\n\n noop = () => {\n // does not notify consumers, the value did not change\n this.count = this.count;\n };\n}\n```",
24294
24336
  "itemtype": "method",
24295
24337
  "name": "tracked",
24296
24338
  "static": 1,
@@ -24301,7 +24343,7 @@
24301
24343
  },
24302
24344
  {
24303
24345
  "file": "packages/@glimmer/tracking/index.ts",
24304
- "line": 151,
24346
+ "line": 225,
24305
24347
  "description": "The `@cached` decorator can be used on getters in order to cache the return\nvalue of the getter. This is useful when a getter is expensive and used very\noften. For instance, in this guest list class, we have the `sortedGuests`\ngetter that sorts the guests alphabetically:\n\n```js\nimport { tracked } from '@glimmer/tracking';\n\nclass GuestList {\n @tracked guests = ['Zoey', 'Tomster'];\n\n get sortedGuests() {\n return this.guests.slice().sort()\n }\n}\n```\n\nEvery time `sortedGuests` is accessed, a new array will be created and sorted,\nbecause JavaScript getters do not cache by default. When the guest list is\nsmall, like the one in the example, this is not a problem. However, if the guest\nlist were to grow very large, it would mean that we would be doing a large\namount of work each time we accessed `sortedGetters`. With `@cached`, we can\ncache the value instead:\n\n```js\nimport { tracked, cached } from '@glimmer/tracking';\n\nclass GuestList {\n @tracked guests = ['Zoey', 'Tomster'];\n\n @cached\n get sortedGuests() {\n return this.guests.slice().sort()\n }\n}\n```\n\nNow the `sortedGuests` getter will be cached based on _autotracking_. It will\nonly rerun and create a new sorted array when the `guests` tracked property is\nupdated.\n\nIn general, you should avoid using `@cached` unless you have confirmed that the\ngetter you are decorating is computationally expensive. `@cached` adds a small\namount of overhead to the getter, making it more expensive. While this overhead\nis small, if `@cached` is overused it can add up to a large impact overall in\nyour app. Many getters and tracked properties are only accessed once, rendered,\nand then never rerendered, so adding `@cached` when it is unnecessary can\nnegatively impact performance.",
24306
24348
  "itemtype": "method",
24307
24349
  "name": "cached",
@@ -24415,6 +24457,55 @@
24415
24457
  "class": "TestAdapter",
24416
24458
  "module": "@glimmer/tracking"
24417
24459
  },
24460
+ {
24461
+ "file": "packages/@glimmer/validator/lib/tracked-value.ts",
24462
+ "line": 8,
24463
+ "description": "A mutable reactive value.\n\nReading `value` consumes the underlying tag (entangling with any active\ntracking frame), and writing `value` dirties it.",
24464
+ "class": "TestAdapter",
24465
+ "module": "@glimmer/tracking"
24466
+ },
24467
+ {
24468
+ "file": "packages/@glimmer/validator/lib/tracked-value.ts",
24469
+ "line": 18,
24470
+ "description": "A reactive value that can only be read.",
24471
+ "class": "TestAdapter",
24472
+ "module": "@glimmer/tracking"
24473
+ },
24474
+ {
24475
+ "file": "packages/@glimmer/validator/lib/tracked-value.ts",
24476
+ "line": 37,
24477
+ "description": "The underlying value.\n\nReading entangles with the current tracking frame, and writing notifies\nconsumers (unless the configured `equals` deems the new value equal to\nthe current one).",
24478
+ "class": "TestAdapter",
24479
+ "module": "@glimmer/tracking"
24480
+ },
24481
+ {
24482
+ "file": "packages/@glimmer/validator/lib/tracked-value.ts",
24483
+ "line": 54,
24484
+ "description": "Function short-hand for reading `value`.",
24485
+ "class": "TestAdapter",
24486
+ "module": "@glimmer/tracking"
24487
+ },
24488
+ {
24489
+ "file": "packages/@glimmer/validator/lib/tracked-value.ts",
24490
+ "line": 61,
24491
+ "description": "Function short-hand for assigning `value`.\n\nReturns `true` if the value changed (and consumers were notified),\n`false` if the new value was equal to the current one.",
24492
+ "class": "TestAdapter",
24493
+ "module": "@glimmer/tracking"
24494
+ },
24495
+ {
24496
+ "file": "packages/@glimmer/validator/lib/tracked-value.ts",
24497
+ "line": 87,
24498
+ "description": "Update the value based on the current value, without consuming it.",
24499
+ "class": "TestAdapter",
24500
+ "module": "@glimmer/tracking"
24501
+ },
24502
+ {
24503
+ "file": "packages/@glimmer/validator/lib/tracked-value.ts",
24504
+ "line": 94,
24505
+ "description": "Prevents further updates, making the TrackedValue behave as a\nReadOnlyReactive.",
24506
+ "class": "TestAdapter",
24507
+ "module": "@glimmer/tracking"
24508
+ },
24418
24509
  {
24419
24510
  "file": "packages/@glimmer/validator/lib/tracking.ts",
24420
24511
  "line": 10,
@@ -24598,7 +24689,7 @@
24598
24689
  },
24599
24690
  {
24600
24691
  "message": "unknown tag: decorator",
24601
- "line": " packages/@ember/-internals/metal/lib/tracked.ts:14"
24692
+ "line": " packages/@ember/-internals/metal/lib/tracked.ts:15"
24602
24693
  },
24603
24694
  {
24604
24695
  "message": "unknown tag: internal",
@@ -25110,7 +25201,27 @@
25110
25201
  },
25111
25202
  {
25112
25203
  "message": "Missing item type",
25113
- "line": " packages/@ember/-internals/metal/lib/tracked.ts:14"
25204
+ "line": " packages/@ember/-internals/metal/lib/tracked.ts:15"
25205
+ },
25206
+ {
25207
+ "message": "Missing item type\nReactivity options for the standalone `tracked(value, options)` form.\n\n- `equals` decides whether writing a value notifies consumers; it defaults to\n `Object.is`.\n- `description` is used in development for debugging.\n\n`equals` is a function-typed property (rather than method syntax) on purpose:\nthis keeps its parameters checked strictly, so passing an `equals` typed for\nthe wrong value type is a type error instead of being silently accepted.",
25208
+ "line": " packages/@ember/-internals/metal/lib/tracked.ts:77"
25209
+ },
25210
+ {
25211
+ "message": "Missing item type\nOptions for `tracked` used as a decorator, or as a field on a *classic* class\n(`EmberObject.extend({ foo: tracked({ value }) })`).\n\nAll properties are optional because this single shape backs several usages:\nclassic-field defaults (`tracked({ value })` / `tracked({ initializer })`) and\noptions-only native decorators (`@tracked({ equals })`). The mutually\nexclusive combinations (e.g. both `value` and `initializer`) and the\nclassic-only restriction on `value`/`initializer` are enforced at runtime via\nassertions rather than in the type, matching the runtime `isDecoratorOptions`\ncheck that accepts any object composed of these keys.\n\n- `value` / `initializer` supply a default value and are only valid on classic\n classes; native classes use class field initializers instead.\n- `equals` / `description` configure reactivity, mirroring\n {@link TrackedValueOptions}.",
25212
+ "line": " packages/@ember/-internals/metal/lib/tracked.ts:93"
25213
+ },
25214
+ {
25215
+ "message": "Missing item type\n`tracked` as a decorator factory: `@tracked({ equals })`, or on classic\nclasses `tracked({ value })` / `tracked({ initializer })`.",
25216
+ "line": " packages/@ember/-internals/metal/lib/tracked.ts:124"
25217
+ },
25218
+ {
25219
+ "message": "Missing item type\n`tracked` as a bare decorator: `@tracked foo = 1`.",
25220
+ "line": " packages/@ember/-internals/metal/lib/tracked.ts:129"
25221
+ },
25222
+ {
25223
+ "message": "Missing item type\n`tracked` as a standalone reactive value, usable outside of classes:\n`const count = tracked(0)`.",
25224
+ "line": " packages/@ember/-internals/metal/lib/tracked.ts:138"
25114
25225
  },
25115
25226
  {
25116
25227
  "message": "Missing item type\nA type registry for the DI system, which other participants in the DI system\ncan register themselves into with declaration merging. The contract for this\ntype is that its keys are the `Type` from a `FullName`, and each value for a\n`Type` is another registry whose keys are the `Name` from a `FullName`. The\nmechanic for providing a registry is [declaration merging][handbook].\n\n[handbook]: https://www.typescriptlang.org/docs/handbook/declaration-merging.html\n\nFor example, Ember's `@ember/service` module includes this set of definitions:\n\n```ts\nexport default class Service extends EmberObject {}\n\n// For concrete singleton classes to be merged into.\ninterface Registry extends Record<string, Service> {}\n\ndeclare module '@ember/owner' {\n service: Registry;\n}\n```\n\nDeclarations of services can then include the registry:\n\n```ts\nimport Service from '@ember/service';\n\nexport default class Session extends Service {\n login(username: string, password: string) {\n // ...\n }\n}\n\ndeclare module '@ember/service' {\n interface Registry {\n session: Session;\n }\n}\n```\n\nThen users of the `Owner` API will be able to do things like this with strong\ntype safety guarantees:\n\n```ts\ngetOwner(this)?.lookup('service:session').login(\"hello\", \"1234abcd\");\n```",
@@ -27540,6 +27651,34 @@
27540
27651
  "message": "Missing item type\nCreates a global autotracking transaction. This will prevent any backflow\nin any `track` calls within the transaction, even if they are not\nexternally consumed.\n\n`runInAutotrackingTransaction` can be called within itself, and it will add\nonto the existing transaction if one exists.\n\nTODO: Only throw an error if the `track` is consumed.",
27541
27652
  "line": " packages/@glimmer/validator/lib/debug.ts:104"
27542
27653
  },
27654
+ {
27655
+ "message": "Missing item type\nA mutable reactive value.\n\nReading `value` consumes the underlying tag (entangling with any active\ntracking frame), and writing `value` dirties it.",
27656
+ "line": " packages/@glimmer/validator/lib/tracked-value.ts:8"
27657
+ },
27658
+ {
27659
+ "message": "Missing item type\nA reactive value that can only be read.",
27660
+ "line": " packages/@glimmer/validator/lib/tracked-value.ts:18"
27661
+ },
27662
+ {
27663
+ "message": "Missing item type\nThe underlying value.\n\nReading entangles with the current tracking frame, and writing notifies\nconsumers (unless the configured `equals` deems the new value equal to\nthe current one).",
27664
+ "line": " packages/@glimmer/validator/lib/tracked-value.ts:37"
27665
+ },
27666
+ {
27667
+ "message": "Missing item type\nFunction short-hand for reading `value`.",
27668
+ "line": " packages/@glimmer/validator/lib/tracked-value.ts:54"
27669
+ },
27670
+ {
27671
+ "message": "Missing item type\nFunction short-hand for assigning `value`.\n\nReturns `true` if the value changed (and consumers were notified),\n`false` if the new value was equal to the current one.",
27672
+ "line": " packages/@glimmer/validator/lib/tracked-value.ts:61"
27673
+ },
27674
+ {
27675
+ "message": "Missing item type\nUpdate the value based on the current value, without consuming it.",
27676
+ "line": " packages/@glimmer/validator/lib/tracked-value.ts:87"
27677
+ },
27678
+ {
27679
+ "message": "Missing item type\nPrevents further updates, making the TrackedValue behave as a\nReadOnlyReactive.",
27680
+ "line": " packages/@glimmer/validator/lib/tracked-value.ts:94"
27681
+ },
27543
27682
  {
27544
27683
  "message": "Missing item type\nAn object that that tracks @tracked properties that were consumed.",
27545
27684
  "line": " packages/@glimmer/validator/lib/tracking.ts:10"
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ember-source",
3
- "version": "7.3.0-alpha.1",
3
+ "version": "7.3.0-alpha.3",
4
4
  "description": "A JavaScript framework for creating ambitious web applications",
5
5
  "type": "module",
6
6
  "keywords": [
@@ -69,7 +69,6 @@
69
69
  "backburner.js": "^2.8.0",
70
70
  "broccoli-file-creator": "^2.1.1",
71
71
  "chalk": "^4.0.0",
72
- "ember-cli-babel": "^8.3.1",
73
72
  "ember-cli-get-component-path-option": "^1.0.0",
74
73
  "ember-cli-normalize-entity-name": "^1.0.0",
75
74
  "ember-cli-path-utils": "^1.0.0",
@@ -149,6 +149,74 @@ declare module '@ember/-internals/glimmer/lib/glimmer-tracking-docs' {
149
149
  });
150
150
  ```
151
151
 
152
+ Calling `tracked` with an initial value creates a standalone reactive
153
+ value, usable outside of classes:
154
+
155
+ ```js
156
+ import { tracked } from '@glimmer/tracking';
157
+
158
+ const count = tracked(0);
159
+
160
+ count.value; // read the value, entangling with any tracking context
161
+ count.value = 1; // write the value, notifying consumers
162
+ count.get(); // function shorthand for reading
163
+ count.set(2); // function shorthand for writing
164
+ count.update((n) => n + 1); // write based on the current value, without entangling
165
+ count.freeze(); // prevent all future writes
166
+ ```
167
+
168
+ Reading `value` in a template (or in a getter used by a template) will
169
+ rerender just like a `@tracked` property:
170
+
171
+ ```gjs
172
+ import { tracked } from '@glimmer/tracking';
173
+ import { on } from '@ember/modifier';
174
+
175
+ const count = tracked(0);
176
+ const increment = () => count.value++;
177
+
178
+ <template>
179
+ Count is: {{count.value}}
180
+
181
+ <button {{on "click" increment}}>add one</button>
182
+ </template>
183
+ ```
184
+
185
+ This form accepts an options object containing an `equals` function, which
186
+ decides whether a written value should notify consumers (it defaults to
187
+ `Object.is`), and a `description` used for debugging:
188
+
189
+ ```js
190
+ const count = tracked(0, { equals: (a, b) => a === b });
191
+
192
+ count.value = 0; // does not notify consumers, the value did not change
193
+ ```
194
+
195
+ Note: when `tracked` is called with a single plain object whose keys are all
196
+ drawn from `value`, `initializer`, `equals`, and `description`, it is treated
197
+ as the configuration object for a decorator (or classic-class field), not as a
198
+ standalone value wrapping that object. To create a standalone reactive value
199
+ around such an object, pass it as an initial value and include a (possibly
200
+ empty) options argument: `tracked({ value: 5 }, {})`.
201
+
202
+ The `@tracked` decorator accepts the same options. By default, setting a
203
+ `@tracked` property always notifies consumers, even when setting the
204
+ property to the same value; passing `equals` opts in to equality-based
205
+ notification instead:
206
+
207
+ ```js
208
+ import { tracked } from '@glimmer/tracking';
209
+
210
+ class Counter {
211
+ @tracked({ equals: (a, b) => a === b }) count = 0;
212
+
213
+ noop = () => {
214
+ // does not notify consumers, the value did not change
215
+ this.count = this.count;
216
+ };
217
+ }
218
+ ```
219
+
152
220
  @method tracked
153
221
  @static
154
222
  @for @glimmer/tracking
@@ -1,4 +1,5 @@
1
1
  declare module '@ember/-internals/metal/lib/tracked' {
2
+ import { type TrackedValue } from "@glimmer/validator/lib/tracked-value";
2
3
  import type { ExtendedMethodDecorator, DecoratorPropertyDescriptor } from "@ember/-internals/metal/lib/decorator";
3
4
  /**
4
5
  @decorator
@@ -62,14 +63,59 @@ declare module '@ember/-internals/metal/lib/tracked' {
62
63
 
63
64
  @param dependencies Optional dependents to be tracked.
64
65
  */
65
- export function tracked(
66
- propertyDesc: {
67
- value: any;
68
- initializer: () => any;
69
- }
70
- ): ExtendedMethodDecorator;
66
+ /**
67
+ * Reactivity options for the standalone `tracked(value, options)` form.
68
+ *
69
+ * - `equals` decides whether writing a value notifies consumers; it defaults to
70
+ * `Object.is`.
71
+ * - `description` is used in development for debugging.
72
+ *
73
+ * `equals` is a function-typed property (rather than method syntax) on purpose:
74
+ * this keeps its parameters checked strictly, so passing an `equals` typed for
75
+ * the wrong value type is a type error instead of being silently accepted.
76
+ */
77
+ interface TrackedValueOptions<Value> {
78
+ equals?: (a: Value, b: Value) => boolean;
79
+ description?: string;
80
+ }
81
+ /**
82
+ * Options for `tracked` used as a decorator, or as a field on a *classic* class
83
+ * (`EmberObject.extend({ foo: tracked({ value }) })`).
84
+ *
85
+ * All properties are optional because this single shape backs several usages:
86
+ * classic-field defaults (`tracked({ value })` / `tracked({ initializer })`) and
87
+ * options-only native decorators (`@tracked({ equals })`). The mutually
88
+ * exclusive combinations (e.g. both `value` and `initializer`) and the
89
+ * classic-only restriction on `value`/`initializer` are enforced at runtime via
90
+ * assertions rather than in the type, matching the runtime `isDecoratorOptions`
91
+ * check that accepts any object composed of these keys.
92
+ *
93
+ * - `value` / `initializer` supply a default value and are only valid on classic
94
+ * classes; native classes use class field initializers instead.
95
+ * - `equals` / `description` configure reactivity, mirroring
96
+ * {@link TrackedValueOptions}.
97
+ */
98
+ interface TrackedDecoratorOptions {
99
+ value?: any;
100
+ initializer?: () => any;
101
+ equals?(a: any, b: any): boolean;
102
+ description?: string;
103
+ }
104
+ /**
105
+ * `tracked` as a decorator factory: `@tracked({ equals })`, or on classic
106
+ * classes `tracked({ value })` / `tracked({ initializer })`.
107
+ */
108
+ export function tracked(propertyDesc: TrackedDecoratorOptions): ExtendedMethodDecorator;
109
+ /**
110
+ * `tracked` as a bare decorator: `@tracked foo = 1`.
111
+ */
71
112
  export function tracked(target: object, key: string): void;
72
113
  export function tracked(target: object, key: string, desc: DecoratorPropertyDescriptor): DecoratorPropertyDescriptor;
114
+ /**
115
+ * `tracked` as a standalone reactive value, usable outside of classes:
116
+ * `const count = tracked(0)`.
117
+ */
118
+ export function tracked<Value>(initialValue: Value, options?: TrackedValueOptions<Value>): TrackedValue<Value>;
73
119
  export class TrackedDescriptor {
74
120
  private _get;
75
121
  private _set;
@@ -77,4 +123,5 @@ declare module '@ember/-internals/metal/lib/tracked' {
77
123
  get(obj: object): unknown;
78
124
  set(obj: object, _key: string, value: unknown): void;
79
125
  }
126
+ export {};
80
127
  }