Skip to content

Commit f357405

Browse files
authored
Merge pull request #18703 from emberjs/bugfix/fix-array-proxy-tags
[BUGFIX release] Correctly links ArrayProxy tags to `arrangedContent`
2 parents 5600946 + cda66b5 commit f357405

File tree

3 files changed

+48
-7
lines changed

3 files changed

+48
-7
lines changed

packages/@ember/-internals/glimmer/tests/integration/syntax/each-test.js

+20-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { moduleFor, RenderingTestCase, applyMixins, strip, runTask } from 'internal-test-helpers';
22

3-
import { get, set, notifyPropertyChange } from '@ember/-internals/metal';
3+
import { get, set, notifyPropertyChange, computed } from '@ember/-internals/metal';
44
import { A as emberA, ArrayProxy, RSVP } from '@ember/-internals/runtime';
55
import { HAS_NATIVE_SYMBOL } from '@ember/-internals/utils';
66

@@ -1089,6 +1089,25 @@ moduleFor(
10891089
}
10901090
);
10911091

1092+
moduleFor(
1093+
'Syntax test: {{#each}} with array proxies, arrangedContent depends on external content',
1094+
class extends EachTest {
1095+
createList(items) {
1096+
let wrapped = emberA(items);
1097+
let proxy = ArrayProxy.extend({
1098+
arrangedContent: computed('wrappedItems.[]', function() {
1099+
// Slice the items to ensure that updates must be propogated
1100+
return this.wrappedItems.slice();
1101+
}),
1102+
}).create({
1103+
wrappedItems: wrapped,
1104+
});
1105+
1106+
return { list: proxy, delegate: wrapped };
1107+
}
1108+
}
1109+
);
1110+
10921111
moduleFor(
10931112
'Syntax test: {{#each as}} undefined path',
10941113
class extends RenderingTestCase {

packages/@ember/-internals/metal/lib/array_events.ts

+8-5
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,8 @@ export function arrayContentDidChange<T extends { length: number }>(
3232
array: T,
3333
startIdx: number,
3434
removeAmt: number,
35-
addAmt: number
35+
addAmt: number,
36+
notify = true
3637
): T {
3738
// if no args are passed assume everything changes
3839
if (startIdx === undefined) {
@@ -50,11 +51,13 @@ export function arrayContentDidChange<T extends { length: number }>(
5051

5152
let meta = peekMeta(array);
5253

53-
if (addAmt < 0 || removeAmt < 0 || addAmt - removeAmt !== 0) {
54-
notifyPropertyChange(array, 'length', meta);
55-
}
54+
if (notify) {
55+
if (addAmt < 0 || removeAmt < 0 || addAmt - removeAmt !== 0) {
56+
notifyPropertyChange(array, 'length', meta);
57+
}
5658

57-
notifyPropertyChange(array, '[]', meta);
59+
notifyPropertyChange(array, '[]', meta);
60+
}
5861

5962
sendEvent(array, '@array:change', [array, startIdx, removeAmt, addAmt]);
6063

packages/@ember/-internals/runtime/lib/system/array_proxy.js

+20-1
Original file line numberDiff line numberDiff line change
@@ -11,11 +11,14 @@ import {
1111
removeArrayObserver,
1212
replace,
1313
getChainTagsForKey,
14+
tagForProperty,
15+
arrayContentDidChange,
16+
arrayContentWillChange,
1417
} from '@ember/-internals/metal';
1518
import EmberObject from './object';
1619
import { isArray, MutableArray } from '../mixins/array';
1720
import { assert } from '@ember/debug';
18-
import { combine, validate, value } from '@glimmer/validator';
21+
import { combine, update, validate, value } from '@glimmer/validator';
1922

2023
const ARRAY_OBSERVER_MAPPING = {
2124
willChange: '_arrangedContentArrayWillChange',
@@ -109,6 +112,12 @@ export default class ArrayProxy extends EmberObject {
109112
this._arrangedContentRevision = value(this._arrangedContentTag);
110113

111114
this._addArrangedContentArrayObserver();
115+
116+
update(tagForProperty(this, '[]'), combine(getChainTagsForKey(this, 'arrangedContent.[]')));
117+
update(
118+
tagForProperty(this, 'length'),
119+
combine(getChainTagsForKey(this, 'arrangedContent.length'))
120+
);
112121
}
113122

114123
willDestroy() {
@@ -316,4 +325,14 @@ ArrayProxy.reopen(MutableArray, {
316325
@public
317326
*/
318327
arrangedContent: alias('content'),
328+
329+
// Array proxies don't need to notify when they change since their `[]` tag is
330+
// already dependent on the `[]` tag of `arrangedContent`
331+
arrayContentWillChange(startIdx, removeAmt, addAmt) {
332+
return arrayContentWillChange(this, startIdx, removeAmt, addAmt, false);
333+
},
334+
335+
arrayContentDidChange(startIdx, removeAmt, addAmt) {
336+
return arrayContentDidChange(this, startIdx, removeAmt, addAmt, false);
337+
},
319338
});

0 commit comments

Comments
 (0)