diff --git a/doc/api/globals.md b/doc/api/globals.md index 73d34250ac06..68ece7042b39 100644 --- a/doc/api/globals.md +++ b/doc/api/globals.md @@ -722,7 +722,11 @@ added: v21.0.0 > Stability: 1.1 - Active development. Disable this API with the > [`--no-experimental-global-navigator`][] CLI flag. -A partial implementation of the [Navigator API][]. +A partial implementation of the [Navigator API][]. All properties that the +HTML specification exposes to non-`Window` environments are implemented; +properties exposed only on `Window` (such as `navigator.plugins`) and most +properties defined by other specifications (such as `navigator.clipboard`) +are not. See below for the full list of supported options. ## `navigator` @@ -733,7 +737,46 @@ added: v21.0.0 > Stability: 1.1 - Active development. Disable this API with the > [`--no-experimental-global-navigator`][] CLI flag. -A partial implementation of [`window.navigator`][]. +A partial implementation of [`window.navigator`][]. All properties of the +[Navigator API][] that the HTML specification exposes to non-`Window` +environments are implemented; properties exposed only on `Window` (such as +`navigator.plugins`) and most properties defined by other specifications +(such as `navigator.clipboard`) are not. + +### `navigator.appCodeName` + + + +* Type: {string} + +The `navigator.appCodeName` read-only property returns `'Mozilla'`, +the constant value mandated by the [Navigator API][] specification. + +### `navigator.appName` + + + +* Type: {string} + +The `navigator.appName` read-only property returns `'Netscape'`, +the constant value mandated by the [Navigator API][] specification. + +### `navigator.appVersion` + + + +* Type: {string} + +The `navigator.appVersion` read-only property returns the empty string. +The [Navigator API][] specification requires this value to be derived from +the default `User-Agent` value and to be the empty string when that value +does not start with `Mozilla/5.0 (`. ### `navigator.hardwareConcurrency` @@ -840,6 +883,18 @@ navigator.locks.request('shared_resource', { mode: 'shared' }, async (lock) => { See [`worker_threads.locks`][] for detailed API documentation. +### `navigator.onLine` + + + +* Type: {boolean} + +The `navigator.onLine` read-only property always returns `true`. The +[Navigator API][] specification only allows returning `false` when the user +agent is definitely offline, which Node.js cannot determine. + ### `navigator.platform` + +* Type: {string} + +The `navigator.product` read-only property returns `'Gecko'`, +the constant value mandated by the [Navigator API][] specification. + ### `navigator.userAgent` + + +registerProtocolHandler() and a handler with %s in the fragment + + + + + +
    +
  1. First, register the handler: . +

  2. Then, run the test: . +

  3. Or, run the test with U+0000 NULL: . +

+
diff --git a/test/fixtures/wpt/html/webappapis/system-state-and-capabilities/the-navigator-object/protocol-handler-fragment-nosw-manual.https.html b/test/fixtures/wpt/html/webappapis/system-state-and-capabilities/the-navigator-object/protocol-handler-fragment-nosw-manual.https.html new file mode 100644 index 000000000000..be3a6be66652 --- /dev/null +++ b/test/fixtures/wpt/html/webappapis/system-state-and-capabilities/the-navigator-object/protocol-handler-fragment-nosw-manual.https.html @@ -0,0 +1,20 @@ + + + + +registerProtocolHandler() and a handler with %s in the fragment (does not use a service worker) + + + + + +
    +
  1. First, register the handler: . +

  2. Then, run the test: . +

  3. Or, run the test with U+0000 NULL: . +

+
diff --git a/test/fixtures/wpt/html/webappapis/system-state-and-capabilities/the-navigator-object/protocol-handler-fragment-nosw.https.html b/test/fixtures/wpt/html/webappapis/system-state-and-capabilities/the-navigator-object/protocol-handler-fragment-nosw.https.html new file mode 100644 index 000000000000..61b9722ec29a --- /dev/null +++ b/test/fixtures/wpt/html/webappapis/system-state-and-capabilities/the-navigator-object/protocol-handler-fragment-nosw.https.html @@ -0,0 +1,25 @@ + + + + +registerProtocolHandler() and a handler with %s in the fragment (does not use a service worker) + + + + + + + + diff --git a/test/fixtures/wpt/html/webappapis/system-state-and-capabilities/the-navigator-object/protocol-handler-fragment.https.html b/test/fixtures/wpt/html/webappapis/system-state-and-capabilities/the-navigator-object/protocol-handler-fragment.https.html new file mode 100644 index 000000000000..1eaefaa45f73 --- /dev/null +++ b/test/fixtures/wpt/html/webappapis/system-state-and-capabilities/the-navigator-object/protocol-handler-fragment.https.html @@ -0,0 +1,25 @@ + + + + +registerProtocolHandler() and a handler with %s in the fragment + + + + + + + + diff --git a/test/fixtures/wpt/html/webappapis/system-state-and-capabilities/the-navigator-object/protocol-handler-path-manual.https.html b/test/fixtures/wpt/html/webappapis/system-state-and-capabilities/the-navigator-object/protocol-handler-path-manual.https.html new file mode 100644 index 000000000000..085c5723ec41 --- /dev/null +++ b/test/fixtures/wpt/html/webappapis/system-state-and-capabilities/the-navigator-object/protocol-handler-path-manual.https.html @@ -0,0 +1,20 @@ + + + + +registerProtocolHandler() and a handler with %s in the path + + + + + +
    +
  1. First, register the handler: . +

  2. Then, run the test: . +

  3. Or, run the test with U+0000 NULL: . +

