feat(iterable_differ): support immutable lists

Closes #7127
This commit is contained in:
Tobias Bosch
2016-02-17 09:17:29 -08:00
parent 9936e347ff
commit a10c02cb41
4 changed files with 64 additions and 19 deletions

View File

@ -109,7 +109,6 @@ export class DefaultIterableDiffer implements IterableDiffer {
onDestroy() {}
// todo(vicb): optim for UnmodifiableListView (frozen arrays)
check(collection: any): boolean {
this._reset();
@ -119,24 +118,27 @@ export class DefaultIterableDiffer implements IterableDiffer {
var item;
var itemTrackBy;
if (isArray(collection)) {
var list = collection;
this._length = collection.length;
if (collection !== this._collection || !ListWrapper.isImmutable(collection)) {
var list = collection;
this._length = collection.length;
for (index = 0; index < this._length; index++) {
item = list[index];
itemTrackBy = this._trackByFn(index, item);
if (record === null || !looseIdentical(record.trackById, itemTrackBy)) {
record = this._mismatch(record, item, itemTrackBy, index);
mayBeDirty = true;
} else {
if (mayBeDirty) {
// TODO(misko): can we limit this to duplicates only?
record = this._verifyReinsertion(record, item, itemTrackBy, index);
for (index = 0; index < this._length; index++) {
item = list[index];
itemTrackBy = this._trackByFn(index, item);
if (record === null || !looseIdentical(record.trackById, itemTrackBy)) {
record = this._mismatch(record, item, itemTrackBy, index);
mayBeDirty = true;
} else {
if (mayBeDirty) {
// TODO(misko): can we limit this to duplicates only?
record = this._verifyReinsertion(record, item, itemTrackBy, index);
}
if (!looseIdentical(record.item, item)) this._addIdentityChange(record, item);
}
if (!looseIdentical(record.item, item)) this._addIdentityChange(record, item);
}
record = record._next;
record = record._next;
}
this._truncate(record);
}
} else {
index = 0;
@ -156,9 +158,9 @@ export class DefaultIterableDiffer implements IterableDiffer {
index++;
});
this._length = index;
this._truncate(record);
}
this._truncate(record);
this._collection = collection;
return this.isDirty;
}

View File

@ -1,6 +1,6 @@
library facade.collection;
import 'dart:collection' show IterableBase;
import 'dart:collection' show IterableBase, UnmodifiableListView;
import 'dart:convert' show JsonEncoder;
export 'dart:core' show Iterator, Map, List, Set;
import 'dart:math' show max, min;
@ -106,6 +106,9 @@ class ListWrapper {
static List createFixedSize(int size) => new List(size);
static List createGrowableSize(int size) =>
new List.generate(size, (_) => null, growable: true);
static UnmodifiableListView createImmutable(List input) {
return new UnmodifiableListView(input);
}
static bool contains(List m, k) => m.contains(k);
static int indexOf(List list, value, [int startIndex = 0]) =>
@ -221,6 +224,10 @@ class ListWrapper {
}
return solution;
}
static bool isImmutable(List l) {
return l is UnmodifiableListView;
}
}
bool isListLikeIterable(obj) => obj is Iterable;

View File

@ -178,6 +178,11 @@ export class ListWrapper {
static createFixedSize(size: number): any[] { return new Array(size); }
static createGrowableSize(size: number): any[] { return new Array(size); }
static clone<T>(array: T[]): T[] { return array.slice(0); }
static createImmutable<T>(array: T[]): T[] {
var result = ListWrapper.clone(array);
Object.seal(result);
return result;
}
static forEachWithIndex<T>(array: T[], fn: (t: T, n: number) => void) {
for (var i = 0; i < array.length; i++) {
fn(array[i], i);
@ -265,6 +270,8 @@ export class ListWrapper {
}
return solution;
}
static isImmutable(list: any[]): boolean { return Object.isSealed(list); }
}
export function isListLikeIterable(obj: any): boolean {