Version 0.2.9.7

Merge revision 16250 to trunk

This fixes issue 7448 in dart2js.
Review URL: https://codereview.chromium.org//11615023

git-svn-id: http://dart.googlecode.com/svn/trunk@16251 260f80e4-7a28-3924-810f-c04153c831b5
diff --git a/runtime/lib/isolate_patch.dart b/runtime/lib/isolate_patch.dart
index ad3864f..fee97ab 100644
--- a/runtime/lib/isolate_patch.dart
+++ b/runtime/lib/isolate_patch.dart
@@ -128,27 +128,27 @@
 patch spawnUri(String uri) native "isolate_spawnUri";
 
 patch class Timer {
-  /* patch */ factory Timer(int milliseconds, void callback(Timer timer)) {
+  /* patch */ factory Timer(int milliSeconds, void callback(Timer timer)) {
     if (_TimerFactory._factory == null) {
       throw new UnsupportedError("Timer interface not supported.");
     }
-    return _TimerFactory._factory(milliseconds, callback, false);
+    return _TimerFactory._factory(milliSeconds, callback, false);
   }
 
   /**
    * Creates a new repeating timer. The [callback] is invoked every
-   * [milliseconds] millisecond until cancelled.
+   * [milliSeconds] millisecond until cancelled.
    */
-  /* patch */ factory Timer.repeating(int milliseconds,
+  /* patch */ factory Timer.repeating(int milliSeconds,
                                       void callback(Timer timer)) {
     if (_TimerFactory._factory == null) {
       throw new UnsupportedError("Timer interface not supported.");
     }
-    return _TimerFactory._factory(milliseconds, callback, true);
+    return _TimerFactory._factory(milliSeconds, callback, true);
   }
 }
 
-typedef Timer _TimerFactoryClosure(int milliseconds,
+typedef Timer _TimerFactoryClosure(int milliSeconds,
                                    void callback(Timer timer),
                                    bool repeating);
 
diff --git a/sdk/lib/_internal/compiler/implementation/compiler.dart b/sdk/lib/_internal/compiler/implementation/compiler.dart
index 1de80f0..9470db5 100644
--- a/sdk/lib/_internal/compiler/implementation/compiler.dart
+++ b/sdk/lib/_internal/compiler/implementation/compiler.dart
@@ -128,7 +128,6 @@
   Element _currentElement;
   LibraryElement coreLibrary;
   LibraryElement isolateLibrary;
-  LibraryElement isolateHelperLibrary;
   LibraryElement jsHelperLibrary;
   LibraryElement interceptorsLibrary;
   LibraryElement foreignLibrary;
@@ -403,33 +402,12 @@
   void enableIsolateSupport(LibraryElement element) {
     // TODO(ahe): Move this method to Enqueuer.
     isolateLibrary = element.patch;
-    isolateHelperLibrary = scanBuiltinLibrary('_isolate_helper');
-    importForeignLibrary(isolateHelperLibrary);
-    importHelperLibrary(isolateHelperLibrary);
-
-    libraryLoader.importLibrary(isolateLibrary, isolateHelperLibrary, null);
+    enqueuer.resolution.addToWorkList(isolateLibrary.find(START_ROOT_ISOLATE));
     enqueuer.resolution.addToWorkList(
-        isolateHelperLibrary.find(START_ROOT_ISOLATE));
+        isolateLibrary.find(const SourceString('_currentIsolate')));
     enqueuer.resolution.addToWorkList(
-        isolateHelperLibrary.find(const SourceString('_currentIsolate')));
-    enqueuer.resolution.addToWorkList(
-        isolateHelperLibrary.find(const SourceString('_callInIsolate')));
-    enqueuer.codegen.addToWorkList(
-        isolateHelperLibrary.find(START_ROOT_ISOLATE));
-
-    // The helper library does not use the native language extension,
-    // so we manually set the native classes this library defines.
-    // TODO(ngeoffray): Enable annotations on these classes.
-    ClassElement cls = isolateHelperLibrary.find(const SourceString('_Window'));
-    cls.setNative('"*DOMWindow"');
-
-    cls = isolateHelperLibrary.find(const SourceString('_WorkerStub'));
-    cls.setNative('"*Worker"');
-
-    enqueuer.resolution.nativeEnqueuer.processNativeClassesInLibrary(
-        isolateHelperLibrary);
-    enqueuer.codegen.nativeEnqueuer.processNativeClassesInLibrary(
-        isolateHelperLibrary);
+        isolateLibrary.find(const SourceString('_callInIsolate')));
+    enqueuer.codegen.addToWorkList(isolateLibrary.find(START_ROOT_ISOLATE));
   }
 
   bool hasIsolateSupport() => isolateLibrary != null;
@@ -522,7 +500,7 @@
 
   /** Define the JS helper functions in the given library. */
   void importForeignLibrary(LibraryElement library) {
-    if (foreignLibrary != null) {
+    if (jsHelperLibrary != null) {
       libraryLoader.importLibrary(library, foreignLibrary, null);
     }
   }
@@ -535,6 +513,7 @@
         'dart/tests/compiler/dart2js_native');
     if (nativeTest
         || libraryName == 'dart:mirrors'
+        || libraryName == 'dart:isolate'
         || libraryName == 'dart:math'
         || libraryName == 'dart:html'
         || libraryName == 'dart:html_common'
diff --git a/sdk/lib/_internal/compiler/implementation/elements/elements.dart b/sdk/lib/_internal/compiler/implementation/elements/elements.dart
index a67fb06..4bb1abb 100644
--- a/sdk/lib/_internal/compiler/implementation/elements/elements.dart
+++ b/sdk/lib/_internal/compiler/implementation/elements/elements.dart
@@ -1761,9 +1761,6 @@
 
   bool isInterface() => false;
   bool isNative() => nativeTagInfo != null;
-  void setNative(String name) {
-    nativeTagInfo = new SourceString(name);
-  }
   int get hashCode => id;
 
   Scope buildScope() => new ClassScope(enclosingElement.buildScope(), this);
diff --git a/sdk/lib/_internal/compiler/implementation/js_backend/emitter.dart b/sdk/lib/_internal/compiler/implementation/js_backend/emitter.dart
index 8b808f0..8a212a4 100644
--- a/sdk/lib/_internal/compiler/implementation/js_backend/emitter.dart
+++ b/sdk/lib/_internal/compiler/implementation/js_backend/emitter.dart
@@ -1843,9 +1843,9 @@
     if (compiler.isMockCompilation) return;
     Element main = compiler.mainApp.find(Compiler.MAIN);
     String mainCall = null;
-    if (compiler.isolateHelperLibrary != null) {
+    if (compiler.isolateLibrary != null) {
       Element isolateMain =
-        compiler.isolateHelperLibrary.find(Compiler.START_ROOT_ISOLATE);
+        compiler.isolateLibrary.find(Compiler.START_ROOT_ISOLATE);
       mainCall = buildIsolateSetup(buffer, main, isolateMain);
     } else {
       mainCall = '${namer.isolateAccess(main)}()';
diff --git a/sdk/lib/_internal/compiler/implementation/lib/isolate_helper.dart b/sdk/lib/_internal/compiler/implementation/lib/isolate_helper.dart
deleted file mode 100644
index f2b8daa..0000000
--- a/sdk/lib/_internal/compiler/implementation/lib/isolate_helper.dart
+++ /dev/null
@@ -1,1283 +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.
-
-library _isolate_helper;
-
-import 'dart:isolate';
-import 'dart:uri';
-
-/**
- * Called by the compiler to support switching
- * between isolates when we get a callback from the DOM.
- */
-void _callInIsolate(_IsolateContext isolate, Function function) {
-  isolate.eval(function);
-  _globalState.topEventLoop.run();
-}
-
-/**
- * Called by the compiler to fetch the current isolate context.
- */
-_IsolateContext _currentIsolate() => _globalState.currentContext;
-
-/********************************************************
-  Inserted from lib/isolate/dart2js/compiler_hooks.dart
- ********************************************************/
-
-/**
- * Wrapper that takes the dart entry point and runs it within an isolate. The
- * dart2js compiler will inject a call of the form
- * [: startRootIsolate(main); :] when it determines that this wrapping
- * is needed. For single-isolate applications (e.g. hello world), this
- * call is not emitted.
- */
-void startRootIsolate(entry) {
-  _globalState = new _Manager();
-
-  // Don't start the main loop again, if we are in a worker.
-  if (_globalState.isWorker) return;
-  final rootContext = new _IsolateContext();
-  _globalState.rootContext = rootContext;
-  _fillStatics(rootContext);
-
-  // BUG(5151491): Setting currentContext should not be necessary, but
-  // because closures passed to the DOM as event handlers do not bind their
-  // isolate automatically we try to give them a reasonable context to live in
-  // by having a "default" isolate (the first one created).
-  _globalState.currentContext = rootContext;
-
-  rootContext.eval(entry);
-  _globalState.topEventLoop.run();
-}
-
-/********************************************************
-  Inserted from lib/isolate/dart2js/isolateimpl.dart
- ********************************************************/
-
-/**
- * Concepts used here:
- *
- * "manager" - A manager contains one or more isolates, schedules their
- * execution, and performs other plumbing on their behalf.  The isolate
- * present at the creation of the manager is designated as its "root isolate".
- * A manager may, for example, be implemented on a web Worker.
- *
- * [_Manager] - State present within a manager (exactly once, as a global).
- *
- * [_ManagerStub] - A handle held within one manager that allows interaction
- * with another manager.  A target manager may be addressed by zero or more
- * [_ManagerStub]s.
- *
- */
-
-/**
- * A native object that is shared across isolates. This object is visible to all
- * isolates running under the same manager (either UI or background web worker).
- *
- * This is code that is intended to 'escape' the isolate boundaries in order to
- * implement the semantics of isolates in JavaScript. Without this we would have
- * been forced to implement more code (including the top-level event loop) in
- * JavaScript itself.
- */
-// TODO(eub, sigmund): move the "manager" to be entirely in JS.
-// Running any Dart code outside the context of an isolate gives it
-// the change to break the isolate abstraction.
-_Manager get _globalState => JS("_Manager", r"$globalState");
-set _globalState(_Manager val) {
-  JS("void", r"$globalState = #", val);
-}
-
-void _fillStatics(context) {
-  JS("void", r"$globals = #.isolateStatics", context);
-  JS("void", r"$static_init()");
-}
-
-ReceivePort lazyPort;
-
-/** State associated with the current manager. See [globalState]. */
-// TODO(sigmund): split in multiple classes: global, thread, main-worker states?
-class _Manager {
-
-  /** Next available isolate id within this [_Manager]. */
-  int nextIsolateId = 0;
-
-  /** id assigned to this [_Manager]. */
-  int currentManagerId = 0;
-
-  /**
-   * Next available manager id. Only used by the main manager to assign a unique
-   * id to each manager created by it.
-   */
-  int nextManagerId = 1;
-
-  /** Context for the currently running [Isolate]. */
-  _IsolateContext currentContext = null;
-
-  /** Context for the root [Isolate] that first run in this [_Manager]. */
-  _IsolateContext rootContext = null;
-
-  /** The top-level event loop. */
-  _EventLoop topEventLoop;
-
-  /** Whether this program is running from the command line. */
-  bool fromCommandLine;
-
-  /** Whether this [_Manager] is running as a web worker. */
-  bool isWorker;
-
-  /** Whether we support spawning web workers. */
-  bool supportsWorkers;
-
-  /**
-   * Whether to use web workers when implementing isolates. Set to false for
-   * debugging/testing.
-   */
-  bool get useWorkers => supportsWorkers;
-
-  /**
-   * Whether to use the web-worker JSON-based message serialization protocol. By
-   * default this is only used with web workers. For debugging, you can force
-   * using this protocol by changing this field value to [true].
-   */
-  bool get needSerialization => useWorkers;
-
-  /**
-   * Registry of isolates. Isolates must be registered if, and only if, receive
-   * ports are alive.  Normally no open receive-ports means that the isolate is
-   * dead, but DOM callbacks could resurrect it.
-   */
-  Map<int, _IsolateContext> isolates;
-
-  /** Reference to the main [_Manager].  Null in the main [_Manager] itself. */
-  _ManagerStub mainManager;
-
-  /** Registry of active [_ManagerStub]s.  Only used in the main [_Manager]. */
-  Map<int, _ManagerStub> managers;
-
-  _Manager() {
-    _nativeDetectEnvironment();
-    topEventLoop = new _EventLoop();
-    isolates = new Map<int, _IsolateContext>();
-    managers = new Map<int, _ManagerStub>();
-    if (isWorker) {  // "if we are not the main manager ourself" is the intent.
-      mainManager = new _MainManagerStub();
-      _nativeInitWorkerMessageHandler();
-    }
-  }
-
-  void _nativeDetectEnvironment() {
-    isWorker = JS("bool", r"$isWorker");
-    supportsWorkers = JS("bool", r"$supportsWorkers");
-    fromCommandLine = JS("bool", r"typeof(window) == 'undefined'");
-  }
-
-  void _nativeInitWorkerMessageHandler() {
-    JS("void", r"""
-$globalThis.onmessage = function (e) {
-  IsolateNatives._processWorkerMessage(this.mainManager, e);
-}""");
-  }
-  /*: TODO: check that _processWorkerMessage is not discarded while treeshaking.
-  """ {
-    IsolateNatives._processWorkerMessage(null, null);
-  }
-  */
-
-
-  /** Close the worker running this code if all isolates are done. */
-  void maybeCloseWorker() {
-    if (isolates.isEmpty) {
-      mainManager.postMessage(_serializeMessage({'command': 'close'}));
-    }
-  }
-}
-
-/** Context information tracked for each isolate. */
-class _IsolateContext {
-  /** Current isolate id. */
-  int id;
-
-  /** Registry of receive ports currently active on this isolate. */
-  Map<int, ReceivePort> ports;
-
-  /** Holds isolate globals (statics and top-level properties). */
-  var isolateStatics; // native object containing all globals of an isolate.
-
-  _IsolateContext() {
-    id = _globalState.nextIsolateId++;
-    ports = new Map<int, ReceivePort>();
-    initGlobals();
-  }
-
-  // these are filled lazily the first time the isolate starts running.
-  void initGlobals() { JS("void", r'$initGlobals(#)', this); }
-
-  /**
-   * Run [code] in the context of the isolate represented by [this]. Note this
-   * is called from JavaScript (see $wrap_call in corejs.dart).
-   */
-  dynamic eval(Function code) {
-    var old = _globalState.currentContext;
-    _globalState.currentContext = this;
-    this._setGlobals();
-    var result = null;
-    try {
-      result = code();
-    } finally {
-      _globalState.currentContext = old;
-      if (old != null) old._setGlobals();
-    }
-    return result;
-  }
-
-  void _setGlobals() { JS("void", r'$setGlobals(#)', this); }
-
-  /** Lookup a port registered for this isolate. */
-  ReceivePort lookup(int portId) => ports[portId];
-
-  /** Register a port on this isolate. */
-  void register(int portId, ReceivePort port)  {
-    if (ports.containsKey(portId)) {
-      throw new Exception("Registry: ports must be registered only once.");
-    }
-    ports[portId] = port;
-    _globalState.isolates[id] = this; // indicate this isolate is active
-  }
-
-  /** Unregister a port on this isolate. */
-  void unregister(int portId) {
-    ports.remove(portId);
-    if (ports.isEmpty) {
-      _globalState.isolates.remove(id); // indicate this isolate is not active
-    }
-  }
-}
-
-/** Represent the event loop on a javascript thread (DOM or worker). */
-class _EventLoop {
-  Queue<_IsolateEvent> events;
-
-  _EventLoop() : events = new Queue<_IsolateEvent>();
-
-  void enqueue(isolate, fn, msg) {
-    events.addLast(new _IsolateEvent(isolate, fn, msg));
-  }
-
-  _IsolateEvent dequeue() {
-    if (events.isEmpty) return null;
-    return events.removeFirst();
-  }
-
-  /** Process a single event, if any. */
-  bool runIteration() {
-    final event = dequeue();
-    if (event == null) {
-      if (_globalState.isWorker) {
-        _globalState.maybeCloseWorker();
-      } else if (_globalState.rootContext != null &&
-                 _globalState.isolates.containsKey(
-                     _globalState.rootContext.id) &&
-                 _globalState.fromCommandLine &&
-                 _globalState.rootContext.ports.isEmpty) {
-        // We want to reach here only on the main [_Manager] and only
-        // on the command-line.  In the browser the isolate might
-        // still be alive due to DOM callbacks, but the presumption is
-        // that on the command-line, no future events can be injected
-        // into the event queue once it's empty.  Node has setTimeout
-        // so this presumption is incorrect there.  We think(?) that
-        // in d8 this assumption is valid.
-        throw new Exception("Program exited with open ReceivePorts.");
-      }
-      return false;
-    }
-    event.process();
-    return true;
-  }
-
-  /**
-   * Runs multiple iterations of the run-loop. If possible, each iteration is
-   * run asynchronously.
-   */
-  void _runHelper() {
-    if (hasWindow()) {
-      // Run each iteration from the browser's top event loop.
-      void next() {
-        if (!runIteration()) return;
-        _window.setTimeout(next, 0);
-      }
-      next();
-    } else {
-      // Run synchronously until no more iterations are available.
-      while (runIteration()) {}
-    }
-  }
-
-  /**
-   * Call [_runHelper] but ensure that worker exceptions are propragated. Note
-   * this is called from JavaScript (see $wrap_call in corejs.dart).
-   */
-  void run() {
-    if (!_globalState.isWorker) {
-      _runHelper();
-    } else {
-      try {
-        _runHelper();
-      } catch (e, trace) {
-        _globalState.mainManager.postMessage(_serializeMessage(
-            {'command': 'error', 'msg': '$e\n$trace' }));
-      }
-    }
-  }
-}
-
-/** An event in the top-level event queue. */
-class _IsolateEvent {
-  _IsolateContext isolate;
-  Function fn;
-  String message;
-
-  _IsolateEvent(this.isolate, this.fn, this.message);
-
-  void process() {
-    isolate.eval(fn);
-  }
-}
-
-/** An interface for a stub used to interact with a manager. */
-abstract class _ManagerStub {
-  get id;
-  void set id(int i);
-  void set onmessage(Function f);
-  void postMessage(msg);
-  void terminate();
-}
-
-/** A stub for interacting with the main manager. */
-class _MainManagerStub implements _ManagerStub {
-  get id => 0;
-  void set id(int i) { throw new UnimplementedError(); }
-  void set onmessage(f) {
-    throw new Exception("onmessage should not be set on MainManagerStub");
-  }
-  void postMessage(msg) { JS("void", r"$globalThis.postMessage(#)", msg); }
-  void terminate() {}  // Nothing useful to do here.
-}
-
-/**
- * A stub for interacting with a manager built on a web worker. This
- * definition uses a 'hidden' type (* prefix on the native name) to
- * enforce that the type is defined dynamically only when web workers
- * are actually available.
- */
-// @Native("*Worker");
-class _WorkerStub implements _ManagerStub {
-  get id => JS("var", "#.id", this);
-  void set id(i) { JS("void", "#.id = #", this, i); }
-  void set onmessage(f) { JS("void", "#.onmessage = #", this, f); }
-  void postMessage(msg) => JS("void", "#.postMessage(#)", this, msg);
-  // terminate() is implemented by Worker.
-  void terminate();
-}
-
-const String _SPAWNED_SIGNAL = "spawned";
-
-class IsolateNatives {
-
-  /**
-   * The src url for the script tag that loaded this code. Used to create
-   * JavaScript workers.
-   */
-  static String get _thisScript => JS("String", r"$thisScriptUrl");
-
-  /** Starts a new worker with the given URL. */
-  static _WorkerStub _newWorker(url) => JS("_WorkerStub", r"new Worker(#)", url);
-
-  /**
-   * Assume that [e] is a browser message event and extract its message data.
-   * We don't import the dom explicitly so, when workers are disabled, this
-   * library can also run on top of nodejs.
-   */
-  //static _getEventData(e) => JS("Object", "#.data", e);
-  static _getEventData(e) => JS("", "#.data", e);
-
-  /**
-   * Process messages on a worker, either to control the worker instance or to
-   * pass messages along to the isolate running in the worker.
-   */
-  static void _processWorkerMessage(sender, e) {
-    var msg = _deserializeMessage(_getEventData(e));
-    switch (msg['command']) {
-      case 'start':
-        _globalState.currentManagerId = msg['id'];
-        Function entryPoint = _getJSFunctionFromName(msg['functionName']);
-        var replyTo = _deserializeMessage(msg['replyTo']);
-        _globalState.topEventLoop.enqueue(new _IsolateContext(), function() {
-          _startIsolate(entryPoint, replyTo);
-        }, 'worker-start');
-        _globalState.topEventLoop.run();
-        break;
-      case 'spawn-worker':
-        _spawnWorker(msg['functionName'], msg['uri'], msg['replyPort']);
-        break;
-      case 'message':
-        msg['port'].send(msg['msg'], msg['replyTo']);
-        _globalState.topEventLoop.run();
-        break;
-      case 'close':
-        _log("Closing Worker");
-        _globalState.managers.remove(sender.id);
-        sender.terminate();
-        _globalState.topEventLoop.run();
-        break;
-      case 'log':
-        _log(msg['msg']);
-        break;
-      case 'print':
-        if (_globalState.isWorker) {
-          _globalState.mainManager.postMessage(
-              _serializeMessage({'command': 'print', 'msg': msg}));
-        } else {
-          print(msg['msg']);
-        }
-        break;
-      case 'error':
-        throw msg['msg'];
-    }
-  }
-
-  /** Log a message, forwarding to the main [_Manager] if appropriate. */
-  static _log(msg) {
-    if (_globalState.isWorker) {
-      _globalState.mainManager.postMessage(
-          _serializeMessage({'command': 'log', 'msg': msg }));
-    } else {
-      try {
-        _consoleLog(msg);
-      } catch (e, trace) {
-        throw new Exception(trace);
-      }
-    }
-  }
-
-  static void _consoleLog(msg) {
-    JS("void", r"$globalThis.console.log(#)", msg);
-  }
-
-  /**
-   * Extract the constructor of runnable, so it can be allocated in another
-   * isolate.
-   */
-  static dynamic _getJSConstructor(Isolate runnable) {
-    return JS("Object", "#.constructor", runnable);
-  }
-
-  /** Extract the constructor name of a runnable */
-  // TODO(sigmund): find a browser-generic way to support this.
-  // TODO(floitsch): is this function still used? If yes, should we use
-  // Primitives.objectTypeName instead?
-  static dynamic _getJSConstructorName(Isolate runnable) {
-    return JS("Object", "#.constructor.name", runnable);
-  }
-
-  /** Find a constructor given its name. */
-  static dynamic _getJSConstructorFromName(String factoryName) {
-    return JS("Object", r"$globalThis[#]", factoryName);
-  }
-
-  static dynamic _getJSFunctionFromName(String functionName) {
-    return JS("Object", r"$globalThis[#]", functionName);
-  }
-
-  /**
-   * Get a string name for the function, if possible.  The result for
-   * anonymous functions is browser-dependent -- it may be "" or "anonymous"
-   * but you should probably not count on this.
-   */
-  static String _getJSFunctionName(Function f) {
-    return JS("Object", r"(#.$name || #)", f, null);
-  }
-
-  /** Create a new JavaScript object instance given its constructor. */
-  static dynamic _allocate(var ctor) {
-    return JS("Object", "new #()", ctor);
-  }
-
-  static SendPort spawnFunction(void topLevelFunction()) {
-    final name = _getJSFunctionName(topLevelFunction);
-    if (name == null) {
-      throw new UnsupportedError(
-          "only top-level functions can be spawned.");
-    }
-    return spawn(name, null, false);
-  }
-
-  // TODO(sigmund): clean up above, after we make the new API the default:
-
-  static SendPort spawn(String functionName, String uri, bool isLight) {
-    Completer<SendPort> completer = new Completer<SendPort>();
-    ReceivePort port = new ReceivePort();
-    port.receive((msg, SendPort replyPort) {
-      port.close();
-      assert(msg == _SPAWNED_SIGNAL);
-      completer.complete(replyPort);
-    });
-
-    SendPort signalReply = port.toSendPort();
-
-    if (_globalState.useWorkers && !isLight) {
-      _startWorker(functionName, uri, signalReply);
-    } else {
-      _startNonWorker(functionName, uri, signalReply);
-    }
-    return new _BufferingSendPort(
-        _globalState.currentContext.id, completer.future);
-  }
-
-  static SendPort _startWorker(
-      String functionName, String uri, SendPort replyPort) {
-    if (_globalState.isWorker) {
-      _globalState.mainManager.postMessage(_serializeMessage({
-          'command': 'spawn-worker',
-          'functionName': functionName,
-          'uri': uri,
-          'replyPort': replyPort}));
-    } else {
-      _spawnWorker(functionName, uri, replyPort);
-    }
-  }
-
-  static SendPort _startNonWorker(
-      String functionName, String uri, SendPort replyPort) {
-    // TODO(eub): support IE9 using an iframe -- Dart issue 1702.
-    if (uri != null) throw new UnsupportedError(
-            "Currently spawnUri is not supported without web workers.");
-    _globalState.topEventLoop.enqueue(new _IsolateContext(), function() {
-      final func = _getJSFunctionFromName(functionName);
-      _startIsolate(func, replyPort);
-    }, 'nonworker start');
-  }
-
-  static void _startIsolate(Function topLevel, SendPort replyTo) {
-    _fillStatics(_globalState.currentContext);
-    lazyPort = new ReceivePort();
-    replyTo.send(_SPAWNED_SIGNAL, port.toSendPort());
-
-    topLevel();
-  }
-
-  /**
-   * Spawns an isolate in a worker. [factoryName] is the Javascript constructor
-   * name for the isolate entry point class.
-   */
-  static void _spawnWorker(functionName, uri, replyPort) {
-    if (functionName == null) functionName = 'main';
-    if (uri == null) uri = _thisScript;
-    if (!(new Uri.fromString(uri).isAbsolute())) {
-      // The constructor of dom workers requires an absolute URL. If we use a
-      // relative path we will get a DOM exception.
-      String prefix = _thisScript.substring(0, _thisScript.lastIndexOf('/'));
-      uri = "$prefix/$uri";
-    }
-    final worker = _newWorker(uri);
-    worker.onmessage = (e) { _processWorkerMessage(worker, e); };
-    var workerId = _globalState.nextManagerId++;
-    // We also store the id on the worker itself so that we can unregister it.
-    worker.id = workerId;
-    _globalState.managers[workerId] = worker;
-    worker.postMessage(_serializeMessage({
-      'command': 'start',
-      'id': workerId,
-      // Note: we serialize replyPort twice because the child worker needs to
-      // first deserialize the worker id, before it can correctly deserialize
-      // the port (port deserialization is sensitive to what is the current
-      // workerId).
-      'replyTo': _serializeMessage(replyPort),
-      'functionName': functionName }));
-  }
-}
-
-/********************************************************
-  Inserted from lib/isolate/dart2js/ports.dart
- ********************************************************/
-
-/** Common functionality to all send ports. */
-class _BaseSendPort implements SendPort {
-  /** Id for the destination isolate. */
-  final int _isolateId;
-
-  const _BaseSendPort(this._isolateId);
-
-  void _checkReplyTo(SendPort replyTo) {
-    if (replyTo != null
-        && replyTo is! _NativeJsSendPort
-        && replyTo is! _WorkerSendPort
-        && replyTo is! _BufferingSendPort) {
-      throw new Exception("SendPort.send: Illegal replyTo port type");
-    }
-  }
-
-  Future call(var message) {
-    final completer = new Completer();
-    final port = new ReceivePortImpl();
-    send(message, port.toSendPort());
-    port.receive((value, ignoreReplyTo) {
-      port.close();
-      if (value is Exception) {
-        completer.completeException(value);
-      } else {
-        completer.complete(value);
-      }
-    });
-    return completer.future;
-  }
-
-  void send(var message, [SendPort replyTo]);
-  bool operator ==(var other);
-  int get hashCode;
-}
-
-/** A send port that delivers messages in-memory via native JavaScript calls. */
-class _NativeJsSendPort extends _BaseSendPort implements SendPort {
-  final ReceivePortImpl _receivePort;
-
-  const _NativeJsSendPort(this._receivePort, int isolateId) : super(isolateId);
-
-  void send(var message, [SendPort replyTo = null]) {
-    _waitForPendingPorts([message, replyTo], () {
-      _checkReplyTo(replyTo);
-      // Check that the isolate still runs and the port is still open
-      final isolate = _globalState.isolates[_isolateId];
-      if (isolate == null) return;
-      if (_receivePort._callback == null) return;
-
-      // We force serialization/deserialization as a simple way to ensure
-      // isolate communication restrictions are respected between isolates that
-      // live in the same worker. [_NativeJsSendPort] delivers both messages
-      // from the same worker and messages from other workers. In particular,
-      // messages sent from a worker via a [_WorkerSendPort] are received at
-      // [_processWorkerMessage] and forwarded to a native port. In such cases,
-      // here we'll see [_globalState.currentContext == null].
-      final shouldSerialize = _globalState.currentContext != null
-          && _globalState.currentContext.id != _isolateId;
-      var msg = message;
-      var reply = replyTo;
-      if (shouldSerialize) {
-        msg = _serializeMessage(msg);
-        reply = _serializeMessage(reply);
-      }
-      _globalState.topEventLoop.enqueue(isolate, () {
-        if (_receivePort._callback != null) {
-          if (shouldSerialize) {
-            msg = _deserializeMessage(msg);
-            reply = _deserializeMessage(reply);
-          }
-          _receivePort._callback(msg, reply);
-        }
-      }, 'receive $message');
-    });
-  }
-
-  bool operator ==(var other) => (other is _NativeJsSendPort) &&
-      (_receivePort == other._receivePort);
-
-  int get hashCode => _receivePort._id;
-}
-
-/** A send port that delivers messages via worker.postMessage. */
-// TODO(eub): abstract this for iframes.
-class _WorkerSendPort extends _BaseSendPort implements SendPort {
-  final int _workerId;
-  final int _receivePortId;
-
-  const _WorkerSendPort(this._workerId, int isolateId, this._receivePortId)
-      : super(isolateId);
-
-  void send(var message, [SendPort replyTo = null]) {
-    _waitForPendingPorts([message, replyTo], () {
-      _checkReplyTo(replyTo);
-      final workerMessage = _serializeMessage({
-          'command': 'message',
-          'port': this,
-          'msg': message,
-          'replyTo': replyTo});
-
-      if (_globalState.isWorker) {
-        // communication from one worker to another go through the main worker:
-        _globalState.mainManager.postMessage(workerMessage);
-      } else {
-        _globalState.managers[_workerId].postMessage(workerMessage);
-      }
-    });
-  }
-
-  bool operator ==(var other) {
-    return (other is _WorkerSendPort) &&
-        (_workerId == other._workerId) &&
-        (_isolateId == other._isolateId) &&
-        (_receivePortId == other._receivePortId);
-  }
-
-  int get hashCode {
-    // TODO(sigmund): use a standard hash when we get one available in corelib.
-    return (_workerId << 16) ^ (_isolateId << 8) ^ _receivePortId;
-  }
-}
-
-/** A port that buffers messages until an underlying port gets resolved. */
-class _BufferingSendPort extends _BaseSendPort implements SendPort {
-  /** Internal counter to assign unique ids to each port. */
-  static int _idCount = 0;
-
-  /** For implementing equals and hashcode. */
-  final int _id;
-
-  /** Underlying port, when resolved. */
-  SendPort _port;
-
-  /**
-   * Future of the underlying port, so that we can detect when this port can be
-   * sent on messages.
-   */
-  Future<SendPort> _futurePort;
-
-  /** Pending messages (and reply ports). */
-  List pending;
-
-  _BufferingSendPort(isolateId, this._futurePort)
-      : super(isolateId), _id = _idCount, pending = [] {
-    _idCount++;
-    _futurePort.then((p) {
-      _port = p;
-      for (final item in pending) {
-        p.send(item['message'], item['replyTo']);
-      }
-      pending = null;
-    });
-  }
-
-  _BufferingSendPort.fromPort(isolateId, this._port)
-      : super(isolateId), _id = _idCount {
-    _idCount++;
-  }
-
-  void send(var message, [SendPort replyTo]) {
-    if (_port != null) {
-      _port.send(message, replyTo);
-    } else {
-      pending.add({'message': message, 'replyTo': replyTo});
-    }
-  }
-
-  bool operator ==(var other) =>
-      other is _BufferingSendPort && _id == other._id;
-  int get hashCode => _id;
-}
-
-/** Implementation of a multi-use [ReceivePort] on top of JavaScript. */
-class ReceivePortImpl implements ReceivePort {
-  int _id;
-  Function _callback;
-  static int _nextFreeId = 1;
-
-  ReceivePortImpl()
-      : _id = _nextFreeId++ {
-    _globalState.currentContext.register(_id, this);
-  }
-
-  void receive(void onMessage(var message, SendPort replyTo)) {
-    _callback = onMessage;
-  }
-
-  void close() {
-    _callback = null;
-    _globalState.currentContext.unregister(_id);
-  }
-
-  SendPort toSendPort() {
-    return new _NativeJsSendPort(this, _globalState.currentContext.id);
-  }
-}
-
-/** Wait until all ports in a message are resolved. */
-_waitForPendingPorts(var message, void callback()) {
-  final finder = new _PendingSendPortFinder();
-  finder.traverse(message);
-  Futures.wait(finder.ports).then((_) => callback());
-}
-
-
-/** Visitor that finds all unresolved [SendPort]s in a message. */
-class _PendingSendPortFinder extends _MessageTraverser {
-  List<Future<SendPort>> ports;
-  _PendingSendPortFinder() : super(), ports = [] {
-    _visited = new _JsVisitedMap();
-  }
-
-  visitPrimitive(x) {}
-
-  visitList(List list) {
-    final seen = _visited[list];
-    if (seen != null) return;
-    _visited[list] = true;
-    // TODO(sigmund): replace with the following: (bug #1660)
-    // list.forEach(_dispatch);
-    list.forEach((e) => _dispatch(e));
-  }
-
-  visitMap(Map map) {
-    final seen = _visited[map];
-    if (seen != null) return;
-
-    _visited[map] = true;
-    // TODO(sigmund): replace with the following: (bug #1660)
-    // map.values.forEach(_dispatch);
-    map.values.forEach((e) => _dispatch(e));
-  }
-
-  visitSendPort(SendPort port) {
-    if (port is _BufferingSendPort && port._port == null) {
-      ports.add(port._futurePort);
-    }
-  }
-}
-
-/********************************************************
-  Inserted from lib/isolate/dart2js/messages.dart
- ********************************************************/
-
-// Defines message visitors, serialization, and deserialization.
-
-/** Serialize [message] (or simulate serialization). */
-_serializeMessage(message) {
-  if (_globalState.needSerialization) {
-    return new _JsSerializer().traverse(message);
-  } else {
-    return new _JsCopier().traverse(message);
-  }
-}
-
-/** Deserialize [message] (or simulate deserialization). */
-_deserializeMessage(message) {
-  if (_globalState.needSerialization) {
-    return new _JsDeserializer().deserialize(message);
-  } else {
-    // Nothing more to do.
-    return message;
-  }
-}
-
-class _JsSerializer extends _Serializer {
-
-  _JsSerializer() : super() { _visited = new _JsVisitedMap(); }
-
-  visitSendPort(SendPort x) {
-    if (x is _NativeJsSendPort) return visitNativeJsSendPort(x);
-    if (x is _WorkerSendPort) return visitWorkerSendPort(x);
-    if (x is _BufferingSendPort) return visitBufferingSendPort(x);
-    throw "Illegal underlying port $x";
-  }
-
-  visitNativeJsSendPort(_NativeJsSendPort port) {
-    return ['sendport', _globalState.currentManagerId,
-        port._isolateId, port._receivePort._id];
-  }
-
-  visitWorkerSendPort(_WorkerSendPort port) {
-    return ['sendport', port._workerId, port._isolateId, port._receivePortId];
-  }
-
-  visitBufferingSendPort(_BufferingSendPort port) {
-    if (port._port != null) {
-      return visitSendPort(port._port);
-    } else {
-      // TODO(floitsch): Use real exception (which one?).
-      throw
-          "internal error: must call _waitForPendingPorts to ensure all"
-          " ports are resolved at this point.";
-    }
-  }
-
-}
-
-
-class _JsCopier extends _Copier {
-
-  _JsCopier() : super() { _visited = new _JsVisitedMap(); }
-
-  visitSendPort(SendPort x) {
-    if (x is _NativeJsSendPort) return visitNativeJsSendPort(x);
-    if (x is _WorkerSendPort) return visitWorkerSendPort(x);
-    if (x is _BufferingSendPort) return visitBufferingSendPort(x);
-    throw "Illegal underlying port $p";
-  }
-
-  SendPort visitNativeJsSendPort(_NativeJsSendPort port) {
-    return new _NativeJsSendPort(port._receivePort, port._isolateId);
-  }
-
-  SendPort visitWorkerSendPort(_WorkerSendPort port) {
-    return new _WorkerSendPort(
-        port._workerId, port._isolateId, port._receivePortId);
-  }
-
-  SendPort visitBufferingSendPort(_BufferingSendPort port) {
-    if (port._port != null) {
-      return visitSendPort(port._port);
-    } else {
-      // TODO(floitsch): Use real exception (which one?).
-      throw
-          "internal error: must call _waitForPendingPorts to ensure all"
-          " ports are resolved at this point.";
-    }
-  }
-
-}
-
-class _JsDeserializer extends _Deserializer {
-
-  SendPort deserializeSendPort(List x) {
-    int managerId = x[1];
-    int isolateId = x[2];
-    int receivePortId = x[3];
-    // If two isolates are in the same manager, we use NativeJsSendPorts to
-    // deliver messages directly without using postMessage.
-    if (managerId == _globalState.currentManagerId) {
-      var isolate = _globalState.isolates[isolateId];
-      if (isolate == null) return null; // Isolate has been closed.
-      var receivePort = isolate.lookup(receivePortId);
-      return new _NativeJsSendPort(receivePort, isolateId);
-    } else {
-      return new _WorkerSendPort(managerId, isolateId, receivePortId);
-    }
-  }
-
-}
-
-class _JsVisitedMap implements _MessageTraverserVisitedMap {
-  List tagged;
-
-  /** Retrieves any information stored in the native object [object]. */
-  operator[](var object) {
-    return _getAttachedInfo(object);
-  }
-
-  /** Injects some information into the native [object]. */
-  void operator[]=(var object, var info) {
-    tagged.add(object);
-    _setAttachedInfo(object, info);
-  }
-
-  /** Get ready to rumble. */
-  void reset() {
-    assert(tagged == null);
-    tagged = new List();
-  }
-
-  /** Remove all information injected in the native objects. */
-  void cleanup() {
-    for (int i = 0, length = tagged.length; i < length; i++) {
-      _clearAttachedInfo(tagged[i]);
-    }
-    tagged = null;
-  }
-
-  void _clearAttachedInfo(var o) {
-    JS("void", "#['__MessageTraverser__attached_info__'] = #", o, null);
-  }
-
-  void _setAttachedInfo(var o, var info) {
-    JS("void", "#['__MessageTraverser__attached_info__'] = #", o, info);
-  }
-
-  _getAttachedInfo(var o) {
-    return JS("", "#['__MessageTraverser__attached_info__']", o);
-  }
-}
-
-// only visible for testing purposes
-// TODO(sigmund): remove once we can disable privacy for testing (bug #1882)
-class TestingOnly {
-  static copy(x) {
-    return new _JsCopier().traverse(x);
-  }
-
-  // only visible for testing purposes
-  static serialize(x) {
-    _Serializer serializer = new _JsSerializer();
-    _Deserializer deserializer = new _JsDeserializer();
-    return deserializer.deserialize(serializer.traverse(x));
-  }
-}
-
-/********************************************************
-  Inserted from lib/isolate/serialization.dart
- ********************************************************/
-
-class _MessageTraverserVisitedMap {
-
-  operator[](var object) => null;
-  void operator[]=(var object, var info) { }
-
-  void reset() { }
-  void cleanup() { }
-
-}
-
-/** Abstract visitor for dart objects that can be sent as isolate messages. */
-class _MessageTraverser {
-
-  _MessageTraverserVisitedMap _visited;
-  _MessageTraverser() : _visited = new _MessageTraverserVisitedMap();
-
-  /** Visitor's entry point. */
-  traverse(var x) {
-    if (isPrimitive(x)) return visitPrimitive(x);
-    _visited.reset();
-    var result;
-    try {
-      result = _dispatch(x);
-    } finally {
-      _visited.cleanup();
-    }
-    return result;
-  }
-
-  _dispatch(var x) {
-    if (isPrimitive(x)) return visitPrimitive(x);
-    if (x is List) return visitList(x);
-    if (x is Map) return visitMap(x);
-    if (x is SendPort) return visitSendPort(x);
-    if (x is SendPortSync) return visitSendPortSync(x);
-
-    // Overridable fallback.
-    return visitObject(x);
-  }
-
-  visitPrimitive(x);
-  visitList(List x);
-  visitMap(Map x);
-  visitSendPort(SendPort x);
-  visitSendPortSync(SendPortSync x);
-
-  visitObject(Object x) {
-    // TODO(floitsch): make this a real exception. (which one)?
-    throw "Message serialization: Illegal value $x passed";
-  }
-
-  static bool isPrimitive(x) {
-    return (x == null) || (x is String) || (x is num) || (x is bool);
-  }
-}
-
-
-/** A visitor that recursively copies a message. */
-class _Copier extends _MessageTraverser {
-
-  visitPrimitive(x) => x;
-
-  List visitList(List list) {
-    List copy = _visited[list];
-    if (copy != null) return copy;
-
-    int len = list.length;
-
-    // TODO(floitsch): we loose the generic type of the List.
-    copy = new List(len);
-    _visited[list] = copy;
-    for (int i = 0; i < len; i++) {
-      copy[i] = _dispatch(list[i]);
-    }
-    return copy;
-  }
-
-  Map visitMap(Map map) {
-    Map copy = _visited[map];
-    if (copy != null) return copy;
-
-    // TODO(floitsch): we loose the generic type of the map.
-    copy = new Map();
-    _visited[map] = copy;
-    map.forEach((key, val) {
-      copy[_dispatch(key)] = _dispatch(val);
-    });
-    return copy;
-  }
-
-}
-
-/** Visitor that serializes a message as a JSON array. */
-class _Serializer extends _MessageTraverser {
-  int _nextFreeRefId = 0;
-
-  visitPrimitive(x) => x;
-
-  visitList(List list) {
-    int copyId = _visited[list];
-    if (copyId != null) return ['ref', copyId];
-
-    int id = _nextFreeRefId++;
-    _visited[list] = id;
-    var jsArray = _serializeList(list);
-    // TODO(floitsch): we are losing the generic type.
-    return ['list', id, jsArray];
-  }
-
-  visitMap(Map map) {
-    int copyId = _visited[map];
-    if (copyId != null) return ['ref', copyId];
-
-    int id = _nextFreeRefId++;
-    _visited[map] = id;
-    var keys = _serializeList(map.keys);
-    var values = _serializeList(map.values);
-    // TODO(floitsch): we are losing the generic type.
-    return ['map', id, keys, values];
-  }
-
-  _serializeList(List list) {
-    int len = list.length;
-    var result = new List(len);
-    for (int i = 0; i < len; i++) {
-      result[i] = _dispatch(list[i]);
-    }
-    return result;
-  }
-}
-
-/** Deserializes arrays created with [_Serializer]. */
-class _Deserializer {
-  Map<int, dynamic> _deserialized;
-
-  _Deserializer();
-
-  static bool isPrimitive(x) {
-    return (x == null) || (x is String) || (x is num) || (x is bool);
-  }
-
-  deserialize(x) {
-    if (isPrimitive(x)) return x;
-    // TODO(floitsch): this should be new HashMap<int, var|Dynamic>()
-    _deserialized = new HashMap();
-    return _deserializeHelper(x);
-  }
-
-  _deserializeHelper(x) {
-    if (isPrimitive(x)) return x;
-    assert(x is List);
-    switch (x[0]) {
-      case 'ref': return _deserializeRef(x);
-      case 'list': return _deserializeList(x);
-      case 'map': return _deserializeMap(x);
-      case 'sendport': return deserializeSendPort(x);
-      default: return deserializeObject(x);
-    }
-  }
-
-  _deserializeRef(List x) {
-    int id = x[1];
-    var result = _deserialized[id];
-    assert(result != null);
-    return result;
-  }
-
-  List _deserializeList(List x) {
-    int id = x[1];
-    // We rely on the fact that Dart-lists are directly mapped to Js-arrays.
-    List dartList = x[2];
-    _deserialized[id] = dartList;
-    int len = dartList.length;
-    for (int i = 0; i < len; i++) {
-      dartList[i] = _deserializeHelper(dartList[i]);
-    }
-    return dartList;
-  }
-
-  Map _deserializeMap(List x) {
-    Map result = new Map();
-    int id = x[1];
-    _deserialized[id] = result;
-    List keys = x[2];
-    List values = x[3];
-    int len = keys.length;
-    assert(len == values.length);
-    for (int i = 0; i < len; i++) {
-      var key = _deserializeHelper(keys[i]);
-      var value = _deserializeHelper(values[i]);
-      result[key] = value;
-    }
-    return result;
-  }
-
-  deserializeSendPort(List x);
-
-  deserializeObject(List x) {
-    // TODO(floitsch): Use real exception (which one?).
-    throw "Unexpected serialized object";
-  }
-}
-
-/********************************************************
-  Inserted from lib/isolate/dart2js/timer_provider.dart
- ********************************************************/
-
-// We don't want to import the DOM library just because of window.setTimeout,
-// so we reconstruct the Window class here. The only conflict that could happen
-// with the other DOMWindow class would be because of subclasses.
-// Currently, none of the two Dart classes have subclasses.
-typedef void _TimeoutHandler();
-
-// @Native("*DOMWindow");
-class _Window {
-  int setTimeout(_TimeoutHandler handler, int timeout) {
-    return JS('int',
-              '#.setTimeout(#, #)',
-              this,
-              convertDartClosureToJS(handler, 0),
-              timeout);
-  }
-
-  int setInterval(_TimeoutHandler handler, int timeout) {
-    return JS('int',
-              '#.setInterval(#, #)',
-              this,
-              convertDartClosureToJS(handler, 0),
-              timeout);
-  }
-
-  void clearTimeout(int handle) {
-    JS('void', '#.clearTimeout(#)', this, handle);
-  }
-
-  void clearInterval(int handle) {
-    JS('void', '#.clearInterval(#)', this, handle);
-  }
-}
-
-_Window get _window =>
-  JS('bool', 'typeof window != "undefined"') ? JS('_Window', 'window') : null;
-
-bool hasWindow() => _window != null;
-
-class TimerImpl implements Timer {
-  final bool _once;
-  int _handle;
-
-  TimerImpl(int milliseconds, void callback(Timer timer))
-      : _once = true {
-    _handle = _window.setTimeout(() => callback(this), milliseconds);
-  }
-
-  TimerImpl.repeating(int milliseconds, void callback(Timer timer))
-      : _once = false {
-    _handle = _window.setInterval(() => callback(this), milliseconds);
-  }
-
-  void cancel() {
-    if (_once) {
-      _window.clearTimeout(_handle);
-    } else {
-      _window.clearInterval(_handle);
-    }
-  }
-}
diff --git a/sdk/lib/_internal/compiler/implementation/lib/isolate_patch.dart b/sdk/lib/_internal/compiler/implementation/lib/isolate_patch.dart
index 3f43fa3..5dd9e44 100644
--- a/sdk/lib/_internal/compiler/implementation/lib/isolate_patch.dart
+++ b/sdk/lib/_internal/compiler/implementation/lib/isolate_patch.dart
@@ -4,45 +4,1295 @@
 
 // Patch file for the dart:isolate library.
 
+import 'dart:uri';
+
+/**
+ * Called by the compiler to support switching
+ * between isolates when we get a callback from the DOM.
+ */
+void _callInIsolate(_IsolateContext isolate, Function function) {
+  isolate.eval(function);
+  _globalState.topEventLoop.run();
+}
+
+/**
+ * Called by the compiler to fetch the current isolate context.
+ */
+_IsolateContext _currentIsolate() => _globalState.currentContext;
+
+/********************************************************
+  Inserted from lib/isolate/dart2js/compiler_hooks.dart
+ ********************************************************/
+
+/**
+ * Wrapper that takes the dart entry point and runs it within an isolate. The
+ * dart2js compiler will inject a call of the form
+ * [: startRootIsolate(main); :] when it determines that this wrapping
+ * is needed. For single-isolate applications (e.g. hello world), this
+ * call is not emitted.
+ */
+void startRootIsolate(entry) {
+  _globalState = new _Manager();
+
+  // Don't start the main loop again, if we are in a worker.
+  if (_globalState.isWorker) return;
+  final rootContext = new _IsolateContext();
+  _globalState.rootContext = rootContext;
+  _fillStatics(rootContext);
+
+  // BUG(5151491): Setting currentContext should not be necessary, but
+  // because closures passed to the DOM as event handlers do not bind their
+  // isolate automatically we try to give them a reasonable context to live in
+  // by having a "default" isolate (the first one created).
+  _globalState.currentContext = rootContext;
+
+  rootContext.eval(entry);
+  _globalState.topEventLoop.run();
+}
+
+/********************************************************
+  Inserted from lib/isolate/dart2js/isolateimpl.dart
+ ********************************************************/
+
+/**
+ * Concepts used here:
+ *
+ * "manager" - A manager contains one or more isolates, schedules their
+ * execution, and performs other plumbing on their behalf.  The isolate
+ * present at the creation of the manager is designated as its "root isolate".
+ * A manager may, for example, be implemented on a web Worker.
+ *
+ * [_Manager] - State present within a manager (exactly once, as a global).
+ *
+ * [_ManagerStub] - A handle held within one manager that allows interaction
+ * with another manager.  A target manager may be addressed by zero or more
+ * [_ManagerStub]s.
+ *
+ */
+
+/**
+ * A native object that is shared across isolates. This object is visible to all
+ * isolates running under the same manager (either UI or background web worker).
+ *
+ * This is code that is intended to 'escape' the isolate boundaries in order to
+ * implement the semantics of isolates in JavaScript. Without this we would have
+ * been forced to implement more code (including the top-level event loop) in
+ * JavaScript itself.
+ */
+// TODO(eub, sigmund): move the "manager" to be entirely in JS.
+// Running any Dart code outside the context of an isolate gives it
+// the change to break the isolate abstraction.
+_Manager get _globalState => JS("_Manager", r"$globalState");
+set _globalState(_Manager val) {
+  JS("void", r"$globalState = #", val);
+}
+
+void _fillStatics(context) {
+  JS("void", r"$globals = #.isolateStatics", context);
+  JS("void", r"$static_init()");
+}
+
+ReceivePort _lazyPort;
 patch ReceivePort get port {
-  if (lazyPort == null) {
-    lazyPort = new ReceivePort();
+  if (_lazyPort == null) {
+    _lazyPort = new ReceivePort();
   }
-  return lazyPort;
+  return _lazyPort;
 }
 
 patch SendPort spawnFunction(void topLevelFunction()) {
-  return IsolateNatives.spawnFunction(topLevelFunction);
+  final name = _IsolateNatives._getJSFunctionName(topLevelFunction);
+  if (name == null) {
+    throw new UnsupportedError(
+        "only top-level functions can be spawned.");
+  }
+  return _IsolateNatives._spawn(name, null, false);
 }
 
 patch SendPort spawnUri(String uri) {
-  return IsolateNatives.spawn(null, uri, false);
+  return _IsolateNatives._spawn(null, uri, false);
 }
 
+/** State associated with the current manager. See [globalState]. */
+// TODO(sigmund): split in multiple classes: global, thread, main-worker states?
+class _Manager {
+
+  /** Next available isolate id within this [_Manager]. */
+  int nextIsolateId = 0;
+
+  /** id assigned to this [_Manager]. */
+  int currentManagerId = 0;
+
+  /**
+   * Next available manager id. Only used by the main manager to assign a unique
+   * id to each manager created by it.
+   */
+  int nextManagerId = 1;
+
+  /** Context for the currently running [Isolate]. */
+  _IsolateContext currentContext = null;
+
+  /** Context for the root [Isolate] that first run in this [_Manager]. */
+  _IsolateContext rootContext = null;
+
+  /** The top-level event loop. */
+  _EventLoop topEventLoop;
+
+  /** Whether this program is running from the command line. */
+  bool fromCommandLine;
+
+  /** Whether this [_Manager] is running as a web worker. */
+  bool isWorker;
+
+  /** Whether we support spawning web workers. */
+  bool supportsWorkers;
+
+  /**
+   * Whether to use web workers when implementing isolates. Set to false for
+   * debugging/testing.
+   */
+  bool get useWorkers => supportsWorkers;
+
+  /**
+   * Whether to use the web-worker JSON-based message serialization protocol. By
+   * default this is only used with web workers. For debugging, you can force
+   * using this protocol by changing this field value to [true].
+   */
+  bool get needSerialization => useWorkers;
+
+  /**
+   * Registry of isolates. Isolates must be registered if, and only if, receive
+   * ports are alive.  Normally no open receive-ports means that the isolate is
+   * dead, but DOM callbacks could resurrect it.
+   */
+  Map<int, _IsolateContext> isolates;
+
+  /** Reference to the main [_Manager].  Null in the main [_Manager] itself. */
+  _ManagerStub mainManager;
+
+  /** Registry of active [_ManagerStub]s.  Only used in the main [_Manager]. */
+  Map<int, _ManagerStub> managers;
+
+  _Manager() {
+    _nativeDetectEnvironment();
+    topEventLoop = new _EventLoop();
+    isolates = new Map<int, _IsolateContext>();
+    managers = new Map<int, _ManagerStub>();
+    if (isWorker) {  // "if we are not the main manager ourself" is the intent.
+      mainManager = new _MainManagerStub();
+      _nativeInitWorkerMessageHandler();
+    }
+  }
+
+  void _nativeDetectEnvironment() {
+    isWorker = JS("bool", r"$isWorker");
+    supportsWorkers = JS("bool", r"$supportsWorkers");
+    fromCommandLine = JS("bool", r"typeof(window) == 'undefined'");
+  }
+
+  void _nativeInitWorkerMessageHandler() {
+    JS("void", r"""
+$globalThis.onmessage = function (e) {
+  _IsolateNatives._processWorkerMessage(this.mainManager, e);
+}""");
+  }
+  /*: TODO: check that _processWorkerMessage is not discarded while treeshaking.
+  """ {
+    _IsolateNatives._processWorkerMessage(null, null);
+  }
+  */
+
+
+  /** Close the worker running this code if all isolates are done. */
+  void maybeCloseWorker() {
+    if (isolates.isEmpty) {
+      mainManager.postMessage(_serializeMessage({'command': 'close'}));
+    }
+  }
+}
+
+/** Context information tracked for each isolate. */
+class _IsolateContext {
+  /** Current isolate id. */
+  int id;
+
+  /** Registry of receive ports currently active on this isolate. */
+  Map<int, ReceivePort> ports;
+
+  /** Holds isolate globals (statics and top-level properties). */
+  var isolateStatics; // native object containing all globals of an isolate.
+
+  _IsolateContext() {
+    id = _globalState.nextIsolateId++;
+    ports = new Map<int, ReceivePort>();
+    initGlobals();
+  }
+
+  // these are filled lazily the first time the isolate starts running.
+  void initGlobals() { JS("void", r'$initGlobals(#)', this); }
+
+  /**
+   * Run [code] in the context of the isolate represented by [this]. Note this
+   * is called from JavaScript (see $wrap_call in corejs.dart).
+   */
+  dynamic eval(Function code) {
+    var old = _globalState.currentContext;
+    _globalState.currentContext = this;
+    this._setGlobals();
+    var result = null;
+    try {
+      result = code();
+    } finally {
+      _globalState.currentContext = old;
+      if (old != null) old._setGlobals();
+    }
+    return result;
+  }
+
+  void _setGlobals() { JS("void", r'$setGlobals(#)', this); }
+
+  /** Lookup a port registered for this isolate. */
+  ReceivePort lookup(int portId) => ports[portId];
+
+  /** Register a port on this isolate. */
+  void register(int portId, ReceivePort port)  {
+    if (ports.containsKey(portId)) {
+      throw new Exception("Registry: ports must be registered only once.");
+    }
+    ports[portId] = port;
+    _globalState.isolates[id] = this; // indicate this isolate is active
+  }
+
+  /** Unregister a port on this isolate. */
+  void unregister(int portId) {
+    ports.remove(portId);
+    if (ports.isEmpty) {
+      _globalState.isolates.remove(id); // indicate this isolate is not active
+    }
+  }
+}
+
+/** Represent the event loop on a javascript thread (DOM or worker). */
+class _EventLoop {
+  Queue<_IsolateEvent> events;
+
+  _EventLoop() : events = new Queue<_IsolateEvent>();
+
+  void enqueue(isolate, fn, msg) {
+    events.addLast(new _IsolateEvent(isolate, fn, msg));
+  }
+
+  _IsolateEvent dequeue() {
+    if (events.isEmpty) return null;
+    return events.removeFirst();
+  }
+
+  /** Process a single event, if any. */
+  bool runIteration() {
+    final event = dequeue();
+    if (event == null) {
+      if (_globalState.isWorker) {
+        _globalState.maybeCloseWorker();
+      } else if (_globalState.rootContext != null &&
+                 _globalState.isolates.containsKey(
+                     _globalState.rootContext.id) &&
+                 _globalState.fromCommandLine &&
+                 _globalState.rootContext.ports.isEmpty) {
+        // We want to reach here only on the main [_Manager] and only
+        // on the command-line.  In the browser the isolate might
+        // still be alive due to DOM callbacks, but the presumption is
+        // that on the command-line, no future events can be injected
+        // into the event queue once it's empty.  Node has setTimeout
+        // so this presumption is incorrect there.  We think(?) that
+        // in d8 this assumption is valid.
+        throw new Exception("Program exited with open ReceivePorts.");
+      }
+      return false;
+    }
+    event.process();
+    return true;
+  }
+
+  /**
+   * Runs multiple iterations of the run-loop. If possible, each iteration is
+   * run asynchronously.
+   */
+  void _runHelper() {
+    // [_window] is defined in timer_provider.dart.
+    if (_window != null) {
+      // Run each iteration from the browser's top event loop.
+      void next() {
+        if (!runIteration()) return;
+        _window.setTimeout(next, 0);
+      }
+      next();
+    } else {
+      // Run synchronously until no more iterations are available.
+      while (runIteration()) {}
+    }
+  }
+
+  /**
+   * Call [_runHelper] but ensure that worker exceptions are propragated. Note
+   * this is called from JavaScript (see $wrap_call in corejs.dart).
+   */
+  void run() {
+    if (!_globalState.isWorker) {
+      _runHelper();
+    } else {
+      try {
+        _runHelper();
+      } catch (e, trace) {
+        _globalState.mainManager.postMessage(_serializeMessage(
+            {'command': 'error', 'msg': '$e\n$trace' }));
+      }
+    }
+  }
+}
+
+/** An event in the top-level event queue. */
+class _IsolateEvent {
+  _IsolateContext isolate;
+  Function fn;
+  String message;
+
+  _IsolateEvent(this.isolate, this.fn, this.message);
+
+  void process() {
+    isolate.eval(fn);
+  }
+}
+
+/** An interface for a stub used to interact with a manager. */
+abstract class _ManagerStub {
+  get id;
+  void set id(int i);
+  void set onmessage(Function f);
+  void postMessage(msg);
+  void terminate();
+}
+
+/** A stub for interacting with the main manager. */
+class _MainManagerStub implements _ManagerStub {
+  get id => 0;
+  void set id(int i) { throw new UnimplementedError(); }
+  void set onmessage(f) {
+    throw new Exception("onmessage should not be set on MainManagerStub");
+  }
+  void postMessage(msg) { JS("void", r"$globalThis.postMessage(#)", msg); }
+  void terminate() {}  // Nothing useful to do here.
+}
+
+/**
+ * A stub for interacting with a manager built on a web worker. This
+ * definition uses a 'hidden' type (* prefix on the native name) to
+ * enforce that the type is defined dynamically only when web workers
+ * are actually available.
+ */
+class _WorkerStub implements _ManagerStub native "*Worker" {
+  get id => JS("var", "#.id", this);
+  void set id(i) { JS("void", "#.id = #", this, i); }
+  void set onmessage(f) { JS("void", "#.onmessage = #", this, f); }
+  void postMessage(msg) => JS("void", "#.postMessage(#)", this, msg);
+  // terminate() is implemented by Worker.
+  void terminate();
+}
+
+const String _SPAWNED_SIGNAL = "spawned";
+
+class _IsolateNatives {
+
+  /**
+   * The src url for the script tag that loaded this code. Used to create
+   * JavaScript workers.
+   */
+  static String get _thisScript => JS("String", r"$thisScriptUrl");
+
+  /** Starts a new worker with the given URL. */
+  static _WorkerStub _newWorker(url) => JS("_WorkerStub", r"new Worker(#)", url);
+
+  /**
+   * Assume that [e] is a browser message event and extract its message data.
+   * We don't import the dom explicitly so, when workers are disabled, this
+   * library can also run on top of nodejs.
+   */
+  //static _getEventData(e) => JS("Object", "#.data", e);
+  static _getEventData(e) => JS("", "#.data", e);
+
+  /**
+   * Process messages on a worker, either to control the worker instance or to
+   * pass messages along to the isolate running in the worker.
+   */
+  static void _processWorkerMessage(sender, e) {
+    var msg = _deserializeMessage(_getEventData(e));
+    switch (msg['command']) {
+      case 'start':
+        _globalState.currentManagerId = msg['id'];
+        Function entryPoint = _getJSFunctionFromName(msg['functionName']);
+        var replyTo = _deserializeMessage(msg['replyTo']);
+        _globalState.topEventLoop.enqueue(new _IsolateContext(), function() {
+          _startIsolate(entryPoint, replyTo);
+        }, 'worker-start');
+        _globalState.topEventLoop.run();
+        break;
+      case 'spawn-worker':
+        _spawnWorker(msg['functionName'], msg['uri'], msg['replyPort']);
+        break;
+      case 'message':
+        msg['port'].send(msg['msg'], msg['replyTo']);
+        _globalState.topEventLoop.run();
+        break;
+      case 'close':
+        _log("Closing Worker");
+        _globalState.managers.remove(sender.id);
+        sender.terminate();
+        _globalState.topEventLoop.run();
+        break;
+      case 'log':
+        _log(msg['msg']);
+        break;
+      case 'print':
+        if (_globalState.isWorker) {
+          _globalState.mainManager.postMessage(
+              _serializeMessage({'command': 'print', 'msg': msg}));
+        } else {
+          print(msg['msg']);
+        }
+        break;
+      case 'error':
+        throw msg['msg'];
+    }
+  }
+
+  /** Log a message, forwarding to the main [_Manager] if appropriate. */
+  static _log(msg) {
+    if (_globalState.isWorker) {
+      _globalState.mainManager.postMessage(
+          _serializeMessage({'command': 'log', 'msg': msg }));
+    } else {
+      try {
+        _consoleLog(msg);
+      } catch (e, trace) {
+        throw new Exception(trace);
+      }
+    }
+  }
+
+  static void _consoleLog(msg) {
+    JS("void", r"$globalThis.console.log(#)", msg);
+  }
+
+  /**
+   * Extract the constructor of runnable, so it can be allocated in another
+   * isolate.
+   */
+  static dynamic _getJSConstructor(Isolate runnable) {
+    return JS("Object", "#.constructor", runnable);
+  }
+
+  /** Extract the constructor name of a runnable */
+  // TODO(sigmund): find a browser-generic way to support this.
+  // TODO(floitsch): is this function still used? If yes, should we use
+  // Primitives.objectTypeName instead?
+  static dynamic _getJSConstructorName(Isolate runnable) {
+    return JS("Object", "#.constructor.name", runnable);
+  }
+
+  /** Find a constructor given its name. */
+  static dynamic _getJSConstructorFromName(String factoryName) {
+    return JS("Object", r"$globalThis[#]", factoryName);
+  }
+
+  static dynamic _getJSFunctionFromName(String functionName) {
+    return JS("Object", r"$globalThis[#]", functionName);
+  }
+
+  /**
+   * Get a string name for the function, if possible.  The result for
+   * anonymous functions is browser-dependent -- it may be "" or "anonymous"
+   * but you should probably not count on this.
+   */
+  static String _getJSFunctionName(Function f) {
+    return JS("Object", r"(#.$name || #)", f, null);
+  }
+
+  /** Create a new JavaScript object instance given its constructor. */
+  static dynamic _allocate(var ctor) {
+    return JS("Object", "new #()", ctor);
+  }
+
+  // TODO(sigmund): clean up above, after we make the new API the default:
+
+  static _spawn(String functionName, String uri, bool isLight) {
+    Completer<SendPort> completer = new Completer<SendPort>();
+    ReceivePort port = new ReceivePort();
+    port.receive((msg, SendPort replyPort) {
+      port.close();
+      assert(msg == _SPAWNED_SIGNAL);
+      completer.complete(replyPort);
+    });
+
+    SendPort signalReply = port.toSendPort();
+
+    if (_globalState.useWorkers && !isLight) {
+      _startWorker(functionName, uri, signalReply);
+    } else {
+      _startNonWorker(functionName, uri, signalReply);
+    }
+    return new _BufferingSendPort(
+        _globalState.currentContext.id, completer.future);
+  }
+
+  static SendPort _startWorker(
+      String functionName, String uri, SendPort replyPort) {
+    if (_globalState.isWorker) {
+      _globalState.mainManager.postMessage(_serializeMessage({
+          'command': 'spawn-worker',
+          'functionName': functionName,
+          'uri': uri,
+          'replyPort': replyPort}));
+    } else {
+      _spawnWorker(functionName, uri, replyPort);
+    }
+  }
+
+  static SendPort _startNonWorker(
+      String functionName, String uri, SendPort replyPort) {
+    // TODO(eub): support IE9 using an iframe -- Dart issue 1702.
+    if (uri != null) throw new UnsupportedError(
+            "Currently spawnUri is not supported without web workers.");
+    _globalState.topEventLoop.enqueue(new _IsolateContext(), function() {
+      final func = _getJSFunctionFromName(functionName);
+      _startIsolate(func, replyPort);
+    }, 'nonworker start');
+  }
+
+  static void _startIsolate(Function topLevel, SendPort replyTo) {
+    _fillStatics(_globalState.currentContext);
+    _lazyPort = new ReceivePort();
+    replyTo.send(_SPAWNED_SIGNAL, port.toSendPort());
+
+    topLevel();
+  }
+
+  /**
+   * Spawns an isolate in a worker. [factoryName] is the Javascript constructor
+   * name for the isolate entry point class.
+   */
+  static void _spawnWorker(functionName, uri, replyPort) {
+    if (functionName == null) functionName = 'main';
+    if (uri == null) uri = _thisScript;
+    if (!(new Uri.fromString(uri).isAbsolute())) {
+      // The constructor of dom workers requires an absolute URL. If we use a
+      // relative path we will get a DOM exception.
+      String prefix = _thisScript.substring(0, _thisScript.lastIndexOf('/'));
+      uri = "$prefix/$uri";
+    }
+    final worker = _newWorker(uri);
+    worker.onmessage = (e) { _processWorkerMessage(worker, e); };
+    var workerId = _globalState.nextManagerId++;
+    // We also store the id on the worker itself so that we can unregister it.
+    worker.id = workerId;
+    _globalState.managers[workerId] = worker;
+    worker.postMessage(_serializeMessage({
+      'command': 'start',
+      'id': workerId,
+      // Note: we serialize replyPort twice because the child worker needs to
+      // first deserialize the worker id, before it can correctly deserialize
+      // the port (port deserialization is sensitive to what is the current
+      // workerId).
+      'replyTo': _serializeMessage(replyPort),
+      'functionName': functionName }));
+  }
+}
+
+/********************************************************
+  Inserted from lib/isolate/dart2js/ports.dart
+ ********************************************************/
+
+/** Common functionality to all send ports. */
+class _BaseSendPort implements SendPort {
+  /** Id for the destination isolate. */
+  final int _isolateId;
+
+  const _BaseSendPort(this._isolateId);
+
+  void _checkReplyTo(SendPort replyTo) {
+    if (replyTo != null
+        && replyTo is! _NativeJsSendPort
+        && replyTo is! _WorkerSendPort
+        && replyTo is! _BufferingSendPort) {
+      throw new Exception("SendPort.send: Illegal replyTo port type");
+    }
+  }
+
+  Future call(var message) {
+    final completer = new Completer();
+    final port = new _ReceivePortImpl();
+    send(message, port.toSendPort());
+    port.receive((value, ignoreReplyTo) {
+      port.close();
+      if (value is Exception) {
+        completer.completeException(value);
+      } else {
+        completer.complete(value);
+      }
+    });
+    return completer.future;
+  }
+
+  void send(var message, [SendPort replyTo]);
+  bool operator ==(var other);
+  int get hashCode;
+}
+
+/** A send port that delivers messages in-memory via native JavaScript calls. */
+class _NativeJsSendPort extends _BaseSendPort implements SendPort {
+  final _ReceivePortImpl _receivePort;
+
+  const _NativeJsSendPort(this._receivePort, int isolateId) : super(isolateId);
+
+  void send(var message, [SendPort replyTo = null]) {
+    _waitForPendingPorts([message, replyTo], () {
+      _checkReplyTo(replyTo);
+      // Check that the isolate still runs and the port is still open
+      final isolate = _globalState.isolates[_isolateId];
+      if (isolate == null) return;
+      if (_receivePort._callback == null) return;
+
+      // We force serialization/deserialization as a simple way to ensure
+      // isolate communication restrictions are respected between isolates that
+      // live in the same worker. [_NativeJsSendPort] delivers both messages
+      // from the same worker and messages from other workers. In particular,
+      // messages sent from a worker via a [_WorkerSendPort] are received at
+      // [_processWorkerMessage] and forwarded to a native port. In such cases,
+      // here we'll see [_globalState.currentContext == null].
+      final shouldSerialize = _globalState.currentContext != null
+          && _globalState.currentContext.id != _isolateId;
+      var msg = message;
+      var reply = replyTo;
+      if (shouldSerialize) {
+        msg = _serializeMessage(msg);
+        reply = _serializeMessage(reply);
+      }
+      _globalState.topEventLoop.enqueue(isolate, () {
+        if (_receivePort._callback != null) {
+          if (shouldSerialize) {
+            msg = _deserializeMessage(msg);
+            reply = _deserializeMessage(reply);
+          }
+          _receivePort._callback(msg, reply);
+        }
+      }, 'receive $message');
+    });
+  }
+
+  bool operator ==(var other) => (other is _NativeJsSendPort) &&
+      (_receivePort == other._receivePort);
+
+  int get hashCode => _receivePort._id;
+}
+
+/** A send port that delivers messages via worker.postMessage. */
+// TODO(eub): abstract this for iframes.
+class _WorkerSendPort extends _BaseSendPort implements SendPort {
+  final int _workerId;
+  final int _receivePortId;
+
+  const _WorkerSendPort(this._workerId, int isolateId, this._receivePortId)
+      : super(isolateId);
+
+  void send(var message, [SendPort replyTo = null]) {
+    _waitForPendingPorts([message, replyTo], () {
+      _checkReplyTo(replyTo);
+      final workerMessage = _serializeMessage({
+          'command': 'message',
+          'port': this,
+          'msg': message,
+          'replyTo': replyTo});
+
+      if (_globalState.isWorker) {
+        // communication from one worker to another go through the main worker:
+        _globalState.mainManager.postMessage(workerMessage);
+      } else {
+        _globalState.managers[_workerId].postMessage(workerMessage);
+      }
+    });
+  }
+
+  bool operator ==(var other) {
+    return (other is _WorkerSendPort) &&
+        (_workerId == other._workerId) &&
+        (_isolateId == other._isolateId) &&
+        (_receivePortId == other._receivePortId);
+  }
+
+  int get hashCode {
+    // TODO(sigmund): use a standard hash when we get one available in corelib.
+    return (_workerId << 16) ^ (_isolateId << 8) ^ _receivePortId;
+  }
+}
+
+/** A port that buffers messages until an underlying port gets resolved. */
+class _BufferingSendPort extends _BaseSendPort implements SendPort {
+  /** Internal counter to assign unique ids to each port. */
+  static int _idCount = 0;
+
+  /** For implementing equals and hashcode. */
+  final int _id;
+
+  /** Underlying port, when resolved. */
+  SendPort _port;
+
+  /**
+   * Future of the underlying port, so that we can detect when this port can be
+   * sent on messages.
+   */
+  Future<SendPort> _futurePort;
+
+  /** Pending messages (and reply ports). */
+  List pending;
+
+  _BufferingSendPort(isolateId, this._futurePort)
+      : super(isolateId), _id = _idCount, pending = [] {
+    _idCount++;
+    _futurePort.then((p) {
+      _port = p;
+      for (final item in pending) {
+        p.send(item['message'], item['replyTo']);
+      }
+      pending = null;
+    });
+  }
+
+  _BufferingSendPort.fromPort(isolateId, this._port)
+      : super(isolateId), _id = _idCount {
+    _idCount++;
+  }
+
+  void send(var message, [SendPort replyTo]) {
+    if (_port != null) {
+      _port.send(message, replyTo);
+    } else {
+      pending.add({'message': message, 'replyTo': replyTo});
+    }
+  }
+
+  bool operator ==(var other) =>
+      other is _BufferingSendPort && _id == other._id;
+  int get hashCode => _id;
+}
 
 /** Default factory for receive ports. */
 patch class ReceivePort {
   patch factory ReceivePort() {
-    return new ReceivePortImpl();
+    return new _ReceivePortImpl();
+  }
+
+}
+
+/** Implementation of a multi-use [ReceivePort] on top of JavaScript. */
+class _ReceivePortImpl implements ReceivePort {
+  int _id;
+  Function _callback;
+  static int _nextFreeId = 1;
+
+  _ReceivePortImpl()
+      : _id = _nextFreeId++ {
+    _globalState.currentContext.register(_id, this);
+  }
+
+  void receive(void onMessage(var message, SendPort replyTo)) {
+    _callback = onMessage;
+  }
+
+  void close() {
+    _callback = null;
+    _globalState.currentContext.unregister(_id);
+  }
+
+  SendPort toSendPort() {
+    return new _NativeJsSendPort(this, _globalState.currentContext.id);
+  }
+}
+
+/** Wait until all ports in a message are resolved. */
+_waitForPendingPorts(var message, void callback()) {
+  final finder = new _PendingSendPortFinder();
+  finder.traverse(message);
+  Futures.wait(finder.ports).then((_) => callback());
+}
+
+
+/** Visitor that finds all unresolved [SendPort]s in a message. */
+class _PendingSendPortFinder extends _MessageTraverser {
+  List<Future<SendPort>> ports;
+  _PendingSendPortFinder() : super(), ports = [] {
+    _visited = new _JsVisitedMap();
+  }
+
+  visitPrimitive(x) {}
+
+  visitList(List list) {
+    final seen = _visited[list];
+    if (seen != null) return;
+    _visited[list] = true;
+    // TODO(sigmund): replace with the following: (bug #1660)
+    // list.forEach(_dispatch);
+    list.forEach((e) => _dispatch(e));
+  }
+
+  visitMap(Map map) {
+    final seen = _visited[map];
+    if (seen != null) return;
+
+    _visited[map] = true;
+    // TODO(sigmund): replace with the following: (bug #1660)
+    // map.values.forEach(_dispatch);
+    map.values.forEach((e) => _dispatch(e));
+  }
+
+  visitSendPort(SendPort port) {
+    if (port is _BufferingSendPort && port._port == null) {
+      ports.add(port._futurePort);
+    }
+  }
+}
+
+/********************************************************
+  Inserted from lib/isolate/dart2js/messages.dart
+ ********************************************************/
+
+// Defines message visitors, serialization, and deserialization.
+
+/** Serialize [message] (or simulate serialization). */
+_serializeMessage(message) {
+  if (_globalState.needSerialization) {
+    return new _JsSerializer().traverse(message);
+  } else {
+    return new _JsCopier().traverse(message);
+  }
+}
+
+/** Deserialize [message] (or simulate deserialization). */
+_deserializeMessage(message) {
+  if (_globalState.needSerialization) {
+    return new _JsDeserializer().deserialize(message);
+  } else {
+    // Nothing more to do.
+    return message;
+  }
+}
+
+class _JsSerializer extends _Serializer {
+
+  _JsSerializer() : super() { _visited = new _JsVisitedMap(); }
+
+  visitSendPort(SendPort x) {
+    if (x is _NativeJsSendPort) return visitNativeJsSendPort(x);
+    if (x is _WorkerSendPort) return visitWorkerSendPort(x);
+    if (x is _BufferingSendPort) return visitBufferingSendPort(x);
+    throw "Illegal underlying port $x";
+  }
+
+  visitNativeJsSendPort(_NativeJsSendPort port) {
+    return ['sendport', _globalState.currentManagerId,
+        port._isolateId, port._receivePort._id];
+  }
+
+  visitWorkerSendPort(_WorkerSendPort port) {
+    return ['sendport', port._workerId, port._isolateId, port._receivePortId];
+  }
+
+  visitBufferingSendPort(_BufferingSendPort port) {
+    if (port._port != null) {
+      return visitSendPort(port._port);
+    } else {
+      // TODO(floitsch): Use real exception (which one?).
+      throw
+          "internal error: must call _waitForPendingPorts to ensure all"
+          " ports are resolved at this point.";
+    }
+  }
+
+}
+
+
+class _JsCopier extends _Copier {
+
+  _JsCopier() : super() { _visited = new _JsVisitedMap(); }
+
+  visitSendPort(SendPort x) {
+    if (x is _NativeJsSendPort) return visitNativeJsSendPort(x);
+    if (x is _WorkerSendPort) return visitWorkerSendPort(x);
+    if (x is _BufferingSendPort) return visitBufferingSendPort(x);
+    throw "Illegal underlying port $p";
+  }
+
+  SendPort visitNativeJsSendPort(_NativeJsSendPort port) {
+    return new _NativeJsSendPort(port._receivePort, port._isolateId);
+  }
+
+  SendPort visitWorkerSendPort(_WorkerSendPort port) {
+    return new _WorkerSendPort(
+        port._workerId, port._isolateId, port._receivePortId);
+  }
+
+  SendPort visitBufferingSendPort(_BufferingSendPort port) {
+    if (port._port != null) {
+      return visitSendPort(port._port);
+    } else {
+      // TODO(floitsch): Use real exception (which one?).
+      throw
+          "internal error: must call _waitForPendingPorts to ensure all"
+          " ports are resolved at this point.";
+    }
+  }
+
+}
+
+class _JsDeserializer extends _Deserializer {
+
+  SendPort deserializeSendPort(List x) {
+    int managerId = x[1];
+    int isolateId = x[2];
+    int receivePortId = x[3];
+    // If two isolates are in the same manager, we use NativeJsSendPorts to
+    // deliver messages directly without using postMessage.
+    if (managerId == _globalState.currentManagerId) {
+      var isolate = _globalState.isolates[isolateId];
+      if (isolate == null) return null; // Isolate has been closed.
+      var receivePort = isolate.lookup(receivePortId);
+      return new _NativeJsSendPort(receivePort, isolateId);
+    } else {
+      return new _WorkerSendPort(managerId, isolateId, receivePortId);
+    }
+  }
+
+}
+
+class _JsVisitedMap implements _MessageTraverserVisitedMap {
+  List tagged;
+
+  /** Retrieves any information stored in the native object [object]. */
+  operator[](var object) {
+    return _getAttachedInfo(object);
+  }
+
+  /** Injects some information into the native [object]. */
+  void operator[]=(var object, var info) {
+    tagged.add(object);
+    _setAttachedInfo(object, info);
+  }
+
+  /** Get ready to rumble. */
+  void reset() {
+    assert(tagged == null);
+    tagged = new List();
+  }
+
+  /** Remove all information injected in the native objects. */
+  void cleanup() {
+    for (int i = 0, length = tagged.length; i < length; i++) {
+      _clearAttachedInfo(tagged[i]);
+    }
+    tagged = null;
+  }
+
+  void _clearAttachedInfo(var o) {
+    JS("void", "#['__MessageTraverser__attached_info__'] = #", o, null);
+  }
+
+  void _setAttachedInfo(var o, var info) {
+    JS("void", "#['__MessageTraverser__attached_info__'] = #", o, info);
+  }
+
+  _getAttachedInfo(var o) {
+    return JS("", "#['__MessageTraverser__attached_info__']", o);
+  }
+}
+
+// only visible for testing purposes
+// TODO(sigmund): remove once we can disable privacy for testing (bug #1882)
+class TestingOnly {
+  static copy(x) {
+    return new _JsCopier().traverse(x);
+  }
+
+  // only visible for testing purposes
+  static serialize(x) {
+    _Serializer serializer = new _JsSerializer();
+    _Deserializer deserializer = new _JsDeserializer();
+    return deserializer.deserialize(serializer.traverse(x));
+  }
+}
+
+/********************************************************
+  Inserted from lib/isolate/serialization.dart
+ ********************************************************/
+
+class _MessageTraverserVisitedMap {
+
+  operator[](var object) => null;
+  void operator[]=(var object, var info) { }
+
+  void reset() { }
+  void cleanup() { }
+
+}
+
+/** Abstract visitor for dart objects that can be sent as isolate messages. */
+class _MessageTraverser {
+
+  _MessageTraverserVisitedMap _visited;
+  _MessageTraverser() : _visited = new _MessageTraverserVisitedMap();
+
+  /** Visitor's entry point. */
+  traverse(var x) {
+    if (isPrimitive(x)) return visitPrimitive(x);
+    _visited.reset();
+    var result;
+    try {
+      result = _dispatch(x);
+    } finally {
+      _visited.cleanup();
+    }
+    return result;
+  }
+
+  _dispatch(var x) {
+    if (isPrimitive(x)) return visitPrimitive(x);
+    if (x is List) return visitList(x);
+    if (x is Map) return visitMap(x);
+    if (x is SendPort) return visitSendPort(x);
+    if (x is SendPortSync) return visitSendPortSync(x);
+
+    // Overridable fallback.
+    return visitObject(x);
+  }
+
+  visitPrimitive(x);
+  visitList(List x);
+  visitMap(Map x);
+  visitSendPort(SendPort x);
+  visitSendPortSync(SendPortSync x);
+
+  visitObject(Object x) {
+    // TODO(floitsch): make this a real exception. (which one)?
+    throw "Message serialization: Illegal value $x passed";
+  }
+
+  static bool isPrimitive(x) {
+    return (x == null) || (x is String) || (x is num) || (x is bool);
+  }
+}
+
+
+/** A visitor that recursively copies a message. */
+class _Copier extends _MessageTraverser {
+
+  visitPrimitive(x) => x;
+
+  List visitList(List list) {
+    List copy = _visited[list];
+    if (copy != null) return copy;
+
+    int len = list.length;
+
+    // TODO(floitsch): we loose the generic type of the List.
+    copy = new List(len);
+    _visited[list] = copy;
+    for (int i = 0; i < len; i++) {
+      copy[i] = _dispatch(list[i]);
+    }
+    return copy;
+  }
+
+  Map visitMap(Map map) {
+    Map copy = _visited[map];
+    if (copy != null) return copy;
+
+    // TODO(floitsch): we loose the generic type of the map.
+    copy = new Map();
+    _visited[map] = copy;
+    map.forEach((key, val) {
+      copy[_dispatch(key)] = _dispatch(val);
+    });
+    return copy;
+  }
+
+}
+
+/** Visitor that serializes a message as a JSON array. */
+class _Serializer extends _MessageTraverser {
+  int _nextFreeRefId = 0;
+
+  visitPrimitive(x) => x;
+
+  visitList(List list) {
+    int copyId = _visited[list];
+    if (copyId != null) return ['ref', copyId];
+
+    int id = _nextFreeRefId++;
+    _visited[list] = id;
+    var jsArray = _serializeList(list);
+    // TODO(floitsch): we are losing the generic type.
+    return ['list', id, jsArray];
+  }
+
+  visitMap(Map map) {
+    int copyId = _visited[map];
+    if (copyId != null) return ['ref', copyId];
+
+    int id = _nextFreeRefId++;
+    _visited[map] = id;
+    var keys = _serializeList(map.keys);
+    var values = _serializeList(map.values);
+    // TODO(floitsch): we are losing the generic type.
+    return ['map', id, keys, values];
+  }
+
+  _serializeList(List list) {
+    int len = list.length;
+    var result = new List(len);
+    for (int i = 0; i < len; i++) {
+      result[i] = _dispatch(list[i]);
+    }
+    return result;
+  }
+}
+
+/** Deserializes arrays created with [_Serializer]. */
+class _Deserializer {
+  Map<int, dynamic> _deserialized;
+
+  _Deserializer();
+
+  static bool isPrimitive(x) {
+    return (x == null) || (x is String) || (x is num) || (x is bool);
+  }
+
+  deserialize(x) {
+    if (isPrimitive(x)) return x;
+    // TODO(floitsch): this should be new HashMap<int, var|Dynamic>()
+    _deserialized = new HashMap();
+    return _deserializeHelper(x);
+  }
+
+  _deserializeHelper(x) {
+    if (isPrimitive(x)) return x;
+    assert(x is List);
+    switch (x[0]) {
+      case 'ref': return _deserializeRef(x);
+      case 'list': return _deserializeList(x);
+      case 'map': return _deserializeMap(x);
+      case 'sendport': return deserializeSendPort(x);
+      default: return deserializeObject(x);
+    }
+  }
+
+  _deserializeRef(List x) {
+    int id = x[1];
+    var result = _deserialized[id];
+    assert(result != null);
+    return result;
+  }
+
+  List _deserializeList(List x) {
+    int id = x[1];
+    // We rely on the fact that Dart-lists are directly mapped to Js-arrays.
+    List dartList = x[2];
+    _deserialized[id] = dartList;
+    int len = dartList.length;
+    for (int i = 0; i < len; i++) {
+      dartList[i] = _deserializeHelper(dartList[i]);
+    }
+    return dartList;
+  }
+
+  Map _deserializeMap(List x) {
+    Map result = new Map();
+    int id = x[1];
+    _deserialized[id] = result;
+    List keys = x[2];
+    List values = x[3];
+    int len = keys.length;
+    assert(len == values.length);
+    for (int i = 0; i < len; i++) {
+      var key = _deserializeHelper(keys[i]);
+      var value = _deserializeHelper(values[i]);
+      result[key] = value;
+    }
+    return result;
+  }
+
+  deserializeSendPort(List x);
+
+  deserializeObject(List x) {
+    // TODO(floitsch): Use real exception (which one?).
+    throw "Unexpected serialized object";
+  }
+}
+
+/********************************************************
+  Inserted from lib/isolate/dart2js/timer_provider.dart
+ ********************************************************/
+
+// We don't want to import the DOM library just because of window.setTimeout,
+// so we reconstruct the Window class here. The only conflict that could happen
+// with the other DOMWindow class would be because of subclasses.
+// Currently, none of the two Dart classes have subclasses.
+typedef void _TimeoutHandler();
+
+class _Window native "@*DOMWindow" {
+  int setTimeout(_TimeoutHandler handler, int timeout) native;
+  int setInterval(_TimeoutHandler handler, int timeout) native;
+  void clearTimeout(int handle) native;
+  void clearInterval(int handle) native;
+}
+
+_Window get _window =>
+  JS('bool', 'typeof window != "undefined"') ? JS('_Window', 'window') : null;
+
+class _Timer implements Timer {
+  final bool _once;
+  int _handle;
+
+  _Timer(int milliSeconds, void callback(Timer timer))
+      : _once = true {
+    _handle = _window.setTimeout(() => callback(this), milliSeconds);
+  }
+
+  _Timer.repeating(int milliSeconds, void callback(Timer timer))
+      : _once = false {
+    _handle = _window.setInterval(() => callback(this), milliSeconds);
+  }
+
+  void cancel() {
+    if (_once) {
+      _window.clearTimeout(_handle);
+    } else {
+      _window.clearInterval(_handle);
+    }
   }
 }
 
 patch class Timer {
-  patch factory Timer(int milliseconds, void callback(Timer timer)) {
-    if (!hasWindow()) {
+  patch factory Timer(int milliSeconds, void callback(Timer timer)) {
+    if (_window == null) {
       throw new UnsupportedError("Timer interface not supported.");
     }
-    return new TimerImpl(milliseconds, callback);
+    return new _Timer(milliSeconds, callback);
   }
 
   /**
    * Creates a new repeating timer. The [callback] is invoked every
-   * [milliseconds] millisecond until cancelled.
+   * [milliSeconds] millisecond until cancelled.
    */
-  patch factory Timer.repeating(int milliseconds, void callback(Timer timer)) {
-    if (!hasWindow()) {
+  patch factory Timer.repeating(int milliSeconds, void callback(Timer timer)) {
+    if (_window == null) {
       throw new UnsupportedError("Timer interface not supported.");
     }
-    return new TimerImpl.repeating(milliseconds, callback);
+    return new _Timer.repeating(milliSeconds, callback);
   }
 }
diff --git a/sdk/lib/_internal/compiler/implementation/native_handler.dart b/sdk/lib/_internal/compiler/implementation/native_handler.dart
index 0d30ecd..38f8439 100644
--- a/sdk/lib/_internal/compiler/implementation/native_handler.dart
+++ b/sdk/lib/_internal/compiler/implementation/native_handler.dart
@@ -453,6 +453,7 @@
   String libraryName = uri.toString();
   if (library.entryCompilationUnit.script.name.contains(
           'dart/tests/compiler/dart2js_native')
+      || libraryName == 'dart:isolate'
       || libraryName == 'dart:html'
       || libraryName == 'dart:html_common'
       || libraryName == 'dart:indexed_db'
diff --git a/sdk/lib/_internal/compiler/implementation/ssa/builder.dart b/sdk/lib/_internal/compiler/implementation/ssa/builder.dart
index 8e51857..cc3f726 100644
--- a/sdk/lib/_internal/compiler/implementation/ssa/builder.dart
+++ b/sdk/lib/_internal/compiler/implementation/ssa/builder.dart
@@ -3027,7 +3027,7 @@
       // Call a helper method from the isolate library. The isolate
       // library uses its own isolate structure, that encapsulates
       // Leg's isolate.
-      Element element = compiler.isolateHelperLibrary.find(
+      Element element = compiler.isolateLibrary.find(
           const SourceString('_currentIsolate'));
       if (element == null) {
         compiler.cancel(
@@ -3047,7 +3047,7 @@
       push(new HInvokeClosure(selector, <HInstruction>[pop()]));
     } else {
       // Call a helper method from the isolate library.
-      Element element = compiler.isolateHelperLibrary.find(
+      Element element = compiler.isolateLibrary.find(
           const SourceString('_callInIsolate'));
       if (element == null) {
         compiler.cancel(
diff --git a/sdk/lib/_internal/libraries.dart b/sdk/lib/_internal/libraries.dart
index 29b3f36..fd8b5ab 100644
--- a/sdk/lib/_internal/libraries.dart
+++ b/sdk/lib/_internal/libraries.dart
@@ -115,12 +115,6 @@
       category: "Internal",
       documented: false,
       platforms: DART2JS_PLATFORM),
-
-  "_isolate_helper": const LibraryInfo(
-      "_internal/compiler/implementation/lib/isolate_helper.dart",
-      category: "Internal",
-      documented: false,
-      platforms: DART2JS_PLATFORM),
 };
 
 /**
diff --git a/sdk/lib/isolate/timer.dart b/sdk/lib/isolate/timer.dart
index 1364239..838348a 100644
--- a/sdk/lib/isolate/timer.dart
+++ b/sdk/lib/isolate/timer.dart
@@ -5,15 +5,15 @@
 abstract class Timer {
   /**
    * Creates a new timer. The [callback] callback is invoked after
-   * [milliseconds] milliseconds.
+   * [milliSeconds] milliseconds.
    */
-  external factory Timer(int milliseconds, void callback(Timer timer));
+  external factory Timer(int milliSeconds, void callback(Timer timer));
 
   /**
    * Creates a new repeating timer. The [callback] is invoked every
-   * [milliseconds] millisecond until cancelled.
+   * [milliSeconds] millisecond until cancelled.
    */
-  external factory Timer.repeating(int milliseconds,
+  external factory Timer.repeating(int milliSeconds,
                                    void callback(Timer timer));
 
   /**
diff --git a/tools/VERSION b/tools/VERSION
index 077bc36..72767085 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -1,4 +1,4 @@
 MAJOR 0
 MINOR 2
 BUILD 9
-PATCH 6
+PATCH 7