Auto merge of #28111 - servo-wpt-sync:wpt_update_27-01-2021, r=servo-wpt-sync

Sync WPT with upstream (27-01-2021)

Automated downstream sync of changes from upstream as of 27-01-2021.
[no-wpt-sync]
r? @servo-wpt-sync
This commit is contained in:
bors-servo 2021-01-27 05:26:18 -05:00 committed by GitHub
commit 35d56e4a5a
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
129 changed files with 2532 additions and 324 deletions

View file

@ -0,0 +1,2 @@
[animation-fallback-missing-100-percent.html]
expected: TIMEOUT

View file

@ -0,0 +1,2 @@
[animation-fallback-replace.html]
expected: TIMEOUT

View file

@ -17,3 +17,6 @@
[test the top of layer]
expected: FAIL
[test some point of the element: top left corner]
expected: FAIL

View file

@ -0,0 +1,2 @@
[matchMedia-display-none-iframe.html]
expected: ERROR

View file

@ -0,0 +1,67 @@
[aria-element-reflection.tentative.html]
[Element reference set in invalid scope remains intact throughout move to valid scope.]
expected: FAIL
[Moving explicitly set elements around within the same scope, and removing from the DOM.]
expected: FAIL
[Deleting a reflected element should return null for the IDL attribute and cause the content attribute to become stale.]
expected: FAIL
[Reparenting an element into a descendant shadow scope hides the element reference.]
expected: FAIL
[aria-activedescendant element reflection]
expected: FAIL
[Reparenting referenced element cannot cause retargeting of reference.]
expected: FAIL
[aria-owns.]
expected: FAIL
[aria-details]
expected: FAIL
[shadow DOM behaviour for FrozenArray element reflection.]
expected: FAIL
[aria-flowto.]
expected: FAIL
[aria-labelledby.]
expected: FAIL
[aria-describedby.]
expected: FAIL
[Changing the ID of an element causes the content attribute to become out of sync.]
expected: FAIL
[aria-controls.]
expected: FAIL
[Setting the IDL attribute to an element which is not the first element in DOM order with its ID causes the content attribute to be an empty string]
expected: FAIL
[Attaching element reference before it's inserted into the DOM.]
expected: FAIL
[Reparenting.]
expected: FAIL
[aria-errormessage]
expected: FAIL
[Cross-document references and moves.]
expected: FAIL
[If the content attribute is set directly, the IDL attribute getter always returns the first element whose ID matches the content attribute.]
expected: FAIL
[Moving explicitly set elements across shadow DOM boundaries.]
expected: FAIL
[Setting an element reference that crosses into a shadow tree is disallowed, but setting one that is in a shadow inclusive ancestor is allowed.]
expected: FAIL

View file

@ -315,12 +315,15 @@
[<iframe>: separate response Content-Type: text/html */*]
expected: FAIL
[<iframe>: separate response Content-Type: text/html;" text/plain]
expected: FAIL
[<iframe>: combined response Content-Type: text/html;" text/plain]
expected: FAIL
[<iframe>: combined response Content-Type: text/html;x=" text/plain]
expected: FAIL
[<iframe>: combined response Content-Type: */* text/html]
expected: FAIL
[<iframe>: combined response Content-Type: text/html;charset=gbk text/plain text/html]
expected: FAIL

View file

@ -1,4 +0,0 @@
[traverse_the_history_5.html]
[Multiple history traversals, last would be aborted]
expected: FAIL

View file

@ -1,5 +1,5 @@
[embedded-opener-remove-frame.html]
expected: TIMEOUT
expected: CRASH
[opener of discarded nested browsing context]
expected: FAIL

View file

@ -1,5 +1,4 @@
[supported-elements.html]
expected: TIMEOUT
[Contenteditable element should support autofocus]
expected: FAIL
@ -10,7 +9,7 @@
expected: FAIL
[Area element should support autofocus]
expected: TIMEOUT
expected: FAIL
[Host element with delegatesFocus should support autofocus]
expected: FAIL

View file

@ -1,5 +1,5 @@
[iframe_sandbox_popups_escaping-1.html]
expected: TIMEOUT
expected: CRASH
[Check that popups from a sandboxed iframe escape the sandbox if\n allow-popups-to-escape-sandbox is used]
expected: TIMEOUT

View file

@ -1,5 +1,5 @@
[iframe_sandbox_popups_escaping-2.html]
expected: TIMEOUT
expected: CRASH
[Check that popups from a sandboxed iframe escape the sandbox if\n allow-popups-to-escape-sandbox is used]
expected: TIMEOUT

View file

@ -1,4 +1,5 @@
[iframe_sandbox_popups_escaping-3.html]
expected: CRASH
[Check that popups from a sandboxed iframe escape the sandbox if\n allow-popups-to-escape-sandbox is used]
expected: FAIL

View file

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

View file

@ -1,4 +1,5 @@
[iframe_sandbox_popups_nonescaping-3.html]
expected: CRASH
[Check that popups from a sandboxed iframe do not escape the sandbox]
expected: FAIL

View file

@ -0,0 +1,4 @@
[form-double-submit.html]
[default submit action should supersede onclick submit()]
expected: FAIL

View file

@ -2,69 +2,78 @@
[input type url: setRangeText() a second time (must not fire select)]
expected: FAIL
[input type url: selectionStart out of range a second time (must not fire select)]
expected: FAIL
[textarea: selectionDirection a second time (must not fire select)]
expected: FAIL
[input type search: selectionEnd a second time (must not fire select)]
expected: FAIL
[input type search: selectionStart a second time (must not fire select)]
expected: FAIL
[input type tel: setSelectionRange() a second time (must not fire select)]
expected: FAIL
[input type password: setRangeText() a second time (must not fire select)]
expected: FAIL
[input type password: select() a second time (must not fire select)]
expected: FAIL
[input type password: setSelectionRange() a second time (must not fire select)]
expected: FAIL
[input type search: setRangeText() a second time (must not fire select)]
expected: FAIL
[textarea: selectionEnd a second time (must not fire select)]
expected: FAIL
[input type password: setSelectionRange out of range a second time (must not fire select)]
expected: FAIL
[input type text: selectionEnd a second time (must not fire select)]
expected: FAIL
[input type tel: setRangeText() a second time (must not fire select)]
expected: FAIL
[textarea: setSelectionRange() a second time (must not fire select)]
expected: FAIL
[input type text: setSelectionRange() a second time (must not fire select)]
expected: FAIL
[input type text: setSelectionRange out of range a second time (must not fire select)]
expected: FAIL
[input type tel: setSelectionRange out of range a second time (must not fire select)]
expected: FAIL
[input type password: selectionEnd a second time (must not fire select)]
expected: FAIL
[input type text: selectionDirection a second time (must not fire select)]
[input type tel: selectionEnd out of range a second time (must not fire select)]
expected: FAIL
[textarea: selectionStart out of range a second time (must not fire select)]
[input type password: selectionStart a second time (must not fire select)]
expected: FAIL
[textarea: setSelectionRange out of range a second time (must not fire select)]
[input type url: setSelectionRange() a second time (must not fire select)]
expected: FAIL
[textarea: selectionEnd out of range a second time (must not fire select)]
[input type url: selectionEnd out of range a second time (must not fire select)]
expected: FAIL
[input type password: selectionEnd out of range a second time (must not fire select)]
expected: FAIL
[input type search: setSelectionRange out of range a second time (must not fire select)]
expected: FAIL
[input type search: setSelectionRange() a second time (must not fire select)]
expected: FAIL
[textarea: selectionStart a second time (must not fire select)]
expected: FAIL
[input type tel: selectionStart out of range a second time (must not fire select)]
expected: FAIL
[input type tel: selectionDirection a second time (must not fire select)]
expected: FAIL
[input type url: select() a second time (must not fire select)]
expected: FAIL
[input type url: selectionDirection a second time (must not fire select)]
expected: FAIL
[input type search: selectionEnd out of range a second time (must not fire select)]
expected: FAIL
[input type search: selectionDirection a second time (must not fire select)]
expected: FAIL
[input type text: selectionStart out of range a second time (must not fire select)]
expected: FAIL
[input type text: selectionStart a second time (must not fire select)]
expected: FAIL
[input type tel: select() a second time (must not fire select)]
expected: FAIL
[input type url: selectionStart a second time (must not fire select)]
expected: FAIL

View file

@ -0,0 +1,2 @@
[popup-stacking.tentative.html]
expected: ERROR

View file

@ -0,0 +1,4 @@
[module-delayed.html]
[async document.write in a module]
expected: FAIL

View file

@ -0,0 +1,4 @@
[module-static-import-delayed.html]
[document.write in an imported module]
expected: FAIL

View file

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

View file

@ -1,9 +1,10 @@
[promise-job-entry.html]
expected: TIMEOUT
[Fulfillment handler on fulfilled promise]
expected: FAIL
[Rejection handler on pending-then-rejected promise]
expected: FAIL
expected: TIMEOUT
[Sanity check: this all works as expected with no promises involved]
expected: FAIL
@ -15,5 +16,5 @@
expected: FAIL
[Fulfillment handler on pending-then-fulfilled promise]
expected: FAIL
expected: TIMEOUT

View file

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

View file

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

View file

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

View file

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

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,2 @@
[animation-fallback-missing-100-percent.html]
expected: TIMEOUT

View file

@ -0,0 +1,2 @@
[animation-fallback-replace.html]
expected: TIMEOUT

View file

@ -21,3 +21,6 @@
[test the top of layer]
expected: FAIL
[test some point of the element: top left corner]
expected: FAIL

View file

@ -0,0 +1,2 @@
[matchMedia-display-none-iframe.html]
expected: ERROR

View file

@ -50,3 +50,21 @@
[Moving explicitly set elements across shadow DOM boundaries.]
expected: FAIL
[Element reference set in invalid scope remains intact throughout move to valid scope.]
expected: FAIL
[Reparenting an element into a descendant shadow scope hides the element reference.]
expected: FAIL
[Reparenting referenced element cannot cause retargeting of reference.]
expected: FAIL
[Attaching element reference before it's inserted into the DOM.]
expected: FAIL
[Reparenting.]
expected: FAIL
[Cross-document references and moves.]
expected: FAIL

View file

@ -315,12 +315,15 @@
[<iframe>: separate response Content-Type: text/html */*]
expected: FAIL
[<iframe>: separate response Content-Type: text/html;" text/plain]
expected: FAIL
[<iframe>: combined response Content-Type: text/html;" text/plain]
expected: FAIL
[<iframe>: combined response Content-Type: text/html;x=" text/plain]
expected: FAIL
[<iframe>: combined response Content-Type: */* text/html]
expected: FAIL
[<iframe>: combined response Content-Type: text/html;charset=gbk text/plain text/html]
expected: FAIL

View file

@ -1,4 +0,0 @@
[traverse_the_history_5.html]
[Multiple history traversals, last would be aborted]
expected: FAIL

View file

@ -1,5 +1,5 @@
[embedded-opener-remove-frame.html]
expected: TIMEOUT
expected: CRASH
[opener and "removed" embedded documents]
expected: FAIL

View file

@ -1,5 +1,4 @@
[supported-elements.html]
expected: TIMEOUT
[Contenteditable element should support autofocus]
expected: FAIL
@ -10,7 +9,7 @@
expected: FAIL
[Area element should support autofocus]
expected: TIMEOUT
expected: FAIL
[Host element with delegatesFocus should support autofocus]
expected: FAIL

View file

@ -1,6 +1,6 @@
[iframe_sandbox_popups_escaping-1.html]
type: testharness
expected: TIMEOUT
expected: CRASH
[Check that popups from a sandboxed iframe escape the sandbox if\n allow-popups-to-escape-sandbox is used]
expected: TIMEOUT

View file

@ -1,5 +1,5 @@
[iframe_sandbox_popups_escaping-2.html]
expected: TIMEOUT
expected: CRASH
[Check that popups from a sandboxed iframe escape the sandbox if\n allow-popups-to-escape-sandbox is used]
expected: TIMEOUT

View file

@ -1,5 +1,6 @@
[iframe_sandbox_popups_escaping-3.html]
type: testharness
expected: CRASH
[Check that popups from a sandboxed iframe escape the sandbox if\n allow-popups-to-escape-sandbox is used]
expected: FAIL

View file

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

View file

@ -1,4 +1,5 @@
[iframe_sandbox_popups_nonescaping-3.html]
expected: CRASH
[Check that popups from a sandboxed iframe do not escape the sandbox]
expected: FAIL

View file

@ -0,0 +1,4 @@
[form-double-submit.html]
[default submit action should supersede onclick submit()]
expected: FAIL

View file

@ -2,69 +2,78 @@
[input type url: setRangeText() a second time (must not fire select)]
expected: FAIL
[input type url: selectionStart out of range a second time (must not fire select)]
expected: FAIL
[textarea: selectionDirection a second time (must not fire select)]
expected: FAIL
[input type search: selectionEnd a second time (must not fire select)]
expected: FAIL
[input type search: selectionStart a second time (must not fire select)]
expected: FAIL
[input type tel: setSelectionRange() a second time (must not fire select)]
expected: FAIL
[input type password: setRangeText() a second time (must not fire select)]
expected: FAIL
[input type password: select() a second time (must not fire select)]
expected: FAIL
[input type password: setSelectionRange() a second time (must not fire select)]
expected: FAIL
[input type search: setRangeText() a second time (must not fire select)]
expected: FAIL
[textarea: selectionEnd a second time (must not fire select)]
expected: FAIL
[input type password: setSelectionRange out of range a second time (must not fire select)]
expected: FAIL
[input type text: selectionEnd a second time (must not fire select)]
expected: FAIL
[input type tel: setRangeText() a second time (must not fire select)]
expected: FAIL
[textarea: setSelectionRange() a second time (must not fire select)]
expected: FAIL
[input type text: setSelectionRange() a second time (must not fire select)]
expected: FAIL
[input type text: setSelectionRange out of range a second time (must not fire select)]
expected: FAIL
[input type tel: setSelectionRange out of range a second time (must not fire select)]
expected: FAIL
[input type password: selectionEnd a second time (must not fire select)]
expected: FAIL
[input type text: selectionDirection a second time (must not fire select)]
[input type tel: selectionEnd out of range a second time (must not fire select)]
expected: FAIL
[textarea: selectionStart out of range a second time (must not fire select)]
[input type password: selectionStart a second time (must not fire select)]
expected: FAIL
[textarea: setSelectionRange out of range a second time (must not fire select)]
[input type url: setSelectionRange() a second time (must not fire select)]
expected: FAIL
[textarea: selectionEnd out of range a second time (must not fire select)]
[input type url: selectionEnd out of range a second time (must not fire select)]
expected: FAIL
[input type password: selectionEnd out of range a second time (must not fire select)]
expected: FAIL
[input type search: setSelectionRange out of range a second time (must not fire select)]
expected: FAIL
[input type search: setSelectionRange() a second time (must not fire select)]
expected: FAIL
[textarea: selectionStart a second time (must not fire select)]
expected: FAIL
[input type tel: selectionStart out of range a second time (must not fire select)]
expected: FAIL
[input type tel: selectionDirection a second time (must not fire select)]
expected: FAIL
[input type url: select() a second time (must not fire select)]
expected: FAIL
[input type url: selectionDirection a second time (must not fire select)]
expected: FAIL
[input type search: selectionEnd out of range a second time (must not fire select)]
expected: FAIL
[input type search: selectionDirection a second time (must not fire select)]
expected: FAIL
[input type text: selectionStart out of range a second time (must not fire select)]
expected: FAIL
[input type text: selectionStart a second time (must not fire select)]
expected: FAIL
[input type tel: select() a second time (must not fire select)]
expected: FAIL
[input type url: selectionStart a second time (must not fire select)]
expected: FAIL

View file

@ -0,0 +1,2 @@
[popup-stacking.tentative.html]
expected: ERROR

View file

@ -0,0 +1,4 @@
[module-delayed.html]
[async document.write in a module]
expected: FAIL

View file

@ -0,0 +1,4 @@
[module-static-import-delayed.html]
[document.write in an imported module]
expected: FAIL

View file

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

View file

@ -1,9 +1,10 @@
[promise-job-entry.html]
expected: TIMEOUT
[Fulfillment handler on fulfilled promise]
expected: FAIL
[Rejection handler on pending-then-rejected promise]
expected: FAIL
expected: TIMEOUT
[Sanity check: this all works as expected with no promises involved]
expected: FAIL
@ -15,5 +16,5 @@
expected: FAIL
[Fulfillment handler on pending-then-fulfilled promise]
expected: FAIL
expected: TIMEOUT

View file

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

View file

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

View file

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

View file

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

View file

@ -47,14 +47,23 @@ promise_test(async t => {
}, 'navigator.clipboard.writeText() fails (expect DOMString)');
promise_test(async () => {
const fetched = await fetch(
'http://localhost:8001/clipboard-apis/resources/greenbox.png');
const fetched = await fetch('/clipboard-apis/resources/greenbox.png');
const image = await fetched.blob();
const item = new ClipboardItem({'image/png': image});
await navigator.clipboard.write([item]);
}, 'navigator.clipboard.write({string : image/png Blob}) succeeds');
promise_test(async() => {
const fetched = await fetch('/clipboard-apis/resources/greenbox.png');
const image = await fetched.blob();
const item = new ClipboardItem({
'text/plain': new Blob(['first'], {type: 'text/plain'}),
'image/png': image});
await navigator.clipboard.write([item]);
}, 'navigator.clipboard.write([text + png] succeeds');
promise_test(async () => {
const result = await navigator.clipboard.read();
assert_true(result instanceof Object);

View file

@ -0,0 +1,934 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- -*- Mode: HTML; tab-width: 2; indent-tabs-mode: nil; -*- -->
<!-- vim: set shiftwidth=2 tabstop=2 autoindent expandtab: -->
<!-- This Source Code Form is subject to the terms of the Mozilla Public
- License, v. 2.0. If a copy of the MPL was not distributed with this
- file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
<!--
Features to add:
* make the left and right parts of the viewer independently scrollable
* make the test list filterable
** default to only showing unexpecteds
* add other ways to highlight differences other than circling?
* add zoom/pan to images
* Add ability to load log via XMLHttpRequest (also triggered via URL param)
* color the test list based on pass/fail and expected/unexpected/random/skip
* ability to load multiple logs ?
** rename them by clicking on the name and editing
** turn the test list into a collapsing tree view
** move log loading into popup from viewer UI
-->
<!DOCTYPE html>
<html lang="en-US" xml:lang="en-US" xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>Reftest analyzer</title>
<style type="text/css"><![CDATA[
html, body { margin: 0; }
html { padding: 0; }
body { padding: 4px; }
#pixelarea, #itemlist, #images { position: absolute; }
#itemlist, #images { overflow: auto; }
#pixelarea { top: 0; left: 0; width: 320px; height: 84px; overflow: visible }
#itemlist { top: 84px; left: 0; width: 320px; bottom: 0; }
#images { top: 0; bottom: 0; left: 320px; right: 0; }
#leftpane { width: 320px; }
#images { position: fixed; top: 10px; left: 340px; }
form#imgcontrols { margin: 0; display: block; }
#itemlist > table { border-collapse: collapse; }
#itemlist > table > tbody > tr > td { border: 1px solid; padding: 1px; }
#itemlist td.activeitem { background-color: yellow; }
/*
#itemlist > table > tbody > tr.pass > td.url { background: lime; }
#itemlist > table > tbody > tr.fail > td.url { background: red; }
*/
#magnification > svg { display: block; width: 84px; height: 84px; }
#pixelinfo { font: small sans-serif; position: absolute; width: 200px; left: 84px; }
#pixelinfo table { border-collapse: collapse; }
#pixelinfo table th { white-space: nowrap; text-align: left; padding: 0; }
#pixelinfo table td { font-family: monospace; padding: 0 0 0 0.25em; }
#pixelhint { display: inline; color: #88f; cursor: help; }
#pixelhint > * { display: none; position: absolute; margin: 8px 0 0 8px; padding: 4px; width: 400px; background: #ffa; color: black; box-shadow: 3px 3px 2px #888; z-index: 1; }
#pixelhint:hover { color: #000; }
#pixelhint:hover > * { display: block; }
#pixelhint p { margin: 0; }
#pixelhint p + p { margin-top: 1em; }
]]></style>
<script type="text/javascript"><![CDATA[
var XLINK_NS = "http://www.w3.org/1999/xlink";
var SVG_NS = "http://www.w3.org/2000/svg";
var IMAGE_NOT_AVAILABLE = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAKAAAAASCAYAAADczdVTAAAACXBIWXMAAAsTAAALEwEAmpwYAAAHy0lEQVRoge2aX2hb5xnGf2dYabROgqQkpMuKnWUJLmxHMFaa/SscteQiF5EvUgqLctEVrDJKK1+MolzkQr4IctgW+SLIheJc1BpFpswJw92FbaZsTCGTL0465AtntUekJdJ8lByVHbnnwLsLKbKdSJbiZBVjeuAYn+/P+z3fc97vfd9zbEVEhB566BK+1m0CPfx/o+eAPXQVbR3QqVapOl8FlR46h0O1Wu02iacCZfsasMKEz8vbx1JYE6fY/dXx6mEbFObPcvDVDBlznpc9G+2r8xNcvLqK2w39r4UI+fs7tFjmytgFFu718865EIebPGincI3zFz7Bcrtx97/GL0P+p+IPbSOgRwXtW3vpewqL/a/g5rgf39hit2m0hGUAHOHrrq3trmef4/lDB7Ay57n01zuPZXPX7jUunv+Yf9ktR7D/0CHca7/n3KXPsHbAuynkCWCZptgiImKLaVqP9NuW1bT9ceybpr3j+WJbYrVa3rbEatGZi2uixvWdrysilmWKae2M+5PqlktoosayLfubcrN10dAk24aynUsIxMVsadwUs+EX7dEyAlaXLqMoCj6fj5HkUqO9MD+Govjx+xXcXi+uoRAhvwuv182Z8Ws4AJUlxoZ8uNxuvF43ii/EtdXNNUuV68lR/IqC4gsxPj7KkE/BF5qmClRXrzFSt+/1ulDOjLNU6eQ4OcyPDqH4hhg5O4LicuN2K4xcvk6jjHUKJM8O1fvcKMoZkouFOq1VPp1OcuXGAvrvfsv0lWmSySTzN0sdH+jyYhK/ouB2e/G6XfjPJikBVG8SUhT8fl99nwVGfQp+vx+f4iO5VO1AtwJjfgXF58M/kqSVJP9ef0xuAI6NlwWmL41xxqeg+PyMXr72yBqW3cI4JaZHh1DcXrxeLy5liORiB7q1PiZFyeV0mQqz9TRZeUmFVUGLSjqdkgCIFp2RTCosEJOiiIihSyKWkDl9WYrFnCQCCNF0w0QmHhBQJTEzJ+nZSQmAoEYks2KIGBkJgASiM5I3LbGMnCSCCEQl38GJMvMZiag1e+nlFcmmIgKaZEwREaPGhWGZ1VfEMFZkNj4sgCSyhoihSzwSlqCGoAUlEo1IJByW+Oxyh+dZJJ+eklhiRnIrRcnrM6KCxLOmiNiipyICSGR2pTY2O1m7T2XEsNrrJmJLfjkn6amwoMbFaMEhG28eAVtzExErW3sOBCWVzkpmNiEqCOEZ2RyLTT3eJAKaMhVEUMOSXjHEtg3JTIUFkNTK9rGwbQrWm2xGb6QoWxIqEtdtEWO28aDtoi6JSFCAjUtL1AUzJA4SSW/IZ2VjjU0V0zEBJBiJSzwWk1g8IZEAAmrdidrBkoSKxB4IW08tGVNEzIxoIJM5a8v4SQ1RY5lGSy6x8xScz6QkHFBre1Zre49nH+y1KDEQLV7TcyU1LBCtHVppp9smxk2dYAMtHXA7blZWNJDZ4sZ4MxPbdHjrbc3WNuvOq4YlkYhLLBaXeKx2sLcrBUS2ScFtUbUBh3WgajvgOYgGuKjw4Rsqb1uvkssbWLbJXFQFqL/I9IEKa2WzYcqy16E2BNteB1R+cuwoRwcHGRx4nlfenWMuPclRDx3goSraqd+7Gj/Y5d76SrXLu3VKLYW1rMZbo/QpB4+9zt6fT1I0Law/LRMBaLzC7ePNuSgL7/2GpcotLr7+AZG5t9gH0Fa3zuFq1tiWG4DKs5tebV1NDDW1XYd26iWO9A8wODjAUfUN5ubm+Ch4ZFuuLRzQoVwqUCqXyN9fg3tFSuUShVIZhyr5O2vo94o42DwD/PP23fq8Bf5urLO+BoHBwxzc20c++wcmz+lAkWLFATwcf3+YDwIDhMYmuDw+wt5j5+C5ZwDYP/gSoLP6xX5+fOIkJ47/lIP8g49/Nc3tDj59OZUiRR3uFYsAVO/eZoE1yvkyeA6gAaff+zU3SxUcp8LilQucnoFTP3hhix19/garlQqFW9eZOBti9Mqt9mubXwBw+NALeDC4cfVDzgP3i3keUN/nf4uo+hEver/DRaK84/9mY/72uoFTKVMolVn5/HPgPvlSmVKhRL2bSrlEqVyidH8N/d7t2u/lakfcKneLgM4rvxhncbXA6tI8kTffB+0NjnrAqZYplcrk83ceXdtzgB+psHD7S/pfPs7JkydQB1x8dnWS2SVje9GaxkVLl+DmNNC4NJn/S6JxH5nJyNRwrW7Qi7oMgxBMyd9molvmRKO1cExgshG6l9NTEhkOynAkLlOJoKBuhPV8ZlK0h9aNTqVbv3ltEK/VIiAQEN0yZVLbuM+aImLoEgts3VdsJrfFil1M1/ZSv9RAROaWO8n/hkyF1Q3bgeFGygvPrDRG5Wcf1IJbq9rlNrrNbra96aqlUVMSWrNnNiw5uw23T/4o4Xq7FtA29h2My3K9WtETgRZr13UxdIk+pGswkpCcsX0N2OZD9BOgWqFsgWePp20KWb0ywkDgEIa8y55Gq0O5XKHP7cGz++l/haxWylgOuD17aG7eoVpxwL27RX8b27jZ42n1qdahXKrg2bfnUW0eQ7edoD232l+/LPp2pHvNfh8eT2f8/3sO2AZLyRAvns6gqToLOgxP6Uz87HvdoNJDF9E1B6ysLrLw5yW+3PUNvv3dH/L9wX3doNFDl9E1B+yhB+j9O1YPXcZ/AAl9BWJNvZE7AAAAAElFTkSuQmCC";
var gPhases = null;
var gIDCache = {};
var gMagPixPaths = []; // 2D array of array-of-two <path> objects used in the pixel magnifier
var gMagWidth = 5; // number of zoomed in pixels to show horizontally
var gMagHeight = 5; // number of zoomed in pixels to show vertically
var gMagZoom = 16; // size of the zoomed in pixels
var gImage1Data; // ImageData object for the reference image
var gImage2Data; // ImageData object for the test output image
var gFlashingPixels = []; // array of <path> objects that should be flashed due to pixel color mismatch
var gParams;
function ID(id) {
if (!(id in gIDCache))
gIDCache[id] = document.getElementById(id);
return gIDCache[id];
}
function hash_parameters() {
var result = { };
var params = window.location.hash.substr(1).split(/[&;]/);
for (var i = 0; i < params.length; i++) {
var parts = params[i].split("=");
result[parts[0]] = unescape(unescape(parts[1]));
}
return result;
}
function load() {
gPhases = [ ID("entry"), ID("loading"), ID("viewer") ];
build_mag();
gParams = hash_parameters();
if (gParams.log) {
show_phase("loading");
process_log(gParams.log);
} else if (gParams.logurl) {
show_phase("loading");
var req = new XMLHttpRequest();
req.onreadystatechange = function() {
if (req.readyState === 4) {
process_log(req.responseText);
}
};
req.open('GET', gParams.logurl, true);
req.send();
}
window.addEventListener('keypress', handle_keyboard_shortcut);
window.addEventListener('keydown', handle_keydown);
ID("image1").addEventListener('error', image_load_error);
ID("image2").addEventListener('error', image_load_error);
}
function image_load_error(e) {
e.target.setAttributeNS(XLINK_NS, "xlink:href", IMAGE_NOT_AVAILABLE);
}
function build_mag() {
var mag = ID("mag");
var r = document.createElementNS(SVG_NS, "rect");
r.setAttribute("x", gMagZoom * -gMagWidth / 2);
r.setAttribute("y", gMagZoom * -gMagHeight / 2);
r.setAttribute("width", gMagZoom * gMagWidth);
r.setAttribute("height", gMagZoom * gMagHeight);
mag.appendChild(r);
mag.setAttribute("transform", "translate(" + (gMagZoom * (gMagWidth / 2) + 1) + "," + (gMagZoom * (gMagHeight / 2) + 1) + ")");
for (var x = 0; x < gMagWidth; x++) {
gMagPixPaths[x] = [];
for (var y = 0; y < gMagHeight; y++) {
var p1 = document.createElementNS(SVG_NS, "path");
p1.setAttribute("d", "M" + ((x - gMagWidth / 2) + 1) * gMagZoom + "," + (y - gMagHeight / 2) * gMagZoom + "h" + -gMagZoom + "v" + gMagZoom);
p1.setAttribute("stroke", "black");
p1.setAttribute("stroke-width", "1px");
p1.setAttribute("fill", "#aaa");
var p2 = document.createElementNS(SVG_NS, "path");
p2.setAttribute("d", "M" + ((x - gMagWidth / 2) + 1) * gMagZoom + "," + (y - gMagHeight / 2) * gMagZoom + "v" + gMagZoom + "h" + -gMagZoom);
p2.setAttribute("stroke", "black");
p2.setAttribute("stroke-width", "1px");
p2.setAttribute("fill", "#888");
mag.appendChild(p1);
mag.appendChild(p2);
gMagPixPaths[x][y] = [p1, p2];
}
}
var flashedOn = false;
setInterval(function() {
flashedOn = !flashedOn;
flash_pixels(flashedOn);
}, 500);
}
function show_phase(phaseid) {
for (var i in gPhases) {
var phase = gPhases[i];
phase.style.display = (phase.id == phaseid) ? "" : "none";
}
if (phase == "viewer")
ID("images").style.display = "none";
}
function fileentry_changed() {
show_phase("loading");
var input = ID("fileentry");
var files = input.files;
if (files.length > 0) {
// Only handle the first file; don't handle multiple selection.
// The parts of the log we care about are ASCII-only. Since we
// can ignore lines we don't care about, best to read in as
// iso-8859-1, which guarantees we don't get decoding errors.
var fileReader = new FileReader();
fileReader.onload = function(e) {
var log = null;
log = e.target.result;
if (log)
process_log(log);
else
show_phase("entry");
}
fileReader.readAsText(files[0], "iso-8859-1");
}
// So the user can process the same filename again (after
// overwriting the log), clear the value on the form input so we
// will always get an onchange event.
input.value = "";
}
function log_pasted() {
show_phase("loading");
var entry = ID("logentry");
var log = entry.value;
entry.value = "";
process_log(log);
}
var gTestItems;
// This function is not used in production code, but can be invoked manually
// from the devtools console in order to test changes to the parsing regexes
// in process_log.
function test_parsing() {
// Note that the logs in these testcases have been manually edited to strip
// out stuff for brevity.
var testcases = [
{ "name": "empty log",
"log": "",
"expected": { "pass": 0, "unexpected": 0, "random": 0, "skip": 0 },
"expected_images": 0,
},
{ "name": "android log",
"log": `[task 2018-12-28T10:36:45.718Z] 10:36:45 INFO - REFTEST TEST-START | a == b
[task 2018-12-28T10:36:45.719Z] 10:36:45 INFO - REFTEST TEST-LOAD | a | 78 / 275 (28%)
[task 2018-12-28T10:36:56.138Z] 10:36:56 INFO - REFTEST TEST-LOAD | b | 78 / 275 (28%)
[task 2018-12-28T10:37:06.559Z] 10:37:06 INFO - REFTEST TEST-UNEXPECTED-FAIL | a == b | image comparison, max difference: 255, number of differing pixels: 5950
[task 2018-12-28T10:37:06.568Z] 10:37:06 INFO - REFTEST IMAGE 1 (TEST): data:image/png;base64,
[task 2018-12-28T10:37:06.577Z] 10:37:06 INFO - REFTEST IMAGE 2 (REFERENCE): data:image/png;base64,
[task 2018-12-28T10:37:06.577Z] 10:37:06 INFO - REFTEST INFO | Saved log: stuff trimmed here
[task 2018-12-28T10:37:06.582Z] 10:37:06 INFO - REFTEST TEST-END | a == b
[task 2018-12-28T10:37:06.583Z] 10:37:06 INFO - REFTEST TEST-START | a2 == b2
[task 2018-12-28T10:37:06.583Z] 10:37:06 INFO - REFTEST TEST-LOAD | a2 | 79 / 275 (28%)
[task 2018-12-28T10:37:06.584Z] 10:37:06 INFO - REFTEST TEST-LOAD | b2 | 79 / 275 (28%)
[task 2018-12-28T10:37:16.982Z] 10:37:16 INFO - REFTEST TEST-PASS | a2 == b2 | image comparison, max difference: 0, number of differing pixels: 0
[task 2018-12-28T10:37:16.982Z] 10:37:16 INFO - REFTEST TEST-END | a2 == b2`,
"expected": { "pass": 1, "unexpected": 1, "random": 0, "skip": 0 },
"expected_images": 2,
},
{ "name": "local reftest run (Linux)",
"log": `REFTEST TEST-START | file:///a == file:///b
REFTEST TEST-LOAD | file:///a | 73 / 86 (84%)
REFTEST TEST-LOAD | file:///b | 73 / 86 (84%)
REFTEST TEST-PASS | file:///a == file:///b | image comparison, max difference: 0, number of differing pixels: 0
REFTEST TEST-END | file:///a == file:///b`,
"expected": { "pass": 1, "unexpected": 0, "random": 0, "skip": 0 },
"expected_images": 0,
},
{ "name": "wpt reftests (Linux automation)",
"log": `16:50:43 INFO - TEST-START | /a
16:50:43 INFO - PID 4276 | 1548694243694 Marionette INFO Testing http://web-platform.test:8000/a == http://web-platform.test:8000/b
16:50:43 INFO - PID 4276 | 1548694243963 Marionette INFO No differences allowed
16:50:44 INFO - TEST-PASS | /a | took 370ms
16:50:44 INFO - TEST-START | /a2
16:50:44 INFO - PID 4276 | 1548694244066 Marionette INFO Testing http://web-platform.test:8000/a2 == http://web-platform.test:8000/b2
16:50:44 INFO - PID 4276 | 1548694244792 Marionette INFO No differences allowed
16:50:44 INFO - PID 4276 | 1548694244792 Marionette INFO Found 28 pixels different, maximum difference per channel 14
16:50:44 INFO - TEST-UNEXPECTED-FAIL | /a2 | Testing http://web-platform.test:8000/a2 == http://web-platform.test:8000/b2
16:50:44 INFO - REFTEST IMAGE 1 (TEST): data:image/png;base64,
16:50:44 INFO - REFTEST IMAGE 2 (REFERENCE): data:image/png;base64,
16:50:44 INFO - TEST-INFO took 840ms`,
"expected": { "pass": 1, "unexpected": 1, "random": 0, "skip": 0 },
"expected_images": 2,
},
{ "name": "windows log",
"log": `12:17:14 INFO - REFTEST TEST-START | a == b
12:17:14 INFO - REFTEST TEST-LOAD | a | 1603 / 2053 (78%)
12:17:14 INFO - REFTEST TEST-LOAD | b | 1603 / 2053 (78%)
12:17:14 INFO - REFTEST TEST-PASS(EXPECTED RANDOM) | a == b | image comparison, max difference: 0, number of differing pixels: 0
12:17:14 INFO - REFTEST TEST-END | a == b
12:17:14 INFO - REFTEST TEST-START | a2 == b2
12:17:14 INFO - REFTEST TEST-LOAD | a2 | 1604 / 2053 (78%)
12:17:14 INFO - REFTEST TEST-LOAD | b2 | 1604 / 2053 (78%)
12:17:14 INFO - REFTEST TEST-UNEXPECTED-FAIL | a2 == b2 | image comparison, max difference: 255, number of differing pixels: 9976
12:17:14 INFO - REFTEST IMAGE 1 (TEST): data:image/png;base64,
12:17:14 INFO - REFTEST IMAGE 2 (REFERENCE): data:image/png;base64,
12:17:14 INFO - REFTEST INFO | Saved log: stuff trimmed here
12:17:14 INFO - REFTEST TEST-END | a2 == b2
12:01:09 INFO - REFTEST TEST-START | a3 == b3
12:01:09 INFO - REFTEST TEST-LOAD | a3 | 66 / 189 (34%)
12:01:09 INFO - REFTEST TEST-LOAD | b3 | 66 / 189 (34%)
12:01:09 INFO - REFTEST TEST-KNOWN-FAIL | a3 == b3 | image comparison, max difference: 255, number of differing pixels: 9654
12:01:09 INFO - REFTEST TEST-END | a3 == b3`,
"expected": { "pass": 1, "unexpected": 1, "random": 1, "skip": 0 },
"expected_images": 2,
},
{ "name": "webrender wrench log (windows)",
"log": `[task 2018-12-29T04:29:48.800Z] REFTEST a == b
[task 2018-12-29T04:29:48.984Z] REFTEST a2 == b2
[task 2018-12-29T04:29:49.053Z] REFTEST TEST-UNEXPECTED-FAIL | a2 == b2 | image comparison, max difference: 255, number of differing pixels: 3128
[task 2018-12-29T04:29:49.053Z] REFTEST IMAGE 1 (TEST): data:image/png;
[task 2018-12-29T04:29:49.053Z] REFTEST IMAGE 2 (REFERENCE): data:image/png;
[task 2018-12-29T04:29:49.053Z] REFTEST TEST-END | a2 == b2`,
"expected": { "pass": 0, "unexpected": 1, "random": 0, "skip": 0 },
"expected_images": 2,
},
{ "name": "wpt reftests (Linux local; Bug 1530008)",
"log": `SUITE-START | Running 1 tests
TEST-START | /css/css-backgrounds/border-image-6.html
TEST-UNEXPECTED-FAIL | /css/css-backgrounds/border-image-6.html | Testing http://web-platform.test:8000/css/css-backgrounds/border-image-6.html == http://web-platform.test:8000/css/css-backgrounds/border-image-6-ref.html
REFTEST IMAGE 1 (TEST): data:image/png;base64,
REFTEST IMAGE 2 (REFERENCE): data:image/png;base64,
TEST-INFO took 425ms
SUITE-END | took 2s`,
"expected": { "pass": 0, "unexpected": 1, "random": 0, "skip": 0 },
"expected_images": 2,
},
{ "name": "wpt reftests (taskcluster log from macOS CI)",
"log": `[task 2020-06-26T01:35:29.065Z] 01:35:29 INFO - TEST-START | /html/rendering/non-replaced-elements/the-page/iframe-scrolling-attribute-values.html
[task 2020-06-26T01:35:29.065Z] 01:35:29 INFO - PID 1353 | 1593135329040 Marionette INFO Testing http://web-platform.test:8000/html/rendering/non-replaced-elements/the-page/iframe-scrolling-attribute-values.html == http://web-platform.test:8000/html/rendering/non-replaced-elements/the-page/iframe-scrolling-attribute-values-ref.html
[task 2020-06-26T01:35:29.673Z] 01:35:29 INFO - PID 1353 | 1593135329633 Marionette INFO No differences allowed
[task 2020-06-26T01:35:29.726Z] 01:35:29 INFO - TEST-KNOWN-INTERMITTENT-FAIL | /html/rendering/non-replaced-elements/the-page/iframe-scrolling-attribute-values.html | took 649ms
[task 2020-06-26T01:35:29.726Z] 01:35:29 INFO - REFTEST IMAGE 1 (TEST): data:image/png;
[task 2020-06-26T01:35:29.726Z] 01:35:29 INFO - REFTEST IMAGE 2 (REFERENCE): data:image/png;`,
"expected": { "pass": 0, "unexpected": 0, "random": 1, "skip": 0 },
"expected_images": 2,
},
{ "name": "wpt reftests (taskcluster log from Windows CI)",
"log": `[task 2020-06-26T01:41:19.205Z] 01:41:19 INFO - TEST-START | /html/rendering/non-replaced-elements/the-page/iframe-scrolling-attribute-values.html
[task 2020-06-26T01:41:19.214Z] 01:41:19 INFO - PID 5920 | 1593135679202 Marionette WARN [24] http://web-platform.test:8000/css/WOFF2/metadatadisplay-schema-license-022-ref.xht overflows viewport (width: 783, height: 731)
[task 2020-06-26T01:41:19.214Z] 01:41:19 INFO - PID 9692 | 1593135679208 Marionette INFO Testing http://web-platform.test:8000/html/rendering/non-replaced-elements/the-page/iframe-scrolling-attribute-values.html == http://web-platform.test:8000/html/rendering/non-replaced-elements/the-page/iframe-scrolling-attribute-values-ref.html
[task 2020-06-26T01:41:19.638Z] 01:41:19 INFO - PID 9692 | 1593135679627 Marionette INFO No differences allowed
[task 2020-06-26T01:41:19.688Z] 01:41:19 INFO - TEST-KNOWN-INTERMITTENT-PASS | /html/rendering/non-replaced-elements/the-page/iframe-scrolling-attribute-values.html | took 474ms
[task 2020-06-26T01:41:19.688Z] 01:41:19 INFO - REFTEST IMAGE 1 (TEST): data:image/png;
[task 2020-06-26T01:41:19.689Z] 01:41:19 INFO - REFTEST IMAGE 2 (REFERENCE): data:image/png;`,
"expected": { "pass": 1, "unexpected": 0, "random": 1, "skip": 0 },
"expected_images": 2,
},
{ "name": "local reftest run with timestamps (Linux; Bug 1167712)",
"log": ` 0:05.21 REFTEST TEST-START | a
0:05.21 REFTEST REFTEST TEST-LOAD | a | 0 / 1 (0%)
0:05.27 REFTEST REFTEST TEST-LOAD | b | 0 / 1 (0%)
0:05.66 REFTEST TEST-UNEXPECTED-FAIL | a | image comparison (==), max difference: 106, number of differing pixels: 800
0:05.67 REFTEST REFTEST IMAGE 1 (TEST): data:image/png;base64,
0:05.67 REFTEST REFTEST IMAGE 2 (REFERENCE): data:image/png;base64,
0:05.73 REFTEST REFTEST TEST-END | a`,
"expected": { "pass": 0, "unexpected": 1, "random": 0, "skip": 0 },
"expected_images": 2,
},
{ "name": "reftest run with whitespace compressed (Treeherder; Bug 1084322)",
"log": ` REFTEST TEST-START | a
REFTEST TEST-LOAD | a | 0 / 1 (0%)
REFTEST TEST-LOAD | b | 0 / 1 (0%)
REFTEST TEST-UNEXPECTED-FAIL | a | image comparison (==), max difference: 106, number of differing pixels: 800
REFTEST REFTEST IMAGE 1 (TEST): data:image/png;base64,
REFTEST REFTEST IMAGE 2 (REFERENCE): data:image/png;base64,
REFTEST REFTEST TEST-END | a`,
"expected": { "pass": 0, "unexpected": 1, "random": 0, "skip": 0 },
"expected_images": 2,
},
];
var current_test = 0;
// Override the build_viewer function invoked at the end of process_log to
// actually just check the results of parsing.
build_viewer = function() {
var expected = testcases[current_test].expected;
var expected_images = testcases[current_test].expected_images;
for (var result of gTestItems) {
for (let type in expected) { // type is "pass", "unexpected" etc.
if (result[type]) {
expected[type]--;
}
}
}
var failed = false;
for (let type in expected) {
if (expected[type] != 0) {
console.log(`Failure: for testcase ${testcases[current_test].name} got ${expected[type]} fewer ${type} results than expected!`);
failed = true;
}
}
let total_images = 0;
for (var result of gTestItems) {
total_images += result.images.length;
}
if (total_images !== expected_images) {
console.log(`Failure: for testcase ${testcases[current_test].name} got ${total_images} images, expected ${expected_images}`);
failed = true;
}
if (!failed) {
console.log(`Success for testcase ${testcases[current_test].name}`);
}
};
while (current_test < testcases.length) {
process_log(testcases[current_test].log);
current_test++;
}
}
function process_log(contents) {
var lines = contents.split(/[\r\n]+/);
gTestItems = [];
for (var j in lines) {
// !!!!!!
// When making any changes to this code, please add a test to the
// test_parsing function above, and ensure all existing tests pass.
// !!!!!!
var line = lines[j];
// Ignore duplicated output in logcat.
if (line.match(/I\/Gecko.*?REFTEST/))
continue;
var match = line.match(/^.*?(?:REFTEST\s+)+(.*)$/);
if (!match) {
// WPT reftests don't always have the "REFTEST" prefix but do have
// mozharness prefixing. Trying to match both prefixes optionally with a
// single regex either makes an unreadable mess or matches everything so
// we do them separately.
match = line.match(/^(?:.*? (?:INFO|ERROR) -\s+)(.*)$/);
}
if (match)
line = match[1];
match = line.match(/^(TEST-PASS|TEST-UNEXPECTED-PASS|TEST-FAIL|TEST-KNOWN-FAIL|TEST-UNEXPECTED-FAIL|TEST-DEBUG-INFO|TEST-KNOWN-INTERMITTENT-FAIL|TEST-KNOWN-INTERMITTENT-PASS)(\(EXPECTED RANDOM\)|) \| ([^\|]+)(?: \|(.*)|$)/);
if (match) {
var state = match[1];
var random = match[2];
var url = match[3];
var extra = match[4];
gTestItems.push(
{
pass: !state.match(/DEBUG-INFO$|FAIL$/),
// only one of the following three should ever be true
unexpected: !!state.match(/^TEST-UNEXPECTED/),
random: (random == "(EXPECTED RANDOM)" || state == "TEST-KNOWN-INTERMITTENT-FAIL" || state == "TEST-KNOWN-INTERMITTENT-PASS"),
skip: (extra == " (SKIP)"),
url: url,
images: [],
imageLabels: []
});
continue;
}
match = line.match(/^IMAGE([^:]*): (data:.*)$/);
if (match) {
var item = gTestItems[gTestItems.length - 1];
item.images.push(match[2]);
item.imageLabels.push(match[1]);
}
}
build_viewer();
}
function build_viewer() {
if (gTestItems.length == 0) {
show_phase("entry");
return;
}
var cell = ID("itemlist");
while (cell.childNodes.length > 0)
cell.removeChild(cell.childNodes[cell.childNodes.length - 1]);
var table = document.createElement("table");
var tbody = document.createElement("tbody");
table.appendChild(tbody);
for (var i in gTestItems) {
var item = gTestItems[i];
// optional url filter for only showing unexpected results
if (parseInt(gParams.only_show_unexpected) && !item.unexpected)
continue;
// XXX regardless skip expected pass items until we have filtering UI
if (item.pass && !item.unexpected)
continue;
var tr = document.createElement("tr");
var rowclass = item.pass ? "pass" : "fail";
var td;
var text;
td = document.createElement("td");
text = "";
if (item.unexpected) { text += "!"; rowclass += " unexpected"; }
if (item.random) { text += "R"; rowclass += " random"; }
if (item.skip) { text += "S"; rowclass += " skip"; }
td.appendChild(document.createTextNode(text));
tr.appendChild(td);
td = document.createElement("td");
td.id = "item" + i;
td.className = "url";
// Only display part of URL after "/mozilla/".
var match = item.url.match(/\/mozilla\/(.*)/);
text = document.createTextNode(match ? match[1] : item.url);
if (item.images.length > 0) {
var a = document.createElement("a");
a.href = "javascript:show_images(" + i + ")";
a.appendChild(text);
td.appendChild(a);
} else {
td.appendChild(text);
}
tr.appendChild(td);
tbody.appendChild(tr);
}
cell.appendChild(table);
show_phase("viewer");
}
function get_image_data(src, whenReady) {
var img = new Image();
img.onload = function() {
var canvas = document.createElement("canvas");
canvas.width = img.naturalWidth;
canvas.height = img.naturalHeight;
var ctx = canvas.getContext("2d");
ctx.drawImage(img, 0, 0);
whenReady(ctx.getImageData(0, 0, img.naturalWidth, img.naturalHeight));
};
img.src = src;
}
function sync_svg_size(imageData) {
// We need the size of the 'svg' and its 'image' elements to match the size
// of the ImageData objects that we're going to read pixels from or else our
// magnify() function will be very broken.
ID("svg").setAttribute("width", imageData.width);
ID("svg").setAttribute("height", imageData.height);
}
function show_images(i) {
var item = gTestItems[i];
var cell = ID("images");
// Remove activeitem class from any existing elements
var activeItems = document.querySelectorAll(".activeitem");
for (var activeItemIdx = activeItems.length; activeItemIdx-- != 0;) {
activeItems[activeItemIdx].classList.remove("activeitem");
}
ID("item" + i).classList.add("activeitem");
ID("image1").style.display = "";
ID("image2").style.display = "none";
ID("diffrect").style.display = "none";
ID("imgcontrols").reset();
ID("pixel-differences").textContent = "";
ID("image1").setAttributeNS(XLINK_NS, "xlink:href", item.images[0]);
// Making the href be #image1 doesn't seem to work
ID("feimage1").setAttributeNS(XLINK_NS, "xlink:href", item.images[0]);
if (item.images.length == 1) {
ID("imgcontrols").style.display = "none";
} else {
ID("imgcontrols").style.display = "";
ID("image2").setAttributeNS(XLINK_NS, "xlink:href", item.images[1]);
// Making the href be #image2 doesn't seem to work
ID("feimage2").setAttributeNS(XLINK_NS, "xlink:href", item.images[1]);
ID("label1").textContent = 'Image ' + item.imageLabels[0];
ID("label2").textContent = 'Image ' + item.imageLabels[1];
}
cell.style.display = "";
let loaded = [false, false];
function images_loaded(id) {
loaded[id] = true;
if (loaded.every(x => x)) {
update_pixel_difference_text()
}
}
get_image_data(item.images[0], function(data) { gImage1Data = data; sync_svg_size(gImage1Data); images_loaded(0)});
get_image_data(item.images[1], function(data) { gImage2Data = data; images_loaded(1)});
}
function update_pixel_difference_text() {
let differenceText;
if (gImage1Data.height !== gImage2Data.height ||
gImage1Data.width !== gImage2Data.width) {
differenceText = "Images are different sizes"
} else {
let [numPixels, maxPerChannel] = get_pixel_differences();
if (!numPixels) {
differenceText = "Images are identical";
} else {
differenceText = `Maximum difference per channel ${maxPerChannel}, ${numPixels} pixels differ`;
}
}
// Disable this for now, because per bug 1633504, the numbers may be
// inaccurate and dependent on the browser's configuration.
// ID("pixel-differences").textContent = differenceText;
}
function get_pixel_differences() {
let numPixels = 0;
let maxPerChannel = 0;
for (var i=0; i<gImage1Data.data.length; i+=4) {
let r1 = gImage1Data.data[i];
let r2 = gImage2Data.data[i];
let g1 = gImage1Data.data[i+1];
let g2 = gImage2Data.data[i+1];
let b1 = gImage1Data.data[i+2];
let b2 = gImage2Data.data[i+2];
// Ignore alpha.
if (r1 == r2 && g1 == g2 && b1 == b2) {
continue;
}
numPixels += 1;
let maxDiff = Math.max(Math.abs(r1-r2),
Math.abs(g1-g2),
Math.abs(b1-b2));
if (maxDiff > maxPerChannel) {
maxPerChannel = maxDiff
}
}
return [numPixels, maxPerChannel];
}
function show_image(i) {
if (i == 1) {
ID("image1").style.display = "";
ID("image2").style.display = "none";
} else {
ID("image1").style.display = "none";
ID("image2").style.display = "";
}
}
function handle_keyboard_shortcut(event) {
switch (event.charCode) {
case 49: // "1" key
document.getElementById("radio1").checked = true;
show_image(1);
break;
case 50: // "2" key
document.getElementById("radio2").checked = true;
show_image(2);
break;
case 100: // "d" key
document.getElementById("differences").click();
break;
case 112: // "p" key
shift_images(-1);
break;
case 110: // "n" key
shift_images(1);
break;
}
}
function handle_keydown(event) {
switch (event.keyCode) {
case 37: // left arrow
move_pixel(-1, 0);
break;
case 38: // up arrow
move_pixel(0,-1);
break;
case 39: // right arrow
move_pixel(1, 0);
break;
case 40: // down arrow
move_pixel(0, 1);
break;
}
}
function shift_images(dir) {
var activeItem = document.querySelector(".activeitem");
if (!activeItem) {
return;
}
for (var elm = activeItem; elm; elm = elm.parentElement) {
if (elm.tagName != "tr") {
continue;
}
elm = dir > 0 ? elm.nextElementSibling : elm.previousElementSibling;
if (elm) {
elm.getElementsByTagName("a")[0].click();
}
return;
}
}
function show_differences(cb) {
ID("diffrect").style.display = cb.checked ? "" : "none";
}
function flash_pixels(on) {
var stroke = on ? "red" : "black";
var strokeWidth = on ? "2px" : "1px";
for (var i = 0; i < gFlashingPixels.length; i++) {
gFlashingPixels[i].setAttribute("stroke", stroke);
gFlashingPixels[i].setAttribute("stroke-width", strokeWidth);
}
}
function cursor_point(evt) {
var m = evt.target.getScreenCTM().inverse();
var p = ID("svg").createSVGPoint();
p.x = evt.clientX;
p.y = evt.clientY;
p = p.matrixTransform(m);
return { x: Math.floor(p.x), y: Math.floor(p.y) };
}
function hex2(i) {
return (i < 16 ? "0" : "") + i.toString(16);
}
function canvas_pixel_as_hex(data, x, y) {
var offset = (y * data.width + x) * 4;
var r = data.data[offset];
var g = data.data[offset + 1];
var b = data.data[offset + 2];
return "#" + hex2(r) + hex2(g) + hex2(b);
}
function hex_as_rgb(hex) {
return "rgb(" + [parseInt(hex.substring(1, 3), 16), parseInt(hex.substring(3, 5), 16), parseInt(hex.substring(5, 7), 16)] + ")";
}
function magnify(evt) {
var { x: x, y: y } = cursor_point(evt);
do_magnify(x, y);
}
function do_magnify(x, y) {
var centerPixelColor1, centerPixelColor2;
var dx_lo = -Math.floor(gMagWidth / 2);
var dx_hi = Math.floor(gMagWidth / 2);
var dy_lo = -Math.floor(gMagHeight / 2);
var dy_hi = Math.floor(gMagHeight / 2);
flash_pixels(false);
gFlashingPixels = [];
for (var j = dy_lo; j <= dy_hi; j++) {
for (var i = dx_lo; i <= dx_hi; i++) {
var px = x + i;
var py = y + j;
var p1 = gMagPixPaths[i + dx_hi][j + dy_hi][0];
var p2 = gMagPixPaths[i + dx_hi][j + dy_hi][1];
// Here we just use the dimensions of gImage1Data since we expect test
// and reference to have the same dimensions.
if (px < 0 || py < 0 || px >= gImage1Data.width || py >= gImage1Data.height) {
p1.setAttribute("fill", "#aaa");
p2.setAttribute("fill", "#888");
} else {
var color1 = canvas_pixel_as_hex(gImage1Data, x + i, y + j);
var color2 = canvas_pixel_as_hex(gImage2Data, x + i, y + j);
p1.setAttribute("fill", color1);
p2.setAttribute("fill", color2);
if (color1 != color2) {
gFlashingPixels.push(p1, p2);
p1.parentNode.appendChild(p1);
p2.parentNode.appendChild(p2);
}
if (i == 0 && j == 0) {
centerPixelColor1 = color1;
centerPixelColor2 = color2;
}
}
}
}
flash_pixels(true);
show_pixelinfo(x, y, centerPixelColor1, hex_as_rgb(centerPixelColor1), centerPixelColor2, hex_as_rgb(centerPixelColor2));
}
function show_pixelinfo(x, y, pix1rgb, pix1hex, pix2rgb, pix2hex) {
var pixelinfo = ID("pixelinfo");
ID("coords").textContent = [x, y];
ID("pix1hex").textContent = pix1hex;
ID("pix1rgb").textContent = pix1rgb;
ID("pix2hex").textContent = pix2hex;
ID("pix2rgb").textContent = pix2rgb;
}
function move_pixel(deltax, deltay) {
coords = ID("coords").textContent.split(',');
x = parseInt(coords[0]);
y = parseInt(coords[1]);
if (isNaN(x) || isNaN(y)) {
return;
}
x = x + deltax;
y = y + deltay;
if (x >= 0 && y >= 0 && x < gImage1Data.width && y < gImage1Data.height) {
do_magnify(x, y);
}
}
]]></script>
</head>
<body onload="load()">
<div id="entry">
<h1>Reftest analyzer: load reftest log</h1>
<p>Either paste your log into this textarea:<br />
<textarea cols="80" rows="10" id="logentry"/><br/>
<input type="button" value="Process pasted log" onclick="log_pasted()" /></p>
<p>... or load it from a file:<br/>
<input type="file" id="fileentry" onchange="fileentry_changed()" />
</p>
</div>
<div id="loading" style="display:none">Loading log...</div>
<div id="viewer" style="display:none">
<div id="pixelarea">
<div id="pixelinfo">
<table>
<tbody>
<tr><th>Pixel at:</th><td colspan="2" id="coords"/></tr>
<tr><th>Image 1:</th><td id="pix1rgb"></td><td id="pix1hex"></td></tr>
<tr><th>Image 2:</th><td id="pix2rgb"></td><td id="pix2hex"></td></tr>
</tbody>
</table>
<div>
<div id="pixelhint">
<div>
<p>Move the mouse over the reftest image on the right to show
magnified pixels on the left. The color information above is for
the pixel centered in the magnified view.</p>
<p>Image 1 is shown in the upper triangle of each pixel and Image 2
is shown in the lower triangle.</p>
</div>
</div>
</div>
</div>
<div id="magnification">
<svg xmlns="http://www.w3.org/2000/svg" width="84" height="84" shape-rendering="optimizeSpeed">
<g id="mag"/>
</svg>
</div>
</div>
<div id="itemlist"></div>
<div id="images" style="display:none">
<form id="imgcontrols">
<input id="radio1" type="radio" name="which" value="0" onchange="show_image(1)" checked="checked" /><label id="label1" title="1" for="radio1">Image 1</label>
<input id="radio2" type="radio" name="which" value="1" onchange="show_image(2)" /><label id="label2" title="2" for="radio2">Image 2</label>
<label><input id="differences" type="checkbox" onchange="show_differences(this)" />Circle differences</label>
</form>
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="800" height="1000" id="svg">
<defs>
<!-- use sRGB to avoid loss of data -->
<filter id="showDifferences" x="0%" y="0%" width="100%" height="100%"
style="color-interpolation-filters: sRGB">
<feImage id="feimage1" result="img1" xlink:href="#image1" />
<feImage id="feimage2" result="img2" xlink:href="#image2" />
<!-- inv1 and inv2 are the images with RGB inverted -->
<feComponentTransfer result="inv1" in="img1">
<feFuncR type="linear" slope="-1" intercept="1" />
<feFuncG type="linear" slope="-1" intercept="1" />
<feFuncB type="linear" slope="-1" intercept="1" />
</feComponentTransfer>
<feComponentTransfer result="inv2" in="img2">
<feFuncR type="linear" slope="-1" intercept="1" />
<feFuncG type="linear" slope="-1" intercept="1" />
<feFuncB type="linear" slope="-1" intercept="1" />
</feComponentTransfer>
<!-- w1 will have non-white pixels anywhere that img2
is brighter than img1, and w2 for the reverse.
It would be nice not to have to go through these
intermediate states, but feComposite
type="arithmetic" can't transform the RGB channels
and leave the alpha channel untouched. -->
<feComposite result="w1" in="img1" in2="inv2" operator="arithmetic" k2="1" k3="1" />
<feComposite result="w2" in="img2" in2="inv1" operator="arithmetic" k2="1" k3="1" />
<!-- c1 will have non-black pixels anywhere that img2
is brighter than img1, and c2 for the reverse -->
<feComponentTransfer result="c1" in="w1">
<feFuncR type="linear" slope="-1" intercept="1" />
<feFuncG type="linear" slope="-1" intercept="1" />
<feFuncB type="linear" slope="-1" intercept="1" />
</feComponentTransfer>
<feComponentTransfer result="c2" in="w2">
<feFuncR type="linear" slope="-1" intercept="1" />
<feFuncG type="linear" slope="-1" intercept="1" />
<feFuncB type="linear" slope="-1" intercept="1" />
</feComponentTransfer>
<!-- c will be nonblack (and fully on) for every pixel+component where there are differences -->
<feComposite result="c" in="c1" in2="c2" operator="arithmetic" k2="255" k3="255" />
<!-- a will be opaque for every pixel with differences and transparent for all others -->
<feColorMatrix result="a" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 0 0" />
<!-- a, dilated by 1 pixel -->
<feMorphology result="dila1" in="a" operator="dilate" radius="1" />
<!-- a, dilated by 2 pixels -->
<feMorphology result="dila2" in="dila1" operator="dilate" radius="1" />
<!-- all the pixels in the 2-pixel dilation of a but not in the 1-pixel dilation, to highlight the diffs -->
<feComposite result="highlight" in="dila2" in2="dila1" operator="out" />
<feFlood result="red" flood-color="red" />
<feComposite result="redhighlight" in="red" in2="highlight" operator="in" />
<feFlood result="black" flood-color="black" flood-opacity="0.5" />
<feMerge>
<feMergeNode in="black" />
<feMergeNode in="redhighlight" />
</feMerge>
</filter>
</defs>
<g onmousemove="magnify(evt)">
<image x="0" y="0" width="100%" height="100%" id="image1" />
<image x="0" y="0" width="100%" height="100%" id="image2" />
</g>
<rect id="diffrect" filter="url(#showDifferences)" pointer-events="none" x="0" y="0" width="100%" height="100%" />
</svg>
<div id="pixel-differences"></div>
</div>
</div>
</body>
</html>

View file

@ -0,0 +1,10 @@
<!DOCTYPE html>
<body>
<canvas id="canvas" width="100" height="100"></canvas>
</body>
<script>
var canvas = document.getElementById('canvas');
var ctx = canvas.getContext('2d');
ctx.fillStyle = 'rgb(0, 100, 100)';
ctx.fillRect(0, 0, 100, 100);
</script>

View file

@ -0,0 +1,36 @@
<!DOCTYPE html>
<html class="reftest-wait">
<link rel="help" href="https://drafts.csswg.org/css-backgrounds-3/#background-color">
<link rel="match" href="animation-fallback-missing-100-percent-ref.html">
<style>
.container {
/*TODO(crbug.com/1163949): Support animation keyframes without 0% or 100%.*/
width: 100px;
height: 100px;
background-color: green;
/* Use a long animation that start at 50% progress where the slope of the
selected timing function is zero. By setting up the animation in this way,
we accommodate lengthy delays in running the test without a potential drift
in the animated property value. This is important for avoiding flakes,
especially on debug builds. The screenshots are taken as soon as the
animation is ready, thus the long animation duration has no bearing on
the actual duration of the test. */
animation: bgcolor 1000000s cubic-bezier(0,1,1,0) -500000s;
}
@keyframes bgcolor {
0% { background-color: rgb(200, 0, 0); }
20% { background-color: rgb(0, 200, 0); }
80% { background-color: rgb(0, 0, 200); }
}
</style>
<script src="/common/reftest-wait.js"></script>
<body>
<div class="container"></div>
<script>
document.getAnimations()[0].ready.then(() => {
takeScreenshot();
});
</script>
</body>
</html>

View file

@ -0,0 +1,10 @@
<!DOCTYPE html>
<body>
<canvas id="canvas" width="100" height="100"></canvas>
</body>
<script>
var canvas = document.getElementById('canvas');
var ctx = canvas.getContext('2d');
ctx.fillStyle = 'rgb(0, 0, 100)';
ctx.fillRect(0, 0, 100, 100);
</script>

View file

@ -0,0 +1,42 @@
<!DOCTYPE html>
<html class="reftest-wait">
<link rel="help" href="https://drafts.csswg.org/css-backgrounds-3/#background-color">
<link rel="match" href="animation-fallback-replace-ref.html">
<style>
.container {
width: 100px;
height: 100px;
background-color: green;
/* Use a long animation that start at 50% progress where the slope of the
selected timing function is zero. By setting up the animation in this way,
we accommodate lengthy delays in running the test without a potential drift
in the animated property value. This is important for avoiding flakes,
especially on debug builds. The screenshots are taken as soon as the
animation is ready, thus the long animation duration has no bearing on
the actual duration of the test. */
animation: red 1000000s cubic-bezier(0,1,1,0) -500000s, green 1000000s cubic-bezier(0,1,1,0) -500000s, blue 1000000s cubic-bezier(0,1,1,0) -500000s;
}
@keyframes red {
0% { background-color: rgb(0, 0, 0); }
100% { background-color: rgb(200, 0, 0); }
}
@keyframes green {
0% { background-color: rgb(0, 0, 0); }
100% { background-color: rgb(0, 200, 0); }
}
@keyframes blue {
0% { background-color: rgb(0, 0, 0); }
100% { background-color: rgb(0, 0, 200); }
}
</style>
<script src="/common/reftest-wait.js"></script>
<body>
<div class="container"></div>
<script>
document.getAnimations()[0].ready.then(() => {
takeScreenshot();
});
</script>
</body>
</html>

View file

@ -0,0 +1,22 @@
<!DOCTYPE html>
<link rel="author" title="David Grogan" href="mailto:dgrogan@chromium.org">
<link rel="help" href="https://crbug.com/1102183">
<link rel="help" href="https://drafts.csswg.org/css-flexbox/#algo-main-item" title="Part E">
<link rel="match" href="../reference/ref-filled-green-100px-square.xht">
<meta name="assert" content="used flex base size includes percent padding on grid items.">
<style>
#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; width: 100px;">
<div style="display: grid; padding-right: 100%; height: 100px; background: green;"></div>
</div>

View file

@ -2,49 +2,35 @@
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<style>
body {
margin: 0px;
height: 2000px;
width: 2000px;
}
#first {
height: 1000px;
background-color: #FFA5D2;
}
#anchor {
position: absolute;
background-color: #84BE6A;
height: 600px;
width: 100%;
}
</style>
<div id="first"></div>
<div id="changer"></div>
<div id="anchor"></div>
<script>
var win;
var messageCount = 0;
// Navigation steps:
// 1- page gets loaded and anchor element gets scrolled into view.
// 2- loaded page refreshed.
async_test(function(t) {
if (window.name == 'second/load') {
assert_equals(window.scrollY, 1000);
// Change height of content above anchor.
var ch = document.getElementById('changer');
ch.style.height = 100;
// Height of first + height changer.
assert_equals(window.scrollY, 1100)
t.done();
} else {
var anchor = document.getElementById('anchor');
anchor.scrollIntoView();
assert_equals(window.scrollY, 1000);
window.name = "second/load";
window.location.reload();
}
window.onmessage = function() {
if (++messageCount == 1) {
t.step(() => {
var anchor = win.document.getElementById('anchor');
anchor.scrollIntoView();
assert_equals(win.scrollY, 1000);
win.location.reload();
});
} else {
t.step(() => {
assert_equals(win.scrollY, 1000);
// Change height of content above anchor.
var ch = win.document.getElementById('changer');
ch.style.height = 100;
// Height of first + height changer.
assert_equals(win.scrollY, 1100)
t.done();
});
win.close();
}
};
win = window.open('support/history-restore-anchors-new-window.html');
}, 'Verify scroll anchoring interaction with history restoration');
</script>

View file

@ -0,0 +1,29 @@
<style>
body {
margin: 0px;
height: 2000px;
width: 2000px;
}
#first {
height: 1000px;
background-color: #FFA5D2;
}
#anchor {
position: absolute;
background-color: #84BE6A;
height: 600px;
width: 100%;
}
</style>
<div id="first"></div>
<div id="changer"></div>
<div id="anchor"></div>
<script>
onload = function() {
opener.postMessage("loaded", "*");
}
</script>

