Skip to content

Commit 2b53a2f

Browse files
committed
fix(ChangeDetector): fix issues with handling empty ranges
1 parent 2797075 commit 2b53a2f

File tree

2 files changed

+187
-61
lines changed

2 files changed

+187
-61
lines changed

modules/change_detection/src/record_range.js

Lines changed: 100 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -100,28 +100,37 @@ export class RecordRange {
100100
this.headRecord = Record.createMarker(this);
101101
this.tailRecord = Record.createMarker(this);
102102

103-
_glue(this.headRecord, this.tailRecord);
103+
_link(this.headRecord, this.tailRecord);
104104
}
105105

106106
/// addRecord assumes that the record is newly created, so it is enabled.
107107
addRecord(record:Record) {
108108
var lastRecord = this.tailRecord.prev;
109109

110-
_glue(lastRecord, record);
111-
_glueEnabled(lastRecord, record);
112-
_glue(record, this.tailRecord);
110+
_link(lastRecord, record);
111+
if (!lastRecord.disabled) {
112+
_linkEnabled(lastRecord, record);
113+
}
114+
_link(record, this.tailRecord);
113115
}
114116

115117
addRange(child:RecordRange) {
116118
var lastRecord = this.tailRecord.prev;
117-
var lastEnabledRecord = this.findLastEnabledRecord();
119+
var prevEnabledRecord = this._prevEnabled(this.tailRecord);
120+
var nextEnabledRerord = this._nextEnabled(this.tailRecord);
121+
118122
var firstEnabledChildRecord = child.findFirstEnabledRecord();
123+
var lastEnabledChildRecord = child.findLastEnabledRecord();
124+
125+
_link(lastRecord, child.headRecord);
126+
_link(child.tailRecord, this.tailRecord);
119127

120-
_glue(lastRecord, child.headRecord);
121-
_glue(child.tailRecord, this.tailRecord);
128+
if (isPresent(prevEnabledRecord) && isPresent(firstEnabledChildRecord)) {
129+
_linkEnabled(prevEnabledRecord, firstEnabledChildRecord);
130+
}
122131

123-
if (isPresent(lastEnabledRecord) && isPresent(firstEnabledChildRecord)) {
124-
_glueEnabled(lastEnabledRecord, firstEnabledChildRecord);
132+
if (isPresent(nextEnabledRerord) && isPresent(lastEnabledChildRecord)) {
133+
_linkEnabled(lastEnabledChildRecord, nextEnabledRerord);
125134
}
126135
}
127136

@@ -132,21 +141,14 @@ export class RecordRange {
132141
var next = child.tailRecord.next;
133142
var prev = child.headRecord.prev;
134143

135-
_glue(prev, next);
136-
137-
var nextEnabled = lastEnabledChildRecord.nextEnabled;
138-
var prevEnabled = firstEnabledChildRecord.prevEnabled;
139-
140-
if (isPresent(nextEnabled)) nextEnabled.prevEnabled = prevEnabled;
141-
if (isPresent(prevEnabled)) prevEnabled.nextEnabled = nextEnabled;
142-
}
143-
144-
findFirstEnabledRecord() {
145-
return this._nextEnabledInCurrentRange(this.headRecord);
146-
}
144+
_link(prev, next);
147145

148-
findLastEnabledRecord() {
149-
return this._prevEnabledInCurrentRange(this.tailRecord);
146+
if (isPresent(firstEnabledChildRecord)) {
147+
var nextEnabled = lastEnabledChildRecord.nextEnabled;
148+
var prevEnabled = firstEnabledChildRecord.prevEnabled;
149+
if (isPresent(nextEnabled)) nextEnabled.prevEnabled = prevEnabled;
150+
if (isPresent(prevEnabled)) prevEnabled.nextEnabled = nextEnabled;
151+
}
150152
}
151153

152154
disableRecord(record:Record) {
@@ -162,8 +164,8 @@ export class RecordRange {
162164
enableRecord(record:Record) {
163165
if (!record.disabled) return;
164166

165-
var prevEnabled = this._prevEnabledInCurrentRange(record);
166-
var nextEnabled = this._nextEnabledInCurrentRange(record);
167+
var prevEnabled = this._prevEnabled(record);
168+
var nextEnabled = this._nextEnabled(record);
167169

168170
record.prevEnabled = prevEnabled;
169171
record.nextEnabled = nextEnabled;
@@ -188,29 +190,38 @@ export class RecordRange {
188190
}
189191

190192
enableRange(child:RecordRange) {
191-
var prevEnabledRecord = this._prevEnabledInCurrentRange(child.headRecord);
192-
var nextEnabledRecord = this._nextEnabledInCurrentRange(child.tailRecord);
193+
var prevEnabledRecord = this._prevEnabled(child.headRecord);
194+
var nextEnabledRecord = this._nextEnabled(child.tailRecord);
193195

194196
var firstEnabledChildRecord = child.findFirstEnabledRecord();
195197
var lastEnabledChildRecord = child.findLastEnabledRecord();
196198

197199
if (isPresent(firstEnabledChildRecord) && isPresent(prevEnabledRecord)){
198-
_glueEnabled(prevEnabledRecord, firstEnabledChildRecord);
200+
_linkEnabled(prevEnabledRecord, firstEnabledChildRecord);
199201
}
200202

201203
if (isPresent(lastEnabledChildRecord) && isPresent(nextEnabledRecord)){
202-
_glueEnabled(lastEnabledChildRecord, nextEnabledRecord);
204+
_linkEnabled(lastEnabledChildRecord, nextEnabledRecord);
203205
}
204206

205207
child.disabled = false;
206208
}
207209

208-
/// Returns the next enabled record in the current range. If no such record, returns null.
209-
_nextEnabledInCurrentRange(record:Record) {
210-
if (record === this.tailRecord) return null;
211-
212-
record = record.next;
213-
while (isPresent(record) && record !== this.tailRecord && record.disabled) {
210+
/**
211+
* Returns the first enabled record in the current range.
212+
*
213+
* [H ER1 ER2 R3 T] returns ER1
214+
* [H R1 ER2 R3 T] returns ER2
215+
*
216+
* If no enabled records, returns null.
217+
*
218+
* [H R1 R2 R3 T] returns null
219+
*
220+
* The function skips disabled sub ranges.
221+
*/
222+
findFirstEnabledRecord() {
223+
var record = this.headRecord.next;
224+
while (record !== this.tailRecord && record.disabled) {
214225
if (record.isMarkerRecord && record.recordRange.disabled) {
215226
record = record.recordRange.tailRecord.next;
216227
} else {
@@ -220,19 +231,66 @@ export class RecordRange {
220231
return record === this.tailRecord ? null : record;
221232
}
222233

223-
/// Returns the prev enabled record in the current range. If no such record, returns null.
224-
_prevEnabledInCurrentRange(record:Record) {
225-
if (record === this.headRecord) return null;
234+
/**
235+
* Returns the last enabled record in the current range.
236+
*
237+
* [H ER1 ER2 R3 T] returns ER2
238+
* [H R1 ER2 R3 T] returns ER2
239+
*
240+
* If no enabled records, returns null.
241+
*
242+
* [H R1 R2 R3 T] returns null
243+
*
244+
* The function skips disabled sub ranges.
245+
*/
246+
findLastEnabledRecord() {
247+
var record = this.tailRecord.prev;
248+
while (record !== this.headRecord && record.disabled) {
249+
if (record.isMarkerRecord && record.recordRange.disabled) {
250+
record = record.recordRange.headRecord.prev;
251+
} else {
252+
record = record.prev;
253+
}
254+
}
255+
return record === this.headRecord ? null : record;
256+
}
226257

258+
/**
259+
* Returns the next enabled record. This search is not limited to the current range.
260+
*
261+
* [H ER1 T] [H ER2 T] _nextEnable(ER1) will return ER2
262+
*
263+
* The function skips disabled sub ranges.
264+
*/
265+
_nextEnabled(record:Record) {
266+
record = record.next;
267+
while (isPresent(record) && record.disabled) {
268+
if (record.isMarkerRecord && record.recordRange.disabled) {
269+
record = record.recordRange.tailRecord.next;
270+
} else {
271+
record = record.next;
272+
}
273+
}
274+
return record;
275+
}
276+
277+
/**
278+
* Returns the prev enabled record. This search is not limited to the current range.
279+
*
280+
* [H ER1 T] [H ER2 T] _nextEnable(ER2) will return ER1
281+
*
282+
* The function skips disabled sub ranges.
283+
*/
284+
_prevEnabled(record:Record) {
227285
record = record.prev;
228-
while (isPresent(record) && record !== this.headRecord && record.disabled) {
286+
while (isPresent(record) && record.disabled) {
229287
if (record.isMarkerRecord && record.recordRange.disabled) {
230288
record = record.recordRange.headRecord.prev;
231289
} else {
232290
record = record.prev;
233291
}
234292
}
235-
return record === this.headRecord ? null : record;
293+
return record;
236294
}
237295

238296
/**
@@ -253,12 +311,12 @@ export class RecordRange {
253311
}
254312
}
255313

256-
function _glue(a:Record, b:Record) {
314+
function _link(a:Record, b:Record) {
257315
a.next = b;
258316
b.prev = a;
259317
}
260318

261-
function _glueEnabled(a:Record, b:Record) {
319+
function _linkEnabled(a:Record, b:Record) {
262320
a.nextEnabled = b;
263321
b.prevEnabled = a;
264322
}

0 commit comments

Comments
 (0)