Reapply setTimeout change.
This CL is identical to 18555. The reason it will  work now is the corresponding
dartium change has been checked in.

TBR-blois

BUG=

Review URL: https://codereview.chromium.org//12254046

git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart@18562 260f80e4-7a28-3924-810f-c04153c831b5
diff --git a/sdk/lib/html/dart2js/html_dart2js.dart b/sdk/lib/html/dart2js/html_dart2js.dart
index 257d672..8688fea 100644
--- a/sdk/lib/html/dart2js/html_dart2js.dart
+++ b/sdk/lib/html/dart2js/html_dart2js.dart
@@ -25826,6 +25826,56 @@
 @DomName('Window')
 class Window extends EventTarget implements WindowBase native "@*DOMWindow" {
 
+  /**
+   * Executes a [callback] after the immediate execution stack has completed.
+   *
+   * This differs from using Timer.run(callback)
+   * because Timer will run in about 4-15 milliseconds, depending on browser,
+   * depending on load. [setImmediate], in contrast, makes browser-specific
+   * changes in behavior to attempt to run immediately after the current
+   * frame unwinds, causing the future to complete after all processing has
+   * completed for the current event, but before any subsequent events.
+   */
+  void setImmediate(TimeoutHandler callback) { 
+    _addMicrotaskCallback(callback);
+  }
+  /**
+   * Lookup a port by its [name].  Return null if no port is
+   * registered under [name].
+   */
+  SendPortSync lookupPort(String name) {
+    var port =
+        json.parse(document.documentElement.attributes['dart-port:$name']);
+    return _deserialize(port);
+  }
+
+  /**
+   * Register a [port] on this window under the given [name].  This
+   * port may be retrieved by any isolate (or JavaScript script)
+   * running in this window.
+   */
+  void registerPort(String name, var port) {
+    var serialized = _serialize(port);
+    document.documentElement.attributes['dart-port:$name'] =
+        json.stringify(serialized);
+  }
+
+  /**
+   * Returns a Future that completes just before the window is about to repaint
+   * so the user can draw an animation frame
+   *
+   * If you need to later cancel this animation, use [requestAnimationFrame]
+   * instead.
+   *
+   * Note: The code that runs when the future completes should call 
+   * [animationFrame] again for the animation to continue.
+   */
+  Future<num> get animationFrame {
+    var completer = new Completer<int>();
+    requestAnimationFrame(completer.complete);
+    return completer.future;
+  }
+
   Document get document => JS('Document', '#.document', this);
 
   WindowBase _open2(url, name) => JS('Window', '#.open(#,#)', this, url, name);
@@ -25891,15 +25941,21 @@
   }
 
   /**
-   * Executes a [callback] after the immediate execution stack has completed.
+   * Called to draw an animation frame and then request the window to repaint
+   * after [callback] has finished (creating the animation). 
    *
-   * This will cause the callback to be executed after all processing has
-   * completed for the current event, but before any subsequent events.
+   * Use this method only if you need to later call [cancelAnimationFrame]. If
+   * not, the preferred Dart idiom is to set animation frames by calling
+   * [animationFrame], which returns a Future.
+   *
+   * Returns a non-zero valued integer to represent the request id for this
+   * request. This value only needs to be saved if you intend to call
+   * [cancelAnimationFrame] so you can specify the particular animation to
+   * cancel.
+   *
+   * Note: The supplied [callback] needs to call [requestAnimationFrame] again
+   * for the animation to continue.
    */
-  void setImmediate(TimeoutHandler callback) {
-    _addMicrotaskCallback(callback);
-  }
-
   @DomName('DOMWindow.requestAnimationFrame')
   int requestAnimationFrame(RequestAnimationFrameCallback callback) {
     _ensureRequestAnimationFrame();
@@ -25958,25 +26014,6 @@
          '#.indexedDB || #.webkitIndexedDB || #.mozIndexedDB',
          this, this, this);
 