+
diff --git a/test/fixtures/wpt/html/webappapis/system-state-and-capabilities/the-navigator-object/protocol-handler-path.https.html b/test/fixtures/wpt/html/webappapis/system-state-and-capabilities/the-navigator-object/protocol-handler-path.https.html new file mode 100644 index 000000000000..a86e79e42eb6 --- /dev/null +++ b/test/fixtures/wpt/html/webappapis/system-state-and-capabilities/the-navigator-object/protocol-handler-path.https.html @@ -0,0 +1,25 @@ + + + + +registerProtocolHandler() and a handler with %s in the path + + + + + + + + diff --git a/test/fixtures/wpt/html/webappapis/system-state-and-capabilities/the-navigator-object/protocol-handler-query-manual.https.html b/test/fixtures/wpt/html/webappapis/system-state-and-capabilities/the-navigator-object/protocol-handler-query-manual.https.html new file mode 100644 index 000000000000..8ce65a5bad88 --- /dev/null +++ b/test/fixtures/wpt/html/webappapis/system-state-and-capabilities/the-navigator-object/protocol-handler-query-manual.https.html @@ -0,0 +1,20 @@ + + + + +registerProtocolHandler() and a handler with %s in the query + + + + + +
    +
  1. First, register the handler: . +

  2. Then, run the test: . +

  3. Or, run the test with U+0000 NULL: . +

+
diff --git a/test/fixtures/wpt/html/webappapis/system-state-and-capabilities/the-navigator-object/protocol-handler-query-nosw-manual.https.html b/test/fixtures/wpt/html/webappapis/system-state-and-capabilities/the-navigator-object/protocol-handler-query-nosw-manual.https.html new file mode 100644 index 000000000000..9b4473fb8952 --- /dev/null +++ b/test/fixtures/wpt/html/webappapis/system-state-and-capabilities/the-navigator-object/protocol-handler-query-nosw-manual.https.html @@ -0,0 +1,20 @@ + + + + +registerProtocolHandler() and a handler with %s in the query (does not use a service worker) + + + + + +
    +
  1. First, register the handler: . +

  2. Then, run the test: . +

  3. Or, run the test with U+0000 NULL: . +

+
diff --git a/test/fixtures/wpt/html/webappapis/system-state-and-capabilities/the-navigator-object/protocol-handler-query-nosw.https.html b/test/fixtures/wpt/html/webappapis/system-state-and-capabilities/the-navigator-object/protocol-handler-query-nosw.https.html new file mode 100644 index 000000000000..97f67e94eceb --- /dev/null +++ b/test/fixtures/wpt/html/webappapis/system-state-and-capabilities/the-navigator-object/protocol-handler-query-nosw.https.html @@ -0,0 +1,25 @@ + + + + +registerProtocolHandler() and a handler with %s in the query (does not use a service worker) + + + + + + + + diff --git a/test/fixtures/wpt/html/webappapis/system-state-and-capabilities/the-navigator-object/protocol-handler-query.https.html b/test/fixtures/wpt/html/webappapis/system-state-and-capabilities/the-navigator-object/protocol-handler-query.https.html new file mode 100644 index 000000000000..8c7b2e1cfdde --- /dev/null +++ b/test/fixtures/wpt/html/webappapis/system-state-and-capabilities/the-navigator-object/protocol-handler-query.https.html @@ -0,0 +1,25 @@ + + + + +registerProtocolHandler() and a handler with %s in the query + + + + + + + + diff --git a/test/fixtures/wpt/html/webappapis/system-state-and-capabilities/the-navigator-object/protocol.https.html b/test/fixtures/wpt/html/webappapis/system-state-and-capabilities/the-navigator-object/protocol.https.html new file mode 100644 index 000000000000..add78d2fd47a --- /dev/null +++ b/test/fixtures/wpt/html/webappapis/system-state-and-capabilities/the-navigator-object/protocol.https.html @@ -0,0 +1,218 @@ + + +protocol handlers + + + + + + +

