Skip to content

Commit

Permalink
lib: add the Navigator object
Browse files Browse the repository at this point in the history
Add the Navigator object with the Device Memory API.

Refs: nodejs#39540
Refs: https://html.spec.whatwg.org/multipage/system-state.html#the-navigator-object
Refs: https://w3c.github.io/device-memory

Co-authored-by: Voltrex <mohammadkeyvanzade94@gmail.com>
  • Loading branch information
Mesteery and VoltrexKeyva committed Jul 29, 2021
1 parent 4350262 commit 4b158f1
Show file tree
Hide file tree
Showing 17 changed files with 227 additions and 4 deletions.
1 change: 1 addition & 0 deletions .eslintrc.js
Original file line number Diff line number Diff line change
Expand Up @@ -361,5 +361,6 @@ module.exports = {
btoa: 'readable',
atob: 'readable',
performance: 'readable',
navigator: 'readable',
},
};
55 changes: 55 additions & 0 deletions doc/api/globals.md
Original file line number Diff line number Diff line change
Expand Up @@ -295,6 +295,58 @@ The `MessagePort` class. See [`MessagePort`][] for more details.

This variable may appear to be global but is not. See [`module`][].

## `navigator`
<!-- YAML
added: REPLACEME
-->

> Stability: 1 - Experimental
An implementation of the [Navigator API][]. Similar to [`window.navigator`][]
in browsers.

### `navigator.deviceMemory`
<!-- YAML
added: REPLACEME
-->

* {number}

The total amount of device memory in GiB, rounded to the nearest power of 2,
between 0.25 and 8 GiB. Part of the [Device Memory API][].

```js
console.log(`This device has ${navigator.deviceMemory} GiB of RAM`);
```

### `navigator.hardwareConcurrency`
<!-- YAML
added: REPLACEME
-->

* {integer}

The number of logical processors.

```js
console.log(`This device has ${navigator.hardwareConcurrency} logical CPUs`);
```

### `navigator.platform`
<!-- YAML
added: REPLACEME
-->

* {string}

A string identifying the operating system platform on which the Node.js process
is running. For example, it returns 'Linux' on Linux, 'Darwin' on macOS, and
'Win32' on Windows.

```js
console.log(`This process is running on ${navigator.platform}`);
```

## `performance`

The [`perf_hooks.performance`][] object.
Expand Down Expand Up @@ -429,6 +481,8 @@ The object that acts as the namespace for all W3C
[WebAssembly][webassembly-org] related functionality. See the
[Mozilla Developer Network][webassembly-mdn] for usage and compatibility.

