From 05a536e1db4a1865100c01f14c770c175c96e853 Mon Sep 17 00:00:00 2001 From: Filip Skokan Date: Mon, 13 Nov 2023 13:47:46 +0100 Subject: [PATCH 1/3] stream: add Symbol.toStringTag to Compression Streams --- lib/internal/webstreams/compression.js | 11 +++++++++++ test/parallel/test-whatwg-webstreams-compression.js | 3 +++ 2 files changed, 14 insertions(+) diff --git a/lib/internal/webstreams/compression.js b/lib/internal/webstreams/compression.js index 32f3f9b4605032..ac10d093dcefcc 100644 --- a/lib/internal/webstreams/compression.js +++ b/lib/internal/webstreams/compression.js @@ -2,6 +2,7 @@ const { ObjectDefineProperties, + SymbolToStringTag, } = primordials; const { @@ -137,11 +138,21 @@ class DecompressionStream { ObjectDefineProperties(CompressionStream.prototype, { readable: kEnumerableProperty, writable: kEnumerableProperty, + [SymbolToStringTag]: { + __proto__: null, + configurable: true, + value: 'CompressionStream', + }, }); ObjectDefineProperties(DecompressionStream.prototype, { readable: kEnumerableProperty, writable: kEnumerableProperty, + [SymbolToStringTag]: { + __proto__: null, + configurable: true, + value: 'DecompressionStream', + }, }); module.exports = { diff --git a/test/parallel/test-whatwg-webstreams-compression.js b/test/parallel/test-whatwg-webstreams-compression.js index fb20801543bff6..c144a0a2e3d43d 100644 --- a/test/parallel/test-whatwg-webstreams-compression.js +++ b/test/parallel/test-whatwg-webstreams-compression.js @@ -15,6 +15,9 @@ async function test(format) { const gzip = new CompressionStream(format); const gunzip = new DecompressionStream(format); + assert.strictEqual(gzip[Symbol.toStringTag], 'CompressionStream'); + assert.strictEqual(gunzip[Symbol.toStringTag], 'DecompressionStream'); + gzip.readable.pipeTo(gunzip.writable).then(common.mustCall()); const reader = gunzip.readable.getReader(); From c79e7dda54459e1cf65a2c7425d7965b6a6ff5ff Mon Sep 17 00:00:00 2001 From: Filip Skokan Date: Mon, 13 Nov 2023 14:30:50 +0100 Subject: [PATCH 2/3] stream: yield expected Error class on zlib errors --- lib/internal/webstreams/adapters.js | 50 +++++++++++++++++++++++------ test/wpt/status/compression.json | 15 +-------- 2 files changed, 42 insertions(+), 23 deletions(-) diff --git a/lib/internal/webstreams/adapters.js b/lib/internal/webstreams/adapters.js index 878fd0a0d4d76b..cffa549eafd683 100644 --- a/lib/internal/webstreams/adapters.js +++ b/lib/internal/webstreams/adapters.js @@ -1,13 +1,19 @@ 'use strict'; const { + ArrayPrototypeFilter, + ArrayPrototypeMap, + Boolean, + ObjectEntries, PromisePrototypeThen, PromiseResolve, SafePromiseAll, SafePromisePrototypeFinally, + SafeSet, TypedArrayPrototypeGetBuffer, - TypedArrayPrototypeGetByteOffset, TypedArrayPrototypeGetByteLength, + TypedArrayPrototypeGetByteOffset, + TypeError, Uint8Array, } = primordials; @@ -82,6 +88,38 @@ const { UV_EOF } = internalBinding('uv'); const encoder = new TextEncoder(); +// Collect all negative (error) ZLIB codes and Z_NEED_DICT +const ZLIB_FAILURES = new SafeSet([ + ...ArrayPrototypeFilter( + ArrayPrototypeMap( + ObjectEntries(internalBinding('constants').zlib), + ({ 0: code, 1: value }) => (value < 0 ? code : null), + ), + Boolean, + ), + 'Z_NEED_DICT', +]); + +/** + * @param {Error|null} cause + * @returns {Error|null} + */ +function handleKnownInternalErrors(cause) { + switch (true) { + case cause?.code === 'ERR_STREAM_PREMATURE_CLOSE': { + return new AbortError(undefined, { cause }); + } + case ZLIB_FAILURES.has(cause?.code): { + // eslint-disable-next-line no-restricted-syntax + const error = new TypeError(undefined, { cause }); + error.code = cause.code; + return error; + } + default: + return cause; + } +} + /** * @typedef {import('../../stream').Writable} Writable * @typedef {import('../../stream').Readable} Readable @@ -137,10 +175,7 @@ function newWritableStreamFromStreamWritable(streamWritable) { } const cleanup = finished(streamWritable, (error) => { - if (error?.code === 'ERR_STREAM_PREMATURE_CLOSE') { - const err = new AbortError(undefined, { cause: error }); - error = err; - } + error = handleKnownInternalErrors(error); cleanup(); // This is a protection against non-standard, legacy streams @@ -440,10 +475,7 @@ function newReadableStreamFromStreamReadable(streamReadable, options = kEmptyObj streamReadable.pause(); const cleanup = finished(streamReadable, (error) => { - if (error?.code === 'ERR_STREAM_PREMATURE_CLOSE') { - const err = new AbortError(undefined, { cause: error }); - error = err; - } + error = handleKnownInternalErrors(error); cleanup(); // This is a protection against non-standard, legacy streams diff --git a/test/wpt/status/compression.json b/test/wpt/status/compression.json index cf979345ea87cb..31a5a78b69ddc0 100644 --- a/test/wpt/status/compression.json +++ b/test/wpt/status/compression.json @@ -14,21 +14,8 @@ "decompression-corrupt-input.tentative.any.js": { "fail": { "expected": [ - "truncating the input for 'deflate' should give an error", "trailing junk for 'deflate' should give an error", - "format 'deflate' field CMF should be error for 0", - "format 'deflate' field FLG should be error for 157", - "format 'deflate' field DATA should be error for 5", - "format 'deflate' field ADLER should be error for 255", - "truncating the input for 'gzip' should give an error", - "trailing junk for 'gzip' should give an error", - "format 'gzip' field ID should be error for 255", - "format 'gzip' field CM should be error for 0", - "format 'gzip' field FLG should be error for 2", - "format 'gzip' field DATA should be error for 3", - "format 'gzip' field CRC should be error for 0", - "format 'gzip' field ISIZE should be error for 1", - "the deflate input compressed with dictionary should give an error" + "trailing junk for 'gzip' should give an error" ] } }, From 74d8ee5f5d189883290d0a73d1bbb5b30a974a8d Mon Sep 17 00:00:00 2001 From: Filip Skokan Date: Mon, 13 Nov 2023 15:32:53 +0100 Subject: [PATCH 3/3] test: update WPT files for WebIDL tests --- test/fixtures/wpt/README.md | 4 +- test/fixtures/wpt/interfaces/compression.idl | 22 + test/fixtures/wpt/interfaces/dom.idl | 3 +- test/fixtures/wpt/interfaces/encoding.idl | 2 +- test/fixtures/wpt/interfaces/hr-time.idl | 2 +- test/fixtures/wpt/interfaces/html.idl | 264 ++++++++-- .../wpt/interfaces/performance-timeline.idl | 8 +- .../wpt/interfaces/resource-timing.idl | 12 +- test/fixtures/wpt/interfaces/streams.idl | 2 + test/fixtures/wpt/interfaces/url.idl | 8 +- test/fixtures/wpt/interfaces/user-timing.idl | 4 +- test/fixtures/wpt/interfaces/webidl.idl | 5 +- .../declarative-shadow-dom-polyfill.js | 3 +- test/fixtures/wpt/resources/idlharness.js | 7 +- test/fixtures/wpt/resources/testdriver.js | 481 ++++++++++++++++-- test/fixtures/wpt/resources/testharness.js | 36 +- test/fixtures/wpt/versions.json | 4 +- test/wpt/status/compression.json | 3 - test/wpt/status/resource-timing.json | 17 + test/wpt/status/streams.json | 3 +- test/wpt/test-compression.js | 2 + 21 files changed, 762 insertions(+), 130 deletions(-) create mode 100644 test/fixtures/wpt/interfaces/compression.idl diff --git a/test/fixtures/wpt/README.md b/test/fixtures/wpt/README.md index 1c7121feb30c9e..26dd520f8f3eed 100644 --- a/test/fixtures/wpt/README.md +++ b/test/fixtures/wpt/README.md @@ -23,10 +23,10 @@ Last update: - html/webappapis/microtask-queuing: https://github.com/web-platform-tests/wpt/tree/2c5c3c4c27/html/webappapis/microtask-queuing - html/webappapis/structured-clone: https://github.com/web-platform-tests/wpt/tree/47d3fb280c/html/webappapis/structured-clone - html/webappapis/timers: https://github.com/web-platform-tests/wpt/tree/5873f2d8f1/html/webappapis/timers -- interfaces: https://github.com/web-platform-tests/wpt/tree/df731dab88/interfaces +- interfaces: https://github.com/web-platform-tests/wpt/tree/727995f043/interfaces - performance-timeline: https://github.com/web-platform-tests/wpt/tree/17ebc3aea0/performance-timeline - resource-timing: https://github.com/web-platform-tests/wpt/tree/22d38586d0/resource-timing -- resources: https://github.com/web-platform-tests/wpt/tree/919874f84f/resources +- resources: https://github.com/web-platform-tests/wpt/tree/1e140d63ec/resources - streams: https://github.com/web-platform-tests/wpt/tree/517e945bbf/streams - url: https://github.com/web-platform-tests/wpt/tree/c2d7e70b52/url - user-timing: https://github.com/web-platform-tests/wpt/tree/5ae85bf826/user-timing diff --git a/test/fixtures/wpt/interfaces/compression.idl b/test/fixtures/wpt/interfaces/compression.idl new file mode 100644 index 00000000000000..7525d7c9847b74 --- /dev/null +++ b/test/fixtures/wpt/interfaces/compression.idl @@ -0,0 +1,22 @@ +// GENERATED CONTENT - DO NOT EDIT +// Content was automatically extracted by Reffy into webref +// (https://github.com/w3c/webref) +// Source: Compression Streams (https://wicg.github.io/compression/) + +enum CompressionFormat { + "deflate", + "deflate-raw", + "gzip", +}; + +[Exposed=*] +interface CompressionStream { + constructor(CompressionFormat format); +}; +CompressionStream includes GenericTransformStream; + +[Exposed=*] +interface DecompressionStream { + constructor(CompressionFormat format); +}; +DecompressionStream includes GenericTransformStream; diff --git a/test/fixtures/wpt/interfaces/dom.idl b/test/fixtures/wpt/interfaces/dom.idl index 96acfc6a717fb2..c2def872fa23eb 100644 --- a/test/fixtures/wpt/interfaces/dom.idl +++ b/test/fixtures/wpt/interfaces/dom.idl @@ -95,6 +95,7 @@ interface AbortController { interface AbortSignal : EventTarget { [NewObject] static AbortSignal abort(optional any reason); [Exposed=(Window,Worker), NewObject] static AbortSignal timeout([EnforceRange] unsigned long long milliseconds); + [NewObject] static AbortSignal _any(sequence signals); readonly attribute boolean aborted; readonly attribute any reason; @@ -618,7 +619,7 @@ callback interface XPathNSResolver { interface mixin XPathEvaluatorBase { [NewObject] XPathExpression createExpression(DOMString expression, optional XPathNSResolver? resolver = null); - XPathNSResolver createNSResolver(Node nodeResolver); + Node createNSResolver(Node nodeResolver); // legacy // XPathResult.ANY_TYPE = 0 XPathResult evaluate(DOMString expression, Node contextNode, optional XPathNSResolver? resolver = null, optional unsigned short type = 0, optional XPathResult? result = null); }; diff --git a/test/fixtures/wpt/interfaces/encoding.idl b/test/fixtures/wpt/interfaces/encoding.idl index a8cbe4431a2dc7..a9499f62378dd9 100644 --- a/test/fixtures/wpt/interfaces/encoding.idl +++ b/test/fixtures/wpt/interfaces/encoding.idl @@ -22,7 +22,7 @@ dictionary TextDecodeOptions { interface TextDecoder { constructor(optional DOMString label = "utf-8", optional TextDecoderOptions options = {}); - USVString decode(optional [AllowShared] BufferSource input, optional TextDecodeOptions options = {}); + USVString decode(optional AllowSharedBufferSource input, optional TextDecodeOptions options = {}); }; TextDecoder includes TextDecoderCommon; diff --git a/test/fixtures/wpt/interfaces/hr-time.idl b/test/fixtures/wpt/interfaces/hr-time.idl index 13aa109b6c764c..835ee8a65c84c0 100644 --- a/test/fixtures/wpt/interfaces/hr-time.idl +++ b/test/fixtures/wpt/interfaces/hr-time.idl @@ -7,7 +7,7 @@ typedef double DOMHighResTimeStamp; typedef unsigned long long EpochTimeStamp; -[Exposed=*] +[Exposed=(Window,Worker)] interface Performance : EventTarget { DOMHighResTimeStamp now(); readonly attribute DOMHighResTimeStamp timeOrigin; diff --git a/test/fixtures/wpt/interfaces/html.idl b/test/fixtures/wpt/interfaces/html.idl index d9068b4ad1e550..c7f744ccbe601b 100644 --- a/test/fixtures/wpt/interfaces/html.idl +++ b/test/fixtures/wpt/interfaces/html.idl @@ -98,7 +98,6 @@ partial interface Document { // also has obsolete members }; Document includes GlobalEventHandlers; -Document includes DocumentAndElementEventHandlers; partial interface mixin DocumentOrShadowRoot { readonly attribute Element? activeElement; @@ -128,10 +127,15 @@ interface HTMLElement : Element { [CEReactions] attribute [LegacyNullToEmptyString] DOMString outerText; ElementInternals attachInternals(); + + // The popover API + undefined showPopover(); + undefined hidePopover(); + boolean togglePopover(optional boolean force); + [CEReactions] attribute DOMString? popover; }; HTMLElement includes GlobalEventHandlers; -HTMLElement includes DocumentAndElementEventHandlers; HTMLElement includes ElementContentEditable; HTMLElement includes HTMLOrSVGElement; @@ -204,6 +208,7 @@ interface HTMLLinkElement : HTMLElement { [CEReactions] attribute DOMString referrerPolicy; [SameObject, PutForwards=value] readonly attribute DOMTokenList blocking; [CEReactions] attribute boolean disabled; + [CEReactions] attribute DOMString fetchPriority; // also has obsolete members }; @@ -432,6 +437,7 @@ interface HTMLImageElement : HTMLElement { [CEReactions] attribute DOMString referrerPolicy; [CEReactions] attribute DOMString decoding; [CEReactions] attribute DOMString loading; + [CEReactions] attribute DOMString fetchPriority; Promise decode(); @@ -886,7 +892,7 @@ interface HTMLInputElement : HTMLElement { [CEReactions] attribute DOMString formTarget; [CEReactions] attribute unsigned long height; attribute boolean indeterminate; - readonly attribute HTMLElement? list; + readonly attribute HTMLDataListElement? list; [CEReactions] attribute DOMString max; [CEReactions] attribute long maxLength; [CEReactions] attribute DOMString min; @@ -931,6 +937,7 @@ interface HTMLInputElement : HTMLElement { // also has obsolete members }; +HTMLInputElement includes PopoverInvokerElement; [Exposed=Window] interface HTMLButtonElement : HTMLElement { @@ -956,6 +963,7 @@ interface HTMLButtonElement : HTMLElement { readonly attribute NodeList labels; }; +HTMLButtonElement includes PopoverInvokerElement; [Exposed=Window] interface HTMLSelectElement : HTMLElement { @@ -1216,6 +1224,7 @@ interface HTMLScriptElement : HTMLElement { [CEReactions] attribute DOMString integrity; [CEReactions] attribute DOMString referrerPolicy; [SameObject, PutForwards=value] readonly attribute DOMTokenList blocking; + [CEReactions] attribute DOMString fetchPriority; static boolean supports(DOMString type); @@ -1364,14 +1373,7 @@ interface mixin CanvasShadowStyles { interface mixin CanvasFilters { // filters - attribute (DOMString or CanvasFilter) filter; // (default "none") -}; - -typedef record CanvasFilterInput; - -[Exposed=(Window,Worker,PaintWorklet)] -interface CanvasFilter { - constructor(optional (CanvasFilterInput or sequence) filters); + attribute DOMString filter; // (default "none") }; interface mixin CanvasRect { @@ -1592,6 +1594,7 @@ OffscreenCanvasRenderingContext2D includes CanvasPath; interface CustomElementRegistry { [CEReactions] undefined define(DOMString name, CustomElementConstructor constructor, optional ElementDefinitionOptions options = {}); (CustomElementConstructor or undefined) get(DOMString name); + DOMString? getName(CustomElementConstructor constructor); Promise whenDefined(DOMString name); [CEReactions] undefined upgrade(Node root); }; @@ -1641,8 +1644,39 @@ dictionary ValidityStateFlags { boolean customError = false; }; +[Exposed=(Window)] +interface VisibilityStateEntry : PerformanceEntry { + readonly attribute DOMString name; // shadows inherited name + readonly attribute DOMString entryType; // shadows inherited entryType + readonly attribute DOMHighResTimeStamp startTime; // shadows inherited startTime + readonly attribute unsigned long duration; // shadows inherited duration +}; + +[Exposed=Window] +interface UserActivation { + readonly attribute boolean hasBeenActive; + readonly attribute boolean isActive; +}; + +partial interface Navigator { + [SameObject] readonly attribute UserActivation userActivation; +}; + +[Exposed=Window] +interface ToggleEvent : Event { + constructor(DOMString type, optional ToggleEventInit eventInitDict = {}); + readonly attribute DOMString oldState; + readonly attribute DOMString newState; +}; + +dictionary ToggleEventInit : EventInit { + DOMString oldState = ""; + DOMString newState = ""; +}; + dictionary FocusOptions { boolean preventScroll = false; + boolean focusVisible; }; interface mixin ElementContentEditable { @@ -1702,6 +1736,11 @@ dictionary DragEventInit : MouseEventInit { DataTransfer? dataTransfer = null; }; +interface mixin PopoverInvokerElement { + [CEReactions] attribute Element? popoverTargetElement; + [CEReactions] attribute DOMString popoverTargetAction; +}; + [Global=Window, Exposed=Window, LegacyUnenumerableNamedProperties] @@ -1713,6 +1752,7 @@ interface Window : EventTarget { attribute DOMString name; [PutForwards=href, LegacyUnforgeable] readonly attribute Location location; readonly attribute History history; + readonly attribute Navigation navigation; readonly attribute CustomElementRegistry customElements; [Replaceable] readonly attribute BarProp locationbar; [Replaceable] readonly attribute BarProp menubar; @@ -1735,14 +1775,15 @@ interface Window : EventTarget { [Replaceable] readonly attribute WindowProxy? parent; readonly attribute Element? frameElement; WindowProxy? open(optional USVString url = "", optional DOMString target = "_blank", optional [LegacyNullToEmptyString] DOMString features = ""); - getter object (DOMString name); + // Since this is the global object, the IDL named getter adds a NamedPropertiesObject exotic // object on the prototype chain. Indeed, this does not make the global object an exotic object. // Indexed access is taken care of by the WindowProxy exotic object. + getter object (DOMString name); // the user agent readonly attribute Navigator navigator; - readonly attribute Navigator clientInformation; // legacy alias of .navigator + [Replaceable] readonly attribute Navigator clientInformation; // legacy alias of .navigator readonly attribute boolean originAgentCluster; // user prompts @@ -1769,20 +1810,6 @@ interface BarProp { readonly attribute boolean visible; }; -enum ScrollRestoration { "auto", "manual" }; - -[Exposed=Window] -interface History { - readonly attribute unsigned long length; - attribute ScrollRestoration scrollRestoration; - readonly attribute any state; - undefined go(optional long delta = 0); - undefined back(); - undefined forward(); - undefined pushState(any data, DOMString unused, optional USVString? url = null); - undefined replaceState(any data, DOMString unused, optional USVString? url = null); -}; - [Exposed=Window] interface Location { // but see also additional creation steps and overridden internal methods [LegacyUnforgeable] stringifier attribute USVString href; @@ -1802,15 +1829,183 @@ interface Location { // but see also additional creation steps and overridden in [LegacyUnforgeable, SameObject] readonly attribute DOMStringList ancestorOrigins; }; +enum ScrollRestoration { "auto", "manual" }; + +[Exposed=Window] +interface History { + readonly attribute unsigned long length; + attribute ScrollRestoration scrollRestoration; + readonly attribute any state; + undefined go(optional long delta = 0); + undefined back(); + undefined forward(); + undefined pushState(any data, DOMString unused, optional USVString? url = null); + undefined replaceState(any data, DOMString unused, optional USVString? url = null); +}; + +[Exposed=Window] +interface Navigation : EventTarget { + sequence entries(); + readonly attribute NavigationHistoryEntry? currentEntry; + undefined updateCurrentEntry(NavigationUpdateCurrentEntryOptions options); + readonly attribute NavigationTransition? transition; + + readonly attribute boolean canGoBack; + readonly attribute boolean canGoForward; + + NavigationResult navigate(USVString url, optional NavigationNavigateOptions options = {}); + NavigationResult reload(optional NavigationReloadOptions options = {}); + + NavigationResult traverseTo(DOMString key, optional NavigationOptions options = {}); + NavigationResult back(optional NavigationOptions options = {}); + NavigationResult forward(optional NavigationOptions options = {}); + + attribute EventHandler onnavigate; + attribute EventHandler onnavigatesuccess; + attribute EventHandler onnavigateerror; + attribute EventHandler oncurrententrychange; +}; + +dictionary NavigationUpdateCurrentEntryOptions { + required any state; +}; + +dictionary NavigationOptions { + any info; +}; + +dictionary NavigationNavigateOptions : NavigationOptions { + any state; + NavigationHistoryBehavior history = "auto"; +}; + +dictionary NavigationReloadOptions : NavigationOptions { + any state; +}; + +dictionary NavigationResult { + Promise committed; + Promise finished; +}; + +enum NavigationHistoryBehavior { + "auto", + "push", + "replace" +}; + +enum NavigationType { + "push", + "replace", + "reload", + "traverse" +}; + +[Exposed=Window] +interface NavigationHistoryEntry : EventTarget { + readonly attribute USVString? url; + readonly attribute DOMString key; + readonly attribute DOMString id; + readonly attribute long long index; + readonly attribute boolean sameDocument; + + any getState(); + + attribute EventHandler ondispose; +}; + +[Exposed=Window] +interface NavigationTransition { + readonly attribute NavigationType navigationType; + readonly attribute NavigationHistoryEntry from; + readonly attribute Promise finished; +}; + +[Exposed=Window] +interface NavigateEvent : Event { + constructor(DOMString type, NavigateEventInit eventInitDict); + + readonly attribute NavigationType navigationType; + readonly attribute NavigationDestination destination; + readonly attribute boolean canIntercept; + readonly attribute boolean userInitiated; + readonly attribute boolean hashChange; + readonly attribute AbortSignal signal; + readonly attribute FormData? formData; + readonly attribute DOMString? downloadRequest; + readonly attribute any info; + readonly attribute boolean hasUAVisualTransition; + + undefined intercept(optional NavigationInterceptOptions options = {}); + undefined scroll(); +}; + +dictionary NavigateEventInit : EventInit { + NavigationType navigationType = "push"; + required NavigationDestination destination; + boolean canIntercept = false; + boolean userInitiated = false; + boolean hashChange = false; + required AbortSignal signal; + FormData? formData = null; + DOMString? downloadRequest = null; + any info; + boolean hasUAVisualTransition = false; +}; + +dictionary NavigationInterceptOptions { + NavigationInterceptHandler handler; + NavigationFocusReset focusReset; + NavigationScrollBehavior scroll; +}; + +enum NavigationFocusReset { + "after-transition", + "manual" +}; + +enum NavigationScrollBehavior { + "after-transition", + "manual" +}; + +callback NavigationInterceptHandler = Promise (); + +[Exposed=Window] +interface NavigationDestination { + readonly attribute USVString url; + readonly attribute DOMString key; + readonly attribute DOMString id; + readonly attribute long long index; + readonly attribute boolean sameDocument; + + any getState(); +}; + +[Exposed=Window] +interface NavigationCurrentEntryChangeEvent : Event { + constructor(DOMString type, NavigationCurrentEntryChangeEventInit eventInitDict); + + readonly attribute NavigationType? navigationType; + readonly attribute NavigationHistoryEntry from; +}; + +dictionary NavigationCurrentEntryChangeEventInit : EventInit { + NavigationType? navigationType = null; + required NavigationHistoryEntry from; +}; + [Exposed=Window] interface PopStateEvent : Event { constructor(DOMString type, optional PopStateEventInit eventInitDict = {}); readonly attribute any state; + readonly attribute boolean hasUAVisualTransition; }; dictionary PopStateEventInit : EventInit { any state = null; + boolean hasUAVisualTransition = false; }; [Exposed=Window] @@ -1891,6 +2086,7 @@ interface mixin GlobalEventHandlers { attribute EventHandler onauxclick; attribute EventHandler onbeforeinput; attribute EventHandler onbeforematch; + attribute EventHandler onbeforetoggle; attribute EventHandler onblur; attribute EventHandler oncancel; attribute EventHandler oncanplay; @@ -1901,7 +2097,9 @@ interface mixin GlobalEventHandlers { attribute EventHandler oncontextlost; attribute EventHandler oncontextmenu; attribute EventHandler oncontextrestored; + attribute EventHandler oncopy; attribute EventHandler oncuechange; + attribute EventHandler oncut; attribute EventHandler ondblclick; attribute EventHandler ondrag; attribute EventHandler ondragend; @@ -1932,6 +2130,7 @@ interface mixin GlobalEventHandlers { attribute EventHandler onmouseout; attribute EventHandler onmouseover; attribute EventHandler onmouseup; + attribute EventHandler onpaste; attribute EventHandler onpause; attribute EventHandler onplay; attribute EventHandler onplaying; @@ -1940,6 +2139,7 @@ interface mixin GlobalEventHandlers { attribute EventHandler onreset; attribute EventHandler onresize; attribute EventHandler onscroll; + attribute EventHandler onscrollend; attribute EventHandler onsecuritypolicyviolation; attribute EventHandler onseeked; attribute EventHandler onseeking; @@ -1978,12 +2178,6 @@ interface mixin WindowEventHandlers { attribute EventHandler onunload; }; -interface mixin DocumentAndElementEventHandlers { - attribute EventHandler oncopy; - attribute EventHandler oncut; - attribute EventHandler onpaste; -}; - typedef (DOMString or Function) TimerHandler; interface mixin WindowOrWorkerGlobalScope { @@ -2132,13 +2326,13 @@ typedef (CanvasImageSource or Blob or ImageData) ImageBitmapSource; -enum ImageOrientation { "none", "flipY" }; +enum ImageOrientation { "from-image", "flipY" }; enum PremultiplyAlpha { "none", "premultiply", "default" }; enum ColorSpaceConversion { "none", "default" }; enum ResizeQuality { "pixelated", "low", "medium", "high" }; dictionary ImageBitmapOptions { - ImageOrientation imageOrientation = "none"; + ImageOrientation imageOrientation = "from-image"; PremultiplyAlpha premultiplyAlpha = "default"; ColorSpaceConversion colorSpaceConversion = "default"; [EnforceRange] unsigned long resizeWidth; diff --git a/test/fixtures/wpt/interfaces/performance-timeline.idl b/test/fixtures/wpt/interfaces/performance-timeline.idl index 9f6cc5e2e902dc..cdd8fafd8c64e6 100644 --- a/test/fixtures/wpt/interfaces/performance-timeline.idl +++ b/test/fixtures/wpt/interfaces/performance-timeline.idl @@ -1,7 +1,7 @@ // GENERATED CONTENT - DO NOT EDIT // Content was automatically extracted by Reffy into webref // (https://github.com/w3c/webref) -// Source: Performance Timeline Level 2 (https://w3c.github.io/performance-timeline/) +// Source: Performance Timeline (https://w3c.github.io/performance-timeline/) partial interface Performance { PerformanceEntryList getEntries (); @@ -10,7 +10,7 @@ partial interface Performance { }; typedef sequence PerformanceEntryList; -[Exposed=*] +[Exposed=(Window,Worker)] interface PerformanceEntry { readonly attribute DOMString name; readonly attribute DOMString entryType; @@ -22,7 +22,7 @@ interface PerformanceEntry { callback PerformanceObserverCallback = undefined (PerformanceObserverEntryList entries, PerformanceObserver observer, optional PerformanceObserverCallbackOptions options = {}); -[Exposed=*] +[Exposed=(Window,Worker)] interface PerformanceObserver { constructor(PerformanceObserverCallback callback); undefined observe (optional PerformanceObserverInit options = {}); @@ -41,7 +41,7 @@ dictionary PerformanceObserverInit { boolean buffered; }; -[Exposed=*] +[Exposed=(Window,Worker)] interface PerformanceObserverEntryList { PerformanceEntryList getEntries(); PerformanceEntryList getEntriesByType (DOMString type); diff --git a/test/fixtures/wpt/interfaces/resource-timing.idl b/test/fixtures/wpt/interfaces/resource-timing.idl index 235963b804bf9a..33fed05b756838 100644 --- a/test/fixtures/wpt/interfaces/resource-timing.idl +++ b/test/fixtures/wpt/interfaces/resource-timing.idl @@ -1,11 +1,12 @@ // GENERATED CONTENT - DO NOT EDIT // Content was automatically extracted by Reffy into webref // (https://github.com/w3c/webref) -// Source: Resource Timing Level 2 (https://w3c.github.io/resource-timing/) +// Source: Resource Timing (https://w3c.github.io/resource-timing/) [Exposed=(Window,Worker)] interface PerformanceResourceTiming : PerformanceEntry { readonly attribute DOMString initiatorType; + readonly attribute DOMString deliveryType; readonly attribute ByteString nextHopProtocol; readonly attribute DOMHighResTimeStamp workerStart; readonly attribute DOMHighResTimeStamp redirectStart; @@ -17,14 +18,23 @@ interface PerformanceResourceTiming : PerformanceEntry { readonly attribute DOMHighResTimeStamp connectEnd; readonly attribute DOMHighResTimeStamp secureConnectionStart; readonly attribute DOMHighResTimeStamp requestStart; + readonly attribute DOMHighResTimeStamp firstInterimResponseStart; readonly attribute DOMHighResTimeStamp responseStart; readonly attribute DOMHighResTimeStamp responseEnd; readonly attribute unsigned long long transferSize; readonly attribute unsigned long long encodedBodySize; readonly attribute unsigned long long decodedBodySize; + readonly attribute unsigned short responseStatus; + readonly attribute RenderBlockingStatusType renderBlockingStatus; + readonly attribute DOMString contentType; [Default] object toJSON(); }; +enum RenderBlockingStatusType { + "blocking", + "non-blocking" +}; + partial interface Performance { undefined clearResourceTimings (); undefined setResourceTimingBufferSize (unsigned long maxSize); diff --git a/test/fixtures/wpt/interfaces/streams.idl b/test/fixtures/wpt/interfaces/streams.idl index fd5420f16a0967..838bf39c6d6df5 100644 --- a/test/fixtures/wpt/interfaces/streams.idl +++ b/test/fixtures/wpt/interfaces/streams.idl @@ -7,6 +7,8 @@ interface ReadableStream { constructor(optional object underlyingSource, optional QueuingStrategy strategy = {}); + static ReadableStream from(any asyncIterable); + readonly attribute boolean locked; Promise cancel(optional any reason); diff --git a/test/fixtures/wpt/interfaces/url.idl b/test/fixtures/wpt/interfaces/url.idl index 360c9adcfa1104..a5e4d1eb492e82 100644 --- a/test/fixtures/wpt/interfaces/url.idl +++ b/test/fixtures/wpt/interfaces/url.idl @@ -8,6 +8,8 @@ interface URL { constructor(USVString url, optional USVString base); + static boolean canParse(USVString url, optional USVString base); + stringifier attribute USVString href; readonly attribute USVString origin; attribute USVString protocol; @@ -28,11 +30,13 @@ interface URL { interface URLSearchParams { constructor(optional (sequence> or record or USVString) init = ""); + readonly attribute unsigned long size; + undefined append(USVString name, USVString value); - undefined delete(USVString name); + undefined delete(USVString name, optional USVString value); USVString? get(USVString name); sequence getAll(USVString name); - boolean has(USVString name); + boolean has(USVString name, optional USVString value); undefined set(USVString name, USVString value); undefined sort(); diff --git a/test/fixtures/wpt/interfaces/user-timing.idl b/test/fixtures/wpt/interfaces/user-timing.idl index a0b8f94710ec33..28ee8aac2b19a6 100644 --- a/test/fixtures/wpt/interfaces/user-timing.idl +++ b/test/fixtures/wpt/interfaces/user-timing.idl @@ -22,13 +22,13 @@ partial interface Performance { undefined clearMeasures(optional DOMString measureName); }; -[Exposed=*] +[Exposed=(Window,Worker)] interface PerformanceMark : PerformanceEntry { constructor(DOMString markName, optional PerformanceMarkOptions markOptions = {}); readonly attribute any detail; }; -[Exposed=*] +[Exposed=(Window,Worker)] interface PerformanceMeasure : PerformanceEntry { readonly attribute any detail; }; diff --git a/test/fixtures/wpt/interfaces/webidl.idl b/test/fixtures/wpt/interfaces/webidl.idl index 43748c5ac4c889..4d0dfaa106275f 100644 --- a/test/fixtures/wpt/interfaces/webidl.idl +++ b/test/fixtures/wpt/interfaces/webidl.idl @@ -9,7 +9,8 @@ typedef (Int8Array or Int16Array or Int32Array or Float32Array or Float64Array or DataView) ArrayBufferView; typedef (ArrayBufferView or ArrayBuffer) BufferSource; -[Exposed=(Window,Worker), +typedef (ArrayBuffer or SharedArrayBuffer or [AllowShared] ArrayBufferView) AllowSharedBufferSource; +[Exposed=*, Serializable] interface DOMException { // but see below note about ECMAScript binding constructor(optional DOMString message = "", optional DOMString name = "Error"); @@ -46,5 +47,3 @@ interface DOMException { // but see below note about ECMAScript binding callback Function = any (any... arguments); callback VoidFunction = undefined (); - -typedef unsigned long long DOMTimeStamp; diff --git a/test/fixtures/wpt/resources/declarative-shadow-dom-polyfill.js b/test/fixtures/wpt/resources/declarative-shadow-dom-polyfill.js index 8ab08b0294c297..99a3e911eb6336 100644 --- a/test/fixtures/wpt/resources/declarative-shadow-dom-polyfill.js +++ b/test/fixtures/wpt/resources/declarative-shadow-dom-polyfill.js @@ -16,7 +16,8 @@ function polyfill_declarative_shadow_dom(root) { return; root.querySelectorAll("template[shadowrootmode]").forEach(template => { const mode = template.getAttribute("shadowrootmode"); - const shadowRoot = template.parentNode.attachShadow({ mode }); + const delegatesFocus = template.hasAttribute("shadowrootdelegatesfocus"); + const shadowRoot = template.parentNode.attachShadow({ mode, delegatesFocus }); shadowRoot.appendChild(template.content); template.remove(); polyfill_declarative_shadow_dom(shadowRoot); diff --git a/test/fixtures/wpt/resources/idlharness.js b/test/fixtures/wpt/resources/idlharness.js index 46aa11e5ca123c..8f741b09b26bcb 100644 --- a/test/fixtures/wpt/resources/idlharness.js +++ b/test/fixtures/wpt/resources/idlharness.js @@ -2357,12 +2357,13 @@ IdlInterface.prototype.do_member_operation_asserts = function(memberHolderObject assert_equals(typeof memberHolderObject[member.name], "function", "property must be a function"); - const ctors = this.members.filter(function(m) { - return m.type == "operation" && m.name == member.name; + const operationOverloads = this.members.filter(function(m) { + return m.type == "operation" && m.name == member.name && + (m.special === "static") === (member.special === "static"); }); assert_equals( memberHolderObject[member.name].length, - minOverloadLength(ctors), + minOverloadLength(operationOverloads), "property has wrong .length"); assert_equals( memberHolderObject[member.name].name, diff --git a/test/fixtures/wpt/resources/testdriver.js b/test/fixtures/wpt/resources/testdriver.js index 76ae2834fdfb0a..ddf723cb3ee8a5 100644 --- a/test/fixtures/wpt/resources/testdriver.js +++ b/test/fixtures/wpt/resources/testdriver.js @@ -220,6 +220,40 @@ return cookie; }, + /** + * Get Computed Label for an element. + * + * This matches the behaviour of the + * `Get Computed Label + * `_ + * WebDriver command. + * + * @param {Element} element + * @returns {Promise} fulfilled after the computed label is returned, or + * rejected in the cases the WebDriver command errors + */ + get_computed_label: async function(element) { + let label = await window.test_driver_internal.get_computed_label(element); + return label; + }, + + /** + * Get Computed Role for an element. + * + * This matches the behaviour of the + * `Get Computed Label + * `_ + * WebDriver command. + * + * @param {Element} element + * @returns {Promise} fulfilled after the computed role is returned, or + * rejected in the cases the WebDriver command errors + */ + get_computed_role: async function(element) { + let role = await window.test_driver_internal.get_computed_role(element); + return role; + }, + /** * Send keys to an element. * @@ -228,7 +262,9 @@ * occurs. * * If ``element`` is from a different browsing context, the - * command will be run in that context. + * command will be run in that context. The test must not depend + * on the ``window.name`` property being unset on the target + * window. * * To send special keys, send the respective key's codepoint, * as defined by `WebDriver @@ -262,12 +298,6 @@ inline: "nearest"}); } - var pointerInteractablePaintTree = getPointerInteractablePaintTree(element); - if (pointerInteractablePaintTree.length === 0 || - !element.contains(pointerInteractablePaintTree[0])) { - return Promise.reject(new Error("element send_keys intercepted error")); - } - return window.test_driver_internal.send_keys(element, keys); }, @@ -300,9 +330,9 @@ * to run the call, or null for the current * browsing context. * - * @returns {Promise} fulfilled with the previous {@link - * https://www.w3.org/TR/webdriver/#dfn-windowrect-object|WindowRect} - * value, after the window is minimized. + * @returns {Promise} fulfilled with the previous `WindowRect + * `_ + * value, after the window is minimized. */ minimize_window: function(context=null) { return window.test_driver_internal.minimize_window(context); @@ -315,8 +345,8 @@ * `_ * WebDriver command * - * @param {Object} rect - A {@link - * https://www.w3.org/TR/webdriver/#dfn-windowrect-object|WindowRect} + * @param {Object} rect - A `WindowRect + * `_ * @param {WindowProxy} context - Browsing context in which * to run the call, or null for the current * browsing context. @@ -389,8 +419,9 @@ /** * Sets the state of a permission * - * This function simulates a user setting a permission into a - * particular state. + * This function causes permission requests and queries for the status + * of a certain permission type (e.g. "push", or "background-fetch") to + * always return ``state``. * * Matches the `Set Permission * `_ @@ -402,8 +433,10 @@ * * @param {PermissionDescriptor} descriptor - a `PermissionDescriptor * `_ - * dictionary. - * @param {String} state - the state of the permission + * or derived object. + * @param {PermissionState} state - a `PermissionState + * `_ + * value. * @param {WindowProxy} context - Browsing context in which * to run the call, or null for the current * browsing context. @@ -646,6 +679,296 @@ set_spc_transaction_mode: function(mode, context=null) { return window.test_driver_internal.set_spc_transaction_mode(mode, context); }, + + /** + * Cancels the Federated Credential Management dialog + * + * Matches the `Cancel dialog + * `_ + * WebDriver command. + * + * @param {WindowProxy} context - Browsing context in which + * to run the call, or null for the current + * browsing context. + * + * @returns {Promise} Fulfilled after the dialog is canceled, or rejected + * in case the WebDriver command errors + */ + cancel_fedcm_dialog: function(context=null) { + return window.test_driver_internal.cancel_fedcm_dialog(context); + }, + + /** + * Clicks a button on the Federated Credential Management dialog + * + * Matches the `Click dialog button + * `_ + * WebDriver command. + * + * @param {String} dialog_button - String enum representing the dialog button to click. + * @param {WindowProxy} context - Browsing context in which + * to run the call, or null for the current + * browsing context. + * + * @returns {Promise} Fulfilled after the button is clicked, + * or rejected in case the WebDriver command errors + */ + click_fedcm_dialog_button: function(dialog_button, context=null) { + return window.test_driver_internal.click_fedcm_dialog_button(dialog_button, context); + }, + + /** + * Selects an account from the Federated Credential Management dialog + * + * Matches the `Select account + * `_ + * WebDriver command. + * + * @param {number} account_index - Index of the account to select. + * @param {WindowProxy} context - Browsing context in which + * to run the call, or null for the current + * browsing context. + * + * @returns {Promise} Fulfilled after the account is selected, + * or rejected in case the WebDriver command errors + */ + select_fedcm_account: function(account_index, context=null) { + return window.test_driver_internal.select_fedcm_account(account_index, context); + }, + + /** + * Gets the account list from the Federated Credential Management dialog + * + * Matches the `Account list + * `_ + * WebDriver command. + * + * @param {WindowProxy} context - Browsing context in which + * to run the call, or null for the current + * browsing context. + * + * @returns {Promise} fulfilled after the account list is returned, or + * rejected in case the WebDriver command errors + */ + get_fedcm_account_list: function(context=null) { + return window.test_driver_internal.get_fedcm_account_list(context); + }, + + /** + * Gets the title of the Federated Credential Management dialog + * + * Matches the `Get title + * `_ + * WebDriver command. + * + * @param {WindowProxy} context - Browsing context in which + * to run the call, or null for the current + * browsing context. + * + * @returns {Promise} Fulfilled after the title is returned, or rejected + * in case the WebDriver command errors + */ + get_fedcm_dialog_title: function(context=null) { + return window.test_driver_internal.get_fedcm_dialog_title(context); + }, + + /** + * Gets the type of the Federated Credential Management dialog + * + * Matches the `Get dialog type + * `_ + * WebDriver command. + * + * @param {WindowProxy} context - Browsing context in which + * to run the call, or null for the current + * browsing context. + * + * @returns {Promise} Fulfilled after the dialog type is returned, or + * rejected in case the WebDriver command errors + */ + get_fedcm_dialog_type: function(context=null) { + return window.test_driver_internal.get_fedcm_dialog_type(context); + }, + + /** + * Sets whether promise rejection delay is enabled for the Federated Credential Management dialog + * + * Matches the `Set delay enabled + * `_ + * WebDriver command. + * + * @param {boolean} enabled - Whether to delay FedCM promise rejection. + * @param {WindowProxy} context - Browsing context in which + * to run the call, or null for the current + * browsing context. + * + * @returns {Promise} Fulfilled after the delay has been enabled or disabled, + * or rejected in case the WebDriver command errors + */ + set_fedcm_delay_enabled: function(enabled, context=null) { + return window.test_driver_internal.set_fedcm_delay_enabled(enabled, context); + }, + + /** + * Resets the Federated Credential Management dialog's cooldown + * + * Matches the `Reset cooldown + * `_ + * WebDriver command. + * + * @param {WindowProxy} context - Browsing context in which + * to run the call, or null for the current + * browsing context. + * + * @returns {Promise} Fulfilled after the cooldown has been reset, + * or rejected in case the WebDriver command errors + */ + reset_fedcm_cooldown: function(context=null) { + return window.test_driver_internal.reset_fedcm_cooldown(context); + }, + + /** + * Creates a virtual sensor for use with the Generic Sensors APIs. + * + * Matches the `Create Virtual Sensor + * `_ + * WebDriver command. + * + * Once created, a virtual sensor is available to all navigables under + * the same top-level traversable (i.e. all frames in the same page, + * regardless of origin). + * + * @param {String} sensor_type - A `virtual sensor type + * `_ + * such as "accelerometer". + * @param {Object} [sensor_params={}] - Optional parameters described + * in `Create Virtual Sensor + * `_. + * @param {WindowProxy} [context=null] - Browsing context in which to + * run the call, or null for the + * current browsing context. + * + * @returns {Promise} Fulfilled when virtual sensor is created. + * Rejected in case the WebDriver command errors out + * (including if a virtual sensor of the same type + * already exists). + */ + create_virtual_sensor: function(sensor_type, sensor_params={}, context=null) { + return window.test_driver_internal.create_virtual_sensor(sensor_type, sensor_params, context); + }, + + /** + * Causes a virtual sensor to report a new reading to any connected + * platform sensor. + * + * Matches the `Update Virtual Sensor Reading + * `_ + * WebDriver command. + * + * Note: The ``Promise`` it returns may fulfill before or after a + * "reading" event is fired. When using + * :js:func:`EventWatcher.wait_for`, it is necessary to take this into + * account: + * + * Note: New values may also be discarded due to the checks in `update + * latest reading + * `_. + * + * @example + * // Avoid races between EventWatcher and update_virtual_sensor(). + * // This assumes you are sure this reading will be processed (see + * // the example below otherwise). + * const reading = { x: 1, y: 2, z: 3 }; + * await Promise.all([ + * test_driver.update_virtual_sensor('gyroscope', reading), + * watcher.wait_for('reading') + * ]); + * + * @example + * // Do not wait forever if you are not sure the reading will be + * // processed. + * const readingPromise = watcher.wait_for('reading'); + * const timeoutPromise = new Promise(resolve => { + * t.step_timeout(() => resolve('TIMEOUT', 3000)) + * }); + * + * const reading = { x: 1, y: 2, z: 3 }; + * await test_driver.update_virtual_sensor('gyroscope', 'reading'); + * + * const value = + * await Promise.race([timeoutPromise, readingPromise]); + * if (value !== 'TIMEOUT') { + * // Do something. The "reading" event was fired. + * } + * + * @param {String} sensor_type - A `virtual sensor type + * `_ + * such as "accelerometer". + * @param {Object} reading - An Object describing a reading in a format + * dependent on ``sensor_type`` (e.g. ``{x: + * 1, y: 2, z: 3}`` or ``{ illuminance: 42 + * }``). + * @param {WindowProxy} [context=null] - Browsing context in which to + * run the call, or null for the + * current browsing context. + * + * @returns {Promise} Fulfilled after the reading update reaches the + * virtual sensor. Rejected in case the WebDriver + * command errors out (including if a virtual sensor + * of the given type does not exist). + */ + update_virtual_sensor: function(sensor_type, reading, context=null) { + return window.test_driver_internal.update_virtual_sensor(sensor_type, reading, context); + }, + + /** + * Triggers the removal of a virtual sensor if it exists. + * + * Matches the `Delete Virtual Sensor + * `_ + * WebDriver command. + * + * @param {String} sensor_type - A `virtual sensor type + * `_ + * such as "accelerometer". + * @param {WindowProxy} [context=null] - Browsing context in which to + * run the call, or null for the + * current browsing context. + * + * @returns {Promise} Fulfilled after the virtual sensor has been + * removed or if a sensor of the given type does not + * exist. Rejected in case the WebDriver command + * errors out. + + */ + remove_virtual_sensor: function(sensor_type, context=null) { + return window.test_driver_internal.remove_virtual_sensor(sensor_type, context); + }, + + /** + * Returns information about a virtual sensor. + * + * Matches the `Get Virtual Sensor Information + * `_ + * WebDriver command. + * + * @param {String} sensor_type - A `virtual sensor type + * `_ + * such as "accelerometer". + * @param {WindowProxy} [context=null] - Browsing context in which to + * run the call, or null for the + * current browsing context. + * + * @returns {Promise} Fulfilled with an Object with the properties + * described in `Get Virtual Sensor Information + * `_. + * Rejected in case the WebDriver command errors out + * (including if a virtual sensor of the given type + * does not exist). + */ + get_virtual_sensor_information: function(sensor_type, context=null) { + return window.test_driver_internal.get_virtual_sensor_information(sensor_type, context); + } }; window.test_driver_internal = { @@ -657,9 +980,9 @@ */ in_automation: false, - click: function(element, coords) { + async click(element, coords) { if (this.in_automation) { - return Promise.reject(new Error('Not implemented')); + throw new Error("click() is not implemented by testdriver-vendor.js"); } return new Promise(function(resolve, reject) { @@ -667,21 +990,21 @@ }); }, - delete_all_cookies: function(context=null) { - return Promise.reject(new Error("unimplemented")); + async delete_all_cookies(context=null) { + throw new Error("delete_all_cookies() is not implemented by testdriver-vendor.js"); }, - get_all_cookies: function(context=null) { - return Promise.reject(new Error("unimplemented")); + async get_all_cookies(context=null) { + throw new Error("get_all_cookies() is not implemented by testdriver-vendor.js"); }, - get_named_cookie: function(name, context=null) { - return Promise.reject(new Error("unimplemented")); + async get_named_cookie(name, context=null) { + throw new Error("get_named_cookie() is not implemented by testdriver-vendor.js"); }, - send_keys: function(element, keys) { + async send_keys(element, keys) { if (this.in_automation) { - return Promise.reject(new Error('Not implemented')); + throw new Error("send_keys() is not implemented by testdriver-vendor.js"); } return new Promise(function(resolve, reject) { @@ -711,66 +1034,112 @@ }); }, - freeze: function(context=null) { - return Promise.reject(new Error("unimplemented")); + async freeze(context=null) { + throw new Error("freeze() is not implemented by testdriver-vendor.js"); }, - minimize_window: function(context=null) { - return Promise.reject(new Error("unimplemented")); + async minimize_window(context=null) { + throw new Error("minimize_window() is not implemented by testdriver-vendor.js"); }, - set_window_rect: function(rect, context=null) { - return Promise.reject(new Error("unimplemented")); + async set_window_rect(rect, context=null) { + throw new Error("set_window_rect() is not implemented by testdriver-vendor.js"); }, - action_sequence: function(actions, context=null) { - return Promise.reject(new Error("unimplemented")); + async action_sequence(actions, context=null) { + throw new Error("action_sequence() is not implemented by testdriver-vendor.js"); }, - generate_test_report: function(message, context=null) { - return Promise.reject(new Error("unimplemented")); + async generate_test_report(message, context=null) { + throw new Error("generate_test_report() is not implemented by testdriver-vendor.js"); }, + async set_permission(permission_params, context=null) { + throw new Error("set_permission() is not implemented by testdriver-vendor.js"); + }, - set_permission: function(permission_params, context=null) { - return Promise.reject(new Error("unimplemented")); + async add_virtual_authenticator(config, context=null) { + throw new Error("add_virtual_authenticator() is not implemented by testdriver-vendor.js"); }, - add_virtual_authenticator: function(config, context=null) { - return Promise.reject(new Error("unimplemented")); + async remove_virtual_authenticator(authenticator_id, context=null) { + throw new Error("remove_virtual_authenticator() is not implemented by testdriver-vendor.js"); }, - remove_virtual_authenticator: function(authenticator_id, context=null) { - return Promise.reject(new Error("unimplemented")); + async add_credential(authenticator_id, credential, context=null) { + throw new Error("add_credential() is not implemented by testdriver-vendor.js"); }, - add_credential: function(authenticator_id, credential, context=null) { - return Promise.reject(new Error("unimplemented")); + async get_credentials(authenticator_id, context=null) { + throw new Error("get_credentials() is not implemented by testdriver-vendor.js"); }, - get_credentials: function(authenticator_id, context=null) { - return Promise.reject(new Error("unimplemented")); + async remove_credential(authenticator_id, credential_id, context=null) { + throw new Error("remove_credential() is not implemented by testdriver-vendor.js"); }, - remove_credential: function(authenticator_id, credential_id, context=null) { - return Promise.reject(new Error("unimplemented")); + async remove_all_credentials(authenticator_id, context=null) { + throw new Error("remove_all_credentials() is not implemented by testdriver-vendor.js"); }, - remove_all_credentials: function(authenticator_id, context=null) { - return Promise.reject(new Error("unimplemented")); + async set_user_verified(authenticator_id, uv, context=null) { + throw new Error("set_user_verified() is not implemented by testdriver-vendor.js"); }, - set_user_verified: function(authenticator_id, uv, context=null) { - return Promise.reject(new Error("unimplemented")); + async set_storage_access(origin, embedding_origin, blocked, context=null) { + throw new Error("set_storage_access() is not implemented by testdriver-vendor.js"); }, - set_storage_access: function(origin, embedding_origin, blocked, context=null) { - return Promise.reject(new Error("unimplemented")); + async set_spc_transaction_mode(mode, context=null) { + throw new Error("set_spc_transaction_mode() is not implemented by testdriver-vendor.js"); }, - set_spc_transaction_mode: function(mode, context=null) { - return Promise.reject(new Error("unimplemented")); + async cancel_fedcm_dialog(context=null) { + throw new Error("cancel_fedcm_dialog() is not implemented by testdriver-vendor.js"); + }, + + async click_fedcm_dialog_button(dialog_button, context=null) { + throw new Error("click_fedcm_dialog_button() is not implemented by testdriver-vendor.js"); + }, + + async select_fedcm_account(account_index, context=null) { + throw new Error("select_fedcm_account() is not implemented by testdriver-vendor.js"); + }, + + async get_fedcm_account_list(context=null) { + throw new Error("get_fedcm_account_list() is not implemented by testdriver-vendor.js"); + }, + + async get_fedcm_dialog_title(context=null) { + throw new Error("get_fedcm_dialog_title() is not implemented by testdriver-vendor.js"); + }, + + async get_fedcm_dialog_type(context=null) { + throw new Error("get_fedcm_dialog_type() is not implemented by testdriver-vendor.js"); }, + async set_fedcm_delay_enabled(enabled, context=null) { + throw new Error("set_fedcm_delay_enabled() is not implemented by testdriver-vendor.js"); + }, + + async reset_fedcm_cooldown(context=null) { + throw new Error("reset_fedcm_cooldown() is not implemented by testdriver-vendor.js"); + }, + + async create_virtual_sensor(sensor_type, sensor_params, context=null) { + throw new Error("create_virtual_sensor() is not implemented by testdriver-vendor.js"); + }, + + async update_virtual_sensor(sensor_type, reading, context=null) { + throw new Error("update_virtual_sensor() is not implemented by testdriver-vendor.js"); + }, + + async remove_virtual_sensor(sensor_type, context=null) { + throw new Error("remove_virtual_sensor() is not implemented by testdriver-vendor.js"); + }, + + async get_virtual_sensor_information(sensor_type, context=null) { + throw new Error("get_virtual_sensor_information() is not implemented by testdriver-vendor.js"); + } }; })(); diff --git a/test/fixtures/wpt/resources/testharness.js b/test/fixtures/wpt/resources/testharness.js index 112790bb1eeb87..497ae23f0e83ee 100644 --- a/test/fixtures/wpt/resources/testharness.js +++ b/test/fixtures/wpt/resources/testharness.js @@ -1426,12 +1426,16 @@ function assert_wrapper(...args) { let status = Test.statuses.TIMEOUT; let stack = null; + let new_assert_index = null; try { if (settings.debug) { console.debug("ASSERT", name, tests.current_test && tests.current_test.name, args); } if (tests.output) { tests.set_assert(name, args); + // Remember the newly pushed assert's index, because `apply` + // below might push new asserts. + new_assert_index = tests.asserts_run.length - 1; } const rv = f.apply(undefined, args); status = Test.statuses.PASS; @@ -1445,7 +1449,7 @@ stack = get_stack(); } if (tests.output) { - tests.set_assert_status(status, stack); + tests.set_assert_status(new_assert_index, status, stack); } } } @@ -1493,7 +1497,7 @@ /** * Assert that ``actual`` is the same value as ``expected``. * - * For objects this compares by cobject identity; for primitives + * For objects this compares by object identity; for primitives * this distinguishes between 0 and -0, and has correct handling * of NaN. * @@ -2725,8 +2729,9 @@ * speed when the condition is quickly met. * * @param {Function} cond A function taking no arguments and - * returning a boolean. The callback is called - * when this function returns true. + * returning a boolean or a Promise. The callback is + * called when this function returns true, or the + * returned Promise is resolved with true. * @param {Function} func A function taking no arguments to call once * the condition is met. * @param {string} [description] Error message to add to assert in case of @@ -2742,11 +2747,11 @@ var remaining = Math.ceil(timeout_full / interval); var test_this = this; - var wait_for_inner = test_this.step_func(() => { - if (cond()) { + const step = test_this.step_func((result) => { + if (result) { func(); } else { - if(remaining === 0) { + if (remaining === 0) { assert(false, "step_wait_func", description, "Timed out waiting on condition"); } @@ -2755,6 +2760,12 @@ } }); + var wait_for_inner = test_this.step_func(() => { + Promise.resolve(cond()).then( + step, + test_this.unreached_func("step_wait_func")); + }); + wait_for_inner(); }; @@ -2780,8 +2791,9 @@ * }, "Navigating a popup to about:blank"); * * @param {Function} cond A function taking no arguments and - * returning a boolean. The callback is called - * when this function returns true. + * returning a boolean or a Promise. The callback is + * called when this function returns true, or the + * returned Promise is resolved with true. * @param {Function} func A function taking no arguments to call once * the condition is met. * @param {string} [description] Error message to add to assert in case of @@ -2817,7 +2829,7 @@ * }, ""); * * @param {Function} cond A function taking no arguments and - * returning a boolean. + * returning a boolean or a Promise. * @param {string} [description] Error message to add to assert in case of * failure. * @param {number} timeout Timeout in ms. This is multiplied by the global @@ -3673,8 +3685,8 @@ this.asserts_run.push(new AssertRecord(this.current_test, assert_name, args)) } - Tests.prototype.set_assert_status = function(status, stack) { - let assert_record = this.asserts_run[this.asserts_run.length - 1]; + Tests.prototype.set_assert_status = function(index, status, stack) { + let assert_record = this.asserts_run[index]; assert_record.status = status; assert_record.stack = stack; } diff --git a/test/fixtures/wpt/versions.json b/test/fixtures/wpt/versions.json index 64de3fbbbeff27..8ec93059e8ea69 100644 --- a/test/fixtures/wpt/versions.json +++ b/test/fixtures/wpt/versions.json @@ -52,7 +52,7 @@ "path": "html/webappapis/timers" }, "interfaces": { - "commit": "df731dab88a1a25c04eb7e6238c11dc28fda0801", + "commit": "727995f0432f7ab2ea35c8679412edc28d87ec08", "path": "interfaces" }, "performance-timeline": { @@ -64,7 +64,7 @@ "path": "resource-timing" }, "resources": { - "commit": "919874f84ff3703365063e749161a34af38c3d2a", + "commit": "1e140d63ec885703ce24b3798abd81912696bb85", "path": "resources" }, "streams": { diff --git a/test/wpt/status/compression.json b/test/wpt/status/compression.json index 31a5a78b69ddc0..0cae222832e823 100644 --- a/test/wpt/status/compression.json +++ b/test/wpt/status/compression.json @@ -22,9 +22,6 @@ "idlharness-shadowrealm.window.js": { "skip": "ShadowRealm support is not enabled" }, - "idlharness.https.any.js": { - "skip": "wpt/resources is not as simple to bring up to date" - }, "third_party/pako/pako_inflate.min.js": { "skip": "This is not a test file." } diff --git a/test/wpt/status/resource-timing.json b/test/wpt/status/resource-timing.json index 22f21cfe48d7fe..db5154260227b3 100644 --- a/test/wpt/status/resource-timing.json +++ b/test/wpt/status/resource-timing.json @@ -19,5 +19,22 @@ }, "buffered-flag.any.js": { "skip": "Browser-specific test" + }, + "idlharness.any.js": { + "fail": { + "expected": [ + "PerformanceResourceTiming interface: attribute deliveryType", + "PerformanceResourceTiming interface: attribute firstInterimResponseStart", + "PerformanceResourceTiming interface: attribute responseStatus", + "PerformanceResourceTiming interface: attribute renderBlockingStatus", + "PerformanceResourceTiming interface: attribute contentType", + "PerformanceResourceTiming interface: resource must inherit property \"deliveryType\" with the proper type", + "PerformanceResourceTiming interface: resource must inherit property \"firstInterimResponseStart\" with the proper type", + "PerformanceResourceTiming interface: resource must inherit property \"responseStatus\" with the proper type", + "PerformanceResourceTiming interface: resource must inherit property \"renderBlockingStatus\" with the proper type", + "PerformanceResourceTiming interface: resource must inherit property \"contentType\" with the proper type", + "PerformanceResourceTiming interface: default toJSON operation on resource" + ] + } } } diff --git a/test/wpt/status/streams.json b/test/wpt/status/streams.json index 6454918110dfbd..fb0064a810503b 100644 --- a/test/wpt/status/streams.json +++ b/test/wpt/status/streams.json @@ -2,7 +2,8 @@ "idlharness.any.js": { "fail": { "expected": [ - "ReadableStream interface: async iterable" + "ReadableStream interface: async iterable", + "ReadableStream interface: operation from(any)" ] } }, diff --git a/test/wpt/test-compression.js b/test/wpt/test-compression.js index 6991adff5645b4..23800734922afe 100644 --- a/test/wpt/test-compression.js +++ b/test/wpt/test-compression.js @@ -4,4 +4,6 @@ const { WPTRunner } = require('../common/wpt'); const runner = new WPTRunner('compression'); +runner.pretendGlobalThisAs('Window'); + runner.runJsTests();