Note: If your browser limits the number of handler +registration requests on a page, you might need to disable or significantly +increase that limit for the tests below to run.

+ + diff --git a/test/fixtures/wpt/html/webappapis/system-state-and-capabilities/the-navigator-object/protocol.tentative.https.html b/test/fixtures/wpt/html/webappapis/system-state-and-capabilities/the-navigator-object/protocol.tentative.https.html new file mode 100644 index 000000000000..0120aaa12ff8 --- /dev/null +++ b/test/fixtures/wpt/html/webappapis/system-state-and-capabilities/the-navigator-object/protocol.tentative.https.html @@ -0,0 +1,30 @@ + + +protocol handlers + + + + + diff --git a/test/fixtures/wpt/html/webappapis/system-state-and-capabilities/the-navigator-object/resources/handler-sw.js b/test/fixtures/wpt/html/webappapis/system-state-and-capabilities/the-navigator-object/resources/handler-sw.js new file mode 100644 index 000000000000..5fd915d17f98 --- /dev/null +++ b/test/fixtures/wpt/html/webappapis/system-state-and-capabilities/the-navigator-object/resources/handler-sw.js @@ -0,0 +1,3 @@ +onfetch = e => { + e.respondWith(fetch("handler.html")); +} diff --git a/test/fixtures/wpt/html/webappapis/system-state-and-capabilities/the-navigator-object/resources/handler-tools.js b/test/fixtures/wpt/html/webappapis/system-state-and-capabilities/the-navigator-object/resources/handler-tools.js new file mode 100644 index 000000000000..88c62ec373d1 --- /dev/null +++ b/test/fixtures/wpt/html/webappapis/system-state-and-capabilities/the-navigator-object/resources/handler-tools.js @@ -0,0 +1,53 @@ +// These can be used in an environment that has these global variables defined: +// * type (one of "path", "query", or "fragment") +// * noSW (a boolean) + +if (type === "path" && noSW) { + throw new Error("There is no support for a path handler without a service worker."); +} + +const swString = noSW ? "" : "sw"; +const handler = { + "path": "PSS%sPSE/?QES\u2020QEE#FES\u2020FEE", + "query": "?QES\u2020QEEPSS%sPSE#FES\u2020FEE", + "fragment": "?QES\u2020QEE#FES\u2020FEEPSS%sPSE" +}[type]; +const scheme = `web+wpt${type}${swString}`; + +function register() { + const handlerURL = noSW ? `resources/handler.html${handler}${type}` : `resources/handler/${type}/${handler}`; + navigator.registerProtocolHandler(scheme, handlerURL, `WPT ${type} handler${noSW ? ", without service worker" : ""}`); +} + +function runTest({ includeNull = false } = {}) { + promise_test(async t => { + const bc = new BroadcastChannel(`protocol-handler-${type}${swString}`); + if (!noSW) { + const reg = await service_worker_unregister_and_register(t, "resources/handler-sw.js", "resources/handler/"); + t.add_cleanup(async () => await reg.unregister()); + await wait_for_state(t, reg.installing, 'activated'); + } + const a = document.body.appendChild(document.createElement("a")); + const codePoints = []; + let i = includeNull ? 0 : 1; + for (; i < 0x82; i++) { + codePoints.push(String.fromCharCode(i)); + } + a.href = `${scheme}:${codePoints.join("")}`; + a.target = "_blank"; + a.click(); + await new Promise(resolve => { + bc.onmessage = t.step_func(e => { + resultingURL = e.data; + assert_equals(stringBetweenMarkers(resultingURL, "QES", "QEE"), "%86", "query baseline"); + assert_equals(stringBetweenMarkers(resultingURL, "FES", "FEE"), "%E2%80%A0", "fragment baseline"); + assert_equals(stringBetweenMarkers(resultingURL, "PSS", "PSE"), `${encodeURIComponent(scheme)}%3A${includeNull ? "%2500" : ""}%2501%2502%2503%2504%2505%2506%2507%2508%250B%250C%250E%250F%2510%2511%2512%2513%2514%2515%2516%2517%2518%2519%251A%251B%251C%251D%251E%251F%20!%22%23%24%25%26${type === "query" ? "%27" : "'"}()*%2B%2C-.%2F0123456789%3A%3B%253C%3D%253E%3F%40ABCDEFGHIJKLMNOPQRSTUVWXYZ%5B%5C%5D%5E_%2560abcdefghijklmnopqrstuvwxyz%7B%7C%7D~%257F%25C2%2580%25C2%2581`, "actual test"); + resolve(); + }); + }); + }); +} + +function stringBetweenMarkers(string, start, end) { + return string.substring(string.indexOf(start) + start.length, string.indexOf(end)); +} diff --git a/test/fixtures/wpt/html/webappapis/system-state-and-capabilities/the-navigator-object/resources/handler.html b/test/fixtures/wpt/html/webappapis/system-state-and-capabilities/the-navigator-object/resources/handler.html new file mode 100644 index 000000000000..552e5417842e --- /dev/null +++ b/test/fixtures/wpt/html/webappapis/system-state-and-capabilities/the-navigator-object/resources/handler.html @@ -0,0 +1,23 @@ + +

