diff --git a/lib/internal/navigator.js b/lib/internal/navigator.js index 2904779a47e64b..d8681c89990494 100644 --- a/lib/internal/navigator.js +++ b/lib/internal/navigator.js @@ -79,7 +79,8 @@ function getNavigatorPlatform(arch, platform) { } class Navigator { - // Private properties are used to avoid brand validations. + // 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; @@ -113,6 +114,10 @@ class Navigator { * @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'; diff --git a/test/parallel/test-navigator.js b/test/parallel/test-navigator.js index 01c5595b93cd12..82e3fe903d455f 100644 --- a/test/parallel/test-navigator.js +++ b/test/parallel/test-navigator.js @@ -147,3 +147,19 @@ Object.defineProperty(navigator, 'language', { value: 'for-testing' }); assert.strictEqual(navigator.language, 'for-testing'); assert.strictEqual(navigator.languages.length, 1); assert.strictEqual(navigator.languages[0] !== 'for-testing', true); + +{ + const { Navigator } = globalThis; + for (const name of Object.keys(Navigator.prototype)) { + assert.throws( + () => Navigator.prototype[name], + { name: 'TypeError' }, + `expected TypeError when reading ${name} on Navigator.prototype`, + ); + assert.throws( + () => Reflect.get(Navigator.prototype, name, {}), + { name: 'TypeError' }, + `expected TypeError when reading ${name} on a plain object`, + ); + } +}