ember-source 5.6.0-alpha.2 → 5.6.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.
- package/build-metadata.json +3 -3
- package/dist/dependencies/@glimmer/debug.js +1533 -0
- package/dist/dependencies/@glimmer/destroyable.js +30 -59
- package/dist/dependencies/@glimmer/encoder.js +13 -24
- package/dist/dependencies/@glimmer/global-context.js +38 -41
- package/dist/dependencies/@glimmer/manager.js +144 -326
- package/dist/dependencies/@glimmer/node.js +14 -46
- package/dist/dependencies/@glimmer/opcode-compiler.js +1673 -2478
- package/dist/dependencies/@glimmer/owner.js +2 -5
- package/dist/dependencies/@glimmer/program.js +102 -185
- package/dist/dependencies/@glimmer/reference.js +58 -126
- package/dist/dependencies/@glimmer/runtime.js +4674 -5639
- package/dist/dependencies/@glimmer/util.js +340 -326
- package/dist/dependencies/@glimmer/validator.js +160 -217
- package/dist/dependencies/@glimmer/vm.js +174 -23
- package/dist/dependencies/@glimmer/wire-format.js +91 -34
- package/dist/dependencies/@simple-dom/document.js +1 -1
- package/dist/dependencies/router_js.js +15 -16
- package/dist/dependencies/rsvp.js +89 -88
- package/dist/ember-template-compiler.js +8574 -8350
- package/dist/ember-template-compiler.map +1 -1
- package/dist/ember-testing.js +107 -107
- package/dist/ember-testing.map +1 -1
- package/dist/ember.debug.js +11199 -9636
- package/dist/ember.debug.map +1 -1
- package/dist/header/license.js +1 -1
- package/dist/packages/@ember/-internals/glimmer/index.js +93 -83
- package/dist/packages/@ember/-internals/metal/index.js +5 -4
- package/dist/packages/@ember/-internals/utils/index.js +3 -4
- package/dist/packages/@ember/array/-internals.js +1 -2
- package/dist/packages/@ember/debug/lib/inspect.js +0 -1
- package/dist/packages/@ember/object/core.js +0 -1
- package/dist/packages/@ember/object/mixin.js +1 -2
- package/dist/packages/@ember/routing/route.js +23 -101
- package/dist/packages/@ember/routing/router.js +25 -84
- package/dist/packages/ember/version.js +1 -1
- package/dist/packages/ember-babel.js +13 -0
- package/docs/data.json +218 -243
- package/lib/index.js +1 -5
- package/package.json +24 -19
- package/types/stable/@ember/-internals/glimmer/index.d.ts +1 -1
- package/types/stable/@ember/-internals/glimmer/lib/component-managers/curly.d.ts +4 -4
- package/types/stable/@ember/-internals/glimmer/lib/component-managers/mount.d.ts +3 -3
- package/types/stable/@ember/-internals/glimmer/lib/component-managers/outlet.d.ts +5 -8
- package/types/stable/@ember/-internals/glimmer/lib/component-managers/root.d.ts +3 -3
- package/types/stable/@ember/-internals/glimmer/lib/renderer.d.ts +3 -3
- package/types/stable/@ember/-internals/glimmer/lib/resolver.d.ts +3 -3
- package/types/stable/@ember/-internals/glimmer/lib/syntax/utils.d.ts +3 -2
- package/types/stable/@ember/-internals/glimmer/lib/utils/iterator.d.ts +2 -2
- package/types/stable/@ember/-internals/glimmer/lib/utils/outlet.d.ts +39 -18
- package/types/stable/@ember/-internals/utility-types/index.d.ts +1 -0
- package/types/stable/@ember/-internals/views/lib/system/utils.d.ts +4 -3
- package/types/stable/@ember/routing/route.d.ts +6 -28
- package/dist/dependencies/@glimmer/low-level.js +0 -77
|
@@ -1,19 +1,12 @@
|
|
|
1
1
|
import { DEBUG } from '@glimmer/env';
|
|
2
2
|
import { assert, scheduleRevalidate } from '@glimmer/global-context';
|
|
3
|
+
import { getLast, asPresentArray } from '@glimmer/util';
|
|
3
4
|
|
|
4
|
-
// eslint-disable-next-line @typescript-eslint/ban-types
|
|
5
5
|
function indexable(input) {
|
|
6
6
|
return input;
|
|
7
|
-
}
|
|
8
|
-
// should not depend on any other @glimmer packages, in order to avoid pulling
|
|
9
|
-
// in types and prevent regressions in `@glimmer/tracking` (which has public types).
|
|
10
|
-
|
|
11
|
-
const symbol = typeof Symbol !== 'undefined' ? Symbol : // eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
12
|
-
key => `__${key}${Math.floor(Math.random() * Date.now())}__`; // eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
13
|
-
|
|
14
|
-
const symbolFor = typeof Symbol !== 'undefined' ? Symbol.for : key => `__GLIMMER_VALIDATOR_SYMBOL_FOR_${key}`;
|
|
7
|
+
}
|
|
15
8
|
function getGlobal() {
|
|
16
|
-
// eslint-disable-next-line
|
|
9
|
+
// eslint-disable-next-line n/no-unsupported-features/es-builtins
|
|
17
10
|
if (typeof globalThis !== 'undefined') return indexable(globalThis);
|
|
18
11
|
if (typeof self !== 'undefined') return indexable(self);
|
|
19
12
|
if (typeof window !== 'undefined') return indexable(window);
|
|
@@ -25,23 +18,16 @@ function unwrap(val) {
|
|
|
25
18
|
return val;
|
|
26
19
|
}
|
|
27
20
|
|
|
28
|
-
|
|
29
|
-
let endTrackingTransaction;
|
|
30
|
-
let runInTrackingTransaction;
|
|
31
|
-
let resetTrackingTransaction;
|
|
32
|
-
let setTrackingTransactionEnv;
|
|
33
|
-
let assertTagNotConsumed;
|
|
34
|
-
let markTagAsConsumed;
|
|
35
|
-
let logTrackingStack;
|
|
36
|
-
|
|
21
|
+
const debug = {};
|
|
37
22
|
if (DEBUG) {
|
|
38
23
|
let CONSUMED_TAGS = null;
|
|
39
|
-
|
|
24
|
+
const TRANSACTION_STACK = [];
|
|
25
|
+
|
|
26
|
+
/////////
|
|
40
27
|
|
|
41
|
-
|
|
28
|
+
const TRANSACTION_ENV = {
|
|
42
29
|
debugMessage(obj, keyName) {
|
|
43
30
|
let objName;
|
|
44
|
-
|
|
45
31
|
if (typeof obj === 'function') {
|
|
46
32
|
objName = obj.name;
|
|
47
33
|
} else if (typeof obj === 'object' && obj !== null) {
|
|
@@ -52,48 +38,39 @@ if (DEBUG) {
|
|
|
52
38
|
} else {
|
|
53
39
|
objName = String(obj);
|
|
54
40
|
}
|
|
55
|
-
|
|
56
41
|
let dirtyString = keyName ? `\`${keyName}\` on \`${objName}\`` : `\`${objName}\``;
|
|
57
42
|
return `You attempted to update ${dirtyString}, but it had already been used previously in the same computation. Attempting to update a value after using it in a computation can cause logical errors, infinite revalidation bugs, and performance issues, and is not supported.`;
|
|
58
43
|
}
|
|
59
|
-
|
|
60
44
|
};
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
beginTrackingTransaction = _debugLabel => {
|
|
45
|
+
debug.setTrackingTransactionEnv = env => Object.assign(TRANSACTION_ENV, env);
|
|
46
|
+
debug.beginTrackingTransaction = _debugLabel => {
|
|
65
47
|
CONSUMED_TAGS = CONSUMED_TAGS || new WeakMap();
|
|
66
48
|
let debugLabel = _debugLabel || undefined;
|
|
67
|
-
let parent = TRANSACTION_STACK[TRANSACTION_STACK.length - 1]
|
|
49
|
+
let parent = TRANSACTION_STACK[TRANSACTION_STACK.length - 1] ?? null;
|
|
68
50
|
TRANSACTION_STACK.push({
|
|
69
51
|
parent,
|
|
70
52
|
debugLabel
|
|
71
53
|
});
|
|
72
54
|
};
|
|
73
|
-
|
|
74
|
-
endTrackingTransaction = () => {
|
|
55
|
+
debug.endTrackingTransaction = () => {
|
|
75
56
|
if (TRANSACTION_STACK.length === 0) {
|
|
76
57
|
throw new Error('attempted to close a tracking transaction, but one was not open');
|
|
77
58
|
}
|
|
78
|
-
|
|
79
59
|
TRANSACTION_STACK.pop();
|
|
80
|
-
|
|
81
60
|
if (TRANSACTION_STACK.length === 0) {
|
|
82
61
|
CONSUMED_TAGS = null;
|
|
83
62
|
}
|
|
84
63
|
};
|
|
85
|
-
|
|
86
|
-
resetTrackingTransaction = () => {
|
|
64
|
+
debug.resetTrackingTransaction = () => {
|
|
87
65
|
let stack = '';
|
|
88
|
-
|
|
89
66
|
if (TRANSACTION_STACK.length > 0) {
|
|
90
|
-
stack = logTrackingStack(TRANSACTION_STACK[TRANSACTION_STACK.length - 1]);
|
|
67
|
+
stack = debug.logTrackingStack(TRANSACTION_STACK[TRANSACTION_STACK.length - 1]);
|
|
91
68
|
}
|
|
92
|
-
|
|
93
|
-
TRANSACTION_STACK = [];
|
|
69
|
+
TRANSACTION_STACK.splice(0, TRANSACTION_STACK.length);
|
|
94
70
|
CONSUMED_TAGS = null;
|
|
95
71
|
return stack;
|
|
96
72
|
};
|
|
73
|
+
|
|
97
74
|
/**
|
|
98
75
|
* Creates a global autotracking transaction. This will prevent any backflow
|
|
99
76
|
* in any `track` calls within the transaction, even if they are not
|
|
@@ -104,100 +81,99 @@ if (DEBUG) {
|
|
|
104
81
|
*
|
|
105
82
|
* TODO: Only throw an error if the `track` is consumed.
|
|
106
83
|
*/
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
runInTrackingTransaction = (fn, debugLabel) => {
|
|
110
|
-
beginTrackingTransaction(debugLabel);
|
|
84
|
+
debug.runInTrackingTransaction = (fn, debugLabel) => {
|
|
85
|
+
debug.beginTrackingTransaction(debugLabel);
|
|
111
86
|
let didError = true;
|
|
112
|
-
|
|
113
87
|
try {
|
|
114
88
|
let value = fn();
|
|
115
89
|
didError = false;
|
|
116
90
|
return value;
|
|
117
91
|
} finally {
|
|
118
92
|
if (didError !== true) {
|
|
119
|
-
endTrackingTransaction();
|
|
93
|
+
debug.endTrackingTransaction();
|
|
120
94
|
}
|
|
95
|
+
|
|
96
|
+
// if (id !== TRANSACTION_STACK.length) {
|
|
97
|
+
// throw new Error(
|
|
98
|
+
// `attempted to close a tracking transaction (${id}), but it was not the last transaction (${TRANSACTION_STACK.length})`
|
|
99
|
+
// );
|
|
100
|
+
// }
|
|
121
101
|
}
|
|
122
102
|
};
|
|
123
103
|
|
|
124
|
-
let nthIndex = (str, pattern, n
|
|
104
|
+
let nthIndex = function (str, pattern, n) {
|
|
105
|
+
let startingPos = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : -1;
|
|
125
106
|
let i = startingPos;
|
|
126
|
-
|
|
127
107
|
while (n-- > 0 && i++ < str.length) {
|
|
128
108
|
i = str.indexOf(pattern, i);
|
|
129
109
|
if (i < 0) break;
|
|
130
110
|
}
|
|
131
|
-
|
|
132
111
|
return i;
|
|
133
112
|
};
|
|
134
|
-
|
|
135
113
|
let makeTrackingErrorMessage = (transaction, obj, keyName) => {
|
|
136
114
|
let message = [TRANSACTION_ENV.debugMessage(obj, keyName && String(keyName))];
|
|
137
115
|
message.push(`\`${String(keyName)}\` was first used:`);
|
|
138
|
-
message.push(logTrackingStack(transaction));
|
|
116
|
+
message.push(debug.logTrackingStack(transaction));
|
|
139
117
|
message.push(`Stack trace for the update:`);
|
|
140
118
|
return message.join('\n\n');
|
|
141
119
|
};
|
|
142
|
-
|
|
143
|
-
logTrackingStack = transaction => {
|
|
120
|
+
debug.logTrackingStack = transaction => {
|
|
144
121
|
let trackingStack = [];
|
|
145
122
|
let current = transaction || TRANSACTION_STACK[TRANSACTION_STACK.length - 1];
|
|
146
123
|
if (current === undefined) return '';
|
|
147
|
-
|
|
148
124
|
while (current) {
|
|
149
125
|
if (current.debugLabel) {
|
|
150
126
|
trackingStack.unshift(current.debugLabel);
|
|
151
127
|
}
|
|
152
|
-
|
|
153
128
|
current = current.parent;
|
|
154
|
-
}
|
|
155
|
-
|
|
129
|
+
}
|
|
156
130
|
|
|
131
|
+
// TODO: Use String.prototype.repeat here once we can drop support for IE11
|
|
157
132
|
return trackingStack.map((label, index) => Array(2 * index + 1).join(' ') + label).join('\n');
|
|
158
133
|
};
|
|
159
|
-
|
|
160
|
-
markTagAsConsumed = _tag => {
|
|
134
|
+
debug.markTagAsConsumed = _tag => {
|
|
161
135
|
if (!CONSUMED_TAGS || CONSUMED_TAGS.has(_tag)) return;
|
|
162
|
-
CONSUMED_TAGS.set(_tag, TRANSACTION_STACK
|
|
136
|
+
CONSUMED_TAGS.set(_tag, getLast(asPresentArray(TRANSACTION_STACK)));
|
|
137
|
+
|
|
138
|
+
// We need to mark the tag and all of its subtags as consumed, so we need to
|
|
163
139
|
// cast it and access its internals. In the future this shouldn't be necessary,
|
|
164
140
|
// this is only for computed properties.
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
if (tag.subtags) {
|
|
173
|
-
tag.subtags.forEach(tag => markTagAsConsumed(tag));
|
|
141
|
+
let subtag = _tag.subtag;
|
|
142
|
+
if (!subtag || !debug.markTagAsConsumed) return;
|
|
143
|
+
if (Array.isArray(subtag)) {
|
|
144
|
+
subtag.forEach(debug.markTagAsConsumed);
|
|
145
|
+
} else {
|
|
146
|
+
debug.markTagAsConsumed(subtag);
|
|
174
147
|
}
|
|
175
148
|
};
|
|
176
|
-
|
|
177
|
-
assertTagNotConsumed = (tag, obj, keyName) => {
|
|
149
|
+
debug.assertTagNotConsumed = (tag, obj, keyName) => {
|
|
178
150
|
if (CONSUMED_TAGS === null) return;
|
|
179
151
|
let transaction = CONSUMED_TAGS.get(tag);
|
|
180
|
-
if (!transaction) return;
|
|
152
|
+
if (!transaction) return;
|
|
153
|
+
|
|
154
|
+
// This hack makes the assertion message nicer, we can cut off the first
|
|
181
155
|
// few lines of the stack trace and let users know where the actual error
|
|
182
156
|
// occurred.
|
|
183
|
-
|
|
184
157
|
try {
|
|
185
158
|
assert(false, makeTrackingErrorMessage(transaction, obj, keyName));
|
|
186
159
|
} catch (e) {
|
|
187
|
-
if (e
|
|
160
|
+
if (hasStack(e)) {
|
|
188
161
|
let updateStackBegin = e.stack.indexOf('Stack trace for the update:');
|
|
189
|
-
|
|
190
162
|
if (updateStackBegin !== -1) {
|
|
191
163
|
let start = nthIndex(e.stack, '\n', 1, updateStackBegin);
|
|
192
164
|
let end = nthIndex(e.stack, '\n', 4, updateStackBegin);
|
|
193
165
|
e.stack = e.stack.substr(0, start) + e.stack.substr(end);
|
|
194
166
|
}
|
|
195
167
|
}
|
|
196
|
-
|
|
197
168
|
throw e;
|
|
198
169
|
}
|
|
199
170
|
};
|
|
200
171
|
}
|
|
172
|
+
function hasStack(error) {
|
|
173
|
+
return typeof error === 'object' && error !== null && 'stack' in error && typeof error.stack === 'string';
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
//////////
|
|
201
177
|
|
|
202
178
|
const CONSTANT = 0;
|
|
203
179
|
const INITIAL = 1;
|
|
@@ -205,9 +181,20 @@ const VOLATILE = NaN;
|
|
|
205
181
|
let $REVISION = INITIAL;
|
|
206
182
|
function bump() {
|
|
207
183
|
$REVISION++;
|
|
208
|
-
}
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
//////////
|
|
187
|
+
|
|
188
|
+
const DIRYTABLE_TAG_ID = 0;
|
|
189
|
+
const UPDATABLE_TAG_ID = 1;
|
|
190
|
+
const COMBINATOR_TAG_ID = 2;
|
|
191
|
+
const CONSTANT_TAG_ID = 3;
|
|
192
|
+
|
|
193
|
+
//////////
|
|
209
194
|
|
|
210
|
-
const COMPUTE =
|
|
195
|
+
const COMPUTE = Symbol('TAG_COMPUTE');
|
|
196
|
+
|
|
197
|
+
//////////
|
|
211
198
|
|
|
212
199
|
/**
|
|
213
200
|
* `value` receives a tag and returns an opaque Revision based on that tag. This
|
|
@@ -217,10 +204,10 @@ const COMPUTE = symbol('TAG_COMPUTE'); //////////
|
|
|
217
204
|
*
|
|
218
205
|
* @param tag
|
|
219
206
|
*/
|
|
220
|
-
|
|
221
207
|
function valueForTag(tag) {
|
|
222
208
|
return tag[COMPUTE]();
|
|
223
209
|
}
|
|
210
|
+
|
|
224
211
|
/**
|
|
225
212
|
* `validate` receives a tag and a snapshot from a previous call to `value` with
|
|
226
213
|
* the same tag, and determines if the tag is still valid compared to the
|
|
@@ -231,19 +218,19 @@ function valueForTag(tag) {
|
|
|
231
218
|
* @param tag
|
|
232
219
|
* @param snapshot
|
|
233
220
|
*/
|
|
234
|
-
|
|
235
221
|
function validateTag(tag, snapshot) {
|
|
236
222
|
return snapshot >= tag[COMPUTE]();
|
|
237
223
|
}
|
|
238
|
-
const TYPE = symbol('TAG_TYPE'); // this is basically a const
|
|
239
|
-
// eslint-disable-next-line @typescript-eslint/naming-convention
|
|
240
224
|
|
|
241
|
-
|
|
225
|
+
//////////
|
|
242
226
|
|
|
227
|
+
const TYPE = Symbol('TAG_TYPE');
|
|
228
|
+
|
|
229
|
+
// this is basically a const
|
|
230
|
+
let ALLOW_CYCLES;
|
|
243
231
|
if (DEBUG) {
|
|
244
232
|
ALLOW_CYCLES = new WeakMap();
|
|
245
233
|
}
|
|
246
|
-
|
|
247
234
|
function allowsCycles(tag) {
|
|
248
235
|
if (ALLOW_CYCLES === undefined) {
|
|
249
236
|
return true;
|
|
@@ -251,65 +238,56 @@ function allowsCycles(tag) {
|
|
|
251
238
|
return ALLOW_CYCLES.has(tag);
|
|
252
239
|
}
|
|
253
240
|
}
|
|
254
|
-
|
|
255
241
|
class MonomorphicTagImpl {
|
|
256
|
-
constructor(type) {
|
|
257
|
-
this.revision = INITIAL;
|
|
258
|
-
this.lastChecked = INITIAL;
|
|
259
|
-
this.lastValue = INITIAL;
|
|
260
|
-
this.isUpdating = false;
|
|
261
|
-
this.subtag = null;
|
|
262
|
-
this.subtagBufferCache = null;
|
|
263
|
-
this[TYPE] = type;
|
|
264
|
-
}
|
|
265
|
-
|
|
266
242
|
static combine(tags) {
|
|
267
243
|
switch (tags.length) {
|
|
268
244
|
case 0:
|
|
269
245
|
return CONSTANT_TAG;
|
|
270
|
-
|
|
271
246
|
case 1:
|
|
272
247
|
return tags[0];
|
|
273
|
-
|
|
274
248
|
default:
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
249
|
+
{
|
|
250
|
+
let tag = new MonomorphicTagImpl(COMBINATOR_TAG_ID);
|
|
251
|
+
tag.subtag = tags;
|
|
252
|
+
return tag;
|
|
253
|
+
}
|
|
280
254
|
}
|
|
281
255
|
}
|
|
282
|
-
|
|
256
|
+
revision = INITIAL;
|
|
257
|
+
lastChecked = INITIAL;
|
|
258
|
+
lastValue = INITIAL;
|
|
259
|
+
isUpdating = false;
|
|
260
|
+
subtag = null;
|
|
261
|
+
subtagBufferCache = null;
|
|
262
|
+
[TYPE];
|
|
263
|
+
constructor(type) {
|
|
264
|
+
this[TYPE] = type;
|
|
265
|
+
}
|
|
283
266
|
[COMPUTE]() {
|
|
284
267
|
let {
|
|
285
268
|
lastChecked
|
|
286
269
|
} = this;
|
|
287
|
-
|
|
288
270
|
if (this.isUpdating === true) {
|
|
289
271
|
if (DEBUG && !allowsCycles(this)) {
|
|
290
272
|
throw new Error('Cycles in tags are not allowed');
|
|
291
273
|
}
|
|
292
|
-
|
|
293
274
|
this.lastChecked = ++$REVISION;
|
|
294
275
|
} else if (lastChecked !== $REVISION) {
|
|
295
276
|
this.isUpdating = true;
|
|
296
277
|
this.lastChecked = $REVISION;
|
|
297
|
-
|
|
298
278
|
try {
|
|
299
279
|
let {
|
|
300
280
|
subtag,
|
|
301
281
|
revision
|
|
302
282
|
} = this;
|
|
303
|
-
|
|
304
283
|
if (subtag !== null) {
|
|
305
284
|
if (Array.isArray(subtag)) {
|
|
306
|
-
for (
|
|
307
|
-
let value =
|
|
285
|
+
for (const tag of subtag) {
|
|
286
|
+
let value = tag[COMPUTE]();
|
|
308
287
|
revision = Math.max(value, revision);
|
|
309
288
|
}
|
|
310
289
|
} else {
|
|
311
290
|
let subtagValue = subtag[COMPUTE]();
|
|
312
|
-
|
|
313
291
|
if (subtagValue === this.subtagBufferCache) {
|
|
314
292
|
revision = Math.max(revision, this.lastValue);
|
|
315
293
|
} else {
|
|
@@ -319,27 +297,21 @@ class MonomorphicTagImpl {
|
|
|
319
297
|
}
|
|
320
298
|
}
|
|
321
299
|
}
|
|
322
|
-
|
|
323
300
|
this.lastValue = revision;
|
|
324
301
|
} finally {
|
|
325
302
|
this.isUpdating = false;
|
|
326
303
|
}
|
|
327
304
|
}
|
|
328
|
-
|
|
329
305
|
return this.lastValue;
|
|
330
306
|
}
|
|
331
|
-
|
|
332
307
|
static updateTag(_tag, _subtag) {
|
|
333
|
-
if (DEBUG && _tag[TYPE] !==
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
throw new Error('Attempted to update a tag that was not updatable');
|
|
337
|
-
} // TODO: TS 3.7 should allow us to do this via assertion
|
|
338
|
-
|
|
308
|
+
if (DEBUG && _tag[TYPE] !== UPDATABLE_TAG_ID) {
|
|
309
|
+
throw new Error('Attempted to update a tag that was not updatable');
|
|
310
|
+
}
|
|
339
311
|
|
|
312
|
+
// TODO: TS 3.7 should allow us to do this via assertion
|
|
340
313
|
let tag = _tag;
|
|
341
314
|
let subtag = _subtag;
|
|
342
|
-
|
|
343
315
|
if (subtag === CONSTANT_TAG) {
|
|
344
316
|
tag.subtag = null;
|
|
345
317
|
} else {
|
|
@@ -365,66 +337,65 @@ class MonomorphicTagImpl {
|
|
|
365
337
|
tag.subtag = subtag;
|
|
366
338
|
}
|
|
367
339
|
}
|
|
368
|
-
|
|
369
340
|
static dirtyTag(tag, disableConsumptionAssertion) {
|
|
370
|
-
if (DEBUG && !(tag[TYPE] ===
|
|
371
|
-
/* Updatable */
|
|
372
|
-
|| tag[TYPE] === 0
|
|
373
|
-
/* Dirtyable */
|
|
374
|
-
)) {
|
|
341
|
+
if (DEBUG && !(tag[TYPE] === UPDATABLE_TAG_ID || tag[TYPE] === DIRYTABLE_TAG_ID)) {
|
|
375
342
|
throw new Error('Attempted to dirty a tag that was not dirtyable');
|
|
376
343
|
}
|
|
377
|
-
|
|
378
344
|
if (DEBUG && disableConsumptionAssertion !== true) {
|
|
379
345
|
// Usually by this point, we've already asserted with better error information,
|
|
380
346
|
// but this is our last line of defense.
|
|
381
|
-
unwrap(assertTagNotConsumed)(tag);
|
|
347
|
+
unwrap(debug.assertTagNotConsumed)(tag);
|
|
382
348
|
}
|
|
383
|
-
|
|
384
349
|
tag.revision = ++$REVISION;
|
|
385
350
|
scheduleRevalidate();
|
|
386
351
|
}
|
|
387
|
-
|
|
388
352
|
}
|
|
389
|
-
|
|
390
353
|
const DIRTY_TAG = MonomorphicTagImpl.dirtyTag;
|
|
391
|
-
const UPDATE_TAG = MonomorphicTagImpl.updateTag;
|
|
354
|
+
const UPDATE_TAG = MonomorphicTagImpl.updateTag;
|
|
355
|
+
|
|
356
|
+
//////////
|
|
392
357
|
|
|
393
358
|
function createTag() {
|
|
394
|
-
return new MonomorphicTagImpl(
|
|
395
|
-
/* Dirtyable */
|
|
396
|
-
);
|
|
359
|
+
return new MonomorphicTagImpl(DIRYTABLE_TAG_ID);
|
|
397
360
|
}
|
|
398
361
|
function createUpdatableTag() {
|
|
399
|
-
return new MonomorphicTagImpl(
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
const CONSTANT_TAG = new MonomorphicTagImpl(
|
|
405
|
-
/* Constant */
|
|
406
|
-
);
|
|
362
|
+
return new MonomorphicTagImpl(UPDATABLE_TAG_ID);
|
|
363
|
+
}
|
|
364
|
+
|
|
365
|
+
//////////
|
|
366
|
+
|
|
367
|
+
const CONSTANT_TAG = new MonomorphicTagImpl(CONSTANT_TAG_ID);
|
|
407
368
|
function isConstTag(tag) {
|
|
408
369
|
return tag === CONSTANT_TAG;
|
|
409
|
-
}
|
|
370
|
+
}
|
|
410
371
|
|
|
372
|
+
//////////
|
|
373
|
+
|
|
374
|
+
const VOLATILE_TAG_ID = 100;
|
|
411
375
|
class VolatileTag {
|
|
376
|
+
[TYPE] = VOLATILE_TAG_ID;
|
|
412
377
|
[COMPUTE]() {
|
|
413
378
|
return VOLATILE;
|
|
414
379
|
}
|
|
415
|
-
|
|
416
380
|
}
|
|
417
|
-
const VOLATILE_TAG = new VolatileTag();
|
|
381
|
+
const VOLATILE_TAG = new VolatileTag();
|
|
418
382
|
|
|
383
|
+
//////////
|
|
384
|
+
|
|
385
|
+
const CURRENT_TAG_ID = 101;
|
|
419
386
|
class CurrentTag {
|
|
387
|
+
[TYPE] = CURRENT_TAG_ID;
|
|
420
388
|
[COMPUTE]() {
|
|
421
389
|
return $REVISION;
|
|
422
390
|
}
|
|
423
|
-
|
|
424
391
|
}
|
|
425
|
-
const CURRENT_TAG = new CurrentTag();
|
|
392
|
+
const CURRENT_TAG = new CurrentTag();
|
|
393
|
+
|
|
394
|
+
//////////
|
|
395
|
+
|
|
396
|
+
const combine = MonomorphicTagImpl.combine;
|
|
426
397
|
|
|
427
|
-
|
|
398
|
+
// Warm
|
|
428
399
|
|
|
429
400
|
let tag1 = createUpdatableTag();
|
|
430
401
|
let tag2 = createUpdatableTag();
|
|
@@ -447,74 +418,63 @@ function isObjectLike(u) {
|
|
|
447
418
|
return typeof u === 'object' && u !== null || typeof u === 'function';
|
|
448
419
|
}
|
|
449
420
|
|
|
421
|
+
///////////
|
|
422
|
+
|
|
450
423
|
const TRACKED_TAGS = new WeakMap();
|
|
451
424
|
function dirtyTagFor(obj, key, meta) {
|
|
452
425
|
if (DEBUG && !isObjectLike(obj)) {
|
|
453
426
|
throw new Error(`BUG: Can't update a tag for a primitive`);
|
|
454
427
|
}
|
|
428
|
+
let tags = meta === undefined ? TRACKED_TAGS.get(obj) : meta;
|
|
455
429
|
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
if (tags === undefined) return; // Dirty the tag for the specific property if it exists
|
|
430
|
+
// No tags have been setup for this object yet, return
|
|
431
|
+
if (tags === undefined) return;
|
|
459
432
|
|
|
433
|
+
// Dirty the tag for the specific property if it exists
|
|
460
434
|
let propertyTag = tags.get(key);
|
|
461
|
-
|
|
462
435
|
if (propertyTag !== undefined) {
|
|
463
436
|
if (DEBUG) {
|
|
464
|
-
unwrap(assertTagNotConsumed)(propertyTag, obj, key);
|
|
437
|
+
unwrap(debug.assertTagNotConsumed)(propertyTag, obj, key);
|
|
465
438
|
}
|
|
466
|
-
|
|
467
439
|
DIRTY_TAG(propertyTag, true);
|
|
468
440
|
}
|
|
469
441
|
}
|
|
470
442
|
function tagMetaFor(obj) {
|
|
471
443
|
let tags = TRACKED_TAGS.get(obj);
|
|
472
|
-
|
|
473
444
|
if (tags === undefined) {
|
|
474
445
|
tags = new Map();
|
|
475
446
|
TRACKED_TAGS.set(obj, tags);
|
|
476
447
|
}
|
|
477
|
-
|
|
478
448
|
return tags;
|
|
479
449
|
}
|
|
480
450
|
function tagFor(obj, key, meta) {
|
|
481
451
|
let tags = meta === undefined ? tagMetaFor(obj) : meta;
|
|
482
452
|
let tag = tags.get(key);
|
|
483
|
-
|
|
484
453
|
if (tag === undefined) {
|
|
485
454
|
tag = createUpdatableTag();
|
|
486
455
|
tags.set(key, tag);
|
|
487
456
|
}
|
|
488
|
-
|
|
489
457
|
return tag;
|
|
490
458
|
}
|
|
491
459
|
|
|
492
460
|
/**
|
|
493
461
|
* An object that that tracks @tracked properties that were consumed.
|
|
494
462
|
*/
|
|
495
|
-
|
|
496
463
|
class Tracker {
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
this.last = null;
|
|
500
|
-
}
|
|
501
|
-
|
|
464
|
+
tags = new Set();
|
|
465
|
+
last = null;
|
|
502
466
|
add(tag) {
|
|
503
467
|
if (tag === CONSTANT_TAG) return;
|
|
504
468
|
this.tags.add(tag);
|
|
505
|
-
|
|
506
469
|
if (DEBUG) {
|
|
507
|
-
unwrap(markTagAsConsumed)(tag);
|
|
470
|
+
unwrap(debug.markTagAsConsumed)(tag);
|
|
508
471
|
}
|
|
509
|
-
|
|
510
472
|
this.last = tag;
|
|
511
473
|
}
|
|
512
|
-
|
|
513
474
|
combine() {
|
|
514
475
|
let {
|
|
515
476
|
tags
|
|
516
477
|
} = this;
|
|
517
|
-
|
|
518
478
|
if (tags.size === 0) {
|
|
519
479
|
return CONSTANT_TAG;
|
|
520
480
|
} else if (tags.size === 1) {
|
|
@@ -525,8 +485,8 @@ class Tracker {
|
|
|
525
485
|
return combine(tagsArr);
|
|
526
486
|
}
|
|
527
487
|
}
|
|
528
|
-
|
|
529
488
|
}
|
|
489
|
+
|
|
530
490
|
/**
|
|
531
491
|
* Whenever a tracked computed property is entered, the current tracker is
|
|
532
492
|
* saved off and a new tracker is replaced.
|
|
@@ -540,29 +500,23 @@ class Tracker {
|
|
|
540
500
|
* that corresponds to the tracked properties consumed inside of
|
|
541
501
|
* itself, including child tracked computed properties.
|
|
542
502
|
*/
|
|
543
|
-
|
|
544
|
-
|
|
545
503
|
let CURRENT_TRACKER = null;
|
|
546
504
|
const OPEN_TRACK_FRAMES = [];
|
|
547
505
|
function beginTrackFrame(debuggingContext) {
|
|
548
506
|
OPEN_TRACK_FRAMES.push(CURRENT_TRACKER);
|
|
549
507
|
CURRENT_TRACKER = new Tracker();
|
|
550
|
-
|
|
551
508
|
if (DEBUG) {
|
|
552
|
-
unwrap(beginTrackingTransaction)(debuggingContext);
|
|
509
|
+
unwrap(debug.beginTrackingTransaction)(debuggingContext);
|
|
553
510
|
}
|
|
554
511
|
}
|
|
555
512
|
function endTrackFrame() {
|
|
556
513
|
let current = CURRENT_TRACKER;
|
|
557
|
-
|
|
558
514
|
if (DEBUG) {
|
|
559
515
|
if (OPEN_TRACK_FRAMES.length === 0) {
|
|
560
516
|
throw new Error('attempted to close a tracking frame, but one was not open');
|
|
561
517
|
}
|
|
562
|
-
|
|
563
|
-
unwrap(endTrackingTransaction)();
|
|
518
|
+
unwrap(debug.endTrackingTransaction)();
|
|
564
519
|
}
|
|
565
|
-
|
|
566
520
|
CURRENT_TRACKER = OPEN_TRACK_FRAMES.pop() || null;
|
|
567
521
|
return unwrap(current).combine();
|
|
568
522
|
}
|
|
@@ -574,19 +528,17 @@ function endUntrackFrame() {
|
|
|
574
528
|
if (DEBUG && OPEN_TRACK_FRAMES.length === 0) {
|
|
575
529
|
throw new Error('attempted to close a tracking frame, but one was not open');
|
|
576
530
|
}
|
|
577
|
-
|
|
578
531
|
CURRENT_TRACKER = OPEN_TRACK_FRAMES.pop() || null;
|
|
579
|
-
}
|
|
532
|
+
}
|
|
580
533
|
|
|
534
|
+
// This function is only for handling errors and resetting to a valid state
|
|
581
535
|
function resetTracking() {
|
|
582
536
|
while (OPEN_TRACK_FRAMES.length > 0) {
|
|
583
537
|
OPEN_TRACK_FRAMES.pop();
|
|
584
538
|
}
|
|
585
|
-
|
|
586
539
|
CURRENT_TRACKER = null;
|
|
587
|
-
|
|
588
540
|
if (DEBUG) {
|
|
589
|
-
return unwrap(resetTrackingTransaction)();
|
|
541
|
+
return unwrap(debug.resetTrackingTransaction)();
|
|
590
542
|
}
|
|
591
543
|
}
|
|
592
544
|
function isTracking() {
|
|
@@ -596,28 +548,28 @@ function consumeTag(tag) {
|
|
|
596
548
|
if (CURRENT_TRACKER !== null) {
|
|
597
549
|
CURRENT_TRACKER.add(tag);
|
|
598
550
|
}
|
|
599
|
-
}
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
const
|
|
604
|
-
const
|
|
551
|
+
}
|
|
552
|
+
|
|
553
|
+
// public interface
|
|
554
|
+
|
|
555
|
+
const FN = Symbol('FN');
|
|
556
|
+
const LAST_VALUE = Symbol('LAST_VALUE');
|
|
557
|
+
const TAG = Symbol('TAG');
|
|
558
|
+
const SNAPSHOT = Symbol('SNAPSHOT');
|
|
559
|
+
const DEBUG_LABEL = Symbol('DEBUG_LABEL');
|
|
605
560
|
function createCache(fn, debuggingLabel) {
|
|
606
561
|
if (DEBUG && !(typeof fn === 'function')) {
|
|
607
562
|
throw new Error(`createCache() must be passed a function as its first parameter. Called with: ${String(fn)}`);
|
|
608
563
|
}
|
|
609
|
-
|
|
610
564
|
let cache = {
|
|
611
565
|
[FN]: fn,
|
|
612
566
|
[LAST_VALUE]: undefined,
|
|
613
567
|
[TAG]: undefined,
|
|
614
568
|
[SNAPSHOT]: -1
|
|
615
569
|
};
|
|
616
|
-
|
|
617
570
|
if (DEBUG) {
|
|
618
571
|
cache[DEBUG_LABEL] = debuggingLabel;
|
|
619
572
|
}
|
|
620
|
-
|
|
621
573
|
return cache;
|
|
622
574
|
}
|
|
623
575
|
function getValue(cache) {
|
|
@@ -625,10 +577,8 @@ function getValue(cache) {
|
|
|
625
577
|
let fn = cache[FN];
|
|
626
578
|
let tag = cache[TAG];
|
|
627
579
|
let snapshot = cache[SNAPSHOT];
|
|
628
|
-
|
|
629
580
|
if (tag === undefined || !validateTag(tag, snapshot)) {
|
|
630
581
|
beginTrackFrame();
|
|
631
|
-
|
|
632
582
|
try {
|
|
633
583
|
cache[LAST_VALUE] = fn();
|
|
634
584
|
} finally {
|
|
@@ -640,7 +590,6 @@ function getValue(cache) {
|
|
|
640
590
|
} else {
|
|
641
591
|
consumeTag(tag);
|
|
642
592
|
}
|
|
643
|
-
|
|
644
593
|
return cache[LAST_VALUE];
|
|
645
594
|
}
|
|
646
595
|
function isConst(cache) {
|
|
@@ -649,45 +598,44 @@ function isConst(cache) {
|
|
|
649
598
|
assertTag(tag, cache);
|
|
650
599
|
return isConstTag(tag);
|
|
651
600
|
}
|
|
652
|
-
|
|
653
601
|
function assertCache(value, fnName) {
|
|
654
602
|
if (DEBUG && !(typeof value === 'object' && value !== null && FN in value)) {
|
|
655
603
|
throw new Error(`${fnName}() can only be used on an instance of a cache created with createCache(). Called with: ${String(value)}`);
|
|
656
604
|
}
|
|
657
|
-
}
|
|
658
|
-
|
|
605
|
+
}
|
|
659
606
|
|
|
607
|
+
// replace this with `expect` when we can
|
|
660
608
|
function assertTag(tag, cache) {
|
|
661
609
|
if (DEBUG && tag === undefined) {
|
|
662
610
|
throw new Error(`isConst() can only be used on a cache once getValue() has been called at least once. Called with cache function:\n\n${String(cache[FN])}`);
|
|
663
611
|
}
|
|
664
|
-
}
|
|
612
|
+
}
|
|
613
|
+
|
|
614
|
+
//////////
|
|
615
|
+
|
|
665
616
|
// Legacy tracking APIs
|
|
617
|
+
|
|
666
618
|
// track() shouldn't be necessary at all in the VM once the autotracking
|
|
667
619
|
// refactors are merged, and we should generally be moving away from it. It may
|
|
668
620
|
// be necessary in Ember for a while longer, but I think we'll be able to drop
|
|
669
621
|
// it in favor of cache sooner rather than later.
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
function track(callback, debugLabel) {
|
|
622
|
+
function track(block, debugLabel) {
|
|
673
623
|
beginTrackFrame(debugLabel);
|
|
674
624
|
let tag;
|
|
675
|
-
|
|
676
625
|
try {
|
|
677
|
-
|
|
626
|
+
block();
|
|
678
627
|
} finally {
|
|
679
628
|
tag = endTrackFrame();
|
|
680
629
|
}
|
|
681
|
-
|
|
682
630
|
return tag;
|
|
683
|
-
}
|
|
631
|
+
}
|
|
632
|
+
|
|
633
|
+
// untrack() is currently mainly used to handle places that were previously not
|
|
684
634
|
// tracked, and that tracking now would cause backtracking rerender assertions.
|
|
685
635
|
// I think once we move everyone forward onto modern APIs, we'll probably be
|
|
686
636
|
// able to remove it, but I'm not sure yet.
|
|
687
|
-
|
|
688
637
|
function untrack(callback) {
|
|
689
638
|
beginUntrackFrame();
|
|
690
|
-
|
|
691
639
|
try {
|
|
692
640
|
return callback();
|
|
693
641
|
} finally {
|
|
@@ -698,39 +646,34 @@ function untrack(callback) {
|
|
|
698
646
|
function trackedData(key, initializer) {
|
|
699
647
|
let values = new WeakMap();
|
|
700
648
|
let hasInitializer = typeof initializer === 'function';
|
|
701
|
-
|
|
702
649
|
function getter(self) {
|
|
703
650
|
consumeTag(tagFor(self, key));
|
|
704
|
-
let value;
|
|
651
|
+
let value;
|
|
705
652
|
|
|
653
|
+
// If the field has never been initialized, we should initialize it
|
|
706
654
|
if (hasInitializer && !values.has(self)) {
|
|
707
655
|
value = initializer.call(self);
|
|
708
656
|
values.set(self, value);
|
|
709
657
|
} else {
|
|
710
658
|
value = values.get(self);
|
|
711
659
|
}
|
|
712
|
-
|
|
713
660
|
return value;
|
|
714
661
|
}
|
|
715
|
-
|
|
716
662
|
function setter(self, value) {
|
|
717
663
|
dirtyTagFor(self, key);
|
|
718
664
|
values.set(self, value);
|
|
719
665
|
}
|
|
720
|
-
|
|
721
666
|
return {
|
|
722
667
|
getter,
|
|
723
668
|
setter
|
|
724
669
|
};
|
|
725
670
|
}
|
|
726
671
|
|
|
727
|
-
const GLIMMER_VALIDATOR_REGISTRATION =
|
|
672
|
+
const GLIMMER_VALIDATOR_REGISTRATION = Symbol('GLIMMER_VALIDATOR_REGISTRATION');
|
|
728
673
|
const globalObj = getGlobal();
|
|
729
|
-
|
|
730
674
|
if (globalObj[GLIMMER_VALIDATOR_REGISTRATION] === true) {
|
|
731
675
|
throw new Error('The `@glimmer/validator` library has been included twice in this application. It could be different versions of the package, or the same version included twice by mistake. `@glimmer/validator` depends on having a single copy of the package in use at any time in an application, even if they are the same version. You must dedupe your build to remove the duplicate packages in order to prevent this error.');
|
|
732
676
|
}
|
|
733
|
-
|
|
734
677
|
globalObj[GLIMMER_VALIDATOR_REGISTRATION] = true;
|
|
735
678
|
|
|
736
|
-
export { ALLOW_CYCLES, COMPUTE, CONSTANT, CONSTANT_TAG, CURRENT_TAG, CurrentTag, INITIAL, VOLATILE, VOLATILE_TAG, VolatileTag, beginTrackFrame,
|
|
679
|
+
export { ALLOW_CYCLES, COMPUTE, CONSTANT, CONSTANT_TAG, CURRENT_TAG, CurrentTag, INITIAL, VOLATILE, VOLATILE_TAG, VolatileTag, beginTrackFrame, beginUntrackFrame, bump, combine, consumeTag, createCache, createTag, createUpdatableTag, debug, DIRTY_TAG as dirtyTag, dirtyTagFor, endTrackFrame, endUntrackFrame, getValue, isConst, isConstTag, isTracking, resetTracking, tagFor, tagMetaFor, track, trackedData, untrack, UPDATE_TAG as updateTag, validateTag, valueForTag };
|