-  /**
-   * Lookup a port by its [name].  Return null if no port is
-   * registered under [name].
-   */
-  SendPortSync lookupPort(String name) {
-    var port = json.parse(document.documentElement.attributes['dart-port:$name']);
-    return _deserialize(port);
-  }
-
-  /**
-   * Register a [port] on this window under the given [name].  This
-   * port may be retrieved by any isolate (or JavaScript script)
-   * running in this window.
-   */
-  void registerPort(String name, var port) {
-    var serialized = _serialize(port);
-    document.documentElement.attributes['dart-port:$name'] = json.stringify(serialized);
-  }
-
   @DomName('Window.console')
   Console get console => Console.safeConsole;
 
@@ -26295,13 +26332,15 @@
   @DocsEditable
   void captureEvents() native;
 
+  @JSName('clearInterval')
   @DomName('DOMWindow.clearInterval')
   @DocsEditable
-  void clearInterval(int handle) native;
+  void _clearInterval(int handle) native;
 
+  @JSName('clearTimeout')
   @DomName('DOMWindow.clearTimeout')
   @DocsEditable
-  void clearTimeout(int handle) native;
+  void _clearTimeout(int handle) native;
 
   @DomName('DOMWindow.close')
   @DocsEditable
@@ -26413,13 +26452,15 @@
   @DocsEditable
   void scrollTo(int x, int y) native;
 
+  @JSName('setInterval')
   @DomName('DOMWindow.setInterval')
   @DocsEditable
-  int setInterval(TimeoutHandler handler, int timeout) native;
+  int _setInterval(TimeoutHandler handler, int timeout) native;
 
+  @JSName('setTimeout')
   @DomName('DOMWindow.setTimeout')
   @DocsEditable
-  int setTimeout(TimeoutHandler handler, int timeout) native;
+  int _setTimeout(TimeoutHandler handler, int timeout) native;
 
   @DomName('DOMWindow.showModalDialog')
   @DocsEditable
@@ -31416,11 +31457,11 @@
   var maker;
   var canceller;
   if (repeating) {
-    maker = window.setInterval;
-    canceller = window.clearInterval;
+    maker = window._setInterval;
+    canceller = window._clearInterval;
   } else {
-    maker = window.setTimeout;
-    canceller = window.clearTimeout;
+    maker = window._setTimeout;
+    canceller = window._clearTimeout;
   }
   Timer timer;
   final int id = maker(() { callback(timer); }, milliSeconds);
diff --git a/sdk/lib/html/dartium/html_dartium.dart b/sdk/lib/html/dartium/html_dartium.dart
index 3aefe46..ff46655 100644
--- a/sdk/lib/html/dartium/html_dartium.dart
+++ b/sdk/lib/html/dartium/html_dartium.dart
@@ -28225,19 +28225,23 @@
   /**
    * Executes a [callback] after the immediate execution stack has completed.
    *
-   * This will cause the callback to be executed after all processing has
+   * This differs from using Timer.run(callback)
+   * because Timer will run in about 4-15 milliseconds, depending on browser,
+   * depending on load. [setImmediate], in contrast, makes browser-specific
+   * changes in behavior to attempt to run immediately after the current
+   * frame unwinds, causing the future to complete after all processing has
    * completed for the current event, but before any subsequent events.
    */
