Chromium Code Reviews| Index: tools/dom/templates/html/impl/impl_Window.darttemplate |
| diff --git a/tools/dom/templates/html/impl/impl_Window.darttemplate b/tools/dom/templates/html/impl/impl_Window.darttemplate |
| index 03bd4da9f4cd1786063d1542753b852017515229..d18116e72a7798baed97cedc87c3184e8c01142c 100644 |
| --- a/tools/dom/templates/html/impl/impl_Window.darttemplate |
| +++ b/tools/dom/templates/html/impl/impl_Window.darttemplate |
| @@ -4,6 +4,84 @@ |
| part of $LIBRARYNAME; |
| +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 can |
| + * therefore not be used as task object. The [Window] class thus keeps a mapping |
| + * from the integer 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 up space, it must be removed as soon as the |
| + * animation-frame task has triggered. The default implementation does this |
| + * automatically, but intercepted implementations of `requestAnimationFrame` |
| + * must ensure to call the [AnimationFrameTask.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. */ |
|
Lasse Reichstein Nielsen
2016/06/29 09:22:12
-> A function which
and consider: when -> if
May
floitsch
2016/06/30 19:42:49
Done.
|
| + void cancel(Window window); |
| + |
| + /** The zone in which the task should run. */ |
|
Lasse Reichstein Nielsen
2016/06/29 09:22:12
should -> will
floitsch
2016/06/30 19:42:49
Done.
|
| + Zone get zone; |
| + |
| + /** |
| + * Maps animation-frame request IDs to their task objects. |
| + */ |
| + static final Map<int, _AnimationFrameTask> _tasks = {}; |
| + |
| + /** |
| + * The function that should be invoked by user-implemented animation-frame |
|
Lasse Reichstein Nielsen
2016/06/29 09:22:12
-> A function which must ...
floitsch
2016/06/30 19:42:49
Reworded.
|
| + * tasks, before running [callback]. |
| + * |
| + * See [AnimationFrameTask]. |
| + */ |
| + static void removeMapping(int id) { |
| + _tasks.remove(id); |
| + } |
| +} |
| + |
| +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. |
|
Lasse Reichstein Nielsen
2016/06/29 09:22:12
Is there anything more to say about this class? Pe
floitsch
2016/06/30 19:42:49
I added an "experimental" note.
|
| + */ |
| +class AnimationFrameRequestSpecification implements TaskSpecification { |
| + /** |
| + * The window on which [Window.requestAnimationFrame] was invoked. |
| + */ |
| + final Window window; |
| + |
| + /** |
| + * The callback that should be executed when the animation-frame is ready. |
|
Lasse Reichstein Nielsen
2016/06/29 09:22:12
should -> will
floitsch
2016/06/30 19:42:49
-> is.
done.
|
| + * |
| + * Note that the callback hasn't been registered in any zone yet. |
|
Lasse Reichstein Nielsen
2016/06/29 09:22:12
"yet" isn't a good word for a final property which
floitsch
2016/06/30 19:42:49
Reworded. The important thing is, that the create
|
| + */ |
| + final FrameRequestCallback callback; |
| + |
| + AnimationFrameRequestSpecification(this.window, this.callback); |
| + |
| + String get name => "dart.html.request-animation-frame"; |
| + bool get isOneShot => true; |
| +} |
| + |
| @DocsEditable() |
| $if DART2JS |
| $(ANNOTATIONS)@Native("Window,DOMWindow") |
| @@ -29,9 +107,7 @@ $endif |
| */ |
| Future<num> get animationFrame { |
| var completer = new Completer<num>.sync(); |
| - requestAnimationFrame((time) { |
| - completer.complete(time); |
| - }); |
| + requestAnimationFrame(completer.complete); |
| return completer.future; |
| } |
| @@ -115,7 +191,30 @@ $if DART2JS |
| @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); |
| + var task = Zone.current.createTask/*<AnimationFrameTask>*/( |
| + _createAnimationFrameTask, spec); |
| + AnimationFrameTask._tasks[task.id] = task; |
| + return task.id; |
| + } |
| + |
| + static _AnimationFrameTask _createAnimationFrameTask( |
| + AnimationFrameRequestSpecification spec, Zone zone) { |
| + var task; |
| + var id = spec.window._requestAnimationFrame((num time) { |
| + AnimationFrameTask.removeMapping(task.id); |
| + zone.runTask(_runAnimationFrame, task, time); |
| + }); |
| + var callback = zone.registerUnaryCallback(spec.callback); |
| + task = new _AnimationFrameTask(id, zone, callback); |
| + return task; |
| + } |
| + |
| + static void _runAnimationFrame(_AnimationFrameTask task, num time) { |
| + task._callback(time); |
| } |
| /** |
| @@ -128,7 +227,13 @@ $if DART2JS |
| */ |
| void cancelAnimationFrame(int id) { |
| _ensureRequestAnimationFrame(); |
| - _cancelAnimationFrame(id); |
| + var task = AnimationFrameTask._tasks.remove(id); |
| + if (task == null) { |
| + // Assume that the animation frame request wasn't intercepted by a zone. |
| + _cancelAnimationFrame(id); |
| + return; |
| + } |
| + task.cancel(this); |
| } |
| @JSName('requestAnimationFrame') |