Update web-platform-tests to revision b'04c64baa69c1692214ef350185b1ef817362a13c'

This commit is contained in:
WPT Sync Bot 2023-06-11 01:21:45 +00:00
parent 7d9839acc8
commit d4243801cf
403 changed files with 9670 additions and 1715 deletions

View file

@ -0,0 +1,2 @@
[malformed-decl-block-001.xht]
expected: FAIL

View file

@ -0,0 +1,2 @@
[opacity-animation-ending-correctly-002.html]
expected: TIMEOUT

View file

@ -0,0 +1,2 @@
[gap-019.html]
expected: FAIL

View file

@ -19,3 +19,9 @@
[.floating-flexbox 7]
expected: FAIL
[.floating-flexbox 8]
expected: FAIL
[.floating-flexbox 9]
expected: FAIL

View file

@ -0,0 +1,3 @@
[row-compat-001.html]
[.flex 1]
expected: FAIL

View file

@ -0,0 +1,6 @@
[row-use-cases-001.html]
[left < right]
expected: FAIL
[no overflow]
expected: FAIL

View file

@ -0,0 +1,2 @@
[row-wrap-002.tentative.html]
expected: FAIL

View file

@ -7,3 +7,12 @@
[e.style['flex-flow'\] = "nowrap" should set the property value]
expected: FAIL
[e.style['flex-flow'\] = "row nowrap" should set the property value]
expected: FAIL
[e.style['flex-flow'\] = "wrap" should set the property value]
expected: FAIL
[e.style['flex-flow'\] = "row wrap" should set the property value]
expected: FAIL

View file

@ -0,0 +1,2 @@
[text-combine-emphasis.html]
expected: FAIL

View file

@ -0,0 +1,3 @@
[MediaQueryListEvent.html]
[constructor of "change" event]
expected: FAIL

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,2 @@
[malformed-decl-block-001.xht]
expected: FAIL

View file

@ -0,0 +1,2 @@
[gap-019.html]
expected: FAIL

View file

@ -19,3 +19,6 @@
[.floating-flexbox 7]
expected: FAIL
[.floating-flexbox 8]
expected: FAIL

View file

@ -0,0 +1,3 @@
[row-compat-001.html]
[.flex 1]
expected: FAIL

View file

@ -0,0 +1,12 @@
[row-use-cases-001.html]
[left < right]
expected: FAIL
[no overflow]
expected: FAIL
[same widths]
expected: FAIL
[zero width]
expected: FAIL

View file

@ -0,0 +1,2 @@
[row-wrap-002.tentative.html]
expected: FAIL

View file

@ -7,3 +7,12 @@
[e.style['flex-flow'\] = "nowrap" should set the property value]
expected: FAIL
[e.style['flex-flow'\] = "row nowrap" should set the property value]
expected: FAIL
[e.style['flex-flow'\] = "wrap" should set the property value]
expected: FAIL
[e.style['flex-flow'\] = "row wrap" should set the property value]
expected: FAIL

View file

@ -0,0 +1,2 @@
[separators.html]
expected: FAIL

View file

@ -0,0 +1,2 @@
[text-combine-emphasis.html]
expected: FAIL

View file

@ -0,0 +1,2 @@
[object-replacement-1.html]
expected: FAIL

View file

@ -0,0 +1,2 @@
[object-replacement-2.html]
expected: FAIL

View file

@ -0,0 +1,93 @@
[calc-infinity-nan-serialize-number.html]
['calc(NaN)' as a specified value should serialize as 'calc(NaN)'.]
expected: FAIL
['calc(infinity)' as a specified value should serialize as 'calc(infinity)'.]
expected: FAIL
['calc(-infinity)' as a specified value should serialize as 'calc(-infinity)'.]
expected: FAIL
['calc(1 * NaN)' as a specified value should serialize as 'calc(NaN)'.]
expected: FAIL
['calc(1 * nan)' as a specified value should serialize as 'calc(NaN)'.]
expected: FAIL
['calc(1 * infinity / infinity)' as a specified value should serialize as 'calc(NaN)'.]
expected: FAIL
['calc(1 * 0 * infinity)' as a specified value should serialize as 'calc(NaN)'.]
expected: FAIL
['calc(1 * (infinity + -infinity))' as a specified value should serialize as 'calc(NaN)'.]
expected: FAIL
['calc(1 * (-infinity + infinity))' as a specified value should serialize as 'calc(NaN)'.]
expected: FAIL
['calc(1 * (infinity - infinity))' as a specified value should serialize as 'calc(NaN)'.]
expected: FAIL
['calc(1 * infinity)' as a specified value should serialize as 'calc(infinity)'.]
expected: FAIL
['calc(1 * -infinity)' as a specified value should serialize as 'calc(-infinity)'.]
expected: FAIL
['calc(1 * iNFinIty)' as a specified value should serialize as 'calc(infinity)'.]
expected: FAIL
['calc(1 * (infinity + infinity))' as a specified value should serialize as 'calc(infinity)'.]
expected: FAIL
['calc(1 * (-infinity + -infinity))' as a specified value should serialize as 'calc(-infinity)'.]
expected: FAIL
['calc(1 * 1/infinity)' as a specified value should serialize as 'calc(0)'.]
expected: FAIL
['calc(1 * infinity * infinity)' as a specified value should serialize as 'calc(infinity)'.]
expected: FAIL
['calc(1 * -infinity * -infinity)' as a specified value should serialize as 'calc(infinity)'.]
expected: FAIL
['calc(1 * max(INFinity*3, 0))' as a specified value should serialize as 'calc(infinity)'.]
expected: FAIL
['calc(1 * min(inFInity*4, 0))' as a specified value should serialize as 'calc(0)'.]
expected: FAIL
['calc(1 * max(nAn*2, 0))' as a specified value should serialize as 'calc(NaN)'.]
expected: FAIL
['calc(1 * min(nan*3, 0))' as a specified value should serialize as 'calc(NaN)'.]
expected: FAIL
['calc(1 * clamp(-INFINITY*20, 0, infiniTY*10))' as a specified value should serialize as 'calc(0)'.]
expected: FAIL
['calc(1 * max(NaN, min(0,10)))' as a specified value should serialize as 'calc(NaN)'.]
expected: FAIL
['calc(1 * clamp(NaN, 0, 10))' as a specified value should serialize as 'calc(NaN)'.]
expected: FAIL
['calc(1 * max(0, min(10, NaN)))' as a specified value should serialize as 'calc(NaN)'.]
expected: FAIL
['calc(1 * clamp(0, 10, NaN))' as a specified value should serialize as 'calc(NaN)'.]
expected: FAIL
['calc(1 * max(0, min(NaN, 10)))' as a specified value should serialize as 'calc(NaN)'.]
expected: FAIL
['calc(1 * clamp(0, NaN, 10))' as a specified value should serialize as 'calc(NaN)'.]
expected: FAIL
['calc(1 * clamp(-Infinity, 0, infinity))' as a specified value should serialize as 'calc(0)'.]
expected: FAIL
['calc(1 * clamp(-inFinity, infinity, 10))' as a specified value should serialize as 'calc(10)'.]
expected: FAIL

View file

@ -0,0 +1,3 @@
[calc-linear-radial-conic-gradient-001.html]
[testing background-image: conic-gradient(rgb(0, 128, 0) calc(50% + 10%), rgb(0, 0, 255) calc(60% + 20%))]
expected: FAIL

View file

@ -0,0 +1,6 @@
[getComputedStyle-calc-mixed-units-002.html]
[testing width: calc(5% + 4rem)]
expected: FAIL
[testing width: calc(8lh + 7px)]
expected: FAIL

View file

@ -32,3 +32,12 @@
[customElements.define must not throw when defining another custom element in a different global object during Get(constructor, "prototype")]
expected: FAIL
[customElements.getName must return null when the registry does not contain an entry with the given constructor]
expected: FAIL
[customElements.getName returns the name of the entry with the given constructor when there is a matching entry.]
expected: FAIL
[customElements.getName returns the name of the entry with the given customized built in constructor when there is a matching entry.]
expected: FAIL

View file

@ -0,0 +1,3 @@
[basic-dom-part-objects.tentative.html]
[Basic imperative DOM Parts object construction]
expected: FAIL

View file

@ -1,3 +1,4 @@
[keepalive.any.html]
expected: TIMEOUT
[keepalive in onunload in nested frame in another window]
expected: FAIL

View file

@ -0,0 +1,2 @@
[cors-keepalive.any.html]
expected: TIMEOUT

View file

@ -1,4 +1,5 @@
[redirect-keepalive.any.html]
expected: TIMEOUT
[[keepalive\][new window\][unload\] same-origin redirect]
expected: FAIL

View file

@ -0,0 +1,120 @@
[fenced-frame-subresource-fetch.tentative.https.window.html?include=from-private]
[private to local: failed preflight.]
expected: FAIL
[private to local: missing CORS headers on preflight response.]
expected: FAIL
[private to local: missing PNA header on preflight response.]
expected: FAIL
[private to local: missing CORS headers on final response.]
expected: FAIL
[private to local: success.]
expected: FAIL
[private to local: PUT success.]
expected: FAIL
[private to local: no-CORS mode failed preflight.]
expected: FAIL
[private to local: no-CORS mode missing CORS headers on preflight response.]
expected: FAIL
[private to local: no-CORS mode missing PNA header on preflight response.]
expected: FAIL
[private to local: no-CORS mode success.]
expected: FAIL
[private to private: no preflight required.]
expected: FAIL
[private to public: no preflight required.]
expected: FAIL
[fenced-frame-subresource-fetch.tentative.https.window.html?include=from-local]
[local to local: no preflight required.]
expected: FAIL
[local to private: no preflight required.]
expected: FAIL
[local to public: no preflight required.]
expected: FAIL
[fenced-frame-subresource-fetch.tentative.https.window.html?include=from-public]
[public to local: failed preflight.]
expected: FAIL
[public to local: missing CORS headers on preflight response.]
expected: FAIL
[public to local: missing PNA header on preflight response.]
expected: FAIL
[public to local: missing CORS headers on final response.]
expected: FAIL
[public to local: success.]
expected: FAIL
[public to local: PUT success.]
expected: FAIL
[public to local: no-CORS mode failed preflight.]
expected: FAIL
[public to local: no-CORS mode missing CORS headers on preflight response.]
expected: FAIL
[public to local: no-CORS mode missing PNA header on preflight response.]
expected: FAIL
[public to local: no-CORS mode success.]
expected: FAIL
[public to private: failed preflight.]
expected: FAIL
[public to private: missing CORS headers on preflight response.]
expected: FAIL
[public to private: missing PNA header on preflight response.]
expected: FAIL
[public to private: missing CORS headers on final response.]
expected: FAIL
[public to private: success.]
expected: FAIL
[public to private: PUT success.]
expected: FAIL
[public to private: no-CORS mode failed preflight.]
expected: FAIL
[public to private: no-CORS mode missing CORS headers on preflight response.]
expected: FAIL
[public to private: no-CORS mode missing PNA header on preflight response.]
expected: FAIL
[public to private: no-CORS mode success.]
expected: FAIL
[public to public: no preflight required.]
expected: FAIL
[fenced-frame-subresource-fetch.tentative.https.window.html?include=baseline]
[local to public: PUT preflight failure.]
expected: FAIL
[local to public: PUT preflight success.]
expected: FAIL