View file

@ -0,0 +1,10 @@
<!DOCTYPE html>
<title>CSS aspect-ratio: div block size + percentage resolution</title>
<link rel="help" href="https://drafts.csswg.org/css-sizing-4/#aspect-ratio">
<link rel="match" href="../../reference/ref-filled-green-100px-square.xht" />
<p>Test passes if there is a filled green square and <strong>no red</strong>.</p>
<div style="height: 100px; width: 50px;">
<div style="height: 100%; aspect-ratio: 1/1; background: green"></div>
</div>

View file

@ -42,6 +42,8 @@
<div id="one" tabindex="0">Click me.</div>
<script>
setup({ explicit_done: true });
document.body.addEventListener("keydown", (e) => {
delete document.body.dataset.hadmousedown;
document.body.dataset.hadkeydown = "";
@ -75,7 +77,7 @@
});
one.addEventListener("focus", handle_initial_focus);
test_driver.click(one);
test_driver.click(one).then(() => done());
}, "Using keyboard while element is focused should trigger :focus-visible; using mouse without moving focus should not cancel it; moving focus using mouse should cancel it.");
</script>
</body>

View file

@ -44,10 +44,12 @@
<div id="target" tabindex="0">Target</div>
<script>
setup({ explicit_done: true });
async_test(function(t) {
initial.addEventListener("focus", t.step_func(function() {
assert_equals(getComputedStyle(initial).outlineColor, "rgb(0, 128, 0)", `outlineColor for ${initial.tagName}#${initial.id} should be green`);
test_driver.click(target);
test_driver.click(target).then(() => done());
}));
target.addEventListener("focus", t.step_func_done(function() {

View file

@ -0,0 +1,52 @@
<!DOCTYPE html>
<body>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script>
document.domain = "{{host}}";
async_test(t => {
const iframe = document.createElement('iframe');
iframe.src = "//{{domains[www1]}}:{{location[port]}}/document-policy/experimental-features/document-domain/resources/document-domain-enabled.html";
iframe.onload = () => {
iframe.contentWindow.postMessage({
type: "set document.domain",
newValue: "{{host}}"
}, "*");
};
window.addEventListener('message', t.step_func(e => {
if (e.source == iframe.contentWindow) {
assert_equals(e.data.oldDomain, "{{domains[www1]}}");
assert_equals(e.data.newDomain, "{{host}}");
t.done();
}
}));
document.body.appendChild(iframe);
}, 'document.domain should be enabled in subframe.');
async_test(t => {
const iframe = document.createElement('iframe');
iframe.src = "//{{domains[www1]}}:{{location[port]}}/document-policy/experimental-features/document-domain/resources/document-domain-disabled.html";
iframe.onload = () => {
iframe.contentWindow.postMessage({
type: "set document.domain",
newValue: "{{host}}"
}, "*");
};
window.addEventListener('message', t.step_func(e => {
if (e.source == iframe.contentWindow) {
assert_equals(e.data.oldDomain, "{{domains[www1]}}");
assert_equals(e.data.newDomain, "{{domains[www1]}}");
t.done();
}
}));
document.body.appendChild(iframe);
}, 'document.domain should be disabled in subframe.');
</script>
</body>

View file

@ -0,0 +1,15 @@
<!DOCTYPE html>
<body>
<script>
window.onmessage = e => {
if (e.data.type === "set document.domain") {
oldDomain = document.domain;
document.domain = e.data.newValue;
e.source.postMessage({
oldDomain,
newDomain: document.domain
}, "*");
}
};
</script>
</body>

View file

@ -0,0 +1,16 @@
<!DOCTYPE html>
<body>
<script>
window.onmessage = e => {
if (e.data.type === "set document.domain") {
oldDomain = document.domain;
document.domain = e.data.newValue;
e.source.postMessage({
oldDomain,
newDomain: document.domain
}, "*");
}
};
</script>
</body>

View file

@ -181,10 +181,8 @@
deletionParent.ariaActiveDescendantElement = idlAttrElement;
assert_equals(deletionParent.getAttribute("aria-activedescendant"), "idlAttrElement");
// The element is still retrieved because it was explicitly set, and was at that point
// in a valid scope.
deletionParent.removeChild(idlAttrElement);
assert_equals(deletionParent.ariaActiveDescendantElement, idlAttrElement);
assert_equals(deletionParent.ariaActiveDescendantElement, null);
// The content attribute will still reflect the id.
assert_equals(deletionParent.getAttribute("aria-activedescendant"), "idlAttrElement");
@ -221,8 +219,9 @@
}, "Changing the ID of an element causes the content attribute to become out of sync.");
</script>
<!-- TODO(chrishall): change naming scheme to inner/outer -->
<div id="lightParent" role="listbox">
<div role="option" id="lightElement">Hello world!</div>
<div id="lightElement" role="option">Hello world!</div>
</div>
<div id="shadowHostElement"></div>
@ -231,23 +230,104 @@
const lightElement = document.getElementById("lightElement");
const shadowRoot = shadowHostElement.attachShadow({mode: "open"});
assert_equals(lightParent.ariaActiveDescendantElement, null, 'null before');
assert_equals(lightParent.getAttribute('aria-activedescendant'), null, 'null before');
lightParent.ariaActiveDescendantElement = lightElement;
assert_equals(lightParent.ariaActiveDescendantElement, lightElement);
assert_equals(lightParent.getAttribute('aria-activedescendant'), "lightElement");
// Move the referenced element into shadow DOM. As it was explicitly set,
// it is still able to be gotten even though it is in a different scope.
// Move the referenced element into shadow DOM.
// This will cause the computed attr-associated element to be null as the
// referenced element will no longer be in a valid scope.
// The underlying reference is kept intact, so if the referenced element is
// later restored to a valid scope the computed attr-associated element will
// then reflect
shadowRoot.appendChild(lightElement);
assert_equals(lightParent.ariaActiveDescendantElement, lightElement);
assert_equals(lightParent.ariaActiveDescendantElement, null, "computed attr-assoc element should be null as referenced element is in an invalid scope");
assert_equals(lightParent.getAttribute("aria-activedescendant"), "lightElement");
// Move the referenced element back into light DOM.
// Since the underlying reference was kept intact, after moving the
// referenced element back to a valid scope should be reflected in the
// computed attr-associated element.
lightParent.appendChild(lightElement);
assert_equals(lightParent.ariaActiveDescendantElement, lightElement);
assert_equals(lightParent.ariaActiveDescendantElement, lightElement, "computed attr-assoc element should be restored as referenced element is back in a valid scope");
assert_equals(lightParent.getAttribute("aria-activedescendant"), "lightElement");
}, "Reparenting an element into a descendant shadow scope nullifies the element reference.");
}, "Reparenting an element into a descendant shadow scope hides the element reference.");
</script>
<div id="billingElement">Billing</div>
<div id='fruitbowl' role='listbox'>
<div id='apple' role='option'>I am an apple</div>
<div id='pear' role='option'>I am a pear</div>
<div id='banana' role='option'>I am a banana</div>
</div>
<div id='shadowFridge'></div>
<script>
test(function(t) {
const shadowRoot = shadowFridge.attachShadow({mode: "open"});
const banana = document.getElementById("banana");
fruitbowl.ariaActiveDescendantElement = apple;
assert_equals(fruitbowl.ariaActiveDescendantElement, apple);
assert_equals(fruitbowl.getAttribute("aria-activedescendant"), "apple");
// Move the referenced element into shadow DOM.
shadowRoot.appendChild(apple);
assert_equals(fruitbowl.ariaActiveDescendantElement, null, "computed attr-assoc element should be null as referenced element is in an invalid scope");
// Note that the content attribute is NOT cleared.
assert_equals(fruitbowl.getAttribute("aria-activedescendant"), "apple");
// let us rename our banana to an apple
banana.setAttribute("id", "apple");
const lyingBanana = document.getElementById("apple");
assert_equals(lyingBanana, banana);
// our ariaActiveDescendantElement thankfully isn't tricked.
// this is thanks to the underlying reference being kept intact, it is
// checked and found to be in an invalid scope and therefore the content
// attribute fallback isn't used.
assert_equals(fruitbowl.ariaActiveDescendantElement, null);
// our content attribute still returns "apple",
// even though fetching that by id would give us our lying banana.
assert_equals(fruitbowl.getAttribute("aria-activedescendant"), "apple");
// when we remove our IDL attribute, the content attribute is also thankfully cleared.
fruitbowl.ariaActiveDescendantElement = null;
assert_equals(fruitbowl.ariaActiveDescendantElement, null);
assert_equals(fruitbowl.getAttribute("aria-activedescendant"), null);
}, "Reparenting referenced element cannot cause retargeting of reference.");
</script>
<div id='toaster' role='listbox'></div>
<div id='shadowPantry'></div>
<script>
test(function(t) {
const shadowRoot = shadowPantry.attachShadow({mode: "open"});
// Our toast starts in the shadowPantry.
const toast = document.createElement("div");
toast.setAttribute("id", "toast");
shadowRoot.appendChild(toast);
// Prepare my toast for toasting
toaster.ariaActiveDescendantElement = toast;
assert_equals(toaster.ariaActiveDescendantElement, null);
assert_equals(toaster.getAttribute("aria-activedescendant"), "");
// Time to make some toast
toaster.appendChild(toast);
assert_equals(toaster.ariaActiveDescendantElement, toast);
// Current spec behaviour:
assert_equals(toaster.getAttribute("aria-activedescendant"), "");
}, "Element reference set in invalid scope remains intact throughout move to valid scope.");
</script>
<div id="billingElementContainer">
<div id="billingElement">Billing</div>
</div>
<div>
<div id="nameElement">Name</div>
<input type="text" id="input1" aria-labelledby="billingElement nameElement"/>
@ -267,9 +347,15 @@
assert_array_equals(input2.ariaLabelledByElements, [billingElement, addressElement], "Testing IDL setter/getter.");
assert_equals(input2.getAttribute("aria-labelledby"), "billingElement addressElement");
// Remove the element from the DOM, but as it was explicitly set whilst in a valid scope
// it can still be retrieved.
// Remove the billingElement from the DOM.
// As it was explicitly set the underlying association will remain intact,
// but it will be hidden until the element is moved back into a valid scope.
billingElement.remove();
assert_array_equals(input2.ariaLabelledByElements, [addressElement]);
// Insert the billingElement back into the DOM and check that it is visible
// again, as the underlying association should have been kept intact.
billingElementContainer.appendChild(billingElement);
assert_array_equals(input2.ariaLabelledByElements, [billingElement, addressElement]);
input2.ariaLabelledByElements = [];
@ -445,8 +531,8 @@
// Elements that cross into shadow DOM are dropped, only reflect the valid
// elements in IDL and in the content attribute.
lightDomHeading.ariaFlowToElements = [shadowChild1, shadowChild2, lightDomText1, lightDomText2];
assert_array_equals(lightDomHeading.ariaFlowToElements, [lightDomText1, lightDomText2]);
assert_equals(lightDomHeading.getAttribute("aria-flowto"), "lightDomText1 lightDomText2", "empty content attribute if any given elements cross shadow boundaries");
assert_array_equals(lightDomHeading.ariaFlowToElements, [lightDomText1, lightDomText2], "IDL should only include valid elements");
assert_equals(lightDomHeading.getAttribute("aria-flowto"), "", "empty content attribute if any given elements cross shadow boundaries");
// Using a mixture of elements in the same scope and in a shadow including
// ancestor should set the IDL attribute, but should reflect the empty
@ -479,29 +565,28 @@
describedElement.ariaDescribedByElements = [description1, description2];
// All elements were in the same scope, so elements are gettable and the content attribute reflects the ids.
assert_array_equals(describedElement.ariaDescribedByElements, [description1, description2]);
assert_array_equals(describedElement.ariaDescribedByElements, [description1, description2], "same scope reference");
assert_equals(describedElement.getAttribute("aria-describedby"), "buttonDescription1 buttonDescription2");
outerShadowRoot.appendChild(describedElement);
// Explicitly set attr-associated-elements should still be gettable because we are referencing elements in a lighter scope.
// The content attr still reflects the ids from the explicit elements because they were in a valid scope at the time of setting.
assert_array_equals(describedElement.ariaDescribedByElements, [description1, description2]);
assert_array_equals(describedElement.ariaDescribedByElements, [description1, description2], "lighter scope reference");
assert_equals(describedElement.getAttribute("aria-describedby"), "buttonDescription1 buttonDescription2");
// Move the explicitly set elements into a deeper shadow DOM to test the relationship should not be gettable.
innerShadowRoot.appendChild(description1);
innerShadowRoot.appendChild(description2);
// Explicitly set elements are still retrieved, because they were in a valid scope when they were set.
// The content attribute still reflects the ids.
assert_array_equals(describedElement.ariaDescribedByElements, [description1, description2]);
// Explicitly set elements are no longer retrievable, because they are no longer in a valid scope.
assert_array_equals(describedElement.ariaDescribedByElements, [], "invalid scope reference");
assert_equals(describedElement.getAttribute("aria-describedby"), "buttonDescription1 buttonDescription2");
// Move into the same shadow scope as the explicitly set elements to test that the elements are gettable
// and reflect the correct IDs onto the content attribute.
innerShadowRoot.appendChild(describedElement);
assert_array_equals(describedElement.ariaDescribedByElements, [description1, description2]);
assert_array_equals(describedElement.ariaDescribedByElements, [description1, description2], "restored valid scope reference");
assert_equals(describedElement.getAttribute("aria-describedby"), "buttonDescription1 buttonDescription2");
}, "Moving explicitly set elements across shadow DOM boundaries.");
</script>
@ -539,20 +624,21 @@
headingElement.ariaLabelledByElements = [headingLabel1, headingLabel2];
assert_equals(headingElement.getAttribute("aria-labelledby"), "headingLabel1 headingLabel2", "Elements are set again, so the content attribute is updated.");
// Remove the referring element from the DOM, elements are gettable.
// Remove the referring element from the DOM, elements are no longer longer exposed,
// underlying internal reference is still kept intact.
headingElement.remove();
assert_array_equals(headingElement.ariaLabelledByElements, [headingLabel1, headingLabel2], "Element is no longer in the document, but references should be gettable.");
assert_array_equals(headingElement.ariaLabelledByElements, [], "Element is no longer in the document, so references should no longer be exposed.");
assert_equals(headingElement.getAttribute("aria-labelledby"), "headingLabel1 headingLabel2");
// Insert it back in.
sameScopeContainer.appendChild(headingElement);
assert_array_equals(headingElement.ariaLabelledByElements, [headingLabel1, headingLabel2]);
assert_array_equals(headingElement.ariaLabelledByElements, [headingLabel1, headingLabel2], "Element is restored to valid scope, so should be gettable.");
assert_equals(headingElement.getAttribute("aria-labelledby"), "headingLabel1 headingLabel2");
// Remove everything from the DOM, everything is still gettable.
// Remove everything from the DOM, nothing is exposed again.
headingLabel1.remove();
headingLabel2.remove();
assert_array_equals(headingElement.ariaLabelledByElements, [headingLabel1, headingLabel2]);
assert_array_equals(headingElement.ariaLabelledByElements, []);
assert_equals(headingElement.getAttribute("aria-labelledby"), "headingLabel1 headingLabel2");
assert_equals(document.getElementById("headingLabel1"), null);
assert_equals(document.getElementById("headingLabel2"), null);
@ -579,4 +665,47 @@
// See: https://github.com/whatwg/html/pull/3917#issuecomment-527263562
assert_equals(input.ariaActiveDescendantElement, first);
}, "Reparenting.");
</script>
<div id='fromDiv'></div>
<script>
test(function(t) {
const toSpan = document.createElement('span');
toSpan.setAttribute("id", "toSpan");
fromDiv.ariaActiveDescendantElement = toSpan;
assert_equals(fromDiv.ariaActiveDescendantElement, null, "Referenced element not inserted into document, so is in an invalid scope.");
assert_equals(fromDiv.getAttribute("aria-activedescendant"), "", "Invalid scope, so content attribute not set.");
fromDiv.appendChild(toSpan);
assert_equals(fromDiv.ariaActiveDescendantElement, toSpan, "Referenced element now inserted into the document.");
assert_equals(fromDiv.getAttribute("aria-activedescendant"), "", "Content attribute remains empty, as it is only updated at set time.");
}, "Attaching element reference before it's inserted into the DOM.");
</script>
<div id='originalDocumentDiv'></div>
<script>
test(function(t) {
const newDoc = document.implementation.createHTMLDocument('new document');
const newDocSpan = newDoc.createElement('span');
newDoc.body.appendChild(newDocSpan);
// Create a reference across documents.
originalDocumentDiv.ariaActiveDescendantElement = newDocSpan;
assert_equals(originalDocumentDiv.ariaActiveDescendantElement, null, "Cross-document is an invalid scope, so reference will not be visible.");
assert_equals(fromDiv.getAttribute("aria-activedescendant"), "", "Invalid scope when set, so content attribute not set.");
// "Move" span to first document.
originalDocumentDiv.appendChild(newDocSpan);
// Implementation defined: moving object into same document from other document may cause reference to become visible.
assert_equals(originalDocumentDiv.ariaActiveDescendantElement, newDocSpan, "Implementation defined: moving object back *may* make reference visible.");
assert_equals(fromDiv.getAttribute("aria-activedescendant"), "", "Invalid scope when set, so content attribute not set.");
}, "Cross-document references and moves.");
</script>
</html>