This popup can be closed if it does not close itself. +

+ diff --git a/test/fixtures/wpt/html/webappapis/system-state-and-capabilities/the-navigator-object/secure_context.html b/test/fixtures/wpt/html/webappapis/system-state-and-capabilities/the-navigator-object/secure_context.html new file mode 100644 index 000000000000..685f5d19d7ca --- /dev/null +++ b/test/fixtures/wpt/html/webappapis/system-state-and-capabilities/the-navigator-object/secure_context.html @@ -0,0 +1,18 @@ + + + + + + + + diff --git a/test/fixtures/wpt/versions.json b/test/fixtures/wpt/versions.json index 4c01b3e53663..1f47de95af53 100644 --- a/test/fixtures/wpt/versions.json +++ b/test/fixtures/wpt/versions.json @@ -47,6 +47,10 @@ "commit": "47d3fb280c9c632e684dee3b78ae1f4c5d5ba640", "path": "html/webappapis/structured-clone" }, + "html/webappapis/system-state-and-capabilities/the-navigator-object": { + "commit": "4832db47614f5f48cc57374cbf5c1f70937fad48", + "path": "html/webappapis/system-state-and-capabilities/the-navigator-object" + }, "html/webappapis/timers": { "commit": "5873f2d8f1f7bbb9c64689e52d04498614632906", "path": "html/webappapis/timers" diff --git a/test/parallel/test-navigator.js b/test/parallel/test-navigator.js index 82e3fe903d45..ebb26e156749 100644 --- a/test/parallel/test-navigator.js +++ b/test/parallel/test-navigator.js @@ -48,6 +48,14 @@ assert.ok(navigator.hardwareConcurrency > 0); assert.strictEqual(typeof navigator.userAgent, 'string'); assert.match(navigator.userAgent, /^Node\.js\/\d+$/); +// Constant values mandated by +// https://html.spec.whatwg.org/multipage/system-state.html#the-navigator-object +assert.strictEqual(navigator.appCodeName, 'Mozilla'); +assert.strictEqual(navigator.appName, 'Netscape'); +assert.strictEqual(navigator.appVersion, ''); +assert.strictEqual(navigator.product, 'Gecko'); +assert.strictEqual(navigator.onLine, true); + assert.strictEqual(typeof navigator.platform, 'string'); if (process.platform === 'darwin') { assert.strictEqual(navigator.platform, 'MacIntel'); diff --git a/test/wpt/status/html/webappapis/system-state-and-capabilities/the-navigator-object.json b/test/wpt/status/html/webappapis/system-state-and-capabilities/the-navigator-object.json new file mode 100644 index 000000000000..8e7783051ce0 --- /dev/null +++ b/test/wpt/status/html/webappapis/system-state-and-capabilities/the-navigator-object.json @@ -0,0 +1,24 @@ +{ + "clientinformation.window.js": { + "skip": "Node.js does not have a window object nor clientInformation" + }, + "historical.https.window.js": { + "fail": { + "note": "registerProtocolHandler is not implemented in Node.js", + "expected": [ + "registerProtocolHandler has no third argument" + ] + } + }, + "navigator.any.js": { + "fail": { + "note": "XMLHttpRequest is not available in Node.js", + "expected": [ + "userAgent value" + ] + } + }, + "per-global.window.js": { + "skip": "Node.js does not support multiple window globals" + } +} diff --git a/test/wpt/test-navigator.js b/test/wpt/test-navigator.js new file mode 100644 index 000000000000..c39b99449c78 --- /dev/null +++ b/test/wpt/test-navigator.js @@ -0,0 +1,7 @@ +'use strict'; + +const { WPTRunner } = require('../common/wpt'); + +const runner = new WPTRunner('html/webappapis/system-state-and-capabilities/the-navigator-object'); + +runner.runJsTests();