diff --git a/test/fixtures/wpt/fetch/api/request/WEB_FEATURES.yml b/test/fixtures/wpt/fetch/api/request/WEB_FEATURES.yml
new file mode 100644
index 00000000000..69b2ea582a2
--- /dev/null
+++ b/test/fixtures/wpt/fetch/api/request/WEB_FEATURES.yml
@@ -0,0 +1,4 @@
+features:
+- name: fetch-priority
+ files:
+ - request-init-priority.any.js
diff --git a/test/fixtures/wpt/fetch/http-cache/no-vary-search.tentative.any.js b/test/fixtures/wpt/fetch/http-cache/no-vary-search.tentative.any.js
index 379da6a0594..6c5a714e287 100644
--- a/test/fixtures/wpt/fetch/http-cache/no-vary-search.tentative.any.js
+++ b/test/fixtures/wpt/fetch/http-cache/no-vary-search.tentative.any.js
@@ -6,12 +6,15 @@
// META: script=http-cache.js
/*
NOTE for testing No-Vary-Search-Header:
-If `params` is set to true, `expect=("dispatch" "uuid")` must be specified.
-Otherwise:
-- The same HTTP Cache will be used by other tests, which are supposed
- to be distinguished by uuid.
-- The test utility cannot get the server's states because UA will use the HTTP
- Cache instead of sending a new request to server to ask for the latest state.
+- If `params` is set to true, `expect=("dispatch" "uuid")` must be specified.
+ Otherwise:
+ - The same HTTP Cache will be used by other tests, which are supposed
+ to be distinguished by uuid.
+ - The test utility cannot get the server's states because UA will use the HTTP
+ Cache instead of sending a new request to server to ask for the latest state.
+- Do not test not_cached cases and cached cases within one test. Test infra
+ checks the number of requests and responses without considering if the
+ previous responses should be served from cache or not.
*/
var tests = [
{
@@ -28,6 +31,61 @@ var tests = [
expected_type: "cached"
}
]
+ },
+ {
+ name: "Ground truth: When key-order is not set, URLs should be compared in an order-sensitive way.",
+ requests: [
+ {
+ url_params: "a=1&b=2",
+ response_headers: [
+ ["Cache-Control", "max-age=10000"],
+ ],
+ },
+ {
+ url_params: "b=2&a=1",
+ expected_type: "not_cached"
+ }
+ ]
+ },
+ {
+ name: "When key-order is set , URLs should be compared in an order-insensitive way. Matched cases:",
+ requests: [
+ {
+ url_params: "a=1&b=2",
+ response_headers: [
+ ["Cache-Control", "max-age=10000"],
+ ["No-Vary-Search", "key-order"],
+ ],
+ },
+ {
+ url_params: "b=2&a=1",
+ expected_type: "cached"
+ }
+ ]
+ },
+ {
+ name: "When key-order is set , URLs should be compared in an order-insensitive way. Not matched cases",
+ requests: [
+ {
+ url_params: "a=1&b=2",
+ response_headers: [
+ ["Cache-Control", "max-age=10000"],
+ ["No-Vary-Search", "key-order"],
+ ],
+ },
+ {
+ url_params: "b=2",
+ expected_type: "not_cached"
+ },
+ {
+ url_params: "a=2&b=2",
+ expected_type: "not_cached"
+ },
+ {
+ url_params: "a=1&b=2&c=3",
+ expected_type: "not_cached"
+ }
+ ]
}
];
run_tests(tests);
diff --git a/test/fixtures/wpt/fetch/http-cache/pragma-no-cache-with-cache-control.html b/test/fixtures/wpt/fetch/http-cache/pragma-no-cache-with-cache-control.html
new file mode 100644
index 00000000000..19a80fe5edc
--- /dev/null
+++ b/test/fixtures/wpt/fetch/http-cache/pragma-no-cache-with-cache-control.html
@@ -0,0 +1,28 @@
+
+
+
HTTP Cache: Cache-Control with Pragma: no-cache
+
+
+
+
+
diff --git a/test/fixtures/wpt/fetch/http-cache/resources/cached_pragma_rand.py b/test/fixtures/wpt/fetch/http-cache/resources/cached_pragma_rand.py
new file mode 100644
index 00000000000..18c7d25159f
--- /dev/null
+++ b/test/fixtures/wpt/fetch/http-cache/resources/cached_pragma_rand.py
@@ -0,0 +1,14 @@
+def main(request, response):
+ # Disable non-standard XSS protection
+ response.headers.set(b"X-XSS-Protection", b"0")
+ response.headers.set(b"Content-Type", b"text/html")
+
+ # Set caching headers
+ # According to rfc9111 Pragma: no-cache is deprecated, so we expect
+ # Cache-Control to take precedence when there's a mismatch.
+ response.headers.set(b"Cache-Control", b"max-age=2592000, public")
+ response.headers.set(b"Pragma", b"no-cache")
+
+ # Include a timestamp to verify caching behavior
+ import time
+ response.content = f"Timestamp: {time.time()}".encode('utf-8')
diff --git a/test/fixtures/wpt/fetch/local-network-access/META.yml b/test/fixtures/wpt/fetch/local-network-access/META.yml
new file mode 100644
index 00000000000..4c5c6983ed0
--- /dev/null
+++ b/test/fixtures/wpt/fetch/local-network-access/META.yml
@@ -0,0 +1,5 @@
+spec: https://wicg.github.io/local-network-access/
+suggested_reviewers:
+ - cthomp
+ - camillelamy
+ - hchao
diff --git a/test/fixtures/wpt/fetch/local-network-access/README.md b/test/fixtures/wpt/fetch/local-network-access/README.md
new file mode 100644
index 00000000000..95066cdcd0b
--- /dev/null
+++ b/test/fixtures/wpt/fetch/local-network-access/README.md
@@ -0,0 +1,11 @@
+# Local Network Access tests
+
+This directory contains tests for Local Network Access' integration with
+the Fetch specification.
+
+See also:
+
+* [Explainer](https://github.com/explainers-by-googlers/local-network-access)
+
+Local Network Access replaced [Private Network
+Access](https://wicg.github.io/local-network-access/).
diff --git a/test/fixtures/wpt/fetch/local-network-access/fetch.tentative.https.html b/test/fixtures/wpt/fetch/local-network-access/fetch.tentative.https.html
new file mode 100644
index 00000000000..9c591f309b7
--- /dev/null
+++ b/test/fixtures/wpt/fetch/local-network-access/fetch.tentative.https.html
@@ -0,0 +1,51 @@
+
+
+LNA Fetch tests: HTTPS
+
+
+
+
+
+
+
+
diff --git a/test/fixtures/wpt/fetch/local-network-access/resources/fetch-private.html b/test/fixtures/wpt/fetch/local-network-access/resources/fetch-private.html
new file mode 100644
index 00000000000..b96a207ec33
--- /dev/null
+++ b/test/fixtures/wpt/fetch/local-network-access/resources/fetch-private.html
@@ -0,0 +1,52 @@
+
+
+Fetch Private resource
+
+
+
+
+
diff --git a/test/fixtures/wpt/fetch/local-network-access/resources/support.sub.js b/test/fixtures/wpt/fetch/local-network-access/resources/support.sub.js
new file mode 100644
index 00000000000..774e34d0a6f
--- /dev/null
+++ b/test/fixtures/wpt/fetch/local-network-access/resources/support.sub.js
@@ -0,0 +1,186 @@
+// Maps protocol (without the trailing colon) and address space to port.
+const SERVER_PORTS = {
+ "http": {
+ "local": {{ports[http][0]}},
+ "private": {{ports[http-private][0]}},
+ "public": {{ports[http-public][0]}},
+ },
+ "https": {
+ "local": {{ports[https][0]}},
+ "other-local": {{ports[https][1]}},
+ "private": {{ports[https-private][0]}},
+ "public": {{ports[https-public][0]}},
+ },
+ "ws": {
+ "local": {{ports[ws][0]}},
+ },
+ "wss": {
+ "local": {{ports[wss][0]}},
+ },
+};
+
+// A `Server` is a web server accessible by tests. It has the following shape:
+//
+// {
+// addressSpace: the IP address space of the server ("local", "private" or
+// "public"),
+// name: a human-readable name for the server,
+// port: the port on which the server listens for connections,
+// protocol: the protocol (including trailing colon) spoken by the server,
+// }
+//
+// Constants below define the available servers, which can also be accessed
+// programmatically with `get()`.
+class Server {
+ // Maps the given `protocol` (without a trailing colon) and `addressSpace` to
+ // a server. Returns null if no such server exists.
+ static get(protocol, addressSpace) {
+ const ports = SERVER_PORTS[protocol];
+ if (ports === undefined) {
+ return null;
+ }
+
+ const port = ports[addressSpace];
+ if (port === undefined) {
+ return null;
+ }
+
+ return {
+ addressSpace,
+ name: `${protocol}-${addressSpace}`,
+ port,
+ protocol: protocol + ':',
+ };
+ }
+
+ static HTTP_LOCAL = Server.get("http", "local");
+ static HTTP_PRIVATE = Server.get("http", "private");
+ static HTTP_PUBLIC = Server.get("http", "public");
+ static HTTPS_LOCAL = Server.get("https", "local");
+ static OTHER_HTTPS_LOCAL = Server.get("https", "other-local");
+ static HTTPS_PRIVATE = Server.get("https", "private");
+ static HTTPS_PUBLIC = Server.get("https", "public");
+ static WS_LOCAL = Server.get("ws", "local");
+ static WSS_LOCAL = Server.get("wss", "local");
+};
+
+// Resolves a URL relative to the current location, returning an absolute URL.
+//
+// `url` specifies the relative URL, e.g. "foo.html" or "http://foo.example".
+// `options`, if defined, should have the following shape:
+//
+// {
+// // Optional. Overrides the protocol of the returned URL.
+// protocol,
+//
+// // Optional. Overrides the port of the returned URL.
+// port,
+//
+// // Extra headers.
+// headers,
+//
+// // Extra search params.
+// searchParams,
+// }
+//
+function resolveUrl(url, options) {
+ const result = new URL(url, window.location);
+ if (options === undefined) {
+ return result;
+ }
+
+ const { port, protocol, headers, searchParams } = options;
+ if (port !== undefined) {
+ result.port = port;
+ }
+ if (protocol !== undefined) {
+ result.protocol = protocol;
+ }
+ if (headers !== undefined) {
+ const pipes = [];
+ for (key in headers) {
+ pipes.push(`header(${key},${headers[key]})`);
+ }
+ result.searchParams.append("pipe", pipes.join("|"));
+ }
+ if (searchParams !== undefined) {
+ for (key in searchParams) {
+ result.searchParams.append(key, searchParams[key]);
+ }
+ }
+
+ return result;
+}
+
+// Computes options to pass to `resolveUrl()` for a source document's URL.
+//
+// `server` identifies the server from which to load the document.
+// `treatAsPublic`, if set to true, specifies that the source document should
+// be artificially placed in the `public` address space using CSP.
+function sourceResolveOptions({ server, treatAsPublic }) {
+ const options = {...server};
+ if (treatAsPublic) {
+ options.headers = { "Content-Security-Policy": "treat-as-public-address" };
+ }
+ return options;
+}
+
+// Computes the URL of a target handler configured with the given options.
+//
+// `server` identifies the server from which to load the resource.
+// `behavior` specifies the behavior of the target server. It may contain:
+// - `response`: The result of calling one of `ResponseBehavior`'s methods.
+// - `redirect`: A URL to which the target should redirect GET requests.
+function resolveTargetUrl({ server, behavior }) {
+ if (server === undefined) {
+ throw new Error("no server specified.");
+ }
+ const options = {...server};
+ if (behavior) {
+ const { response, redirect } = behavior;
+ options.searchParams = {
+ ...response,
+ };
+ if (redirect !== undefined) {
+ options.searchParams.redirect = redirect;
+ }
+ }
+
+ return resolveUrl("target.py", options);
+}
+
+// Methods generate behavior specifications for how `resources/target.py`
+// should behave upon receiving a regular (non-preflight) request.
+const ResponseBehavior = {
+ // The response should succeed without CORS headers.
+ default: () => ({}),
+
+ // The response should succeed with CORS headers.
+ allowCrossOrigin: () => ({ "final-headers": "cors" }),
+};
+
+const FetchTestResult = {
+ SUCCESS: {
+ ok: true,
+ body: "success",
+ },
+ OPAQUE: {
+ ok: false,
+ type: "opaque",
+ body: "",
+ },
+ FAILURE: {
+ error: "TypeError: Failed to fetch",
+ },
+};
+
+// Helper function for checking results from fetch tests.
+function checkTestResult(actual, expected) {
+ assert_equals(actual.error, expected.error, "error mismatch");
+ assert_equals(actual.ok, expected.ok, "response ok mismatch");
+ assert_equals(actual.body, expected.body, "response body mismatch");
+
+ if (expected.type !== undefined) {
+ assert_equals(type, expected.type, "response type mismatch");
+ }
+}
diff --git a/test/fixtures/wpt/fetch/local-network-access/resources/target.py b/test/fixtures/wpt/fetch/local-network-access/resources/target.py
new file mode 100644
index 00000000000..eabcdd47517
--- /dev/null
+++ b/test/fixtures/wpt/fetch/local-network-access/resources/target.py
@@ -0,0 +1,105 @@
+# This endpoint responds to requests for a target of a (possible) LNA request.
+#
+# Its behavior can be configured with various search/GET parameters, all of
+# which are optional:
+#
+# - final-headers: Valid values are:
+# - cors: this endpoint responds with valid CORS headers to CORS-enabled
+# non-preflight requests. These should be sufficient for non-preflighted
+# CORS-enabled requests to succeed.
+# - sw: this endpoint responds with a valid Service-Worker header to allow
+# for the request to serve as a Service worker script resource. This is
+# only valid in conjunction with the cors value above.
+# - unspecified: this endpoint responds with no CORS headers to non-preflight
+# requests. This should fail CORS-enabled requests, but be sufficient for
+# no-CORS requests.
+#
+# The following parameters only affect non-preflight responses:
+#
+# - redirect: If set, the response code is set to 301 and the `Location`
+# response header is set to this value.
+# - mime-type: If set, the `Content-Type` response header is set to this value.
+# - file: Specifies a path (relative to this file's directory) to a file. If
+# set, the response body is copied from this file.
+# - random-js-prefix: If set to any value, the response body is prefixed with
+# a Javascript comment line containing a random value. This is useful in
+# service worker tests, since service workers are only updated if the new
+# script is not byte-for-byte identical with the old script.
+# - body: If set and `file` is not, the response body is set to this value.
+#
+
+import os
+import random
+
+from wptserve.utils import isomorphic_encode
+
+_ACAO = ("Access-Control-Allow-Origin", "*")
+_ACAH = ("Access-Control-Allow-Headers", "Service-Worker")
+
+def _get_response_headers(method, mode, origin):
+ acam = ("Access-Control-Allow-Methods", method)
+
+ if mode == b"cors":
+ return [acam, _ACAO]
+
+ if mode == b"cors+sw":
+ return [acam, _ACAO, _ACAH]
+
+ if mode == b"navigation":
+ return [
+ acam,
+ ("Access-Control-Allow-Origin", origin),
+ ("Access-Control-Allow-Credentials", "true"),
+ ]
+
+ return []
+
+
+def _is_loaded_in_fenced_frame(request):
+ return request.GET.get(b"is-loaded-in-fenced-frame")
+
+def _final_response_body(request):
+ file_name = None
+ if file_name is None:
+ file_name = request.GET.get(b"file")
+ if file_name is None:
+ return request.GET.get(b"body") or "success"
+
+ prefix = b""
+ if request.GET.get(b"random-js-prefix"):
+ value = random.randint(0, 1000000000)
+ prefix = isomorphic_encode("// Random value: {}\n\n".format(value))
+
+ path = os.path.join(os.path.dirname(isomorphic_encode(__file__)), file_name)
+ with open(path, 'rb') as f:
+ contents = f.read()
+
+ return prefix + contents
+
+def _handle_final_request(request, response):
+ mode = request.GET.get(b"final-headers")
+ origin = request.headers.get("Origin")
+ headers = _get_response_headers(request.method, mode, origin)
+
+ redirect = request.GET.get(b"redirect")
+ if redirect is not None:
+ headers.append(("Location", redirect))
+ return (301, headers, b"")
+
+ mime_type = request.GET.get(b"mime-type")
+ if mime_type is not None:
+ headers.append(("Content-Type", mime_type),)
+
+ if _is_loaded_in_fenced_frame(request):
+ headers.append(("Supports-Loading-Mode", "fenced-frame"))
+
+ body = _final_response_body(request)
+ return (headers, body)
+
+
+def main(request, response):
+ try:
+ return _handle_final_request(request, response)
+ except BaseException as e:
+ # Surface exceptions to the client, where they show up as assertion errors.
+ return (500, [("X-exception", str(e))], "exception: {}".format(e))
diff --git a/test/fixtures/wpt/interfaces/fedcm.idl b/test/fixtures/wpt/interfaces/fedcm.idl
index 215f375432e..5ce2d260f11 100644
--- a/test/fixtures/wpt/interfaces/fedcm.idl
+++ b/test/fixtures/wpt/interfaces/fedcm.idl
@@ -84,8 +84,10 @@ dictionary IdentityProviderAPIConfig {
dictionary IdentityProviderAccount {
required USVString id;
- required USVString name;
- required USVString email;
+ USVString name;
+ USVString email;
+ USVString tel;
+ USVString username;
USVString given_name;
USVString picture;
sequence approved_clients;
diff --git a/test/fixtures/wpt/interfaces/image-capture.idl b/test/fixtures/wpt/interfaces/image-capture.idl
index 21e03d4db82..26cc7fab5cd 100644
--- a/test/fixtures/wpt/interfaces/image-capture.idl
+++ b/test/fixtures/wpt/interfaces/image-capture.idl
@@ -3,7 +3,7 @@
// (https://github.com/w3c/webref)
// Source: MediaStream Image Capture (https://w3c.github.io/mediacapture-image/)
-[Exposed=Window]
+[Exposed=Window, SecureContext]
interface ImageCapture {
constructor(MediaStreamTrack videoTrack);
Promise takePhoto(optional PhotoSettings photoSettings = {});
diff --git a/test/fixtures/wpt/interfaces/largest-contentful-paint.idl b/test/fixtures/wpt/interfaces/largest-contentful-paint.idl
index 872ba552b0d..d1630cc7daa 100644
--- a/test/fixtures/wpt/interfaces/largest-contentful-paint.idl
+++ b/test/fixtures/wpt/interfaces/largest-contentful-paint.idl
@@ -5,7 +5,6 @@
[Exposed=Window]
interface LargestContentfulPaint : PerformanceEntry {
- readonly attribute DOMHighResTimeStamp renderTime;
readonly attribute DOMHighResTimeStamp loadTime;
readonly attribute unsigned long size;
readonly attribute DOMString id;
@@ -13,3 +12,5 @@ interface LargestContentfulPaint : PerformanceEntry {
readonly attribute Element? element;
[Default] object toJSON();
};
+
+LargestContentfulPaint includes PaintTimingMixin;
diff --git a/test/fixtures/wpt/interfaces/mediastream-recording.idl b/test/fixtures/wpt/interfaces/mediastream-recording.idl
index 496bfcf2e27..68c891cdc91 100644
--- a/test/fixtures/wpt/interfaces/mediastream-recording.idl
+++ b/test/fixtures/wpt/interfaces/mediastream-recording.idl
@@ -56,7 +56,7 @@ interface BlobEvent : Event {
readonly attribute DOMHighResTimeStamp timecode;
};
-dictionary BlobEventInit {
+dictionary BlobEventInit : EventInit {
required Blob data;
DOMHighResTimeStamp timecode;
};
diff --git a/test/fixtures/wpt/interfaces/service-workers.idl b/test/fixtures/wpt/interfaces/service-workers.idl
index d9ff2f651f8..34af3372401 100644
--- a/test/fixtures/wpt/interfaces/service-workers.idl
+++ b/test/fixtures/wpt/interfaces/service-workers.idl
@@ -34,7 +34,7 @@ interface ServiceWorkerRegistration : EventTarget {
readonly attribute USVString scope;
readonly attribute ServiceWorkerUpdateViaCache updateViaCache;
- [NewObject] Promise update();
+ [NewObject] Promise update();
[NewObject] Promise unregister();
// event
diff --git a/test/fixtures/wpt/interfaces/turtledove.idl b/test/fixtures/wpt/interfaces/turtledove.idl
index b9f50d47885..7f11cdc3790 100644
--- a/test/fixtures/wpt/interfaces/turtledove.idl
+++ b/test/fixtures/wpt/interfaces/turtledove.idl
@@ -206,6 +206,7 @@ partial interface Navigator {
[Exposed=InterestGroupScriptRunnerGlobalScope]
interface InterestGroupScriptRunnerGlobalScope {
readonly attribute PrivateAggregation? privateAggregation;
+ readonly attribute ProtectedAudienceUtilities protectedAudience;
};
dictionary PASignalValue {
@@ -220,6 +221,12 @@ dictionary PAExtendedHistogramContribution {
bigint filteringId = 0;
};
+[Exposed=InterestGroupScriptRunnerGlobalScope]
+interface ProtectedAudienceUtilities {
+ Uint8Array encodeUtf8(USVString input);
+ USVString decodeUtf8(Uint8Array bytes);
+};
+
[Exposed=InterestGroupBiddingAndScoringScriptRunnerGlobalScope]
interface ForDebuggingOnly {
undefined reportAdAuctionWin(USVString url);
diff --git a/test/fixtures/wpt/interfaces/webauthn.idl b/test/fixtures/wpt/interfaces/webauthn.idl
index a33c85e7bad..7fbe55e6765 100644
--- a/test/fixtures/wpt/interfaces/webauthn.idl
+++ b/test/fixtures/wpt/interfaces/webauthn.idl
@@ -311,22 +311,37 @@ enum PublicKeyCredentialHint {
partial dictionary AuthenticationExtensionsClientInputs {
DOMString appid;
};
+partial dictionary AuthenticationExtensionsClientInputsJSON {
+ DOMString appid;
+};
partial dictionary AuthenticationExtensionsClientOutputs {
boolean appid;
};
+partial dictionary AuthenticationExtensionsClientOutputsJSON {
+ boolean appid;
+};
partial dictionary AuthenticationExtensionsClientInputs {
DOMString appidExclude;
};
+partial dictionary AuthenticationExtensionsClientInputsJSON {
+ DOMString appidExclude;
+};
partial dictionary AuthenticationExtensionsClientOutputs {
boolean appidExclude;
};
+partial dictionary AuthenticationExtensionsClientOutputsJSON {
+ boolean appidExclude;
+};
partial dictionary AuthenticationExtensionsClientInputs {
boolean credProps;
};
+partial dictionary AuthenticationExtensionsClientInputsJSON {
+ boolean credProps;
+};
dictionary CredentialPropertiesOutput {
boolean rk;
@@ -335,33 +350,57 @@ dictionary CredentialPropertiesOutput {
partial dictionary AuthenticationExtensionsClientOutputs {
CredentialPropertiesOutput credProps;
};
+partial dictionary AuthenticationExtensionsClientOutputsJSON {
+ CredentialPropertiesOutput credProps;
+};
dictionary AuthenticationExtensionsPRFValues {
required BufferSource first;
BufferSource second;
};
+dictionary AuthenticationExtensionsPRFValuesJSON {
+ required Base64URLString first;
+ Base64URLString second;
+};
dictionary AuthenticationExtensionsPRFInputs {
AuthenticationExtensionsPRFValues eval;
record evalByCredential;
};
+dictionary AuthenticationExtensionsPRFInputsJSON {
+ AuthenticationExtensionsPRFValuesJSON eval;
+ record evalByCredential;
+};
partial dictionary AuthenticationExtensionsClientInputs {
AuthenticationExtensionsPRFInputs prf;
};
+partial dictionary AuthenticationExtensionsClientInputsJSON {
+ AuthenticationExtensionsPRFInputsJSON prf;
+};
dictionary AuthenticationExtensionsPRFOutputs {
boolean enabled;
AuthenticationExtensionsPRFValues results;
};
+dictionary AuthenticationExtensionsPRFOutputsJSON {
+ boolean enabled;
+ AuthenticationExtensionsPRFValuesJSON results;
+};
partial dictionary AuthenticationExtensionsClientOutputs {
AuthenticationExtensionsPRFOutputs prf;
};
+partial dictionary AuthenticationExtensionsClientOutputsJSON {
+ AuthenticationExtensionsPRFOutputsJSON prf;
+};
partial dictionary AuthenticationExtensionsClientInputs {
AuthenticationExtensionsLargeBlobInputs largeBlob;
};
+partial dictionary AuthenticationExtensionsClientInputsJSON {
+ AuthenticationExtensionsLargeBlobInputsJSON largeBlob;
+};
enum LargeBlobSupport {
"required",
@@ -373,13 +412,26 @@ dictionary AuthenticationExtensionsLargeBlobInputs {
boolean read;
BufferSource write;
};
+dictionary AuthenticationExtensionsLargeBlobInputsJSON {
+ DOMString support;
+ boolean read;
+ Base64URLString write;
+};
partial dictionary AuthenticationExtensionsClientOutputs {
AuthenticationExtensionsLargeBlobOutputs largeBlob;
};
+partial dictionary AuthenticationExtensionsClientOutputsJSON {
+ AuthenticationExtensionsLargeBlobOutputsJSON largeBlob;
+};
dictionary AuthenticationExtensionsLargeBlobOutputs {
boolean supported;
ArrayBuffer blob;
boolean written;
};
+dictionary AuthenticationExtensionsLargeBlobOutputsJSON {
+ boolean supported;
+ Base64URLString blob;
+ boolean written;
+};
diff --git a/test/fixtures/wpt/interfaces/webcodecs.idl b/test/fixtures/wpt/interfaces/webcodecs.idl
index 274ef96578a..3d4db1ed49d 100644
--- a/test/fixtures/wpt/interfaces/webcodecs.idl
+++ b/test/fixtures/wpt/interfaces/webcodecs.idl
@@ -141,7 +141,7 @@ dictionary AudioDecoderConfig {
required DOMString codec;
[EnforceRange] required unsigned long sampleRate;
[EnforceRange] required unsigned long numberOfChannels;
- BufferSource description;
+ AllowSharedBufferSource description;
};
dictionary VideoDecoderConfig {
diff --git a/test/fixtures/wpt/interfaces/WebCryptoAPI.idl b/test/fixtures/wpt/interfaces/webcrypto.idl
similarity index 100%
rename from test/fixtures/wpt/interfaces/WebCryptoAPI.idl
rename to test/fixtures/wpt/interfaces/webcrypto.idl
diff --git a/test/fixtures/wpt/interfaces/webgpu.idl b/test/fixtures/wpt/interfaces/webgpu.idl
index de1f7c1e52b..4fec46a2557 100644
--- a/test/fixtures/wpt/interfaces/webgpu.idl
+++ b/test/fixtures/wpt/interfaces/webgpu.idl
@@ -109,6 +109,7 @@ dictionary GPUDeviceDescriptor
};
enum GPUFeatureName {
+ "core-features-and-limits",
"depth-clip-control",
"depth32float-stencil8",
"texture-compression-bc",
diff --git a/test/fixtures/wpt/interfaces/webnn.idl b/test/fixtures/wpt/interfaces/webnn.idl
index 57f2a4a9890..37fcc32501e 100644
--- a/test/fixtures/wpt/interfaces/webnn.idl
+++ b/test/fixtures/wpt/interfaces/webnn.idl
@@ -36,6 +36,8 @@ interface MLContext {
undefined dispatch(MLGraph graph, MLNamedTensors inputs, MLNamedTensors outputs);
Promise createTensor(MLTensorDescriptor descriptor);
+ Promise createConstantTensor(
+ MLOperandDescriptor descriptor, AllowSharedBufferSource inputData);
Promise readTensor(MLTensor tensor);
Promise readTensor(MLTensor tensor, AllowSharedBufferSource outputData);
@@ -133,6 +135,7 @@ interface MLTensor {
readonly attribute FrozenArray shape;
readonly attribute boolean readable;
readonly attribute boolean writable;
+ readonly attribute boolean constant;
undefined destroy();
};
@@ -154,6 +157,9 @@ interface MLGraphBuilder {
// Create a scalar operand from the specified number of the specified type.
MLOperand constant(MLOperandDataType type, MLNumber value);
+ // Create an operand from a specified constant tensor.
+ MLOperand constant(MLTensor tensor);
+
// Compile the graph up to the specified output operands asynchronously.
Promise build(MLNamedOperands outputs);
};
diff --git a/test/fixtures/wpt/interfaces/webxr-depth-sensing.idl b/test/fixtures/wpt/interfaces/webxr-depth-sensing.idl
index 9befd640646..7ddbec7cc97 100644
--- a/test/fixtures/wpt/interfaces/webxr-depth-sensing.idl
+++ b/test/fixtures/wpt/interfaces/webxr-depth-sensing.idl
@@ -34,6 +34,10 @@ partial interface XRSession {
readonly attribute XRDepthUsage depthUsage;
readonly attribute XRDepthDataFormat depthDataFormat;
readonly attribute XRDepthType? depthType;
+ readonly attribute boolean? depthActive;
+
+ undefined pauseDepthSensing();
+ undefined resumeDepthSensing();
};
[SecureContext, Exposed=Window]
@@ -43,9 +47,10 @@ interface XRDepthInformation {
[SameObject] readonly attribute XRRigidTransform normDepthBufferFromNormView;
readonly attribute float rawValueToMeters;
- readonly attribute XRView? view;
};
+XRDepthInformation includes XRViewGeometry;
+
[Exposed=Window]
interface XRCPUDepthInformation : XRDepthInformation {
[SameObject] readonly attribute ArrayBuffer data;
diff --git a/test/fixtures/wpt/interfaces/webxr.idl b/test/fixtures/wpt/interfaces/webxr.idl
index 1098000d6c2..874994086a2 100644
--- a/test/fixtures/wpt/interfaces/webxr.idl
+++ b/test/fixtures/wpt/interfaces/webxr.idl
@@ -118,6 +118,11 @@ interface XRBoundedReferenceSpace : XRReferenceSpace {
readonly attribute FrozenArray boundsGeometry;
};
+[SecureContext, Exposed=Window] interface mixin XRViewGeometry {
+ readonly attribute Float32Array projectionMatrix;
+ [SameObject] readonly attribute XRRigidTransform transform;
+};
+
enum XREye {
"none",
"left",
@@ -126,13 +131,13 @@ enum XREye {
[SecureContext, Exposed=Window] interface XRView {
readonly attribute XREye eye;
- readonly attribute Float32Array projectionMatrix;
- [SameObject] readonly attribute XRRigidTransform transform;
readonly attribute double? recommendedViewportScale;
undefined requestViewportScale(double? scale);
};
+XRView includes XRViewGeometry;
+
[SecureContext, Exposed=Window] interface XRViewport {
readonly attribute long x;
readonly attribute long y;
diff --git a/test/fixtures/wpt/interfaces/writing-assistance-apis.idl b/test/fixtures/wpt/interfaces/writing-assistance-apis.idl
new file mode 100644
index 00000000000..916daee754e
--- /dev/null
+++ b/test/fixtures/wpt/interfaces/writing-assistance-apis.idl
@@ -0,0 +1,193 @@
+// GENERATED CONTENT - DO NOT EDIT
+// Content was automatically extracted by Reffy into webref
+// (https://github.com/w3c/webref)
+// Source: Writing Assistance APIs (https://webmachinelearning.github.io/writing-assistance-apis/)
+
+[Exposed=Window, SecureContext]
+interface Summarizer {
+ static Promise create(optional SummarizerCreateOptions options = {});
+ static Promise availability(optional SummarizerCreateCoreOptions options = {});
+
+ Promise summarize(
+ DOMString input,
+ optional SummarizerSummarizeOptions options = {}
+ );
+ ReadableStream summarizeStreaming(
+ DOMString input,
+ optional SummarizerSummarizeOptions options = {}
+ );
+
+ readonly attribute DOMString sharedContext;
+ readonly attribute SummarizerType type;
+ readonly attribute SummarizerFormat format;
+ readonly attribute SummarizerLength length;
+
+ readonly attribute FrozenArray? expectedInputLanguages;
+ readonly attribute FrozenArray? expectedContextLanguages;
+ readonly attribute DOMString? outputLanguage;
+
+ Promise measureInputUsage(
+ DOMString input,
+ optional SummarizerSummarizeOptions options = {}
+ );
+ readonly attribute unrestricted double inputQuota;
+};
+Summarizer includes DestroyableModel;
+
+dictionary SummarizerCreateCoreOptions {
+ SummarizerType type = "key-points";
+ SummarizerFormat format = "markdown";
+ SummarizerLength length = "short";
+
+ sequence expectedInputLanguages;
+ sequence expectedContextLanguages;
+ DOMString outputLanguage;
+};
+
+dictionary SummarizerCreateOptions : SummarizerCreateCoreOptions {
+ AbortSignal signal;
+ CreateMonitorCallback monitor;
+
+ DOMString sharedContext;
+};
+
+dictionary SummarizerSummarizeOptions {
+ AbortSignal signal;
+ DOMString context;
+};
+
+enum SummarizerType { "tl;dr", "teaser", "key-points", "headline" };
+enum SummarizerFormat { "plain-text", "markdown" };
+enum SummarizerLength { "short", "medium", "long" };
+
+[Exposed=Window, SecureContext]
+interface Writer {
+ static Promise create(optional WriterCreateOptions options = {});
+ static Promise availability(optional WriterCreateCoreOptions options = {});
+
+ Promise write(
+ DOMString input,
+ optional WriterWriteOptions options = {}
+ );
+ ReadableStream writeStreaming(
+ DOMString input,
+ optional WriterWriteOptions options = {}
+ );
+
+ readonly attribute DOMString sharedContext;
+ readonly attribute WriterTone tone;
+ readonly attribute WriterFormat format;
+ readonly attribute WriterLength length;
+
+ readonly attribute FrozenArray? expectedInputLanguages;
+ readonly attribute FrozenArray? expectedContextLanguages;
+ readonly attribute DOMString? outputLanguage;
+
+ Promise measureInputUsage(
+ DOMString input,
+ optional WriterWriteOptions options = {}
+ );
+ readonly attribute unrestricted double inputQuota;
+};
+Writer includes DestroyableModel;
+
+dictionary WriterCreateCoreOptions {
+ WriterTone tone = "neutral";
+ WriterFormat format = "markdown";
+ WriterLength length = "short";
+
+ sequence expectedInputLanguages;
+ sequence expectedContextLanguages;
+ DOMString outputLanguage;
+};
+
+dictionary WriterCreateOptions : WriterCreateCoreOptions {
+ AbortSignal signal;
+ CreateMonitorCallback monitor;
+
+ DOMString sharedContext;
+};
+
+dictionary WriterWriteOptions {
+ DOMString context;
+ AbortSignal signal;
+};
+
+enum WriterTone { "formal", "neutral", "casual" };
+enum WriterFormat { "plain-text", "markdown" };
+enum WriterLength { "short", "medium", "long" };
+
+[Exposed=Window, SecureContext]
+interface Rewriter {
+ static Promise create(optional RewriterCreateOptions options = {});
+ static Promise availability(optional RewriterCreateCoreOptions options = {});
+
+ Promise rewrite(
+ DOMString input,
+ optional RewriterRewriteOptions options = {}
+ );
+ ReadableStream rewriteStreaming(
+ DOMString input,
+ optional RewriterRewriteOptions options = {}
+ );
+
+ readonly attribute DOMString sharedContext;
+ readonly attribute RewriterTone tone;
+ readonly attribute RewriterFormat format;
+ readonly attribute RewriterLength length;
+
+ readonly attribute FrozenArray? expectedInputLanguages;
+ readonly attribute FrozenArray? expectedContextLanguages;
+ readonly attribute DOMString? outputLanguage;
+
+ Promise measureInputUsage(
+ DOMString input,
+ optional RewriterRewriteOptions options = {}
+ );
+ readonly attribute unrestricted double inputQuota;
+};
+Rewriter includes DestroyableModel;
+
+dictionary RewriterCreateCoreOptions {
+ RewriterTone tone = "as-is";
+ RewriterFormat format = "as-is";
+ RewriterLength length = "as-is";
+
+ sequence expectedInputLanguages;
+ sequence expectedContextLanguages;
+ DOMString outputLanguage;
+};
+
+dictionary RewriterCreateOptions : RewriterCreateCoreOptions {
+ AbortSignal signal;
+ CreateMonitorCallback monitor;
+
+ DOMString sharedContext;
+};
+
+dictionary RewriterRewriteOptions {
+ DOMString context;
+ AbortSignal signal;
+};
+
+enum RewriterTone { "as-is", "more-formal", "more-casual" };
+enum RewriterFormat { "as-is", "plain-text", "markdown" };
+enum RewriterLength { "as-is", "shorter", "longer" };
+
+[Exposed=Window, SecureContext]
+interface CreateMonitor : EventTarget {
+ attribute EventHandler ondownloadprogress;
+};
+
+callback CreateMonitorCallback = undefined (CreateMonitor monitor);
+
+enum Availability {
+ "unavailable",
+ "downloadable",
+ "downloading",
+ "available"
+};
+
+interface mixin DestroyableModel {
+ undefined destroy();
+};
diff --git a/test/fixtures/wpt/resources/chromium/webxr-test.js b/test/fixtures/wpt/resources/chromium/webxr-test.js
index 41340aa27e0..ce2503b1bbc 100644
--- a/test/fixtures/wpt/resources/chromium/webxr-test.js
+++ b/test/fixtures/wpt/resources/chromium/webxr-test.js
@@ -757,30 +757,34 @@ class MockRuntime {
const viewport_size = 20;
return [{
eye: vrMojom.XREye.kLeft,
- fieldOfView: {
- upDegrees: 48.316,
- downDegrees: 50.099,
- leftDegrees: 50.899,
- rightDegrees: 35.197
+ geometry: {
+ fieldOfView: {
+ upDegrees: 48.316,
+ downDegrees: 50.099,
+ leftDegrees: 50.899,
+ rightDegrees: 35.197
+ },
+ mojoFromView: this._getMojoFromViewerWithOffset(composeGFXTransform({
+ position: [-0.032, 0, 0],
+ orientation: [0, 0, 0, 1]
+ }))
},
- mojoFromView: this._getMojoFromViewerWithOffset(composeGFXTransform({
- position: [-0.032, 0, 0],
- orientation: [0, 0, 0, 1]
- })),
viewport: { x: 0, y: 0, width: viewport_size, height: viewport_size }
},
{
eye: vrMojom.XREye.kRight,
- fieldOfView: {
- upDegrees: 48.316,
- downDegrees: 50.099,
- leftDegrees: 50.899,
- rightDegrees: 35.197
+ geometry: {
+ fieldOfView: {
+ upDegrees: 48.316,
+ downDegrees: 50.099,
+ leftDegrees: 50.899,
+ rightDegrees: 35.197
+ },
+ mojoFromView: this._getMojoFromViewerWithOffset(composeGFXTransform({
+ position: [0.032, 0, 0],
+ orientation: [0, 0, 0, 1]
+ }))
},
- mojoFromView: this._getMojoFromViewerWithOffset(composeGFXTransform({
- position: [0.032, 0, 0],
- orientation: [0, 0, 0, 1]
- })),
viewport: { x: viewport_size, y: 0, width: viewport_size, height: viewport_size }
}];
}
@@ -835,13 +839,15 @@ class MockRuntime {
return {
eye: viewEye,
- fieldOfView: fov,
- mojoFromView: this._getMojoFromViewerWithOffset(composeGFXTransform(fakeXRViewInit.viewOffset)),
+ geometry: {
+ fieldOfView: fov,
+ mojoFromView: this._getMojoFromViewerWithOffset(composeGFXTransform(fakeXRViewInit.viewOffset))
+ },
viewport: {
x: xOffset,
- y: 0,
- width: fakeXRViewInit.resolution.width,
- height: fakeXRViewInit.resolution.height
+ y: 0,
+ width: fakeXRViewInit.resolution.width,
+ height: fakeXRViewInit.resolution.height
},
isFirstPersonObserver: fakeXRViewInit.isFirstPersonObserver ? true : false,
viewOffset: composeGFXTransform(fakeXRViewInit.viewOffset)
@@ -915,12 +921,12 @@ class MockRuntime {
let frame_views = this.primaryViews_;
for (let i = 0; i < this.primaryViews_.length; i++) {
- this.primaryViews_[i].mojoFromView =
+ this.primaryViews_[i].geometry.mojoFromView =
this._getMojoFromViewerWithOffset(this.primaryViews_[i].viewOffset);
}
if (this.enabledFeatures_.includes(xrSessionMojom.XRSessionFeature.SECONDARY_VIEWS)) {
for (let i = 0; i < this.secondaryViews_.length; i++) {
- this.secondaryViews_[i].mojoFromView =
+ this.secondaryViews_[i].geometry.mojoFromView =
this._getMojoFromViewerWithOffset(this.secondaryViews_[i].viewOffset);
}
@@ -956,7 +962,9 @@ class MockRuntime {
this._calculateAnchorInformation(frameData);
- this._calculateDepthInformation(frameData);
+ if (options.depthActive) {
+ this._calculateDepthInformation(frameData);
+ }
this._injectAdditionalFrameData(options, frameData);
diff --git a/test/fixtures/wpt/resources/test/conftest.py b/test/fixtures/wpt/resources/test/conftest.py
index 723087d3184..1301e7a9f77 100644
--- a/test/fixtures/wpt/resources/test/conftest.py
+++ b/test/fixtures/wpt/resources/test/conftest.py
@@ -263,4 +263,4 @@ def _run_functional_test(self):
@staticmethod
def _assert_sequence(nums):
if nums and len(nums) > 0:
- assert nums == list(range(1, nums[-1] + 1))
+ assert nums == list(range(nums[-1] + 1))
diff --git a/test/fixtures/wpt/resources/test/tests/functional/api-tests-1.html b/test/fixtures/wpt/resources/test/tests/functional/api-tests-1.html
index 9de875b0f12..6ec396c221b 100644
--- a/test/fixtures/wpt/resources/test/tests/functional/api-tests-1.html
+++ b/test/fixtures/wpt/resources/test/tests/functional/api-tests-1.html
@@ -132,7 +132,13 @@ Sample HTML5 API Tests
{
assert_less_than(10, 11, "10 is less than 11")
}
- test(basicAssertApproxEquals, "basic assert_less_than test");
+ test(basicAssertLessThan, "basic assert_less_than test");
+
+ function bigintAssertLessThan()
+ {
+ assert_less_than(10n, 11n, "10n is less than 11n")
+ }
+ test(bigintAssertLessThan, "bigint assert_less_than test");
function basicAssertGreaterThan()
{
@@ -140,12 +146,24 @@ Sample HTML5 API Tests
}
test(basicAssertGreaterThan, "assert_greater_than expected to fail");
+ function bigintAssertGreaterThan()
+ {
+ assert_greater_than(10n, 11n, "10n is not greater than 11n");
+ }
+ test(bigintAssertGreaterThan, "bigint assert_greater_than expected to fail");
+
function basicAssertGreaterThanEqual()
{
assert_greater_than_equal(10, 10, "10 is greater than or equal to 10")
}
test(basicAssertGreaterThanEqual, "basic assert_greater_than_equal test");
+ function bigintAssertGreaterThanEqual()
+ {
+ assert_greater_than_equal(10n, 10n, "10n is greater than or equal to 10n")
+ }
+ test(bigintAssertGreaterThanEqual, "bigint assert_greater_than_equal test");
+
function basicAssertLessThanEqual()
{
assert_greater_than_equal('10', 10, "'10' is not a number")
@@ -462,6 +480,12 @@ Sample HTML5 API Tests
"message": "assert_greater_than: 10 is not greater than 11 expected a number greater than 11 but got 10",
"properties": {}
},
+ {
+ "status_string": "FAIL",
+ "name": "bigint assert_greater_than expected to fail",
+ "message": "assert_greater_than: 10n is not greater than 11n expected a number greater than 11n but got 10n",
+ "properties": {}
+ },
{
"status_string": "FAIL",
"name": "assert_less_than_equal expected to fail",
@@ -516,12 +540,24 @@ Sample HTML5 API Tests
"message": null,
"properties": {}
},
+ {
+ "status_string": "PASS",
+ "name": "bigint assert_greater_than_equal test",
+ "message": null,
+ "properties": {}
+ },
{
"status_string": "PASS",
"name": "basic assert_less_than test",
"message": null,
"properties": {}
},
+ {
+ "status_string": "PASS",
+ "name": "bigint assert_less_than test",
+ "message": null,
+ "properties": {}
+ },
{
"status_string": "PASS",
"name": "body element fires the onload event set from the attribute",
@@ -745,13 +781,22 @@ Sample HTML5 API Tests
"status": 0
},
{
- "assert_name": "assert_approx_equals",
+ "assert_name": "assert_less_than",
"test": "basic assert_less_than test",
"args": [
"10",
"11",
- "1",
- "\"10 is approximately (+/- 1) 11\""
+ "\"10 is less than 11\""
+ ],
+ "status": 0
+ },
+ {
+ "assert_name": "assert_less_than",
+ "test": "bigint assert_less_than test",
+ "args": [
+ "10n",
+ "11n",
+ "\"10n is less than 11n\""
],
"status": 0
},
@@ -765,6 +810,16 @@ Sample HTML5 API Tests
],
"status": 1
},
+ {
+ "assert_name": "assert_greater_than",
+ "test": "bigint assert_greater_than expected to fail",
+ "args": [
+ "10n",
+ "11n",
+ "\"10n is not greater than 11n\""
+ ],
+ "status": 1
+ },
{
"assert_name": "assert_greater_than_equal",
"test": "basic assert_greater_than_equal test",
@@ -775,6 +830,16 @@ Sample HTML5 API Tests
],
"status": 0
},
+ {
+ "assert_name": "assert_greater_than_equal",
+ "test": "bigint assert_greater_than_equal test",
+ "args": [
+ "10n",
+ "10n",
+ "\"10n is greater than or equal to 10n\""
+ ],
+ "status": 0
+ },
{
"assert_name": "assert_greater_than_equal",
"test": "assert_less_than_equal expected to fail",
diff --git a/test/fixtures/wpt/resources/testdriver.js b/test/fixtures/wpt/resources/testdriver.js
index f127e2b2c8d..992b9e3ab2c 100644
--- a/test/fixtures/wpt/resources/testdriver.js
+++ b/test/fixtures/wpt/resources/testdriver.js
@@ -254,12 +254,63 @@
}
},
/**
- * `log `_ module.
+ * `emulation `_ module.
+ */
+ emulation: {
+ /**
+ * Overrides the geolocation coordinates for the specified
+ * browsing contexts.
+ * Matches the `emulation.setGeolocationOverride
+ * `_
+ * WebDriver BiDi command.
+ *
+ * @example
+ * await test_driver.bidi.emulation.set_geolocation_override({
+ * coordinates: {
+ * latitude: 52.51,
+ * longitude: 13.39,
+ * accuracy: 0.5,
+ * altitude: 34,
+ * altitudeAccuracy: 0.75,
+ * heading: 180,
+ * speed: 2.77
+ * }
+ * });
+ *
+ * @param {object} params - Parameters for the command.
+ * @param {null|object} params.coordinates - The optional
+ * geolocation coordinates to set. Matches the
+ * `emulation.GeolocationCoordinates `_
+ * value. If null or omitted and the `params.error` is set, the
+ * emulation will be removed. Mutually exclusive with
+ * `params.error`.
+ * @param {object} params.error - The optional
+ * geolocation error to emulate. Matches the
+ * `emulation.GeolocationPositionError `_
+ * value. Mutually exclusive with `params.coordinates`.
+ * @param {null|Array.<(Context)>} [params.contexts] The
+ * optional contexts parameter specifies which browsing contexts
+ * to set the geolocation override on. It should be either an
+ * array of Context objects (window or browsing context id), or
+ * null. If null or omitted, the override will be set on the
+ * current browsing context.
+ * @returns {Promise} Resolves when the geolocation
+ * override is successfully set.
+ */
+ set_geolocation_override: function (params) {
+ // Ensure the bidi feature is enabled before calling the internal method
+ assertBidiIsEnabled();
+ return window.test_driver_internal.bidi.emulation.set_geolocation_override(
+ params);
+ },
+ },
+ /**
+ * `log `_ module.
*/
log: {
entry_added: {
/**
- * @typedef {object} LogEntryAdded `log.entryAdded `_ event.
+ * @typedef {object} LogEntryAdded `log.entryAdded `_ event.
*/
/**
@@ -1576,6 +1627,12 @@
}
}
},
+ emulation: {
+ set_geolocation_override: function (params) {
+ throw new Error(
+ "bidi.emulation.set_geolocation_override is not implemented by testdriver-vendor.js");
+ }
+ },
log: {
entry_added: {
async subscribe() {
diff --git a/test/fixtures/wpt/resources/testharness.js b/test/fixtures/wpt/resources/testharness.js
index 8ef0574f1f0..6ccede34483 100644
--- a/test/fixtures/wpt/resources/testharness.js
+++ b/test/fixtures/wpt/resources/testharness.js
@@ -88,7 +88,7 @@
status: harness_status.structured_clone(),
asserts: asserts.map(assert => assert.structured_clone())});
}]
- }
+ };
on_event(window, 'load', function() {
setTimeout(() => {
@@ -203,7 +203,7 @@
}
});
this.message_events = new_events;
- }
+ };
WindowTestEnvironment.prototype.next_default_test_name = function() {
var suffix = this.name_counter > 0 ? " " + this.name_counter : "";
@@ -225,8 +225,8 @@
WindowTestEnvironment.prototype.test_timeout = function() {
var metas = document.getElementsByTagName("meta");
for (var i = 0; i < metas.length; i++) {
- if (metas[i].name == "timeout") {
- if (metas[i].content == "long") {
+ if (metas[i].name === "timeout") {
+ if (metas[i].content === "long") {
return settings.harness_timeout.long;
}
break;
@@ -487,7 +487,7 @@
this.all_loaded = false;
this.on_loaded_callback = null;
Promise.resolve().then(function() {
- this.all_loaded = true
+ this.all_loaded = true;
if (this.on_loaded_callback) {
this.on_loaded_callback();
}
@@ -563,7 +563,7 @@
// The worker object may be from another execution context,
// so do not use instanceof here.
return 'ServiceWorker' in global_scope &&
- Object.prototype.toString.call(worker) == '[object ServiceWorker]';
+ Object.prototype.toString.call(worker) === '[object ServiceWorker]';
}
var seen_func_name = Object.create(null);
@@ -810,7 +810,7 @@
return bring_promise_to_current_realm(promise)
.then(test.unreached_func("Should have rejected: " + description))
.catch(function(e) {
- assert_throws_js_impl(constructor, function() { throw e },
+ assert_throws_js_impl(constructor, function() { throw e; },
description, "promise_rejects_js");
});
}
@@ -862,7 +862,7 @@
return bring_promise_to_current_realm(promise)
.then(test.unreached_func("Should have rejected: " + description))
.catch(function(e) {
- assert_throws_dom_impl(type, function() { throw e }, description,
+ assert_throws_dom_impl(type, function() { throw e; }, description,
"promise_rejects_dom", constructor);
});
}
@@ -881,7 +881,7 @@
return bring_promise_to_current_realm(promise)
.then(test.unreached_func("Should have rejected: " + description))
.catch(function(e) {
- assert_throws_exactly_impl(exception, function() { throw e },
+ assert_throws_exactly_impl(exception, function() { throw e; },
description, "promise_rejects_exactly");
});
}
@@ -907,7 +907,7 @@
*/
function EventWatcher(test, watchedNode, eventTypes, timeoutPromise)
{
- if (typeof eventTypes == 'string') {
+ if (typeof eventTypes === 'string') {
eventTypes = [eventTypes];
}
@@ -972,7 +972,7 @@
if (waitingFor) {
return Promise.reject('Already waiting for an event or events');
}
- if (typeof types == 'string') {
+ if (typeof types === 'string') {
types = [types];
}
if (options && options.record && options.record === 'all') {
@@ -987,7 +987,7 @@
// This should always fail, otherwise we should have
// resolved the promise.
- assert_true(waitingFor.types.length == 0,
+ assert_true(waitingFor.types.length === 0,
'Timed out waiting for ' + waitingFor.types.join(', '));
var result = recordedEvents;
recordedEvents = null;
@@ -1400,6 +1400,8 @@
return "-0";
}
return String(val);
+ case "bigint":
+ return String(val) + 'n';
case "object":
if (val === null) {
return "null";
@@ -1423,11 +1425,11 @@
case Node.COMMENT_NODE:
return "Comment node ";
case Node.DOCUMENT_NODE:
- return "Document node with " + val.childNodes.length + (val.childNodes.length == 1 ? " child" : " children");
+ return "Document node with " + val.childNodes.length + (val.childNodes.length === 1 ? " child" : " children");
case Node.DOCUMENT_TYPE_NODE:
return "DocumentType node";
case Node.DOCUMENT_FRAGMENT_NODE:
- return "DocumentFragment node with " + val.childNodes.length + (val.childNodes.length == 1 ? " child" : " children");
+ return "DocumentFragment node with " + val.childNodes.length + (val.childNodes.length === 1 ? " child" : " children");
default:
return "Node object of unknown type";
}
@@ -1771,20 +1773,25 @@
/**
* Assert that ``actual`` is a number less than ``expected``.
*
- * @param {number} actual - Test value.
- * @param {number} expected - Number that ``actual`` must be less than.
+ * @param {number|bigint} actual - Test value.
+ * @param {number|bigint} expected - Value that ``actual`` must be less than.
* @param {string} [description] - Description of the condition being tested.
*/
function assert_less_than(actual, expected, description)
{
/*
- * Test if a primitive number is less than another
+ * Test if a primitive number (or bigint) is less than another
*/
- assert(typeof actual === "number",
+ assert(typeof actual === "number" || typeof actual === "bigint",
"assert_less_than", description,
"expected a number but got a ${type_actual}",
{type_actual:typeof actual});
+ assert(typeof actual === typeof expected,
+ "assert_less_than", description,
+ "expected a ${type_expected} but got a ${type_actual}",
+ {type_expected:typeof expected, type_actual:typeof actual});
+
assert(actual < expected,
"assert_less_than", description,
"expected a number less than ${expected} but got ${actual}",
@@ -1795,20 +1802,25 @@
/**
* Assert that ``actual`` is a number greater than ``expected``.
*
- * @param {number} actual - Test value.
- * @param {number} expected - Number that ``actual`` must be greater than.
+ * @param {number|bigint} actual - Test value.
+ * @param {number|bigint} expected - Value that ``actual`` must be greater than.
* @param {string} [description] - Description of the condition being tested.
*/
function assert_greater_than(actual, expected, description)
{
/*
- * Test if a primitive number is greater than another
+ * Test if a primitive number (or bigint) is greater than another
*/
- assert(typeof actual === "number",
+ assert(typeof actual === "number" || typeof actual === "bigint",
"assert_greater_than", description,
"expected a number but got a ${type_actual}",
{type_actual:typeof actual});
+ assert(typeof actual === typeof expected,
+ "assert_greater_than", description,
+ "expected a ${type_expected} but got a ${type_actual}",
+ {type_expected:typeof expected, type_actual:typeof actual});
+
assert(actual > expected,
"assert_greater_than", description,
"expected a number greater than ${expected} but got ${actual}",
@@ -1820,21 +1832,31 @@
* Assert that ``actual`` is a number greater than ``lower`` and less
* than ``upper`` but not equal to either.
*
- * @param {number} actual - Test value.
- * @param {number} lower - Number that ``actual`` must be greater than.
- * @param {number} upper - Number that ``actual`` must be less than.
+ * @param {number|bigint} actual - Test value.
+ * @param {number|bigint} lower - Value that ``actual`` must be greater than.
+ * @param {number|bigint} upper - Value that ``actual`` must be less than.
* @param {string} [description] - Description of the condition being tested.
*/
function assert_between_exclusive(actual, lower, upper, description)
{
/*
- * Test if a primitive number is between two others
+ * Test if a primitive number (or bigint) is between two others
*/
- assert(typeof actual === "number",
+ assert(typeof lower === typeof upper,
+ "assert_between_exclusive", description,
+ "expected lower (${type_lower}) and upper (${type_upper}) types to match (test error)",
+ {type_lower:typeof lower, type_upper:typeof upper});
+
+ assert(typeof actual === "number" || typeof actual === "bigint",
"assert_between_exclusive", description,
"expected a number but got a ${type_actual}",
{type_actual:typeof actual});
+ assert(typeof actual === typeof lower,
+ "assert_between_exclusive", description,
+ "expected a ${type_lower} but got a ${type_actual}",
+ {type_lower:typeof lower, type_actual:typeof actual});
+
assert(actual > lower && actual < upper,
"assert_between_exclusive", description,
"expected a number greater than ${lower} " +
@@ -1846,21 +1868,26 @@
/**
* Assert that ``actual`` is a number less than or equal to ``expected``.
*
- * @param {number} actual - Test value.
- * @param {number} expected - Number that ``actual`` must be less
+ * @param {number|bigint} actual - Test value.
+ * @param {number|bigint} expected - Value that ``actual`` must be less
* than or equal to.
* @param {string} [description] - Description of the condition being tested.
*/
function assert_less_than_equal(actual, expected, description)
{
/*
- * Test if a primitive number is less than or equal to another
+ * Test if a primitive number (or bigint) is less than or equal to another
*/
- assert(typeof actual === "number",
+ assert(typeof actual === "number" || typeof actual === "bigint",
"assert_less_than_equal", description,
"expected a number but got a ${type_actual}",
{type_actual:typeof actual});
+ assert(typeof actual === typeof expected,
+ "assert_less_than_equal", description,
+ "expected a ${type_expected} but got a ${type_actual}",
+ {type_expected:typeof expected, type_actual:typeof actual});
+
assert(actual <= expected,
"assert_less_than_equal", description,
"expected a number less than or equal to ${expected} but got ${actual}",
@@ -1871,21 +1898,26 @@
/**
* Assert that ``actual`` is a number greater than or equal to ``expected``.
*
- * @param {number} actual - Test value.
- * @param {number} expected - Number that ``actual`` must be greater
+ * @param {number|bigint} actual - Test value.
+ * @param {number|bigint} expected - Value that ``actual`` must be greater
* than or equal to.
* @param {string} [description] - Description of the condition being tested.
*/
function assert_greater_than_equal(actual, expected, description)
{
/*
- * Test if a primitive number is greater than or equal to another
+ * Test if a primitive number (or bigint) is greater than or equal to another
*/
- assert(typeof actual === "number",
+ assert(typeof actual === "number" || typeof actual === "bigint",
"assert_greater_than_equal", description,
"expected a number but got a ${type_actual}",
{type_actual:typeof actual});
+ assert(typeof actual === typeof expected,
+ "assert_greater_than_equal", description,
+ "expected a ${type_expected} but got a ${type_actual}",
+ {type_expected:typeof expected, type_actual:typeof actual});
+
assert(actual >= expected,
"assert_greater_than_equal", description,
"expected a number greater than or equal to ${expected} but got ${actual}",
@@ -1897,21 +1929,31 @@
* Assert that ``actual`` is a number greater than or equal to ``lower`` and less
* than or equal to ``upper``.
*
- * @param {number} actual - Test value.
- * @param {number} lower - Number that ``actual`` must be greater than or equal to.
- * @param {number} upper - Number that ``actual`` must be less than or equal to.
+ * @param {number|bigint} actual - Test value.
+ * @param {number|bigint} lower - Value that ``actual`` must be greater than or equal to.
+ * @param {number|bigint} upper - Value that ``actual`` must be less than or equal to.
* @param {string} [description] - Description of the condition being tested.
*/
function assert_between_inclusive(actual, lower, upper, description)
{
/*
- * Test if a primitive number is between to two others or equal to either of them
+ * Test if a primitive number (or bigint) is between to two others or equal to either of them
*/
- assert(typeof actual === "number",
+ assert(typeof lower === typeof upper,
+ "assert_between_inclusive", description,
+ "expected lower (${type_lower}) and upper (${type_upper}) types to match (test error)",
+ {type_lower:typeof lower, type_upper:typeof upper});
+
+ assert(typeof actual === "number" || typeof actual === "bigint",
"assert_between_inclusive", description,
"expected a number but got a ${type_actual}",
{type_actual:typeof actual});
+ assert(typeof actual === typeof lower,
+ "assert_between_inclusive", description,
+ "expected a ${type_lower} but got a ${type_actual}",
+ {type_lower:typeof lower, type_actual:typeof actual});
+
assert(actual >= lower && actual <= upper,
"assert_between_inclusive", description,
"expected a number greater than or equal to ${lower} " +
@@ -2121,7 +2163,7 @@
{func:func});
// Basic sanity-check on the passed-in constructor
- assert(typeof constructor == "function",
+ assert(typeof constructor === "function",
assertion_type, description,
"${constructor} is not a constructor",
{constructor:constructor});
@@ -2196,7 +2238,7 @@
assert(maybeDescription === undefined,
"Too many args passed to no-constructor version of assert_throws_dom, or accidentally explicitly passed undefined");
}
- assert_throws_dom_impl(type, func, description, "assert_throws_dom", constructor)
+ assert_throws_dom_impl(type, func, description, "assert_throws_dom", constructor);
}
expose_assert(assert_throws_dom, "assert_throws_dom");
@@ -2229,8 +2271,8 @@
{func:func});
// Sanity-check our type
- assert(typeof type == "number" ||
- typeof type == "string",
+ assert(typeof type === "number" ||
+ typeof type === "string",
assertion_type, description,
"${type} is not a number or string",
{type:type});
@@ -2459,7 +2501,7 @@
function assert_implements(condition, description) {
assert(!!condition, "assert_implements", description);
}
- expose_assert(assert_implements, "assert_implements")
+ expose_assert(assert_implements, "assert_implements");
/**
* Assert that an optional feature is implemented, based on a 'truthy' condition.
@@ -2573,11 +2615,11 @@
2: "Timeout",
3: "Not Run",
4: "Optional Feature Unsupported",
- }
+ };
Test.prototype.format_status = function() {
return this.status_formats[this.status];
- }
+ };
Test.prototype.structured_clone = function()
{
@@ -2887,7 +2929,7 @@
return new Promise(resolve => {
this.step_wait_func(cond, resolve, description, timeout, interval);
});
- }
+ };
/*
* Private method for registering cleanup functions. `testharness.js`
@@ -3120,7 +3162,7 @@
throw new Error("AbortController is not supported in this browser");
}
return this._abortController.signal;
- }
+ };
/**
* A RemoteTest object mirrors a Test object on a remote worker. The
@@ -3196,11 +3238,11 @@
function(callback) {
callback();
});
- }
+ };
RemoteTest.prototype.format_status = function() {
return Test.prototype.status_formats[this.status];
- }
+ };
/*
* A RemoteContext listens for test events from a remote test context, such
@@ -3472,7 +3514,7 @@
this.all_done_callbacks = [];
this.hide_test_state = false;
- this.pending_remotes = [];
+ this.remotes = [];
this.current_test = null;
this.asserts_run = [];
@@ -3514,26 +3556,26 @@
for (var p in properties) {
if (properties.hasOwnProperty(p)) {
var value = properties[p];
- if (p == "allow_uncaught_exception") {
+ if (p === "allow_uncaught_exception") {
this.allow_uncaught_exception = value;
- } else if (p == "explicit_done" && value) {
+ } else if (p === "explicit_done" && value) {
this.wait_for_finish = true;
- } else if (p == "explicit_timeout" && value) {
+ } else if (p === "explicit_timeout" && value) {
this.timeout_length = null;
if (this.timeout_id)
{
clearTimeout(this.timeout_id);
}
- } else if (p == "single_test" && value) {
+ } else if (p === "single_test" && value) {
this.set_file_is_test();
- } else if (p == "timeout_multiplier") {
+ } else if (p === "timeout_multiplier") {
this.timeout_multiplier = value;
if (this.timeout_length) {
this.timeout_length *= this.timeout_multiplier;
}
- } else if (p == "hide_test_state") {
+ } else if (p === "hide_test_state") {
this.hide_test_state = value;
- } else if (p == "output") {
+ } else if (p === "output") {
this.output = value;
} else if (p === "debug") {
settings.debug = value;
@@ -3626,11 +3668,14 @@
Tests.prototype.push = function(test)
{
+ if (this.phase === this.phases.COMPLETE) {
+ return;
+ }
if (this.phase < this.phases.HAVE_TESTS) {
this.start();
}
this.num_pending++;
- test.index = this.tests.push(test);
+ test.index = this.tests.push(test) - 1;
this.notify_test_state(test);
};
@@ -3643,11 +3688,11 @@
};
Tests.prototype.all_done = function() {
- return (this.tests.length > 0 || this.pending_remotes.length > 0) &&
+ return (this.tests.length > 0 || this.remotes.length > 0) &&
test_environment.all_loaded &&
(this.num_pending === 0 || this.is_aborted) && !this.wait_for_finish &&
!this.processing_callbacks &&
- !this.pending_remotes.some(function(w) { return w.running; });
+ !this.remotes.some(function(w) { return w.running; });
};
Tests.prototype.start = function() {
@@ -3716,7 +3761,8 @@
function(test, testDone)
{
if (test.phase === test.phases.INITIAL) {
- test.phase = test.phases.COMPLETE;
+ test.phase = test.phases.HAS_RESULT;
+ test.done();
testDone();
} else {
add_test_done_callback(test, testDone);
@@ -3727,14 +3773,14 @@
};
Tests.prototype.set_assert = function(assert_name, args) {
- this.asserts_run.push(new AssertRecord(this.current_test, assert_name, args))
- }
+ this.asserts_run.push(new AssertRecord(this.current_test, assert_name, args));
+ };
Tests.prototype.set_assert_status = function(index, status, stack) {
let assert_record = this.asserts_run[index];
assert_record.status = status;
assert_record.stack = stack;
- }
+ };
/**
* Update the harness status to reflect an unrecoverable harness error that
@@ -3876,7 +3922,7 @@
}
var remoteContext = this.create_remote_worker(worker);
- this.pending_remotes.push(remoteContext);
+ this.remotes.push(remoteContext);
return remoteContext.done;
};
@@ -3899,7 +3945,7 @@
}
var remoteContext = this.create_remote_window(remote);
- this.pending_remotes.push(remoteContext);
+ this.remotes.push(remoteContext);
return remoteContext.done;
};
@@ -4111,8 +4157,8 @@
} else {
var root = output_document.documentElement;
var is_html = (root &&
- root.namespaceURI == "http://www.w3.org/1999/xhtml" &&
- root.localName == "html");
+ root.namespaceURI === "http://www.w3.org/1999/xhtml" &&
+ root.localName === "html");
var is_svg = (output_document.defaultView &&
"SVGSVGElement" in output_document.defaultView &&
root instanceof output_document.defaultView.SVGSVGElement);
@@ -4557,7 +4603,7 @@
*/
function AssertionError(message)
{
- if (typeof message == "string") {
+ if (typeof message === "string") {
message = sanitize_unpaired_surrogates(message);
}
this.message = message;
@@ -4603,7 +4649,7 @@
}
return lines.slice(i).join("\n");
- }
+ };
function OptionalFeatureUnsupportedError(message)
{