View file

@ -1,5 +1,6 @@
// META: title=Encoding API: Encoding labels
// META: script=resources/encodings.js
// META: timeout=long
var whitespace = [' ', '\t', '\n', '\f', '\r'];
encodings_table.forEach(function(section) {

View file

@ -1,3 +1,4 @@
// META: timeout=long
// DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py.
// OffscreenCanvas test in a worker:2d.composite.uncovered.fill.destination-in
// Description:fill() draws pixels not covered by the source object as (0,0,0,0), and does not leave the pixels unchanged.

View file

@ -1,3 +1,4 @@
// META: timeout=long
// DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py.
// OffscreenCanvas test in a worker:2d.drawImage.3arg
// Description:

View file

@ -1,3 +1,4 @@
// META: timeout=long
// DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py.
// OffscreenCanvas test in a worker:2d.drawImage.5arg
// Description:

View file

@ -1,3 +1,4 @@
// META: timeout=long
// DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py.
// OffscreenCanvas test in a worker:2d.drawImage.9arg.basic
// Description:

View file

@ -1,3 +1,4 @@
// META: timeout=long
// DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py.
// OffscreenCanvas test in a worker:2d.drawImage.9arg.destpos
// Description:

View file

@ -1,3 +1,4 @@
// META: timeout=long
// DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py.
// OffscreenCanvas test in a worker:2d.drawImage.9arg.destsize
// Description:

View file

@ -1,3 +1,4 @@
// META: timeout=long
// DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py.
// OffscreenCanvas test in a worker:2d.drawImage.9arg.sourcepos
// Description:

View file

@ -1,3 +1,4 @@
// META: timeout=long
// DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py.
// OffscreenCanvas test in a worker:2d.drawImage.9arg.sourcesize
// Description:

View file

@ -1,3 +1,4 @@
// META: timeout=long
// DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py.
// OffscreenCanvas test in a worker:2d.drawImage.alpha
// Description:

View file

@ -1,3 +1,4 @@
// META: timeout=long
// DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py.
// OffscreenCanvas test in a worker:2d.drawImage.animated.poster
// Description:drawImage() of an APNG draws the poster frame

View file

@ -1,3 +1,4 @@
// META: timeout=long
// DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py.
// OffscreenCanvas test in a worker:2d.drawImage.broken
// Description:

View file

@ -1,3 +1,4 @@
// META: timeout=long
// DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py.
// OffscreenCanvas test in a worker:2d.drawImage.canvas
// Description:

View file

@ -1,3 +1,4 @@
// META: timeout=long
// DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py.
// OffscreenCanvas test in a worker:2d.drawImage.clip
// Description:

View file

@ -1,3 +1,4 @@
// META: timeout=long
// DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py.
// OffscreenCanvas test in a worker:2d.drawImage.composite
// Description:

View file

@ -1,3 +1,4 @@
// META: timeout=long
// DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py.
// OffscreenCanvas test in a worker:2d.drawImage.floatsource
// Description:

View file

@ -1,3 +1,4 @@
// META: timeout=long
// DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py.
// OffscreenCanvas test in a worker:2d.drawImage.negativedest
// Description:Negative destination width/height represents the correct rectangle

View file

@ -1,3 +1,4 @@
// META: timeout=long
// DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py.
// OffscreenCanvas test in a worker:2d.drawImage.negativedir
// Description:Negative dimensions do not affect the direction of the image

View file

@ -1,3 +1,4 @@
// META: timeout=long
// DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py.
// OffscreenCanvas test in a worker:2d.drawImage.negativesource
// Description:Negative source width/height represents the correct rectangle

View file

@ -1,3 +1,4 @@
// META: timeout=long
// DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py.
// OffscreenCanvas test in a worker:2d.drawImage.nonfinite
// Description:drawImage() with Infinity/NaN is ignored

View file

@ -1,3 +1,4 @@
// META: timeout=long
// DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py.
// OffscreenCanvas test in a worker:2d.drawImage.nowrap
// Description:Stretched images do not get pixels wrapping around the edges

View file

@ -1,3 +1,4 @@
// META: timeout=long
// DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py.
// OffscreenCanvas test in a worker:2d.drawImage.null
// Description:

View file

@ -1,3 +1,4 @@
// META: timeout=long
// DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py.
// OffscreenCanvas test in a worker:2d.drawImage.path
// Description:

View file

@ -1,3 +1,4 @@
// META: timeout=long
// DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py.
// OffscreenCanvas test in a worker:2d.drawImage.self.1
// Description:

View file

@ -1,3 +1,4 @@
// META: timeout=long
// DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py.
// OffscreenCanvas test in a worker:2d.drawImage.self.2
// Description:

View file

@ -1,3 +1,4 @@
// META: timeout=long
// DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py.
// OffscreenCanvas test in a worker:2d.drawImage.svg
// Description:drawImage() of an SVG image

View file

@ -1,3 +1,4 @@
// META: timeout=long
// DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py.
// OffscreenCanvas test in a worker:2d.drawImage.transform
// Description:

View file

@ -1,3 +1,4 @@
// META: timeout=long
// DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py.
// OffscreenCanvas test in a worker:2d.drawImage.wrongtype
// Description:Incorrect image types in drawImage do not match any defined overloads, so WebIDL throws a TypeError

View file

@ -1,3 +1,4 @@
// META: timeout=long
// DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py.
// OffscreenCanvas test in a worker:2d.drawImage.zerocanvas
// Description:

View file

@ -1,3 +1,4 @@
// META: timeout=long
// DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py.
// OffscreenCanvas test in a worker:2d.drawImage.zerosource.image
// Description:drawImage with zero-sized source rectangle from image draws nothing without exception

View file

@ -1,3 +1,4 @@
// META: timeout=long
// DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py.
// OffscreenCanvas test in a worker:2d.drawImage.zerosource
// Description:drawImage with zero-sized source rectangle draws nothing without exception

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