| Index: packages/observable/lib/src/observable_list.dart
 | 
| diff --git a/packages/observe/lib/src/observable_list.dart b/packages/observable/lib/src/observable_list.dart
 | 
| similarity index 76%
 | 
| rename from packages/observe/lib/src/observable_list.dart
 | 
| rename to packages/observable/lib/src/observable_list.dart
 | 
| index 9d09b38d560b43844f98b40f7d2ea2ff44a28cdd..16c49f579782d2e4db3ae806eb325d8eb902109e 100644
 | 
| --- a/packages/observe/lib/src/observable_list.dart
 | 
| +++ b/packages/observable/lib/src/observable_list.dart
 | 
| @@ -1,21 +1,22 @@
 | 
| -// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
 | 
| +// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
 | 
|  // for details. All rights reserved. Use of this source code is governed by a
 | 
|  // BSD-style license that can be found in the LICENSE file.
 | 
|  
 | 
| -library observe.src.observable_list;
 | 
| +library observable.src.observable_list;
 | 
|  
 | 
|  import 'dart:async';
 | 
|  import 'dart:collection' show ListBase, UnmodifiableListView;
 | 
| -import 'package:observe/observe.dart';
 | 
| -import 'list_diff.dart' show projectListSplices, calcSplices;
 | 
| +
 | 
| +import 'list_diff.dart' show ListChangeRecord, projectListSplices, calcSplices;
 | 
| +import 'observable.dart' show Observable;
 | 
|  
 | 
|  /// Represents an observable list of model values. If any items are added,
 | 
|  /// removed, or replaced, then observers that are listening to [changes]
 | 
|  /// will be notified.
 | 
