repo_description: Node.js JavaScript runtime ✨🐢🚀✨
repo_topics: javascript js linux macos mit node nodejs runtime windows
code: '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.
    #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() {
      // 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,
  };
  