View file

@ -0,0 +1,87 @@
[fenced-frame.tentative.https.window.html]
[local to local: no preflight required.]
expected: FAIL
[local to private: no preflight required.]
expected: FAIL
[local to public: no preflight required.]
expected: FAIL
[private to local: failed preflight.]
expected: FAIL
[private to local: missing CORS headers.]
expected: FAIL
[private to local: missing PNA header.]
expected: FAIL
[private to local: failed because fenced frames are incompatible with PNA.]
expected: FAIL
[private to private: no preflight required.]
expected: FAIL
[private to public: no preflight required.]
expected: FAIL
[public to local: failed preflight.]
expected: FAIL
[public to local: missing CORS headers.]
expected: FAIL
[public to local: missing PNA header.]
expected: FAIL
[public to local: failed because fenced frames are incompatible with PNA.]
expected: FAIL
[public to private: failed preflight.]
expected: FAIL
[public to private: missing CORS headers.]
expected: FAIL
[public to private: missing PNA header.]
expected: FAIL
[public to private: failed because fenced frames are incompatible with PNA.]
expected: FAIL
[public to public: no preflight required.]
expected: FAIL
[treat-as-public-address to local: failed preflight.]
expected: FAIL
[treat-as-public-address to local: missing CORS headers.]
expected: FAIL
[treat-as-public-address to local: missing PNA header.]
expected: FAIL
[treat-as-public-address to local: failed because fenced frames are incompatible with PNA.]
expected: FAIL
[treat-as-public-address to local (same-origin): fenced frame embedder initiated navigation has opaque origin.]
expected: FAIL
[treat-as-public-address to private: failed preflight.]
expected: FAIL
[treat-as-public-address to private: missing CORS headers.]
expected: FAIL
[treat-as-public-address to private: missing PNA header.]
expected: FAIL
[treat-as-public-address to private: failed because fenced frames are incompatible with PNA.]
expected: FAIL
[treat-as-public-address to public: no preflight required.]
expected: FAIL
[treat-as-public-address to local: optional preflight]
expected: FAIL

View file

@ -44,3 +44,54 @@
[treat-as-public to local (same-origin): no preflight required.]
expected: NOTRUN
[service-worker-fetch.https.window.html?9-last]
expected: TIMEOUT
[public to public: success.]
expected: TIMEOUT
[treat-as-public to local: failed preflight.]
expected: NOTRUN
[treat-as-public to local: success.]
expected: NOTRUN
[treat-as-public to local (same-origin): no preflight required.]
expected: NOTRUN
[treat-as-public to private: failed preflight.]
expected: NOTRUN
[treat-as-public to private: success.]
expected: NOTRUN
[treat-as-public to public: success.]
expected: NOTRUN
[service-worker-fetch.https.window.html?1-8]
expected: TIMEOUT
[local to local: success.]
expected: TIMEOUT
[private to local: failed preflight.]
expected: NOTRUN
[private to local: success.]
expected: NOTRUN
[private to private: success.]
expected: NOTRUN
[public to local: failed preflight.]
expected: NOTRUN
[public to local: success.]
expected: NOTRUN
[public to private: failed preflight.]
expected: NOTRUN
[public to private: success.]
expected: NOTRUN

View file

@ -5,9 +5,6 @@
[private to local: failure.]
expected: FAIL
[private to private: success.]
expected: FAIL
[public to local: failure.]
expected: FAIL

View file

