/
githubmirror
/
node
Обзор
Документация
Войти
/
githubmirror
/
node
Код
Запросы
0
Пакеты
0
Релизы
0
Аналитика
Безопасность
main
lib/internal/navigator.js
164 строки
4 KB
Mohamed Sayed
lib: make `Navigator#language` getter throw on invalid `this`
02 июн 2026, 15:25
Не верифицирован
02 июн 2026, 15:25
ba7e6b3
Код
Авторство
О чём код?
'use strict'; const { ObjectDefineProperties, ObjectFreeze, StringPrototypeIndexOf, StringPrototypeSlice, StringPrototypeToUpperCase, Symbol, } = primordials; const { ERR_ILLEGAL_CONSTRUCTOR, } = require('internal/errors').codes; const { kEnumerableProperty, } = require('internal/util'); const { getAvailableParallelism, } = internalBinding('os'); const kInitialize = Symbol('kInitialize'); const { platform, arch, version: nodeVersion, } = require('internal/process/per_thread'); const { getDefaultLocale, } = internalBinding('config'); /** * @param {string} arch * @param {string} platform * @returns {string} */ function getNavigatorPlatform(arch, platform) { if (platform === 'darwin') { // On macOS, modern browsers return 'MacIntel' even if running on Apple Silicon. return 'MacIntel'; } else if (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 (platform === 'linux') { if (arch === 'ia32') { return 'Linux i686'; } else if (arch === 'x64') { return 'Linux x86_64'; } return `Linux ${arch}`; } else if (platform === 'freebsd') { if (arch === 'ia32') { return 'FreeBSD i386'; } else if (arch === 'x64') { return 'FreeBSD amd64'; } return `FreeBSD ${arch}`; } else if (platform === 'openbsd') { if (arch === 'ia32') { return 'OpenBSD i386'; } else if (arch === 'x64') { return 'OpenBSD amd64'; } return `OpenBSD ${arch}`; } else if (platform === 'sunos') { if (arch === 'ia32') { return 'SunOS i86pc'; } return `SunOS ${arch}`; } else if (platform === 'aix') { return 'AIX'; } return `${StringPrototypeToUpperCase(platform[0])}${StringPrototypeSlice(platform, 1)} ${arch}`; } class Navigator { // Private properties are used to avoid brand validations: reading a private // field from a non-Navigator receiver throws a TypeError on its own. #availableParallelism; #locks; #userAgent; #platform; #languages; constructor() { if (arguments[0] === kInitialize) { return; } throw new ERR_ILLEGAL_CONSTRUCTOR(); } /** * @returns {number} */ get hardwareConcurrency() { this.#availableParallelism ??= getAvailableParallelism(); return this.#availableParallelism; } /** * @returns {LockManager} */ get locks() { this.#locks ??= require('internal/locks').locks; return this.#locks; } /** * @returns {string} */ get language() { // `language` does not read a private field, so brand-check explicitly // to keep parity with the other getters when called on a non-Navigator // receiver (e.g. `Navigator.prototype.language`). this.#languages; // eslint-disable-line no-unused-expressions // The default locale might be changed dynamically, so always invoke the // binding. return getDefaultLocale() || 'en-US'; } /** * @returns {Array<string>} */ get languages() { this.#languages ??= ObjectFreeze([this.language]); return this.#languages; } /** * @returns {string} */ get userAgent() { this.#userAgent ??= `Node.js/${StringPrototypeSlice(nodeVersion, 1, StringPrototypeIndexOf(nodeVersion, '.'))}`; return this.#userAgent; } /** * @returns {string} */ get platform() { this.#platform ??= getNavigatorPlatform(arch, platform); return this.#platform; } } ObjectDefineProperties(Navigator.prototype, { hardwareConcurrency: kEnumerableProperty, language: kEnumerableProperty, languages: kEnumerableProperty, userAgent: kEnumerableProperty, platform: kEnumerableProperty, locks: kEnumerableProperty, }); module.exports = { getNavigatorPlatform, navigator: new Navigator(kInitialize), Navigator, };