Skip to content

Commit 64481f5

Browse files
committed
lib: make navigator not runtime-lookup process.version, arch, or platform
Preserves most of nodejs#53649, except for `#language` due to the lack of Intl primordials.
1 parent b9289a6 commit 64481f5

File tree

6 files changed

+53
-25
lines changed

6 files changed

+53
-25
lines changed

lib/internal/bootstrap/node.js

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,10 @@ const {
8585
},
8686
} = internalBinding('util');
8787

88+
require('internal/process/arch'); // ensure the process arch is cached
89+
require('internal/process/platform'); // ensure the process platform is cached
90+
require('internal/process/version'); // ensure the process version is cached
91+
8892
setupProcessObject();
8993

9094
setupGlobalProxy();

lib/internal/navigator.js

Lines changed: 25 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -27,60 +27,62 @@ const {
2727
} = internalBinding('os');
2828

2929
const kInitialize = Symbol('kInitialize');
30-
const nodeVersion = process.version;
30+
const nodeVersion = require('internal/process/version');
31+
const platform = require('internal/process/platform');
32+
const arch = require('internal/process/arch');
3133

3234
/**
3335
* @param {object} process
3436
* @param {string} process.platform
3537
* @param {string} process.arch
3638
* @returns {string}
3739
*/
38-
function getNavigatorPlatform(process) {
39-
if (process.platform === 'darwin') {
40+
function getNavigatorPlatform({ platform, arch }) {
41+
if (platform === 'darwin') {
4042
// On macOS, modern browsers return 'MacIntel' even if running on Apple Silicon.
4143
return 'MacIntel';
42-
} else if (process.platform === 'win32') {
44+
} else if (platform === 'win32') {
4345
// On Windows, modern browsers return 'Win32' even if running on a 64-bit version of Windows.
4446
// https://developer.mozilla.org/en-US/docs/Web/API/Navigator/platform#usage_notes
4547
return 'Win32';
46-
} else if (process.platform === 'linux') {
47-
if (process.arch === 'ia32') {
48+
} else if (platform === 'linux') {
49+
if (arch === 'ia32') {
4850
return 'Linux i686';
49-
} else if (process.arch === 'x64') {
51+
} else if (arch === 'x64') {
5052
return 'Linux x86_64';
5153
}
52-
return `Linux ${process.arch}`;
53-
} else if (process.platform === 'freebsd') {
54-
if (process.arch === 'ia32') {
54+
return `Linux ${arch}`;
55+
} else if (platform === 'freebsd') {
56+
if (arch === 'ia32') {
5557
return 'FreeBSD i386';
56-
} else if (process.arch === 'x64') {
58+
} else if (arch === 'x64') {
5759
return 'FreeBSD amd64';
5860
}
59-
return `FreeBSD ${process.arch}`;
60-
} else if (process.platform === 'openbsd') {
61-
if (process.arch === 'ia32') {
61+
return `FreeBSD ${arch}`;
62+
} else if (platform === 'openbsd') {
63+
if (arch === 'ia32') {
6264
return 'OpenBSD i386';
63-
} else if (process.arch === 'x64') {
65+
} else if (arch === 'x64') {
6466
return 'OpenBSD amd64';
6567
}
66-
return `OpenBSD ${process.arch}`;
67-
} else if (process.platform === 'sunos') {
68-
if (process.arch === 'ia32') {
68+
return `OpenBSD ${arch}`;
69+
} else if (platform === 'sunos') {
70+
if (arch === 'ia32') {
6971
return 'SunOS i86pc';
7072
}
71-
return `SunOS ${process.arch}`;
72-
} else if (process.platform === 'aix') {
73+
return `SunOS ${arch}`;
74+
} else if (platform === 'aix') {
7375
return 'AIX';
7476
}
75-
return `${StringPrototypeToUpperCase(process.platform[0])}${StringPrototypeSlice(process.platform, 1)} ${process.arch}`;
77+
return `${StringPrototypeToUpperCase(platform[0])}${StringPrototypeSlice(platform, 1)} ${arch}`;
7678
}
7779

7880
class Navigator {
7981
// Private properties are used to avoid brand validations.
8082
#availableParallelism;
8183
#userAgent;
8284
#platform;
83-
#language;
85+
#language = Intl?.Collator().resolvedOptions().locale || 'en-US';
8486
#languages;
8587

8688
constructor() {
@@ -102,7 +104,6 @@ class Navigator {
102104
* @return {string}
103105
*/
104106
get language() {
105-
this.#language ??= Intl?.Collator().resolvedOptions().locale || 'en-US';
106107
return this.#language;
107108
}
108109

@@ -126,7 +127,7 @@ class Navigator {
126127
* @return {string}
127128
*/
128129
get platform() {
129-
this.#platform ??= getNavigatorPlatform(process);
130+
this.#platform ??= getNavigatorPlatform({ arch, platform });
130131
return this.#platform;
131132
}
132133
}

lib/internal/process/arch.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
module.exports = require('process').arch;

lib/internal/process/platform.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
module.exports = require('process').platform;

lib/internal/process/version.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
module.exports = require('process').version;

test/parallel/test-navigator.js

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,28 @@
22

33
'use strict';
44

5-
const common = require('../common');
65
const assert = require('assert');
6+
7+
{
8+
9+
assert.strictEqual(require.resolve('../common') in require.cache, false); // ensures `navigator` has not been evaluated yet
10+
11+
let called = false;
12+
const { version, platform, arch } = process;
13+
Object.defineProperty(process, 'arch', { get() { called += 'arch|'; return arch; } });
14+
Object.defineProperty(process, 'platform', { get() { called = 'platform|'; return platform; } });
15+
Object.defineProperty(process, 'version', { get() { called = 'version|'; return version; } });
16+
17+
navigator;
18+
19+
assert.strictEqual(called, false, 'evaluating navigator does not runtime-call `process.version`, `process.platform`, `platform.version`');
20+
21+
Object.defineProperty(process, 'arch', { value: arch });
22+
Object.defineProperty(process, 'platform', { value: platform });
23+
Object.defineProperty(process, 'version', { value: version });
24+
}
25+
26+
const common = require('../common');
727
const { getNavigatorPlatform } = require('internal/navigator');
828
const { execFile } = require('child_process');
929

0 commit comments

Comments
 (0)