-  void setImmediate(TimeoutHandler callback) {
+  void setImmediate(TimeoutHandler callback) { 
     _addMicrotaskCallback(callback);
   }
-
   /**
    * Lookup a port by its [name].  Return null if no port is
    * registered under [name].
    */
-  lookupPort(String name) {
-    var port = json.parse(document.documentElement.attributes['dart-port:$name']);
+  SendPortSync lookupPort(String name) {
+    var port =
+        json.parse(document.documentElement.attributes['dart-port:$name']);
     return _deserialize(port);
   }
 
@@ -28246,9 +28250,26 @@
    * port may be retrieved by any isolate (or JavaScript script)
    * running in this window.
    */
-  registerPort(String name, var port) {
+  void registerPort(String name, var port) {
     var serialized = _serialize(port);
-    document.documentElement.attributes['dart-port:$name'] = json.stringify(serialized);
+    document.documentElement.attributes['dart-port:$name'] =
+        json.stringify(serialized);
+  }
+
+  /**
+   * Returns a Future that completes just before the window is about to repaint
+   * so the user can draw an animation frame
+   *
+   * If you need to later cancel this animation, use [requestAnimationFrame]
+   * instead.
+   *
+   * Note: The code that runs when the future completes should call 
+   * [animationFrame] again for the animation to continue.
+   */
+  Future<num> get animationFrame {
+    var completer = new Completer<int>();
+    requestAnimationFrame(completer.complete);
+    return completer.future;
   }
 
   /// Checks if _setImmediate is supported.
@@ -28589,11 +28610,11 @@
 
   @DomName('DOMWindow.clearInterval')
   @DocsEditable
-  void clearInterval(int handle) native "DOMWindow_clearInterval_Callback";
+  void _clearInterval(int handle) native "DOMWindow_clearInterval_Callback";
 
   @DomName('DOMWindow.clearTimeout')
   @DocsEditable
-  void clearTimeout(int handle) native "DOMWindow_clearTimeout_Callback";
+  void _clearTimeout(int handle) native "DOMWindow_clearTimeout_Callback";
 
   @DomName('DOMWindow.close')
   @DocsEditable
@@ -28688,11 +28709,11 @@
 
   @DomName('DOMWindow.setInterval')
   @DocsEditable
-  int setInterval(TimeoutHandler handler, int timeout) native "DOMWindow_setInterval_Callback";
+  int _setInterval(TimeoutHandler handler, int timeout) native "DOMWindow_setInterval_Callback";
 
   @DomName('DOMWindow.setTimeout')
   @DocsEditable
-  int setTimeout(TimeoutHandler handler, int timeout) native "DOMWindow_setTimeout_Callback";
+  int _setTimeout(TimeoutHandler handler, int timeout) native "DOMWindow_setTimeout_Callback";
 
   @DomName('DOMWindow.showModalDialog')
   @DocsEditable
@@ -33885,11 +33906,11 @@
   var maker;
   var canceller;
   if (repeating) {
-    maker = window.setInterval;
-    canceller = window.clearInterval;
+    maker = window._setInterval;
+    canceller = window._clearInterval;
   } else {
-    maker = window.setTimeout;
-    canceller = window.clearTimeout;
+    maker = window._setTimeout;
+    canceller = window._clearTimeout;
   }
   Timer timer;
   final int id = maker(() { callback(timer); }, milliSeconds);
diff --git a/tests/benchmark_smoke/benchmark_base.dart b/tests/benchmark_smoke/benchmark_base.dart
index e2699cd..6b724c1 100644
--- a/tests/benchmark_smoke/benchmark_base.dart
+++ b/tests/benchmark_smoke/benchmark_base.dart
@@ -94,7 +94,7 @@
 class BenchmarkSuite {
   /** The set of benchmarks that have yet to run. */
   List<Function> benchmarks;
-  
+
   /**
    * The set of scores from the benchmarks that have already run. (Used for
    * calculating the Geometric mean).
@@ -112,15 +112,15 @@
     benchmarks = [() => Smoketest.main()];
     totalBenchmarks = benchmarks.length;
   }
-  
+
   /** Run all of the benchmarks that we have in our benchmarks list. */
   runBenchmarks() {
     runBenchmarksHelper(benchmarks);
   }
- 
+
    /**
    * Run the remaining benchmarks in our list. We chain the calls providing
-   * little breaks for the main page to gain control, so we don't force the 
+   * little breaks for the main page to gain control, so we don't force the
    * entire page to hang the whole time.
    */
   runBenchmarksHelper(List<Function> remainingBenchmarks) {
@@ -128,10 +128,11 @@
     var benchmark = remainingBenchmarks.removeLast();
     benchmark();
     if (remainingBenchmarks.length > 0) {
-      /* Provide small breaks between each benchmark, so that the browser 
+      /* Provide small breaks between each benchmark, so that the browser
       doesn't get unhappy about long running scripts, and so the user
       can regain control of the UI to kill the page as needed. */
-      window.setTimeout(() => runBenchmarksHelper(remainingBenchmarks), 25);
+      new Timer(const Duration(milliseconds: 25),
+          () => runBenchmarksHelper(remainingBenchmarks));
     } else if (remainingBenchmarks.length == 0) {
       // We've run all of the benchmarks. Update the page with the score.
       BENCHMARK_VIEW.setScore(geometricMean(scores));
@@ -140,7 +141,7 @@
 
   /** Store the results of a single benchmark run. */
   updateIndividualScore(String name, num score) {
-    scores.add(score); 
+    scores.add(score);
     BENCHMARK_VIEW.incrementProgress(name, score, totalBenchmarks);
   }
 
@@ -172,9 +173,9 @@
     body.nodes.add(
         new Element.html("<p id='testResultScore'>Score: $newScore</p>"));
   }
- 
+
   /**
-   * Update the page HTML to show how much progress we've made through the 
+   * Update the page HTML to show how much progress we've made through the
    * benchmarks.
    */
   incrementProgress(String name, num score, num totalBenchmarks) {
@@ -184,8 +185,8 @@
     // the user we're making progress.
     num percentage = 100 * numCompleted ~/ totalBenchmarks;
   }
-  
-  /** 
+
+  /**
    * Rounds the score to have at least three significant digits (hopefully)
    * helping readability of the scores.
    */
diff --git a/tests/benchmark_smoke/benchmark_lib.dart b/tests/benchmark_smoke/benchmark_lib.dart
index 33233ad..4171b28 100644
--- a/tests/benchmark_smoke/benchmark_lib.dart
+++ b/tests/benchmark_smoke/benchmark_lib.dart
@@ -4,6 +4,7 @@
 
 library benchmark_lib;
 
+import 'dart:async';
 import 'dart:html';
 import 'dart:math' as Math;
 
diff --git a/tests/benchmark_smoke/benchmark_smoke_test.dart b/tests/benchmark_smoke/benchmark_smoke_test.dart
index 2c46a48..2e45827 100644
--- a/tests/benchmark_smoke/benchmark_smoke_test.dart
+++ b/tests/benchmark_smoke/benchmark_smoke_test.dart
@@ -6,6 +6,7 @@
 
 // Tests that benchmark classes used in perf testing are not broken.
 import 'benchmark_lib.dart';
+import 'dart:async';
 import 'dart:html';
 import '../../pkg/unittest/lib/unittest.dart';
 import '../../pkg/unittest/lib/html_config.dart';
@@ -13,9 +14,9 @@
 void main() {
   useHtmlConfiguration();
 
-  test('performanceTesting', () { 
-    window.setTimeout(BENCHMARK_SUITE.runBenchmarks, 0);
-    window.setTimeout(expectAsync0(testForCompletion), 0);
+  test('performanceTesting', () {
+    Timer.run(BENCHMARK_SUITE.runBenchmarks);
+    Timer.run(expectAsync0(testForCompletion));
   });
 }
 
diff --git a/tests/html/async_window_test.dart b/tests/html/async_window_test.dart
index 1e55448..7410e49 100644
--- a/tests/html/async_window_test.dart
+++ b/tests/html/async_window_test.dart
@@ -2,29 +2,32 @@
 import '../../pkg/unittest/lib/unittest.dart';
 import '../../pkg/unittest/lib/html_config.dart';
 import 'dart:html';
+import 'dart:async';
 
 main() {
   useHtmlConfiguration();
-  test('Window.setTimeout', () {
-    window.setTimeout(expectAsync0((){}), 10);
+  test('Timer', () {
+    new Timer(const Duration(milliseconds: 10), expectAsync0((){}));
   });
-  test('Window.setInterval', () {
+  test('Timer.repeating', () {
     int counter = 0;
     int id = null;
-    id = window.setInterval(expectAsyncUntil0(
-      () {
-        if (counter == 3) {
-          counter = 1024;
-          window.clearInterval(id);
-          // Wait some more time to be sure callback won't be invoked any more.
-          window.setTimeout(expectAsync0((){}), 50);
-          return;
-        }
-        // As callback should have been cleared on 4th invocation, counter
-        // should never be greater than 3.
-        assert(counter < 3);
-        counter++;
-      },
-      () => counter == 3), 10);
+    new Timer.repeating(const Duration(milliseconds: 10),
+        expectAsyncUntil1(
+        (timer) {
+          if (counter == 3) {
+            counter = 1024;
+            timer.cancel();
+            // Wait some more time to be sure callback won't be invoked any
+            // more.
+            new Timer(const Duration(milliseconds: 50), expectAsync0((){}));
+            return;
+          }
+          // As callback should have been cleared on 4th invocation, counter
+          // should never be greater than 3.
+          assert(counter < 3);
+          counter++;
+        },
+        () => counter == 3));
   });
 }
diff --git a/tests/html/cssstyledeclaration_test.dart b/tests/html/cssstyledeclaration_test.dart
index a0ef366..1f86605 100644
--- a/tests/html/cssstyledeclaration_test.dart
+++ b/tests/html/cssstyledeclaration_test.dart
@@ -6,6 +6,7 @@
 import '../../pkg/unittest/lib/unittest.dart';
 import '../../pkg/unittest/lib/html_config.dart';
 import 'dart:html';
+import 'dart:async';
 
 main() {
   useHtmlConfiguration();
@@ -84,10 +85,10 @@
     document.body.children.add(element);
 
     // Need to wait one tick after the element has been added to the page.
-    window.setTimeout(expectAsync0(() {
+    new Timer(const Duration(milliseconds: 10), expectAsync0(() {
       element.style.textDecoration = 'underline';
       var style = element.getComputedStyle();
       expect(style.textDecoration, equals('underline'));
-    }), 10);
+    }));
   });
 }
diff --git a/tests/html/dromaeo_noop/dromaeo_smoke.dart b/tests/html/dromaeo_noop/dromaeo_smoke.dart
index fbae236..4dd24f2 100644
--- a/tests/html/dromaeo_noop/dromaeo_smoke.dart
+++ b/tests/html/dromaeo_noop/dromaeo_smoke.dart
@@ -3,6 +3,7 @@
 // BSD-style license that can be found in the LICENSE file.
 
 library dromaeo;
+import 'dart:async';
 import 'dart:html';
 import 'dart:json' as json;
 import '../../../samples/third_party/dromaeo/common/common.dart';
diff --git a/tests/html/history_test.dart b/tests/html/history_test.dart
index f2c7c12..7ee08ce 100644
--- a/tests/html/history_test.dart
+++ b/tests/html/history_test.dart
@@ -2,6 +2,7 @@
 import '../../pkg/unittest/lib/unittest.dart';
 import '../../pkg/unittest/lib/html_individual_config.dart';
 import 'dart:html';
+import 'dart:async';
 
 main() {
   useHtmlIndividualConfiguration();
@@ -42,14 +43,14 @@
         expect(window.location.href.endsWith('dummy2'), isTrue);
 
         // Need to wait a frame or two to let the pushState events occur.
-        window.setTimeout(expectAsync0(() {
+        new Timer(const Duration(milliseconds: 100), expectAsync0(() {
           window.onPopState.first.then(expectAsync1((_){
             expect(window.history.length, length);
             expect(window.location.href.endsWith('dummy1'), isTrue);
           }));
 
           window.history.back();
-        }), 100);
+        }));
       }, expectation);
     });
 
diff --git a/tests/html/js_interop_3_test.dart b/tests/html/js_interop_3_test.dart
index 142c4d9..390c687 100644
--- a/tests/html/js_interop_3_test.dart
+++ b/tests/html/js_interop_3_test.dart
@@ -5,6 +5,7 @@
 library JsInterop3Test;
 import '../../pkg/unittest/lib/unittest.dart';
 import '../../pkg/unittest/lib/html_config.dart';
+import 'dart:async';
 import 'dart:html';
 import 'dart:isolate';
 
@@ -43,7 +44,7 @@
     var done = expectAsync0(() {});
     var fun2 = (message) {
       expect(message, 42);
-      window.setTimeout(done, 0);
+      Timer.run(done);
     };
 
     var port2 = new ReceivePortSync();
diff --git a/tests/html/js_interop_4_test.dart b/tests/html/js_interop_4_test.dart
index 935c790..944506b 100644
--- a/tests/html/js_interop_4_test.dart
+++ b/tests/html/js_interop_4_test.dart
@@ -5,6 +5,7 @@
 library JsInterop4Test;
 import '../../pkg/unittest/lib/unittest.dart';
 import '../../pkg/unittest/lib/html_config.dart';
+import 'dart:async';
 import 'dart:html';
 import 'dart:isolate';
 
@@ -52,7 +53,7 @@
     var done = expectAsync0(() {});
     var fun2 = (message) {
       expect(message, 3);
-      window.setTimeout(done, 0);
+      Timer.run(done);
     };
 
     var port2 = new ReceivePortSync();
diff --git a/tests/html/microtask_test.dart b/tests/html/microtask_test.dart
index 0dfcc53..79adb28 100644
--- a/tests/html/microtask_test.dart
+++ b/tests/html/microtask_test.dart
@@ -5,6 +5,7 @@
 library microtask_;
 import '../../pkg/unittest/lib/unittest.dart';
 import '../../pkg/unittest/lib/html_config.dart';
+import 'dart:async';
 import 'dart:html';
 
 main() {
@@ -15,10 +16,10 @@
     var rafCalled = false;
     var immediateCalled = false;
 
-    window.setTimeout(expectAsync0(() {
+    Timer.run(expectAsync0(() {
       timeoutCalled = true;
       expect(immediateCalled, true);
-    }), 0);
+    }));
 
 
     window.requestAnimationFrame((_) {
diff --git a/tests/html/transition_event_test.dart b/tests/html/transition_event_test.dart
index c96b46b..8e04110 100644
--- a/tests/html/transition_event_test.dart
+++ b/tests/html/transition_event_test.dart
@@ -6,6 +6,7 @@
 import '../../pkg/unittest/lib/unittest.dart';
 import '../../pkg/unittest/lib/html_individual_config.dart';
 import 'dart:html';
+import 'dart:async';
 
 main() {
   useHtmlIndividualConfiguration();
@@ -28,14 +29,14 @@
         element.style.background = 'red';
         element.style.transition = 'opacity .1s';
 
-        window.setTimeout(expectAsync0(() {
+        new Timer(const Duration(milliseconds: 100), expectAsync0(() {
           element.onTransitionEnd.first.then(expectAsync1((e) {
             expect(e is TransitionEvent, isTrue);
             expect(e.propertyName, 'opacity');
           }));
 
           element.style.opacity = '1';
-        }), 100);
+        }));
       }
     });
   });
diff --git a/tests/html/window_open_test.dart b/tests/html/window_open_test.dart
index 8fbe664..23baef4 100644
--- a/tests/html/window_open_test.dart
+++ b/tests/html/window_open_test.dart
@@ -2,6 +2,7 @@
 import '../../pkg/unittest/lib/unittest.dart';
 import '../../pkg/unittest/lib/html_config.dart';
 import 'dart:html';
+import 'dart:async';
 
 main() {
   useHtmlConfiguration();
@@ -26,8 +27,8 @@
   win.close();
   doneHandler() {
     if (!win.closed) {
-      window.setTimeout(expectAsync0(doneHandler), 1);
+      new Timer(const Duration(milliseconds: 1), expectAsync0(doneHandler));
     }
   }
-  window.setTimeout(expectAsync0(doneHandler), 1);
+  new Timer(const Duration(milliseconds: 1), expectAsync0(doneHandler));
 }
diff --git a/tools/dom/scripts/htmlrenamer.py b/tools/dom/scripts/htmlrenamer.py
index 0eb33ac..32bb712 100644
--- a/tools/dom/scripts/htmlrenamer.py
+++ b/tools/dom/scripts/htmlrenamer.py
@@ -194,6 +194,10 @@
     'Document.defaultView': 'window',
     'DOMURL.createObjectURL': 'createObjectUrl',
     'DOMURL.revokeObjectURL': 'revokeObjectUrl',
+    'DOMWindow.clearTimeout': '_clearTimeout',
+    'DOMWindow.clearInterval': '_clearInterval',
+    'DOMWindow.setTimeout': '_setTimeout',
+    'DOMWindow.setInterval': '_setInterval',
     'DOMWindow.webkitConvertPointFromNodeToPage': 'convertPointFromNodeToPage',
     'DOMWindow.webkitConvertPointFromPageToNode': 'convertPointFromPageToNode',
     'DOMWindow.webkitNotifications': 'notifications',
diff --git a/tools/dom/src/Timer.dart b/tools/dom/src/Timer.dart
index 91ad281..01048ea 100644
--- a/tools/dom/src/Timer.dart
+++ b/tools/dom/src/Timer.dart
@@ -17,11 +17,11 @@
   var maker;
   var canceller;
   if (repeating) {
-    maker = window.setInterval;
-    canceller = window.clearInterval;
+    maker = window._setInterval;
+    canceller = window._clearInterval;
   } else {
-    maker = window.setTimeout;
-    canceller = window.clearTimeout;
+    maker = window._setTimeout;
+    canceller = window._clearTimeout;
   }
   Timer timer;
   final int id = maker(() { callback(timer); }, milliSeconds);
diff --git a/tools/dom/templates/html/dartium/impl_Window.darttemplate b/tools/dom/templates/html/dartium/impl_Window.darttemplate
deleted file mode 100644
index 3c4125b..0000000
--- a/tools/dom/templates/html/dartium/impl_Window.darttemplate
+++ /dev/null
@@ -1,47 +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.
-
-part of $LIBRARYNAME;
-
-$(ANNOTATIONS)class $CLASSNAME$EXTENDS$IMPLEMENTS$NATIVESPEC {
-
-  /**
-   * Executes a [callback] after the immediate execution stack has completed.
-   *
-   * This will cause the callback to be executed after all processing has
-   * completed for the current event, but before any subsequent events.
-   */
-  void setImmediate(TimeoutHandler callback) {
-    _addMicrotaskCallback(callback);
-  }
-
-  /**
-   * Lookup a port by its [name].  Return null if no port is
-   * registered under [name].
-   */
-  lookupPort(String name) {
-    var port = json.parse(document.documentElement.attributes['dart-port:$name']);
-    return _deserialize(port);
-  }
-
-  /**
-   * Register a [port] on this window under the given [name].  This
-   * port may be retrieved by any isolate (or JavaScript script)
-   * running in this window.
-   */
-  registerPort(String name, var port) {
-    var serialized = _serialize(port);
-    document.documentElement.attributes['dart-port:$name'] = json.stringify(serialized);
-  }
-
-  /// Checks if _setImmediate is supported.
-  static bool get _supportsSetImmediate => false;
-
-  /// Dartium stub for IE's setImmediate.
-  void _setImmediate(void callback()) {
-    throw new UnsupportedError('setImmediate is not supported');
-  }
-
-$!MEMBERS
-}
diff --git a/tools/dom/templates/html/dart2js/impl_Window.darttemplate b/tools/dom/templates/html/impl/impl_Window.darttemplate
similarity index 71%
rename from tools/dom/templates/html/dart2js/impl_Window.darttemplate
rename to tools/dom/templates/html/impl/impl_Window.darttemplate
index 1f74f22..083aebd 100644
--- a/tools/dom/templates/html/dart2js/impl_Window.darttemplate
+++ b/tools/dom/templates/html/impl/impl_Window.darttemplate
@@ -4,8 +4,63 @@
 
 part of $LIBRARYNAME;
 
+$if DART2JS
 $(ANNOTATIONS)class $CLASSNAME$EXTENDS$IMPLEMENTS native "@*DOMWindow" {
+$else
+$(ANNOTATIONS)class $CLASSNAME$EXTENDS$IMPLEMENTS$NATIVESPEC {
+$endif
 
+  /**
+   * Executes a [callback] after the immediate execution stack has completed.
+   *
+   * This differs from using Timer.run(callback)
+   * because Timer will run in about 4-15 milliseconds, depending on browser,
+   * depending on load. [setImmediate], in contrast, makes browser-specific
+   * changes in behavior to attempt to run immediately after the current
+   * frame unwinds, causing the future to complete after all processing has
+   * completed for the current event, but before any subsequent events.
+   */
+  void setImmediate(TimeoutHandler callback) { 
+    _addMicrotaskCallback(callback);
+  }
+  /**
+   * Lookup a port by its [name].  Return null if no port is
+   * registered under [name].
+   */
+  SendPortSync lookupPort(String name) {
+    var port =
+        json.parse(document.documentElement.attributes['dart-port:$name']);
+    return _deserialize(port);
+  }
+
+  /**
+   * Register a [port] on this window under the given [name].  This
+   * port may be retrieved by any isolate (or JavaScript script)
+   * running in this window.
+   */
+  void registerPort(String name, var port) {
+    var serialized = _serialize(port);
+    document.documentElement.attributes['dart-port:$name'] =
+        json.stringify(serialized);
+  }
+
+  /**
+   * Returns a Future that completes just before the window is about to repaint
+   * so the user can draw an animation frame
+   *
+   * If you need to later cancel this animation, use [requestAnimationFrame]
+   * instead.
+   *
+   * Note: The code that runs when the future completes should call 
+   * [animationFrame] again for the animation to continue.
+   */
+  Future<num> get animationFrame {
+    var completer = new Completer<int>();
+    requestAnimationFrame(completer.complete);
+    return completer.future;
+  }
+
+$if DART2JS
   Document get document => JS('Document', '#.document', this);
 
   WindowBase _open2(url, name) => JS('Window', '#.open(#,#)', this, url, name);
@@ -71,15 +126,21 @@
   }
 
   /**
-   * Executes a [callback] after the immediate execution stack has completed.
+   * Called to draw an animation frame and then request the window to repaint
+   * after [callback] has finished (creating the animation). 
    *
-   * This will cause the callback to be executed after all processing has
-   * completed for the current event, but before any subsequent events.
+   * Use this method only if you need to later call [cancelAnimationFrame]. If
+   * not, the preferred Dart idiom is to set animation frames by calling
+   * [animationFrame], which returns a Future.
+   *
+   * Returns a non-zero valued integer to represent the request id for this
+   * request. This value only needs to be saved if you intend to call
+   * [cancelAnimationFrame] so you can specify the particular animation to
+   * cancel.
+   *
+   * Note: The supplied [callback] needs to call [requestAnimationFrame] again
+   * for the animation to continue.
    */
-  void setImmediate(TimeoutHandler callback) {
-    _addMicrotaskCallback(callback);
-  }
-
   @DomName('DOMWindow.requestAnimationFrame')
   int requestAnimationFrame(RequestAnimationFrameCallback callback) {
     _ensureRequestAnimationFrame();
@@ -138,25 +199,6 @@
          '#.indexedDB || #.webkitIndexedDB || #.mozIndexedDB',
          this, this, this);
 
-  /**
-   * Lookup a port by its [name].  Return null if no port is
-   * registered under [name].
-   */
-  SendPortSync lookupPort(String name) {
-    var port = json.parse(document.documentElement.attributes['dart-port:$name']);
-    return _deserialize(port);
-  }
-
-  /**
-   * Register a [port] on this window under the given [name].  This
-   * port may be retrieved by any isolate (or JavaScript script)
-   * running in this window.
-   */
-  void registerPort(String name, var port) {
-    var serialized = _serialize(port);
-    document.documentElement.attributes['dart-port:$name'] = json.stringify(serialized);
-  }
-
   @DomName('Window.console')
   Console get console => Console.safeConsole;
 
@@ -168,6 +210,15 @@
   void _setImmediate(void callback()) {
     JS('void', '#.setImmediate(#)', this, convertDartClosureToJS(callback, 0));
   }
+$else
+  /// Checks if _setImmediate is supported.
+  static bool get _supportsSetImmediate => false;
+
+  /// Dartium stub for IE's setImmediate.
+  void _setImmediate(void callback()) {
+    throw new UnsupportedError('setImmediate is not supported');
+  }
+$endif
 
 $!MEMBERS
 }