Version 0.6.14.0 .

svn merge -r 25579:25717  https://dart.googlecode.com/svn/branches/bleeding_edge trunk

git-svn-id: http://dart.googlecode.com/svn/trunk@25719 260f80e4-7a28-3924-810f-c04153c831b5
diff --git a/dart.gyp b/dart.gyp
index 0b02fc1..70d9da6 100644
--- a/dart.gyp
+++ b/dart.gyp
@@ -44,6 +44,7 @@
         ['OS!="android"', {
           'dependencies': [
             'runtime/dart-runtime.gyp:test_extension',
+            'samples/sample_extension/sample_extension.gyp:sample_extension',
           ],
         }],
       ],
diff --git a/pkg/analyzer_experimental/lib/analyzer.dart b/pkg/analyzer_experimental/lib/analyzer.dart
index 2a9d9ac..644009c 100644
--- a/pkg/analyzer_experimental/lib/analyzer.dart
+++ b/pkg/analyzer_experimental/lib/analyzer.dart
@@ -26,7 +26,16 @@
   var contents = new File(path).readAsStringSync();
   var errorCollector = new _ErrorCollector();
   var sourceFactory = new SourceFactory.con2([new FileUriResolver()]);
-  var source = sourceFactory.forUri(pathos.toUri(path).toString());
+
+  var absolutePath = pathos.absolute(path);
+  var source = sourceFactory.forUri(pathos.toUri(absolutePath).toString());
+  if (source == null) {
+    throw new ArgumentError("Can't get source for path $path");
+  }
+  if (!source.exists()) {
+    throw new ArgumentError("Source $source doesn't exist");
+  }
+
   var scanner = new StringScanner(source, contents, errorCollector);
   var token = scanner.tokenize();
   var parser = new Parser(source, errorCollector);
diff --git a/pkg/barback/lib/barback.dart b/pkg/barback/lib/barback.dart
index eb0e1e8..539d732 100644
--- a/pkg/barback/lib/barback.dart
+++ b/pkg/barback/lib/barback.dart
@@ -6,6 +6,7 @@
 
 export 'src/asset.dart';
 export 'src/asset_id.dart';
+export 'src/barback.dart';
 export 'src/errors.dart';
 export 'src/package_provider.dart';
 export 'src/transform.dart' show Transform;
diff --git a/pkg/barback/lib/src/asset_cascade.dart b/pkg/barback/lib/src/asset_cascade.dart
index 3d6416f..40a615c 100644
--- a/pkg/barback/lib/src/asset_cascade.dart
+++ b/pkg/barback/lib/src/asset_cascade.dart
@@ -7,9 +7,12 @@
 import 'dart:async';
 import 'dart:collection';
 
+import 'package:stack_trace/stack_trace.dart';
+
 import 'asset.dart';
 import 'asset_id.dart';
-import 'asset_set.dart';
+import 'asset_node.dart';
+import 'cancelable_future.dart';
 import 'errors.dart';
 import 'change_batch.dart';
 import 'package_graph.dart';
@@ -36,6 +39,17 @@
   /// the current app.
   final PackageGraph _graph;
 
+  /// The controllers for the [AssetNode]s that provide information about this
+  /// cascade's package's source assets.
+  final _sourceControllerMap = new Map<AssetId, AssetNodeController>();
+
+  /// Futures for source assets that are currently being loaded.
+  ///
+  /// These futures are cancelable so that if an asset is updated after a load
+  /// has been kicked off, the previous load can be ignored in favor of a new
+  /// one.
+  final _loadingSources = new Map<AssetId, CancelableFuture<Asset>>();
+
   final _phases = <Phase>[];
 
   /// A stream that emits a [BuildResult] each time the build is completed,
@@ -66,7 +80,9 @@
   /// If no build it in progress, is `null`.
   Future _processDone;
 
-  ChangeBatch _sourceChanges;
+  /// Whether any source assets have been updated or removed since processing
+  /// last began.
+  var _newChanges = false;
 
   /// Creates a new [AssetCascade].
   ///
@@ -104,54 +120,95 @@
     // * [id] may be generated before the compilation is finished. We should
     //   be able to quickly check whether there are any more in-place
     //   transformations that can be run on it. If not, we can return it early.
-    // * If everything is compiled, something that didn't output [id] is
-    //   dirtied, and then [id] is requested, we can return it immediately,
-    //   since anything overwriting it at that point is an error.
     // * If [id] has never been generated and all active transformers provide
     //   metadata about the file names of assets it can emit, we can prove that
     //   none of them can emit [id] and fail early.
-    return (_processDone == null ? new Future.value() : _processDone).then((_) {
-      // Each phase's inputs are the outputs of the previous phase. Find the
-      // last phase that contains the asset. Since the last phase has no
-      // transformers, this will find the latest output for that id.
+    return newFuture(() {
+      var node = _getAssetNode(id);
 
-      // TODO(rnystrom): Currently does not omit assets that are actually used
-      // as inputs for transformers. This means you can request and get an
-      // asset that should be "consumed" because it's used to generate the
-      // real asset you care about. Need to figure out how we want to handle
-      // that and what use cases there are related to it.
-      for (var i = _phases.length - 1; i >= 0; i--) {
-        var node = _phases[i].inputs[id];
-        if (node != null) {
-          // By the time we get here, the asset should have been built.
-          assert(node.asset != null);
-          return node.asset;
-        }
+      // If the requested asset is available, we can just return it.
+      if (node != null) return node.asset;
+
+      // If there's a build running, that build might generate the asset, so we
+      // wait for it to complete and then try again.
+      if (_processDone != null) {
+        return _processDone.then((_) => getAssetById(id));
       }
 
-      // Couldn't find it.
+      // If the asset hasn't been built and nothing is building now, the asset
+      // won't be generated, so we throw an error.
       throw new AssetNotFoundException(id);
     });
   }
 
+  // Returns the post-transformation asset node for [id], if one is available.
+  //
+  // This will only return a node that has an asset available, and only if that
+  // node is guaranteed not to be consumed by any transforms. If the phase is
+  // still working to figure out if a node will be consumed by a transformer,
+  // that node won't be returned.
+  AssetNode _getAssetNode(AssetId id) {
+    // Each phase's inputs are the outputs of the previous phase. Find the last
+    // phase that contains the asset. Since the last phase has no transformers,
+    // this will find the latest output for that id.
+    for (var i = _phases.length - 1; i >= 0; i--) {
+      var node = _phases[i].getUnconsumedInput(id);
+      if (node != null) return node;
+    }
+
+    return null;
+  }
+
   /// Adds [sources] to the graph's known set of source assets.
   ///
   /// Begins applying any transforms that can consume any of the sources. If a
   /// given source is already known, it is considered modified and all
   /// transforms that use it will be re-applied.
   void updateSources(Iterable<AssetId> sources) {
-    if (_sourceChanges == null) _sourceChanges = new ChangeBatch();
-    assert(sources.every((id) => id.package == package));
-    _sourceChanges.update(sources);
+    _newChanges = true;
+
+    for (var id in sources) {
+      var controller = _sourceControllerMap[id];
+      if (controller != null) {
+        controller.setDirty();
+      } else {
+        _sourceControllerMap[id] = new AssetNodeController(id);
+        _phases.first.addInput(_sourceControllerMap[id].node);
+      }
+
+      // If this source was already loading, cancel the old load, since it may
+      // return out-of-date contents for the asset.
+      if (_loadingSources.containsKey(id)) _loadingSources[id].cancel();
+
+      _loadingSources[id] =
+          new CancelableFuture<Asset>(_graph.provider.getAsset(id));
+      _loadingSources[id].whenComplete(() {
+        _loadingSources.remove(id);
+      }).then((asset) {
+        var controller = _sourceControllerMap[id].setAvailable(asset);
+      }).catchError((error) {
+        reportError(error);
+
+        // TODO(nweiz): propagate error information through asset nodes.
+        _sourceControllerMap.remove(id).setRemoved();
+      });
+    }
 
     _waitForProcess();
   }
 
   /// Removes [removed] from the graph's known set of source assets.
   void removeSources(Iterable<AssetId> removed) {
-    if (_sourceChanges == null) _sourceChanges = new ChangeBatch();
-    assert(removed.every((id) => id.package == package));
-    _sourceChanges.remove(removed);
+    _newChanges = true;
+
+    removed.forEach((id) {
+      // If the source was being loaded, cancel that load.
+      if (_loadingSources.containsKey(id)) _loadingSources.remove(id).cancel();
+
+      var controller = _sourceControllerMap.remove(id);
+      // Don't choke if an id is double-removed for some reason.
+      if (controller != null) controller.setRemoved();
+    });
 
     _waitForProcess();
   }
@@ -196,7 +253,8 @@
   ///
   /// Returns a future that completes when all assets have been processed.
   Future _process() {
-    return _processSourceChanges().then((_) {
+    _newChanges = false;
+    return newFuture(() {
       // Find the first phase that has work to do and do it.
       var future;
       for (var phase in _phases) {
@@ -207,7 +265,7 @@
       // If all phases are done and no new updates have come in, we're done.
       if (future == null) {
         // If changes have come in, start over.
-        if (_sourceChanges != null) return _process();
+        if (_newChanges) return _process();
 
         // Otherwise, everything is done.
         return;
@@ -217,42 +275,6 @@
       return future.then((_) => _process());
     });
   }
-
-  /// Processes the current batch of changes to source assets.
-  Future _processSourceChanges() {
-    // Always pump the event loop. This ensures a bunch of synchronous source
-    // changes are processed in a single batch even when the first one starts
-    // the build process.
-    return newFuture(() {
-      if (_sourceChanges == null) return null;
-
-      // Take the current batch to ensure it doesn't get added to while we're
-      // processing it.
-      var changes = _sourceChanges;
-      _sourceChanges = null;
-
-      var updated = new AssetSet();
-      var futures = [];
-      for (var id in changes.updated) {
-        // TODO(rnystrom): Catch all errors from provider and route to results.
-        futures.add(_graph.provider.getAsset(id).then((asset) {
-          updated.add(asset);
-        }).catchError((error) {
-          if (error is AssetNotFoundException) {
-            // Handle missing asset errors like regular missing assets.
-            reportError(error);
-          } else {
-            // It's an unexpected error, so rethrow it.
-            throw error;
-          }
-        }));
-      }
-
-      return Future.wait(futures).then((_) {
-        _phases.first.updateInputs(updated, changes.removed);
-      });
-    });
-  }
 }
 
 /// An event indicating that the cascade has finished building all assets.
diff --git a/pkg/barback/lib/src/asset_node.dart b/pkg/barback/lib/src/asset_node.dart
index ae2b70e..6e7789a 100644
--- a/pkg/barback/lib/src/asset_node.dart
+++ b/pkg/barback/lib/src/asset_node.dart
@@ -8,30 +8,189 @@
 
 import 'asset.dart';
 import 'asset_id.dart';
+import 'errors.dart';
 import 'phase.dart';
 import 'transform_node.dart';
 
-/// Describes an asset and its relationship to the build dependency graph.
+/// Describes the current state of an asset as part of a transformation graph.
 ///
-/// Keeps a cache of the last asset that was built for this node (i.e. for this
-/// node's ID and phase) and tracks which transforms depend on it.
+/// An asset node can be in one of three states (see [AssetState]). It provides
+/// an [onStateChange] stream that emits an event whenever it changes state.
+///
+/// Asset nodes are controlled using [AssetNodeController]s.
 class AssetNode {
-  Asset asset;
+  /// The id of the asset that this node represents.
+  final AssetId id;
 
-  /// The [TransformNode]s that consume this node's asset as an input.
-  final consumers = new Set<TransformNode>();
+  /// The current state of the asset node.
+  AssetState get state => _state;
+  AssetState _state;
 
-  AssetId get id => asset.id;
+  /// The concrete asset that this node represents.
+  ///
+  /// This is null unless [state] is [AssetState.AVAILABLE].
+  Asset get asset => _asset;
+  Asset _asset;
 
-  AssetNode(this.asset);
+  /// A broadcast stream that emits an event whenever the node changes state.
+  ///
+  /// This stream is synchronous to ensure that when a source asset is modified
+  /// or removed, the appropriate portion of the asset graph is dirtied before
+  /// any [Barback.getAssetById] calls emit newly-incorrect values.
+  Stream<AssetState> get onStateChange => _stateChangeController.stream;
 
-  /// Updates this node's generated asset value and marks all transforms that
-  /// use this as dirty.
-  void updateAsset(Asset asset) {
-    // Cannot update an asset to one with a different ID.
-    assert(id == asset.id);
+  /// This is synchronous so that a source being updated will always be
+  /// propagated through the build graph before anything that depends on it is
+  /// requested.
+  final _stateChangeController =
+      new StreamController<AssetState>.broadcast(sync: true);
 
-    this.asset = asset;
-    consumers.forEach((consumer) => consumer.dirty());
+  /// Returns a Future that completes when the node's asset is available.
+  ///
+  /// If the asset is currently available, this completes synchronously to
+  /// ensure that the asset is still available in the [Future.then] callback.
+  ///
+  /// If the asset is removed before becoming available, this will throw an
+  /// [AssetNotFoundException].
+  Future<Asset> get whenAvailable {
+    return _waitForState((state) => state.isAvailable || state.isRemoved)
+        .then((state) {
+      if (state.isRemoved) throw new AssetNotFoundException(id);
+      return asset;
+    });
   }
+
+  /// Returns a Future that completes when the node's asset is removed.
+  ///
+  /// If the asset is already removed when this is called, it completes
+  /// synchronously.
+  Future get whenRemoved => _waitForState((state) => state.isRemoved);
+
+  /// Runs [callback] repeatedly until the node's asset has maintained the same
+  /// value for the duration.
+  ///
+  /// This will run [callback] as soon as the asset is available (synchronously
+  /// if it's available immediately). If the [state] changes at all while
+  /// waiting for the Future returned by [callback] to complete, it will be
+  /// re-run as soon as it completes and the asset is available again. This will
+  /// continue until [state] doesn't change at all.
+  ///
+  /// If this asset is removed, this will throw an [AssetNotFoundException] as
+  /// soon as [callback]'s Future is finished running.
+  Future tryUntilStable(Future callback(Asset asset)) {
+    return whenAvailable.then((asset) {
+      var modifiedDuringCallback = false;
+      var subscription;
+      subscription = onStateChange.listen((_) {
+        modifiedDuringCallback = true;
+        subscription.cancel();
+      });
+
+      return callback(asset).then((result) {
+        subscription.cancel();
+
+        // If the asset was modified at all while running the callback, the
+        // result was invalid and we should try again.
+        if (modifiedDuringCallback) return tryUntilStable(callback);
+        return result;
+      });
+    });
+  }
+
+  /// Returns a Future that completes as soon as the node is in a state that
+  /// matches [test].
+  ///
+  /// The Future completes synchronously if this is already in such a state.
+  Future<AssetState> _waitForState(bool test(AssetState state)) {
+    if (test(state)) return new Future.sync(() => state);
+    return onStateChange.firstWhere(test);
+  }
+
+  AssetNode._(this.id)
+      : _state = AssetState.DIRTY;
+
+  AssetNode._available(Asset asset)
+      : id = asset.id,
+        _asset = asset,
+        _state = AssetState.AVAILABLE;
+}
+
+/// The controller for an [AssetNode].
+///
+/// This controls which state the node is in.
+class AssetNodeController {
+  final AssetNode node;
+
+  /// Creates a controller for a dirty node.
+  AssetNodeController(AssetId id)
+      : node = new AssetNode._(id);
+
+  /// Creates a controller for an available node with the given concrete
+  /// [asset].
+  AssetNodeController.available(Asset asset)
+      : node = new AssetNode._available(asset);
+
+  /// Marks the node as [AssetState.DIRTY].
+  void setDirty() {
+    assert(node._state != AssetState.REMOVED);
+    node._state = AssetState.DIRTY;
+    node._asset = null;
+    node._stateChangeController.add(AssetState.DIRTY);
+  }
+
+  /// Marks the node as [AssetState.REMOVED].
+  ///
+  /// Once a node is marked as removed, it can't be marked as any other state.
+  /// If a new asset is created with the same id, it will get a new node.
+  void setRemoved() {
+    assert(node._state != AssetState.REMOVED);
+    node._state = AssetState.REMOVED;
+    node._asset = null;
+    node._stateChangeController.add(AssetState.REMOVED);
+  }
+
+  /// Marks the node as [AssetState.AVAILABLE] with the given concrete [asset].
+  ///
+  /// It's an error to mark an already-available node as available. It should be
+  /// marked as dirty first.
+  void setAvailable(Asset asset) {
+    assert(asset.id == node.id);
+    assert(node._state != AssetState.REMOVED);
+    assert(node._state != AssetState.AVAILABLE);
+    node._state = AssetState.AVAILABLE;
+    node._asset = asset;
+    node._stateChangeController.add(AssetState.AVAILABLE);
+  }
+}
+
+// TODO(nweiz): add an error state.
+/// An enum of states that an [AssetNode] can be in.
+class AssetState {
+  /// The node has a concrete asset loaded, available, and up-to-date. The asset
+  /// is accessible via [AssetNode.asset]. An asset can only be marked available
+  /// again from the [AssetState.DIRTY] state.
+  static final AVAILABLE = const AssetState._("available");
+
+  /// The asset is no longer available, possibly for good. A removed asset will
+  /// never enter another state.
+  static final REMOVED = const AssetState._("removed");
+
+  /// The asset will exist in the future (unless it's removed), but the concrete
+  /// asset is not yet available.
+  static final DIRTY = const AssetState._("dirty");
+
+  /// Whether this state is [AssetState.AVAILABLE].
+  bool get isAvailable => this == AssetState.AVAILABLE;
+
+  /// Whether this state is [AssetState.REMOVED].
+  bool get isRemoved => this == AssetState.REMOVED;
+
+  /// Whether this state is [AssetState.DIRTY].
+  bool get isDirty => this == AssetState.DIRTY;
+
+  final String name;
+
+  const AssetState._(this.name);
+
+  String toString() => name;
 }
diff --git a/pkg/barback/lib/src/asset_set.dart b/pkg/barback/lib/src/asset_set.dart
index f58e188..b432425 100644
--- a/pkg/barback/lib/src/asset_set.dart
+++ b/pkg/barback/lib/src/asset_set.dart
@@ -18,6 +18,18 @@
 class AssetSet extends IterableBase<Asset> {
   final _assets = new Map<AssetId, Asset>();
 
+  AssetSet();
+
+  /// Creates a new AssetSet from the contents of [other].
+  ///
+  /// If multiple assets in [other] have the same id, the last one takes
+  /// precedence.
+  AssetSet.from(Iterable<Asset> other) {
+    for (var asset in other) {
+      _assets[asset.id] = asset;
+    }
+  }
+
   Iterator<Asset> get iterator => _assets.values.iterator;
 
   int get length => _assets.length;
@@ -51,6 +63,9 @@
     return _assets.containsKey(id);
   }
 
+  /// If the set contains an [Asset] with [id], removes and returns it.
+  Asset removeId(AssetId id) => _assets.remove(id);
+
   /// Removes all assets from the set.
   void clear() {
     _assets.clear();
diff --git a/pkg/barback/lib/src/barback.dart b/pkg/barback/lib/src/barback.dart
new file mode 100644
index 0000000..2797c1a
--- /dev/null
+++ b/pkg/barback/lib/src/barback.dart
@@ -0,0 +1,85 @@
+// Copyright (c) 2013, 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 barback.barback;
+
+import 'dart:async';
+
+import 'asset.dart';
+import 'asset_id.dart';
+import 'asset_cascade.dart';
+import 'package_graph.dart';
+import 'package_provider.dart';
+
+/// A general-purpose asynchronous build dependency graph manager.
+///
+/// It consumes source assets (including Dart files) in a set of packages,
+/// runs transformations on them, and then tracks which sources have been
+/// modified and which transformations need to be re-run.
+///
+/// To do this, you give barback a [PackageProvider] which can yield a set of
+/// [Transformer]s and raw source [Asset]s. Then you tell it which input files
+/// have been added or modified by calling [updateSources]. Barback will
+/// automatically wire up the appropriate transformers to those inputs and
+/// start running them asynchronously. If a transformer produces outputs that
+/// can be consumed by other transformers, they will automatically be pipelined
+/// correctly.
+///
+/// You can then request assets (either source or generated) by calling
+/// [getAssetById]. This will wait for any necessary transformations and then
+/// return the asset.
+///
+/// When source files have been modified or removed, tell barback by calling
+/// [updateSources] and [removeSources] as appropriate. Barback will
+/// automatically track which transformations are affected by those changes and
+/// re-run them as needed.
+///
+/// Barback tries to be resilient to errors since assets are often in an
+/// in-progress state. When errors occur, they will be captured and emitted on
+/// the [errors] stream.
+class Barback {
+  /// The graph managed by this instance.
+  final PackageGraph _graph;
+
+  /// A stream that emits a [BuildResult] each time the build is completed,
+  /// whether or not it succeeded.
+  ///
+  /// This will emit a result only once every package's [AssetCascade] has
+  /// finished building.
+  ///
+  /// If an unexpected error in barback itself occurs, it will be emitted
+  /// through this stream's error channel.
+  Stream<BuildResult> get results => _graph.results;
+
+  /// A stream that emits any errors from the graph or the transformers.
+  ///
+  /// This emits errors as they're detected. If an error occurs in one part of
+  /// the graph, unrelated parts will continue building.
+  ///
+  /// This will not emit programming errors from barback itself. Those will be
+  /// emitted through the [results] stream's error channel.
+  Stream get errors => _graph.errors;
+
+  Barback(PackageProvider provider)
+      : _graph = new PackageGraph(provider);
+
+  /// Gets the asset identified by [id].
+  ///
+  /// If [id] is for a generated or transformed asset, this will wait until
+  /// it has been created and return it. If the asset cannot be found, throws
+  /// [AssetNotFoundException].
+  Future<Asset> getAssetById(AssetId id) => _graph.getAssetById(id);
+
+  /// Adds [sources] to the graph's known set of source assets.
+  ///
+  /// Begins applying any transforms that can consume any of the sources. If a
+  /// given source is already known, it is considered modified and all
+  /// transforms that use it will be re-applied.
+  void updateSources(Iterable<AssetId> sources) =>
+      _graph.updateSources(sources);
+
+  /// Removes [removed] from the graph's known set of source assets.
+  void removeSources(Iterable<AssetId> removed) =>
+      _graph.removeSources(removed);
+}
\ No newline at end of file
diff --git a/pkg/barback/lib/src/cancelable_future.dart b/pkg/barback/lib/src/cancelable_future.dart
new file mode 100644
index 0000000..043ad6c
--- /dev/null
+++ b/pkg/barback/lib/src/cancelable_future.dart
@@ -0,0 +1,40 @@
+// Copyright (c) 2013, 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 barback.cancelable_future;
+
+import 'dart:async';
+
+/// A wrapper for [Future] that can be cancelled.
+///
+/// When this is cancelled, that means it won't complete either successfully or
+/// with an error, regardless of whether the wrapped Future completes.
+/// Cancelling this won't stop whatever code is feeding the wrapped future from
+/// running.
+class CancelableFuture<T> implements Future<T> {
+  bool _canceled = false;
+  final _completer = new Completer<T>();
+
+  CancelableFuture(Future<T> inner) {
+    inner.then((result) {
+      if (_canceled) return;
+      _completer.complete(result);
+    }).catchError((error) {
+      if (_canceled) return;
+      _completer.completeError(error);
+    });
+  }
+
+  Stream<T> asStream() => _completer.future.asStream();
+  Future catchError(onError(asyncError), {bool test(error)}) =>
+    _completer.future.catchError(onError, test: test);
+  Future then(onValue(T value), {onError(error)}) =>
+    _completer.future.then(onValue, onError: onError);
+  Future<T> whenComplete(action()) => _completer.future.whenComplete(action);
+
+  /// Cancels this future.
+  void cancel() {
+    _canceled = true;
+  }
+}
diff --git a/pkg/barback/lib/src/package_provider.dart b/pkg/barback/lib/src/package_provider.dart
index 8506d14..031caf8 100644
--- a/pkg/barback/lib/src/package_provider.dart
+++ b/pkg/barback/lib/src/package_provider.dart
@@ -21,19 +21,15 @@
   /// dependencies.
   Iterable<String> get packages;
 
-  // TODO(rnystrom): Make this async.
-  /// The paths of all available asset files in [package], relative to the
-  /// package's root directory.
-  ///
-  /// You can pass [within], which should be the relative path to a directory
-  /// within the package, to only return the files within that subdirectory.
-  List<AssetId> listAssets(String package, {String within});
-
   /// Returns the list of transformer phases that are applicable to [package].
   ///
   /// The phases will be run in sequence, with the outputs of one pipelined into
   /// the next. All [Transformer]s in a single phase will be run in parallel.
   Iterable<Iterable<Transformer>> getTransformers(String package);
 
+  /// Loads an asset from disk.
+  ///
+  /// This should be re-entrant; it may be called multiple times with the same
+  /// id before the previously returned future has completed.
   Future<Asset> getAsset(AssetId id);
 }
diff --git a/pkg/barback/lib/src/phase.dart b/pkg/barback/lib/src/phase.dart
index e16f94b..4d2afb4 100644
--- a/pkg/barback/lib/src/phase.dart
+++ b/pkg/barback/lib/src/phase.dart
@@ -14,6 +14,7 @@
 import 'errors.dart';
 import 'transform_node.dart';
 import 'transformer.dart';
+import 'utils.dart';
 
 /// One phase in the ordered series of transformations in an [AssetCascade].
 ///
@@ -45,19 +46,32 @@
   /// phases, they will be the outputs from the previous phase.
   final inputs = new Map<AssetId, AssetNode>();
 
-  /// The transforms currently applicable to assets in [inputs].
+  /// The transforms currently applicable to assets in [inputs], indexed by
+  /// the ids of their primary inputs.
   ///
   /// These are the transforms that have been "wired up": they represent a
   /// repeatable transformation of a single concrete set of inputs. "dart2js"
   /// is a transformer. "dart2js on web/main.dart" is a transform.
-  final _transforms = new Set<TransformNode>();
+  final _transforms = new Map<AssetId, Set<TransformNode>>();
 
-  /// The nodes that are new in this phase since the last time [process] was
-  /// called.
+  /// Futures that will complete once the transformers that can consume a given
+  /// asset are determined.
   ///
-  /// When we process, we'll check these to see if we can hang new transforms
-  /// off them.
-  final _newInputs = new Set<AssetNode>();
+  /// Whenever an asset is added or modified, we need to asynchronously
+  /// determine which transformers can use it as their primary input. We can't
+  /// start processing until we know which transformers to run, and this allows
+  /// us to wait until we do.
+  var _adjustTransformersFutures = new Map<AssetId, Future>();
+
+  /// New asset nodes that were added while [_adjustTransformers] was still
+  /// being run on an old version of that asset.
+  var _pendingNewInputs = new Map<AssetId, AssetNode>();
+
+  /// The ids of assets that are emitted by transforms in this phase.
+  ///
+  /// This is used to detect collisions where multiple transforms emit the same
+  /// output.
+  final _outputs = new Set<AssetId>();
 
   /// The phase after this one.
   ///
@@ -66,133 +80,217 @@
 
   Phase(this.cascade, this._index, this._transformers, this._next);
 
-  /// Updates the phase's inputs with [updated] and removes [removed].
+  /// Adds a new asset as an input for this phase.
   ///
-  /// This marks any affected [transforms] as dirty or discards them if their
-  /// inputs are removed.
-  void updateInputs(AssetSet updated, Set<AssetId> removed) {
-    // Remove any nodes that are no longer being output. Handle removals first
-    // in case there are assets that were removed by one transform but updated
-    // by another. In that case, the update should win.
-    for (var id in removed) {
-      var node = inputs.remove(id);
+  /// [node] doesn't have to be [AssetState.AVAILABLE]. Once it is, the phase
+  /// will automatically begin determining which transforms can consume it as a
+  /// primary input. The transforms themselves won't be applied until [process]
+  /// is called, however.
+  ///
+  /// This should only be used for brand-new assets or assets that have been
+  /// removed and re-created. The phase will automatically handle updated assets
+  /// using the [AssetNode.onStateChange] stream.
+  void addInput(AssetNode node) {
+    // We remove [node.id] from [inputs] as soon as the node is removed rather
+    // than at the same time [node.id] is removed from [_transforms] so we don't
+    // have to wait on [_adjustTransformers]. It's important that [inputs] is
+    // always up-to-date so that the [AssetCascade] can look there for available
+    // assets.
+    inputs[node.id] = node;
+    node.whenRemoved.then((_) => inputs.remove(node.id));
 
-      // Every transform that was using it is dirty now.
-      if (node != null) {
-        node.consumers.forEach((consumer) => consumer.dirty());
-      }
+    if (!_adjustTransformersFutures.containsKey(node.id)) {
+      _transforms[node.id] = new Set<TransformNode>();
+      _adjustTransformers(node);
+      return;
     }
 
-    // Update and new or modified assets.
-    for (var asset in updated) {
-      var node = inputs[asset.id];
-      if (node == null) {
-        // It's a new node. Add it and remember it so we can see if any new
-        // transforms will consume it.
-        node = new AssetNode(asset);
-        inputs[asset.id] = node;
-        _newInputs.add(node);
-      } else {
-        node.updateAsset(asset);
-      }
-    }
+    // If an input is added while the same input is still being processed,
+    // that means that the asset was removed and recreated while
+    // [_adjustTransformers] was being run on the old value. We have to wait
+    // until that finishes, then run it again on whatever the newest version
+    // of that asset is.
+
+    // We may already be waiting for the existing [_adjustTransformers] call to
+    // finish. If so, all we need to do is change the node that will be loaded
+    // after it completes.
+    var containedKey = _pendingNewInputs.containsKey(node.id);
+    _pendingNewInputs[node.id] = node;
+    if (containedKey) return;
+
+    // If we aren't already waiting, start doing so.
+    _adjustTransformersFutures[node.id].then((_) {
+      assert(!_adjustTransformersFutures.containsKey(node.id));
+      assert(_pendingNewInputs.containsKey(node.id));
+      _transforms[node.id] = new Set<TransformNode>();
+      _adjustTransformers(_pendingNewInputs.remove(node.id));
+    }, onError: (_) {
+      // If there was a programmatic error while processing the old input,
+      // we don't want to just ignore it; it may have left the system in an
+      // inconsistent state. We also don't want to top-level it, so we
+      // ignore it here but don't start processing the new input. That way
+      // when [process] is called, the error will be piped through its
+      // return value.
+    }).catchError((e) {
+      // If our code above has a programmatic error, ensure it will be piped
+      // through [process] by putting it into [_adjustTransformersFutures].
+      _adjustTransformersFutures[node.id] = new Future.error(e);
+    });
+  }
+
+  /// Returns the input for this phase with the given [id], but only if that
+  /// input is known not to be consumed as a transformer's primary input.
+  ///
+  /// If the input is unavailable, or if the phase hasn't determined whether or
+  /// not any transformers will consume it as a primary input, null will be
+  /// returned instead. This means that the return value is guaranteed to always
+  /// be [AssetState.AVAILABLE].
+  AssetNode getUnconsumedInput(AssetId id) {
+    if (!inputs.containsKey(id)) return null;
+
+    // If the asset has transforms, it's not unconsumed.
+    if (!_transforms[id].isEmpty) return null;
+
+    // If we're working on figuring out if the asset has transforms, we can't
+    // prove that it's unconsumed.
+    if (_adjustTransformersFutures.containsKey(id)) return null;
+
+    // The asset should be available. If it were removed, it wouldn't be in
+    // _inputs, and if it were dirty, it'd be in _adjustTransformersFutures.
+    assert(inputs[id].state.isAvailable);
+    return inputs[id];
+  }
+
+  /// Asynchronously determines which transformers can consume [node] as a
+  /// primary input and creates transforms for them.
+  ///
+  /// This ensures that if [node] is modified or removed during or after the
+  /// time it takes to adjust its transformers, they're appropriately
+  /// re-adjusted. Its progress can be tracked in [_adjustTransformersFutures].
+  void _adjustTransformers(AssetNode node) {
+    // Once the input is available, hook up transformers for it. If it changes
+    // while that's happening, try again.
+    _adjustTransformersFutures[node.id] = node.tryUntilStable((asset) {
+      var oldTransformers = _transforms[node.id]
+          .map((transform) => transform.transformer).toSet();
+
+      return _removeStaleTransforms(asset)
+          .then((_) => _addFreshTransforms(node, oldTransformers));
+    }).then((_) {
+      // Now all the transforms are set up correctly and the asset is available
+      // for the time being. Set up handlers for when the asset changes in the
+      // future.
+      node.onStateChange.first.then((state) {
+        if (state.isRemoved) {
+          _transforms.remove(node.id);
+        } else {
+          _adjustTransformers(node);
+        }
+      }).catchError((e) {
+        _adjustTransformersFutures[node.id] = new Future.error(e);
+      });
+    }).catchError((error) {
+      if (error is! AssetNotFoundException || error.id != node.id) throw error;
+
+      // If the asset is removed, [tryUntilStable] will throw an
+      // [AssetNotFoundException]. In that case, just remove all transforms for
+      // the node.
+      _transforms.remove(node.id);
+    }).whenComplete(() {
+      _adjustTransformersFutures.remove(node.id);
+    });
+
+    // Don't top-level errors coming from the input processing. Any errors will
+    // eventually be piped through [process]'s returned Future.
+    _adjustTransformersFutures[node.id].catchError((_) {});
+  }
+
+  // Remove any old transforms that used to have [asset] as a primary asset but
+  // no longer apply to its new contents.
+  Future _removeStaleTransforms(Asset asset) {
+    return Future.wait(_transforms[asset.id].map((transform) {
+      // TODO(rnystrom): Catch all errors from isPrimary() and redirect to
+      // results.
+      return transform.transformer.isPrimary(asset).then((isPrimary) {
+        if (isPrimary) return;
+        _transforms[asset.id].remove(transform);
+        transform.remove();
+      });
+    }));
+  }
+
+  // Add new transforms for transformers that consider [node]'s asset to be a
+  // primary input.
+  //
+  // [oldTransformers] is the set of transformers that had [node] as a primary
+  // input prior to this. They don't need to be checked, since they were removed
+  // or preserved in [_removeStaleTransforms].
+  Future _addFreshTransforms(AssetNode node, Set<Transformer> oldTransformers) {
+    return Future.wait(_transformers.map((transformer) {
+      if (oldTransformers.contains(transformer)) return new Future.value();
+
+      // If the asset is unavailable, the results of this [_adjustTransformers]
+      // run will be discarded, so we can just short-circuit.
+      if (node.asset == null) return new Future.value();
+
+      // We can safely access [node.asset] here even though it might have
+      // changed since (as above) if it has, [_adjustTransformers] will just be
+      // re-run.
+      // TODO(rnystrom): Catch all errors from isPrimary() and redirect to
+      // results.
+      return transformer.isPrimary(node.asset).then((isPrimary) {
+        if (!isPrimary) return;
+        _transforms[node.id].add(new TransformNode(this, transformer, node));
+      });
+    }));
   }
 
   /// Processes this phase.
   ///
-  /// For all new inputs, it tries to see if there are transformers that can
-  /// consume them. Then all applicable transforms are applied.
-  ///
   /// Returns a future that completes when processing is done. If there is
   /// nothing to process, returns `null`.
   Future process() {
-    var future = _processNewInputs();
-    if (future == null) {
-      return _processTransforms();
-    }
-
-    return future.then((_) => _processTransforms());
+    if (_adjustTransformersFutures.isEmpty) return _processTransforms();
+    return _waitForInputs().then((_) => _processTransforms());
   }
 
-  /// Creates new transforms for any new inputs that are applicable.
-  Future _processNewInputs() {
-    if (_newInputs.isEmpty) return null;
-
-    var futures = [];
-    for (var node in _newInputs) {
-      for (var transformer in _transformers) {
-        // TODO(rnystrom): Catch all errors from isPrimary() and redirect
-        // to results.
-        futures.add(transformer.isPrimary(node.asset).then((isPrimary) {
-          if (!isPrimary) return;
-          var transform = new TransformNode(this, transformer, node);
-          node.consumers.add(transform);
-          _transforms.add(transform);
-        }));
-      }
-    }
-
-    _newInputs.clear();
-
-    return Future.wait(futures);
+  Future _waitForInputs() {
+    if (_adjustTransformersFutures.isEmpty) return new Future.value();
+    return Future.wait(_adjustTransformersFutures.values)
+        .then((_) => _waitForInputs());
   }
 
   /// Applies all currently wired up and dirty transforms.
-  ///
-  /// Passes their outputs to the next phase.
   Future _processTransforms() {
     // Convert this to a list so we can safely modify _transforms while
     // iterating over it.
-    var dirtyTransforms = _transforms.where((transform) => transform.isDirty)
-        .toList();
+    var dirtyTransforms =
+        flatten(_transforms.values.map((transforms) => transforms.toList()))
+        .where((transform) => transform.isDirty).toList();
     if (dirtyTransforms.isEmpty) return null;
 
-    return Future.wait(dirtyTransforms.map((transform) {
-      if (inputs.containsKey(transform.primary.id)) return transform.apply();
+    return Future.wait(dirtyTransforms.map((transform) => transform.apply()))
+        .then((allNewOutputs) {
+      var newOutputs = allNewOutputs.reduce((set1, set2) => set1.union(set2));
 
-      // If the primary input for the transform has been removed, get rid of it
-      // and all its outputs.
-      _transforms.remove(transform);
-      return new Future.value(
-          new TransformOutputs(new AssetSet(), transform.outputs));
-    })).then((transformOutputs) {
-      // Collect all of the outputs. Since the transforms are run in parallel,
-      // we have to be careful here to ensure that the result is deterministic
-      // and not influenced by the order that transforms complete.
-      var updated = new AssetSet();
-      var removed = new Set<AssetId>();
       var collisions = new Set<AssetId>();
-
-      // Handle the generated outputs of all transforms first.
-      for (var outputs in transformOutputs) {
-        // Collect the outputs of all transformers together.
-        for (var asset in outputs.updated) {
-          if (updated.containsId(asset.id)) {
-            // Report a collision.
-            collisions.add(asset.id);
-          } else {
-            // TODO(rnystrom): In the case of a collision, the asset that
-            // "wins" is chosen non-deterministically. Do something better.
-            updated.add(asset);
-          }
+      for (var newOutput in newOutputs) {
+        if (_outputs.contains(newOutput.id)) {
+          collisions.add(newOutput.id);
+        } else {
+          _next.addInput(newOutput);
+          _outputs.add(newOutput.id);
+          newOutput.whenRemoved.then((_) => _outputs.remove(newOutput.id));
         }
-
-        // Track any assets no longer output by this transform. We don't
-        // handle the case where *another* transform generates the asset
-        // no longer generated by this one. updateInputs() handles that.
-        removed.addAll(outputs.removed);
       }
 
-      // Report any collisions in deterministic order.
+      // Report collisions in a deterministic order.
       collisions = collisions.toList();
       collisions.sort((a, b) => a.toString().compareTo(b.toString()));
       for (var collision in collisions) {
         cascade.reportError(new AssetCollisionException(collision));
         // TODO(rnystrom): Define what happens after a collision occurs.
       }
-
-      // Pass the outputs to the next phase.
-      _next.updateInputs(updated, removed);
     });
   }
 }
diff --git a/pkg/barback/lib/src/transform.dart b/pkg/barback/lib/src/transform.dart
index cb51753..77800db 100644
--- a/pkg/barback/lib/src/transform.dart
+++ b/pkg/barback/lib/src/transform.dart
@@ -19,9 +19,8 @@
 /// Lets [TransformNode] create [Transforms] without giving a [Transform]
 /// itself a public constructor, which would be visible to external users.
 /// Unlike the [Transform] class, this function is not exported by barback.dart.
-Transform createTransform(TransformNode node, Set<AssetNode> inputs,
-                          AssetSet outputs) =>
-    new Transform._(node, inputs, outputs);
+Transform createTransform(TransformNode node, AssetSet outputs) =>
+    new Transform._(node, outputs);
 
 /// While a [Transformer] represents a *kind* of transformation, this defines
 /// one specific usage of it on a set of files.
@@ -33,7 +32,6 @@
 class Transform {
   final TransformNode _node;
 
-  final Set<AssetNode> _inputs;
   final AssetSet _outputs;
 
   /// Gets the ID of the primary input for this transformation.
@@ -50,28 +48,13 @@
   /// Gets the asset for the primary input.
   Future<Asset> get primaryInput => getInput(primaryId);
 
-  Transform._(this._node, this._inputs, this._outputs);
+  Transform._(this._node, this._outputs);
 
   /// Gets the asset for for an input [id].
   ///
   /// If an input with that ID cannot be found, throws an
   /// [AssetNotFoundException].
-  Future<Asset> getInput(AssetId id) {
-    return newFuture(() {
-      var node = _node.phase.inputs[id];
-      // TODO(rnystrom): Need to handle passthrough where an asset from a
-      // previous phase can be found.
-
-      // Throw if the input isn't found. This ensures the transformer's apply
-      // is exited. We'll then catch this and report it through the proper
-      // results stream.
-      if (node == null) throw new MissingInputException(id);
-
-      // Keep track of which assets this transform depends on.
-      _inputs.add(node);
-      return node.asset;
-    });
-  }
+  Future<Asset> getInput(AssetId id) => _node.getInput(id);
 
   /// Stores [output] as the output created by this transformation.
   ///
diff --git a/pkg/barback/lib/src/transform_node.dart b/pkg/barback/lib/src/transform_node.dart
index 84e42c0..863bac5 100644
--- a/pkg/barback/lib/src/transform_node.dart
+++ b/pkg/barback/lib/src/transform_node.dart
@@ -14,6 +14,7 @@
 import 'phase.dart';
 import 'transform.dart';
 import 'transformer.dart';
+import 'utils.dart';
 
 /// Describes a transform on a set of assets and its relationship to the build
 /// dependency graph.
@@ -25,94 +26,157 @@
   final Phase phase;
 
   /// The [Transformer] to apply to this node's inputs.
-  final Transformer _transformer;
+  final Transformer transformer;
 
   /// The node for the primary asset this transform depends on.
   final AssetNode primary;
 
+  /// The subscription to [primary]'s [AssetNode.onStateChange] stream.
+  StreamSubscription _primarySubscription;
+
   /// True if an input has been modified since the last time this transform
-  /// was run.
+  /// began running.
   bool get isDirty => _isDirty;
   var _isDirty = true;
 
-  /// The inputs read by this transform the last time it was run.
+  /// The subscriptions to each input's [AssetNode.onStateChange] stream.
+  var _inputSubscriptions = new Map<AssetId, StreamSubscription>();
+
+  /// The controllers for the asset nodes emitted by this node.
+  var _outputControllers = new Map<AssetId, AssetNodeController>();
+
+  TransformNode(this.phase, this.transformer, this.primary) {
+    _primarySubscription = primary.onStateChange.listen((state) {
+      if (state.isRemoved) {
+        remove();
+      } else {
+        _dirty();
+      }
+    });
+  }
+
+  /// Marks this transform as removed.
   ///
-  /// Used to tell if an input was removed in a later run.
-  var _inputs = new Set<AssetNode>();
-
-  /// The outputs created by this transform the last time it was run.
-  ///
-  /// Used to tell if an output was removed in a later run.
-  Set<AssetId> get outputs => _outputs;
-  var _outputs = new Set<AssetId>();
-
-  TransformNode(this.phase, this._transformer, this.primary);
-
-  /// Marks this transform as needing to be run.
-  void dirty() {
+  /// This causes all of the transform's outputs to be marked as removed as
+  /// well. Normally this will be automatically done internally based on events
+  /// from the primary input, but it's possible for a transform to no longer be
+  /// valid even if its primary input still exists.
+  void remove() {
     _isDirty = true;
+    _primarySubscription.cancel();
+    for (var subscription in _inputSubscriptions.values) {
+      subscription.cancel();
+    }
+    for (var controller in _outputControllers.values) {
+      controller.setRemoved();
+    }
+  }
+
+  /// Marks this transform as dirty.
+  ///
+  /// This causes all of the transform's outputs to be marked as dirty as well.
+  void _dirty() {
+    _isDirty = true;
+    for (var controller in _outputControllers.values) {
+      controller.setDirty();
+    }
   }
 
   /// Applies this transform.
   ///
-  /// Returns a [TransformOutputs] describing the resulting outputs compared to
-  /// previous runs.
-  Future<TransformOutputs> apply() {
-    var newInputs = new Set<AssetNode>();
+  /// Returns a set of asset nodes representing the outputs from this transform
+  /// that weren't emitted last time it was run.
+  Future<Set<AssetNode>> apply() {
     var newOutputs = new AssetSet();
-    var transform = createTransform(this, newInputs, newOutputs);
-    return _transformer.apply(transform).catchError((error) {
-      // Catch all transformer errors and pipe them to the results stream. This
-      // is so a broken transformer doesn't take down the whole graph.
+    var transform = createTransform(this, newOutputs);
+
+    // Clear all the old input subscriptions. If an input is re-used, we'll
+    // re-subscribe.
+    for (var subscription in _inputSubscriptions.values) {
+      subscription.cancel();
+    }
+    _inputSubscriptions.clear();
+
+    _isDirty = false;
+    return transformer.apply(transform).catchError((error) {
+      // If the transform became dirty while processing, ignore any errors from
+      // it.
+      if (_isDirty) return;
+
+      // Catch all transformer errors and pipe them to the results stream.
+      // This is so a broken transformer doesn't take down the whole graph.
       phase.cascade.reportError(error);
 
       // Don't allow partial results from a failed transform.
       newOutputs.clear();
     }).then((_) {
-      _isDirty = false;
+      if (_isDirty) return [];
 
-      // Stop watching any inputs that were removed.
-      for (var oldInput in _inputs) {
-        oldInput.consumers.remove(this);
-      }
-
-      // Watch any new inputs so this transform will be re-processed when an
-      // input is modified.
-      for (var newInput in newInputs) {
-        newInput.consumers.add(this);
-      }
-
-      _inputs = newInputs;
-
-      // See which outputs are missing from the last run.
-      var outputIds = newOutputs.map((asset) => asset.id).toSet();
-      var invalidIds = outputIds
-          .where((id) => id.package != phase.cascade.package).toSet();
-      outputIds.removeAll(invalidIds);
-
-      for (var id in invalidIds) {
-        // TODO(nweiz): report this as a warning rather than a failing error.
-        phase.cascade.reportError(
-            new InvalidOutputException(phase.cascade.package, id));
-      }
-
-      var removed = _outputs.difference(outputIds);
-      _outputs = outputIds;
-
-      return new TransformOutputs(newOutputs, removed);
+      return _adjustOutputs(newOutputs);
     });
   }
-}
 
-/// The result of running a [Transform], compared to the previous time it was
-/// applied.
-class TransformOutputs {
-  /// The outputs that are new or were modified since the last run.
-  final AssetSet updated;
+  Future<Asset> getInput(AssetId id) {
+    return newFuture(() {
+      var node = phase.inputs[id];
+      // TODO(rnystrom): Need to handle passthrough where an asset from a
+      // previous phase can be found.
 
-  /// The outputs that were created by the previous run but were not generated
-  /// by the most recent run.
-  final Set<AssetId> removed;
+      // Throw if the input isn't found. This ensures the transformer's apply
+      // is exited. We'll then catch this and report it through the proper
+      // results stream.
+      if (node == null) throw new MissingInputException(id);
 
-  TransformOutputs(this.updated, this.removed);
+      // If the asset node is found, wait until its contents are actually
+      // available before we return them.
+      return node.whenAvailable.then((asset) {
+        _inputSubscriptions.putIfAbsent(node.id,
+            () => node.onStateChange.listen((_) => _dirty()));
+
+        return asset;
+      }).catchError((error) {
+        if (error is! AssetNotFoundException || error.id != id) throw error;
+        // If the node was removed before it could be loaded, treat it as though
+        // it never existed and throw a MissingInputException.
+        throw new MissingInputException(id);
+      });
+    });
+  }
+
+  /// Adjusts the outputs of the transform to reflect the outputs emitted on its
+  /// most recent run.
+  Set<AssetNode> _adjustOutputs(AssetSet newOutputs) {
+    // Any ids that are for a different package are invalid.
+    var invalidIds = newOutputs
+        .map((asset) => asset.id)
+        .where((id) => id.package != phase.cascade.package)
+        .toSet();
+    for (var id in invalidIds) {
+      newOutputs.removeId(id);
+      // TODO(nweiz): report this as a warning rather than a failing error.
+      phase.cascade.reportError(
+          new InvalidOutputException(phase.cascade.package, id));
+    }
+
+    // Remove outputs that used to exist but don't anymore.
+    for (var id in _outputControllers.keys.toList()) {
+      if (newOutputs.containsId(id)) continue;
+      _outputControllers.remove(id).setRemoved();
+    }
+
+    var brandNewOutputs = new Set<AssetNode>();
+    // Store any new outputs or new contents for existing outputs.
+    for (var asset in newOutputs) {
+      var controller = _outputControllers[asset.id];
+      if (controller != null) {
+        controller.setAvailable(asset);
+      } else {
+        var controller = new AssetNodeController.available(asset);
+        _outputControllers[asset.id] = controller;
+        brandNewOutputs.add(controller.node);
+      }
+    }
+
+    return brandNewOutputs;
+  }
 }
diff --git a/pkg/barback/test/asset_set_test.dart b/pkg/barback/test/asset_set_test.dart
index 6cb1eb8..5b6b652 100644
--- a/pkg/barback/test/asset_set_test.dart
+++ b/pkg/barback/test/asset_set_test.dart
@@ -18,11 +18,25 @@
 
   var fooId = new AssetId.parse("app|foo.txt");
   var barId = new AssetId.parse("app|bar.txt");
+  var bazId = new AssetId.parse("app|baz.txt");
+
+  group(".from()", () {
+    test("creates a set from an iterable", () {
+      var set = new AssetSet.from([
+        new Asset.fromString(fooId, "foo"),
+        new Asset.fromString(barId, "bar")
+      ]);
+
+      expect(set.containsId(fooId), isTrue);
+      expect(set.containsId(barId), isTrue);
+      expect(set.containsId(bazId), isFalse);
+    });
+  });
 
   group("[] operator", () {
     test("gets an asset with the given ID", () {
       var set = new AssetSet();
-      var foo = new MockAsset(fooId, "foo");
+      var foo = new Asset.fromString(fooId, "foo");
       set.add(foo);
 
       expect(set[fooId], equals(foo));
@@ -37,21 +51,21 @@
   group(".add()", () {
     test("adds the asset to the set", () {
       var set = new AssetSet();
-      var foo = new MockAsset(fooId, "foo");
+      var foo = new Asset.fromString(fooId, "foo");
       set.add(foo);
       expect(set.contains(foo), isTrue);
     });
 
     test("replaces a previously added asset with that ID", () {
       var set = new AssetSet();
-      set.add(new MockAsset(fooId, "before"));
-      set.add(new MockAsset(fooId, "after"));
-      expect(set[fooId].contents, equals("after"));
+      set.add(new Asset.fromString(fooId, "before"));
+      set.add(new Asset.fromString(fooId, "after"));
+      expect(set[fooId].readAsString(), completion(equals("after")));
     });
 
     test("returns the added item", () {
       var set = new AssetSet();
-      var foo = new MockAsset(fooId, "foo");
+      var foo = new Asset.fromString(fooId, "foo");
       expect(set.add(foo), equals(foo));
     });
   });
@@ -59,8 +73,8 @@
   group(".addAll()", () {
     test("adds the assets to the set", () {
       var set = new AssetSet();
-      var foo = new MockAsset(fooId, "foo");
-      var bar = new MockAsset(barId, "bar");
+      var foo = new Asset.fromString(fooId, "foo");
+      var bar = new Asset.fromString(barId, "bar");
       set.addAll([foo, bar]);
       expect(set.contains(foo), isTrue);
       expect(set.contains(bar), isTrue);
@@ -68,17 +82,17 @@
 
     test("replaces assets earlier in the sequence with later ones", () {
       var set = new AssetSet();
-      var foo1 = new MockAsset(fooId, "before");
-      var foo2 = new MockAsset(fooId, "after");
+      var foo1 = new Asset.fromString(fooId, "before");
+      var foo2 = new Asset.fromString(fooId, "after");
       set.addAll([foo1, foo2]);
-      expect(set[fooId].contents, equals("after"));
+      expect(set[fooId].readAsString(), completion(equals("after")));
     });
   });
 
   group(".clear()", () {
     test("empties the set", () {
       var set = new AssetSet();
-      var foo = new MockAsset(fooId, "foo");
+      var foo = new Asset.fromString(fooId, "foo");
       set.add(foo);
       set.clear();
 
@@ -90,8 +104,8 @@
   group(".contains()", () {
     test("returns true if the asset is in the set", () {
       var set = new AssetSet();
-      var foo = new MockAsset(fooId, "foo");
-      var bar = new MockAsset(barId, "bar");
+      var foo = new Asset.fromString(fooId, "foo");
+      var bar = new Asset.fromString(barId, "bar");
       set.add(foo);
 
       expect(set.contains(foo), isTrue);
@@ -102,11 +116,38 @@
   group(".containsId()", () {
     test("returns true if an asset with the ID is in the set", () {
       var set = new AssetSet();
-      var foo = new MockAsset(fooId, "foo");
+      var foo = new Asset.fromString(fooId, "foo");
       set.add(foo);
 
       expect(set.containsId(fooId), isTrue);
       expect(set.containsId(barId), isFalse);
     });
   });
+
+  group(".removeId()", () {
+    test("removes the asset with the ID from the set", () {
+      var set = new AssetSet();
+      var foo = new Asset.fromString(fooId, "foo");
+      set.add(foo);
+
+      set.removeId(fooId);
+      expect(set.containsId(fooId), isFalse);
+    });
+
+    test("returns the removed asset", () {
+      var set = new AssetSet();
+      var foo = new Asset.fromString(fooId, "foo");
+      set.add(foo);
+
+      expect(set.removeId(fooId).readAsString(), completion(equals("foo")));
+    });
+
+    test("returns null when removing an asset not in the set", () {
+      var set = new AssetSet();
+      var foo = new Asset.fromString(fooId, "foo");
+      set.add(foo);
+
+      expect(set.removeId(barId), isNull);
+    });
+  });
 }
diff --git a/pkg/barback/test/cancelable_future_test.dart b/pkg/barback/test/cancelable_future_test.dart
new file mode 100644
index 0000000..d5f9ae4
--- /dev/null
+++ b/pkg/barback/test/cancelable_future_test.dart
@@ -0,0 +1,62 @@
+// Copyright (c) 2013, 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 barback.test.cancelable_future_test;
+
+import 'dart:async';
+
+import 'package:barback/src/cancelable_future.dart';
+import 'package:barback/src/utils.dart';
+import 'package:unittest/unittest.dart';
+
+import 'utils.dart';
+
+main() {
+  initConfig();
+
+  var completer;
+  var future;
+  setUp(() {
+    completer = new Completer();
+    future = new CancelableFuture(completer.future);
+  });
+
+  group("when not canceled", () {
+    test("correctly completes successfully", () {
+      expect(future, completion(equals("success")));
+      completer.complete("success");
+    });
+
+    test("correctly completes with an error", () {
+      expect(future, throwsA(equals("error")));
+      completer.completeError("error");
+    });
+  });
+
+  group("when canceled", () {
+    test("never completes successfully", () {
+      var completed = false;
+      future.whenComplete(() {
+        completed = true;
+      });
+
+      future.cancel();
+      completer.complete("success");
+
+      expect(pumpEventQueue().then((_) => completed), completion(isFalse));
+    });
+
+    test("never completes with an error", () {
+      var completed = false;
+      future.catchError((_) {}).whenComplete(() {
+        completed = true;
+      });
+
+      future.cancel();
+      completer.completeError("error");
+
+      expect(pumpEventQueue().then((_) => completed), completion(isFalse));
+    });
+  });
+}
diff --git a/pkg/barback/test/package_graph/errors_test.dart b/pkg/barback/test/package_graph/errors_test.dart
index 0653022..973155b 100644
--- a/pkg/barback/test/package_graph/errors_test.dart
+++ b/pkg/barback/test/package_graph/errors_test.dart
@@ -26,6 +26,22 @@
     buildShouldFail([isAssetCollisionException("app|foo.b")]);
   });
 
+  test("errors if a new transformer outputs the same file as an old "
+      "transformer", () {
+    initGraph(["app|foo.a", "app|foo.b"], {"app": [
+      [
+        new RewriteTransformer("a", "c"),
+        new RewriteTransformer("b", "c")
+      ]
+    ]});
+    updateSources(["app|foo.a"]);
+    expectAsset("app|foo.c", "foo.c");
+    buildShouldSucceed();
+
+    schedule(() => updateSources(["app|foo.b"]));
+    buildShouldFail([isAssetCollisionException("app|foo.c")]);
+  });
+
   test("does not report asset not found errors in results", () {
     initGraph(["app|bar.txt"]);
 
@@ -107,9 +123,7 @@
     buildShouldFail([equals(BadTransformer.ERROR)]);
   });
 
-  // TODO(rnystrom): Is this the behavior we expect? If a transformer fails
-  // to transform a file, should we just skip past it to the source?
-  test("yields a source if a transform fails on it", () {
+  test("doesn't yield a source if a transform fails on it", () {
     initGraph(["app|foo.txt"], {"app": [
       [new BadTransformer(["app|foo.txt"])]
     ]});
@@ -118,7 +132,7 @@
       updateSources(["app|foo.txt"]);
     });
 
-    expectAsset("app|foo.txt");
+    expectNoAsset("app|foo.txt");
   });
 
   test("catches errors even if nothing is waiting for process results", () {
@@ -172,4 +186,13 @@
       equals(BadTransformer.ERROR)
     ]);
   });
+
+  test("an error loading an asset removes the asset from the graph", () {
+    initGraph(["app|foo.txt"]);
+
+    setAssetError("app|foo.txt");
+    schedule(() => updateSources(["app|foo.txt"]));
+    expectNoAsset("app|foo.txt");
+    buildShouldFail([isMockLoadException("app|foo.txt")]);
+  });
 }
diff --git a/pkg/barback/test/package_graph/source_test.dart b/pkg/barback/test/package_graph/source_test.dart
index 0185679..e6627e7 100644
--- a/pkg/barback/test/package_graph/source_test.dart
+++ b/pkg/barback/test/package_graph/source_test.dart
@@ -7,6 +7,7 @@
 import 'dart:async';
 
 import 'package:barback/barback.dart';
+import 'package:barback/src/utils.dart';
 import 'package:scheduled_test/scheduled_test.dart';
 
 import '../utils.dart';
@@ -112,6 +113,24 @@
     buildShouldSucceed();
   });
 
+  test("reloads an asset that's updated while loading", () {
+    initGraph({"app|foo.txt": "foo"});
+
+    pauseProvider();
+    schedule(() {
+      // The mock provider synchronously loads the value of the assets, so this
+      // will kick off two loads with different values. The second one should
+      // win.
+      updateSources(["app|foo.txt"]);
+      modifyAsset("app|foo.txt", "bar");
+      updateSources(["app|foo.txt"]);
+    });
+
+    resumeProvider();
+    expectAsset("app|foo.txt", "bar");
+    buildShouldSucceed();
+  });
+
   test("restarts a build if a source is updated while sources are loading", () {
     var transformer = new RewriteTransformer("txt", "out");
     initGraph(["app|foo.txt", "app|other.bar"], {"app": [[transformer]]});
diff --git a/pkg/barback/test/package_graph/transform_test.dart b/pkg/barback/test/package_graph/transform_test.dart
index bcb7c33..670848a 100644
--- a/pkg/barback/test/package_graph/transform_test.dart
+++ b/pkg/barback/test/package_graph/transform_test.dart
@@ -7,6 +7,7 @@
 import 'dart:async';
 
 import 'package:barback/barback.dart';
+import 'package:barback/src/utils.dart';
 import 'package:scheduled_test/scheduled_test.dart';
 
 import '../utils.dart';
@@ -104,8 +105,8 @@
     var transformerB = new RewriteTransformer("txt", "b");
     initGraph(["app|foo.txt"], {"app": [[transformerA, transformerB]]});
 
-    transformerA.wait();
-    transformerB.wait();
+    transformerA.pauseApply();
+    transformerB.pauseApply();
 
     schedule(() {
       updateSources(["app|foo.txt"]);
@@ -119,8 +120,8 @@
       expect(transformerA.isRunning, isTrue);
       expect(transformerB.isRunning, isTrue);
 
-      transformerA.complete();
-      transformerB.complete();
+      transformerA.resumeApply();
+      transformerB.resumeApply();
     });
 
     expectAsset("app|foo.a", "foo.a");
@@ -128,6 +129,18 @@
     buildShouldSucceed();
   });
 
+  test("outputs are inaccessible once used", () {
+    initGraph(["app|foo.a"], {"app": [
+      [new RewriteTransformer("a", "b")],
+      [new RewriteTransformer("a", "c")]
+    ]});
+    updateSources(["app|foo.a"]);
+    expectAsset("app|foo.b", "foo.b");
+    expectNoAsset("app|foo.a");
+    expectNoAsset("app|foo.c");
+    buildShouldSucceed();
+  });
+
   test("does not reapply transform when inputs are not modified", () {
     var transformer = new RewriteTransformer("blub", "blab");
     initGraph(["app|foo.blub"], {"app": [[transformer]]});
@@ -186,10 +199,8 @@
     buildShouldSucceed();
 
     // Remove the dependency on the non-primary input.
-    schedule(() {
-      modifyAsset("app|a.txt", "a.inc");
-      updateSources(["app|a.txt"]);
-    });
+    modifyAsset("app|a.txt", "a.inc");
+    schedule(() => updateSources(["app|a.txt"]));
 
     // Process it again.
     expectAsset("app|a.out", "a");
@@ -269,8 +280,25 @@
     buildShouldSucceed();
   });
 
+  test("discards outputs from a transform whose primary input is removed "
+      "during processing", () {
+    var rewrite = new RewriteTransformer("txt", "out");
+    initGraph(["app|foo.txt"], {"app": [[rewrite]]});
+
+    rewrite.pauseApply();
+    updateSources(["app|foo.txt"]);
+    schedule(() => rewrite.started);
+    schedule(() {
+      removeSources(["app|foo.txt"]);
+      rewrite.resumeApply();
+    });
+
+    expectNoAsset("app|foo.out");
+    buildShouldSucceed();
+  });
+
   test("reapplies a transform when a non-primary input changes", () {
-   initGraph({
+    initGraph({
       "app|a.txt": "a.inc",
       "app|a.inc": "a"
     }, {"app": [[new ManyToOneTransformer("txt")]]});
@@ -279,20 +307,81 @@
     expectAsset("app|a.out", "a");
     buildShouldSucceed();
 
-    schedule(() {
-      modifyAsset("app|a.inc", "after");
-      updateSources(["app|a.inc"]);
-    });
+    modifyAsset("app|a.inc", "after");
+    schedule(() => updateSources(["app|a.inc"]));
 
     expectAsset("app|a.out", "after");
     buildShouldSucceed();
   });
 
+  test("applies a transform when it becomes newly primary", () {
+    initGraph({
+      "app|foo.txt": "this",
+    }, {"app": [[new CheckContentTransformer("that", " and the other")]]});
+
+    updateSources(["app|foo.txt"]);
+    expectAsset("app|foo.txt", "this");
+    buildShouldSucceed();
+
+    modifyAsset("app|foo.txt", "that");
+    schedule(() => updateSources(["app|foo.txt"]));
+
+    expectAsset("app|foo.txt", "that and the other");
+    buildShouldSucceed();
+  });
+
+  test("applies the correct transform if an asset is modified during isPrimary",
+      () {
+    var check1 = new CheckContentTransformer("first", "#1");
+    var check2 = new CheckContentTransformer("second", "#2");
+    initGraph({
+      "app|foo.txt": "first",
+    }, {"app": [[check1, check2]]});
+
+    check1.pauseIsPrimary("app|foo.txt");
+    updateSources(["app|foo.txt"]);
+    // Ensure that we're waiting on check1's isPrimary.
+    schedule(pumpEventQueue);
+
+    modifyAsset("app|foo.txt", "second");
+    schedule(() {
+      updateSources(["app|foo.txt"]);
+      check1.resumeIsPrimary("app|foo.txt");
+    });
+
+    expectAsset("app|foo.txt", "second#2");
+    buildShouldSucceed();
+  });
+
+  test("applies the correct transform if an asset is removed and added during "
+      "isPrimary", () {
+    var check1 = new CheckContentTransformer("first", "#1");
+    var check2 = new CheckContentTransformer("second", "#2");
+    initGraph({
+      "app|foo.txt": "first",
+    }, {"app": [[check1, check2]]});
+
+    check1.pauseIsPrimary("app|foo.txt");
+    updateSources(["app|foo.txt"]);
+    // Ensure that we're waiting on check1's isPrimary.
+    schedule(pumpEventQueue);
+
+    schedule(() => removeSources(["app|foo.txt"]));
+    modifyAsset("app|foo.txt", "second");
+    schedule(() {
+      updateSources(["app|foo.txt"]);
+      check1.resumeIsPrimary("app|foo.txt");
+    });
+
+    expectAsset("app|foo.txt", "second#2");
+    buildShouldSucceed();
+  });
+
   test("restarts processing if a change occurs during processing", () {
     var transformer = new RewriteTransformer("txt", "out");
     initGraph(["app|foo.txt"], {"app": [[transformer]]});
 
-    transformer.wait();
+    transformer.pauseApply();
 
     schedule(() {
       updateSources(["app|foo.txt"]);
@@ -304,10 +393,7 @@
     schedule(() {
       // Now update the graph during it.
       updateSources(["app|foo.txt"]);
-    });
-
-    schedule(() {
-      transformer.complete();
+      transformer.resumeApply();
     });
 
     expectAsset("app|foo.out", "foo.out");
@@ -318,6 +404,108 @@
     });
   });
 
+  test("aborts processing if the primary input is removed during processing",
+      () {
+    var transformer = new RewriteTransformer("txt", "out");
+    initGraph(["app|foo.txt"], {"app": [[transformer]]});
+
+    transformer.pauseApply();
+
+    schedule(() {
+      updateSources(["app|foo.txt"]);
+
+      // Wait for the transform to start.
+      return transformer.started;
+    });
+
+    schedule(() {
+      // Now remove its primary input while it's running.
+      removeSources(["app|foo.txt"]);
+      transformer.resumeApply();
+    });
+
+    expectNoAsset("app|foo.out");
+    buildShouldSucceed();
+
+    schedule(() {
+      expect(transformer.numRuns, equals(1));
+    });
+  });
+
+  test("restarts processing if a change to a new secondary input occurs during "
+      "processing", () {
+    var transformer = new ManyToOneTransformer("txt");
+    initGraph({
+      "app|foo.txt": "bar.inc",
+      "app|bar.inc": "bar"
+    }, {"app": [[transformer]]});
+
+    transformer.pauseApply();
+
+    updateSources(["app|foo.txt", "app|bar.inc"]);
+    // Wait for the transform to start.
+    schedule(() => transformer.started);
+
+    // Give the transform time to load bar.inc the first time.
+    schedule(pumpEventQueue);
+
+    // Now update the secondary input before the transform finishes.
+    modifyAsset("app|bar.inc", "baz");
+    schedule(() => updateSources(["app|bar.inc"]));
+    // Give bar.inc enough time to be loaded and marked available before the
+    // transformer completes.
+    schedule(pumpEventQueue);
+
+    schedule(transformer.resumeApply);
+
+    expectAsset("app|foo.out", "baz");
+    buildShouldSucceed();
+
+    schedule(() {
+      expect(transformer.numRuns, equals(2));
+    });
+  });
+
+  test("doesn't restart processing if a change to an old secondary input "
+      "occurs during processing", () {
+    var transformer = new ManyToOneTransformer("txt");
+    initGraph({
+      "app|foo.txt": "bar.inc",
+      "app|bar.inc": "bar",
+      "app|baz.inc": "baz"
+    }, {"app": [[transformer]]});
+
+    updateSources(["app|foo.txt", "app|bar.inc", "app|baz.inc"]);
+    expectAsset("app|foo.out", "bar");
+    buildShouldSucceed();
+
+    schedule(transformer.pauseApply);
+    modifyAsset("app|foo.txt", "baz.inc");
+    schedule(() {
+      updateSources(["app|foo.txt"]);
+      // Wait for the transform to start.
+      return transformer.started;
+    });
+
+    // Now update the old secondary input before the transform finishes.
+    modifyAsset("app|bar.inc", "new bar");
+    schedule(() => updateSources(["app|bar.inc"]));
+    // Give bar.inc enough time to be loaded and marked available before the
+    // transformer completes.
+    schedule(pumpEventQueue);
+
+    schedule(transformer.resumeApply);
+
+    expectAsset("app|foo.out", "baz");
+    buildShouldSucceed();
+
+    schedule(() {
+      // Should have run once the first time, then again when switching to
+      // baz.inc. Should not run a third time because of bar.inc being modified.
+      expect(transformer.numRuns, equals(2));
+    });
+  });
+
   test("handles an output moving from one transformer to another", () {
     // In the first run, "shared.out" is created by the "a.a" transformer.
     initGraph({
@@ -336,11 +524,9 @@
 
     // Now switch their contents so that "shared.out" will be output by "b.b"'s
     // transformer.
-    schedule(() {
-      modifyAsset("app|a.a", "a.out");
-      modifyAsset("app|b.b", "b.out,shared.out");
-      updateSources(["app|a.a", "app|b.b"]);
-    });
+    modifyAsset("app|a.a", "a.out");
+    modifyAsset("app|b.b", "b.out,shared.out");
+    schedule(() => updateSources(["app|a.a", "app|b.b"]));
 
     expectAsset("app|a.out", "spread a");
     expectAsset("app|b.out", "spread b");
@@ -354,7 +540,7 @@
     initGraph(["app|foo.txt", "app|bar.txt"],
         {"app": [[txtToInt], [intToOut]]});
 
-    txtToInt.wait();
+    txtToInt.pauseApply();
 
     schedule(() {
       updateSources(["app|foo.txt"]);
@@ -369,7 +555,7 @@
     });
 
     schedule(() {
-      txtToInt.complete();
+      txtToInt.resumeApply();
     });
 
     expectAsset("app|foo.out", "foo.int.out");
@@ -408,6 +594,281 @@
     buildShouldSucceed();
   });
 
+  test("doesn't return an asset until it's finished rebuilding", () {
+    initGraph(["app|foo.in"], {"app": [
+      [new RewriteTransformer("in", "mid")],
+      [new RewriteTransformer("mid", "out")]
+    ]});
+
+    updateSources(["app|foo.in"]);
+    expectAsset("app|foo.out", "foo.mid.out");
+    buildShouldSucceed();
+
+    pauseProvider();
+    modifyAsset("app|foo.in", "new");
+    schedule(() => updateSources(["app|foo.in"]));
+    expectAssetDoesNotComplete("app|foo.out");
+    buildShouldNotBeDone();
+
+    resumeProvider();
+    expectAsset("app|foo.out", "new.mid.out");
+    buildShouldSucceed();
+  });
+
+  test("doesn't return an asset until its in-place transform is done", () {
+    var rewrite = new RewriteTransformer("txt", "txt");
+    initGraph(["app|foo.txt"], {"app": [[rewrite]]});
+
+    rewrite.pauseApply();
+    updateSources(["app|foo.txt"]);
+    expectAssetDoesNotComplete("app|foo.txt");
+
+    schedule(rewrite.resumeApply);
+    expectAsset("app|foo.txt", "foo.txt");
+    buildShouldSucceed();
+  });
+
+  test("doesn't return an asset until we know it won't be transformed",
+      () {
+    var rewrite = new RewriteTransformer("txt", "txt");
+    initGraph(["app|foo.a"], {"app": [[rewrite]]});
+
+    rewrite.pauseIsPrimary("app|foo.a");
+    updateSources(["app|foo.a"]);
+    expectAssetDoesNotComplete("app|foo.a");
+
+    schedule(() => rewrite.resumeIsPrimary("app|foo.a"));
+    expectAsset("app|foo.a", "foo");
+    buildShouldSucceed();
+  });
+
+  test("doesn't return a modified asset until we know it will still be "
+      "transformed", () {
+    var rewrite = new RewriteTransformer("txt", "txt");
+    initGraph(["app|foo.txt"], {"app": [[rewrite]]});
+
+    updateSources(["app|foo.txt"]);
+    expectAsset("app|foo.txt", "foo.txt");
+    buildShouldSucceed();
+
+    schedule(() => rewrite.pauseIsPrimary("app|foo.txt"));
+    schedule(() => updateSources(["app|foo.txt"]));
+    expectAssetDoesNotComplete("app|foo.txt");
+
+    schedule(() => rewrite.resumeIsPrimary("app|foo.txt"));
+    expectAsset("app|foo.txt", "foo.txt");
+    buildShouldSucceed();
+  });
+
+  test("doesn't return an asset that's removed during isPrimary", () {
+    var rewrite = new RewriteTransformer("txt", "txt");
+    initGraph(["app|foo.txt"], {"app": [[rewrite]]});
+
+    rewrite.pauseIsPrimary("app|foo.txt");
+    updateSources(["app|foo.txt"]);
+    // Make sure we're waiting on isPrimary.
+    schedule(pumpEventQueue);
+
+    schedule(() {
+      removeSources(["app|foo.txt"]);
+      rewrite.resumeIsPrimary("app|foo.txt");
+    });
+    expectNoAsset("app|foo.txt");
+    buildShouldSucceed();
+  });
+
+  test("doesn't transform an asset that goes from primary to non-primary "
+      "during isPrimary", () {
+    var check = new CheckContentTransformer("do", "ne");
+    initGraph({
+      "app|foo.txt": "do"
+    }, {"app": [[check]]});
+
+    check.pauseIsPrimary("app|foo.txt");
+    updateSources(["app|foo.txt"]);
+    // Make sure we're waiting on isPrimary.
+    schedule(pumpEventQueue);
+
+    modifyAsset("app|foo.txt", "don't");
+    schedule(() {
+      updateSources(["app|foo.txt"]);
+      check.resumeIsPrimary("app|foo.txt");
+    });
+
+    expectAsset("app|foo.txt", "don't");
+    buildShouldSucceed();
+  });
+
+  test("transforms an asset that goes from non-primary to primary "
+      "during isPrimary", () {
+    var check = new CheckContentTransformer("do", "ne");
+    initGraph({
+      "app|foo.txt": "don't"
+    }, {"app": [[check]]});
+
+    check.pauseIsPrimary("app|foo.txt");
+    updateSources(["app|foo.txt"]);
+    // Make sure we're waiting on isPrimary.
+    schedule(pumpEventQueue);
+
+    modifyAsset("app|foo.txt", "do");
+    schedule(() {
+      updateSources(["app|foo.txt"]);
+      check.resumeIsPrimary("app|foo.txt");
+    });
+
+    expectAsset("app|foo.txt", "done");
+    buildShouldSucceed();
+  });
+
+  test("doesn't return an asset that's removed during another transformer's "
+      "isPrimary", () {
+    var rewrite1 = new RewriteTransformer("txt", "txt");
+    var rewrite2 = new RewriteTransformer("md", "md");
+    initGraph(["app|foo.txt", "app|foo.md"], {"app": [[rewrite1, rewrite2]]});
+
+    rewrite2.pauseIsPrimary("app|foo.md");
+    updateSources(["app|foo.txt", "app|foo.md"]);
+    // Make sure we're waiting on the correct isPrimary.
+    schedule(pumpEventQueue);
+
+    schedule(() {
+      removeSources(["app|foo.txt"]);
+      rewrite2.resumeIsPrimary("app|foo.md");
+    });
+    expectNoAsset("app|foo.txt");
+    expectAsset("app|foo.md", "foo.md");
+    buildShouldSucceed();
+  });
+
+  test("doesn't transform an asset that goes from primary to non-primary "
+      "during another transformer's isPrimary", () {
+    var rewrite = new RewriteTransformer("md", "md");
+    var check = new CheckContentTransformer("do", "ne");
+    initGraph({
+      "app|foo.txt": "do",
+      "app|foo.md": "foo"
+    }, {"app": [[rewrite, check]]});
+
+    rewrite.pauseIsPrimary("app|foo.md");
+    updateSources(["app|foo.txt", "app|foo.md"]);
+    // Make sure we're waiting on the correct isPrimary.
+    schedule(pumpEventQueue);
+
+    modifyAsset("app|foo.txt", "don't");
+    schedule(() {
+      updateSources(["app|foo.txt"]);
+      rewrite.resumeIsPrimary("app|foo.md");
+    });
+
+    expectAsset("app|foo.txt", "don't");
+    expectAsset("app|foo.md", "foo.md");
+    buildShouldSucceed();
+  });
+
+  test("transforms an asset that goes from non-primary to primary "
+      "during another transformer's isPrimary", () {
+    var rewrite = new RewriteTransformer("md", "md");
+    var check = new CheckContentTransformer("do", "ne");
+    initGraph({
+      "app|foo.txt": "don't",
+      "app|foo.md": "foo"
+    }, {"app": [[rewrite, check]]});
+
+    rewrite.pauseIsPrimary("app|foo.md");
+    updateSources(["app|foo.txt", "app|foo.md"]);
+    // Make sure we're waiting on the correct isPrimary.
+    schedule(pumpEventQueue);
+
+    modifyAsset("app|foo.txt", "do");
+    schedule(() {
+      updateSources(["app|foo.txt"]);
+      rewrite.resumeIsPrimary("app|foo.md");
+    });
+
+    expectAsset("app|foo.txt", "done");
+    expectAsset("app|foo.md", "foo.md");
+    buildShouldSucceed();
+  });
+
+  test("removes pipelined transforms when the root primary input is removed",
+      () {
+    initGraph(["app|foo.txt"], {"app": [
+      [new RewriteTransformer("txt", "mid")],
+      [new RewriteTransformer("mid", "out")]
+    ]});
+
+    updateSources(["app|foo.txt"]);
+    expectAsset("app|foo.out", "foo.mid.out");
+    buildShouldSucceed();
+
+    schedule(() => removeSources(["app|foo.txt"]));
+    expectNoAsset("app|foo.out");
+    buildShouldSucceed();
+  });
+
+  test("removes pipelined transforms when the parent ceases to generate the "
+      "primary input", () {
+    initGraph({"app|foo.txt": "foo.mid"}, {'app': [
+      [new OneToManyTransformer('txt')],
+      [new RewriteTransformer('mid', 'out')]
+    ]});
+
+    updateSources(['app|foo.txt']);
+    expectAsset('app|foo.out', 'spread txt.out');
+    buildShouldSucceed();
+
+    modifyAsset("app|foo.txt", "bar.mid");
+    schedule(() => updateSources(["app|foo.txt"]));
+    expectNoAsset('app|foo.out');
+    expectAsset('app|bar.out', 'spread txt.out');
+    buildShouldSucceed();
+  });
+
+  test("returns an asset even if an unrelated build is running", () {
+    initGraph([
+      "app|foo.in",
+      "app|bar.in",
+    ], {"app": [[new RewriteTransformer("in", "out")]]});
+
+    updateSources(["app|foo.in", "app|bar.in"]);
+    expectAsset("app|foo.out", "foo.out");
+    expectAsset("app|bar.out", "bar.out");
+    buildShouldSucceed();
+
+    pauseProvider();
+    modifyAsset("app|foo.in", "new");
+    schedule(() => updateSources(["app|foo.in"]));
+    expectAssetDoesNotComplete("app|foo.out");
+    expectAsset("app|bar.out", "bar.out");
+    buildShouldNotBeDone();
+
+    resumeProvider();
+    expectAsset("app|foo.out", "new.out");
+    buildShouldSucceed();
+  });
+
+  test("doesn't report AssetNotFound until all builds are finished", () {
+    initGraph([
+      "app|foo.in",
+    ], {"app": [[new RewriteTransformer("in", "out")]]});
+
+    updateSources(["app|foo.in"]);
+    expectAsset("app|foo.out", "foo.out");
+    buildShouldSucceed();
+
+    pauseProvider();
+    schedule(() => updateSources(["app|foo.in"]));
+    expectAssetDoesNotComplete("app|foo.out");
+    expectAssetDoesNotComplete("app|non-existent.out");
+    buildShouldNotBeDone();
+
+    resumeProvider();
+    expectAsset("app|foo.out", "foo.out");
+    expectNoAsset("app|non-existent.out");
+    buildShouldSucceed();
+  });
+
   test("doesn't emit a result until all builds are finished", () {
     var rewrite = new RewriteTransformer("txt", "out");
     initGraph([
diff --git a/pkg/barback/test/transformer/bad.dart b/pkg/barback/test/transformer/bad.dart
new file mode 100644
index 0000000..49046ca
--- /dev/null
+++ b/pkg/barback/test/transformer/bad.dart
@@ -0,0 +1,39 @@
+// Copyright (c) 2013, 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 barback.test.transformer.bad;
+
+import 'dart:async';
+
+import 'package:barback/barback.dart';
+import 'package:barback/src/utils.dart';
+
+import 'mock.dart';
+
+/// A transformer that throws an exception when run, after generating the
+/// given outputs.
+class BadTransformer extends MockTransformer {
+  /// The error it throws.
+  static const ERROR = "I am a bad transformer!";
+
+  /// The list of asset names that it should output.
+  final List<String> outputs;
+
+  BadTransformer(this.outputs);
+
+  Future<bool> doIsPrimary(Asset asset) => new Future.value(true);
+
+  Future doApply(Transform transform) {
+    return newFuture(() {
+      // Create the outputs first.
+      for (var output in outputs) {
+        var id = new AssetId.parse(output);
+        transform.addOutput(new Asset.fromString(id, output));
+      }
+
+      // Then fail.
+      throw ERROR;
+    });
+  }
+}
diff --git a/pkg/barback/test/transformer/check_content.dart b/pkg/barback/test/transformer/check_content.dart
new file mode 100644
index 0000000..252ee1c
--- /dev/null
+++ b/pkg/barback/test/transformer/check_content.dart
@@ -0,0 +1,31 @@
+// Copyright (c) 2013, 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 barback.test.transformer.check_content;
+
+import 'dart:async';
+
+import 'package:barback/barback.dart';
+
+import 'mock.dart';
+
+/// A transformer that modifies assets with the given content.
+class CheckContentTransformer extends MockTransformer {
+  final String content;
+  final String addition;
+
+  CheckContentTransformer(this.content, this.addition);
+
+  Future<bool> doIsPrimary(Asset asset) =>
+    asset.readAsString().then((value) => value == content);
+
+  Future doApply(Transform transform) {
+    return getPrimary(transform).then((primary) {
+      return primary.readAsString().then((value) {
+        transform.addOutput(
+            new Asset.fromString(primary.id, "$value$addition"));
+      });
+    });
+  }
+}
diff --git a/pkg/barback/test/transformer/create_asset.dart b/pkg/barback/test/transformer/create_asset.dart
new file mode 100644
index 0000000..9e89516
--- /dev/null
+++ b/pkg/barback/test/transformer/create_asset.dart
@@ -0,0 +1,28 @@
+// Copyright (c) 2013, 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 barback.test.transformer.create_asset;
+
+import 'dart:async';
+
+import 'package:barback/barback.dart';
+import 'package:barback/src/utils.dart';
+
+import 'mock.dart';
+
+/// A transformer that outputs an asset with the given id.
+class CreateAssetTransformer extends MockTransformer {
+  final String output;
+
+  CreateAssetTransformer(this.output);
+
+  Future<bool> doIsPrimary(Asset asset) => new Future.value(true);
+
+  Future doApply(Transform transform) {
+    return newFuture(() {
+      transform.addOutput(
+          new Asset.fromString(new AssetId.parse(output), output));
+    });
+  }
+}
diff --git a/pkg/barback/test/transformer/many_to_one.dart b/pkg/barback/test/transformer/many_to_one.dart
new file mode 100644
index 0000000..efaf3c47
--- /dev/null
+++ b/pkg/barback/test/transformer/many_to_one.dart
@@ -0,0 +1,46 @@
+// Copyright (c) 2013, 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 barback.test.transformer.many_to_one;
+
+import 'dart:async';
+
+import 'package:barback/barback.dart';
+import 'package:barback/src/utils.dart';
+
+import 'mock.dart';
+
+/// A transformer that uses the contents of a file to define the other inputs.
+///
+/// Outputs a file with the same name as the primary but with an "out"
+/// extension containing the concatenated contents of all non-primary inputs.
+class ManyToOneTransformer extends MockTransformer {
+  final String extension;
+
+  /// Creates a transformer that consumes assets with [extension].
+  ///
+  /// That file contains a comma-separated list of paths and it will input
+  /// files at each of those paths.
+  ManyToOneTransformer(this.extension);
+
+  Future<bool> doIsPrimary(Asset asset) =>
+    new Future.value(asset.id.extension == ".$extension");
+
+  Future doApply(Transform transform) {
+    return getPrimary(transform)
+        .then((primary) => primary.readAsString())
+        .then((contents) {
+      // Get all of the included inputs.
+      return Future.wait(contents.split(",").map((path) {
+        var id = new AssetId(transform.primaryId.package, path);
+        return getInput(transform, id).then((input) => input.readAsString());
+      }));
+    }).then((outputs) {
+      var id = transform.primaryId.changeExtension(".out");
+      transform.addOutput(new Asset.fromString(id, outputs.join()));
+    });
+  }
+
+  String toString() => "many->1 $extension";
+}
diff --git a/pkg/barback/test/transformer/mock.dart b/pkg/barback/test/transformer/mock.dart
new file mode 100644
index 0000000..b831cf7
--- /dev/null
+++ b/pkg/barback/test/transformer/mock.dart
@@ -0,0 +1,134 @@
+// Copyright (c) 2013, 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 barback.test.transformer.mock;
+
+import 'dart:async';
+
+import 'package:barback/barback.dart';
+import 'package:barback/src/utils.dart';
+
+/// The abstract base class for transformers used to test barback.
+///
+/// This adds the ability to pause and resume different components of the
+/// transformers, and to tell whether they're running, when they start running,
+/// and how many times they've run.
+///
+/// Transformers extending this should override [doIsPrimary] and [doApply]
+/// rather than [isPrimary] and [apply], and they should use [getInput] and
+/// [getPrimary] rather than [transform.getInput] and [transform.primaryInput].
+abstract class MockTransformer extends Transformer {
+  /// The number of times the transformer has been applied.
+  int get numRuns => _numRuns;
+  var _numRuns = 0;
+
+  /// The number of currently running transforms.
+  int _runningTransforms = 0;
+
+  // A completer for pausing the transformer before it finishes running [apply].
+  Completer _apply;
+
+  // Completers for pausing the transformer before it finishes running
+  // [isPrimary].
+  final _isPrimary = new Map<AssetId, Completer>();
+
+  // Completers for pausing the transformer before it finishes getting inputs
+  // the [Transform].
+  final _getInput = new Map<AssetId, Completer>();
+
+  /// A future that completes when this transformer begins running.
+  ///
+  /// Once this transformer finishes running, this is reset to a new completer,
+  /// so it can be used multiple times.
+  Future get started => _started.future;
+  var _started = new Completer();
+
+  /// `true` if any transforms are currently running.
+  bool get isRunning => _runningTransforms > 0;
+
+  /// Causes the transformer to pause after running [apply] but before the
+  /// returned Future completes.
+  ///
+  /// This can be resumed by calling [resumeApply].
+  void pauseApply() {
+    _apply = new Completer();
+  }
+
+  /// Resumes the transformer's [apply] call after [pauseApply] was called.
+  void resumeApply() {
+    _apply.complete();
+    _apply = null;
+  }
+
+  /// Causes the transformer to pause after running [isPrimary] on the asset
+  /// with the given [name], but before the returned Future completes.
+  ///
+  /// This can be resumed by calling [resumeIsPrimary].
+  void pauseIsPrimary(String name) {
+    _isPrimary[new AssetId.parse(name)] = new Completer();
+  }
+
+  /// Resumes the transformer's [isPrimary] call on the asset with the given
+  /// [name] after [pauseIsPrimary] was called.
+  void resumeIsPrimary(String name) {
+    _isPrimary.remove(new AssetId.parse(name)).complete();
+  }
+
+  /// Causes the transformer to pause while loading the input with the given
+  /// [name]. This can be the primary input or a secondary input.
+  ///
+  /// This can be resumed by calling [resumeGetInput].
+  void pauseGetInput(String name) {
+    _getInput[new AssetId.parse(name)] = new Completer();
+  }
+
+  /// Resumes the transformer's loading of the input with the given [name] after
+  /// [pauseGetInput] was called.
+  void resumeGetInput(String name) {
+    _getInput.remove(new AssetId.parse(name)).complete();
+  }
+
+  /// Like [Transform.getInput], but respects [pauseGetInput].
+  ///
+  /// This is intended for use by subclasses of [MockTransformer].
+  Future<Asset> getInput(Transform transform, AssetId id) {
+    return newFuture(() {
+      if (_getInput.containsKey(id)) return _getInput[id].future;
+    }).then((_) => transform.getInput(id));
+  }
+
+  /// Like [Transform.primaryInput], but respects [pauseGetInput].
+  ///
+  /// This is intended for use by subclasses of [MockTransformer].
+  Future<Asset> getPrimary(Transform transform) =>
+      getInput(transform, transform.primaryId);
+
+  Future<bool> isPrimary(Asset asset) {
+    return newFuture(() => doIsPrimary(asset)).then((result) {
+      return newFuture(() {
+        if (_isPrimary.containsKey(asset.id)) {
+          return _isPrimary[asset.id].future;
+        }
+      }).then((_) => result);
+    });
+  }
+
+  Future apply(Transform transform) {
+    _numRuns++;
+    if (_runningTransforms == 0) _started.complete();
+    _runningTransforms++;
+    return newFuture(() => doApply(transform)).then((_) {
+      if (_apply != null) return _apply.future;
+    }).whenComplete(() {
+      _runningTransforms--;
+      if (_runningTransforms == 0) _started = new Completer();
+    });
+  }
+
+  /// The wrapped version of [isPrimary] for subclasses to override.
+  Future<bool> doIsPrimary(Asset asset);
+
+  /// The wrapped version of [doApply] for subclasses to override.
+  Future doApply(Transform transform);
+}
diff --git a/pkg/barback/test/transformer/one_to_many.dart b/pkg/barback/test/transformer/one_to_many.dart
new file mode 100644
index 0000000..e9d301d
--- /dev/null
+++ b/pkg/barback/test/transformer/one_to_many.dart
@@ -0,0 +1,39 @@
+// Copyright (c) 2013, 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 barback.test.transformer.one_to_many;
+
+import 'dart:async';
+
+import 'package:barback/barback.dart';
+
+import 'mock.dart';
+
+/// A [Transformer] that takes an input asset that contains a comma-separated
+/// list of paths and outputs a file for each path.
+class OneToManyTransformer extends MockTransformer {
+  final String extension;
+
+  /// Creates a transformer that consumes assets with [extension].
+  ///
+  /// That file contains a comma-separated list of paths and it will output
+  /// files at each of those paths.
+  OneToManyTransformer(this.extension);
+
+  Future<bool> doIsPrimary(Asset asset) =>
+    new Future.value(asset.id.extension == ".$extension");
+
+  Future doApply(Transform transform) {
+    return getPrimary(transform)
+        .then((input) => input.readAsString())
+        .then((lines) {
+      for (var line in lines.split(",")) {
+        var id = new AssetId(transform.primaryId.package, line);
+        transform.addOutput(new Asset.fromString(id, "spread $extension"));
+      }
+    });
+  }
+
+  String toString() => "1->many $extension";
+}
diff --git a/pkg/barback/test/transformer/rewrite.dart b/pkg/barback/test/transformer/rewrite.dart
new file mode 100644
index 0000000..4d3faa88
--- /dev/null
+++ b/pkg/barback/test/transformer/rewrite.dart
@@ -0,0 +1,43 @@
+// Copyright (c) 2013, 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 barback.test.transformer.rewrite;
+
+import 'dart:async';
+
+import 'package:barback/barback.dart';
+
+import 'mock.dart';
+
+/// A [Transformer] that takes assets ending with one extension and generates
+/// assets with a given extension.
+///
+/// Appends the output extension to the contents of the input file.
+class RewriteTransformer extends MockTransformer {
+  final String from;
+  final String to;
+
+  /// Creates a transformer that rewrites assets whose extension is [from] to
+  /// one whose extension is [to].
+  ///
+  /// [to] may be a space-separated list in which case multiple outputs will be
+  /// created for each input.
+  RewriteTransformer(this.from, this.to);
+
+  Future<bool> doIsPrimary(Asset asset) =>
+    new Future.value(asset.id.extension == ".$from");
+
+  Future doApply(Transform transform) {
+    return getPrimary(transform).then((input) {
+      return Future.wait(to.split(" ").map((extension) {
+        var id = transform.primaryId.changeExtension(".$extension");
+        return input.readAsString().then((content) {
+          transform.addOutput(new Asset.fromString(id, "$content.$extension"));
+        });
+      }));
+    });
+  }
+
+  String toString() => "$from->$to";
+}
diff --git a/pkg/barback/test/utils.dart b/pkg/barback/test/utils.dart
index fcda962..ab41a59 100644
--- a/pkg/barback/test/utils.dart
+++ b/pkg/barback/test/utils.dart
@@ -10,6 +10,8 @@
 
 import 'package:barback/barback.dart';
 import 'package:barback/src/asset_cascade.dart';
+import 'package:barback/src/asset_set.dart';
+import 'package:barback/src/cancelable_future.dart';
 import 'package:barback/src/package_graph.dart';
 import 'package:barback/src/utils.dart';
 import 'package:path/path.dart' as pathos;
@@ -17,6 +19,14 @@
 import 'package:stack_trace/stack_trace.dart';
 import 'package:unittest/compact_vm_config.dart';
 
+export 'transformer/bad.dart';
+export 'transformer/check_content.dart';
+export 'transformer/create_asset.dart';
+export 'transformer/many_to_one.dart';
+export 'transformer/mock.dart';
+export 'transformer/one_to_many.dart';
+export 'transformer/rewrite.dart';
+
 var _configured = false;
 
 MockProvider _provider;
@@ -96,6 +106,16 @@
   }, "modify asset $name");
 }
 
+/// Schedules an error to be generated when loading the asset identified by
+/// [name].
+///
+/// Does not update the asset in the graph.
+void setAssetError(String name) {
+  schedule(() {
+    _provider._setAssetError(name);
+  }, "set error for asset $name");
+}
+
 /// Schedules a pause of the internally created [PackageProvider].
 ///
 /// All asset requests that the [PackageGraph] makes to the provider after this
@@ -117,31 +137,16 @@
 /// [buildShouldFail], so those can be used to validate build results before and
 /// after this.
 void buildShouldNotBeDone() {
-  var resultAllowed = false;
-  var trace = new Trace.current();
-  _graph.results.elementAt(_nextBuildResult).then((result) {
-    if (resultAllowed) return;
-
-    currentSchedule.signalError(
-        new Exception("Expected build not to terminate "
-            "here, but it terminated with result: $result"), trace);
-  }).catchError((error) {
-    if (resultAllowed) return;
-    currentSchedule.signalError(error);
-  });
-
-  schedule(() {
-    // Pump the event queue in case the build completes out-of-band after we get
-    // here. If it does, we want to signal an error.
-    return pumpEventQueue().then((_) {
-      resultAllowed = true;
-    });
-  }, "ensuring build doesn't terminate");
+  _futureShouldNotCompleteUntil(
+      _graph.results.elementAt(_nextBuildResult),
+      schedule(() => pumpEventQueue(), "build should not terminate"),
+      "build");
 }
 
 /// Expects that the next [BuildResult] is a build success.
 void buildShouldSucceed() {
   expect(_getNextBuildResult().then((result) {
+    result.errors.forEach(currentSchedule.signalError);
     expect(result.succeeded, isTrue);
   }), completes);
 }
@@ -190,9 +195,8 @@
   schedule(() {
     return _graph.getAssetById(id).then((asset) {
       // TODO(rnystrom): Make an actual Matcher class for this.
-      expect(asset, new isInstanceOf<MockAsset>());
       expect(asset.id, equals(id));
-      expect(asset.contents, equals(contents));
+      expect(asset.readAsString(), completion(equals(contents)));
     });
   }, "get asset $name");
 }
@@ -213,12 +217,25 @@
   }, "get asset $name");
 }
 
+/// Schedules an expectation that a [getAssetById] call for the given asset
+/// won't terminate at this point in the schedule.
+void expectAssetDoesNotComplete(String name) {
+  var id = new AssetId.parse(name);
+
+  schedule(() {
+    return _futureShouldNotCompleteUntil(
+        _graph.getAssetById(id),
+        pumpEventQueue(),
+        "asset $id");
+  }, "asset $id should not complete");
+}
+
 /// Returns a matcher for an [AssetNotFoundException] with the given [id].
 Matcher isAssetNotFoundException(String name) {
   var id = new AssetId.parse(name);
   return allOf(
       new isInstanceOf<AssetNotFoundException>(),
-      predicate((error) => error.id == id, 'id is $name'));
+      predicate((error) => error.id == id, 'id == $name'));
 }
 
 /// Returns a matcher for an [AssetCollisionException] with the given [id].
@@ -226,7 +243,7 @@
   var id = new AssetId.parse(name);
   return allOf(
       new isInstanceOf<AssetCollisionException>(),
-      predicate((error) => error.id == id, 'id is $name'));
+      predicate((error) => error.id == id, 'id == $name'));
 }
 
 /// Returns a matcher for a [MissingInputException] with the given [id].
@@ -234,7 +251,7 @@
   var id = new AssetId.parse(name);
   return allOf(
       new isInstanceOf<MissingInputException>(),
-      predicate((error) => error.id == id, 'id is $name'));
+      predicate((error) => error.id == id, 'id == $name'));
 }
 
 /// Returns a matcher for an [InvalidOutputException] with the given id and
@@ -244,7 +261,37 @@
   return allOf(
       new isInstanceOf<InvalidOutputException>(),
       predicate((error) => error.package == package, 'package is $package'),
-      predicate((error) => error.id == id, 'id is $name'));
+      predicate((error) => error.id == id, 'id == $name'));
+}
+
+/// Returns a matcher for a [MockLoadException] with the given [id].
+Matcher isMockLoadException(String name) {
+  var id = new AssetId.parse(name);
+  return allOf(
+      new isInstanceOf<MockLoadException>(),
+      predicate((error) => error.id == id, 'id == $name'));
+}
+
+/// Asserts that [future] shouldn't complete until after [delay] completes.
+///
+/// Once [delay] completes, the output of [future] is ignored, even if it's an
+/// error.
+///
+/// [description] should describe [future].
+Future _futureShouldNotCompleteUntil(Future future, Future delay,
+    String description) {
+  var trace = new Trace.current();
+  var cancelable = new CancelableFuture(future);
+  cancelable.then((result) {
+    currentSchedule.signalError(
+        new Exception("Expected $description not to complete here, but it "
+            "completed with result: $result"),
+        trace);
+  }).catchError((error) {
+    currentSchedule.signalError(error);
+  });
+
+  return delay.then((_) => cancelable.cancel());
 }
 
 /// An [AssetProvider] that provides the given set of assets.
@@ -253,6 +300,10 @@
 
   Map<String, _MockPackage> _packages;
 
+  /// The set of assets for which [MockLoadException]s should be emitted if
+  /// they're loaded.
+  final _errors = new Set<AssetId>();
+
   /// The completer that [getAsset()] is waiting on to complete when paused.
   ///
   /// If `null` it will return the asset immediately.
@@ -277,13 +328,13 @@
     if (assets is Map) {
       assetList = assets.keys.map((asset) {
         var id = new AssetId.parse(asset);
-        return new MockAsset(id, assets[asset]);
+        return new _MockAsset(id, assets[asset]);
       });
     } else if (assets is Iterable) {
       assetList = assets.map((asset) {
         var id = new AssetId.parse(asset);
         var contents = pathos.basenameWithoutExtension(id.path);
-        return new MockAsset(id, contents);
+        return new _MockAsset(id, contents);
       });
     }
 
@@ -291,21 +342,26 @@
         (package, assets) {
       var packageTransformers = transformers[package];
       if (packageTransformers == null) packageTransformers = [];
-      return new _MockPackage(assets, packageTransformers.toList());
+      return new _MockPackage(
+          new AssetSet.from(assets), packageTransformers.toList());
     });
 
     // If there are no assets or transformers, add a dummy package. This better
     // simulates the real world, where there'll always be at least the
     // entrypoint package.
-    if (_packages.isEmpty) _packages = {"app": new _MockPackage([], [])};
+    if (_packages.isEmpty) {
+      _packages = {"app": new _MockPackage(new AssetSet(), [])};
+    }
   }
 
   void _modifyAsset(String name, String contents) {
     var id = new AssetId.parse(name);
-    var asset = _packages[id.package].assets.firstWhere((a) => a.id == id);
-    asset.contents = contents;
+    _errors.remove(id);
+    _packages[id.package].assets[id].contents = contents;
   }
 
+  void _setAssetError(String name) => _errors.add(new AssetId.parse(name));
+
   List<AssetId> listAssets(String package, {String within}) {
     if (within != null) {
       throw new UnimplementedError("Doesn't handle 'within' yet.");
@@ -323,6 +379,14 @@
   }
 
   Future<Asset> getAsset(AssetId id) {
+    // Eagerly load the asset so we can test an asset's value changing between
+    // when a load starts and when it finishes.
+    var package = _packages[id.package];
+    var asset;
+    if (package != null) asset = package.assets[id];
+
+    var hasError = _errors.contains(id);
+
     var future;
     if (_pauseCompleter != null) {
       future = _pauseCompleter.future;
@@ -331,225 +395,38 @@
     }
 
     return future.then((_) {
-      var package = _packages[id.package];
-      if (package == null) throw new AssetNotFoundException(id);
-
-      return package.assets.firstWhere((asset) => asset.id == id,
-          orElse: () => throw new AssetNotFoundException(id));
+      if (hasError) throw new MockLoadException(id);
+      if (asset == null) throw new AssetNotFoundException(id);
+      return asset;
     });
   }
 }
 
+/// Error thrown for assets with [setAssetError] set.
+class MockLoadException implements Exception {
+  final AssetId id;
+
+  MockLoadException(this.id);
+
+  String toString() => "Error loading $id.";
+}
+
 /// Used by [MockProvider] to keep track of which assets and transformers exist
 /// for each package.
 class _MockPackage {
-  final List<MockAsset> assets;
+  final AssetSet assets;
   final List<List<Transformer>> transformers;
 
   _MockPackage(this.assets, Iterable<Iterable<Transformer>> transformers)
       : transformers = transformers.map((phase) => phase.toList()).toList();
 }
 
-/// A [Transformer] that takes assets ending with one extension and generates
-/// assets with a given extension.
-///
-/// Appends the output extension to the contents of the input file.
-class RewriteTransformer extends Transformer {
-  final String from;
-  final String to;
-
-  /// The number of times the transformer has been applied.
-  int numRuns = 0;
-
-  /// The number of currently running transforms.
-  int _runningTransforms = 0;
-
-  /// The completer that the transform is waiting on to complete.
-  ///
-  /// If `null` the transform will complete immediately.
-  Completer _wait;
-
-  /// A future that completes when the first apply of this transformer begins.
-  Future get started => _started.future;
-  final _started = new Completer();
-
-  /// Creates a transformer that rewrites assets whose extension is [from] to
-  /// one whose extension is [to].
-  ///
-  /// [to] may be a space-separated list in which case multiple outputs will be
-  /// created for each input.
-  RewriteTransformer(this.from, this.to);
-
-  /// `true` if any transforms are currently running.
-  bool get isRunning => _runningTransforms > 0;
-
-  /// Tells the transform to wait during its transformation until [complete()]
-  /// is called.
-  ///
-  /// Lets you test the asynchronous behavior of transformers.
-  void wait() {
-    _wait = new Completer();
-  }
-
-  void complete() {
-    _wait.complete();
-    _wait = null;
-  }
-
-  Future<bool> isPrimary(Asset asset) {
-    return new Future.value(asset.id.extension == ".$from");
-  }
-
-  Future apply(Transform transform) {
-    numRuns++;
-    if (!_started.isCompleted) _started.complete();
-    _runningTransforms++;
-    return transform.primaryInput.then((input) {
-      return Future.wait(to.split(" ").map((extension) {
-        var id = transform.primaryId.changeExtension(".$extension");
-        return input.readAsString().then((content) {
-          transform.addOutput(new MockAsset(id, "$content.$extension"));
-        });
-      })).then((_) {
-        if (_wait != null) return _wait.future;
-      });
-    }).whenComplete(() {
-      _runningTransforms--;
-    });
-  }
-
-  String toString() => "$from->$to";
-}
-
-/// A [Transformer] that takes an input asset that contains a comma-separated
-/// list of paths and outputs a file for each path.
-class OneToManyTransformer extends Transformer {
-  final String extension;
-
-  /// The number of times the transformer has been applied.
-  int numRuns = 0;
-
-  /// Creates a transformer that consumes assets with [extension].
-  ///
-  /// That file contains a comma-separated list of paths and it will output
-  /// files at each of those paths.
-  OneToManyTransformer(this.extension);
-
-  Future<bool> isPrimary(Asset asset) {
-    return new Future.value(asset.id.extension == ".$extension");
-  }
-
-  Future apply(Transform transform) {
-    numRuns++;
-    return transform.primaryInput.then((input) {
-      return input.readAsString().then((lines) {
-        for (var line in lines.split(",")) {
-          var id = new AssetId(transform.primaryId.package, line);
-          transform.addOutput(new MockAsset(id, "spread $extension"));
-        }
-      });
-    });
-  }
-
-  String toString() => "1->many $extension";
-}
-
-/// A transformer that uses the contents of a file to define the other inputs.
-///
-/// Outputs a file with the same name as the primary but with an "out"
-/// extension containing the concatenated contents of all non-primary inputs.
-class ManyToOneTransformer extends Transformer {
-  final String extension;
-
-  /// The number of times the transformer has been applied.
-  int numRuns = 0;
-
-  /// Creates a transformer that consumes assets with [extension].
-  ///
-  /// That file contains a comma-separated list of paths and it will input
-  /// files at each of those paths.
-  ManyToOneTransformer(this.extension);
-
-  Future<bool> isPrimary(Asset asset) {
-    return new Future.value(asset.id.extension == ".$extension");
-  }
-
-  Future apply(Transform transform) {
-    numRuns++;
-    return transform.primaryInput.then((primary) {
-      return primary.readAsString().then((contents) {
-        // Get all of the included inputs.
-        var inputs = contents.split(",").map((path) {
-          var id = new AssetId(transform.primaryId.package, path);
-          return transform.getInput(id);
-        });
-
-        return Future.wait(inputs);
-      }).then((inputs) {
-        // Concatenate them to one output.
-        var output = "";
-        return Future.forEach(inputs, (input) {
-          return input.readAsString().then((contents) {
-            output += contents;
-          });
-        }).then((_) {
-          var id = transform.primaryId.changeExtension(".out");
-          transform.addOutput(new MockAsset(id, output));
-        });
-      });
-    });
-  }
-
-  String toString() => "many->1 $extension";
-}
-
-/// A transformer that throws an exception when run, after generating the
-/// given outputs.
-class BadTransformer extends Transformer {
-  /// The error it throws.
-  static const ERROR = "I am a bad transformer!";
-
-  /// The list of asset names that it should output.
-  final List<String> outputs;
-
-  BadTransformer(this.outputs);
-
-  Future<bool> isPrimary(Asset asset) => new Future.value(true);
-  Future apply(Transform transform) {
-    return newFuture(() {
-      // Create the outputs first.
-      for (var output in outputs) {
-        var id = new AssetId.parse(output);
-        transform.addOutput(new MockAsset(id, output));
-      }
-
-      // Then fail.
-      throw ERROR;
-    });
-  }
-}
-
-/// A transformer that outputs an asset with the given id.
-class CreateAssetTransformer extends Transformer {
-  final String output;
-
-  CreateAssetTransformer(this.output);
-
-  Future<bool> isPrimary(Asset asset) => new Future.value(true);
-
-  Future apply(Transform transform) {
-    return newFuture(() {
-      transform.addOutput(new MockAsset(new AssetId.parse(output), output));
-    });
-  }
-}
-
 /// An implementation of [Asset] that never hits the file system.
-class MockAsset implements Asset {
+class _MockAsset implements Asset {
   final AssetId id;
   String contents;
 
-  MockAsset(this.id, this.contents);
+  _MockAsset(this.id, this.contents);
 
   Future<String> readAsString({Encoding encoding}) =>
       new Future.value(contents);
@@ -557,4 +434,4 @@
   Stream<List<int>> read() => throw new UnimplementedError();
 
   String toString() => "MockAsset $id $contents";
-}
\ No newline at end of file
+}
diff --git a/pkg/custom_element/lib/custom_element.dart b/pkg/custom_element/lib/custom_element.dart
new file mode 100644
index 0000000..369501c
--- /dev/null
+++ b/pkg/custom_element/lib/custom_element.dart
@@ -0,0 +1,705 @@
+// Copyright (c) 2013, 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.
+
+/**
+ * Custom Elements let authors define their own elements. Authors associate code
+ * with custom tag names, and then use those custom tag names as they would any
+ * standard tag. See <www.polymer-project.org/platform/custom-elements.html>
+ * for more information.
+ */
+library custom_element;
+
+import 'dart:async';
+import 'dart:html';
+import 'package:mdv/mdv.dart' as mdv;
+import 'package:meta/meta.dart';
+import 'src/custom_tag_name.dart';
+
+// TODO(jmesserly): replace with a real custom element polyfill.
+// This is just something temporary.
+/**
+ * *Warning*: this implementation is a work in progress. It only implements
+ * the specification partially.
+ *
+ * Registers a custom HTML element with [localName] and the associated
+ * constructor. This will ensure the element is detected and
+ *
+ * See the specification at:
+ * <https://dvcs.w3.org/hg/webcomponents/raw-file/tip/spec/custom/index.html>
+ */
+void registerCustomElement(String localName, CustomElement create()) {
+  if (_customElements == null) {
+    _customElements = {};
+    CustomElement.templateCreated.add(initCustomElements);
+    // TODO(jmesserly): use MutationObserver to watch for inserts?
+  }
+
+  if (!isCustomTag(localName)) {
+    throw new ArgumentError('$localName is not a valid custom element name, '
+        'it should have at least one dash and not be a reserved name.');
+  }
+
+  if (_customElements.containsKey(localName)) {
+    throw new ArgumentError('custom element $localName already registered.');
+  }
+
+  // TODO(jmesserly): validate this is a valid tag name, not a selector.
+  _customElements[localName] = create;
+
+  // Initialize elements already on the page.
+  for (var query in [localName, '[is=$localName]']) {
+    for (var element in document.queryAll(query)) {
+      _initCustomElement(element, create);
+    }
+  }
+}
+
+/**
+ * Creates a new element and returns it. If the [localName] has been registered
+ * with [registerCustomElement], it will create the custom element.
+ *
+ * This is similar to `new Element.tag` in Dart and `document.createElement`
+ * in JavaScript.
+ *
+ * *Warning*: this API is temporary until [dart:html] supports custom elements.
+ */
+Element createElement(String localName) =>
+    initCustomElements(new Element.tag(localName));
+
+/**
+ * Similar to `new Element.html`, but automatically creates registed custom
+ * elements.
+ * *Warning*: this API is temporary until [dart:html] supports custom elements.
+ */
+Element createElementFromHtml(String html) =>
+    initCustomElements(new Element.html(html));
+
+/**
+ * Initialize any registered custom elements recursively in the [node] tree.
+ * For convenience this returns the [node] instance.
+ *
+ * *Warning*: this API is temporary until [dart:html] supports custom elements.
+ */
+Node initCustomElements(Node node) {
+  for (var c = node.firstChild; c != null; c = c.nextNode) {
+    initCustomElements(c);
+  }
+  if (node is Element) {
+    var ctor = _customElements[node.localName];
+    if (ctor == null) {
+      var attr = node.attributes['is'];
+      if (attr != null) ctor = _customElements[attr];
+    }
+    if (ctor != null) _initCustomElement(node, ctor);
+  }
+  return node;
+}
+
+/**
+ * The base class for all Dart web components. In addition to the [Element]
+ * interface, it also provides lifecycle methods:
+ * - [created]
+ * - [inserted]
+ * - [attributeChanged]
+ * - [removed]
+ */
+class CustomElement implements Element {
+  /** The web component element wrapped by this class. */
+  Element _host;
+  List _shadowRoots;
+
+  /**
+   * Shadow roots generated by dwc for each custom element, indexed by the
+   * custom element tag name.
+   */
+  Map<String, dynamic> _generatedRoots = {};
+
+  /**
+   * Temporary property until components extend [Element]. An element can
+   * only be associated with one host, and it is an error to use a web component
+   * without an associated host element.
+   */
+  Element get host {
+    if (_host == null) throw new StateError('host element has not been set.');
+    return _host;
+  }
+
+  set host(Element value) {
+    if (value == null) {
+      throw new ArgumentError('host must not be null.');
+    }
+    // TODO(jmesserly): xtag used to return "null" if unset, now it checks for
+    // "this". Temporarily allow both.
+    var xtag = value.xtag;
+    if (xtag != null && xtag != value) {
+      throw new ArgumentError('host must not have its xtag property set.');
+    }
+    if (_host != null) {
+      throw new StateError('host can only be set once.');
+    }
+
+    value.xtag = this;
+    _host = value;
+  }
+
+  /**
+   * **Note**: This is an implementation helper and should not need to be called
+   * from your code.
+   *
+   * Creates the [ShadowRoot] backing this component.
+   */
+  createShadowRoot([String componentName]) {
+    var root = host.createShadowRoot();
+    if (componentName != null) {
+      _generatedRoots[componentName] = root;
+    }
+    return root;
+  }
+
+  getShadowRoot(String componentName) => _generatedRoots[componentName];
+
+
+  /**
+   * *Warning*: This is an implementation helper for Custom Elements and
+   * should not be used in your code.
+   *
+   * Clones the template, instantiates custom elements and hooks events, then
+   * returns it.
+   */
+  DocumentFragment cloneTemplate(DocumentFragment shadowTemplate) {
+    var result = shadowTemplate.clone(true);
+    // TODO(jmesserly): should bindModel ensure this happens?
+    TemplateElement.bootstrap(result);
+    if (_templateCreated != null) {
+      for (var callback in _templateCreated) callback(result);
+    }
+    return result;
+  }
+
+  // TODO(jmesserly): ideally this would be a stream, but they don't allow
+  // reentrancy.
+  static Set<DocumentFragmentCreated> _templateCreated;
+
+  /**
+   * *Warning*: This is an implementation helper for Custom Elements and
+   * should not be used in your code.
+   *
+   * This event is fired whenever a template is instantiated via
+   * [cloneTemplate] or via [Element.createInstance]
+   */
+  // TODO(jmesserly): This is a hack, and is neccesary for the polyfill
+  // because custom elements are not upgraded during clone()
+  static Set<DocumentFragmentCreated> get templateCreated {
+    if (_templateCreated == null) {
+      _templateCreated = new Set<DocumentFragmentCreated>();
+      mdv.instanceCreated.listen((value) {
+        for (var callback in _templateCreated) callback(value);
+      });
+    }
+    return _templateCreated;
+  }
+  /**
+   * Invoked when this component gets created.
+   * Note that [root] will be a [ShadowRoot] if the browser supports Shadow DOM.
+   */
+  void created() {}
+
+  /** Invoked when this component gets inserted in the DOM tree. */
+  void inserted() {}
+
+  /** Invoked when this component is removed from the DOM tree. */
+  void removed() {}
+
+  // TODO(jmesserly): how do we implement this efficiently?
+  // See https://github.com/dart-lang/web-ui/issues/37
+  /** Invoked when any attribute of the component is modified. */
+  void attributeChanged(String name, String oldValue, String newValue) {}
+
+  get model => host.model;
+
+  void set model(newModel) {
+    host.model = newModel;
+  }
+
+  get templateInstance => host.templateInstance;
+  get isTemplate => host.isTemplate;
+  get ref => host.ref;
+  get content => host.content;
+  DocumentFragment createInstance(model, [BindingDelegate delegate]) =>
+      host.createInstance(model, delegate);
+  createBinding(String name, model, String path) =>
+      host.createBinding(name, model, path);
+  void bind(String name, model, String path) => host.bind(name, model, path);
+  void unbind(String name) => host.unbind(name);
+  void unbindAll() => host.unbindAll();
+  get bindings => host.bindings;
+  BindingDelegate get bindingDelegate => host.bindingDelegate;
+  set bindingDelegate(BindingDelegate value) { host.bindingDelegate = value; }
+
+  // TODO(jmesserly): this forwarding is temporary until Dart supports
+  // subclassing Elements.
+  // TODO(jmesserly): we were missing the setter for title, are other things
+  // missing setters?
+
+  List<Node> get nodes => host.nodes;
+
+  set nodes(Iterable<Node> value) { host.nodes = value; }
+
+  /**
+   * Replaces this node with another node.
+   */
+  Node replaceWith(Node otherNode) { host.replaceWith(otherNode); }
+
+  /**
+   * Removes this node from the DOM.
+   */
+  void remove() => host.remove();
+
+  Node get nextNode => host.nextNode;
+
+  String get nodeName => host.nodeName;
+
+  Document get document => host.document;
+
+  Node get previousNode => host.previousNode;
+
+  String get text => host.text;
+
+  set text(String v) { host.text = v; }
+
+  bool contains(Node other) => host.contains(other);
+
+  bool hasChildNodes() => host.hasChildNodes();
+
+  Node insertBefore(Node newChild, Node refChild) =>
+    host.insertBefore(newChild, refChild);
+
+  Node insertAllBefore(Iterable<Node> newChild, Node refChild) =>
+    host.insertAllBefore(newChild, refChild);
+
+  Map<String, String> get attributes => host.attributes;
+  set attributes(Map<String, String> value) {
+    host.attributes = value;
+  }
+
+  List<Element> get elements => host.children;
+
+  set elements(List<Element> value) {
+    host.children = value;
+  }
+
+  List<Element> get children => host.children;
+
+  set children(List<Element> value) {
+    host.children = value;
+  }
+
+  Set<String> get classes => host.classes;
+
+  set classes(Iterable<String> value) {
+    host.classes = value;
+  }
+
+  CssRect get contentEdge => host.contentEdge;
+  CssRect get paddingEdge => host.paddingEdge;
+  CssRect get borderEdge => host.borderEdge;
+  CssRect get marginEdge => host.marginEdge;
+  Point get documentOffset => host.documentOffset;
+  Point offsetTo(Element parent) => host.offsetTo(parent);
+
+  Map<String, String> getNamespacedAttributes(String namespace) =>
+      host.getNamespacedAttributes(namespace);
+
+  CssStyleDeclaration getComputedStyle([String pseudoElement])
+    => host.getComputedStyle(pseudoElement);
+
+  Element clone(bool deep) => host.clone(deep);
+
+  Element get parent => host.parent;
+
+  Node get parentNode => host.parentNode;
+
+  String get nodeValue => host.nodeValue;
+
+  @deprecated
+  // TODO(sigmund): restore the old return type and call host.on when
+  // dartbug.com/8131 is fixed.
+  dynamic get on { throw new UnsupportedError('on is deprecated'); }
+
+  String get contentEditable => host.contentEditable;
+  set contentEditable(String v) { host.contentEditable = v; }
+
+  String get dir => host.dir;
+  set dir(String v) { host.dir = v; }
+
+  bool get draggable => host.draggable;
+  set draggable(bool v) { host.draggable = v; }
+
+  bool get hidden => host.hidden;
+  set hidden(bool v) { host.hidden = v; }
+
+  String get id => host.id;
+  set id(String v) { host.id = v; }
+
+  String get innerHTML => host.innerHtml;
+
+  void set innerHTML(String v) {
+    host.innerHtml = v;
+  }
+
+  String get innerHtml => host.innerHtml;
+  void set innerHtml(String v) {
+    host.innerHtml = v;
+  }
+
+  bool get isContentEditable => host.isContentEditable;
+
+  String get lang => host.lang;
+  set lang(String v) { host.lang = v; }
+
+  String get outerHtml => host.outerHtml;
+
+  bool get spellcheck => host.spellcheck;
+  set spellcheck(bool v) { host.spellcheck = v; }
+
+  int get tabIndex => host.tabIndex;
+  set tabIndex(int i) { host.tabIndex = i; }
+
+  String get title => host.title;
+
+  set title(String value) { host.title = value; }
+
+  bool get translate => host.translate;
+  set translate(bool v) { host.translate = v; }
+
+  String get dropzone => host.dropzone;
+  set dropzone(String v) { host.dropzone = v; }
+
+  void click() { host.click(); }
+
+  InputMethodContext getInputContext() => host.getInputContext();
+
+  Element insertAdjacentElement(String where, Element element) =>
+    host.insertAdjacentElement(where, element);
+
+  void insertAdjacentHtml(String where, String html) {
+    host.insertAdjacentHtml(where, html);
+  }
+
+  void insertAdjacentText(String where, String text) {
+    host.insertAdjacentText(where, text);
+  }
+
+  Map<String, String> get dataset => host.dataset;
+
+  set dataset(Map<String, String> value) {
+    host.dataset = value;
+  }
+
+  Element get nextElementSibling => host.nextElementSibling;
+
+  Element get offsetParent => host.offsetParent;
+
+  Element get previousElementSibling => host.previousElementSibling;
+
+  CssStyleDeclaration get style => host.style;
+
+  String get tagName => host.tagName;
+
+  String get pseudo => host.pseudo;
+
+  void set pseudo(String value) {
+    host.pseudo = value;
+  }
+
+  // Note: we are not polyfilling the shadow root here. This will be fixed when
+  // we migrate to the JS Shadow DOM polyfills. You can still use getShadowRoot
+  // to retrieve a node that behaves as the shadow root when Shadow DOM is not
+  // enabled.
+  ShadowRoot get shadowRoot => host.shadowRoot;
+
+  void blur() { host.blur(); }
+
+  void focus() { host.focus(); }
+
+  void scrollByLines(int lines) {
+    host.scrollByLines(lines);
+  }
+
+  void scrollByPages(int pages) {
+    host.scrollByPages(pages);
+  }
+
+  void scrollIntoView([ScrollAlignment alignment]) {
+    host.scrollIntoView(alignment);
+  }
+
+  bool matches(String selectors) => host.matches(selectors);
+
+  @deprecated
+  void requestFullScreen(int flags) { requestFullscreen(); }
+
+  void requestFullscreen() { host.requestFullscreen(); }
+
+  void requestPointerLock() { host.requestPointerLock(); }
+
+  Element query(String selectors) => host.query(selectors);
+
+  ElementList queryAll(String selectors) => host.queryAll(selectors);
+
+  HtmlCollection get $dom_children => host.$dom_children;
+
+  int get $dom_childElementCount => host.$dom_childElementCount;
+
+  String get className => host.className;
+  set className(String value) { host.className = value; }
+
+  @deprecated
+  int get clientHeight => client.height;
+
+  @deprecated
+  int get clientLeft => client.left;
+
+  @deprecated
+  int get clientTop => client.top;
+
+  @deprecated
+  int get clientWidth => client.width;
+
+  Rect get client => host.client;
+
+  Element get $dom_firstElementChild => host.$dom_firstElementChild;
+
+  Element get $dom_lastElementChild => host.$dom_lastElementChild;
+
+  @deprecated
+  int get offsetHeight => offset.height;
+
+  @deprecated
+  int get offsetLeft => offset.left;
+
+  @deprecated
+  int get offsetTop => offset.top;
+
+  @deprecated
+  int get offsetWidth => offset.width;
+
+  Rect get offset => host.offset;
+
+  int get scrollHeight => host.scrollHeight;
+
+  int get scrollLeft => host.scrollLeft;
+
+  int get scrollTop => host.scrollTop;
+
+  set scrollLeft(int value) { host.scrollLeft = value; }
+
+  set scrollTop(int value) { host.scrollTop = value; }
+
+  int get scrollWidth => host.scrollWidth;
+
+  String $dom_getAttribute(String name) =>
+      host.$dom_getAttribute(name);
+
+  String $dom_getAttributeNS(String namespaceUri, String localName) =>
+      host.$dom_getAttributeNS(namespaceUri, localName);
+
+  String $dom_setAttributeNS(
+      String namespaceUri, String localName, String value) {
+    host.$dom_setAttributeNS(namespaceUri, localName, value);
+  }
+
+  bool $dom_hasAttributeNS(String namespaceUri, String localName) =>
+      host.$dom_hasAttributeNS(namespaceUri, localName);
+
+  void $dom_removeAttributeNS(String namespaceUri, String localName) =>
+      host.$dom_removeAttributeNS(namespaceUri, localName);
+
+  Rect getBoundingClientRect() => host.getBoundingClientRect();
+
+  List<Rect> getClientRects() => host.getClientRects();
+
+  List<Node> getElementsByClassName(String name) =>
+      host.getElementsByClassName(name);
+
+  List<Node> $dom_getElementsByTagName(String name) =>
+      host.$dom_getElementsByTagName(name);
+
+  bool $dom_hasAttribute(String name) =>
+      host.$dom_hasAttribute(name);
+
+  List<Node> $dom_querySelectorAll(String selectors) =>
+      host.$dom_querySelectorAll(selectors);
+
+  void $dom_removeAttribute(String name) =>
+      host.$dom_removeAttribute(name);
+
+  void $dom_setAttribute(String name, String value) =>
+      host.$dom_setAttribute(name, value);
+
+  get $dom_attributes => host.$dom_attributes;
+
+  List<Node> get $dom_childNodes => host.$dom_childNodes;
+
+  Node get firstChild => host.firstChild;
+
+  Node get lastChild => host.lastChild;
+
+  String get localName => host.localName;
+  String get $dom_localName => host.$dom_localName;
+
+  String get namespaceUri => host.namespaceUri;
+  String get $dom_namespaceUri => host.$dom_namespaceUri;
+
+  int get nodeType => host.nodeType;
+
+  void $dom_addEventListener(String type, EventListener listener,
+                             [bool useCapture]) {
+    host.$dom_addEventListener(type, listener, useCapture);
+  }
+
+  bool dispatchEvent(Event event) => host.dispatchEvent(event);
+
+  Node $dom_removeChild(Node oldChild) => host.$dom_removeChild(oldChild);
+
+  void $dom_removeEventListener(String type, EventListener listener,
+                                [bool useCapture]) {
+    host.$dom_removeEventListener(type, listener, useCapture);
+  }
+
+  Node $dom_replaceChild(Node newChild, Node oldChild) =>
+      host.$dom_replaceChild(newChild, oldChild);
+
+  get xtag => host.xtag;
+
+  set xtag(value) { host.xtag = value; }
+
+  Node append(Node e) => host.append(e);
+
+  void appendText(String text) => host.appendText(text);
+
+  void appendHtml(String html) => host.appendHtml(html);
+
+  void $dom_scrollIntoView([bool alignWithTop]) {
+    if (alignWithTop == null) {
+      host.$dom_scrollIntoView();
+    } else {
+      host.$dom_scrollIntoView(alignWithTop);
+    }
+  }
+
+  void $dom_scrollIntoViewIfNeeded([bool centerIfNeeded]) {
+    if (centerIfNeeded == null) {
+      host.$dom_scrollIntoViewIfNeeded();
+    } else {
+      host.$dom_scrollIntoViewIfNeeded(centerIfNeeded);
+    }
+  }
+
+  String get regionOverset => host.regionOverset;
+
+  List<Range> getRegionFlowRanges() => host.getRegionFlowRanges();
+
+  // TODO(jmesserly): rename "created" to "onCreated".
+  void onCreated() => created();
+
+  Stream<Event> get onAbort => host.onAbort;
+  Stream<Event> get onBeforeCopy => host.onBeforeCopy;
+  Stream<Event> get onBeforeCut => host.onBeforeCut;
+  Stream<Event> get onBeforePaste => host.onBeforePaste;
+  Stream<Event> get onBlur => host.onBlur;
+  Stream<Event> get onChange => host.onChange;
+  Stream<MouseEvent> get onClick => host.onClick;
+  Stream<MouseEvent> get onContextMenu => host.onContextMenu;
+  Stream<Event> get onCopy => host.onCopy;
+  Stream<Event> get onCut => host.onCut;
+  Stream<Event> get onDoubleClick => host.onDoubleClick;
+  Stream<MouseEvent> get onDrag => host.onDrag;
+  Stream<MouseEvent> get onDragEnd => host.onDragEnd;
+  Stream<MouseEvent> get onDragEnter => host.onDragEnter;
+  Stream<MouseEvent> get onDragLeave => host.onDragLeave;
+  Stream<MouseEvent> get onDragOver => host.onDragOver;
+  Stream<MouseEvent> get onDragStart => host.onDragStart;
+  Stream<MouseEvent> get onDrop => host.onDrop;
+  Stream<Event> get onError => host.onError;
+  Stream<Event> get onFocus => host.onFocus;
+  Stream<Event> get onInput => host.onInput;
+  Stream<Event> get onInvalid => host.onInvalid;
+  Stream<KeyboardEvent> get onKeyDown => host.onKeyDown;
+  Stream<KeyboardEvent> get onKeyPress => host.onKeyPress;
+  Stream<KeyboardEvent> get onKeyUp => host.onKeyUp;
+  Stream<Event> get onLoad => host.onLoad;
+  Stream<MouseEvent> get onMouseDown => host.onMouseDown;
+  Stream<MouseEvent> get onMouseMove => host.onMouseMove;
+  Stream<Event> get onFullscreenChange => host.onFullscreenChange;
+  Stream<Event> get onFullscreenError => host.onFullscreenError;
+  Stream<Event> get onPaste => host.onPaste;
+  Stream<Event> get onReset => host.onReset;
+  Stream<Event> get onScroll => host.onScroll;
+  Stream<Event> get onSearch => host.onSearch;
+  Stream<Event> get onSelect => host.onSelect;
+  Stream<Event> get onSelectStart => host.onSelectStart;
+  Stream<Event> get onSubmit => host.onSubmit;
+  Stream<MouseEvent> get onMouseOut => host.onMouseOut;
+  Stream<MouseEvent> get onMouseOver => host.onMouseOver;
+  Stream<MouseEvent> get onMouseUp => host.onMouseUp;
+  Stream<TouchEvent> get onTouchCancel => host.onTouchCancel;
+  Stream<TouchEvent> get onTouchEnd => host.onTouchEnd;
+  Stream<TouchEvent> get onTouchEnter => host.onTouchEnter;
+  Stream<TouchEvent> get onTouchLeave => host.onTouchLeave;
+  Stream<TouchEvent> get onTouchMove => host.onTouchMove;
+  Stream<TouchEvent> get onTouchStart => host.onTouchStart;
+  Stream<TransitionEvent> get onTransitionEnd => host.onTransitionEnd;
+
+  // TODO(sigmund): do the normal forwarding when dartbug.com/7919 is fixed.
+  Stream<WheelEvent> get onMouseWheel {
+    throw new UnsupportedError('onMouseWheel is not supported');
+  }
+}
+
+
+typedef DocumentFragmentCreated(DocumentFragment fragment);
+
+Map<String, Function> _customElements;
+
+void _initCustomElement(Element node, CustomElement ctor()) {
+  CustomElement element = ctor();
+  element.host = node;
+
+  // TODO(jmesserly): replace lifecycle stuff with a proper polyfill.
+  element.created();
+
+  _registerLifecycleInsert(element);
+}
+
+void _registerLifecycleInsert(CustomElement element) {
+  runAsync(() {
+    // TODO(jmesserly): bottom up or top down insert?
+    var node = element.host;
+
+    // TODO(jmesserly): need a better check to see if the node has been removed.
+    if (node.parentNode == null) return;
+
+    _registerLifecycleRemove(element);
+    element.inserted();
+  });
+}
+
+void _registerLifecycleRemove(CustomElement element) {
+  // TODO(jmesserly): need fallback or polyfill for MutationObserver.
+  if (!MutationObserver.supported) return;
+
+  new MutationObserver((records, observer) {
+    var node = element.host;
+    for (var record in records) {
+      for (var removed in record.removedNodes) {
+        if (identical(node, removed)) {
+          observer.disconnect();
+          element.removed();
+          return;
+        }
+      }
+    }
+  }).observe(element.parentNode, childList: true);
+}
diff --git a/pkg/custom_element/lib/src/custom_tag_name.dart b/pkg/custom_element/lib/src/custom_tag_name.dart
new file mode 100644
index 0000000..72d9150
--- /dev/null
+++ b/pkg/custom_element/lib/src/custom_tag_name.dart
@@ -0,0 +1,27 @@
+// Copyright (c) 2013, 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 custom_element.src.custom_tag_name;
+
+/**
+ * Returns true if this is a valid custom element name. See:
+ * <https://dvcs.w3.org/hg/webcomponents/raw-file/tip/spec/custom/index.html#dfn-custom-element-name>
+ */
+bool isCustomTag(String name) {
+  if (!name.contains('-')) return false;
+
+  // These names have meaning in SVG or MathML, so they aren't allowed as custom
+  // tags.
+  var invalidNames = const {
+    'annotation-xml': '',
+    'color-profile': '',
+    'font-face': '',
+    'font-face-src': '',
+    'font-face-uri': '',
+    'font-face-format': '',
+    'font-face-name': '',
+    'missing-glyph': '',
+  };
+  return !invalidNames.containsKey(name);
+}
diff --git a/pkg/custom_element/pubspec.yaml b/pkg/custom_element/pubspec.yaml
new file mode 100644
index 0000000..e52b080
--- /dev/null
+++ b/pkg/custom_element/pubspec.yaml
@@ -0,0 +1,14 @@
+name: custom_element
+author: "Web UI Team <web-ui-dev@dartlang.org>"
+homepage: http://www.dartlang.org/
+description: >
+  Custom Elements let authors define their own elements. Authors associate code
+  with custom tag names, and then use those custom tag names as they would any
+  standard tag.
+dependencies:
+  meta: any
+  mutation_observer: any
+  # TODO(jmesserly): fix this, we should not depend on MDV.
+  mdv: any
+dev_dependencies:
+  unittest: any
diff --git a/pkg/custom_element/test/analyzer_test.dart b/pkg/custom_element/test/analyzer_test.dart
new file mode 100644
index 0000000..1ac251b
--- /dev/null
+++ b/pkg/custom_element/test/analyzer_test.dart
@@ -0,0 +1,13 @@
+// Copyright (c) 2013, 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 custom_element.test.analyzer_test;
+
+import 'package:custom_element/custom_element.dart';
+
+// @static-clean
+
+// This test ensures CustomElement compiles without errors.
+void main() {
+}
diff --git a/pkg/custom_element/test/custom_element_test.dart b/pkg/custom_element/test/custom_element_test.dart
new file mode 100644
index 0000000..e2f920a
--- /dev/null
+++ b/pkg/custom_element/test/custom_element_test.dart
@@ -0,0 +1,93 @@
+// Copyright (c) 2013, 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 custom_element.test.custom_element_test;
+
+import 'dart:async';
+import 'dart:html';
+import 'package:custom_element/custom_element.dart';
+import 'package:unittest/html_config.dart';
+import 'package:unittest/unittest.dart';
+
+main() {
+  useHtmlConfiguration();
+
+  // Load the MutationObserver polyfill.
+  HttpRequest.getString('/root_dart/pkg/mutation_observer/lib/'
+      'mutation_observer.js').then((code) {
+    document.head.children.add(new ScriptElement()..text = code);
+
+    customElementTests();
+  });
+}
+
+customElementTests() {
+  test('register creates the element and calls lifecycle methods', () {
+    // Add element to the page.
+    var element = new Element.html('<fancy-button>foo bar</fancy-button>');
+    document.body.nodes.add(element);
+
+    var xtag = null;
+    registerCustomElement('fancy-button', () => xtag = new FancyButton());
+    expect(xtag, isNotNull, reason: 'FancyButton was created');
+    expect(element.xtag, xtag, reason: 'xtag pointer should be set');
+    expect(xtag.host, element, reason: 'host pointer should be set');
+    expect(xtag.lifecycle, ['created']);
+    return new Future(() {
+      expect(xtag.lifecycle, ['created', 'inserted']);
+      element.remove();
+      // TODO(jmesserly): the extra future here is to give IE9 time to deliver
+      // its event. This seems wrong. We'll probably need some cooperation
+      // between Dart and the polyfill to coordinate the microtask event loop.
+      return new Future(() => new Future(() {
+        expect(xtag.lifecycle, ['created', 'inserted', 'removed']);
+      }));
+    });
+  });
+
+  test('create a component in code', () {
+    var element = createElement('super-button');
+    expect(element.xtag, element, reason: 'element not registered');
+
+    var xtag = null;
+    registerCustomElement('super-button', () => xtag = new FancyButton());
+
+    element = createElement('super-button');
+    expect(xtag, isNotNull, reason: 'FancyButton was created');
+    expect(element.xtag, xtag, reason: 'xtag pointer should be set');
+    expect(xtag.host, element, reason: 'host pointer should be set');
+    expect(xtag.lifecycle, ['created']);
+    return new Future(() {
+      expect(xtag.lifecycle, ['created'], reason: 'not inserted into document');
+
+      document.body.nodes.add(element);
+      return new Future(() {
+        expect(xtag.lifecycle, ['created'],
+            reason: 'mutation observer not implemented yet');
+
+        element.remove();
+        return new Future(() {
+          expect(xtag.lifecycle, ['created'],
+              reason: 'mutation observer not implemented yet');
+        });
+      });
+    });
+  });
+}
+
+class FancyButton extends CustomElement {
+  final lifecycle = [];
+  created() {
+    super.created();
+    lifecycle.add('created');
+  }
+  inserted() {
+    super.inserted();
+    lifecycle.add('inserted');
+  }
+  removed() {
+    super.removed();
+    lifecycle.add('removed');
+  }
+}
diff --git a/pkg/docgen/bin/docgen.dart b/pkg/docgen/bin/docgen.dart
index d10c325..48b9071 100644
--- a/pkg/docgen/bin/docgen.dart
+++ b/pkg/docgen/bin/docgen.dart
@@ -22,7 +22,8 @@
       outputToYaml: !results['json'],  
       includePrivate: results['include-private'], 
       includeSdk: results['parse-sdk'] || results['include-sdk'], 
-      parseSdk: results['parse-sdk']);
+      parseSdk: results['parse-sdk'],
+      append: results['append'] && new Directory('docs').existsSync());
 }
 
 /**
@@ -57,6 +58,9 @@
       defaultsTo: false, negatable: false);
   parser.addOption('package-root', 
       help: "Sets the package root of the library being analyzed.");
+  parser.addFlag('append', 
+      help: 'Append to the docs folder, library_list.txt and index.txt', 
+      defaultsTo: false, negatable: false);
   
   return parser;
 }
diff --git a/pkg/docgen/lib/docgen.dart b/pkg/docgen/lib/docgen.dart
index 6ad2609..2844d28 100644
--- a/pkg/docgen/lib/docgen.dart
+++ b/pkg/docgen/lib/docgen.dart
@@ -67,15 +67,19 @@
  */
 Future<bool> docgen(List<String> files, {String packageRoot,
     bool outputToYaml: true, bool includePrivate: false, bool includeSdk: false,
-    bool parseSdk: false}) {
+    bool parseSdk: false, bool append: false}) {
+  if (!append) {
+    var dir = new Directory('docs');
+    if (dir.existsSync()) dir.deleteSync(recursive: true);
+  }
+  
   if (packageRoot == null && !parseSdk) {
-    // TODO(janicejl): At the moment, if a single file is passed it, it is
-    // assumed that it does not have a package root unless it is passed in by
-    // the user. In future, find a better way to find the packageRoot and also
-    // fully test finding the packageRoot.
-    if (FileSystemEntity.typeSync(files.first)
-        == FileSystemEntityType.DIRECTORY) {
+    var type = FileSystemEntity.typeSync(files.first);
+    if (type == FileSystemEntityType.DIRECTORY) {
       packageRoot = _findPackageRoot(files.first);
+    } else if (type == FileSystemEntityType.FILE) {
+      logger.warning('WARNING: No package root defined. If Docgen fails, try '
+          'again by setting the --package-root option.');
     }
   }
   logger.info('Package Root: ${packageRoot}');
@@ -90,16 +94,13 @@
       }
       _documentLibraries(mirrorSystem.libraries.values,
           includeSdk: includeSdk, includePrivate: includePrivate,
-          outputToYaml: outputToYaml);
+          outputToYaml: outputToYaml, append: append);
 
       return true;
     });
 }
 
 List<String> _listLibraries(List<String> args) {
-  // TODO(janicejl): At the moment, only have support to have either one file,
-  // or one directory. This is because there can only be one package directory
-  // since only one docgen is created per run.
   if (args.length != 1) throw new UnsupportedError(USAGE);
   var libraries = new List<String>();
   var type = FileSystemEntity.typeSync(args[0]);
@@ -151,7 +152,7 @@
  * documentation of the libraries.
  */
 Future<MirrorSystem> getMirrorSystem(List<String> args, {String packageRoot,
-    bool parseSdk:false}) {
+    bool parseSdk: false}) {
   var libraries = !parseSdk ? _listLibraries(args) : _listSdk();
   if (libraries.isEmpty) throw new StateError('No Libraries.');
   // Finds the root of SDK library based off the location of docgen.
@@ -196,8 +197,8 @@
  * Creates documentation for filtered libraries.
  */
 void _documentLibraries(List<LibraryMirror> libraries,
-    {bool includeSdk:false, bool includePrivate:false, bool
-     outputToYaml:true}) {
+    {bool includeSdk: false, bool includePrivate: false, 
+    bool outputToYaml: true, bool append: false}) {
   libraries.forEach((lib) {
     // Files belonging to the SDK have a uri that begins with 'dart:'.
     if (includeSdk || !lib.uri.toString().startsWith('dart:')) {
@@ -209,14 +210,14 @@
   // the libraries. This will help the viewer know what files are available
   // to read in.
   _writeToFile(listDir('docs').join('\n').replaceAll('docs/', ''),
-      'library_list.txt');
+      'library_list.txt', append: append);
   // Outputs all the qualified names documented. This will help generate search
   // results. 
-  _writeToFile(qualifiedNameIndex.join('\n'), 'index.txt');
+  _writeToFile(qualifiedNameIndex.join('\n'), 'index.txt', append: append);
 }
 
 Library generateLibrary(dart2js.Dart2JsLibraryMirror library,
-  {bool includePrivate:false}) {
+  {bool includePrivate: false}) {
   _currentLibrary = library;
   var result = new Library(library.qualifiedName, _getComment(library),
       _getVariables(library.variables, includePrivate),
@@ -443,7 +444,7 @@
 /**
  * Writes text to a file in the 'docs' directory.
  */
-void _writeToFile(String text, String filename) {
+void _writeToFile(String text, String filename, {bool append: false}) {
   Directory dir = new Directory('docs');
   if (!dir.existsSync()) {
     dir.createSync();
@@ -452,8 +453,7 @@
   if (!file.existsSync()) {
     file.createSync();
   }
-  file.openSync();
-  file.writeAsString(text);
+  file.writeAsString(text, mode: append ? FileMode.APPEND : FileMode.WRITE);
 }
 
 /**
diff --git a/pkg/fixnum/lib/src/int32.dart b/pkg/fixnum/lib/src/int32.dart
index 84d9bfc..fb78a48 100644
--- a/pkg/fixnum/lib/src/int32.dart
+++ b/pkg/fixnum/lib/src/int32.dart
@@ -8,34 +8,34 @@
  * An immutable 32-bit signed integer, in the range [-2^31, 2^31 - 1].
  * Arithmetic operations may overflow in order to maintain this range.
  */
-class int32 implements intx {
+class Int32 implements IntX {
 
   /**
-   * The maximum positive value attainable by an [int32], namely
+   * The maximum positive value attainable by an [Int32], namely
    * 2147483647.
    */
-  static const int32 MAX_VALUE = const int32._internal(0x7FFFFFFF);
+  static const Int32 MAX_VALUE = const Int32._internal(0x7FFFFFFF);
 
   /**
-   * The minimum positive value attainable by an [int32], namely
+   * The minimum positive value attainable by an [Int32], namely
    * -2147483648.
    */
-  static int32 MIN_VALUE = const int32._internal(-0x80000000);
+  static const Int32 MIN_VALUE = const Int32._internal(-0x80000000);
 
   /**
-   * An [int32] constant equal to 0.
+   * An [Int32] constant equal to 0.
    */
-  static int32 ZERO = const int32._internal(0);
+  static const Int32 ZERO = const Int32._internal(0);
 
   /**
-   * An [int32] constant equal to 1.
+   * An [Int32] constant equal to 1.
    */
-  static int32 ONE = const int32._internal(1);
+  static const Int32 ONE = const Int32._internal(1);
 
   /**
-   * An [int32] constant equal to 2.
+   * An [Int32] constant equal to 2.
    */
-  static int32 TWO = const int32._internal(2);
+  static const Int32 TWO = const Int32._internal(2);
 
   // Hex digit char codes
   static const int _CC_0 = 48; // '0'.codeUnitAt(0)
@@ -59,14 +59,14 @@
 
   /**
    * Parses a [String] in a given [radix] between 2 and 16 and returns an
-   * [int32].
+   * [Int32].
    */
   // TODO(rice) - Make this faster by converting several digits at once.
-  static int32 parseRadix(String s, int radix) {
+  static Int32 parseRadix(String s, int radix) {
     if ((radix <= 1) || (radix > 16)) {
-      throw "Bad radix: $radix";
+      throw new ArgumentError("Bad radix: $radix");
     }
-    int32 x = ZERO;
+    Int32 x = ZERO;
     for (int i = 0; i < s.length; i++) {
       int c = s.codeUnitAt(i);
       int digit = _decodeHex(c);
@@ -79,14 +79,14 @@
   }
 
   /**
-   * Parses a decimal [String] and returns an [int32].
+   * Parses a decimal [String] and returns an [Int32].
    */
-  static int32 parseInt(String s) => new int32.fromInt(int.parse(s));
+  static Int32 parseInt(String s) => new Int32.fromInt(int.parse(s));
 
   /**
-   * Parses a hexadecimal [String] and returns an [int32].
+   * Parses a hexadecimal [String] and returns an [Int32].
    */
-  static int32 parseHex(String s) => parseRadix(s, 16);
+  static Int32 parseHex(String s) => parseRadix(s, 16);
 
   // Assumes i is <= 32-bit.
   static int _bitCount(int i) {
@@ -130,18 +130,18 @@
   // The internal value, kept in the range [MIN_VALUE, MAX_VALUE].
   final int _i;
 
-  const int32._internal(int i) : _i = i;
+  const Int32._internal(int i) : _i = i;
 
   /**
-   * Constructs an [int32] from an [int].  Only the low 32 bits of the input
+   * Constructs an [Int32] from an [int].  Only the low 32 bits of the input
    * are used.
    */
-  int32.fromInt(int i) : _i = (i & 0x7fffffff) - (i & 0x80000000);
+  Int32.fromInt(int i) : _i = (i & 0x7fffffff) - (i & 0x80000000);
 
   // Returns the [int] representation of the specified value. Throws
   // [ArgumentError] for non-integer arguments.
   int _toInt(val) {
-    if (val is int32) {
+    if (val is Int32) {
       return val._i;
     } else if (val is int) {
       return val;
@@ -151,99 +151,99 @@
 
   // The +, -, * , &, |, and ^ operaters deal with types as follows:
   //
-  // int32 + int => int32
-  // int32 + int32 => int32
-  // int32 + int64 => int64
+  // Int32 + int => Int32
+  // Int32 + Int32 => Int32
+  // Int32 + Int64 => Int64
   //
-  // The %, ~/ and remainder operators return an int32 even with an int64
+  // The %, ~/ and remainder operators return an Int32 even with an Int64
   // argument, since the result cannot be greater than the value on the
   // left-hand side:
   //
-  // int32 % int => int32
-  // int32 % int32 => int32
-  // int32 % int64 => int32
+  // Int32 % int => Int32
+  // Int32 % Int32 => Int32
+  // Int32 % Int64 => Int32
 
-  intx operator +(other) {
-    if (other is int64) {
+  IntX operator +(other) {
+    if (other is Int64) {
       return this.toInt64() + other;
     }
-    return new int32.fromInt(_i + _toInt(other));
+    return new Int32.fromInt(_i + _toInt(other));
   }
 
-  intx operator -(other) {
-    if (other is int64) {
+  IntX operator -(other) {
+    if (other is Int64) {
       return this.toInt64() - other;
     }
-    return new int32.fromInt(_i - _toInt(other));
+    return new Int32.fromInt(_i - _toInt(other));
   }
 
-  int32 operator -() => new int32.fromInt(-_i);
+  Int32 operator -() => new Int32.fromInt(-_i);
 
-  intx operator *(other) {
-    if (other is int64) {
+  IntX operator *(other) {
+    if (other is Int64) {
       return this.toInt64() * other;
     }
     // TODO(rice) - optimize
     return (this.toInt64() * other).toInt32();
   }
 
-  int32 operator %(other) {
-    if (other is int64) {
-      // Result will be int32
+  Int32 operator %(other) {
+    if (other is Int64) {
+      // Result will be Int32
       return (this.toInt64() % other).toInt32();
     }
-    return new int32.fromInt(_i % _toInt(other));
+    return new Int32.fromInt(_i % _toInt(other));
   }
 
-  int32 operator ~/(other) {
-    if (other is int64) {
+  Int32 operator ~/(other) {
+    if (other is Int64) {
       return (this.toInt64() ~/ other).toInt32();
     }
-    return new int32.fromInt(_i ~/ _toInt(other));
+    return new Int32.fromInt(_i ~/ _toInt(other));
   }
 
-  int32 remainder(other) {
-    if (other is int64) {
-      int64 t = this.toInt64();
+  Int32 remainder(other) {
+    if (other is Int64) {
+      Int64 t = this.toInt64();
       return (t - (t ~/ other) * other).toInt32();
     }
     return this - (this ~/ other) * other;
   }
 
-  int32 operator &(other) {
-    if (other is int64) {
+  Int32 operator &(other) {
+    if (other is Int64) {
       return (this.toInt64() & other).toInt32();
     }
-    return new int32.fromInt(_i & _toInt(other));
+    return new Int32.fromInt(_i & _toInt(other));
   }
 
-  int32 operator |(other) {
-    if (other is int64) {
+  Int32 operator |(other) {
+    if (other is Int64) {
       return (this.toInt64() | other).toInt32();
     }
-    return new int32.fromInt(_i | _toInt(other));
+    return new Int32.fromInt(_i | _toInt(other));
   }
 
-  int32 operator ^(other) {
-    if (other is int64) {
+  Int32 operator ^(other) {
+    if (other is Int64) {
       return (this.toInt64() ^ other).toInt32();
     }
-    return new int32.fromInt(_i ^ _toInt(other));
+    return new Int32.fromInt(_i ^ _toInt(other));
   }
 
-  int32 operator ~() => new int32.fromInt(~_i);
+  Int32 operator ~() => new Int32.fromInt(~_i);
 
-  int32 operator <<(int n) {
+  Int32 operator <<(int n) {
     if (n < 0) {
-      throw new ArgumentError("$n");
+      throw new ArgumentError(n);
     }
     n &= 31;
-    return new int32.fromInt(_i << n);
+    return new Int32.fromInt(_i << n);
   }
 
-  int32 operator >>(int n) {
+  Int32 operator >>(int n) {
     if (n < 0) {
-      throw new ArgumentError("$n");
+      throw new ArgumentError(n);
     }
     n &= 31;
     int value;
@@ -252,12 +252,12 @@
     } else {
       value = (_i >> n) | (0xffffffff << (32 - n));
     }
-    return new int32.fromInt(value);
+    return new Int32.fromInt(value);
   }
 
-  int32 shiftRightUnsigned(int n) {
+  Int32 shiftRightUnsigned(int n) {
     if (n < 0) {
-      throw new ArgumentError("$n");
+      throw new ArgumentError(n);
     }
     n &= 31;
     int value;
@@ -266,17 +266,17 @@
     } else {
       value = (_i >> n) & ((1 << (32 - n)) - 1);
     }
-    return new int32.fromInt(value);
+    return new Int32.fromInt(value);
   }
 
   /**
-   * Returns [true] if this [int32] has the same numeric value as the
-   * given object.  The argument may be an [int] or an [intx].
+   * Returns [true] if this [Int32] has the same numeric value as the
+   * given object.  The argument may be an [int] or an [IntX].
    */
   bool operator ==(other) {
-    if (other is int32) {
+    if (other is Int32) {
       return _i == other._i;
-    } else if (other is int64) {
+    } else if (other is Int64) {
       return this.toInt64() == other;
     } else if (other is int) {
       return _i == other;
@@ -285,35 +285,35 @@
   }
 
   int compareTo(Comparable other) {
-    if (other is int64) {
+    if (other is Int64) {
       return this.toInt64().compareTo(other);
     }
     return _i.compareTo(_toInt(other));
   }
 
   bool operator <(other) {
-    if (other is int64) {
+    if (other is Int64) {
       return this.toInt64() < other;
     }
     return _i < _toInt(other);
   }
 
   bool operator <=(other) {
-    if (other is int64) {
+    if (other is Int64) {
       return this.toInt64() <= other;
     }
     return _i <= _toInt(other);
   }
 
   bool operator >(other) {
-    if (other is int64) {
+    if (other is Int64) {
       return this.toInt64() > other;
     }
     return _i > _toInt(other);
   }
 
   bool operator >=(other) {
-    if (other is int64) {
+    if (other is Int64) {
       return this.toInt64() >= other;
     }
     return _i >= _toInt(other);
@@ -328,7 +328,7 @@
 
   int get hashCode => _i;
 
-  int32 abs() => _i < 0 ? new int32.fromInt(-_i) : this;
+  Int32 abs() => _i < 0 ? new Int32.fromInt(-_i) : this;
 
   int numberOfLeadingZeros() => _numberOfLeadingZeros(_i);
   int numberOfTrailingZeros() => _numberOfTrailingZeros(_i);
@@ -343,8 +343,8 @@
   }
 
   int toInt() => _i;
-  int32 toInt32() => this;
-  int64 toInt64() => new int64.fromInt(_i);
+  Int32 toInt32() => this;
+  Int64 toInt64() => new Int64.fromInt(_i);
 
   String toString() => _i.toString();
   String toHexString() => _i.toRadixString(16);
diff --git a/pkg/fixnum/lib/src/int64.dart b/pkg/fixnum/lib/src/int64.dart
index a179105..1a9d73a 100644
--- a/pkg/fixnum/lib/src/int64.dart
+++ b/pkg/fixnum/lib/src/int64.dart
@@ -8,7 +8,7 @@
  * An immutable 64-bit signed integer, in the range [-2^63, 2^63 - 1].
  * Arithmetic operations may overflow in order to maintain this range.
  */
-class int64 implements intx {
+class Int64 implements IntX {
 
   // A 64-bit integer is represented internally as three non-negative
   // integers, storing the 22 low, 22 middle, and 20 high bits of the
@@ -16,7 +16,7 @@
   // [0, 2^22 - 1] and _h (high) is in the range [0, 2^20 - 1].
   int _l, _m, _h;
 
-  // Note: instances of int64 are immutable outside of this library,
+  // Note: instances of [Int64] are immutable outside of this library,
   // therefore we may return a reference to an existing instance.
   // We take care to perform mutation only on internally-generated
   // instances before they are exposed to external code.
@@ -31,11 +31,11 @@
   static const int _SIGN_BIT_VALUE = 524288; // 1 << _SIGN_BIT
 
   // Cached constants
-  static int64 _MAX_VALUE;
-  static int64 _MIN_VALUE;
-  static int64 _ZERO;
-  static int64 _ONE;
-  static int64 _TWO;
+  static Int64 _MAX_VALUE;
+  static Int64 _MIN_VALUE;
+  static Int64 _ZERO;
+  static Int64 _ONE;
+  static Int64 _TWO;
 
   // Precompute the radix strings for MIN_VALUE to avoid the problem
   // of overflow of -MIN_VALUE.
@@ -59,70 +59,70 @@
   ];
 
   // The remainder of the last divide operation.
-  static int64 _remainder;
+  static Int64 _remainder;
 
   /**
-   * The maximum positive value attainable by an [int64], namely
+   * The maximum positive value attainable by an [Int64], namely
    * 9,223,372,036,854,775,807.
    */
-  static int64 get MAX_VALUE {
+  static Int64 get MAX_VALUE {
     if (_MAX_VALUE == null) {
-      _MAX_VALUE = new int64._bits(_MASK, _MASK, _MASK_2 >> 1);
+      _MAX_VALUE = new Int64._bits(_MASK, _MASK, _MASK_2 >> 1);
     }
     return _MAX_VALUE;
   }
 
   /**
-   * The minimum positive value attainable by an [int64], namely
+   * The minimum positive value attainable by an [Int64], namely
    * -9,223,372,036,854,775,808.
    */
-  static int64 get MIN_VALUE {
+  static Int64 get MIN_VALUE {
     if (_MIN_VALUE == null) {
-      _MIN_VALUE = new int64._bits(0, 0, _SIGN_BIT_VALUE);
+      _MIN_VALUE = new Int64._bits(0, 0, _SIGN_BIT_VALUE);
     }
     return _MIN_VALUE;
   }
 
   /**
-   * An [int64] constant equal to 0.
+   * An [Int64] constant equal to 0.
    */
-  static int64 get ZERO {
+  static Int64 get ZERO {
     if (_ZERO == null) {
-      _ZERO = new int64();
+      _ZERO = new Int64();
     }
     return _ZERO;
   }
 
   /**
-   * An [int64] constant equal to 1.
+   * An [Int64] constant equal to 1.
    */
-  static int64 get ONE {
+  static Int64 get ONE {
     if (_ONE == null) {
-      _ONE = new int64._bits(1, 0, 0);
+      _ONE = new Int64._bits(1, 0, 0);
     }
     return _ONE;
   }
 
   /**
-   * An [int64] constant equal to 2.
+   * An [Int64] constant equal to 2.
    */
-  static int64 get TWO {
+  static Int64 get TWO {
     if (_TWO == null) {
-      _TWO = new int64._bits(2, 0, 0);
+      _TWO = new Int64._bits(2, 0, 0);
     }
     return _TWO;
   }
 
   /**
    * Parses a [String] in a given [radix] between 2 and 16 and returns an
-   * [int64].
+   * [Int64].
    */
   // TODO(rice) - make this faster by converting several digits at once.
-  static int64 parseRadix(String s, int radix) {
+  static Int64 parseRadix(String s, int radix) {
     if ((radix <= 1) || (radix > 16)) {
-      throw "Bad radix: $radix";
+      throw new ArgumentError("Bad radix: $radix");
     }
-    int64 x = ZERO;
+    Int64 x = ZERO;
     int i = 0;
     bool negative = false;
     if (s[0] == '-') {
@@ -131,7 +131,7 @@
     }
     for (; i < s.length; i++) {
       int c = s.codeUnitAt(i);
-      int digit = int32._decodeHex(c);
+      int digit = Int32._decodeHex(c);
       if (digit < 0 || digit >= radix) {
         throw new Exception("Non-radix char code: $c");
       }
@@ -141,28 +141,28 @@
   }
 
   /**
-   * Parses a decimal [String] and returns an [int64].
+   * Parses a decimal [String] and returns an [Int64].
    */
-  static int64 parseInt(String s) => parseRadix(s, 10);
+  static Int64 parseInt(String s) => parseRadix(s, 10);
 
   /**
-   * Parses a hexadecimal [String] and returns an [int64].
+   * Parses a hexadecimal [String] and returns an [Int64].
    */
-  static int64 parseHex(String s) => parseRadix(s, 16);
+  static Int64 parseHex(String s) => parseRadix(s, 16);
 
   //
   // Public constructors
   //
 
   /**
-   * Constructs an [int64] equal to 0.
+   * Constructs an [Int64] equal to 0.
    */
-  int64() : _l = 0, _m = 0, _h = 0;
+  Int64() : _l = 0, _m = 0, _h = 0;
 
   /**
-   * Constructs an [int64] with a given [int] value.
+   * Constructs an [Int64] with a given [int] value.
    */
-  int64.fromInt(int value) {
+  Int64.fromInt(int value) {
     bool negative = false;
     if (value < 0) {
       negative = true;
@@ -188,7 +188,7 @@
     }
   }
 
-  factory int64.fromBytes(List<int> bytes) {
+  factory Int64.fromBytes(List<int> bytes) {
     int top = bytes[7] & 0xff;
     top <<= 8;
     top |= bytes[6] & 0xff;
@@ -205,10 +205,10 @@
     bottom <<= 8;
     bottom |= bytes[0] & 0xff;
 
-    return new int64.fromInts(top, bottom);
+    return new Int64.fromInts(top, bottom);
   }
 
-  factory int64.fromBytesBigEndian(List<int> bytes) {
+  factory Int64.fromBytesBigEndian(List<int> bytes) {
     int top = bytes[0] & 0xff;
     top <<= 8;
     top |= bytes[1] & 0xff;
@@ -225,14 +225,14 @@
     bottom <<= 8;
     bottom |= bytes[7] & 0xff;
 
-    return new int64.fromInts(top, bottom);
+    return new Int64.fromInts(top, bottom);
  }
 
   /**
-   * Constructs an [int64] from a pair of 32-bit integers having the value
+   * Constructs an [Int64] from a pair of 32-bit integers having the value
    * [:((top & 0xffffffff) << 32) | (bottom & 0xffffffff):].
    */
-  int64.fromInts(int top, int bottom) {
+  Int64.fromInts(int top, int bottom) {
     top &= 0xffffffff;
     bottom &= 0xffffffff;
     _l = bottom & _MASK;
@@ -240,50 +240,50 @@
     _h = (top >> 12) & _MASK_2;
   }
 
-  // Returns the [int64] representation of the specified value. Throws
+  // Returns the [Int64] representation of the specified value. Throws
   // [ArgumentError] for non-integer arguments.
-  int64 _promote(val) {
-    if (val is int64) {
+  Int64 _promote(val) {
+    if (val is Int64) {
       return val;
     } else if (val is int) {
-      return new int64.fromInt(val);
-    } else if (val is int32) {
+      return new Int64.fromInt(val);
+    } else if (val is Int32) {
       return val.toInt64();
     }
     throw new ArgumentError(val);
   }
 
-  int64 operator +(other) {
-    int64 o = _promote(other);
+  Int64 operator +(other) {
+    Int64 o = _promote(other);
     int sum0 = _l + o._l;
     int sum1 = _m + o._m + _shiftRight(sum0, _BITS);
     int sum2 = _h + o._h + _shiftRight(sum1, _BITS);
 
-    int64 result = new int64._bits(sum0 & _MASK, sum1 & _MASK, sum2 & _MASK_2);
+    Int64 result = new Int64._bits(sum0 & _MASK, sum1 & _MASK, sum2 & _MASK_2);
     return result;
   }
 
-  int64 operator -(other) {
-    int64 o = _promote(other);
+  Int64 operator -(other) {
+    Int64 o = _promote(other);
     int sum0 = _l - o._l;
     int sum1 = _m - o._m + _shiftRight(sum0, _BITS);
     int sum2 = _h - o._h + _shiftRight(sum1, _BITS);
 
-    int64 result = new int64._bits(sum0 & _MASK, sum1 & _MASK, sum2 & _MASK_2);
+    Int64 result = new Int64._bits(sum0 & _MASK, sum1 & _MASK, sum2 & _MASK_2);
     return result;
   }
 
-  int64 operator -() {
+  Int64 operator -() {
     // Like 0 - this.
     int sum0 = -_l;
     int sum1 = -_m + _shiftRight(sum0, _BITS);
     int sum2 = -_h + _shiftRight(sum1, _BITS);
 
-    return new int64._bits(sum0 & _MASK, sum1 & _MASK, sum2 & _MASK_2);
+    return new Int64._bits(sum0 & _MASK, sum1 & _MASK, sum2 & _MASK_2);
   }
 
-  int64 operator *(other) {
-    int64 o = _promote(other);
+  Int64 operator *(other) {
+    Int64 o = _promote(other);
 
     // Grab 13-bit chunks.
     int a0 = _l & 0x1fff;
@@ -363,65 +363,65 @@
     c1 &= _MASK;
     c2 &= _MASK_2;
 
-    return new int64._bits(c0, c1, c2);
+    return new Int64._bits(c0, c1, c2);
   }
 
-  int64 operator %(other) {
+  Int64 operator %(other) {
     if (other.isZero) {
       throw new IntegerDivisionByZeroException();
     }
     if (this.isZero) {
       return ZERO;
     }
-    int64 o = _promote(other).abs();
+    Int64 o = _promote(other).abs();
     _divMod(this, o, true);
     return _remainder < 0 ? (_remainder + o) : _remainder;
   }
 
-  int64 operator ~/(other) => _divMod(this, _promote(other), false);
+  Int64 operator ~/(other) => _divMod(this, _promote(other), false);
 
-  // int64 remainder(other) => this - (this ~/ other) * other;
-  int64 remainder(other) {
+  // Int64 remainder(other) => this - (this ~/ other) * other;
+  Int64 remainder(other) {
     if (other.isZero) {
       throw new IntegerDivisionByZeroException();
     }
-    int64 o = _promote(other).abs();
+    Int64 o = _promote(other).abs();
     _divMod(this, o, true);
     return _remainder;
   }
 
-  int64 operator &(other) {
-    int64 o = _promote(other);
+  Int64 operator &(other) {
+    Int64 o = _promote(other);
     int a0 = _l & o._l;
     int a1 = _m & o._m;
     int a2 = _h & o._h;
-    return new int64._bits(a0, a1, a2);
+    return new Int64._bits(a0, a1, a2);
   }
 
-  int64 operator |(other) {
-    int64 o = _promote(other);
+  Int64 operator |(other) {
+    Int64 o = _promote(other);
     int a0 = _l | o._l;
     int a1 = _m | o._m;
     int a2 = _h | o._h;
-    return new int64._bits(a0, a1, a2);
+    return new Int64._bits(a0, a1, a2);
   }
 
-  int64 operator ^(other) {
-    int64 o = _promote(other);
+  Int64 operator ^(other) {
+    Int64 o = _promote(other);
     int a0 = _l ^ o._l;
     int a1 = _m ^ o._m;
     int a2 = _h ^ o._h;
-    return new int64._bits(a0, a1, a2);
+    return new Int64._bits(a0, a1, a2);
   }
 
-  int64 operator ~() {
-    var result = new int64._bits((~_l) & _MASK, (~_m) & _MASK, (~_h) & _MASK_2);
+  Int64 operator ~() {
+    var result = new Int64._bits((~_l) & _MASK, (~_m) & _MASK, (~_h) & _MASK_2);
     return result;
   }
 
-  int64 operator <<(int n) {
+  Int64 operator <<(int n) {
     if (n < 0) {
-      throw new ArgumentError("$n");
+      throw new ArgumentError(n);
     }
     n &= 63;
 
@@ -440,12 +440,12 @@
       res2 = _l << (n - _BITS01);
     }
 
-    return new int64._bits(res0 & _MASK, res1 & _MASK, res2 & _MASK_2);
+    return new Int64._bits(res0 & _MASK, res1 & _MASK, res2 & _MASK_2);
   }
 
-  int64 operator >>(int n) {
+  Int64 operator >>(int n) {
     if (n < 0) {
-      throw new ArgumentError("$n");
+      throw new ArgumentError(n);
     }
     n &= 63;
 
@@ -481,12 +481,12 @@
       }
     }
 
-    return new int64._bits(res0 & _MASK, res1 & _MASK, res2 & _MASK_2);
+    return new Int64._bits(res0 & _MASK, res1 & _MASK, res2 & _MASK_2);
   }
 
-  int64 shiftRightUnsigned(int n) {
+  Int64 shiftRightUnsigned(int n) {
     if (n < 0) {
-      throw new ArgumentError("$n");
+      throw new ArgumentError(n);
     }
     n &= 63;
 
@@ -506,20 +506,20 @@
       res0 = a2 >> (n - _BITS01);
     }
 
-    return new int64._bits(res0 & _MASK, res1 & _MASK, res2 & _MASK_2);
+    return new Int64._bits(res0 & _MASK, res1 & _MASK, res2 & _MASK_2);
   }
 
   /**
-   * Returns [true] if this [int64] has the same numeric value as the
-   * given object.  The argument may be an [int] or an [intx].
+   * Returns [true] if this [Int64] has the same numeric value as the
+   * given object.  The argument may be an [int] or an [IntX].
    */
   bool operator ==(other) {
-    int64 o;
-    if (other is int64) {
+    Int64 o;
+    if (other is Int64) {
       o = other;
     } else if (other is int) {
-      o = new int64.fromInt(other);
-    } else if (other is int32) {
+      o = new Int64.fromInt(other);
+    } else if (other is Int32) {
       o = other.toInt64();
     }
     if (o != null) {
@@ -529,7 +529,7 @@
   }
 
   int compareTo(Comparable other) {
-    int64 o = _promote(other);
+    Int64 o = _promote(other);
     int signa = _h >> (_BITS2 - 1);
     int signb = o._h >> (_BITS2 - 1);
     if (signa != signb) {
@@ -577,7 +577,7 @@
   bool get isZero => _h == 0 && _m == 0 && _l == 0;
 
   /**
-   * Returns a hash code based on all the bits of this [int64].
+   * Returns a hash code based on all the bits of this [Int64].
    */
   int get hashCode {
     int bottom = ((_m & 0x3ff) << _BITS) | _l;
@@ -585,20 +585,20 @@
     return bottom ^ top;
   }
 
-  int64 abs() {
+  Int64 abs() {
     return this < 0 ? -this : this;
   }
 
   /**
-   * Returns the number of leading zeros in this [int64] as an [int]
+   * Returns the number of leading zeros in this [Int64] as an [int]
    * between 0 and 64.
    */
   int numberOfLeadingZeros() {
-    int b2 = int32._numberOfLeadingZeros(_h);
+    int b2 = Int32._numberOfLeadingZeros(_h);
     if (b2 == 32) {
-      int b1 = int32._numberOfLeadingZeros(_m);
+      int b1 = Int32._numberOfLeadingZeros(_m);
       if (b1 == 32) {
-        return int32._numberOfLeadingZeros(_l) + 32;
+        return Int32._numberOfLeadingZeros(_l) + 32;
       } else {
         return b1 + _BITS2 - (32 - _BITS);
       }
@@ -608,21 +608,21 @@
   }
 
   /**
-   * Returns the number of trailing zeros in this [int64] as an [int]
+   * Returns the number of trailing zeros in this [Int64] as an [int]
    * between 0 and 64.
    */
   int numberOfTrailingZeros() {
-    int zeros = int32._numberOfTrailingZeros(_l);
+    int zeros = Int32._numberOfTrailingZeros(_l);
     if (zeros < 32) {
       return zeros;
     }
 
-    zeros = int32._numberOfTrailingZeros(_m);
+    zeros = Int32._numberOfTrailingZeros(_m);
     if (zeros < 32) {
       return _BITS + zeros;
     }
 
-    zeros = int32._numberOfTrailingZeros(_h);
+    zeros = Int32._numberOfTrailingZeros(_h);
     if (zeros < 32) {
       return _BITS01 + zeros;
     }
@@ -665,23 +665,23 @@
   }
 
   /**
-   * Returns an [int32] containing the low 32 bits of this [int64].
+   * Returns an [Int32] containing the low 32 bits of this [Int64].
    */
-  int32 toInt32() {
-    return new int32.fromInt(((_m & 0x3ff) << _BITS) | _l);
+  Int32 toInt32() {
+    return new Int32.fromInt(((_m & 0x3ff) << _BITS) | _l);
   }
 
   /**
    * Returns [this].
    */
-  int64 toInt64() => this;
+  Int64 toInt64() => this;
 
   /**
-   * Returns the value of this [int64] as a decimal [String].
+   * Returns the value of this [Int64] as a decimal [String].
    */
   // TODO(rice) - Make this faster by converting several digits at once.
   String toString() {
-    int64 a = this;
+    Int64 a = this;
     if (a.isZero) {
       return "0";
     }
@@ -696,7 +696,7 @@
       a = -a;
     }
 
-    int64 ten = new int64._bits(10, 0, 0);
+    Int64 ten = new Int64._bits(10, 0, 0);
     while (!a.isZero) {
       a = _divMod(a, ten, true);
       result = "${_remainder._l}$result";
@@ -709,12 +709,12 @@
 
   // TODO(rice) - Make this faster by avoiding arithmetic.
   String toHexString() {
-    int64 x = new int64._copy(this);
+    Int64 x = new Int64._copy(this);
     if (isZero) {
       return "0";
     }
     String hexStr = "";
-    int64 digit_f = new int64.fromInt(0xf);
+    Int64 digit_f = new Int64.fromInt(0xf);
     while (!x.isZero) {
       int digit = x._l & 0xf;
       hexStr = "${_hexDigit(digit)}$hexStr";
@@ -725,9 +725,9 @@
 
   String toRadixString(int radix) {
     if ((radix <= 1) || (radix > 16)) {
-      throw "Bad radix: $radix";
+      throw new ArgumentError("Bad radix: $radix");
     }
-    int64 a = this;
+    Int64 a = this;
     if (a.isZero) {
       return "0";
     }
@@ -742,7 +742,7 @@
       a = -a;
     }
 
-    int64 r = new int64._bits(radix, 0, 0);
+    Int64 r = new Int64._bits(radix, 0, 0);
     while (!a.isZero) {
       a = _divMod(a, r, true);
       result = "${_hexDigit(_remainder._l)}$result";
@@ -751,19 +751,19 @@
   }
 
   String toDebugString() {
-    return "int64[_l=$_l, _m=$_m, _h=$_h]";
+    return "Int64[_l=$_l, _m=$_m, _h=$_h]";
   }
 
   /**
-   * Constructs an [int64] with a given bitwise representation.  No validation
+   * Constructs an [Int64] with a given bitwise representation.  No validation
    * is performed.
    */
-  int64._bits(int this._l, int this._m, int this._h);
+  Int64._bits(int this._l, int this._m, int this._h);
 
   /**
-   * Constructs an [int64] with the same value as an existing [int64].
+   * Constructs an [Int64] with the same value as an existing [Int64].
    */
-  int64._copy(int64 other) {
+  Int64._copy(Int64 other) {
     _l = other._l;
     _m = other._m;
     _h = other._h;
@@ -848,7 +848,7 @@
    * }
    */
   // Note: mutates [a].
-  static bool _trialSubtract(int64 a, int64 b) {
+  static bool _trialSubtract(Int64 a, Int64 b) {
     // Early exit.
     int sum2 = a._h - b._h;
     if (sum2 < 0) {
@@ -871,15 +871,15 @@
   }
 
   // Note: mutates [a] via _trialSubtract.
-  static int64 _divModHelper(int64 a, int64 b,
+  static Int64 _divModHelper(Int64 a, Int64 b,
       bool negative, bool aIsNegative, bool aIsMinValue,
       bool computeRemainder) {
     // Align the leading one bits of a and b by shifting b left.
     int shift = b.numberOfLeadingZeros() - a.numberOfLeadingZeros();
-    int64 bshift = b << shift;
+    Int64 bshift = b << shift;
 
     // Quotient must be a new instance since we mutate it.
-    int64 quotient = new int64();
+    Int64 quotient = new Int64();
     while (shift >= 0) {
       bool gte = _trialSubtract(a, bshift);
       if (gte) {
@@ -911,7 +911,7 @@
     return quotient;
   }
 
-  int64 _divModByMinValue(bool computeRemainder) {
+  Int64 _divModByMinValue(bool computeRemainder) {
     // MIN_VALUE / MIN_VALUE == 1, remainder = 0
     // (x != MIN_VALUE) / MIN_VALUE == 0, remainder == x
     if (isMinValue) {
@@ -930,7 +930,7 @@
    * this &= ((1L << bits) - 1)
    */
   // Note: mutates [this].
-  int64 _maskRight(int bits) {
+  Int64 _maskRight(int bits) {
     int b0, b1, b2;
     if (bits <= _BITS) {
       b0 = _l & ((1 << bits) - 1);
@@ -950,16 +950,16 @@
     _h = b2;
   }
 
-  static int64 _divModByShift(int64 a, int bpower, bool negative, bool aIsCopy,
+  static Int64 _divModByShift(Int64 a, int bpower, bool negative, bool aIsCopy,
       bool aIsNegative, bool computeRemainder) {
-    int64 c = a >> bpower;
+    Int64 c = a >> bpower;
     if (negative) {
       c._negate();
     }
 
     if (computeRemainder) {
       if (!aIsCopy) {
-        a = new int64._copy(a);
+        a = new Int64._copy(a);
       }
       a._maskRight(bpower);
       if (aIsNegative) {
@@ -991,19 +991,19 @@
       return -1;
     }
     if (h == 0 && m == 0 && l != 0) {
-      return int32._numberOfTrailingZeros(l);
+      return Int32._numberOfTrailingZeros(l);
     }
     if (h == 0 && m != 0 && l == 0) {
-      return int32._numberOfTrailingZeros(m) + _BITS;
+      return Int32._numberOfTrailingZeros(m) + _BITS;
     }
     if (h != 0 && m == 0 && l == 0) {
-      return int32._numberOfTrailingZeros(h) + _BITS01;
+      return Int32._numberOfTrailingZeros(h) + _BITS01;
     }
 
     return -1;
   }
 
-  static int64 _divMod(int64 a, int64 b, bool computeRemainder) {
+  static Int64 _divMod(Int64 a, Int64 b, bool computeRemainder) {
     if (b.isZero) {
       throw new IntegerDivisionByZeroException();
     }
@@ -1029,7 +1029,7 @@
 
     // True if the original value of a is negative.
     bool aIsNegative = false;
-    // True if the original value of a is int64.MIN_VALUE.
+    // True if the original value of a is Int64.MIN_VALUE.
     bool aIsMinValue = false;
 
     /*
@@ -1056,12 +1056,12 @@
       // If b is not a power of two, treat -a as MAX_VALUE (instead of the
       // actual value (MAX_VALUE + 1)).
       if (bpower == -1) {
-        a = new int64._copy(MAX_VALUE);
+        a = new Int64._copy(MAX_VALUE);
         aIsCopy = true;
         negative = !negative;
       } else {
         // Signed shift of MIN_VALUE produces the right answer.
-        int64 c = a >> bpower;
+        Int64 c = a >> bpower;
         if (negative) {
           c._negate();
         }
@@ -1090,14 +1090,14 @@
         if (aIsNegative) {
           _remainder = -a;
         } else {
-          _remainder = aIsCopy ? a : new int64._copy(a);
+          _remainder = aIsCopy ? a : new Int64._copy(a);
         }
       }
       return ZERO;
     }
 
     // Generate the quotient using bit-at-a-time long division.
-    return _divModHelper(aIsCopy ? a : new int64._copy(a), b, negative,
+    return _divModHelper(aIsCopy ? a : new Int64._copy(a), b, negative,
         aIsNegative, aIsMinValue, computeRemainder);
   }
 }
diff --git a/pkg/fixnum/lib/src/intx.dart b/pkg/fixnum/lib/src/intx.dart
index 582fe72..a2bb0f0 100644
--- a/pkg/fixnum/lib/src/intx.dart
+++ b/pkg/fixnum/lib/src/intx.dart
@@ -7,32 +7,32 @@
 /**
  * A fixed-precision integer.
  */
-abstract class intx implements Comparable {
+abstract class IntX implements Comparable {
 
   // Arithmetic operations.
-  intx operator +(other);
-  intx operator -(other);
+  IntX operator +(other);
+  IntX operator -(other);
   // The unary '-' operator.  Note that -MIN_VALUE will be equal
   // to MIN_VALUE due to overflow.
-  intx operator -();
-  intx operator *(other);
-  intx operator %(other);
+  IntX operator -();
+  IntX operator *(other);
+  IntX operator %(other);
   // Truncating division.
-  intx operator ~/(other);
-  intx remainder(other);
+  IntX operator ~/(other);
+  IntX remainder(other);
 
   // Note: no / operator
 
   // Bit-operations.
-  intx operator &(other);
-  intx operator |(other);
-  intx operator ^(other);
-  intx operator ~();
-  intx operator <<(int shiftAmount);
-  intx operator >>(int shiftAmount);
-  intx shiftRightUnsigned(int shiftAmount);
+  IntX operator &(other);
+  IntX operator |(other);
+  IntX operator ^(other);
+  IntX operator ~();
+  IntX operator <<(int shiftAmount);
+  IntX operator >>(int shiftAmount);
+  IntX shiftRightUnsigned(int shiftAmount);
 
-  // Relational operations, may be applied to intx or int.
+  // Relational operations, may be applied to IntX or int.
   int compareTo(Comparable other);
   bool operator ==(other);
   bool operator <(other);
@@ -50,55 +50,55 @@
 
   int get hashCode;
 
-  intx abs();
+  IntX abs();
 
   /**
-   * Returns the number of leading zeros in this [intx] as an [int]
+   * Returns the number of leading zeros in this [IntX] as an [int]
    * between 0 and 64.
    */
   int numberOfLeadingZeros();
 
   /**
-   * Returns the number of trailing zeros in this [intx] as an [int]
+   * Returns the number of trailing zeros in this [IntX] as an [int]
    * between 0 and 64.
    */
   int numberOfTrailingZeros();
 
   /**
-   * Converts this [intx] to a [List] of [int], starting with the least
+   * Converts this [IntX] to a [List] of [int], starting with the least
    * significant byte.
    */
   List<int> toBytes();
 
   /**
-   * Converts this [intx] to an [int].  On some platforms, inputs with large
+   * Converts this [IntX] to an [int].  On some platforms, inputs with large
    * absolute values (i.e., > 2^52) may lose some of their low bits.
    */
   int toInt();
 
   /**
-   * Converts an [intx] to 32 bits.  Narrower values are sign extended and
+   * Converts an [IntX] to 32 bits.  Narrower values are sign extended and
    * wider values have their high bits truncated.
    */
-  int32 toInt32();
+  Int32 toInt32();
 
   /**
-   * Converts an [intx] to 64 bits.
+   * Converts an [IntX] to 64 bits.
    */
-  int64 toInt64();
+  Int64 toInt64();
 
   /**
-   * Returns the value of this [intx] as a decimal [String].
+   * Returns the value of this [IntX] as a decimal [String].
    */
   String toString();
 
   /**
-   * Returns the value of this [intx] as a hexadecimal [String].
+   * Returns the value of this [IntX] as a hexadecimal [String].
    */
   String toHexString();
 
   /**
-   * Returns the value of this [intx] as a [String] in the given radix.
+   * Returns the value of this [IntX] as a [String] in the given radix.
    * [radix] must be an integer between 2 and 16, inclusive.
    */
   String toRadixString(int radix);
diff --git a/pkg/fixnum/test/int_32_test.dart b/pkg/fixnum/test/int_32_test.dart
index 7e27d41..401f533 100644
--- a/pkg/fixnum/test/int_32_test.dart
+++ b/pkg/fixnum/test/int_32_test.dart
@@ -2,251 +2,251 @@
 // 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 int32test;
+library Int32test;
 import 'package:fixnum/fixnum.dart';
 import 'package:unittest/unittest.dart';
 
 void main() {
   group("arithmetic operators", () {
-    int32 n1 = new int32.fromInt(1234);
-    int32 n2 = new int32.fromInt(9876);
-    int32 n3 = new int32.fromInt(-1234);
-    int32 n4 = new int32.fromInt(-9876);
-    int32 n5 = new int32.fromInt(0x12345678);
-    int32 n6 = new int32.fromInt(0x22222222);
+    Int32 n1 = new Int32.fromInt(1234);
+    Int32 n2 = new Int32.fromInt(9876);
+    Int32 n3 = new Int32.fromInt(-1234);
+    Int32 n4 = new Int32.fromInt(-9876);
+    Int32 n5 = new Int32.fromInt(0x12345678);
+    Int32 n6 = new Int32.fromInt(0x22222222);
 
     test("+", () {
-      expect(n1 + n2, new int32.fromInt(11110));
-      expect(n3 + n2, new int32.fromInt(8642));
-      expect(n3 + n4, new int32.fromInt(-11110));
-      expect(int32.MAX_VALUE + 1, int32.MIN_VALUE);
-      expect(() => new int32.fromInt(17) + null, throws);
+      expect(n1 + n2, new Int32.fromInt(11110));
+      expect(n3 + n2, new Int32.fromInt(8642));
+      expect(n3 + n4, new Int32.fromInt(-11110));
+      expect(Int32.MAX_VALUE + 1, Int32.MIN_VALUE);
+      expect(() => new Int32.fromInt(17) + null, throws);
     });
 
     test("-", () {
-      expect(n1 - n2, new int32.fromInt(-8642));
-      expect(n3 - n2, new int32.fromInt(-11110));
-      expect(n3 - n4, new int32.fromInt(8642));
-      expect(int32.MIN_VALUE - 1, int32.MAX_VALUE);
-      expect(() => new int32.fromInt(17) - null, throws);
+      expect(n1 - n2, new Int32.fromInt(-8642));
+      expect(n3 - n2, new Int32.fromInt(-11110));
+      expect(n3 - n4, new Int32.fromInt(8642));
+      expect(Int32.MIN_VALUE - 1, Int32.MAX_VALUE);
+      expect(() => new Int32.fromInt(17) - null, throws);
     });
 
     test("unary -", () {
-      expect(-n1, new int32.fromInt(-1234));
-      expect(-int32.ZERO, int32.ZERO);
+      expect(-n1, new Int32.fromInt(-1234));
+      expect(-Int32.ZERO, Int32.ZERO);
     });
 
     test("*", () {
-      expect(n1 * n2, new int32.fromInt(12186984));
-      expect(n2 * n3, new int32.fromInt(-12186984));
-      expect(n3 * n3, new int32.fromInt(1522756));
-      expect(n3 * n2, new int32.fromInt(-12186984));
-      expect(new int32.fromInt(0x12345678) * new int32.fromInt(0x22222222),
-          new int32.fromInt(-899716112));
-      expect((new int32.fromInt(123456789) * new int32.fromInt(987654321)),
-          new int32.fromInt(-67153019));
-      expect(new int32.fromInt(0x12345678) * new int64.fromInt(0x22222222),
-          new int64.fromInts(0x026D60DC, 0xCA5F6BF0));
-      expect((new int32.fromInt(123456789) * 987654321),
-          new int32.fromInt(-67153019));
-      expect(() => new int32.fromInt(17) * null, throws);
+      expect(n1 * n2, new Int32.fromInt(12186984));
+      expect(n2 * n3, new Int32.fromInt(-12186984));
+      expect(n3 * n3, new Int32.fromInt(1522756));
+      expect(n3 * n2, new Int32.fromInt(-12186984));
+      expect(new Int32.fromInt(0x12345678) * new Int32.fromInt(0x22222222),
+          new Int32.fromInt(-899716112));
+      expect((new Int32.fromInt(123456789) * new Int32.fromInt(987654321)),
+          new Int32.fromInt(-67153019));
+      expect(new Int32.fromInt(0x12345678) * new Int64.fromInt(0x22222222),
+          new Int64.fromInts(0x026D60DC, 0xCA5F6BF0));
+      expect((new Int32.fromInt(123456789) * 987654321),
+          new Int32.fromInt(-67153019));
+      expect(() => new Int32.fromInt(17) * null, throws);
     });
 
     test("~/", () {
-      expect(new int32.fromInt(829893893) ~/ new int32.fromInt(1919),
-          new int32.fromInt(432461));
-      expect(new int32.fromInt(0x12345678) ~/ new int32.fromInt(0x22),
-          new int32.fromInt(0x12345678 ~/ 0x22));
-      expect(new int32.fromInt(829893893) ~/ new int64.fromInt(1919),
-          new int32.fromInt(432461));
-      expect(new int32.fromInt(0x12345678) ~/ new int64.fromInt(0x22),
-          new int32.fromInt(0x12345678 ~/ 0x22));
-      expect(new int32.fromInt(829893893) ~/ 1919, new int32.fromInt(432461));
-      expect(() => new int32.fromInt(17) ~/ int32.ZERO, throws);
-      expect(() => new int32.fromInt(17) ~/ null, throws);
+      expect(new Int32.fromInt(829893893) ~/ new Int32.fromInt(1919),
+          new Int32.fromInt(432461));
+      expect(new Int32.fromInt(0x12345678) ~/ new Int32.fromInt(0x22),
+          new Int32.fromInt(0x12345678 ~/ 0x22));
+      expect(new Int32.fromInt(829893893) ~/ new Int64.fromInt(1919),
+          new Int32.fromInt(432461));
+      expect(new Int32.fromInt(0x12345678) ~/ new Int64.fromInt(0x22),
+          new Int32.fromInt(0x12345678 ~/ 0x22));
+      expect(new Int32.fromInt(829893893) ~/ 1919, new Int32.fromInt(432461));
+      expect(() => new Int32.fromInt(17) ~/ Int32.ZERO, throws);
+      expect(() => new Int32.fromInt(17) ~/ null, throws);
     });
 
     test("%", () {
-      expect(new int32.fromInt(0x12345678) % new int32.fromInt(0x22),
-          new int32.fromInt(0x12345678 % 0x22));
-      expect(new int32.fromInt(0x12345678) % new int64.fromInt(0x22),
-          new int32.fromInt(0x12345678 % 0x22));
-      expect(() => new int32.fromInt(17) % null, throws);
+      expect(new Int32.fromInt(0x12345678) % new Int32.fromInt(0x22),
+          new Int32.fromInt(0x12345678 % 0x22));
+      expect(new Int32.fromInt(0x12345678) % new Int64.fromInt(0x22),
+          new Int32.fromInt(0x12345678 % 0x22));
+      expect(() => new Int32.fromInt(17) % null, throws);
     });
 
     test("remainder", () {
-      expect(new int32.fromInt(0x12345678).remainder(new int32.fromInt(0x22)),
-          new int32.fromInt(0x12345678.remainder(0x22)));
-      expect(new int32.fromInt(0x12345678).remainder(new int32.fromInt(-0x22)),
-          new int32.fromInt(0x12345678.remainder(-0x22)));
-      expect(new int32.fromInt(-0x12345678).remainder(new int32.fromInt(-0x22)),
-          new int32.fromInt(-0x12345678.remainder(-0x22)));
-      expect(new int32.fromInt(-0x12345678).remainder(new int32.fromInt(0x22)),
-          new int32.fromInt(-0x12345678.remainder(0x22)));
-      expect(new int32.fromInt(0x12345678).remainder(new int64.fromInt(0x22)),
-          new int32.fromInt(0x12345678.remainder(0x22)));
-      expect(() => new int32.fromInt(17).remainder(null), throws);
+      expect(new Int32.fromInt(0x12345678).remainder(new Int32.fromInt(0x22)),
+          new Int32.fromInt(0x12345678.remainder(0x22)));
+      expect(new Int32.fromInt(0x12345678).remainder(new Int32.fromInt(-0x22)),
+          new Int32.fromInt(0x12345678.remainder(-0x22)));
+      expect(new Int32.fromInt(-0x12345678).remainder(new Int32.fromInt(-0x22)),
+          new Int32.fromInt(-0x12345678.remainder(-0x22)));
+      expect(new Int32.fromInt(-0x12345678).remainder(new Int32.fromInt(0x22)),
+          new Int32.fromInt(-0x12345678.remainder(0x22)));
+      expect(new Int32.fromInt(0x12345678).remainder(new Int64.fromInt(0x22)),
+          new Int32.fromInt(0x12345678.remainder(0x22)));
+      expect(() => new Int32.fromInt(17).remainder(null), throws);
     });
   });
 
   group("comparison operators", () {
     test("<", () {
-      expect(new int32.fromInt(17) < new int32.fromInt(18), true);
-      expect(new int32.fromInt(17) < new int32.fromInt(17), false);
-      expect(new int32.fromInt(17) < new int32.fromInt(16), false);
-      expect(new int32.fromInt(17) < new int64.fromInt(18), true);
-      expect(new int32.fromInt(17) < new int64.fromInt(17), false);
-      expect(new int32.fromInt(17) < new int64.fromInt(16), false);
-      expect(int32.MIN_VALUE < int32.MAX_VALUE, true);
-      expect(int32.MAX_VALUE < int32.MIN_VALUE, false);
-      expect(() => new int32.fromInt(17) < null, throws);
+      expect(new Int32.fromInt(17) < new Int32.fromInt(18), true);
+      expect(new Int32.fromInt(17) < new Int32.fromInt(17), false);
+      expect(new Int32.fromInt(17) < new Int32.fromInt(16), false);
+      expect(new Int32.fromInt(17) < new Int64.fromInt(18), true);
+      expect(new Int32.fromInt(17) < new Int64.fromInt(17), false);
+      expect(new Int32.fromInt(17) < new Int64.fromInt(16), false);
+      expect(Int32.MIN_VALUE < Int32.MAX_VALUE, true);
+      expect(Int32.MAX_VALUE < Int32.MIN_VALUE, false);
+      expect(() => new Int32.fromInt(17) < null, throws);
     });
 
     test("<=", () {
-      expect(new int32.fromInt(17) <= new int32.fromInt(18), true);
-      expect(new int32.fromInt(17) <= new int32.fromInt(17), true);
-      expect(new int32.fromInt(17) <= new int32.fromInt(16), false);
-      expect(new int32.fromInt(17) <= new int64.fromInt(18), true);
-      expect(new int32.fromInt(17) <= new int64.fromInt(17), true);
-      expect(new int32.fromInt(17) <= new int64.fromInt(16), false);
-      expect(int32.MIN_VALUE <= int32.MAX_VALUE, true);
-      expect(int32.MAX_VALUE <= int32.MIN_VALUE, false);
-      expect(() => new int32.fromInt(17) <= null, throws);
+      expect(new Int32.fromInt(17) <= new Int32.fromInt(18), true);
+      expect(new Int32.fromInt(17) <= new Int32.fromInt(17), true);
+      expect(new Int32.fromInt(17) <= new Int32.fromInt(16), false);
+      expect(new Int32.fromInt(17) <= new Int64.fromInt(18), true);
+      expect(new Int32.fromInt(17) <= new Int64.fromInt(17), true);
+      expect(new Int32.fromInt(17) <= new Int64.fromInt(16), false);
+      expect(Int32.MIN_VALUE <= Int32.MAX_VALUE, true);
+      expect(Int32.MAX_VALUE <= Int32.MIN_VALUE, false);
+      expect(() => new Int32.fromInt(17) <= null, throws);
     });
 
     test("==", () {
-      expect(new int32.fromInt(17) == new int32.fromInt(18), false);
-      expect(new int32.fromInt(17) == new int32.fromInt(17), true);
-      expect(new int32.fromInt(17) == new int32.fromInt(16), false);
-      expect(new int32.fromInt(17) == new int64.fromInt(18), false);
-      expect(new int32.fromInt(17) == new int64.fromInt(17), true);
-      expect(new int32.fromInt(17) == new int64.fromInt(16), false);
-      expect(int32.MIN_VALUE == int32.MAX_VALUE, false);
-      expect(new int32.fromInt(17) == new Object(), false);
-      expect(new int32.fromInt(17) == null, false);
+      expect(new Int32.fromInt(17) == new Int32.fromInt(18), false);
+      expect(new Int32.fromInt(17) == new Int32.fromInt(17), true);
+      expect(new Int32.fromInt(17) == new Int32.fromInt(16), false);
+      expect(new Int32.fromInt(17) == new Int64.fromInt(18), false);
+      expect(new Int32.fromInt(17) == new Int64.fromInt(17), true);
+      expect(new Int32.fromInt(17) == new Int64.fromInt(16), false);
+      expect(Int32.MIN_VALUE == Int32.MAX_VALUE, false);
+      expect(new Int32.fromInt(17) == new Object(), false);
+      expect(new Int32.fromInt(17) == null, false);
     });
 
     test(">=", () {
-      expect(new int32.fromInt(17) >= new int32.fromInt(18), false);
-      expect(new int32.fromInt(17) >= new int32.fromInt(17), true);
-      expect(new int32.fromInt(17) >= new int32.fromInt(16), true);
-      expect(new int32.fromInt(17) >= new int64.fromInt(18), false);
-      expect(new int32.fromInt(17) >= new int64.fromInt(17), true);
-      expect(new int32.fromInt(17) >= new int64.fromInt(16), true);
-      expect(int32.MIN_VALUE >= int32.MAX_VALUE, false);
-      expect(int32.MAX_VALUE >= int32.MIN_VALUE, true);
-      expect(() => new int32.fromInt(17) >= null, throws);
+      expect(new Int32.fromInt(17) >= new Int32.fromInt(18), false);
+      expect(new Int32.fromInt(17) >= new Int32.fromInt(17), true);
+      expect(new Int32.fromInt(17) >= new Int32.fromInt(16), true);
+      expect(new Int32.fromInt(17) >= new Int64.fromInt(18), false);
+      expect(new Int32.fromInt(17) >= new Int64.fromInt(17), true);
+      expect(new Int32.fromInt(17) >= new Int64.fromInt(16), true);
+      expect(Int32.MIN_VALUE >= Int32.MAX_VALUE, false);
+      expect(Int32.MAX_VALUE >= Int32.MIN_VALUE, true);
+      expect(() => new Int32.fromInt(17) >= null, throws);
     });
 
     test(">", () {
-      expect(new int32.fromInt(17) > new int32.fromInt(18), false);
-      expect(new int32.fromInt(17) > new int32.fromInt(17), false);
-      expect(new int32.fromInt(17) > new int32.fromInt(16), true);
-      expect(new int32.fromInt(17) > new int64.fromInt(18), false);
-      expect(new int32.fromInt(17) > new int64.fromInt(17), false);
-      expect(new int32.fromInt(17) > new int64.fromInt(16), true);
-      expect(int32.MIN_VALUE > int32.MAX_VALUE, false);
-      expect(int32.MAX_VALUE > int32.MIN_VALUE, true);
-      expect(() => new int32.fromInt(17) > null, throws);
+      expect(new Int32.fromInt(17) > new Int32.fromInt(18), false);
+      expect(new Int32.fromInt(17) > new Int32.fromInt(17), false);
+      expect(new Int32.fromInt(17) > new Int32.fromInt(16), true);
+      expect(new Int32.fromInt(17) > new Int64.fromInt(18), false);
+      expect(new Int32.fromInt(17) > new Int64.fromInt(17), false);
+      expect(new Int32.fromInt(17) > new Int64.fromInt(16), true);
+      expect(Int32.MIN_VALUE > Int32.MAX_VALUE, false);
+      expect(Int32.MAX_VALUE > Int32.MIN_VALUE, true);
+      expect(() => new Int32.fromInt(17) > null, throws);
     });
   });
 
   group("bitwise operators", () {
     test("&", () {
-      expect(new int32.fromInt(0x12345678) & new int32.fromInt(0x22222222),
-          new int32.fromInt(0x12345678 & 0x22222222));
-      expect(new int32.fromInt(0x12345678) & new int64.fromInt(0x22222222),
-          new int64.fromInt(0x12345678 & 0x22222222));
-      expect(() => new int32.fromInt(17) & null, throwsArgumentError);
+      expect(new Int32.fromInt(0x12345678) & new Int32.fromInt(0x22222222),
+          new Int32.fromInt(0x12345678 & 0x22222222));
+      expect(new Int32.fromInt(0x12345678) & new Int64.fromInt(0x22222222),
+          new Int64.fromInt(0x12345678 & 0x22222222));
+      expect(() => new Int32.fromInt(17) & null, throwsArgumentError);
     });
 
     test("|", () {
-      expect(new int32.fromInt(0x12345678) | new int32.fromInt(0x22222222),
-          new int32.fromInt(0x12345678 | 0x22222222));
-      expect(new int32.fromInt(0x12345678) | new int64.fromInt(0x22222222),
-          new int64.fromInt(0x12345678 | 0x22222222));
-      expect(() => new int32.fromInt(17) | null, throws);
+      expect(new Int32.fromInt(0x12345678) | new Int32.fromInt(0x22222222),
+          new Int32.fromInt(0x12345678 | 0x22222222));
+      expect(new Int32.fromInt(0x12345678) | new Int64.fromInt(0x22222222),
+          new Int64.fromInt(0x12345678 | 0x22222222));
+      expect(() => new Int32.fromInt(17) | null, throws);
     });
 
     test("^", () {
-      expect(new int32.fromInt(0x12345678) ^ new int32.fromInt(0x22222222),
-          new int32.fromInt(0x12345678 ^ 0x22222222));
-      expect(new int32.fromInt(0x12345678) ^ new int64.fromInt(0x22222222),
-          new int64.fromInt(0x12345678 ^ 0x22222222));
-      expect(() => new int32.fromInt(17) ^ null, throws);
+      expect(new Int32.fromInt(0x12345678) ^ new Int32.fromInt(0x22222222),
+          new Int32.fromInt(0x12345678 ^ 0x22222222));
+      expect(new Int32.fromInt(0x12345678) ^ new Int64.fromInt(0x22222222),
+          new Int64.fromInt(0x12345678 ^ 0x22222222));
+      expect(() => new Int32.fromInt(17) ^ null, throws);
     });
 
     test("~", () {
-      expect(~(new int32.fromInt(0x12345678)), new int32.fromInt(~0x12345678));
-      expect(-(new int32.fromInt(0x12345678)), new int64.fromInt(-0x12345678));
+      expect(~(new Int32.fromInt(0x12345678)), new Int32.fromInt(~0x12345678));
+      expect(-(new Int32.fromInt(0x12345678)), new Int64.fromInt(-0x12345678));
     });
   });
 
   group("bitshift operators", () {
     test("<<", () {
-      expect(new int32.fromInt(0x12345678) << 7,
-          new int32.fromInt(0x12345678 << 7));
-      expect(() => new int32.fromInt(17) << -1, throwsArgumentError);
-      expect(() => new int32.fromInt(17) << null, throws);
+      expect(new Int32.fromInt(0x12345678) << 7,
+          new Int32.fromInt(0x12345678 << 7));
+      expect(() => new Int32.fromInt(17) << -1, throwsArgumentError);
+      expect(() => new Int32.fromInt(17) << null, throws);
     });
 
     test(">>", () {
-      expect(new int32.fromInt(0x12345678) >> 7,
-          new int32.fromInt(0x12345678 >> 7));
-      expect(() => new int32.fromInt(17) >> -1, throwsArgumentError);
-      expect(() => new int32.fromInt(17) >> null, throws);
+      expect(new Int32.fromInt(0x12345678) >> 7,
+          new Int32.fromInt(0x12345678 >> 7));
+      expect(() => new Int32.fromInt(17) >> -1, throwsArgumentError);
+      expect(() => new Int32.fromInt(17) >> null, throws);
     });
 
     test("shiftRightUnsigned", () {
-      expect(new int32.fromInt(0x12345678).shiftRightUnsigned(7),
-          new int32.fromInt(0x12345678 >> 7));
-      expect(() => (new int32.fromInt(17).shiftRightUnsigned(-1)),
+      expect(new Int32.fromInt(0x12345678).shiftRightUnsigned(7),
+          new Int32.fromInt(0x12345678 >> 7));
+      expect(() => (new Int32.fromInt(17).shiftRightUnsigned(-1)),
           throwsArgumentError);
-      expect(() => (new int32.fromInt(17).shiftRightUnsigned(null)), throws);
+      expect(() => (new Int32.fromInt(17).shiftRightUnsigned(null)), throws);
     });
   });
 
   group("type conversions", () {
-    expect(new int32.fromInt(17).toInt(), 17);
-    expect(new int32.fromInt(-17).toInt(), -17);
-    expect(new int32.fromInt(17).toInt32(), new int32.fromInt(17));
-    expect(new int32.fromInt(-17).toInt32(), new int32.fromInt(-17));
-    expect(new int32.fromInt(17).toInt64(), new int64.fromInt(17));
-    expect(new int32.fromInt(-17).toInt64(), new int64.fromInt(-17));
+    expect(new Int32.fromInt(17).toInt(), 17);
+    expect(new Int32.fromInt(-17).toInt(), -17);
+    expect(new Int32.fromInt(17).toInt32(), new Int32.fromInt(17));
+    expect(new Int32.fromInt(-17).toInt32(), new Int32.fromInt(-17));
+    expect(new Int32.fromInt(17).toInt64(), new Int64.fromInt(17));
+    expect(new Int32.fromInt(-17).toInt64(), new Int64.fromInt(-17));
   });
 
   group("string representation", () {
     test("toString", () {
-      expect(new int32.fromInt(0).toString(), "0");
-      expect(new int32.fromInt(1).toString(), "1");
-      expect(new int32.fromInt(-1).toString(), "-1");
-      expect(new int32.fromInt(1000).toString(), "1000");
-      expect(new int32.fromInt(-1000).toString(), "-1000");
-      expect(new int32.fromInt(123456789).toString(), "123456789");
-      expect(new int32.fromInt(2147483647).toString(), "2147483647");
-      expect(new int32.fromInt(2147483648).toString(), "-2147483648");
-      expect(new int32.fromInt(2147483649).toString(), "-2147483647");
-      expect(new int32.fromInt(2147483650).toString(), "-2147483646");
-      expect(new int32.fromInt(-2147483648).toString(), "-2147483648");
-      expect(new int32.fromInt(-2147483649).toString(), "2147483647");
-      expect(new int32.fromInt(-2147483650).toString(), "2147483646");
+      expect(new Int32.fromInt(0).toString(), "0");
+      expect(new Int32.fromInt(1).toString(), "1");
+      expect(new Int32.fromInt(-1).toString(), "-1");
+      expect(new Int32.fromInt(1000).toString(), "1000");
+      expect(new Int32.fromInt(-1000).toString(), "-1000");
+      expect(new Int32.fromInt(123456789).toString(), "123456789");
+      expect(new Int32.fromInt(2147483647).toString(), "2147483647");
+      expect(new Int32.fromInt(2147483648).toString(), "-2147483648");
+      expect(new Int32.fromInt(2147483649).toString(), "-2147483647");
+      expect(new Int32.fromInt(2147483650).toString(), "-2147483646");
+      expect(new Int32.fromInt(-2147483648).toString(), "-2147483648");
+      expect(new Int32.fromInt(-2147483649).toString(), "2147483647");
+      expect(new Int32.fromInt(-2147483650).toString(), "2147483646");
     });
   });
 
   group("toHexString", () {
     test("returns hexadecimal string representation", () {
-      expect(new int32.fromInt(-1).toHexString(), "-1");
-      expect((new int32.fromInt(-1) >> 8).toHexString(), "-1");
-      expect((new int32.fromInt(-1) << 8).toHexString(), "-100");
-      expect(new int32.fromInt(123456789).toHexString(), "75bcd15");
-      expect(new int32.fromInt(-1).shiftRightUnsigned(8).toHexString(),
+      expect(new Int32.fromInt(-1).toHexString(), "-1");
+      expect((new Int32.fromInt(-1) >> 8).toHexString(), "-1");
+      expect((new Int32.fromInt(-1) << 8).toHexString(), "-100");
+      expect(new Int32.fromInt(123456789).toHexString(), "75bcd15");
+      expect(new Int32.fromInt(-1).shiftRightUnsigned(8).toHexString(),
           "ffffff");
     });
   });
 
   group("toRadixString", () {
     test("returns base n string representation", () {
-      expect(new int32.fromInt(123456789).toRadixString(5), "223101104124");
+      expect(new Int32.fromInt(123456789).toRadixString(5), "223101104124");
     });
   });
 }
diff --git a/pkg/fixnum/test/int_64_test.dart b/pkg/fixnum/test/int_64_test.dart
index 4ff8e1c..545de3c 100644
--- a/pkg/fixnum/test/int_64_test.dart
+++ b/pkg/fixnum/test/int_64_test.dart
@@ -8,592 +8,592 @@
 
 void main() {
   group("arithmetic operators", () {
-    int64 n1 = new int64.fromInt(1234);
-    int64 n2 = new int64.fromInt(9876);
-    int64 n3 = new int64.fromInt(-1234);
-    int64 n4 = new int64.fromInt(-9876);
-    int64 n5 = new int64.fromInts(0x12345678, 0xabcdabcd);
-    int64 n6 = new int64.fromInts(0x77773333, 0x22224444);
+    Int64 n1 = new Int64.fromInt(1234);
+    Int64 n2 = new Int64.fromInt(9876);
+    Int64 n3 = new Int64.fromInt(-1234);
+    Int64 n4 = new Int64.fromInt(-9876);
+    Int64 n5 = new Int64.fromInts(0x12345678, 0xabcdabcd);
+    Int64 n6 = new Int64.fromInts(0x77773333, 0x22224444);
 
     test("+", () {
-      expect(n1 + n2, new int64.fromInt(11110));
-      expect(n3 + n2, new int64.fromInt(8642));
-      expect(n3 + n4, new int64.fromInt(-11110));
-      expect(n5 + n6, new int64.fromInts(0x89ab89ab, 0xcdeff011));
-      expect(int64.MAX_VALUE + 1, int64.MIN_VALUE);
+      expect(n1 + n2, new Int64.fromInt(11110));
+      expect(n3 + n2, new Int64.fromInt(8642));
+      expect(n3 + n4, new Int64.fromInt(-11110));
+      expect(n5 + n6, new Int64.fromInts(0x89ab89ab, 0xcdeff011));
+      expect(Int64.MAX_VALUE + 1, Int64.MIN_VALUE);
     });
 
     test("-", () {
-      expect(n1 - n2, new int64.fromInt(-8642));
-      expect(n3 - n2, new int64.fromInt(-11110));
-      expect(n3 - n4, new int64.fromInt(8642));
-      expect(n5 - n6, new int64.fromInts(0x9abd2345, 0x89ab6789));
-      expect(int64.MIN_VALUE - 1, int64.MAX_VALUE);
+      expect(n1 - n2, new Int64.fromInt(-8642));
+      expect(n3 - n2, new Int64.fromInt(-11110));
+      expect(n3 - n4, new Int64.fromInt(8642));
+      expect(n5 - n6, new Int64.fromInts(0x9abd2345, 0x89ab6789));
+      expect(Int64.MIN_VALUE - 1, Int64.MAX_VALUE);
     });
 
     test("unary -", () {
-      expect(-n1, new int64.fromInt(-1234));
-      expect(-int64.ZERO, int64.ZERO);
+      expect(-n1, new Int64.fromInt(-1234));
+      expect(-Int64.ZERO, Int64.ZERO);
     });
 
     test("*", () {
-      expect(new int64.fromInt(1111) * new int64.fromInt(3),
-          new int64.fromInt(3333));
-      expect(new int64.fromInt(1111) * new int64.fromInt(-3),
-          new int64.fromInt(-3333));
-      expect(new int64.fromInt(-1111) * new int64.fromInt(3),
-          new int64.fromInt(-3333));
-      expect(new int64.fromInt(-1111) * new int64.fromInt(-3),
-          new int64.fromInt(3333));
-      expect(new int64.fromInt(100) * new int64.fromInt(0),
-          new int64.fromInt(0));
+      expect(new Int64.fromInt(1111) * new Int64.fromInt(3),
+          new Int64.fromInt(3333));
+      expect(new Int64.fromInt(1111) * new Int64.fromInt(-3),
+          new Int64.fromInt(-3333));
+      expect(new Int64.fromInt(-1111) * new Int64.fromInt(3),
+          new Int64.fromInt(-3333));
+      expect(new Int64.fromInt(-1111) * new Int64.fromInt(-3),
+          new Int64.fromInt(3333));
+      expect(new Int64.fromInt(100) * new Int64.fromInt(0),
+          new Int64.fromInt(0));
 
-      expect(new int64.fromInts(0x12345678, 0x12345678) *
-          new int64.fromInts(0x1234, 0x12345678),
-          new int64.fromInts(0x7ff63f7c, 0x1df4d840));
-      expect(new int64.fromInts(0xf2345678, 0x12345678) *
-          new int64.fromInts(0x1234, 0x12345678),
-          new int64.fromInts(0x7ff63f7c, 0x1df4d840));
-      expect(new int64.fromInts(0xf2345678, 0x12345678) *
-          new int64.fromInts(0xffff1234, 0x12345678),
-          new int64.fromInts(0x297e3f7c, 0x1df4d840));
+      expect(new Int64.fromInts(0x12345678, 0x12345678) *
+          new Int64.fromInts(0x1234, 0x12345678),
+          new Int64.fromInts(0x7ff63f7c, 0x1df4d840));
+      expect(new Int64.fromInts(0xf2345678, 0x12345678) *
+          new Int64.fromInts(0x1234, 0x12345678),
+          new Int64.fromInts(0x7ff63f7c, 0x1df4d840));
+      expect(new Int64.fromInts(0xf2345678, 0x12345678) *
+          new Int64.fromInts(0xffff1234, 0x12345678),
+          new Int64.fromInts(0x297e3f7c, 0x1df4d840));
 
-      // RHS int32
-      expect((new int64.fromInt(123456789) * new int32.fromInt(987654321)),
-          new int64.fromInts(0x1b13114, 0xfbff5385));
-      expect((new int64.fromInt(123456789) * new int32.fromInt(987654321)),
-          new int64.fromInts(0x1b13114, 0xfbff5385));
+      // RHS Int32
+      expect((new Int64.fromInt(123456789) * new Int32.fromInt(987654321)),
+          new Int64.fromInts(0x1b13114, 0xfbff5385));
+      expect((new Int64.fromInt(123456789) * new Int32.fromInt(987654321)),
+          new Int64.fromInts(0x1b13114, 0xfbff5385));
 
       // Wraparound
-      expect((new int64.fromInt(123456789) * new int64.fromInt(987654321)),
-          new int64.fromInts(0x1b13114, 0xfbff5385));
+      expect((new Int64.fromInt(123456789) * new Int64.fromInt(987654321)),
+          new Int64.fromInts(0x1b13114, 0xfbff5385));
 
-      expect(int64.MIN_VALUE * new int64.fromInt(2), new int64.fromInt(0));
-      expect(int64.MIN_VALUE * new int64.fromInt(1), int64.MIN_VALUE);
-      expect(int64.MIN_VALUE * new int64.fromInt(-1), int64.MIN_VALUE);
+      expect(Int64.MIN_VALUE * new Int64.fromInt(2), new Int64.fromInt(0));
+      expect(Int64.MIN_VALUE * new Int64.fromInt(1), Int64.MIN_VALUE);
+      expect(Int64.MIN_VALUE * new Int64.fromInt(-1), Int64.MIN_VALUE);
     });
 
     test("~/", () {
-      int64 deadBeef = new int64.fromInts(0xDEADBEEF, 0xDEADBEEF);
-      int64 ten = new int64.fromInt(10);
+      Int64 deadBeef = new Int64.fromInts(0xDEADBEEF, 0xDEADBEEF);
+      Int64 ten = new Int64.fromInt(10);
 
-      expect(deadBeef ~/ ten, new int64.fromInts(0xfcaaf97e, 0x63115fe5));
-      expect(int64.ONE ~/ int64.TWO, int64.ZERO);
-      expect(int64.MAX_VALUE ~/ int64.TWO,
-          new int64.fromInts(0x3fffffff, 0xffffffff));
-      expect(int64.ZERO ~/ new int64.fromInt(1000), int64.ZERO);
-      expect(int64.MIN_VALUE ~/ int64.MIN_VALUE, int64.ONE);
-      expect(new int64.fromInt(1000) ~/ int64.MIN_VALUE, int64.ZERO);
-      expect(int64.MIN_VALUE ~/ new int64.fromInt(8192),
-          new int64.fromInt(-1125899906842624));
-      expect(int64.MIN_VALUE ~/ new int64.fromInt(8193),
-          new int64.fromInt(-1125762484664320));
-      expect(new int64.fromInt(-1000) ~/ new int64.fromInt(8192), int64.ZERO);
-      expect(new int64.fromInt(-1000) ~/ new int64.fromInt(8193), int64.ZERO);
-      expect(new int64.fromInt(-1000000000) ~/ new int64.fromInt(8192),
-          new int64.fromInt(-122070));
-      expect(new int64.fromInt(-1000000000) ~/ new int64.fromInt(8193),
-          new int64.fromInt(-122055));
-      expect(new int64.fromInt(1000000000) ~/ new int64.fromInt(8192),
-          new int64.fromInt(122070));
-      expect(new int64.fromInt(1000000000) ~/ new int64.fromInt(8193),
-          new int64.fromInt(122055));
-      expect(int64.MAX_VALUE ~/ new int64.fromInts(0x00000000, 0x00000400),
-          new int64.fromInts(0x1fffff, 0xffffffff));
-      expect(int64.MAX_VALUE ~/ new int64.fromInts(0x00000000, 0x00040000),
-          new int64.fromInts(0x1fff, 0xffffffff));
-      expect(int64.MAX_VALUE ~/ new int64.fromInts(0x00000000, 0x04000000),
-          new int64.fromInts(0x1f, 0xffffffff));
-      expect(int64.MAX_VALUE ~/ new int64.fromInts(0x00000004, 0x00000000),
-          new int64.fromInt(536870911));
-      expect(int64.MAX_VALUE ~/ new int64.fromInts(0x00000400, 0x00000000),
-          new int64.fromInt(2097151));
-      expect(int64.MAX_VALUE ~/ new int64.fromInts(0x00040000, 0x00000000),
-          new int64.fromInt(8191));
-      expect(int64.MAX_VALUE ~/ new int64.fromInts(0x04000000, 0x00000000),
-          new int64.fromInt(31));
-      expect(int64.MAX_VALUE ~/ new int64.fromInts(0x00000000, 0x00000300),
-          new int64.fromInts(0x2AAAAA, 0xAAAAAAAA));
-      expect(int64.MAX_VALUE ~/ new int64.fromInts(0x00000000, 0x30000000),
-          new int64.fromInts(0x2, 0xAAAAAAAA));
-      expect(int64.MAX_VALUE ~/ new int64.fromInts(0x00300000, 0x00000000),
-          new int64.fromInt(0x2AA));
-      expect(int64.MAX_VALUE ~/ new int64.fromInt(0x123456),
-          new int64.fromInts(0x708, 0x002E9501));
-      expect(int64.MAX_VALUE % new int64.fromInt(0x123456),
-          new int64.fromInt(0x3BDA9));
-      expect(new int64.fromInt(5) ~/ new int64.fromInt(5),
-          new int64.fromInt(1));
-      expect(new int64.fromInt(1000) ~/ new int64.fromInt(3),
-          new int64.fromInt(333));
-      expect(new int64.fromInt(1000) ~/ new int64.fromInt(-3),
-          new int64.fromInt(-333));
-      expect(new int64.fromInt(-1000) ~/ new int64.fromInt(3),
-          new int64.fromInt(-333));
-      expect(new int64.fromInt(-1000) ~/ new int64.fromInt(-3),
-          new int64.fromInt(333));
-      expect(new int64.fromInt(3) ~/ new int64.fromInt(1000),
-          new int64.fromInt(0));
-      expect(new int64.fromInts( 0x12345678, 0x12345678) ~/
-          new int64.fromInts(0x0, 0x123),
-          new int64.fromInts(0x1003d0, 0xe84f5ae8));
-      expect(new int64.fromInts(0x12345678, 0x12345678) ~/
-          new int64.fromInts(0x1234, 0x12345678),
-          new int64.fromInts(0x0, 0x10003));
-      expect(new int64.fromInts(0xf2345678, 0x12345678) ~/
-          new int64.fromInts(0x1234, 0x12345678),
-          new int64.fromInts(0xffffffff, 0xffff3dfe));
-      expect(new int64.fromInts(0xf2345678, 0x12345678) ~/
-          new int64.fromInts(0xffff1234, 0x12345678),
-          new int64.fromInts(0x0, 0xeda));
-      expect(new int64.fromInt(829893893) ~/ new int32.fromInt(1919),
-          new int32.fromInt(432461));
-      expect(new int64.fromInt(829893893) ~/ new int64.fromInt(1919),
-          new int32.fromInt(432461));
-      expect(new int64.fromInt(829893893) ~/ 1919,
-          new int32.fromInt(432461));
-      expect(() => new int64.fromInt(1) ~/ new int64.fromInt(0),
+      expect(deadBeef ~/ ten, new Int64.fromInts(0xfcaaf97e, 0x63115fe5));
+      expect(Int64.ONE ~/ Int64.TWO, Int64.ZERO);
+      expect(Int64.MAX_VALUE ~/ Int64.TWO,
+          new Int64.fromInts(0x3fffffff, 0xffffffff));
+      expect(Int64.ZERO ~/ new Int64.fromInt(1000), Int64.ZERO);
+      expect(Int64.MIN_VALUE ~/ Int64.MIN_VALUE, Int64.ONE);
+      expect(new Int64.fromInt(1000) ~/ Int64.MIN_VALUE, Int64.ZERO);
+      expect(Int64.MIN_VALUE ~/ new Int64.fromInt(8192),
+          new Int64.fromInt(-1125899906842624));
+      expect(Int64.MIN_VALUE ~/ new Int64.fromInt(8193),
+          new Int64.fromInt(-1125762484664320));
+      expect(new Int64.fromInt(-1000) ~/ new Int64.fromInt(8192), Int64.ZERO);
+      expect(new Int64.fromInt(-1000) ~/ new Int64.fromInt(8193), Int64.ZERO);
+      expect(new Int64.fromInt(-1000000000) ~/ new Int64.fromInt(8192),
+          new Int64.fromInt(-122070));
+      expect(new Int64.fromInt(-1000000000) ~/ new Int64.fromInt(8193),
+          new Int64.fromInt(-122055));
+      expect(new Int64.fromInt(1000000000) ~/ new Int64.fromInt(8192),
+          new Int64.fromInt(122070));
+      expect(new Int64.fromInt(1000000000) ~/ new Int64.fromInt(8193),
+          new Int64.fromInt(122055));
+      expect(Int64.MAX_VALUE ~/ new Int64.fromInts(0x00000000, 0x00000400),
+          new Int64.fromInts(0x1fffff, 0xffffffff));
+      expect(Int64.MAX_VALUE ~/ new Int64.fromInts(0x00000000, 0x00040000),
+          new Int64.fromInts(0x1fff, 0xffffffff));
+      expect(Int64.MAX_VALUE ~/ new Int64.fromInts(0x00000000, 0x04000000),
+          new Int64.fromInts(0x1f, 0xffffffff));
+      expect(Int64.MAX_VALUE ~/ new Int64.fromInts(0x00000004, 0x00000000),
+          new Int64.fromInt(536870911));
+      expect(Int64.MAX_VALUE ~/ new Int64.fromInts(0x00000400, 0x00000000),
+          new Int64.fromInt(2097151));
+      expect(Int64.MAX_VALUE ~/ new Int64.fromInts(0x00040000, 0x00000000),
+          new Int64.fromInt(8191));
+      expect(Int64.MAX_VALUE ~/ new Int64.fromInts(0x04000000, 0x00000000),
+          new Int64.fromInt(31));
+      expect(Int64.MAX_VALUE ~/ new Int64.fromInts(0x00000000, 0x00000300),
+          new Int64.fromInts(0x2AAAAA, 0xAAAAAAAA));
+      expect(Int64.MAX_VALUE ~/ new Int64.fromInts(0x00000000, 0x30000000),
+          new Int64.fromInts(0x2, 0xAAAAAAAA));
+      expect(Int64.MAX_VALUE ~/ new Int64.fromInts(0x00300000, 0x00000000),
+          new Int64.fromInt(0x2AA));
+      expect(Int64.MAX_VALUE ~/ new Int64.fromInt(0x123456),
+          new Int64.fromInts(0x708, 0x002E9501));
+      expect(Int64.MAX_VALUE % new Int64.fromInt(0x123456),
+          new Int64.fromInt(0x3BDA9));
+      expect(new Int64.fromInt(5) ~/ new Int64.fromInt(5),
+          new Int64.fromInt(1));
+      expect(new Int64.fromInt(1000) ~/ new Int64.fromInt(3),
+          new Int64.fromInt(333));
+      expect(new Int64.fromInt(1000) ~/ new Int64.fromInt(-3),
+          new Int64.fromInt(-333));
+      expect(new Int64.fromInt(-1000) ~/ new Int64.fromInt(3),
+          new Int64.fromInt(-333));
+      expect(new Int64.fromInt(-1000) ~/ new Int64.fromInt(-3),
+          new Int64.fromInt(333));
+      expect(new Int64.fromInt(3) ~/ new Int64.fromInt(1000),
+          new Int64.fromInt(0));
+      expect(new Int64.fromInts( 0x12345678, 0x12345678) ~/
+          new Int64.fromInts(0x0, 0x123),
+          new Int64.fromInts(0x1003d0, 0xe84f5ae8));
+      expect(new Int64.fromInts(0x12345678, 0x12345678) ~/
+          new Int64.fromInts(0x1234, 0x12345678),
+          new Int64.fromInts(0x0, 0x10003));
+      expect(new Int64.fromInts(0xf2345678, 0x12345678) ~/
+          new Int64.fromInts(0x1234, 0x12345678),
+          new Int64.fromInts(0xffffffff, 0xffff3dfe));
+      expect(new Int64.fromInts(0xf2345678, 0x12345678) ~/
+          new Int64.fromInts(0xffff1234, 0x12345678),
+          new Int64.fromInts(0x0, 0xeda));
+      expect(new Int64.fromInt(829893893) ~/ new Int32.fromInt(1919),
+          new Int32.fromInt(432461));
+      expect(new Int64.fromInt(829893893) ~/ new Int64.fromInt(1919),
+          new Int32.fromInt(432461));
+      expect(new Int64.fromInt(829893893) ~/ 1919,
+          new Int32.fromInt(432461));
+      expect(() => new Int64.fromInt(1) ~/ new Int64.fromInt(0),
           throwsA(new isInstanceOf<IntegerDivisionByZeroException>()));
-      expect(int64.MIN_VALUE ~/ new int64.fromInt(2),
-          new int64.fromInts(0xc0000000, 0x00000000));
-      expect(int64.MIN_VALUE ~/ new int64.fromInt(1), int64.MIN_VALUE);
-      expect(int64.MIN_VALUE ~/ new int64.fromInt(-1), int64.MIN_VALUE);
-      expect(() => new int64.fromInt(17) ~/ int64.ZERO, throws);
-      expect(() => new int64.fromInt(17) ~/ null, throwsArgumentError);
+      expect(Int64.MIN_VALUE ~/ new Int64.fromInt(2),
+          new Int64.fromInts(0xc0000000, 0x00000000));
+      expect(Int64.MIN_VALUE ~/ new Int64.fromInt(1), Int64.MIN_VALUE);
+      expect(Int64.MIN_VALUE ~/ new Int64.fromInt(-1), Int64.MIN_VALUE);
+      expect(() => new Int64.fromInt(17) ~/ Int64.ZERO, throws);
+      expect(() => new Int64.fromInt(17) ~/ null, throwsArgumentError);
     });
 
     test("%", () {
       // Define % as Euclidean mod, with positive result for all arguments
-      expect(int64.ZERO % new int64.fromInt(1000), new int64.fromInt(0));
-      expect(int64.MIN_VALUE % int64.MIN_VALUE, new int64.fromInt(0));
-      expect(new int64.fromInt(1000) % int64.MIN_VALUE,
-          new int64.fromInt(1000));
-      expect(int64.MIN_VALUE % new int64.fromInt(8192), new int64.fromInt(0));
-      expect(int64.MIN_VALUE % new int64.fromInt(8193),
-          new int64.fromInt(6145));
-      expect(new int64.fromInt(-1000) % new int64.fromInt(8192),
-          new int64.fromInt(7192));
-      expect(new int64.fromInt(-1000) % new int64.fromInt(8193),
-          new int64.fromInt(7193));
-      expect(new int64.fromInt(-1000000000) % new int64.fromInt(8192),
-          new int64.fromInt(5632));
-      expect(new int64.fromInt(-1000000000) % new int64.fromInt(8193),
-          new int64.fromInt(4808));
-      expect(new int64.fromInt(1000000000) % new int64.fromInt(8192),
-          new int64.fromInt(2560));
-      expect(new int64.fromInt(1000000000) % new int64.fromInt(8193),
-          new int64.fromInt(3385));
-      expect(int64.MAX_VALUE % new int64.fromInts(0x00000000, 0x00000400),
-          new int64.fromInts(0x0, 0x3ff));
-      expect(int64.MAX_VALUE % new int64.fromInts(0x00000000, 0x00040000),
-          new int64.fromInts(0x0, 0x3ffff));
-      expect(int64.MAX_VALUE % new int64.fromInts(0x00000000, 0x04000000),
-          new int64.fromInts(0x0, 0x3ffffff));
-      expect(int64.MAX_VALUE % new int64.fromInts(0x00000004, 0x00000000),
-          new int64.fromInts(0x3, 0xffffffff));
-      expect(int64.MAX_VALUE % new int64.fromInts(0x00000400, 0x00000000),
-          new int64.fromInts(0x3ff, 0xffffffff));
-      expect(int64.MAX_VALUE % new int64.fromInts(0x00040000, 0x00000000),
-          new int64.fromInts(0x3ffff, 0xffffffff));
-      expect(int64.MAX_VALUE % new int64.fromInts(0x04000000, 0x00000000),
-          new int64.fromInts(0x3ffffff, 0xffffffff));
-      expect(new int64.fromInt(0x12345678).remainder(new int64.fromInt(0x22)),
-          new int64.fromInt(0x12345678.remainder(0x22)));
-      expect(new int64.fromInt(0x12345678).remainder(new int64.fromInt(-0x22)),
-          new int64.fromInt(0x12345678.remainder(-0x22)));
-      expect(new int64.fromInt(-0x12345678).remainder(new int64.fromInt(-0x22)),
-          new int64.fromInt(-0x12345678.remainder(-0x22)));
-      expect(new int64.fromInt(-0x12345678).remainder(new int64.fromInt(0x22)),
-          new int64.fromInt(-0x12345678.remainder(0x22)));
-      expect(new int32.fromInt(0x12345678).remainder(new int64.fromInt(0x22)),
-          new int64.fromInt(0x12345678.remainder(0x22)));
+      expect(Int64.ZERO % new Int64.fromInt(1000), new Int64.fromInt(0));
+      expect(Int64.MIN_VALUE % Int64.MIN_VALUE, new Int64.fromInt(0));
+      expect(new Int64.fromInt(1000) % Int64.MIN_VALUE,
+          new Int64.fromInt(1000));
+      expect(Int64.MIN_VALUE % new Int64.fromInt(8192), new Int64.fromInt(0));
+      expect(Int64.MIN_VALUE % new Int64.fromInt(8193),
+          new Int64.fromInt(6145));
+      expect(new Int64.fromInt(-1000) % new Int64.fromInt(8192),
+          new Int64.fromInt(7192));
+      expect(new Int64.fromInt(-1000) % new Int64.fromInt(8193),
+          new Int64.fromInt(7193));
+      expect(new Int64.fromInt(-1000000000) % new Int64.fromInt(8192),
+          new Int64.fromInt(5632));
+      expect(new Int64.fromInt(-1000000000) % new Int64.fromInt(8193),
+          new Int64.fromInt(4808));
+      expect(new Int64.fromInt(1000000000) % new Int64.fromInt(8192),
+          new Int64.fromInt(2560));
+      expect(new Int64.fromInt(1000000000) % new Int64.fromInt(8193),
+          new Int64.fromInt(3385));
+      expect(Int64.MAX_VALUE % new Int64.fromInts(0x00000000, 0x00000400),
+          new Int64.fromInts(0x0, 0x3ff));
+      expect(Int64.MAX_VALUE % new Int64.fromInts(0x00000000, 0x00040000),
+          new Int64.fromInts(0x0, 0x3ffff));
+      expect(Int64.MAX_VALUE % new Int64.fromInts(0x00000000, 0x04000000),
+          new Int64.fromInts(0x0, 0x3ffffff));
+      expect(Int64.MAX_VALUE % new Int64.fromInts(0x00000004, 0x00000000),
+          new Int64.fromInts(0x3, 0xffffffff));
+      expect(Int64.MAX_VALUE % new Int64.fromInts(0x00000400, 0x00000000),
+          new Int64.fromInts(0x3ff, 0xffffffff));
+      expect(Int64.MAX_VALUE % new Int64.fromInts(0x00040000, 0x00000000),
+          new Int64.fromInts(0x3ffff, 0xffffffff));
+      expect(Int64.MAX_VALUE % new Int64.fromInts(0x04000000, 0x00000000),
+          new Int64.fromInts(0x3ffffff, 0xffffffff));
+      expect(new Int64.fromInt(0x12345678).remainder(new Int64.fromInt(0x22)),
+          new Int64.fromInt(0x12345678.remainder(0x22)));
+      expect(new Int64.fromInt(0x12345678).remainder(new Int64.fromInt(-0x22)),
+          new Int64.fromInt(0x12345678.remainder(-0x22)));
+      expect(new Int64.fromInt(-0x12345678).remainder(new Int64.fromInt(-0x22)),
+          new Int64.fromInt(-0x12345678.remainder(-0x22)));
+      expect(new Int64.fromInt(-0x12345678).remainder(new Int64.fromInt(0x22)),
+          new Int64.fromInt(-0x12345678.remainder(0x22)));
+      expect(new Int32.fromInt(0x12345678).remainder(new Int64.fromInt(0x22)),
+          new Int64.fromInt(0x12345678.remainder(0x22)));
     });
   });
 
   group("comparison operators", () {
-    int64 largeNeg = new int64.fromInts(0x82341234, 0x0);
-    int64 largePos = new int64.fromInts(0x12341234, 0x0);
-    int64 largePosPlusOne = largePos + new int64.fromInt(1);
+    Int64 largeNeg = new Int64.fromInts(0x82341234, 0x0);
+    Int64 largePos = new Int64.fromInts(0x12341234, 0x0);
+    Int64 largePosPlusOne = largePos + new Int64.fromInt(1);
 
     test("<", () {
-      expect(new int64.fromInt(10) < new int64.fromInt(11), true);
-      expect(new int64.fromInt(10) < new int64.fromInt(10), false);
-      expect(new int64.fromInt(10) < new int64.fromInt(9), false);
-      expect(new int64.fromInt(10) < new int32.fromInt(11), true);
-      expect(new int64.fromInt(10) < new int32.fromInt(10), false);
-      expect(new int64.fromInt(10) < new int32.fromInt(9), false);
-      expect(new int64.fromInt(-10) < new int64.fromInt(-11), false);
-      expect(int64.MIN_VALUE < new int64.fromInt(0), true);
+      expect(new Int64.fromInt(10) < new Int64.fromInt(11), true);
+      expect(new Int64.fromInt(10) < new Int64.fromInt(10), false);
+      expect(new Int64.fromInt(10) < new Int64.fromInt(9), false);
+      expect(new Int64.fromInt(10) < new Int32.fromInt(11), true);
+      expect(new Int64.fromInt(10) < new Int32.fromInt(10), false);
+      expect(new Int64.fromInt(10) < new Int32.fromInt(9), false);
+      expect(new Int64.fromInt(-10) < new Int64.fromInt(-11), false);
+      expect(Int64.MIN_VALUE < new Int64.fromInt(0), true);
       expect(largeNeg < largePos, true);
       expect(largePos < largePosPlusOne, true);
       expect(largePos < largePos, false);
       expect(largePosPlusOne < largePos, false);
-      expect(int64.MIN_VALUE < int64.MAX_VALUE, true);
-      expect(int64.MAX_VALUE < int64.MIN_VALUE, false);
-      expect(() => new int64.fromInt(17) < null, throwsArgumentError);
+      expect(Int64.MIN_VALUE < Int64.MAX_VALUE, true);
+      expect(Int64.MAX_VALUE < Int64.MIN_VALUE, false);
+      expect(() => new Int64.fromInt(17) < null, throwsArgumentError);
     });
 
     test("<=", () {
-      expect(new int64.fromInt(10) <= new int64.fromInt(11), true);
-      expect(new int64.fromInt(10) <= new int64.fromInt(10), true);
-      expect(new int64.fromInt(10) <= new int64.fromInt(9), false);
-      expect(new int64.fromInt(10) <= new int32.fromInt(11), true);
-      expect(new int64.fromInt(10) <= new int32.fromInt(10), true);
-      expect(new int64.fromInt(10) <= new int64.fromInt(9), false);
-      expect(new int64.fromInt(-10) <= new int64.fromInt(-11), false);
-      expect(new int64.fromInt(-10) <= new int64.fromInt(-10), true);
+      expect(new Int64.fromInt(10) <= new Int64.fromInt(11), true);
+      expect(new Int64.fromInt(10) <= new Int64.fromInt(10), true);
+      expect(new Int64.fromInt(10) <= new Int64.fromInt(9), false);
+      expect(new Int64.fromInt(10) <= new Int32.fromInt(11), true);
+      expect(new Int64.fromInt(10) <= new Int32.fromInt(10), true);
+      expect(new Int64.fromInt(10) <= new Int64.fromInt(9), false);
+      expect(new Int64.fromInt(-10) <= new Int64.fromInt(-11), false);
+      expect(new Int64.fromInt(-10) <= new Int64.fromInt(-10), true);
       expect(largeNeg <= largePos, true);
       expect(largePos <= largeNeg, false);
       expect(largePos <= largePosPlusOne, true);
       expect(largePos <= largePos, true);
       expect(largePosPlusOne <= largePos, false);
-      expect(int64.MIN_VALUE <= int64.MAX_VALUE, true);
-      expect(int64.MAX_VALUE <= int64.MIN_VALUE, false);
-      expect(() => new int64.fromInt(17) <= null, throwsArgumentError);
+      expect(Int64.MIN_VALUE <= Int64.MAX_VALUE, true);
+      expect(Int64.MAX_VALUE <= Int64.MIN_VALUE, false);
+      expect(() => new Int64.fromInt(17) <= null, throwsArgumentError);
     });
 
     test("==", () {
-      expect(new int64.fromInt(10) == new int64.fromInt(11), false);
-      expect(new int64.fromInt(10) == new int64.fromInt(10), true);
-      expect(new int64.fromInt(10) == new int64.fromInt(9), false);
-      expect(new int64.fromInt(10) == new int32.fromInt(11), false);
-      expect(new int64.fromInt(10) == new int32.fromInt(10), true);
-      expect(new int64.fromInt(10) == new int32.fromInt(9), false);
-      expect(new int64.fromInt(-10) == new int64.fromInt(-10), true);
-      expect(new int64.fromInt(-10) != new int64.fromInt(-10), false);
+      expect(new Int64.fromInt(10) == new Int64.fromInt(11), false);
+      expect(new Int64.fromInt(10) == new Int64.fromInt(10), true);
+      expect(new Int64.fromInt(10) == new Int64.fromInt(9), false);
+      expect(new Int64.fromInt(10) == new Int32.fromInt(11), false);
+      expect(new Int64.fromInt(10) == new Int32.fromInt(10), true);
+      expect(new Int64.fromInt(10) == new Int32.fromInt(9), false);
+      expect(new Int64.fromInt(-10) == new Int64.fromInt(-10), true);
+      expect(new Int64.fromInt(-10) != new Int64.fromInt(-10), false);
       expect(largePos == largePos, true);
       expect(largePos == largePosPlusOne, false);
       expect(largePosPlusOne == largePos, false);
-      expect(int64.MIN_VALUE == int64.MAX_VALUE, false);
-      expect(new int64.fromInt(17) == new Object(), false);
-      expect(new int64.fromInt(17) == null, false);
+      expect(Int64.MIN_VALUE == Int64.MAX_VALUE, false);
+      expect(new Int64.fromInt(17) == new Object(), false);
+      expect(new Int64.fromInt(17) == null, false);
     });
 
     test(">=", () {
-      expect(new int64.fromInt(10) >= new int64.fromInt(11), false);
-      expect(new int64.fromInt(10) >= new int64.fromInt(10), true);
-      expect(new int64.fromInt(10) >= new int64.fromInt(9), true);
-      expect(new int64.fromInt(10) >= new int32.fromInt(11), false);
-      expect(new int64.fromInt(10) >= new int32.fromInt(10), true);
-      expect(new int64.fromInt(10) >= new int32.fromInt(9), true);
-      expect(new int64.fromInt(-10) >= new int64.fromInt(-11), true);
-      expect(new int64.fromInt(-10) >= new int64.fromInt(-10), true);
+      expect(new Int64.fromInt(10) >= new Int64.fromInt(11), false);
+      expect(new Int64.fromInt(10) >= new Int64.fromInt(10), true);
+      expect(new Int64.fromInt(10) >= new Int64.fromInt(9), true);
+      expect(new Int64.fromInt(10) >= new Int32.fromInt(11), false);
+      expect(new Int64.fromInt(10) >= new Int32.fromInt(10), true);
+      expect(new Int64.fromInt(10) >= new Int32.fromInt(9), true);
+      expect(new Int64.fromInt(-10) >= new Int64.fromInt(-11), true);
+      expect(new Int64.fromInt(-10) >= new Int64.fromInt(-10), true);
       expect(largePos >= largeNeg, true);
       expect(largeNeg >= largePos, false);
       expect(largePos >= largePosPlusOne, false);
       expect(largePos >= largePos, true);
       expect(largePosPlusOne >= largePos, true);
-      expect(int64.MIN_VALUE >= int64.MAX_VALUE, false);
-      expect(int64.MAX_VALUE >= int64.MIN_VALUE, true);
-      expect(() => new int64.fromInt(17) >= null, throwsArgumentError);
+      expect(Int64.MIN_VALUE >= Int64.MAX_VALUE, false);
+      expect(Int64.MAX_VALUE >= Int64.MIN_VALUE, true);
+      expect(() => new Int64.fromInt(17) >= null, throwsArgumentError);
     });
 
     test(">", () {
-      expect(new int64.fromInt(10) > new int64.fromInt(11), false);
-      expect(new int64.fromInt(10) > new int64.fromInt(10), false);
-      expect(new int64.fromInt(10) > new int64.fromInt(9), true);
-      expect(new int64.fromInt(10) > new int32.fromInt(11), false);
-      expect(new int64.fromInt(10) > new int32.fromInt(10), false);
-      expect(new int64.fromInt(10) > new int32.fromInt(9), true);
-      expect(new int64.fromInt(-10) > new int64.fromInt(-11), true);
-      expect(new int64.fromInt(10) > new int64.fromInt(-11), true);
-      expect(new int64.fromInt(-10) > new int64.fromInt(11), false);
+      expect(new Int64.fromInt(10) > new Int64.fromInt(11), false);
+      expect(new Int64.fromInt(10) > new Int64.fromInt(10), false);
+      expect(new Int64.fromInt(10) > new Int64.fromInt(9), true);
+      expect(new Int64.fromInt(10) > new Int32.fromInt(11), false);
+      expect(new Int64.fromInt(10) > new Int32.fromInt(10), false);
+      expect(new Int64.fromInt(10) > new Int32.fromInt(9), true);
+      expect(new Int64.fromInt(-10) > new Int64.fromInt(-11), true);
+      expect(new Int64.fromInt(10) > new Int64.fromInt(-11), true);
+      expect(new Int64.fromInt(-10) > new Int64.fromInt(11), false);
       expect(largePos > largeNeg, true);
       expect(largeNeg > largePos, false);
       expect(largePos > largePosPlusOne, false);
       expect(largePos > largePos, false);
       expect(largePosPlusOne > largePos, true);
-      expect(new int64.fromInt(0) > int64.MIN_VALUE, true);
-      expect(int64.MIN_VALUE > int64.MAX_VALUE, false);
-      expect(int64.MAX_VALUE > int64.MIN_VALUE, true);
-      expect(() => new int64.fromInt(17) > null, throwsArgumentError);
+      expect(new Int64.fromInt(0) > Int64.MIN_VALUE, true);
+      expect(Int64.MIN_VALUE > Int64.MAX_VALUE, false);
+      expect(Int64.MAX_VALUE > Int64.MIN_VALUE, true);
+      expect(() => new Int64.fromInt(17) > null, throwsArgumentError);
     });
   });
 
   group("bitwise operators", () {
-    int64 n1 = new int64.fromInt(1234);
-    int64 n2 = new int64.fromInt(9876);
-    int64 n3 = new int64.fromInt(-1234);
-    int64 n4 = new int64.fromInt(0x1234) << 32;
-    int64 n5 = new int64.fromInt(0x9876) << 32;
+    Int64 n1 = new Int64.fromInt(1234);
+    Int64 n2 = new Int64.fromInt(9876);
+    Int64 n3 = new Int64.fromInt(-1234);
+    Int64 n4 = new Int64.fromInt(0x1234) << 32;
+    Int64 n5 = new Int64.fromInt(0x9876) << 32;
 
     test("&", () {
-      expect(n1 & n2, new int64.fromInt(1168));
-      expect(n3 & n2, new int64.fromInt(8708));
-      expect(n4 & n5, new int64.fromInt(0x1034) << 32);
+      expect(n1 & n2, new Int64.fromInt(1168));
+      expect(n3 & n2, new Int64.fromInt(8708));
+      expect(n4 & n5, new Int64.fromInt(0x1034) << 32);
       expect(() => n1 & null, throwsArgumentError);
     });
 
     test("|", () {
-      expect(n1 | n2, new int64.fromInt(9942));
-      expect(n3 | n2, new int64.fromInt(-66));
-      expect(n4 | n5, new int64.fromInt(0x9a76) << 32);
+      expect(n1 | n2, new Int64.fromInt(9942));
+      expect(n3 | n2, new Int64.fromInt(-66));
+      expect(n4 | n5, new Int64.fromInt(0x9a76) << 32);
       expect(() => n1 | null, throwsArgumentError);
     });
 
     test("^", () {
-      expect(n1 ^ n2, new int64.fromInt(8774));
-      expect(n3 ^ n2, new int64.fromInt(-8774));
-      expect(n4 ^ n5, new int64.fromInt(0x8a42) << 32);
+      expect(n1 ^ n2, new Int64.fromInt(8774));
+      expect(n3 ^ n2, new Int64.fromInt(-8774));
+      expect(n4 ^ n5, new Int64.fromInt(0x8a42) << 32);
       expect(() => n1 ^ null, throwsArgumentError);
     });
 
     test("~", () {
-      expect(-new int64.fromInt(1), new int64.fromInt(-1));
-      expect(-new int64.fromInt(-1), new int64.fromInt(1));
-      expect(-int64.MIN_VALUE, int64.MIN_VALUE);
+      expect(-new Int64.fromInt(1), new Int64.fromInt(-1));
+      expect(-new Int64.fromInt(-1), new Int64.fromInt(1));
+      expect(-Int64.MIN_VALUE, Int64.MIN_VALUE);
 
-      expect(~n1, new int64.fromInt(-1235));
-      expect(~n2, new int64.fromInt(-9877));
-      expect(~n3, new int64.fromInt(1233));
-      expect(~n4, new int64.fromInts(0xffffedcb, 0xffffffff));
-      expect(~n5, new int64.fromInts(0xffff6789, 0xffffffff));
+      expect(~n1, new Int64.fromInt(-1235));
+      expect(~n2, new Int64.fromInt(-9877));
+      expect(~n3, new Int64.fromInt(1233));
+      expect(~n4, new Int64.fromInts(0xffffedcb, 0xffffffff));
+      expect(~n5, new Int64.fromInts(0xffff6789, 0xffffffff));
     });
   });
 
   group("bitshift operators", () {
     test("<<", () {
-      expect(new int64.fromInts(0x12341234, 0x45674567) << 10,
-          new int64.fromInts(0xd048d115, 0x9d159c00));
-      expect(new int64.fromInts(0x92341234, 0x45674567) << 10,
-          new int64.fromInts(0xd048d115, 0x9d159c00));
-      expect(new int64.fromInt(-1) << 5, new int64.fromInt(-32));
-      expect(new int64.fromInt(-1) << 0, new int64.fromInt(-1));
-      expect(() => new int64.fromInt(17) << -1, throwsArgumentError);
-      expect(() => new int64.fromInt(17) << null, throws);
+      expect(new Int64.fromInts(0x12341234, 0x45674567) << 10,
+          new Int64.fromInts(0xd048d115, 0x9d159c00));
+      expect(new Int64.fromInts(0x92341234, 0x45674567) << 10,
+          new Int64.fromInts(0xd048d115, 0x9d159c00));
+      expect(new Int64.fromInt(-1) << 5, new Int64.fromInt(-32));
+      expect(new Int64.fromInt(-1) << 0, new Int64.fromInt(-1));
+      expect(() => new Int64.fromInt(17) << -1, throwsArgumentError);
+      expect(() => new Int64.fromInt(17) << null, throws);
     });
 
     test(">>", () {
-      expect((int64.MIN_VALUE >> 13).toString(), "-1125899906842624");
-      expect(new int64.fromInts(0x12341234, 0x45674567) >> 10,
-          new int64.fromInts(0x48d04, 0x8d1159d1));
-      expect(new int64.fromInts(0x92341234, 0x45674567) >> 10,
-          new int64.fromInts(0xffe48d04, 0x8d1159d1));
-      expect(new int64.fromInts(0xFFFFFFF, 0xFFFFFFFF) >> 34,
-          new int64.fromInt(67108863));
+      expect((Int64.MIN_VALUE >> 13).toString(), "-1125899906842624");
+      expect(new Int64.fromInts(0x12341234, 0x45674567) >> 10,
+          new Int64.fromInts(0x48d04, 0x8d1159d1));
+      expect(new Int64.fromInts(0x92341234, 0x45674567) >> 10,
+          new Int64.fromInts(0xffe48d04, 0x8d1159d1));
+      expect(new Int64.fromInts(0xFFFFFFF, 0xFFFFFFFF) >> 34,
+          new Int64.fromInt(67108863));
       for (int n = 0; n <= 66; n++) {
-        expect(new int64.fromInt(-1) >> n, new int64.fromInt(-1));
+        expect(new Int64.fromInt(-1) >> n, new Int64.fromInt(-1));
       }
-      expect(new int64.fromInts(0x72345678, 0x9abcdef0) >> 8,
-          new int64.fromInts(0x00723456, 0x789abcde));
-      expect(new int64.fromInts(0x72345678, 0x9abcdef0) >> 16,
-          new int64.fromInts(0x00007234, 0x56789abc));
-      expect(new int64.fromInts(0x72345678, 0x9abcdef0) >> 24,
-          new int64.fromInts(0x00000072, 0x3456789a));
-      expect(new int64.fromInts(0x72345678, 0x9abcdef0) >> 28,
-          new int64.fromInts(0x00000007, 0x23456789));
-      expect(new int64.fromInts(0x72345678, 0x9abcdef0) >> 32,
-          new int64.fromInts(0x00000000, 0x72345678));
-      expect(new int64.fromInts(0x72345678, 0x9abcdef0) >> 36,
-          new int64.fromInts(0x00000000, 0x07234567));
-      expect(new int64.fromInts(0x72345678, 0x9abcdef0) >> 40,
-          new int64.fromInts(0x00000000, 0x00723456));
-      expect(new int64.fromInts(0x72345678, 0x9abcde00) >> 44,
-          new int64.fromInts(0x00000000, 0x00072345));
-      expect(new int64.fromInts(0x72345678, 0x9abcdef0) >> 48,
-          new int64.fromInts(0x00000000, 0x00007234));
-      expect(new int64.fromInts(0x92345678, 0x9abcdef0) >> 8,
-          new int64.fromInts(0xff923456, 0x789abcde));
-      expect(new int64.fromInts(0x92345678, 0x9abcdef0) >> 16,
-          new int64.fromInts(0xffff9234, 0x56789abc));
-      expect(new int64.fromInts(0x92345678, 0x9abcdef0) >> 24,
-          new int64.fromInts(0xffffff92, 0x3456789a));
-      expect(new int64.fromInts(0x92345678, 0x9abcdef0) >> 28,
-          new int64.fromInts(0xfffffff9, 0x23456789));
-      expect(new int64.fromInts(0x92345678, 0x9abcdef0) >> 32,
-          new int64.fromInts(0xffffffff, 0x92345678));
-      expect(new int64.fromInts(0x92345678, 0x9abcdef0) >> 36,
-          new int64.fromInts(0xffffffff, 0xf9234567));
-      expect(new int64.fromInts(0x92345678, 0x9abcdef0) >> 40,
-          new int64.fromInts(0xffffffff, 0xff923456));
-      expect(new int64.fromInts(0x92345678, 0x9abcdef0) >> 44,
-          new int64.fromInts(0xffffffff, 0xfff92345));
-      expect(new int64.fromInts(0x92345678, 0x9abcdef0) >> 48,
-          new int64.fromInts(0xffffffff, 0xffff9234));
-      expect(() => new int64.fromInt(17) >> -1, throwsArgumentError);
-      expect(() => new int64.fromInt(17) >> null, throws);
+      expect(new Int64.fromInts(0x72345678, 0x9abcdef0) >> 8,
+          new Int64.fromInts(0x00723456, 0x789abcde));
+      expect(new Int64.fromInts(0x72345678, 0x9abcdef0) >> 16,
+          new Int64.fromInts(0x00007234, 0x56789abc));
+      expect(new Int64.fromInts(0x72345678, 0x9abcdef0) >> 24,
+          new Int64.fromInts(0x00000072, 0x3456789a));
+      expect(new Int64.fromInts(0x72345678, 0x9abcdef0) >> 28,
+          new Int64.fromInts(0x00000007, 0x23456789));
+      expect(new Int64.fromInts(0x72345678, 0x9abcdef0) >> 32,
+          new Int64.fromInts(0x00000000, 0x72345678));
+      expect(new Int64.fromInts(0x72345678, 0x9abcdef0) >> 36,
+          new Int64.fromInts(0x00000000, 0x07234567));
+      expect(new Int64.fromInts(0x72345678, 0x9abcdef0) >> 40,
+          new Int64.fromInts(0x00000000, 0x00723456));
+      expect(new Int64.fromInts(0x72345678, 0x9abcde00) >> 44,
+          new Int64.fromInts(0x00000000, 0x00072345));
+      expect(new Int64.fromInts(0x72345678, 0x9abcdef0) >> 48,
+          new Int64.fromInts(0x00000000, 0x00007234));
+      expect(new Int64.fromInts(0x92345678, 0x9abcdef0) >> 8,
+          new Int64.fromInts(0xff923456, 0x789abcde));
+      expect(new Int64.fromInts(0x92345678, 0x9abcdef0) >> 16,
+          new Int64.fromInts(0xffff9234, 0x56789abc));
+      expect(new Int64.fromInts(0x92345678, 0x9abcdef0) >> 24,
+          new Int64.fromInts(0xffffff92, 0x3456789a));
+      expect(new Int64.fromInts(0x92345678, 0x9abcdef0) >> 28,
+          new Int64.fromInts(0xfffffff9, 0x23456789));
+      expect(new Int64.fromInts(0x92345678, 0x9abcdef0) >> 32,
+          new Int64.fromInts(0xffffffff, 0x92345678));
+      expect(new Int64.fromInts(0x92345678, 0x9abcdef0) >> 36,
+          new Int64.fromInts(0xffffffff, 0xf9234567));
+      expect(new Int64.fromInts(0x92345678, 0x9abcdef0) >> 40,
+          new Int64.fromInts(0xffffffff, 0xff923456));
+      expect(new Int64.fromInts(0x92345678, 0x9abcdef0) >> 44,
+          new Int64.fromInts(0xffffffff, 0xfff92345));
+      expect(new Int64.fromInts(0x92345678, 0x9abcdef0) >> 48,
+          new Int64.fromInts(0xffffffff, 0xffff9234));
+      expect(() => new Int64.fromInt(17) >> -1, throwsArgumentError);
+      expect(() => new Int64.fromInt(17) >> null, throws);
     });
 
     test("shiftRightUnsigned", () {
-      expect(new int64.fromInts(0x12341234, 0x45674567).shiftRightUnsigned(10),
-          new int64.fromInts(0x48d04, 0x8d1159d1));
-      expect(new int64.fromInts(0x92341234, 0x45674567).shiftRightUnsigned(10),
-          new int64.fromInts(0x248d04, 0x8d1159d1));
-      expect(new int64.fromInts(0x72345678, 0x9abcdef0).shiftRightUnsigned(8),
-          new int64.fromInts(0x00723456, 0x789abcde));
-      expect(new int64.fromInts(0x72345678, 0x9abcdef0).shiftRightUnsigned(16),
-          new int64.fromInts(0x00007234, 0x56789abc));
-      expect(new int64.fromInts(0x72345678, 0x9abcdef0).shiftRightUnsigned(24),
-          new int64.fromInts(0x00000072, 0x3456789a));
-      expect(new int64.fromInts(0x72345678, 0x9abcdef0).shiftRightUnsigned(28),
-          new int64.fromInts(0x00000007, 0x23456789));
-      expect(new int64.fromInts(0x72345678, 0x9abcdef0).shiftRightUnsigned(32),
-          new int64.fromInts(0x00000000, 0x72345678));
-      expect(new int64.fromInts(0x72345678, 0x9abcdef0).shiftRightUnsigned(36),
-          new int64.fromInts(0x00000000, 0x07234567));
-      expect(new int64.fromInts(0x72345678, 0x9abcdef0).shiftRightUnsigned(40),
-          new int64.fromInts(0x00000000, 0x00723456));
-      expect(new int64.fromInts(0x72345678, 0x9abcde00).shiftRightUnsigned(44),
-          new int64.fromInts(0x00000000, 0x00072345));
-      expect(new int64.fromInts(0x72345678, 0x9abcdef0).shiftRightUnsigned(48),
-          new int64.fromInts(0x00000000, 0x00007234));
-      expect(new int64.fromInts(0x92345678, 0x9abcdef0).shiftRightUnsigned(8),
-          new int64.fromInts(0x00923456, 0x789abcde));
-      expect(new int64.fromInts(0x92345678, 0x9abcdef0).shiftRightUnsigned(16),
-          new int64.fromInts(0x00009234, 0x56789abc));
-      expect(new int64.fromInts(0x92345678, 0x9abcdef0).shiftRightUnsigned(24),
-          new int64.fromInts(0x00000092, 0x3456789a));
-      expect(new int64.fromInts(0x92345678, 0x9abcdef0).shiftRightUnsigned(28),
-          new int64.fromInts(0x00000009, 0x23456789));
-      expect(new int64.fromInts(0x92345678, 0x9abcdef0).shiftRightUnsigned(32),
-          new int64.fromInts(0x00000000, 0x92345678));
-      expect(new int64.fromInts(0x92345678, 0x9abcdef0).shiftRightUnsigned(36),
-          new int64.fromInts(0x00000000, 0x09234567));
-      expect(new int64.fromInts(0x92345678, 0x9abcdef0).shiftRightUnsigned(40),
-          new int64.fromInts(0x00000000, 0x00923456));
-      expect(new int64.fromInts(0x92345678, 0x9abcdef0).shiftRightUnsigned(44),
-          new int64.fromInts(0x00000000, 0x00092345));
-      expect(new int64.fromInts(0x00000000, 0x00009234),
-          new int64.fromInts(0x92345678, 0x9abcdef0).shiftRightUnsigned(48));
-      expect(() => new int64.fromInt(17).shiftRightUnsigned(-1),
+      expect(new Int64.fromInts(0x12341234, 0x45674567).shiftRightUnsigned(10),
+          new Int64.fromInts(0x48d04, 0x8d1159d1));
+      expect(new Int64.fromInts(0x92341234, 0x45674567).shiftRightUnsigned(10),
+          new Int64.fromInts(0x248d04, 0x8d1159d1));
+      expect(new Int64.fromInts(0x72345678, 0x9abcdef0).shiftRightUnsigned(8),
+          new Int64.fromInts(0x00723456, 0x789abcde));
+      expect(new Int64.fromInts(0x72345678, 0x9abcdef0).shiftRightUnsigned(16),
+          new Int64.fromInts(0x00007234, 0x56789abc));
+      expect(new Int64.fromInts(0x72345678, 0x9abcdef0).shiftRightUnsigned(24),
+          new Int64.fromInts(0x00000072, 0x3456789a));
+      expect(new Int64.fromInts(0x72345678, 0x9abcdef0).shiftRightUnsigned(28),
+          new Int64.fromInts(0x00000007, 0x23456789));
+      expect(new Int64.fromInts(0x72345678, 0x9abcdef0).shiftRightUnsigned(32),
+          new Int64.fromInts(0x00000000, 0x72345678));
+      expect(new Int64.fromInts(0x72345678, 0x9abcdef0).shiftRightUnsigned(36),
+          new Int64.fromInts(0x00000000, 0x07234567));
+      expect(new Int64.fromInts(0x72345678, 0x9abcdef0).shiftRightUnsigned(40),
+          new Int64.fromInts(0x00000000, 0x00723456));
+      expect(new Int64.fromInts(0x72345678, 0x9abcde00).shiftRightUnsigned(44),
+          new Int64.fromInts(0x00000000, 0x00072345));
+      expect(new Int64.fromInts(0x72345678, 0x9abcdef0).shiftRightUnsigned(48),
+          new Int64.fromInts(0x00000000, 0x00007234));
+      expect(new Int64.fromInts(0x92345678, 0x9abcdef0).shiftRightUnsigned(8),
+          new Int64.fromInts(0x00923456, 0x789abcde));
+      expect(new Int64.fromInts(0x92345678, 0x9abcdef0).shiftRightUnsigned(16),
+          new Int64.fromInts(0x00009234, 0x56789abc));
+      expect(new Int64.fromInts(0x92345678, 0x9abcdef0).shiftRightUnsigned(24),
+          new Int64.fromInts(0x00000092, 0x3456789a));
+      expect(new Int64.fromInts(0x92345678, 0x9abcdef0).shiftRightUnsigned(28),
+          new Int64.fromInts(0x00000009, 0x23456789));
+      expect(new Int64.fromInts(0x92345678, 0x9abcdef0).shiftRightUnsigned(32),
+          new Int64.fromInts(0x00000000, 0x92345678));
+      expect(new Int64.fromInts(0x92345678, 0x9abcdef0).shiftRightUnsigned(36),
+          new Int64.fromInts(0x00000000, 0x09234567));
+      expect(new Int64.fromInts(0x92345678, 0x9abcdef0).shiftRightUnsigned(40),
+          new Int64.fromInts(0x00000000, 0x00923456));
+      expect(new Int64.fromInts(0x92345678, 0x9abcdef0).shiftRightUnsigned(44),
+          new Int64.fromInts(0x00000000, 0x00092345));
+      expect(new Int64.fromInts(0x00000000, 0x00009234),
+          new Int64.fromInts(0x92345678, 0x9abcdef0).shiftRightUnsigned(48));
+      expect(() => new Int64.fromInt(17).shiftRightUnsigned(-1),
           throwsArgumentError);
-      expect(() => new int64.fromInt(17).shiftRightUnsigned(null), throws);
+      expect(() => new Int64.fromInt(17).shiftRightUnsigned(null), throws);
     });
 
     test("overflow", () {
-      expect((new int64.fromInt(1) << 63) >> 1,
-          -new int64.fromInts(0x40000000, 0x00000000));
-      expect((new int64.fromInt(-1) << 32) << 32, new int64.fromInt(0));
-      expect(int64.MIN_VALUE << 0, int64.MIN_VALUE);
-      expect(int64.MIN_VALUE << 1, new int64.fromInt(0));
-      expect((-new int64.fromInts(8, 0)) >> 1,
-          new int64.fromInts(0xfffffffc, 0x00000000));
-      expect((-new int64.fromInts(8, 0)).shiftRightUnsigned(1),
-          new int64.fromInts(0x7ffffffc, 0x0));
+      expect((new Int64.fromInt(1) << 63) >> 1,
+          -new Int64.fromInts(0x40000000, 0x00000000));
+      expect((new Int64.fromInt(-1) << 32) << 32, new Int64.fromInt(0));
+      expect(Int64.MIN_VALUE << 0, Int64.MIN_VALUE);
+      expect(Int64.MIN_VALUE << 1, new Int64.fromInt(0));
+      expect((-new Int64.fromInts(8, 0)) >> 1,
+          new Int64.fromInts(0xfffffffc, 0x00000000));
+      expect((-new Int64.fromInts(8, 0)).shiftRightUnsigned(1),
+          new Int64.fromInts(0x7ffffffc, 0x0));
     });
   });
 
   group("type conversions", () {
     test("toInt", () {
-      expect(new int64.fromInt(0).toInt(), 0);
-      expect(new int64.fromInt(100).toInt(), 100);
-      expect(new int64.fromInt(-100).toInt(), -100);
-      expect(new int64.fromInt(2147483647).toInt(), 2147483647);
-      expect(new int64.fromInt(2147483648).toInt(), 2147483648);
-      expect(new int64.fromInt(-2147483647).toInt(), -2147483647);
-      expect(new int64.fromInt(-2147483648).toInt(), -2147483648);
-      expect(new int64.fromInt(4503599627370495).toInt(), 4503599627370495);
-      expect(new int64.fromInt(4503599627370496).toInt(), 4503599627370496);
-      expect(new int64.fromInt(-4503599627370495).toInt(), -4503599627370495);
-      expect(new int64.fromInt(-4503599627370496).toInt(), -4503599627370496);
+      expect(new Int64.fromInt(0).toInt(), 0);
+      expect(new Int64.fromInt(100).toInt(), 100);
+      expect(new Int64.fromInt(-100).toInt(), -100);
+      expect(new Int64.fromInt(2147483647).toInt(), 2147483647);
+      expect(new Int64.fromInt(2147483648).toInt(), 2147483648);
+      expect(new Int64.fromInt(-2147483647).toInt(), -2147483647);
+      expect(new Int64.fromInt(-2147483648).toInt(), -2147483648);
+      expect(new Int64.fromInt(4503599627370495).toInt(), 4503599627370495);
+      expect(new Int64.fromInt(4503599627370496).toInt(), 4503599627370496);
+      expect(new Int64.fromInt(-4503599627370495).toInt(), -4503599627370495);
+      expect(new Int64.fromInt(-4503599627370496).toInt(), -4503599627370496);
     });
 
     test("toInt32", () {
-      expect(new int64.fromInt(0).toInt32(), new int32.fromInt(0));
-      expect(new int64.fromInt(1).toInt32(), new int32.fromInt(1));
-      expect(new int64.fromInt(-1).toInt32(), new int32.fromInt(-1));
-      expect(new int64.fromInt(2147483647).toInt32(),
-          new int32.fromInt(2147483647));
-      expect(new int64.fromInt(2147483648).toInt32(),
-          new int32.fromInt(-2147483648));
-      expect(new int64.fromInt(2147483649).toInt32(),
-          new int32.fromInt(-2147483647));
-      expect(new int64.fromInt(2147483650).toInt32(),
-          new int32.fromInt(-2147483646));
-      expect(new int64.fromInt(-2147483648).toInt32(),
-          new int32.fromInt(-2147483648));
-      expect(new int64.fromInt(-2147483649).toInt32(),
-          new int32.fromInt(2147483647));
-      expect(new int64.fromInt(-2147483650).toInt32(),
-          new int32.fromInt(2147483646));
-      expect(new int64.fromInt(-2147483651).toInt32(),
-          new int32.fromInt(2147483645));
+      expect(new Int64.fromInt(0).toInt32(), new Int32.fromInt(0));
+      expect(new Int64.fromInt(1).toInt32(), new Int32.fromInt(1));
+      expect(new Int64.fromInt(-1).toInt32(), new Int32.fromInt(-1));
+      expect(new Int64.fromInt(2147483647).toInt32(),
+          new Int32.fromInt(2147483647));
+      expect(new Int64.fromInt(2147483648).toInt32(),
+          new Int32.fromInt(-2147483648));
+      expect(new Int64.fromInt(2147483649).toInt32(),
+          new Int32.fromInt(-2147483647));
+      expect(new Int64.fromInt(2147483650).toInt32(),
+          new Int32.fromInt(-2147483646));
+      expect(new Int64.fromInt(-2147483648).toInt32(),
+          new Int32.fromInt(-2147483648));
+      expect(new Int64.fromInt(-2147483649).toInt32(),
+          new Int32.fromInt(2147483647));
+      expect(new Int64.fromInt(-2147483650).toInt32(),
+          new Int32.fromInt(2147483646));
+      expect(new Int64.fromInt(-2147483651).toInt32(),
+          new Int32.fromInt(2147483645));
     });
   });
 
   test("JavaScript 53-bit integer boundary", () {
-    int64 _factorial(int64 n) {
+    Int64 _factorial(Int64 n) {
       if (n.isZero) {
-        return new int64.fromInt(1);
+        return new Int64.fromInt(1);
       } else {
-        return n * _factorial(n - new int64.fromInt(1));
+        return n * _factorial(n - new Int64.fromInt(1));
       }
     }
-    int64 fact18 = _factorial(new int64.fromInt(18));
-    int64 fact17 = _factorial(new int64.fromInt(17));
-    expect(fact18 ~/ fact17, new int64.fromInt(18));
+    Int64 fact18 = _factorial(new Int64.fromInt(18));
+    Int64 fact17 = _factorial(new Int64.fromInt(17));
+    expect(fact18 ~/ fact17, new Int64.fromInt(18));
   });
 
   test("min, max values", () {
-    expect(new int64.fromInt(1) << 63, int64.MIN_VALUE);
-    expect(-(int64.MIN_VALUE + new int64.fromInt(1)), int64.MAX_VALUE);
+    expect(new Int64.fromInt(1) << 63, Int64.MIN_VALUE);
+    expect(-(Int64.MIN_VALUE + new Int64.fromInt(1)), Int64.MAX_VALUE);
   });
 
   group("string representation", () {
     test("toString", () {
-      expect(new int64.fromInt(0).toString(), "0");
-      expect(new int64.fromInt(1).toString(), "1");
-      expect(new int64.fromInt(-1).toString(), "-1");
-      expect(new int64.fromInt(-10).toString(), "-10");
-      expect(int64.MIN_VALUE.toString(), "-9223372036854775808");
-      expect(int64.MAX_VALUE.toString(), "9223372036854775807");
+      expect(new Int64.fromInt(0).toString(), "0");
+      expect(new Int64.fromInt(1).toString(), "1");
+      expect(new Int64.fromInt(-1).toString(), "-1");
+      expect(new Int64.fromInt(-10).toString(), "-10");
+      expect(Int64.MIN_VALUE.toString(), "-9223372036854775808");
+      expect(Int64.MAX_VALUE.toString(), "9223372036854775807");
 
       int top = 922337201;
       int bottom = 967490662;
-      int64 fullnum = (new int64.fromInt(1000000000) * new int64.fromInt(top)) +
-          new int64.fromInt(bottom);
+      Int64 fullnum = (new Int64.fromInt(1000000000) * new Int64.fromInt(top)) +
+          new Int64.fromInt(bottom);
       expect(fullnum.toString(), "922337201967490662");
       expect((-fullnum).toString(), "-922337201967490662");
-      expect(new int64.fromInt(123456789).toString(), "123456789");
+      expect(new Int64.fromInt(123456789).toString(), "123456789");
     });
 
     test("toHexString", () {
-      int64 deadbeef12341234 = new int64.fromInts(0xDEADBEEF, 0x12341234);
-      expect(int64.ZERO.toHexString(), "0");
+      Int64 deadbeef12341234 = new Int64.fromInts(0xDEADBEEF, 0x12341234);
+      expect(Int64.ZERO.toHexString(), "0");
       expect(deadbeef12341234.toHexString(), "DEADBEEF12341234");
-      expect(new int64.fromInts(0x17678A7, 0xDEF01234).toHexString(),
+      expect(new Int64.fromInts(0x17678A7, 0xDEF01234).toHexString(),
           "17678A7DEF01234");
-      expect(new int64.fromInt(123456789).toHexString(), "75BCD15");
+      expect(new Int64.fromInt(123456789).toHexString(), "75BCD15");
     });
 
     test("toRadixString", () {
-      expect(new int64.fromInt(123456789).toRadixString(5), "223101104124");
-      expect(int64.MIN_VALUE.toRadixString(2),
+      expect(new Int64.fromInt(123456789).toRadixString(5), "223101104124");
+      expect(Int64.MIN_VALUE.toRadixString(2),
           "-1000000000000000000000000000000000000000000000000000000000000000");
-      expect(int64.MIN_VALUE.toRadixString(3),
+      expect(Int64.MIN_VALUE.toRadixString(3),
           "-2021110011022210012102010021220101220222");
-      expect(int64.MIN_VALUE.toRadixString(4),
+      expect(Int64.MIN_VALUE.toRadixString(4),
           "-20000000000000000000000000000000");
-      expect(int64.MIN_VALUE.toRadixString(5), "-1104332401304422434310311213");
-      expect(int64.MIN_VALUE.toRadixString(6), "-1540241003031030222122212");
-      expect(int64.MIN_VALUE.toRadixString(7), "-22341010611245052052301");
-      expect(int64.MIN_VALUE.toRadixString(8), "-1000000000000000000000");
-      expect(int64.MIN_VALUE.toRadixString(9), "-67404283172107811828");
-      expect(int64.MIN_VALUE.toRadixString(10), "-9223372036854775808");
-      expect(int64.MIN_VALUE.toRadixString(11), "-1728002635214590698");
-      expect(int64.MIN_VALUE.toRadixString(12), "-41A792678515120368");
-      expect(int64.MIN_VALUE.toRadixString(13), "-10B269549075433C38");
-      expect(int64.MIN_VALUE.toRadixString(14), "-4340724C6C71DC7A8");
-      expect(int64.MIN_VALUE.toRadixString(15), "-160E2AD3246366808");
-      expect(int64.MIN_VALUE.toRadixString(16), "-8000000000000000");
-      expect(int64.MAX_VALUE.toRadixString(2),
+      expect(Int64.MIN_VALUE.toRadixString(5), "-1104332401304422434310311213");
+      expect(Int64.MIN_VALUE.toRadixString(6), "-1540241003031030222122212");
+      expect(Int64.MIN_VALUE.toRadixString(7), "-22341010611245052052301");
+      expect(Int64.MIN_VALUE.toRadixString(8), "-1000000000000000000000");
+      expect(Int64.MIN_VALUE.toRadixString(9), "-67404283172107811828");
+      expect(Int64.MIN_VALUE.toRadixString(10), "-9223372036854775808");
+      expect(Int64.MIN_VALUE.toRadixString(11), "-1728002635214590698");
+      expect(Int64.MIN_VALUE.toRadixString(12), "-41A792678515120368");
+      expect(Int64.MIN_VALUE.toRadixString(13), "-10B269549075433C38");
+      expect(Int64.MIN_VALUE.toRadixString(14), "-4340724C6C71DC7A8");
+      expect(Int64.MIN_VALUE.toRadixString(15), "-160E2AD3246366808");
+      expect(Int64.MIN_VALUE.toRadixString(16), "-8000000000000000");
+      expect(Int64.MAX_VALUE.toRadixString(2),
           "111111111111111111111111111111111111111111111111111111111111111");
-      expect(int64.MAX_VALUE.toRadixString(3),
+      expect(Int64.MAX_VALUE.toRadixString(3),
           "2021110011022210012102010021220101220221");
-      expect(int64.MAX_VALUE.toRadixString(4),
+      expect(Int64.MAX_VALUE.toRadixString(4),
           "13333333333333333333333333333333");
-      expect(int64.MAX_VALUE.toRadixString(5), "1104332401304422434310311212");
-      expect(int64.MAX_VALUE.toRadixString(6), "1540241003031030222122211");
-      expect(int64.MAX_VALUE.toRadixString(7), "22341010611245052052300");
-      expect(int64.MAX_VALUE.toRadixString(8), "777777777777777777777");
-      expect(int64.MAX_VALUE.toRadixString(9), "67404283172107811827");
-      expect(int64.MAX_VALUE.toRadixString(10), "9223372036854775807");
-      expect(int64.MAX_VALUE.toRadixString(11), "1728002635214590697");
-      expect(int64.MAX_VALUE.toRadixString(12), "41A792678515120367");
-      expect(int64.MAX_VALUE.toRadixString(13), "10B269549075433C37");
-      expect(int64.MAX_VALUE.toRadixString(14), "4340724C6C71DC7A7");
-      expect(int64.MAX_VALUE.toRadixString(15), "160E2AD3246366807");
-      expect(int64.MAX_VALUE.toRadixString(16), "7FFFFFFFFFFFFFFF");
+      expect(Int64.MAX_VALUE.toRadixString(5), "1104332401304422434310311212");
+      expect(Int64.MAX_VALUE.toRadixString(6), "1540241003031030222122211");
+      expect(Int64.MAX_VALUE.toRadixString(7), "22341010611245052052300");
+      expect(Int64.MAX_VALUE.toRadixString(8), "777777777777777777777");
+      expect(Int64.MAX_VALUE.toRadixString(9), "67404283172107811827");
+      expect(Int64.MAX_VALUE.toRadixString(10), "9223372036854775807");
+      expect(Int64.MAX_VALUE.toRadixString(11), "1728002635214590697");
+      expect(Int64.MAX_VALUE.toRadixString(12), "41A792678515120367");
+      expect(Int64.MAX_VALUE.toRadixString(13), "10B269549075433C37");
+      expect(Int64.MAX_VALUE.toRadixString(14), "4340724C6C71DC7A7");
+      expect(Int64.MAX_VALUE.toRadixString(15), "160E2AD3246366807");
+      expect(Int64.MAX_VALUE.toRadixString(16), "7FFFFFFFFFFFFFFF");
     });
   });
 }
diff --git a/pkg/mdv/lib/mdv.dart b/pkg/mdv/lib/mdv.dart
index 8c46580..8ba6bf6 100644
--- a/pkg/mdv/lib/mdv.dart
+++ b/pkg/mdv/lib/mdv.dart
@@ -47,29 +47,15 @@
  */
 // TODO(rafaelw): This is a hack, and is neccesary for the polyfill
 // because custom elements are not upgraded during clone()
+// TODO(jmesserly): polymer removed this in:
+// https://github.com/Polymer/platform/commit/344ffeaae475babb529403f6608588a0fc73f4e7
 Stream<DocumentFragment> get instanceCreated {
   if (_instanceCreated == null) {
-    _instanceCreated =
-        new StreamController<DocumentFragment>(sync: true);
+    _instanceCreated = new StreamController<DocumentFragment>(sync: true);
   }
   return _instanceCreated.stream;
 }
 
-/**
- * Binds all mustaches recursively starting from the [root] node.
- *
- * Note: this is not an official Model-Driven-Views API; it is intended to
- * support binding the [ShadowRoot]'s content to a model.
- */
-// TODO(jmesserly): this is needed to avoid two <template> nodes when using
-// bindings in a custom element's template. See also:
-// https://github.com/polymer-project/polymer/blob/master/src/bindMDV.js#L68
-// Called from:
-// https://github.com/polymer-project/polymer/blob/master/src/register.js#L99
-void bindModel(Node root, model, [BindingDelegate delegate]) {
-  _addBindings(root, model, delegate);
-}
-
 
 // TODO(jmesserly): investigate if expandos give us enough performance.
 
diff --git a/pkg/mdv/lib/src/template_iterator.dart b/pkg/mdv/lib/src/template_iterator.dart
index 8cca7ce..6c87a42 100644
--- a/pkg/mdv/lib/src/template_iterator.dart
+++ b/pkg/mdv/lib/src/template_iterator.dart
@@ -99,14 +99,12 @@
     return;
   }
 
-  var replacementBinding = new CompoundBinding();
-  for (var i = 1; i < tokens.length; i += 2) {
-    // TODO(jmesserly): not sure if this index is correct. See my comment here:
-    // https://github.com/Polymer/mdv/commit/f1af6fe683fd06eed2a7a7849f01c227db12cda3#L0L1035
-    _bindOrDelegate(replacementBinding, i, model, tokens[i], delegate);
-  }
-
-  replacementBinding.combinator = (values) {
+  // TODO(jmesserly): MDV caches the closure on the tokens, but I'm not sure
+  // why they do that instead of just caching the entire CompoundBinding object
+  // and unbindAll then bind to the new model.
+  var replacementBinding = new CompoundBinding()
+      ..scheduled = true
+      ..combinator = (values) {
     var newValue = new StringBuffer();
 
     for (var i = 0, text = true; i < tokens.length; i++, text = !text) {
@@ -123,6 +121,14 @@
     return newValue.toString();
   };
 
+  for (var i = 1; i < tokens.length; i += 2) {
+    // TODO(jmesserly): not sure if this index is correct. See my comment here:
+    // https://github.com/Polymer/mdv/commit/f1af6fe683fd06eed2a7a7849f01c227db12cda3#L0L1035
+    _bindOrDelegate(replacementBinding, i, model, tokens[i], delegate);
+  }
+
+  replacementBinding.resolve();
+
   node.bind(name, replacementBinding, 'value');
 }
 
@@ -159,7 +165,7 @@
  * [TEXT, (PATH, TEXT)+] if there is at least one mustache.
  */
 List<String> _parseMustacheTokens(String s) {
-  if (s.isEmpty) return;
+  if (s.isEmpty) return null;
 
   var tokens = null;
   var length = s.length;
diff --git a/pkg/mdv/test/analyzer_test.dart b/pkg/mdv/test/analyzer_test.dart
new file mode 100644
index 0000000..68f5e85
--- /dev/null
+++ b/pkg/mdv/test/analyzer_test.dart
@@ -0,0 +1,12 @@
+// Copyright (c) 2013, 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 mdv.test.analyzer_test;
+
+import 'package:mdv/mdv.dart';
+
+// @static-clean
+
+// This test ensures MDV compiles without errors.
+void main() {}
diff --git a/pkg/mdv/test/template_element_test.dart b/pkg/mdv/test/template_element_test.dart
index d4cd501..a424e9e 100644
--- a/pkg/mdv/test/template_element_test.dart
+++ b/pkg/mdv/test/template_element_test.dart
@@ -1566,22 +1566,20 @@
     }
   });
 
-  observeTest('BindShadowDOM bindModel', () {
+  observeTest('BindShadowDOM createInstance', () {
     if (ShadowRoot.supported) {
-      var root = createShadowTestHtml('Hi {{ name }}');
       var model = toSymbolMap({'name': 'Leela'});
-      mdv.bindModel(root, model);
+      var template = new Element.html('<template>Hi {{ name }}</template>');
+      var root = createShadowTestHtml('');
+      root.nodes.add(template.createInstance(model));
+
       performMicrotaskCheckpoint();
       expect(root.text, 'Hi Leela');
-    }
-  });
 
-  observeTest('bindModel to polyfilled shadow root', () {
-    var root = createTestHtml('Hi {{ name }}');
-    var model = toSymbolMap({'name': 'Leela'});
-    mdv.bindModel(root, model);
-    performMicrotaskCheckpoint();
-    expect(root.text, 'Hi Leela');
+      model[sym('name')] = 'Fry';
+      performMicrotaskCheckpoint();
+      expect(root.text, 'Hi Fry');
+    }
   });
 
   observeTest('BindShadowDOM Template Ref', () {
diff --git a/pkg/mutation_observer/README.md b/pkg/mutation_observer/README.md
new file mode 100644
index 0000000..ea4f66a
--- /dev/null
+++ b/pkg/mutation_observer/README.md
@@ -0,0 +1,42 @@
+# Mutation Observers polyfill
+
+Mutation Observers provide a way to react to changes in the DOM. This is needed
+on IE versions 9 and 10, see <http://caniuse.com/mutationobserver>.
+
+## More information
+
+* [API documentation](http://api.dartlang.org/docs/bleeding_edge/dart_html/MutationObserver.html)
+* [Mozilla Developer Network page](https://developer.mozilla.org/en-US/docs/Web/API/MutationObserver)
+* [Specification](https://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#mutation-observers)
+
+## Getting started
+
+Include the polyfill in your HTML `<head>`:
+
+```html
+    <script src="packages/mutation_observer/mutation_observer.js"></script>
+```
+
+You can also use a minified version for deployment:
+
+```html
+    <script src="packages/mutation_observer/mutation_observer.min.js"></script>
+```
+
+## Getting the source code
+
+The source for this package is at:
+<https://code.google.com/p/dart/source/browse/branches/bleeding_edge/dart/pkg/mutation_observer/>
+
+The original source of the JavaScript code is at:
+<https://github.com/Polymer/MutationObservers/tree/master>
+
+## Building
+
+The minified version is produced with:
+
+```bash
+    uglifyjs mutation_observer.js -o mutation_observer.min.js
+```
+
+See <https://github.com/mishoo/UglifyJS2> for usage of UglifyJS.
diff --git a/pkg/mutation_observer/lib/mutation_observer.js b/pkg/mutation_observer/lib/mutation_observer.js
new file mode 100644
index 0000000..cae8709
--- /dev/null
+++ b/pkg/mutation_observer/lib/mutation_observer.js
@@ -0,0 +1,588 @@
+/*
+ * Copyright 2013 The Polymer Authors. All rights reserved.
+ * Use of this source code is goverened by a BSD-style
+ * license that can be found in the LICENSE file.
+ */
+
+// TODO(jmesserly): polyfill does not have feature testing or the definition of
+// SideTable. The extra code is from:
+// https://github.com/Polymer/CustomElements/blob/master/src/MutationObserver.js
+// https://github.com/Polymer/CustomElements/blob/master/src/sidetable.js
+// I also renamed JsMutationObserver -> MutationObserver to correctly interact
+// with dart2js interceptors.
+
+if (!window.MutationObserver && !window.WebKitMutationObserver) {
+
+(function(global) {
+  // SideTable is a weak map where possible. If WeakMap is not available the
+  // association is stored as an expando property.
+  var SideTable;
+  // TODO(arv): WeakMap does not allow for Node etc to be keys in Firefox
+  if (typeof WeakMap !== 'undefined' && navigator.userAgent.indexOf('Firefox/') < 0) {
+    SideTable = WeakMap;
+  } else {
+    (function() {
+      var defineProperty = Object.defineProperty;
+      var hasOwnProperty = Object.hasOwnProperty;
+      var counter = new Date().getTime() % 1e9;
+
+      SideTable = function() {
+        this.name = '__st' + (Math.random() * 1e9 >>> 0) + (counter++ + '__');
+      };
+
+      SideTable.prototype = {
+        set: function(key, value) {
+          defineProperty(key, this.name, {value: value, writable: true});
+        },
+        get: function(key) {
+          return hasOwnProperty.call(key, this.name) ? key[this.name] : undefined;
+        },
+        delete: function(key) {
+          this.set(key, undefined);
+        }
+      }
+    })();
+  }
+
+  var registrationsTable = new SideTable();
+
+  // We use setImmediate or postMessage for our future callback.
+  var setImmediate = window.msSetImmediate;
+
+  // Use post message to emulate setImmediate.
+  if (!setImmediate) {
+    var setImmediateQueue = [];
+    var sentinel = String(Math.random());
+    window.addEventListener('message', function(e) {
+      if (e.data === sentinel) {
+        var queue = setImmediateQueue;
+        setImmediateQueue = [];
+        queue.forEach(function(func) {
+          func();
+        });
+      }
+    });
+    setImmediate = function(func) {
+      setImmediateQueue.push(func);
+      window.postMessage(sentinel, '*');
+    };
+  }
+
+  // This is used to ensure that we never schedule 2 callas to setImmediate
+  var isScheduled = false;
+
+  // Keep track of observers that needs to be notified next time.
+  var scheduledObservers = [];
+
+  /**
+   * Schedules |dispatchCallback| to be called in the future.
+   * @param {MutationObserver} observer
+   */
+  function scheduleCallback(observer) {
+    scheduledObservers.push(observer);
+    if (!isScheduled) {
+      isScheduled = true;
+      setImmediate(dispatchCallbacks);
+    }
+  }
+
+  function wrapIfNeeded(node) {
+    return window.ShadowDOMPolyfill &&
+        window.ShadowDOMPolyfill.wrapIfNeeded(node) ||
+        node;
+  }
+
+  function dispatchCallbacks() {
+    // http://dom.spec.whatwg.org/#mutation-observers
+
+    isScheduled = false; // Used to allow a new setImmediate call above.
+
+    var observers = scheduledObservers;
+    scheduledObservers = [];
+    // Sort observers based on their creation UID (incremental).
+    observers.sort(function(o1, o2) {
+      return o1.uid_ - o2.uid_;
+    });
+
+    var anyNonEmpty = false;
+    observers.forEach(function(observer) {
+
+      // 2.1, 2.2
+      var queue = observer.takeRecords();
+      // 2.3. Remove all transient registered observers whose observer is mo.
+      removeTransientObserversFor(observer);
+
+      // 2.4
+      if (queue.length) {
+        observer.callback_(queue, observer);
+        anyNonEmpty = true;
+      }
+    });
+
+    // 3.
+    if (anyNonEmpty)
+      dispatchCallbacks();
+  }
+
+  function removeTransientObserversFor(observer) {
+    observer.nodes_.forEach(function(node) {
+      var registrations = registrationsTable.get(node);
+      if (!registrations)
+        return;
+      registrations.forEach(function(registration) {
+        if (registration.observer === observer)
+          registration.removeTransientObservers();
+      });
+    });
+  }
+
+  /**
+   * This function is used for the "For each registered observer observer (with
+   * observer's options as options) in target's list of registered observers,
+   * run these substeps:" and the "For each ancestor ancestor of target, and for
+   * each registered observer observer (with options options) in ancestor's list
+   * of registered observers, run these substeps:" part of the algorithms. The
+   * |options.subtree| is checked to ensure that the callback is called
+   * correctly.
+   *
+   * @param {Node} target
+   * @param {function(MutationObserverInit):MutationRecord} callback
+   */
+  function forEachAncestorAndObserverEnqueueRecord(target, callback) {
+    for (var node = target; node; node = node.parentNode) {
+      var registrations = registrationsTable.get(node);
+
+      if (registrations) {
+        for (var j = 0; j < registrations.length; j++) {
+          var registration = registrations[j];
+          var options = registration.options;
+
+          // Only target ignores subtree.
+          if (node !== target && !options.subtree)
+            continue;
+
+          var record = callback(options);
+          if (record)
+            registration.enqueue(record);
+        }
+      }
+    }
+  }
+
+  var uidCounter = 0;
+
+  /**
+   * The class that maps to the DOM MutationObserver interface.
+   * @param {Function} callback.
+   * @constructor
+   */
+  function MutationObserver(callback) {
+    this.callback_ = callback;
+    this.nodes_ = [];
+    this.records_ = [];
+    this.uid_ = ++uidCounter;
+  }
+
+  MutationObserver.prototype = {
+    observe: function(target, options) {
+      target = wrapIfNeeded(target);
+
+      // 1.1
+      if (!options.childList && !options.attributes && !options.characterData ||
+
+          // 1.2
+          options.attributeOldValue && !options.attributes ||
+
+          // 1.3
+          options.attributeFilter && options.attributeFilter.length &&
+              !options.attributes ||
+
+          // 1.4
+          options.characterDataOldValue && !options.characterData) {
+
+        throw new SyntaxError();
+      }
+
+      var registrations = registrationsTable.get(target);
+      if (!registrations)
+        registrationsTable.set(target, registrations = []);
+
+      // 2
+      // If target's list of registered observers already includes a registered
+      // observer associated with the context object, replace that registered
+      // observer's options with options.
+      var registration;
+      for (var i = 0; i < registrations.length; i++) {
+        if (registrations[i].observer === this) {
+          registration = registrations[i];
+          registration.removeListeners();
+          registration.options = options;
+          break;
+        }
+      }
+
+      // 3.
+      // Otherwise, add a new registered observer to target's list of registered
+      // observers with the context object as the observer and options as the
+      // options, and add target to context object's list of nodes on which it
+      // is registered.
+      if (!registration) {
+        registration = new Registration(this, target, options);
+        registrations.push(registration);
+        this.nodes_.push(target);
+      }
+
+      registration.addListeners();
+    },
+
+    disconnect: function() {
+      this.nodes_.forEach(function(node) {
+        var registrations = registrationsTable.get(node);
+        for (var i = 0; i < registrations.length; i++) {
+          var registration = registrations[i];
+          if (registration.observer === this) {
+            registration.removeListeners();
+            registrations.splice(i, 1);
+            // Each node can only have one registered observer associated with
+            // this observer.
+            break;
+          }
+        }
+      }, this);
+      this.records_ = [];
+    },
+
+    takeRecords: function() {
+      var copyOfRecords = this.records_;
+      this.records_ = [];
+      return copyOfRecords;
+    }
+  };
+
+  /**
+   * @param {string} type
+   * @param {Node} target
+   * @constructor
+   */
+  function MutationRecord(type, target) {
+    this.type = type;
+    this.target = target;
+    this.addedNodes = [];
+    this.removedNodes = [];
+    this.previousSibling = null;
+    this.nextSibling = null;
+    this.attributeName = null;
+    this.attributeNamespace = null;
+    this.oldValue = null;
+  }
+
+  // TODO(jmesserly): this fixes the interceptor dispatch on IE.
+  // Not sure why this is necessary.
+  MutationObserver.prototype.constructor = MutationObserver;
+  MutationObserver.name = 'MutationObserver';
+  MutationRecord.prototype.constructor = MutationRecord;
+  MutationRecord.name = 'MutationRecord';
+
+  function copyMutationRecord(original) {
+    var record = new MutationRecord(original.type, original.target);
+    record.addedNodes = original.addedNodes.slice();
+    record.removedNodes = original.removedNodes.slice();
+    record.previousSibling = original.previousSibling;
+    record.nextSibling = original.nextSibling;
+    record.attributeName = original.attributeName;
+    record.attributeNamespace = original.attributeNamespace;
+    record.oldValue = original.oldValue;
+    return record;
+  };
+
+  // We keep track of the two (possibly one) records used in a single mutation.
+  var currentRecord, recordWithOldValue;
+
+  /**
+   * Creates a record without |oldValue| and caches it as |currentRecord| for
+   * later use.
+   * @param {string} oldValue
+   * @return {MutationRecord}
+   */
+  function getRecord(type, target) {
+    return currentRecord = new MutationRecord(type, target);
+  }
+
+  /**
+   * Gets or creates a record with |oldValue| based in the |currentRecord|
+   * @param {string} oldValue
+   * @return {MutationRecord}
+   */
+  function getRecordWithOldValue(oldValue) {
+    if (recordWithOldValue)
+      return recordWithOldValue;
+    recordWithOldValue = copyMutationRecord(currentRecord);
+    recordWithOldValue.oldValue = oldValue;
+    return recordWithOldValue;
+  }
+
+  function clearRecords() {
+    currentRecord = recordWithOldValue = undefined;
+  }
+
+  /**
+   * @param {MutationRecord} record
+   * @return {boolean} Whether the record represents a record from the current
+   * mutation event.
+   */
+  function recordRepresentsCurrentMutation(record) {
+    return record === recordWithOldValue || record === currentRecord;
+  }
+
+  /**
+   * Selects which record, if any, to replace the last record in the queue.
+   * This returns |null| if no record should be replaced.
+   *
+   * @param {MutationRecord} lastRecord
+   * @param {MutationRecord} newRecord
+   * @param {MutationRecord}
+   */
+  function selectRecord(lastRecord, newRecord) {
+    if (lastRecord === newRecord)
+      return lastRecord;
+
+    // Check if the the record we are adding represents the same record. If
+    // so, we keep the one with the oldValue in it.
+    if (recordWithOldValue && recordRepresentsCurrentMutation(lastRecord))
+      return recordWithOldValue;
+
+    return null;
+  }
+
+  /**
+   * Class used to represent a registered observer.
+   * @param {MutationObserver} observer
+   * @param {Node} target
+   * @param {MutationObserverInit} options
+   * @constructor
+   */
+  function Registration(observer, target, options) {
+    this.observer = observer;
+    this.target = target;
+    this.options = options;
+    this.transientObservedNodes = [];
+  }
+
+  Registration.prototype = {
+    enqueue: function(record) {
+      var records = this.observer.records_;
+      var length = records.length;
+
+      // There are cases where we replace the last record with the new record.
+      // For example if the record represents the same mutation we need to use
+      // the one with the oldValue. If we get same record (this can happen as we
+      // walk up the tree) we ignore the new record.
+      if (records.length > 0) {
+        var lastRecord = records[length - 1];
+        var recordToReplaceLast = selectRecord(lastRecord, record);
+        if (recordToReplaceLast) {
+          records[length - 1] = recordToReplaceLast;
+          return;
+        }
+      } else {
+        scheduleCallback(this.observer);
+      }
+
+      records[length] = record;
+    },
+
+    addListeners: function() {
+      this.addListeners_(this.target);
+    },
+
+    addListeners_: function(node) {
+      var options = this.options;
+      if (options.attributes)
+        node.addEventListener('DOMAttrModified', this, true);
+
+      if (options.characterData)
+        node.addEventListener('DOMCharacterDataModified', this, true);
+
+      if (options.childList)
+        node.addEventListener('DOMNodeInserted', this, true);
+
+      if (options.childList || options.subtree)
+        node.addEventListener('DOMNodeRemoved', this, true);
+    },
+
+    removeListeners: function() {
+      this.removeListeners_(this.target);
+    },
+
+    removeListeners_: function(node) {
+      var options = this.options;
+      if (options.attributes)
+        node.removeEventListener('DOMAttrModified', this, true);
+
+      if (options.characterData)
+        node.removeEventListener('DOMCharacterDataModified', this, true);
+
+      if (options.childList)
+        node.removeEventListener('DOMNodeInserted', this, true);
+
+      if (options.childList || options.subtree)
+        node.removeEventListener('DOMNodeRemoved', this, true);
+    },
+
+    /**
+     * Adds a transient observer on node. The transient observer gets removed
+     * next time we deliver the change records.
+     * @param {Node} node
+     */
+    addTransientObserver: function(node) {
+      // Don't add transient observers on the target itself. We already have all
+      // the required listeners set up on the target.
+      if (node === this.target)
+        return;
+
+      this.addListeners_(node);
+      this.transientObservedNodes.push(node);
+      var registrations = registrationsTable.get(node);
+      if (!registrations)
+        registrationsTable.set(node, registrations = []);
+
+      // We know that registrations does not contain this because we already
+      // checked if node === this.target.
+      registrations.push(this);
+    },
+
+    removeTransientObservers: function() {
+      var transientObservedNodes = this.transientObservedNodes;
+      this.transientObservedNodes = [];
+
+      transientObservedNodes.forEach(function(node) {
+        // Transient observers are never added to the target.
+        this.removeListeners_(node);
+
+        var registrations = registrationsTable.get(node);
+        for (var i = 0; i < registrations.length; i++) {
+          if (registrations[i] === this) {
+            registrations.splice(i, 1);
+            // Each node can only have one registered observer associated with
+            // this observer.
+            break;
+          }
+        }
+      }, this);
+    },
+
+    handleEvent: function(e) {
+      // Stop propagation since we are managing the propagation manually.
+      // This means that other mutation events on the page will not work
+      // correctly but that is by design.
+      e.stopImmediatePropagation();
+
+      switch (e.type) {
+        case 'DOMAttrModified':
+          // http://dom.spec.whatwg.org/#concept-mo-queue-attributes
+
+          var name = e.attrName;
+          var namespace = e.relatedNode.namespaceURI;
+          var target = e.target;
+
+          // 1.
+          var record = new getRecord('attributes', target);
+          record.attributeName = name;
+          record.attributeNamespace = namespace;
+
+          // 2.
+          var oldValue =
+              e.attrChange === MutationEvent.ADDITION ? null : e.prevValue;
+
+          forEachAncestorAndObserverEnqueueRecord(target, function(options) {
+            // 3.1, 4.2
+            if (!options.attributes)
+              return;
+
+            // 3.2, 4.3
+            if (options.attributeFilter && options.attributeFilter.length &&
+                options.attributeFilter.indexOf(name) === -1 &&
+                options.attributeFilter.indexOf(namespace) === -1) {
+              return;
+            }
+            // 3.3, 4.4
+            if (options.attributeOldValue)
+              return getRecordWithOldValue(oldValue);
+
+            // 3.4, 4.5
+            return record;
+          });
+
+          break;
+
+        case 'DOMCharacterDataModified':
+          // http://dom.spec.whatwg.org/#concept-mo-queue-characterdata
+          var target = e.target;
+
+          // 1.
+          var record = getRecord('characterData', target);
+
+          // 2.
+          var oldValue = e.prevValue;
+
+
+          forEachAncestorAndObserverEnqueueRecord(target, function(options) {
+            // 3.1, 4.2
+            if (!options.characterData)
+              return;
+
+            // 3.2, 4.3
+            if (options.characterDataOldValue)
+              return getRecordWithOldValue(oldValue);
+
+            // 3.3, 4.4
+            return record;
+          });
+
+          break;
+
+        case 'DOMNodeRemoved':
+          this.addTransientObserver(e.target);
+          // Fall through.
+        case 'DOMNodeInserted':
+          // http://dom.spec.whatwg.org/#concept-mo-queue-childlist
+          var target = e.relatedNode;
+          var changedNode = e.target;
+          var addedNodes, removedNodes;
+          if (e.type === 'DOMNodeInserted') {
+            addedNodes = [changedNode];
+            removedNodes = [];
+          } else {
+
+            addedNodes = [];
+            removedNodes = [changedNode];
+          }
+          var previousSibling = changedNode.previousSibling;
+          var nextSibling = changedNode.nextSibling;
+
+          // 1.
+          var record = getRecord('childList', target);
+          record.addedNodes = addedNodes;
+          record.removedNodes = removedNodes;
+          record.previousSibling = previousSibling;
+          record.nextSibling = nextSibling;
+
+          forEachAncestorAndObserverEnqueueRecord(target, function(options) {
+            // 2.1, 3.2
+            if (!options.childList)
+              return;
+
+            // 2.2, 3.3
+            return record;
+          });
+
+      }
+
+      clearRecords();
+    }
+  };
+
+  global.MutationObserver = MutationObserver;
+})(window);
+
+}
diff --git a/pkg/mutation_observer/lib/mutation_observer.min.js b/pkg/mutation_observer/lib/mutation_observer.min.js
new file mode 100644
index 0000000..1c25e0b
--- /dev/null
+++ b/pkg/mutation_observer/lib/mutation_observer.min.js
@@ -0,0 +1 @@
+if(!window.MutationObserver&&!window.WebKitMutationObserver){!function(global){var SideTable;if(typeof WeakMap!=="undefined"&&navigator.userAgent.indexOf("Firefox/")<0){SideTable=WeakMap}else{!function(){var defineProperty=Object.defineProperty;var hasOwnProperty=Object.hasOwnProperty;var counter=(new Date).getTime()%1e9;SideTable=function(){this.name="__st"+(Math.random()*1e9>>>0)+(counter++ +"__")};SideTable.prototype={set:function(key,value){defineProperty(key,this.name,{value:value,writable:true})},get:function(key){return hasOwnProperty.call(key,this.name)?key[this.name]:undefined},"delete":function(key){this.set(key,undefined)}}}()}var registrationsTable=new SideTable;var setImmediate=window.msSetImmediate;if(!setImmediate){var setImmediateQueue=[];var sentinel=String(Math.random());window.addEventListener("message",function(e){if(e.data===sentinel){var queue=setImmediateQueue;setImmediateQueue=[];queue.forEach(function(func){func()})}});setImmediate=function(func){setImmediateQueue.push(func);window.postMessage(sentinel,"*")}}var isScheduled=false;var scheduledObservers=[];function scheduleCallback(observer){scheduledObservers.push(observer);if(!isScheduled){isScheduled=true;setImmediate(dispatchCallbacks)}}function wrapIfNeeded(node){return window.ShadowDOMPolyfill&&window.ShadowDOMPolyfill.wrapIfNeeded(node)||node}function dispatchCallbacks(){isScheduled=false;var observers=scheduledObservers;scheduledObservers=[];observers.sort(function(o1,o2){return o1.uid_-o2.uid_});var anyNonEmpty=false;observers.forEach(function(observer){var queue=observer.takeRecords();removeTransientObserversFor(observer);if(queue.length){observer.callback_(queue,observer);anyNonEmpty=true}});if(anyNonEmpty)dispatchCallbacks()}function removeTransientObserversFor(observer){observer.nodes_.forEach(function(node){var registrations=registrationsTable.get(node);if(!registrations)return;registrations.forEach(function(registration){if(registration.observer===observer)registration.removeTransientObservers()})})}function forEachAncestorAndObserverEnqueueRecord(target,callback){for(var node=target;node;node=node.parentNode){var registrations=registrationsTable.get(node);if(registrations){for(var j=0;j<registrations.length;j++){var registration=registrations[j];var options=registration.options;if(node!==target&&!options.subtree)continue;var record=callback(options);if(record)registration.enqueue(record)}}}}var uidCounter=0;function MutationObserver(callback){this.callback_=callback;this.nodes_=[];this.records_=[];this.uid_=++uidCounter}MutationObserver.prototype={observe:function(target,options){target=wrapIfNeeded(target);if(!options.childList&&!options.attributes&&!options.characterData||options.attributeOldValue&&!options.attributes||options.attributeFilter&&options.attributeFilter.length&&!options.attributes||options.characterDataOldValue&&!options.characterData){throw new SyntaxError}var registrations=registrationsTable.get(target);if(!registrations)registrationsTable.set(target,registrations=[]);var registration;for(var i=0;i<registrations.length;i++){if(registrations[i].observer===this){registration=registrations[i];registration.removeListeners();registration.options=options;break}}if(!registration){registration=new Registration(this,target,options);registrations.push(registration);this.nodes_.push(target)}registration.addListeners()},disconnect:function(){this.nodes_.forEach(function(node){var registrations=registrationsTable.get(node);for(var i=0;i<registrations.length;i++){var registration=registrations[i];if(registration.observer===this){registration.removeListeners();registrations.splice(i,1);break}}},this);this.records_=[]},takeRecords:function(){var copyOfRecords=this.records_;this.records_=[];return copyOfRecords}};function MutationRecord(type,target){this.type=type;this.target=target;this.addedNodes=[];this.removedNodes=[];this.previousSibling=null;this.nextSibling=null;this.attributeName=null;this.attributeNamespace=null;this.oldValue=null}MutationObserver.prototype.constructor=MutationObserver;MutationObserver.name="MutationObserver";MutationRecord.prototype.constructor=MutationRecord;MutationRecord.name="MutationRecord";function copyMutationRecord(original){var record=new MutationRecord(original.type,original.target);record.addedNodes=original.addedNodes.slice();record.removedNodes=original.removedNodes.slice();record.previousSibling=original.previousSibling;record.nextSibling=original.nextSibling;record.attributeName=original.attributeName;record.attributeNamespace=original.attributeNamespace;record.oldValue=original.oldValue;return record}var currentRecord,recordWithOldValue;function getRecord(type,target){return currentRecord=new MutationRecord(type,target)}function getRecordWithOldValue(oldValue){if(recordWithOldValue)return recordWithOldValue;recordWithOldValue=copyMutationRecord(currentRecord);recordWithOldValue.oldValue=oldValue;return recordWithOldValue}function clearRecords(){currentRecord=recordWithOldValue=undefined}function recordRepresentsCurrentMutation(record){return record===recordWithOldValue||record===currentRecord}function selectRecord(lastRecord,newRecord){if(lastRecord===newRecord)return lastRecord;if(recordWithOldValue&&recordRepresentsCurrentMutation(lastRecord))return recordWithOldValue;return null}function Registration(observer,target,options){this.observer=observer;this.target=target;this.options=options;this.transientObservedNodes=[]}Registration.prototype={enqueue:function(record){var records=this.observer.records_;var length=records.length;if(records.length>0){var lastRecord=records[length-1];var recordToReplaceLast=selectRecord(lastRecord,record);if(recordToReplaceLast){records[length-1]=recordToReplaceLast;return}}else{scheduleCallback(this.observer)}records[length]=record},addListeners:function(){this.addListeners_(this.target)},addListeners_:function(node){var options=this.options;if(options.attributes)node.addEventListener("DOMAttrModified",this,true);if(options.characterData)node.addEventListener("DOMCharacterDataModified",this,true);if(options.childList)node.addEventListener("DOMNodeInserted",this,true);if(options.childList||options.subtree)node.addEventListener("DOMNodeRemoved",this,true)},removeListeners:function(){this.removeListeners_(this.target)},removeListeners_:function(node){var options=this.options;if(options.attributes)node.removeEventListener("DOMAttrModified",this,true);if(options.characterData)node.removeEventListener("DOMCharacterDataModified",this,true);if(options.childList)node.removeEventListener("DOMNodeInserted",this,true);if(options.childList||options.subtree)node.removeEventListener("DOMNodeRemoved",this,true)},addTransientObserver:function(node){if(node===this.target)return;this.addListeners_(node);this.transientObservedNodes.push(node);var registrations=registrationsTable.get(node);if(!registrations)registrationsTable.set(node,registrations=[]);registrations.push(this)},removeTransientObservers:function(){var transientObservedNodes=this.transientObservedNodes;this.transientObservedNodes=[];transientObservedNodes.forEach(function(node){this.removeListeners_(node);var registrations=registrationsTable.get(node);for(var i=0;i<registrations.length;i++){if(registrations[i]===this){registrations.splice(i,1);break}}},this)},handleEvent:function(e){e.stopImmediatePropagation();switch(e.type){case"DOMAttrModified":var name=e.attrName;var namespace=e.relatedNode.namespaceURI;var target=e.target;var record=new getRecord("attributes",target);record.attributeName=name;record.attributeNamespace=namespace;var oldValue=e.attrChange===MutationEvent.ADDITION?null:e.prevValue;forEachAncestorAndObserverEnqueueRecord(target,function(options){if(!options.attributes)return;if(options.attributeFilter&&options.attributeFilter.length&&options.attributeFilter.indexOf(name)===-1&&options.attributeFilter.indexOf(namespace)===-1){return}if(options.attributeOldValue)return getRecordWithOldValue(oldValue);return record});break;case"DOMCharacterDataModified":var target=e.target;var record=getRecord("characterData",target);var oldValue=e.prevValue;forEachAncestorAndObserverEnqueueRecord(target,function(options){if(!options.characterData)return;if(options.characterDataOldValue)return getRecordWithOldValue(oldValue);return record});break;case"DOMNodeRemoved":this.addTransientObserver(e.target);case"DOMNodeInserted":var target=e.relatedNode;var changedNode=e.target;var addedNodes,removedNodes;if(e.type==="DOMNodeInserted"){addedNodes=[changedNode];removedNodes=[]}else{addedNodes=[];removedNodes=[changedNode]}var previousSibling=changedNode.previousSibling;var nextSibling=changedNode.nextSibling;var record=getRecord("childList",target);record.addedNodes=addedNodes;record.removedNodes=removedNodes;record.previousSibling=previousSibling;record.nextSibling=nextSibling;forEachAncestorAndObserverEnqueueRecord(target,function(options){if(!options.childList)return;return record})}clearRecords()}};global.MutationObserver=MutationObserver}(window)}
\ No newline at end of file
diff --git a/pkg/mutation_observer/pubspec.yaml b/pkg/mutation_observer/pubspec.yaml
new file mode 100644
index 0000000..cafca55
--- /dev/null
+++ b/pkg/mutation_observer/pubspec.yaml
@@ -0,0 +1,8 @@
+name: mutation_observer
+author: "Web UI Team <web-ui-dev@dartlang.org>"
+homepage: https://code.google.com/p/dart/source/browse/branches/bleeding_edge/dart/pkg/mutation_observer/
+documentation: https://api.dartlang.org/docs/releases/latest/dart_html/MutationObserver.html
+description: >
+  Mutation Observers provide a way to react to changes in the DOM.
+dev_dependencies:
+  unittest: any
diff --git a/pkg/mutation_observer/test/mutation_observer_test.dart b/pkg/mutation_observer/test/mutation_observer_test.dart
new file mode 100644
index 0000000..c4c84e3e4
--- /dev/null
+++ b/pkg/mutation_observer/test/mutation_observer_test.dart
@@ -0,0 +1,114 @@
+// Copyright (c) 2013, 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 mutation_observer_test;
+
+import 'dart:html';
+import 'package:unittest/unittest.dart';
+import 'package:unittest/html_config.dart';
+
+main() {
+  useHtmlConfiguration();
+
+  // Load the MutationObserver polyfill.
+  HttpRequest.getString('/root_dart/pkg/mutation_observer/lib/'
+      'mutation_observer.min.js').then((code) {
+
+    // Force MutationObserver polyfill to be used so we can test it, even in
+    // browsers with native support.
+    document.head.children.add(new ScriptElement()
+        ..text = 'window.MutationObserver = void 0;'
+                 'window.WebKitMutationObserver = void 0;'
+                 '$code');
+
+    testMutationObserver();
+  });
+}
+
+/**
+ * Test suite for Mutation Observers. This is just a small set of sanity
+ * checks, not a complete test suite.
+ */
+testMutationObserver() {
+  group('supported', () {
+    test('supported', () {
+      expect(MutationObserver.supported, true, reason: 'polyfill loaded.');
+    });
+  });
+
+  group('childList', () {
+    mutationCallback(count, expectation) {
+      var done = false;
+      var nodes = [];
+
+      callback(mutations, observer) {
+        for (MutationRecord mutation in mutations) {
+          for (Node node in mutation.addedNodes) {
+            nodes.add(node);
+          }
+        }
+        if (nodes.length >= count) {
+          done = true;
+          expect(nodes.length, count);
+          expect(nodes, expectation);
+        }
+      }
+
+      return expectAsyncUntil2(callback, () => done);
+    }
+
+    test('empty options is syntax error', () {
+      var mutationObserver = new MutationObserver(
+          (mutations, observer) { expect(false, isTrue,
+              reason: 'Should not be reached'); });
+      expect(() { mutationObserver.observe(document, {}); },
+             throws);
+    });
+
+    test('direct-parallel options-named', () {
+      var container = new DivElement();
+      var div1 = new DivElement();
+      var div2 = new DivElement();
+      var mutationObserver = new MutationObserver(
+          mutationCallback(2, orderedEquals([div1, div2])));
+      mutationObserver.observe(container, childList: true);
+
+      container.append(div1);
+      container.append(div2);
+    });
+
+    test('direct-nested options-named', () {
+      var container = new DivElement();
+      var div1 = new DivElement();
+      var div2 = new DivElement();
+      var mutationObserver =
+          new MutationObserver(mutationCallback(1, orderedEquals([div1])));
+      mutationObserver.observe(container, childList: true);
+
+      container.append(div1);
+      div1.append(div2);
+    });
+
+    test('subtree options-named', () {
+      var container = new DivElement();
+      var div1 = new DivElement();
+      var div2 = new DivElement();
+      var mutationObserver = new MutationObserver(
+          mutationCallback(2, orderedEquals([div1, div2])));
+      mutationObserver.observe(container, childList: true, subtree: true);
+
+      container.append(div1);
+      div1.append(div2);
+    });
+
+    test('mutation event', () {
+      var event = new MutationEvent('something', prevValue: 'prev',
+          newValue: 'new', attrName: 'attr');
+      expect(event is MutationEvent, isTrue);
+      expect(event.prevValue, 'prev');
+      expect(event.newValue, 'new');
+      expect(event.attrName, 'attr');
+    });
+  });
+}
diff --git a/pkg/observe/lib/src/compound_binding.dart b/pkg/observe/lib/src/compound_binding.dart
index 625c82c..94db67a8 100644
--- a/pkg/observe/lib/src/compound_binding.dart
+++ b/pkg/observe/lib/src/compound_binding.dart
@@ -34,9 +34,22 @@
   // use integers.
   Map<dynamic, StreamSubscription> _observers = new Map();
   Map _values = new Map();
-  bool _scheduled = false;
   Object _value;
 
+  /**
+   * True if [resolve] is scheduled. You can set this to true if you plan to
+   * call [resolve] manually, avoiding the need for scheduling an asynchronous
+   * resolve.
+   */
+  // TODO(jmesserly): I don't like having this public, is the optimization
+  // really needed? "runAsync" in Dart should be pretty cheap.
+  bool scheduled = false;
+
+  /**
+   * Creates a new CompoundBinding, optionally proving the [combinator] function
+   * for computing the value. You can also set [schedule] to true if you plan
+   * to invoke [resolve] manually after initial construction of the binding.
+   */
   CompoundBinding([CompoundBindingCombinator combinator]) {
     // TODO(jmesserly): this is a tweak to the original code, it seemed to me
     // that passing the combinator to the constructor should be equivalent to
@@ -86,14 +99,14 @@
   // TODO(rafaelw): Consider having a seperate ChangeSummary for
   // CompoundBindings so to excess dirtyChecks.
   void _scheduleResolve() {
-    if (_scheduled) return;
-    _scheduled = true;
+    if (scheduled) return;
+    scheduled = true;
     runAsync(resolve);
   }
 
   void resolve() {
     if (_observers.isEmpty) return;
-    _scheduled = false;
+    scheduled = false;
 
     if (_combinator == null) {
       throw new StateError(
diff --git a/pkg/observe/lib/src/observable.dart b/pkg/observe/lib/src/observable.dart
index a49f8f1..7610a0f 100644
--- a/pkg/observe/lib/src/observable.dart
+++ b/pkg/observe/lib/src/observable.dart
@@ -63,6 +63,12 @@
   void notifyChange(ChangeRecord record);
 
   /**
+   * True if this object has any observers, and should call
+   * [notifyChange] for changes.
+   */
+  bool get hasObservers;
+
+  /**
    * Performs dirty checking of objects that inherit from [ObservableMixin].
    * This scans all observed objects using mirrors and determines if any fields
    * have changed. If they have, it delivers the changes for the object.
@@ -99,10 +105,6 @@
     return _changes.stream;
   }
 
-  /**
-   * True if this object has any observers, and should call
-   * [notifyPropertyChange] for changes.
-   */
   bool get hasObservers => _changes != null && _changes.hasListener;
 
   void _observed() {
diff --git a/pkg/observe/lib/src/observable_map.dart b/pkg/observe/lib/src/observable_map.dart
index 2cd64d5..621c86f 100644
--- a/pkg/observe/lib/src/observable_map.dart
+++ b/pkg/observe/lib/src/observable_map.dart
@@ -67,9 +67,7 @@
    * you should use [toObservable].
    */
   factory ObservableMap.from(Map<K, V> other) {
-    var result = new ObservableMap<K, V>._createFromType(other);
-    other.forEach((key, value) { result[key] = value; });
-    return result;
+    return new ObservableMap<K, V>._createFromType(other)..addAll(other);
   }
 
   factory ObservableMap._createFromType(Map<K, V> other) {
@@ -114,6 +112,10 @@
     }
   }
 
+  void addAll(Map<K, V> other) {
+    other.forEach((K key, V value) { this[key] = value; });
+  }
+
   V putIfAbsent(K key, V ifAbsent()) {
     int len = _map.length;
     V result = _map.putIfAbsent(key, ifAbsent);
diff --git a/pkg/observe/test/list_change_test.dart b/pkg/observe/test/list_change_test.dart
index ae433d1..8f44357 100644
--- a/pkg/observe/test/list_change_test.dart
+++ b/pkg/observe/test/list_change_test.dart
@@ -76,7 +76,7 @@
       }
 
       // Note: compare strings for easier debugging.
-      expect('$copy', '$model', reason: '!!! summary $summary');
+      expect('$copy', '$model', reason: 'summary $summary');
     }
 
     observeTest('Contained', () {
diff --git a/pkg/observe/test/observe_test.dart b/pkg/observe/test/observe_test.dart
index c898e43..8b07d4b 100644
--- a/pkg/observe/test/observe_test.dart
+++ b/pkg/observe/test/observe_test.dart
@@ -9,6 +9,9 @@
 import 'package:unittest/unittest.dart';
 import 'observe_test_utils.dart';
 
+// Note: this ensures we run the dartanalyzer on the @observe package.
+// @static-clean
+
 const _VALUE = const Symbol('value');
 
 main() {
diff --git a/pkg/path/lib/path.dart b/pkg/path/lib/path.dart
index 95bc90d..eb126d5 100644
--- a/pkg/path/lib/path.dart
+++ b/pkg/path/lib/path.dart
@@ -55,10 +55,17 @@
 /// functional interface and not require users to create one.
 final _builder = new Builder();
 
-/**
- * Inserts [length] elements in front of the [list] and fills them with the
- * [fillValue].
- */
+/// A default builder for manipulating POSIX paths.
+final posix = new Builder(style: Style.posix);
+
+/// A default builder for manipulating Windows paths.
+final windows = new Builder(style: Style.windows);
+
+/// A default builder for manipulating URLs.
+final url = new Builder(style: Style.url);
+
+/// Inserts [length] elements in front of the [list] and fills them with the
+/// [fillValue].
 void _growListFront(List list, int length, fillValue) =>
   list.insertAll(0, new List.filled(length, fillValue));
 
@@ -376,25 +383,22 @@
   /// Creates a new path builder for the given style and root directory.
   ///
   /// If [style] is omitted, it uses the host operating system's path style. If
-  /// [root] is omitted, it defaults to the current working directory. If [root]
-  /// is relative, it is considered relative to the current working directory.
+  /// only [root] is omitted, it defaults ".". If *both* [style] and [root] are
+  /// omitted, [root] defaults to the current working directory.
   ///
   /// On the browser, the path style is [Style.url]. In Dartium, [root] defaults
   /// to the current URL. When using dart2js, it currently defaults to `.` due
   /// to technical constraints.
   factory Builder({Style style, String root}) {
-    if (style == null) {
-      if (_io == null) {
-        style = Style.url;
-      } else if (_io.classes[const Symbol('Platform')]
-          .getField(const Symbol('operatingSystem')).reflectee == 'windows') {
-        style = Style.windows;
+    if (root == null) {
+      if (style == null) {
+        root = current;
       } else {
-        style = Style.posix;
+        root = ".";
       }
     }
 
-    if (root == null) root = current;
+    if (style == null) style = Style.platform;
 
     return new Builder._(style, root);
   }
@@ -855,6 +859,24 @@
   /// `file://`) or with "/".
   static final url = new _UrlStyle();
 
+  /// The style of the host platform.
+  ///
+  /// When running on the command line, this will be [windows] or [posix] based
+  /// on the host operating system. On a browser, this will be [url].
+  static final platform = _getPlatformStyle();
+
+  /// Gets the type of the host platform.
+  static Style _getPlatformStyle() {
+    if (_io == null) return Style.url;
+
+    if (_io.classes[const Symbol('Platform')]
+        .getField(const Symbol('operatingSystem')).reflectee == 'windows') {
+      return Style.windows;
+    }
+
+    return Style.posix;
+  }
+
   /// The name of this path style. Will be "posix" or "windows".
   String get name;
 
diff --git a/pkg/path/test/browser_test.dart b/pkg/path/test/browser_test.dart
index 2a830c7..0725646 100644
--- a/pkg/path/test/browser_test.dart
+++ b/pkg/path/test/browser_test.dart
@@ -12,15 +12,24 @@
   useHtmlConfiguration();
 
   group('new Builder()', () {
-    test('uses the current working directory if root is omitted', () {
+    test('uses the window location if root and style are omitted', () {
       var builder = new path.Builder();
       expect(builder.root, window.location.href);
     });
 
-    test('uses URL if style is omitted', () {
-      var builder = new path.Builder();
-      expect(builder.style, path.Style.url);
+    test('uses "." if root is omitted', () {
+      var builder = new path.Builder(style: path.Style.platform);
+      expect(builder.root, ".");
     });
+
+    test('uses the host platform if style is omitted', () {
+      var builder = new path.Builder();
+      expect(builder.style, path.Style.platform);
+    });
+  });
+
+  test('Style.platform is url', () {
+    expect(path.Style.platform, path.Style.url);
   });
 
   test('current', () {
diff --git a/pkg/path/test/io_test.dart b/pkg/path/test/io_test.dart
index fc29ced..6651249 100644
--- a/pkg/path/test/io_test.dart
+++ b/pkg/path/test/io_test.dart
@@ -9,19 +9,28 @@
 
 main() {
   group('new Builder()', () {
-    test('uses the current working directory if root is omitted', () {
+    test('uses the current directory if root and style are omitted', () {
       var builder = new path.Builder();
       expect(builder.root, io.Directory.current.path);
     });
 
-    test('uses the host OS if style is omitted', () {
-      var builder = new path.Builder();
-      if (io.Platform.operatingSystem == 'windows') {
-        expect(builder.style, path.Style.windows);
-      } else {
-        expect(builder.style, path.Style.posix);
-      }
+    test('uses "." if root is omitted', () {
+      var builder = new path.Builder(style: path.Style.platform);
+      expect(builder.root, ".");
     });
+
+    test('uses the host platform if style is omitted', () {
+      var builder = new path.Builder();
+      expect(builder.style, path.Style.platform);
+    });
+  });
+
+  test('Style.platform returns the host platform style', () {
+    if (io.Platform.operatingSystem == 'windows') {
+      expect(path.Style.platform, path.Style.windows);
+    } else {
+      expect(path.Style.platform, path.Style.posix);
+    }
   });
 
   test('current', () {
diff --git a/pkg/path/test/path_test.dart b/pkg/path/test/path_test.dart
index ef3cf21e..d6c2f34 100644
--- a/pkg/path/test/path_test.dart
+++ b/pkg/path/test/path_test.dart
@@ -34,4 +34,19 @@
       expect(builder.style, path.Style.windows);
     });
   });
+
+  test('posix is a default Builder for the POSIX style', () {
+    expect(path.posix.style, path.Style.posix);
+    expect(path.posix.root, ".");
+  });
+
+  test('windows is a default Builder for the Windows style', () {
+    expect(path.windows.style, path.Style.windows);
+    expect(path.windows.root, ".");
+  });
+
+  test('url is a default Builder for the URL style', () {
+    expect(path.url.style, path.Style.url);
+    expect(path.url.root, ".");
+  });
 }
diff --git a/pkg/pkg.status b/pkg/pkg.status
index c8d7b4d..4a3e6b8 100644
--- a/pkg/pkg.status
+++ b/pkg/pkg.status
@@ -17,15 +17,10 @@
 
 [ $runtime == vm ]
 watcher/test/no_subscription_test: Pass, Fail # Issue 12107
-
-[ $compiler == none && $runtime == drt && $mode == debug]
-mdv/test/custom_element_bindings_test: Fail # Issue 11657
-
-[ $compiler == dart2js && $runtime == ff ]
-unittest/test/unittest_test: Pass, Timeout # http://dartbug.com/11473
+watcher/test/directory_watcher_test: Pass, Fail # Issue 12107
 
 [ $runtime == d8 || $runtime == jsshell ]
-unittest/test/unittest_test: Pass, Fail # http://dartbug.com/10109
+unittest/test/unittest_nested_groups_setup_teardown_test: Pass, Fail # http://dartbug.com/10109
 stack_trace/test/vm_test: Fail, OK # VM-specific traces
 sequence_zip/test/stream_test: Fail, OK # Timers are not supported.
 
@@ -72,14 +67,16 @@
 unittest/test/mock_stepwise_negative_test: Skip
 
 [ $compiler == dart2js && $csp ]
-unittest/test/unittest_test: Pass, Crash # Issue 10935
+unittest/test/mirror_matchers_test: Skip # Issue 12151
 observe/test/observe_test: Fail # Issue 11970
 observe/test/path_observer_test: Fail  # Issue 11970
 mdv/test/binding_syntax_test: Fail # Issue 11970
-
 serialization/test/serialization_test: Fail # Issue 6490
 serialization/test/no_library_test: Fail # Issue 6490
 
+# This test cannot run under CSP because it is injecting a JavaScript polyfill
+mutation_observer: Skip
+
 [ $compiler == dart2js && $minified ]
 # The unminified unittest tests test that the real names of Dart types are
 # printed. Minified versions of these tests exist that test the behavior when
@@ -140,6 +137,7 @@
 scheduled_test/test/scheduled_test/wrap_async_test: Fail # http://dartbug.com/8440
 scheduled_test/test/scheduled_test/wrap_future_test: Fail # http://dartbug.com/8440
 
+*/test/analyzer_test: Skip  # No need to run analysis tests on browser bots
 
 [ $runtime == safari]
  # Bug in JSC: the test only passes when being debugged.
@@ -170,10 +168,13 @@
 # test on Dartium, which requires all tests to have a library.
 [ $runtime == dartium || $runtime == drt ]
 serialization/test/no_library_test: Skip # Expected Failure
+mdv/test/template_element_test: Pass, Fail # Issue 12177
 
-# Skip mdv tests on command line VM, they only run in the browser.
+# Skip tests on the VM if the package depends on dart:html
 [ $runtime == vm ]
+custom_element: Skip
 mdv: Skip
+mutation_observer: Skip
 
 [ $runtime == safari || $runtime == chrome || $runtime == ie9 || $runtime == ff || $runtime == dartium || $runtime == drt ]
 docgen/test/single_library_test: Skip # Uses dart:io
diff --git a/pkg/unittest/lib/interactive_html_config.dart b/pkg/unittest/lib/interactive_html_config.dart
index b962e1e..4f5dccd 100644
--- a/pkg/unittest/lib/interactive_html_config.dart
+++ b/pkg/unittest/lib/interactive_html_config.dart
@@ -19,6 +19,7 @@
 
 import 'dart:html';
 import 'dart:async';
+import 'dart:json' as json;
 import 'dart:math';
 
 import 'package:stack_trace/stack_trace.dart';
@@ -165,7 +166,7 @@
     int elapsed = end.difference(_testStarts[testCase.id]).inMilliseconds;
     if (testCase.stackTrace != null) {
       var message = json.stringify(testCase.stackTrace.frames.map((frame) {
-        return <String>{
+        return <String, dynamic>{
           "uri": frame.uri.toString(),
           "line": frame.line,
           "column": frame.column,
diff --git a/pkg/unittest/lib/mirror_matchers.dart b/pkg/unittest/lib/mirror_matchers.dart
new file mode 100644
index 0000000..7e91529
--- /dev/null
+++ b/pkg/unittest/lib/mirror_matchers.dart
@@ -0,0 +1,92 @@
+// Copyright (c) 2013, 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.
+/**
+ * The mirror matchers library provides some additional matchers that
+ * make use of dart:mirrors.
+ *
+ * ## Installing ##
+ *
+ * Use [pub][] to install this package. Add the following to your `pubspec.yaml`
+ * file.
+ *
+ *     dependencies:
+ *       unittest: any
+ *
+ * Then run `pub install`.
+ *
+ * Import this into your Dart code with:
+ *
+ *     import 'package:unittest/mirror_matchers.dart';
+ *
+ * For more information, see the [unittest package on pub.dartlang.org].
+ * (http://pub.dartlang.org/packages/unittest).
+ *
+ * [pub]: http://pub.dartlang.org
+ * [pkg]: http://pub.dartlang.org/packages/mirror_matchers
+ */
+library mirror_matchers;
+
+import 'dart:async';
+import 'dart:mirrors';
+import 'package:meta/meta.dart';
+
+import 'matcher.dart';
+
+/**
+ * Returns a matcher that checks if a class instance has a property
+ * with name [name], and optionally, if that property in turn satisfies
+ * a [matcher].
+ */
+Matcher hasProperty(String name, [matcher]) =>
+  new _HasProperty(name, matcher == null ? null : wrapMatcher(matcher));
+
+class _HasProperty extends Matcher {
+  final String _name;
+  final Matcher _matcher;
+
+  const _HasProperty(this._name, [this._matcher]);
+
+  bool matches(item, Map matchState) {
+    var mirror = reflect(item);
+    var classMirror = mirror.type;
+    var symbol = new Symbol(_name);
+    if (!classMirror.getters.containsKey(symbol)) {
+      addStateInfo(matchState, {'reason': 'has no property named "$_name"'});
+      return false;
+    }
+    if (_matcher == null) return true;
+    var result = mirror.getField(symbol);
+    var resultMatches = _matcher.matches(result.reflectee, matchState);
+    if (!resultMatches) {
+      addStateInfo(matchState, {'value': result.reflectee});
+    }
+    return resultMatches;
+  }
+
+  Description describe(Description description) {
+    description.add('has property "$_name"');
+    if (_matcher != null) {
+      description.add(' which matches ').addDescriptionOf(_matcher);
+    }
+    return description;
+  }
+
+  Description describeMismatch(item, Description mismatchDescription,
+                               Map matchState, bool verbose) {
+    var reason = matchState == null ? null : matchState['reason'];
+    if (reason != null) {
+      mismatchDescription.add(reason);
+    } else {
+      mismatchDescription.add('has property "$_name" with value ').
+        addDescriptionOf(matchState['value']);
+      var innerDescription = new StringDescription();
+      _matcher.describeMismatch(matchState['value'], innerDescription,
+          matchState['state'], verbose);
+      if (innerDescription.length > 0) {
+        mismatchDescription.add(' which ').add(innerDescription.toString());
+      }
+    }
+    return mismatchDescription;
+  }
+}
diff --git a/pkg/unittest/lib/src/core_matchers.dart b/pkg/unittest/lib/src/core_matchers.dart
index 3d10f6d..b9bde13 100644
--- a/pkg/unittest/lib/src/core_matchers.dart
+++ b/pkg/unittest/lib/src/core_matchers.dart
@@ -849,13 +849,8 @@
  * have a Widget class where each Widget has a price; we could make a
  * [CustomMatcher] that can make assertions about prices with:
  *
-<<<<<<< .mine
  *     class HasPrice extends CustomMatcher {
  *       const HasPrice(matcher) :
-=======
- *     class HasPrice extends CustomMatcher {
- *       HasPrice(matcher) :
->>>>>>> .r25321
  *           super("Widget with price that is", "price", matcher);
  *       featureValueOf(actual) => actual.price;
  *     }
@@ -898,4 +893,3 @@
     return mismatchDescription;
   }
 }
-
diff --git a/pkg/unittest/pubspec.yaml b/pkg/unittest/pubspec.yaml
index ecaba6d..aa32b1d 100644
--- a/pkg/unittest/pubspec.yaml
+++ b/pkg/unittest/pubspec.yaml
@@ -1,9 +1,9 @@
 name: unittest
-author: "Dart Team <misc@dartlang.org>"
+author: Dart Team <misc@dartlang.org>
+description: A library for writing dart unit tests.
 homepage: http://www.dartlang.org
 documentation: http://api.dartlang.org/docs/pkg/unittest
-description: >
- A library for writing dart unit tests.
 dependencies:
+  json: any
   meta: any
   stack_trace: any
diff --git a/pkg/unittest/test/matchers_test.dart b/pkg/unittest/test/matchers_test.dart
index 6f4338c..b78ee47 100644
--- a/pkg/unittest/test/matchers_test.dart
+++ b/pkg/unittest/test/matchers_test.dart
@@ -203,7 +203,7 @@
 
     test('isZero', () {
       shouldPass(0, isZero);
-      shouldFail(1, isZero, 
+      shouldFail(1, isZero,
           "Expected: a value equal to <0> "
           "Actual: <1> "
           "Which: is not a value equal to <0>");
@@ -222,7 +222,7 @@
           "Expected: a positive value "
           "Actual: <-1> "
           "Which: is not a positive value");
-      shouldFail(0, isPositive, 
+      shouldFail(0, isPositive,
           "Expected: a positive value "
           "Actual: <0> "
           "Which: is not a positive value");
@@ -428,7 +428,7 @@
           "Which: has value ['foo', 'bar'] which has value 'bar' "
           "which is different. Expected: foo Actual: bar ^ "
           "Differ at offset 0 at index 1 at index 0");
-      shouldFail(d, everyElement(allOf(hasLength(greaterThan(0)), 
+      shouldFail(d, everyElement(allOf(hasLength(greaterThan(0)),
           contains('foo'))),
            "Expected: every element((an object with length of a value "
            "greater than <0> and contains 'foo')) "
@@ -759,7 +759,7 @@
     print(foo);
   }
 }
- 
+
 abstract class Abstraction {
   void norealization();
 }
diff --git a/pkg/unittest/test/mirror_matchers_test.dart b/pkg/unittest/test/mirror_matchers_test.dart
new file mode 100644
index 0000000..22e011c
--- /dev/null
+++ b/pkg/unittest/test/mirror_matchers_test.dart
@@ -0,0 +1,29 @@
+// Copyright (c) 2012, 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.
+
+import 'dart:async';
+import 'dart:collection';
+
+import 'package:unittest/unittest.dart';
+import 'package:unittest/mirror_matchers.dart';
+
+import 'test_common.dart';
+import 'test_utils.dart';
+
+void main() {
+
+  initUtils();
+
+  test('hasProperty', () {
+    var foo = [3];
+    shouldPass(foo, hasProperty('length', 1));
+    shouldFail(foo, hasProperty('foo'), 'Expected: has property "foo" '
+        'Actual: [3] '
+        'Which: has no property named "foo"');
+    shouldFail(foo, hasProperty('length', 2),
+        'Expected: has property "length" which matches <2> '
+        'Actual: [3] '
+        'Which: has property "length" with value <1>');
+  });
+}
\ No newline at end of file
diff --git a/pkg/unittest/test/unittest_async_exception_test.dart b/pkg/unittest/test/unittest_async_exception_test.dart
new file mode 100644
index 0000000..34298b7
--- /dev/null
+++ b/pkg/unittest/test/unittest_async_exception_test.dart
@@ -0,0 +1,21 @@
+// Copyright (c) 2013, 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 unittestTest;
+import 'dart:isolate';
+import 'dart:async';
+import 'package:unittest/unittest.dart';
+
+part 'unittest_test_utils.dart';
+
+var testName = 'async exception test';
+
+var testFunction = (_) {
+  test(testName, () {
+    expectAsync0(() {});
+    _defer(() => guardAsync(() { throw "error!"; }));
+  });
+};
+
+var expected = buildStatusString(0, 1, 0, testName, message: 'Caught error!');
diff --git a/pkg/unittest/test/unittest_async_setup_teardown_test.dart b/pkg/unittest/test/unittest_async_setup_teardown_test.dart
new file mode 100644
index 0000000..a73efc8
--- /dev/null
+++ b/pkg/unittest/test/unittest_async_setup_teardown_test.dart
@@ -0,0 +1,64 @@
+// Copyright (c) 2013, 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 unittestTest;
+import 'dart:isolate';
+import 'dart:async';
+import 'package:unittest/unittest.dart';
+
+part 'unittest_test_utils.dart';
+
+var testName = 'async setup teardown test';
+
+var testFunction = (_) {
+  group('good setup/good teardown', () {
+    setUp(() {
+      return new Future.value(0);
+    });
+    tearDown(() {
+      return new Future.value(0);
+    });
+    test('foo1', (){});
+  });
+  group('good setup/bad teardown', () {
+    setUp(() {
+      return new Future.value(0);
+    });
+    tearDown(() {
+      return new Future.error("Failed to complete tearDown");
+    });
+    test('foo2', (){});
+  });
+  group('bad setup/good teardown', () {
+    setUp(() {
+      return new Future.error("Failed to complete setUp");
+    });
+    tearDown(() {
+      return new Future.value(0);
+    });
+    test('foo3', (){});
+  });
+  group('bad setup/bad teardown', () {
+    setUp(() {
+      return new Future.error("Failed to complete setUp");
+    });
+    tearDown(() {
+      return new Future.error("Failed to complete tearDown");
+    });
+    test('foo4', (){});
+  });
+  // The next test is just to make sure we make steady progress
+  // through the tests.
+  test('post groups', () {});
+};
+
+var expected = buildStatusString(2, 0, 3,
+    'good setup/good teardown foo1::'
+    'good setup/bad teardown foo2:'
+    'Teardown failed: Caught Failed to complete tearDown:'
+    'bad setup/good teardown foo3:'
+    'Setup failed: Caught Failed to complete setUp:'
+    'bad setup/bad teardown foo4:'
+    'Setup failed: Caught Failed to complete setUp:'
+    'post groups');
diff --git a/pkg/unittest/test/unittest_completion_test.dart b/pkg/unittest/test/unittest_completion_test.dart
new file mode 100644
index 0000000..97fa9d0
--- /dev/null
+++ b/pkg/unittest/test/unittest_completion_test.dart
@@ -0,0 +1,27 @@
+// Copyright (c) 2013, 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 unittestTest;
+import 'dart:isolate';
+import 'dart:async';
+import 'package:unittest/unittest.dart';
+
+part 'unittest_test_utils.dart';
+
+var testName = 'completion test';
+
+var testFunction = (TestConfiguration testConfig) {
+  test(testName, () {
+    var _callback;
+    _callback = expectAsyncUntil0(() {
+      if (++testConfig.count < 10) {
+        _defer(_callback);
+      }
+    },
+    () => (testConfig.count == 10));
+    _defer(_callback);
+  });
+};
+
+var expected =  buildStatusString(1, 0, 0, testName, count: 10);
diff --git a/pkg/unittest/test/unittest_correct_callback_test.dart b/pkg/unittest/test/unittest_correct_callback_test.dart
new file mode 100644
index 0000000..cd52ba0
--- /dev/null
+++ b/pkg/unittest/test/unittest_correct_callback_test.dart
@@ -0,0 +1,19 @@
+// Copyright (c) 2013, 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 unittestTest;
+import 'dart:isolate';
+import 'dart:async';
+import 'package:unittest/unittest.dart';
+
+part 'unittest_test_utils.dart';
+
+var testName = 'correct callback test';
+
+var testFunction = (TestConfiguration testConfig) {
+  test(testName,
+      () =>_defer(expectAsync0((){ ++testConfig.count;})));
+};
+
+var expected = buildStatusString(1, 0, 0, testName, count: 1);
diff --git a/pkg/unittest/test/unittest_exception_test.dart b/pkg/unittest/test/unittest_exception_test.dart
new file mode 100644
index 0000000..23d302d
--- /dev/null
+++ b/pkg/unittest/test/unittest_exception_test.dart
@@ -0,0 +1,19 @@
+// Copyright (c) 2013, 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 unittestTest;
+import 'dart:isolate';
+import 'dart:async';
+import 'package:unittest/unittest.dart';
+
+part 'unittest_test_utils.dart';
+
+var testName = 'exception test';
+
+var testFunction = (_) {
+  test(testName, () { throw new Exception('Fail.'); });
+};
+
+var expected =  buildStatusString(0, 0, 1, testName,
+    message: 'Test failed: Caught Exception: Fail.');
diff --git a/pkg/unittest/test/unittest_excess_callback_test.dart b/pkg/unittest/test/unittest_excess_callback_test.dart
new file mode 100644
index 0000000..f3876b5
--- /dev/null
+++ b/pkg/unittest/test/unittest_excess_callback_test.dart
@@ -0,0 +1,28 @@
+// Copyright (c) 2013, 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 unittestTest;
+import 'dart:isolate';
+import 'dart:async';
+import 'package:unittest/unittest.dart';
+
+part 'unittest_test_utils.dart';
+
+var testName = 'excess callback test';
+
+var testFunction = (TestConfiguration testConfig) {
+  test(testName, () {
+    var _callback0 = expectAsync0(() => ++testConfig.count);
+    var _callback1 = expectAsync0(() => ++testConfig.count);
+    var _callback2 = expectAsync0(() {
+      _callback1();
+      _callback1();
+      _callback0();
+    });
+    _defer(_callback2);
+  });
+};
+
+var expected = buildStatusString(0, 1, 0, testName,
+    count: 1, message: 'Callback called more times than expected (1).');
diff --git a/pkg/unittest/test/unittest_late_exception_test.dart b/pkg/unittest/test/unittest_late_exception_test.dart
new file mode 100644
index 0000000..7a5c3e6
--- /dev/null
+++ b/pkg/unittest/test/unittest_late_exception_test.dart
@@ -0,0 +1,27 @@
+// Copyright (c) 2013, 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 unittestTest;
+import 'dart:isolate';
+import 'dart:async';
+import 'package:unittest/unittest.dart';
+
+part 'unittest_test_utils.dart';
+
+var testName = 'late exception test';
+
+var testFunction = (_) {
+  var f;
+  test('testOne', () {
+    f = expectAsync0(() {});
+    _defer(f);
+  });
+  test('testTwo', () {
+    _defer(expectAsync0(() { f(); }));
+  });
+};
+
+var expected = buildStatusString(1, 0, 1, 'testOne',
+    message: 'Callback called (2) after test case testOne has already '
+        'been marked as pass.:testTwo:');
diff --git a/pkg/unittest/test/unittest_middle_exception_test.dart b/pkg/unittest/test/unittest_middle_exception_test.dart
new file mode 100644
index 0000000..d405500
--- /dev/null
+++ b/pkg/unittest/test/unittest_middle_exception_test.dart
@@ -0,0 +1,27 @@
+// Copyright (c) 2013, 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 unittestTest;
+import 'dart:isolate';
+import 'dart:async';
+import 'package:unittest/unittest.dart';
+
+part 'unittest_test_utils.dart';
+
+var testName = 'late exception test';
+
+var testFunction = (_) {
+  test('testOne', () { expect(true, isTrue); });
+  test('testTwo', () { expect(true, isFalse); });
+  test('testThree', () {
+    var done = expectAsync0((){});
+    _defer(() {
+      expect(true, isTrue);
+      done();
+    });
+  });
+};
+
+var expected = buildStatusString(2, 1, 0,
+    'testOne::testTwo:Expected: false Actual: <true>:testThree');
diff --git a/pkg/unittest/test/unittest_nested_groups_setup_teardown_test.dart b/pkg/unittest/test/unittest_nested_groups_setup_teardown_test.dart
new file mode 100644
index 0000000..1cb16a0
--- /dev/null
+++ b/pkg/unittest/test/unittest_nested_groups_setup_teardown_test.dart
@@ -0,0 +1,43 @@
+// Copyright (c) 2013, 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 unittestTest;
+import 'dart:isolate';
+import 'dart:async';
+import 'package:unittest/unittest.dart';
+
+part 'unittest_test_utils.dart';
+
+var testName = 'nested groups setup/teardown';
+
+var testFunction = (_) {
+  StringBuffer s = new StringBuffer();
+  group('level 1', () {
+    setUp(makeDelayedSetup(1, s));
+    group('level 2', () {
+      setUp(makeImmediateSetup(2, s));
+      tearDown(makeDelayedTeardown(2, s));
+      group('level 3', () {
+        group('level 4', () {
+          setUp(makeDelayedSetup(4, s));
+          tearDown(makeImmediateTeardown(4, s));
+          group('level 5', () {
+            setUp(makeImmediateSetup(5, s));
+            group('level 6', () {
+              tearDown(makeDelayedTeardown(6, s));
+              test('inner', () {});
+            });
+          });
+        });
+      });
+    });
+  });
+  test('after nest', () {
+    expect(s.toString(), "l1 U l2 U l4 U l5 U l6 D l4 D l2 D ");
+  });
+};
+
+var expected = buildStatusString(2, 0, 0,
+    'level 1 level 2 level 3 level 4 level 5 level 6 inner::'
+    'after nest');
diff --git a/pkg/unittest/test/unittest_runtests_without_tests_test.dart b/pkg/unittest/test/unittest_runtests_without_tests_test.dart
new file mode 100644
index 0000000..e8c26f8
--- /dev/null
+++ b/pkg/unittest/test/unittest_runtests_without_tests_test.dart
@@ -0,0 +1,18 @@
+// Copyright (c) 2013, 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 unittestTest;
+import 'dart:isolate';
+import 'dart:async';
+import 'package:unittest/unittest.dart';
+
+part 'unittest_test_utils.dart';
+
+var testName = 'runTests() without tests';
+
+var testFunction = (_) {
+  runTests();
+};
+
+var expected = buildStatusString(0, 0, 0, null);
diff --git a/pkg/unittest/test/unittest_setup_and_teardown_test.dart b/pkg/unittest/test/unittest_setup_and_teardown_test.dart
new file mode 100644
index 0000000..0c20cf3
--- /dev/null
+++ b/pkg/unittest/test/unittest_setup_and_teardown_test.dart
@@ -0,0 +1,23 @@
+// Copyright (c) 2013, 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 unittestTest;
+import 'dart:isolate';
+import 'dart:async';
+import 'package:unittest/unittest.dart';
+
+part 'unittest_test_utils.dart';
+
+var testName = 'setup and teardown test';
+
+var testFunction = (TestConfiguration testConfig) {
+  group('a', () {
+    setUp(() { testConfig.setup = 'setup'; });
+    tearDown(() { testConfig.teardown = 'teardown'; });
+    test(testName, () {});
+  });
+};
+
+var expected = buildStatusString(1, 0, 0, 'a $testName', count: 0,
+    setup: 'setup', teardown: 'teardown');
diff --git a/pkg/unittest/test/unittest_setup_test.dart b/pkg/unittest/test/unittest_setup_test.dart
new file mode 100644
index 0000000..0050f64
--- /dev/null
+++ b/pkg/unittest/test/unittest_setup_test.dart
@@ -0,0 +1,24 @@
+// Copyright (c) 2013, 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 unittestTest;
+import 'dart:isolate';
+import 'dart:async';
+import 'package:unittest/unittest.dart';
+
+part 'unittest_test_utils.dart';
+
+var testName = 'setup test';
+
+var testFunction = (TestConfiguration testConfig) {
+  group('a', () {
+    setUp(() { testConfig.setup = 'setup'; });
+    test(testName, () {});
+  });
+};
+
+var expected = buildStatusString(1, 0, 0, 'a $testName',
+    count: 0, setup: 'setup');
+
+
diff --git a/pkg/unittest/test/unittest_single_correct_test.dart b/pkg/unittest/test/unittest_single_correct_test.dart
new file mode 100644
index 0000000..23c31fd
--- /dev/null
+++ b/pkg/unittest/test/unittest_single_correct_test.dart
@@ -0,0 +1,18 @@
+// Copyright (c) 2013, 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 unittestTest;
+import 'dart:isolate';
+import 'dart:async';
+import 'package:unittest/unittest.dart';
+
+part 'unittest_test_utils.dart';
+
+var testName = 'single correct test';
+
+var testFunction = (_) {
+  test(testName, () => expect(2 + 3, equals(5)));
+};
+
+var expected = buildStatusString(1, 0, 0, testName);
diff --git a/pkg/unittest/test/unittest_single_failing_test.dart b/pkg/unittest/test/unittest_single_failing_test.dart
new file mode 100644
index 0000000..c965e7a
--- /dev/null
+++ b/pkg/unittest/test/unittest_single_failing_test.dart
@@ -0,0 +1,19 @@
+// Copyright (c) 2013, 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 unittestTest;
+import 'dart:isolate';
+import 'dart:async';
+import 'package:unittest/unittest.dart';
+
+part 'unittest_test_utils.dart';
+
+var testName = 'single failing test';
+
+var testFunction = (_) {
+  test(testName, () => expect(2 + 2, equals(5)));
+};
+
+var expected = buildStatusString(0, 1, 0, testName,
+    message: 'Expected: <5> Actual: <4>');
diff --git a/pkg/unittest/test/unittest_skipped_soloed_nested_test.dart b/pkg/unittest/test/unittest_skipped_soloed_nested_test.dart
new file mode 100644
index 0000000..2ec908d
--- /dev/null
+++ b/pkg/unittest/test/unittest_skipped_soloed_nested_test.dart
@@ -0,0 +1,77 @@
+// Copyright (c) 2013, 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 unittestTest;
+import 'dart:isolate';
+import 'dart:async';
+import 'package:unittest/unittest.dart';
+
+part 'unittest_test_utils.dart';
+
+var testName = 'skipped/soloed nested groups with setup/teardown';
+
+var testFunction = (_) {
+  StringBuffer s = null;
+  setUp(() {
+    if (s == null)
+      s = new StringBuffer();
+  });
+  test('top level', () {
+    s.write('A');
+  });
+  skip_test('skipped top level', () {
+    s.write('B');
+  });
+  skip_group('skipped top level group', () {
+    setUp(() {
+      s.write('C');
+    });
+    solo_test('skipped solo nested test', () {
+      s.write('D');
+    });
+  });
+  group('non-solo group', () {
+    setUp(() {
+      s.write('E');
+    });
+    test('in non-solo group', () {
+      s.write('F');
+    });
+    solo_test('solo_test in non-solo group', () {
+      s.write('G');
+    });
+  });
+  solo_group('solo group', () {
+    setUp(() {
+      s.write('H');
+    });
+    test('solo group non-solo test', () {
+      s.write('I');
+    });
+    solo_test('solo group solo test', () {
+      s.write('J');
+    });
+    group('nested non-solo group in solo group', () {
+      test('nested non-solo group non-solo test', () {
+        s.write('K');
+      });
+      solo_test('nested non-solo group solo test', () {
+        s.write('L');
+      });
+    });
+  });
+  solo_test('final', () {
+    expect(s.toString(), "EGHIHJHKHL");
+  });
+};
+
+var expected =  buildStatusString(6, 0, 0,
+    'non-solo group solo_test in non-solo group::'
+    'solo group solo group non-solo test::'
+    'solo group solo group solo test::'
+    'solo group nested non-solo group in solo group nested non-'
+    'solo group non-solo test::'
+    'solo group nested non-solo group in solo'
+    ' group nested non-solo group solo test::'
+    'final');
diff --git a/pkg/unittest/test/unittest_teardown_test.dart b/pkg/unittest/test/unittest_teardown_test.dart
new file mode 100644
index 0000000..c01bdaf
--- /dev/null
+++ b/pkg/unittest/test/unittest_teardown_test.dart
@@ -0,0 +1,22 @@
+// Copyright (c) 2013, 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 unittestTest;
+import 'dart:isolate';
+import 'dart:async';
+import 'package:unittest/unittest.dart';
+
+part 'unittest_test_utils.dart';
+
+var testName = 'teardown test';
+
+var testFunction = (TestConfiguration testConfig) {
+  group('a', () {
+    tearDown(() { testConfig.teardown = 'teardown'; });
+    test(testName, () {});
+  });
+};
+
+var expected = buildStatusString(1, 0, 0, 'a $testName',
+    count: 0, setup: '', teardown: 'teardown');
diff --git a/pkg/unittest/test/unittest_test.dart b/pkg/unittest/test/unittest_test.dart
deleted file mode 100644
index 852ea73..0000000
--- a/pkg/unittest/test/unittest_test.dart
+++ /dev/null
@@ -1,479 +0,0 @@
-// Copyright (c) 2012, 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.
-
-// TODO(gram):
-// Unfortunately I can't seem to test anything that involves timeouts, e.g.
-// insufficient callbacks, because the timeout is controlled externally
-// (test.dart?), and we would need to use a shorter timeout for the inner tests
-// so the outer timeout doesn't fire. So I removed all such tests.
-// I'd like to revisit this at some point.
-
-library unittestTest;
-import 'dart:isolate';
-import 'dart:async';
-import 'package:unittest/unittest.dart';
-
-Future _defer(void fn()) {
-  return new Future.sync(fn);
-}
-
-String buildStatusString(int passed, int failed, int errors,
-                         var results,
-                         {int count: 0,
-                         String setup: '', String teardown: '',
-                         String uncaughtError: null,
-                         String message: ''}) {
-  var totalTests = 0;
-  var testDetails = new StringBuffer();
-  if(results == null) {
-    // no op
-    assert(message == '');
-  } else if (results is String) {
-    totalTests = passed + failed + errors;
-    testDetails.write(':$results:$message');
-  } else {
-    totalTests = results.length;
-    for (var i = 0; i < results.length; i++) {
-      testDetails.write(':${results[i].description}:'
-          '${collapseWhitespace(results[i].message)}');
-    }
-  }
-  return '$passed:$failed:$errors:$totalTests:$count:'
-      '$setup:$teardown:$uncaughtError$testDetails';
-}
-
-class TestConfiguration extends Configuration {
-
-  // Some test state that is captured
-  int count = 0; // a count of callbacks
-  String setup = ''; // the name of the test group setup function, if any
-  String teardown = ''; // the name of the test group teardown function, if any
-
-  // The port to communicate with the parent isolate
-  final SendPort _port;
-  String _result;
-
-  TestConfiguration(this._port);
-
-  void onSummary(int passed, int failed, int errors, List<TestCase> results,
-      String uncaughtError) {
-    _result = buildStatusString(passed, failed, errors, results,
-        count: count, setup: setup, teardown: teardown,
-        uncaughtError: uncaughtError);
-  }
-
-  void onDone(bool success) {
-    _port.send(_result);
-  }
-}
-
-makeDelayedSetup(index, s) => () {
-  return new Future.delayed(new Duration(milliseconds:1), () {
-    s.write('l$index U ');
-  });
-};
-
-makeDelayedTeardown(index, s) => () {
-  return new Future.delayed(new Duration(milliseconds:1), () {
-    s.write('l$index D ');
-  });
-};
-
-makeImmediateSetup(index, s) => () {
-  s.write('l$index U ');
-};
-
-makeImmediateTeardown(index, s) => () {
-  s.write('l$index D ');
-};
-
-runTest() {
-  port.receive((String testName, sendport) {
-    var testConfig = new TestConfiguration(sendport);
-    unittestConfiguration = testConfig;
-
-    if (testName == 'single correct test') {
-      test(testName, () => expect(2 + 3, equals(5)));
-    } else if (testName == 'single failing test') {
-      test(testName, () => expect(2 + 2, equals(5)));
-    } else if (testName == 'exception test') {
-      test(testName, () { throw new Exception('Fail.'); });
-    } else if (testName == 'group name test') {
-      group('a', () {
-        test('a', () {});
-        group('b', () {
-          test('b', () {});
-        });
-      });
-    } else if (testName == 'setup test') {
-      group('a', () {
-        setUp(() { testConfig.setup = 'setup'; });
-        test(testName, () {});
-      });
-    } else if (testName == 'teardown test') {
-      group('a', () {
-        tearDown(() { testConfig.teardown = 'teardown'; });
-        test(testName, () {});
-      });
-    } else if (testName == 'setup and teardown test') {
-      group('a', () {
-        setUp(() { testConfig.setup = 'setup'; });
-        tearDown(() { testConfig.teardown = 'teardown'; });
-        test(testName, () {});
-      });
-    } else if (testName == 'correct callback test') {
-      test(testName,
-        () =>_defer(expectAsync0((){ ++testConfig.count;})));
-    } else if (testName == 'excess callback test') {
-      test(testName, () {
-        var _callback0 = expectAsync0(() => ++testConfig.count);
-        var _callback1 = expectAsync0(() => ++testConfig.count);
-        var _callback2 = expectAsync0(() {
-          _callback1();
-          _callback1();
-          _callback0();
-        });
-        _defer(_callback2);
-      });
-    } else if (testName == 'completion test') {
-      test(testName, () {
-             var _callback;
-             _callback = expectAsyncUntil0(() {
-               if (++testConfig.count < 10) {
-                 _defer(_callback);
-               }
-             },
-             () => (testConfig.count == 10));
-             _defer(_callback);
-      });
-    } else if (testName == 'async exception test') {
-      test(testName, () {
-        expectAsync0(() {});
-        _defer(() => guardAsync(() { throw "error!"; }));
-      });
-    } else if (testName == 'late exception test') {
-      var f;
-      test('testOne', () {
-        f = expectAsync0(() {});
-        _defer(f);
-      });
-      test('testTwo', () {
-        _defer(expectAsync0(() { f(); }));
-      });
-    } else if (testName == 'middle exception test') {
-      test('testOne', () { expect(true, isTrue); });
-      test('testTwo', () { expect(true, isFalse); });
-      test('testThree', () {
-        var done = expectAsync0((){});
-        _defer(() {
-          expect(true, isTrue);
-          done();
-        });
-      });
-    } else if (testName == 'async setup/teardown test') {
-      group('good setup/good teardown', () {
-        setUp(() {
-          return new Future.value(0);
-        });
-        tearDown(() {
-          return new Future.value(0);
-        });
-        test('foo1', (){});
-      });
-      group('good setup/bad teardown', () {
-        setUp(() {
-          return new Future.value(0);
-        });
-        tearDown(() {
-          return new Future.error("Failed to complete tearDown");
-        });
-        test('foo2', (){});
-      });
-      group('bad setup/good teardown', () {
-        setUp(() {
-          return new Future.error("Failed to complete setUp");
-        });
-        tearDown(() {
-          return new Future.value(0);
-        });
-        test('foo3', (){});
-      });
-      group('bad setup/bad teardown', () {
-        setUp(() {
-          return new Future.error("Failed to complete setUp");
-        });
-        tearDown(() {
-          return new Future.error("Failed to complete tearDown");
-        });
-        test('foo4', (){});
-      });
-      // The next test is just to make sure we make steady progress
-      // through the tests.
-      test('post groups', () {});
-    } else if (testName == 'test returning future') {
-      test("successful", () {
-        return _defer(() {
-          expect(true, true);
-        });
-      });
-      // We repeat the fail and error tests, because during development
-      // I had a situation where either worked fine on their own, and
-      // error/fail worked, but fail/error would time out.
-      test("error1", () {
-        var callback = expectAsync0((){});
-        var excesscallback = expectAsync0((){});
-        return _defer(() {
-          excesscallback();
-          excesscallback();
-          excesscallback();
-          callback();
-        });
-      });
-      test("fail1", () {
-        return _defer(() {
-          expect(true, false);
-        });
-      });
-      test("error2", () {
-        var callback = expectAsync0((){});
-        var excesscallback = expectAsync0((){});
-        return _defer(() {
-          excesscallback();
-          excesscallback();
-          callback();
-        });
-      });
-      test("fail2", () {
-        return _defer(() {
-          fail('failure');
-        });
-      });
-      test('foo5', () {
-      });
-    } else if (testName == 'test returning future using runAsync') {
-      test("successful", () {
-        return _defer(() {
-          runAsync(() {
-            guardAsync(() {
-              expect(true, true);
-            });
-          });
-        });
-      });
-      test("fail1", () {
-        var callback = expectAsync0((){});
-        return _defer(() {
-          runAsync(() {
-            guardAsync(() {
-              expect(true, false);
-              callback();
-            });
-          });
-        });
-      });
-      test('error1', () {
-        var callback = expectAsync0((){});
-        var excesscallback = expectAsync0((){});
-        return _defer(() {
-          runAsync(() {
-            guardAsync(() {
-              excesscallback();
-              excesscallback();
-              callback();
-            });
-          });
-        });
-      });
-      test("fail2", () {
-        var callback = expectAsync0((){});
-        return _defer(() {
-          runAsync(() {
-            guardAsync(() {
-              fail('failure');
-              callback();
-            });
-          });
-        });
-      });
-      test('error2', () {
-        var callback = expectAsync0((){});
-        var excesscallback = expectAsync0((){});
-        return _defer(() {
-          runAsync(() {
-            guardAsync(() {
-              excesscallback();
-              excesscallback();
-              excesscallback();
-              callback();
-            });
-          });
-        });
-      });
-      test('foo6', () {
-      });
-    } else if (testName == 'testCases immutable') {
-      test(testName, () {
-        expect(() => testCases.clear(), throwsUnsupportedError);
-        expect(() => testCases.removeLast(), throwsUnsupportedError);
-      });
-    } else if (testName == 'runTests without tests') {
-      runTests();
-    } else if (testName == 'nested groups setup/teardown') {
-      StringBuffer s = new StringBuffer();
-      group('level 1', () {
-        setUp(makeDelayedSetup(1, s));
-        group('level 2', () {
-          setUp(makeImmediateSetup(2, s));
-          tearDown(makeDelayedTeardown(2, s));
-          group('level 3', () {
-            group('level 4', () {
-              setUp(makeDelayedSetup(4, s));
-              tearDown(makeImmediateTeardown(4, s));
-              group('level 5', () {
-                setUp(makeImmediateSetup(5, s));
-                group('level 6', () {
-                  tearDown(makeDelayedTeardown(6, s));
-                  test('inner', () {});
-                });
-              });
-            });
-          });
-        });
-      });
-      test('after nest', () {
-        expect(s.toString(), "l1 U l2 U l4 U l5 U l6 D l4 D l2 D ");
-      });
-    } else if (testName == 'skipped/soloed nested groups with setup/teardown') {
-      StringBuffer s = null;
-      setUp(() {
-        if (s == null) 
-          s = new StringBuffer();
-      });
-      test('top level', () {
-        s.write('A');
-      });
-      skip_test('skipped top level', () {
-        s.write('B');
-      });
-      skip_group('skipped top level group', () {
-        setUp(() {
-          s.write('C');
-        });
-        solo_test('skipped solo nested test', () {
-          s.write('D');
-        });
-      });
-      group('non-solo group', () {
-        setUp(() {
-          s.write('E');
-        });
-        test('in non-solo group', () {
-          s.write('F');
-        });
-        solo_test('solo_test in non-solo group', () {
-          s.write('G');
-        });
-      });
-      solo_group('solo group', () {
-        setUp(() {
-          s.write('H');
-        });
-        test('solo group non-solo test', () {
-          s.write('I');
-        });
-        solo_test('solo group solo test', () {
-          s.write('J');
-        });
-        group('nested non-solo group in solo group', () {
-          test('nested non-solo group non-solo test', () {
-            s.write('K');
-          });
-          solo_test('nested non-solo group solo test', () {
-            s.write('L');
-          });
-        });
-      });
-      solo_test('final', () {
-        expect(s.toString(), "EGHIHJHKHL");
-      });
-    }
-  });
-}
-
-main() {
-  var tests = {
-    'single correct test': buildStatusString(1, 0, 0, 'single correct test'),
-    'single failing test': buildStatusString(0, 1, 0, 'single failing test',
-        message: 'Expected: <5> Actual: <4>'),
-    'exception test': buildStatusString(0, 0, 1, 'exception test',
-        message: 'Test failed: Caught Exception: Fail.'),
-    'group name test': buildStatusString(2, 0, 0, 'a a::a b b'),
-    'setup test': buildStatusString(1, 0, 0, 'a setup test',
-        count: 0, setup: 'setup'),
-    'teardown test': buildStatusString(1, 0, 0, 'a teardown test',
-        count: 0, setup: '', teardown: 'teardown'),
-    'setup and teardown test': buildStatusString(1, 0, 0,
-        'a setup and teardown test', count: 0, setup: 'setup',
-        teardown: 'teardown'),
-    'correct callback test': buildStatusString(1, 0, 0, 'correct callback test',
-        count: 1),
-    'excess callback test': buildStatusString(0, 1, 0, 'excess callback test',
-        count: 1, message: 'Callback called more times than expected (1).'),
-    'completion test': buildStatusString(1, 0, 0, 'completion test', count: 10),
-    'async exception test': buildStatusString(0, 1, 0, 'async exception test',
-        message: 'Caught error!'),
-    'late exception test': buildStatusString(1, 0, 1, 'testOne',
-        message: 'Callback called (2) after test case testOne has already '
-                 'been marked as pass.:testTwo:'),
-    'middle exception test': buildStatusString(2, 1, 0,
-        'testOne::testTwo:Expected: false Actual: <true>:testThree'),
-    'async setup/teardown test': buildStatusString(2, 0, 3,
-        'good setup/good teardown foo1::'
-        'good setup/bad teardown foo2:'
-            'Teardown failed: Caught Failed to complete tearDown:'
-        'bad setup/good teardown foo3:'
-            'Setup failed: Caught Failed to complete setUp:'
-        'bad setup/bad teardown foo4:'
-            'Setup failed: Caught Failed to complete setUp:'
-        'post groups'),
-    'test returning future': buildStatusString(2, 4, 0,
-        'successful::'
-        'error1:Callback called more times than expected (1).:'
-        'fail1:Expected: <false> Actual: <true>:'
-        'error2:Callback called more times than expected (1).:'
-        'fail2:failure:'
-        'foo5'),
-    'test returning future using runAsync': buildStatusString(2, 4, 0,
-        'successful::'
-        'fail1:Expected: <false> Actual: <true>:'
-        'error1:Callback called more times than expected (1).:'
-        'fail2:failure:'
-        'error2:Callback called more times than expected (1).:'
-        'foo6'),
-    'testCases immutable':
-        buildStatusString(1, 0, 0, 'testCases immutable'),
-    'runTests without tests': buildStatusString(0, 0, 0, null),
-    'nested groups setup/teardown':
-        buildStatusString(2, 0, 0,
-            'level 1 level 2 level 3 level 4 level 5 level 6 inner::'
-            'after nest'),
-    'skipped/soloed nested groups with setup/teardown':
-        buildStatusString(6, 0, 0,
-            'non-solo group solo_test in non-solo group::'
-            'solo group solo group non-solo test::'
-            'solo group solo group solo test::'
-            'solo group nested non-solo group in solo group nested non-'
-            'solo group non-solo test::'
-            'solo group nested non-solo group in solo'
-            ' group nested non-solo group solo test::'
-            'final')
-  };
-
-  tests.forEach((String name, String expected) {
-    test(name, () => spawnFunction(runTest)
-        .call(name)
-        .then((String msg) => expect(msg.trim(), equals(expected))));
-    });
-}
-
diff --git a/pkg/unittest/test/unittest_test_returning_future_test.dart b/pkg/unittest/test/unittest_test_returning_future_test.dart
new file mode 100644
index 0000000..a74a8db
--- /dev/null
+++ b/pkg/unittest/test/unittest_test_returning_future_test.dart
@@ -0,0 +1,62 @@
+// Copyright (c) 2013, 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 unittestTest;
+import 'dart:isolate';
+import 'dart:async';
+import 'package:unittest/unittest.dart';
+
+part 'unittest_test_utils.dart';
+
+var testName = 'test returning future';
+
+var testFunction = (_) {
+  test("successful", () {
+    return _defer(() {
+      expect(true, true);
+    });
+  });
+  // We repeat the fail and error tests, because during development
+  // I had a situation where either worked fine on their own, and
+  // error/fail worked, but fail/error would time out.
+  test("error1", () {
+    var callback = expectAsync0((){});
+    var excesscallback = expectAsync0((){});
+    return _defer(() {
+      excesscallback();
+      excesscallback();
+      excesscallback();
+      callback();
+    });
+  });
+  test("fail1", () {
+    return _defer(() {
+      expect(true, false);
+    });
+  });
+  test("error2", () {
+    var callback = expectAsync0((){});
+    var excesscallback = expectAsync0((){});
+    return _defer(() {
+      excesscallback();
+      excesscallback();
+      callback();
+    });
+  });
+  test("fail2", () {
+    return _defer(() {
+      fail('failure');
+    });
+  });
+  test('foo5', () {
+  });
+};
+
+var expected = buildStatusString(2, 4, 0,
+    'successful::'
+    'error1:Callback called more times than expected (1).:'
+    'fail1:Expected: <false> Actual: <true>:'
+    'error2:Callback called more times than expected (1).:'
+    'fail2:failure:'
+    'foo5');
diff --git a/pkg/unittest/test/unittest_test_returning_future_using_runasync_test.dart b/pkg/unittest/test/unittest_test_returning_future_using_runasync_test.dart
new file mode 100644
index 0000000..2b8d343
--- /dev/null
+++ b/pkg/unittest/test/unittest_test_returning_future_using_runasync_test.dart
@@ -0,0 +1,83 @@
+// Copyright (c) 2013, 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 unittestTest;
+import 'dart:isolate';
+import 'dart:async';
+import 'package:unittest/unittest.dart';
+
+part 'unittest_test_utils.dart';
+
+var testName = 'test returning future using runAsync';
+
+var testFunction = (_) {
+  test("successful", () {
+    return _defer(() {
+      runAsync(() {
+        guardAsync(() {
+          expect(true, true);
+        });
+      });
+    });
+  });
+  test("fail1", () {
+    var callback = expectAsync0((){});
+    return _defer(() {
+      runAsync(() {
+        guardAsync(() {
+          expect(true, false);
+          callback();
+        });
+      });
+    });
+  });
+  test('error1', () {
+    var callback = expectAsync0((){});
+    var excesscallback = expectAsync0((){});
+    return _defer(() {
+      runAsync(() {
+        guardAsync(() {
+          excesscallback();
+          excesscallback();
+          callback();
+        });
+      });
+    });
+  });
+  test("fail2", () {
+    var callback = expectAsync0((){});
+    return _defer(() {
+      runAsync(() {
+        guardAsync(() {
+          fail('failure');
+          callback();
+        });
+      });
+    });
+  });
+  test('error2', () {
+    var callback = expectAsync0((){});
+    var excesscallback = expectAsync0((){});
+    return _defer(() {
+      runAsync(() {
+        guardAsync(() {
+          excesscallback();
+          excesscallback();
+          excesscallback();
+          callback();
+        });
+      });
+    });
+  });
+  test('foo6', () {
+  });
+};
+
+var expected = buildStatusString(2, 4, 0,
+    'successful::'
+    'fail1:Expected: <false> Actual: <true>:'
+    'error1:Callback called more times than expected (1).:'
+    'fail2:failure:'
+    'error2:Callback called more times than expected (1).:'
+    'foo6');
diff --git a/pkg/unittest/test/unittest_test_utils.dart b/pkg/unittest/test/unittest_test_utils.dart
new file mode 100644
index 0000000..ab83927
--- /dev/null
+++ b/pkg/unittest/test/unittest_test_utils.dart
@@ -0,0 +1,95 @@
+// Copyright (c) 2013, 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.
+
+part of unittestTest;
+
+Future _defer(void fn()) {
+  return new Future.sync(fn);
+}
+
+String buildStatusString(int passed, int failed, int errors,
+                         var results,
+                         {int count: 0,
+                         String setup: '', String teardown: '',
+                         String uncaughtError: null,
+                         String message: ''}) {
+  var totalTests = 0;
+  var testDetails = new StringBuffer();
+  if(results == null) {
+    // no op
+    assert(message == '');
+  } else if (results is String) {
+    totalTests = passed + failed + errors;
+    testDetails.write(':$results:$message');
+  } else {
+    totalTests = results.length;
+    for (var i = 0; i < results.length; i++) {
+      testDetails.write(':${results[i].description}:'
+          '${collapseWhitespace(results[i].message)}');
+    }
+  }
+  return '$passed:$failed:$errors:$totalTests:$count:'
+      '$setup:$teardown:$uncaughtError$testDetails';
+}
+
+class TestConfiguration extends Configuration {
+
+  // Some test state that is captured.
+  int count = 0; // A count of callbacks.
+  String setup = ''; // The name of the test group setup function, if any.
+  String teardown = ''; // The name of the group teardown function, if any.
+
+  // The port to communicate with the parent isolate
+  final SendPort _port;
+  String _result;
+
+  TestConfiguration(this._port);
+
+  void onSummary(int passed, int failed, int errors, List<TestCase> results,
+      String uncaughtError) {
+    _result = buildStatusString(passed, failed, errors, results,
+        count: count, setup: setup, teardown: teardown,
+        uncaughtError: uncaughtError);
+  }
+
+  void onDone(bool success) {
+    _port.send(_result);
+  }
+}
+
+makeDelayedSetup(index, s) => () {
+  return new Future.delayed(new Duration(milliseconds:1), () {
+    s.write('l$index U ');
+  });
+};
+
+makeDelayedTeardown(index, s) => () {
+  return new Future.delayed(new Duration(milliseconds:1), () {
+    s.write('l$index D ');
+  });
+};
+
+makeImmediateSetup(index, s) => () {
+  s.write('l$index U ');
+};
+
+makeImmediateTeardown(index, s) => () {
+  s.write('l$index D ');
+};
+
+runTestInIsolate() {
+  port.receive((_, sendport) {
+    var testConfig = new TestConfiguration(sendport);
+    unittestConfiguration = testConfig;
+    testFunction(testConfig);
+  });
+}
+
+main() {
+  spawnFunction(runTestInIsolate)
+      .call('')
+      .then((String msg) {
+        expect(msg.trim(), equals(expected));
+      });
+}
diff --git a/pkg/unittest/test/unittest_testcases_immutable_test.dart b/pkg/unittest/test/unittest_testcases_immutable_test.dart
new file mode 100644
index 0000000..891ea3a
--- /dev/null
+++ b/pkg/unittest/test/unittest_testcases_immutable_test.dart
@@ -0,0 +1,21 @@
+// Copyright (c) 2013, 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 unittestTest;
+import 'dart:isolate';
+import 'dart:async';
+import 'package:unittest/unittest.dart';
+
+part 'unittest_test_utils.dart';
+
+var testName = 'testcases immutable';
+
+var testFunction = (_) {
+  test(testName, () {
+    expect(() => testCases.clear(), throwsUnsupportedError);
+    expect(() => testCases.removeLast(), throwsUnsupportedError);
+  });
+};
+
+var expected = buildStatusString(1, 0, 0, testName);
diff --git a/pkg/unittest/test/unitttest_group_name_test.dart b/pkg/unittest/test/unitttest_group_name_test.dart
new file mode 100644
index 0000000..8f6b87b
--- /dev/null
+++ b/pkg/unittest/test/unitttest_group_name_test.dart
@@ -0,0 +1,23 @@
+// Copyright (c) 2013, 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 unittestTest;
+import 'dart:isolate';
+import 'dart:async';
+import 'package:unittest/unittest.dart';
+
+part 'unittest_test_utils.dart';
+
+var testName = 'group name test';
+
+var testFunction = (_) {
+  group('a', () {
+    test('a', () {});
+    group('b', () {
+      test('b', () {});
+    });
+  });
+};
+
+var expected = buildStatusString(2, 0, 0, 'a a::a b b');
diff --git a/runtime/bin/dartutils.cc b/runtime/bin/dartutils.cc
index 5de42ac..a90694d 100644
--- a/runtime/bin/dartutils.cc
+++ b/runtime/bin/dartutils.cc
@@ -389,6 +389,7 @@
     return Dart_Error(error_msg);
   }
   Dart_Handle str = Dart_NewStringFromUTF8(text_buffer, len);
+  free(const_cast<uint8_t *>(text_buffer));
   return str;
 }
 
@@ -594,23 +595,27 @@
   Dart_StringToCString(script_path, &script_path_cstr);
   const char* error_msg = NULL;
   intptr_t len;
-  const uint8_t* text_buffer = ReadFileFully(script_path_cstr,
-                                             &len,
-                                             &error_msg);
-  if (text_buffer == NULL) {
+  const uint8_t* buffer = ReadFileFully(script_path_cstr,
+                                        &len,
+                                        &error_msg);
+  if (buffer == NULL) {
     return Dart_Error(error_msg);
   }
   bool is_snapshot = false;
-  text_buffer = SniffForMagicNumber(text_buffer, &len, &is_snapshot);
+  const uint8_t *payload = SniffForMagicNumber(buffer, &len, &is_snapshot);
+  Dart_Handle returnValue;
   if (is_snapshot) {
-    return Dart_LoadScriptFromSnapshot(text_buffer, len);
+    returnValue = Dart_LoadScriptFromSnapshot(payload, len);
   } else {
-    Dart_Handle source = Dart_NewStringFromUTF8(text_buffer, len);
+    Dart_Handle source = Dart_NewStringFromUTF8(buffer, len);
     if (Dart_IsError(source)) {
-      return source;
+      returnValue = source;
+    } else {
+      returnValue = Dart_LoadScript(resolved_script_uri, source, 0, 0);
     }
-    return Dart_LoadScript(resolved_script_uri, source, 0, 0);
   }
+  free(const_cast<uint8_t *>(buffer));
+  return returnValue;
 }
 
 
diff --git a/runtime/bin/io_natives.cc b/runtime/bin/io_natives.cc
index f9adf09..e771d89 100644
--- a/runtime/bin/io_natives.cc
+++ b/runtime/bin/io_natives.cc
@@ -50,6 +50,7 @@
   V(SecureSocket_RegisterHandshakeCompleteCallback, 2)                         \
   V(SecureSocket_Renegotiate, 4)                                               \
   V(SecureSocket_InitializeLibrary, 3)                                         \
+  V(SecureSocket_AddCertificate, 2)                                            \
   V(SecureSocket_NewServicePort, 0)                                            \
   V(SecureSocket_FilterPointer, 1)                                             \
   V(ServerSocket_CreateBindListen, 5)                                          \
diff --git a/runtime/bin/secure_socket.cc b/runtime/bin/secure_socket.cc
index 9cf0d7d..ad6ae82 100644
--- a/runtime/bin/secure_socket.cc
+++ b/runtime/bin/secure_socket.cc
@@ -278,6 +278,92 @@
 }
 
 
+static Dart_Handle X509FromCertificate(CERTCertificate* certificate) {
+  PRTime start_validity;
+  PRTime end_validity;
+  SECStatus status =
+      CERT_GetCertTimes(certificate, &start_validity, &end_validity);
+  if (status != SECSuccess) {
+    ThrowPRException("CertificateException",
+                     "Cannot get validity times from certificate");
+  }
+  int64_t start_epoch_ms = start_validity / PR_USEC_PER_MSEC;
+  int64_t end_epoch_ms = end_validity / PR_USEC_PER_MSEC;
+  Dart_Handle subject_name_object =
+      DartUtils::NewString(certificate->subjectName);
+  Dart_Handle issuer_name_object =
+      DartUtils::NewString(certificate->issuerName);
+  Dart_Handle start_epoch_ms_int = Dart_NewInteger(start_epoch_ms);
+  Dart_Handle end_epoch_ms_int = Dart_NewInteger(end_epoch_ms);
+
+  Dart_Handle date_type =
+      DartUtils::GetDartType(DartUtils::kCoreLibURL, "DateTime");
+  Dart_Handle from_milliseconds =
+      DartUtils::NewString("fromMillisecondsSinceEpoch");
+
+  Dart_Handle start_validity_date =
+      Dart_New(date_type, from_milliseconds, 1, &start_epoch_ms_int);
+  Dart_Handle end_validity_date =
+      Dart_New(date_type, from_milliseconds, 1, &end_epoch_ms_int);
+
+  Dart_Handle x509_type =
+      DartUtils::GetDartType(DartUtils::kIOLibURL, "X509Certificate");
+  Dart_Handle arguments[] = { subject_name_object,
+                              issuer_name_object,
+                              start_validity_date,
+                              end_validity_date };
+  return Dart_New(x509_type, Dart_Null(), 4, arguments);
+}
+
+
+void FUNCTION_NAME(SecureSocket_AddCertificate)
+    (Dart_NativeArguments args) {
+  Dart_EnterScope();
+  Dart_Handle certificate_object =
+      ThrowIfError(Dart_GetNativeArgument(args, 0));
+  Dart_Handle trust_object = ThrowIfError(Dart_GetNativeArgument(args, 1));
+
+  if (!Dart_IsList(certificate_object) || !Dart_IsString(trust_object)) {
+    Dart_ThrowException(DartUtils::NewDartArgumentError(
+        "Bad argument to SecureSocket.addCertificate"));
+  }
+
+  intptr_t length;
+  ThrowIfError(Dart_ListLength(certificate_object, &length));
+  uint8_t* certificate = reinterpret_cast<uint8_t*>(malloc(length + 1));
+  if (certificate == NULL) {
+    FATAL("Out of memory in SecureSocket.addCertificate");
+  }
+  ThrowIfError(Dart_ListGetAsBytes(
+      certificate_object, 0, certificate, length));
+
+  const char* trust_string;
+  ThrowIfError(Dart_StringToCString(trust_object,
+                                    &trust_string));
+
+  CERTCertificate* cert = CERT_DecodeCertFromPackage(
+      reinterpret_cast<char*>(certificate), length);
+  if (cert == NULL) {
+    ThrowPRException("CertificateException", "Certificate cannot be decoded");
+  }
+  CERTCertTrust trust;
+  SECStatus status = CERT_DecodeTrustString(&trust, trust_string);
+  if (status != SECSuccess) {
+    ThrowPRException("CertificateException", "Trust string cannot be decoded");
+  }
+
+  status = CERT_ChangeCertTrust(CERT_GetDefaultCertDB(), cert, &trust);
+  if (status != SECSuccess) {
+    ThrowPRException("CertificateException", "Cannot set trust attributes");
+  }
+
+  Dart_SetReturnValue(args, X509FromCertificate(cert));
+  Dart_ExitScope();
+  return;
+}
+
+
+
 void FUNCTION_NAME(SecureSocket_PeerCertificate)
     (Dart_NativeArguments args) {
   Dart_EnterScope();
@@ -428,44 +514,6 @@
 }
 
 
-static Dart_Handle X509FromCertificate(CERTCertificate* certificate) {
-  PRTime start_validity;
-  PRTime end_validity;
-  SECStatus status =
-      CERT_GetCertTimes(certificate, &start_validity, &end_validity);
-  if (status != SECSuccess) {
-    ThrowPRException("CertificateException",
-                     "Cannot get validity times from certificate");
-  }
-  int64_t start_epoch_ms = start_validity / PR_USEC_PER_MSEC;
-  int64_t end_epoch_ms = end_validity / PR_USEC_PER_MSEC;
-  Dart_Handle subject_name_object =
-      DartUtils::NewString(certificate->subjectName);
-  Dart_Handle issuer_name_object =
-      DartUtils::NewString(certificate->issuerName);
-  Dart_Handle start_epoch_ms_int = Dart_NewInteger(start_epoch_ms);
-  Dart_Handle end_epoch_ms_int = Dart_NewInteger(end_epoch_ms);
-
-  Dart_Handle date_type =
-      DartUtils::GetDartType(DartUtils::kCoreLibURL, "DateTime");
-  Dart_Handle from_milliseconds =
-      DartUtils::NewString("fromMillisecondsSinceEpoch");
-
-  Dart_Handle start_validity_date =
-      Dart_New(date_type, from_milliseconds, 1, &start_epoch_ms_int);
-  Dart_Handle end_validity_date =
-      Dart_New(date_type, from_milliseconds, 1, &end_epoch_ms_int);
-
-  Dart_Handle x509_type =
-      DartUtils::GetDartType(DartUtils::kIOLibURL, "X509Certificate");
-  Dart_Handle arguments[] = { subject_name_object,
-                              issuer_name_object,
-                              start_validity_date,
-                              end_validity_date };
-  return Dart_New(x509_type, Dart_Null(), 4, arguments);
-}
-
-
 void SSLFilter::Init(Dart_Handle dart_this) {
   if (!library_initialized_) {
     InitializeLibrary(NULL, "", true, false);
diff --git a/runtime/bin/secure_socket_patch.dart b/runtime/bin/secure_socket_patch.dart
index 104f562..96d6565a 100644
--- a/runtime/bin/secure_socket_patch.dart
+++ b/runtime/bin/secure_socket_patch.dart
@@ -9,7 +9,11 @@
   /* patch */ static void initialize({String database,
                                       String password,
                                       bool useBuiltinRoots: true})
-  native "SecureSocket_InitializeLibrary";
+      native "SecureSocket_InitializeLibrary";
+
+  /* patch */ static X509Certificate addCertificate(List<int> certificate,
+                                                    String trust)
+      native "SecureSocket_AddCertificate";
 }
 
 
diff --git a/runtime/bin/secure_socket_unsupported.cc b/runtime/bin/secure_socket_unsupported.cc
index de97dc8..6695fa9 100644
--- a/runtime/bin/secure_socket_unsupported.cc
+++ b/runtime/bin/secure_socket_unsupported.cc
@@ -27,6 +27,14 @@
 }
 
 
+void FUNCTION_NAME(SecureSocket_AddCertificate)(Dart_NativeArguments args) {
+  Dart_EnterScope();
+  Dart_ThrowException(DartUtils::NewDartArgumentError(
+      "Secure Sockets unsupported on this platform"));
+  Dart_ExitScope();
+}
+
+
 void FUNCTION_NAME(SecureSocket_Destroy)(Dart_NativeArguments args) {
   Dart_EnterScope();
   Dart_ThrowException(DartUtils::NewDartArgumentError(
diff --git a/runtime/include/dart_api.h b/runtime/include/dart_api.h
index e336288..b47b40c 100755
--- a/runtime/include/dart_api.h
+++ b/runtime/include/dart_api.h
@@ -1981,6 +1981,15 @@
 DART_EXPORT void Dart_SetReturnValue(Dart_NativeArguments args,
                                      Dart_Handle retval);
 
+DART_EXPORT void Dart_SetBooleanReturnValue(Dart_NativeArguments args,
+                                            bool retval);
+
+DART_EXPORT void Dart_SetIntegerReturnValue(Dart_NativeArguments args,
+                                            intptr_t retval);
+
+DART_EXPORT void Dart_SetDoubleReturnValue(Dart_NativeArguments args,
+                                           double retval);
+
 /**
  * A native function.
  */
diff --git a/runtime/lib/bool_patch.dart b/runtime/lib/bool_patch.dart
index fd84119..f5020c3 100644
--- a/runtime/lib/bool_patch.dart
+++ b/runtime/lib/bool_patch.dart
@@ -5,10 +5,9 @@
 // Dart core library.
 
 patch class bool {
-  
-  /* patch */ int get hashCode {
+
+  int get hashCode {
     return this ? 1231 : 1237;
   }
 
-  /* patch */ bool operator ==(other) => identical(this, other);
 }
diff --git a/runtime/lib/errors_patch.dart b/runtime/lib/errors_patch.dart
index 62148ac..c68ea47 100644
--- a/runtime/lib/errors_patch.dart
+++ b/runtime/lib/errors_patch.dart
@@ -178,9 +178,9 @@
   }
 }
 
-class _FiftyThreeBitOverflowError extends Error {
+class _JavascriptIntegerOverflowError extends Error {
   final Object _value;
 
-  _FiftyThreeBitOverflowError(this._value);
-  String toString() => "53-bit Overflow: $_value";
+  _JavascriptIntegerOverflowError(this._value);
+  String toString() => "Javascript Integer Overflow: $_value";
 }
diff --git a/runtime/lib/map_patch.dart b/runtime/lib/map_patch.dart
index cbc03fb..e723828 100644
--- a/runtime/lib/map_patch.dart
+++ b/runtime/lib/map_patch.dart
@@ -9,7 +9,7 @@
   // in checked mode.
   // The values are at position 2*n+1 and are not yet type checked.
   factory Map._fromLiteral(List elements) {
-    var map = new LinkedHashMap<String, V>();
+    var map = new LinkedHashMap<K, V>();
     var len = elements.length;
     for (int i = 1; i < len; i += 2) {
       map[elements[i - 1]] = elements[i];
diff --git a/runtime/lib/mirror_reference.dart b/runtime/lib/mirror_reference.dart
index 7bdbc2d..b0f7726 100644
--- a/runtime/lib/mirror_reference.dart
+++ b/runtime/lib/mirror_reference.dart
@@ -7,4 +7,6 @@
     throw new UnsupportedError(
         "class _MirrorReference cannot be instantiated");
   }
+
+  bool operator ==(other) native "MirrorReference_equals";
 }
diff --git a/runtime/lib/mirrors.cc b/runtime/lib/mirrors.cc
index f9a1dcf..98806b1 100644
--- a/runtime/lib/mirrors.cc
+++ b/runtime/lib/mirrors.cc
@@ -2,19 +2,13 @@
 // 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.
 
-#include "include/dart_api.h"
-#include "include/dart_debugger_api.h"
-#include "include/dart_mirrors_api.h"
-#include "vm/dart_api_impl.h"
-#include "vm/dart_api_state.h"  // TODO(11742): Remove with CreateMirrorRef.
+#include "lib/invocation_mirror.h"
 #include "vm/bootstrap_natives.h"
 #include "vm/dart_entry.h"
 #include "vm/exceptions.h"
-#include "vm/message.h"
+#include "vm/object_store.h"
 #include "vm/port.h"
-#include "vm/resolver.h"
 #include "vm/symbols.h"
-#include "lib/invocation_mirror.h"
 
 namespace dart {
 
@@ -28,16 +22,11 @@
                                        mirror_class_name,
                                        constructor_name,
                                        constructor_arguments));
-  ASSERT(result.IsInstance());
+  ASSERT(!result.IsError());
   return Instance::Cast(result).raw();
 }
 
 
-inline Dart_Handle NewString(const char* str) {
-  return Dart_NewStringFromCString(str);
-}
-
-
 DEFINE_NATIVE_ENTRY(Mirrors_isLocalPort, 1) {
   GET_NON_NULL_NATIVE_ARGUMENT(Instance, port, arguments->NativeArgAt(0));
 
@@ -55,51 +44,6 @@
 }
 
 
-// TODO(turnidge): Add Map support to the dart embedding api instead
-// of implementing it here.
-static Dart_Handle CoreLib() {
-  Dart_Handle core_lib_name = NewString("dart:core");
-  return Dart_LookupLibrary(core_lib_name);
-}
-
-
-static Dart_Handle MapNew() {
-  // TODO(turnidge): Switch to an order-preserving map type.
-  Dart_Handle type = Dart_GetType(CoreLib(), NewString("Map"), 0, NULL);
-  if (Dart_IsError(type)) {
-    return type;
-  }
-  return Dart_New(type, Dart_Null(), 0, NULL);
-}
-
-
-static Dart_Handle MapAdd(Dart_Handle map, Dart_Handle key, Dart_Handle value) {
-  Dart_Handle args[] = { key, value };
-  return Dart_Invoke(map, NewString("[]="), ARRAY_SIZE(args), args);
-}
-
-
-static Dart_Handle MirrorLib() {
-  Dart_Handle mirror_lib_name = NewString("dart:mirrors");
-  return Dart_LookupLibrary(mirror_lib_name);
-}
-
-
-// TODO(11742): Remove once there are no more users of the Dart_Handle-based
-// VMReferences.
-static Dart_Handle CreateMirrorReference(Dart_Handle handle) {
-  Isolate* isolate = Isolate::Current();
-  DARTSCOPE(isolate);
-  const Object& referent = Object::Handle(isolate, Api::UnwrapHandle(handle));
-  const MirrorReference& reference =
-       MirrorReference::Handle(MirrorReference::New(referent));
-  return Api::NewHandle(isolate, reference.raw());
-}
-
-
-static Dart_Handle CreateLazyMirror(Dart_Handle target);
-
-
 static RawInstance* CreateParameterMirrorList(const Function& func) {
   HANDLESCOPE(Isolate::Current());
   const intptr_t param_cnt = func.num_fixed_parameters() -
@@ -123,311 +67,74 @@
 }
 
 
-static Dart_Handle CreateParameterMirrorListUsingApi(Dart_Handle func) {
-  ASSERT(Dart_IsFunction(func));
-  Isolate* isolate = Isolate::Current();
-  return Api::NewHandle(
-      isolate, CreateParameterMirrorList(Api::UnwrapFunctionHandle(
-          isolate, func)));
-}
-
-
-static Dart_Handle CreateLazyMirror(Dart_Handle target) {
-  if (Dart_IsNull(target) || Dart_IsError(target)) {
-    return target;
-  }
-
-  if (Dart_IsLibrary(target)) {
-    Dart_Handle cls_name = NewString("_LazyLibraryMirror");
-    Dart_Handle type = Dart_GetType(MirrorLib(), cls_name, 0, NULL);
-    Dart_Handle args[] = { Dart_LibraryUrl(target) };
-    return Dart_New(type, Dart_Null(), ARRAY_SIZE(args), args);
-  }
-
-  if (Dart_IsClass(target)) {
-    if (Dart_ClassIsFunctionType(target)) {
-      Dart_Handle cls_name = NewString("_LazyFunctionTypeMirror");
-      Dart_Handle type = Dart_GetType(MirrorLib(), cls_name, 0, NULL);
-
-      Dart_Handle sig = Dart_ClassGetFunctionTypeSignature(target);
-      Dart_Handle return_type = Dart_FunctionReturnType(sig);
-      if (Dart_IsError(return_type)) {
-        return return_type;
-      }
-
-      Dart_Handle args[] = {
-        CreateLazyMirror(return_type),
-        CreateParameterMirrorListUsingApi(sig),
-      };
-      return Dart_New(type, Dart_Null(), ARRAY_SIZE(args), args);
-    } else {
-      Dart_Handle cls_name = NewString("_LazyTypeMirror");
-      Dart_Handle type = Dart_GetType(MirrorLib(), cls_name, 0, NULL);
-      Dart_Handle lib = Dart_ClassGetLibrary(target);
-      Dart_Handle lib_url;
-      if (Dart_IsNull(lib)) {
-        lib_url = Dart_Null();
-      } else {
-        lib_url = Dart_LibraryUrl(lib);
-      }
-      Dart_Handle args[] = { lib_url, Dart_ClassName(target) };
-      return Dart_New(type, Dart_Null(), ARRAY_SIZE(args), args);
-    }
-  }
-
-  if (Dart_IsTypeVariable(target)) {
-    Dart_Handle var_name = Dart_TypeVariableName(target);
-    Dart_Handle owner = Dart_TypeVariableOwner(target);
-    Dart_Handle owner_mirror = CreateLazyMirror(owner);
-
-    Dart_Handle cls_name = NewString("_LazyTypeVariableMirror");
-    Dart_Handle type = Dart_GetType(MirrorLib(), cls_name, 0, NULL);
-
-    Dart_Handle args[] = { var_name, owner_mirror };
-    return Dart_New(type, Dart_Null(), ARRAY_SIZE(args), args);
-  }
-
-  UNREACHABLE();
-  return Dart_Null();
-}
-
-
-static Dart_Handle CreateImplementsList(Dart_Handle intf) {
-  intptr_t len = 0;
-  Dart_Handle result = Dart_ClassGetInterfaceCount(intf, &len);
-  if (Dart_IsError(result)) {
-    return result;
-  }
-
-  Dart_Handle mirror_list = Dart_NewList(len);
-  if (Dart_IsError(mirror_list)) {
-    return mirror_list;
-  }
-
-  for (intptr_t i = 0; i < len; i++) {
-    Dart_Handle interface = Dart_ClassGetInterfaceAt(intf, i);
-    if (Dart_IsError(interface)) {
-      return interface;
-    }
-    Dart_Handle mirror = CreateLazyMirror(interface);
-    if (Dart_IsError(mirror)) {
-      return mirror;
-    }
-    Dart_Handle result = Dart_ListSetAt(mirror_list, i, mirror);
-    if (Dart_IsError(result)) {
-      return result;
-    }
-  }
-  return mirror_list;
-}
-
-
-static Dart_Handle CreateTypeVariableMirrorUsingApi(Dart_Handle type_var,
-                                                    Dart_Handle type_var_name,
-                                                    Dart_Handle owner_mirror) {
-  ASSERT(Dart_IsTypeVariable(type_var));
-  Dart_Handle cls_name = NewString("_LocalTypeVariableMirrorImpl");
-  Dart_Handle type = Dart_GetType(MirrorLib(), cls_name, 0, NULL);
-  if (Dart_IsError(type)) {
-    return type;
-  }
-
-  Dart_Handle upper_bound = Dart_TypeVariableUpperBound(type_var);
-  if (Dart_IsError(upper_bound)) {
-    return upper_bound;
-  }
-
-  Dart_Handle args[] = {
-    CreateMirrorReference(type_var),
-    type_var_name,
-    owner_mirror,
-    CreateLazyMirror(upper_bound),
-  };
-  Dart_Handle mirror = Dart_New(type, Dart_Null(), ARRAY_SIZE(args), args);
-  return mirror;
-}
-
-
 static RawInstance* CreateTypeVariableMirror(const TypeParameter& param,
                                              const Instance& owner_mirror) {
-  Instance& retvalue = Instance::Handle();
-  Dart_EnterScope();
-  Isolate* isolate = Isolate::Current();
-  Dart_Handle param_handle = Api::NewHandle(isolate, param.raw());
-  if (Dart_IsError(param_handle)) {
-    Dart_PropagateError(param_handle);
-  }
-  Dart_Handle name_handle = Api::NewHandle(isolate, param.Name());
-  if (Dart_IsError(name_handle)) {
-    Dart_PropagateError(name_handle);
-  }
-  // Until we get rid of lazy mirrors, we must have owners.
-  Dart_Handle owner_handle;
-  if (owner_mirror.IsNull()) {
-    owner_handle = Api::NewHandle(isolate, param.parameterized_class());
-    if (Dart_IsError(owner_handle)) {
-      Dart_PropagateError(owner_handle);
-    }
-    owner_handle = CreateLazyMirror(owner_handle);
-    if (Dart_IsError(owner_handle)) {
-      Dart_PropagateError(owner_handle);
-    }
-  } else {
-    owner_handle = Api::NewHandle(isolate, owner_mirror.raw());
-    if (Dart_IsError(owner_handle)) {
-      Dart_PropagateError(owner_handle);
-    }
-  }
-  // TODO(11742): At some point the handle calls will be replaced by inlined
-  // functionality.
-  Dart_Handle result =  CreateTypeVariableMirrorUsingApi(param_handle,
-                                                         name_handle,
-                                                         owner_handle);
-  if (Dart_IsError(result)) {
-    Dart_PropagateError(result);
-  }
-  retvalue ^= Api::UnwrapHandle(result);
-  Dart_ExitScope();
-  return retvalue.raw();
+  const Array& args = Array::Handle(Array::New(3));
+  args.SetAt(0, param);
+  args.SetAt(1, String::Handle(param.name()));
+  args.SetAt(2, owner_mirror);
+  return CreateMirror(Symbols::_LocalTypeVariableMirrorImpl(), args);
 }
 
 
-static Dart_Handle CreateTypeVariableMap(Dart_Handle owner,
-                                         Dart_Handle owner_mirror) {
-  ASSERT(Dart_IsClass(owner));
-  // TODO(turnidge): This should be an immutable map.
-  Dart_Handle map = MapNew();
-  if (Dart_IsError(map)) {
-    return map;
+// We create a list in native code and let Dart code create the type mirror
+// object and the ordered map.
+static RawInstance* CreateTypeVariableList(const Class& cls) {
+  const TypeArguments& args = TypeArguments::Handle(cls.type_parameters());
+  if (args.IsNull()) {
+    return Object::empty_array().raw();
   }
-
-  Dart_Handle names = Dart_GetTypeVariableNames(owner);
-  if (Dart_IsError(names)) {
-    return names;
+  const Array& result = Array::Handle(Array::New(args.Length() * 2));
+  TypeParameter& type = TypeParameter::Handle();
+  String& name = String::Handle();
+  for (intptr_t i = 0; i < args.Length(); i++) {
+    type ^= args.TypeAt(i);
+    ASSERT(type.IsTypeParameter());
+    name ^= type.name();
+    result.SetAt(2 * i, name);
+    result.SetAt(2 * i + 1, type);
   }
-  intptr_t len;
-  Dart_Handle result = Dart_ListLength(names, &len);
-  if (Dart_IsError(result)) {
-    return result;
-  }
-  for (intptr_t i = 0; i < len; i++) {
-    Dart_Handle type_var_name = Dart_ListGetAt(names, i);
-    Dart_Handle type_var = Dart_LookupTypeVariable(owner, type_var_name);
-    if (Dart_IsError(type_var)) {
-      return type_var;
-    }
-    ASSERT(!Dart_IsNull(type_var));
-    Dart_Handle type_var_mirror =
-        CreateTypeVariableMirrorUsingApi(type_var, type_var_name, owner_mirror);
-    if (Dart_IsError(type_var_mirror)) {
-      return type_var_mirror;
-    }
-    result = MapAdd(map, type_var_name, type_var_mirror);
-    if (Dart_IsError(result)) {
-      return result;
-    }
-  }
-  return map;
+  return result.raw();
 }
 
 
-static Dart_Handle CreateTypedefMirror(Dart_Handle cls,
-                                       Dart_Handle cls_name,
-                                       Dart_Handle owner_mirror) {
-  Dart_Handle mirror_cls_name = NewString("_LocalTypedefMirrorImpl");
-  Dart_Handle mirror_type = Dart_GetType(MirrorLib(), mirror_cls_name, 0, NULL);
-  if (Dart_IsError(mirror_type)) {
-    return mirror_type;
-  }
-
-  Dart_Handle referent = Dart_ClassGetTypedefReferent(cls);
-  if (Dart_IsError(referent)) {
-    return referent;
-  }
-
-  Dart_Handle args[] = {
-    CreateMirrorReference(cls),
-    cls_name,
-    owner_mirror,
-    CreateLazyMirror(referent),
-  };
-  Dart_Handle mirror =
-      Dart_New(mirror_type, Dart_Null(), ARRAY_SIZE(args), args);
-  return mirror;
+static RawInstance* CreateTypedefMirror(const Class& cls,
+                                        const Instance& owner_mirror) {
+  const Array& args = Array::Handle(Array::New(3));
+  args.SetAt(0, MirrorReference::Handle(MirrorReference::New(cls)));
+  args.SetAt(1, String::Handle(cls.UserVisibleName()));
+  args.SetAt(2, owner_mirror);
+  return CreateMirror(Symbols::_LocalTypedefMirrorImpl(), args);
 }
 
 
-static Dart_Handle CreateClassMirrorUsingApi(Dart_Handle intf,
-                                             Dart_Handle intf_name,
-                                             Dart_Handle lib_mirror) {
-  ASSERT(Dart_IsClass(intf));
-  if (Dart_ClassIsTypedef(intf)) {
-    // This class is actually a typedef.  Represent it specially in
-    // reflection.
-    return CreateTypedefMirror(intf, intf_name, lib_mirror);
-  }
-
-  Dart_Handle cls_name = NewString("_LocalClassMirrorImpl");
-  Dart_Handle type = Dart_GetType(MirrorLib(), cls_name, 0, NULL);
-  if (Dart_IsError(type)) {
-    return type;
-  }
-
-  Dart_Handle super_class = Dart_Null();
-  // TODO(turnidge): Simplify code, now that default classes have been removed.
-  Dart_Handle default_class = Dart_Null();
-
-  Dart_Handle intf_mirror = CreateLazyMirror(intf);
-  if (Dart_IsError(intf_mirror)) {
-    return intf_mirror;
-  }
-  Dart_Handle type_var_map = CreateTypeVariableMap(intf, intf_mirror);
-  if (Dart_IsError(type_var_map)) {
-    return type_var_map;
-  }
-
-  Dart_Handle args[] = {
-    CreateMirrorReference(intf),
-    Dart_Null(),  // "name"
-    Dart_NewBoolean(Dart_IsClass(intf)),
-    lib_mirror,
-    super_class,
-    CreateImplementsList(intf),
-    CreateLazyMirror(default_class),
-    type_var_map,
-  };
-  Dart_Handle mirror = Dart_New(type, Dart_Null(), ARRAY_SIZE(args), args);
-  return mirror;
+static RawInstance* CreateFunctionTypeMirror(const Class& cls) {
+  const Array& args = Array::Handle(Array::New(1));
+  args.SetAt(0, MirrorReference::Handle(MirrorReference::New(cls)));
+  return CreateMirror(Symbols::_LocalFunctionTypeMirrorImpl(), args);
 }
 
 
 static RawInstance* CreateMethodMirror(const Function& func,
                                        const Instance& owner_mirror) {
-  const Array& args = Array::Handle(Array::New(11));
+  const Array& args = Array::Handle(Array::New(12));
   args.SetAt(0, MirrorReference::Handle(MirrorReference::New(func)));
-  args.SetAt(1, owner_mirror);
-  args.SetAt(2, func.is_static() ? Bool::True() : Bool::False());
-  args.SetAt(3, func.is_abstract() ? Bool::True() : Bool::False());
-  args.SetAt(4, func.IsGetterFunction() ? Bool::True() : Bool::False());
-  args.SetAt(5, func.IsSetterFunction() ? Bool::True() : Bool::False());
-  args.SetAt(6, func.IsConstructor() ? Bool::True() : Bool::False());
+  args.SetAt(1, String::Handle(func.UserVisibleName()));
+  args.SetAt(2, owner_mirror);
+  args.SetAt(3, func.is_static() ? Bool::True() : Bool::False());
+  args.SetAt(4, func.is_abstract() ? Bool::True() : Bool::False());
+  args.SetAt(5, func.IsGetterFunction() ? Bool::True() : Bool::False());
+  args.SetAt(6, func.IsSetterFunction() ? Bool::True() : Bool::False());
+  args.SetAt(7, func.IsConstructor() ? Bool::True() : Bool::False());
   // TODO(mlippautz): Implement different constructor kinds.
-  args.SetAt(7, Bool::False());
   args.SetAt(8, Bool::False());
   args.SetAt(9, Bool::False());
   args.SetAt(10, Bool::False());
+  args.SetAt(11, Bool::False());
   return CreateMirror(Symbols::_LocalMethodMirrorImpl(), args);
 }
 
 
-static Dart_Handle CreateMethodMirrorUsingApi(Dart_Handle func,
-                                              Dart_Handle owner_mirror) {
-  Isolate* isolate = Isolate::Current();
-  return Api::NewHandle(isolate, CreateMethodMirror(
-      Api::UnwrapFunctionHandle(isolate, func),
-      Api::UnwrapInstanceHandle(isolate, owner_mirror)));
-}
-
 static RawInstance* CreateVariableMirror(const Field& field,
                                          const Instance& owner_mirror) {
   const MirrorReference& field_ref =
@@ -447,224 +154,34 @@
 }
 
 
-static Dart_Handle CreateLibraryMirrorUsingApi(Dart_Handle lib) {
-  Dart_Handle cls_name = NewString("_LocalLibraryMirrorImpl");
-  Dart_Handle type = Dart_GetType(MirrorLib(), cls_name, 0, NULL);
-  if (Dart_IsError(type)) {
-    return type;
-  }
-  Dart_Handle lazy_lib_mirror = CreateLazyMirror(lib);
-  if (Dart_IsError(lazy_lib_mirror)) {
-    return lazy_lib_mirror;
-  }
-  Dart_Handle args[] = {
-    CreateMirrorReference(lib),
-    Dart_LibraryName(lib),
-    Dart_LibraryUrl(lib),
-  };
-  Dart_Handle lib_mirror = Dart_New(type, Dart_Null(), ARRAY_SIZE(args), args);
-  if (Dart_IsError(lib_mirror)) {
-    return lib_mirror;
-  }
-
-  return lib_mirror;
-}
-
-
-static Dart_Handle CreateLibrariesMap() {
-  // TODO(turnidge): This should be an immutable map.
-  Dart_Handle map = MapNew();
-
-  Dart_Handle lib_ids = Dart_GetLibraryIds();
-  if (Dart_IsError(lib_ids)) {
-    return lib_ids;
-  }
-  intptr_t len;
-  Dart_Handle result = Dart_ListLength(lib_ids, &len);
-  if (Dart_IsError(result)) {
-    return result;
-  }
-  for (intptr_t i = 0; i < len; i++) {
-    Dart_Handle lib_id = Dart_ListGetAt(lib_ids, i);
-    int64_t id64;
-    Dart_IntegerToInt64(lib_id, &id64);
-    Dart_Handle lib_url = Dart_GetLibraryURL(id64);
-    if (Dart_IsError(lib_url)) {
-      return lib_url;
-    }
-    Dart_Handle lib = Dart_LookupLibrary(lib_url);
-    if (Dart_IsError(lib)) {
-      return lib;
-    }
-    Dart_Handle lib_mirror = CreateLibraryMirrorUsingApi(lib);
-    if (Dart_IsError(lib_mirror)) {
-      return lib_mirror;
-    }
-    result = MapAdd(map, lib_url, lib_mirror);
-  }
-  return map;
-}
-
-
-static Dart_Handle CreateIsolateMirror() {
-  Dart_Handle cls_name = NewString("_LocalIsolateMirrorImpl");
-  Dart_Handle type = Dart_GetType(MirrorLib(), cls_name, 0, NULL);
-  if (Dart_IsError(type)) {
-    return type;
-  }
-  Dart_Handle args[] = {
-    Dart_DebugName(),
-    CreateLazyMirror(Dart_RootLibrary()),
-  };
-  return Dart_New(type, Dart_Null(), ARRAY_SIZE(args), args);
-}
-
-
-static Dart_Handle CreateMirrorSystem() {
-  Dart_Handle cls_name = NewString("_LocalMirrorSystemImpl");
-  Dart_Handle type = Dart_GetType(MirrorLib(), cls_name, 0, NULL);
-  if (Dart_IsError(type)) {
-    return type;
-  }
-
-  Dart_Handle libraries = CreateLibrariesMap();
-  if (Dart_IsError(libraries)) {
-    return libraries;
-  }
-
-  Dart_Handle args[] = {
-    libraries,
-    CreateIsolateMirror(),
-  };
-  Dart_Handle mirror = Dart_New(type, Dart_Null(), ARRAY_SIZE(args), args);
-  if (Dart_IsError(mirror)) {
-    return mirror;
-  }
-
-  return mirror;
-}
-
-
-static Dart_Handle CreateNullMirror() {
-  Dart_Handle cls_name = NewString("_LocalInstanceMirrorImpl");
-  Dart_Handle type = Dart_GetType(MirrorLib(), cls_name, 0, NULL);
-  if (Dart_IsError(type)) {
-    return type;
-  }
-
-  // TODO(turnidge): This is wrong.  The Null class is distinct from object.
-  Dart_Handle object_class = Dart_GetClass(CoreLib(), NewString("Object"));
-
-  Dart_Handle args[] = {
-    CreateLazyMirror(object_class),
-    Dart_Null(),
-  };
-  Dart_Handle mirror = Dart_New(type, Dart_Null(), ARRAY_SIZE(args), args);
-  return mirror;
-}
-
-
-static Dart_Handle CreateInstanceMirror(Dart_Handle instance) {
-  if (Dart_IsNull(instance)) {
-    return CreateNullMirror();
-  }
-  ASSERT(Dart_IsInstance(instance));
-
-  Dart_Handle instance_cls = Dart_InstanceGetClass(instance);
-  if (Dart_IsError(instance_cls)) {
-    return instance_cls;
-  }
-
-  if (Dart_IsClosure(instance)) {
-    Dart_Handle cls_name = NewString("_LocalClosureMirrorImpl");
-    Dart_Handle type = Dart_GetType(MirrorLib(), cls_name, 0, NULL);
-    if (Dart_IsError(type)) {
-      return type;
-    }
-    // We set the function field of ClosureMirrors outside of the constructor
-    // to break the mutual recursion.
-    Dart_Handle func = Dart_ClosureFunction(instance);
-    if (Dart_IsError(func)) {
-      return func;
-    }
-
-    // TODO(turnidge): Why not use the real function name here?
-    Dart_Handle func_owner = Dart_FunctionOwner(func);
-    if (Dart_IsError(func_owner)) {
-      return func_owner;
-    }
-
-    // TODO(turnidge): Pass the function owner here.  This will require
-    // us to support functions in CreateLazyMirror.
-    Dart_Handle func_mirror =
-        CreateMethodMirrorUsingApi(func, Dart_Null());
-    if (Dart_IsError(func_mirror)) {
-      return func_mirror;
-    }
-    Dart_Handle args[] = {
-      CreateLazyMirror(instance_cls),
-      instance,
-      func_mirror,
-    };
-    return Dart_New(type, Dart_Null(), ARRAY_SIZE(args), args);
-
-  } else {
-    Dart_Handle cls_name = NewString("_LocalInstanceMirrorImpl");
-    Dart_Handle type = Dart_GetType(MirrorLib(), cls_name, 0, NULL);
-    if (Dart_IsError(type)) {
-      return type;
-    }
-    Dart_Handle args[] = {
-      CreateLazyMirror(instance_cls),
-      instance,
-    };
-    return Dart_New(type, Dart_Null(), ARRAY_SIZE(args), args);
-  }
-}
-
-
 static RawInstance* CreateClassMirror(const Class& cls,
                                       const Instance& owner_mirror) {
-  Instance& retvalue = Instance::Handle();
-  Dart_EnterScope();
-  Isolate* isolate = Isolate::Current();
-  Dart_Handle cls_handle = Api::NewHandle(isolate, cls.raw());
-  if (Dart_IsError(cls_handle)) {
-    Dart_PropagateError(cls_handle);
+  if (cls.IsSignatureClass()) {
+    if (cls.IsCanonicalSignatureClass()) {
+      // We represent function types as canonical signature classes.
+      return CreateFunctionTypeMirror(cls);
+    } else {
+      // We represent typedefs as non-canonical signature classes.
+      return CreateTypedefMirror(cls, owner_mirror);
+    }
   }
-  Dart_Handle name_handle = Api::NewHandle(isolate, cls.Name());
-  if (Dart_IsError(name_handle)) {
-    Dart_PropagateError(name_handle);
-  }
-  Dart_Handle lib_mirror = Api::NewHandle(isolate, owner_mirror.raw());
-  // TODO(11742): At some point the handle calls will be replaced by inlined
-  // functionality.
-  Dart_Handle result =  CreateClassMirrorUsingApi(cls_handle,
-                                                  name_handle,
-                                                  lib_mirror);
-  if (Dart_IsError(result)) {
-    Dart_PropagateError(result);
-  }
-  retvalue ^= Api::UnwrapHandle(result);
-  Dart_ExitScope();
-  return retvalue.raw();
+
+  const Array& args = Array::Handle(Array::New(2));
+  args.SetAt(0, MirrorReference::Handle(MirrorReference::New(cls)));
+  args.SetAt(1, String::Handle(cls.UserVisibleName()));
+  return CreateMirror(Symbols::_LocalClassMirrorImpl(), args);
 }
 
 
 static RawInstance* CreateLibraryMirror(const Library& lib) {
-  Instance& retvalue = Instance::Handle();
-  Dart_EnterScope();
-  Isolate* isolate = Isolate::Current();
-  Dart_Handle lib_handle = Api::NewHandle(isolate, lib.raw());
-  // TODO(11742): At some point the handle calls will be replaced by inlined
-  // functionality.
-  Dart_Handle result = CreateLibraryMirrorUsingApi(lib_handle);
-  if (Dart_IsError(result)) {
-    Dart_PropagateError(result);
-  }
-  retvalue ^= Api::UnwrapHandle(result);
-  Dart_ExitScope();
-  return retvalue.raw();
+  const Array& args = Array::Handle(Array::New(3));
+  args.SetAt(0, MirrorReference::Handle(MirrorReference::New(lib)));
+  String& str = String::Handle();
+  str = lib.name();
+  args.SetAt(1, str);
+  str = lib.url();
+  args.SetAt(2, str);
+  return CreateMirror(Symbols::_LocalLibraryMirrorImpl(), args);
 }
 
 
@@ -694,58 +211,55 @@
 }
 
 
-void NATIVE_ENTRY_FUNCTION(Mirrors_makeLocalMirrorSystem)(
-    Dart_NativeArguments args) {
-  Dart_EnterScope();
-  Dart_Handle mirrors = CreateMirrorSystem();
-  if (Dart_IsError(mirrors)) {
-    Dart_PropagateError(mirrors);
-  }
-  Dart_SetReturnValue(args, mirrors);
-  Dart_ExitScope();
-}
-
-
-void NATIVE_ENTRY_FUNCTION(Mirrors_makeLocalInstanceMirror)(
-    Dart_NativeArguments args) {
-  Dart_EnterScope();
-  Dart_Handle reflectee = Dart_GetNativeArgument(args, 0);
-  Dart_Handle mirror = CreateInstanceMirror(reflectee);
-  if (Dart_IsError(mirror)) {
-    Dart_PropagateError(mirror);
-  }
-  Dart_SetReturnValue(args, mirror);
-  Dart_ExitScope();
-}
-
-
-void NATIVE_ENTRY_FUNCTION(Mirrors_makeLocalClassMirror)(
-    Dart_NativeArguments args) {
-  Dart_EnterScope();
+static RawInstance* CreateIsolateMirror() {
   Isolate* isolate = Isolate::Current();
-  Dart_Handle key = Dart_GetNativeArgument(args, 0);
-  if (Dart_IsError(key)) {
-    Dart_PropagateError(key);
+  const String& debug_name = String::Handle(String::New(isolate->name()));
+  const Library& root_library =
+      Library::Handle(isolate, isolate->object_store()->root_library());
+  const Instance& root_library_mirror =
+      Instance::Handle(CreateLibraryMirror(root_library));
+
+  const Array& args = Array::Handle(Array::New(2));
+  args.SetAt(0, debug_name);
+  args.SetAt(1, root_library_mirror);
+  return CreateMirror(Symbols::_LocalIsolateMirrorImpl(), args);
+}
+
+
+static RawInstance* CreateMirrorSystem() {
+  Isolate* isolate = Isolate::Current();
+  const GrowableObjectArray& libraries =
+      GrowableObjectArray::Handle(isolate->object_store()->libraries());
+
+  const int num_libraries = libraries.Length();
+  const Array& library_mirrors = Array::Handle(Array::New(num_libraries));
+  Library& library = Library::Handle();
+  Instance& library_mirror = Instance::Handle();
+
+  for (int i = 0; i < num_libraries; i++) {
+    library ^= libraries.At(i);
+    library_mirror = CreateLibraryMirror(library);
+    library_mirrors.SetAt(i, library_mirror);
   }
-  const Type& type = Api::UnwrapTypeHandle(isolate, key);
+
+  const Instance& isolate_mirror = Instance::Handle(CreateIsolateMirror());
+
+  const Array& args = Array::Handle(Array::New(2));
+  args.SetAt(0, library_mirrors);
+  args.SetAt(1, isolate_mirror);
+  return CreateMirror(Symbols::_LocalMirrorSystemImpl(), args);
+}
+
+
+DEFINE_NATIVE_ENTRY(Mirrors_makeLocalMirrorSystem, 0) {
+  return CreateMirrorSystem();
+}
+
+
+DEFINE_NATIVE_ENTRY(Mirrors_makeLocalClassMirror, 1) {
+  GET_NON_NULL_NATIVE_ARGUMENT(Type, type, arguments->NativeArgAt(0));
   const Class& cls = Class::Handle(type.type_class());
-  Dart_Handle cls_handle = Api::NewHandle(isolate, cls.raw());
-  if (Dart_IsError(cls_handle)) {
-    Dart_PropagateError(cls_handle);
-  }
-  Dart_Handle name_handle = Api::NewHandle(isolate, cls.Name());
-  if (Dart_IsError(name_handle)) {
-    Dart_PropagateError(name_handle);
-  }
-  Dart_Handle lib_mirror = Dart_Null();
-  Dart_Handle result = CreateClassMirrorUsingApi(cls_handle,
-                                                 name_handle,
-                                                 lib_mirror);
-  if (Dart_IsError(result)) {
-    Dart_PropagateError(result);
-  }
-  Dart_SetReturnValue(args, result);
-  Dart_ExitScope();
+  return CreateClassMirror(cls, Object::null_instance());
 }
 
 
@@ -771,6 +285,13 @@
 }
 
 
+DEFINE_NATIVE_ENTRY(MirrorReference_equals, 2) {
+  GET_NON_NULL_NATIVE_ARGUMENT(MirrorReference, a, arguments->NativeArgAt(0));
+  GET_NON_NULL_NATIVE_ARGUMENT(MirrorReference, b, arguments->NativeArgAt(1));
+  return Bool::Get(a.referent() == b.referent());
+}
+
+
 DEFINE_NATIVE_ENTRY(DeclarationMirror_metadata, 1) {
   const MirrorReference& decl_ref =
       MirrorReference::CheckedHandle(arguments->NativeArgAt(0));
@@ -796,10 +317,20 @@
 }
 
 
-void HandleMirrorsMessage(Isolate* isolate,
-                          Dart_Port reply_port,
-                          const Instance& message) {
-  UNIMPLEMENTED();
+DEFINE_NATIVE_ENTRY(FunctionTypeMirror_parameters, 1) {
+  GET_NON_NULL_NATIVE_ARGUMENT(MirrorReference, ref, arguments->NativeArgAt(0));
+  const Class& cls = Class::Handle(ref.GetClassReferent());
+  const Function& func = Function::Handle(cls.signature_function());
+  return CreateParameterMirrorList(func);
+}
+
+
+DEFINE_NATIVE_ENTRY(FunctionTypeMirror_return_type, 1) {
+  GET_NON_NULL_NATIVE_ARGUMENT(MirrorReference, ref, arguments->NativeArgAt(0));
+  const Class& cls = Class::Handle(ref.GetClassReferent());
+  const Function& func = Function::Handle(cls.signature_function());
+  const AbstractType& return_type = AbstractType::Handle(func.result_type());
+  return CreateTypeMirror(return_type);
 }
 
 
@@ -835,6 +366,20 @@
   return klass.super_type();
 }
 
+
+DEFINE_NATIVE_ENTRY(ClassMirror_interfaces, 1) {
+  GET_NON_NULL_NATIVE_ARGUMENT(MirrorReference, ref, arguments->NativeArgAt(0));
+  const Class& klass = Class::Handle(ref.GetClassReferent());
+
+  const Error& error = Error::Handle(klass.EnsureIsFinalized(isolate));
+  if (!error.IsNull()) {
+    ThrowInvokeError(error);
+  }
+
+  return klass.interfaces();
+}
+
+
 DEFINE_NATIVE_ENTRY(ClassMirror_members, 2) {
   GET_NON_NULL_NATIVE_ARGUMENT(Instance,
                                owner_mirror,
@@ -965,6 +510,26 @@
 }
 
 
+DEFINE_NATIVE_ENTRY(ClassMirror_type_variables, 1) {
+  GET_NON_NULL_NATIVE_ARGUMENT(MirrorReference, ref, arguments->NativeArgAt(0));
+  const Class& klass = Class::Handle(ref.GetClassReferent());
+  return CreateTypeVariableList(klass);
+}
+
+
+DEFINE_NATIVE_ENTRY(LocalTypeVariableMirror_owner, 1) {
+  GET_NON_NULL_NATIVE_ARGUMENT(TypeParameter, param, arguments->NativeArgAt(0));
+  return CreateClassMirror(Class::Handle(param.parameterized_class()),
+                           Instance::null_instance());
+}
+
+
+DEFINE_NATIVE_ENTRY(LocalTypeVariableMirror_upper_bound, 1) {
+  GET_NON_NULL_NATIVE_ARGUMENT(TypeParameter, param, arguments->NativeArgAt(0));
+  return CreateTypeMirror(AbstractType::Handle(param.bound()));
+}
+
+
 // Invoke the function, or noSuchMethod if it is null. Propagate any unhandled
 // exceptions. Wrap and propagate any compilation errors.
 static RawObject* ReflectivelyInvokeDynamicFunction(const Instance& receiver,
@@ -1016,11 +581,21 @@
 
   ArgumentsDescriptor args_desc(
       Array::Handle(ArgumentsDescriptor::New(args.Length())));
-  // TODO(11771): This won't find private members.
-  const Function& function = Function::Handle(
-      Resolver::ResolveDynamic(reflectee,
-                               function_name,
-                               args_desc));
+
+  Class& klass = Class::Handle(reflectee.clazz());
+  Function& function = Function::Handle();
+  while (!klass.IsNull()) {
+    function = klass.LookupDynamicFunctionAllowPrivate(function_name);
+    if (!function.IsNull()) {
+      break;
+    }
+    klass = klass.SuperClass();
+  }
+
+  if (!function.IsNull() &&
+      !function.AreValidArguments(args_desc, NULL)) {
+    function = Function::null();
+  }
 
   return ReflectivelyInvokeDynamicFunction(reflectee,
                                            function,
@@ -1134,6 +709,15 @@
 }
 
 
+DEFINE_NATIVE_ENTRY(ClosureMirror_function, 1) {
+  GET_NON_NULL_NATIVE_ARGUMENT(Instance, closure, arguments->NativeArgAt(0));
+  ASSERT(closure.IsClosure());
+
+  const Function& func = Function::Handle(Closure::function(closure));
+  return CreateMethodMirror(func, Instance::null_instance());
+}
+
+
 static void ThrowNoSuchMethod(const Instance& receiver,
                               const String& function_name,
                               const Function& function,
@@ -1544,13 +1128,6 @@
 }
 
 
-DEFINE_NATIVE_ENTRY(MethodMirror_name, 1) {
-  GET_NON_NULL_NATIVE_ARGUMENT(MirrorReference, ref, arguments->NativeArgAt(0));
-  const Function& func = Function::Handle(ref.GetFunctionReferent());
-  return func.UserVisibleName();
-}
-
-
 DEFINE_NATIVE_ENTRY(MethodMirror_owner, 1) {
   GET_NON_NULL_NATIVE_ARGUMENT(MirrorReference, ref, arguments->NativeArgAt(0));
   const Function& func = Function::Handle(ref.GetFunctionReferent());
@@ -1583,6 +1160,15 @@
 }
 
 
+DEFINE_NATIVE_ENTRY(TypedefMirror_referent, 1) {
+  GET_NON_NULL_NATIVE_ARGUMENT(MirrorReference, ref, arguments->NativeArgAt(0));
+  const Class& cls = Class::Handle(ref.GetClassReferent());
+  const Function& sig_func = Function::Handle(cls.signature_function());
+  const Class& sig_cls = Class::Handle(sig_func.signature_class());
+  return MirrorReference::New(sig_cls);
+}
+
+
 DEFINE_NATIVE_ENTRY(ParameterMirror_type, 2) {
   GET_NON_NULL_NATIVE_ARGUMENT(MirrorReference, ref, arguments->NativeArgAt(0));
   GET_NON_NULL_NATIVE_ARGUMENT(Smi, pos, arguments->NativeArgAt(1));
diff --git a/runtime/lib/mirrors_impl.dart b/runtime/lib/mirrors_impl.dart
index 80d2ea4..5fb76c7 100644
--- a/runtime/lib/mirrors_impl.dart
+++ b/runtime/lib/mirrors_impl.dart
@@ -4,6 +4,8 @@
 
 // VM-specific implementation of the dart:mirrors library.
 
+import "dart:collection";
+
 // These values are allowed to be passed directly over the wire.
 bool _isSimpleValue(var value) {
   return (value == null || value is num || value is String || value is bool);
@@ -68,12 +70,10 @@
   return buf.toString();
 }
 
-Map<Uri, LibraryMirror> _createLibrariesMap(Map<String, LibraryMirror> map) {
-    var result = new Map<Uri, LibraryMirror>();
-    map.forEach((String url, LibraryMirror mirror) {
-      result[Uri.parse(url)] = mirror;
-    });
-    return result;
+Map<Uri, LibraryMirror> _createLibrariesMap(List<LibraryMirror> list) {
+  var map = new Map<Uri, LibraryMirror>();
+  list.forEach((LibraryMirror mirror) => map[mirror.uri] = mirror);
+  return map;
 }
 
 List _metadata(reflectee)
@@ -98,9 +98,8 @@
 
 class _LocalMirrorSystemImpl extends MirrorSystem {
   // Change parameter back to "this.libraries" when native code is changed.
-  _LocalMirrorSystemImpl(Map<String, LibraryMirror> libraries, this.isolate)
-      : this.libraries = _createLibrariesMap(libraries),
-        _functionTypes = new Map<String, FunctionTypeMirror>();
+  _LocalMirrorSystemImpl(List<LibraryMirror> libraries, this.isolate)
+      : this.libraries = _createLibrariesMap(libraries);
 
   final Map<Uri, LibraryMirror> libraries;
   final IsolateMirror isolate;
@@ -123,22 +122,6 @@
     return _voidType;
   }
 
-  final Map<String, FunctionTypeMirror> _functionTypes;
-  FunctionTypeMirror _lookupFunctionTypeMirror(
-      TypeMirror returnType,
-      List<ParameterMirror> parameters) {
-    var sigString = _makeSignatureString(returnType, parameters);
-    var mirror = _functionTypes[sigString];
-    if (mirror == null) {
-      mirror = new _LocalFunctionTypeMirrorImpl(null,
-                                                sigString,
-                                                returnType,
-                                                parameters);
-      _functionTypes[sigString] = mirror;
-    }
-    return mirror;
-  }
-
   String toString() => "MirrorSystem for isolate '${isolate.debugName}'";
 }
 
@@ -154,18 +137,11 @@
 
 class _LocalIsolateMirrorImpl extends _LocalMirrorImpl
     implements IsolateMirror {
-  _LocalIsolateMirrorImpl(this.debugName, this._rootLibrary) {}
+  _LocalIsolateMirrorImpl(this.debugName, this.rootLibrary) {}
 
   final String debugName;
   final bool isCurrent = true;
-
-  var _rootLibrary;
-  LibraryMirror get rootLibrary {
-    if (_rootLibrary is _LazyLibraryMirror) {
-      _rootLibrary = _rootLibrary.resolve(mirrors);
-    }
-    return _rootLibrary;
-  }
+  final LibraryMirror rootLibrary;
 
   String toString() => "IsolateMirror on '$debugName'";
 }
@@ -268,13 +244,14 @@
   // TODO(ahe): This is a hack, see delegate below.
   static Function _invokeOnClosure;
 
-  _LocalInstanceMirrorImpl(this._type,
-                           reflectee) : super(reflectee) {}
+  _LocalInstanceMirrorImpl(reflectee) : super(reflectee);
 
-  var _type;
+  ClassMirror _type;
   ClassMirror get type {
-    if (_type is! Mirror) {
-      _type = _type.resolve(mirrors);
+    if (_type == null) {
+      // Note it not safe to use reflectee.runtimeType because runtimeType may
+      // be overridden.
+      _type = reflectClass(_computeType(reflectee));
     }
     return _type;
   }
@@ -292,15 +269,22 @@
       // private method does not work.
       
       _LocalInstanceMirrorImpl mirror =
-          _Mirrors.makeLocalInstanceMirror(invocation);
-      _invokeOnClosure =
-          reflectClass(invocation.runtimeType).getField(const Symbol('_invokeOnClosure')).reflectee;
+          reflect(invocation);
+      _invokeOnClosure = reflectClass(invocation.runtimeType)
+          .getField(const Symbol('_invokeOnClosure')).reflectee;
     }
     return _invokeOnClosure(reflectee, invocation);
   }
 
   String toString() => 'InstanceMirror on ${Error.safeToString(_reflectee)}';
 
+  bool operator ==(other) {
+    return other is _LocalInstanceMirrorImpl &&
+           identical(_reflectee, other._reflectee);
+  }
+
+  int get hashCode => _reflectee.hashCode;
+
   _invoke(reflectee, functionName, positionalArguments)
       native 'InstanceMirror_invoke';
 
@@ -309,15 +293,22 @@
 
   _invokeSetter(reflectee, setterName, value)
       native 'InstanceMirror_invokeSetter';
+
+  static _computeType(reflectee)
+      native 'Object_runtimeType';
 }
 
 class _LocalClosureMirrorImpl extends _LocalInstanceMirrorImpl
     implements ClosureMirror {
-  _LocalClosureMirrorImpl(type,
-                          reflectee,
-                          this.function) : super(type, reflectee) {}
+  _LocalClosureMirrorImpl(reflectee) : super(reflectee);
 
-  final MethodMirror function;
+  MethodMirror _function;
+  MethodMirror get function {
+    if (_function == null) {
+      _function = _computeFunction(reflectee);
+    }
+    return _function;
+  }
 
   String get source {
     throw new UnimplementedError(
@@ -352,58 +343,25 @@
     }
   }
 
-
-
   Future<InstanceMirror> findInContext(Symbol name) {
     throw new UnimplementedError(
         'ClosureMirror.findInContext() is not implemented');
   }
 
+  String toString() => "ClosureMirror on '${Error.safeToString(_reflectee)}'";
+
   static _apply(reflectee, positionalArguments)
       native 'ClosureMirror_apply';
 
-  String toString() => "ClosureMirror on '${Error.safeToString(_reflectee)}'";
-}
-
-class _LazyTypeMirror {
-  _LazyTypeMirror(String this.libraryUrl, String typeName)
-      : this.typeName = _s(typeName);
-
-  TypeMirror resolve(MirrorSystem mirrors) {
-    if (libraryUrl == null) {
-      if (typeName == const Symbol('dynamic')) {
-        return mirrors.dynamicType;
-      } else if (typeName == const Symbol('void')) {
-        return mirrors.voidType;
-      } else {
-        throw new UnimplementedError(
-            "Mirror for type '$typeName' is not implemented");
-      }
-    }
-    var resolved = mirrors.libraries[Uri.parse(libraryUrl)].members[typeName];
-    if (resolved == null) {
-      throw new UnimplementedError(
-          "Mirror for type '$typeName' is not implemented");
-    }
-    return resolved;
-  }
-
-  final String libraryUrl;
-  final Symbol typeName;
+  static _computeFunction(reflectee)
+      native 'ClosureMirror_function';
 }
 
 class _LocalClassMirrorImpl extends _LocalObjectMirrorImpl
     implements ClassMirror {
   _LocalClassMirrorImpl(reflectee,
-                        String simpleName,
-                        this.isClass,
-                        this._owner,
-                        this._superclass,
-                        this._superinterfaces,
-                        this._defaultFactory,
-                        Map<String, Mirror> typeVariables)
+                        String simpleName)
       : this._simpleName = _s(simpleName),
-        this.typeVariables = _convertStringToSymbolMap(typeVariables),
         super(reflectee);
 
   Symbol _simpleName;
@@ -429,9 +387,6 @@
     if (_owner == null) {
       _owner = _library(_reflectee);
     }
-    if (_owner is! Mirror) {
-      _owner = _owner.resolve(mirrors);
-    }
     return _owner;
   }
 
@@ -444,9 +399,12 @@
         'ClassMirror.location is not implemented');
   }
 
-  final bool isClass;
+  // TODO(rmacnak): Remove these left-overs from the days of separate interfaces
+  // once we send out a breaking change.
+  bool get isClass => true;
+  ClassMirror get defaultFactory => null;
 
-  var _superclass;
+  ClassMirror _superclass;
   ClassMirror get superclass {
     if (_superclass == null) {
       Type supertype = _supertype(_reflectee);
@@ -456,33 +414,18 @@
       }
       _superclass = reflectClass(supertype);
     }
-    if (_superclass is! Mirror) {
-      _superclass = _superclass.resolve(mirrors);
-    }
     return _superclass;
   }
 
   var _superinterfaces;
   List<ClassMirror> get superinterfaces {
-    if (_superinterfaces.length > 0 &&
-        _superinterfaces[0] is! Mirror) {
-      List<ClassMirror> resolved = new List<ClassMirror>();
-      for (int i = 0; i < _superinterfaces.length; i++) {
-        resolved.add(_superinterfaces[i].resolve(mirrors));
-      }
-      _superinterfaces = resolved;
+    if (_superinterfaces == null) {
+      _superinterfaces = _interfaces(_reflectee)
+          .map((i) => reflectClass(i)).toList(growable:false);
     }
     return _superinterfaces;
   }
 
-  var _defaultFactory;
-  ClassMirror get defaultFactory {
-    if (_defaultFactory != null && _defaultFactory is! Mirror) {
-      _defaultFactory = _defaultFactory.resolve(mirrors);
-    }
-    return _defaultFactory;
-  }
-
   Map<Symbol, Mirror> _members;
 
   Map<Symbol, Mirror> get members {
@@ -542,7 +485,21 @@
     return _constructors;
   }
 
-  Map<Symbol, TypeVariableMirror> typeVariables;
+  Map<Symbol, TypeVariableMirror> _typeVariables = null;
+
+  Map<Symbol, TypeVariableMirror> get typeVariables {
+    if (_typeVariables == null) {
+      List params = _ClassMirror_type_variables(_reflectee);
+      _typeVariables = new LinkedHashMap<Symbol, TypeVariableMirror>();
+      var mirror;
+      for (var i = 0; i < params.length; i += 2) {
+        mirror = new _LocalTypeVariableMirrorImpl(
+            params[i + 1], params[i], this);
+        _typeVariables[mirror.simpleName] = mirror;
+      }
+    }
+    return _typeVariables;
+  }
 
   Map<Symbol, TypeMirror> get typeArguments {
     throw new UnimplementedError(
@@ -560,8 +517,7 @@
   }
 
   String toString() {
-    String prettyName = isClass ? 'ClassMirror' : 'TypeMirror';
-    return "$prettyName on '${_n(simpleName)}'";
+    return "ClassMirror on '${_n(simpleName)}'";
   }
 
   InstanceMirror newInstance(Symbol constructorName,
@@ -600,6 +556,13 @@
     return _metadata(_reflectee).map(reflect).toList(growable:false);
   }
 
+  bool operator ==(other) {
+    return this.runtimeType == other.runtimeType &&
+           this._reflectee == other._reflectee;
+  }
+
+  int get hashCode => simpleName.hashCode;
+
   static _name(reflectee)
       native "ClassMirror_name";
 
@@ -609,6 +572,9 @@
   static _supertype(reflectee)
       native "ClassMirror_supertype";
 
+  static _interfaces(reflectee)
+      native "ClassMirror_interfaces";
+
   _computeMembers(reflectee)
       native "ClassMirror_members";
   
@@ -626,84 +592,58 @@
 
   static _invokeConstructor(reflectee, constructorName, positionalArguments)
       native 'ClassMirror_invokeConstructor';
-}
 
-class _LazyFunctionTypeMirror {
-  _LazyFunctionTypeMirror(this.returnType, this.parameters) {}
-
-  ClassMirror resolve(MirrorSystem mirrors) {
-    return mirrors._lookupFunctionTypeMirror(returnType.resolve(mirrors),
-                                             parameters);
-  }
-
-  final returnType;
-  final List<ParameterMirror> parameters;
+  static _ClassMirror_type_variables(reflectee)
+      native "ClassMirror_type_variables";
 }
 
 class _LocalFunctionTypeMirrorImpl extends _LocalClassMirrorImpl
     implements FunctionTypeMirror {
-  _LocalFunctionTypeMirrorImpl(reflectee,
-                               simpleName,
-                               this._returnType,
-                               this.parameters)
-      : super(reflectee,
-              simpleName,
-              true,
-              null,
-              new _LazyTypeMirror('dart:core', 'Object'),
-              [ new _LazyTypeMirror('dart:core', 'Function') ],
-              null,
-              const {});
+  _LocalFunctionTypeMirrorImpl(reflectee) : super(reflectee, null);
 
-  Map<Symbol, Mirror> get members => new Map<Symbol,Mirror>();
-  Map<Symbol, MethodMirror> get constructors => new Map<Symbol,MethodMirror>();
+  // FunctionTypeMirrors have a simpleName generated from their signature.
+  Symbol _simpleName = null;
+  Symbol get simpleName {
+    if (_simpleName == null) {
+      _simpleName = _s(_makeSignatureString(returnType, parameters));
+    }
+    return _simpleName;
+  }
 
-  var _returnType;
+  TypeMirror _returnType = null;
   TypeMirror get returnType {
-    if (_returnType is! Mirror) {
-      _returnType = _returnType.resolve(mirrors);
+    if (_returnType == null) {
+      _returnType = _FunctionTypeMirror_return_type(_reflectee);
     }
     return _returnType;
   }
 
-  final List<ParameterMirror> parameters;
+  List<ParameterMirror> _parameters = null;
+  List<ParameterMirror> get parameters {
+    if (_parameters == null) {
+      _parameters = _FunctionTypeMirror_parameters(_reflectee);
+    }
+    return _parameters;
+  }
+
+  Map<Symbol, Mirror> get members => new Map<Symbol,Mirror>();
+  Map<Symbol, MethodMirror> get constructors => new Map<Symbol,MethodMirror>();
+  final Map<Symbol, TypeVariableMirror> typeVariables = const {};
 
   String toString() => "FunctionTypeMirror on '${_n(simpleName)}'";
+
+  static TypeMirror _FunctionTypeMirror_return_type(reflectee)
+      native "FunctionTypeMirror_return_type";
+
+  static List<ParameterMirror> _FunctionTypeMirror_parameters(reflectee)
+      native "FunctionTypeMirror_parameters";
 }
 
 abstract class _LocalDeclarationMirrorImpl extends _LocalMirrorImpl
     implements DeclarationMirror {
-    _LocalDeclarationMirrorImpl(this._reflectee);
-    final _MirrorReference _reflectee;
+  _LocalDeclarationMirrorImpl(this._reflectee, this.simpleName);
 
-    List<InstanceMirror> get metadata {
-      // Get the metadata objects, convert them into InstanceMirrors using
-      // reflect() and then make them into a Dart list.
-      return _metadata(_reflectee).map(reflect).toList(growable:false);
-    }
-}
-
-class _LazyTypeVariableMirror {
-  _LazyTypeVariableMirror(String variableName, this._owner)
-      : this._variableName = _s(variableName);
-
-  TypeVariableMirror resolve(MirrorSystem mirrors) {
-    ClassMirror owner = _owner.resolve(mirrors);
-    return owner.typeVariables[_variableName];
-  }
-
-  final Symbol _variableName;
-  final _LazyTypeMirror _owner;
-}
-
-class _LocalTypeVariableMirrorImpl extends _LocalDeclarationMirrorImpl
-    implements TypeVariableMirror {
-  _LocalTypeVariableMirrorImpl(reflectee,
-                               String simpleName,
-                               this._owner,
-                               this._upperBound)
-      : this.simpleName = _s(simpleName),
-        super(reflectee);
+  final _reflectee;
 
   final Symbol simpleName;
 
@@ -715,10 +655,31 @@
     return _qualifiedName;
   }
 
-  var _owner;
+  List<InstanceMirror> get metadata {
+    // Get the metadata objects, convert them into InstanceMirrors using
+    // reflect() and then make them into a Dart list.
+    return _metadata(_reflectee).map(reflect).toList(growable:false);
+  }
+
+  bool operator ==(other) {
+    return this.runtimeType == other.runtimeType &&
+           this._reflectee == other._reflectee; 
+  }
+
+  int get hashCode => simpleName.hashCode;
+}
+
+class _LocalTypeVariableMirrorImpl extends _LocalDeclarationMirrorImpl
+    implements TypeVariableMirror {
+  _LocalTypeVariableMirrorImpl(reflectee,
+                               String simpleName,
+                               this._owner)
+      : super(reflectee, _s(simpleName));
+
+  DeclarationMirror _owner;
   DeclarationMirror get owner {
-    if (_owner is! Mirror) {
-      _owner = _owner.resolve(mirrors);
+    if (_owner == null) {
+      _owner = _LocalTypeVariableMirror_owner(_reflectee);
     }
     return _owner;
   }
@@ -732,10 +693,10 @@
         'TypeVariableMirror.location is not implemented');
   }
 
-  var _upperBound;
+  TypeMirror _upperBound = null;
   TypeMirror get upperBound {
-    if (_upperBound is! Mirror) {
-      _upperBound = _upperBound.resolve(mirrors);
+    if (_upperBound == null) {
+      _upperBound = _LocalTypeVariableMirror_upper_bound(_reflectee);
     }
     return _upperBound;
   }
@@ -746,6 +707,12 @@
   }
 
   String toString() => "TypeVariableMirror on '${_n(simpleName)}'";
+
+  static DeclarationMirror _LocalTypeVariableMirror_owner(reflectee)
+      native "LocalTypeVariableMirror_owner";
+
+  static TypeMirror _LocalTypeVariableMirror_upper_bound(reflectee)
+      native "LocalTypeVariableMirror_upper_bound";
 }
 
 
@@ -753,29 +720,14 @@
     implements TypedefMirror {
   _LocalTypedefMirrorImpl(reflectee,
                           String simpleName,
-                          this._owner,
-                          this._referent)
-      : this.simpleName = _s(simpleName),
-        super(reflectee);
+                          this._owner)
+      : super(reflectee, _s(simpleName));
 
-  final Symbol simpleName;
-
-  Symbol _qualifiedName = null;
-  Symbol get qualifiedName {
-    if (_qualifiedName == null) {
-      _qualifiedName = _computeQualifiedName(owner, simpleName);
-    }
-    return _qualifiedName;
-  }
-
-  var _owner;
+  DeclarationMirror _owner;
   DeclarationMirror get owner {
     if (_owner == null) {
       _owner = _LocalClassMirrorImpl._library(_reflectee);
     }
-    if (_owner is! Mirror) {
-      _owner = _owner.resolve(mirrors);
-    }
     return _owner;
   }
 
@@ -788,26 +740,19 @@
         'TypedefMirror.location is not implemented');
   }
 
-  var _referent;
+  TypeMirror _referent = null;
   TypeMirror get referent {
-    if (_referent is! Mirror) {
-      _referent = _referent.resolve(mirrors);
+    if (_referent == null) {
+      return new _LocalFunctionTypeMirrorImpl(
+          _TypedefMirror_referent(_reflectee));
     }
     return _referent;
   }
 
   String toString() => "TypedefMirror on '${_n(simpleName)}'";
-}
 
-
-class _LazyLibraryMirror {
-  _LazyLibraryMirror(String this.libraryUrl);
-
-  LibraryMirror resolve(MirrorSystem mirrors) {
-    return mirrors.libraries[Uri.parse(libraryUrl)];
-  }
-
-  final String libraryUrl;
+  static _TypedefMirror_referent(_reflectee)
+      native "TypedefMirror_referent";
 }
 
 class _LocalLibraryMirrorImpl extends _LocalObjectMirrorImpl
@@ -903,6 +848,13 @@
 
   String toString() => "LibraryMirror on '${_n(simpleName)}'";
 
+  bool operator ==(other) {
+    return this.runtimeType == other.runtimeType &&
+           this._reflectee == other._reflectee; 
+  }
+
+  int get hashCode => simpleName.hashCode;
+
   _invoke(reflectee, memberName, positionalArguments)
       native 'LibraryMirror_invoke';
 
@@ -919,6 +871,7 @@
 class _LocalMethodMirrorImpl extends _LocalDeclarationMirrorImpl
     implements MethodMirror {
   _LocalMethodMirrorImpl(reflectee,
+                         String simpleName,
                          this._owner,
                          this.isStatic,
                          this.isAbstract,
@@ -928,35 +881,16 @@
                          this.isConstConstructor,
                          this.isGenerativeConstructor,
                          this.isRedirectingConstructor,
-                         this.isFactoryConstructor) : super(reflectee);
+                         this.isFactoryConstructor)
+      : super(reflectee, _s(simpleName));
 
-  Symbol _simpleName = null;
-  Symbol get simpleName {
-    if (_simpleName == null) {
-      _simpleName = _s(_MethodMirror_name(_reflectee));
-    }
-    return _simpleName;
-  }
-
-  Symbol _qualifiedName = null;
-  Symbol get qualifiedName {
-    if (_qualifiedName == null) {
-      _qualifiedName = _computeQualifiedName(owner, simpleName);
-    }
-    return _qualifiedName;
-  }
-
-  var _owner;
+  DeclarationMirror _owner;
   DeclarationMirror get owner {
     // For nested closures it is possible, that the mirror for the owner has not
     // been created yet.
     if (_owner == null) {
       _owner = _MethodMirror_owner(_reflectee);
     }
-    // TODO(11897): This will go away, as soon as lazy mirrors go away.
-    if (_owner is! Mirror) {
-      _owner = _owner.resolve(mirrors);
-    }
     return _owner;
   }
 
@@ -1034,9 +968,6 @@
 
   String toString() => "MethodMirror on '${_n(simpleName)}'";
 
-  static String _MethodMirror_name(reflectee)
-      native "MethodMirror_name";
-
   static dynamic _MethodMirror_owner(reflectee)
       native "MethodMirror_owner";
 
@@ -1051,30 +982,13 @@
     implements VariableMirror {
   _LocalVariableMirrorImpl(reflectee,
                            String simpleName,
-                           this._owner,
+                           this.owner,
                            this._type,
                            this.isStatic,
                            this.isFinal)
-      : this.simpleName = _s(simpleName),
-        super(reflectee);
+      : super(reflectee, _s(simpleName));
 
-  final Symbol simpleName;
-
-  Symbol _qualifiedName = null;
-  Symbol get qualifiedName {
-    if (_qualifiedName == null) {
-      _qualifiedName = _computeQualifiedName(owner, simpleName);
-    }
-    return _qualifiedName;
-  }
-
-  var _owner;
-  DeclarationMirror get owner {
-    if (_owner is! Mirror) {
-      _owner = _owner.resolve(mirrors);
-    }
-    return _owner;
-  }
+  final DeclarationMirror owner;
 
   bool get isPrivate {
     return _n(simpleName).startsWith('_');
@@ -1089,14 +1003,11 @@
         'VariableMirror.location is not implemented');
   }
 
-  var _type;
+  TypeMirror _type;
   TypeMirror get type {
     if (_type == null) {
        _type = _VariableMirror_type(_reflectee);
     }
-    if (_type is! Mirror) {
-      _type = _type.resolve(mirrors);
-    }
     return _type;
   }
 
@@ -1174,7 +1085,7 @@
 
   // TODO(11955): Remove once dynamicType and voidType are canonical objects in
   // the object store.
-  operator ==(other) {
+  bool operator ==(other) {
     if (other is! _SpecialTypeMirrorImpl) {
       return false;
     }
@@ -1217,13 +1128,11 @@
     }
   }
 
-  // Creates a new local InstanceMirror
-  static InstanceMirror makeLocalInstanceMirror(Object reflectee)
-      native 'Mirrors_makeLocalInstanceMirror';
-
   // Creates a new local mirror for some Object.
   static InstanceMirror reflect(Object reflectee) {
-    return makeLocalInstanceMirror(reflectee);
+    return reflectee is Function 
+        ? new _LocalClosureMirrorImpl(reflectee)
+        : new _LocalInstanceMirrorImpl(reflectee);
   }
 
   // Creates a new local ClassMirror.
diff --git a/runtime/lib/object.cc b/runtime/lib/object.cc
index 8410af4..086198a 100644
--- a/runtime/lib/object.cc
+++ b/runtime/lib/object.cc
@@ -115,6 +115,17 @@
   const bool is_instance_of = instance.IsInstanceOf(type,
                                                     instantiator_type_arguments,
                                                     &malformed_error);
+  if (FLAG_trace_type_checks) {
+    const char* result_str = is_instance_of ? "true" : "false";
+    OS::Print("Object.instanceOf: result %s\n", result_str);
+    const Type& instance_type = Type::Handle(instance.GetType());
+    OS::Print("  instance type: %s\n",
+              String::Handle(instance_type.Name()).ToCString());
+    OS::Print("  test type: %s\n", String::Handle(type.Name()).ToCString());
+    if (!malformed_error.IsNull()) {
+      OS::Print("  malformed error: %s\n", malformed_error.ToErrorCString());
+    }
+  }
   if (!is_instance_of && !malformed_error.IsNull()) {
     // Throw a dynamic type error only if the instanceof test fails.
     DartFrameIterator iterator;
@@ -128,17 +139,6 @@
         Symbols::Empty(), malformed_error_message);
     UNREACHABLE();
   }
-
-  if (FLAG_trace_type_checks) {
-    const char* result_str = is_instance_of ? "true" : "false";
-    OS::Print("Object.instanceOf: result %s\n", result_str);
-    const Class& instance_class = Class::Handle(instance.clazz());
-    OS::Print("  instance  [class: %s]\n",
-        String::Handle(instance_class.Name()).ToCString());
-    OS::Print("  test-type [class: %s]\n",
-        String::Handle(Class::Handle(type.type_class()).Name()).ToCString());
-    OS::Print("  type-args %s\n", instantiator_type_arguments.ToCString());
-  }
   return Bool::Get(negate.value() ? !is_instance_of : is_instance_of);
 }
 
diff --git a/runtime/lib/typed_data.dart b/runtime/lib/typed_data.dart
index 437be6a..de61ae0 100644
--- a/runtime/lib/typed_data.dart
+++ b/runtime/lib/typed_data.dart
@@ -229,6 +229,14 @@
     return new _Float32x4Array(length);
   }
 
+  /* patch */ factory Float32x4List.fromList(List<Float32x4> elements) {
+    var result = new _Float32x4Array(elements.length);
+    for (int i = 0; i < elements.length; i++) {
+      result[i] = elements[i];
+    }
+    return result;
+  }
+
   /* patch */ factory Float32x4List.view(ByteBuffer buffer,
                                          [int offsetInBytes = 0, int length]) {
     return new _Float32x4ArrayView(buffer, offsetInBytes, length);
diff --git a/runtime/tests/vm/dart/isolate_mirror_local_test.dart b/runtime/tests/vm/dart/isolate_mirror_local_test.dart
index dc31e38..b07be27 100644
--- a/runtime/tests/vm/dart/isolate_mirror_local_test.dart
+++ b/runtime/tests/vm/dart/isolate_mirror_local_test.dart
@@ -390,8 +390,7 @@
 }
 
 void testNullInstanceMirror(InstanceMirror mirror) {
-  // TODO(turnidge): This is returning the wrong class.  Fix it.
-  Expect.equals(const Symbol('Object'), mirror.type.simpleName);
+  Expect.equals(const Symbol('Null'), mirror.type.simpleName);
   Expect.isTrue(mirror.hasReflectee);
   Expect.equals(null, mirror.reflectee);
   Expect.equals("InstanceMirror on null", mirror.toString());
diff --git a/runtime/vm/assembler.cc b/runtime/vm/assembler.cc
index 64a7716..dc33ed5 100644
--- a/runtime/vm/assembler.cc
+++ b/runtime/vm/assembler.cc
@@ -15,6 +15,11 @@
 
 DEFINE_FLAG(bool, code_comments, false,
             "Include comments into code and disassembly");
+// TODO(zra): Remove once far branches are enabled automatically on a
+// per-function basis.
+#if defined(TARGET_ARCH_ARM) || defined(TARGET_ARCH_MIPS)
+DEFINE_FLAG(bool, use_far_branches, false, "Enable far branches");
+#endif
 
 
 static uword NewContents(intptr_t capacity) {
diff --git a/runtime/vm/assembler.h b/runtime/vm/assembler.h
index 200716a..102afc8 100644
--- a/runtime/vm/assembler.h
+++ b/runtime/vm/assembler.h
@@ -13,6 +13,12 @@
 
 namespace dart {
 
+// TODO(zra): Remove once far branches are enabled automatically on a
+// per-function basis.
+#if defined(TARGET_ARCH_ARM) || defined(TARGET_ARCH_MIPS)
+DECLARE_FLAG(bool, use_far_branches);
+#endif
+
 // Forward declarations.
 class Assembler;
 class AssemblerFixup;
diff --git a/runtime/vm/assembler_arm.cc b/runtime/vm/assembler_arm.cc
index e50ac3a..d08f3db 100644
--- a/runtime/vm/assembler_arm.cc
+++ b/runtime/vm/assembler_arm.cc
@@ -305,18 +305,6 @@
 }
 
 
-void Assembler::EmitBranch(Condition cond, Label* label, bool link) {
-  if (label->IsBound()) {
-    EmitType5(cond, label->Position() - buffer_.Size(), link);
-  } else {
-    int position = buffer_.Size();
-    // Use the offset field of the branch instruction for linking the sites.
-    EmitType5(cond, label->position_, link);
-    label->LinkTo(position);
-  }
-}
-
-
 void Assembler::and_(Register rd, Register rn, ShifterOperand so,
                      Condition cond) {
   EmitType01(cond, so.type(), AND, 0, rn, rd, so);
@@ -1424,6 +1412,11 @@
 }
 
 
+void Assembler::vzipqw(QRegister qd, QRegister qm) {
+  EmitSIMDqqq(B24 | B23 | B21 | B20 | B19 | B17 | B8 | B7, kByte, qd, Q0, qm);
+}
+
+
 void Assembler::vceqqi(OperandSize sz,
                       QRegister qd, QRegister qn, QRegister qm) {
   EmitSIMDqqq(B24 | B11 | B4, sz, qd, qn, qm);
@@ -1725,15 +1718,172 @@
 }
 
 
+static bool CanEncodeBranchOffset(int32_t offset) {
+  offset -= Instr::kPCReadOffset;
+  ASSERT(Utils::IsAligned(offset, 4));
+  return Utils::IsInt(Utils::CountOneBits(kBranchOffsetMask), offset);
+}
+
+
+int32_t Assembler::EncodeBranchOffset(int32_t offset, int32_t inst) {
+  // The offset is off by 8 due to the way the ARM CPUs read PC.
+  offset -= Instr::kPCReadOffset;
+  ASSERT(Utils::IsAligned(offset, 4));
+  ASSERT(Utils::IsInt(Utils::CountOneBits(kBranchOffsetMask), offset));
+
+  // Properly preserve only the bits supported in the instruction.
+  offset >>= 2;
+  offset &= kBranchOffsetMask;
+  return (inst & ~kBranchOffsetMask) | offset;
+}
+
+
+int Assembler::DecodeBranchOffset(int32_t inst) {
+  // Sign-extend, left-shift by 2, then add 8.
+  return ((((inst & kBranchOffsetMask) << 8) >> 6) + Instr::kPCReadOffset);
+}
+
+
+static int32_t DecodeLoadImmediate(int32_t movt, int32_t movw) {
+  int32_t offset = 0;
+  offset |= (movt & 0xf0000) << 12;
+  offset |= (movt & 0xfff) << 16;
+  offset |= (movw & 0xf0000) >> 4;
+  offset |= movw & 0xfff;
+  return offset;
+}
+
+
+class PatchFarBranch : public AssemblerFixup {
+ public:
+  PatchFarBranch() {}
+
+  void Process(const MemoryRegion& region, int position) {
+    const int32_t movw = region.Load<int32_t>(position);
+    const int32_t movt = region.Load<int32_t>(position + Instr::kInstrSize);
+    const int32_t bx = region.Load<int32_t>(position + 2 * Instr::kInstrSize);
+
+    if (((movt & 0xfff0f000) == 0xe340c000) &&  // movt IP, high
+        ((movw & 0xfff0f000) == 0xe300c000)) {   // movw IP, low
+      const int32_t offset = DecodeLoadImmediate(movt, movw);
+      const int32_t dest = region.start() + offset;
+      const uint16_t dest_high = Utils::High16Bits(dest);
+      const uint16_t dest_low = Utils::Low16Bits(dest);
+      const int32_t patched_movt =
+          0xe340c000 | ((dest_high >> 12) << 16) | (dest_high & 0xfff);
+      const int32_t patched_movw =
+          0xe300c000 | ((dest_low >> 12) << 16) | (dest_low & 0xfff);
+
+      region.Store<int32_t>(position, patched_movw);
+      region.Store<int32_t>(position + Instr::kInstrSize, patched_movt);
+      return;
+    }
+
+    // If the offset loading instructions aren't there, we must have replaced
+    // the far branch with a near one, and so these instructions should be NOPs.
+    ASSERT((movt == Instr::kNopInstruction) &&
+           (bx == Instr::kNopInstruction));
+  }
+};
+
+
+void Assembler::EmitFarBranch(Condition cond, int32_t offset, bool link) {
+  const uint16_t low = Utils::Low16Bits(offset);
+  const uint16_t high = Utils::High16Bits(offset);
+  buffer_.EmitFixup(new PatchFarBranch());
+  movw(IP, low);
+  movt(IP, high);
+  if (link) {
+    blx(IP, cond);
+  } else {
+    bx(IP, cond);
+  }
+}
+
+
+void Assembler::EmitBranch(Condition cond, Label* label, bool link) {
+  if (label->IsBound()) {
+    const int32_t dest = label->Position() - buffer_.Size();
+    if (FLAG_use_far_branches && !CanEncodeBranchOffset(dest)) {
+      EmitFarBranch(cond, label->Position(), link);
+    } else {
+      EmitType5(cond, dest, link);
+    }
+  } else {
+    const int position = buffer_.Size();
+    if (FLAG_use_far_branches) {
+      const int32_t dest = label->position_;
+      EmitFarBranch(cond, dest, link);
+    } else {
+      // Use the offset field of the branch instruction for linking the sites.
+      EmitType5(cond, label->position_, link);
+    }
+    label->LinkTo(position);
+  }
+}
+
+
 void Assembler::Bind(Label* label) {
   ASSERT(!label->IsBound());
   int bound_pc = buffer_.Size();
   while (label->IsLinked()) {
-    int32_t position = label->Position();
-    int32_t next = buffer_.Load<int32_t>(position);
-    int32_t encoded = Assembler::EncodeBranchOffset(bound_pc - position, next);
-    buffer_.Store<int32_t>(position, encoded);
-    label->position_ = Assembler::DecodeBranchOffset(next);
+    const int32_t position = label->Position();
+    int32_t dest = bound_pc - position;
+    if (FLAG_use_far_branches && !CanEncodeBranchOffset(dest)) {
+      // Far branches are enabled and we can't encode the branch offset.
+
+      // Grab instructions that load the offset.
+      const int32_t movw =
+          buffer_.Load<int32_t>(position);
+      const int32_t movt =
+          buffer_.Load<int32_t>(position + 1 * Instr::kInstrSize);
+
+      // Change from relative to the branch to relative to the assembler buffer.
+      dest = buffer_.Size();
+      const uint16_t dest_high = Utils::High16Bits(dest);
+      const uint16_t dest_low = Utils::Low16Bits(dest);
+      const int32_t patched_movt =
+          0xe340c000 | ((dest_high >> 12) << 16) | (dest_high & 0xfff);
+      const int32_t patched_movw =
+          0xe300c000 | ((dest_low >> 12) << 16) | (dest_low & 0xfff);
+
+      // Rewrite the instructions.
+      buffer_.Store<int32_t>(position, patched_movw);
+      buffer_.Store<int32_t>(position + 1 * Instr::kInstrSize, patched_movt);
+      label->position_ = DecodeLoadImmediate(movt, movw);
+    } else if (FLAG_use_far_branches && CanEncodeBranchOffset(dest)) {
+      // Far branches are enabled, but we can encode the branch offset.
+
+      // Grab instructions that load the offset, and the branch.
+      const int32_t movw =
+          buffer_.Load<int32_t>(position);
+      const int32_t movt =
+          buffer_.Load<int32_t>(position + 1 * Instr::kInstrSize);
+      const int32_t branch =
+          buffer_.Load<int32_t>(position + 2 * Instr::kInstrSize);
+
+      // Grab the branch condition, and encode the link bit.
+      const int32_t cond = branch & 0xf0000000;
+      const int32_t link = (branch & 0x20) << 19;
+
+      // Encode the branch and the offset.
+      const int32_t new_branch = cond | link | 0x0a000000;
+      const int32_t encoded = EncodeBranchOffset(dest, new_branch);
+
+      // Write the encoded branch instruction followed by two nops.
+      buffer_.Store<int32_t>(position, encoded);
+      buffer_.Store<int32_t>(position + 1 * Instr::kInstrSize,
+          Instr::kNopInstruction);
+      buffer_.Store<int32_t>(position + 2 * Instr::kInstrSize,
+          Instr::kNopInstruction);
+
+      label->position_ = DecodeLoadImmediate(movt, movw);
+    } else {
+      int32_t next = buffer_.Load<int32_t>(position);
+      int32_t encoded = Assembler::EncodeBranchOffset(dest, next);
+      buffer_.Store<int32_t>(position, encoded);
+      label->position_ = Assembler::DecodeBranchOffset(next);
+    }
   }
   label->BindTo(bound_pc);
 }
@@ -2415,10 +2565,10 @@
   const intptr_t offset = CodeSize();
 
   Comment("EnterOsrFrame");
-  mov(TMP, ShifterOperand(PC));
+  mov(IP, ShifterOperand(PC));
 
-  AddImmediate(TMP, -offset);
-  str(TMP, Address(FP, kPcMarkerSlotFromFp * kWordSize));
+  AddImmediate(IP, -offset);
+  str(IP, Address(FP, kPcMarkerSlotFromFp * kWordSize));
 
   // Setup pool pointer for this dart function.
   LoadPoolPointer();
@@ -2473,16 +2623,16 @@
     AddImmediate(instance_reg, instance_size);
 
     // instance_reg: potential next object start.
-    LoadImmediate(TMP, heap->EndAddress());
-    ldr(TMP, Address(TMP, 0));
-    cmp(TMP, ShifterOperand(instance_reg));
+    LoadImmediate(IP, heap->EndAddress());
+    ldr(IP, Address(IP, 0));
+    cmp(IP, ShifterOperand(instance_reg));
     // fail if heap end unsigned less than or equal to instance_reg.
     b(failure, LS);
 
     // Successfully allocated the object, now update top to point to
     // next object start and store the class in the class field of object.
-    LoadImmediate(TMP, heap->TopAddress());
-    str(instance_reg, Address(TMP, 0));
+    LoadImmediate(IP, heap->TopAddress());
+    str(instance_reg, Address(IP, 0));
 
     ASSERT(instance_size >= kHeapObjectTag);
     AddImmediate(instance_reg, -instance_size + kHeapObjectTag);
@@ -2491,8 +2641,8 @@
     tags = RawObject::SizeTag::update(instance_size, tags);
     ASSERT(cls.id() != kIllegalCid);
     tags = RawObject::ClassIdTag::update(cls.id(), tags);
-    LoadImmediate(TMP, tags);
-    str(TMP, FieldAddress(instance_reg, Object::tags_offset()));
+    LoadImmediate(IP, tags);
+    str(IP, FieldAddress(instance_reg, Object::tags_offset()));
   } else {
     b(failure);
   }
@@ -2518,25 +2668,6 @@
 }
 
 
-int32_t Assembler::EncodeBranchOffset(int32_t offset, int32_t inst) {
-  // The offset is off by 8 due to the way the ARM CPUs read PC.
-  offset -= 8;
-  ASSERT(Utils::IsAligned(offset, 4));
-  ASSERT(Utils::IsInt(Utils::CountOneBits(kBranchOffsetMask), offset));
-
-  // Properly preserve only the bits supported in the instruction.
-  offset >>= 2;
-  offset &= kBranchOffsetMask;
-  return (inst & ~kBranchOffsetMask) | offset;
-}
-
-
-int Assembler::DecodeBranchOffset(int32_t inst) {
-  // Sign-extend, left-shift by 2, then add 8.
-  return ((((inst & kBranchOffsetMask) << 8) >> 6) + 8);
-}
-
-
 int32_t Assembler::AddObject(const Object& obj) {
   ASSERT(obj.IsNotTemporaryScopedHandle());
   ASSERT(obj.IsOld());
diff --git a/runtime/vm/assembler_arm.h b/runtime/vm/assembler_arm.h
index 5044eed..d9cb891 100644
--- a/runtime/vm/assembler_arm.h
+++ b/runtime/vm/assembler_arm.h
@@ -538,6 +538,10 @@
   // a list of 'length' registers starting with dn. The result is placed in dd.
   void vtbl(DRegister dd, DRegister dn, int length, DRegister dm);
 
+  // The words of qd and qm are interleaved with the low words of the result
+  // in qd and the high words in qm.
+  void vzipqw(QRegister qd, QRegister qm);
+
   // Branch instructions.
   void b(Label* label, Condition cond = AL);
   void bl(Label* label, Condition cond = AL);
@@ -843,6 +847,7 @@
   void EmitSIMDddd(int32_t opcode, OperandSize sz,
                    DRegister dd, DRegister dn, DRegister dm);
 
+  void EmitFarBranch(Condition cond, int32_t offset, bool link);
   void EmitBranch(Condition cond, Label* label, bool link);
   static int32_t EncodeBranchOffset(int32_t offset, int32_t inst);
   static int DecodeBranchOffset(int32_t inst);
diff --git a/runtime/vm/assembler_arm_test.cc b/runtime/vm/assembler_arm_test.cc
index 3e61347..47f656c 100644
--- a/runtime/vm/assembler_arm_test.cc
+++ b/runtime/vm/assembler_arm_test.cc
@@ -2638,6 +2638,40 @@
 }
 
 
+ASSEMBLER_TEST_GENERATE(Vzipqw, assembler) {
+  if (CPUFeatures::neon_supported()) {
+    __ LoadSImmediate(S0, 0.0);
+    __ LoadSImmediate(S1, 1.0);
+    __ LoadSImmediate(S2, 2.0);
+    __ LoadSImmediate(S3, 3.0);
+    __ LoadSImmediate(S4, 4.0);
+    __ LoadSImmediate(S5, 5.0);
+    __ LoadSImmediate(S6, 6.0);
+    __ LoadSImmediate(S7, 7.0);
+
+    __ vzipqw(Q0, Q1);
+
+    __ vsubqs(Q0, Q1, Q0);
+
+    __ vadds(S0, S0, S1);
+    __ vadds(S0, S0, S2);
+    __ vadds(S0, S0, S3);
+    __ bx(LR);
+  } else {
+    __ LoadSImmediate(S0, 8.0);
+    __ bx(LR);
+  }
+}
+
+
+ASSEMBLER_TEST_RUN(Vzipqw, test) {
+  EXPECT(test != NULL);
+  typedef float (*Vzipqw)();
+  float res = EXECUTE_TEST_CODE_FLOAT(Vzipqw, test->entry());
+  EXPECT_FLOAT_EQ(8.0, res, 0.0001f);
+}
+
+
 ASSEMBLER_TEST_GENERATE(Vceqqi32, assembler) {
   if (CPUFeatures::neon_supported()) {
     __ mov(R0, ShifterOperand(1));
diff --git a/runtime/vm/assembler_ia32.cc b/runtime/vm/assembler_ia32.cc
index 4244adb..c04347c 100644
--- a/runtime/vm/assembler_ia32.cc
+++ b/runtime/vm/assembler_ia32.cc
@@ -330,6 +330,22 @@
 }
 
 
+void Assembler::cmovgel(Register dst, Register src) {
+  AssemblerBuffer::EnsureCapacity ensured(&buffer_);
+  EmitUint8(0x0F);
+  EmitUint8(0x4D);
+  EmitRegisterOperand(dst, src);
+}
+
+
+void Assembler::cmovlessl(Register dst, Register src) {
+  AssemblerBuffer::EnsureCapacity ensured(&buffer_);
+  EmitUint8(0x0F);
+  EmitUint8(0x4C);
+  EmitRegisterOperand(dst, src);
+}
+
+
 void Assembler::rep_movsb() {
   AssemblerBuffer::EnsureCapacity ensured(&buffer_);
   EmitUint8(0xF3);
diff --git a/runtime/vm/assembler_ia32.h b/runtime/vm/assembler_ia32.h
index b9aa149..3103b5d 100644
--- a/runtime/vm/assembler_ia32.h
+++ b/runtime/vm/assembler_ia32.h
@@ -366,6 +366,9 @@
   void cmovs(Register dst, Register src);
   void cmovns(Register dst, Register src);
 
+  void cmovgel(Register dst, Register src);
+  void cmovlessl(Register dst, Register src);
+
   void rep_movsb();
 
   void movss(XmmRegister dst, const Address& src);
diff --git a/runtime/vm/assembler_ia32_test.cc b/runtime/vm/assembler_ia32_test.cc
index edb1820..3a7d4a5 100644
--- a/runtime/vm/assembler_ia32_test.cc
+++ b/runtime/vm/assembler_ia32_test.cc
@@ -2627,6 +2627,28 @@
 }
 
 
+ASSEMBLER_TEST_GENERATE(ConditionalMovesCompare, assembler) {
+  __ movl(EDX, Immediate(1));  // Greater equal.
+  __ movl(ECX, Immediate(-1));  // Less
+  __ movl(EAX, Address(ESP, 1 * kWordSize));
+  __ cmpl(EAX, Address(ESP, 2 * kWordSize));
+  __ cmovlessl(EAX, ECX);
+  __ cmovgel(EAX, EDX);
+  __ ret();
+}
+
+
+ASSEMBLER_TEST_RUN(ConditionalMovesCompare, test) {
+  typedef int (*ConditionalMovesCompareCode)(int i, int j);
+  int res = reinterpret_cast<ConditionalMovesCompareCode>(test->entry())(10, 5);
+  EXPECT_EQ(1, res);  // Greater equal.
+  res = reinterpret_cast<ConditionalMovesCompareCode>(test->entry())(5, 5);
+  EXPECT_EQ(1, res);  // Greater equal.
+  res = reinterpret_cast<ConditionalMovesCompareCode>(test->entry())(2, 5);
+  EXPECT_EQ(-1, res);  // Less.
+}
+
+
 ASSEMBLER_TEST_GENERATE(TestLoadDoubleConstant, assembler) {
   __ LoadDoubleConstant(XMM3, -12.34);
   __ pushl(EAX);
diff --git a/runtime/vm/assembler_mips.cc b/runtime/vm/assembler_mips.cc
index f1f15e0..47b423f 100644
--- a/runtime/vm/assembler_mips.cc
+++ b/runtime/vm/assembler_mips.cc
@@ -17,7 +17,6 @@
 DECLARE_FLAG(bool, trace_sim);
 #endif
 DEFINE_FLAG(bool, print_stop_message, false, "Print stop message.");
-DEFINE_FLAG(bool, use_far_branches, false, "Enable far branches on MIPS");
 DECLARE_FLAG(bool, inline_alloc);
 
 void Assembler::InitializeMemoryWithBreakpoints(uword data, int length) {
diff --git a/runtime/vm/assembler_mips.h b/runtime/vm/assembler_mips.h
index d2cb44f..2d45ef7 100644
--- a/runtime/vm/assembler_mips.h
+++ b/runtime/vm/assembler_mips.h
@@ -22,8 +22,6 @@
 //   The MIPS32® Instruction Set" in short "VolII-A"
 namespace dart {
 
-DECLARE_FLAG(bool, use_far_branches);
-
 // Forward declarations.
 class RuntimeEntry;
 
diff --git a/runtime/vm/assembler_x64.cc b/runtime/vm/assembler_x64.cc
index ebeb998..488cd55 100644
--- a/runtime/vm/assembler_x64.cc
+++ b/runtime/vm/assembler_x64.cc
@@ -406,6 +406,27 @@
 }
 
 
+void Assembler::cmovgeq(Register dst, Register src) {
+  AssemblerBuffer::EnsureCapacity ensured(&buffer_);
+  Operand operand(src);
+  EmitOperandREX(dst, operand, REX_W);
+  EmitUint8(0x0F);
+  EmitUint8(0x4D);
+  EmitOperand(dst & 7, operand);
+}
+
+
+void Assembler::cmovlessq(Register dst, Register src) {
+  AssemblerBuffer::EnsureCapacity ensured(&buffer_);
+  Operand operand(src);
+  EmitOperandREX(dst, operand, REX_W);
+  EmitUint8(0x0F);
+  EmitUint8(0x4C);
+  EmitOperand(dst & 7, operand);
+}
+
+
+
 void Assembler::movss(XmmRegister dst, const Address& src) {
   ASSERT(dst <= XMM15);
   AssemblerBuffer::EnsureCapacity ensured(&buffer_);
diff --git a/runtime/vm/assembler_x64.h b/runtime/vm/assembler_x64.h
index c87aec7..165642b 100644
--- a/runtime/vm/assembler_x64.h
+++ b/runtime/vm/assembler_x64.h
@@ -383,6 +383,9 @@
 
   void leaq(Register dst, const Address& src);
 
+  void cmovgeq(Register dst, Register src);
+  void cmovlessq(Register dst, Register src);
+
   void movss(XmmRegister dst, const Address& src);
   void movss(const Address& dst, XmmRegister src);
   void movss(XmmRegister dst, XmmRegister src);
diff --git a/runtime/vm/assembler_x64_test.cc b/runtime/vm/assembler_x64_test.cc
index 688f874..7fe6a08 100644
--- a/runtime/vm/assembler_x64_test.cc
+++ b/runtime/vm/assembler_x64_test.cc
@@ -2567,6 +2567,29 @@
   delete [] to;
 }
 
+
+ASSEMBLER_TEST_GENERATE(ConditionalMovesCompare, assembler) {
+  // RDI: Arg0.
+  // RSI: Arg1.
+  __ movq(RDX, Immediate(1));  // Greater equal.
+  __ movq(RCX, Immediate(-1));  // Less
+  __ cmpq(RDI, RSI);
+  __ cmovlessq(RAX, RCX);
+  __ cmovgeq(RAX, RDX);
+  __ ret();
+}
+
+
+ASSEMBLER_TEST_RUN(ConditionalMovesCompare, test) {
+  typedef int (*ConditionalMovesCompareCode)(int i, int j);
+  int res = reinterpret_cast<ConditionalMovesCompareCode>(test->entry())(10, 5);
+  EXPECT_EQ(1, res);  // Greater equal.
+  res = reinterpret_cast<ConditionalMovesCompareCode>(test->entry())(5, 5);
+  EXPECT_EQ(1, res);  // Greater equal.
+  res = reinterpret_cast<ConditionalMovesCompareCode>(test->entry())(2, 5);
+  EXPECT_EQ(-1, res);  // Less.
+}
+
 }  // namespace dart
 
 #endif  // defined TARGET_ARCH_X64
diff --git a/runtime/vm/bootstrap_natives.h b/runtime/vm/bootstrap_natives.h
index 26d8be4..d890bf4 100644
--- a/runtime/vm/bootstrap_natives.h
+++ b/runtime/vm/bootstrap_natives.h
@@ -240,16 +240,18 @@
   V(isolate_spawnFunction, 2)                                                  \
   V(isolate_spawnUri, 1)                                                       \
   V(Mirrors_isLocalPort, 1)                                                    \
-  V(Mirrors_makeLocalInstanceMirror, 1)                                        \
   V(Mirrors_makeLocalClassMirror, 1)                                           \
   V(Mirrors_makeLocalMirrorSystem, 0)                                          \
+  V(MirrorReference_equals, 2)                                                 \
   V(InstanceMirror_invoke, 4)                                                  \
   V(InstanceMirror_invokeGetter, 3)                                            \
   V(InstanceMirror_invokeSetter, 4)                                            \
+  V(ClosureMirror_function, 1)                                                 \
   V(ClosureMirror_apply, 2)                                                    \
   V(ClassMirror_name, 1)                                                       \
   V(ClassMirror_library, 1)                                                    \
   V(ClassMirror_supertype, 1)                                                  \
+  V(ClassMirror_interfaces, 1)                                                 \
   V(ClassMirror_members, 2)                                                    \
   V(ClassMirror_constructors, 2)                                               \
   V(LibraryMirror_members, 2)                                                  \
@@ -257,15 +259,20 @@
   V(ClassMirror_invokeGetter, 3)                                               \
   V(ClassMirror_invokeSetter, 4)                                               \
   V(ClassMirror_invokeConstructor, 3)                                          \
+  V(ClassMirror_type_variables, 1)                                             \
   V(LibraryMirror_invoke, 4)                                                   \
   V(LibraryMirror_invokeGetter, 3)                                             \
   V(LibraryMirror_invokeSetter, 4)                                             \
+  V(LocalTypeVariableMirror_owner, 1)                                          \
+  V(LocalTypeVariableMirror_upper_bound, 1)                                    \
   V(DeclarationMirror_metadata, 1)                                             \
-  V(MethodMirror_name, 1)                                                      \
+  V(FunctionTypeMirror_parameters, 1)                                          \
+  V(FunctionTypeMirror_return_type, 1)                                         \
   V(MethodMirror_owner, 1)                                                     \
   V(MethodMirror_parameters, 1)                                                \
   V(MethodMirror_return_type, 1)                                               \
   V(ParameterMirror_type, 2)                                                   \
+  V(TypedefMirror_referent, 1)                                                 \
   V(VariableMirror_type, 1)                                                    \
   V(GrowableObjectArray_allocate, 2)                                           \
   V(GrowableObjectArray_getIndexed, 2)                                         \
diff --git a/runtime/vm/class_finalizer.cc b/runtime/vm/class_finalizer.cc
index 0134612..91410fa 100644
--- a/runtime/vm/class_finalizer.cc
+++ b/runtime/vm/class_finalizer.cc
@@ -347,7 +347,6 @@
         Error::Handle(),  // No previous error.
         cls,
         factory.token_pos(),
-        kResolveTypeParameters,  // No compile-time error.
         "factory may not redirect to 'dynamic'");
     factory.SetRedirectionType(type);
     ASSERT(factory.RedirectionTarget() == Function::null());
@@ -375,7 +374,6 @@
         Error::Handle(),  // No previous error.
         cls,
         factory.token_pos(),
-        kResolveTypeParameters,  // No compile-time error.
         "class '%s' has no constructor or factory named '%s'",
         target_class_name.ToCString(),
         user_visible_target_name.ToCString());
@@ -390,7 +388,6 @@
         Error::Handle(),  // No previous error.
         cls,
         factory.token_pos(),
-        kResolveTypeParameters,  // No compile-time error.
         "constructor '%s' has incompatible parameters with "
         "redirecting factory '%s'",
         String::Handle(target.name()).ToCString(),
@@ -437,8 +434,7 @@
       if (malformed_error.IsNull()) {
         target_type ^= FinalizeType(cls, target_type, kCanonicalize);
       } else {
-        FinalizeMalformedType(malformed_error,
-                              cls, target_type, kFinalize,
+        FinalizeMalformedType(malformed_error, cls, target_type,
                               "cannot resolve redirecting factory");
         target_target = Function::null();
       }
@@ -453,9 +449,6 @@
                                  const AbstractType& type,
                                  FinalizationKind finalization) {
   if (type.IsResolved() || type.IsFinalized()) {
-    if ((finalization == kCanonicalizeWellFormed) && type.IsMalformed()) {
-      ReportError(Error::Handle(type.malformed_error()));
-    }
     return;
   }
   if (FLAG_trace_type_finalization) {
@@ -479,17 +472,27 @@
 
     // Replace unresolved class with resolved type class.
     const Type& parameterized_type = Type::Cast(type);
-    if (!type_class.IsNull()) {
-      parameterized_type.set_type_class(type_class);
-    } else {
-      // The type class could not be resolved. The type is malformed.
-      FinalizeMalformedType(ambiguous_error,  // May be null.
-                            cls, parameterized_type, finalization,
-                            "cannot resolve class name '%s' from '%s'",
-                            String::Handle(unresolved_class.Name()).ToCString(),
-                            String::Handle(cls.Name()).ToCString());
+    if (type_class.IsNull()) {
+      if ((finalization == kCanonicalizeWellFormed) ||
+          FLAG_error_on_malformed_type) {
+        // The type class could not be resolved. The type is malformed.
+        FinalizeMalformedType(
+            ambiguous_error,  // May be null.
+            cls,
+            parameterized_type,
+            "cannot resolve class '%s' from '%s'",
+            String::Handle(unresolved_class.Name()).ToCString(),
+            String::Handle(cls.Name()).ToCString());
+      } else {
+        // Map the malformed type to dynamic and ignore type arguments.
+        parameterized_type.set_type_class(Class::Handle(
+            Object::dynamic_class()));
+        parameterized_type.set_arguments(
+            Object::null_abstract_type_arguments());
+      }
       return;
     }
+    parameterized_type.set_type_class(type_class);
   }
 
   // Resolve type arguments, if any.
@@ -708,14 +711,8 @@
   if (type.IsFinalized()) {
     // Ensure type is canonical if canonicalization is requested, unless type is
     // malformed.
-    if (finalization >= kCanonicalize) {
-      if (type.IsMalformed()) {
-        if (finalization == kCanonicalizeWellFormed) {
-          ReportError(Error::Handle(type.malformed_error()));
-        }
-      } else {
-        return type.Canonicalize();
-      }
+    if ((finalization >= kCanonicalize) && !type.IsMalformed()) {
+      return type.Canonicalize();
     }
     return type.raw();
   }
@@ -749,15 +746,8 @@
   // At this point, we can only have a parameterized_type.
   const Type& parameterized_type = Type::Cast(type);
 
-  if (parameterized_type.IsBeingFinalized()) {
-    // Self reference detected. The type is malformed.
-    FinalizeMalformedType(
-        Error::Handle(),  // No previous error.
-        cls, parameterized_type, finalization,
-        "type '%s' illegally refers to itself",
-        String::Handle(parameterized_type.UserVisibleName()).ToCString());
-    return parameterized_type.raw();
-  }
+  // Types illegally referring to themselves should have been detected earlier.
+  ASSERT(!parameterized_type.IsBeingFinalized());
 
   // Mark type as being finalized in order to detect illegal self reference.
   parameterized_type.set_is_being_finalized();
@@ -784,19 +774,8 @@
       type_argument = arguments.TypeAt(i);
       type_argument = FinalizeType(cls, type_argument, finalization);
       if (type_argument.IsMalformed()) {
-        // In production mode, malformed type arguments are mapped to dynamic.
-        // In checked mode, a type with malformed type arguments is malformed.
-        if (FLAG_enable_type_checks || FLAG_error_on_malformed_type) {
-          const Error& error = Error::Handle(type_argument.malformed_error());
-          const String& type_name =
-              String::Handle(parameterized_type.UserVisibleName());
-          FinalizeMalformedType(error, cls, parameterized_type, finalization,
-                                "type '%s' has malformed type argument",
-                                type_name.ToCString());
-          return parameterized_type.raw();
-        } else {
-          type_argument = Type::DynamicType();
-        }
+        // Malformed type arguments are mapped to dynamic.
+        type_argument = Type::DynamicType();
       }
       arguments.SetTypeAt(i, type_argument);
     }
@@ -813,20 +792,17 @@
   // However, type parameter bounds are checked below, even for a raw type.
   if (!arguments.IsNull() && (arguments.Length() != num_type_parameters)) {
     // Wrong number of type arguments. The type is malformed.
-    if (finalization >= kCanonicalizeExpression) {
+    if (FLAG_error_on_malformed_type) {
       const Script& script = Script::Handle(cls.script());
-      const String& type_name =
-          String::Handle(parameterized_type.UserVisibleName());
+      const String& type_class_name = String::Handle(type_class.Name());
       ReportError(script, parameterized_type.token_pos(),
-                  "wrong number of type arguments in type '%s'",
-                  type_name.ToCString());
+                  "wrong number of type arguments for class '%s'",
+                  type_class_name.ToCString());
     }
-    FinalizeMalformedType(
-        Error::Handle(),  // No previous error.
-        cls, parameterized_type, finalization,
-        "wrong number of type arguments in type '%s'",
-        String::Handle(parameterized_type.UserVisibleName()).ToCString());
-    return parameterized_type.raw();
+    // Make the type raw and continue without reporting any error.
+    // A static warning should have been reported.
+    arguments = AbstractTypeArguments::null();
+    parameterized_type.set_arguments(arguments);
   }
   // The full type argument vector consists of the type arguments of the
   // super types of type_class, which may be initialized from the parsed
@@ -908,17 +884,12 @@
   // The malformed bound will be ignored in production mode.
   if (!bound_error.IsNull()) {
     // No compile-time error during finalization.
-    FinalizationKind bound_finalization = kResolveTypeParameters;
-    if (FLAG_enable_type_checks || FLAG_error_on_malformed_type) {
-      bound_finalization = finalization;
-    }
     const String& parameterized_type_name = String::Handle(
         parameterized_type.UserVisibleName());
     const Type& malformed_bound = Type::Handle(
         NewFinalizedMalformedType(bound_error,
                                   cls,
                                   parameterized_type.token_pos(),
-                                  bound_finalization,
                                   "type '%s' has an out of bound type argument",
                                   parameterized_type_name.ToCString()));
     return BoundedType::New(parameterized_type,
@@ -942,10 +913,8 @@
   // interface.
   ResolveType(cls, type, kCanonicalize);
   type = FinalizeType(cls, type, kCanonicalize);
-  // In production mode, a malformed result type is mapped to dynamic.
-  if (!FLAG_enable_type_checks && type.IsMalformed()) {
-    type = Type::DynamicType();
-  }
+  // A malformed result type is mapped to dynamic.
+  ASSERT(!type.IsMalformed());
   function.set_result_type(type);
   // Resolve formal parameter types.
   const intptr_t num_parameters = function.NumParameters();
@@ -953,10 +922,8 @@
     type = function.ParameterTypeAt(i);
     ResolveType(cls, type, kCanonicalize);
     type = FinalizeType(cls, type, kCanonicalize);
-    // In production mode, a malformed parameter type is mapped to dynamic.
-    if (!FLAG_enable_type_checks && type.IsMalformed()) {
-      type = Type::DynamicType();
-    }
+    // A malformed parameter type is mapped to dynamic.
+    ASSERT(!type.IsMalformed());
     function.SetParameterTypeAt(i, type);
   }
 }
@@ -1875,6 +1842,9 @@
 
   // Resolve super type. Failures lead to a longjmp.
   ResolveType(cls, super_type, kCanonicalizeWellFormed);
+  if (super_type.IsMalformed()) {
+    ReportError(Error::Handle(super_type.malformed_error()));
+  }
   if (super_type.IsDynamicType()) {
     const Script& script = Script::Handle(cls.script());
     ReportError(script, cls.token_pos(),
@@ -1940,6 +1910,9 @@
     interface ^= super_interfaces.At(i);
     ResolveType(cls, interface, kCanonicalizeWellFormed);
     ASSERT(!interface.IsTypeParameter());  // Should be detected by parser.
+    if (interface.IsMalformed()) {
+      ReportError(Error::Handle(interface.malformed_error()));
+    }
     if (interface.IsDynamicType()) {
       const Script& script = Script::Handle(cls.script());
       ReportError(script, cls.token_pos(),
@@ -2051,35 +2024,24 @@
 void ClassFinalizer::ReportMalformedType(const Error& prev_error,
                                          const Class& cls,
                                          const Type& type,
-                                         FinalizationKind finalization,
                                          const char* format,
                                          va_list args) {
   LanguageError& error = LanguageError::Handle();
-  if (FLAG_enable_type_checks ||
-      !type.HasResolvedTypeClass() ||
-      (finalization == kCanonicalizeWellFormed) ||
-      FLAG_error_on_malformed_type) {
-    const Script& script = Script::Handle(cls.script());
-    if (prev_error.IsNull()) {
-      error ^= Parser::FormatError(
-          script, type.token_pos(), "Error", format, args);
-    } else {
-      error ^= Parser::FormatErrorWithAppend(
-          prev_error, script, type.token_pos(), "Error", format, args);
-    }
-    if ((finalization == kCanonicalizeWellFormed) ||
-        FLAG_error_on_malformed_type) {
-      ReportError(error);
-    }
+  const Script& script = Script::Handle(cls.script());
+  if (prev_error.IsNull()) {
+    error ^= Parser::FormatError(
+        script, type.token_pos(), "Error", format, args);
+  } else {
+    error ^= Parser::FormatErrorWithAppend(
+        prev_error, script, type.token_pos(), "Error", format, args);
   }
-  // In checked mode, always mark the type as malformed.
-  // In production mode, mark the type as malformed only if its type class is
-  // not resolved.
-  // In both mode, make the type raw, since it may not be possible to
+  if (FLAG_error_on_malformed_type) {
+    ReportError(error);
+  }
+  type.set_malformed_error(error);
+  // Make the type raw, since it may not be possible to
   // properly finalize its type arguments.
-  if (FLAG_enable_type_checks || !type.HasResolvedTypeClass()) {
-    type.set_malformed_error(error);
-  }
+  type.set_type_class(Class::Handle(Object::dynamic_class()));
   type.set_arguments(Object::null_abstract_type_arguments());
   if (!type.IsFinalized()) {
     type.SetIsFinalized();
@@ -2092,12 +2054,10 @@
 }
 
 
-RawType* ClassFinalizer::NewFinalizedMalformedType(
-    const Error& prev_error,
-    const Class& cls,
-    intptr_t type_pos,
-    FinalizationKind finalization,
-    const char* format, ...) {
+RawType* ClassFinalizer::NewFinalizedMalformedType(const Error& prev_error,
+                                                   const Class& cls,
+                                                   intptr_t type_pos,
+                                                   const char* format, ...) {
   va_list args;
   va_start(args, format);
   const UnresolvedClass& unresolved_class = UnresolvedClass::Handle(
@@ -2106,7 +2066,7 @@
                            type_pos));
   const Type& type = Type::Handle(
       Type::New(unresolved_class, TypeArguments::Handle(), type_pos));
-  ReportMalformedType(prev_error, cls, type, finalization, format, args);
+  ReportMalformedType(prev_error, cls, type, format, args);
   va_end(args);
   ASSERT(type.IsMalformed());
   ASSERT(type.IsFinalized());
@@ -2117,11 +2077,10 @@
 void ClassFinalizer::FinalizeMalformedType(const Error& prev_error,
                                            const Class& cls,
                                            const Type& type,
-                                           FinalizationKind finalization,
                                            const char* format, ...) {
   va_list args;
   va_start(args, format);
-  ReportMalformedType(prev_error, cls, type, finalization, format, args);
+  ReportMalformedType(prev_error, cls, type, format, args);
   va_end(args);
 }
 
diff --git a/runtime/vm/class_finalizer.h b/runtime/vm/class_finalizer.h
index b82cabf..809adee 100644
--- a/runtime/vm/class_finalizer.h
+++ b/runtime/vm/class_finalizer.h
@@ -34,16 +34,11 @@
     kDoNotResolve,             // Type resolution is postponed.
     kResolveTypeParameters,    // Resolve type parameters only.
     kFinalize,                 // Type resolution and type finalization are
-                               // required; a malformed type is tolerated, since
-                               // the type may be used as a type annotation.
+                               // required; replace a malformed type by dynamic.
     kCanonicalize,             // Same as kFinalize, but with canonicalization.
-    kCanonicalizeExpression,   // Same as kCanonicalize, but do not tolerate
-                               // wrong number of type arguments or ambiguous
-                               // type reference, since the type is not used as
-                               // a type annotation, but as a type expression.
     kCanonicalizeWellFormed    // Error-free resolution, finalization, and
                                // canonicalization are required; a malformed
-                               // type is not tolerated.
+                               // type is marked as such.
   };
 
   // Finalize given type while parsing class cls.
@@ -59,9 +54,8 @@
   static RawType* NewFinalizedMalformedType(const Error& prev_error,
                                             const Class& cls,
                                             intptr_t type_pos,
-                                            FinalizationKind finalization,
                                             const char* format, ...)
-       PRINTF_ATTRIBUTE(5, 6);
+       PRINTF_ATTRIBUTE(4, 5);
 
   // Depending on the given type, finalization mode, and execution mode, mark
   // the given type as malformed or report a compile time error.
@@ -70,9 +64,8 @@
   static void FinalizeMalformedType(const Error& prev_error,
                                     const Class& cls,
                                     const Type& type,
-                                    FinalizationKind finalization,
                                     const char* format, ...)
-       PRINTF_ATTRIBUTE(5, 6);
+       PRINTF_ATTRIBUTE(4, 5);
 
   // Return false if we still have classes pending to be finalized.
   static bool AllClassesFinalized();
@@ -145,7 +138,6 @@
   static void ReportMalformedType(const Error& prev_error,
                                   const Class& cls,
                                   const Type& type,
-                                  FinalizationKind finalization,
                                   const char* format,
                                   va_list args);
   static void ReportError(const Error& error);
diff --git a/runtime/vm/constants_arm.h b/runtime/vm/constants_arm.h
index 5c1dd00..63a88e9 100644
--- a/runtime/vm/constants_arm.h
+++ b/runtime/vm/constants_arm.h
@@ -405,6 +405,8 @@
     kPCReadOffset = 8
   };
 
+  static const int32_t kNopInstruction =  // nop
+      ((AL << kConditionShift) | (0x32 << 20) | (0xf << 12));
   static const int32_t kBreakPointInstruction =  // svc #kBreakpointSvcCode
       ((AL << kConditionShift) | (0xf << 24) | kBreakpointSvcCode);
   static const int kBreakPointInstructionSize = kInstrSize;
diff --git a/runtime/vm/dart_api_impl.cc b/runtime/vm/dart_api_impl.cc
index d298335..4b91917 100644
--- a/runtime/vm/dart_api_impl.cc
+++ b/runtime/vm/dart_api_impl.cc
@@ -3565,7 +3565,7 @@
         "%s: argument 'arg_index' out of range. Expected 0..%d but saw %d.",
         CURRENT_FUNC, arguments->NativeArgCount() - 1, arg_index);
   }
-  Isolate* isolate = Isolate::Current();
+  Isolate* isolate = arguments->isolate();
   DARTSCOPE(isolate);
   const Object& obj = Object::Handle(isolate,
                                      arguments->NativeArgAt(arg_index));
@@ -3593,14 +3593,48 @@
 
 DART_EXPORT void Dart_SetReturnValue(Dart_NativeArguments args,
                                      Dart_Handle retval) {
-  const Object& ret_obj = Object::Handle(Api::UnwrapHandle(retval));
-  if (!ret_obj.IsNull() && !ret_obj.IsInstance()) {
+  NativeArguments* arguments = reinterpret_cast<NativeArguments*>(args);
+  Isolate* isolate = arguments->isolate();
+  CHECK_ISOLATE(isolate);
+  if ((retval != Api::Null()) && (!Api::IsInstance(retval))) {
+    const Object& ret_obj = Object::Handle(Api::UnwrapHandle(retval));
     FATAL1("Return value check failed: saw '%s' expected a dart Instance.",
            ret_obj.ToCString());
   }
-  NoGCScope no_gc_scope;
+  ASSERT(retval != 0);
+  Api::SetReturnValue(arguments, retval);
+}
+
+
+DART_EXPORT void Dart_SetBooleanReturnValue(Dart_NativeArguments args,
+                                            bool retval) {
   NativeArguments* arguments = reinterpret_cast<NativeArguments*>(args);
-  arguments->SetReturn(ret_obj);
+  arguments->SetReturn(retval ? Bool::True() : Bool::False());
+}
+
+
+DART_EXPORT void Dart_SetIntegerReturnValue(Dart_NativeArguments args,
+                                            intptr_t retval) {
+  NativeArguments* arguments = reinterpret_cast<NativeArguments*>(args);
+  Isolate* isolate = arguments->isolate();
+  CHECK_ISOLATE(isolate);
+  if (Smi::IsValid64(retval)) {
+    Api::SetSmiReturnValue(arguments, retval);
+  } else {
+    // Slow path for Mints and Bigints.
+    ASSERT_CALLBACK_STATE(isolate);
+    Api::SetIntegerReturnValue(arguments, retval);
+  }
+}
+
+
+DART_EXPORT void Dart_SetDoubleReturnValue(Dart_NativeArguments args,
+                                           double retval) {
+  NativeArguments* arguments = reinterpret_cast<NativeArguments*>(args);
+  Isolate* isolate = arguments->isolate();
+  CHECK_ISOLATE(isolate);
+  ASSERT_CALLBACK_STATE(isolate);
+  Api::SetDoubleReturnValue(arguments, retval);
 }
 
 
diff --git a/runtime/vm/dart_api_impl.h b/runtime/vm/dart_api_impl.h
index c3b66e6..95b1b1a 100644
--- a/runtime/vm/dart_api_impl.h
+++ b/runtime/vm/dart_api_impl.h
@@ -6,6 +6,7 @@
 #define VM_DART_API_IMPL_H_
 
 #include "vm/allocation.h"
+#include "vm/native_arguments.h"
 #include "vm/object.h"
 
 namespace dart {
@@ -147,6 +148,11 @@
     return !raw->IsHeapObject();
   }
 
+  // Returns true if the handle holds a Dart Instance.
+  static bool IsInstance(Dart_Handle handle) {
+    return (ClassId(handle) >= kInstanceCid);
+  }
+
   // Returns the value of a Smi.
   static intptr_t SmiValue(Dart_Handle handle) {
     // TODO(turnidge): Assumes RawObject* is at offset zero.  Fix.
@@ -187,6 +193,20 @@
   // Helper function to get the peer value of an external string object.
   static bool ExternalStringGetPeerHelper(Dart_Handle object, void** peer);
 
+  // Helper function to set the return value of native functions.
+  static void SetReturnValue(NativeArguments* args, Dart_Handle retval) {
+    args->SetReturnUnsafe(UnwrapHandle(retval));
+  }
+  static void SetSmiReturnValue(NativeArguments* args, intptr_t retval) {
+    args->SetReturnUnsafe(Smi::New(retval));
+  }
+  static void SetIntegerReturnValue(NativeArguments* args, intptr_t retval) {
+    args->SetReturnUnsafe(Integer::New(retval));
+  }
+  static void SetDoubleReturnValue(NativeArguments* args, double retval) {
+    args->SetReturnUnsafe(Double::New(retval));
+  }
+
  private:
   // Thread local key used by the API. Currently holds the current
   // ApiNativeScope if any.
@@ -225,6 +245,9 @@
     return reinterpret_cast<Dart_Handle>(Api::AcquiredError(isolate));         \
   }                                                                            \
 
+#define ASSERT_CALLBACK_STATE(isolate)                                         \
+  ASSERT(isolate->no_callback_scope_depth() == 0)
+
 }  // namespace dart.
 
 #endif  // VM_DART_API_IMPL_H_
diff --git a/runtime/vm/debugger_api_impl.cc b/runtime/vm/debugger_api_impl.cc
index b3c3739..32e8a3a 100644
--- a/runtime/vm/debugger_api_impl.cc
+++ b/runtime/vm/debugger_api_impl.cc
@@ -523,9 +523,16 @@
   DARTSCOPE(isolate);
 
   UNWRAP_AND_CHECK_PARAM(Type, type, type_in);
+  if (!type.IsFinalized()) {
+    return Api::NewError("%s: type in 'type_in' is not a finalized type",
+                         CURRENT_FUNC);
+  }
+  if (!type.IsInstantiated()) {
+    return Api::NewError("%s: type in 'type_in' is not an instantiated type",
+                         CURRENT_FUNC);
+  }
   const Class& cls= Class::Handle(type.type_class());
-  intptr_t num_expected_type_arguments = cls.NumTypeParameters();
-  if (num_expected_type_arguments == 0) {
+  if (cls.NumTypeParameters() == 0) {
     // The super type has no type parameters or it is already instantiated
     // just return it.
     const AbstractType& type = AbstractType::Handle(cls.super_type());
@@ -536,26 +543,25 @@
   }
   // Set up the type arguments array for the super class type.
   const Class& super_cls = Class::Handle(cls.SuperClass());
-  num_expected_type_arguments = super_cls.NumTypeParameters();
+  intptr_t num_expected_type_arguments = super_cls.NumTypeArguments();
+  TypeArguments& super_type_args_array = TypeArguments::Handle();
   const AbstractTypeArguments& type_args_array =
       AbstractTypeArguments::Handle(type.arguments());
-  const TypeArguments& super_type_args_array =
-      TypeArguments::Handle(TypeArguments::New(num_expected_type_arguments));
-  AbstractType& type_arg = AbstractType::Handle();
-  intptr_t index_offset =
-      super_cls.NumTypeArguments() - num_expected_type_arguments;
-  for (intptr_t i = 0; i < num_expected_type_arguments; i++) {
-    type_arg ^= type_args_array.TypeAt(i + index_offset);
-    super_type_args_array.SetTypeAt(i, type_arg);
+  if (!type_args_array.IsNull() && (num_expected_type_arguments > 0)) {
+    super_type_args_array = TypeArguments::New(num_expected_type_arguments);
+    AbstractType& type_arg = AbstractType::Handle();
+    for (intptr_t i = 0; i < num_expected_type_arguments; i++) {
+      type_arg ^= type_args_array.TypeAt(i);
+      super_type_args_array.SetTypeAt(i, type_arg);
+    }
   }
 
   // Construct the super type object, canonicalize it and return.
   Type& instantiated_type = Type::Handle(
       Type::New(super_cls, super_type_args_array, Scanner::kDummyTokenIndex));
   ASSERT(!instantiated_type.IsNull());
-  instantiated_type ^= ClassFinalizer::FinalizeType(
-      super_cls, instantiated_type, ClassFinalizer::kCanonicalize);
-  return Api::NewHandle(isolate, instantiated_type.raw());
+  instantiated_type.SetIsFinalized();
+  return Api::NewHandle(isolate, instantiated_type.Canonicalize());
 }
 
 
diff --git a/runtime/vm/debugger_api_impl_test.cc b/runtime/vm/debugger_api_impl_test.cc
index 2f53eb8..7890195 100644
--- a/runtime/vm/debugger_api_impl_test.cc
+++ b/runtime/vm/debugger_api_impl_test.cc
@@ -1462,6 +1462,7 @@
       "}\n"
       "class Test5<A, B, C> extends Test4<A, B> {\n"
       "}\n"
+      "var s = new Set();\n"
       "int main() {\n"
       "}\n";
 
@@ -1479,6 +1480,8 @@
   Dart_Handle Test5_name = Dart_NewStringFromCString("Test5");
   Dart_Handle object_name = Dart_NewStringFromCString("Object");
   Dart_Handle int_name = Dart_NewStringFromCString("int");
+  Dart_Handle set_name = Dart_NewStringFromCString("Set");
+  Dart_Handle iterable_name = Dart_NewStringFromCString("IterableBase");
 
   Dart_Handle object_type = Dart_GetType(core_lib, object_name, 0, NULL);
   Dart_Handle int_type = Dart_GetType(core_lib, int_name, 0, NULL);
@@ -1494,14 +1497,14 @@
   Dart_Handle Test3_type = Dart_GetType(script_lib, Test3_name, 0, NULL);
   type_args = Dart_NewList(2);
   Dart_ListSetAt(type_args, 0, int_type);
-  Dart_ListSetAt(type_args, 1, int_type);
+  Dart_ListSetAt(type_args, 1, Test_type);
   Dart_Handle Test4_int_type = Dart_GetType(script_lib,
                                             Test4_name,
                                             2,
                                             &type_args);
   type_args = Dart_NewList(3);
   Dart_ListSetAt(type_args, 0, int_type);
-  Dart_ListSetAt(type_args, 1, int_type);
+  Dart_ListSetAt(type_args, 1, Test_type);
   Dart_ListSetAt(type_args, 2, int_type);
   Dart_Handle Test5_int_type = Dart_GetType(script_lib,
                                             Test5_name,
@@ -1535,6 +1538,14 @@
     const Type& actual_type = Api::UnwrapTypeHandle(isolate, super_type);
     EXPECT(expected_type.raw() == actual_type.raw());
   }
+  {
+    Dart_Handle set_type = Dart_GetType(core_lib, set_name, 0, NULL);
+    Dart_Handle super_type = Dart_GetSupertype(set_type);
+    Dart_Handle iterable_type = Dart_GetType(core_lib, iterable_name, 0, NULL);
+    const Type& expected_type = Api::UnwrapTypeHandle(isolate, iterable_type);
+    const Type& actual_type = Api::UnwrapTypeHandle(isolate, super_type);
+    EXPECT(expected_type.raw() == actual_type.raw());
+  }
 }
 
 }  // namespace dart
diff --git a/runtime/vm/disassembler_arm.cc b/runtime/vm/disassembler_arm.cc
index bcb2b45..6acd20f 100644
--- a/runtime/vm/disassembler_arm.cc
+++ b/runtime/vm/disassembler_arm.cc
@@ -1379,6 +1379,10 @@
       } else {
         Unknown(instr);
       }
+    } else if ((instr->Bits(8, 4) == 1) && (instr->Bit(4) == 0) &&
+               (instr->Bits(20, 2) == 3) && (instr->Bits(23, 2) == 3) &&
+               (instr->Bit(7) == 1) && (instr->Bits(16, 4) == 10)) {
+      Format(instr, "vzipqw 'qd, 'qm");
     } else if ((instr->Bits(8, 4) == 8) && (instr->Bit(4) == 1) &&
                (instr->Bits(23, 2) == 2)) {
       Format(instr, "vceqq'sz 'qd, 'qn, 'qm");
diff --git a/runtime/vm/disassembler_ia32.cc b/runtime/vm/disassembler_ia32.cc
index 49664cc..5f1131e 100644
--- a/runtime/vm/disassembler_ia32.cc
+++ b/runtime/vm/disassembler_ia32.cc
@@ -226,6 +226,10 @@
 // Returns NULL if the instruction is not handled here.
 static const char* F0Mnem(uint8_t f0byte) {
   switch (f0byte) {
+    case 0x12: return "movhlps";
+    case 0x14: return "unpcklps";
+    case 0x15: return "unpckhps";
+    case 0x16: return "movlhps";
     case 0xA2: return "cpuid";
     case 0x31: return "rdtsc";
     case 0xBE: return "movsx_b";
@@ -258,6 +262,16 @@
 }
 
 
+static bool IsTwoXmmRegInstruction(uint8_t f0byte) {
+  return f0byte == 0x28 || f0byte == 0x11 || f0byte == 0x12 ||
+         f0byte == 0x14 || f0byte == 0x15 || f0byte == 0x16 ||
+         f0byte == 0x51 || f0byte == 0x52 || f0byte == 0x53 ||
+         f0byte == 0x54 || f0byte == 0x56 || f0byte == 0x58 ||
+         f0byte == 0x59 || f0byte == 0x5C || f0byte == 0x5D ||
+         f0byte == 0x5E || f0byte == 0x5F;
+}
+
+
 // The implementation of x86 decoding based on the above tables.
 class X86Decoder : public ValueObject {
  public:
@@ -1362,22 +1376,6 @@
               PrintCPURegister(regop);
               Print(",cl");
             }
-          } else if (f0byte == 0x28) {
-            // movaps
-            Print(f0mnem);
-            int mod, regop, rm;
-            GetModRm(*data, &mod, &regop, &rm);
-            Print(" ");
-            PrintXmmRegister(regop);
-            Print(",");
-            data += PrintRightXmmOperand(data);
-          } else if (f0byte == 0x11) {
-            Print("movups ");
-            int mod, regop, rm;
-            GetModRm(*data, &mod, &regop, &rm);
-            data += PrintRightXmmOperand(data);
-            Print(",");
-            PrintXmmRegister(regop);
           } else if (f0byte == 0x10) {
             int mod, regop, rm;
             GetModRm(*data, &mod, &regop, &rm);
@@ -1385,10 +1383,7 @@
             PrintXmmRegister(regop);
             Print(",");
             data += PrintRightOperand(data);
-          } else if (f0byte == 0x51 || f0byte == 0x52 || f0byte == 0x53 ||
-                     f0byte == 0x54 || f0byte == 0x56 || f0byte == 0x58 ||
-                     f0byte == 0x59 || f0byte == 0x5C || f0byte == 0x5D ||
-                     f0byte == 0x5E || f0byte == 0x5F) {
+          } else if (IsTwoXmmRegInstruction(f0byte)) {
             int mod, regop, rm;
             GetModRm(*data, &mod, &regop, &rm);
             Print(f0mnem);
@@ -1598,6 +1593,22 @@
             } else {
               UNIMPLEMENTED();
             }
+          } else if (*data == 0x14) {
+            int mod, regop, rm;
+            GetModRm(*(data+1), &mod, &regop, &rm);
+            Print("unpcklpd ");
+            PrintXmmRegister(regop);
+            Print(",");
+            PrintXmmRegister(rm);
+            data += 2;
+          } else if (*data == 0x15) {
+            int mod, regop, rm;
+            GetModRm(*(data+1), &mod, &regop, &rm);
+            Print("unpckhpd ");
+            PrintXmmRegister(regop);
+            Print(",");
+            PrintXmmRegister(rm);
+            data += 2;
           } else {
             UNIMPLEMENTED();
           }
diff --git a/runtime/vm/disassembler_x64.cc b/runtime/vm/disassembler_x64.cc
index 4af7ba3..f42ebac 100644
--- a/runtime/vm/disassembler_x64.cc
+++ b/runtime/vm/disassembler_x64.cc
@@ -1268,7 +1268,11 @@
         current += PrintRightXMMOperand(current);
       } else {
         const char* mnemonic = "?";
-        if (opcode == 0x54) {
+        if (opcode == 0x14) {
+          mnemonic = "unpcklpd";
+        } else if (opcode == 0x15) {
+          mnemonic = "unpckhpd";
+        } else if (opcode == 0x54) {
           mnemonic = "andpd";
         } else  if (opcode == 0x56) {
           mnemonic = "orpd";
@@ -1425,12 +1429,18 @@
     byte_size_operand_ = idesc.byte_size_operation;
     current += PrintOperands(idesc.mnem, idesc.op_order_, current);
 
-  } else if (opcode == 0x51 || opcode == 0x52 || opcode == 0x53 ||
-             opcode == 0x54 || opcode == 0x56 || opcode == 0x57 ||
-             opcode == 0x58 || opcode == 0x59 || opcode == 0x5C ||
-             opcode == 0x5D || opcode == 0x5E || opcode == 0x5F) {
+  } else if (opcode == 0x12 || opcode == 0x14 || opcode == 0x15 ||
+             opcode == 0x16 || opcode == 0x51 || opcode == 0x52 ||
+             opcode == 0x53 || opcode == 0x54 || opcode == 0x56 ||
+             opcode == 0x57 || opcode == 0x58 || opcode == 0x59 ||
+             opcode == 0x5C || opcode == 0x5D || opcode == 0x5E ||
+             opcode == 0x5F) {
     const char* mnemonic = NULL;
     switch (opcode) {
+      case 0x12: mnemonic = "movhlps"; break;
+      case 0x14: mnemonic = "unpcklps"; break;
+      case 0x15: mnemonic = "unpckhps"; break;
+      case 0x16: mnemonic = "movlhps"; break;
       case 0x51: mnemonic = "sqrtps"; break;
       case 0x52: mnemonic = "rsqrtps"; break;
       case 0x53: mnemonic = "rcpps"; break;
diff --git a/runtime/vm/exceptions.cc b/runtime/vm/exceptions.cc
index 0f7b8a4..2712f6f 100644
--- a/runtime/vm/exceptions.cc
+++ b/runtime/vm/exceptions.cc
@@ -671,9 +671,9 @@
       library = Library::IsolateLibrary();
       class_name = &Symbols::IsolateUnhandledException();
       break;
-    case kFiftyThreeBitOverflowError:
+    case kJavascriptIntegerOverflowError:
       library = Library::CoreLibrary();
-      class_name = &Symbols::FiftyThreeBitOverflowError();
+      class_name = &Symbols::JavascriptIntegerOverflowError();
       break;
     case kAssertion:
       library = Library::CoreLibrary();
diff --git a/runtime/vm/exceptions.h b/runtime/vm/exceptions.h
index 04623a4..79f7e3a 100644
--- a/runtime/vm/exceptions.h
+++ b/runtime/vm/exceptions.h
@@ -52,7 +52,7 @@
     kNullThrown,
     kIsolateSpawn,
     kIsolateUnhandledException,
-    kFiftyThreeBitOverflowError,
+    kJavascriptIntegerOverflowError,
     kAssertion,
     kCast,
     kType,
diff --git a/runtime/vm/flow_graph_builder.cc b/runtime/vm/flow_graph_builder.cc
index eb6822b..900e7ff 100644
--- a/runtime/vm/flow_graph_builder.cc
+++ b/runtime/vm/flow_graph_builder.cc
@@ -1840,8 +1840,9 @@
   char name[64];
   OS::SNPrint(name, 64, ":tmp_local%"Pd, index);
   LocalVariable*  var =
-      new LocalVariable(0, String::ZoneHandle(Symbols::New(name)),
-                        Type::ZoneHandle(Type::DynamicType()));
+      new LocalVariable(0,
+                        String::ZoneHandle(Symbols::New(name)),
+                        *value->Type()->ToAbstractType());
   var->set_index(index);
   return var;
 }
@@ -1978,7 +1979,6 @@
     ReturnDefinition(new ConstantInstr(closure));
     return;
   }
-  Value* receiver = NULL;
   if (function.IsNonImplicitClosureFunction()) {
     // The context scope may have already been set by the non-optimizing
     // compiler.  If it was not, set it here.
@@ -1990,40 +1990,109 @@
       ASSERT(function.context_scope() == ContextScope::null());
       function.set_context_scope(context_scope);
     }
-    receiver = BuildNullValue();
+    ZoneGrowableArray<PushArgumentInstr*>* arguments =
+        new ZoneGrowableArray<PushArgumentInstr*>(2);
+    ASSERT(function.context_scope() != ContextScope::null());
+
+    // The function type of a closure may have type arguments. In that case,
+    // pass the type arguments of the instantiator.
+    const Class& cls = Class::ZoneHandle(function.signature_class());
+    ASSERT(!cls.IsNull());
+    const bool requires_type_arguments = cls.HasTypeArguments();
+    Value* type_arguments = NULL;
+    if (requires_type_arguments) {
+      ASSERT(cls.type_arguments_field_offset() ==
+             Closure::type_arguments_offset());
+      const Class& instantiator_class = Class::Handle(
+          owner()->parsed_function()->function().Owner());
+      type_arguments = BuildInstantiatorTypeArguments(node->token_pos(),
+                                                      instantiator_class,
+                                                      NULL);
+      arguments->Add(PushArgument(type_arguments));
+
+      Value* instantiator_val = Bind(new ConstantInstr(
+          Smi::ZoneHandle(Smi::New(StubCode::kNoInstantiator))));
+      arguments->Add(PushArgument(instantiator_val));
+    }
+    AllocateObjectInstr* alloc = new AllocateObjectInstr(node->token_pos(),
+                                                         cls,
+                                                         arguments);
+    alloc->set_closure_function(function);
+
+    // Create fake fields for function and context. Only the context field is
+    // stored at the allocation to be used later when inlining a closure call.
+    const Field& function_field =
+        Field::ZoneHandle(
+            Field::New(Symbols::ClosureFunctionField(),
+            false,  // !static
+            false,  // !final
+            false,  // !const
+            alloc->cls(),
+            0));  // No token position.
+    function_field.SetOffset(Closure::function_offset());
+    const Field& context_field =
+        Field::ZoneHandle(Field::New(
+            Symbols::ClosureContextField(),
+            false,  // !static
+            false,  // !final
+            false,  // !const
+            alloc->cls(),
+            0));  // No token position.
+    context_field.SetOffset(Closure::context_offset());
+    alloc->set_context_field(context_field);
+
+    Value* closure_val = Bind(alloc);
+    { LocalVariable* tmp_var = EnterTempLocalScope(closure_val);
+      // Store function.
+      Value* tmp_val = Bind(new LoadLocalInstr(*tmp_var));
+      Value* func_val =
+          Bind(new ConstantInstr(Function::ZoneHandle(function.raw())));
+      Do(new StoreInstanceFieldInstr(function_field,
+                                     tmp_val,
+                                     func_val,
+                                     kEmitStoreBarrier));
+      // Store current context.
+      tmp_val = Bind(new LoadLocalInstr(*tmp_var));
+      Value* context = Bind(new CurrentContextInstr());
+      Do(new StoreInstanceFieldInstr(context_field,
+                                     tmp_val,
+                                     context,
+                                     kEmitStoreBarrier));
+      ReturnDefinition(ExitTempLocalScope(tmp_var));
+    }
   } else {
     ASSERT(function.IsImplicitInstanceClosureFunction());
     ValueGraphVisitor for_receiver(owner(), temp_index());
     node->receiver()->Visit(&for_receiver);
     Append(for_receiver);
-    receiver = for_receiver.value();
-  }
-  PushArgumentInstr* push_receiver = PushArgument(receiver);
-  ZoneGrowableArray<PushArgumentInstr*>* arguments =
-      new ZoneGrowableArray<PushArgumentInstr*>(2);
-  arguments->Add(push_receiver);
-  ASSERT(function.context_scope() != ContextScope::null());
+    Value* receiver = for_receiver.value();
 
-  // The function type of a closure may have type arguments. In that case, pass
-  // the type arguments of the instantiator. Otherwise, pass null object.
-  const Class& cls = Class::Handle(function.signature_class());
-  ASSERT(!cls.IsNull());
-  const bool requires_type_arguments = cls.HasTypeArguments();
-  Value* type_arguments = NULL;
-  if (requires_type_arguments) {
-    ASSERT(!function.IsImplicitStaticClosureFunction());
-    const Class& instantiator_class = Class::Handle(
-        owner()->parsed_function()->function().Owner());
-    type_arguments = BuildInstantiatorTypeArguments(node->token_pos(),
-                                                    instantiator_class,
-                                                    NULL);
-  } else {
-    type_arguments = BuildNullValue();
+    PushArgumentInstr* push_receiver = PushArgument(receiver);
+    ZoneGrowableArray<PushArgumentInstr*>* arguments =
+        new ZoneGrowableArray<PushArgumentInstr*>(2);
+    arguments->Add(push_receiver);
+    ASSERT(function.context_scope() != ContextScope::null());
+
+    // The function type of a closure may have type arguments. In that case,
+    // pass the type arguments of the instantiator. Otherwise, pass null object.
+    const Class& cls = Class::Handle(function.signature_class());
+    ASSERT(!cls.IsNull());
+    const bool requires_type_arguments = cls.HasTypeArguments();
+    Value* type_arguments = NULL;
+    if (requires_type_arguments) {
+      const Class& instantiator_class = Class::Handle(
+          owner()->parsed_function()->function().Owner());
+      type_arguments = BuildInstantiatorTypeArguments(node->token_pos(),
+                                                      instantiator_class,
+                                                      NULL);
+    } else {
+      type_arguments = BuildNullValue();
+    }
+    PushArgumentInstr* push_type_arguments = PushArgument(type_arguments);
+    arguments->Add(push_type_arguments);
+    ReturnDefinition(
+        new CreateClosureInstr(node->function(), arguments, node->token_pos()));
   }
-  PushArgumentInstr* push_type_arguments = PushArgument(type_arguments);
-  arguments->Add(push_type_arguments);
-  ReturnDefinition(
-      new CreateClosureInstr(node->function(), arguments, node->token_pos()));
 }
 
 
@@ -2200,7 +2269,10 @@
       BuildConstructorTypeArguments(node, allocate_arguments);
     }
 
-    allocation = new AllocateObjectInstr(node, allocate_arguments);
+    allocation = new AllocateObjectInstr(
+        node->token_pos(),
+        Class::ZoneHandle(node->constructor().Owner()),
+        allocate_arguments);
   }
   return Bind(allocation);
 }
diff --git a/runtime/vm/flow_graph_inliner.cc b/runtime/vm/flow_graph_inliner.cc
index 229f7fc..247b0fe 100644
--- a/runtime/vm/flow_graph_inliner.cc
+++ b/runtime/vm/flow_graph_inliner.cc
@@ -681,6 +681,13 @@
           new LoadFieldInstr(new Value(closure),
                              Closure::context_offset(),
                              Type::ZoneHandle());
+      AllocateObjectInstr* alloc =
+          closure_call->ArgumentAt(0)->AsAllocateObject();
+      if ((alloc != NULL) && !alloc->closure_function().IsNull()) {
+        ASSERT(!alloc->context_field().IsNull());
+        context->set_field(&alloc->context_field());
+      }
+
       context->set_ssa_temp_index(caller_graph()->alloc_ssa_temp_index());
       context->InsertAfter(callee_entry);
       StoreContextInstr* set_context =
@@ -803,9 +810,19 @@
       ClosureCallInstr* call = calls[i];
       // Find the closure of the callee.
       ASSERT(call->ArgumentCount() > 0);
-      const CreateClosureInstr* closure =
+      Function& target = Function::ZoneHandle();
+      CreateClosureInstr* closure =
           call->ArgumentAt(0)->AsCreateClosure();
-      if (closure == NULL) {
+      if (closure != NULL) {
+        target ^= closure->function().raw();
+      }
+      AllocateObjectInstr* alloc =
+          call->ArgumentAt(0)->AsAllocateObject();
+      if ((alloc != NULL) && !alloc->closure_function().IsNull()) {
+        target ^= alloc->closure_function().raw();
+        ASSERT(target.signature_class() == alloc->cls().raw());
+      }
+      if (target.IsNull()) {
         TRACE_INLINING(OS::Print("     Bailout: non-closure operator\n"));
         continue;
       }
@@ -814,7 +831,7 @@
         arguments.Add(call->PushArgumentAt(i)->value());
       }
       InlinedCallData call_data(call, &arguments);
-      if (TryInlining(closure->function(),
+      if (TryInlining(target,
                       call->argument_names(),
                       &call_data)) {
         InlineCall(&call_data);
@@ -1180,6 +1197,10 @@
             callee_entry->AsGraphEntry()->normal_entry();
         cursor->LinkTo(target->next());
         target->ReplaceAsPredecessorWith(current_block);
+        // Unuse all inputs of the graph entry and the normal entry. They are
+        // not in the graph anymore.
+        callee_entry->UnuseAllInputs();
+        target->UnuseAllInputs();
         // All blocks that were dominated by the normal entry are now
         // dominated by the current block.
         for (intptr_t j = 0;
@@ -1230,6 +1251,8 @@
       if (callee_entry->IsGraphEntry()) {
         // Unshared.
         true_target = callee_entry->AsGraphEntry()->normal_entry();
+        // Unuse all inputs of the graph entry. It is not in the graph anymore.
+        callee_entry->UnuseAllInputs();
       } else if (callee_entry->IsTargetEntry()) {
         // Shared inlined body and this is the first entry.  We have already
         // constructed a join and this target jumps to it.
diff --git a/runtime/vm/flow_graph_optimizer.cc b/runtime/vm/flow_graph_optimizer.cc
index 170f5a4..fce131c 100644
--- a/runtime/vm/flow_graph_optimizer.cc
+++ b/runtime/vm/flow_graph_optimizer.cc
@@ -592,19 +592,9 @@
 }
 
 
-static bool HasOnlyTwoSmis(const ICData& ic_data) {
+static bool HasOnlyTwoOf(const ICData& ic_data, intptr_t cid) {
   return (ic_data.NumberOfChecks() == 1) &&
-      ICDataHasReceiverArgumentClassIds(ic_data, kSmiCid, kSmiCid);
-}
-
-static bool HasOnlyTwoFloat32x4s(const ICData& ic_data) {
-  return (ic_data.NumberOfChecks() == 1) &&
-      ICDataHasReceiverArgumentClassIds(ic_data, kFloat32x4Cid, kFloat32x4Cid);
-}
-
-static bool HasOnlyTwoUint32x4s(const ICData& ic_data) {
-  return (ic_data.NumberOfChecks() == 1) &&
-      ICDataHasReceiverArgumentClassIds(ic_data, kUint32x4Cid, kUint32x4Cid);
+      ICDataHasReceiverArgumentClassIds(ic_data, cid, cid);
 }
 
 // Returns false if the ICData contains anything other than the 4 combinations
@@ -1030,7 +1020,7 @@
   switch (op_kind) {
     case Token::kADD:
     case Token::kSUB:
-      if (HasOnlyTwoSmis(ic_data)) {
+      if (HasOnlyTwoOf(ic_data, kSmiCid)) {
         // Don't generate smi code if the IC data is marked because
         // of an overflow.
         operands_type = (ic_data.deopt_reason() == kDeoptBinarySmiOp)
@@ -1044,14 +1034,14 @@
         operands_type = kMintCid;
       } else if (ShouldSpecializeForDouble(ic_data)) {
         operands_type = kDoubleCid;
-      } else if (HasOnlyTwoFloat32x4s(ic_data)) {
+      } else if (HasOnlyTwoOf(ic_data, kFloat32x4Cid)) {
         operands_type = kFloat32x4Cid;
       } else {
         return false;
       }
       break;
     case Token::kMUL:
-      if (HasOnlyTwoSmis(ic_data)) {
+      if (HasOnlyTwoOf(ic_data, kSmiCid)) {
         // Don't generate smi code if the IC data is marked because of an
         // overflow.
         // TODO(fschneider): Add unboxed mint multiplication.
@@ -1059,23 +1049,24 @@
         operands_type = kSmiCid;
       } else if (ShouldSpecializeForDouble(ic_data)) {
         operands_type = kDoubleCid;
-      } else if (HasOnlyTwoFloat32x4s(ic_data)) {
+      } else if (HasOnlyTwoOf(ic_data, kFloat32x4Cid)) {
         operands_type = kFloat32x4Cid;
       } else {
         return false;
       }
       break;
     case Token::kDIV:
-      if (ShouldSpecializeForDouble(ic_data) || HasOnlyTwoSmis(ic_data)) {
+      if (ShouldSpecializeForDouble(ic_data) ||
+          HasOnlyTwoOf(ic_data, kSmiCid)) {
         operands_type = kDoubleCid;
-      } else if (HasOnlyTwoFloat32x4s(ic_data)) {
+      } else if (HasOnlyTwoOf(ic_data, kFloat32x4Cid)) {
         operands_type = kFloat32x4Cid;
       } else {
         return false;
       }
       break;
     case Token::kMOD:
-      if (HasOnlyTwoSmis(ic_data)) {
+      if (HasOnlyTwoOf(ic_data, kSmiCid)) {
         operands_type = kSmiCid;
       } else {
         return false;
@@ -1084,11 +1075,11 @@
     case Token::kBIT_AND:
     case Token::kBIT_OR:
     case Token::kBIT_XOR:
-      if (HasOnlyTwoSmis(ic_data)) {
+      if (HasOnlyTwoOf(ic_data, kSmiCid)) {
         operands_type = kSmiCid;
       } else if (HasTwoMintOrSmi(ic_data)) {
         operands_type = kMintCid;
-      } else if (HasOnlyTwoUint32x4s(ic_data)) {
+      } else if (HasOnlyTwoOf(ic_data, kUint32x4Cid)) {
         operands_type = kUint32x4Cid;
       } else {
         return false;
@@ -1096,7 +1087,7 @@
       break;
     case Token::kSHR:
     case Token::kSHL:
-      if (HasOnlyTwoSmis(ic_data)) {
+      if (HasOnlyTwoOf(ic_data, kSmiCid)) {
         // Left shift may overflow from smi into mint or big ints.
         // Don't generate smi code if the IC data is marked because
         // of an overflow.
@@ -1117,7 +1108,7 @@
       }
       break;
     case Token::kTRUNCDIV:
-      if (HasOnlyTwoSmis(ic_data)) {
+      if (HasOnlyTwoOf(ic_data, kSmiCid)) {
         if (ic_data.deopt_reason() == kDeoptBinarySmiOp) return false;
         operands_type = kSmiCid;
       } else {
@@ -1336,7 +1327,6 @@
     }
     AddToGuardedFields(field);
   }
-  load->set_field_name(String::Handle(field.name()).ToCString());
 
   // Discard the environment from the original instruction because the load
   // can't deoptimize.
@@ -2053,6 +2043,26 @@
       ReplaceCall(call, minmax);
       return true;
     }
+    case MethodRecognizer::kFloat32x4WithZWInXY:
+    case MethodRecognizer::kFloat32x4InterleaveXY:
+    case MethodRecognizer::kFloat32x4InterleaveZW:
+    case MethodRecognizer::kFloat32x4InterleaveXYPairs:
+    case MethodRecognizer::kFloat32x4InterleaveZWPairs: {
+      Definition* left = call->ArgumentAt(0);
+      Definition* right = call->ArgumentAt(1);
+      // Type check left.
+      AddCheckClass(left,
+                    ICData::ZoneHandle(
+                        call->ic_data()->AsUnaryClassChecksForArgNr(0)),
+                    call->deopt_id(),
+                    call->env(),
+                    call);
+      Float32x4TwoArgShuffleInstr* two_arg_shuffle =
+          new Float32x4TwoArgShuffleInstr(recognized_kind, new Value(left),
+                                          new Value(right), call->deopt_id());
+      ReplaceCall(call, two_arg_shuffle);
+      return true;
+    }
     case MethodRecognizer::kFloat32x4Scale: {
       Definition* left = call->ArgumentAt(0);
       Definition* right = call->ArgumentAt(1);
@@ -2757,15 +2767,14 @@
                                           Instruction* current_instruction) {
   ASSERT(ic_data.num_args_tested() == 2);
   ASSERT(comp->operation_cid() == kIllegalCid);
-  Instruction* instr = current_iterator()->Current();
-  if (HasOnlyTwoSmis(ic_data)) {
-    InsertBefore(instr,
+  if (HasOnlyTwoOf(ic_data, kSmiCid)) {
+    InsertBefore(current_instruction,
                  new CheckSmiInstr(comp->left()->Copy(), comp->deopt_id()),
-                 instr->env(),
+                 current_instruction->env(),
                  Definition::kEffect);
-    InsertBefore(instr,
+    InsertBefore(current_instruction,
                  new CheckSmiInstr(comp->right()->Copy(), comp->deopt_id()),
-                 instr->env(),
+                 current_instruction->env(),
                  Definition::kEffect);
     comp->set_operation_cid(kSmiCid);
   } else if (HasTwoMintOrSmi(ic_data) &&
@@ -2780,11 +2789,11 @@
         // We cannot use double comparison on two Smi-s.
         ASSERT(comp->operation_cid() == kIllegalCid);
       } else {
-        InsertBefore(instr,
+        InsertBefore(current_instruction,
                      new CheckEitherNonSmiInstr(comp->left()->Copy(),
                                                 comp->right()->Copy(),
                                                 comp->deopt_id()),
-                     instr->env(),
+                     current_instruction->env(),
                      Definition::kEffect);
         comp->set_operation_cid(kDoubleCid);
       }
@@ -2872,10 +2881,54 @@
 }
 
 
+// Returns true if we converted EqualityCompare to StrictCompare.
+template <typename T>
+bool FlowGraphOptimizer::StrictifyEqualityCompareWithICData(
+    EqualityCompareInstr* compare,
+    const ICData& unary_ic_data,
+    T current_instruction) {
+  ASSERT(unary_ic_data.num_args_tested() == 1);
+  if (unary_ic_data.NumberOfChecks() <= FLAG_max_polymorphic_checks) {
+    // If possible classes do not override Object's equality then replace
+    // with strict equality.
+    Function& target = Function::Handle();
+    Class& targets_class = Class::Handle();
+    for (intptr_t i = 0; i < unary_ic_data.NumberOfChecks(); i++) {
+      intptr_t cid = kIllegalCid;
+      unary_ic_data.GetOneClassCheckAt(i, &cid, &target);
+      targets_class = target.Owner();
+      if (targets_class.id() != kInstanceCid) {
+        // Overriden equality operator.
+        return false;
+      }
+    }
+    AddCheckClass(compare->left()->definition(),
+                  unary_ic_data,
+                  compare->deopt_id(),
+                  current_instruction->env(),
+                  current_instruction);
+    ASSERT((compare->kind() == Token::kEQ) || (compare->kind() == Token::kNE));
+    Token::Kind strict_kind = (compare->kind() == Token::kEQ) ?
+        Token::kEQ_STRICT : Token::kNE_STRICT;
+    StrictCompareInstr* strict_comp =
+        new StrictCompareInstr(compare->token_pos(),
+                               strict_kind,
+                               compare->left()->Copy(),
+                               compare->right()->Copy());
+    // Numbers override equality and are therefore not part of this conversion.
+    strict_comp->set_needs_number_check(false);
+    current_instruction->ReplaceWith(strict_comp, current_iterator());
+    return true;
+  }
+  return false;
+}
+
+
 template <typename T>
 void FlowGraphOptimizer::HandleEqualityCompare(EqualityCompareInstr* comp,
                                                T current_instruction) {
   if (StrictifyEqualityCompare(comp, current_instruction)) {
+    // Based on input types, equality converted to strict-equality.
     return;
   }
 
@@ -2891,6 +2944,14 @@
     return;
   }
 
+  const ICData& unary_checks_0 =
+      ICData::ZoneHandle(comp->ic_data()->AsUnaryClassChecks());
+  if (StrictifyEqualityCompareWithICData(
+        comp, unary_checks_0, current_instruction)) {
+    // Based on ICData, equality converted to strict-equality.
+    return;
+  }
+
   // Check if ICDData contains checks with Smi/Null combinations. In that case
   // we can still emit the optimized Smi equality operation but need to add
   // checks for null or Smi.
@@ -2901,8 +2962,6 @@
   if (ICDataHasOnlyReceiverArgumentClassIds(ic_data,
                                             smi_or_null,
                                             smi_or_null)) {
-    const ICData& unary_checks_0 =
-        ICData::ZoneHandle(comp->ic_data()->AsUnaryClassChecks());
     AddCheckClass(comp->left()->definition(),
                   unary_checks_0,
                   comp->deopt_id(),
@@ -4722,8 +4781,8 @@
 
               if (alloc->ArgumentCount() > 0) {
                 ASSERT(alloc->ArgumentCount() == 2);
-                const Class& cls = Class::Handle(alloc->constructor().Owner());
-                intptr_t type_args_offset = cls.type_arguments_field_offset();
+                intptr_t type_args_offset =
+                    alloc->cls().type_arguments_field_offset();
                 if (load->offset_in_bytes() == type_args_offset) {
                   (*out_values)[load->place_id()] =
                       alloc->PushArgumentAt(0)->value()->definition();
@@ -6372,6 +6431,11 @@
   SetValue(instr, non_constant_);
 }
 
+void ConstantPropagator::VisitFloat32x4TwoArgShuffle(
+    Float32x4TwoArgShuffleInstr* instr) {
+  SetValue(instr, non_constant_);
+}
+
 
 void ConstantPropagator::VisitUint32x4BoolConstructor(
     Uint32x4BoolConstructorInstr* instr) {
@@ -7112,7 +7176,7 @@
        use != NULL;
        use = use->next_use()) {
     if (!(use->instruction()->IsStoreInstanceField() &&
-          use->use_index() == 0)) {
+          (use->use_index() == 0))) {
       return false;
     }
   }
@@ -7250,6 +7314,7 @@
 // present there.
 static void AddInstruction(GrowableArray<Instruction*>* exits,
                            Instruction* exit) {
+  ASSERT(!exit->IsGraphEntry());
   for (intptr_t i = 0; i < exits->length(); i++) {
     if ((*exits)[i] == exit) {
       return;
@@ -7325,10 +7390,9 @@
             false,  // !static
             false,  // !final
             false,  // !const
-            Class::Handle(alloc->constructor().Owner()),
+            alloc->cls(),
             0));  // No token position.
-    const Class& cls = Class::Handle(alloc->constructor().Owner());
-    type_args_field.SetOffset(cls.type_arguments_field_offset());
+    type_args_field.SetOffset(alloc->cls().type_arguments_field_offset());
     AddField(fields, type_args_field);
   }
 
@@ -7341,9 +7405,8 @@
   }
 
   // Insert materializations at environment uses.
-  const Class& cls = Class::Handle(alloc->constructor().Owner());
   for (intptr_t i = 0; i < exits.length(); i++) {
-    CreateMaterializationAt(exits[i], alloc, cls, *fields);
+    CreateMaterializationAt(exits[i], alloc, alloc->cls(), *fields);
   }
 }
 
diff --git a/runtime/vm/flow_graph_optimizer.h b/runtime/vm/flow_graph_optimizer.h
index ced6e0f..d92ee29 100644
--- a/runtime/vm/flow_graph_optimizer.h
+++ b/runtime/vm/flow_graph_optimizer.h
@@ -189,6 +189,11 @@
   bool StrictifyEqualityCompare(EqualityCompareInstr* compare,
                                 T current_instruction) const;
 
+  template <typename T>
+  bool StrictifyEqualityCompareWithICData(EqualityCompareInstr* compare,
+                                          const ICData& unary_ic_data,
+                                          T current_instruction);
+
   void OptimizeLeftShiftBitAndSmiOp(Definition* bit_and_instr,
                                     Definition* left_instr,
                                     Definition* right_instr);
diff --git a/runtime/vm/flow_graph_type_propagator.cc b/runtime/vm/flow_graph_type_propagator.cc
index fd021ff..e20774b 100644
--- a/runtime/vm/flow_graph_type_propagator.cc
+++ b/runtime/vm/flow_graph_type_propagator.cc
@@ -865,8 +865,8 @@
 }
 
 
-CompileType DropTempsInstr::ComputeType() const {
-  return CompileType::Dynamic();
+CompileType* DropTempsInstr::ComputeInitialType() const {
+  return value()->Type();
 }
 
 
@@ -915,8 +915,14 @@
 
 
 CompileType AllocateObjectInstr::ComputeType() const {
+  if (!closure_function().IsNull()) {
+    ASSERT(cls().raw() == closure_function().signature_class());
+    return CompileType(CompileType::kNonNullable,
+                       cls().id(),
+                       &Type::ZoneHandle(cls().SignatureType()));
+  }
   // TODO(vegorov): Incorporate type arguments into the returned type.
-  return CompileType::FromCid(cid_);
+  return CompileType::FromCid(cls().id());
 }
 
 
@@ -1082,6 +1088,11 @@
 }
 
 
+CompileType Float32x4TwoArgShuffleInstr::ComputeType() const {
+  return CompileType::FromCid(kFloat32x4Cid);
+}
+
+
 CompileType Uint32x4BoolConstructorInstr::ComputeType() const {
   return CompileType::FromCid(kUint32x4Cid);
 }
diff --git a/runtime/vm/il_printer.cc b/runtime/vm/il_printer.cc
index 638081c..e396518 100644
--- a/runtime/vm/il_printer.cc
+++ b/runtime/vm/il_printer.cc
@@ -475,7 +475,7 @@
 
 
 void AllocateObjectInstr::PrintOperandsTo(BufferFormatter* f) const {
-  f->Print("%s", Class::Handle(constructor().Owner()).ToCString());
+  f->Print("%s", cls().ToCString());
   for (intptr_t i = 0; i < ArgumentCount(); i++) {
     f->Print(", ");
     PushArgumentAt(i)->value()->PrintTo(f);
@@ -526,11 +526,8 @@
   instance()->PrintTo(f);
   f->Print(", %"Pd, offset_in_bytes());
 
-  if (field_name_ != NULL) {
-    f->Print(" {%s}", field_name_);
-  }
-
   if (field() != NULL) {
+    f->Print(" {%s}", String::Handle(field()->name()).ToCString());
     const char* expected = "?";
     if (field()->guarded_cid() != kIllegalCid) {
       const Class& cls = Class::Handle(
@@ -706,6 +703,14 @@
 }
 
 
+void Float32x4TwoArgShuffleInstr::PrintOperandsTo(BufferFormatter* f) const {
+  f->Print("%s, ", MethodRecognizer::KindToCString(op_kind()));
+  left()->PrintTo(f);
+  f->Print(", ");
+  right()->PrintTo(f);
+}
+
+
 void Uint32x4BoolConstructorInstr::PrintOperandsTo(BufferFormatter* f) const {
   f->Print("Uint32x4.bool(");
   value0()->PrintTo(f);
diff --git a/runtime/vm/intermediate_language.h b/runtime/vm/intermediate_language.h
index dc9768c..2492bfa 100644
--- a/runtime/vm/intermediate_language.h
+++ b/runtime/vm/intermediate_language.h
@@ -108,6 +108,11 @@
   V(_Float32x4, withZ, Float32x4WithZ, 881355277)                              \
   V(_Float32x4, withW, Float32x4WithW, 441497035)                              \
   V(_Float32x4, _toUint32x4, Float32x4ToUint32x4, 802289205)                   \
+  V(_Float32x4, withZWInXY, Float32x4WithZWInXY, 465519415)                    \
+  V(_Float32x4, interleaveXY, Float32x4InterleaveXY, 465519415)                \
+  V(_Float32x4, interleaveZW, Float32x4InterleaveZW, 465519415)                \
+  V(_Float32x4, interleaveXYPairs, Float32x4InterleaveXYPairs, 465519415)      \
+  V(_Float32x4, interleaveZWPairs, Float32x4InterleaveZWPairs, 465519415)      \
   V(Uint32x4, Uint32x4.bool, Uint32x4BoolConstructor, 487876159)               \
   V(_Uint32x4, get:flagX, Uint32x4GetFlagX, 782547529)                         \
   V(_Uint32x4, get:flagY, Uint32x4GetFlagY, 782547529)                         \
@@ -613,6 +618,7 @@
   M(Float32x4Clamp)                                                            \
   M(Float32x4With)                                                             \
   M(Float32x4ToUint32x4)                                                       \
+  M(Float32x4TwoArgShuffle)                                                    \
   M(MaterializeObject)                                                         \
   M(Uint32x4BoolConstructor)                                                   \
   M(Uint32x4GetFlag)                                                           \
@@ -899,6 +905,7 @@
   friend class Float32x4ClampInstr;
   friend class Float32x4WithInstr;
   friend class Float32x4ToUint32x4Instr;
+  friend class Float32x4TwoArgShuffleInstr;
   friend class Uint32x4BoolConstructorInstr;
   friend class Uint32x4GetFlagInstr;
   friend class Uint32x4SetFlagInstr;
@@ -3187,7 +3194,7 @@
 
   intptr_t num_temps() const { return num_temps_; }
 
-  virtual CompileType ComputeType() const;
+  virtual CompileType* ComputeInitialType() const;
 
   virtual bool CanDeoptimize() const { return false; }
 
@@ -3671,12 +3678,15 @@
 
 class AllocateObjectInstr : public TemplateDefinition<0> {
  public:
-  AllocateObjectInstr(ConstructorCallNode* node,
+  AllocateObjectInstr(intptr_t token_pos,
+                      const Class& cls,
                       ZoneGrowableArray<PushArgumentInstr*>* arguments)
-      : ast_node_(*node),
+      : token_pos_(token_pos),
+        cls_(cls),
         arguments_(arguments),
-        cid_(Class::Handle(node->constructor().Owner()).id()),
-        identity_(kUnknown) {
+        identity_(kUnknown),
+        closure_function_(Function::ZoneHandle()),
+        context_field_(Field::ZoneHandle()) {
     // Either no arguments or one type-argument and one instantiator.
     ASSERT(arguments->is_empty() || (arguments->length() == 2));
   }
@@ -3689,8 +3699,18 @@
     return (*arguments_)[index];
   }
 
-  const Function& constructor() const { return ast_node_.constructor(); }
-  intptr_t token_pos() const { return ast_node_.token_pos(); }
+  const Class& cls() const { return cls_; }
+  intptr_t token_pos() const { return token_pos_; }
+
+  const Function& closure_function() const { return closure_function_; }
+  void set_closure_function(const Function& function) {
+    closure_function_ ^= function.raw();
+  }
+
+  const Field& context_field() const { return context_field_; }
+  void set_context_field(const Field& field) {
+    context_field_ ^= field.raw();
+  }
 
   virtual void PrintOperandsTo(BufferFormatter* f) const;
 
@@ -3713,10 +3733,12 @@
   void set_identity(Identity identity) { identity_ = identity; }
 
  private:
-  const ConstructorCallNode& ast_node_;
+  const intptr_t token_pos_;
+  const Class& cls_;
   ZoneGrowableArray<PushArgumentInstr*>* const arguments_;
-  const intptr_t cid_;
   Identity identity_;
+  Function& closure_function_;
+  Field& context_field_;
 
   DISALLOW_COPY_AND_ASSIGN(AllocateObjectInstr);
 };
@@ -3965,7 +3987,6 @@
         result_cid_(kDynamicCid),
         immutable_(immutable),
         recognized_kind_(MethodRecognizer::kUnknown),
-        field_name_(NULL),
         field_(NULL) {
     ASSERT(type.IsZoneHandle());  // May be null if field is not an instance.
     SetInputAt(0, instance);
@@ -3977,9 +3998,6 @@
   void set_result_cid(intptr_t value) { result_cid_ = value; }
   intptr_t result_cid() const { return result_cid_; }
 
-  void set_field_name(const char* name) { field_name_ = name; }
-  const char* field_name() const { return field_name_; }
-
   const Field* field() const { return field_; }
   void set_field(const Field* field) { field_ = field; }
 
@@ -4023,7 +4041,6 @@
 
   MethodRecognizer::Kind recognized_kind_;
 
-  const char* field_name_;
   const Field* field_;
 
   DISALLOW_COPY_AND_ASSIGN(LoadFieldInstr);
@@ -5512,6 +5529,59 @@
 };
 
 
+class Float32x4TwoArgShuffleInstr : public TemplateDefinition<2> {
+ public:
+  Float32x4TwoArgShuffleInstr(MethodRecognizer::Kind op_kind, Value* left,
+                              Value* right, intptr_t deopt_id)
+      : op_kind_(op_kind) {
+    SetInputAt(0, left);
+    SetInputAt(1, right);
+    deopt_id_ = deopt_id;
+  }
+
+  Value* left() const { return inputs_[0]; }
+  Value* right() const { return inputs_[1]; }
+
+  MethodRecognizer::Kind op_kind() const { return op_kind_; }
+
+  virtual void PrintOperandsTo(BufferFormatter* f) const;
+
+  virtual bool CanDeoptimize() const { return false; }
+
+  virtual Representation representation() const {
+    return kUnboxedFloat32x4;
+  }
+
+  virtual Representation RequiredInputRepresentation(intptr_t idx) const {
+    ASSERT((idx == 0) || (idx == 1));
+    return kUnboxedFloat32x4;
+  }
+
+  virtual intptr_t DeoptimizationTarget() const {
+    // Direct access since this instruction cannot deoptimize, and the deopt-id
+    // was inherited from another instruction that could deoptimize.
+    return deopt_id_;
+  }
+
+  DECLARE_INSTRUCTION(Float32x4TwoArgShuffle)
+  virtual CompileType ComputeType() const;
+
+  virtual bool AllowsCSE() const { return true; }
+  virtual EffectSet Effects() const { return EffectSet::None(); }
+  virtual EffectSet Dependencies() const { return EffectSet::None(); }
+  virtual bool AttributesEqual(Instruction* other) const {
+    return op_kind() == other->AsFloat32x4TwoArgShuffle()->op_kind();
+  }
+
+  virtual bool MayThrow() const { return false; }
+
+ private:
+  const MethodRecognizer::Kind op_kind_;
+
+  DISALLOW_COPY_AND_ASSIGN(Float32x4TwoArgShuffleInstr);
+};
+
+
 class Uint32x4SelectInstr : public TemplateDefinition<3> {
  public:
   Uint32x4SelectInstr(Value* mask, Value* trueValue, Value* falseValue,
diff --git a/runtime/vm/intermediate_language_arm.cc b/runtime/vm/intermediate_language_arm.cc
index dcf9143..dd22a39 100644
--- a/runtime/vm/intermediate_language_arm.cc
+++ b/runtime/vm/intermediate_language_arm.cc
@@ -3341,6 +3341,56 @@
 }
 
 
+LocationSummary* Float32x4TwoArgShuffleInstr::MakeLocationSummary() const {
+  const intptr_t kNumInputs = 2;
+  const intptr_t kNumTemps = 0;
+  LocationSummary* summary =
+      new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall);
+  summary->set_in(0, Location::RequiresFpuRegister());
+  summary->set_in(1, Location::RequiresFpuRegister());
+  summary->set_out(Location::SameAsFirstInput());
+  return summary;
+}
+
+
+void Float32x4TwoArgShuffleInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
+  QRegister left = locs()->in(0).fpu_reg();
+  QRegister right = locs()->in(1).fpu_reg();
+  QRegister result = locs()->out().fpu_reg();
+
+  ASSERT(result == left);
+
+  DRegister dleft0 = EvenDRegisterOf(left);
+  DRegister dleft1 = OddDRegisterOf(left);
+  DRegister dright0 = EvenDRegisterOf(right);
+  DRegister dright1 = OddDRegisterOf(right);
+
+  switch (op_kind()) {
+    case MethodRecognizer::kFloat32x4WithZWInXY:
+      __ vmovd(dleft0, dright1);
+      break;
+    case MethodRecognizer::kFloat32x4InterleaveXY:
+      __ vmovq(QTMP, right);
+      __ vzipqw(left, QTMP);
+      break;
+    case MethodRecognizer::kFloat32x4InterleaveZW:
+      __ vmovq(QTMP, right);
+      __ vzipqw(left, QTMP);
+      __ vmovq(left, QTMP);
+      break;
+    case MethodRecognizer::kFloat32x4InterleaveXYPairs:
+      __ vmovd(dleft1, dright0);
+      break;
+    case MethodRecognizer::kFloat32x4InterleaveZWPairs:
+      __ vmovq(QTMP, right);
+      __ vmovd(EvenDRegisterOf(QTMP), dleft1);
+      __ vmovq(result, QTMP);
+      break;
+    default: UNREACHABLE();
+  }
+}
+
+
 LocationSummary* Uint32x4BoolConstructorInstr::MakeLocationSummary() const {
   const intptr_t kNumInputs = 4;
   const intptr_t kNumTemps = 1;
@@ -4342,9 +4392,8 @@
 
 
 void AllocateObjectInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
-  const Class& cls = Class::ZoneHandle(constructor().Owner());
-  const Code& stub = Code::Handle(StubCode::GetAllocationStubForClass(cls));
-  const ExternalLabel label(cls.ToCString(), stub.EntryPoint());
+  const Code& stub = Code::Handle(StubCode::GetAllocationStubForClass(cls()));
+  const ExternalLabel label(cls().ToCString(), stub.EntryPoint());
   compiler->GenerateCall(token_pos(),
                          &label,
                          PcDescriptors::kOther,
diff --git a/runtime/vm/intermediate_language_ia32.cc b/runtime/vm/intermediate_language_ia32.cc
index fef3d76..b6c0a89 100644
--- a/runtime/vm/intermediate_language_ia32.cc
+++ b/runtime/vm/intermediate_language_ia32.cc
@@ -3371,6 +3371,45 @@
 }
 
 
+LocationSummary* Float32x4TwoArgShuffleInstr::MakeLocationSummary() const {
+  const intptr_t kNumInputs = 2;
+  const intptr_t kNumTemps = 0;
+  LocationSummary* summary =
+      new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall);
+  summary->set_in(0, Location::RequiresFpuRegister());
+  summary->set_in(1, Location::RequiresFpuRegister());
+  summary->set_out(Location::SameAsFirstInput());
+  return summary;
+}
+
+
+void Float32x4TwoArgShuffleInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
+  XmmRegister left = locs()->in(0).fpu_reg();
+  XmmRegister right = locs()->in(1).fpu_reg();
+
+  ASSERT(locs()->out().fpu_reg() == left);
+
+  switch (op_kind()) {
+    case MethodRecognizer::kFloat32x4WithZWInXY:
+      __ movhlps(left, right);
+    break;
+    case MethodRecognizer::kFloat32x4InterleaveXY:
+      __ unpcklps(left, right);
+    break;
+    case MethodRecognizer::kFloat32x4InterleaveZW:
+      __ unpckhps(left, right);
+    break;
+    case MethodRecognizer::kFloat32x4InterleaveXYPairs:
+      __ unpcklpd(left, right);
+    break;
+    case MethodRecognizer::kFloat32x4InterleaveZWPairs:
+      __ unpckhpd(left, right);
+    break;
+    default: UNREACHABLE();
+  }
+}
+
+
 LocationSummary* Uint32x4BoolConstructorInstr::MakeLocationSummary() const {
   const intptr_t kNumInputs = 4;
   const intptr_t kNumTemps = 0;
@@ -3647,6 +3686,7 @@
     summary->set_temp(0, Location::RequiresRegister());
     return summary;
   }
+
   ASSERT(result_cid() == kSmiCid);
   const intptr_t kNumInputs = 2;
   const intptr_t kNumTemps = 0;
@@ -3707,20 +3747,17 @@
     return;
   }
 
-  Label done;
   ASSERT(result_cid() == kSmiCid);
   Register left = locs()->in(0).reg();
   Register right = locs()->in(1).reg();
   Register result = locs()->out().reg();
   __ cmpl(left, right);
+  ASSERT(result == left);
   if (is_min) {
-    ASSERT(result == left);
-    __ j(LESS_EQUAL, &done, Assembler::kNearJump);
+    __ cmovgel(result, right);
   } else {
-    __ j(GREATER_EQUAL, &done, Assembler::kNearJump);
+    __ cmovlessl(result, right);
   }
-  __ movl(result, right);
-  __ Bind(&done);
 }
 
 
@@ -4812,9 +4849,8 @@
 
 
 void AllocateObjectInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
-  const Class& cls = Class::ZoneHandle(constructor().Owner());
-  const Code& stub = Code::Handle(StubCode::GetAllocationStubForClass(cls));
-  const ExternalLabel label(cls.ToCString(), stub.EntryPoint());
+  const Code& stub = Code::Handle(StubCode::GetAllocationStubForClass(cls()));
+  const ExternalLabel label(cls().ToCString(), stub.EntryPoint());
   compiler->GenerateCall(token_pos(),
                          &label,
                          PcDescriptors::kOther,
diff --git a/runtime/vm/intermediate_language_mips.cc b/runtime/vm/intermediate_language_mips.cc
index 85bf725..7051056 100644
--- a/runtime/vm/intermediate_language_mips.cc
+++ b/runtime/vm/intermediate_language_mips.cc
@@ -2998,6 +2998,17 @@
 }
 
 
+LocationSummary* Float32x4TwoArgShuffleInstr::MakeLocationSummary() const {
+  UNIMPLEMENTED();
+  return NULL;
+}
+
+
+void Float32x4TwoArgShuffleInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
+  UNIMPLEMENTED();
+}
+
+
 LocationSummary* Uint32x4BoolConstructorInstr::MakeLocationSummary() const {
   UNIMPLEMENTED();
   return NULL;
@@ -3833,9 +3844,8 @@
 void AllocateObjectInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
   __ TraceSimMsg("AllocateObjectInstr");
   __ Comment("AllocateObjectInstr");
-  const Class& cls = Class::ZoneHandle(constructor().Owner());
-  const Code& stub = Code::Handle(StubCode::GetAllocationStubForClass(cls));
-  const ExternalLabel label(cls.ToCString(), stub.EntryPoint());
+  const Code& stub = Code::Handle(StubCode::GetAllocationStubForClass(cls()));
+  const ExternalLabel label(cls().ToCString(), stub.EntryPoint());
   compiler->GenerateCall(token_pos(),
                          &label,
                          PcDescriptors::kOther,
diff --git a/runtime/vm/intermediate_language_x64.cc b/runtime/vm/intermediate_language_x64.cc
index 3ab4d0f..f93fc93 100644
--- a/runtime/vm/intermediate_language_x64.cc
+++ b/runtime/vm/intermediate_language_x64.cc
@@ -2151,18 +2151,20 @@
 }
 
 
-static void Emit53BitOverflowCheck(FlowGraphCompiler* compiler,
+static void Emit54BitOverflowCheck(FlowGraphCompiler* compiler,
                                    Label* overflow,
                                    Register result) {
   if (FLAG_throw_on_javascript_int_overflow) {
     ASSERT(overflow != NULL);
     __ movq(TMP, result);  // result is a tagged Smi.
-    // Bits 54...64 must be all 0 or all 1. (It would be bit 53, but result
+    // Bits 55...64 must be all 0 or all 1. (It would be bit 54, but result
     // is tagged.)
-    __ shlq(result, Immediate(64 - 54));
-    __ sarq(result, Immediate(64 - 54));
+    __ shlq(result, Immediate(64 - 55));
+    __ sarq(result, Immediate(64 - 55));
     __ cmpq(result, TMP);
-    __ j(NOT_EQUAL, overflow);  // 53-bit overflow.
+    __ j(NOT_EQUAL, overflow);  // 54-bit overflow.
+    __ cmpq(result, Immediate(-0x1FFFFFFFFFFFFFLL - 1));
+    __ j(EQUAL, overflow);  // The most negative 54-bit int is also disallowed.
   }
 }
 
@@ -2206,7 +2208,7 @@
       // Shift for result now we know there is no overflow.
       __ shlq(left, Immediate(value));
     }
-    Emit53BitOverflowCheck(compiler, deopt, result);
+    Emit54BitOverflowCheck(compiler, deopt, result);
     return;
   }
 
@@ -2236,7 +2238,7 @@
       __ SmiUntag(right);
       __ shlq(left, right);
     }
-    Emit53BitOverflowCheck(compiler, deopt, result);
+    Emit54BitOverflowCheck(compiler, deopt, result);
     return;
   }
 
@@ -2287,7 +2289,7 @@
     // Shift for result now we know there is no overflow.
     __ shlq(left, right);
   }
-  Emit53BitOverflowCheck(compiler, deopt, result);
+  Emit54BitOverflowCheck(compiler, deopt, result);
 }
 
 
@@ -2486,7 +2488,7 @@
         UNREACHABLE();
         break;
     }
-    Emit53BitOverflowCheck(compiler, deopt, result);
+    Emit54BitOverflowCheck(compiler, deopt, result);
     return;
   }  // locs()->in(1).IsConstant().
 
@@ -2529,7 +2531,7 @@
         UNREACHABLE();
         break;
     }
-    Emit53BitOverflowCheck(compiler, deopt, result);
+    Emit54BitOverflowCheck(compiler, deopt, result);
     return;
   }  // locs()->in(1).IsStackSlot().
 
@@ -2659,7 +2661,7 @@
       UNREACHABLE();
       break;
   }
-  Emit53BitOverflowCheck(compiler, deopt, result);
+  Emit54BitOverflowCheck(compiler, deopt, result);
 }
 
 
@@ -3412,6 +3414,45 @@
 }
 
 
+LocationSummary* Float32x4TwoArgShuffleInstr::MakeLocationSummary() const {
+  const intptr_t kNumInputs = 2;
+  const intptr_t kNumTemps = 0;
+  LocationSummary* summary =
+      new LocationSummary(kNumInputs, kNumTemps, LocationSummary::kNoCall);
+  summary->set_in(0, Location::RequiresFpuRegister());
+  summary->set_in(1, Location::RequiresFpuRegister());
+  summary->set_out(Location::SameAsFirstInput());
+  return summary;
+}
+
+
+void Float32x4TwoArgShuffleInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
+  XmmRegister left = locs()->in(0).fpu_reg();
+  XmmRegister right = locs()->in(1).fpu_reg();
+
+  ASSERT(locs()->out().fpu_reg() == left);
+
+  switch (op_kind()) {
+    case MethodRecognizer::kFloat32x4WithZWInXY:
+      __ movhlps(left, right);
+    break;
+    case MethodRecognizer::kFloat32x4InterleaveXY:
+      __ unpcklps(left, right);
+    break;
+    case MethodRecognizer::kFloat32x4InterleaveZW:
+      __ unpckhps(left, right);
+    break;
+    case MethodRecognizer::kFloat32x4InterleaveXYPairs:
+      __ unpcklpd(left, right);
+    break;
+    case MethodRecognizer::kFloat32x4InterleaveZWPairs:
+      __ unpckhpd(left, right);
+    break;
+    default: UNREACHABLE();
+  }
+}
+
+
 LocationSummary* Uint32x4BoolConstructorInstr::MakeLocationSummary() const {
   const intptr_t kNumInputs = 4;
   const intptr_t kNumTemps = 1;
@@ -3775,7 +3816,6 @@
     return;
   }
 
-  Label done;
   ASSERT(result_cid() == kSmiCid);
   Register left = locs()->in(0).reg();
   Register right = locs()->in(1).reg();
@@ -3783,12 +3823,10 @@
   __ cmpq(left, right);
   ASSERT(result == left);
   if (is_min) {
-    __ j(LESS_EQUAL, &done, Assembler::kNearJump);
+    __ cmovgeq(result, right);
   } else {
-    __ j(GREATER_EQUAL, &done, Assembler::kNearJump);
+    __ cmovlessq(result, right);
   }
-  __ movq(result, right);
-  __ Bind(&done);
 }
 
 
@@ -3801,7 +3839,7 @@
                                             kDeoptUnaryOp);
       __ negq(value);
       __ j(OVERFLOW, deopt);
-      Emit53BitOverflowCheck(compiler, deopt, value);
+      Emit54BitOverflowCheck(compiler, deopt, value);
       break;
     }
     case Token::kBIT_NOT:
@@ -3862,7 +3900,7 @@
   __ shlq(temp, Immediate(1));
   __ j(OVERFLOW, &do_call, Assembler::kNearJump);
   __ SmiTag(result);
-  Emit53BitOverflowCheck(compiler, &do_call, result);
+  Emit54BitOverflowCheck(compiler, &do_call, result);
   __ jmp(&done);
   __ Bind(&do_call);
   ASSERT(instance_call()->HasICData());
@@ -3908,7 +3946,7 @@
   __ shlq(temp, Immediate(1));
   __ j(OVERFLOW, deopt);
   __ SmiTag(result);
-  Emit53BitOverflowCheck(compiler, deopt, result);
+  Emit54BitOverflowCheck(compiler, deopt, result);
 }
 
 
@@ -4485,9 +4523,8 @@
 
 
 void AllocateObjectInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
-  const Class& cls = Class::ZoneHandle(constructor().Owner());
-  const Code& stub = Code::Handle(StubCode::GetAllocationStubForClass(cls));
-  const ExternalLabel label(cls.ToCString(), stub.EntryPoint());
+  const Code& stub = Code::Handle(StubCode::GetAllocationStubForClass(cls()));
+  const ExternalLabel label(cls().ToCString(), stub.EntryPoint());
   compiler->GenerateCall(token_pos(),
                          &label,
                          PcDescriptors::kOther,
diff --git a/runtime/vm/native_arguments.h b/runtime/vm/native_arguments.h
index 1027e3f..9be5e0e 100644
--- a/runtime/vm/native_arguments.h
+++ b/runtime/vm/native_arguments.h
@@ -47,8 +47,6 @@
 
 #endif
 
-void SetReturnValueHelper(Dart_NativeArguments, Dart_Handle);
-
 
 // Class NativeArguments is used to access arguments passed in from
 // generated dart code to a runtime function or a dart library native
@@ -158,9 +156,9 @@
   class ArgcBits : public BitField<int, kArgcBit, kArgcSize> {};
   class InstanceFunctionBit : public BitField<bool, kInstanceFunctionBit, 1> {};
   class ClosureFunctionBit : public BitField<bool, kClosureFunctionBit, 1> {};
+  friend class Api;
   friend class BootstrapNatives;
   friend class Simulator;
-  friend void SetReturnValueHelper(Dart_NativeArguments, Dart_Handle);
 
   // Since this function is passed a RawObject directly, we need to be
   // exceedingly careful when we use it.  If there are any other side
diff --git a/runtime/vm/object.cc b/runtime/vm/object.cc
index dae6510..44d0ea5 100644
--- a/runtime/vm/object.cc
+++ b/runtime/vm/object.cc
@@ -52,7 +52,8 @@
 DEFINE_FLAG(int, huge_method_cutoff_in_code_size, 200000,
     "Huge method cutoff in unoptimized code size (in bytes).");
 DEFINE_FLAG(bool, throw_on_javascript_int_overflow, false,
-    "Throw an exception when integer arithmetic exceeds 53 bits.");
+    "Throw an exception when the result of an integer calculation will not "
+    "fit into a javascript integer.");
 DECLARE_FLAG(bool, trace_compiler);
 DECLARE_FLAG(bool, eliminate_type_checks);
 DECLARE_FLAG(bool, enable_type_checks);
@@ -10503,6 +10504,13 @@
 }
 
 
+void Type::ResetIsFinalized() const {
+  ASSERT(IsFinalized());
+  set_type_state(RawType::kBeingFinalized);
+  SetIsFinalized();
+}
+
+
 void Type::set_is_being_finalized() const {
   ASSERT(!IsFinalized() && !IsBeingFinalized());
   set_type_state(RawType::kBeingFinalized);
@@ -11233,12 +11241,13 @@
 }
 
 
-// Throw FiftyThreeBitOverflow exception.
-static void ThrowFiftyThreeBitOverflow(const Integer& i) {
+// Throw JavascriptIntegerOverflow exception.
+static void ThrowJavascriptIntegerOverflow(const Integer& i) {
   const Array& exc_args = Array::Handle(Array::New(1));
   const String& i_str = String::Handle(String::New(i.ToCString()));
   exc_args.SetAt(0, i_str);
-  Exceptions::ThrowByType(Exceptions::kFiftyThreeBitOverflowError, exc_args);
+  Exceptions::ThrowByType(Exceptions::kJavascriptIntegerOverflowError,
+      exc_args);
 }
 
 
@@ -11251,7 +11260,7 @@
     ASSERT(!BigintOperations::FitsIntoSmi(big));
     ASSERT(!BigintOperations::FitsIntoInt64(big));
     if (FLAG_throw_on_javascript_int_overflow) {
-      ThrowFiftyThreeBitOverflow(big);
+      ThrowJavascriptIntegerOverflow(big);
     }
     return big.raw();
   }
@@ -11260,7 +11269,7 @@
 
 
 // This is called from LiteralToken::New() in the parser, so we can't
-// raise an exception for 53-bit overflow here. Instead we do it in
+// raise an exception for 54-bit overflow here. Instead we do it in
 // Parser::CurrentIntegerLiteral(), which is the point in the parser where
 // integer literals escape, so we can call Parser::ErrorMsg().
 RawInteger* Integer::NewCanonical(const String& str) {
@@ -11280,13 +11289,23 @@
 }
 
 
+// dart2js represents integers as double precision floats. It does this using
+// a sign bit and 53 fraction bits. This gives us the range
+// -2^54 - 1 ... 2^54 - 1, i.e. the same as a 54-bit signed integer
+// without the most negative number. Thus, here we check if the value is
+// a 54-bit signed integer and not -2^54
+static bool Is54BitNoMinInt(int64_t value) {
+  return (Utils::IsInt(54, value)) && (value != (-0x1FFFFFFFFFFFFFLL - 1));
+}
+
+
 RawInteger* Integer::New(int64_t value, Heap::Space space) {
   if ((value <= Smi::kMaxValue) && (value >= Smi::kMinValue)) {
     return Smi::New(value);
   }
-  if (FLAG_throw_on_javascript_int_overflow && !Utils::IsInt(53, value)) {
+  if (FLAG_throw_on_javascript_int_overflow && !Is54BitNoMinInt(value)) {
     const Integer &i = Integer::Handle(Mint::New(value));
-    ThrowFiftyThreeBitOverflow(i);
+    ThrowJavascriptIntegerOverflow(i);
   }
   return Mint::New(value, space);
 }
@@ -11297,7 +11316,7 @@
     if (FLAG_throw_on_javascript_int_overflow) {
       const Integer &i =
           Integer::Handle(BigintOperations::NewFromUint64(value));
-      ThrowFiftyThreeBitOverflow(i);
+      ThrowJavascriptIntegerOverflow(i);
     }
     return BigintOperations::NewFromUint64(value);
   } else {
@@ -11324,8 +11343,9 @@
 }
 
 
-// Returns true if the signed Integer requires more than 53 bits.
-bool Integer::CheckFiftyThreeBitOverflow() const {
+// Returns true if the signed Integer does not fit into a
+// Javascript (54-bit) integer.
+bool Integer::CheckJavascriptIntegerOverflow() const {
   // Always overflow if the value doesn't fit into an int64_t.
   int64_t value = 1ULL << 63;
   if (IsSmi()) {
@@ -11342,14 +11362,14 @@
       value = BigintOperations::ToInt64(big_value);
     }
   }
-  return !Utils::IsInt(53, value);
+  return !Is54BitNoMinInt(value);
 }
 
 
 RawInteger* Integer::AsValidInteger() const {
   if (FLAG_throw_on_javascript_int_overflow &&
-      CheckFiftyThreeBitOverflow()) {
-    ThrowFiftyThreeBitOverflow(*this);
+      CheckJavascriptIntegerOverflow()) {
+    ThrowJavascriptIntegerOverflow(*this);
   }
   if (IsSmi()) return raw();
   if (IsMint()) {
@@ -14360,6 +14380,12 @@
 }
 
 
+RawTypeParameter* MirrorReference::GetTypeParameterReferent() const {
+  ASSERT(Object::Handle(referent()).IsTypeParameter());
+  return TypeParameter::Cast(Object::Handle(referent())).raw();
+}
+
+
 RawMirrorReference* MirrorReference::New(const Object& referent,
                                          Heap::Space space) {
   ASSERT(Isolate::Current()->object_store()->mirror_reference_class()
diff --git a/runtime/vm/object.h b/runtime/vm/object.h
index a02cee2..2e0d6c7 100644
--- a/runtime/vm/object.h
+++ b/runtime/vm/object.h
@@ -3821,6 +3821,7 @@
     (raw_ptr()->type_state_ == RawType::kFinalizedUninstantiated);
   }
   void SetIsFinalized() const;
+  void ResetIsFinalized() const;  // Ignore current state and set again.
   virtual bool IsBeingFinalized() const {
     return raw_ptr()->type_state_ == RawType::kBeingFinalized;
   }
@@ -4137,8 +4138,8 @@
   RawInteger* ArithmeticOp(Token::Kind operation, const Integer& other) const;
   RawInteger* BitOp(Token::Kind operation, const Integer& other) const;
 
-  // Returns true if the Integer does not fit in 53 bits.
-  bool CheckFiftyThreeBitOverflow() const;
+  // Returns true if the Integer does not fit in a Javascript integer.
+  bool CheckJavascriptIntegerOverflow() const;
 
  private:
   // Return an integer in the form of a RawBigint.
@@ -5899,6 +5900,8 @@
 
   RawLibrary* GetLibraryReferent() const;
 
+  RawTypeParameter* GetTypeParameterReferent() const;
+
   static RawMirrorReference* New(const Object& referent,
                                  Heap::Space space = Heap::kNew);
 
diff --git a/runtime/vm/parser.cc b/runtime/vm/parser.cc
index 11bd5e7..61e184e 100644
--- a/runtime/vm/parser.cc
+++ b/runtime/vm/parser.cc
@@ -29,6 +29,7 @@
 DEFINE_FLAG(bool, trace_parser, false, "Trace parser operations.");
 DEFINE_FLAG(bool, warning_as_error, false, "Treat warnings as errors.");
 DEFINE_FLAG(bool, silent_warnings, false, "Silence warnings.");
+DECLARE_FLAG(bool, error_on_malformed_type);
 DECLARE_FLAG(bool, throw_on_javascript_int_overflow);
 
 static void CheckedModeHandler(bool value) {
@@ -378,9 +379,10 @@
   RawInteger* ri = Integer::RawCast(literal_token_.value());
   if (FLAG_throw_on_javascript_int_overflow) {
     const Integer& i = Integer::Handle(ri);
-    if (i.CheckFiftyThreeBitOverflow()) {
-      ErrorMsg(TokenPos(), "Integer literal does not fit in 53 bits: %s.",
-               i.ToCString());
+    if (i.CheckJavascriptIntegerOverflow()) {
+      ErrorMsg(TokenPos(),
+          "Integer literal does not fit in a Javascript integer: %s.",
+          i.ToCString());
     }
   }
   return ri;
@@ -2934,7 +2936,6 @@
           Error::Handle(),  // No previous error.
           current_class(),
           type_pos,
-          ClassFinalizer::kResolveTypeParameters,  // No compile-time error.
           "factory '%s' may not redirect to type parameter '%s'",
           method->name->ToCString(),
           String::Handle(type.UserVisibleName()).ToCString());
@@ -4119,7 +4120,6 @@
 
 
 RawAbstractTypeArguments* Parser::ParseTypeArguments(
-    Error* malformed_error,
     ClassFinalizer::FinalizationKind finalization) {
   TRACE_PARSER("ParseTypeArguments");
   if (CurrentToken() == Token::kLT) {
@@ -4129,14 +4129,8 @@
     do {
       ConsumeToken();
       type = ParseType(finalization);
-      // Only keep the error for the first malformed type argument.
-      if (malformed_error->IsNull() && type.IsMalformed()) {
-        *malformed_error = type.malformed_error();
-      }
-      // Map a malformed type argument to dynamic, so that malformed types with
-      // a resolved type class are handled properly in production mode.
+      // Map a malformed type argument to dynamic.
       if (type.IsMalformed()) {
-        ASSERT(finalization < ClassFinalizer::kCanonicalizeWellFormed);
         type = Type::DynamicType();
       }
       types.Add(type);
@@ -5375,6 +5369,10 @@
       function_type.set_malformed_error(error);
     }
 
+    // The function type was initially marked as instantiated, but it may
+    // actually be uninstantiated.
+    function_type.ResetIsFinalized();
+
     // The function variable type should have been patched above.
     ASSERT((function_variable == NULL) ||
            (function_variable->type().raw() == function_type.raw()));
@@ -6430,10 +6428,8 @@
     catch_seen = true;
     if (IsLiteral("on")) {
       ConsumeToken();
-      // TODO(regis): The spec may change in the way a malformed 'on' type is
-      // treated. For now, we require the type to be wellformed.
       exception_param.type = &AbstractType::ZoneHandle(
-          ParseType(ClassFinalizer::kCanonicalizeWellFormed));
+          ParseType(ClassFinalizer::kCanonicalize));
     } else {
       exception_param.type =
           &AbstractType::ZoneHandle(Type::DynamicType());
@@ -7141,13 +7137,15 @@
         }
         const intptr_t type_pos = TokenPos();
         const AbstractType& type = AbstractType::ZoneHandle(
-            ParseType(ClassFinalizer::kCanonicalizeExpression));
+            ParseType(ClassFinalizer::kCanonicalize));
         if (!type.IsInstantiated() &&
             (current_block_->scope->function_level() > 0)) {
           // Make sure that the instantiator is captured.
           CaptureInstantiator();
         }
         right_operand = new TypeNode(type_pos, type);
+        // If the type is malformed, it is actually malbounded in checked mode.
+        ASSERT(!type.IsMalformed() || FLAG_enable_type_checks);
         if (((op_kind == Token::kIS) || (op_kind == Token::kISNOT)) &&
             type.IsMalformed()) {
           // Note that a type error is thrown even if the tested value is null
@@ -8159,26 +8157,36 @@
           // referenced by a static member.
           if (ParsingStaticMember()) {
             ASSERT(scope_class.raw() == current_class().raw());
-            *type = ClassFinalizer::NewFinalizedMalformedType(
-                Error::Handle(),  // No previous error.
-                scope_class,
-                type->token_pos(),
-                finalization,
-                "type parameter '%s' cannot be referenced "
-                "from static member",
-                String::Handle(type_parameter.name()).ToCString());
+            if ((finalization == ClassFinalizer::kCanonicalizeWellFormed) ||
+                FLAG_error_on_malformed_type) {
+              *type = ClassFinalizer::NewFinalizedMalformedType(
+                  Error::Handle(),  // No previous error.
+                  scope_class,
+                  type->token_pos(),
+                  "type parameter '%s' cannot be referenced "
+                  "from static member",
+                  String::Handle(type_parameter.name()).ToCString());
+            } else {
+              // Map the malformed type to dynamic and ignore type arguments.
+              *type = Type::DynamicType();
+            }
             return;
           }
           // A type parameter cannot be parameterized, so make the type
           // malformed if type arguments have previously been parsed.
           if (!AbstractTypeArguments::Handle(type->arguments()).IsNull()) {
-            *type = ClassFinalizer::NewFinalizedMalformedType(
-                Error::Handle(),  // No previous error.
-                scope_class,
-                type_parameter.token_pos(),
-                finalization,
-                "type parameter '%s' cannot be parameterized",
-                String::Handle(type_parameter.name()).ToCString());
+            if ((finalization == ClassFinalizer::kCanonicalizeWellFormed) ||
+                FLAG_error_on_malformed_type) {
+              *type = ClassFinalizer::NewFinalizedMalformedType(
+                  Error::Handle(),  // No previous error.
+                  scope_class,
+                  type_parameter.token_pos(),
+                  "type parameter '%s' cannot be parameterized",
+                  String::Handle(type_parameter.name()).ToCString());
+            } else {
+              // Map the malformed type to dynamic and ignore type arguments.
+              *type = Type::DynamicType();
+            }
             return;
           }
           *type = type_parameter.raw();
@@ -8190,22 +8198,23 @@
       if (finalization > ClassFinalizer::kResolveTypeParameters) {
         // Resolve classname in the scope of the current library.
         Error& error = Error::Handle();
-        // If we finalize a type expression, as opposed to a type annotation,
-        // we tell the resolver (by passing NULL) to immediately report an
-        // ambiguous type as a compile time error.
         resolved_type_class = ResolveClassInCurrentLibraryScope(
             unresolved_class.token_pos(),
             unresolved_class_name,
-            finalization >= ClassFinalizer::kCanonicalizeExpression ?
-                NULL : &error);
+            &error);
         if (!error.IsNull()) {
-          *type = ClassFinalizer::NewFinalizedMalformedType(
-              error,
-              scope_class,
-              unresolved_class.token_pos(),
-              finalization,
-              "cannot resolve class '%s'",
-              unresolved_class_name.ToCString());
+          if ((finalization == ClassFinalizer::kCanonicalizeWellFormed) ||
+              FLAG_error_on_malformed_type) {
+            *type = ClassFinalizer::NewFinalizedMalformedType(
+                error,
+                scope_class,
+                unresolved_class.token_pos(),
+                "cannot resolve class '%s'",
+                unresolved_class_name.ToCString());
+          } else {
+            // Map the malformed type to dynamic and ignore type arguments.
+            *type = Type::DynamicType();
+          }
           return;
         }
       }
@@ -8214,39 +8223,46 @@
           LibraryPrefix::Handle(unresolved_class.library_prefix());
       // Resolve class name in the scope of the library prefix.
       Error& error = Error::Handle();
-      // If we finalize a type expression, as opposed to a type annotation, we
-      // tell the resolver (by passing NULL) to immediately report an ambiguous
-      // type as a compile time error.
       resolved_type_class = ResolveClassInPrefixScope(
           unresolved_class.token_pos(),
           lib_prefix,
           unresolved_class_name,
-          finalization >= ClassFinalizer::kCanonicalizeExpression ?
-              NULL : &error);
+          &error);
       if (!error.IsNull()) {
-        *type = ClassFinalizer::NewFinalizedMalformedType(
-            error,
-            scope_class,
-            unresolved_class.token_pos(),
-            finalization,
-            "cannot resolve class '%s'",
-            unresolved_class_name.ToCString());
+        if ((finalization == ClassFinalizer::kCanonicalizeWellFormed) ||
+            FLAG_error_on_malformed_type) {
+          *type = ClassFinalizer::NewFinalizedMalformedType(
+              error,
+              scope_class,
+              unresolved_class.token_pos(),
+              "cannot resolve class '%s'",
+              unresolved_class_name.ToCString());
+        } else {
+          // Map the malformed type to dynamic and ignore type arguments.
+          *type = Type::DynamicType();
+        }
         return;
       }
     }
     // At this point, we can only have a parameterized_type.
-    Type& parameterized_type = Type::Handle();
-    parameterized_type ^= type->raw();
+    const Type& parameterized_type = Type::Cast(*type);
     if (!resolved_type_class.IsNull()) {
       // Replace unresolved class with resolved type class.
       parameterized_type.set_type_class(resolved_type_class);
     } else if (finalization >= ClassFinalizer::kCanonicalize) {
-      // The type is malformed.
-      ClassFinalizer::FinalizeMalformedType(
-          Error::Handle(),  // No previous error.
-          current_class(), parameterized_type, finalization,
-          "type '%s' is not loaded",
-          String::Handle(parameterized_type.UserVisibleName()).ToCString());
+      if ((finalization == ClassFinalizer::kCanonicalizeWellFormed) ||
+          FLAG_error_on_malformed_type) {
+        ClassFinalizer::FinalizeMalformedType(
+            Error::Handle(),  // No previous error.
+            scope_class,
+            parameterized_type,
+            "type '%s' is not loaded",
+            String::Handle(parameterized_type.UserVisibleName()).ToCString());
+      } else {
+        // Map the malformed type to dynamic and ignore type arguments.
+        *type = Type::DynamicType();
+      }
+      return;
     }
   }
   // Resolve type arguments, if any.
@@ -8954,8 +8970,17 @@
     if (!is_top_level_ &&
         (type_name.lib_prefix == NULL) &&
         ResolveIdentInLocalScope(type_name.ident_pos, *type_name.ident, NULL)) {
-      ErrorMsg(type_name.ident_pos, "using '%s' in this context is invalid",
-               type_name.ident->ToCString());
+      // The type is malformed. Skip over its type arguments.
+      ParseTypeArguments(ClassFinalizer::kIgnore);
+      if (finalization == ClassFinalizer::kCanonicalizeWellFormed) {
+        return ClassFinalizer::NewFinalizedMalformedType(
+            Error::Handle(),  // No previous error.
+            current_class(),
+            type_name.ident_pos,
+            "using '%s' in this context is invalid",
+            type_name.ident->ToCString());
+      }
+      return Type::DynamicType();
     }
   }
   Object& type_class = Object::Handle(isolate());
@@ -8969,27 +8994,13 @@
                                       *type_name.ident,
                                       type_name.ident_pos);
   }
-  Error& malformed_error = Error::Handle(isolate());
-  AbstractTypeArguments& type_arguments =
-      AbstractTypeArguments::Handle(isolate(),
-                                    ParseTypeArguments(&malformed_error,
-                                                       finalization));
+  AbstractTypeArguments& type_arguments = AbstractTypeArguments::Handle(
+      isolate(), ParseTypeArguments(finalization));
   if (finalization == ClassFinalizer::kIgnore) {
     return Type::DynamicType();
   }
   AbstractType& type = AbstractType::Handle(
-      isolate(),
-      Type::New(type_class, type_arguments, type_name.ident_pos));
-  // In production mode, malformed type arguments are mapped to dynamic.
-  // In checked mode, a type with malformed type arguments is malformed.
-  if (FLAG_enable_type_checks && !malformed_error.IsNull()) {
-    Type& parameterized_type = Type::Handle(isolate());
-    parameterized_type ^= type.raw();
-    parameterized_type.set_type_class(
-        Class::Handle(isolate(), Object::dynamic_class()));
-    parameterized_type.set_arguments(Object::null_abstract_type_arguments());
-    parameterized_type.set_malformed_error(malformed_error);
-  }
+      isolate(), Type::New(type_class, type_arguments, type_name.ident_pos));
   if (finalization >= ClassFinalizer::kResolveTypeParameters) {
     ResolveTypeFromClass(current_class(), finalization, &type);
     if (finalization >= ClassFinalizer::kCanonicalize) {
@@ -9031,16 +9042,23 @@
   ConsumeToken();
 
   AbstractType& element_type = Type::ZoneHandle(Type::DynamicType());
+  AbstractTypeArguments& list_type_arguments =
+      AbstractTypeArguments::ZoneHandle(type_arguments.raw());
   // If no type argument vector is provided, leave it as null, which is
   // equivalent to using dynamic as the type argument for the element type.
-  if (!type_arguments.IsNull()) {
-    ASSERT(type_arguments.Length() > 0);
+  if (!list_type_arguments.IsNull()) {
+    ASSERT(list_type_arguments.Length() > 0);
     // List literals take a single type argument.
-    element_type = type_arguments.TypeAt(0);
-    if (type_arguments.Length() != 1) {
-      ErrorMsg(type_pos,
-               "a list literal takes one type argument specifying "
-               "the element type");
+    if (list_type_arguments.Length() == 1) {
+      element_type = list_type_arguments.TypeAt(0);
+    } else {
+      if (FLAG_error_on_malformed_type) {
+        ErrorMsg(type_pos,
+                 "a list literal takes one type argument specifying "
+                 "the element type");
+      }
+      // Ignore type arguments.
+      list_type_arguments = AbstractTypeArguments::null();
     }
     if (is_const && !element_type.IsInstantiated()) {
       ErrorMsg(type_pos,
@@ -9048,11 +9066,12 @@
                "a type variable");
     }
   }
-  ASSERT(type_arguments.IsNull() || (type_arguments.Length() == 1));
+  ASSERT((list_type_arguments.IsNull() && element_type.IsDynamicType()) ||
+         ((list_type_arguments.Length() == 1) && !element_type.IsNull()));
   const Class& array_class = Class::Handle(
       isolate()->object_store()->array_class());
   Type& type = Type::ZoneHandle(
-      Type::New(array_class, type_arguments, type_pos));
+      Type::New(array_class, list_type_arguments, type_pos));
   type ^= ClassFinalizer::FinalizeType(
       current_class(), type, ClassFinalizer::kCanonicalize);
   GrowableArray<AstNode*> element_list;
@@ -9087,7 +9106,7 @@
     Array& const_list =
         Array::ZoneHandle(Array::New(element_list.length(), Heap::kOld));
     const_list.SetTypeArguments(
-        AbstractTypeArguments::Handle(type_arguments.Canonicalize()));
+        AbstractTypeArguments::Handle(list_type_arguments.Canonicalize()));
     Error& malformed_error = Error::Handle();
     for (int i = 0; i < element_list.length(); i++) {
       AstNode* elem = element_list[i];
@@ -9124,14 +9143,14 @@
         factory_class.LookupFactory(
             PrivateCoreLibName(Symbols::ListLiteralFactory())));
     ASSERT(!factory_method.IsNull());
-    if (!type_arguments.IsNull() &&
-        !type_arguments.IsInstantiated() &&
+    if (!list_type_arguments.IsNull() &&
+        !list_type_arguments.IsInstantiated() &&
         (current_block_->scope->function_level() > 0)) {
       // Make sure that the instantiator is captured.
       CaptureInstantiator();
     }
     AbstractTypeArguments& factory_type_args =
-        AbstractTypeArguments::ZoneHandle(type_arguments.raw());
+        AbstractTypeArguments::ZoneHandle(list_type_arguments.raw());
     // If the factory class extends other parameterized classes, adjust the
     // type argument vector.
     if (!factory_type_args.IsNull() && (factory_class.NumTypeArguments() > 1)) {
@@ -9212,49 +9231,72 @@
   const intptr_t literal_pos = TokenPos();
   ConsumeToken();
 
+  AbstractType& key_type = Type::ZoneHandle(Type::DynamicType());
   AbstractType& value_type = Type::ZoneHandle(Type::DynamicType());
   AbstractTypeArguments& map_type_arguments =
       AbstractTypeArguments::ZoneHandle(type_arguments.raw());
   // If no type argument vector is provided, leave it as null, which is
-  // equivalent to using dynamic as the type argument for the value type.
+  // equivalent to using dynamic as the type argument for the both key and value
+  // types.
   if (!map_type_arguments.IsNull()) {
     ASSERT(map_type_arguments.Length() > 0);
     // Map literals take two type arguments.
-    if (map_type_arguments.Length() != 2) {
-      ErrorMsg(type_pos,
-               "a map literal takes two type arguments specifying "
-               "the key type and the value type");
-    }
-    const AbstractType& key_type =
-        AbstractType::Handle(map_type_arguments.TypeAt(0));
-    value_type = map_type_arguments.TypeAt(1);
-    if (!key_type.IsStringType()) {
-      ErrorMsg(type_pos, "the key type of a map literal must be 'String'");
-    }
-    if (is_const && !value_type.IsInstantiated()) {
-      ErrorMsg(type_pos,
-               "the type argument of a constant map literal cannot include "
-               "a type variable");
+    if (map_type_arguments.Length() == 2) {
+      key_type = map_type_arguments.TypeAt(0);
+      value_type = map_type_arguments.TypeAt(1);
+      if (is_const && !type_arguments.IsInstantiated()) {
+        ErrorMsg(type_pos,
+                 "the type arguments of a constant map literal cannot include "
+                 "a type variable");
+      }
+      if (key_type.IsMalformed()) {
+        if (FLAG_error_on_malformed_type) {
+          ErrorMsg(Error::Handle(key_type.malformed_error()));
+        }
+        // Map malformed key type to dynamic.
+        key_type = Type::DynamicType();
+        map_type_arguments.SetTypeAt(0, key_type);
+      }
+      if (value_type.IsMalformed()) {
+        if (FLAG_error_on_malformed_type) {
+          ErrorMsg(Error::Handle(value_type.malformed_error()));
+        }
+        // Map malformed value type to dynamic.
+        value_type = Type::DynamicType();
+        map_type_arguments.SetTypeAt(1, value_type);
+      }
+    } else {
+      if (FLAG_error_on_malformed_type) {
+        ErrorMsg(type_pos,
+                 "a map literal takes two type arguments specifying "
+                 "the key type and the value type");
+      }
+      // Ignore type arguments.
+      map_type_arguments = AbstractTypeArguments::null();
     }
   }
-  ASSERT(map_type_arguments.IsNull() || (map_type_arguments.Length() == 2));
+  ASSERT((map_type_arguments.IsNull() &&
+          key_type.IsDynamicType() && value_type.IsDynamicType()) ||
+         ((map_type_arguments.Length() == 2) &&
+          !key_type.IsMalformed() && !value_type.IsMalformed()));
   map_type_arguments ^= map_type_arguments.Canonicalize();
 
   GrowableArray<AstNode*> kv_pairs_list;
   // Parse the map entries. Note: there may be an optional extra
   // comma after the last entry.
   while (CurrentToken() != Token::kRBRACE) {
-    AstNode* key = NULL;
-    if (CurrentToken() == Token::kSTRING) {
-      key = ParseStringLiteral();
-    }
-    if (key == NULL) {
-      ErrorMsg("map entry key must be string literal");
-    } else if (is_const && !key->IsLiteralNode()) {
-      ErrorMsg("map entry key must be compile-time constant string");
+    const bool saved_mode = SetAllowFunctionLiterals(true);
+    const intptr_t key_pos = TokenPos();
+    AstNode* key = ParseExpr(is_const, kConsumeCascades);
+    if (FLAG_enable_type_checks &&
+        !is_const &&
+        !key_type.IsDynamicType()) {
+      key = new AssignableNode(key_pos,
+                               key,
+                               key_type,
+                               Symbols::ListLiteralElement());
     }
     ExpectToken(Token::kCOLON);
-    const bool saved_mode = SetAllowFunctionLiterals(true);
     const intptr_t value_pos = TokenPos();
     AstNode* value = ParseExpr(is_const, kConsumeCascades);
     SetAllowFunctionLiterals(saved_mode);
@@ -9285,27 +9327,38 @@
     // First, create the canonicalized key-value pair array.
     Array& key_value_array =
         Array::ZoneHandle(Array::New(kv_pairs_list.length(), Heap::kOld));
+    AbstractType& arg_type = Type::Handle();
     Error& malformed_error = Error::Handle();
     for (int i = 0; i < kv_pairs_list.length(); i++) {
       AstNode* arg = kv_pairs_list[i];
       // Arguments have been evaluated to a literal value already.
       ASSERT(arg->IsLiteralNode());
       ASSERT(!is_top_level_);  // We cannot check unresolved types.
-      if (FLAG_enable_type_checks &&
-          ((i % 2) == 1) &&  // Check values only, not keys.
-          !value_type.IsDynamicType() &&
-          (!arg->AsLiteralNode()->literal().IsNull() &&
-           !arg->AsLiteralNode()->literal().IsInstanceOf(
-               value_type, TypeArguments::Handle(), &malformed_error))) {
-        // If the failure is due to a malformed type error, display it instead.
-        if (!malformed_error.IsNull()) {
-          ErrorMsg(malformed_error);
+      if (FLAG_enable_type_checks) {
+        if ((i % 2) == 0) {
+          // Check key type.
+          arg_type = key_type.raw();
         } else {
-          ErrorMsg(arg->AsLiteralNode()->token_pos(),
-                   "map literal value at index %d must be "
-                   "a constant of type '%s'",
-                   i >> 1,
-                   String::Handle(value_type.UserVisibleName()).ToCString());
+          // Check value type.
+          arg_type = value_type.raw();
+        }
+        if (!arg_type.IsDynamicType() &&
+            (!arg->AsLiteralNode()->literal().IsNull() &&
+             !arg->AsLiteralNode()->literal().IsInstanceOf(
+                 arg_type,
+                 Object::null_abstract_type_arguments(),
+                 &malformed_error))) {
+          // If the failure is due to a malformed type error, display it.
+          if (!malformed_error.IsNull()) {
+            ErrorMsg(malformed_error);
+          } else {
+            ErrorMsg(arg->AsLiteralNode()->token_pos(),
+                     "map literal %s at index %d must be "
+                     "a constant of type '%s'",
+                     ((i % 2) == 0) ? "key" : "value",
+                     i >> 1,
+                     String::Handle(arg_type.UserVisibleName()).ToCString());
+          }
         }
       }
       key_value_array.SetAt(i, arg->AsLiteralNode()->literal());
@@ -9391,15 +9444,10 @@
     ConsumeToken();
   }
   const intptr_t type_pos = TokenPos();
-  Error& malformed_error = Error::Handle();
-  AbstractTypeArguments& type_arguments = AbstractTypeArguments::ZoneHandle(
-      ParseTypeArguments(&malformed_error,
-                         ClassFinalizer::kCanonicalizeWellFormed));
+  AbstractTypeArguments& type_arguments = AbstractTypeArguments::Handle(
+      ParseTypeArguments(ClassFinalizer::kCanonicalize));
   // Map and List interfaces do not declare bounds on their type parameters, so
-  // we should never see a malformed type error here.
-  // Note that a bound error is the only possible malformed type error returned
-  // when requesting kCanonicalizeWellFormed type finalization.
-  ASSERT(malformed_error.IsNull());
+  // we should never see a malformed type argument mapped to dynamic here.
   AstNode* primary = NULL;
   if ((CurrentToken() == Token::kLBRACK) ||
       (CurrentToken() == Token::kINDEX)) {
@@ -9438,7 +9486,7 @@
   }
   intptr_t type_pos = TokenPos();
   AbstractType& type = AbstractType::Handle(
-      ParseType(ClassFinalizer::kCanonicalizeExpression));
+      ParseType(ClassFinalizer::kCanonicalizeWellFormed));
   // In case the type is malformed, throw a dynamic type error after finishing
   // parsing the instance creation expression.
   if (!type.IsMalformed() && (type.IsTypeParameter() || type.IsDynamicType())) {
@@ -9447,7 +9495,6 @@
         Error::Handle(),  // No previous error.
         current_class(),
         type_pos,
-        ClassFinalizer::kResolveTypeParameters,  // No compile-time error.
         "%s'%s' cannot be instantiated",
         type.IsTypeParameter() ? "type parameter " : "",
         type.IsTypeParameter() ?
@@ -9455,9 +9502,9 @@
   }
 
   // The grammar allows for an optional ('.' identifier)? after the type, which
-  // is a named constructor. Note that ParseType(kMustResolve) above will not
-  // consume it as part of a misinterpreted qualified identifier, because only a
-  // valid library prefix is accepted as qualifier.
+  // is a named constructor. Note that ParseType() above will not consume it as
+  // part of a misinterpreted qualified identifier, because only a valid library
+  // prefix is accepted as qualifier.
   String* named_constructor = NULL;
   if (CurrentToken() == Token::kPERIOD) {
     ConsumeToken();
@@ -9513,7 +9560,6 @@
             Error::Handle(),  // No previous error.
             current_class(),
             call_pos,
-            ClassFinalizer::kResolveTypeParameters,  // No compile-time error.
             "class '%s' has no constructor or factory named '%s'",
             String::Handle(type_class.Name()).ToCString(),
             external_constructor_name.ToCString());
@@ -9633,7 +9679,6 @@
               malformed_error,
               current_class(),
               new_pos,
-              ClassFinalizer::kResolveTypeParameters,  // No compile-time error.
               "const factory result is not an instance of '%s'",
               String::Handle(type_bound.UserVisibleName()).ToCString());
           new_object = ThrowTypeError(new_pos, type_bound);
diff --git a/runtime/vm/parser.h b/runtime/vm/parser.h
index cca62c0..be417ae 100644
--- a/runtime/vm/parser.h
+++ b/runtime/vm/parser.h
@@ -358,7 +358,6 @@
   RawAbstractType* ParseType(ClassFinalizer::FinalizationKind finalization);
   void ParseTypeParameters(const Class& cls);
   RawAbstractTypeArguments* ParseTypeArguments(
-      Error* malformed_error,
       ClassFinalizer::FinalizationKind finalization);
   void ParseQualIdent(QualIdent* qual_ident);
   void ParseMethodOrConstructor(ClassDesc* members, MemberDesc* method);
diff --git a/runtime/vm/simulator_arm.cc b/runtime/vm/simulator_arm.cc
index 760fdfd..3469ab7 100644
--- a/runtime/vm/simulator_arm.cc
+++ b/runtime/vm/simulator_arm.cc
@@ -421,7 +421,11 @@
   while (!done) {
     if (last_pc != sim_->get_pc()) {
       last_pc = sim_->get_pc();
-      Disassembler::Disassemble(last_pc, last_pc + Instr::kInstrSize);
+      if (Simulator::IsIllegalAddress(last_pc)) {
+        OS::Print("pc is out of bounds: 0x%"Px"\n", last_pc);
+      } else {
+        Disassembler::Disassemble(last_pc, last_pc + Instr::kInstrSize);
+      }
     }
     char* line = ReadLine("sim> ");
     if (line == NULL) {
@@ -2992,6 +2996,15 @@
 }
 
 
+static void simd_value_swap(simd_value_t* s1, int i1,
+                            simd_value_t* s2, int i2) {
+  uint32_t tmp;
+  tmp = s1->data_[i1].u;
+  s1->data_[i1].u = s2->data_[i2].u;
+  s2->data_[i2].u = tmp;
+}
+
+
 void Simulator::DecodeSIMDDataProcessing(Instr* instr) {
   ASSERT(instr->ConditionField() == kSpecialCondition);
 
@@ -3227,6 +3240,20 @@
       } else {
         UnimplementedInstruction(instr);
       }
+    } else if ((instr->Bits(8, 4) == 1) && (instr->Bit(4) == 0) &&
+               (instr->Bits(20, 2) == 3) && (instr->Bits(23, 2) == 3) &&
+               (instr->Bit(7) == 1) && (instr->Bits(16, 4) == 10)) {
+      // Format(instr, "vzipqw 'qd, 'qm");
+      get_qregister(qd, &s8d);
+
+      // Interleave the elements with the low words in qd, and the high words
+      // in qm.
+      simd_value_swap(&s8d, 3, &s8m, 2);
+      simd_value_swap(&s8d, 3, &s8m, 1);
+      simd_value_swap(&s8d, 2, &s8m, 0);
+      simd_value_swap(&s8d, 2, &s8d, 1);
+
+      set_qregister(qm, s8m);  // Writes both qd and qm.
     } else if ((instr->Bits(8, 4) == 8) && (instr->Bit(4) == 1) &&
                (instr->Bits(23, 2) == 2)) {
       // Format(instr, "vceqq'sz 'qd, 'qn, 'qm");
diff --git a/runtime/vm/symbols.h b/runtime/vm/symbols.h
index 3345429..9edb6bf 100644
--- a/runtime/vm/symbols.h
+++ b/runtime/vm/symbols.h
@@ -60,6 +60,8 @@
   V(StacktraceVar, ":stacktrace_var")                                          \
   V(ListLiteralElement, "list literal element")                                \
   V(ForInIter, ":for-in-iter")                                                 \
+  V(ClosureFunctionField, ":function")                                         \
+  V(ClosureContextField, ":context")                                           \
   V(Library, "library")                                                        \
   V(Import, "import")                                                          \
   V(Source, "source")                                                          \
@@ -228,7 +230,7 @@
   V(NullThrownError, "NullThrownError")                                        \
   V(IsolateSpawnException, "IsolateSpawnException")                            \
   V(IsolateUnhandledException, "IsolateUnhandledException")                    \
-  V(FiftyThreeBitOverflowError, "_FiftyThreeBitOverflowError")                 \
+  V(JavascriptIntegerOverflowError, "_JavascriptIntegerOverflowError")         \
   V(MirroredCompilationError, "MirroredCompilationError")                      \
   V(MirroredUncaughtExceptionError, "MirroredUncaughtExceptionError")          \
   V(_setupFullStackTrace, "_setupFullStackTrace")                              \
@@ -269,9 +271,16 @@
   V(_A, "_A")                                                                  \
   V(_stackTrace, "_stackTrace")                                                \
   V(_SpecialTypeMirrorImpl, "_SpecialTypeMirrorImpl")                          \
+  V(_LocalClassMirrorImpl, "_LocalClassMirrorImpl")                            \
+  V(_LocalFunctionTypeMirrorImpl, "_LocalFunctionTypeMirrorImpl")              \
+  V(_LocalLibraryMirrorImpl, "_LocalLibraryMirrorImpl")                        \
   V(_LocalMethodMirrorImpl, "_LocalMethodMirrorImpl")                          \
   V(_LocalVariableMirrorImpl, "_LocalVariableMirrorImpl")                      \
   V(_LocalParameterMirrorImpl, "_LocalParameterMirrorImpl")                    \
+  V(_LocalIsolateMirrorImpl, "_LocalIsolateMirrorImpl")                        \
+  V(_LocalMirrorSystemImpl, "_LocalMirrorSystemImpl")                          \
+  V(_LocalTypedefMirrorImpl, "_LocalTypedefMirrorImpl")                        \
+  V(_LocalTypeVariableMirrorImpl, "_LocalTypeVariableMirrorImpl")              \
 
 
 // Contains a list of frequently used strings in a canonicalized form. This
diff --git a/sdk/lib/_internal/compiler/implementation/compiler.dart b/sdk/lib/_internal/compiler/implementation/compiler.dart
index 86f5db8..1aa47b7 100644
--- a/sdk/lib/_internal/compiler/implementation/compiler.dart
+++ b/sdk/lib/_internal/compiler/implementation/compiler.dart
@@ -211,6 +211,17 @@
   void registerMetadataInstantiatedType(DartType type, TreeElements elements) {}
   void registerMetadataStaticUse(Element element) {}
   void registerMetadataGetOfStaticFunction(FunctionElement element) {}
+
+  /// Called by [MirrorUsageAnalyzerTask] after it has merged all @MirrorsUsed
+  /// annotations. The arguments corresponds to the unions of the corresponding
+  /// fields of the annotations.
+  void registerMirrorUsage(Set<String> symbols,
+                           Set<Element> targets,
+                           Set<Element> metaTargets) {}
+
+  /// Returns true if this element should be retained for reflection even if it
+  /// would normally be tree-shaken away.
+  bool isNeededForReflection(Element element) => false;
 }
 
 /**
@@ -338,6 +349,9 @@
   LibraryElement foreignLibrary;
   LibraryElement mainApp;
 
+  /// Initialized when dart:mirrors is loaded.
+  LibraryElement mirrorsLibrary;
+
   ClassElement objectClass;
   ClassElement closureClass;
   ClassElement boundClosureClass;
@@ -361,6 +375,9 @@
   // Initialized when dart:mirrors is loaded.
   ClassElement mirrorSystemClass;
 
+  // Initialized when dart:mirrors is loaded.
+  ClassElement mirrorsUsedClass;
+
   // Initialized after mirrorSystemClass has been resolved.
   FunctionElement mirrorSystemGetNameFunction;
 
@@ -437,6 +454,7 @@
   EnqueueTask enqueuer;
   CompilerTask fileReadingTask;
   DeferredLoadTask deferredLoadTask;
+  MirrorUsageAnalyzerTask mirrorUsageAnalyzerTask;
   ContainerTracer containerTracer;
   String buildId;
 
@@ -545,6 +563,7 @@
       containerTracer = new ContainerTracer(this),
       constantHandler = new ConstantHandler(this, backend.constantSystem),
       deferredLoadTask = new DeferredLoadTask(this),
+      mirrorUsageAnalyzerTask = new MirrorUsageAnalyzerTask(this),
       enqueuer = new EnqueueTask(this)];
 
     tasks.addAll(backend.tasks);
@@ -692,8 +711,11 @@
       });
     }
     if (uri == new Uri(scheme: 'dart', path: 'mirrors')) {
+      mirrorsLibrary = library;
       mirrorSystemClass =
           findRequiredElement(library, const SourceString('MirrorSystem'));
+      mirrorsUsedClass =
+          findRequiredElement(library, const SourceString('MirrorsUsed'));
     } else if (uri == new Uri(scheme: 'dart', path: '_collection-dev')) {
       symbolImplementationClass =
           findRequiredElement(library, const SourceString('Symbol'));
@@ -898,6 +920,8 @@
         });
       }
 
+      mirrorUsageAnalyzerTask.analyzeUsage(mainApp);
+
       // In order to see if a library is deferred, we must compute the
       // compile-time constants that are metadata.  This means adding
       // something to the resolution queue.  So we cannot wait with
@@ -1181,6 +1205,11 @@
                   api.Diagnostic.HINT);
   }
 
+  /// For debugging only, print a message with a source location.
+  void reportHere(Spannable node, String debugMessage) {
+    reportInfo(node, MessageKind.GENERIC, {'text': 'HERE: $debugMessage'});
+  }
+
   void reportInternalError(Spannable node, String message) {
     reportError(
         node, MessageKind.GENERIC, {'text': 'Internal Error: $message'});
diff --git a/sdk/lib/_internal/compiler/implementation/constants.dart b/sdk/lib/_internal/compiler/implementation/constants.dart
index 5e3a429..4ff011c 100644
--- a/sdk/lib/_internal/compiler/implementation/constants.dart
+++ b/sdk/lib/_internal/compiler/implementation/constants.dart
@@ -485,4 +485,15 @@
   List<Constant> getDependencies() => fields;
 
   accept(ConstantVisitor visitor) => visitor.visitConstructed(this);
+
+  Map<Element, Constant> get fieldElements {
+    // TODO(ahe): Refactor constant system to store this information directly.
+    ClassElement classElement = type.element;
+    int count = 0;
+    Map<Element, Constant> result = new Map<Element, Constant>();
+    classElement.implementation.forEachInstanceField((holder, field) {
+      result[field] = fields[count++];
+    }, includeSuperAndInjectedMembers: true);
+    return result;
+  }
 }
diff --git a/sdk/lib/_internal/compiler/implementation/dart2jslib.dart b/sdk/lib/_internal/compiler/implementation/dart2jslib.dart
index c789d11..1af5315 100644
--- a/sdk/lib/_internal/compiler/implementation/dart2jslib.dart
+++ b/sdk/lib/_internal/compiler/implementation/dart2jslib.dart
@@ -32,6 +32,7 @@
 import 'js/js.dart' as js;
 import 'deferred_load.dart' show DeferredLoadTask;
 import 'types/container_tracer.dart' show ContainerTracer;
+import 'mirrors_used.dart' show MirrorUsageAnalyzerTask;
 
 export 'resolution/resolution.dart' show TreeElements, TreeElementMapping;
 export 'scanner/scannerlib.dart' show SourceString,
diff --git a/sdk/lib/_internal/compiler/implementation/dart_backend/utils.dart b/sdk/lib/_internal/compiler/implementation/dart_backend/utils.dart
index 4979d19..61bad39 100644
--- a/sdk/lib/_internal/compiler/implementation/dart_backend/utils.dart
+++ b/sdk/lib/_internal/compiler/implementation/dart_backend/utils.dart
@@ -169,11 +169,6 @@
   visitReturn(Return node) => new Return(
       node.beginToken, node.endToken, visit(node.expression));
 
-  visitScriptTag(ScriptTag node) => new ScriptTag(
-      visit(node.tag), visit(node.argument),
-      visit(node.prefixIdentifier), visit(node.prefix),
-      node.beginToken, node.endToken);
-
   visitSend(Send node) => new Send(
       visit(node.receiver), visit(node.selector), visit(node.argumentsNode));
 
diff --git a/sdk/lib/_internal/compiler/implementation/dart_types.dart b/sdk/lib/_internal/compiler/implementation/dart_types.dart
index a3e0821..f490288 100644
--- a/sdk/lib/_internal/compiler/implementation/dart_types.dart
+++ b/sdk/lib/_internal/compiler/implementation/dart_types.dart
@@ -86,21 +86,6 @@
    * by the user. 
    */
   DartType get userProvidedBadType => null;
-  
-  /// Returns [:true:] if this type contains an ambiguous type.
-  bool get containsAmbiguousTypes {
-    return !forEachAmbiguousType((_) => false);
-  }
-  
-  /**
-   * Calls [f] with each [AmbiguousType] within this type.
-   *
-   * If [f] returns [: false :], the traversal stops prematurely.
-   *
-   * [forEachAmbiguousType] returns [: false :] if the traversal was stopped
-   * prematurely.
-   */
-  bool forEachAmbiguousType(bool f(AmbiguousType type)) => true;
 
   /// Is [: true :] if this type has no explict type arguments.
   bool get isRaw => true;
@@ -364,14 +349,6 @@
   }
 }
 
-class AmbiguousType extends MalformedType {
-  AmbiguousType(ErroneousElement element, 
-                [Link<DartType> typeArguments = null]) 
-      : super(element, null, typeArguments);
-
-  bool forEachAmbiguousType(bool f(AmbiguousType type)) => f(this);
-}
-
 abstract class GenericType extends DartType {
   final Link<DartType> typeArguments;
 
@@ -401,15 +378,6 @@
     return this;
   }
 
-  bool forEachAmbiguousType(bool f(AmbiguousType type)) {
-    for (DartType typeArgument in typeArguments) {
-      if (!typeArgument.forEachAmbiguousType(f)) {
-        return false;
-      }
-    }
-    return true;
-  }
-
   TypeVariableType get typeVariableOccurrence {
     return _findTypeVariableOccurrence(typeArguments);
   }
@@ -686,28 +654,6 @@
     return this;
   }
 
-  bool forEachAmbiguousType(bool f(AmbiguousType type)) {
-    if (!returnType.forEachAmbiguousType(f)) {
-      return false;
-    }
-    for (DartType parameterType in parameterTypes) {
-      if (!parameterType.forEachAmbiguousType(f)) {
-        return false;
-      }
-    }
-    for (DartType parameterType in optionalParameterTypes) {
-      if (!parameterType.forEachAmbiguousType(f)) {
-        return false;
-      }
-    }
-    for (DartType parameterType in namedParameterTypes) {
-      if (!parameterType.forEachAmbiguousType(f)) {
-        return false;
-      }
-    }
-    return true;
-  }
-
   DartType unalias(Compiler compiler) => this;
 
   DartType get typeVariableOccurrence {
@@ -1239,23 +1185,6 @@
   }
 
   /**
-   * Combine error messages in a type containing ambiguous types to a single 
-   * message string.
-   */
-  static String fetchReasonsFromAmbiguousType(DartType type) {
-    // TODO(johnniwinther): Figure out how to produce good error message in face
-    // of multiple errors, and how to ensure non-localized error messages.
-    var reasons = new List<String>();
-    type.forEachAmbiguousType((AmbiguousType ambiguousType) {
-      ErroneousElement error = ambiguousType.element;
-      Message message = error.messageKind.message(error.messageArguments);
-      reasons.add(message.toString());
-      return true;
-    });
-    return reasons.join(', ');
-  }
-
-  /**
    * Returns the [ClassElement] which declares the type variables occurring in
    * [type], or [:null:] if [type] does not contain type variables.
    */
diff --git a/sdk/lib/_internal/compiler/implementation/deferred_load.dart b/sdk/lib/_internal/compiler/implementation/deferred_load.dart
index 7745460..53eca97 100644
--- a/sdk/lib/_internal/compiler/implementation/deferred_load.dart
+++ b/sdk/lib/_internal/compiler/implementation/deferred_load.dart
@@ -194,6 +194,8 @@
   Link<LibraryElement> findDeferredLibraries(LibraryElement library) {
     Link<LibraryElement> link = const Link<LibraryElement>();
     for (LibraryTag tag in library.tags) {
+      // TODO(ahe): This iterates over parts and exports as well, but should
+      // only iterate over imports.
       Link<MetadataAnnotation> metadata = tag.metadata;
       if (metadata == null) continue;
       for (MetadataAnnotation metadata in tag.metadata) {
diff --git a/sdk/lib/_internal/compiler/implementation/elements/elements.dart b/sdk/lib/_internal/compiler/implementation/elements/elements.dart
index 6413fc1..30825c7 100644
--- a/sdk/lib/_internal/compiler/implementation/elements/elements.dart
+++ b/sdk/lib/_internal/compiler/implementation/elements/elements.dart
@@ -119,8 +119,6 @@
       const ElementKind('ambiguous', ElementCategory.NONE);
   static const ElementKind ERROR =
       const ElementKind('error', ElementCategory.NONE);
-  static const ElementKind MALFORMED_TYPE =
-      const ElementKind('malformed', ElementCategory.NONE);
 
   toString() => id;
 }
diff --git a/sdk/lib/_internal/compiler/implementation/elements/modelx.dart b/sdk/lib/_internal/compiler/implementation/elements/modelx.dart
index 57b7c7b..6c8bdd1 100644
--- a/sdk/lib/_internal/compiler/implementation/elements/modelx.dart
+++ b/sdk/lib/_internal/compiler/implementation/elements/modelx.dart
@@ -795,8 +795,8 @@
   bool hasLibraryName() => libraryTag != null;
 
   /**
-   * Returns the library name (as defined by the #library tag) or for script
-   * (which have no #library tag) the script file name. The latter case is used
+   * Returns the library name (as defined by the library tag) or for script
+   * (which have no library tag) the script file name. The latter case is used
    * to private 'library name' for scripts to use for instance in dartdoc.
    */
   String getLibraryOrScriptName() {
diff --git a/sdk/lib/_internal/compiler/implementation/enqueue.dart b/sdk/lib/_internal/compiler/implementation/enqueue.dart
index 353897d..288065d 100644
--- a/sdk/lib/_internal/compiler/implementation/enqueue.dart
+++ b/sdk/lib/_internal/compiler/implementation/enqueue.dart
@@ -114,20 +114,16 @@
   void internalAddToWorkList(Element element);
 
   void registerInstantiatedType(InterfaceType type, TreeElements elements) {
-    ClassElement cls = type.element;
-    elements.registerDependency(cls);
-    cls.ensureResolved(compiler);
-    universe.instantiatedTypes.add(type);
-    if (universe.instantiatedClasses.contains(cls)) return;
-    if (!cls.isAbstract(compiler)) {
-      universe.instantiatedClasses.add(cls);
-    }
-    onRegisterInstantiatedClass(cls);
-    // We only tell the backend once that [cls] was instantiated, so
-    // any additional dependencies must be treated as global
-    // dependencies.
-    compiler.backend.registerInstantiatedClass(
-        cls, this, compiler.globalDependencies);
+    task.measure(() {
+      ClassElement cls = type.element;
+      elements.registerDependency(cls);
+      cls.ensureResolved(compiler);
+      universe.instantiatedTypes.add(type);
+      if (!cls.isAbstract(compiler)) {
+        universe.instantiatedClasses.add(cls);
+      }
+      onRegisterInstantiatedClass(cls);
+    });
   }
 
   void registerInstantiatedClass(ClassElement cls, TreeElements elements) {
@@ -254,6 +250,7 @@
 
   void onRegisterInstantiatedClass(ClassElement cls) {
     task.measure(() {
+      if (seenClasses.contains(cls)) return;
       // The class must be resolved to compute the set of all
       // supertypes.
       cls.ensureResolved(compiler);
@@ -267,6 +264,11 @@
         if (isResolutionQueue) {
           compiler.resolver.checkClass(cls);
         }
+        // We only tell the backend once that [cls] was instantiated, so
+        // any additional dependencies must be treated as global
+        // dependencies.
+        compiler.backend.registerInstantiatedClass(
+            cls, this, compiler.globalDependencies);
       }
       processClass(cls);
       for (Link<DartType> supertypes = cls.allSupertypes;
@@ -311,6 +313,7 @@
   }
 
   void pretendElementWasUsed(Element element, TreeElements elements) {
+    if (!compiler.backend.isNeededForReflection(element)) return;
     if (Elements.isUnresolved(element)) {
       // Ignore.
     } else if (element.isSynthesized
diff --git a/sdk/lib/_internal/compiler/implementation/js_backend/backend.dart b/sdk/lib/_internal/compiler/implementation/js_backend/backend.dart
index 99b1dae..cc7b0fb 100644
--- a/sdk/lib/_internal/compiler/implementation/js_backend/backend.dart
+++ b/sdk/lib/_internal/compiler/implementation/js_backend/backend.dart
@@ -105,23 +105,6 @@
   }
 }
 
-class AmbiguousTypeCheckedModeHelper extends CheckedModeHelper {
-  const AmbiguousTypeCheckedModeHelper(SourceString name) : super(name);
-
-  void generateAdditionalArguments(SsaCodeGenerator codegen,
-                                   HTypeConversion node,
-                                   List<jsAst.Expression> arguments) {
-    DartType type = node.typeExpression;
-    assert(type.containsAmbiguousTypes);
-    String reasons = Types.fetchReasonsFromAmbiguousType(type);
-
-    arguments.add(js.string(quote('$type')));
-    arguments.add(js.string(quote(reasons)));
-  }
-
-  String quote(String string) => string.replaceAll('"', r'\"');
-}
-
 /*
  * Invariants:
  *   canInline(function) implies canInline(function, insideLoop:true)
@@ -337,6 +320,16 @@
   /// preserved, these elements must be compiled.
   final List<FunctionElement> metadataGetOfStaticFunction = <FunctionElement>[];
 
+  /// List of symbols that the user has requested for reflection.
+  final Set<String> symbolsUsed = new Set<String>();
+
+  /// List of elements that the user has requested for reflection.
+  final Set<Element> targetsUsed = new Set<Element>();
+
+  /// List of annotations provided by user that indicate that the annotated
+  /// element must be retained.
+  final Set<Element> metaTargetsUsed = new Set<Element>();
+
   JavaScriptBackend(Compiler compiler, bool generateSourceMap, bool disableEval)
       : namer = determineNamer(compiler),
         oneShotInterceptors = new Map<String, Selector>(),
@@ -853,13 +846,6 @@
       // We also need the native variant of the check (for DOM types).
       helper = getNativeCheckedModeHelper(type, typeCast: false);
       if (helper != null) world.addToWorkList(helper.getElement(compiler));
-      if (type.containsAmbiguousTypes) {
-        enqueueInResolution(getThrowMalformedSubtypeError(), elements);
-        return;
-      }
-    } else if (type.containsAmbiguousTypes) {
-      registerThrowRuntimeError(elements);
-      return;
     }
     bool isTypeVariable = type.kind == TypeKind.TYPE_VARIABLE;
     if (!type.isRaw || type.containsTypeVariables) {
@@ -1120,16 +1106,7 @@
     Element element = type.element;
     bool nativeCheck = nativeCheckOnly ||
         emitter.nativeEmitter.requiresNativeIsCheck(element);
-    if (type.containsAmbiguousTypes) {
-      // Check for malformed types first, because the type may be a list type
-      // with a malformed argument type.
-      if (nativeCheckOnly) return null;
-      return typeCast
-          ? const AmbiguousTypeCheckedModeHelper(
-              const SourceString('malformedTypeCast'))
-          : const AmbiguousTypeCheckedModeHelper(
-              const SourceString('malformedTypeCheck'));
-    } else if (type == compiler.types.voidType) {
+    if (type == compiler.types.voidType) {
       assert(!typeCast); // Cannot cast to void.
       if (nativeCheckOnly) return null;
       return const CheckedModeHelper(const SourceString('voidTypeCheck'));
@@ -1255,11 +1232,6 @@
     return compiler.findHelper(const SourceString('throwRuntimeError'));
   }
 
-  Element getThrowMalformedSubtypeError() {
-    return compiler.findHelper(
-        const SourceString('throwMalformedSubtypeError'));
-  }
-
   Element getThrowAbstractClassInstantiationError() {
     return compiler.findHelper(
         const SourceString('throwAbstractClassInstantiationError'));
@@ -1484,6 +1456,26 @@
       metadataGetOfStaticFunction.add(element);
     }
   }
+
+  void registerMirrorUsage(Set<String> symbols,
+                           Set<Element> targets,
+                           Set<Element> metaTargets) {
+    if (symbols != null) symbolsUsed.addAll(symbols);
+    if (targets != null) {
+      for (Element element in targets) {
+        // TODO(ahe): Implement finer granularity.
+        targetsUsed.add(element.getLibrary());
+      }
+    }
+    if (metaTargets != null) metaTargetsUsed.addAll(metaTargets);
+  }
+
+  bool isNeededForReflection(Element element) {
+    // TODO(ahe): Implement this.
+    if (!metaTargetsUsed.isEmpty) return true;
+    if (targetsUsed.contains(element.getLibrary())) return true;
+    return false;
+  }
 }
 
 /// Records that [type] is used by [user.element].
diff --git a/sdk/lib/_internal/compiler/implementation/js_backend/emitter.dart b/sdk/lib/_internal/compiler/implementation/js_backend/emitter.dart
index 2ee81e7..2302aec 100644
--- a/sdk/lib/_internal/compiler/implementation/js_backend/emitter.dart
+++ b/sdk/lib/_internal/compiler/implementation/js_backend/emitter.dart
@@ -726,7 +726,7 @@
           ])),
 
           js('var constructor = defineClass(name, cls, fields, desc)'),
-          optional(backend.hasRetainedMetadata,
+          optional(backend.isTreeShakingDisabled,
                    js('constructor["${namer.metadataField}"] = desc')),
           js('isolateProperties[cls] = constructor'),
           js.if_('supr', js('pendingClasses[cls] = supr'))
diff --git a/sdk/lib/_internal/compiler/implementation/js_backend/namer.dart b/sdk/lib/_internal/compiler/implementation/js_backend/namer.dart
index 92a4898..796718a 100644
--- a/sdk/lib/_internal/compiler/implementation/js_backend/namer.dart
+++ b/sdk/lib/_internal/compiler/implementation/js_backend/namer.dart
@@ -724,8 +724,7 @@
           kind == ElementKind.GETTER ||
           kind == ElementKind.SETTER ||
           kind == ElementKind.TYPEDEF ||
-          kind == ElementKind.LIBRARY ||
-          kind == ElementKind.MALFORMED_TYPE) {
+          kind == ElementKind.LIBRARY) {
         bool fixedName = false;
         if (kind == ElementKind.CLASS) {
           ClassElement classElement = element;
diff --git a/sdk/lib/_internal/compiler/implementation/mirrors/dart2js_mirror.dart b/sdk/lib/_internal/compiler/implementation/mirrors/dart2js_mirror.dart
index a00716e..2910563 100644
--- a/sdk/lib/_internal/compiler/implementation/mirrors/dart2js_mirror.dart
+++ b/sdk/lib/_internal/compiler/implementation/mirrors/dart2js_mirror.dart
@@ -531,8 +531,8 @@
   LibraryMirror library() => this;
 
   /**
-   * Returns the library name (for libraries with a #library tag) or the script
-   * file name (for scripts without a #library tag). The latter case is used to
+   * Returns the library name (for libraries with a library tag) or the script
+   * file name (for scripts without a library tag). The latter case is used to
    * provide a 'library name' for scripts, to use for instance in dartdoc.
    */
   String get simpleName {
diff --git a/sdk/lib/_internal/compiler/implementation/mirrors_used.dart b/sdk/lib/_internal/compiler/implementation/mirrors_used.dart
new file mode 100644
index 0000000..7b795a2
--- /dev/null
+++ b/sdk/lib/_internal/compiler/implementation/mirrors_used.dart
@@ -0,0 +1,391 @@
+// Copyright (c) 2013, 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 dart2js.mirrors_used;
+
+import 'dart2jslib.dart' show
+    Compiler,
+    CompilerTask,
+    Constant,
+    ConstructedConstant,
+    ListConstant,
+    MessageKind,
+    SourceString,
+    StringConstant,
+    TypeConstant;
+
+import 'elements/elements.dart' show
+    Element,
+    LibraryElement,
+    MetadataAnnotation,
+    VariableElement;
+
+import 'util/util.dart' show
+    Link;
+
+import 'dart_types.dart' show
+    DartType;
+
+import 'tree/tree.dart' show
+    Import,
+    LibraryTag;
+
+/**
+ * Compiler task that analyzes MirrorsUsed annotations.
+ *
+ * When importing 'dart:mirrors', it is possible to annotate the import with
+ * MirrorsUsed annotation.  This is a way to declare what elements will be
+ * reflected on at runtime.  Such elements, even they would normally be
+ * discarded by the implicit tree-shaking algorithm must be preserved in the
+ * final output.
+ *
+ * Since some libraries cannot tell exactly what they will be reflecting on, it
+ * is possible for one library to specify a MirrorsUsed annotation that applies
+ * to another library. For example:
+ *
+ * Mirror utility library that cannot tell what it is reflecting on:
+ * library mirror_utils;
+ * import 'dart:mirrors';
+ * ...
+ *
+ * The main app which knows how it use the mirror utility library:
+ * library main_app;
+ * @MirrorsUsed(override='mirror_utils')
+ * import 'dart:mirrors';
+ * import 'mirror_utils.dart';
+ * ...
+ *
+ * In this case, we say that @MirrorsUsed in main_app overrides @MirrorsUsed in
+ * mirror_utils.
+ *
+ * It is possible to override all libraries using override='*'.  If multiple
+ * catch-all overrides like this, they are merged together.
+ *
+ * It is possible for library "a" to declare that it overrides library "b", and
+ * vice versa. In this case, both annotations will be discarded and the
+ * compiler will emit a hint (that is, a warning that is not specified by the
+ * language specification).
+ *
+ * After applying all the overrides, we can iterate over libraries that import
+ * 'dart:mirrors'. If a library does not have an associated MirrorsUsed
+ * annotation, then we have to discard all MirrorsUsed annotations and assume
+ * everything can be reflected on.
+ *
+ * On the other hand, if all libraries importing dart:mirrors have a
+ * MirrorsUsed annotation, these annotations are merged.
+ *
+ * MERGING MIRRORSUSED
+ *
+ * TBD.
+ */
+class MirrorUsageAnalyzerTask extends CompilerTask {
+  Set<LibraryElement> librariesWithUsage;
+
+  MirrorUsageAnalyzerTask(Compiler compiler)
+      : super(compiler);
+
+  void analyzeUsage(LibraryElement mainApp) {
+    if (compiler.mirrorsLibrary == null) return;
+    MirrorUsageAnalyzer analyzer = new MirrorUsageAnalyzer(compiler, this);
+    measure(analyzer.run);
+    List<String> symbols = analyzer.mergedMirrorUsage.symbols;
+    List<Element> targets = analyzer.mergedMirrorUsage.targets;
+    List<Element> metaTargets = analyzer.mergedMirrorUsage.metaTargets;
+    compiler.backend.registerMirrorUsage(
+        symbols == null ? null : new Set<String>.from(symbols),
+        targets == null ? null : new Set<Element>.from(targets),
+        metaTargets == null ? null : new Set<Element>.from(metaTargets));
+    librariesWithUsage = analyzer.librariesWithUsage;
+  }
+
+  bool hasMirrorUsage(Element element) {
+    return librariesWithUsage != null
+        && librariesWithUsage.contains(element.getLibrary());
+  }
+}
+
+class MirrorUsageAnalyzer {
+  final Compiler compiler;
+  final MirrorUsageAnalyzerTask task;
+  final List<LibraryElement> wildcard;
+  final Set<LibraryElement> librariesWithUsage;
+  final Set<LibraryElement> librariesWithoutUsage;
+  MirrorUsage mergedMirrorUsage;
+
+  MirrorUsageAnalyzer(Compiler compiler, this.task)
+      : compiler = compiler,
+        wildcard = compiler.libraries.values.toList(),
+        librariesWithUsage = new Set<LibraryElement>(),
+        librariesWithoutUsage = new Set<LibraryElement>();
+
+  void run() {
+    Map<LibraryElement, List<MirrorUsage>> usageMap =
+        collectMirrorsUsedAnnotation();
+    propagateOverrides(usageMap);
+    librariesWithoutUsage.removeAll(usageMap.keys);
+    if (librariesWithoutUsage.isEmpty) {
+      mergedMirrorUsage = mergeUsages(usageMap);
+    } else {
+      mergedMirrorUsage = new MirrorUsage(null, wildcard, null, null);
+    }
+  }
+
+  Map<LibraryElement, List<MirrorUsage>> collectMirrorsUsedAnnotation() {
+    Map<LibraryElement, List<MirrorUsage>> result =
+        new Map<LibraryElement, List<MirrorUsage>>();
+    for (LibraryElement library in compiler.libraries.values) {
+      if (library.isInternalLibrary) continue;
+      librariesWithoutUsage.add(library);
+      for (LibraryTag tag in library.tags) {
+        Import importTag = tag.asImport();
+        if (importTag == null) continue;
+        compiler.withCurrentElement(library, () {
+          List<MirrorUsage> usages =
+              mirrorsUsedOnLibraryTag(library, importTag);
+          if (usages != null) {
+            List<MirrorUsage> existing = result[library];
+            if (existing != null) {
+              existing.addAll(usages);
+            } else {
+              result[library] = usages;
+            }
+          }
+        });
+      }
+    }
+    return result;
+  }
+
+  void propagateOverrides(Map<LibraryElement, List<MirrorUsage>> usageMap) {
+    Map<LibraryElement, List<MirrorUsage>> propagatedOverrides =
+        new Map<LibraryElement, List<MirrorUsage>>();
+    usageMap.forEach((LibraryElement library, List<MirrorUsage> usages) {
+      for (MirrorUsage usage in usages) {
+        List<Element> override = usage.override;
+        if (override == null) continue;
+        if (override == wildcard) {
+          for (LibraryElement overridden in wildcard) {
+            if (overridden != library) {
+              List<MirrorUsage> overriddenUsages = propagatedOverrides
+                  .putIfAbsent(overridden, () => <MirrorUsage>[]);
+              overriddenUsages.add(usage);
+            }
+          }
+        } else {
+          for (Element overridden in override) {
+            List<MirrorUsage> overriddenUsages = propagatedOverrides
+                .putIfAbsent(overridden, () => <MirrorUsage>[]);
+            overriddenUsages.add(usage);
+          }
+        }
+      }
+    });
+    propagatedOverrides.forEach((LibraryElement overridden,
+                                 List<MirrorUsage> overriddenUsages) {
+      List<MirrorUsage> usages =
+          usageMap.putIfAbsent(overridden, () => <MirrorUsage>[]);
+      usages.addAll(overriddenUsages);
+    });
+  }
+
+  List<MirrorUsage> mirrorsUsedOnLibraryTag(LibraryElement library,
+                                            Import tag) {
+    LibraryElement importedLibrary = library.getLibraryFromTag(tag);
+    if (importedLibrary != compiler.mirrorsLibrary) {
+      return null;
+    }
+    List<MirrorUsage> result = <MirrorUsage>[];
+    for (MetadataAnnotation metadata in tag.metadata) {
+      metadata.ensureResolved(compiler);
+      Element element = metadata.value.computeType(compiler).element;
+      if (element == compiler.mirrorsUsedClass) {
+        try {
+          MirrorUsage usage =
+              new MirrorUsageBuilder(this, library).build(metadata.value);
+          result.add(usage);
+        } on BadMirrorsUsedAnnotation catch (e) {
+          compiler.reportError(
+              metadata, MessageKind.GENERIC, {'text': e.message});
+        }
+      }
+    }
+    return result;
+  }
+
+  MirrorUsage mergeUsages(Map<LibraryElement, List<MirrorUsage>> usageMap) {
+    Set<MirrorUsage> usagesToMerge = new Set<MirrorUsage>();
+    usageMap.forEach((LibraryElement library, List<MirrorUsage> usages) {
+      librariesWithUsage.add(library);
+      usagesToMerge.addAll(usages);
+    });
+    if (usagesToMerge.isEmpty) {
+      return new MirrorUsage(null, wildcard, null, null);
+    } else {
+      MirrorUsage result = new MirrorUsage(null, null, null, null);
+      for (MirrorUsage usage in usagesToMerge) {
+        result = merge(result, usage);
+      }
+      return result;
+    }
+  }
+
+  MirrorUsage merge(MirrorUsage a, MirrorUsage b) {
+    if (a.symbols == null && a.targets == null && a.metaTargets == null) {
+      return b;
+    } else if (
+        b.symbols == null && b.targets == null && b.metaTargets == null) {
+      return a;
+    }
+    // TODO(ahe): Test the following cases.
+    List<String> symbols = a.symbols;
+    if (symbols == null) {
+      symbols = b.symbols;
+    } else if (b.symbols != null) {
+      symbols.addAll(b.symbols);
+    }
+    List<Element> targets = a.targets;
+    if (targets == null) {
+      targets = b.targets;
+    } else if (targets != wildcard && b.targets != null) {
+      targets.addAll(b.targets);
+    }
+    List<Element> metaTargets = a.metaTargets;
+    if (metaTargets == null) {
+      metaTargets = b.metaTargets;
+    } else if (metaTargets != wildcard && b.metaTargets != null) {
+      metaTargets.addAll(b.metaTargets);
+    }
+    return new MirrorUsage(symbols, targets, metaTargets, null);
+  }
+}
+
+class MirrorUsage {
+  final List<String> symbols;
+  final List<Element> targets;
+  final List<Element> metaTargets;
+  final List<Element> override;
+
+  MirrorUsage(this.symbols, this.targets, this.metaTargets, this.override);
+
+  String toString() {
+    return
+        'MirrorUsage('
+        'symbols = $symbols, '
+        'targets = $targets, '
+        'metaTargets = $metaTargets, '
+        'override = $override'
+        ')';
+
+  }
+}
+
+class MirrorUsageBuilder {
+  MirrorUsageAnalyzer analyzer;
+  LibraryElement enclosingLibrary;
+
+  MirrorUsageBuilder(this.analyzer, this.enclosingLibrary);
+
+  Compiler get compiler => analyzer.compiler;
+
+  MirrorUsage build(ConstructedConstant constant) {
+    Map<Element, Constant> fields = constant.fieldElements;
+    VariableElement symbolsField = compiler.mirrorsUsedClass.lookupLocalMember(
+        const SourceString('symbols'));
+    VariableElement targetsField = compiler.mirrorsUsedClass.lookupLocalMember(
+        const SourceString('targets'));
+    VariableElement metaTargetsField =
+        compiler.mirrorsUsedClass.lookupLocalMember(
+            const SourceString('metaTargets'));
+    VariableElement overrideField = compiler.mirrorsUsedClass.lookupLocalMember(
+        const SourceString('override'));
+    List<String> symbols =
+        convertToListOfStrings(
+            convertConstantToUsageList(fields[symbolsField]));
+    List<Element> targets =
+        resolveUsageList(convertConstantToUsageList(fields[targetsField]));
+
+    List<Element> metaTargets =
+        resolveUsageList(convertConstantToUsageList(fields[metaTargetsField]));
+    List<Element> override =
+        resolveUsageList(convertConstantToUsageList(fields[overrideField]));
+    return new MirrorUsage(symbols, targets, metaTargets, override);
+  }
+
+  List convertConstantToUsageList(Constant constant) {
+    if (constant.isNull()) {
+      return null;
+    } else if (constant.isList()) {
+      ListConstant list = constant;
+      List result = [];
+      for (Constant entry in list.entries) {
+        if (entry.isString()) {
+          StringConstant string = entry;
+          result.add(string.value.slowToString());
+        } else if (entry.isType()) {
+          TypeConstant type = entry;
+          result.add(type.representedType);
+        } else {
+          throw new BadMirrorsUsedAnnotation(
+              'Expected a string or type, but got "$entry".');
+        }
+      }
+      return result;
+    } else if (constant.isType()) {
+      TypeConstant type = constant;
+      return [type.representedType];
+    } else if (constant.isString()) {
+      StringConstant string = constant;
+      return
+          string.value.slowToString().split(',').map((e) => e.trim()).toList();
+    } else {
+      throw new BadMirrorsUsedAnnotation(
+          'Expected a string or a list of string, but got "$constant".');
+    }
+  }
+
+  List<String> convertToListOfStrings(List list) {
+    if (list == null) return null;
+    List<String> result = new List<String>(list.length);
+    int count = 0;
+    for (var entry in list) {
+      if (entry is! String) {
+        throw new BadMirrorsUsedAnnotation(
+            'Expected a string, but got "$entry"');
+      }
+      result[count++] = entry;
+    }
+    return result;
+  }
+
+  List<Element> resolveUsageList(List list) {
+    if (list == null) return null;
+    if (list.length == 1 && list[0] == '*') {
+      return analyzer.wildcard;
+    }
+    List<Element> result = <Element>[];
+    for (var entry in list) {
+      if (entry is DartType) {
+        DartType type = entry;
+        result.add(type.element);
+      } else {
+        String string = entry;
+        for (LibraryElement l in compiler.libraries.values) {
+          if (l.hasLibraryName()) {
+            String libraryName = l.getLibraryOrScriptName();
+            if (string == libraryName || string.startsWith('$libraryName.')) {
+              result.add(l);
+              break;
+            }
+          }
+        }
+      }
+    }
+    return result;
+  }
+}
+
+class BadMirrorsUsedAnnotation {
+  final String message;
+  BadMirrorsUsedAnnotation(this.message);
+}
diff --git a/sdk/lib/_internal/compiler/implementation/resolution/members.dart b/sdk/lib/_internal/compiler/implementation/resolution/members.dart
index cea260d..607bc6e 100644
--- a/sdk/lib/_internal/compiler/implementation/resolution/members.dart
+++ b/sdk/lib/_internal/compiler/implementation/resolution/members.dart
@@ -1428,8 +1428,7 @@
   }
 
   DartType resolveTypeAnnotation(MappingVisitor visitor, TypeAnnotation node,
-                                 {bool malformedIsError: false,
-                                  bool ambiguousIsError: false}) {
+                                 {bool malformedIsError: false}) {
     Identifier typeName;
     SourceString prefixName;
     Send send = node.typeName.asSend();
@@ -1446,10 +1445,8 @@
 
     DartType reportFailureAndCreateType(DualKind messageKind,
                                         Map messageArguments,
-                                        {DartType userProvidedBadType,
-                                         bool isError: false,
-                                         bool isAmbiguous: false}) {
-      if (isError) {
+                                        {DartType userProvidedBadType}) {
+      if (malformedIsError) {
         visitor.error(node, messageKind.error, messageArguments);
       } else {
         visitor.warning(node, messageKind.warning, messageArguments);
@@ -1459,9 +1456,7 @@
           visitor.enclosingElement);
       var arguments = new LinkBuilder<DartType>();
       resolveTypeArguments(visitor, node, null, arguments);
-      return isAmbiguous
-          ? new AmbiguousType(erroneousElement, arguments.toLink())
-          : new MalformedType(erroneousElement,
+      return new MalformedType(erroneousElement,
               userProvidedBadType, arguments.toLink());
     }
 
@@ -1480,18 +1475,15 @@
 
     if (element == null) {
       type = reportFailureAndCreateType(
-          MessageKind.CANNOT_RESOLVE_TYPE, {'typeName': node.typeName},
-          isError: malformedIsError);
+          MessageKind.CANNOT_RESOLVE_TYPE, {'typeName': node.typeName});
     } else if (element.isAmbiguous()) {
       AmbiguousElement ambiguous = element;
       type = reportFailureAndCreateType(
-          ambiguous.messageKind, ambiguous.messageArguments,
-          isError: ambiguousIsError, isAmbiguous: true);
+          ambiguous.messageKind, ambiguous.messageArguments);
       ambiguous.diagnose(visitor.mapping.currentElement, compiler);
     } else if (!element.impliesType()) {
       type = reportFailureAndCreateType(
-          MessageKind.NOT_A_TYPE, {'node': node.typeName},
-          isError: malformedIsError);
+          MessageKind.NOT_A_TYPE, {'node': node.typeName});
     } else {
       if (identical(element, compiler.types.voidType.element) ||
           identical(element, compiler.dynamicClass)) {
@@ -1545,8 +1537,7 @@
           type = reportFailureAndCreateType(
               MessageKind.TYPE_VARIABLE_WITHIN_STATIC_MEMBER,
               {'typeVariableName': node},
-              userProvidedBadType: element.computeType(compiler),
-              isError: malformedIsError);
+              userProvidedBadType: element.computeType(compiler));
         } else {
           type = element.computeType(compiler);
         }
@@ -1570,8 +1561,7 @@
       MappingVisitor visitor,
       TypeAnnotation node,
       Link<DartType> typeVariables,
-      LinkBuilder<DartType> arguments,
-      {bool ambiguousIsError: false}) {
+      LinkBuilder<DartType> arguments) {
     if (node.typeArguments == null) {
       return false;
     }
@@ -1584,8 +1574,7 @@
             typeArguments.head, MessageKind.ADDITIONAL_TYPE_ARGUMENT.warning);
         typeArgumentCountMismatch = true;
       }
-      DartType argType = resolveTypeAnnotation(visitor, typeArguments.head,
-          ambiguousIsError: ambiguousIsError);
+      DartType argType = resolveTypeAnnotation(visitor, typeArguments.head);
       arguments.addLast(argType);
       if (typeVariables != null && !typeVariables.isEmpty) {
         typeVariables = typeVariables.tail;
@@ -2228,7 +2217,9 @@
     Element target = resolveSend(node);
     sendIsMemberAccess = oldSendIsMemberAccess;
 
-    if (target != null && target == compiler.mirrorSystemGetNameFunction) {
+    if (target != null
+        && target == compiler.mirrorSystemGetNameFunction
+        && !compiler.mirrorUsageAnalyzerTask.hasMirrorUsage(enclosingElement)) {
       compiler.reportHint(
           node.selector, MessageKind.STATIC_FUNCTION_BLOAT,
           {'class': compiler.mirrorSystemClass.name,
@@ -2646,9 +2637,12 @@
           }
         }
       } else {
-        compiler.reportHint(
-            node.newToken, MessageKind.NON_CONST_BLOAT,
-            {'name': compiler.symbolClass.name});
+        if (!compiler.mirrorUsageAnalyzerTask.hasMirrorUsage(
+                enclosingElement)) {
+          compiler.reportHint(
+              node.newToken, MessageKind.NON_CONST_BLOAT,
+              {'name': compiler.symbolClass.name});
+        }
         world.registerNewSymbol(mapping);
       }
     }
@@ -2686,13 +2680,11 @@
   }
 
   DartType resolveTypeExpression(TypeAnnotation node) {
-    return resolveTypeAnnotation(node, isTypeExpression: true);
+    return resolveTypeAnnotation(node);
   }
 
-  DartType resolveTypeAnnotation(TypeAnnotation node,
-                                 {bool isTypeExpression: false}) {
-    DartType type = typeResolver.resolveTypeAnnotation(
-        this, node, ambiguousIsError: isTypeExpression);
+  DartType resolveTypeAnnotation(TypeAnnotation node) {
+    DartType type = typeResolver.resolveTypeAnnotation(this, node);
     if (type == null) return null;
     if (inCheckContext) {
       compiler.enqueuer.resolution.registerIsCheck(type, mapping);
diff --git a/sdk/lib/_internal/compiler/implementation/scanner/listener.dart b/sdk/lib/_internal/compiler/implementation/scanner/listener.dart
index 5c69c08..65f35e2 100644
--- a/sdk/lib/_internal/compiler/implementation/scanner/listener.dart
+++ b/sdk/lib/_internal/compiler/implementation/scanner/listener.dart
@@ -287,12 +287,6 @@
                           Token beginToken, Token endToken) {
   }
 
-  void beginScriptTag(Token token) {
-  }
-
-  void endScriptTag(bool hasPrefix, Token beginToken, Token endToken) {
-  }
-
   void beginSend(Token token) {
   }
 
@@ -729,26 +723,6 @@
     compilationUnitElement.setPartOf(tag, listener);
   }
 
-  void endScriptTag(bool hasPrefix, Token beginToken, Token endToken) {
-    LiteralString prefix = null;
-    Identifier argumentName = null;
-    if (hasPrefix) {
-      prefix = popLiteralString();
-      argumentName = popNode();
-    }
-    LiteralString firstArgument = popLiteralString();
-    Identifier tag = popNode();
-    ScriptTag scriptTag = new ScriptTag(tag, firstArgument, argumentName,
-                                        prefix, beginToken, endToken);
-    if (const SourceString('import') == tag.source ||
-        const SourceString('source') == tag.source ||
-        const SourceString('library') == tag.source) {
-      addScriptTag(scriptTag);
-    } else {
-      recoverableError('unknown tag: ${tag.source.slowToString()}', node: tag);
-    }
-  }
-
   void endMetadata(Token beginToken, Token periodBeforeName, Token endToken) {
     if (periodBeforeName != null) {
       popNode(); // Discard name.
@@ -1041,12 +1015,6 @@
     metadata = metadata.prepend(annotation);
   }
 
-  // TODO(ahe): Remove this method.
-  void addScriptTag(ScriptTag tag) {
-    listener.onDeprecatedFeature(tag, '# tags');
-    addLibraryTag(tag.toLibraryTag());
-  }
-
   void addLibraryTag(LibraryTag tag) {
     if (!allowLibraryTags()) {
       recoverableError('library tags not allowed here', node: tag);
diff --git a/sdk/lib/_internal/compiler/implementation/scanner/parser.dart b/sdk/lib/_internal/compiler/implementation/scanner/parser.dart
index 78329cc..ee84b4c 100644
--- a/sdk/lib/_internal/compiler/implementation/scanner/parser.dart
+++ b/sdk/lib/_internal/compiler/implementation/scanner/parser.dart
@@ -52,8 +52,6 @@
       return parseClass(token);
     } else if (identical(value, 'typedef')) {
       return parseTypedef(token);
-    } else if (identical(value, '#')) {
-      return parseScriptTags(token);
     } else if (identical(value, 'library')) {
       return parseLibraryName(token);
     } else if (identical(value, 'import')) {
@@ -747,24 +745,6 @@
     return token;
   }
 
-  Token parseScriptTags(Token token) {
-    Token begin = token;
-    listener.beginScriptTag(token);
-    token = parseIdentifier(token.next);
-    token = expect('(', token);
-    token = parseLiteralStringOrRecoverExpression(token);
-    bool hasPrefix = false;
-    if (optional(',', token)) {
-      hasPrefix = true;
-      token = parseIdentifier(token.next);
-      token = expect(':', token);
-      token = parseLiteralStringOrRecoverExpression(token);
-    }
-    token = expect(')', token);
-    listener.endScriptTag(hasPrefix, begin, token);
-    return expectSemicolon(token);
-  }
-
   Token parseLiteralStringOrRecoverExpression(Token token) {
     if (identical(token.kind, STRING_TOKEN)) {
       return parseLiteralString(token);
diff --git a/sdk/lib/_internal/compiler/implementation/ssa/builder.dart b/sdk/lib/_internal/compiler/implementation/ssa/builder.dart
index 151efbd..12be2f6 100644
--- a/sdk/lib/_internal/compiler/implementation/ssa/builder.dart
+++ b/sdk/lib/_internal/compiler/implementation/ssa/builder.dart
@@ -2770,21 +2770,12 @@
     bool isNot = node.isIsNotCheck;
     DartType type = elements.getType(node.typeAnnotationFromIsCheckOrCast);
     type = type.unalias(compiler);
-    if (type.containsAmbiguousTypes) {
-      String reasons = Types.fetchReasonsFromAmbiguousType(type);
-      if (compiler.enableTypeAssertions) {
-        generateMalformedSubtypeError(node, expression, type, reasons);
-      } else {
-        generateRuntimeError(node, '$type is ambiguous: $reasons');
-      }
-    } else {
-      HInstruction instruction = buildIsNode(node, type, expression);
-      if (isNot) {
-        add(instruction);
-        instruction = new HNot(instruction);
-      }
-      push(instruction);
+    HInstruction instruction = buildIsNode(node, type, expression);
+    if (isNot) {
+      add(instruction);
+      instruction = new HNot(instruction);
     }
+    push(instruction);
   }
 
   HLiteralList buildTypeVariableList(ClassElement contextClass) {
@@ -3409,11 +3400,6 @@
     }
   }
 
-  /**
-   * Documentation wanted -- johnniwinther
-   *
-   * Invariant: [argument] must not be malformed in checked mode.
-   */
   HInstruction analyzeTypeArgument(DartType argument) {
     if (argument.treatAsDynamic) {
       // Represent [dynamic] as [null].
@@ -3464,11 +3450,6 @@
     pop();
   }
 
-  /**
-   * Documentation wanted -- johnniwinther
-   *
-   * Invariant: [type] must not be malformed in checked mode.
-   */
   handleNewSend(NewExpression node, InterfaceType type) {
     Send send = node.send;
     bool isListConstructor = false;
@@ -3745,14 +3726,6 @@
                               existingArguments: existingArguments);
   }
 
-  void generateMalformedSubtypeError(Node node, HInstruction value,
-                                     DartType type, String reasons) {
-    HInstruction typeString = addConstantString(node, type.toString());
-    HInstruction reasonsString = addConstantString(node, reasons);
-    Element helper = backend.getThrowMalformedSubtypeError();
-    pushInvokeStatic(node, helper, [value, typeString, reasonsString]);
-  }
-
   visitNewExpression(NewExpression node) {
     Element element = elements[node.send];
     final bool isSymbolConstructor = element == compiler.symbolConstructor;
@@ -3782,16 +3755,9 @@
       }
     } else {
       DartType type = elements.getType(node);
-      if (compiler.enableTypeAssertions && type.containsAmbiguousTypes) {
-        String reasons = Types.fetchReasonsFromAmbiguousType(type);
-        // TODO(johnniwinther): Change to resemble type errors from bounds check
-        // on type arguments.
-        generateRuntimeError(node, '$type is malformed: $reasons');
-      } else {
-        // TODO(karlklose): move this type registration to the codegen.
-        compiler.codegenWorld.instantiatedTypes.add(type);
-        handleNewSend(node, type);
-      }
+      // TODO(karlklose): move this type registration to the codegen.
+      compiler.codegenWorld.instantiatedTypes.add(type);
+      handleNewSend(node, type);
     }
   }
 
@@ -4952,21 +4918,6 @@
       void visitThen() {
         CatchBlock catchBlock = link.head;
         link = link.tail;
-
-        if (compiler.enableTypeAssertions) {
-          // In checked mode: throw a type error if the on-catch type is
-          // malformed.
-          if (catchBlock.onKeyword != null) {
-            DartType type = elements.getType(catchBlock.type);
-            if (type != null && type.containsAmbiguousTypes) {
-              String reasons = Types.fetchReasonsFromAmbiguousType(type);
-              generateMalformedSubtypeError(node,
-                  unwrappedException, type, reasons);
-              pop();
-              return;
-            }
-          }
-        }
         if (catchBlock.exception != null) {
           localsHandler.updateLocal(elements[catchBlock.exception],
                                     unwrappedException);
@@ -5076,10 +5027,6 @@
     inTryStatement = oldInTryStatement;
   }
 
-  visitScriptTag(ScriptTag node) {
-    compiler.unimplemented('SsaBuilder.visitScriptTag', node: node);
-  }
-
   visitCatchBlock(CatchBlock node) {
     visit(node.block);
   }
diff --git a/sdk/lib/_internal/compiler/implementation/ssa/nodes.dart b/sdk/lib/_internal/compiler/implementation/ssa/nodes.dart
index 38e9e4f..a580f24 100644
--- a/sdk/lib/_internal/compiler/implementation/ssa/nodes.dart
+++ b/sdk/lib/_internal/compiler/implementation/ssa/nodes.dart
@@ -1117,9 +1117,6 @@
     // available.
     assert(type.kind != TypeKind.TYPE_VARIABLE);
     assert(type.isRaw || type.kind == TypeKind.FUNCTION);
-    if (type.containsAmbiguousTypes) {
-      return new HTypeConversion(type, kind, HType.UNKNOWN, this);
-    }
     if (type.treatAsDynamic) return this;
     if (identical(type.element, compiler.objectClass)) return this;
     if (type.kind != TypeKind.INTERFACE) {
diff --git a/sdk/lib/_internal/compiler/implementation/tree/nodes.dart b/sdk/lib/_internal/compiler/implementation/tree/nodes.dart
index d0d94a4..210ebe5 100644
--- a/sdk/lib/_internal/compiler/implementation/tree/nodes.dart
+++ b/sdk/lib/_internal/compiler/implementation/tree/nodes.dart
@@ -66,7 +66,6 @@
   R visitPrefix(Prefix node) => visitNodeList(node);
   R visitRethrow(Rethrow node) => visitStatement(node);
   R visitReturn(Return node) => visitStatement(node);
-  R visitScriptTag(ScriptTag node) => visitNode(node);
   R visitSend(Send node) => visitExpression(node);
   R visitSendSet(SendSet node) => visitSend(node);
   R visitStatement(Statement node) => visitNode(node);
@@ -181,7 +180,6 @@
   PartOf asPartOf() => null;
   Rethrow asRethrow() => null;
   Return asReturn() => null;
-  ScriptTag asScriptTag() => null;
   Send asSend() => null;
   SendSet asSendSet() => null;
   Statement asStatement() => null;
@@ -1695,59 +1693,6 @@
   Node getBody() => statement;
 }
 
-class ScriptTag extends Node {
-  final Identifier tag;
-  final StringNode argument;
-  final Identifier prefixIdentifier;
-  final StringNode prefix;
-
-  final Token beginToken;
-  final Token endToken;
-
-  ScriptTag(this.tag, this.argument, this.prefixIdentifier, this.prefix,
-            this.beginToken, this.endToken);
-
-  bool isImport() => tag.source == const SourceString("import");
-  bool isSource() => tag.source == const SourceString("source");
-  bool isLibrary() => tag.source == const SourceString("library");
-
-  ScriptTag asScriptTag() => this;
-
-  accept(Visitor visitor) => visitor.visitScriptTag(this);
-
-  visitChildren(Visitor visitor) {
-    tag.accept(visitor);
-    argument.accept(visitor);
-    if (prefixIdentifier != null) prefixIdentifier.accept(visitor);
-    if (prefix != null) prefix.accept(visitor);
-  }
-
-  Token getBeginToken() => beginToken;
-
-  Token getEndToken() => endToken;
-
-  LibraryTag toLibraryTag() {
-    if (isImport()) {
-      Identifier prefixNode;
-      if (prefix != null) {
-        SourceString source = prefix.dartString.source;
-        Token prefixToken = prefix.getBeginToken();
-        Token token = new StringToken.fromSource(IDENTIFIER_INFO, source,
-                                                 prefixToken.charOffset);
-        token.next = prefixToken.next;
-        prefixNode = new Identifier(token);
-      }
-      return new Import(tag.token, argument, prefixNode, null, null);
-    } else if (isLibrary()) {
-      return new LibraryName(tag.token, argument, null);
-    } else if (isSource()) {
-      return new Part(tag.token, argument, null);
-    } else {
-      throw 'Unknown script tag ${tag.token.slowToString()}';
-    }
-  }
-}
-
 abstract class LibraryTag extends Node {
   final Link<MetadataAnnotation> metadata;
 
diff --git a/sdk/lib/_internal/compiler/implementation/tree/prettyprint.dart b/sdk/lib/_internal/compiler/implementation/tree/prettyprint.dart
index 6d85e08..60f4807 100644
--- a/sdk/lib/_internal/compiler/implementation/tree/prettyprint.dart
+++ b/sdk/lib/_internal/compiler/implementation/tree/prettyprint.dart
@@ -314,10 +314,6 @@
     closeNode();
   }
 
-  visitScriptTag(ScriptTag node) {
-    visitNodeWithChildren(node, "ScriptTag");
-  }
-
   visitChildNode(Node node, String fieldName) {
     if (node == null) return;
     addCurrentIndent();
diff --git a/sdk/lib/_internal/compiler/implementation/tree/unparser.dart b/sdk/lib/_internal/compiler/implementation/tree/unparser.dart
index 274117b..92d10e3 100644
--- a/sdk/lib/_internal/compiler/implementation/tree/unparser.dart
+++ b/sdk/lib/_internal/compiler/implementation/tree/unparser.dart
@@ -477,20 +477,6 @@
     sb.write('import "$uri"$suffix;');
   }
 
-  visitScriptTag(ScriptTag node) {
-    add(node.beginToken.value);
-    visit(node.tag);
-    sb.write('(');
-    visit(node.argument);
-    if (node.prefixIdentifier != null) {
-      visit(node.prefixIdentifier);
-      sb.write(':');
-      visit(node.prefix);
-    }
-    sb.write(')');
-    add(node.endToken.value);
-  }
-
   visitTryStatement(TryStatement node) {
     addToken(node.tryKeyword);
     visit(node.tryBlock);
diff --git a/sdk/lib/_internal/compiler/implementation/types/concrete_types_inferrer.dart b/sdk/lib/_internal/compiler/implementation/types/concrete_types_inferrer.dart
index 57b7904..ab7226b 100644
--- a/sdk/lib/_internal/compiler/implementation/types/concrete_types_inferrer.dart
+++ b/sdk/lib/_internal/compiler/implementation/types/concrete_types_inferrer.dart
@@ -2165,10 +2165,6 @@
     inferrer.fail(node, 'not yet implemented');
   }
 
-  ConcreteType visitScriptTag(ScriptTag node) {
-    inferrer.fail(node, 'not yet implemented');
-  }
-
   ConcreteType visitCatchBlock(CatchBlock node) {
     inferrer.fail(node, 'not yet implemented');
   }
diff --git a/sdk/lib/_internal/lib/io_patch.dart b/sdk/lib/_internal/lib/io_patch.dart
index c077360..d5e55c6 100644
--- a/sdk/lib/_internal/lib/io_patch.dart
+++ b/sdk/lib/_internal/lib/io_patch.dart
@@ -277,6 +277,11 @@
                                 bool useBuiltinRoots: true}) {
     throw new UnsupportedError("SecureSocket.initialize");
   }
+
+  patch static X509Certificate addCertificate(List<int> certificate,
+                                              String trust) {
+    throw new UnsupportedError("SecureSocket.addCertificate");
+  }
 }
 
 patch class _SecureFilter {
diff --git a/sdk/lib/_internal/lib/js_helper.dart b/sdk/lib/_internal/lib/js_helper.dart
index 5f590b0..0efd6c2 100644
--- a/sdk/lib/_internal/lib/js_helper.dart
+++ b/sdk/lib/_internal/lib/js_helper.dart
@@ -802,14 +802,6 @@
   throw new RuntimeError(message);
 }
 
-/**
- * The SSA builder generates a call to this method when a malformed type is used
- * in a subtype test.
- */
-throwMalformedSubtypeError(value, type, reasons) {
-  throw new TypeErrorImplementation.malformedSubtype(value, type, reasons);
-}
-
 throwAbstractClassInstantiationError(className) {
   throw new AbstractClassInstantiationError(className);
 }
@@ -1801,16 +1793,6 @@
   throw new TypeErrorImplementation(value, 'void');
 }
 
-malformedTypeCheck(value, type, reasons) {
-  if (value == null) return value;
-  throwMalformedSubtypeError(value, type, reasons);
-}
-
-malformedTypeCast(value, type, reasons) {
-  if (value == null) return value;
-  throw new CastErrorImplementation.malformedTypeCast(value, type, reasons);
-}
-
 /**
  * Special interface recognized by the compiler and implemented by DOM
  * objects that support integer indexing. This interface is not
@@ -1833,14 +1815,6 @@
       : message = "type '${Primitives.objectTypeName(value)}' is not a subtype "
                   "of type '$type'";
 
-  /**
-   * Type error caused by a subtype test on a malformed type.
-   */
-  TypeErrorImplementation.malformedSubtype(Object value,
-                                           String type, String reasons)
-      : message = "type '${Primitives.objectTypeName(value)}' is not a subtype "
-                  "of type '$type' because '$type' is malformed: $reasons.";
-
   String toString() => message;
 }
 
@@ -1856,17 +1830,6 @@
       : message = "CastError: Casting value of type $actualType to"
                   " incompatible type $expectedType";
 
-
-  /**
-   * Cast error caused by a type cast to a malformed type.
-   */
-  CastErrorImplementation.malformedTypeCast(Object value,
-                                            String type, String reasons)
-      : message = "CastError: Type '${Primitives.objectTypeName(value)}' "
-                  "cannot be cast to type '$type' because '$type' is "
-                  "malformed: $reasons.";
-
-
   String toString() => message;
 }
 
diff --git a/sdk/lib/_internal/pub/lib/src/command.dart b/sdk/lib/_internal/pub/lib/src/command.dart
index 8e3f9b5..97ad11ce 100644
--- a/sdk/lib/_internal/pub/lib/src/command.dart
+++ b/sdk/lib/_internal/pub/lib/src/command.dart
@@ -15,6 +15,7 @@
 import 'command/help.dart';
 import 'command/install.dart';
 import 'command/lish.dart';
+import 'command/serve.dart';
 import 'command/update.dart';
 import 'command/uploader.dart';
 import 'command/version.dart';
@@ -193,6 +194,7 @@
     'help': new HelpCommand(),
     'install': new InstallCommand(),
     'publish': new LishCommand(),
+    'serve': new ServeCommand(),
     'update': new UpdateCommand(),
     'uploader': new UploaderCommand(),
     'version': new VersionCommand()
diff --git a/sdk/lib/_internal/pub/lib/src/command/serve.dart b/sdk/lib/_internal/pub/lib/src/command/serve.dart
new file mode 100644
index 0000000..ce8db31
--- /dev/null
+++ b/sdk/lib/_internal/pub/lib/src/command/serve.dart
@@ -0,0 +1,172 @@
+// Copyright (c) 2013, 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 pub.command.serve;
+
+import 'dart:async';
+import 'dart:io';
+
+import 'package:barback/barback.dart';
+import 'package:path/path.dart' as path;
+
+import '../command.dart';
+import '../entrypoint.dart';
+import '../exit_codes.dart' as exit_codes;
+import '../log.dart' as log;
+import '../pub_package_provider.dart';
+import '../utils.dart';
+
+final _green = getPlatformString('\u001b[32m');
+final _red = getPlatformString('\u001b[31m');
+final _none = getPlatformString('\u001b[0m');
+
+/// Handles the `serve` pub command.
+class ServeCommand extends PubCommand {
+  String get description => "Run a local web development server.";
+  String get usage => 'pub serve';
+
+  ServeCommand() {
+    commandParser.addOption('port', defaultsTo: '8080',
+        help: 'The port to listen on.');
+  }
+
+  Future onRun() {
+    // The completer for the top-level future returned by the command. Only
+    // used to keep pub running (by not completing) and to pipe fatal errors
+    // to pub's top-level error-handling machinery.
+    var completer = new Completer();
+
+    return new Future.value().then((_) {
+      // The server relies on an up-to-date lockfile, so install first if
+      // needed.
+      if (!entrypoint.isLockFileUpToDate()) {
+        log.message("Dependencies have changed, installing...");
+        return entrypoint.installDependencies().then((_) {
+          log.message("Dependencies installed!");
+        });
+      }
+    }).then((_) {
+      return PubPackageProvider.create(entrypoint);
+    }).then((provider) {
+      var port;
+      try {
+        port = int.parse(commandOptions['port']);
+      } on FormatException catch(_) {
+        log.error('Could not parse port "${commandOptions['port']}"');
+        this.printUsage();
+        exit(exit_codes.USAGE);
+      }
+
+      var barback = new Barback(provider);
+
+      barback.results.listen((result) {
+        if (result.succeeded) {
+          // TODO(rnystrom): Report using growl/inotify-send where available.
+          log.message("Build completed ${_green}successfully$_none");
+        } else {
+          log.message("Build completed with "
+              "${_red}${result.errors.length}$_none errors.");
+        }
+      });
+
+      barback.errors.listen((error) {
+        log.error("${_red}Build error:\n$error$_none");
+      });
+
+      // TODO(rnystrom): Watch file system and update sources again when they
+      // are added or modified.
+
+      HttpServer.bind("localhost", port).then((server) {
+        log.message("Serving ${entrypoint.root.name} "
+                    "on http://localhost:${server.port}");
+
+        // Add all of the visible files.
+        for (var package in provider.packages) {
+          barback.updateSources(provider.listAssets(package));
+        }
+
+        server.listen((request) {
+          var id = getIdFromUri(request.uri);
+          if (id == null) {
+            return notFound(request, "Path ${request.uri.path} is not valid.");
+          }
+
+          barback.getAssetById(id).then((asset) {
+            log.message(
+                "$_green${request.method}$_none ${request.uri} -> $asset");
+            // TODO(rnystrom): Set content-type based on asset type.
+            return request.response.addStream(asset.read()).then((_) {
+              request.response.close();
+            });
+            // TODO(rnystrom): Serve up a 500 if we get an error reading the
+            // asset.
+          }).catchError((error) {
+            log.error("$_red${request.method}$_none ${request.uri} -> $error");
+            if (error is! AssetNotFoundException) {
+              completer.completeError(error);
+              return;
+            }
+
+            notFound(request, error);
+          });
+        });
+      });
+
+      return completer.future;
+    });
+  }
+
+  /// Responds to [request] with a 404 response and closes it.
+  void notFound(HttpRequest request, message) {
+    request.response.statusCode = 404;
+    request.response.reasonPhrase = "Not Found";
+    request.response.write(message);
+    request.response.close();
+  }
+
+  AssetId getIdFromUri(Uri uri) {
+    var parts = path.url.split(uri.path);
+
+    // Strip the leading "/" from the URL.
+    parts.removeAt(0);
+
+    var isSpecial = false;
+
+    // Checks to see if [uri]'s path contains a special directory [name] that
+    // identifies an asset within some package. If so, maps the package name
+    // and path following that to be within [dir] inside that package.
+    AssetId _trySpecialUrl(String name, String dir) {
+      // Find the package name and the relative path in the package.
+      var index = parts.indexOf(name);
+      if (index == -1) return null;
+
+      // If we got here, the path *did* contain the special directory, which
+      // means we should not interpret it as a regular path, even if it's
+      // missing the package name after it, which makes it invalid here.
+      isSpecial = true;
+      if (index + 1 >= parts.length) return null;
+
+      var package = parts[index + 1];
+      var assetPath = path.url.join(dir,
+          path.url.joinAll(parts.skip(index + 2)));
+      return new AssetId(package, assetPath);
+    }
+
+    // See if it's "packages" URL.
+    var id = _trySpecialUrl("packages", "lib");
+    if (id != null) return id;
+
+    // See if it's an "assets" URL.
+    id = _trySpecialUrl("assets", "asset");
+    if (id != null) return id;
+
+    // If we got here, we had a path like "/packages" which is a special
+    // directory, but not a valid path since it lacks a following package name.
+    if (isSpecial) return null;
+
+    // Otherwise, it's a path in current package's web directory.
+    return new AssetId(entrypoint.root.name,
+        path.url.join("web", path.url.joinAll(parts)));
+  }
+}
diff --git a/sdk/lib/_internal/pub/lib/src/entrypoint.dart b/sdk/lib/_internal/pub/lib/src/entrypoint.dart
index 1f09a3a..70888bc 100644
--- a/sdk/lib/_internal/pub/lib/src/entrypoint.dart
+++ b/sdk/lib/_internal/pub/lib/src/entrypoint.dart
@@ -154,6 +154,36 @@
     return new LockFile.load(lockFilePath, cache.sources);
   }
 
+  /// Determines whether or not the lockfile is out of date with respect to the
+  /// pubspec.
+  ///
+  /// This will be `false` if there is no lockfile at all, or if the pubspec
+  /// contains dependencies that are not in the lockfile or that don't match
+  /// what's in there.
+  bool isLockFileUpToDate() {
+    var lockFile = loadLockFile();
+
+    checkDependency(package) {
+      var locked = lockFile.packages[package.name];
+      if (locked == null) return false;
+
+      if (package.source != locked.source) return false;
+      if (!package.constraint.allows(locked.version)) return false;
+
+      var source = cache.sources[package.source];
+      if (!source.descriptionsEqual(package.description, locked.description)) {
+        return false;
+      }
+
+      return true;
+    }
+
+    if (!root.dependencies.every(checkDependency)) return false;
+    if (!root.devDependencies.every(checkDependency)) return false;
+
+    return true;
+  }
+
   /// Saves a list of concrete package versions to the `pubspec.lock` file.
   void _saveLockFile(List<PackageId> packageIds) {
     var lockFile = new LockFile.empty();
diff --git a/sdk/lib/_internal/pub/lib/src/package.dart b/sdk/lib/_internal/pub/lib/src/package.dart
index 6f1be0b..315f189 100644
--- a/sdk/lib/_internal/pub/lib/src/package.dart
+++ b/sdk/lib/_internal/pub/lib/src/package.dart
@@ -34,10 +34,12 @@
   /// The parsed pubspec associated with this package.
   final Pubspec pubspec;
 
-  /// The ids of the packages that this package depends on. This is what is
-  /// specified in the pubspec when this package depends on another.
+  /// The immediate dependencies this package specifies in its pubspec.
   List<PackageDep> get dependencies => pubspec.dependencies;
 
+  /// The immediate dev dependencies this package specifies in its pubspec.
+  List<PackageDep> get devDependencies => pubspec.devDependencies;
+
   /// Returns the path to the README file at the root of the entrypoint, or null
   /// if no README file is found. If multiple READMEs are found, this uses the
   /// same conventions as pub.dartlang.org for choosing the primary one: the
diff --git a/sdk/lib/_internal/pub/lib/src/pub_package_provider.dart b/sdk/lib/_internal/pub/lib/src/pub_package_provider.dart
new file mode 100644
index 0000000..6243127
--- /dev/null
+++ b/sdk/lib/_internal/pub/lib/src/pub_package_provider.dart
@@ -0,0 +1,97 @@
+// Copyright (c) 2013, 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 pub.pub_package_provider;
+
+import 'dart:async';
+import 'dart:io';
+
+import 'package:barback/barback.dart';
+import 'package:path/path.dart' as path;
+
+import 'entrypoint.dart';
+import 'io.dart';
+
+/// An implementation of barback's [PackageProvider] interface so that barback
+/// can assets within pub packages.
+class PubPackageProvider implements PackageProvider {
+  /// The [Entrypoint] package being served.
+  final Entrypoint _entrypoint;
+
+  /// Maps the names of all of the packages in [_entrypoint]'s transitive
+  /// dependency graph to the local path of the directory for that package.
+  final Map<String, String> _packageDirs;
+
+  /// Creates a new provider for [entrypoint].
+  static Future<PubPackageProvider> create(Entrypoint entrypoint) {
+    var packageDirs = <String, String>{};
+
+    packageDirs[entrypoint.root.name] = entrypoint.root.dir;
+
+    // Cache package directories up front so we can have synchronous access
+    // to them.
+    // TODO(rnystrom): Handle missing or out of date lockfile.
+    var futures = [];
+    entrypoint.loadLockFile().packages.forEach((name, package) {
+      var source = entrypoint.cache.sources[package.source];
+      futures.add(source.getDirectory(package).then((packageDir) {
+        packageDirs[name] = packageDir;
+      }));
+    });
+
+    return Future.wait(futures).then((_) {
+      return new PubPackageProvider._(entrypoint, packageDirs);
+    });
+  }
+
+  PubPackageProvider._(this._entrypoint, this._packageDirs);
+
+  Iterable<String> get packages => _packageDirs.keys;
+
+  /// Lists all of the visible files in [package].
+  ///
+  /// This is the recursive contents of the "asset" and "lib" directories (if
+  /// present). If [package] is the entrypoint package, it also includes the
+  /// contents of "web".
+  List<AssetId> listAssets(String package) {
+    var files = <AssetId>[];
+
+    addFiles(String dirPath) {
+      var packageDir = _packageDirs[package];
+      var dir = path.join(packageDir, dirPath);
+      if (!dirExists(dir)) return;
+      for (var entry in listDir(dir, recursive: true)) {
+        // Ignore "packages" symlinks if there.
+        if (path.split(entry).contains("packages")) continue;
+
+        // Skip directories.
+        if (!fileExists(entry)) continue;
+
+        // AssetId paths use "/" on all platforms.
+        var relative = path.relative(entry, from: packageDir);
+        relative = path.toUri(relative).path;
+        files.add(new AssetId(package, relative));
+      }
+    }
+
+    // Expose the "asset" and "lib" directories.
+    addFiles("asset");
+    addFiles("lib");
+
+    // The entrypoint's "web" directory is also visible.
+    if (package == _entrypoint.root.name) {
+      addFiles("web");
+    }
+
+    return files;
+  }
+
+  // TODO(rnystrom): Actually support transformers.
+  Iterable<Iterable<Transformer>> getTransformers(String package) => [];
+
+  Future<Asset> getAsset(AssetId id) {
+    var file = path.join(_packageDirs[id.package], id.path);
+    return new Future.value(new Asset.fromPath(id, file));
+  }
+}
diff --git a/sdk/lib/_internal/pub/lib/src/source.dart b/sdk/lib/_internal/pub/lib/src/source.dart
index 66428f5..99f12ab 100644
--- a/sdk/lib/_internal/pub/lib/src/source.dart
+++ b/sdk/lib/_internal/pub/lib/src/source.dart
@@ -184,6 +184,14 @@
     return false;
   }
 
+  /// Returns the directory where this package has been installed. If this is
+  /// a cached source, it will be in the system cache. Otherwise, it will
+  /// depend on the source.
+  Future<String> getDirectory(PackageId id) {
+    if (shouldCache) return systemCacheDirectory(id);
+    throw new UnimplementedError("Source $name must implement this.");
+  }
+
   /// Returns the directory in the system cache that the package identified by
   /// [id] should be installed to. This should return a path to a subdirectory
   /// of [systemCacheRoot].
diff --git a/sdk/lib/_internal/pub/lib/src/source/path.dart b/sdk/lib/_internal/pub/lib/src/source/path.dart
index 809481e..6a9363a 100644
--- a/sdk/lib/_internal/pub/lib/src/source/path.dart
+++ b/sdk/lib/_internal/pub/lib/src/source/path.dart
@@ -52,6 +52,13 @@
     });
   }
 
+  Future<String> getDirectory(PackageId id) {
+    return newFuture(() {
+      _validatePath(id.name, id.description);
+      return id.description["path"];
+    });
+  }
+
   /// Parses a path dependency. This takes in a path string and returns a map.
   /// The "path" key will be the original path but resolved relative to the
   /// containing path. The "relative" key will be `true` if the original path
diff --git a/sdk/lib/_internal/pub/lib/src/utils.dart b/sdk/lib/_internal/pub/lib/src/utils.dart
index 16e7bef..6a048cf 100644
--- a/sdk/lib/_internal/pub/lib/src/utils.dart
+++ b/sdk/lib/_internal/pub/lib/src/utils.dart
@@ -72,6 +72,14 @@
   Future<List> get future => _completer.future;
 }
 
+/// Returns [posix] on POSIX machines and [windows] on Windows.
+///
+/// If [windows] is omitted, returns `""` on Windows.
+String getPlatformString(String posix, [String windows]) {
+  if (windows == null) windows = "";
+  return Platform.operatingSystem == "windows" ? windows : posix;
+}
+
 /// Like [new Future], but avoids around issue 11911 by using [new Future.value]
 /// under the covers.
 Future newFuture(callback()) => new Future.value().then((_) => callback());
diff --git a/sdk/lib/_internal/pub/test/pub_test.dart b/sdk/lib/_internal/pub/test/pub_test.dart
index 949f437..a521491 100644
--- a/sdk/lib/_internal/pub/test/pub_test.dart
+++ b/sdk/lib/_internal/pub/test/pub_test.dart
@@ -35,6 +35,7 @@
       help       Display help information for Pub.
       install    Install the current package's dependencies.
       publish    Publish the current package to pub.dartlang.org.
+      serve      Run a local web development server.
       update     Update the current package's dependencies to the latest versions.
       uploader   Manage uploaders for a package on pub.dartlang.org.
       version    Print pub version.
diff --git a/sdk/lib/_internal/pub/test/serve/does_not_install_first_if_a_dependency_is_removed_test.dart b/sdk/lib/_internal/pub/test/serve/does_not_install_first_if_a_dependency_is_removed_test.dart
new file mode 100644
index 0000000..8166680
--- /dev/null
+++ b/sdk/lib/_internal/pub/test/serve/does_not_install_first_if_a_dependency_is_removed_test.dart
@@ -0,0 +1,39 @@
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS d.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 pub_tests;
+
+import 'dart:io';
+import 'dart:json' as json;
+
+import '../descriptor.dart' as d;
+import '../test_pub.dart';
+import 'utils.dart';
+
+main() {
+  initConfig();
+  integration("does not install if a dependency is removed", () {
+    d.dir("foo", [
+      d.libPubspec("foo", "0.0.1"),
+      d.libDir("foo")
+    ]).create();
+
+    // Install to get "foo" into the lock file.
+    d.dir(appPath, [
+      d.appPubspec({
+        "foo": {"path": "../foo"}
+      })
+    ]).create();
+    pubInstall();
+
+    // Remove it from the pubspec.
+    d.dir(appPath, [
+      d.appPubspec()
+    ]).create();
+
+    startPubServe(shouldInstallFirst: false);
+    requestShouldSucceed("packages/foo/foo.dart", 'main() => "foo";');
+    endPubServe();
+  });
+}
diff --git a/sdk/lib/_internal/pub/test/serve/does_not_install_first_if_git_url_did_not_change_test.dart b/sdk/lib/_internal/pub/test/serve/does_not_install_first_if_git_url_did_not_change_test.dart
new file mode 100644
index 0000000..ee92c92
--- /dev/null
+++ b/sdk/lib/_internal/pub/test/serve/does_not_install_first_if_git_url_did_not_change_test.dart
@@ -0,0 +1,32 @@
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS d.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 pub_tests;
+
+import 'dart:io';
+import 'dart:json' as json;
+
+import '../descriptor.dart' as d;
+import '../test_pub.dart';
+import 'utils.dart';
+
+main() {
+  initConfig();
+  integration("does not install first if a git dependency's url is "
+      "unchanged", () {
+    d.git('foo.git', [
+      d.libPubspec('foo', '1.0.0'),
+      d.libDir("foo")
+    ]).create();
+
+    d.appDir({
+      "foo": {"git": "../foo.git"}
+    }).create();
+
+    pubInstall();
+    startPubServe(shouldInstallFirst: false);
+    requestShouldSucceed("packages/foo/foo.dart", 'main() => "foo";');
+    endPubServe();
+  });
+}
diff --git a/sdk/lib/_internal/pub/test/serve/does_not_install_first_if_locked_version_matches_test.dart b/sdk/lib/_internal/pub/test/serve/does_not_install_first_if_locked_version_matches_test.dart
new file mode 100644
index 0000000..fd2c2ff
--- /dev/null
+++ b/sdk/lib/_internal/pub/test/serve/does_not_install_first_if_locked_version_matches_test.dart
@@ -0,0 +1,48 @@
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS d.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 pub_tests;
+
+import 'dart:io';
+import 'dart:json' as json;
+
+import '../descriptor.dart' as d;
+import '../test_pub.dart';
+import 'utils.dart';
+
+main() {
+  initConfig();
+  integration("does not install if the locked version of a dependency is "
+      "allowed by the pubspec's constraint", () {
+    d.dir("foo", [
+      d.libPubspec("foo", "0.0.1"),
+      d.libDir("foo")
+    ]).create();
+
+    // Install to get "foo" into the lock file.
+    d.dir(appPath, [
+      d.appPubspec({
+        "foo": {
+          "path": "../foo",
+          "version": ">=0.0.1"
+        },
+      })
+    ]).create();
+    pubInstall();
+
+    // Change the version.
+    d.dir(appPath, [
+      d.appPubspec({
+        "foo": {
+          "path": "../foo",
+          "version": "<2.0.0"
+        },
+      })
+    ]).create();
+
+    startPubServe(shouldInstallFirst: false);
+    requestShouldSucceed("packages/foo/foo.dart", 'main() => "foo";');
+    endPubServe();
+  });
+}
diff --git a/sdk/lib/_internal/pub/test/serve/installs_first_if_dependency_added_test.dart b/sdk/lib/_internal/pub/test/serve/installs_first_if_dependency_added_test.dart
new file mode 100644
index 0000000..42bcdfd
--- /dev/null
+++ b/sdk/lib/_internal/pub/test/serve/installs_first_if_dependency_added_test.dart
@@ -0,0 +1,39 @@
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS d.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 pub_tests;
+
+import 'dart:io';
+import 'dart:json' as json;
+
+import '../descriptor.dart' as d;
+import '../test_pub.dart';
+import 'utils.dart';
+
+main() {
+  initConfig();
+  integration("installs first if a dependency is not in the lock file", () {
+    d.dir("foo", [
+      d.libPubspec("foo", "0.0.1"),
+      d.libDir("foo")
+    ]).create();
+
+    // Create a lock file without "foo".
+    d.dir(appPath, [
+      d.appPubspec()
+    ]).create();
+    pubInstall();
+
+    // Add it to the pubspec.
+    d.dir(appPath, [
+      d.appPubspec({
+        "foo": {"path": "../foo"}
+      })
+    ]).create();
+
+    startPubServe(shouldInstallFirst: true);
+    requestShouldSucceed("packages/foo/foo.dart", 'main() => "foo";');
+    endPubServe();
+  });
+}
diff --git a/sdk/lib/_internal/pub/test/serve/installs_first_if_dependency_version_changed_test.dart b/sdk/lib/_internal/pub/test/serve/installs_first_if_dependency_version_changed_test.dart
new file mode 100644
index 0000000..cb64373
--- /dev/null
+++ b/sdk/lib/_internal/pub/test/serve/installs_first_if_dependency_version_changed_test.dart
@@ -0,0 +1,49 @@
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS d.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 pub_tests;
+
+import 'dart:io';
+import 'dart:json' as json;
+
+import '../descriptor.dart' as d;
+import '../test_pub.dart';
+import 'utils.dart';
+
+main() {
+  initConfig();
+  integration("installs first if a dependency's version doesn't match the one "
+      "in the lock file", () {
+    d.dir("foo", [
+      d.libPubspec("foo", "0.0.1"),
+      d.libDir("foo")
+    ]).create();
+
+    d.appDir({
+      "foo": {
+        "path": "../foo",
+        "version": "0.0.1"
+      }
+    }).create();
+
+    pubInstall();
+
+    // Change the version in the pubspec and package.
+    d.appDir({
+      "foo": {
+        "path": "../foo",
+        "version": "0.0.2"
+      }
+    }).create();
+
+    d.dir("foo", [
+      d.libPubspec("foo", "0.0.2"),
+      d.libDir("foo")
+    ]).create();
+
+    startPubServe(shouldInstallFirst: true);
+    requestShouldSucceed("packages/foo/foo.dart", 'main() => "foo";');
+    endPubServe();
+  });
+}
diff --git a/sdk/lib/_internal/pub/test/serve/installs_first_if_dev_dependency_changed_test.dart b/sdk/lib/_internal/pub/test/serve/installs_first_if_dev_dependency_changed_test.dart
new file mode 100644
index 0000000..5854fb6
--- /dev/null
+++ b/sdk/lib/_internal/pub/test/serve/installs_first_if_dev_dependency_changed_test.dart
@@ -0,0 +1,39 @@
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS d.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 pub_tests;
+
+import 'dart:io';
+import 'dart:json' as json;
+
+import '../descriptor.dart' as d;
+import '../test_pub.dart';
+import 'utils.dart';
+
+main() {
+  initConfig();
+  integration("installs first if a dev dependency has changed", () {
+    d.dir("foo", [
+      d.libPubspec("foo", "0.0.1"),
+      d.libDir("foo")
+    ]).create();
+
+    // Create a pubspec with "foo" and a lock file without it.
+    d.dir(appPath, [
+      d.pubspec({
+        "name": "myapp",
+        "dev_dependencies": {
+          "foo": {"path": "../foo"}
+        }
+      }),
+      d.file("pubspec.lock", json.stringify({
+        'packages': {}
+      }))
+    ]).create();
+
+    startPubServe(shouldInstallFirst: true);
+    requestShouldSucceed("packages/foo/foo.dart", 'main() => "foo";');
+    endPubServe();
+  });
+}
diff --git a/sdk/lib/_internal/pub/test/serve/installs_first_if_git_ref_changed_test.dart b/sdk/lib/_internal/pub/test/serve/installs_first_if_git_ref_changed_test.dart
new file mode 100644
index 0000000..a1906fd
--- /dev/null
+++ b/sdk/lib/_internal/pub/test/serve/installs_first_if_git_ref_changed_test.dart
@@ -0,0 +1,48 @@
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS d.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 pub_tests;
+
+import 'dart:io';
+import 'dart:json' as json;
+
+import '../descriptor.dart' as d;
+import '../test_pub.dart';
+import 'utils.dart';
+
+main() {
+  initConfig();
+  integration("installs first if a git dependency's ref doesn't match the one "
+      "in the lock file", () {
+    var repo = d.git('foo.git', [
+      d.libDir('foo', 'before'),
+      d.libPubspec('foo', '1.0.0')
+    ]);
+    repo.create();
+    var commit1 = repo.revParse('HEAD');
+
+    d.git('foo.git', [
+      d.libDir('foo', 'after'),
+      d.libPubspec('foo', '1.0.0')
+    ]).commit();
+
+    var commit2 = repo.revParse('HEAD');
+
+    // Lock it to the ref of the first commit.
+    d.appDir({
+      "foo": {"git": {"url": "../foo.git", "ref": commit1}}
+    }).create();
+
+    pubInstall();
+
+    // Change the commit in the pubspec.
+    d.appDir({
+      "foo": {"git": {"url": "../foo.git", "ref": commit2}}
+    }).create();
+
+    startPubServe(shouldInstallFirst: true);
+    requestShouldSucceed("packages/foo/foo.dart", 'main() => "after";');
+    endPubServe();
+  });
+}
diff --git a/sdk/lib/_internal/pub/test/serve/installs_first_if_git_url_changed_test.dart b/sdk/lib/_internal/pub/test/serve/installs_first_if_git_url_changed_test.dart
new file mode 100644
index 0000000..844e293
--- /dev/null
+++ b/sdk/lib/_internal/pub/test/serve/installs_first_if_git_url_changed_test.dart
@@ -0,0 +1,43 @@
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS d.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 pub_tests;
+
+import 'dart:io';
+import 'dart:json' as json;
+
+import '../descriptor.dart' as d;
+import '../test_pub.dart';
+import 'utils.dart';
+
+main() {
+  initConfig();
+  integration("installs first if a git dependency's url doesn't match the one "
+      "in the lock file", () {
+    d.git("foo-before.git", [
+      d.libPubspec("foo", "1.0.0"),
+      d.libDir("foo", "before")
+    ]).create();
+
+    d.git("foo-after.git", [
+      d.libPubspec("foo", "1.0.0"),
+      d.libDir("foo", "after")
+    ]).create();
+
+    d.appDir({
+      "foo": {"git": "../foo-before.git"}
+    }).create();
+
+    pubInstall();
+
+    // Change the path in the pubspec.
+    d.appDir({
+      "foo": {"git": "../foo-after.git"}
+    }).create();
+
+    startPubServe(shouldInstallFirst: true);
+    requestShouldSucceed("packages/foo/foo.dart", 'main() => "after";');
+    endPubServe();
+  });
+}
diff --git a/sdk/lib/_internal/pub/test/serve/installs_first_if_no_lockfile_test.dart b/sdk/lib/_internal/pub/test/serve/installs_first_if_no_lockfile_test.dart
new file mode 100644
index 0000000..9988113
--- /dev/null
+++ b/sdk/lib/_internal/pub/test/serve/installs_first_if_no_lockfile_test.dart
@@ -0,0 +1,29 @@
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS d.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 pub_tests;
+
+import 'dart:io';
+
+import '../descriptor.dart' as d;
+import '../test_pub.dart';
+import 'utils.dart';
+
+main() {
+  initConfig();
+  integration("installs first if there is no lockfile", () {
+    d.dir("foo", [
+      d.libPubspec("foo", "0.0.1"),
+      d.libDir("foo")
+    ]).create();
+
+    d.appDir({
+      "foo": {"path": "../foo"}
+    }).create();
+
+    startPubServe(shouldInstallFirst: true);
+    requestShouldSucceed("packages/foo/foo.dart", 'main() => "foo";');
+    endPubServe();
+  });
+}
diff --git a/sdk/lib/_internal/pub/test/serve/installs_first_if_path_dependency_changed_test.dart b/sdk/lib/_internal/pub/test/serve/installs_first_if_path_dependency_changed_test.dart
new file mode 100644
index 0000000..0380a9a
--- /dev/null
+++ b/sdk/lib/_internal/pub/test/serve/installs_first_if_path_dependency_changed_test.dart
@@ -0,0 +1,43 @@
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS d.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 pub_tests;
+
+import 'dart:io';
+import 'dart:json' as json;
+
+import '../descriptor.dart' as d;
+import '../test_pub.dart';
+import 'utils.dart';
+
+main() {
+  initConfig();
+  integration("installs first if a path dependency's path doesn't match the "
+      "one in the lock file", () {
+    d.dir("foo-before", [
+      d.libPubspec("foo", "0.0.1"),
+      d.libDir("foo", "before")
+    ]).create();
+
+    d.dir("foo-after", [
+      d.libPubspec("foo", "0.0.1"),
+      d.libDir("foo", "after")
+    ]).create();
+
+    d.appDir({
+      "foo": {"path": "../foo-before"}
+    }).create();
+
+    pubInstall();
+
+    // Change the path in the pubspec.
+    d.appDir({
+      "foo": {"path": "../foo-after"}
+    }).create();
+
+    startPubServe(shouldInstallFirst: true);
+    requestShouldSucceed("packages/foo/foo.dart", 'main() => "after";');
+    endPubServe();
+  });
+}
diff --git a/sdk/lib/_internal/pub/test/serve/installs_first_if_source_changed_test.dart b/sdk/lib/_internal/pub/test/serve/installs_first_if_source_changed_test.dart
new file mode 100644
index 0000000..85d0eee
--- /dev/null
+++ b/sdk/lib/_internal/pub/test/serve/installs_first_if_source_changed_test.dart
@@ -0,0 +1,44 @@
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS d.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 pub_tests;
+
+import 'dart:io';
+import 'dart:json' as json;
+
+import '../descriptor.dart' as d;
+import '../test_pub.dart';
+import 'utils.dart';
+
+main() {
+  initConfig();
+  integration("installs first if a dependency's source doesn't match the one "
+      "in the lock file", () {
+    d.dir("foo", [
+      d.libPubspec("foo", "0.0.1"),
+      d.libDir("foo")
+    ]).create();
+
+    d.dir(appPath, [
+      // A pubspec with a path source.
+      d.appPubspec({
+        "foo": {"path": "../foo"}
+      }),
+      // A lock file with the hosted source.
+      d.file("pubspec.lock", json.stringify({
+        'packages': {
+          'foo': {
+            'version': '0.0.0',
+            'source': 'hosted',
+            'description': 'foo'
+          }
+        }
+      }))
+    ]).create();
+
+    startPubServe(shouldInstallFirst: true);
+    requestShouldSucceed("packages/foo/foo.dart", 'main() => "foo";');
+    endPubServe();
+  });
+}
diff --git a/sdk/lib/_internal/pub/test/serve/invalid_urls_test.dart b/sdk/lib/_internal/pub/test/serve/invalid_urls_test.dart
new file mode 100644
index 0000000..bb830733
--- /dev/null
+++ b/sdk/lib/_internal/pub/test/serve/invalid_urls_test.dart
@@ -0,0 +1,61 @@
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS d.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 pub_tests;
+
+import 'dart:io';
+
+import '../descriptor.dart' as d;
+import '../test_pub.dart';
+import 'utils.dart';
+
+main() {
+  initConfig();
+  integration("responds with a 404 on incomplete special URLs", () {
+    d.dir("foo", [
+      d.libPubspec("foo", "0.0.1")
+    ]).create();
+
+    d.dir(appPath, [
+      d.appPubspec({
+        "foo": {"path": "../foo"}
+      }),
+      // Make files that map to the special directory names to ensure they
+      // are *not* found.
+      d.dir("asset", [
+        d.file("packages"),
+        d.file("assets")
+      ]),
+      d.dir("lib", [
+        d.file("packages"),
+        d.file("assets")
+      ]),
+      d.dir("web", [
+        d.file("packages"),
+        d.file("assets")
+      ])
+    ]).create();
+
+    pubInstall();
+    startPubServe();
+    requestShould404("packages");
+    requestShould404("assets");
+    requestShould404("packages/");
+    requestShould404("assets/");
+    requestShould404("packages/myapp");
+    requestShould404("assets/myapp");
+    requestShould404("packages/myapp/");
+    requestShould404("assets/myapp/");
+    requestShould404("packages/foo");
+    requestShould404("assets/foo");
+    requestShould404("packages/foo/");
+    requestShould404("assets/foo/");
+    requestShould404("packages/unknown");
+    requestShould404("assets/unknown");
+    requestShould404("packages/unknown/");
+    requestShould404("assets/unknown/");
+    endPubServe();
+  });
+
+}
diff --git a/sdk/lib/_internal/pub/test/serve/missing_dependency_file_test.dart b/sdk/lib/_internal/pub/test/serve/missing_dependency_file_test.dart
new file mode 100644
index 0000000..d1c47f2
--- /dev/null
+++ b/sdk/lib/_internal/pub/test/serve/missing_dependency_file_test.dart
@@ -0,0 +1,34 @@
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS d.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 pub_tests;
+
+import 'dart:io';
+
+import '../descriptor.dart' as d;
+import '../test_pub.dart';
+import 'utils.dart';
+
+main() {
+  initConfig();
+  integration("responds with a 404 for a missing files in dependencies", () {
+    d.dir("foo", [
+      d.libPubspec("foo", "0.0.1")
+    ]).create();
+
+    d.dir(appPath, [
+      d.appPubspec({
+        "foo": {"path": "../foo"}
+      })
+    ]).create();
+
+    pubInstall();
+    startPubServe();
+    requestShould404("packages/foo/nope.dart");
+    requestShould404("assets/foo/nope.png");
+    requestShould404("dir/packages/foo/nope.dart");
+    requestShould404("dir/assets/foo/nope.png");
+    endPubServe();
+  });
+}
diff --git a/sdk/lib/_internal/pub/test/serve/missing_file_test.dart b/sdk/lib/_internal/pub/test/serve/missing_file_test.dart
new file mode 100644
index 0000000..cfd7d07
--- /dev/null
+++ b/sdk/lib/_internal/pub/test/serve/missing_file_test.dart
@@ -0,0 +1,28 @@
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS d.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 pub_tests;
+
+import 'dart:io';
+
+import '../descriptor.dart' as d;
+import '../test_pub.dart';
+import 'utils.dart';
+
+main() {
+  initConfig();
+  integration("responds with a 404 for missing files", () {
+    d.dir(appPath, [
+      d.appPubspec()
+    ]).create();
+
+    startPubServe();
+    requestShould404("index.html");
+    requestShould404("packages/myapp/nope.dart");
+    requestShould404("assets/myapp/nope.png");
+    requestShould404("dir/packages/myapp/nope.dart");
+    requestShould404("dir/assets/myapp/nope.png");
+    endPubServe();
+  });
+}
diff --git a/sdk/lib/_internal/pub/test/serve/serve_from_app_asset_test.dart b/sdk/lib/_internal/pub/test/serve/serve_from_app_asset_test.dart
new file mode 100644
index 0000000..1f072fc
--- /dev/null
+++ b/sdk/lib/_internal/pub/test/serve/serve_from_app_asset_test.dart
@@ -0,0 +1,35 @@
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS d.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 pub_tests;
+
+import 'dart:io';
+
+import '../descriptor.dart' as d;
+import '../test_pub.dart';
+import 'utils.dart';
+
+main() {
+  initConfig();
+  integration("'assets' URLs look in the app's 'asset' directory", () {
+    d.dir(appPath, [
+      d.appPubspec(),
+      d.dir("asset", [
+        d.file("foo.txt", "foo"),
+        d.dir("sub", [
+          d.file("bar.txt", "bar"),
+        ])
+      ])
+    ]).create();
+
+    startPubServe();
+    requestShouldSucceed("assets/myapp/foo.txt", "foo");
+    requestShouldSucceed("assets/myapp/sub/bar.txt", "bar");
+
+    // "assets" can be in a subpath of the URL:
+    requestShouldSucceed("foo/assets/myapp/foo.txt", "foo");
+    requestShouldSucceed("a/b/assets/myapp/sub/bar.txt", "bar");
+    endPubServe();
+  });
+}
diff --git a/sdk/lib/_internal/pub/test/serve/serve_from_app_lib_test.dart b/sdk/lib/_internal/pub/test/serve/serve_from_app_lib_test.dart
new file mode 100644
index 0000000..0ddea5f
--- /dev/null
+++ b/sdk/lib/_internal/pub/test/serve/serve_from_app_lib_test.dart
@@ -0,0 +1,35 @@
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS d.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 pub_tests;
+
+import 'dart:io';
+
+import '../descriptor.dart' as d;
+import '../test_pub.dart';
+import 'utils.dart';
+
+main() {
+  initConfig();
+  integration("'packages' URLs look in the app's lib directory", () {
+    d.dir(appPath, [
+      d.appPubspec(),
+      d.dir("lib", [
+        d.file("lib.dart", "foo() => 'foo';"),
+        d.dir("sub", [
+          d.file("lib.dart", "bar() => 'bar';"),
+        ])
+      ])
+    ]).create();
+
+    startPubServe();
+    requestShouldSucceed("packages/myapp/lib.dart", "foo() => 'foo';");
+    requestShouldSucceed("packages/myapp/sub/lib.dart", "bar() => 'bar';");
+
+    // "packages" can be in a subpath of the URL:
+    requestShouldSucceed("foo/packages/myapp/lib.dart", "foo() => 'foo';");
+    requestShouldSucceed("a/b/packages/myapp/sub/lib.dart", "bar() => 'bar';");
+    endPubServe();
+  });
+}
diff --git a/sdk/lib/_internal/pub/test/serve/serve_from_app_web_test.dart b/sdk/lib/_internal/pub/test/serve/serve_from_app_web_test.dart
new file mode 100644
index 0000000..9c0a7f5
--- /dev/null
+++ b/sdk/lib/_internal/pub/test/serve/serve_from_app_web_test.dart
@@ -0,0 +1,35 @@
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS d.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 pub_tests;
+
+import 'dart:io';
+
+import '../descriptor.dart' as d;
+import '../test_pub.dart';
+import 'utils.dart';
+
+main() {
+  initConfig();
+  integration("finds files in the app's web directory", () {
+    d.dir(appPath, [
+      d.appPubspec(),
+      d.dir("web", [
+        d.file("index.html", "<body>"),
+        d.file("file.dart", "void main() => print('hello');"),
+        d.dir("sub", [
+          d.file("file.html", "<body>in subdir</body>"),
+          d.file("lib.dart", "void foo() => 'foo';"),
+        ])
+      ])
+    ]).create();
+
+    startPubServe();
+    requestShouldSucceed("index.html", "<body>");
+    requestShouldSucceed("file.dart", "void main() => print('hello');");
+    requestShouldSucceed("sub/file.html", "<body>in subdir</body>");
+    requestShouldSucceed("sub/lib.dart", "void foo() => 'foo';");
+    endPubServe();
+  });
+}
diff --git a/sdk/lib/_internal/pub/test/serve/serve_from_dependency_asset_test.dart b/sdk/lib/_internal/pub/test/serve/serve_from_dependency_asset_test.dart
new file mode 100644
index 0000000..f30d72c
--- /dev/null
+++ b/sdk/lib/_internal/pub/test/serve/serve_from_dependency_asset_test.dart
@@ -0,0 +1,42 @@
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS d.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 pub_tests;
+
+import 'dart:io';
+
+import '../descriptor.dart' as d;
+import '../test_pub.dart';
+import 'utils.dart';
+
+main() {
+  initConfig();
+  integration("'assets' URLs look in the dependency's asset directory", () {
+    d.dir("foo", [
+      d.libPubspec("foo", "0.0.1"),
+      d.dir("asset", [
+        d.file("foo.txt", "foo"),
+        d.dir("sub", [
+          d.file("bar.txt", "bar"),
+        ])
+      ])
+    ]).create();
+
+    d.dir(appPath, [
+      d.appPubspec({
+        "foo": {"path": "../foo"}
+      })
+    ]).create();
+
+    pubInstall();
+    startPubServe();
+    requestShouldSucceed("assets/foo/foo.txt", "foo");
+    requestShouldSucceed("assets/foo/sub/bar.txt", "bar");
+
+    // "assets" can be in a subpath of the URL:
+    requestShouldSucceed("foo/assets/foo/foo.txt", "foo");
+    requestShouldSucceed("a/b/assets/foo/sub/bar.txt", "bar");
+    endPubServe();
+  });
+}
diff --git a/sdk/lib/_internal/pub/test/serve/serve_from_dependency_lib_test.dart b/sdk/lib/_internal/pub/test/serve/serve_from_dependency_lib_test.dart
new file mode 100644
index 0000000..a6a9ab2
--- /dev/null
+++ b/sdk/lib/_internal/pub/test/serve/serve_from_dependency_lib_test.dart
@@ -0,0 +1,42 @@
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS d.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 pub_tests;
+
+import 'dart:io';
+
+import '../descriptor.dart' as d;
+import '../test_pub.dart';
+import 'utils.dart';
+
+main() {
+  initConfig();
+  integration("'packages' URLs look in the dependency's lib directory", () {
+    d.dir("foo", [
+      d.libPubspec("foo", "0.0.1"),
+      d.dir("lib", [
+        d.file("lib.dart", "foo() => 'foo';"),
+        d.dir("sub", [
+          d.file("lib.dart", "bar() => 'bar';"),
+        ])
+      ])
+    ]).create();
+
+    d.dir(appPath, [
+      d.appPubspec({
+        "foo": {"path": "../foo"}
+      })
+    ]).create();
+
+    pubInstall();
+    startPubServe();
+    requestShouldSucceed("packages/foo/lib.dart", "foo() => 'foo';");
+    requestShouldSucceed("packages/foo/sub/lib.dart", "bar() => 'bar';");
+
+    // "packages" can be in a subpath of the URL:
+    requestShouldSucceed("foo/packages/foo/lib.dart", "foo() => 'foo';");
+    requestShouldSucceed("a/b/packages/foo/sub/lib.dart", "bar() => 'bar';");
+    endPubServe();
+  });
+}
diff --git a/sdk/lib/_internal/pub/test/serve/unknown_dependency_test.dart b/sdk/lib/_internal/pub/test/serve/unknown_dependency_test.dart
new file mode 100644
index 0000000..434a84c
--- /dev/null
+++ b/sdk/lib/_internal/pub/test/serve/unknown_dependency_test.dart
@@ -0,0 +1,27 @@
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS d.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 pub_tests;
+
+import 'dart:io';
+
+import '../descriptor.dart' as d;
+import '../test_pub.dart';
+import 'utils.dart';
+
+main() {
+  initConfig();
+  integration("responds with a 404 unknown dependencies", () {
+    d.dir(appPath, [
+      d.appPubspec()
+    ]).create();
+
+    startPubServe();
+    requestShould404("packages/foo/nope.dart");
+    requestShould404("assets/foo/nope.png");
+    requestShould404("dir/packages/foo/nope.dart");
+    requestShould404("dir/assets/foo/nope.png");
+    endPubServe();
+  });
+}
diff --git a/sdk/lib/_internal/pub/test/serve/utils.dart b/sdk/lib/_internal/pub/test/serve/utils.dart
new file mode 100644
index 0000000..e03edd0
--- /dev/null
+++ b/sdk/lib/_internal/pub/test/serve/utils.dart
@@ -0,0 +1,72 @@
+// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS d.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 pub_tests;
+
+import 'dart:async';
+import 'dart:io';
+
+import 'package:http/http.dart' as http;
+import 'package:scheduled_test/scheduled_process.dart';
+import 'package:scheduled_test/scheduled_test.dart';
+
+import '../descriptor.dart' as d;
+import '../test_pub.dart';
+
+/// The pub process running "pub serve".
+ScheduledProcess _pubServer;
+
+/// The ephemeral port assigned to the running server.
+int _port;
+
+/// Schedules starting the "pub serve" process.
+///
+/// If [shouldInstallFirst] is `true`, validates that pub install is run first.
+void startPubServe({bool shouldInstallFirst: false}) {
+  // Use port 0 to get an ephemeral port.
+  _pubServer = startPub(args: ["serve", "--port=0"]);
+
+  if (shouldInstallFirst) {
+    expect(_pubServer.nextLine(),
+        completion(startsWith("Dependencies have changed")));
+    expect(_pubServer.nextLine(),
+        completion(startsWith("Resolving dependencies...")));
+    expect(_pubServer.nextLine(),
+        completion(equals("Dependencies installed!")));
+  }
+
+  expect(_pubServer.nextLine().then(_parsePort), completes);
+}
+
+/// Parses the port number from the "Serving blah on localhost:1234" line
+/// printed by pub serve.
+void _parsePort(String line) {
+  var match = new RegExp(r"localhost:(\d+)").firstMatch(line);
+  assert(match != null);
+  _port = int.parse(match[1]);
+}
+
+void endPubServe() {
+  _pubServer.kill();
+}
+
+/// Schedules an HTTP request to the running pub server with [urlPath] and
+/// verifies that it responds with [expected].
+void requestShouldSucceed(String urlPath, String expected) {
+  schedule(() {
+    return http.get("http://localhost:$_port/$urlPath").then((response) {
+      expect(response.body, equals(expected));
+    });
+  }, "request $urlPath");
+}
+
+/// Schedules an HTTP request to the running pub server with [urlPath] and
+/// verifies that it responds with a 404.
+void requestShould404(String urlPath) {
+  schedule(() {
+    return http.get("http://localhost:$_port/$urlPath").then((response) {
+      expect(response.statusCode, equals(404));
+    });
+  }, "request $urlPath");
+}
\ No newline at end of file
diff --git a/sdk/lib/html/dart2js/html_dart2js.dart b/sdk/lib/html/dart2js/html_dart2js.dart
index 6bd9e6c..74a14e5 100644
--- a/sdk/lib/html/dart2js/html_dart2js.dart
+++ b/sdk/lib/html/dart2js/html_dart2js.dart
@@ -199,39 +199,6 @@
 
 
 @DocsEditable()
-@DomName('ANGLEInstancedArrays')
-@Experimental() // untriaged
-class AngleInstancedArrays extends Interceptor native "ANGLEInstancedArrays" {
-
-  @DomName('ANGLEInstancedArrays.VERTEX_ATTRIB_ARRAY_DIVISOR_ANGLE')
-  @DocsEditable()
-  @Experimental() // untriaged
-  static const int VERTEX_ATTRIB_ARRAY_DIVISOR_ANGLE = 0x88FE;
-
-  @JSName('drawArraysInstancedANGLE')
-  @DomName('ANGLEInstancedArrays.drawArraysInstancedANGLE')
-  @DocsEditable()
-  @Experimental() // untriaged
-  void drawArraysInstancedAngle(int mode, int first, int count, int primcount) native;
-
-  @JSName('drawElementsInstancedANGLE')
-  @DomName('ANGLEInstancedArrays.drawElementsInstancedANGLE')
-  @DocsEditable()
-  @Experimental() // untriaged
-  void drawElementsInstancedAngle(int mode, int count, int type, int offset, int primcount) native;
-
-  @JSName('vertexAttribDivisorANGLE')
-  @DomName('ANGLEInstancedArrays.vertexAttribDivisorANGLE')
-  @DocsEditable()
-  @Experimental() // untriaged
-  void vertexAttribDivisorAngle(int index, int divisor) native;
-}
-// Copyright (c) 2012, 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.
-
-
-@DocsEditable()
 @DomName('WebKitAnimationEvent')
 @SupportedBrowser(SupportedBrowser.CHROME)
 @SupportedBrowser(SupportedBrowser.SAFARI)
@@ -2634,7 +2601,8 @@
 
 
 @DomName('CSSStyleDeclaration')
-class CssStyleDeclaration extends Interceptor native "CSSStyleDeclaration,MSStyleCSSProperties,CSS2Properties" {
+ class CssStyleDeclaration  extends Interceptor with 
+    CssStyleDeclarationBase  native "CSSStyleDeclaration,MSStyleCSSProperties,CSS2Properties" {
   factory CssStyleDeclaration() => new CssStyleDeclaration.css('');
 
   factory CssStyleDeclaration.css(String css) {
@@ -2642,7 +2610,37 @@
     style.cssText = css;
     return style;
   }
+  
+  String getPropertyValue(String propertyName) {
+    var propValue = _getPropertyValue(propertyName);
+    return propValue != null ? propValue : '';
+  }
 
+  @DomName('CSSStyleDeclaration.setProperty')
+  void setProperty(String propertyName, String value, [String priority]) {
+    // try/catch for IE9 which throws on unsupported values.
+    try {
+      if (priority == null) {
+        priority = '';
+      }
+      JS('void', '#.setProperty(#, #, #)', this, propertyName, value, priority);
+      // Bug #2772, IE9 requires a poke to actually apply the value.
+      if (JS('bool', '!!#.setAttribute', this)) {
+        JS('void', '#.setAttribute(#, #)', this, propertyName, value);
+      }
+    } catch (e) {}
+  }
+  
+  /**
+   * Checks to see if CSS Transitions are supported.
+   */
+  static bool get supportsTransitions {
+    if (JS('bool', '"transition" in document.body.style')) {
+      return true;
+    }
+    var propertyName = '${Device.propertyPrefix}Transition';
+    return JS('bool', '# in document.body.style', propertyName);
+  }
 
   @DomName('CSSStyleDeclaration.cssText')
   @DocsEditable()
@@ -2677,37 +2675,35 @@
   @DocsEditable()
   String removeProperty(String propertyName) native;
 
+}
 
-  String getPropertyValue(String propertyName) {
-    var propValue = _getPropertyValue(propertyName);
-    return propValue != null ? propValue : '';
+class _CssStyleDeclarationSet extends Object with CssStyleDeclarationBase {
+  final Iterable<Element> _elementIterable;
+  Iterable<CssStyleDeclaration> _elementCssStyleDeclarationSetIterable;
+
+  _CssStyleDeclarationSet(this._elementIterable) {
+    _elementCssStyleDeclarationSetIterable = new List.from(
+        _elementIterable).map((e) => e.style);
   }
 
-  @DomName('CSSStyleDeclaration.setProperty')
+  String getPropertyValue(String propertyName) =>
+      _elementCssStyleDeclarationSetIterable.first.getPropertyValue(
+          propertyName);
+
   void setProperty(String propertyName, String value, [String priority]) {
-    // try/catch for IE9 which throws on unsupported values.
-    try {
-      if (priority == null) {
-        priority = '';
-      }
-      JS('void', '#.setProperty(#, #, #)', this, propertyName, value, priority);
-      // Bug #2772, IE9 requires a poke to actually apply the value.
-      if (JS('bool', '!!#.setAttribute', this)) {
-        JS('void', '#.setAttribute(#, #)', this, propertyName, value);
-      }
-    } catch (e) {}
+    _elementCssStyleDeclarationSetIterable.forEach((e) =>
+        e.setProperty(propertyName, value, priority));
   }
+  // Important note: CssStyleDeclarationSet does NOT implement every method
+  // available in CssStyleDeclaration. Some of the methods don't make so much
+  // sense in terms of having a resonable value to return when you're
+  // considering a list of Elements. You will need to manually add any of the
+  // items in the MEMBERS set if you want that functionality.
+}
 
-  /**
-   * Checks to see if CSS Transitions are supported.
-   */
-  static bool get supportsTransitions {
-    if (JS('bool', '"transition" in document.body.style')) {
-      return true;
-    }
-    var propertyName = '${Device.propertyPrefix}Transition';
-    return JS('bool', '# in document.body.style', propertyName);
-  }
+abstract class CssStyleDeclarationBase {
+  String getPropertyValue(String propertyName);  
+  void setProperty(String propertyName, String value, [String priority]);
 
   // TODO(jacobr): generate this list of properties using the existing script.
   /** Gets the value of "align-content" */
@@ -7970,7 +7966,7 @@
 
 /**
  * An immutable list containing HTML elements. This list contains some
- * additional methods when compared to regular lists for ease of CSS 
+ * additional methods when compared to regular lists for ease of CSS
  * manipulation on a group of elements.
  */
 abstract class ElementList<T extends Element> extends ListBase<T> {
@@ -7989,28 +7985,40 @@
   /** Replace the classes with `value` for every element in this list. */
   set classes(Iterable<String> value);
 
-  /** 
+  /**
+   * Access the union of all [CssStyleDeclaration]s that are associated with an
+   * [ElementList].
+   *
+   * Grouping the style objects all together provides easy editing of specific
+   * properties of a collection of elements. Setting a specific property value
+   * will set that property in all [Element]s in the [ElementList]. Getting a
+   * specific property value will return the value of the property of the first
+   * element in the [ElementList].
+   */
+  CssStyleDeclarationBase get style;
+
+  /**
    * Access dimensions and position of the Elements in this list.
-   * 
+   *
    * Setting the height or width properties will set the height or width
-   * property for all elements in the list. This returns a rectangle with the 
+   * property for all elements in the list. This returns a rectangle with the
    * dimenions actually available for content
-   * in this element, in pixels, regardless of this element's box-sizing 
+   * in this element, in pixels, regardless of this element's box-sizing
    * property. Getting the height or width returns the height or width of the
-   * first Element in this list. 
+   * first Element in this list.
    *
    * Unlike [getBoundingClientRect], the dimensions of this rectangle
    * will return the same numerical height if the element is hidden or not.
    */
   @Experimental()
   CssRect get contentEdge;
-  
+
   /**
    * Access dimensions and position of the first Element's content + padding box
    * in this list.
-   * 
+   *
    * This returns a rectangle with the dimenions actually available for content
-   * in this element, in pixels, regardless of this element's box-sizing 
+   * in this element, in pixels, regardless of this element's box-sizing
    * property. Unlike [getBoundingClientRect], the dimensions of this rectangle
    * will return the same numerical height if the element is hidden or not. This
    * can be used to retrieve jQuery's `innerHeight` value for an element. This
@@ -8023,9 +8031,9 @@
   /**
    * Access dimensions and position of the first Element's content + padding +
    * border box in this list.
-   * 
+   *
    * This returns a rectangle with the dimenions actually available for content
-   * in this element, in pixels, regardless of this element's box-sizing 
+   * in this element, in pixels, regardless of this element's box-sizing
    * property. Unlike [getBoundingClientRect], the dimensions of this rectangle
    * will return the same numerical height if the element is hidden or not. This
    * can be used to retrieve jQuery's `outerHeight` value for an element.
@@ -8036,9 +8044,9 @@
   /**
    * Access dimensions and position of the first Element's content + padding +
    * border + margin box in this list.
-   * 
+   *
    * This returns a rectangle with the dimenions actually available for content
-   * in this element, in pixels, regardless of this element's box-sizing 
+   * in this element, in pixels, regardless of this element's box-sizing
    * property. Unlike [getBoundingClientRect], the dimensions of this rectangle
    * will return the same numerical height if the element is hidden or not. This
    * can be used to retrieve jQuery's `outerHeight` value for an element.
@@ -8084,12 +8092,15 @@
 
   CssClassSet get classes => new _MultiElementCssClassSet(_elementList);
 
+  CssStyleDeclarationBase get style =>
+      new _CssStyleDeclarationSet(_elementList);
+
   void set classes(Iterable<String> value) {
     _elementList.forEach((e) => e.classes = value);
   }
 
   CssRect get contentEdge => new _ContentCssListRect(_elementList);
-  
+
   CssRect get paddingEdge => _elementList.first.paddingEdge;
 
   CssRect get borderEdge => _elementList.first.borderEdge;
@@ -8740,13 +8751,13 @@
   }
 
   /**
-   * Creates an instance of the template, using the provided model and binding
-   * delegate.
+   * Creates an instance of the template, using the provided model and optional
+   * binding delegate.
    *
    * This is only supported if [isTemplate] is true.
    */
   @Experimental()
-  DocumentFragment createInstance(model, BindingDelegate delegate) {
+  DocumentFragment createInstance(model, [BindingDelegate delegate]) {
     _ensureTemplate();
     return TemplateElement.mdvPackage(this).createInstance(model, delegate);
   }
@@ -8822,35 +8833,35 @@
 
   /**
    * Access this element's content position.
-   * 
+   *
    * This returns a rectangle with the dimenions actually available for content
-   * in this element, in pixels, regardless of this element's box-sizing 
+   * in this element, in pixels, regardless of this element's box-sizing
    * property. Unlike [getBoundingClientRect], the dimensions of this rectangle
    * will return the same numerical height if the element is hidden or not.
-   * 
+   *
    * _Important_ _note_: use of this method _will_ perform CSS calculations that
-   * can trigger a browser reflow. Therefore, use of this property _during_ an 
-   * animation frame is discouraged. See also: 
+   * can trigger a browser reflow. Therefore, use of this property _during_ an
+   * animation frame is discouraged. See also:
    * [Browser Reflow](https://developers.google.com/speed/articles/reflow)
    */
   @Experimental()
   CssRect get contentEdge => new _ContentCssRect(this);
-  
+
   /**
    * Access the dimensions and position of this element's content + padding box.
-   * 
+   *
    * This returns a rectangle with the dimenions actually available for content
-   * in this element, in pixels, regardless of this element's box-sizing 
+   * in this element, in pixels, regardless of this element's box-sizing
    * property. Unlike [getBoundingClientRect], the dimensions of this rectangle
    * will return the same numerical height if the element is hidden or not. This
    * can be used to retrieve jQuery's
-   * [innerHeight](http://api.jquery.com/innerHeight/) value for an element. 
+   * [innerHeight](http://api.jquery.com/innerHeight/) value for an element.
    * This is also a rectangle equalling the dimensions of clientHeight and
    * clientWidth.
-   * 
+   *
    * _Important_ _note_: use of this method _will_ perform CSS calculations that
-   * can trigger a browser reflow. Therefore, use of this property _during_ an 
-   * animation frame is discouraged. See also: 
+   * can trigger a browser reflow. Therefore, use of this property _during_ an
+   * animation frame is discouraged. See also:
    * [Browser Reflow](https://developers.google.com/speed/articles/reflow)
    */
   @Experimental()
@@ -8859,17 +8870,17 @@
   /**
    * Access the dimensions and position of this element's content + padding +
    * border box.
-   * 
+   *
    * This returns a rectangle with the dimenions actually available for content
-   * in this element, in pixels, regardless of this element's box-sizing 
+   * in this element, in pixels, regardless of this element's box-sizing
    * property. Unlike [getBoundingClientRect], the dimensions of this rectangle
    * will return the same numerical height if the element is hidden or not. This
    * can be used to retrieve jQuery's
    * [outerHeight](http://api.jquery.com/outerHeight/) value for an element.
-   * 
-   * _Important_ _note_: use of this method _will_ perform CSS calculations that 
-   * can trigger a browser reflow. Therefore, use of this property _during_ an 
-   * animation frame is discouraged. See also: 
+   *
+   * _Important_ _note_: use of this method _will_ perform CSS calculations that
+   * can trigger a browser reflow. Therefore, use of this property _during_ an
+   * animation frame is discouraged. See also:
    * [Browser Reflow](https://developers.google.com/speed/articles/reflow)
    */
   @Experimental()
@@ -8878,38 +8889,38 @@
   /**
    * Access the dimensions and position of this element's content + padding +
    * border + margin box.
-   * 
+   *
    * This returns a rectangle with the dimenions actually available for content
-   * in this element, in pixels, regardless of this element's box-sizing 
+   * in this element, in pixels, regardless of this element's box-sizing
    * property. Unlike [getBoundingClientRect], the dimensions of this rectangle
    * will return the same numerical height if the element is hidden or not. This
    * can be used to retrieve jQuery's
    * [outerHeight](http://api.jquery.com/outerHeight/) value for an element.
-   * 
+   *
    * _Important_ _note_: use of this method will perform CSS calculations that
-   * can trigger a browser reflow. Therefore, use of this property _during_ an 
-   * animation frame is discouraged. See also: 
+   * can trigger a browser reflow. Therefore, use of this property _during_ an
+   * animation frame is discouraged. See also:
    * [Browser Reflow](https://developers.google.com/speed/articles/reflow)
    */
   @Experimental()
   CssRect get marginEdge => new _MarginCssRect(this);
 
-  /** 
-   * Provides the coordinates of the element relative to the top of the 
-   * document. 
+  /**
+   * Provides the coordinates of the element relative to the top of the
+   * document.
    *
-   * This method is the Dart equivalent to jQuery's 
+   * This method is the Dart equivalent to jQuery's
    * [offset](http://api.jquery.com/offset/) method.
    */
   Point get documentOffset => offsetTo(document.documentElement);
 
-  /** 
+  /**
    * Provides the offset of this element's [borderEdge] relative to the
    * specified [parent].
-   * 
+   *
    * This is the Dart equivalent of jQuery's
    * [position](http://api.jquery.com/position/) method. Unlike jQuery's
-   * position, however, [parent] can be any parent element of `this`, 
+   * position, however, [parent] can be any parent element of `this`,
    * rather than only `this`'s immediate [offsetParent]. If the specified
    * element is _not_ an offset parent or transitive offset parent to this
    * element, an [ArgumentError] is thrown.
@@ -8920,7 +8931,7 @@
 
   static Point _offsetToHelper(Element current, Element parent) {
     // We're hopping from _offsetParent_ to offsetParent (not just parent), so
-    // offsetParent, "tops out" at BODY. But people could conceivably pass in 
+    // offsetParent, "tops out" at BODY. But people could conceivably pass in
     // the document.documentElement and I want it to return an absolute offset,
     // so we have the special case checking for HTML.
     bool foundAsParent = identical(current, parent) || parent.tagName == 'HTML';
@@ -8928,7 +8939,7 @@
       if (foundAsParent) return new Point(0, 0);
       throw new ArgumentError("Specified element is not a transitive offset "
           "parent of this element.");
-    } 
+    }
     Element parentOffset = current.offsetParent;
     Point p = Element._offsetToHelper(parentOffset, parent);
     return new Point(p.x + current.offsetLeft, p.y + current.offsetTop);
diff --git a/sdk/lib/html/dartium/html_dartium.dart b/sdk/lib/html/dartium/html_dartium.dart
index d667804..555a0d0 100644
--- a/sdk/lib/html/dartium/html_dartium.dart
+++ b/sdk/lib/html/dartium/html_dartium.dart
@@ -281,39 +281,6 @@
 
 
 @DocsEditable()
-@DomName('ANGLEInstancedArrays')
-@Experimental() // untriaged
-class AngleInstancedArrays extends NativeFieldWrapperClass1 {
-
-  @DomName('ANGLEInstancedArrays.VERTEX_ATTRIB_ARRAY_DIVISOR_ANGLE')
-  @DocsEditable()
-  @Experimental() // untriaged
-  static const int VERTEX_ATTRIB_ARRAY_DIVISOR_ANGLE = 0x88FE;
-
-  @DomName('ANGLEInstancedArrays.drawArraysInstancedANGLE')
-  @DocsEditable()
-  @Experimental() // untriaged
-  void drawArraysInstancedAngle(int mode, int first, int count, int primcount) native "ANGLEInstancedArrays_drawArraysInstancedANGLE_Callback";
-
-  @DomName('ANGLEInstancedArrays.drawElementsInstancedANGLE')
-  @DocsEditable()
-  @Experimental() // untriaged
-  void drawElementsInstancedAngle(int mode, int count, int type, int offset, int primcount) native "ANGLEInstancedArrays_drawElementsInstancedANGLE_Callback";
-
-  @DomName('ANGLEInstancedArrays.vertexAttribDivisorANGLE')
-  @DocsEditable()
-  @Experimental() // untriaged
-  void vertexAttribDivisorAngle(int index, int divisor) native "ANGLEInstancedArrays_vertexAttribDivisorANGLE_Callback";
-
-}
-// Copyright (c) 2012, 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.
-
-// WARNING: Do not edit - generated code.
-
-
-@DocsEditable()
 @DomName('WebKitAnimationEvent')
 @SupportedBrowser(SupportedBrowser.CHROME)
 @SupportedBrowser(SupportedBrowser.SAFARI)
@@ -3128,7 +3095,8 @@
 
 
 @DomName('CSSStyleDeclaration')
-class CssStyleDeclaration extends NativeFieldWrapperClass1 {
+ class CssStyleDeclaration  extends NativeFieldWrapperClass1 with 
+    CssStyleDeclarationBase  {
   factory CssStyleDeclaration() => new CssStyleDeclaration.css('');
 
   factory CssStyleDeclaration.css(String css) {
@@ -3136,7 +3104,24 @@
     style.cssText = css;
     return style;
   }
+  
+  String getPropertyValue(String propertyName) {
+    var propValue = _getPropertyValue(propertyName);
+    return propValue != null ? propValue : '';
+  }
 
+  @DomName('CSSStyleDeclaration.setProperty')
+  void setProperty(String propertyName, String value, [String priority]) {
+    if (priority == null) {
+      priority = '';
+    }
+    _setProperty(propertyName, value, priority);
+  }
+
+  /**
+   * Checks to see if CSS Transitions are supported.
+   */
+  static bool get supportsTransitions => true;
 
   @DomName('CSSStyleDeclaration.cssText')
   @DocsEditable()
@@ -3178,24 +3163,35 @@
   @DocsEditable()
   void _setProperty(String propertyName, String value, String priority) native "CSSStyleDeclaration_setProperty_Callback";
 
+}
 
-  String getPropertyValue(String propertyName) {
-    var propValue = _getPropertyValue(propertyName);
-    return propValue != null ? propValue : '';
+class _CssStyleDeclarationSet extends Object with CssStyleDeclarationBase {
+  final Iterable<Element> _elementIterable;
+  Iterable<CssStyleDeclaration> _elementCssStyleDeclarationSetIterable;
+
+  _CssStyleDeclarationSet(this._elementIterable) {
+    _elementCssStyleDeclarationSetIterable = new List.from(
+        _elementIterable).map((e) => e.style);
   }
 
-  /**
-   * Checks to see if CSS Transitions are supported.
-   */
-  static bool get supportsTransitions => true;
+  String getPropertyValue(String propertyName) =>
+      _elementCssStyleDeclarationSetIterable.first.getPropertyValue(
+          propertyName);
 
-  @DomName('CSSStyleDeclaration.setProperty')
   void setProperty(String propertyName, String value, [String priority]) {
-    if (priority == null) {
-      priority = '';
-    }
-    _setProperty(propertyName, value, priority);
+    _elementCssStyleDeclarationSetIterable.forEach((e) =>
+        e.setProperty(propertyName, value, priority));
   }
+  // Important note: CssStyleDeclarationSet does NOT implement every method
+  // available in CssStyleDeclaration. Some of the methods don't make so much
+  // sense in terms of having a resonable value to return when you're
+  // considering a list of Elements. You will need to manually add any of the
+  // items in the MEMBERS set if you want that functionality.
+}
+
+abstract class CssStyleDeclarationBase {
+  String getPropertyValue(String propertyName);  
+  void setProperty(String propertyName, String value, [String priority]);
 
   // TODO(jacobr): generate this list of properties using the existing script.
   /** Gets the value of "align-content" */
@@ -8487,7 +8483,7 @@
 
 /**
  * An immutable list containing HTML elements. This list contains some
- * additional methods when compared to regular lists for ease of CSS 
+ * additional methods when compared to regular lists for ease of CSS
  * manipulation on a group of elements.
  */
 abstract class ElementList<T extends Element> extends ListBase<T> {
@@ -8506,28 +8502,40 @@
   /** Replace the classes with `value` for every element in this list. */
   set classes(Iterable<String> value);
 
-  /** 
+  /**
+   * Access the union of all [CssStyleDeclaration]s that are associated with an
+   * [ElementList].
+   *
+   * Grouping the style objects all together provides easy editing of specific
+   * properties of a collection of elements. Setting a specific property value
+   * will set that property in all [Element]s in the [ElementList]. Getting a
+   * specific property value will return the value of the property of the first
+   * element in the [ElementList].
+   */
+  CssStyleDeclarationBase get style;
+
+  /**
    * Access dimensions and position of the Elements in this list.
-   * 
+   *
    * Setting the height or width properties will set the height or width
-   * property for all elements in the list. This returns a rectangle with the 
+   * property for all elements in the list. This returns a rectangle with the
    * dimenions actually available for content
-   * in this element, in pixels, regardless of this element's box-sizing 
+   * in this element, in pixels, regardless of this element's box-sizing
    * property. Getting the height or width returns the height or width of the
-   * first Element in this list. 
+   * first Element in this list.
    *
    * Unlike [getBoundingClientRect], the dimensions of this rectangle
    * will return the same numerical height if the element is hidden or not.
    */
   @Experimental()
   CssRect get contentEdge;
-  
+
   /**
    * Access dimensions and position of the first Element's content + padding box
    * in this list.
-   * 
+   *
    * This returns a rectangle with the dimenions actually available for content
-   * in this element, in pixels, regardless of this element's box-sizing 
+   * in this element, in pixels, regardless of this element's box-sizing
    * property. Unlike [getBoundingClientRect], the dimensions of this rectangle
    * will return the same numerical height if the element is hidden or not. This
    * can be used to retrieve jQuery's `innerHeight` value for an element. This
@@ -8540,9 +8548,9 @@
   /**
    * Access dimensions and position of the first Element's content + padding +
    * border box in this list.
-   * 
+   *
    * This returns a rectangle with the dimenions actually available for content
-   * in this element, in pixels, regardless of this element's box-sizing 
+   * in this element, in pixels, regardless of this element's box-sizing
    * property. Unlike [getBoundingClientRect], the dimensions of this rectangle
    * will return the same numerical height if the element is hidden or not. This
    * can be used to retrieve jQuery's `outerHeight` value for an element.
@@ -8553,9 +8561,9 @@
   /**
    * Access dimensions and position of the first Element's content + padding +
    * border + margin box in this list.
-   * 
+   *
    * This returns a rectangle with the dimenions actually available for content
-   * in this element, in pixels, regardless of this element's box-sizing 
+   * in this element, in pixels, regardless of this element's box-sizing
    * property. Unlike [getBoundingClientRect], the dimensions of this rectangle
    * will return the same numerical height if the element is hidden or not. This
    * can be used to retrieve jQuery's `outerHeight` value for an element.
@@ -8601,12 +8609,15 @@
 
   CssClassSet get classes => new _MultiElementCssClassSet(_elementList);
 
+  CssStyleDeclarationBase get style =>
+      new _CssStyleDeclarationSet(_elementList);
+
   void set classes(Iterable<String> value) {
     _elementList.forEach((e) => e.classes = value);
   }
 
   CssRect get contentEdge => new _ContentCssListRect(_elementList);
-  
+
   CssRect get paddingEdge => _elementList.first.paddingEdge;
 
   CssRect get borderEdge => _elementList.first.borderEdge;
@@ -9108,13 +9119,13 @@
   }
 
   /**
-   * Creates an instance of the template, using the provided model and binding
-   * delegate.
+   * Creates an instance of the template, using the provided model and optional
+   * binding delegate.
    *
    * This is only supported if [isTemplate] is true.
    */
   @Experimental()
-  DocumentFragment createInstance(model, BindingDelegate delegate) {
+  DocumentFragment createInstance(model, [BindingDelegate delegate]) {
     _ensureTemplate();
     return TemplateElement.mdvPackage(this).createInstance(model, delegate);
   }
@@ -9190,35 +9201,35 @@
 
   /**
    * Access this element's content position.
-   * 
+   *
    * This returns a rectangle with the dimenions actually available for content
-   * in this element, in pixels, regardless of this element's box-sizing 
+   * in this element, in pixels, regardless of this element's box-sizing
    * property. Unlike [getBoundingClientRect], the dimensions of this rectangle
    * will return the same numerical height if the element is hidden or not.
-   * 
+   *
    * _Important_ _note_: use of this method _will_ perform CSS calculations that
-   * can trigger a browser reflow. Therefore, use of this property _during_ an 
-   * animation frame is discouraged. See also: 
+   * can trigger a browser reflow. Therefore, use of this property _during_ an
+   * animation frame is discouraged. See also:
    * [Browser Reflow](https://developers.google.com/speed/articles/reflow)
    */
   @Experimental()
   CssRect get contentEdge => new _ContentCssRect(this);
-  
+
   /**
    * Access the dimensions and position of this element's content + padding box.
-   * 
+   *
    * This returns a rectangle with the dimenions actually available for content
-   * in this element, in pixels, regardless of this element's box-sizing 
+   * in this element, in pixels, regardless of this element's box-sizing
    * property. Unlike [getBoundingClientRect], the dimensions of this rectangle
    * will return the same numerical height if the element is hidden or not. This
    * can be used to retrieve jQuery's
-   * [innerHeight](http://api.jquery.com/innerHeight/) value for an element. 
+   * [innerHeight](http://api.jquery.com/innerHeight/) value for an element.
    * This is also a rectangle equalling the dimensions of clientHeight and
    * clientWidth.
-   * 
+   *
    * _Important_ _note_: use of this method _will_ perform CSS calculations that
-   * can trigger a browser reflow. Therefore, use of this property _during_ an 
-   * animation frame is discouraged. See also: 
+   * can trigger a browser reflow. Therefore, use of this property _during_ an
+   * animation frame is discouraged. See also:
    * [Browser Reflow](https://developers.google.com/speed/articles/reflow)
    */
   @Experimental()
@@ -9227,17 +9238,17 @@
   /**
    * Access the dimensions and position of this element's content + padding +
    * border box.
-   * 
+   *
    * This returns a rectangle with the dimenions actually available for content
-   * in this element, in pixels, regardless of this element's box-sizing 
+   * in this element, in pixels, regardless of this element's box-sizing
    * property. Unlike [getBoundingClientRect], the dimensions of this rectangle
    * will return the same numerical height if the element is hidden or not. This
    * can be used to retrieve jQuery's
    * [outerHeight](http://api.jquery.com/outerHeight/) value for an element.
-   * 
-   * _Important_ _note_: use of this method _will_ perform CSS calculations that 
-   * can trigger a browser reflow. Therefore, use of this property _during_ an 
-   * animation frame is discouraged. See also: 
+   *
+   * _Important_ _note_: use of this method _will_ perform CSS calculations that
+   * can trigger a browser reflow. Therefore, use of this property _during_ an
+   * animation frame is discouraged. See also:
    * [Browser Reflow](https://developers.google.com/speed/articles/reflow)
    */
   @Experimental()
@@ -9246,38 +9257,38 @@
   /**
    * Access the dimensions and position of this element's content + padding +
    * border + margin box.
-   * 
+   *
    * This returns a rectangle with the dimenions actually available for content
-   * in this element, in pixels, regardless of this element's box-sizing 
+   * in this element, in pixels, regardless of this element's box-sizing
    * property. Unlike [getBoundingClientRect], the dimensions of this rectangle
    * will return the same numerical height if the element is hidden or not. This
    * can be used to retrieve jQuery's
    * [outerHeight](http://api.jquery.com/outerHeight/) value for an element.
-   * 
+   *
    * _Important_ _note_: use of this method will perform CSS calculations that
-   * can trigger a browser reflow. Therefore, use of this property _during_ an 
-   * animation frame is discouraged. See also: 
+   * can trigger a browser reflow. Therefore, use of this property _during_ an
+   * animation frame is discouraged. See also:
    * [Browser Reflow](https://developers.google.com/speed/articles/reflow)
    */
   @Experimental()
   CssRect get marginEdge => new _MarginCssRect(this);
 
-  /** 
-   * Provides the coordinates of the element relative to the top of the 
-   * document. 
+  /**
+   * Provides the coordinates of the element relative to the top of the
+   * document.
    *
-   * This method is the Dart equivalent to jQuery's 
+   * This method is the Dart equivalent to jQuery's
    * [offset](http://api.jquery.com/offset/) method.
    */
   Point get documentOffset => offsetTo(document.documentElement);
 
-  /** 
+  /**
    * Provides the offset of this element's [borderEdge] relative to the
    * specified [parent].
-   * 
+   *
    * This is the Dart equivalent of jQuery's
    * [position](http://api.jquery.com/position/) method. Unlike jQuery's
-   * position, however, [parent] can be any parent element of `this`, 
+   * position, however, [parent] can be any parent element of `this`,
    * rather than only `this`'s immediate [offsetParent]. If the specified
    * element is _not_ an offset parent or transitive offset parent to this
    * element, an [ArgumentError] is thrown.
@@ -9288,7 +9299,7 @@
 
   static Point _offsetToHelper(Element current, Element parent) {
     // We're hopping from _offsetParent_ to offsetParent (not just parent), so
-    // offsetParent, "tops out" at BODY. But people could conceivably pass in 
+    // offsetParent, "tops out" at BODY. But people could conceivably pass in
     // the document.documentElement and I want it to return an absolute offset,
     // so we have the special case checking for HTML.
     bool foundAsParent = identical(current, parent) || parent.tagName == 'HTML';
@@ -9296,7 +9307,7 @@
       if (foundAsParent) return new Point(0, 0);
       throw new ArgumentError("Specified element is not a transitive offset "
           "parent of this element.");
-    } 
+    }
     Element parentOffset = current.offsetParent;
     Point p = Element._offsetToHelper(parentOffset, parent);
     return new Point(p.x + current.offsetLeft, p.y + current.offsetTop);
diff --git a/sdk/lib/io/directory_impl.dart b/sdk/lib/io/directory_impl.dart
index 5429a29..17d67be 100644
--- a/sdk/lib/io/directory_impl.dart
+++ b/sdk/lib/io/directory_impl.dart
@@ -14,7 +14,16 @@
   static const LIST_STOP_REQUEST = 6;
   static const RENAME_REQUEST = 7;
 
-  _Directory(String this._path);
+  final String path;
+  SendPort _directoryService;
+
+  _Directory(String this.path) {
+    if (path is! String) {
+      throw new ArgumentError('${Error.safeToString(path)} '
+                              'is not a String');
+    }
+  }
+
   _Directory.fromPath(Path path) : this(path.toNativePath());
 
   external static String _current();
@@ -43,7 +52,7 @@
     _ensureDirectoryService();
     List request = new List(2);
     request[0] = EXISTS_REQUEST;
-    request[1] = _path;
+    request[1] = path;
     return _directoryService.call(request).then((response) {
       if (_isErrorResponse(response)) {
         throw _exceptionOrErrorFromResponse(response, "Exists failed");
@@ -53,12 +62,9 @@
   }
 
   bool existsSync() {
-    if (_path is !String) {
-      throw new ArgumentError();
-    }
-    var result = _exists(_path);
+    var result = _exists(path);
     if (result is OSError) {
-      throw new DirectoryException("Exists failed", _path, result);
+      throw new DirectoryException("Exists failed", path, result);
     }
     return (result == 1);
   }
@@ -92,10 +98,7 @@
   }
 
   Future<Directory> createRecursively() {
-    if (_path is !String) {
-      throw new ArgumentError();
-    }
-    var path = new Path(_path);
+    var path = new Path(path);
     var dirsToCreate = [];
     var terminator = path.isAbsolute ? '/' : '';
     while (path.toString() != terminator) {
@@ -126,7 +129,7 @@
     _ensureDirectoryService();
     List request = new List(2);
     request[0] = CREATE_REQUEST;
-    request[1] = _path;
+    request[1] = path;
     return _directoryService.call(request).then((response) {
       if (_isErrorResponse(response)) {
         throw _exceptionOrErrorFromResponse(response, "Creation failed");
@@ -136,7 +139,7 @@
   }
 
   void createRecursivelySync() {
-    var path = new Path(_path);
+    var path = new Path(path);
     var dirsToCreate = [];
     var terminator = path.isAbsolute ? '/' : '';
     while (path.toString() != terminator) {
@@ -151,13 +154,10 @@
   }
 
   void createSync({recursive: false}) {
-    if (_path is !String) {
-      throw new ArgumentError();
-    }
     if (recursive) return createRecursivelySync();
-    var result = _create(_path);
+    var result = _create(path);
     if (result is OSError) {
-      throw new DirectoryException("Creation failed", _path, result);
+      throw new DirectoryException("Creation failed", path, result);
     }
   }
 
@@ -165,7 +165,7 @@
     _ensureDirectoryService();
     List request = new List(2);
     request[0] = CREATE_TEMP_REQUEST;
-    request[1] = _path;
+    request[1] = path;
     return _directoryService.call(request).then((response) {
       if (_isErrorResponse(response)) {
         throw _exceptionOrErrorFromResponse(
@@ -176,13 +176,10 @@
   }
 
   Directory createTempSync() {
-    if (_path is !String) {
-      throw new ArgumentError();
-    }
     var result = _createTemp(path);
     if (result is OSError) {
       throw new DirectoryException("Creation of temporary directory failed",
-                                   _path,
+                                   path,
                                    result);
     }
     return new Directory(result);
@@ -192,7 +189,7 @@
     _ensureDirectoryService();
     List request = new List(3);
     request[0] = DELETE_REQUEST;
-    request[1] = _path;
+    request[1] = path;
     request[2] = recursive;
     return _directoryService.call(request).then((response) {
       if (_isErrorResponse(response)) {
@@ -203,12 +200,9 @@
   }
 
   void deleteSync({recursive: false}) {
-    if (_path is !String) {
-      throw new ArgumentError();
-    }
-    var result = _delete(_path, recursive);
+    var result = _delete(path, recursive);
     if (result is OSError) {
-      throw new DirectoryException("Deletion failed", _path, result);
+      throw new DirectoryException("Deletion failed", path, result);
     }
   }
 
@@ -216,7 +210,7 @@
     _ensureDirectoryService();
     List request = new List(3);
     request[0] = RENAME_REQUEST;
-    request[1] = _path;
+    request[1] = path;
     request[2] = newPath;
     return _directoryService.call(request).then((response) {
       if (_isErrorResponse(response)) {
@@ -227,12 +221,12 @@
   }
 
   Directory renameSync(String newPath) {
-    if (_path is !String || newPath is !String) {
+    if (newPath is !String) {
       throw new ArgumentError();
     }
-    var result = _rename(_path, newPath);
+    var result = _rename(path, newPath);
     if (result is OSError) {
-      throw new DirectoryException("Rename failed", _path, result);
+      throw new DirectoryException("Rename failed", path, result);
     }
     return new Directory(newPath);
   }
@@ -262,14 +256,12 @@
   }
 
   List listSync({bool recursive: false, bool followLinks: true}) {
-    if (_path is! String || recursive is! bool || followLinks is! bool) {
+    if (recursive is! bool || followLinks is! bool) {
       throw new ArgumentError();
     }
     return _list(_trimTrailingPathSeparators(path), recursive, followLinks);
   }
 
-  String get path => _path;
-
   String toString() => "Directory: '$path'";
 
   bool _isErrorResponse(response) {
@@ -284,7 +276,7 @@
       case _OSERROR_RESPONSE:
         var err = new OSError(response[_OSERROR_RESPONSE_MESSAGE],
                               response[_OSERROR_RESPONSE_ERROR_CODE]);
-        return new DirectoryException(message, _path, err);
+        return new DirectoryException(message, path, err);
       default:
         return new Exception("Unknown error");
     }
@@ -295,9 +287,6 @@
       _directoryService = _newServicePort();
     }
   }
-
-  final String _path;
-  SendPort _directoryService;
 }
 
 class _AsyncDirectoryLister {
diff --git a/sdk/lib/io/file_impl.dart b/sdk/lib/io/file_impl.dart
index 0789990..b6a47c79 100644
--- a/sdk/lib/io/file_impl.dart
+++ b/sdk/lib/io/file_impl.dart
@@ -235,10 +235,13 @@
 
 // Class for encapsulating the native implementation of files.
 class _File implements File {
+  final String path;
+  SendPort _fileService;
+
   // Constructor for file.
-  _File(String this._path) {
-    if (_path is! String) {
-      throw new ArgumentError('${Error.safeToString(_path)} '
+  _File(String this.path) {
+    if (path is! String) {
+      throw new ArgumentError('${Error.safeToString(path)} '
                               'is not a String');
     }
   }
@@ -250,10 +253,10 @@
     _ensureFileService();
     List request = new List(2);
     request[0] = _EXISTS_REQUEST;
-    request[1] = _path;
+    request[1] = path;
     return _fileService.call(request).then((response) {
       if (_isErrorResponse(response)) {
-        throw _exceptionFromResponse(response, "Cannot check existence", _path);
+        throw _exceptionFromResponse(response, "Cannot check existence", path);
       }
       return response;
     });
@@ -262,8 +265,8 @@
   external static _exists(String path);
 
   bool existsSync() {
-    var result = _exists(_path);
-    throwIfError(result, "Cannot check existence of file", _path);
+    var result = _exists(path);
+    throwIfError(result, "Cannot check existence of file", path);
     return result;
   }
 
@@ -275,10 +278,10 @@
     _ensureFileService();
     List request = new List(2);
     request[0] = _CREATE_REQUEST;
-    request[1] = _path;
+    request[1] = path;
     return _fileService.call(request).then((response) {
       if (_isErrorResponse(response)) {
-        throw _exceptionFromResponse(response, "Cannot create file", _path);
+        throw _exceptionFromResponse(response, "Cannot create file", path);
       }
       return this;
     });
@@ -291,18 +294,18 @@
   external static _linkTarget(String path);
 
   void createSync() {
-    var result = _create(_path);
-    throwIfError(result, "Cannot create file", _path);
+    var result = _create(path);
+    throwIfError(result, "Cannot create file", path);
   }
 
   Future<File> delete() {
     _ensureFileService();
     List request = new List(2);
     request[0] = _DELETE_REQUEST;
-    request[1] = _path;
+    request[1] = path;
     return _fileService.call(request).then((response) {
       if (_isErrorResponse(response)) {
-        throw _exceptionFromResponse(response, "Cannot delete file", _path);
+        throw _exceptionFromResponse(response, "Cannot delete file", path);
       }
       return this;
     });
@@ -313,20 +316,20 @@
   external static _deleteLink(String path);
 
   void deleteSync() {
-    var result = _delete(_path);
-    throwIfError(result, "Cannot delete file", _path);
+    var result = _delete(path);
+    throwIfError(result, "Cannot delete file", path);
   }
 
   Future<File> rename(String newPath) {
     _ensureFileService();
     List request = new List(3);
     request[0] = _RENAME_REQUEST;
-    request[1] = _path;
+    request[1] = path;
     request[2] = newPath;
     return _fileService.call(request).then((response) {
       if (_isErrorResponse(response)) {
         throw _exceptionFromResponse(
-            response, "Cannot rename file to '$newPath'", _path);
+            response, "Cannot rename file to '$newPath'", path);
       }
       return new File(newPath);
     });
@@ -337,13 +340,13 @@
   external static _renameLink(String oldPath, String newPath);
 
   File renameSync(String newPath) {
-    var result = _rename(_path, newPath);
-    throwIfError(result, "Cannot rename file to '$newPath'", _path);
+    var result = _rename(path, newPath);
+    throwIfError(result, "Cannot rename file to '$newPath'", path);
     return new File(newPath);
   }
 
   Directory get directory {
-    Path path = new Path(_path).directoryPath;
+    Path path = new Path(path).directoryPath;
     return new Directory.fromPath(path);
   }
 
@@ -356,13 +359,13 @@
     }
     List request = new List(3);
     request[0] = _OPEN_REQUEST;
-    request[1] = _path;
+    request[1] = path;
     request[2] = mode._mode;  // Direct int value for serialization.
     return _fileService.call(request).then((response) {
       if (_isErrorResponse(response)) {
-        throw _exceptionFromResponse(response, "Cannot open file", _path);
+        throw _exceptionFromResponse(response, "Cannot open file", path);
       }
-      return new _RandomAccessFile(response, _path);
+      return new _RandomAccessFile(response, path);
     });
   }
 
@@ -370,12 +373,12 @@
     _ensureFileService();
     List request = new List(2);
     request[0] = _LENGTH_FROM_PATH_REQUEST;
-    request[1] = _path;
+    request[1] = path;
     return _fileService.call(request).then((response) {
       if (_isErrorResponse(response)) {
         throw _exceptionFromResponse(response,
                                      "Cannot retrieve length of file",
-                                     _path);
+                                     path);
       }
       return response;
     });
@@ -385,8 +388,8 @@
   external static _lengthFromPath(String path);
 
   int lengthSync() {
-    var result = _lengthFromPath(_path);
-    throwIfError(result, "Cannot retrieve length of file", _path);
+    var result = _lengthFromPath(path);
+    throwIfError(result, "Cannot retrieve length of file", path);
     return result;
   }
 
@@ -394,12 +397,12 @@
     _ensureFileService();
     List request = new List(2);
     request[0] = _LAST_MODIFIED_REQUEST;
-    request[1] = _path;
+    request[1] = path;
     return _fileService.call(request).then((response) {
       if (_isErrorResponse(response)) {
         throw _exceptionFromResponse(response,
                                      "Cannot retrieve modification time",
-                                     _path);
+                                     path);
       }
       return new DateTime.fromMillisecondsSinceEpoch(response);
     });
@@ -409,7 +412,7 @@
 
   DateTime lastModifiedSync() {
     var ms = _lastModified(path);
-    throwIfError(ms, "Cannot retrieve modification time", _path);
+    throwIfError(ms, "Cannot retrieve modification time", path);
     return new DateTime.fromMillisecondsSinceEpoch(ms);
   }
 
@@ -421,11 +424,11 @@
         mode != FileMode.APPEND) {
       throw new FileException("Unknown file mode. Use FileMode.READ, "
                               "FileMode.WRITE or FileMode.APPEND.",
-                              _path);
+                              path);
     }
-    var id = _open(_path, mode._mode);
-    throwIfError(id, "Cannot open file", _path);
-    return new _RandomAccessFile(id, _path);
+    var id = _open(path, mode._mode);
+    throwIfError(id, "Cannot open file", path);
+    return new _RandomAccessFile(id, path);
   }
 
   external static int _openStdio(int fd);
@@ -442,12 +445,12 @@
     _ensureFileService();
     List request = new List(2);
     request[0] = _FULL_PATH_REQUEST;
-    request[1] = _path;
+    request[1] = path;
     return _fileService.call(request).then((response) {
       if (_isErrorResponse(response)) {
         throw _exceptionFromResponse(response,
                                      "Cannot retrieve full path",
-                                     _path);
+                                     path);
       }
       return response;
     });
@@ -456,13 +459,13 @@
   external static _fullPath(String path);
 
   String fullPathSync() {
-    var result = _fullPath(_path);
-    throwIfError(result, "Cannot retrieve full path", _path);
+    var result = _fullPath(path);
+    throwIfError(result, "Cannot retrieve full path", path);
     return result;
   }
 
   Stream<List<int>> openRead([int start, int end]) {
-    return new _FileStream(_path, start, end);
+    return new _FileStream(path, start, end);
   }
 
   IOSink openWrite({FileMode mode: FileMode.WRITE,
@@ -573,8 +576,6 @@
     writeAsBytesSync(_encodeString(contents, encoding), mode: mode);
   }
 
-  String get path => _path;
-
   String toString() => "File: '$path'";
 
   void _ensureFileService() {
@@ -588,15 +589,15 @@
       throw new FileException(msg, path, result);
     }
   }
-
-  final String _path;
-
-  SendPort _fileService;
 }
 
 
 class _RandomAccessFile implements RandomAccessFile {
-  _RandomAccessFile(int this._id, String this._path);
+  final String path;
+  int _id;
+  SendPort _fileService;
+
+  _RandomAccessFile(int this._id, String this.path);
 
   Future<RandomAccessFile> close() {
     if (closed) return _closedException();
@@ -612,7 +613,7 @@
         _id = result;
         return this;
       } else {
-        throw new FileException("Cannot close file", _path);
+        throw new FileException("Cannot close file", path);
       }
     });
   }
@@ -623,7 +624,7 @@
     _checkNotClosed();
     var id = _close(_id);
     if (id == -1) {
-      throw new FileException("Cannot close file", _path);
+      throw new FileException("Cannot close file", path);
     }
     _id = id;
   }
@@ -636,7 +637,7 @@
     request[1] = _id;
     return _fileService.call(request).then((response) {
       if (_isErrorResponse(response)) {
-        throw _exceptionFromResponse(response, "readByte failed", _path);
+        throw _exceptionFromResponse(response, "readByte failed", path);
       }
       return response;
     });
@@ -648,7 +649,7 @@
     _checkNotClosed();
     var result = _readByte(_id);
     if (result is OSError) {
-      throw new FileException("readByte failed", _path, result);
+      throw new FileException("readByte failed", path, result);
     }
     return result;
   }
@@ -665,7 +666,7 @@
     request[2] = bytes;
     return _fileService.call(request).then((response) {
       if (_isErrorResponse(response)) {
-        throw _exceptionFromResponse(response, "read failed", _path);
+        throw _exceptionFromResponse(response, "read failed", path);
       }
       return response[1];
     });
@@ -680,7 +681,7 @@
     }
     var result = _read(_id, bytes);
     if (result is OSError) {
-      throw new FileException("readSync failed",_path, result);
+      throw new FileException("readSync failed", path, result);
     }
     return result;
   }
@@ -701,7 +702,7 @@
     request[2] = end - start;
     return _fileService.call(request).then((response) {
       if (_isErrorResponse(response)) {
-        throw _exceptionFromResponse(response, "readInto failed", _path);
+        throw _exceptionFromResponse(response, "readInto failed", path);
       }
       var read = response[1];
       var data = response[2];
@@ -733,7 +734,7 @@
     _checkReadWriteListArguments(buffer.length, start, end);
     var result = _readInto(_id, buffer, start, end);
     if (result is OSError) {
-      throw new FileException("readInto failed", _path, result);
+      throw new FileException("readInto failed", path, result);
     }
     return result;
   }
@@ -750,7 +751,7 @@
     request[2] = value;
     return _fileService.call(request).then((response) {
       if (_isErrorResponse(response)) {
-        throw _exceptionFromResponse(response, "writeByte failed",_path);
+        throw _exceptionFromResponse(response, "writeByte failed", path);
       }
       return this;
     });
@@ -765,7 +766,7 @@
     }
     var result = _writeByte(_id, value);
     if (result is OSError) {
-      throw new FileException("writeByte failed", _path, result);
+      throw new FileException("writeByte failed", path, result);
     }
     return result;
   }
@@ -795,7 +796,7 @@
     request[4] = end - (start - result.start);
     return _fileService.call(request).then((response) {
       if (_isErrorResponse(response)) {
-        throw _exceptionFromResponse(response, "writeFrom failed", _path);
+        throw _exceptionFromResponse(response, "writeFrom failed", path);
       }
       return this;
     });
@@ -821,7 +822,7 @@
                             bufferAndStart.start,
                             end - (start - bufferAndStart.start));
     if (result is OSError) {
-      throw new FileException("writeFrom failed", _path, result);
+      throw new FileException("writeFrom failed", path, result);
     }
   }
 
@@ -850,7 +851,7 @@
     request[1] = _id;
     return _fileService.call(request).then((response) {
       if (_isErrorResponse(response)) {
-        throw _exceptionFromResponse(response, "position failed", _path);
+        throw _exceptionFromResponse(response, "position failed", path);
       }
       return response;
     });
@@ -862,7 +863,7 @@
     _checkNotClosed();
     var result = _position(_id);
     if (result is OSError) {
-      throw new FileException("position failed", _path, result);
+      throw new FileException("position failed", path, result);
     }
     return result;
   }
@@ -876,7 +877,7 @@
     request[2] = position;
     return _fileService.call(request).then((response) {
       if (_isErrorResponse(response)) {
-        throw _exceptionFromResponse(response, "setPosition failed", _path);
+        throw _exceptionFromResponse(response, "setPosition failed", path);
       }
       return this;
     });
@@ -888,7 +889,7 @@
     _checkNotClosed();
     var result = _setPosition(_id, position);
     if (result is OSError) {
-      throw new FileException("setPosition failed", _path, result);
+      throw new FileException("setPosition failed", path, result);
     }
   }
 
@@ -901,7 +902,7 @@
     request[2] = length;
     return _fileService.call(request).then((response) {
       if (_isErrorResponse(response)) {
-        throw _exceptionFromResponse(response, "truncate failed", _path);
+        throw _exceptionFromResponse(response, "truncate failed", path);
       }
       return this;
     });
@@ -913,7 +914,7 @@
     _checkNotClosed();
     var result = _truncate(_id, length);
     if (result is OSError) {
-      throw new FileException("truncate failed", _path, result);
+      throw new FileException("truncate failed", path, result);
     }
   }
 
@@ -925,7 +926,7 @@
     request[1] = _id;
     return _fileService.call(request).then((response) {
       if (_isErrorResponse(response)) {
-        throw _exceptionFromResponse(response, "length failed", _path);
+        throw _exceptionFromResponse(response, "length failed", path);
       }
       return response;
     });
@@ -937,7 +938,7 @@
     _checkNotClosed();
     var result = _length(_id);
     if (result is OSError) {
-      throw new FileException("length failed", _path, result);
+      throw new FileException("length failed", path, result);
     }
     return result;
   }
@@ -952,7 +953,7 @@
       if (_isErrorResponse(response)) {
         throw _exceptionFromResponse(response,
                                      "flush failed",
-                                     _path);
+                                     path);
       }
       return this;
     });
@@ -964,12 +965,10 @@
     _checkNotClosed();
     var result = _flush(_id);
     if (result is OSError) {
-      throw new FileException("flush failed", _path, result);
+      throw new FileException("flush failed", path, result);
     }
   }
 
-  String get path => _path;
-
   void _ensureFileService() {
     if (_fileService == null) {
       _fileService = _FileUtils._newServicePort();
@@ -980,16 +979,11 @@
 
   void _checkNotClosed() {
     if (closed) {
-      throw new FileException("File closed", _path);
+      throw new FileException("File closed", path);
     }
   }
 
   Future _closedException() {
-    return new Future.error(new FileException("File closed", _path));
+    return new Future.error(new FileException("File closed", path));
   }
-
-  final String _path;
-  int _id;
-
-  SendPort _fileService;
 }
diff --git a/sdk/lib/io/http.dart b/sdk/lib/io/http.dart
index 6764ab2..755c96c 100644
--- a/sdk/lib/io/http.dart
+++ b/sdk/lib/io/http.dart
@@ -497,7 +497,7 @@
  */
 abstract class HeaderValue {
   /**
-   * Creates a new header value object setting the value part.
+   * Creates a new header value object setting the value and parameters.
    */
   factory HeaderValue([String value = "", Map<String, String> parameters]) {
     return new _HeaderValue(value, parameters);
@@ -519,6 +519,9 @@
 
   /**
    * Gets the map of parameters.
+   *
+   * This map cannot be modified. invoking any operation which would
+   * modify the map will throw [UnsupportedError].
    */
   Map<String, String> get parameters;
 
@@ -940,12 +943,21 @@
   factory HttpClient() => new _HttpClient();
 
   /**
-   * Opens a HTTP connection. The returned [HttpClientRequest] is used to
-   * fill in the content of the request before sending it. The 'host' header for
-   * the request will be set to the value [host]:[port]. This can be overridden
-   * through the [HttpClientRequest] interface before the request is sent.
-   * NOTE if [host] is an IP address this will still be set in the 'host'
+   * Opens a HTTP connection.
+   *
+   * The HTTP method to use is specified in [method], the server is
+   * specified using [host] and [port], and the path (including
+   * possible fragment and query) is specified using [path].
+   *
+   * The `Host` header for the request will be set to the value
+   * [host]:[port]. This can be overridden through the
+   * [HttpClientRequest] interface before the request is sent.  NOTE
+   * if [host] is an IP address this will still be set in the `Host`
    * header.
+   *
+   * For additional information on the sequence of events during an
+   * HTTP transaction, and the objects returned by the futures, see
+   * the overall documentation for the class [HttpClient].
    */
   Future<HttpClientRequest> open(String method,
                                  String host,
@@ -953,36 +965,60 @@
                                  String path);
 
   /**
-   * Opens a HTTP connection. The returned [HttpClientRequest] is used to
-   * fill in the content of the request before sending it. The 'hosth header for
-   * the request will be set to the value [host]:[port]. This can be overridden
-   * through the [HttpClientRequest] interface before the request is sent.
-   * NOTE if [host] is an IP address this will still be set in the 'host'
+   * Opens a HTTP connection.
+   *
+   * The HTTP method is specified in [method] and the URL to use in
+   * [url].
+   *
+   * The `Host` header for the request will be set to the value
+   * [host]:[port]. This can be overridden through the
+   * [HttpClientRequest] interface before the request is sent.  NOTE
+   * if [host] is an IP address this will still be set in the `Host`
    * header.
+   *
+   * For additional information on the sequence of events during an
+   * HTTP transaction, and the objects returned by the futures, see
+   * the overall documentation for the class [HttpClient].
    */
   Future<HttpClientRequest> openUrl(String method, Uri url);
 
   /**
-   * Opens a HTTP connection using the GET method. See [open] for
-   * details. Using this method to open a HTTP connection will set the
-   * content length to 0.
+   * Opens a HTTP connection using the GET method.
+   *
+   * The server is specified using [host] and [port], and the path
+   * (including possible fragment and query) is specified using
+   * [path].
+   *
+   * See [open] for details.
    */
   Future<HttpClientRequest> get(String host, int port, String path);
 
   /**
-   * Opens a HTTP connection using the GET method. See [openUrl] for
-   * details. Using this method to open a HTTP connection will set the
-   * content length to 0.
+   * Opens a HTTP connection using the GET method.
+   *
+   * The URL to use is specified in [url].
+   *
+   * See [openUrl] for details.
    */
   Future<HttpClientRequest> getUrl(Uri url);
 
   /**
-   * Opens a HTTP connection using the POST method. See [open] for details.
+   * Opens a HTTP connection using the POST method.
+   *
+   * The server is specified using [host] and [port], and the path
+   * (including possible fragment and query) is specified using
+   * [path].
+   *
+   * See [open] for details.
    */
   Future<HttpClientRequest> post(String host, int port, String path);
 
   /**
-   * Opens a HTTP connection using the POST method. See [openUrl] for details.
+   * Opens a HTTP connection using the POST method.
+   *
+   * The URL to use is specified in [url].
+   *
+   * See [openUrl] for details.
    */
   Future<HttpClientRequest> postUrl(Uri url);
 
diff --git a/sdk/lib/io/http_headers.dart b/sdk/lib/io/http_headers.dart
index eec66c6..b355aa0 100644
--- a/sdk/lib/io/http_headers.dart
+++ b/sdk/lib/io/http_headers.dart
@@ -473,9 +473,14 @@
 
 class _HeaderValue implements HeaderValue {
   String _value;
-  Map<String, String> _parameters;
+  _UnmodifiableMap<String, String> _parameters;
 
-  _HeaderValue([String this._value = "", this._parameters]);
+  _HeaderValue([String this._value = "", Map<String, String> parameters]) {
+    if (parameters != null) {
+      _parameters =
+          new _UnmodifiableMap(new Map<String, String>.from(parameters));
+    }
+  }
 
   static _HeaderValue parse(String value, {parameterSeparator: ";"}) {
     // Parse the string.
@@ -486,8 +491,14 @@
 
   String get value => _value;
 
+  void _ensureParameters() {
+    if (_parameters == null) {
+      _parameters = new _UnmodifiableMap(new Map<String, String>());
+    }
+  }
+
   Map<String, String> get parameters {
-    if (_parameters == null) _parameters = new Map<String, String>();
+    _ensureParameters();
     return _parameters;
   }
 
@@ -540,7 +551,8 @@
     }
 
     void parseParameters() {
-      _parameters = new Map<String, String>();
+      var parameters = new Map<String, String>();
+      _parameters = new _UnmodifiableMap(parameters);
 
       String parseParameterName() {
         int start = index;
@@ -584,7 +596,7 @@
         expect("=");
         skipWS();
         String value = parseParameterValue();
-        _parameters[name] = value;
+        parameters[name] = value;
         skipWS();
         if (done()) return;
         expect(parameterSeparator);
@@ -612,14 +624,16 @@
       : _primaryType = primaryType, _subType = subType, super("") {
     if (_primaryType == null) _primaryType = "";
     if (_subType == null) _subType = "";
-    _value = "$_primaryType/$_subType";;
+    _value = "$_primaryType/$_subType";
     if (parameters != null) {
+      _ensureParameters();
       parameters.forEach((String key, String value) {
-        this.parameters[key.toLowerCase()] = value.toLowerCase();
+        this._parameters._map[key.toLowerCase()] = value.toLowerCase();
       });
     }
     if (charset != null) {
-      this.parameters["charset"] = charset.toLowerCase();
+      _ensureParameters();
+      this._parameters._map["charset"] = charset.toLowerCase();
     }
   }
 
@@ -633,7 +647,8 @@
       result._primaryType = result._value.trim().toLowerCase();
       result._subType = "";
     } else {
-      result._primaryType = result._value.substring(0, index).trim().toLowerCase();
+      result._primaryType =
+          result._value.substring(0, index).trim().toLowerCase();
       result._subType = result._value.substring(index + 1).trim().toLowerCase();
     }
     return result;
@@ -778,3 +793,34 @@
   bool httpOnly = false;
   bool secure = false;
 }
+
+
+class _UnmodifiableMap<K, V> implements Map<K, V> {
+  final Map _map;
+  const _UnmodifiableMap(this._map);
+
+  bool containsValue(Object value) => _map.containsValue(value);
+  bool containsKey(Object key) => _map.containsKey(key);
+  V operator [](Object key) => _map[key];
+  void operator []=(K key, V value) {
+    throw new UnsupportedError("Cannot modify an unmodifiable map");
+  }
+  V putIfAbsent(K key, V ifAbsent()) {
+    throw new UnsupportedError("Cannot modify an unmodifiable map");
+  }
+  addAll(Map other) {
+    throw new UnsupportedError("Cannot modify an unmodifiable map");
+  }
+  V remove(Object key) {
+    throw new UnsupportedError("Cannot modify an unmodifiable map");
+  }
+  void clear() {
+    throw new UnsupportedError("Cannot modify an unmodifiable map");
+  }
+  void forEach(void f(K key, V value)) => _map.forEach(f);
+  Iterable<K> get keys => _map.keys;
+  Iterable<V> get values => _map.values;
+  int get length => _map.length;
+  bool get isEmpty => _map.isEmpty;
+  bool get isNotEmpty => _map.isNotEmpty;
+}
diff --git a/sdk/lib/io/link.dart b/sdk/lib/io/link.dart
index 237154d..8c28eb4 100644
--- a/sdk/lib/io/link.dart
+++ b/sdk/lib/io/link.dart
@@ -130,7 +130,13 @@
 
   SendPort _fileService;
 
-  _Link(String this.path);
+  _Link(String this.path) {
+    if (path is! String) {
+      throw new ArgumentError('${Error.safeToString(path)} '
+                              'is not a String');
+    }
+  }
+
 
   _Link.fromPath(Path inputPath) : path = inputPath.toNativePath();
 
diff --git a/sdk/lib/io/secure_socket.dart b/sdk/lib/io/secure_socket.dart
index 1867050..2fd9659 100644
--- a/sdk/lib/io/secure_socket.dart
+++ b/sdk/lib/io/secure_socket.dart
@@ -96,6 +96,7 @@
     return completer.future;
   }
 
+
   /**
    * Takes an already connected [socket] and starts server side TLS
    * handshake to make the communication secure. When the returned
@@ -205,6 +206,40 @@
   external static void initialize({String database,
                                    String password,
                                    bool useBuiltinRoots: true});
+
+
+  /**
+   * Trust strings for use in [addCertificate].
+   */
+  static const String TRUST_ISSUE_SERVER_CERTIFICATES = 'C,,';
+  static const String TRUST_ISSUE_CLIENT_CERTIFICATES = 'T,,';
+  static const String TRUST_ISSUE_CLIENT_SERVER_CERTIFICATES = 'TC,,';
+  static const String TRUST_CERTIFICATE = 'P,,';
+
+
+  /**
+   * Adds a X509 certificate (for SSL and TLS secure networking) to the
+   * in-memory certificate database.  Returns an X509Certificate object
+   * with information about the added certificate.
+   *
+   * [certificate] must be a list of bytes encoding a certificate in
+   *  PEM format: a base64 encoded DER certificate, enclosed between
+   * "-----BEGIN CERTIFICATE-----" and "-----END CERTIFICATE-----".
+   *
+   * [trust] is a string specifying the allowed uses of this certificate.
+   * For example, 'TC,,' specifies that the certificate is for a certificate
+   * authority that is trusted to issue server and client certificates, so
+   * that a server or client certificate signed by this authority will be
+   * accepted.
+   *
+   * See the documentation of NSS certutil at
+   * http://developer.mozilla.org/en-US/docs/NSS_reference/NSS_tools_:_certutil
+   * or
+   * http://blogs.oracle.com/meena/entry/notes_about_trust_flags
+   * for more information about trust attributes.
+   */
+  external static X509Certificate addCertificate(List<int> certificate,
+                                                 String trust);
 }
 
 
@@ -412,7 +447,8 @@
   static final int NUM_BUFFERS = 4;
 
   // Is a buffer identifier for an encrypted buffer?
-  static bool _isBufferEncrypted(int identifier) => identifier >= READ_ENCRYPTED;
+  static bool _isBufferEncrypted(int identifier) =>
+      identifier >= READ_ENCRYPTED;
 
   RawSocket _socket;
   final Completer<_RawSecureSocket> _handshakeComplete =
diff --git a/sdk/lib/io/websocket_impl.dart b/sdk/lib/io/websocket_impl.dart
index dd837445..140bd3b 100644
--- a/sdk/lib/io/websocket_impl.dart
+++ b/sdk/lib/io/websocket_impl.dart
@@ -572,6 +572,9 @@
   StreamController _controller;
   StreamSubscription _subscription;
   bool _issuedPause = false;
+  // Only report error if the last message was a user-provided message and not a
+  // ping or pong message.
+  bool _reportError = false;
   Completer _closeCompleter = new Completer();
   Completer _completer;
 
@@ -613,8 +616,13 @@
                 _closeCompleter.complete(webSocket);
               },
               onError: (error) {
-                if (!_done(error)) {
-                  _closeCompleter.completeError(error);
+                if (_reportError) {
+                  if (!_done(error)) {
+                    _closeCompleter.completeError(error);
+                  }
+                } else {
+                  _done();
+                  _closeCompleter.complete(webSocket);
                 }
               });
   }
@@ -635,6 +643,7 @@
     _completer = new Completer();
     _subscription = stream.listen(
         (data) {
+          _reportError = true;
           _controller.add(data);
         },
         onDone: () {
@@ -662,6 +671,7 @@
 
   void add(data) {
     _ensureController();
+    _reportError = false;
     _controller.add(data);
   }
 }
diff --git a/sdk/lib/mirrors/mirrors.dart b/sdk/lib/mirrors/mirrors.dart
index 5353755..f189dc0 100644
--- a/sdk/lib/mirrors/mirrors.dart
+++ b/sdk/lib/mirrors/mirrors.dart
@@ -1226,10 +1226,10 @@
    * The list of strings passed to new [Symbol], and symbols that might be
    * passed to [MirrorSystem.getName].
    *
-   * Combined with the names of [reflectiveTarget], [metaTargets] and their
-   * members, this forms the complete list of strings passed to new [Symbol],
-   * and symbols that might be passed to [MirrorSystem.getName] by the library
-   * to which this metadata applies.
+   * Combined with the names of [targets], [metaTargets] and their members,
+   * this forms the complete list of strings passed to new [Symbol], and
+   * symbols that might be passed to [MirrorSystem.getName] by the library to
+   * which this metadata applies.
    *
    * The following text is non-normative:
    *
diff --git a/sdk/lib/svg/dartium/svg_dartium.dart b/sdk/lib/svg/dartium/svg_dartium.dart
index 0e76bcc..35fa28a 100644
--- a/sdk/lib/svg/dartium/svg_dartium.dart
+++ b/sdk/lib/svg/dartium/svg_dartium.dart
@@ -3435,9 +3435,8 @@
   Length operator[](int index) {
     if (index < 0 || index >= length)
       throw new RangeError.range(index, 0, length);
-    return _nativeIndexedGetter(index);
+    return this.getItem(index)(index);
   }
-  Length _nativeIndexedGetter(int index) native "SVGLengthList_item_Callback";
 
   void operator[]=(int index, Length value) {
     throw new UnsupportedError("Cannot assign element of immutable List.");
@@ -4025,9 +4024,8 @@
   Number operator[](int index) {
     if (index < 0 || index >= length)
       throw new RangeError.range(index, 0, length);
-    return _nativeIndexedGetter(index);
+    return this.getItem(index)(index);
   }
-  Number _nativeIndexedGetter(int index) native "SVGNumberList_item_Callback";
 
   void operator[]=(int index, Number value) {
     throw new UnsupportedError("Cannot assign element of immutable List.");
@@ -5096,9 +5094,8 @@
   PathSeg operator[](int index) {
     if (index < 0 || index >= length)
       throw new RangeError.range(index, 0, length);
-    return _nativeIndexedGetter(index);
+    return this.getItem(index)(index);
   }
-  PathSeg _nativeIndexedGetter(int index) native "SVGPathSegList_item_Callback";
 
   void operator[]=(int index, PathSeg value) {
     throw new UnsupportedError("Cannot assign element of immutable List.");
@@ -6005,9 +6002,8 @@
   String operator[](int index) {
     if (index < 0 || index >= length)
       throw new RangeError.range(index, 0, length);
-    return _nativeIndexedGetter(index);
+    return this.getItem(index)(index);
   }
-  String _nativeIndexedGetter(int index) native "SVGStringList_item_Callback";
 
   void operator[]=(int index, String value) {
     throw new UnsupportedError("Cannot assign element of immutable List.");
@@ -7143,9 +7139,8 @@
   Transform operator[](int index) {
     if (index < 0 || index >= length)
       throw new RangeError.range(index, 0, length);
-    return _nativeIndexedGetter(index);
+    return this.getItem(index)(index);
   }
-  Transform _nativeIndexedGetter(int index) native "SVGTransformList_item_Callback";
 
   void operator[]=(int index, Transform value) {
     throw new UnsupportedError("Cannot assign element of immutable List.");
diff --git a/sdk/lib/typed_data/typed_data.dart b/sdk/lib/typed_data/typed_data.dart
index 739eae8..f75b4bb 100644
--- a/sdk/lib/typed_data/typed_data.dart
+++ b/sdk/lib/typed_data/typed_data.dart
@@ -798,6 +798,12 @@
   external factory Float32x4List(int length);
 
   /**
+   * Creates a [Float32x4List] with the same size as the [elements] list
+   * and copies over the elements.
+   */
+  external factory Float32x4List.fromList(List<Float32x4> elements);
+
+  /**
    * Creates a [Float32x4List] _view_ of the specified region in the specified
    * byte buffer. Changes in the [Float32x4List] will be visible in the byte
    * buffer and vice versa. If the [offsetInBytes] index of the region is not
diff --git a/sdk/lib/web_gl/dart2js/web_gl_dart2js.dart b/sdk/lib/web_gl/dart2js/web_gl_dart2js.dart
index 11e9e01..65c742b 100644
--- a/sdk/lib/web_gl/dart2js/web_gl_dart2js.dart
+++ b/sdk/lib/web_gl/dart2js/web_gl_dart2js.dart
@@ -345,6 +345,39 @@
 
 
 @DocsEditable()
+@DomName('ANGLEInstancedArrays')
+@Experimental() // untriaged
+class AngleInstancedArrays extends Interceptor native "ANGLEInstancedArrays" {
+
+  @DomName('ANGLEInstancedArrays.VERTEX_ATTRIB_ARRAY_DIVISOR_ANGLE')
+  @DocsEditable()
+  @Experimental() // untriaged
+  static const int VERTEX_ATTRIB_ARRAY_DIVISOR_ANGLE = 0x88FE;
+
+  @JSName('drawArraysInstancedANGLE')
+  @DomName('ANGLEInstancedArrays.drawArraysInstancedANGLE')
+  @DocsEditable()
+  @Experimental() // untriaged
+  void drawArraysInstancedAngle(int mode, int first, int count, int primcount) native;
+
+  @JSName('drawElementsInstancedANGLE')
+  @DomName('ANGLEInstancedArrays.drawElementsInstancedANGLE')
+  @DocsEditable()
+  @Experimental() // untriaged
+  void drawElementsInstancedAngle(int mode, int count, int type, int offset, int primcount) native;
+
+  @JSName('vertexAttribDivisorANGLE')
+  @DomName('ANGLEInstancedArrays.vertexAttribDivisorANGLE')
+  @DocsEditable()
+  @Experimental() // untriaged
+  void vertexAttribDivisorAngle(int index, int divisor) native;
+}
+// Copyright (c) 2012, 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.
+
+
+@DocsEditable()
 @DomName('WebGLBuffer')
 @Unstable()
 class Buffer extends Interceptor native "WebGLBuffer" {
@@ -726,7 +759,7 @@
 @DomName('WebGLLoseContext')
 // http://www.khronos.org/registry/webgl/extensions/WEBGL_lose_context/
 @Experimental()
-class LoseContext extends Interceptor native "WebGLLoseContext" {
+class LoseContext extends Interceptor native "WebGLLoseContext,WebGLExtensionLoseContext" {
 
   @DomName('WebGLLoseContext.loseContext')
   @DocsEditable()
diff --git a/sdk/lib/web_gl/dartium/web_gl_dartium.dart b/sdk/lib/web_gl/dartium/web_gl_dartium.dart
index 7637a680..411dd69 100644
--- a/sdk/lib/web_gl/dartium/web_gl_dartium.dart
+++ b/sdk/lib/web_gl/dartium/web_gl_dartium.dart
@@ -348,6 +348,39 @@
 
 
 @DocsEditable()
+@DomName('ANGLEInstancedArrays')
+@Experimental() // untriaged
+class AngleInstancedArrays extends NativeFieldWrapperClass1 {
+
+  @DomName('ANGLEInstancedArrays.VERTEX_ATTRIB_ARRAY_DIVISOR_ANGLE')
+  @DocsEditable()
+  @Experimental() // untriaged
+  static const int VERTEX_ATTRIB_ARRAY_DIVISOR_ANGLE = 0x88FE;
+
+  @DomName('ANGLEInstancedArrays.drawArraysInstancedANGLE')
+  @DocsEditable()
+  @Experimental() // untriaged
+  void drawArraysInstancedAngle(int mode, int first, int count, int primcount) native "ANGLEInstancedArrays_drawArraysInstancedANGLE_Callback";
+
+  @DomName('ANGLEInstancedArrays.drawElementsInstancedANGLE')
+  @DocsEditable()
+  @Experimental() // untriaged
+  void drawElementsInstancedAngle(int mode, int count, int type, int offset, int primcount) native "ANGLEInstancedArrays_drawElementsInstancedANGLE_Callback";
+
+  @DomName('ANGLEInstancedArrays.vertexAttribDivisorANGLE')
+  @DocsEditable()
+  @Experimental() // untriaged
+  void vertexAttribDivisorAngle(int index, int divisor) native "ANGLEInstancedArrays_vertexAttribDivisorANGLE_Callback";
+
+}
+// Copyright (c) 2012, 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.
+
+// WARNING: Do not edit - generated code.
+
+
+@DocsEditable()
 @DomName('WebGLBuffer')
 @Unstable()
 class Buffer extends NativeFieldWrapperClass1 {
diff --git a/tests/co19/co19-dart2dart.status b/tests/co19/co19-dart2dart.status
index 7b828a5..687842a 100644
--- a/tests/co19/co19-dart2dart.status
+++ b/tests/co19/co19-dart2dart.status
@@ -402,6 +402,12 @@
 LibTest/math/atan_A01_t01: Fail, OK # co19 issue 44
 
 [ $compiler == dart2dart ]
+Language/03_Overview/2_Privacy_A01_t06: Fail # co19 issue 463
+Language/09_Generics/09_Generics_A05_t01: Fail # co19 issue 463
+Language/11_Expressions/31_Type_Test_A04_t01: Fail # co19 issue 463
+Language/11_Expressions/32_Type_Cast_A03_t01: Fail # co19 issue 463
+Language/11_Expressions/32_Type_Cast_A03_t02: Fail # co19 issue 463
+Language/14_Types/2_Dynamic_Type_System_A02_t01: Fail # co19 issue 463
 Language/14_Types/4_Interface_Types_A11_t01: Pass, Crash # Issue 8857
 Language/14_Types/4_Interface_Types_A11_t02: Pass, Crash # Issue 8857
 
@@ -574,3 +580,12 @@
 Language/11_Expressions/33_Argument_Definition_Test_A02_t02: Fail, OK # co19 issue 436
 Language/11_Expressions/33_Argument_Definition_Test_A03_t01: Fail, OK # co19 issue 436
 Language/11_Expressions/33_Argument_Definition_Test_A03_t02: Fail, OK # co19 issue 436
+
+Language/13_Libraries_and_Scripts/1_Imports_A03_t02: Fail # 481
+Language/13_Libraries_and_Scripts/1_Imports_A03_t05: Fail # 481
+Language/13_Libraries_and_Scripts/1_Imports_A03_t22: Fail # 481
+Language/13_Libraries_and_Scripts/1_Imports_A03_t25: Fail # 481
+Language/13_Libraries_and_Scripts/1_Imports_A03_t42: Fail # 481
+Language/13_Libraries_and_Scripts/1_Imports_A03_t45: Fail # 481
+Language/13_Libraries_and_Scripts/1_Imports_A03_t62: Fail # 481
+Language/13_Libraries_and_Scripts/1_Imports_A03_t65: Fail # 481
diff --git a/tests/co19/co19-dart2js.status b/tests/co19/co19-dart2js.status
index e7c7f0d..f4d828f 100644
--- a/tests/co19/co19-dart2js.status
+++ b/tests/co19/co19-dart2js.status
@@ -558,6 +558,15 @@
 Language/11_Expressions/11_Instance_Creation_A04_t03: Fail # co19 issue 466
 Language/11_Expressions/11_Instance_Creation_A04_t04: Fail # co19 issue 466
 
+Language/13_Libraries_and_Scripts/1_Imports_A03_t02: Fail # 481
+Language/13_Libraries_and_Scripts/1_Imports_A03_t05: Fail # 481
+Language/13_Libraries_and_Scripts/1_Imports_A03_t22: Fail # 481
+Language/13_Libraries_and_Scripts/1_Imports_A03_t25: Fail # 481
+Language/13_Libraries_and_Scripts/1_Imports_A03_t42: Fail # 481
+Language/13_Libraries_and_Scripts/1_Imports_A03_t45: Fail # 481
+Language/13_Libraries_and_Scripts/1_Imports_A03_t62: Fail # 481
+Language/13_Libraries_and_Scripts/1_Imports_A03_t65: Fail # 481
+
 [ $compiler == dart2js && $checked ]
 
 Language/03_Overview/1_Scoping_A02_t30: Fail # co19 issue 463
@@ -567,6 +576,8 @@
 Language/11_Expressions/32_Type_Cast_A05_t04: Fail # co19 issue 463
 Language/14_Types/8_Parameterized_Types_A02_t01: Fail # co19 issue 463
 
+Language/13_Libraries_and_Scripts/1_Imports_A03_t31: Fail # 481
+
 [ $compiler == dart2js && $unchecked ]
 LibTest/core/List/setRange_A05_t01: Fail # setRange throws StateError if there aren't enough elements in the iterable. Issue 402
 
diff --git a/tests/co19/co19-runtime.status b/tests/co19/co19-runtime.status
index c26a8af..7311058 100644
--- a/tests/co19/co19-runtime.status
+++ b/tests/co19/co19-runtime.status
@@ -93,8 +93,6 @@
 Language/07_Classes/6_Constructors/3_Constant_Constructors_A05_t01: Fail # co19 issue 426
 Language/11_Expressions/05_Strings_A02_t46: Fail # Dart issue 4009
 Language/11_Expressions/05_Strings_A02_t48: Fail # Dart issue 4009
-Language/11_Expressions/11_Instance_Creation/1_New_A02_t03: Fail # Dart issue 3309
-Language/11_Expressions/11_Instance_Creation/1_New_A02_t05: Fail # Dart issue 7247
 Language/11_Expressions/11_Instance_Creation/1_New_A09_t09: Fail # Dart issue 1372
 Language/11_Expressions/11_Instance_Creation/2_Const_A10_t01: Fail # Dart issue 5775
 Language/11_Expressions/30_Identifier_Reference_A05_t02: Fail # Dart issue 2492
@@ -394,6 +392,43 @@
 Language/07_Classes/1_Instance_Methods_A02_t02: Fail # Override rules have been relaxed. Issue
 Language/07_Classes/1_Instance_Methods_A02_t05: Fail # Override rules have been relaxed. Issue
 
+Language/03_Overview/1_Scoping_A02_t28: Fail # Issue 463
+Language/03_Overview/2_Privacy_A01_t06: Fail # Issue 463
+Language/09_Generics/09_Generics_A05_t01: Fail # Issue 463
+Language/11_Expressions/11_Instance_Creation/1_New_A05_t01: Fail # Issue 463
+Language/11_Expressions/11_Instance_Creation/1_New_A05_t02: Fail # Issue 463
+Language/11_Expressions/11_Instance_Creation/1_New_A05_t03: Fail # Issue 463
+Language/11_Expressions/11_Instance_Creation/2_Const_A07_t01: Fail # Issue 463
+Language/11_Expressions/11_Instance_Creation/2_Const_A07_t02: Fail # Issue 463
+Language/11_Expressions/11_Instance_Creation/2_Const_A07_t03: Fail # Issue 463
+Language/11_Expressions/11_Instance_Creation_A03_t01: Fail # Issue 463
+Language/11_Expressions/11_Instance_Creation_A03_t02: Fail # Issue 463
+Language/11_Expressions/11_Instance_Creation_A04_t01: Fail # Issue 463
+Language/11_Expressions/11_Instance_Creation_A04_t02: Fail # Issue 463
+Language/11_Expressions/11_Instance_Creation_A04_t03: Fail # Issue 463
+Language/11_Expressions/11_Instance_Creation_A04_t04: Fail # Issue 463
+Language/11_Expressions/31_Type_Test_A04_t01: Fail # Issue 463
+Language/11_Expressions/31_Type_Test_A05_t01: Fail # Issue 463
+Language/11_Expressions/31_Type_Test_A05_t02: Fail # Issue 463
+Language/11_Expressions/31_Type_Test_A05_t03: Fail # Issue 463
+Language/11_Expressions/32_Type_Cast_A03_t01: Fail # Issue 463
+Language/11_Expressions/32_Type_Cast_A03_t02: Fail # Issue 463
+Language/11_Expressions/32_Type_Cast_A04_t01: Fail # Issue 463
+Language/11_Expressions/32_Type_Cast_A04_t02: Fail # Issue 463
+Language/13_Libraries_and_Scripts/1_Imports_A03_t02: Fail # Issue 463
+Language/13_Libraries_and_Scripts/1_Imports_A03_t05: Fail # Issue 463
+Language/13_Libraries_and_Scripts/1_Imports_A03_t08: Fail # Issue 463
+Language/13_Libraries_and_Scripts/1_Imports_A03_t22: Fail # Issue 463
+Language/13_Libraries_and_Scripts/1_Imports_A03_t25: Fail # Issue 463
+Language/13_Libraries_and_Scripts/1_Imports_A03_t28: Fail # Issue 463
+Language/13_Libraries_and_Scripts/1_Imports_A03_t42: Fail # Issue 463
+Language/13_Libraries_and_Scripts/1_Imports_A03_t45: Fail # Issue 463
+Language/13_Libraries_and_Scripts/1_Imports_A03_t48: Fail # Issue 463
+Language/13_Libraries_and_Scripts/1_Imports_A03_t62: Fail # Issue 463
+Language/13_Libraries_and_Scripts/1_Imports_A03_t65: Fail # Issue 463
+Language/13_Libraries_and_Scripts/1_Imports_A03_t68: Fail # Issue 463
+Language/14_Types/2_Dynamic_Type_System_A02_t01: Fail # Issue 463
+
 # end [ $compiler == none && $runtime == vm ]
 
 
@@ -404,6 +439,15 @@
 
 
 [ $compiler == none && $runtime == vm && $checked ]
+Language/03_Overview/1_Scoping_A02_t30: Fail # co19 issue 463
+Language/09_Generics/09_Generics_A05_t02: Fail # co19 issue 463
+Language/13_Libraries_and_Scripts/1_Imports_A03_t06: Fail # co19 issue 463, bound is mapped to dynamic, no error.
+Language/13_Libraries_and_Scripts/1_Imports_A03_t26: Fail # co19 issue 463, bound is mapped to dynamic, no error.
+Language/13_Libraries_and_Scripts/1_Imports_A03_t46: Fail # co19 issue 463, bound is mapped to dynamic, no error.
+Language/13_Libraries_and_Scripts/1_Imports_A03_t66: Fail # co19 issue 463, bound is mapped to dynamic, no error.
+Language/13_Libraries_and_Scripts/1_Imports_A03_t31: Fail # co19 issue 463
+Language/14_Types/8_Parameterized_Types_A02_t01: Fail # co19 issue 463
+
 LibTest/core/AssertionError/line_A01_t02: Fail # co19 issue 479
 LibTest/core/Set/intersection_A03_t01: Fail # co19 issue 480
 LibTest/core/TypeError/line_A01_t01: Fail # co19 issue 479
@@ -416,36 +460,40 @@
 Language/11_Expressions/14_Function_Invocation/4_Function_Expression_Invocation_A01_t02: Fail, OK # co19 issue 405
 Language/11_Expressions/15_Method_Invocation/1_Ordinary_Invocation_A05_t02: Fail, OK # co19 issue 405
 Language/11_Expressions/15_Method_Invocation/1_Ordinary_Invocation_A05_t03: Fail, OK # co19 issue 405
-Language/11_Expressions/15_Method_Invocation/1_Ordinary_Invocation_A05_t06: Fail, OK # co19 issue 405
-Language/11_Expressions/15_Method_Invocation/4_Super_Invocation_A04_t01: Fail, OK # co19 issue 405
-Language/11_Expressions/15_Method_Invocation/4_Super_Invocation_A04_t02: Fail, OK # co19 issue 405
-Language/11_Expressions/15_Method_Invocation/4_Super_Invocation_A04_t03: Fail, OK # co19 issue 405
-Language/11_Expressions/15_Method_Invocation/4_Super_Invocation_A04_t04: Fail, OK # co19 issue 405
 Language/11_Expressions/17_Getter_Invocation_A02_t01: Fail, OK # co19 issue 405
-Language/11_Expressions/17_Getter_Invocation_A02_t02: Fail, OK # co19 issue 405
 Language/11_Expressions/18_Assignment_A05_t02: Fail, OK # co19 issue 405
 Language/11_Expressions/18_Assignment_A05_t04: Fail, OK # co19 issue 405
 Language/11_Expressions/18_Assignment_A05_t05: Fail, OK # co19 issue 405
 Language/11_Expressions/18_Assignment_A08_t04: Fail, OK # co19 issue 405
 Language/11_Expressions/30_Identifier_Reference_A07_t01: Fail, OK # co19 issue 460
 
-Language/12_Statements/09_Switch_A05_t01: Fail # co19 issue 442
+# Passing for the wrong reasons:
+Language/11_Expressions/15_Method_Invocation/4_Super_Invocation_A04_t01: Pass # co19 issues 405 and 463
+Language/11_Expressions/15_Method_Invocation/4_Super_Invocation_A04_t02: Pass # co19 issues 405 and 463
+Language/11_Expressions/15_Method_Invocation/4_Super_Invocation_A04_t03: Pass # co19 issues 405 and 463
+Language/11_Expressions/15_Method_Invocation/4_Super_Invocation_A04_t04: Pass # co19 issues 405 and 463
+Language/11_Expressions/15_Method_Invocation/1_Ordinary_Invocation_A05_t06: Pass # co19 issues 405 and 463
+Language/11_Expressions/17_Getter_Invocation_A02_t02: Pass # co19 issues 405 and 463
+Language/11_Expressions/32_Type_Cast_A05_t01: Fail # co19 issue 463 and issue 5280
+Language/11_Expressions/32_Type_Cast_A05_t02: Pass # co19 issue 463 and issue 5280
+Language/11_Expressions/32_Type_Cast_A05_t04: Pass # co19 issue 463 and issue 5280
 
-Language/03_Overview/1_Scoping_A02_t30: Fail
+Language/12_Statements/09_Switch_A05_t01: Fail # co19 issue 442
 
 LibTest/core/Set/intersection_A01_t01: Fail # issue 390
 LibTest/core/Set/intersection_A01_t02: Fail # issue 390
 LibTest/core/Set/intersection_A01_t03: Fail # issue 390
-LibTest/collection/Queue/Queue.from_A01_t01: Fail # Issue 400
-LibTest/collection/Queue/Queue.from_A01_t02: Fail # Issue 400
-LibTest/core/List/List.from_A01_t01: Fail # Issue 400
-LibTest/core/List/every_A01_t01: Fail # Issue 400
-LibTest/core/Match/str_A01_t01: Fail # Issue 400
+LibTest/collection/Queue/Queue.from_A01_t01: Pass # Issue 400 and 463
+LibTest/collection/Queue/Queue.from_A01_t02: Pass # Issue 400 and 463
+LibTest/core/List/List.from_A01_t01: Pass # Issue 400 and 463
+LibTest/core/List/every_A01_t01: Pass # Issue 400 and 463
+LibTest/core/Match/str_A01_t01: Pass # Issue 400 and 463
 
-LibTest/async/Completer/completeError_A03_t02: Fail # No AsyncError anymore. Issue 407
-LibTest/async/Completer/complete_A02_t02: Fail # No AsyncError anymore. Issue 407
-LibTest/async/Future/catchError_A01_t01: Fail # No AsyncError anymore. Issue 407
-LibTest/async/Future/catchError_A01_t02: Fail # No AsyncError anymore. Issue 407
+# Passing for the wrong reasons:
+LibTest/async/Completer/completeError_A03_t02: Pass # No AsyncError anymore. Issue 407 and 463
+LibTest/async/Completer/complete_A02_t02: Pass # No AsyncError anymore. Issue 407 and 463
+LibTest/async/Future/catchError_A01_t01: Pass # No AsyncError anymore. Issue 407 and 463
+LibTest/async/Future/catchError_A01_t02: Pass # No AsyncError anymore. Issue 407 and 463
 
 #end [ $compiler == none && $runtime == vm && $checked ]
 
diff --git a/tests/compiler/dart2js/deprecated_features_test.dart b/tests/compiler/dart2js/deprecated_features_test.dart
index ab679c3..58d8f07 100644
--- a/tests/compiler/dart2js/deprecated_features_test.dart
+++ b/tests/compiler/dart2js/deprecated_features_test.dart
@@ -54,11 +54,10 @@
       // "message" is the expected message as a [String].  This is a
       // short-term solution and should eventually changed to include
       // a symbolic reference to a MessageKind.
-      "0<#library('test');>::${deprecatedMessage('# tags')}\n"
-      "19<part 'part.dart';>::${deprecatedMessage('missing part-of tag')}\n"
+      "15<part 'part.dart';>::${deprecatedMessage('missing part-of tag')}\n"
       "0<>:/part.dart:info: Note: This file has no part-of tag, but it is being"
       " used as a part.\n"
-      "57<()>::${deprecatedMessage('getter parameters')}\n",
+      "53<()>::${deprecatedMessage('getter parameters')}\n",
       messages.toString());
 }
 
@@ -70,7 +69,7 @@
 
 const Map<String, String> TEST_SOURCE =
   const <String, String>{ '': """
-#library('test');
+library test;
 
 part 'part.dart';
 
diff --git a/tests/compiler/dart2js/memory_compiler.dart b/tests/compiler/dart2js/memory_compiler.dart
index 3bf07d2..a45e1ca 100644
--- a/tests/compiler/dart2js/memory_compiler.dart
+++ b/tests/compiler/dart2js/memory_compiler.dart
@@ -1,68 +1,68 @@
-// Copyright (c) 2013, 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 dart2js.test.memory_compiler;

-

-import 'package:expect/expect.dart';

-import 'memory_source_file_helper.dart';

-

-import '../../../sdk/lib/_internal/compiler/implementation/dart2jslib.dart'

-       show NullSink;

-

-import '../../../sdk/lib/_internal/compiler/compiler.dart'

-       show DiagnosticHandler;

-

-import 'dart:async';

-

-import '../../../sdk/lib/_internal/compiler/implementation/mirrors/mirrors.dart';

-import '../../../sdk/lib/_internal/compiler/implementation/mirrors/dart2js_mirror.dart';

-

-Compiler compilerFor(Map<String,String> memorySourceFiles, 

-                     {DiagnosticHandler diagnosticHandler,

-                      List<String> options: const []}) {

-  Uri script = currentDirectory.resolve(nativeToUriPath(Platform.script));

-  Uri libraryRoot = script.resolve('../../../sdk/');

-  Uri packageRoot = script.resolve('./packages/');

-

-  MemorySourceFileProvider.MEMORY_SOURCE_FILES = memorySourceFiles;

-  var provider = new MemorySourceFileProvider();

-  if (diagnosticHandler == null) {

-    diagnosticHandler = new FormattingDiagnosticHandler(provider);

-  }

-  

-  EventSink<String> outputProvider(String name, String extension) {

-    if (name != '') throw 'Attempt to output file "$name.$extension"';

-    return new NullSink('$name.$extension');

-  }

-

-  Compiler compiler = new Compiler(provider.readStringFromUri,

-                                   outputProvider,

-                                   diagnosticHandler,

-                                   libraryRoot,

-                                   packageRoot,

-                                   options);

-  return compiler;

-}

-

-Future<MirrorSystem> mirrorSystemFor(Map<String,String> memorySourceFiles, 

-                                     {DiagnosticHandler diagnosticHandler,

-                                      List<String> options: const []}) {

-  Uri script = currentDirectory.resolve(nativeToUriPath(Platform.script));

-  Uri libraryRoot = script.resolve('../../../sdk/');

-  Uri packageRoot = script.resolve('./packages/');

-

-  MemorySourceFileProvider.MEMORY_SOURCE_FILES = memorySourceFiles;

-  var provider = new MemorySourceFileProvider();

-  if (diagnosticHandler == null) {

-    diagnosticHandler = new FormattingDiagnosticHandler(provider);

-  }

-  

-  List<Uri> libraries = <Uri>[];

-  memorySourceFiles.forEach((String path, _) {

-    libraries.add(new Uri(scheme: 'memory', path: path));

-  });

-  

-  return analyze(libraries, libraryRoot, packageRoot, 

-                 provider, diagnosticHandler, options);

-}

+// Copyright (c) 2013, 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 dart2js.test.memory_compiler;
+
+import 'package:expect/expect.dart';
+import 'memory_source_file_helper.dart';
+
+import '../../../sdk/lib/_internal/compiler/implementation/dart2jslib.dart'
+       show NullSink;
+
+import '../../../sdk/lib/_internal/compiler/compiler.dart'
+       show DiagnosticHandler;
+
+import 'dart:async';
+
+import '../../../sdk/lib/_internal/compiler/implementation/mirrors/mirrors.dart';
+import '../../../sdk/lib/_internal/compiler/implementation/mirrors/dart2js_mirror.dart';
+
+Compiler compilerFor(Map<String,String> memorySourceFiles,
+                     {DiagnosticHandler diagnosticHandler,
+                      List<String> options: const []}) {
+  Uri script = currentDirectory.resolve(nativeToUriPath(Platform.script));
+  Uri libraryRoot = script.resolve('../../../sdk/');
+  Uri packageRoot = script.resolve('./packages/');
+
+  MemorySourceFileProvider.MEMORY_SOURCE_FILES = memorySourceFiles;
+  var provider = new MemorySourceFileProvider();
+  if (diagnosticHandler == null) {
+    diagnosticHandler = new FormattingDiagnosticHandler(provider);
+  }
+
+  EventSink<String> outputProvider(String name, String extension) {
+    if (name != '') throw 'Attempt to output file "$name.$extension"';
+    return new NullSink('$name.$extension');
+  }
+
+  Compiler compiler = new Compiler(provider.readStringFromUri,
+                                   outputProvider,
+                                   diagnosticHandler,
+                                   libraryRoot,
+                                   packageRoot,
+                                   options);
+  return compiler;
+}
+
+Future<MirrorSystem> mirrorSystemFor(Map<String,String> memorySourceFiles,
+                                     {DiagnosticHandler diagnosticHandler,
+                                      List<String> options: const []}) {
+  Uri script = currentDirectory.resolve(nativeToUriPath(Platform.script));
+  Uri libraryRoot = script.resolve('../../../sdk/');
+  Uri packageRoot = script.resolve('./packages/');
+
+  MemorySourceFileProvider.MEMORY_SOURCE_FILES = memorySourceFiles;
+  var provider = new MemorySourceFileProvider();
+  if (diagnosticHandler == null) {
+    diagnosticHandler = new FormattingDiagnosticHandler(provider);
+  }
+
+  List<Uri> libraries = <Uri>[];
+  memorySourceFiles.forEach((String path, _) {
+    libraries.add(new Uri(scheme: 'memory', path: path));
+  });
+
+  return analyze(libraries, libraryRoot, packageRoot,
+                 provider, diagnosticHandler, options);
+}
diff --git a/tests/compiler/dart2js/mirrors_lookup_test.dart b/tests/compiler/dart2js/mirrors_lookup_test.dart
index 26dbae9..8cda12e 100644
--- a/tests/compiler/dart2js/mirrors_lookup_test.dart
+++ b/tests/compiler/dart2js/mirrors_lookup_test.dart
@@ -1,263 +1,261 @@
-// Copyright (c) 2013, 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 dart2js.test.memory_source_file_helper;

-

-import 'package:expect/expect.dart';

-import 'memory_compiler.dart';

-import '../../../sdk/lib/_internal/compiler/implementation/mirrors/mirrors.dart';

-import '../../../sdk/lib/_internal/compiler/implementation/mirrors/mirrors_util.dart';

-

-const Map MEMORY_SOURCE_FILES = const {

-  'main.dart': r"""

-

-library main;

-

-import 'dart:async' as async show Future;

-

-var variable;

-

-method(a, [b]) {}

-

-class Class<A> {

-  var field;

-  var variable;

-  method(c, {d}) {}

-}

-

-class Subclass<B> extends Class<B> {

-  var subfield;

-}

-""",

-};

-

-void main() {

-  mirrorSystemFor(MEMORY_SOURCE_FILES).then(

-      (MirrorSystem mirrors) => test(mirrors),

-      onError: (e) => Expect.fail('$e'));

-}

-

-void test(MirrorSystem mirrors) {

-  LibraryMirror dartCore = mirrors.libraries[Uri.parse('dart:core')];

-  Expect.isNotNull(dartCore);

-  

-  LibraryMirror dartAsync = mirrors.libraries[Uri.parse('dart:async')];

-  Expect.isNotNull(dartAsync);

-  

-  LibraryMirror library = mirrors.libraries[Uri.parse('memory:main.dart')];

-  Expect.isNotNull(library);

-  

-  // Check top-level scope.

-  

-  DeclarationMirror String_ = library.lookupInScope('String');

-  Expect.isTrue(String_ is ClassMirror);

-  Expect.equals('String', String_.simpleName);

-  Expect.equals(dartCore, String_.owner);

-  

-  Expect.isNull(library.lookupInScope('async'));

-  Expect.isNull(library.lookupInScope('Future'));

-  DeclarationMirror Future_ = library.lookupInScope('async.Future');

-  Expect.isTrue(Future_ is ClassMirror);

-  Expect.equals('Future', Future_.simpleName);

-  Expect.equals(dartAsync, Future_.owner);

-  // Timer is not in scope.

-  Expect.isNull(library.lookupInScope('Timer'));

-  // async.Timer is hidden.

-  Expect.isNull(library.lookupInScope('async.Timer'));

-  

-  DeclarationMirror variable = library.lookupInScope('variable');

-  Expect.isTrue(variable is VariableMirror);

-  Expect.equals('variable', variable.simpleName);

-  Expect.equals('main.variable', variable.qualifiedName);

-  Expect.equals(library, variable.owner);

-  // Parameter `a` is not in scope.

-  Expect.isNull(library.lookupInScope('a'));

-  // Parameter `b` is not in scope.

-  Expect.isNull(library.lookupInScope('b'));

-  

-  DeclarationMirror method = library.lookupInScope('method');

-  Expect.isTrue(method is MethodMirror);

-  Expect.equals('method', method.simpleName);

-  Expect.equals('main.method', method.qualifiedName);

-  Expect.equals(library, method.owner);

-  

-  DeclarationMirror Class = library.lookupInScope('Class');

-  Expect.isTrue(Class is ClassMirror);

-  Expect.equals('Class', Class.simpleName);

-  Expect.equals('main.Class', Class.qualifiedName);

-  Expect.equals(library, Class.owner);

-  // Type variable `A` is not in scope.

-  Expect.isNull(library.lookupInScope('A'));

-  

-  DeclarationMirror Subclass = library.lookupInScope('Subclass');

-  Expect.isTrue(Subclass is ClassMirror);

-  Expect.equals('Subclass', Subclass.simpleName);

-  Expect.equals('main.Subclass', Subclass.qualifiedName);

-  Expect.equals(library, Subclass.owner);

-  // Type variable `B` is not in scope.

-  Expect.isNull(library.lookupInScope('B'));

-  

-  // Check top-level declaration scope.

-  checkTopScope(DeclarationMirror declaration) {

-    Expect.equals(String_, declaration.lookupInScope('String'));

-    Expect.equals(Future_, declaration.lookupInScope('async.Future'));

-    Expect.isNull(method.lookupInScope('Timer'));

-    Expect.isNull(declaration.lookupInScope('async.Timer'));

-    Expect.equals(variable, declaration.lookupInScope('variable'));

-    Expect.equals(method, declaration.lookupInScope('method'));

-    Expect.equals(Class, declaration.lookupInScope('Class'));

-    // Type variable `A` is not in scope.

-    Expect.isNull(declaration.lookupInScope('A'));

-    // Field `field` is not in scope.

-    Expect.isNull(declaration.lookupInScope('field'));

-    Expect.equals(Subclass, declaration.lookupInScope('Subclass'));

-    // Type variable `B` is not in scope.

-    Expect.isNull(declaration.lookupInScope('B'));

-    // Field `subfield` is not in scope.

-    Expect.isNull(declaration.lookupInScope('subfield'));

-  }

-  

-  checkTopScope(variable);

-  // Parameter `a` is not in scope of `variable`.

-  Expect.isNull(variable.lookupInScope('a'));

-  // Parameter `b` is not in scope of `variable`.

-  Expect.isNull(variable.lookupInScope('b'));

-

-  checkTopScope(method);

-  // Parameter `a` is in scope of `method`.

-  Expect.isTrue(method.lookupInScope('a') is ParameterMirror);

-  // Parameter `b` is in scope of `method`.

-  Expect.isTrue(method.lookupInScope('b') is ParameterMirror);

-

-  // Check class scope.

-  DeclarationMirror Class_field = Class.lookupInScope('field');

-  Expect.isTrue(Class_field is VariableMirror);

-  Expect.notEquals(variable, Class_field);

-  Expect.equals(Class, Class_field.owner);

-  

-  DeclarationMirror Class_variable = Class.lookupInScope('variable');

-  Expect.isTrue(Class_variable is VariableMirror);

-  Expect.notEquals(variable, Class_variable);

-  Expect.equals(Class, Class_variable.owner);

-  

-  DeclarationMirror Class_method = Class.lookupInScope('method');

-  Expect.isTrue(Class_method is MethodMirror);

-  Expect.notEquals(method, Class_method);

-  Expect.equals(Class, Class_method.owner);

-  

-  checkClassScope(DeclarationMirror declaration, {bool parametersInScope}) {

-    Expect.equals(String_, declaration.lookupInScope('String'));

-    Expect.equals(Future_, declaration.lookupInScope('async.Future'));

-    Expect.isNull(declaration.lookupInScope('Timer'));

-    Expect.isNull(declaration.lookupInScope('async.Timer'));

-  

-    Expect.equals(Class_field, declaration.lookupInScope('field'));

-    Expect.equals(Class_variable, declaration.lookupInScope('variable'));

-    Expect.equals(Class_method, declaration.lookupInScope('method'));

-  

-    // Parameter `a` is not in scope.

-    Expect.isNull(declaration.lookupInScope('a'));

-    // Parameter `b` is not in scope.

-    Expect.isNull(declaration.lookupInScope('b'));

-    

-    if (parametersInScope) {

-      // Parameter `c` is in scope.

-      Expect.isTrue(declaration.lookupInScope('c') is ParameterMirror);

-      // Parameter `d` is in scope.

-      Expect.isTrue(declaration.lookupInScope('d') is ParameterMirror);

-    } else {

-      // Parameter `c` is not in scope.

-      Expect.isNull(declaration.lookupInScope('c'));

-      // Parameter `d` is not in scope.

-      Expect.isNull(declaration.lookupInScope('d'));

-    }

-    

-    Expect.equals(Class, declaration.lookupInScope('Class'));

-    // Type variable `A` is in scope.

-    Expect.isTrue(declaration.lookupInScope('A') is TypeVariableMirror);

-    Expect.equals(Subclass, declaration.lookupInScope('Subclass'));

-    // Type variable `B` is not in scope.

-    Expect.isNull(declaration.lookupInScope('B'));

-    // Field `subfield` is not in scope.

-    Expect.isNull(declaration.lookupInScope('subfield'));

-  }

-  checkClassScope(Class, parametersInScope: false);

-  checkClassScope(Class_field, parametersInScope: false);

-  checkClassScope(Class_variable, parametersInScope: false);

-  checkClassScope(Class_method, parametersInScope: true);

-

-  // Check class scope.

-  DeclarationMirror Subclass_subfield = Subclass.lookupInScope('subfield');

-  Expect.isTrue(Subclass_subfield is VariableMirror);

-  Expect.notEquals(variable, Subclass_subfield);

-  Expect.equals(Subclass, Subclass_subfield.owner);

-  

-  checkSubclassScope(DeclarationMirror declaration) {

-    Expect.equals(String_, declaration.lookupInScope('String'));

-    Expect.equals(Future_, declaration.lookupInScope('async.Future'));

-    Expect.isNull(declaration.lookupInScope('Timer'));

-    Expect.isNull(declaration.lookupInScope('async.Timer'));

-  

-    // Top level `variable` is in scope.

-    Expect.equals(variable, declaration.lookupInScope('variable'));

-    // Top level `method` is in scope.

-    Expect.equals(method, declaration.lookupInScope('method'));

-  

-    // Parameter `a` is not in scope

-    Expect.isNull(declaration.lookupInScope('a'));

-    // Parameter `b` is not in scope

-    Expect.isNull(declaration.lookupInScope('b'));

-    

-    // Parameter `c` is not in scope.

-    Expect.isNull(declaration.lookupInScope('c'));

-    // Parameter `d` is not in scope.

-    Expect.isNull(declaration.lookupInScope('d'));

-    

-    Expect.equals(Class, declaration.lookupInScope('Class'));

-    // Type variable `A` is not in scope

-    Expect.isNull(declaration.lookupInScope('A'));

-    // Field `field` is in scope

-    Expect.equals(Class_field, declaration.lookupInScope('field'));

-    Expect.equals(Subclass, declaration.lookupInScope('Subclass'));

-    // Type variable `B` is in scope

-    Expect.isTrue(declaration.lookupInScope('B') is TypeVariableMirror);

-    // Field `subfield` is in scope

-    Expect.equals(Subclass_subfield, declaration.lookupInScope('subfield'));

-  }

-  checkSubclassScope(Subclass);

-  checkSubclassScope(Subclass_subfield);

-  

-  // `Timer` is in scope of `Future`.

-  Expect.isTrue(Future_.lookupInScope('Timer') is ClassMirror);

-  

-  // Check qualified lookup.

-  Expect.equals(variable, lookupQualifiedInScope(library, 'variable'));

-  Expect.equals(method, lookupQualifiedInScope(library, 'method'));

-  Expect.isTrue(lookupQualifiedInScope(library, 'method.a') is ParameterMirror);

-  

-  Expect.equals(Class, lookupQualifiedInScope(library, 'Class'));

-  Expect.isTrue(

-      lookupQualifiedInScope(library, 'Class.A') is TypeVariableMirror);

-  

-  Expect.isNull(library.lookupInScope('Class.field'));

-  Expect.equals(Class_field, lookupQualifiedInScope(library, 'Class.field'));

-  

-  Expect.equals(Class_method, lookupQualifiedInScope(library, 'Class.method'));

-  Expect.isTrue(

-      lookupQualifiedInScope(library, 'Class.method.c') is ParameterMirror);

-  

-  // `field` should not be found through the prefix `Subclass`.

-  Expect.isNull(lookupQualifiedInScope(library, 'Subclass.field'));

-  Expect.equals(Subclass_subfield, 

-                lookupQualifiedInScope(library, 'Subclass.subfield'));

-  

-  Expect.equals(Future_, lookupQualifiedInScope(library, 'async.Future'));

-  Expect.isTrue(

-      lookupQualifiedInScope(library, 'async.Future.then') is MethodMirror);

-  // `Timer` should not be found through the prefix `async.Future`.

-  Expect.isNull(

-      lookupQualifiedInScope(library, 'async.Future.Timer'));

-}

-

-

+// Copyright (c) 2013, 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 dart2js.test.memory_source_file_helper;
+
+import 'package:expect/expect.dart';
+import 'memory_compiler.dart';
+import '../../../sdk/lib/_internal/compiler/implementation/mirrors/mirrors.dart';
+import '../../../sdk/lib/_internal/compiler/implementation/mirrors/mirrors_util.dart';
+
+const Map MEMORY_SOURCE_FILES = const {
+  'main.dart': r"""
+
+library main;
+
+import 'dart:async' as async show Future;
+
+var variable;
+
+method(a, [b]) {}
+
+class Class<A> {
+  var field;
+  var variable;
+  method(c, {d}) {}
+}
+
+class Subclass<B> extends Class<B> {
+  var subfield;
+}
+""",
+};
+
+void main() {
+  mirrorSystemFor(MEMORY_SOURCE_FILES).then(
+      (MirrorSystem mirrors) => test(mirrors),
+      onError: (e) => Expect.fail('$e'));
+}
+
+void test(MirrorSystem mirrors) {
+  LibraryMirror dartCore = mirrors.libraries[Uri.parse('dart:core')];
+  Expect.isNotNull(dartCore);
+
+  LibraryMirror dartAsync = mirrors.libraries[Uri.parse('dart:async')];
+  Expect.isNotNull(dartAsync);
+
+  LibraryMirror library = mirrors.libraries[Uri.parse('memory:main.dart')];
+  Expect.isNotNull(library);
+
+  // Check top-level scope.
+
+  DeclarationMirror String_ = library.lookupInScope('String');
+  Expect.isTrue(String_ is ClassMirror);
+  Expect.equals('String', String_.simpleName);
+  Expect.equals(dartCore, String_.owner);
+
+  Expect.isNull(library.lookupInScope('async'));
+  Expect.isNull(library.lookupInScope('Future'));
+  DeclarationMirror Future_ = library.lookupInScope('async.Future');
+  Expect.isTrue(Future_ is ClassMirror);
+  Expect.equals('Future', Future_.simpleName);
+  Expect.equals(dartAsync, Future_.owner);
+  // Timer is not in scope.
+  Expect.isNull(library.lookupInScope('Timer'));
+  // async.Timer is hidden.
+  Expect.isNull(library.lookupInScope('async.Timer'));
+
+  DeclarationMirror variable = library.lookupInScope('variable');
+  Expect.isTrue(variable is VariableMirror);
+  Expect.equals('variable', variable.simpleName);
+  Expect.equals('main.variable', variable.qualifiedName);
+  Expect.equals(library, variable.owner);
+  // Parameter `a` is not in scope.
+  Expect.isNull(library.lookupInScope('a'));
+  // Parameter `b` is not in scope.
+  Expect.isNull(library.lookupInScope('b'));
+
+  DeclarationMirror method = library.lookupInScope('method');
+  Expect.isTrue(method is MethodMirror);
+  Expect.equals('method', method.simpleName);
+  Expect.equals('main.method', method.qualifiedName);
+  Expect.equals(library, method.owner);
+
+  DeclarationMirror Class = library.lookupInScope('Class');
+  Expect.isTrue(Class is ClassMirror);
+  Expect.equals('Class', Class.simpleName);
+  Expect.equals('main.Class', Class.qualifiedName);
+  Expect.equals(library, Class.owner);
+  // Type variable `A` is not in scope.
+  Expect.isNull(library.lookupInScope('A'));
+
+  DeclarationMirror Subclass = library.lookupInScope('Subclass');
+  Expect.isTrue(Subclass is ClassMirror);
+  Expect.equals('Subclass', Subclass.simpleName);
+  Expect.equals('main.Subclass', Subclass.qualifiedName);
+  Expect.equals(library, Subclass.owner);
+  // Type variable `B` is not in scope.
+  Expect.isNull(library.lookupInScope('B'));
+
+  // Check top-level declaration scope.
+  checkTopScope(DeclarationMirror declaration) {
+    Expect.equals(String_, declaration.lookupInScope('String'));
+    Expect.equals(Future_, declaration.lookupInScope('async.Future'));
+    Expect.isNull(method.lookupInScope('Timer'));
+    Expect.isNull(declaration.lookupInScope('async.Timer'));
+    Expect.equals(variable, declaration.lookupInScope('variable'));
+    Expect.equals(method, declaration.lookupInScope('method'));
+    Expect.equals(Class, declaration.lookupInScope('Class'));
+    // Type variable `A` is not in scope.
+    Expect.isNull(declaration.lookupInScope('A'));
+    // Field `field` is not in scope.
+    Expect.isNull(declaration.lookupInScope('field'));
+    Expect.equals(Subclass, declaration.lookupInScope('Subclass'));
+    // Type variable `B` is not in scope.
+    Expect.isNull(declaration.lookupInScope('B'));
+    // Field `subfield` is not in scope.
+    Expect.isNull(declaration.lookupInScope('subfield'));
+  }
+
+  checkTopScope(variable);
+  // Parameter `a` is not in scope of `variable`.
+  Expect.isNull(variable.lookupInScope('a'));
+  // Parameter `b` is not in scope of `variable`.
+  Expect.isNull(variable.lookupInScope('b'));
+
+  checkTopScope(method);
+  // Parameter `a` is in scope of `method`.
+  Expect.isTrue(method.lookupInScope('a') is ParameterMirror);
+  // Parameter `b` is in scope of `method`.
+  Expect.isTrue(method.lookupInScope('b') is ParameterMirror);
+
+  // Check class scope.
+  DeclarationMirror Class_field = Class.lookupInScope('field');
+  Expect.isTrue(Class_field is VariableMirror);
+  Expect.notEquals(variable, Class_field);
+  Expect.equals(Class, Class_field.owner);
+
+  DeclarationMirror Class_variable = Class.lookupInScope('variable');
+  Expect.isTrue(Class_variable is VariableMirror);
+  Expect.notEquals(variable, Class_variable);
+  Expect.equals(Class, Class_variable.owner);
+
+  DeclarationMirror Class_method = Class.lookupInScope('method');
+  Expect.isTrue(Class_method is MethodMirror);
+  Expect.notEquals(method, Class_method);
+  Expect.equals(Class, Class_method.owner);
+
+  checkClassScope(DeclarationMirror declaration, {bool parametersInScope}) {
+    Expect.equals(String_, declaration.lookupInScope('String'));
+    Expect.equals(Future_, declaration.lookupInScope('async.Future'));
+    Expect.isNull(declaration.lookupInScope('Timer'));
+    Expect.isNull(declaration.lookupInScope('async.Timer'));
+
+    Expect.equals(Class_field, declaration.lookupInScope('field'));
+    Expect.equals(Class_variable, declaration.lookupInScope('variable'));
+    Expect.equals(Class_method, declaration.lookupInScope('method'));
+
+    // Parameter `a` is not in scope.
+    Expect.isNull(declaration.lookupInScope('a'));
+    // Parameter `b` is not in scope.
+    Expect.isNull(declaration.lookupInScope('b'));
+
+    if (parametersInScope) {
+      // Parameter `c` is in scope.
+      Expect.isTrue(declaration.lookupInScope('c') is ParameterMirror);
+      // Parameter `d` is in scope.
+      Expect.isTrue(declaration.lookupInScope('d') is ParameterMirror);
+    } else {
+      // Parameter `c` is not in scope.
+      Expect.isNull(declaration.lookupInScope('c'));
+      // Parameter `d` is not in scope.
+      Expect.isNull(declaration.lookupInScope('d'));
+    }
+
+    Expect.equals(Class, declaration.lookupInScope('Class'));
+    // Type variable `A` is in scope.
+    Expect.isTrue(declaration.lookupInScope('A') is TypeVariableMirror);
+    Expect.equals(Subclass, declaration.lookupInScope('Subclass'));
+    // Type variable `B` is not in scope.
+    Expect.isNull(declaration.lookupInScope('B'));
+    // Field `subfield` is not in scope.
+    Expect.isNull(declaration.lookupInScope('subfield'));
+  }
+  checkClassScope(Class, parametersInScope: false);
+  checkClassScope(Class_field, parametersInScope: false);
+  checkClassScope(Class_variable, parametersInScope: false);
+  checkClassScope(Class_method, parametersInScope: true);
+
+  // Check class scope.
+  DeclarationMirror Subclass_subfield = Subclass.lookupInScope('subfield');
+  Expect.isTrue(Subclass_subfield is VariableMirror);
+  Expect.notEquals(variable, Subclass_subfield);
+  Expect.equals(Subclass, Subclass_subfield.owner);
+
+  checkSubclassScope(DeclarationMirror declaration) {
+    Expect.equals(String_, declaration.lookupInScope('String'));
+    Expect.equals(Future_, declaration.lookupInScope('async.Future'));
+    Expect.isNull(declaration.lookupInScope('Timer'));
+    Expect.isNull(declaration.lookupInScope('async.Timer'));
+
+    // Top level `variable` is in scope.
+    Expect.equals(variable, declaration.lookupInScope('variable'));
+    // Top level `method` is in scope.
+    Expect.equals(method, declaration.lookupInScope('method'));
+
+    // Parameter `a` is not in scope
+    Expect.isNull(declaration.lookupInScope('a'));
+    // Parameter `b` is not in scope
+    Expect.isNull(declaration.lookupInScope('b'));
+
+    // Parameter `c` is not in scope.
+    Expect.isNull(declaration.lookupInScope('c'));
+    // Parameter `d` is not in scope.
+    Expect.isNull(declaration.lookupInScope('d'));
+
+    Expect.equals(Class, declaration.lookupInScope('Class'));
+    // Type variable `A` is not in scope
+    Expect.isNull(declaration.lookupInScope('A'));
+    // Field `field` is in scope
+    Expect.equals(Class_field, declaration.lookupInScope('field'));
+    Expect.equals(Subclass, declaration.lookupInScope('Subclass'));
+    // Type variable `B` is in scope
+    Expect.isTrue(declaration.lookupInScope('B') is TypeVariableMirror);
+    // Field `subfield` is in scope
+    Expect.equals(Subclass_subfield, declaration.lookupInScope('subfield'));
+  }
+  checkSubclassScope(Subclass);
+  checkSubclassScope(Subclass_subfield);
+
+  // `Timer` is in scope of `Future`.
+  Expect.isTrue(Future_.lookupInScope('Timer') is ClassMirror);
+
+  // Check qualified lookup.
+  Expect.equals(variable, lookupQualifiedInScope(library, 'variable'));
+  Expect.equals(method, lookupQualifiedInScope(library, 'method'));
+  Expect.isTrue(lookupQualifiedInScope(library, 'method.a') is ParameterMirror);
+
+  Expect.equals(Class, lookupQualifiedInScope(library, 'Class'));
+  Expect.isTrue(
+      lookupQualifiedInScope(library, 'Class.A') is TypeVariableMirror);
+
+  Expect.isNull(library.lookupInScope('Class.field'));
+  Expect.equals(Class_field, lookupQualifiedInScope(library, 'Class.field'));
+
+  Expect.equals(Class_method, lookupQualifiedInScope(library, 'Class.method'));
+  Expect.isTrue(
+      lookupQualifiedInScope(library, 'Class.method.c') is ParameterMirror);
+
+  // `field` should not be found through the prefix `Subclass`.
+  Expect.isNull(lookupQualifiedInScope(library, 'Subclass.field'));
+  Expect.equals(Subclass_subfield,
+                lookupQualifiedInScope(library, 'Subclass.subfield'));
+
+  Expect.equals(Future_, lookupQualifiedInScope(library, 'async.Future'));
+  Expect.isTrue(
+      lookupQualifiedInScope(library, 'async.Future.then') is MethodMirror);
+  // `Timer` should not be found through the prefix `async.Future`.
+  Expect.isNull(
+      lookupQualifiedInScope(library, 'async.Future.Timer'));
+}
diff --git a/tests/compiler/dart2js/mirrors_used_test.dart b/tests/compiler/dart2js/mirrors_used_test.dart
new file mode 100644
index 0000000..09fdd29
--- /dev/null
+++ b/tests/compiler/dart2js/mirrors_used_test.dart
@@ -0,0 +1,95 @@
+// Copyright (c) 2013, 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.
+
+/// Test that the @MirrorsUsed annotation suppress hints and that only
+/// requested elements are retained for reflection.
+library dart2js.test.mirrors_used_test;
+
+import 'package:expect/expect.dart';
+
+import 'memory_compiler.dart' show
+    compilerFor;
+
+import '../../../sdk/lib/_internal/compiler/implementation/apiimpl.dart' show
+    Compiler;
+
+import '../../../sdk/lib/_internal/compiler/implementation/dart2jslib.dart' show
+    SourceString;
+
+import
+    '../../../sdk/lib/_internal/compiler/implementation/elements/elements.dart'
+show
+    Elements;
+
+void expectOnlyVerboseInfo(Uri uri, int begin, int end, String message, kind) {
+  if (kind.name == 'verbose info') {
+    print(message);
+    return;
+  }
+  throw '$uri:$begin:$end: $kind: $message';
+}
+
+void main() {
+  Compiler compiler = compilerFor(
+      MEMORY_SOURCE_FILES, diagnosticHandler: expectOnlyVerboseInfo);
+  compiler.runCompiler(Uri.parse('memory:main.dart'));
+
+  print('');
+  List generatedCode =
+      Elements.sortedByPosition(compiler.enqueuer.codegen.generatedCode.keys);
+  for (var element in generatedCode) {
+    print(element);
+  }
+  print('');
+
+  // This assertion can fail for two reasons:
+  // 1. Too many elements retained for reflection.
+  // 2. Some code was refactored, and there are more methods.
+  // Either situation could be problematic, but in situation 2, it is often
+  // acceptable to increase [expectedMethodCount] a little.
+  int expectedMethodCount = 315;
+  Expect.isTrue(
+      generatedCode.length <= expectedMethodCount,
+      'Too many compiled methods: '
+      '${generatedCode.length} > $expectedMethodCount');
+
+  for (var library in compiler.libraries.values) {
+    library.forEachLocalMember((member) {
+      if (library == compiler.mainApp) {
+        // TODO(ahe): We currently retain the entire library. Update this test
+        // to test that only Foo is retained.
+        Expect.isTrue(
+            compiler.backend.isNeededForReflection(member), '$member');
+      } else {
+        Expect.isFalse(
+            compiler.backend.isNeededForReflection(member), '$member');
+      }
+    });
+  }
+}
+
+const MEMORY_SOURCE_FILES = const <String, String> {
+  'main.dart': """
+@MirrorsUsed(targets: const [Foo], override: '*')
+import 'dart:mirrors';
+
+import 'library.dart';
+
+class Foo {}
+
+main() {
+  useReflect(Foo);
+}
+""",
+  'library.dart': """
+library lib;
+
+import 'dart:mirrors';
+
+useReflect(type) {
+  print(new Symbol('Foo'));
+  print(MirrorSystem.getName(reflectClass(type).owner.qualifiedName));
+}
+""",
+};
diff --git a/tests/html/cssstyledeclaration_test.dart b/tests/html/cssstyledeclaration_test.dart
index 13a9730..45df00c 100644
--- a/tests/html/cssstyledeclaration_test.dart
+++ b/tests/html/cssstyledeclaration_test.dart
@@ -97,4 +97,52 @@
     // Should not throw an error.
     element.style.background = 'some_bad_value';
   });
+
+  test('css multi get', () {
+    var listElement = new Element.html('<ul class="foo">'
+        '<li class="bar" style="background-color: red; border-left: 10px;">'
+        '<li class="baz" style="background-color: black;>'
+        '<li class="baz classy" style="background-color: blue; ">'
+        '</ul>');
+    document.documentElement.children.add(listElement);
+
+    var elements = document.queryAll('li');
+    expect(elements.style.backgroundColor, equals('red'));
+    expect(elements.style.borderLeftWidth, equals('10px'));
+    elements = document.queryAll('.baz');
+    expect(elements.style.backgroundColor, equals('black'));
+    expect(elements.style.borderLeftWidth, equals(''));
+    elements = document.queryAll('.bar');
+    expect(elements.style.backgroundColor, equals('red'));
+  });
+
+  test('css multi set', () {
+    var listElement = new Element.html('<ul class="foo">'
+        '<li class="bar" style="background-color: red; border-left: 10px;">'
+        '<li class="baz" style="background-color: black;>'
+        '<li class="baz" id="wat" style="background-color: blue; ">'
+        '</ul>');
+    document.documentElement.children.add(listElement);
+
+    var elements = document.queryAll('li');
+    elements.style.backgroundColor = 'green';
+    expect(elements.style.backgroundColor, equals('green'));
+    expect(elements.style.borderLeftWidth, equals('10px'));
+
+    elements = document.queryAll('.baz');
+    expect(elements.style.backgroundColor, equals('green'));
+    elements.style.backgroundColor = 'yellow';
+    expect(elements.style.backgroundColor, equals('yellow'));
+    expect(elements.style.borderLeftWidth, equals(''));
+
+    elements = document.queryAll('.bar');
+    expect(elements.style.backgroundColor, equals('green'));
+    elements = document.queryAll('#wat');
+    expect(elements.style.backgroundColor, equals('yellow'));
+
+    elements.style.borderLeftWidth = '18px';
+    expect(elements.style.borderLeftWidth, equals('18px'));
+    elements = document.queryAll('li');
+    expect(elements.style.borderLeftWidth, equals('10px'));
+  });
 }
diff --git a/tests/html/custom_elements_test.dart b/tests/html/custom_elements_test.dart
index 7e17912..71714b3 100644
--- a/tests/html/custom_elements_test.dart
+++ b/tests/html/custom_elements_test.dart
@@ -2,9 +2,9 @@
 // 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 blob_test;
+library custom_elements_test;
 import '../../pkg/unittest/lib/unittest.dart';
-import '../../pkg/unittest/lib/html_config.dart';
+import '../../pkg/unittest/lib/html_individual_config.dart';
 import 'dart:html';
 
 class CustomType extends Element {
@@ -17,77 +17,82 @@
 class NotAnElement {}
 
 main() {
-  useHtmlConfiguration();
+  useHtmlIndividualConfiguration();
 
-  test('register', () {
-    document.register('x-type1', CustomType);
+  group('register', () {
+    test('register', () {
+      document.register('x-type1', CustomType);
 
-    var element = new Element.tag('x-type1');
-    expect(element, isNotNull);
-    expect(element is CustomType, isTrue);
-    expect(element.onCreatedCalled, isTrue);
-  });
+      var element = new Element.tag('x-type1');
+      expect(element, isNotNull);
+      expect(element is CustomType, isTrue);
+      expect(element.onCreatedCalled, isTrue);
+    });
 
-  test('register twice', () {
-    document.register('x-type2', CustomType);
-    expect(() {
+    test('register twice', () {
       document.register('x-type2', CustomType);
-    }, throws, reason: 'Cannot register a tag more than once.');
+      expect(() {
+        document.register('x-type2', CustomType);
+      }, throws, reason: 'Cannot register a tag more than once.');
 
-    document.register('x-type3', CustomType);
+      document.register('x-type3', CustomType);
 
-    var element = new Element.tag('x-type3');
-    expect(element, isNotNull);
-    expect(element is CustomType, isTrue);
-  });
-
-  test('register null', () {
-    expect(() {
-      document.register('x-type4', null);
-    }, throws, reason: 'Cannot register a null type.');
-  });
-
-  test('register native', () {
-    expect(() {
-      document.register('x-type5', BodyElement);
-    }, throws, reason: 'Cannot register a native element.');
-  });
-
-  test('register non-element', () {
-    expect(() {
-      document.register('x-type6', NotAnElement);
-    }, throws, reason: 'Cannot register a non-element.');
-  });
-
-  test('pre-registration construction', () {
-    var dom = new Element.html('<div><x-type7></x-type7></div>');
-    var preElement = dom.children[0];
-    expect(preElement, isNotNull);
-    expect(preElement is UnknownElement, isTrue);
-    var firedOnPre = false;
-    preElement.onFocus.listen((_) {
-      firedOnPre = true;
+      var element = new Element.tag('x-type3');
+      expect(element, isNotNull);
+      expect(element is CustomType, isTrue);
     });
 
-    document.register('x-type7', CustomType);
-
-    var postElement = dom.children[0];
-    expect(postElement, isNotNull);
-    expect(postElement is CustomType, isTrue);
-    expect(postElement.onCreatedCalled, isTrue);
-
-    // Element from first query remains an UnknownElement.
-    expect(preElement is UnknownElement, isTrue);
-    expect(preElement.parent, isNull);
-    expect(dom.children.length, 1);
-
-    var firedOnPost = false;
-    postElement.onFocus.listen((_) {
-      firedOnPost = true;
+    test('register null', () {
+      expect(() {
+        document.register('x-type4', null);
+      }, throws, reason: 'Cannot register a null type.');
     });
-    // Event handlers should not persist to new element.
-    postElement.dispatchEvent(new Event('focus'));
-    expect(firedOnPre, isFalse);
-    expect(firedOnPost, isTrue);
+
+    test('register native', () {
+      expect(() {
+        document.register('x-type5', BodyElement);
+      }, throws, reason: 'Cannot register a native element.');
+    });
+
+    test('register non-element', () {
+      expect(() {
+        document.register('x-type6', NotAnElement);
+      }, throws, reason: 'Cannot register a non-element.');
+    });
+  });
+
+  group('preregister', () {
+    // TODO(vsm): Modify this test once we agree on the proper semantics.
+    test('pre-registration construction', () {
+      var dom = new Element.html('<div><x-type7></x-type7></div>');
+      var preElement = dom.children[0];
+      expect(preElement, isNotNull);
+      expect(preElement is UnknownElement, isTrue);
+      var firedOnPre = false;
+      preElement.onFocus.listen((_) {
+        firedOnPre = true;
+      });
+
+      document.register('x-type7', CustomType);
+
+      var postElement = dom.children[0];
+      expect(postElement, isNotNull);
+      expect(postElement is CustomType, isTrue);
+      expect(postElement.onCreatedCalled, isTrue);
+
+      // Element from first query remains an UnknownElement.
+      expect(preElement is UnknownElement, isTrue);
+      expect(preElement.parent, isNull);
+      expect(dom.children.length, 1);
+
+      var firedOnPost = false;
+      postElement.onFocus.listen((_) {
+        firedOnPost = true;
+      });
+      // Event handlers should not persist to new element.
+      postElement.dispatchEvent(new Event('focus'));
+      expect(firedOnPre, isFalse);
+      expect(firedOnPost, isTrue);
+    });
   });
 }
diff --git a/tests/html/custom_tags_test.dart b/tests/html/custom_tags_test.dart
new file mode 100644
index 0000000..7ac344c
--- /dev/null
+++ b/tests/html/custom_tags_test.dart
@@ -0,0 +1,46 @@
+// Copyright (c) 2013, 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 custom_tags_test;
+import '../../pkg/unittest/lib/unittest.dart';
+import '../../pkg/unittest/lib/html_config.dart';
+import 'dart:html';
+
+main() {
+  useHtmlConfiguration();
+
+  test('create via custom tag', () {
+    var element = new Element.tag('x-basic1')..id = 'basic1';
+    document.body.nodes.add(element);
+
+    var queryById = query('#basic1');
+    expect(queryById, equals(element));
+
+    var queryByTag = queryAll('x-basic1');
+    expect(queryByTag.length, equals(1));
+    expect(queryByTag[0], equals(element));
+  });
+
+  test('custom inner html', () {
+    var element = new DivElement();
+    element.innerHtml = "<x-basic2 id='basic2'></x-basic2>";
+    document.body.nodes.add(element);
+
+    var queryById = query('#basic2');
+    expect(queryById is Element, isTrue);
+
+    var queryByTag = queryAll('x-basic2');
+    expect(queryByTag.length, equals(1));
+    expect(queryByTag[0], equals(queryById));
+  });
+
+  test('type extension inner html', () {
+    var element = new DivElement();
+    element.innerHtml = "<div is='x-basic3' id='basic3'></div>";
+    document.body.nodes.add(element);
+
+    var queryById = query('#basic3');
+    expect(queryById is DivElement, isTrue);
+  });
+}
diff --git a/tests/html/html.status b/tests/html/html.status
index e03aa5c..03be635 100644
--- a/tests/html/html.status
+++ b/tests/html/html.status
@@ -3,11 +3,21 @@
 # BSD-style license that can be found in the LICENSE file.
 
 async_window_test: Skip #TODO(gram): investigating
-
 event_test: Skip  # Issue 1996
-custom_elements_test: Skip # Not yet implemented.
 interactive_test: Skip # Must be run manually.
 
+# Issue 9326
+custom_elements_test/register: Fail
+custom_elements_test/preregister: Fail
+
+[ $compiler == dart2js ]
+# Document.register is unimplemented.
+custom_elements_test: Skip
+
+[ $compiler == dartanalyzer ]
+# Document.register is unimplemented.
+custom_elements_test: Skip
+
 [ $compiler == none && ($runtime == drt || $runtime == dartium) && $mode == debug && $system == macos]
 audiobuffersourcenode_test: Pass, Fail, Crash # http://crbug.com/256601
 
diff --git a/tests/html/serialized_script_value_test.dart b/tests/html/serialized_script_value_test.dart
index afbf04c..af673b6 100644
--- a/tests/html/serialized_script_value_test.dart
+++ b/tests/html/serialized_script_value_test.dart
@@ -36,4 +36,17 @@
   serializationTest('simple list', simpleList);
   serializationTest('dag list', dagList);
   serializationTest('cyclic list', cyclicList);
+
+  serializationTest('datetime', [new DateTime.now()]);
+
+  var blob = new Blob(
+      ['Indescribable... Indestructible! Nothing can stop it!'],
+      'text/plain');
+  serializationTest('blob', [blob]);
+
+  var canvas = new CanvasElement();
+  canvas.width = 100;
+  canvas.height = 100;
+  var imageData = canvas.context2D.getImageData(0, 0, 1, 1);
+  serializationTest('imagedata', [imageData]);
 }
diff --git a/tests/html/svgelement_test.dart b/tests/html/svgelement_test.dart
index 6bc60b0..f94baae 100644
--- a/tests/html/svgelement_test.dart
+++ b/tests/html/svgelement_test.dart
@@ -439,4 +439,14 @@
       expect(rect.height, closeTo(100, 1));
     });
   });
+
+  group('PathElement', () {
+    test('pathSegList', () {
+      svg.PathElement path =
+          new svg.SvgElement.svg('<path d="M 100 100 L 300 100 L 200 300 z"/>');
+      for (var seg in path.pathSegList) {
+        expect(seg is svg.PathSeg, isTrue);
+      }
+    });
+  });
 }
diff --git a/tests/html/utils.dart b/tests/html/utils.dart
index 24e7711..38ed073 100644
--- a/tests/html/utils.dart
+++ b/tests/html/utils.dart
@@ -41,6 +41,16 @@
     eItems.add(expected);
     aItems.add(actual);
 
+    if (expected is Blob) {
+      expect(actual is Blob, isTrue,
+          reason: '$actual is Blob');
+      expect(expected.type, equals(actual.type),
+          reason: message(path, '.type'));
+      expect(expected.size, equals(actual.size),
+          reason: message(path, '.size'));
+      return;
+    }
+
     if (expected is ByteBuffer) {
       expect(actual is ByteBuffer, isTrue,
           reason: '$actual is ByteBuffer');
@@ -51,6 +61,26 @@
       return;
     }
 
+    if (expected is DateTime) {
+      expect(actual is DateTime, isTrue,
+          reason: '$actual is DateTime');
+      expect(expected.millisecondsSinceEpoch,
+          equals(actual.millisecondsSinceEpoch),
+          reason: message(path, '.millisecondsSinceEpoch'));
+      return;
+    }
+
+    if (expected is ImageData) {
+      expect(actual is ImageData, isTrue,
+          reason: '$actual is ImageData');
+      expect(expected.width, equals(actual.width),
+          reason: message(path, '.width'));
+      expect(expected.height, equals(actual.height),
+          reason: message(path, '.height'));
+      walk('$path.data', expected.data, actual.data);
+      return;
+    }
+
     if (expected is TypedData) {
       expect(actual is TypedData, isTrue,
           reason: '$actual is TypedData');
diff --git a/tests/language/allocation_sinking_inlining_test.dart b/tests/language/allocation_sinking_inlining_test.dart
new file mode 100644
index 0000000..9ed27b6
--- /dev/null
+++ b/tests/language/allocation_sinking_inlining_test.dart
@@ -0,0 +1,36 @@
+
+// Copyright (c) 2013, 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.
+// VMOptions=--optimization-counter-threshold=10 --no-use-osr
+
+// Test allocation sinking with polymorphic inlining.
+
+import "package:expect/expect.dart";
+
+class A {
+  foo(x) => ++x.f;
+}
+
+class B {
+  foo(x) => --x.f;
+}
+
+class C {
+  int f = 0;
+}
+
+test(obj) {
+  var c = new C();
+  return obj.foo(c);
+}
+
+main() {
+  var a = new A();
+  var b = new B();
+  Expect.equals(1, test(a));
+  Expect.equals(-1, test(b));
+  for (var i = 0; i < 20; i++) test(a);
+  Expect.equals(1, test(a));
+  Expect.equals(-1, test(b));
+}
diff --git a/tests/language/equality_test.dart b/tests/language/equality_test.dart
index a0faac4..208ed0c 100644
--- a/tests/language/equality_test.dart
+++ b/tests/language/equality_test.dart
@@ -1,7 +1,7 @@
 // Copyright (c) 2012, 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.
-// VMOptions=--optimization-counter-threshold=10
+// VMOptions=--optimization-counter-threshold=10 --no-use-osr
 
 import "package:expect/expect.dart";
 
@@ -53,6 +53,30 @@
   }
 }
 
+boolEqualityPositiveA(a) => a == true;
+boolEqualityNegativeA(a) => a != true;
+
+boolEqualityPositiveB(a) => true == a;
+boolEqualityNegativeB(a) => true != a;
+
 main() {
-  for (int i = 0; i < 20; i++) tests();
+  for (int i = 0; i < 20; i++) {
+    tests();
+    // Do not inline calls to prevent constant folding.
+    Expect.isTrue(boolEqualityPositiveA(true));
+    Expect.isFalse(boolEqualityPositiveA(false));
+    Expect.isFalse(boolEqualityNegativeA(true));
+    Expect.isTrue(boolEqualityNegativeA(false));
+
+    Expect.isTrue(boolEqualityPositiveB(true));
+    Expect.isFalse(boolEqualityPositiveB(false));
+    Expect.isFalse(boolEqualityNegativeB(true));
+    Expect.isTrue(boolEqualityNegativeB(false));
+  }
+
+  // Deoptimize.
+  Expect.isFalse(boolEqualityPositiveA(1));
+  Expect.isTrue(boolEqualityNegativeA("hi"));
+  Expect.isFalse(boolEqualityPositiveB(2.0));
+  Expect.isTrue(boolEqualityNegativeB([]));
 }
diff --git a/tests/language/function_subtype_local6_test.dart b/tests/language/function_subtype_local6_test.dart
new file mode 100644
index 0000000..95817d1
--- /dev/null
+++ b/tests/language/function_subtype_local6_test.dart
@@ -0,0 +1,17 @@
+// Copyright (c) 2013, 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.
+// Dart test program for constructors and initializers.
+// VMOptions=--no-eliminate-type-checks
+
+// Regression test for issue 12127.
+
+class C<T> {
+  void test() {
+    void foo(T a) {}
+  }
+}
+
+main() {
+  new C<bool>().test();
+}
diff --git a/tests/language/instanceof3_test.dart b/tests/language/instanceof3_test.dart
index 5075840..746c8bf 100644
--- a/tests/language/instanceof3_test.dart
+++ b/tests/language/instanceof3_test.dart
@@ -5,8 +5,8 @@
 
 import "package:expect/expect.dart";
 
-// In the type test 'e is T', it is a run-time error if T does not denote a type
-// available in the current lexical scope.
+// In the type test 'e is T', if T does not denote a type available in the
+// current lexical scope, then T is mapped to dynamic and the test succeeds.
 
 isCheckedMode() {
   try {
@@ -23,23 +23,23 @@
     bool got_type_error = false;
     var x = null;
     try {
-      Expect.isFalse(x is UndeclaredType);  // x is null.
+      Expect.isTrue(x is UndeclaredType);  // x is null.
     } on TypeError catch (error) {
       got_type_error = true;
     }
-    // Type error in production mode and in checked mode.
-    Expect.isTrue(got_type_error);
+    // No type error.
+    Expect.isFalse(got_type_error);
   }
   {
     bool got_type_error = false;
     var x = 1;
     try {
-      Expect.isFalse(x is UndeclaredType);  // x is not null.
+      Expect.isTrue(x is UndeclaredType);  // x is not null.
     } on TypeError catch (error) {
       got_type_error = true;
     }
-    // Type error in production mode and in checked mode.
-    Expect.isTrue(got_type_error);
+    // No type error.
+    Expect.isFalse(got_type_error);
   }
   {
     bool got_type_error = false;
@@ -49,8 +49,8 @@
     } on TypeError catch (error) {
       got_type_error = true;
     }
-    // Type error in checked mode only.
-    Expect.isTrue(got_type_error == isCheckedMode());
+    // No type error.
+    Expect.isFalse(got_type_error);
   }
   {
     bool got_type_error = false;
@@ -60,8 +60,8 @@
     } on TypeError catch (error) {
       got_type_error = true;
     }
-    // Type error in checked mode only.
-    Expect.isTrue(got_type_error == isCheckedMode());
+    // No type error.
+    Expect.isFalse(got_type_error);
   }
   {
     bool got_type_error = false;
@@ -71,8 +71,8 @@
     } on TypeError catch (error) {
       got_type_error = true;
     }
-    // Type error in checked mode only.
-    Expect.isTrue(got_type_error == isCheckedMode());
+    // No type error.
+    Expect.isFalse(got_type_error);
   }
   {
     bool got_type_error = false;
@@ -82,8 +82,8 @@
     } on TypeError catch (error) {
       got_type_error = true;
     }
-    // Type error in checked mode only.
-    Expect.isTrue(got_type_error == isCheckedMode());
+    // No type error.
+    Expect.isFalse(got_type_error);
   }
 }
 
diff --git a/tests/language/isnot_malformed_type_test.dart b/tests/language/isnot_malformed_type_test.dart
index 593fc75..11abe66 100644
--- a/tests/language/isnot_malformed_type_test.dart
+++ b/tests/language/isnot_malformed_type_test.dart
@@ -1,13 +1,14 @@
 // Copyright (c) 2012, 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.
-// Parser throws an error when parsing x is! T with malformed type T.
+
+import 'package:expect/expect.dart';
 
 f(obj) {
-  // 'Baz' is not loaded error.
-  return (obj is !Baz);  /// 01: runtime error
+  // 'Baz' is not loaded, mapped to dynamic.
+  return (obj is !Baz);
 }
 
 main () {
-  f(null);  
+  Expect.isFalse(f(null));
 }
diff --git a/tests/language/language.status b/tests/language/language.status
index 67e3e67..e788b73 100644
--- a/tests/language/language.status
+++ b/tests/language/language.status
@@ -80,40 +80,6 @@
 const_constructor_mixin2_test/01: Fail # Issue 11917
 const_constructor_mixin3_test/01: Fail # Issue 11917
 
-is_not_class2_test: Fail # Issue 9055
-list_literal_syntax_test/01: Fail # Issue 9055
-list_literal_syntax_test/02: Fail # Issue 9055
-list_literal_syntax_test/03: Fail # Issue 9055
-malformed_inheritance_test/02: Fail # Issue 9055
-malformed_inheritance_test/04: Fail # Issue 9055
-malformed_inheritance_test/06: Fail # Issue 9055
-malformed_test/none: Fail # Issue 9055
-prefix9_test: Fail # Issue 9055
-try_catch_on_syntax_test/07: Fail # Issue 9055
-try_catch_syntax_test/08: Fail # Issue 9055
-type_variable_bounds_test/08: Fail # Issue 9055
-wrong_number_type_arguments_test/01: Fail # Issue 9055
-
-[ $compiler == none && $checked ]
-function_malformed_result_type_test: Fail # Issue 9055
-new_expression_type_args_test/02: Fail # Issue 9055
-prefix16_test: Fail # Issue 9055
-type_parameter_test/01: Fail # Issue 9055
-type_parameter_test/02: Fail # Issue 9055
-type_parameter_test/03: Fail # Issue 9055
-type_parameter_test/04: Fail # Issue 9055
-type_parameter_test/05: Fail # Issue 9055
-type_parameter_test/06: Fail # Issue 9055
-type_variable_bounds_test/07: Fail # Issue 9055
-type_variable_scope2_test: Fail # Issue 9055
-type_variable_scope_test/00: Fail # Issue 9055
-type_variable_scope_test/01: Fail # Issue 9055
-type_variable_scope_test/02: Fail # Issue 9055
-type_variable_scope_test/03: Fail # Issue 9055
-type_variable_scope_test/04: Fail # Issue 9055
-type_variable_scope_test/05: Fail # Issue 9055
-wrong_number_type_arguments_test/02: Fail # Issue 9055
-
 [ $compiler == none && $unchecked ]
 
 # Only checked mode reports an error on type assignment
@@ -337,18 +303,6 @@
 
 bound_closure_equality_test: Fail # Issue 10849
 
-is_not_class2_test: Fail # Issue 9055
-list_literal_syntax_test/01: Fail # Issue 9055
-list_literal_syntax_test/02: Fail # Issue 9055
-list_literal_syntax_test/03: Fail # Issue 9055
-malformed_inheritance_test/02: Fail # Issue 9055
-malformed_inheritance_test/04: Fail # Issue 9055
-malformed_inheritance_test/06: Fail # Issue 9055
-malformed_test/none: Fail # Issue 9055
-try_catch_on_syntax_test/07: Fail # Issue 9055
-try_catch_syntax_test/08: Fail # Issue 9055
-
-
 [ $compiler == dart2dart && $minified ]
 super_getter_setter_test: Fail # Issue 11065.
 
diff --git a/tests/language/language_analyzer.status b/tests/language/language_analyzer.status
index 82e8b5f..e977432 100644
--- a/tests/language/language_analyzer.status
+++ b/tests/language/language_analyzer.status
@@ -3,76 +3,15 @@
 # BSD-style license that can be found in the LICENSE file.
 
 [ $compiler == dartanalyzer ]
+
+# Runtime negative test. No static errors or warnings.
+closure_call_wrong_argument_count_negative_test: skip
+
+
 #argument_definition_test/01: fail  # issue 11565 (passing for the wrong reason)
 
 illegal_invocation_test/01: fail # Issue: 11892
 
-# test issue 11581, it is not warning to call dynamic
-call_through_getter_test: fail
-
-# test issue 11582, non-final field with 'const' constructor
-compile_time_constant10_test/none: fail
-
-# test issue 11583, int is valid key for constant map literal
-compile_time_constant_c_test/01: fail
-
-# test issue 11589, export D from 2 export directives
-export_cyclic_test: fail
-
-# test issue 11580, Function is not a malformed type
-black_listed_test/11: fail
-
-# test issue 11584, positional arguments cannot be used for named parameters
-compile_time_constant_e_test: fail
-
-# test issue 11585, static warning, not negative test
-constructor3_negative_test: fail # issue 11585
-constructor_call_wrong_argument_count_negative_test: fail
-instance_call_wrong_argument_count_negative_test: fail
-
-# test issue 11586, Class(args) is compile-time warning, not error
-constructor_negative_test: fail
-
-# test issue 11590, runtime only negative test
-field_method4_negative_test: fail
-
-# test issue 11591, assigning to the final variable is warning, not error
-final_for_in_variable_test/01: fail
-final_param_negative_test: fail
-final_var_negative_test: fail
-final_variable_assignment_test/01: fail
-final_variable_assignment_test/02: fail
-final_variable_assignment_test/03: fail
-final_variable_assignment_test/04: fail
-getter_no_setter_test/01: fail
-
-# test issue 11592, Function type alias (typedef) is not a constant
-first_class_types_constants_test: fail
-
-# test issue 11594, Reference to a not resolve identifier is static warning
-import_combinators_negative_test: fail
-interface_static_non_final_fields_negative_test: fail
-
-# test issue 11595, It is static warning to create instance (new) of the malformed type
-instantiate_type_variable_negative_test: fail
-
-# test issue 11596. e is Unknown is not a compile time error
-is_not_class2_negative_test: fail
-
-# test issue 11597, It is a compile-time error if part has no "part of" directive
-library_juxtaposition_test: fail
-
-# test issue 11598, 	Any use of a malbounded type gives rise to a static warning
-mixin_type_parameters_errors_test/01: fail
-mixin_type_parameters_errors_test/02: fail
-mixin_type_parameters_errors_test/05: fail
-
-
-
-
-# TBF: a.imethod = () { return 1; };
-assign_instance_method_negative_test: fail
-
 # TBF: m([int p = 'String'])
 assign_static_type_test/06: fail
 
@@ -84,25 +23,14 @@
 cast_test/05: fail
 
 # TBF: It is a compile-time error if the superclass of a class C appears in the implements clause of C.
-closure_call_wrong_argument_count_negative_test: fail
 const_constructor_super_test/01: fail
 compile_time_constant10_test/none: fail
 compile_time_constant_c_test/01: fail
 
-# Runtime negative test. No static errors or warnings.
-closure_call_wrong_argument_count_negative_test: skip
-
 # TBF: m([int p = 'String']) and call 'const' instance creation
 compile_time_constant_checked2_test/03: fail
 compile_time_constant_checked3_test/03: fail
 
-# TBF: not initialized final instance variable
-constructor2_negative_test: fail
-constructor3_negative_test: fail
-constructor_call_wrong_argument_count_negative_test: fail
-constructor_initializer_test: fail # uses argument definition test
-constructor_negative_test: fail
-
 # TBF: It is a static type warning if a type parameter is a supertype of its upper bound.
 cyclic_type_variable_test/01: fail
 cyclic_type_variable_test/02: fail
@@ -125,54 +53,44 @@
 list_literal_syntax_test/02: fail # Issue 12103
 list_literal_syntax_test/03: fail # Issue 12103
 malformed_test/none: fail
+
+# TBF: disallowed in the most recent spec
 named_parameters_aggregated_test/03: fail
-no_such_method_negative_test: fail
+
+# TBF: non-const superinitializer; 7.6.3 Constant Constructors: The superinitializer that appears, explicitly or implicitly, in the initializer list of a constant constructor must specify a constant constructor of the superclass of the immediately enclosing class.
 non_const_super_negative_test: fail
+
+# TBF: 1is int; invalid character in number
 number_identifier_negative_test: fail
+
+# TBF: we should check conflicts not only for methods, but for accessors too
 override_field_test/01: fail
 override_field_test/02: fail
 override_field_test/03: fail
+
+# TBF: prefix T hidden by type variable T in 'new T.Class()'
 prefix10_negative_test: fail
-prefix11_negative_test: fail
-prefix12_negative_test: fail
-prefix1_negative_test: fail
-prefix2_negative_test: fail
-prefix4_negative_test: fail
-prefix5_negative_test: fail
-prefix6_negative_test: fail
-prefix8_negative_test: fail
-prefix9_negative_test: fail
+
+# TBF: no error if A in our library, B extends A in other library, reference B._private from Test extends B in our library.
 private_member1_negative_test: fail
 private_member2_negative_test: fail
 private_member3_negative_test: fail
-pseudo_kw_illegal_test/14: fail
+
+# TBF
 pseudo_kw_test: fail
+
+# TBF: hiding at start of the block and declared after declaration statement
 scope_negative_test: fail
-static_call_wrong_argument_count_negative_test: fail
+
+# TBF: 'instance.staticMethod()' is static warning
 static_field_test/01: fail
 static_field_test/02: fail
 static_field_test/03: fail
-static_final_field2_negative_test: fail
-static_final_field_negative_test: fail
-syntax_test/28: fail
-syntax_test/29: fail
-syntax_test/30: fail
-syntax_test/31: fail
-syntax_test/32: fail
-syntax_test/33: fail
-throw7_negative_test: fail
-type_error_test: fail
-type_parameter_test/none: fail
-type_variable_bounds2_test/00: fail
-type_variable_bounds2_test/01: fail
-type_variable_bounds2_test/02: fail
-type_variable_bounds2_test/03: fail
-type_variable_bounds2_test/04: fail
-type_variable_bounds2_test/06: fail
-type_variable_static_context_negative_test: fail
-unresolved_in_factory_negative_test: fail
-unresolved_top_level_method_negative_test: fail
-unresolved_top_level_var_negative_test: fail
+
+library_ambiguous_test/04: Fail # TBF: Issue 12106
+
+
+
 
 # test issue 10683, It is a compile-time error if e refers to the name v or the name v=.
 block_scope_test: fail
@@ -186,6 +104,7 @@
 stack_trace_test: fail
 throw3_test: fail
 try_catch3_test: fail
+type_error_test: fail
 
 # test issue 10890; on-catch UnknownType is a static warning, not error
 try_catch_on_syntax_test/01: fail
@@ -271,10 +190,136 @@
 # test issue 11579, assignment, no setter
 getter_no_setter_test/none: fail
 
+# test issue 11580, Function is not a malformed type
+black_listed_test/11: fail
+
+# test issue 11581, it is not warning to call dynamic
+call_through_getter_test: fail
+
+# test issue 11582, non-final field with 'const' constructor
+compile_time_constant10_test/none: fail
+
+# test issue 11583, int is valid key for constant map literal
+compile_time_constant_c_test/01: fail
+
+# test issue 11584, positional arguments cannot be used for named parameters
+compile_time_constant_e_test: fail
+
+# test issue 11585, static warning, not negative test
+constructor3_negative_test: fail
+constructor_call_wrong_argument_count_negative_test: fail
+instance_call_wrong_argument_count_negative_test: fail
+
+# test issue 11586, Class(args) is compile-time warning, not error
+constructor_negative_test: fail
+
+# test issue 11589, export D from 2 export directives
+export_cyclic_test: fail
+
+# test issue 11590, runtime only negative test
+field_method4_negative_test: fail
+
+# test issue 11591, assigning to the final variable is warning, not error
+final_for_in_variable_test/01: fail
+final_param_negative_test: fail
+final_var_negative_test: fail
+final_variable_assignment_test/01: fail
+final_variable_assignment_test/02: fail
+final_variable_assignment_test/03: fail
+final_variable_assignment_test/04: fail
+getter_no_setter_test/01: fail
+
+# test issue 11592, Function type alias (typedef) is not a constant
+first_class_types_constants_test: fail
+
+# test issue 11594, Reference to a not resolve identifier is static warning
+import_combinators_negative_test: fail
+interface_static_non_final_fields_negative_test: fail
+
+# test issue 11595, It is static warning to create instance (new) of the malformed type
+instantiate_type_variable_negative_test: fail
+
+# test issue 11596. e is Unknown is not a compile time error
+is_not_class2_negative_test: fail
+
+# test issue 11597, It is a compile-time error if part has no "part of" directive
+library_juxtaposition_test: fail
+
+# test issue 11598, Any use of a malbounded type gives rise to a static warning
+mixin_type_parameters_errors_test/01: fail
+mixin_type_parameters_errors_test/02: fail
+mixin_type_parameters_errors_test/05: fail
+
+# test issue 11698, no setter, so warning, not error
+assign_instance_method_negative_test: fail
+
 # test issue 11918: mixin and const constructor
 const_constructor_mixin_test/01: fail
 const_constructor_mixin3_test/01: fail
 
+# test issue 11958, fails only at runtime
+no_such_method_negative_test: fail
+
+# test issue 11962, it is warning, not error to reference undeclared identifier
+prefix1_negative_test: fail
+prefix2_negative_test: fail
+prefix4_negative_test: fail
+prefix5_negative_test: fail
+prefix12_negative_test: fail
+
+# test issue 11963, it is fine to access any property of the dynamic variable
+prefix6_negative_test: fail
+
+# test issue 11964, Any use of a malformed type gives rise to a static warning.
+prefix8_negative_test: fail
+prefix9_negative_test: fail
+prefix11_negative_test: fail
+
+# test issue 11965, 'source' is not built-in identifier anymore
+pseudo_kw_illegal_test/14: fail
+
+# test issue 12156, fails only at runtime
+static_call_wrong_argument_count_negative_test: fail
+
+# test issue 12157, uninitializer instance variable is warning, so not negative test
+static_final_field_negative_test: fail
+constructor2_negative_test: fail
+
+# test issue 12158, 'native' is not in spec, so analyzer does not generate compile-time error
+syntax_test/28: fail
+syntax_test/29: fail
+syntax_test/30: fail
+syntax_test/31: fail
+syntax_test/32: fail
+syntax_test/33: fail
+
+# test issue 12159, print(exception.message_); causes static warning, not an error
+throw7_negative_test: fail
+
+# test issue 12160, not annotated warnings for type variables from static member
+type_parameter_test/none: fail
+# test issue 12161, type variable in static, malformed type, static warning
+type_variable_static_context_negative_test: fail
+
+# test issue 12162, 'a' has dynamic type, so it statically it is assignable to anything
+type_variable_bounds2_test/00: fail
+type_variable_bounds2_test/01: fail
+type_variable_bounds2_test/02: fail
+type_variable_bounds2_test/03: fail
+type_variable_bounds2_test/04: fail
+type_variable_bounds2_test/06: fail
+
+# test issue 12163, unresolved identifier is static warning in static context
+unresolved_in_factory_negative_test: fail
+unresolved_top_level_method_negative_test: fail
+unresolved_top_level_var_negative_test: fail
+
+# test issue 12181, uses argument definition test
+constructor_initializer_test: fail
+
+# test issue 12184, It is static warning, not error, to assign to a constant variable.
+static_final_field2_negative_test: fail
+
 [ $compiler == dartanalyzer && $checked ]
 factory1_test/00: fail
 factory1_test/01: fail
diff --git a/tests/language/language_dart2js.status b/tests/language/language_dart2js.status
index fa07442..528d5e9 100644
--- a/tests/language/language_dart2js.status
+++ b/tests/language/language_dart2js.status
@@ -29,6 +29,11 @@
 
 constructor_initializer_test: Fail, OK # Depends on ?parameter check.
 
+# Issues related to undeclared prefix resolution.
+malformed_test/none: Fail
+malformed_test/05: Fail
+malformed_test/06: Fail
+
 # Fails due to inlining. Not all expected frames are in the trace.
 full_stacktrace1_test: Pass, Fail  # issue 9895
 full_stacktrace2_test: Pass, Fail  # issue 9895
@@ -110,7 +115,6 @@
 call_nonexistent_constructor_test: Fail
 constructor_named_arguments_test/01: Fail # http://dartbug.com/5519
 getter_no_setter_test/01: Fail # http://dartbug.com/5519
-isnot_malformed_type_test/01: Fail # http://dartbug.com/5519
 not_enough_positional_arguments_test/01: Fail # http://dartbug.com/5519
 error_stacktrace_test: Fail # (Issue 11681).
 
@@ -163,10 +167,6 @@
 mixin_type_parameters_errors_test/02: Fail
 mixin_type_parameters_errors_test/05: Fail
 
-# new with wrong number of type arguments should be a runtime error.
-mixin_type_parameters_errors_test/03: Fail
-mixin_type_parameters_errors_test/04: Fail
-
 # External tests.
 external_test/01: Fail
 external_test/02: Fail
@@ -184,7 +184,6 @@
 
 
 # Implementation errors (library or generated code).
-instanceof3_test: Fail # cannot resolve type UndeclaredType.
 instanceof4_test: Fail # Expect.isTrue(false) fails.
 list_literal4_test: Fail # Illegal argument(s): 0 -- checked mode test.
 map_literal4_test: Fail # Attempt to modify an immutable object -- checked mode test.
diff --git a/tests/language/library_ambiguous_test.dart b/tests/language/library_ambiguous_test.dart
index 75d2fda..cb02c8d 100644
--- a/tests/language/library_ambiguous_test.dart
+++ b/tests/language/library_ambiguous_test.dart
@@ -17,7 +17,7 @@
   print(bar());  /// 01: compile-time error
   print(baz());  /// 02: compile-time error
   print(bay());  /// 03: compile-time error
-  print(main is bax);  /// 04: compile-time error
+  print(main is bax);  /// 04: static type warning
   var x = new X();  /// 05: continued
   print("No error expected if ambiguous definitions are not used.");
 }
diff --git a/tests/language/malformed_test.dart b/tests/language/malformed_test.dart
index eb2834a..8f15dff 100644
--- a/tests/language/malformed_test.dart
+++ b/tests/language/malformed_test.dart
@@ -6,6 +6,7 @@
 // wrong number of type arguments are handled as raw types.
 
 import 'package:expect/expect.dart';
+import 'package:expect/expect.dart' as prefix;  // Define 'prefix'.
 
 checkIsUnresolved(var v) {
   Expect.isTrue(v is Unresolved);
@@ -76,8 +77,7 @@
 
   checkIsListDynamic(true, []);
   checkIsListDynamic(true, <>[]); /// 01: compile-time error
-// TODO(johnniwinther): Create runtime type information on literal lists.
-//  checkIsListDynamic(false, <int>[]);
+  checkIsListDynamic(false, <int>[]);
   checkIsListDynamic(true, <Unresolved>[]);
   checkIsListDynamic(true, <Unresolved<int>>[]);
   checkIsListDynamic(true, <prefix.Unresolved>[]);
@@ -92,16 +92,16 @@
   checkIsListDynamic(true, new List<prefix.Unresolved<int>>());
   checkIsListDynamic(true, new List<int, String>());
 
+  checkIsMapDynamic(true, true, <dynamic, dynamic>{});
   checkIsMapDynamic(true, true, {});
   checkIsMapDynamic(true, true, <>{}); /// 03: compile-time error
   checkIsMapDynamic(true, true, <int>{});
-// TODO(johnniwinther): Create runtime type information on literal maps.
-//  checkIsMapDynamic(false, false, <String, int>{});
+  checkIsMapDynamic(false, false, <String, int>{});
   checkIsMapDynamic(true, true, <String, int, String>{});
-//  checkIsMapDynamic(true, false, <Unresolved, int>{});
-//  checkIsMapDynamic(false, true, <String, Unresolved<int>>{});
-//  checkIsMapDynamic(true, false,  <prefix.Unresolved, int>{});
-//  checkIsMapDynamic(false, true, <String, prefix.Unresolved<int>>{});
+  checkIsMapDynamic(true, false, <Unresolved, int>{});
+  checkIsMapDynamic(false, true, <String, Unresolved<int>>{});
+  checkIsMapDynamic(true, false,  <prefix.Unresolved, int>{});
+  checkIsMapDynamic(false, true, <String, prefix.Unresolved<int>>{});
 
   checkIsMapDynamic(true, true, new Map());
   checkIsMapDynamic(true, true, new Map<>); /// 04: compile-time error
@@ -118,28 +118,36 @@
   Expect.throws(() => new prefix.Unresolved(), (e) => true);
   Expect.throws(() => new prefix.Unresolved<int>(), (e) => true);
 
+  // The expression 'undeclared_prefix.Unresolved()' is parsed as the invocation
+  // of the named constructor 'Unresolved' on the type 'undeclared_prefix'.
+  Expect.throws(() => new undeclared_prefix.Unresolved(), (e) => true);
+  // The expression 'undeclared_prefix.Unresolved<int>' cannot be parsed.
+  Expect.throws(() => new undeclared_prefix.Unresolved<int>(), (e) => true);  /// 05: compile-time error
+
   try {
     throw 'foo';
   } on Unresolved catch (e) {
-  } catch (e) {
-    Expect.fail();
+    // Equivalent to 'on dynamic', catches 'foo'.
   }
   try {
     throw 'foo';
   } on Unresolved<int> catch (e) {
-  } catch (e) {
-    Expect.fail();
+    // Equivalent to 'on dynamic', catches 'foo'.
   }
   try {
     throw 'foo';
   } on prefix.Unresolved catch (e) {
-  } catch (e) {
-    Expect.fail();
+    // Equivalent to 'on dynamic', catches 'foo'.
   }
   try {
     throw 'foo';
   } on prefix.Unresolved<int> catch (e) {
-  } catch (e) {
-    Expect.fail();
+    // Equivalent to 'on dynamic', catches 'foo'.
+  }
+  try {
+    throw 'foo';
+  }
+    on undeclared_prefix.Unresolved<int>  /// 06: compile-time error
+    catch (e) {
   }
 }
\ No newline at end of file
diff --git a/tests/language/mixin_type_parameters_errors_test.dart b/tests/language/mixin_type_parameters_errors_test.dart
index 7938160..be459bd 100644
--- a/tests/language/mixin_type_parameters_errors_test.dart
+++ b/tests/language/mixin_type_parameters_errors_test.dart
@@ -16,7 +16,7 @@
   var a;
   a = new A();
   a = new A<int>();
-  a = new A<String, String>();  /// 03: static type warning, runtime error
+  a = new A<String, String>();  /// 03: static type warning
   a = new F<int>();
-  a = new F<int, String>();   /// 04: static type warning, runtime error
+  a = new F<int, String>();   /// 04: static type warning
 } 
\ No newline at end of file
diff --git a/tests/lib/analyzer/analyze_tests.status b/tests/lib/analyzer/analyze_tests.status
index 4011835..802f246 100644
--- a/tests/lib/analyzer/analyze_tests.status
+++ b/tests/lib/analyzer/analyze_tests.status
@@ -3,7 +3,7 @@
 # BSD-style license that can be found in the LICENSE file.
 
 [ $compiler == dartanalyzer ]
-53bit_overflow_literal_test/01: fail, ok
+javascript_int_overflow_literal_test/01: fail, ok
 
 # https://code.google.com/p/dart/issues/detail?id=11665
 standalone/assert_test: fail
@@ -32,7 +32,7 @@
 
 
 [ $compiler == dart2analyzer ]
-53bit_overflow_literal_test/01: fail, ok
+javascript_int_overflow_literal_test/01: fail, ok
 
 # https://code.google.com/p/dart/issues/detail?id=11665
 standalone/assert_test: fail
diff --git a/tests/lib/lib.status b/tests/lib/lib.status
index faa078e..0690589 100644
--- a/tests/lib/lib.status
+++ b/tests/lib/lib.status
@@ -4,10 +4,14 @@
 
 [ $compiler == dart2js ]
 math/*: Skip
+mirrors/class_mirror_type_variables_test: Fail # Issue 12087
+mirrors/invoke_private_test: Fail # Issue 12164
+mirrors/function_type_mirror_test: Fail # Issue 12166
 mirrors/method_mirror_name_test: Fail # Issue 6335
 mirrors/method_mirror_properties_test: Fail # Issue 11861
 mirrors/method_mirror_returntype_test : Fail # Issue 11928
 mirrors/mirrors_test: Fail # TODO(ahe): I'm working on fixing this.
+mirrors/null_test : Fail # Issue 12129
 mirrors/library_uri_io_test: Skip # Not intended for dart2js as it uses dart:io.
 async/run_async3_test: Fail # _enqueueImmediate runs after Timer. http://dartbug.com/9002
 async/run_async4_test: Pass, Fail # no global exception handler in isolates. http://dartbug.com/9012
@@ -89,13 +93,14 @@
 mirrors/library_metadata_test: Fail # http://dartbug.com/10906
 mirrors/parameter_test: Fail # http://dartbug.com/11567
 mirrors/operator_test: Fail # http://dartbug.com/11944
-mirrors/local_isolate_test: Fail # http://dartbug.com/12026
+mirrors/null_test: Fail # Issue 12128
 
 [ $compiler == none && $runtime == drt ]
 async/timer_isolate_test: Skip # See Issue 4997
 async/timer_not_available_test: Skip # only meant to test when there is no way to
                                      # implement timer (currently only in d8)
 mirrors/library_uri_io_test: Skip # Not intended for drt as it uses dart:io.
+mirrors/local_isolate_test: Skip # http://dartbug.com/12188
 async/run_async6_test: Fail # Issue 10910
 
 [ $compiler == none && $runtime == drt && $system == windows ]
@@ -107,3 +112,4 @@
 
 [ $arch == simmips ]
 convert/chunked_conversion_utf88_test: Pass, Slow # Issue 12025.
+convert/streamed_conversion_json_utf8_decode_test: Pass, Slow
diff --git a/tests/lib/mirrors/class_mirror_type_variables_test.dart b/tests/lib/mirrors/class_mirror_type_variables_test.dart
new file mode 100644
index 0000000..2b02bad
--- /dev/null
+++ b/tests/lib/mirrors/class_mirror_type_variables_test.dart
@@ -0,0 +1,33 @@
+// Copyright (c) 2013, 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.
+
+import "dart:mirrors";
+
+import "package:expect/expect.dart";
+
+class C<R,S,T> {
+  R foo(R r) => r; 
+  S bar(S s) => s; 
+  T baz(T t) => t; 
+}
+
+class NoTypeParams {}
+
+main() {
+  ClassMirror cm;
+  cm = reflectClass(C);
+  Expect.equals(3, cm.typeVariables.length);
+  Expect.equals(true, cm.typeVariables.containsKey(const Symbol("R")));
+  Expect.equals(true, cm.typeVariables.containsKey(const Symbol("S")));
+  Expect.equals(true, cm.typeVariables.containsKey(const Symbol("T")));
+  var values = cm.typeVariables.values;
+  values.forEach((e) {
+    Expect.equals(true, e is TypeVariableMirror);
+  });
+  Expect.equals(const Symbol("R"), values.elementAt(0).simpleName);
+  Expect.equals(const Symbol("S"), values.elementAt(1).simpleName);
+  Expect.equals(const Symbol("T"), values.elementAt(2).simpleName);
+  cm = reflectClass(NoTypeParams);
+  Expect.equals(cm.typeVariables.length, 0);
+}
diff --git a/tests/lib/mirrors/function_type_mirror_test.dart b/tests/lib/mirrors/function_type_mirror_test.dart
new file mode 100644
index 0000000..4376c83
--- /dev/null
+++ b/tests/lib/mirrors/function_type_mirror_test.dart
@@ -0,0 +1,23 @@
+// Copyright (c) 2013, 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.
+
+import "dart:mirrors";
+
+import "package:expect/expect.dart";
+
+typedef void FooFunction(int a, double b);
+
+bar(int a) {}
+
+main() {
+  TypedefMirror tm = reflectClass(FooFunction);
+  FunctionTypeMirror ftm = tm.referent;
+  Expect.equals(const Symbol("void"), ftm.returnType.simpleName);
+  Expect.equals(const Symbol("int"), ftm.parameters[0].type.simpleName);
+  Expect.equals(const Symbol("double"), ftm.parameters[1].type.simpleName);
+  ClosureMirror cm = reflect(bar);
+  ftm = cm.type;
+  Expect.equals(const Symbol("dynamic"), ftm.returnType.simpleName);
+  Expect.equals(const Symbol("int"), ftm.parameters[0].type.simpleName);
+}
diff --git a/tests/lib/mirrors/invoke_private_test.dart b/tests/lib/mirrors/invoke_private_test.dart
new file mode 100644
index 0000000..cac9f1e
--- /dev/null
+++ b/tests/lib/mirrors/invoke_private_test.dart
@@ -0,0 +1,86 @@
+// Copyright (c) 2013, 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 test.invoke_test;
+
+import 'dart:mirrors';
+
+import 'package:expect/expect.dart';
+import '../../async_helper.dart';
+
+class C {
+  var _field;
+  C() : this._field = 'default';
+  C._named(this._field);
+
+  get _getter => 'get $_field';
+  set _setter(v) => _field = 'set $v';
+  _method(x, y, z) => '$x+$y+$z';
+
+  static var _staticField = 'initial';
+  static get _staticGetter => 'sget $_staticField';
+  static set _staticSetter(v) => _staticField = 'sset $v';
+  static _staticFunction(x, y) => "($x,$y)";
+}
+
+var _libraryField = 'a priori';
+get _libraryGetter => 'lget $_libraryField';
+set _librarySetter(v) => _libraryField = 'lset $v';
+_libraryFunction(x,y) => '$x$y';
+
+main() {
+  var result;
+
+  // InstanceMirror.
+  C c = new C();
+  InstanceMirror im = reflect(c);
+  result = im.invoke(const Symbol('_method'), [2,4,8]);
+  Expect.equals('2+4+8', result.reflectee);
+
+  result = im.getField(const Symbol('_getter'));
+  Expect.equals('get default', result.reflectee);
+  result = im.getField(const Symbol('_field'));
+  Expect.equals('default', result.reflectee);
+
+  im.setField(const Symbol('_setter'), 'foo');
+  Expect.equals('set foo', c._field);
+  im.setField(const Symbol('_field'), 'bar');
+  Expect.equals('bar', c._field);
+
+
+  // ClassMirror.
+  ClassMirror cm = reflectClass(C);
+  result = cm.invoke(const Symbol('_staticFunction'),[3,4]);
+  Expect.equals('(3,4)', result.reflectee);
+
+  result = cm.getField(const Symbol('_staticGetter'));
+  Expect.equals('sget initial', result.reflectee);
+  result = cm.getField(const Symbol('_staticField'));
+  Expect.equals('initial', result.reflectee);
+
+  cm.setField(const Symbol('_staticSetter'), 'sfoo');
+  Expect.equals('sset sfoo', C._staticField);
+  cm.setField(const Symbol('_staticField'), 'sbar');
+  Expect.equals('sbar', C._staticField);
+
+  result = cm.newInstance(const Symbol('_named'), ['my value']);
+  Expect.isTrue(result.reflectee is C);
+  Expect.equals('my value', result.reflectee._field);
+
+
+  // LibraryMirror.
+  LibraryMirror lm = cm.owner;
+  result = lm.invoke(const Symbol('_libraryFunction'),[':',')']);
+  Expect.equals(':)', result.reflectee);
+
+  result = lm.getField(const Symbol('_libraryGetter'));
+  Expect.equals('lget a priori', result.reflectee);
+  result = lm.getField(const Symbol('_libraryField'));
+  Expect.equals('a priori', result.reflectee);
+
+  lm.setField(const Symbol('_librarySetter'), 'lfoo');
+  Expect.equals('lset lfoo', _libraryField);
+  lm.setField(const Symbol('_libraryField'), 'lbar');
+  Expect.equals('lbar', _libraryField);
+}
diff --git a/tests/lib/mirrors/null_test.dart b/tests/lib/mirrors/null_test.dart
new file mode 100644
index 0000000..9142c6d
--- /dev/null
+++ b/tests/lib/mirrors/null_test.dart
@@ -0,0 +1,31 @@
+// Copyright (c) 2013, 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 test.null_test;
+
+import 'dart:mirrors';
+
+import 'package:expect/expect.dart';
+
+main() {
+  InstanceMirror nullMirror = reflect(null);
+  Expect.isTrue(nullMirror.getField(const Symbol('hashCode')).reflectee is int);
+  Expect.equals('Null',
+                nullMirror.getField(const Symbol('runtimeType')).reflectee
+                .toString());
+  Expect.isTrue(nullMirror.invoke(const Symbol('=='), [null]).reflectee);
+  Expect.isFalse(nullMirror.invoke(const Symbol('=='), [new Object()])
+                 .reflectee);
+  Expect.equals('null',
+                nullMirror.invoke(const Symbol('toString'), []).reflectee);
+  Expect.throws(() => nullMirror.invoke(const Symbol('notDefined'), []),
+                (e) => e is NoSuchMethodError,
+                'noSuchMethod');
+
+  ClassMirror NullMirror = nullMirror.type;
+  Expect.equals(const Symbol('Null'), NullMirror.simpleName);
+  Expect.equals(const Symbol('Object'), NullMirror.superclass.simpleName);
+  Expect.equals(null, NullMirror.superclass.superclass);
+  Expect.equals(null, NullMirror.owner);  // Null belongs to no library.
+}
diff --git a/tests/lib/typed_data/float32x4_cross_test.dart b/tests/lib/typed_data/float32x4_cross_test.dart
new file mode 100644
index 0000000..0816846
--- /dev/null
+++ b/tests/lib/typed_data/float32x4_cross_test.dart
@@ -0,0 +1,50 @@
+// Copyright (c) 2013, 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.
+// VMOptions=--optimization-counter-threshold=10
+
+// Library tag to be able to run in html test framework.
+library float32x4_cross_test;
+
+import 'dart:typed_data';
+import 'package:expect/expect.dart';
+
+Float32x4 cross(Float32x4 a, Float32x4 b) {
+  var t0 = a.yzxw;
+  var t1 = b.zxyw;
+  var l = t0 * t1;
+  t0 = a.zxyw;
+  t1 = b.yzxw;
+  var r = t0 * t1;
+  return l-r;
+}
+
+void testCross(Float32x4 a, Float32x4 b, Float32x4 r) {
+  var x = cross(a, b);
+  Expect.equals(r.x, x.x);
+  Expect.equals(r.y, x.y);
+  Expect.equals(r.z, x.z);
+  Expect.equals(r.w, x.w);
+}
+
+main() {
+  var x = new Float32x4(1.0, 0.0, 0.0, 0.0);
+  var y = new Float32x4(0.0, 1.0, 0.0, 0.0);
+  var z = new Float32x4(0.0, 0.0, 1.0, 0.0);
+  var zero = new Float32x4.zero();
+
+  for (int i = 0; i < 20; i++) {
+    testCross(x, y, z);
+    testCross(z, x, y);
+    testCross(y, z, x);
+    testCross(z, y, -x);
+    testCross(x, z, -y);
+    testCross(y, x, -z);
+    testCross(x, x, zero);
+    testCross(y, y, zero);
+    testCross(z, z, zero);
+    testCross(x, y, cross(-y, x));
+    testCross(x, y+z, cross(x, y) + cross(x, z));
+  }
+}
+
diff --git a/tests/lib/typed_data/float32x4_transpose_test.dart b/tests/lib/typed_data/float32x4_transpose_test.dart
new file mode 100644
index 0000000..f408d74
--- /dev/null
+++ b/tests/lib/typed_data/float32x4_transpose_test.dart
@@ -0,0 +1,62 @@
+// Copyright (c) 2013, 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.
+// VMOptions=--optimization-counter-threshold=10
+
+// Library tag to be able to run in html test framework.
+library float32x4_transpose_test;
+
+import 'dart:typed_data';
+import 'package:expect/expect.dart';
+
+void transpose(Float32x4List m) {
+  Expect.equals(4, m.length);
+  var m0 = m[0];
+  var m1 = m[1];
+  var m2 = m[2];
+  var m3 = m[3];
+  var t0 = m0.interleaveXY(m1);
+  var t1 = m2.interleaveXY(m3);
+  var t2 = m0.interleaveZW(m1);
+  var t3 = m2.interleaveZW(m3);
+  m[0] = t0.interleaveXYPairs(t1);
+  m[1] = t0.interleaveZWPairs(t1);
+  m[2] = t2.interleaveXYPairs(t3);
+  m[3] = t2.interleaveZWPairs(t3);
+}
+
+void testTranspose(Float32x4List m, Float32x4List r) {
+  transpose(m); // In place transpose.
+  for (int i = 0; i < 4; i++) {
+    var a = m[i];
+    var b = r[i];
+    Expect.equals(b.x, a.x);
+    Expect.equals(b.y, a.y);
+    Expect.equals(b.z, a.z);
+    Expect.equals(b.w, a.w);
+  }
+}
+
+main() {
+  var A = new Float32x4List(4);
+  A[0] = new Float32x4(1.0, 2.0, 3.0, 4.0);
+  A[1] = new Float32x4(5.0, 6.0, 7.0, 8.0);
+  A[2] = new Float32x4(9.0, 10.0, 11.0, 12.0);
+  A[3] = new Float32x4(13.0, 14.0, 15.0, 16.0);
+  var B = new Float32x4List(4);
+  B[0] = new Float32x4(1.0, 5.0, 9.0, 13.0);
+  B[1] = new Float32x4(2.0, 6.0, 10.0, 14.0);
+  B[2] = new Float32x4(3.0, 7.0, 11.0, 15.0);
+  B[3] = new Float32x4(4.0, 8.0, 12.0, 16.0);
+  var I = new Float32x4List(4);
+  I[0] = new Float32x4(1.0, 0.0, 0.0, 0.0);
+  I[1] = new Float32x4(0.0, 1.0, 0.0, 0.0);
+  I[2] = new Float32x4(0.0, 0.0, 1.0, 0.0);
+  I[3] = new Float32x4(0.0, 0.0, 0.0, 1.0);
+  for (int i = 0; i < 20; i++) {
+    var m = new Float32x4List.fromList(I);
+    testTranspose(m, I);
+    m = new Float32x4List.fromList(A);
+    testTranspose(m, B);
+  }
+}
diff --git a/tests/lib/typed_data/float32x4_two_arg_shuffle_test.dart b/tests/lib/typed_data/float32x4_two_arg_shuffle_test.dart
index f991356..5186b60 100644
--- a/tests/lib/typed_data/float32x4_two_arg_shuffle_test.dart
+++ b/tests/lib/typed_data/float32x4_two_arg_shuffle_test.dart
@@ -1,6 +1,7 @@
 // Copyright (c) 2013, 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.
+// VMOptions=--optimization-counter-threshold=10
 
 // Library tag to be able to run in html test framework.
 library float32x4_two_arg_shuffle_test;
@@ -59,7 +60,7 @@
 }
 
 main() {
-  for (int i = 0; i < 4000; i++) {
+  for (int i = 0; i < 20; i++) {
     testWithZWInXY();
     testInterleaveXY();
     testInterleaveZW();
diff --git a/tests/standalone/53bit_overflow_test.dart b/tests/standalone/53bit_overflow_test.dart
deleted file mode 100644
index 3bbc6e3..0000000
--- a/tests/standalone/53bit_overflow_test.dart
+++ /dev/null
@@ -1,118 +0,0 @@
-// Copyright (c) 2013, 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.
-
-// VMOptions=--throw_on_javascript_int_overflow --optimization_counter_threshold=10
-
-
-import "package:expect/expect.dart";
-import 'dart:typed_data';
-
-
-double dti_arg;
-int double_to_int() {
-  return dti_arg.toInt();
-}
-
-
-int ia_arg1;
-int ia_arg2;
-int integer_add() {
-  return ia_arg1 + ia_arg2;
-}
-
-
-int is_arg;
-int integer_shift() {
-  return is_arg << 1;
-}
-
-
-int max_add_throws() {
-  return 0xFFFFFFFFFFFFF + 1;
-}
-
-
-int min_sub_throws() {
-  return -0xFFFFFFFFFFFFF - 2;
-}
-
-
-int n_arg;
-int negate() {
-  return -n_arg;
-}
-
-
-int max_literal() {
-  return 0xFFFFFFFFFFFFF;
-}
-
-
-int min_literal() {
-  var min_literal = -0xFFFFFFFFFFFFF - 1;
-  return min_literal;
-}
-
-// We don't test for the _FiftyThreeBitOverflowError since it's not visible.
-// It's should not be visible since it doesn't exist on dart2js.
-bool is53BitError(e) => e is Error && "$e".startsWith("53-bit Overflow:");
-
-main() {
-  Expect.equals(0xFFFFFFFFFFFFF, max_literal());
-  Expect.equals(-0xFFFFFFFFFFFFF - 1, min_literal());
-
-  // Run the tests once before optimizations.
-  dti_arg = 1.9e16;
-  Expect.throws(double_to_int, is53BitError);
-
-  ia_arg1 = (1 << 51);
-  ia_arg2 = (1 << 51);
-  Expect.throws(integer_add, is53BitError);
-
-  n_arg = -0xFFFFFFFFFFFFF - 1;
-  Expect.throws(negate, is53BitError);
-
-  is_arg = (1 << 51);
-  Expect.throws(integer_shift, is53BitError);
-
-  Expect.throws(max_add_throws, is53BitError);
-  Expect.throws(min_sub_throws, is53BitError);
-
-  for (int i = 0; i < 20; i++) {
-    dti_arg = i.toDouble();
-    // Expect.throws calls through the closure, so we have to here, too.
-    var f = double_to_int;
-    Expect.equals(i, f());
-
-    ia_arg1 = i;
-    ia_arg2 = i;
-    f = integer_add;
-    Expect.equals(i + i, f());
-
-    n_arg = i;
-    f = negate;
-    Expect.equals(-i, f());
-
-    is_arg = i;
-    f = integer_shift;
-    Expect.equals(i << 1, f());
-  }
-
-   // The optimized functions should now deoptimize and throw the error.
-  dti_arg = 1.9e16;
-  Expect.throws(double_to_int, is53BitError);
-
-  ia_arg1 = (1 << 51);
-  ia_arg2 = (1 << 51);
-  Expect.throws(integer_add, is53BitError);
-
-  n_arg = -0xFFFFFFFFFFFFF - 1;
-  Expect.throws(negate, is53BitError);
-
-  is_arg = (1 << 51);
-  Expect.throws(integer_shift, is53BitError);
-
-  Expect.throws(max_add_throws, is53BitError);
-  Expect.throws(min_sub_throws, is53BitError);
-}
diff --git a/tests/standalone/io/certificate_test.dart b/tests/standalone/io/certificate_test.dart
new file mode 100644
index 0000000..fb5b423
--- /dev/null
+++ b/tests/standalone/io/certificate_test.dart
@@ -0,0 +1,38 @@
+// Copyright (c) 2013, 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.
+
+// This test verifies that a server certificate can be verified by a client
+// that loads the certificate authority certificate it depends on at runtime.
+
+import "package:path/path.dart";
+import "dart:io";
+import "dart:async";
+
+String scriptDir = dirname(new Options().script);
+
+void main() {
+  SecureSocket.initialize(database: join(scriptDir, 'pkcert'),
+                          password: 'dartdart');
+  runServer().then((SecureServerSocket server) {
+    return Process.run(new Options().executable,
+                       ['--checked',
+                        join(scriptDir, 'certificate_test_client.dart'),
+                        server.port.toString(),
+                        join(scriptDir, 'pkcert', 'myauthority.pem')]);
+  }).then((ProcessResult result) {
+    if (result.exitCode != 0) {
+      print("Client failed with exit code ${result.exitCode}");
+      print("  stdout:");
+      print(result.stdout);
+      print("  stderr:");
+      print(result.stderr);
+      throw new AssertionError();
+    }
+  });
+}
+
+Future<SecureServerSocket> runServer() =>
+  SecureServerSocket.bind("localhost", 0, "localhost_cert")
+    .then((server) => server..listen(
+        (socket) => socket.pipe(socket).then((_) => server.close())));
diff --git a/tests/standalone/io/certificate_test_client.dart b/tests/standalone/io/certificate_test_client.dart
new file mode 100644
index 0000000..f7f2fb2
--- /dev/null
+++ b/tests/standalone/io/certificate_test_client.dart
@@ -0,0 +1,41 @@
+// Copyright (c) 2013, 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.
+//
+// Client that tests that a certificate authority certificate loaded
+// at runtime can be used to verify a certificate chain. The server it
+// connects to uses localhost_cert, signed by myauthority_cert, to connect
+// securely.
+
+import 'dart:io';
+
+void main() {
+  int port = int.parse(new Options().arguments[0]);
+  String certificate = new Options().arguments[1];
+  SecureSocket.initialize();
+  var mycert = new File(certificate).readAsBytesSync();
+  bool threw = false;
+  try {
+    SecureSocket.addCertificate("I am not a cert".codeUnits,
+                                SecureSocket.TRUST_ISSUE_SERVER_CERTIFICATES);
+  } on CertificateException catch (e) {
+    threw = true;
+  }
+  if (!threw) throw new AssertException("Expected bad certificate to throw");
+
+  threw = false;
+  try {
+    SecureSocket.addCertificate(mycert, "Trust me, I'm a string");
+  } on CertificateException catch (e) {
+    threw = true;
+  }
+  if (!threw) throw new AssertException("Expected bad trust string to throw");
+
+  SecureSocket.addCertificate(mycert,
+                              SecureSocket.TRUST_ISSUE_SERVER_CERTIFICATES);
+  SecureSocket.connect('localhost', port).then((SecureSocket socket) {
+    socket.writeln("hello world");
+    socket.listen((data) { });
+    socket.close();
+  });
+}
diff --git a/tests/standalone/io/directory_fuzz_test.dart b/tests/standalone/io/directory_fuzz_test.dart
index dda9fe3..fb66b94 100644
--- a/tests/standalone/io/directory_fuzz_test.dart
+++ b/tests/standalone/io/directory_fuzz_test.dart
@@ -8,6 +8,7 @@
 import 'dart:async';
 import 'dart:io';
 import 'dart:isolate';
+import "package:expect/expect.dart";
 
 import 'fuzz_support.dart';
 
@@ -39,6 +40,11 @@
   var port = new ReceivePort();
   var futures = [];
   typeMapping.forEach((k, v) {
+    if (v is! String) {
+      Expect.throws(() => new Directory(v),
+                    (e) => e is ArgumentError);
+      return;
+    }
     var d = new Directory(v);
     futures.add(doItAsync(d.exists));
     futures.add(doItAsync(d.create));
diff --git a/tests/standalone/io/directory_invalid_arguments_test.dart b/tests/standalone/io/directory_invalid_arguments_test.dart
index 29f96c8..1b35aa0 100644
--- a/tests/standalone/io/directory_invalid_arguments_test.dart
+++ b/tests/standalone/io/directory_invalid_arguments_test.dart
@@ -22,29 +22,13 @@
 }
 
 void testInvalidArguments() {
-  Directory d = new Directory(12);
   try {
-    d.existsSync();
+    Directory d = new Directory(12);
     Expect.fail("No exception thrown");
   } catch (e) {
     Expect.isTrue(e is ArgumentError);
   }
-  try {
-    d.deleteSync();
-    Expect.fail("No exception thrown");
-  } catch (e) {
-    Expect.isTrue(e is ArgumentError);
-  }
-  try {
-    d.createSync();
-    Expect.fail("No exception thrown");
-  } catch (e) {
-    Expect.isTrue(e is ArgumentError);
-  }
-  testFailingList(d, false);
-  Expect.throws(() => d.listSync(recursive: true),
-                (e) => e is ArgumentError);
-  d = new Directory(".");
+  Directory d = new Directory(".");
   testFailingList(d, 1);
   Expect.throws(() => d.listSync(recursive: 1),
                 (e) => e is ArgumentError);
diff --git a/tests/standalone/io/http_headers_test.dart b/tests/standalone/io/http_headers_test.dart
index 845f6f6..4b9b7a7 100644
--- a/tests/standalone/io/http_headers_test.dart
+++ b/tests/standalone/io/http_headers_test.dart
@@ -251,6 +251,8 @@
   Expect.equals("", contentType.primaryType);
   Expect.equals("", contentType.subType);
   Expect.equals("/", contentType.value);
+  Expect.throws(() => contentType.parameters["xxx"] = "yyy",
+                (e) => e is UnsupportedError);
 
   contentType = ContentType.parse("text/html");
   check(contentType, "text", "html");
@@ -258,6 +260,8 @@
   contentType = new ContentType("text", "html", charset: "utf-8");
   check(contentType, "text", "html", {"charset": "utf-8"});
   Expect.equals("text/html; charset=utf-8", contentType.toString());
+  Expect.throws(() => contentType.parameters["xxx"] = "yyy",
+                (e) => e is UnsupportedError);
 
   contentType = new ContentType("text",
                                 "html",
@@ -267,6 +271,8 @@
   bool expectedToString = (s == "text/html; charset=utf-8; xxx=yyy" ||
                            s == "text/html; xxx=yyy; charset=utf-8");
   Expect.isTrue(expectedToString);
+  Expect.throws(() => contentType.parameters["xxx"] = "yyy",
+                (e) => e is UnsupportedError);
 
   contentType = new ContentType("text",
                                 "html",
diff --git a/tests/standalone/io/pkcert/myauthority.pem b/tests/standalone/io/pkcert/myauthority.pem
new file mode 100644
index 0000000..3aebea4
--- /dev/null
+++ b/tests/standalone/io/pkcert/myauthority.pem
@@ -0,0 +1,11 @@
+-----BEGIN CERTIFICATE-----
+MIIBpDCCAQ2gAwIBAgIFAJq4IS0wDQYJKoZIhvcNAQEFBQAwFjEUMBIGA1UEAxML

+bXlhdXRob3JpdHkwHhcNMTMwMjE1MTA0MzA5WhcNMTgwMjE1MTA0MzA5WjAWMRQw

+EgYDVQQDEwtteWF1dGhvcml0eTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA

+tnrkyrXF1SEUeOdIiULWs0dOEUlX6t73UDVbbTorF6R66fkjkEK3vW9ekZFUWq5+

+HVku4LUViJR140+F+CzUYtN73Ur28GqLa6LY4XtzHfPSfgecgayI1mEU+0f/2l8B

+4RiE9V8mW9RqPM6Lb69QrwXSYdzStl6ltuLJhgPGqAMCAwEAATANBgkqhkiG9w0B

+AQUFAAOBgQBdBUQTUR5oIRdqBGR87qW7caLAuPoVmzikOrSBNoyamVF0lwFFxgNw

+sj5VWdMn0SJhXd3EUMVlHr+4B/c3jUy1PlvBQGURn2cp5c4tj3FMOqkemuA0ywOF

+gbt2lqi7/RW4bHITqfPi7CDzE36n25vXc64Ylk7vEi3hUfjYfIqNcA==
+-----END CERTIFICATE-----
diff --git a/tests/standalone/53bit_overflow_literal_test.dart b/tests/standalone/javascript_int_overflow_literal_test.dart
similarity index 71%
rename from tests/standalone/53bit_overflow_literal_test.dart
rename to tests/standalone/javascript_int_overflow_literal_test.dart
index 1062af0..36c7b5b 100644
--- a/tests/standalone/53bit_overflow_literal_test.dart
+++ b/tests/standalone/javascript_int_overflow_literal_test.dart
@@ -8,11 +8,11 @@
 import "package:expect/expect.dart";
 
 int literals() {
-  var okay_literal = 0xFFFFFFFFFFFFF;
-  var too_big_literal = 0x1FFFFFFFFFFFFF;  /// 01: compile-time error
+  var okay_literal = 0x1FFFFFFFFFFFFF;
+  var too_big_literal = 0x20000000000000;  /// 01: compile-time error
   return okay_literal;
 }
 
 main() {
-  Expect.equals(0xFFFFFFFFFFFFF, literals());
+  Expect.equals(0x1FFFFFFFFFFFFF, literals());
 }
diff --git a/tests/standalone/javascript_int_overflow_test.dart b/tests/standalone/javascript_int_overflow_test.dart
new file mode 100644
index 0000000..6e1eb9b
--- /dev/null
+++ b/tests/standalone/javascript_int_overflow_test.dart
@@ -0,0 +1,119 @@
+// Copyright (c) 2013, 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.
+
+// VMOptions=--throw_on_javascript_int_overflow --optimization_counter_threshold=10
+
+
+import "package:expect/expect.dart";
+import 'dart:typed_data';
+
+
+double dti_arg;
+int double_to_int() {
+  return dti_arg.toInt();
+}
+
+
+int ia_arg1;
+int ia_arg2;
+int integer_add() {
+  return ia_arg1 + ia_arg2;
+}
+
+
+int is_arg;
+int integer_shift() {
+  return is_arg << 1;
+}
+
+
+int max_add_throws() {
+  return 0x1FFFFFFFFFFFFF + 1;
+}
+
+
+int min_sub_throws() {
+  return -0x1FFFFFFFFFFFFF - 1;
+}
+
+
+int n_arg;
+int negate() {
+  return -n_arg;
+}
+
+
+int max_literal() {
+  return 0x1FFFFFFFFFFFFF;
+}
+
+
+int min_literal() {
+  var min_literal = -0x1FFFFFFFFFFFFF;
+  return min_literal;
+}
+
+// We don't test for the _JavascriptIntegerOverflowError since it's not visible.
+// It should not be visible since it doesn't exist on dart2js.
+bool isJavascriptIntError(e) =>
+    e is Error && "$e".startsWith("Javascript Integer Overflow:");
+
+main() {
+  Expect.equals(0x1FFFFFFFFFFFFF, max_literal());
+  Expect.equals(-0x1FFFFFFFFFFFFF, min_literal());
+
+  // Run the tests once before optimizations.
+  dti_arg = 1.9e16;
+  Expect.throws(double_to_int, isJavascriptIntError);
+
+  ia_arg1 = (1 << 52);
+  ia_arg2 = (1 << 52);
+  Expect.throws(integer_add, isJavascriptIntError);
+
+  n_arg = -0x1FFFFFFFFFFFFF;
+  Expect.equals(0x1FFFFFFFFFFFFF, negate());
+
+  is_arg = (1 << 52);
+  Expect.throws(integer_shift, isJavascriptIntError);
+
+  Expect.throws(max_add_throws, isJavascriptIntError);
+  Expect.throws(min_sub_throws, isJavascriptIntError);
+
+  for (int i = 0; i < 20; i++) {
+    dti_arg = i.toDouble();
+    // Expect.throws calls through the closure, so we have to here, too.
+    var f = double_to_int;
+    Expect.equals(i, f());
+
+    ia_arg1 = i;
+    ia_arg2 = i;
+    f = integer_add;
+    Expect.equals(i + i, f());
+
+    n_arg = i;
+    f = negate;
+    Expect.equals(-i, f());
+
+    is_arg = i;
+    f = integer_shift;
+    Expect.equals(i << 1, f());
+  }
+
+   // The optimized functions should now deoptimize and throw the error.
+  dti_arg = 1.9e16;
+  Expect.throws(double_to_int, isJavascriptIntError);
+
+  ia_arg1 = (1 << 52);
+  ia_arg2 = (1 << 52);
+  Expect.throws(integer_add, isJavascriptIntError);
+
+  n_arg = -0x1FFFFFFFFFFFFF;
+  Expect.equals(0x1FFFFFFFFFFFFF, negate());
+
+  is_arg = (1 << 52);
+  Expect.throws(integer_shift, isJavascriptIntError);
+
+  Expect.throws(max_add_throws, isJavascriptIntError);
+  Expect.throws(min_sub_throws, isJavascriptIntError);
+}
diff --git a/tests/standalone/standalone.status b/tests/standalone/standalone.status
index 6622e10..abac10e 100644
--- a/tests/standalone/standalone.status
+++ b/tests/standalone/standalone.status
@@ -24,6 +24,9 @@
 io/file_fuzz_test: Skip
 io/directory_fuzz_test: Skip
 
+[ $runtime == vm && $system == windows ]
+vmservice/multiple_isolate_list_test: Fail, Pass # http://dartbug.com/12124
+
 [ $runtime == vm && $system == macos ]
 # This test fails with "Too many open files" on the Mac OS buildbot.
 # This is expected as MacOS by default runs with a very low number
@@ -49,12 +52,10 @@
 coverage_test: Skip
 http_launch_test: Skip
 vmservice/*: Skip # Do not run standalone vm service tests in browser.
-53bit_overflow_literal_test: fail # Issue 12044
-53bit_overflow_test: fail # Issue 12044
 
 
 [ $compiler == dartanalyzer ]
-53bit_overflow_literal_test/01: fail, ok
+javascript_int_overflow_literal_test/01: fail, ok
 
 # test issue https://code.google.com/p/dart/issues/detail?id=11518
 io/file_constructor_test: fail
@@ -75,7 +76,7 @@
 package/package_isolate_test: fail
 
 [ $compiler == dart2analyzer ]
-53bit_overflow_literal_test/01: fail, ok
+javascript_int_overflow_literal_test/01: fail, ok
 package/package_isolate_test: fail # issue 11647
 
 # test issue https://code.google.com/p/dart/issues/detail?id=11518
@@ -115,8 +116,8 @@
 pow_test: Skip # Precision > 53 bits.
 double_smi_comparison_test: Skip # Precision > 53 bits.
 http_launch_test: Skip
-53bit_overflow_test: Skip
-53bit_overflow_literal_test: Skip
+javascript_int_overflow_test: Skip
+javascript_int_overflow_literal_test: Skip
 oom_error_stacktrace_test: Fail, OK # (OOM on JS may produce a stacktrace).
 vmservice/*: Skip # Do not run standalone vm service tests with dart2js.
 
@@ -156,6 +157,8 @@
 
 [ $arch == simmips ]
 io/file_fuzz_test: Pass, Timeout
+io/web_socket_test: Pass, Slow
+io/http_server_response_test: Pass, Slow
 out_of_memory_test: Skip # passes on Mac, crashes on Linux
 oom_error_stacktrace_test: Skip # Fails on Linux
 io/web_socket_ping_test: Skip # TODO(ajohnsen): Timeout issue
diff --git a/tools/VERSION b/tools/VERSION
index 0e05268..5c1426a 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -1,4 +1,4 @@
 MAJOR 0
 MINOR 6
-BUILD 13
+BUILD 14
 PATCH 0
diff --git a/tools/dom/scripts/generator.py b/tools/dom/scripts/generator.py
index f966029..9ec3351 100644
--- a/tools/dom/scripts/generator.py
+++ b/tools/dom/scripts/generator.py
@@ -136,6 +136,8 @@
 
     'TransitionEvent': 'TransitionEvent,WebKitTransitionEvent',
 
+    'WebGLLoseContext': 'WebGLLoseContext,WebGLExtensionLoseContext',
+
     'WebKitCSSKeyframeRule':
         'CSSKeyframeRule,MozCSSKeyframeRule,WebKitCSSKeyframeRule',
 
diff --git a/tools/dom/scripts/htmlrenamer.py b/tools/dom/scripts/htmlrenamer.py
index 89753be..a8ca1a2 100644
--- a/tools/dom/scripts/htmlrenamer.py
+++ b/tools/dom/scripts/htmlrenamer.py
@@ -717,9 +717,10 @@
 
 # Manual dart: library name lookup.
 _library_names = monitored.Dict('htmlrenamer._library_names', {
-  'Window': 'html',
+  'ANGLEInstancedArrays': 'web_gl',
   'Database': 'web_sql',
   'Navigator': 'html',
+  'Window': 'html',
   'WorkerContext': 'html',
 })
 
diff --git a/tools/dom/scripts/systemnative.py b/tools/dom/scripts/systemnative.py
index 1c5930a..91dd180 100644
--- a/tools/dom/scripts/systemnative.py
+++ b/tools/dom/scripts/systemnative.py
@@ -478,6 +478,8 @@
     dart_element_type = self._DartType(element_type)
     if self._HasNativeIndexGetter():
       self._EmitNativeIndexGetter(dart_element_type)
+    elif self._HasExplicitIndexedGetter():
+      self._EmitExplicitIndexedGetter(dart_element_type)
     else:
       self._members_emitter.Emit(
           '\n'
@@ -526,6 +528,23 @@
     self._GenerateNativeBinding('numericIndexGetter', 2, dart_declaration,
         'Callback', True)
 
+  def _HasExplicitIndexedGetter(self):
+    return any(op.id == 'getItem' for op in self._interface.operations)
+
+  def _EmitExplicitIndexedGetter(self, dart_element_type):
+    if any(op.id == 'getItem' for op in self._interface.operations):
+      indexed_getter = 'getItem'
+
+    self._members_emitter.Emit(
+        '\n'
+        '  $TYPE operator[](int index) {\n'
+        '    if (index < 0 || index >= length)\n'
+        '      throw new RangeError.range(index, 0, length);\n'
+        '    return $INDEXED_GETTER(index);\n'
+        '  }\n',
+        TYPE=dart_element_type,
+        INDEXED_GETTER=indexed_getter)
+
   def _HasNativeIndexSetter(self):
     return 'CustomIndexedSetter' in self._interface.ext_attrs
 
@@ -899,12 +918,18 @@
         value_expression = function_call
 
       # Generate to Dart conversion of C++ value.
-      to_dart_conversion = return_type_info.to_dart_conversion(value_expression, self._interface.id, ext_attrs)
+      if return_type_info.dart_type() == 'bool':
+        set_return_value = 'Dart_SetBooleanReturnValue(args, %s)' % (value_expression)
+      elif return_type_info.dart_type() == 'int':
+        set_return_value = 'Dart_SetIntegerReturnValue(args, %s)' % (value_expression)
+      elif return_type_info.dart_type() == 'double':
+        set_return_value = 'Dart_SetDoubleReturnValue(args, %s)' % (value_expression)
+      else:
+        to_dart_conversion = return_type_info.to_dart_conversion(value_expression, self._interface.id, ext_attrs)
+        set_return_value = 'Dart_SetReturnValue(args, %s)' % (to_dart_conversion)
       invocation_emitter.Emit(
-        '        Dart_Handle returnValue = $TO_DART_CONVERSION;\n'
-        '        if (returnValue)\n'
-        '            Dart_SetReturnValue(args, returnValue);\n',
-        TO_DART_CONVERSION=to_dart_conversion)
+        '        $RETURN_VALUE;\n',
+        RETURN_VALUE=set_return_value)
 
   def _GenerateNativeBinding(self, idl_name, argument_count, dart_declaration,
       native_suffix, is_custom, emit_metadata=True):
diff --git a/tools/dom/templates/html/impl/impl_CSSStyleDeclaration.darttemplate b/tools/dom/templates/html/impl/impl_CSSStyleDeclaration.darttemplate
index 984f10d..c0120c2 100644
--- a/tools/dom/templates/html/impl/impl_CSSStyleDeclaration.darttemplate
+++ b/tools/dom/templates/html/impl/impl_CSSStyleDeclaration.darttemplate
@@ -4,7 +4,8 @@
 
 part of $LIBRARYNAME;
 
-$(ANNOTATIONS)$(CLASS_MODIFIERS)class $CLASSNAME$EXTENDS$IMPLEMENTS$NATIVESPEC {
+$(ANNOTATIONS)$(CLASS_MODIFIERS) class $CLASSNAME $EXTENDS with 
+    $(CLASSNAME)Base $IMPLEMENTS$NATIVESPEC {
   factory $CLASSNAME() => new CssStyleDeclaration.css('');
 
   factory $CLASSNAME.css(String css) {
@@ -12,9 +13,7 @@
     style.cssText = css;
     return style;
   }
-
-$!MEMBERS
-
+  
   String getPropertyValue(String propertyName) {
     var propValue = _getPropertyValue(propertyName);
     return propValue != null ? propValue : '';
@@ -35,7 +34,7 @@
       }
     } catch (e) {}
   }
-
+  
   /**
    * Checks to see if CSS Transitions are supported.
    */
@@ -47,11 +46,6 @@
     return JS('bool', '# in document.body.style', propertyName);
   }
 $else
-  /**
-   * Checks to see if CSS Transitions are supported.
-   */
-  static bool get supportsTransitions => true;
-
   @DomName('CSSStyleDeclaration.setProperty')
   void setProperty(String propertyName, String value, [String priority]) {
     if (priority == null) {
@@ -59,7 +53,42 @@
     }
     _setProperty(propertyName, value, priority);
   }
+
+  /**
+   * Checks to see if CSS Transitions are supported.
+   */
+  static bool get supportsTransitions => true;
 $endif
+$!MEMBERS
+}
+
+class _CssStyleDeclarationSet extends Object with CssStyleDeclarationBase {
+  final Iterable<Element> _elementIterable;
+  Iterable<CssStyleDeclaration> _elementCssStyleDeclarationSetIterable;
+
+  _CssStyleDeclarationSet(this._elementIterable) {
+    _elementCssStyleDeclarationSetIterable = new List.from(
+        _elementIterable).map((e) => e.style);
+  }
+
+  String getPropertyValue(String propertyName) =>
+      _elementCssStyleDeclarationSetIterable.first.getPropertyValue(
+          propertyName);
+
+  void setProperty(String propertyName, String value, [String priority]) {
+    _elementCssStyleDeclarationSetIterable.forEach((e) =>
+        e.setProperty(propertyName, value, priority));
+  }
+  // Important note: CssStyleDeclarationSet does NOT implement every method
+  // available in CssStyleDeclaration. Some of the methods don't make so much
+  // sense in terms of having a resonable value to return when you're
+  // considering a list of Elements. You will need to manually add any of the
+  // items in the MEMBERS set if you want that functionality.
+}
+
+abstract class CssStyleDeclarationBase {
+  String getPropertyValue(String propertyName);  
+  void setProperty(String propertyName, String value, [String priority]);
 
   // TODO(jacobr): generate this list of properties using the existing script.
   /** Gets the value of "align-content" */
diff --git a/tools/dom/templates/html/impl/impl_Element.darttemplate b/tools/dom/templates/html/impl/impl_Element.darttemplate
index 29533d8..8cfb668 100644
--- a/tools/dom/templates/html/impl/impl_Element.darttemplate
+++ b/tools/dom/templates/html/impl/impl_Element.darttemplate
@@ -157,7 +157,7 @@
 
 /**
  * An immutable list containing HTML elements. This list contains some
- * additional methods when compared to regular lists for ease of CSS 
+ * additional methods when compared to regular lists for ease of CSS
  * manipulation on a group of elements.
  */
 abstract class ElementList<T extends Element> extends ListBase<T> {
@@ -176,28 +176,40 @@
   /** Replace the classes with `value` for every element in this list. */
   set classes(Iterable<String> value);
 
-  /** 
+  /**
+   * Access the union of all [CssStyleDeclaration]s that are associated with an
+   * [ElementList].
+   *
+   * Grouping the style objects all together provides easy editing of specific
+   * properties of a collection of elements. Setting a specific property value
+   * will set that property in all [Element]s in the [ElementList]. Getting a
+   * specific property value will return the value of the property of the first
+   * element in the [ElementList].
+   */
+  CssStyleDeclarationBase get style;
+
+  /**
    * Access dimensions and position of the Elements in this list.
-   * 
+   *
    * Setting the height or width properties will set the height or width
-   * property for all elements in the list. This returns a rectangle with the 
+   * property for all elements in the list. This returns a rectangle with the
    * dimenions actually available for content
-   * in this element, in pixels, regardless of this element's box-sizing 
+   * in this element, in pixels, regardless of this element's box-sizing
    * property. Getting the height or width returns the height or width of the
-   * first Element in this list. 
+   * first Element in this list.
    *
    * Unlike [getBoundingClientRect], the dimensions of this rectangle
    * will return the same numerical height if the element is hidden or not.
    */
   @Experimental()
   CssRect get contentEdge;
-  
+
   /**
    * Access dimensions and position of the first Element's content + padding box
    * in this list.
-   * 
+   *
    * This returns a rectangle with the dimenions actually available for content
-   * in this element, in pixels, regardless of this element's box-sizing 
+   * in this element, in pixels, regardless of this element's box-sizing
    * property. Unlike [getBoundingClientRect], the dimensions of this rectangle
    * will return the same numerical height if the element is hidden or not. This
    * can be used to retrieve jQuery's `innerHeight` value for an element. This
@@ -210,9 +222,9 @@
   /**
    * Access dimensions and position of the first Element's content + padding +
    * border box in this list.
-   * 
+   *
    * This returns a rectangle with the dimenions actually available for content
-   * in this element, in pixels, regardless of this element's box-sizing 
+   * in this element, in pixels, regardless of this element's box-sizing
    * property. Unlike [getBoundingClientRect], the dimensions of this rectangle
    * will return the same numerical height if the element is hidden or not. This
    * can be used to retrieve jQuery's `outerHeight` value for an element.
@@ -223,9 +235,9 @@
   /**
    * Access dimensions and position of the first Element's content + padding +
    * border + margin box in this list.
-   * 
+   *
    * This returns a rectangle with the dimenions actually available for content
-   * in this element, in pixels, regardless of this element's box-sizing 
+   * in this element, in pixels, regardless of this element's box-sizing
    * property. Unlike [getBoundingClientRect], the dimensions of this rectangle
    * will return the same numerical height if the element is hidden or not. This
    * can be used to retrieve jQuery's `outerHeight` value for an element.
@@ -271,12 +283,15 @@
 
   CssClassSet get classes => new _MultiElementCssClassSet(_elementList);
 
+  CssStyleDeclarationBase get style =>
+      new _CssStyleDeclarationSet(_elementList);
+
   void set classes(Iterable<String> value) {
     _elementList.forEach((e) => e.classes = value);
   }
 
   CssRect get contentEdge => new _ContentCssListRect(_elementList);
-  
+
   CssRect get paddingEdge => _elementList.first.paddingEdge;
 
   CssRect get borderEdge => _elementList.first.borderEdge;
@@ -937,13 +952,13 @@
   }
 
   /**
-   * Creates an instance of the template, using the provided model and binding
-   * delegate.
+   * Creates an instance of the template, using the provided model and optional
+   * binding delegate.
    *
    * This is only supported if [isTemplate] is true.
    */
   @Experimental()
-  DocumentFragment createInstance(model, BindingDelegate delegate) {
+  DocumentFragment createInstance(model, [BindingDelegate delegate]) {
     _ensureTemplate();
     return TemplateElement.mdvPackage(this).createInstance(model, delegate);
   }
@@ -1019,35 +1034,35 @@
 
   /**
    * Access this element's content position.
-   * 
+   *
    * This returns a rectangle with the dimenions actually available for content
-   * in this element, in pixels, regardless of this element's box-sizing 
+   * in this element, in pixels, regardless of this element's box-sizing
    * property. Unlike [getBoundingClientRect], the dimensions of this rectangle
    * will return the same numerical height if the element is hidden or not.
-   * 
+   *
    * _Important_ _note_: use of this method _will_ perform CSS calculations that
-   * can trigger a browser reflow. Therefore, use of this property _during_ an 
-   * animation frame is discouraged. See also: 
+   * can trigger a browser reflow. Therefore, use of this property _during_ an
+   * animation frame is discouraged. See also:
    * [Browser Reflow](https://developers.google.com/speed/articles/reflow)
    */
   @Experimental()
   CssRect get contentEdge => new _ContentCssRect(this);
-  
+
   /**
    * Access the dimensions and position of this element's content + padding box.
-   * 
+   *
    * This returns a rectangle with the dimenions actually available for content
-   * in this element, in pixels, regardless of this element's box-sizing 
+   * in this element, in pixels, regardless of this element's box-sizing
    * property. Unlike [getBoundingClientRect], the dimensions of this rectangle
    * will return the same numerical height if the element is hidden or not. This
    * can be used to retrieve jQuery's
-   * [innerHeight](http://api.jquery.com/innerHeight/) value for an element. 
+   * [innerHeight](http://api.jquery.com/innerHeight/) value for an element.
    * This is also a rectangle equalling the dimensions of clientHeight and
    * clientWidth.
-   * 
+   *
    * _Important_ _note_: use of this method _will_ perform CSS calculations that
-   * can trigger a browser reflow. Therefore, use of this property _during_ an 
-   * animation frame is discouraged. See also: 
+   * can trigger a browser reflow. Therefore, use of this property _during_ an
+   * animation frame is discouraged. See also:
    * [Browser Reflow](https://developers.google.com/speed/articles/reflow)
    */
   @Experimental()
@@ -1056,17 +1071,17 @@
   /**
    * Access the dimensions and position of this element's content + padding +
    * border box.
-   * 
+   *
    * This returns a rectangle with the dimenions actually available for content
-   * in this element, in pixels, regardless of this element's box-sizing 
+   * in this element, in pixels, regardless of this element's box-sizing
    * property. Unlike [getBoundingClientRect], the dimensions of this rectangle
    * will return the same numerical height if the element is hidden or not. This
    * can be used to retrieve jQuery's
    * [outerHeight](http://api.jquery.com/outerHeight/) value for an element.
-   * 
-   * _Important_ _note_: use of this method _will_ perform CSS calculations that 
-   * can trigger a browser reflow. Therefore, use of this property _during_ an 
-   * animation frame is discouraged. See also: 
+   *
+   * _Important_ _note_: use of this method _will_ perform CSS calculations that
+   * can trigger a browser reflow. Therefore, use of this property _during_ an
+   * animation frame is discouraged. See also:
    * [Browser Reflow](https://developers.google.com/speed/articles/reflow)
    */
   @Experimental()
@@ -1075,38 +1090,38 @@
   /**
    * Access the dimensions and position of this element's content + padding +
    * border + margin box.
-   * 
+   *
    * This returns a rectangle with the dimenions actually available for content
-   * in this element, in pixels, regardless of this element's box-sizing 
+   * in this element, in pixels, regardless of this element's box-sizing
    * property. Unlike [getBoundingClientRect], the dimensions of this rectangle
    * will return the same numerical height if the element is hidden or not. This
    * can be used to retrieve jQuery's
    * [outerHeight](http://api.jquery.com/outerHeight/) value for an element.
-   * 
+   *
    * _Important_ _note_: use of this method will perform CSS calculations that
-   * can trigger a browser reflow. Therefore, use of this property _during_ an 
-   * animation frame is discouraged. See also: 
+   * can trigger a browser reflow. Therefore, use of this property _during_ an
+   * animation frame is discouraged. See also:
    * [Browser Reflow](https://developers.google.com/speed/articles/reflow)
    */
   @Experimental()
   CssRect get marginEdge => new _MarginCssRect(this);
 
-  /** 
-   * Provides the coordinates of the element relative to the top of the 
-   * document. 
+  /**
+   * Provides the coordinates of the element relative to the top of the
+   * document.
    *
-   * This method is the Dart equivalent to jQuery's 
+   * This method is the Dart equivalent to jQuery's
    * [offset](http://api.jquery.com/offset/) method.
    */
   Point get documentOffset => offsetTo(document.documentElement);
 
-  /** 
+  /**
    * Provides the offset of this element's [borderEdge] relative to the
    * specified [parent].
-   * 
+   *
    * This is the Dart equivalent of jQuery's
    * [position](http://api.jquery.com/position/) method. Unlike jQuery's
-   * position, however, [parent] can be any parent element of `this`, 
+   * position, however, [parent] can be any parent element of `this`,
    * rather than only `this`'s immediate [offsetParent]. If the specified
    * element is _not_ an offset parent or transitive offset parent to this
    * element, an [ArgumentError] is thrown.
@@ -1117,7 +1132,7 @@
 
   static Point _offsetToHelper(Element current, Element parent) {
     // We're hopping from _offsetParent_ to offsetParent (not just parent), so
-    // offsetParent, "tops out" at BODY. But people could conceivably pass in 
+    // offsetParent, "tops out" at BODY. But people could conceivably pass in
     // the document.documentElement and I want it to return an absolute offset,
     // so we have the special case checking for HTML.
     bool foundAsParent = identical(current, parent) || parent.tagName == 'HTML';
@@ -1125,7 +1140,7 @@
       if (foundAsParent) return new Point(0, 0);
       throw new ArgumentError("Specified element is not a transitive offset "
           "parent of this element.");
-    } 
+    }
     Element parentOffset = current.offsetParent;
     Point p = Element._offsetToHelper(parentOffset, parent);
     return new Point(p.x + current.offsetLeft, p.y + current.offsetTop);