Skip to content

Commit

Permalink
lib: add requestAnimationFrame global
Browse files Browse the repository at this point in the history
Adds the browser API `requestAnimationFrame()` as an isomorphic
wrapper around `setImmediate()`. Marked Legacy with a clear
indication that code targeting Node.js should use `setImmediate()`
instead.

Signed-off-by: James M Snell <jasnell@gmail.com>
  • Loading branch information
jasnell committed Mar 30, 2021
1 parent 30fe4ed commit b6cd147
Show file tree
Hide file tree
Showing 5 changed files with 81 additions and 0 deletions.
1 change: 1 addition & 0 deletions .eslintrc.js
Original file line number Diff line number Diff line change
Expand Up @@ -331,5 +331,6 @@ module.exports = {
globalThis: 'readable',
btoa: 'readable',
atob: 'readable',
requestAnimationFrame: 'readable',
},
};
50 changes: 50 additions & 0 deletions doc/api/globals.md
Original file line number Diff line number Diff line change
Expand Up @@ -164,6 +164,29 @@ added: REPLACEME
Global alias for [`buffer.btoa()`][].

## `cancelAnimationFrame(immediateObject)`
<!-- YAML
added: REPLACEME
-->

<!--type=global-->

> Stability: 3 - Legacy: Use clearImmediate() instead.
* `immediateObject` {Object} The return value of `requestAnimationFrame()`
identifying the request being canceled.

```js
const req = requestAnimationFrame((ts) => {
console.log(`called at ${ts}`);
});

cancelAnimationFrame(req);
```

In Node.js, `cancelAnimationFrame()` is an alias for `clearImmediate()`.
Code specifically targeting Node.js should use `clearImmediate()` instead.

## `clearImmediate(immediateObject)`
<!-- YAML
added: v0.9.1
Expand Down Expand Up @@ -329,6 +352,33 @@ DataHandler.prototype.load = async function load(key) {
};
```

## `requestAnimationFrame(callback)`
<!-- YAML
added: REPLACEME
-->

<!--type=global-->

> Stability: 3 - Legacy: Use the setImmediate() instead.
* `callback` {Function}
* Returns {Object}

Registers a function with `setImmediate()` that is invoked with a single
argument set to the value of `perf_hooks.performance.now()`.

```js
requestAnimationFrame((ts) => {
console.log(`called at ${ts}`);
});
```

Node.js does not implement the same timing and event loop frame semantics
as Web Browsers and does not include any notion of rendering or "animation".
The `requestAnimationFrame()` method should be considered a close approximation
to enable cross-environment portable JavaScript code to be written. Code
specifically targeting Node.js should use `setImmediate()` instead.

## `require()`

This variable may appear to be global but is not. See [`require()`][].
Expand Down
14 changes: 14 additions & 0 deletions lib/internal/bootstrap/node.js
Original file line number Diff line number Diff line change
Expand Up @@ -239,6 +239,20 @@ if (!config.noBrowserGlobals) {
// Non-standard extensions:
defineOperation(global, 'clearImmediate', timers.clearImmediate);
defineOperation(global, 'setImmediate', timers.setImmediate);

function requestAnimationFrame(callback) {
const { performance } = require('perf_hooks');
const {
codes: {
ERR_INVALID_ARG_TYPE,
},
} = require('internal/errors');
if (typeof callback !== 'function')
throw new ERR_INVALID_ARG_TYPE('callback', 'Function', callback);
timers.setImmediate(() => callback(performance.now()));
}
defineOperation(global, 'requestAnimationFrame', requestAnimationFrame);
defineOperation(global, 'cancelAnimationFrame', timers.clearImmediate);
}

// Set the per-Environment callback that will be called
Expand Down
3 changes: 3 additions & 0 deletions test/common/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -261,13 +261,16 @@ function platformTimeout(ms) {
return ms; // ARMv8+
}

const requestAnimationFrame = globalThis.requestAnimationFrame;

let knownGlobals = [
atob,
btoa,
clearImmediate,
clearInterval,
clearTimeout,
global,
requestAnimationFrame,
setImmediate,
setInterval,
setTimeout,
Expand Down
13 changes: 13 additions & 0 deletions test/parallel/test-requestanimationframe.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
'use strict';

const common = require('../common');
const { strictEqual } = require('assert');

let called = false;

requestAnimationFrame(common.mustCall((ts) => {
called = true;
strictEqual(typeof ts, 'number');
}));

strictEqual(called, false);

0 comments on commit b6cd147

Please sign in to comment.