[Device Memory API]: https://w3c.github.io/device-memory/
[Navigator API]: https://html.spec.whatwg.org/multipage/system-state.html#the-navigator-object
[`AbortController`]: https://developer.mozilla.org/en-US/docs/Web/API/AbortController
[`EventTarget` and `Event` API]: events.md#event-target-and-event-api
[`MessageChannel`]: worker_threads.md#worker_threads_class_messagechannel
Expand All @@ -455,6 +509,7 @@ The object that acts as the namespace for all W3C
[`setImmediate`]: timers.md#timers_setimmediate_callback_args
[`setInterval`]: timers.md#timers_setinterval_callback_delay_args
[`setTimeout`]: timers.md#timers_settimeout_callback_delay_args
[`window.navigator`]: https://developer.mozilla.org/en-US/docs/Web/API/Window/navigator
[buffer section]: buffer.md
[built-in objects]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects
[module system documentation]: modules.md
Expand Down
8 changes: 8 additions & 0 deletions lib/internal/bootstrap/node.js
Original file line number Diff line number Diff line change
Expand Up @@ -241,6 +241,14 @@ if (!config.noBrowserGlobals) {

defineOperation(globalThis, 'queueMicrotask', queueMicrotask);

// https://html.spec.whatwg.org/multipage/system-state.html#the-navigator-object
ObjectDefineProperty(globalThis, 'navigator', {
enumerable: true,
configurable: true,
writable: false,
value: require('internal/navigator'),
});

// https://www.w3.org/TR/hr-time-2/#the-performance-attribute
defineReplacableAttribute(globalThis, 'performance',
require('perf_hooks').performance);
Expand Down
67 changes: 67 additions & 0 deletions lib/internal/navigator.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
'use strict';

const {
ObjectDefineProperties,
ObjectSetPrototypeOf,
MathClz32,
} = primordials;

const {
codes: {
ERR_ILLEGAL_CONSTRUCTOR,
}
} = require('internal/errors');

const {
getCPUs,
getOSInformation,
getTotalMem,
} = internalBinding('os');

class Navigator {
constructor() {
throw new ERR_ILLEGAL_CONSTRUCTOR();
}
}

class InternalNavigator {}
InternalNavigator.prototype.constructor = Navigator.prototype.constructor;
ObjectSetPrototypeOf(InternalNavigator.prototype, Navigator.prototype);

function getDeviceMemory() {
const mem = getTotalMem() / 1024 / 1024;
if (mem <= 0.25 * 1024) return 0.25;
if (mem >= 8 * 1024) return 8;
const lowerBound = 1 << 31 - MathClz32(mem - 1);
const upperBound = lowerBound * 2;
return mem - lowerBound <= upperBound - mem ?
lowerBound / 1024 :
upperBound / 1024;
}

function getPlatform() {
if (process.platform === 'win32') return 'Win32';
if (process.platform === 'android') return 'Android';
return getOSInformation()[0];
}

const cpuData = getCPUs();
ObjectDefineProperties(Navigator.prototype, {
deviceMemory: {
configurable: true,
enumerable: true,
value: getDeviceMemory(),
},
hardwareConcurrency: {
configurable: true,
enumerable: true,
value: cpuData ? cpuData.length / 7 : 1,
},
platform: {
configurable: true,
enumerable: true,
value: getPlatform(),
},
});

module.exports = new InternalNavigator();
4 changes: 3 additions & 1 deletion test/common/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -282,7 +282,9 @@ if (global.AbortController)
if (global.gc) {
knownGlobals.push(global.gc);
}

if (global.navigator) {
knownGlobals.push(global.navigator);
}
if (global.performance) {
knownGlobals.push(global.performance);
}
Expand Down
2 changes: 1 addition & 1 deletion test/fixtures/wpt/LICENSE.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# The 3-Clause BSD License

Copyright 2019 web-platform-tests contributors
Copyright © web-platform-tests contributors

Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:

Expand Down
3 changes: 2 additions & 1 deletion test/fixtures/wpt/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,14 +12,15 @@ Last update:

- common: https://github.com/web-platform-tests/wpt/tree/bb97a68974/common
- console: https://github.com/web-platform-tests/wpt/tree/3b1f72e99a/console
- device-memory: https://github.com/web-platform-tests/wpt/tree/c0cdd63f19/device-memory
- dom/abort: https://github.com/web-platform-tests/wpt/tree/1728d198c9/dom/abort
- encoding: https://github.com/web-platform-tests/wpt/tree/35f70910d3/encoding
- FileAPI: https://github.com/web-platform-tests/wpt/tree/3b279420d4/FileAPI
- hr-time: https://github.com/web-platform-tests/wpt/tree/9910784394/hr-time
- html/webappapis/atob: https://github.com/web-platform-tests/wpt/tree/f267e1dca6/html/webappapis/atob
- html/webappapis/microtask-queuing: https://github.com/web-platform-tests/wpt/tree/2c5c3c4c27/html/webappapis/microtask-queuing
- html/webappapis/timers: https://github.com/web-platform-tests/wpt/tree/5873f2d8f1/html/webappapis/timers
- interfaces: https://github.com/web-platform-tests/wpt/tree/80a4176623/interfaces
- interfaces: https://github.com/web-platform-tests/wpt/tree/fc086c82d5/interfaces
- performance-timeline: https://github.com/web-platform-tests/wpt/tree/17ebc3aea0/performance-timeline
- resources: https://github.com/web-platform-tests/wpt/tree/972ca5b669/resources
- streams: https://github.com/web-platform-tests/wpt/tree/8f60d94439/streams
Expand Down
3 changes: 3 additions & 0 deletions test/fixtures/wpt/device-memory/META.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
spec: https://w3c.github.io/device-memory/
suggested_reviewers:
- npm1
8 changes: 8 additions & 0 deletions test/fixtures/wpt/device-memory/device-memory.https.any.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
test(function() {
assert_equals(typeof navigator.deviceMemory, "number",
"navigator.deviceMemory returns a number");
assert_true(navigator.deviceMemory >= 0,
"navigator.deviceMemory returns a positive value");
assert_true([0.25, 0.5, 1, 2, 4, 8].includes(navigator.deviceMemory),
"navigator.deviceMemory returns a power of 2 between 0.25 and 8");
}, "navigator.deviceMemory is a positive number, a power of 2, between 0.25 and 8");
19 changes: 19 additions & 0 deletions test/fixtures/wpt/device-memory/idlharness.https.any.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
// META: script=/resources/WebIDLParser.js
// META: script=/resources/idlharness.js
// META: timeout=long

// https://w3c.github.io/device-memory/

"use strict";

idl_test(
['device-memory'],
['html'],
async idl_array => {
if (self.GLOBAL.isWorker()) {
idl_array.add_objects({ WorkerNavigator: ['navigator'] });
} else {
idl_array.add_objects({ Navigator: ['navigator'] });
}
}
);
14 changes: 14 additions & 0 deletions test/fixtures/wpt/interfaces/device-memory.idl
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
// GENERATED CONTENT - DO NOT EDIT
// Content was automatically extracted by Reffy into webref
// (https://github.com/w3c/webref)
// Source: Device Memory 1 (https://w3c.github.io/device-memory/)

[
SecureContext,
Exposed=(Window,Worker)
] interface mixin NavigatorDeviceMemory {
readonly attribute double deviceMemory;
};

Navigator includes NavigatorDeviceMemory;
WorkerNavigator includes NavigatorDeviceMemory;
6 changes: 5 additions & 1 deletion test/fixtures/wpt/versions.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,10 @@
"commit": "3b1f72e99a91d31551edd2147dc7b564eaf25d72",
"path": "console"
},
"device-memory": {
"commit": "c0cdd63f19507a784531ff4ccc1c71456f79b867",
"path": "device-memory"
},
"dom/abort": {
"commit": "1728d198c92834d92f7f399ef35e7823d5bfa0e4",
"path": "dom/abort"
Expand Down Expand Up @@ -36,7 +40,7 @@
"path": "html/webappapis/timers"
},
"interfaces": {
"commit": "80a417662387b6eda904607d78ad246c5d8bf191",
"commit": "fc086c82d5a7e9b01a684a23336d6d1f9e79e303",
"path": "interfaces"
},
"performance-timeline": {
Expand Down
1 change: 1 addition & 0 deletions test/parallel/test-global.js
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ builtinModules.forEach((moduleName) => {
'clearImmediate',
'clearInterval',
'clearTimeout',
'navigator',
'performance',
'setImmediate',
'setInterval',
Expand Down
7 changes: 7 additions & 0 deletions test/parallel/test-navigator-global.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
'use strict';
/* eslint-disable no-global-assign */
require('../common');
const { notStrictEqual } = require('assert');

performance = undefined;
notStrictEqual(globalThis.performance, undefined);
21 changes: 21 additions & 0 deletions test/parallel/test-navigator.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
'use strict';
require('../common');
const assert = require('assert');
const { cpus } = require('os');
const { platform } = require('process');

assert.ok(navigator.deviceMemory >= 0.25 && navigator.deviceMemory <= 8);

assert.strictEqual(navigator.platform, {
aix: 'AIX',
android: 'Android',
darwin: 'Darwin',
freebsd: 'FreeBSD',
linux: 'Linux',
openbsd: 'OpenBSD',
sunos: 'SunOS',
win32: 'Win32',
}[platform]);

assert.ok(navigator.hardwareConcurrency >= 1);
assert.strictEqual(navigator.hardwareConcurrency, cpus().length);
5 changes: 5 additions & 0 deletions test/wpt/status/device-memory.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"idlharness.https.any.js": {
"skip": "idlharness cannot recognize Node.js environment"
}
}
7 changes: 7 additions & 0 deletions test/wpt/test-device-memory.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
'use strict';
require('../common');
const { WPTRunner } = require('../common/wpt');

const runner = new WPTRunner('device-memory');

runner.runJsTests();

0 comments on commit 4b158f1

Please sign in to comment.