| Index: sdk/lib/html/dart2js/html_dart2js.dart
|
| diff --git a/sdk/lib/html/dart2js/html_dart2js.dart b/sdk/lib/html/dart2js/html_dart2js.dart
|
| index 492a1d929fa6b8c409de5be4e38d2e2d0c4d0ce1..f3d743e65774a1056b63cbef2b3602676173f685 100644
|
| --- a/sdk/lib/html/dart2js/html_dart2js.dart
|
| +++ b/sdk/lib/html/dart2js/html_dart2js.dart
|
| @@ -34485,6 +34485,77 @@ class WheelEvent extends MouseEvent {
|
| // BSD-style license that can be found in the LICENSE file.
|
|
|
|
|
| +typedef void RemoveFrameRequestMapping(int id);
|
| +
|
| +/**
|
| + * The task object representing animation-frame requests.
|
| + *
|
| + * For historical reasons, [Window.requestAnimationFrame] returns an integer
|
| + * to users. However, zone-tasks must be unique objects, and an integer thus
|
| + * doesn't work. The [Window] class thus keeps a mapping from the id to the
|
| + * corresponding task object. All zone related operations work on this task
|
| + * object, whereas users of [Window.requestAnimationFrame] only see the integer
|
| + * id.
|
| + *
|
| + * Since this mapping takes space, it must be removed as soon as the animation-
|
| + * frame task triggered. The default-implementations do this automatically, but
|
| + * intercepted implementations of `requestAnimationFrame` must ensure to
|
| + * call the [AnimationFrameRequestSpecification.removeMapping] function that is
|
| + * provided in the task specification.
|
| + */
|
| +abstract class AnimationFrameTask {
|
| + /** The id that is returned to users. */
|
| + int get id;
|
| +
|
| + /** The function that is invoked when the user cancels the request. */
|
| + void cancel(Window window);
|
| +
|
| + /** The zone in which the task should run (and cancel). */
|
| + Zone get zone;
|
| +}
|
| +
|
| +class _AnimationFrameTask implements AnimationFrameTask {
|
| + final int id;
|
| + final Zone zone;
|
| + final FrameRequestCallback _callback;
|
| +
|
| + _AnimationFrameTask(this.id, this.zone, this._callback);
|
| +
|
| + void cancel(Window window) {
|
| + window._cancelAnimationFrame(this.id);
|
| + }
|
| +}
|
| +
|
| +/**
|
| + * The task specification for an animation-frame request.
|
| + *
|
| + * The task specification of animation-frame requests include a `removeMapping`
|
| + * function. This function must be called by the created task before it
|
| + * runs the frame-request callback.
|
| + */
|
| +class AnimationFrameRequestSpecification implements TaskSpecification {
|
| + final Window window;
|
| + /**
|
| + * The callback that should be executed when the animation-frame is ready.
|
| + *
|
| + * Note that the callback hasn't been registered in any zone yet.
|
| + */
|
| + final FrameRequestCallback callback;
|
| +
|
| + /**
|
| + * The function that should be invoked by the task before running [callback].
|
| + *
|
| + * See [AnimationFrame].
|
| + */
|
| + final RemoveFrameRequestMapping removeMapping;
|
| +
|
| + AnimationFrameRequestSpecification(
|
| + this.window, this.callback, this.removeMapping);
|
| +
|
| + String get name => "dart.html.request-animation-frame";
|
| + bool get isOneShot => true;
|
| +}
|
| +
|
| @DocsEditable()
|
| /**
|
| * Top-level container for the current browser tab or window.
|
| @@ -34540,9 +34611,7 @@ class Window extends EventTarget implements WindowEventHandlers, WindowBase, Glo
|
| */
|
| Future<num> get animationFrame {
|
| var completer = new Completer<num>.sync();
|
| - requestAnimationFrame((time) {
|
| - completer.complete(time);
|
| - });
|
| + requestAnimationFrame(completer.complete);
|
| return completer.future;
|
| }
|
|
|
| @@ -34607,6 +34676,12 @@ class Window extends EventTarget implements WindowEventHandlers, WindowBase, Glo
|
| }
|
|
|
| /**
|
| + * Maps animation-frame request ids to their task objects.
|
| + */
|
| + static final Map<int, _AnimationFrameTask> _animationFrameTasks =
|
| + <int, _AnimationFrameTask>{};
|
| +
|
| + /**
|
| * Called to draw an animation frame and then request the window to repaint
|
| * after [callback] has finished (creating the animation).
|
| *
|
| @@ -34625,7 +34700,35 @@ class Window extends EventTarget implements WindowEventHandlers, WindowBase, Glo
|
| @DomName('Window.requestAnimationFrame')
|
| int requestAnimationFrame(FrameRequestCallback callback) {
|
| _ensureRequestAnimationFrame();
|
| - return _requestAnimationFrame(_wrapZone/*<dynamic, num>*/(callback));
|
| + if (identical(Zone.current, Zone.ROOT)) {
|
| + return _requestAnimationFrame(callback);
|
| + }
|
| + var spec = new AnimationFrameRequestSpecification(
|
| + this, callback, _removeTaskMapping);
|
| + var task = Zone.current.createTask/*<AnimationFrameTask>*/(
|
| + _createAnimationFrameTask, spec);
|
| + _animationFrameTasks[task.id] = task;
|
| + return task.id;
|
| + }
|
| +
|
| + static _AnimationFrameTask _createAnimationFrameTask(
|
| + AnimationFrameRequestSpecification spec, Zone zone) {
|
| + var task;
|
| + var id = spec.window._requestAnimationFrame((num time) {
|
| + spec.removeMapping(task.id);
|
| + zone.runTask(_runAnimationFrame, task, time);
|
| + });
|
| + var callback = zone.registerUnaryCallback(spec.callback);
|
| + task = new _AnimationFrameTask(id, zone, callback);
|
| + return task;
|
| + }
|
| +
|
| + static void _removeTaskMapping(int id) {
|
| + _animationFrameTasks.remove(id);
|
| + }
|
| +
|
| + static void _runAnimationFrame(_AnimationFrameTask task, num time) {
|
| + task._callback(time);
|
| }
|
|
|
| /**
|
| @@ -34638,7 +34741,12 @@ class Window extends EventTarget implements WindowEventHandlers, WindowBase, Glo
|
| */
|
| void cancelAnimationFrame(int id) {
|
| _ensureRequestAnimationFrame();
|
| - _cancelAnimationFrame(id);
|
| + var task = _animationFrameTasks[id];
|
| + if (task == null) {
|
| + _cancelAnimationFrame(id);
|
| + }
|
| + _animationFrameTasks.remove(id);
|
| + task.cancel(this);
|
| }
|
|
|
| @JSName('requestAnimationFrame')
|
|
|