| -class ObservableList<E> extends ListBase<E> with ChangeNotifier {
 | 
| +class ObservableList<E> extends ListBase<E> with Observable {
 | 
|    List<ListChangeRecord> _listRecords;
 | 
|  
 | 
| -  StreamController _listChanges;
 | 
| +  StreamController<List<ListChangeRecord>> _listChanges;
 | 
|  
 | 
|    /// The inner [List<E>] with the actual storage.
 | 
|    final List<E> _list;
 | 
| @@ -30,6 +31,14 @@ class ObservableList<E> extends ListBase<E> with ChangeNotifier {
 | 
|    ObservableList([int length])
 | 
|        : _list = length != null ? new List<E>(length) : <E>[];
 | 
|  
 | 
| +  /// Creates an observable list of the given [length].
 | 
| +  ///
 | 
| +  /// This constructor exists to work around an issue in the VM whereby
 | 
| +  /// classes that derive from [ObservableList] and mixin other classes
 | 
| +  /// require a default generative constructor in the super class that
 | 
| +  /// does not take optional arguments.
 | 
| +  ObservableList.withLength(int length) : this(length);
 | 
| +
 | 
|    /// Creates an observable list with the elements of [other]. The order in
 | 
|    /// the list will be the order provided by the iterator of [other].
 | 
|    factory ObservableList.from(Iterable<E> other) =>
 | 
| @@ -58,18 +67,21 @@ class ObservableList<E> extends ListBase<E> with ChangeNotifier {
 | 
|    Stream<List<ListChangeRecord>> get listChanges {
 | 
|      if (_listChanges == null) {
 | 
|        // TODO(jmesserly): split observed/unobserved notions?
 | 
| -      _listChanges = new StreamController.broadcast(sync: true,
 | 
| -          onCancel: () { _listChanges = null; });
 | 
| +      _listChanges = new StreamController.broadcast(
 | 
| +        sync: true,
 | 
| +        onCancel: () {
 | 
| +          _listChanges = null;
 | 
| +        },
 | 
| +      );
 | 
|      }
 | 
|      return _listChanges.stream;
 | 
|    }
 | 
|  
 | 
| -  bool get hasListObservers =>
 | 
| -      _listChanges != null && _listChanges.hasListener;
 | 
| +  bool get hasListObservers => _listChanges != null && _listChanges.hasListener;
 | 
|  
 | 
| -  @reflectable int get length => _list.length;
 | 
| +  int get length => _list.length;
 | 
|  
 | 
| -  @reflectable set length(int value) {
 | 
| +  set length(int value) {
 | 
|      int len = _list.length;
 | 
|      if (len == value) return;
 | 
|  
 | 
| @@ -77,30 +89,28 @@ class ObservableList<E> extends ListBase<E> with ChangeNotifier {
 | 
|      _notifyChangeLength(len, value);
 | 
|      if (hasListObservers) {
 | 
|        if (value < len) {
 | 
| -        _recordChange(new ListChangeRecord(this, value,
 | 
| -            removed: _list.getRange(value, len).toList()));
 | 
| +        _notifyListChange(value, removed: _list.getRange(value, len).toList());
 | 
|        } else {
 | 
| -        _recordChange(new ListChangeRecord(this, len, addedCount: value - len));
 | 
| +        _notifyListChange(len, addedCount: value - len);
 | 
|        }
 | 
|      }
 | 
|  
 | 
|      _list.length = value;
 | 
|    }
 | 
|  
 | 
| -  @reflectable E operator [](int index) => _list[index];
 | 
| +  E operator [](int index) => _list[index];
 | 
|  
 | 
| -  @reflectable void operator []=(int index, E value) {
 | 
| -    var oldValue = _list[index];
 | 
| +  void operator []=(int index, E value) {
 | 
| +    E oldValue = _list[index];
 | 
|      if (hasListObservers && oldValue != value) {
 | 
| -      _recordChange(new ListChangeRecord(this, index, addedCount: 1,
 | 
| -          removed: [oldValue]));
 | 
| +      _notifyListChange(index, addedCount: 1, removed: [oldValue]);
 | 
|      }
 | 
|      _list[index] = value;
 | 
|    }
 | 
|  
 | 
|    // Forwarders so we can reflect on the properties.
 | 
| -  @reflectable bool get isEmpty => super.isEmpty;
 | 
| -  @reflectable bool get isNotEmpty => super.isNotEmpty;
 | 
| +  bool get isEmpty => super.isEmpty;
 | 
| +  bool get isNotEmpty => super.isNotEmpty;
 | 
|  
 | 
|    // TODO(jmesserly): should we support first/last/single? They're kind of
 | 
|    // dangerous to use in a path because they throw exceptions. Also we'd need
 | 
| @@ -113,10 +123,10 @@ class ObservableList<E> extends ListBase<E> with ChangeNotifier {
 | 
|      if (iterable is! List && iterable is! Set) {
 | 
|        iterable = iterable.toList();
 | 
|      }
 | 
| -    var len = iterable.length;
 | 
| -    if (hasListObservers && len > 0) {
 | 
| -      _recordChange(new ListChangeRecord(this, index, addedCount: len,
 | 
| -          removed: _list.getRange(index, len).toList()));
 | 
| +    int length = iterable.length;
 | 
| +    if (hasListObservers && length > 0) {
 | 
| +      _notifyListChange(index,
 | 
| +          addedCount: length, removed: _list.sublist(index, length));
 | 
|      }
 | 
|      _list.setAll(index, iterable);
 | 
|    }
 | 
| @@ -125,7 +135,7 @@ class ObservableList<E> extends ListBase<E> with ChangeNotifier {
 | 
|      int len = _list.length;
 | 
|      _notifyChangeLength(len, len + 1);
 | 
|      if (hasListObservers) {
 | 
| -      _recordChange(new ListChangeRecord(this, len, addedCount: 1));
 | 
| +      _notifyListChange(len, addedCount: 1);
 | 
|      }
 | 
|  
 | 
|      _list.add(value);
 | 
| @@ -139,7 +149,7 @@ class ObservableList<E> extends ListBase<E> with ChangeNotifier {
 | 
|  
 | 
|      int added = _list.length - len;
 | 
|      if (hasListObservers && added > 0) {
 | 
| -      _recordChange(new ListChangeRecord(this, len, addedCount: added));
 | 
| +      _notifyListChange(len, addedCount: added);
 | 
|      }
 | 
|    }
 | 
|  
 | 
| @@ -160,8 +170,7 @@ class ObservableList<E> extends ListBase<E> with ChangeNotifier {
 | 
|  
 | 
|      _notifyChangeLength(len, len - rangeLength);
 | 
|      if (hasListObservers && rangeLength > 0) {
 | 
| -      _recordChange(new ListChangeRecord(this, start,
 | 
| -          removed: _list.getRange(start, end).toList()));
 | 
| +      _notifyListChange(start, removed: _list.getRange(start, end).toList());
 | 
|      }
 | 
|  
 | 
|      _list.removeRange(start, end);
 | 
| @@ -188,8 +197,7 @@ class ObservableList<E> extends ListBase<E> with ChangeNotifier {
 | 
|      _notifyChangeLength(len, _list.length);
 | 
|  
 | 
|      if (hasListObservers && insertionLength > 0) {
 | 
| -      _recordChange(new ListChangeRecord(this, index,
 | 
| -          addedCount: insertionLength));
 | 
| +      _notifyListChange(index, addedCount: insertionLength);
 | 
|      }
 | 
|    }
 | 
|  
 | 
| @@ -210,12 +218,11 @@ class ObservableList<E> extends ListBase<E> with ChangeNotifier {
 | 
|  
 | 
|      _notifyChangeLength(_list.length - 1, _list.length);
 | 
|      if (hasListObservers) {
 | 
| -      _recordChange(new ListChangeRecord(this, index, addedCount: 1));
 | 
| +      _notifyListChange(index, addedCount: 1);
 | 
|      }
 | 
|      _list[index] = element;
 | 
|    }
 | 
|  
 | 
| -
 | 
|    E removeAt(int index) {
 | 
|      E result = this[index];
 | 
|      removeRange(index, index + 1);
 | 
| @@ -231,14 +238,14 @@ class ObservableList<E> extends ListBase<E> with ChangeNotifier {
 | 
|      }
 | 
|    }
 | 
|  
 | 
| -  void _recordChange(ListChangeRecord record) {
 | 
| +  void _notifyListChange(int index, {List removed, int addedCount}) {
 | 
|      if (!hasListObservers) return;
 | 
| -
 | 
|      if (_listRecords == null) {
 | 
|        _listRecords = [];
 | 
|        scheduleMicrotask(deliverListChanges);
 | 
|      }
 | 
| -    _listRecords.add(record);
 | 
| +    _listRecords.add(new ListChangeRecord(this, index,
 | 
| +        removed: removed, addedCount: addedCount));
 | 
|    }
 | 
|  
 | 
|    void _notifyChangeLength(int oldValue, int newValue) {
 | 
| @@ -247,10 +254,6 @@ class ObservableList<E> extends ListBase<E> with ChangeNotifier {
 | 
|      notifyPropertyChange(#isNotEmpty, oldValue != 0, newValue != 0);
 | 
|    }
 | 
|  
 | 
| -  /// Deprecated. Name had a typo, use [discardListChanges] instead.
 | 
| -  @deprecated
 | 
| -  void discardListChages() => discardListChanges();
 | 
| -
 | 
|    void discardListChanges() {
 | 
|      // Leave _listRecords set so we don't schedule another delivery.
 | 
|      if (_listRecords != null) _listRecords = [];
 | 
| @@ -258,10 +261,10 @@ class ObservableList<E> extends ListBase<E> with ChangeNotifier {
 | 
|  
 | 
|    bool deliverListChanges() {
 | 
|      if (_listRecords == null) return false;
 | 
| -    var records = projectListSplices(this, _listRecords);
 | 
| +    List<ListChangeRecord> records = projectListSplices(this, _listRecords);
 | 
|      _listRecords = null;
 | 
|  
 | 
| -    if (hasListObservers && !records.isEmpty) {
 | 
| +    if (hasListObservers && records.isNotEmpty) {
 | 
|        _listChanges.add(new UnmodifiableListView<ListChangeRecord>(records));
 | 
|        return true;
 | 
|      }
 | 
| @@ -281,23 +284,22 @@ class ObservableList<E> extends ListBase<E> with ChangeNotifier {
 | 
|    /// Complexity is `O(l * p)` where `l` is the length of the current list and
 | 
|    /// `p` is the length of the old list.
 | 
|    static List<ListChangeRecord> calculateChangeRecords(
 | 
| -      List<Object> oldValue, List<Object> newValue) =>
 | 
| +          List<Object> oldValue, List<Object> newValue) =>
 | 
|        calcSplices(newValue, 0, newValue.length, oldValue, 0, oldValue.length);
 | 
|  
 | 
| -  /// Updates the [previous] list using the change [records]. For added items,
 | 
| +  /// Updates the [previous] list using the [changeRecords]. For added items,
 | 
|    /// the [current] list is used to find the current value.
 | 
|    static void applyChangeRecords(List<Object> previous, List<Object> current,
 | 
|        List<ListChangeRecord> changeRecords) {
 | 
| -
 | 
|      if (identical(previous, current)) {
 | 
|        throw new ArgumentError("can't use same list for previous and current");
 | 
|      }
 | 
|  
 | 
| -    for (var change in changeRecords) {
 | 
| +    for (ListChangeRecord change in changeRecords) {
 | 
|        int addEnd = change.index + change.addedCount;
 | 
|        int removeEnd = change.index + change.removed.length;
 | 
|  
 | 
| -      var addedItems = current.getRange(change.index, addEnd);
 | 
| +      Iterable addedItems = current.getRange(change.index, addEnd);
 | 
|        previous.replaceRange(change.index, removeEnd, addedItems);
 | 
|      }
 | 
|    }
 | 
| 
 |