|
5 | 5 | * Use of this source code is governed by an MIT-style license that can be
|
6 | 6 | * found in the LICENSE file at https://angular.io/license
|
7 | 7 | */
|
| 8 | + |
8 | 9 | import {global} from './global';
|
9 | 10 |
|
10 | 11 | export function getNativeRequestAnimationFrame() {
|
| 12 | + // Note: the `getNativeRequestAnimationFrame` is used in the `NgZone` class, but we cannot use the |
| 13 | + // `inject` function. The `NgZone` instance may be created manually, and thus the injection |
| 14 | + // context will be unavailable. This might be enough to check whether `requestAnimationFrame` is |
| 15 | + // available because otherwise, we'll fall back to `setTimeout`. |
| 16 | + const isBrowser = typeof global['requestAnimationFrame'] === 'function'; |
| 17 | + |
| 18 | + // Note: `requestAnimationFrame` is unavailable when the code runs in the Node.js environment. We |
| 19 | + // use `setTimeout` because no changes are required other than checking if the current platform is |
| 20 | + // the browser. `setTimeout` is a well-established API that is available in both environments. |
| 21 | + // `requestAnimationFrame` is used in the browser to coalesce event tasks since event tasks are |
| 22 | + // usually executed within the same rendering frame (but this is more implementation details of |
| 23 | + // browsers). |
11 | 24 | let nativeRequestAnimationFrame: (callback: FrameRequestCallback) => number =
|
12 |
| - global['requestAnimationFrame']; |
13 |
| - let nativeCancelAnimationFrame: (handle: number) => void = global['cancelAnimationFrame']; |
| 25 | + global[isBrowser ? 'requestAnimationFrame' : 'setTimeout']; |
| 26 | + |
| 27 | + let nativeCancelAnimationFrame: (handle: number) => void = |
| 28 | + global[isBrowser ? 'cancelAnimationFrame' : 'clearTimeout']; |
| 29 | + |
14 | 30 | if (typeof Zone !== 'undefined' && nativeRequestAnimationFrame! && nativeCancelAnimationFrame!) {
|
15 |
| - // use unpatched version of requestAnimationFrame(native delegate) if possible |
16 |
| - // to avoid another Change detection |
| 31 | + // Note: zone.js sets original implementations on patched APIs behind the |
| 32 | + // `__zone_symbol__OriginalDelegate` key (see `attachOriginToPatched`). Given the following |
| 33 | + // example: `window.requestAnimationFrame.__zone_symbol__OriginalDelegate`; this would return an |
| 34 | + // unpatched implementation of the `requestAnimationFrame`, which isn't intercepted by the |
| 35 | + // Angular zone. We use the unpatched implementation to avoid another change detection when |
| 36 | + // coalescing tasks. |
17 | 37 | const unpatchedRequestAnimationFrame =
|
18 | 38 | (nativeRequestAnimationFrame as any)[(Zone as any).__symbol__('OriginalDelegate')];
|
19 | 39 | if (unpatchedRequestAnimationFrame) {
|
|
0 commit comments