Skip to content

Commit

Permalink
lib: add navigator.platform
Browse files Browse the repository at this point in the history
PR-URL: #50385
Reviewed-By: Geoffrey Booth <webadmin@geoffreybooth.com>
Reviewed-By: Yagiz Nizipli <yagiz@nizipli.com>
Reviewed-By: James M Snell <jasnell@gmail.com>
  • Loading branch information
Uzlopak authored Nov 2, 2023
1 parent 196224c commit a450eed
Show file tree
Hide file tree
Showing 3 changed files with 131 additions and 0 deletions.
15 changes: 15 additions & 0 deletions doc/api/globals.md
Original file line number Diff line number Diff line change
Expand Up @@ -637,6 +637,21 @@ logical processors available to the current Node.js instance.
console.log(`This process is running on ${navigator.hardwareConcurrency} logical processors`);
```

### `navigator.platform`

<!-- YAML
added: REPLACEME
-->

* {string}

The `navigator.platform` read-only property returns a string identifying the
platform on which the Node.js instance is running.

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

### `navigator.userAgent`

<!-- YAML
Expand Down
57 changes: 57 additions & 0 deletions lib/internal/navigator.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ const {
ObjectDefineProperties,
StringPrototypeIndexOf,
StringPrototypeSlice,
StringPrototypeToUpperCase,
Symbol,
} = primordials;

Expand All @@ -22,10 +23,57 @@ const {
const kInitialize = Symbol('kInitialize');
const nodeVersion = process.version;

/**
* @param {object} process
* @param {string} process.platform
* @param {string} process.arch
* @returns {string}
*/
function getNavigatorPlatform(process) {
if (process.platform === 'darwin') {
// On macOS, modern browsers return 'MacIntel' even if running on Apple Silicon.
return 'MacIntel';
} else if (process.platform === 'win32') {
// On Windows, modern browsers return 'Win32' even if running on a 64-bit version of Windows.
// https://developer.mozilla.org/en-US/docs/Web/API/Navigator/platform#usage_notes
return 'Win32';
} else if (process.platform === 'linux') {
if (process.arch === 'ia32') {
return 'Linux i686';
} else if (process.arch === 'x64') {
return 'Linux x86_64';
}
return `Linux ${process.arch}`;
} else if (process.platform === 'freebsd') {
if (process.arch === 'ia32') {
return 'FreeBSD i386';
} else if (process.arch === 'x64') {
return 'FreeBSD amd64';
}
return `FreeBSD ${process.arch}`;
} else if (process.platform === 'openbsd') {
if (process.arch === 'ia32') {
return 'OpenBSD i386';
} else if (process.arch === 'x64') {
return 'OpenBSD amd64';
}
return `OpenBSD ${process.arch}`;
} else if (process.platform === 'sunos') {
if (process.arch === 'ia32') {
return 'SunOS i86pc';
}
return `SunOS ${process.arch}`;
} else if (process.platform === 'aix') {
return 'AIX';
}
return `${StringPrototypeToUpperCase(process.platform[0])}${StringPrototypeSlice(process.platform, 1)} ${process.arch}`;
}

class Navigator {
// Private properties are used to avoid brand validations.
#availableParallelism;
#userAgent = `Node.js/${StringPrototypeSlice(nodeVersion, 1, StringPrototypeIndexOf(nodeVersion, '.'))}`;
#platform = getNavigatorPlatform(process);

constructor() {
if (arguments[0] === kInitialize) {
Expand All @@ -48,14 +96,23 @@ class Navigator {
get userAgent() {
return this.#userAgent;
}

/**
* @return {string}
*/
get platform() {
return this.#platform;
}
}

ObjectDefineProperties(Navigator.prototype, {
hardwareConcurrency: kEnumerableProperty,
userAgent: kEnumerableProperty,
platform: kEnumerableProperty,
});

module.exports = {
getNavigatorPlatform,
navigator: new Navigator(kInitialize),
Navigator,
};
59 changes: 59 additions & 0 deletions test/parallel/test-navigator.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
'use strict';

// Flags: --expose-internals

require('../common');
const assert = require('assert');
const { getNavigatorPlatform } = require('internal/navigator');

const is = {
number: (value, key) => {
Expand All @@ -15,3 +18,59 @@ is.number(navigator.hardwareConcurrency, 'hardwareConcurrency');
assert.ok(navigator.hardwareConcurrency > 0);
assert.strictEqual(typeof navigator.userAgent, 'string');
assert.match(navigator.userAgent, /^Node\.js\/\d+$/);

assert.strictEqual(typeof navigator.platform, 'string');
if (process.platform === 'darwin') {
assert.strictEqual(navigator.platform, 'MacIntel');
} else if (process.platform === 'win32') {
assert.strictEqual(navigator.platform, 'Win32');
} else if (process.platform === 'linux' && process.arch === 'ia32') {
assert.strictEqual(navigator.platform, 'Linux i686');
} else if (process.platform === 'linux' && process.arch === 'x64') {
assert.strictEqual(navigator.platform, 'Linux x86_64');
} else if (process.platform === 'freebsd') {
if (process.arch === 'ia32') {
assert.strictEqual(navigator.platform, 'FreeBSD i386');
} else if (process.arch === 'x64') {
assert.strictEqual(navigator.platform, 'FreeBSD amd64');
} else {
assert.strictEqual(navigator.platform, `FreeBSD ${process.arch}`);
}
} else if (process.platform === 'openbsd') {
if (process.arch === 'ia32') {
assert.strictEqual(navigator.platform, 'OpenBSD i386');
} else if (process.arch === 'x64') {
assert.strictEqual(navigator.platform, 'OpenBSD amd64');
} else {
assert.strictEqual(navigator.platform, `OpenBSD ${process.arch}`);
}
} else if (process.platform === 'sunos') {
if (process.arch === 'ia32') {
assert.strictEqual(navigator.platform, 'SunOS i86pc');
} else {
assert.strictEqual(navigator.platform, `SunOS ${process.arch}`);
}
} else if (process.platform === 'aix') {
assert.strictEqual(navigator.platform, 'AIX');
} else {
assert.strictEqual(navigator.platform, `${process.platform[0].toUpperCase()}${process.platform.slice(1)} ${process.arch}`);
}

assert.strictEqual(getNavigatorPlatform({ arch: 'x64', platform: 'darwin' }), 'MacIntel');
assert.strictEqual(getNavigatorPlatform({ arch: 'arm64', platform: 'darwin' }), 'MacIntel');
assert.strictEqual(getNavigatorPlatform({ arch: 'ia32', platform: 'linux' }), 'Linux i686');
assert.strictEqual(getNavigatorPlatform({ arch: 'x64', platform: 'linux' }), 'Linux x86_64');
assert.strictEqual(getNavigatorPlatform({ arch: 'arm64', platform: 'linux' }), 'Linux arm64');
assert.strictEqual(getNavigatorPlatform({ arch: 'ia32', platform: 'win32' }), 'Win32');
assert.strictEqual(getNavigatorPlatform({ arch: 'x64', platform: 'win32' }), 'Win32');
assert.strictEqual(getNavigatorPlatform({ arch: 'arm64', platform: 'win32' }), 'Win32');
assert.strictEqual(getNavigatorPlatform({ arch: 'ia32', platform: 'freebsd' }), 'FreeBSD i386');
assert.strictEqual(getNavigatorPlatform({ arch: 'x64', platform: 'freebsd' }), 'FreeBSD amd64');
assert.strictEqual(getNavigatorPlatform({ arch: 'arm64', platform: 'freebsd' }), 'FreeBSD arm64');
assert.strictEqual(getNavigatorPlatform({ arch: 'ia32', platform: 'openbsd' }), 'OpenBSD i386');
assert.strictEqual(getNavigatorPlatform({ arch: 'x64', platform: 'openbsd' }), 'OpenBSD amd64');
assert.strictEqual(getNavigatorPlatform({ arch: 'arm64', platform: 'openbsd' }), 'OpenBSD arm64');
assert.strictEqual(getNavigatorPlatform({ arch: 'ia32', platform: 'sunos' }), 'SunOS i86pc');
assert.strictEqual(getNavigatorPlatform({ arch: 'x64', platform: 'sunos' }), 'SunOS x64');
assert.strictEqual(getNavigatorPlatform({ arch: 'ppc', platform: 'aix' }), 'AIX');
assert.strictEqual(getNavigatorPlatform({ arch: 'x64', platform: 'reactos' }), 'Reactos x64');

0 comments on commit a450eed

Please sign in to comment.