@ -1,7 +1,6 @@
[consecutive-srcdoc.html]
expected: TIMEOUT
[changing srcdoc does a replace navigation since the URL is still about:srcdoc]
expected: FAIL
[changing srcdoc to about:srcdoc#yo then another srcdoc does two push navigations and we can navigate back]
expected: TIMEOUT
expected: FAIL

View file

@ -1,13 +1,12 @@
[failure-check-sequence.https.html]
expected: TIMEOUT
[CSP check precedes COEP check - CSP header first]
expected: NOTRUN
expected: FAIL
[COEP check precedes X-Frame-Options check]
expected: NOTRUN
expected: FAIL
[CSP check precedes COEP check - COEP header first]
expected: NOTRUN
expected: FAIL
[CSP check precedes X-Frame-Options check]
expected: TIMEOUT
expected: FAIL

View file

@ -1,9 +1,10 @@
[iframe-src-aboutblank-navigate-immediately.html]
expected: TIMEOUT
[Navigating to a different document with window.open]
expected: FAIL
[Navigating to a different document with link click]
expected: FAIL
expected: TIMEOUT
[Navigating to a different document with form submission]
expected: FAIL
expected: NOTRUN

View file

@ -1,3 +1,6 @@
[navigate-to-unparseable-url.html]
[location.href setter throws a SyntaxError DOMException for unparseable URLs]
expected: FAIL
[<a> tag navigate fails for unparseable URLs]
expected: FAIL

View file

@ -0,0 +1,3 @@
[navigation-unload-cross-origin.sub.window.html]
[Cross-origin navigation started from unload handler must be ignored]
expected: FAIL

View file

@ -1,3 +0,0 @@
[navigation-unload-same-origin-fragment.html]
[Tests that a fragment navigation in the unload handler will not block the initial navigation]
expected: FAIL

View file

@ -1,3 +0,0 @@
[navigation-unload-same-origin.window.html]
[Same-origin navigation started from unload handler must be ignored]
expected: FAIL

View file

@ -1,3 +0,0 @@
[a-click.html]
[aElement.click() before the load event must NOT replace]
expected: FAIL

View file

@ -1,4 +0,0 @@
[traverse-during-unload.html]
expected: TIMEOUT
[Traversing the history during unload]
expected: TIMEOUT

View file

@ -1,3 +0,0 @@
[navigate-to-about-blank-while-initial-load-pending.html]
[Navigating to about:blank while window.open initial load pending.]
expected: FAIL

View file

@ -1,7 +1,6 @@
[update-the-rendering.html]
expected: TIMEOUT
["Flush autofocus candidates" should be happen after the first animation frame callbacks, and before a resize event in the next iteration of window event loop.]
expected: TIMEOUT
["Flush autofocus candidates" should be happen before a scroll event and animation frame callbacks]
expected: TIMEOUT
expected: FAIL

View file

@ -18,3 +18,41 @@
[redirected to cross-origin HTMLVideoElement: Setting fillStyle to an origin-unclear pattern makes the canvas origin-unclean]
expected: NOTRUN
[cross-origin SVGImageElement: Setting fillStyle to an origin-unclean pattern makes the canvas origin-unclean]
expected: TIMEOUT
[cross-origin HTMLVideoElement: Setting fillStyle to an origin-unclean pattern makes the canvas origin-unclean]
expected: NOTRUN
[redirected to cross-origin HTMLVideoElement: Setting fillStyle to an origin-unclean pattern makes the canvas origin-unclean]
expected: NOTRUN
[redirected to same-origin HTMLVideoElement: Setting fillStyle to an origin-unclean pattern makes the canvas origin-unclean]
expected: NOTRUN
[unclean HTMLCanvasElement: Setting fillStyle to an origin-unclean pattern makes the canvas origin-unclean]
expected: NOTRUN
[unclean ImageBitmap: Setting fillStyle to an origin-unclean pattern makes the canvas origin-unclean]
expected: NOTRUN
[cross-origin HTMLImageElement: Setting fillStyle to an origin-unclean offscreen canvas pattern makes the canvas origin-unclean]
expected: NOTRUN
[cross-origin SVGImageElement: Setting fillStyle to an origin-unclean offscreen canvas pattern makes the canvas origin-unclean]
expected: NOTRUN
[cross-origin HTMLVideoElement: Setting fillStyle to an origin-unclean offscreen canvas pattern makes the canvas origin-unclean]
expected: NOTRUN
[redirected to cross-origin HTMLVideoElement: Setting fillStyle to an origin-unclean offscreen canvas pattern makes the canvas origin-unclean]
expected: NOTRUN
[redirected to same-origin HTMLVideoElement: Setting fillStyle to an origin-unclean offscreen canvas pattern makes the canvas origin-unclean]
expected: NOTRUN
[unclean HTMLCanvasElement: Setting fillStyle to an origin-unclean offscreen canvas pattern makes the canvas origin-unclean]
expected: NOTRUN
[unclean ImageBitmap: Setting fillStyle to an origin-unclean offscreen canvas pattern makes the canvas origin-unclean]
expected: NOTRUN

View file

@ -1,5 +1,4 @@
[iframe_sandbox_popups_nonescaping-2.html]
type: testharness
expected: TIMEOUT
[Check that popups from a sandboxed iframe do not escape the sandbox]
expected: NOTRUN
expected: FAIL

View file

@ -1,4 +0,0 @@
[reparent-form-during-planned-navigation-task.html]
expected: TIMEOUT
[reparent-form-during-planned-navigation-task]
expected: TIMEOUT

View file

@ -0,0 +1,9 @@
[pattern_attribute_v_flag.html]
[<input pattern> supports set difference syntax]
expected: FAIL
[<input pattern> supports string literal syntax]
expected: FAIL
[<input pattern> enables the RegExp v flag]
expected: FAIL

View file

@ -7,3 +7,6 @@
[mutually exclusive details across multiple names and multiple tree scopes]
expected: FAIL
[mutation event and toggle event order matches order of insertion in set of named elements]
expected: FAIL

View file

@ -1,3 +0,0 @@
[DOMContentLoaded-defer.html]
[The end: DOMContentLoaded and defer scripts]
expected: FAIL

View file

@ -3,6 +3,3 @@
expected: TIMEOUT
[The incumbent settings object while executing the compiled callback via Web IDL's invoke must be that of the node document]
expected: TIMEOUT
[The entry settings object while executing the compiled callback via Web IDL's invoke must be that of the node document]
expected: FAIL

View file

@ -1,10 +1,9 @@
[promise-job-entry-different-function-realm.html]
expected: TIMEOUT
[Fulfillment handler on fulfilled promise]
expected: FAIL
[Rejection handler on pending-then-rejected promise]
expected: TIMEOUT
expected: FAIL
[Thenable resolution]
expected: FAIL
@ -13,4 +12,4 @@
expected: FAIL
[Fulfillment handler on pending-then-fulfilled promise]
expected: TIMEOUT
expected: FAIL

View file

@ -1,5 +1,4 @@
[promise-job-entry.html]
expected: TIMEOUT
[Fulfillment handler on fulfilled promise]
expected: FAIL
@ -7,7 +6,7 @@
expected: FAIL
[Sanity check: this all works as expected with no promises involved]
expected: TIMEOUT
expected: FAIL
[Thenable resolution]
expected: FAIL

View file

@ -0,0 +1,171 @@
[from.any.serviceworker.html]
expected: ERROR
[from.any.html]
[ReadableStream.from accepts an array of values]
expected: FAIL
[ReadableStream.from accepts an array of promises]
expected: FAIL
[ReadableStream.from accepts an array iterator]
expected: FAIL
[ReadableStream.from accepts a string]
expected: FAIL
[ReadableStream.from accepts a Set]
expected: FAIL
[ReadableStream.from accepts a Set iterator]
expected: FAIL
[ReadableStream.from accepts a sync generator]
expected: FAIL
[ReadableStream.from accepts an async generator]
expected: FAIL
[ReadableStream.from accepts a sync iterable of values]
expected: FAIL
[ReadableStream.from accepts a sync iterable of promises]
expected: FAIL
[ReadableStream.from accepts an async iterable]
expected: FAIL
[ReadableStream.from accepts a ReadableStream]
expected: FAIL
[ReadableStream.from accepts a ReadableStream async iterator]
expected: FAIL
[ReadableStream.from re-throws errors from calling the @@iterator method]
expected: FAIL
[ReadableStream.from re-throws errors from calling the @@asyncIterator method]
expected: FAIL
[ReadableStream.from ignores @@iterator if @@asyncIterator exists]
expected: FAIL
[ReadableStream.from accepts an empty iterable]
expected: FAIL
[ReadableStream.from: stream errors when next() rejects]
expected: FAIL
[ReadableStream.from: stream stalls when next() never settles]
expected: FAIL
[ReadableStream.from: calls next() after first read()]
expected: FAIL
[ReadableStream.from: cancelling the returned stream calls and awaits return()]
expected: FAIL
[ReadableStream.from: return() is not called when iterator completes normally]
expected: FAIL
[ReadableStream.from: cancel() rejects when return() fulfills with a non-object]
expected: FAIL
[ReadableStream.from: reader.read() inside next()]
expected: FAIL
[ReadableStream.from: reader.cancel() inside next()]
expected: FAIL
[ReadableStream.from: reader.cancel() inside return()]
expected: FAIL
[ReadableStream.from(array), push() to array while reading]
expected: FAIL
[from.any.worker.html]
[ReadableStream.from accepts an array of values]
expected: FAIL
[ReadableStream.from accepts an array of promises]
expected: FAIL
[ReadableStream.from accepts an array iterator]
expected: FAIL
[ReadableStream.from accepts a string]
expected: FAIL
[ReadableStream.from accepts a Set]
expected: FAIL
[ReadableStream.from accepts a Set iterator]
expected: FAIL
[ReadableStream.from accepts a sync generator]
expected: FAIL
[ReadableStream.from accepts an async generator]
expected: FAIL
[ReadableStream.from accepts a sync iterable of values]
expected: FAIL
[ReadableStream.from accepts a sync iterable of promises]
expected: FAIL
[ReadableStream.from accepts an async iterable]
expected: FAIL
[ReadableStream.from accepts a ReadableStream]
expected: FAIL
[ReadableStream.from accepts a ReadableStream async iterator]
expected: FAIL
[ReadableStream.from re-throws errors from calling the @@iterator method]
expected: FAIL
[ReadableStream.from re-throws errors from calling the @@asyncIterator method]
expected: FAIL
[ReadableStream.from ignores @@iterator if @@asyncIterator exists]
expected: FAIL
[ReadableStream.from accepts an empty iterable]
expected: FAIL
[ReadableStream.from: stream errors when next() rejects]
expected: FAIL
[ReadableStream.from: stream stalls when next() never settles]
expected: FAIL
[ReadableStream.from: calls next() after first read()]
expected: FAIL
[ReadableStream.from: cancelling the returned stream calls and awaits return()]
expected: FAIL
[ReadableStream.from: return() is not called when iterator completes normally]
expected: FAIL
[ReadableStream.from: cancel() rejects when return() fulfills with a non-object]
expected: FAIL
[ReadableStream.from: reader.read() inside next()]
expected: FAIL
[ReadableStream.from: reader.cancel() inside next()]
expected: FAIL
[ReadableStream.from: reader.cancel() inside return()]
expected: FAIL
[ReadableStream.from(array), push() to array while reading]
expected: FAIL
[from.any.sharedworker.html]
expected: ERROR

View file

@ -1,5 +1,4 @@
[audiocontext-not-fully-active.html]
expected: TIMEOUT
[frame in navigated remote-site frame]
expected: FAIL

View file

@ -0,0 +1,3 @@
[audioworklet-denormals.https.window.html]
[Test denormal behavior in AudioWorkletGlobalScope]
expected: FAIL

View file

@ -0,0 +1,4 @@
[017.html]
expected: TIMEOUT
[origin of the script that invoked the method, about:blank]
expected: TIMEOUT

View file

@ -0,0 +1,4 @@
[018.html]
expected: TIMEOUT
[origin of the script that invoked the method, javascript:]
expected: TIMEOUT

View file

@ -0,0 +1,4 @@
[017.html]
expected: TIMEOUT
[origin of the script that invoked the method, about:blank]
expected: TIMEOUT

View file

@ -0,0 +1,4 @@
[018.html]
expected: TIMEOUT
[origin of the script that invoked the method, javascript:]
expected: TIMEOUT

View file

@ -0,0 +1,4 @@
[localstorage-about-blank-3P-iframe-opens-3P-window.partitioned.tentative.html]
expected: TIMEOUT
[StorageKey: test 3P about:blank window opened from a 3P iframe]
expected: TIMEOUT

View file

@ -0,0 +1,2 @@
[Worker-constructor.html]
expected: ERROR

View file

@ -0,0 +1,8 @@
<!DOCTYPE html>
<div>
<div role="combobox">
<input id="textfield" role="textbox" aria-hidden="true" tabindex="-1" aria-readonly="true" aria-label="foo" aria-autocomplete="both">
<div role="listbox">
</div>
</div>
</div>

View file

@ -0,0 +1,18 @@
<!doctype HTML>
<style>
article::after {
content: url(data:text/plain,test);}
</style>
This test passes if it does not crash.
<img usemap="#map2">
<map id=map name="map2">
<command id=command>
<article id=article ></article>
</command>
</map>
<script>
command.appendChild(article);
requestAnimationFrame(() => requestAnimationFrame(() => {
map.style.content = "none";
}));
</script>

View file

@ -0,0 +1,51 @@
<!doctype html>
<meta charset=utf-8>
<meta name=timeout content=long>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="/attribution-reporting/resources/helpers.js"></script>
<script>
attribution_reporting_promise_test(async t => {
const host = 'https://{{host}}';
const expectedSourceEventId = generateSourceEventId();
const expectedSourceDebugKey = '456';
const expectedTriggerDebugKey = '654';
registerAttributionSrcByImg(createRedirectChain([
{
cookie: attributionDebugCookie,
source: {
aggregation_keys: {
campaignCounts: '0x159',
},
debug_key: expectedSourceDebugKey,
destination: host,
source_event_id: expectedSourceEventId,
},
},
{
trigger : {
aggregatable_values: {
geoValue: 32768,
},
debug_key: expectedTriggerDebugKey,
debug_reporting: true,
},
},
]));
const debugPayload = await pollVerboseDebugReports();
assert_equals(debugPayload.reports.length, 1);
const debugReport = JSON.parse(debugPayload.reports[0].body);
assert_equals(debugReport.length, 1);
assert_equals(debugReport[0].type, 'trigger-aggregate-no-contributions');
assert_own_property(debugReport[0], 'body');
const debugReportBody = debugReport[0].body;
assert_equals(debugReportBody.attribution_destination, host);
assert_equals(debugReportBody.source_event_id, expectedSourceEventId);
assert_equals(debugReportBody.source_site, host);
assert_equals(debugReportBody.source_debug_key, expectedSourceDebugKey);
assert_equals(debugReportBody.trigger_debug_key, expectedTriggerDebugKey);
}, 'Aggregatable report is not created due to no contributions.');
</script>

View file

@ -0,0 +1,66 @@
<!doctype html>
<meta charset=utf-8>
<meta name=timeout content=long>
<meta name=variant content="?method=a&expected-eligible=navigation-source">
<meta name=variant content="?method=img&expected-eligible=event-source, trigger">
<meta name=variant content="?method=img&eligible&expected-eligible=event-source, trigger">
<meta name=variant content="?method=open&expected-eligible=navigation-source">
<meta name=variant content="?method=script&expected-eligible=event-source, trigger">
<meta name=variant content="?method=script&eligible&expected-eligible=event-source, trigger">
<meta name=variant content="?method=fetch">
<meta name=variant content='?method=fetch&eligible={"eventSourceEligible":true,"triggerEligible":false}&expected-eligible=event-source'>
<meta name=variant content="?method=xhr">
<meta name=variant content='?method=xhr&eligible={"eventSourceEligible":true,"triggerEligible":false}&expected-eligible=event-source'>
<script src="/resources/testdriver.js"></script>
<script src="/resources/testdriver-vendor.js"></script>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="resources/helpers.js"></script>
<body>
<script>
const waitForRequest = async () => {
const url = blankURL();
url.searchParams.set('get-requests', 'true');
for (let i = 0; i < 20; i++) {
const resp = await fetch(url);
const payload = await resp.json();
if (payload !== null && payload.length > 0) {
return payload;
}
await delay(100);
}
throw new Error('Timeout polling requests');
};
const searchParams = new URLSearchParams(location.search);
const expected_eligible =
searchParams.get('expected-eligible') === null ? undefined : searchParams.get('expected-eligible');
promise_test(async t => {
// Set mixed-case query params to ensure that they are propagated correctly.
await registerAttributionSrc({
method: 'variant',
extraQueryParams: {'aB': 'Cd', 'store-request': 'true'},
});
const requests = await waitForRequest();
assert_equals(requests.length, 1);
assert_equals(requests[0].method, 'GET');
// TODO(apaseltiner): Check header values once WPT can parse structured dictionaries.
if (expected_eligible) {
assert_own_property(requests[0], 'attribution-reporting-eligible');
} else {
assert_not_own_property(requests[0], 'attribution-reporting-eligible');
}
assert_equals(requests[0].referer, location.toString());
// TODO(apaseltiner): Test various referrer policies.
// TODO(apaseltiner): Test cookie propagation.
const expectedURL = blankURL();
expectedURL.searchParams.set('aB', 'Cd');
expectedURL.searchParams.set('store-request', 'true');
assert_equals(requests[0].url, expectedURL.toString());
}, 'attributionsrc request has the proper format.');
</script>

View file

@ -0,0 +1,360 @@
/**
* Helper functions for attribution reporting API tests.
*/
const blankURL = (base = location.origin) => new URL('/attribution-reporting/resources/reporting_origin.py', base);
const attribution_reporting_promise_test = (f, name) =>
promise_test(async t => {
await resetWptServer();
return f(t);
}, name);
const resetWptServer = () =>
Promise
.all([
resetAttributionReports(eventLevelReportsUrl),
resetAttributionReports(aggregatableReportsUrl),
resetAttributionReports(eventLevelDebugReportsUrl),
resetAttributionReports(aggregatableDebugReportsUrl),
resetAttributionReports(verboseDebugReportsUrl),
resetRegisteredSources(),
]);
const eventLevelReportsUrl =
'/.well-known/attribution-reporting/report-event-attribution';
const eventLevelDebugReportsUrl =
'/.well-known/attribution-reporting/debug/report-event-attribution';
const aggregatableReportsUrl =
'/.well-known/attribution-reporting/report-aggregate-attribution';
const aggregatableDebugReportsUrl =
'/.well-known/attribution-reporting/debug/report-aggregate-attribution';
const verboseDebugReportsUrl =
'/.well-known/attribution-reporting/debug/verbose';
const attributionDebugCookie = 'ar_debug=1;Secure;HttpOnly;SameSite=None;Path=/';
const pipeHeaderPattern = /[,)]/g;
// , and ) in pipe values must be escaped with \
const encodeForPipe = urlString => urlString.replace(pipeHeaderPattern, '\\$&');
const blankURLWithHeaders = (headers, origin, status) => {
const url = blankURL(origin);
const parts = headers.map(h => `header(${h.name},${encodeForPipe(h.value)})`);
if (status !== undefined) {
parts.push(`status(${encodeForPipe(status)})`);
}
if (parts.length > 0) {
url.searchParams.set('pipe', parts.join('|'));
}
return url;
};
/**
* Clears the source registration stash.
*/
const resetRegisteredSources = () => {
return fetch(`${blankURL()}?clear-stash=true`);
}
/**
* Method to clear the stash. Takes the URL as parameter. This could be for
* event-level or aggregatable reports.
*/
const resetAttributionReports = url => {
// The view of the stash is path-specific (https://web-platform-tests.org/tools/wptserve/docs/stash.html),
// therefore the origin doesn't need to be specified.
url = `${url}?clear_stash=true`;
const options = {
method: 'POST',
};
return fetch(url, options);
};
const redirectReportsTo = origin => {
return Promise.all([
fetch(`${eventLevelReportsUrl}?redirect_to=${origin}`, {method: 'POST'}),
fetch(`${aggregatableReportsUrl}?redirect_to=${origin}`, {method: 'POST'})
]);
};
const getFetchParams = (origin, cookie) => {
let credentials;
const headers = [];
if (!origin || origin === location.origin) {
return {credentials, headers};
}
// https://fetch.spec.whatwg.org/#http-cors-protocol
const allowOriginHeader = 'Access-Control-Allow-Origin';
const allowHeadersHeader = 'Access-Control-Allow-Headers';
if (cookie) {
credentials = 'include';
headers.push({
name: 'Access-Control-Allow-Credentials',
value: 'true',
});
headers.push({
name: allowOriginHeader,
value: `${location.origin}`,
});
} else {
headers.push({
name: allowOriginHeader,
value: '*',
});
headers.push({
name: allowHeadersHeader,
value: '*',
})
}
return {credentials, headers};
};
const getDefaultReportingOrigin = () => {
// cross-origin means that the reporting origin differs from the source/destination origin.
const crossOrigin = new URLSearchParams(location.search).get('cross-origin');
return crossOrigin === null ? location.origin : get_host_info().HTTPS_REMOTE_ORIGIN;
};
const createRedirectChain = (redirects) => {
let redirectTo;
for (let i = redirects.length - 1; i >= 0; i--) {
const {source, trigger, cookie, reportingOrigin} = redirects[i];
const headers = [];
if (source) {
headers.push({
name: 'Attribution-Reporting-Register-Source',
value: JSON.stringify(source),
});
}
if (trigger) {
headers.push({
name: 'Attribution-Reporting-Register-Trigger',
value: JSON.stringify(trigger),
});
}
if (cookie) {
headers.push({name: 'Set-Cookie', value: cookie});
}
let status;
if (redirectTo) {
headers.push({name: 'Location', value: redirectTo.toString()});
status = '302';
}
redirectTo = blankURLWithHeaders(
headers, reportingOrigin || getDefaultReportingOrigin(), status);
}
return redirectTo;
};
const registerAttributionSrcByImg = (attributionSrc) => {
const element = document.createElement('img');
element.attributionSrc = attributionSrc;
};
const registerAttributionSrc = async ({
source,
trigger,
cookie,
method = 'img',
extraQueryParams = {},
reportingOrigin,
}) => {
const searchParams = new URLSearchParams(location.search);
if (method === 'variant') {
method = searchParams.get('method');
}
const eligible = searchParams.get('eligible');
let headers = [];
if (source) {
headers.push({
name: 'Attribution-Reporting-Register-Source',
value: JSON.stringify(source),
});
}
if (trigger) {
headers.push({
name: 'Attribution-Reporting-Register-Trigger',
value: JSON.stringify(trigger),
});
}
if (cookie) {
const name = 'Set-Cookie';
headers.push({name, value: cookie});
}
let credentials;
if (method === 'fetch') {
const params = getFetchParams(reportingOrigin, cookie);
credentials = params.credentials;
headers = headers.concat(params.headers);
}
const url = blankURLWithHeaders(headers, reportingOrigin);
Object.entries(extraQueryParams)
.forEach(([key, value]) => url.searchParams.set(key, value));
switch (method) {
case 'img':
const img = document.createElement('img');
if (eligible === null) {
img.attributionSrc = url;
} else {
await new Promise(resolve => {
img.onload = resolve;
// Since the resource being fetched isn't a valid image, onerror will
// be fired, but the browser will still process the
// attribution-related headers, so resolve the promise instead of
// rejecting.
img.onerror = resolve;
img.attributionSrc = '';
img.src = url;
});
}
return 'event';
case 'script':
const script = document.createElement('script');
if (eligible === null) {
script.attributionSrc = url;
} else {
await new Promise(resolve => {
script.onload = resolve;
script.attributionSrc = '';
script.src = url;
document.body.appendChild(script);
});
}
return 'event';
case 'a':
const a = document.createElement('a');
a.target = '_blank';
a.textContent = 'link';
if (eligible === null) {
a.attributionSrc = url;
a.href = blankURL();
} else {
a.attributionSrc = '';
a.href = url;
}
document.body.appendChild(a);
await test_driver.click(a);
return 'navigation';
case 'open':
await test_driver.bless('open window', () => {
if (eligible === null) {
open(
blankURL(), '_blank',
`attributionsrc=${encodeURIComponent(url)}`);
} else {
open(url, '_blank', 'attributionsrc');
}
});
return 'navigation';
case 'fetch': {
let attributionReporting;
if (eligible !== null) {
attributionReporting = JSON.parse(eligible);
}
await fetch(url, {credentials, attributionReporting});
return 'event';
}
case 'xhr':
await new Promise((resolve, reject) => {
const req = new XMLHttpRequest();
req.open('GET', url);
if (eligible !== null) {
req.setAttributionReporting(JSON.parse(eligible));
}
req.onload = resolve;
req.onerror = () => reject(req.statusText);
req.send();
});
return 'event';
default:
throw `unknown method "${method}"`;
}
};
/**
* Generates a random pseudo-unique source event id.
*/
const generateSourceEventId = () => {
return `${Math.round(Math.random() * 10000000000000)}`;
}
/**
* Delay method that waits for prescribed number of milliseconds.
*/
const delay = ms => new Promise(resolve => step_timeout(resolve, ms));
/**
* Method that polls a particular URL for reports. Once reports
* are received, returns the payload as promise. Returns null if the
* timeout is reached before a report is available.
*/
const pollAttributionReports = async (url, origin = location.origin, timeout = 60 * 1000 /*ms*/) => {
let startTime = performance.now();
while (performance.now() - startTime < timeout) {
const resp = await fetch(new URL(url, origin));
const payload = await resp.json();
if (payload.reports.length > 0) {
return payload;
}
await delay(/*ms=*/ 100);
}
return null;
};
// Verbose debug reporting must have been enabled on the source registration for this to work.
const waitForSourceToBeRegistered = async (sourceId, reportingOrigin) => {
const debugReportPayload = await pollVerboseDebugReports(reportingOrigin);
assert_equals(debugReportPayload.reports.length, 1);
const debugReport = JSON.parse(debugReportPayload.reports[0].body);
assert_equals(debugReport.length, 1);
assert_equals(debugReport[0].type, 'source-success');
assert_equals(debugReport[0].body.source_event_id, sourceId);
};
const pollEventLevelReports = (origin) =>
pollAttributionReports(eventLevelReportsUrl, origin);
const pollEventLevelDebugReports = (origin) =>
pollAttributionReports(eventLevelDebugReportsUrl, origin);
const pollAggregatableReports = (origin) =>
pollAttributionReports(aggregatableReportsUrl, origin);
const pollAggregatableDebugReports = (origin) =>
pollAttributionReports(aggregatableDebugReportsUrl, origin);
const pollVerboseDebugReports = (origin) =>
pollAttributionReports(verboseDebugReportsUrl, origin);
const validateReportHeaders = headers => {
assert_array_equals(headers['content-type'], ['application/json']);
assert_array_equals(headers['cache-control'], ['no-cache']);
assert_own_property(headers, 'user-agent');
assert_not_own_property(headers, 'cookie');
assert_not_own_property(headers, 'referer');
};

View file

@ -0,0 +1,65 @@
"""Test reporting origin server used for two reasons:
1. It is a workaround for lack of preflight support in the test server.
2. Stashes requests so they can be inspected by tests.
"""
from wptserve.stash import Stash
import json
REQUESTS = "9250f93f-2c05-4aae-83b9-2817b0e18b4d"
headers = [
b"attribution-reporting-eligible",
b"attribution-reporting-support",
b"referer",
]
def store_request(request) -> None:
obj = {
"method": request.method,
"url": request.url,
}
for header in headers:
value = request.headers.get(header)
if value is not None:
obj[str(header, "utf-8")] = str(value, "utf-8")
with request.server.stash.lock:
requests = request.server.stash.take(REQUESTS)
if not requests:
requests = []
requests.append(obj)
request.server.stash.put(REQUESTS, requests)
return None
def get_requests(request) -> str:
with request.server.stash.lock:
return json.dumps(request.server.stash.take(REQUESTS))
def main(request, response):
"""
For most requests, simply returns a 200. Actual source/trigger registration
headers are piped using the `pipe` query param.
If a `clear-stash` param is set, it will clear the stash.
"""
if request.GET.get(b"clear-stash"):
request.stash.take(REQUESTS)
return
# We dont want to redirect preflight requests. The cors headers are piped
# so we can simply return a 200 and redirect the following request
if request.method == "OPTIONS":
response.status = 200
return
if request.GET.get(b"get-requests"):
return get_requests(request)
if request.GET.get(b"store-request"):
store_request(request)
return ""

View file

@ -0,0 +1,32 @@
<!doctype html>
<meta charset=utf-8>
<meta name=timeout content=long>
<script src="/common/get-host-info.sub.js"></script>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="/attribution-reporting/resources/helpers.js"></script>
<script>
attribution_reporting_promise_test(async t => {
const expectedTriggerDebugKey = '456';
registerAttributionSrcByImg(createRedirectChain([
{
cookie: attributionDebugCookie,
trigger: {
debug_reporting: true,
debug_key: expectedTriggerDebugKey,
event_trigger_data: [{}],
},
},
]));
const payload = await pollVerboseDebugReports();
assert_equals(payload.reports.length, 1);
const report = JSON.parse(payload.reports[0].body);
assert_equals(report.length, 1);
assert_equals(report[0].type, 'trigger-no-matching-source');
assert_own_property(report[0], 'body');
assert_equals(report[0].body.attribution_destination, 'https://{{host}}');
assert_equals(report[0].body.trigger_debug_key, expectedTriggerDebugKey);
}, 'Verbose debug report is received.');
</script>

View file

@ -9,10 +9,15 @@ function getVideoURI(base)
var videotag = document.createElement("video");
if ( videotag.canPlayType &&
videotag.canPlayType('video/ogg; codecs="theora, vorbis"') )
if ( videotag.canPlayType )
{
extension = '.ogv';
if (videotag.canPlayType('video/webm; codecs="vp9, opus"') )
{
extension = '.webm';
} else if ( videotag.canPlayType('video/ogg; codecs="theora, vorbis"') )
{
extension = '.ogv';
}
}
return base + extension;
@ -46,10 +51,11 @@ function getAudioURI(base)
function getMediaContentType(url) {
var extension = new URL(url, location).pathname.split(".").pop();
var map = {
"mp4": "video/mp4",
"ogv": "application/ogg",
"mp3": "audio/mp3",
"oga": "application/ogg",
"mp4" : "video/mp4",
"ogv" : "application/ogg",
"webm": "video/webm",
"mp3" : "audio/mp3",
"oga" : "application/ogg",
};
return map[extension];
}

View file

@ -7,11 +7,11 @@
<body>
<script type="module">
import {default_request_options,
import {request_options_with_mediation_required,
fedcm_test} from './support/fedcm-helper.sub.js';
fedcm_test(async t => {
const cred = await navigator.credentials.get(default_request_options());
const cred = await navigator.credentials.get(request_options_with_mediation_required());
assert_equals(cred.token, 'token');
}, 'Test that COEP policy do not apply to FedCM requests');

View file

@ -7,10 +7,12 @@
<body>
<script type="module">
import {default_request_options, fedcm_test, set_fedcm_cookie} from './support/fedcm-helper.sub.js';
import {request_options_with_mediation_required,
fedcm_test,
set_fedcm_cookie} from './support/fedcm-helper.sub.js';
fedcm_test(async t => {
const cred = navigator.credentials.get(default_request_options());
const cred = navigator.credentials.get(request_options_with_mediation_required());
return promise_rejects_dom(t, "NetworkError", cred);
}, "Provider configURL should honor Content-Security-Policy.");

View file

@ -0,0 +1,33 @@
<!DOCTYPE html>
<title>Federated Credential Management API login hint tests.</title>
<link rel="help" href="https://fedidcg.github.io/FedCM">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="/service-workers/service-worker/resources/test-helpers.sub.js"></script>
<body>
<script type="module">
import {fedcm_test,
request_options_with_login_hint,
select_manifest} from './support/fedcm-helper.sub.js';
fedcm_test(async t => {
let options = request_options_with_login_hint('manifest.py', 'nomatch');
const cred = navigator.credentials.get(options);
return promise_rejects_dom(t, "NetworkError", cred);
}, "No login hint matches an account.");
fedcm_test(async t => {
let options = request_options_with_login_hint('manifest.py', 'john_doe');
const cred = await navigator.credentials.get(options);
assert_equals(cred.token, 'token');
}, "Login hint matches an account.");
fedcm_test(async t => {
let options = request_options_with_login_hint('manifest_with_two_accounts.json', 'john_doe');
await select_manifest(t, options);
const cred = await navigator.credentials.get(options);
assert_equals(cred.token, 'account_id=john_doe');
}, "Login hint matches an account from two accounts.");
</script>

View file

@ -8,10 +8,9 @@
<body>
<script type="module">
import {alt_manifest_origin,
default_request_options,
default_alt_request_options,
request_options_with_auto_reauthn,
import {request_options_with_mediation_required,
alt_request_options_with_mediation_required,
request_options_with_mediation_optional,
fedcm_test,
select_manifest,
set_fedcm_cookie} from './support/fedcm-helper.sub.js';
@ -25,24 +24,14 @@ function loadUrlInIframe(url) {
});
}
async function createIframeWithPermissionPolicyAndWaitForMessage(test, iframeUrl) {
const messageWatcher = new EventWatcher(test, window, "message");
let iframe = document.createElement("iframe");
iframe.src = iframeUrl;
iframe.allow = "identity-credentials-get";
document.body.appendChild(iframe);
const message = await messageWatcher.wait_for("message");
return message.data;
}
fedcm_test(async t => {
const cred = await navigator.credentials.get(default_request_options());
const cred = await navigator.credentials.get(request_options_with_mediation_required());
assert_equals(cred.token, "token");
}, "Successfully obtaining token should resolve the promise.");
fedcm_test(async t => {
const first = navigator.credentials.get(default_request_options());
const second = navigator.credentials.get(default_alt_request_options());
const first = navigator.credentials.get(request_options_with_mediation_required());
const second = navigator.credentials.get(alt_request_options_with_mediation_required());
// We have to call promise_rejects_dom here, because if we call it after
// the promise gets rejected, the unhandled rejection event handler is called
@ -57,35 +46,35 @@ fedcm_test(async t => {
"When there's a pending request, a second `get` call should be rejected. ");
fedcm_test(async t => {
let test_options = default_request_options();
let test_options = request_options_with_mediation_required();
test_options.identity.providers = [];
const cred = navigator.credentials.get(test_options);
return promise_rejects_js(t, TypeError, cred);
}, "Reject when provider list is empty");
fedcm_test(async t => {
let test_options = default_request_options();
let test_options = request_options_with_mediation_required();
delete test_options.identity.providers[0].configURL;
const cred = navigator.credentials.get(test_options);
return promise_rejects_js(t, TypeError, cred);
}, "Reject when configURL is missing" );
fedcm_test(async t => {
let test_options = default_request_options();
let test_options = request_options_with_mediation_required();
test_options.identity.providers[0].configURL = 'test';
const cred = navigator.credentials.get(test_options);
return promise_rejects_dom(t, "InvalidStateError", cred);
}, "Reject when configURL is invalid");
fedcm_test(async t => {
let test_options = default_request_options();
let test_options = request_options_with_mediation_required();
test_options.identity.providers[0].clientId = '';
const cred = navigator.credentials.get(test_options);
return promise_rejects_dom(t, "InvalidStateError", cred);
}, "Reject when clientId is empty");
fedcm_test(async t => {
let test_options = default_request_options();
let test_options = request_options_with_mediation_required();
assert_true("nonce" in test_options.identity.providers[0]);
delete test_options.identity.providers[0].nonce;
const cred = await navigator.credentials.get(test_options);
@ -93,7 +82,7 @@ fedcm_test(async t => {
}, "nonce is not required in FederatedIdentityProvider.");
fedcm_test(async t => {
let test_options = default_request_options();
let test_options = request_options_with_mediation_required();
delete test_options.identity.providers[0].clientId;
const cred = navigator.credentials.get(test_options);
return promise_rejects_js(t, TypeError, cred);
@ -101,7 +90,7 @@ fedcm_test(async t => {
fedcm_test(async t => {
let controller = new AbortController();
let test_options = default_request_options();
let test_options = request_options_with_mediation_required();
test_options.signal = controller.signal;
const cred = navigator.credentials.get(test_options);
controller.abort();
@ -110,24 +99,24 @@ fedcm_test(async t => {
fedcm_test(async t => {
let controller = new AbortController();
let test_options = default_request_options();
let test_options = request_options_with_mediation_required();
test_options.signal = controller.signal;
const first_cred = navigator.credentials.get(test_options);
controller.abort();
await promise_rejects_dom(t, 'AbortError', first_cred);
const second_cred = await navigator.credentials.get(default_request_options());
const second_cred = await navigator.credentials.get(request_options_with_mediation_required());
assert_equals(second_cred.token, "token");
}, "Get after abort should work");
fedcm_test(async t => {
let test_options = default_request_options('manifest-not-in-list.json');
let test_options = request_options_with_mediation_required('manifest-not-in-list.json');
const cred = navigator.credentials.get(test_options);
return promise_rejects_dom(t, 'NetworkError', cred);
}, 'Test that the promise is rejected if the manifest is not in the manifest list');
fedcm_test(async t => {
let test_options = default_request_options("manifest_redirect_accounts.json");
let test_options = request_options_with_mediation_required("manifest_redirect_accounts.json");
await select_manifest(t, test_options);
const cred = navigator.credentials.get(test_options);
@ -137,7 +126,7 @@ fedcm_test(async t => {
// legitimate IDP in order to get the list of user accounts.
fedcm_test(async t => {
let test_options = default_request_options("manifest_redirect_token.json");
let test_options = request_options_with_mediation_required("manifest_redirect_token.json");
await select_manifest(t, test_options);
const cred = navigator.credentials.get(test_options);
@ -151,7 +140,7 @@ fedcm_test(async t => {
const clear_metadata_count_path = `support/fedcm/client_metadata_clear_count.py`;
await fetch(clear_metadata_count_path);
const cred = await navigator.credentials.get(default_request_options());
const cred = await navigator.credentials.get(request_options_with_mediation_required());
assert_equals(cred.token, "token");
await new Promise(resolve => {
@ -193,7 +182,7 @@ fedcm_test(async t => {
assert_equals(query_sw_iframe.contentDocument.body.textContent, "1");
await set_fedcm_cookie();
const cred = await navigator.credentials.get(default_request_options());
const cred = await navigator.credentials.get(request_options_with_mediation_required());
assert_equals(cred.token, "token");
// Use cache buster query parameter to avoid cached response.
@ -202,57 +191,14 @@ fedcm_test(async t => {
}, 'Test that service worker cannot observe fetches performed by FedCM API');
fedcm_test(async t => {
const cred = await navigator.credentials.get(default_alt_request_options());
assert_equals(cred.token, "token");
const iframe_in_idp_scope = `${alt_manifest_origin}/\
credential-management/support/fedcm/userinfo-iframe.html`;
const message = await createIframeWithPermissionPolicyAndWaitForMessage(t, iframe_in_idp_scope);
assert_equals(message.result, "Pass");
assert_equals(message.numAccounts, 1);
assert_equals(message.firstAccountEmail, "john_doe@idp.example");
assert_equals(message.firstAccountName, "John Doe");
assert_equals(message.firstAccountGivenName, "John");
assert_equals(message.firstAccountPicture, "https://idp.example/profile/123");
}, 'Test basic User InFo API flow');
fedcm_test(async t => {
const cred = await navigator.credentials.get(default_alt_request_options());
assert_equals(cred.token, "token");
const iframe_in_idp_scope = `support/fedcm/userinfo-iframe.html`;
const message = await createIframeWithPermissionPolicyAndWaitForMessage(t, iframe_in_idp_scope);
assert_equals(message.result, "Fail");
}, 'Test that User Info API only works when invoked from iframe that is same origin as the IDP');
fedcm_test(async t => {
const cred = await navigator.credentials.get(default_alt_request_options());
assert_equals(cred.token, "token");
try {
const manifest_path = `${alt_manifest_origin}/\
credential-management/support/fedcm/manifest.py`;
const user_info = await IdentityProvider.getUserInfo({
configURL: manifest_path,
// Approved client
clientId: '123',
});
assert_unreached("Failure message");
} catch (error) {
assert_equals(error.message, "UserInfo request must be initiated from a frame that is the same origin with the provider.");
// Expect failure
}
}, 'Test that User Info API does not work in the top frame');
fedcm_test(async t => {
let test_options = request_options_with_auto_reauthn("manifest_with_single_account.json");
let test_options = request_options_with_mediation_optional("manifest_with_single_account.json");
await select_manifest(t, test_options);
// Signs in john_doe so that they will be a returning user
let cred = await navigator.credentials.get(test_options);
assert_equals(cred.token, "account_id=john_doe");
test_options = request_options_with_auto_reauthn("manifest_with_two_accounts.json");
test_options = request_options_with_mediation_optional("manifest_with_two_accounts.json");
await select_manifest(t, test_options);
// There are two accounts "Jane" and "John" returned in that order. Without

View file

@ -0,0 +1,67 @@
<!DOCTYPE html>
<title>Federated Credential Management API getUserInfo() tests.</title>
<link rel="help" href="https://fedidcg.github.io/FedCM">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<body>
<script type="module">
import {alt_manifest_origin,
alt_request_options_with_mediation_required,
fedcm_test} from './support/fedcm-helper.sub.js';
async function createIframeWithPermissionPolicyAndWaitForMessage(test, iframeUrl) {
const messageWatcher = new EventWatcher(test, window, "message");
let iframe = document.createElement("iframe");
iframe.src = iframeUrl;
iframe.allow = "identity-credentials-get";
document.body.appendChild(iframe);
const message = await messageWatcher.wait_for("message");
return message.data;
}
fedcm_test(async t => {
const cred = await navigator.credentials.get(alt_request_options_with_mediation_required());
assert_equals(cred.token, "token");
const iframe_in_idp_scope = `${alt_manifest_origin}/\
credential-management/support/fedcm/userinfo-iframe.html`;
const message = await createIframeWithPermissionPolicyAndWaitForMessage(t, iframe_in_idp_scope);
assert_equals(message.result, "Pass");
assert_equals(message.numAccounts, 1);
assert_equals(message.firstAccountEmail, "john_doe@idp.example");
assert_equals(message.firstAccountName, "John Doe");
assert_equals(message.firstAccountGivenName, "John");
assert_equals(message.firstAccountPicture, "https://idp.example/profile/123");
}, 'Test basic User InFo API flow');
fedcm_test(async t => {
const cred = await navigator.credentials.get(alt_request_options_with_mediation_required());
assert_equals(cred.token, "token");
const iframe_in_idp_scope = `support/fedcm/userinfo-iframe.html`;
const message = await createIframeWithPermissionPolicyAndWaitForMessage(t, iframe_in_idp_scope);
assert_equals(message.result, "Fail");
}, 'Test that User Info API only works when invoked from iframe that is same origin as the IDP');
fedcm_test(async t => {
const cred = await navigator.credentials.get(alt_request_options_with_mediation_required());
assert_equals(cred.token, "token");
try {
const manifest_path = `${alt_manifest_origin}/\
credential-management/support/fedcm/manifest.py`;
const user_info = await IdentityProvider.getUserInfo({
configURL: manifest_path,
// Approved client
clientId: '123',
});
assert_unreached("Failure message");
} catch (error) {
assert_equals(error.message, "UserInfo request must be initiated from a frame that is the same origin with the provider.");
// Expect failure
}
}, 'Test that User Info API does not work in the top frame');
</script>

View file

@ -29,7 +29,7 @@ export function set_alt_fedcm_cookie() {
// Returns FedCM CredentialRequestOptions for which navigator.credentials.get()
// succeeds.
export function default_request_options(manifest_filename) {
export function request_options_with_mediation_required(manifest_filename) {
if (manifest_filename === undefined) {
manifest_filename = "manifest.py";
}
@ -40,15 +40,16 @@ credential-management/support/fedcm/${manifest_filename}`;
providers: [{
configURL: manifest_path,
clientId: '1',
nonce: '2',
nonce: '2'
}]
}
},
mediation: 'required'
};
}
// Returns alternate FedCM CredentialRequestOptions for which navigator.credentials.get()
// succeeds.
export function default_alt_request_options(manifest_filename) {
export function alt_request_options_with_mediation_required(manifest_filename) {
if (manifest_filename === undefined) {
manifest_filename = "manifest.py";
}
@ -59,19 +60,20 @@ credential-management/support/fedcm/${manifest_filename}`;
providers: [{
configURL: manifest_path,
clientId: '1',
nonce: '2',
nonce: '2'
}]
}
},
mediation: 'required'
};
}
// Returns FedCM CredentialRequestOptions with auto re-authentication.
// succeeds.
export function request_options_with_auto_reauthn(manifest_filename) {
let options = default_request_options(manifest_filename);
export function request_options_with_mediation_optional(manifest_filename) {
let options = alt_request_options_with_mediation_required(manifest_filename);
// Approved client
options.identity.providers[0].clientId = '123';
options.identity.autoReauthn = true;
options.mediation = 'optional';
return options;
}
@ -108,3 +110,10 @@ export function select_manifest(test, test_options) {
const manifest_url = test_options.identity.providers[0].configURL;
return select_manifest_impl(manifest_url);
}
export function request_options_with_login_hint(manifest_filename, login_hint) {
let options = request_options_with_mediation_required(manifest_filename);
options.identity.providers[0].loginHint = login_hint;
return options;
}

View file

@ -1,6 +1,6 @@
<!doctype html>
<script type="module">
import {default_request_options} from './fedcm-helper.sub.js';
import {request_options_with_mediation_required} from './fedcm-helper.sub.js';
// Loading fedcm-iframe.html in the test will make a FedCM call on load, and
// trigger a postMessage upon completion.
@ -13,7 +13,7 @@ import {default_request_options} from './fedcm-helper.sub.js';
window.onload = async () => {
try {
const cred = await navigator.credentials.get(default_request_options());
const cred = await navigator.credentials.get(request_options_with_mediation_required());
window.top.postMessage({result: "Pass", token: cred.token}, '*');
} catch (error) {
window.top.postMessage({result: "Fail", errorType: error.name}, '*');

View file

@ -20,7 +20,8 @@ def main(request, response):
"name": "John Doe",
"email": "john_doe@idp.example",
"picture": "https://idp.example/profile/123",
"approved_clients": ["123", "456", "789"]
"approved_clients": ["123", "456", "789"],
"login_hints": ["john_doe"]
}]
}
"""

View file

@ -29,7 +29,8 @@ def main(request, response):
"name": "John Doe",
"email": "john_doe@idp.example",
"picture": "https://idp.example/profile/123",
"approved_clients": ["123", "456", "789"]
"approved_clients": ["123", "456", "789"],
"login_hints": ["john_doe"]
}
]
}

View file

@ -1,16 +0,0 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>CSS Reftest Reference</title>
<link rel="author" title="Ms2ger" href="mailto:Ms2ger@gmail.com"/>
<style type="text/css">
p.test {
color: green;
}
</style>
</head>
<body>
<p>There must be no red.</p>
<p class="test">This sentence must be green.</p>
</body>
</html>

View file

@ -1,24 +0,0 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" lang="en">
<head>
<title>CSS Test: Nested blocks in unexpected places</title>
<link rel="author" title="Ian Hickson" href="mailto:ian@hixie.ch"/>
<link rel="alternate" href="http://www.hixie.ch/tests/adhoc/css/parsing/core-syntax/002.html" type="text/html"/>
<link rel="help" href="http://www.w3.org/TR/CSS21/syndata.html#parsing-errors" />
<link rel="match" href="core-syntax-002-ref.xht"/>
<meta name="flags" content="invalid" />
<style type="text/css">
.instruct { color: black; background: white; }
p {
color: green;
/* no "}" */
span { color: yellow; background: red; }
.test { color: maroon; background: yellow; }
}
</style>
</head>
<body>
<p class="instruct">There must be no red.</p>
<p>This sentence <span>must</span> be <span class="test">green</span>.</p>
</body>
</html>

View file

@ -1,15 +0,0 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" lang="en">
<head>
<title>CSS Test: Nested blocks in unexpected places (with no whitespace)</title>
<link rel="author" title="Ian Hickson" href="mailto:ian@hixie.ch"/>
<link rel="alternate" href="http://www.hixie.ch/tests/adhoc/css/parsing/core-syntax/003.html" type="text/html"/>
<link rel="help" href="http://www.w3.org/TR/CSS21/syndata.html#parsing-errors" />
<link rel="match" href="../reference/ref-this-text-should-be-green.xht"/>
<meta name="flags" content="invalid" />
<style type="text/css">p{color:green;/*no"}"*/span{color:yellow;background:red;}.test{color:maroon;background:yellow;}}</style>
</head>
<body>
<p>This text <span>should</span> be <span class="test">green</span>.</p>
</body>
</html>

View file

@ -1,18 +0,0 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" lang="en">
<head>
<title>CSS Test: Nested blocks in unexpected places (with no whitespace)</title>
<link rel="author" title="Ian Hickson" href="mailto:ian@hixie.ch"/>
<link rel="alternate" href="http://www.hixie.ch/tests/adhoc/css/parsing/core-syntax/002-demo.html" type="text/html"/>
<link rel="help" href="http://www.w3.org/TR/CSS21/syndata.html#parsing-errors" />
<link rel="match" href="../reference/ref-this-text-should-be-green.xht"/>
<meta name="flags" content="invalid" />
<style type="text/css">
body { color : green ; p{color : red ; }
span { color : red ; }
</style>
</head>
<body>
<p>This <span>text</span> should be <span>green</span>.</p>
</body>
</html>

View file

@ -17,7 +17,7 @@
#p3 {@foo {color: red} color: green}
#p4 {12; color: green}
#p5 {color: green; 12 color: red}
#p6 {color: green; 12 @page {color: red} color: red}
#p6 {color: orange; 12 @page {color: red} color: green}
#p7 {@foo {color: red}; color: green}
</style>
</head>

View file

@ -0,0 +1,71 @@
<!DOCTYPE html>
<title>Tests automatic anchor positioning without fallbacks</title>
<link rel="help" href="https://drafts.csswg.org/css-anchor-position-1/#anchor-auto">
<link rel="auto" href="mailto:xiaochengh@chromium.org">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="/resources/check-layout-th.js"></script>
<script src="support/test-common.js"></script>
<style>
body {
margin: 0;
}
#cb {
position: absolute;
width: 500px;
height: 500px;
}
#anchor {
margin-left: 150px;
margin-top: 250px;
width: 100px;
height: 100px;
background: orange;
anchor-name: --a;
}
.target {
position: absolute;
width: 100px;
height: 100px;
background: lime;
}
#target1 {
top: anchor(--a auto); /* should evaluate to `bottom` */
left: anchor(--a auto-same); /* should evaluate to `left` */
}
#target2 {
bottom: anchor(--a auto); /* should evaluate to `top` */
right: anchor(--a auto-same); /* should evaluate to `right` */
}
#target3 {
top: anchor(--a auto-same); /* should evaluate to `top` */
left: anchor(--a auto); /* should evaluate to `right` */
}
#target4 {
bottom: anchor(--a auto-same); /* should evaluate to `bottom` */
right: anchor(--a auto); /* should evaluate to `left` */
}
</style>
<body onload="checkLayoutForAnchorPos('.target')">
<div id="cb">
<div id="anchor"></div>
<div id="target1" class="target"
data-offset-x="150" data-offset-y="350"></div>
<div id="target2" class="target"
data-offset-x="150" data-offset-y="150"></div>
<div id="target3" class="target"
data-offset-x="250" data-offset-y="250"></div>
<div id="target4" class="target"
data-offset-x="50" data-offset-y="250"></div>
</div>
</body>

View file

@ -73,10 +73,10 @@ for (const colorSpace of [ "xyz", "xyz-d50", "xyz-d65" ]) {
test_valid_value("color", `color(${colorSpace} none none none / 0.5)`, `color(${resultColorSpace} none none none / 0.5)`);
test_valid_value("color", `color(${colorSpace} 0 0 0 / none)`, `color(${resultColorSpace} 0 0 0 / none)`);
test_valid_value("color", `color(${colorSpace} 0 calc(infinity) 0)`, `color(${colorSpace} 0 calc(infinity) 0)`);
test_valid_value("color", `color(${colorSpace} 0 calc(-infinity) 0)`, `color(${colorSpace} 0 calc(-infinity) 0)`);
test_valid_value("color", `color(${colorSpace} calc(NaN) 0 0)`, `color(${colorSpace} calc(NaN) 0 0)`);
test_valid_value("color", `color(${colorSpace} calc(0 / 0) 0 0)`, `color(${colorSpace} calc(NaN) 0 0)`);
test_valid_value("color", `color(${colorSpace} 0 calc(infinity) 0)`, `color(${resultColorSpace} 0 calc(infinity) 0)`);
test_valid_value("color", `color(${colorSpace} 0 calc(-infinity) 0)`, `color(${resultColorSpace} 0 calc(-infinity) 0)`);
test_valid_value("color", `color(${colorSpace} calc(NaN) 0 0)`, `color(${resultColorSpace} calc(NaN) 0 0)`);
test_valid_value("color", `color(${colorSpace} calc(0 / 0) 0 0)`, `color(${resultColorSpace} calc(NaN) 0 0)`);
}
</script>
</body>

View file

@ -0,0 +1,38 @@
<!DOCTYPE html>
<html class="reftest-wait">
<meta charset="utf-8">
<title>Container Queries - Size change during transitions crash</title>
<script src="/common/reftest-wait.js"></script>
<link rel="help" href="https://crbug.com/1451359">
<style>
#outer {
container-type: inline-size;
width: 100px;
}
#inner {
background-color: black;
transition: background-color 60s;
}
#inner.target {
background-color: white;
}
@container (width > 200px) {
#inner.target {
background-color: lime;
}
}
</style>
<p>Pass if no crash.</p>
<div id="outer">
<div id="inner">Look at my background</div>
</div>
<script>
inner.offsetTop;
inner.className = "target";
requestAnimationFrame(() => {
requestAnimationFrame(() => {
outer.style.width = "300px";
takeScreenshot();
});
});
</script>

View file

@ -87,13 +87,13 @@ async_test((t) => {
end.focus();
requestAnimationFrame(step5);
}
// After blurring the focused element, we should go back to the contained
// height of 100px.
// After blurring the focused element, we keep the last rendered size, see
// https://github.com/w3c/csswg-drafts/issues/8407.
function step5() {
const r = container.getBoundingClientRect();
t.step(() => {
assert_equals(r.y, 3000, "step5 offset");
assert_equals(r.height, 100, "step5 height");
assert_equals(r.height, 10, "step5 height");
});
t.done();
}

View file

@ -96,13 +96,13 @@ async_test((t) => {
requestAnimationFrame(step6);
}
// After removing the selection we should go back to the contained
// height of 100px.
// After removing the selection, we keep the last rendered size, see
// https://github.com/w3c/csswg-drafts/issues/8407.
function step6() {
const r = container.getBoundingClientRect();
t.step(() => {
assert_equals(r.y, 3000, "step5 offset");
assert_equals(r.height, 100, "step5 height");
assert_equals(r.y, 3000, "step6 offset");
assert_equals(r.height, 10, "step6 height");
});
t.done();
}

View file

@ -0,0 +1,33 @@
<!DOCTYPE html>
<title>Flex gaps</title>
<link rel="author" title="David Grogan" href="mailto:dgrogan@chromium.org">
<link rel="help" href="https://drafts.csswg.org/css-flexbox/#intrinsic-sizes">
<link rel="help" href="https://drafts.csswg.org/css-align/#gaps">
<link rel="match" href="../reference/ref-filled-green-100px-square.xht">
<meta name="assert"
content="Intrinsic max size of multiline row flex containers includes gaps" />
<style>
.item {
flex: 0 0 10px;
}
#reference-overlapped-red {
position: absolute;
background-color: red;
width: 100px;
height: 100px;
z-index: -1;
}
</style>
<p>Test passes if there is a filled green square and <strong>no red</strong>.
</p>
<div id=reference-overlapped-red></div>
<div
style="display: flex; column-gap: 80px; background: green; height: 100px; width: max-content; flex-wrap: wrap;">
<div class=item></div>
<div class=item></div>
</div>

View file

@ -4,7 +4,8 @@
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="/resources/check-layout-th.js"></script>
<meta name="assert" content="min-content width is calculated correctly in a variety of scenarios with two flex items" />
<meta name="assert"
content="min-content width is calculated correctly in a variety of scenarios with multiple flex items" />
<style>
.zero-width {
@ -28,23 +29,27 @@
background: orange;
}
.floating-flexbox>div:nth-child(3) {
background: lightblue;
}
.floating-flexbox>div>div {
width: 100px;
}
</style>
<body onload="checkLayout('.floating-flexbox')">
<div id="log"></div>
<div class="zero-width">
<div class="floating-flexbox" data-expected-width="300">
<div class="floating-flexbox" data-expected-width="200">
<!-- min contribution: 100 -->
<!-- fraction: -0.5 -->
<!-- flex base size + product: 200px + -0.5*200px = 100px -->
<div style="flex: 1 1 200px; width:50px;">
<!-- desired fraction: -0.5 -->
<!-- chosen fraction <=0 and desired fraction <=0 and item can shrink, so it contributes its min-content contribution -->
<div style="flex: 1 1 200px; width:50px; min-width:0px;">
<div></div>
</div>
<!-- min contribution: 100 -->
<!-- fraction: -0.75 -->
<!-- flex base size + product: 400px + -0.5*400px = 200px -->
<!-- chosen fraction <=0 and desired fraction <=0 and item can shrink, so it contributes its min-content contribution -->
<div style="flex: 1 1 400px; width:50px;">
<div></div>
</div>
@ -52,10 +57,18 @@
</div>
<div class="zero-width">
<div class="floating-flexbox" data-expected-width="225">
<div class="floating-flexbox" data-expected-width="200">
<!-- min contribution: 100 -->
<!-- min contribution - flex basis: -100 -->
<!-- desired fraction: -0.5 -->
<!-- chosen fraction <=0 and desired fraction <=0 and item can shrink, so it contributes its min-content contribution -->
<div style="flex: 1 1 200px; width:50px;">
<div></div>
</div>
<!-- min contribution: 100 -->
<!-- min contribution - flex basis: -300 -->
<!-- desired fraction: -300/(2*400) = -0.375 -->
<!-- chosen fraction <=0 and desired fraction <=0 and item can shrink, so it contributes its min-content contribution -->
<div style="flex: 1 2 400px; width:50px;">
<div></div>
</div>
@ -65,7 +78,7 @@
<!-- This is same as above except for min-width auto is no longer in
effect. EdgeHTML renders it differently than the above. -->
<div class="zero-width">
<div class="floating-flexbox" data-expected-width="225">
<div class="floating-flexbox" data-expected-width="200">
<div style="flex: 1 1 200px; width:50px; min-width: 0px;">
<div></div>
</div>
@ -76,16 +89,17 @@
</div>
<div class="zero-width">
<!-- first item contributes 200px. second item contributes 100px -->
<div class="floating-flexbox" data-expected-width="300">
<!-- min contribution: 100 -->
<!-- fraction: -inf -->
<!-- flex base size + product: 200px + -0.75*0px = 200px -->
<!-- desired fraction: -inf -->
<!-- chosen fraction <= 0 and item can't shrink, so contribute flex basis -->
<div style="flex: 1 0 200px; width:50px;">
<div></div>
</div>
<!-- min contribution: 100 -->
<!-- fraction: -0.75 -->
<!-- flex base size + product: 400px + -0.75*400px = 100px -->
<!-- desired fraction: -0.75 -->
<!-- chosen fraction <= 0 and item CAN shrink, so contribute min contribution -->
<div style="flex: 1 1 400px; width:50px;">
<div></div>
</div>
@ -94,9 +108,15 @@
<div class="zero-width">
<div class="floating-flexbox" data-expected-width="200">
<!-- min contribution: 200 -->
<!-- min contribution - flex basis: 150 -->
<!-- desired fraction: 0 (because flex grow factor is 0) -->
<!-- chosen fraction <= 0 so contribute flex basis 50px -->
<!-- except flex basis is outside of used min/max, so contribute clamped flex basis = 100px -->
<div style="flex: 0 0 50px; width: 200px;">
<div></div>
</div>
<!-- identical to above -->
<div style="flex: 0 0 50px; width: 200px;">
<div></div>
</div>
@ -106,14 +126,14 @@
<div class="zero-width">
<!-- 200 + 400 = 600 -->
<div class="floating-flexbox" data-expected-width="600">
<!-- contribution: 200 -->
<!-- fraction: 150 -->
<!-- min contribution: 200 -->
<!-- desired fraction: 150px -->
<!-- 50 + 1*150 = 200 -->
<div style="flex: 1 0 50px; width: 200px;">
<div></div>
</div>
<!-- contribution: 200 -->
<!-- fraction: 100 -->
<!-- min contribution: 200 -->
<!-- desired fraction: 100px -->
<!-- 100 + 2*150 = 400 -->
<div style="flex: 2 0 100px; width: 200px;">
<div></div>
@ -122,19 +142,60 @@
</div>
<div class="zero-width">
<!-- chosen fraction: 50px -->
<div class="floating-flexbox" data-expected-width="400">
<!-- min contribution: 100 -->
<!-- fraction: -0.5 -->
<!-- flex base size + product: = 200px + 50px*0 = 200px -->
<!-- desired fraction: -0.5 -->
<!-- final contribution = flex base size + product = 200px + 50px*0 = 200px -->
<div style="flex: 0 1 200px; width: 50px;">
<div></div>
</div>
<!-- min contribution: 200 -->
<!-- fraction: (200px - 100px) / 2 = 50px -->
<!-- flex base size + product: = 100px + 50px*2 = 200px -->
<!-- desired fraction: (200px - 100px) / 2 = 50px -->
<!-- final contribution = flex base size + product = 100px + 50px*2 = 200px -->
<div style="flex: 2 0 100px; width: 200px;">
<div></div>
</div>
</div>
</div>
<div class="zero-width">
<!-- chosen fraction: 0 -->
<div class="floating-flexbox" data-expected-width="600">
<!-- min contribution: 250 -->
<!-- wants to grow, but can't -->
<!-- desired fraction: 0 -->
<!-- final contribution: 100 -->
<div style="flex: 0 1 100px; width: 250px;"></div>
<!-- min contribution: 100 -->
<!-- wants to shrink, but can't -->
<!-- desired fraction: -inf -->
<!-- final contribution: 200 -->
<div style="flex: 1 0 200px; width: 100px;"></div>
<!-- min contribution: -->
<!-- doesn't have to change --->
<!-- desired fraction: 0 -->
<!-- final contribution: 300 -->
<div style="flex: 1 1 300px; width: 300px;"></div>
</div>
</div>
<div class="zero-width">
<!-- chosen fraction: 0 -->
<div class="floating-flexbox" data-expected-width="700">
<!-- min contribution: 100 -->
<!-- wants to shrink, but can't -->
<!-- desired fraction: -inf -->
<!-- final contribution: 200 -->
<!-- In legacy and V2, this item gets 0 width. -->
<div style="flex: 0 10 300px; width: 200px;"></div>
<!-- min contribution: -->
<!-- doesn't have to change --->
<!-- desired fraction: 0 -->
<!-- final contribution: 300 -->
<!-- In legacy and V2, this item gets all the width. -->
<div style="flex: 0 1 1000px; width: 500px;">
</div>
</div>
</div>
</body>

View file

@ -0,0 +1,51 @@
<!DOCTYPE html>
<link rel="author" title="David Grogan" href="mailto:dgrogan@chromium.org">
<link rel="help" href="https://drafts.csswg.org/css-flexbox/#intrinsic-sizes">
<link rel="help" href="https://crbug.com/1445937">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="/resources/check-layout-th.js"></script>
<meta name="assert"
content="Virtually all of the compat problems reduced to this case" />
<style>
section.bugreport {
outline: 1px solid grey;
margin-bottom: 25px;
padding: 3px;
}
#gmail .flex {
display: flex;
width: min-content;
outline: 2px solid;
margin-bottom: 10px;
}
#gmail span.orange100 {
float: left;
height: 25px;
width: 100px;
background: orange;
}
</style>
<section id="gmail" class="bugreport">
<p>https://crbug.com/1445937 We need to see a 100x100 orange square, not a
400x25 orange rectangle.</p>
<div class="flex" data-expected-width="100">
<!-- one item with very negative desired flex fraction -->
<div>
<span class="orange100"></span>
<span class="orange100"></span>
<span class="orange100"></span>
<span class="orange100"></span>
</div>
<!-- second item with desired flex fraction 0 -->
<div></div>
</div>
</section>
<script>
checkLayout('.flex');
</script>

Some files were not shown because too many files have changed in this diff Show more