mirror of
https://github.com/servo/servo.git
synced 2025-08-07 14:35:33 +01:00
Update web-platform-tests to revision a46616a5b18e83587ddbbed756c7b96cbb4b015d
This commit is contained in:
parent
3f07cfec7c
commit
578498ba24
4001 changed files with 159517 additions and 30260 deletions
|
@ -0,0 +1,21 @@
|
|||
<!doctype html>
|
||||
<html>
|
||||
<head>
|
||||
<title>img ismap attribute coordinate origin</title>
|
||||
<style>
|
||||
#bg { background-color: lightgray; position: relative; }
|
||||
#target { position: absolute; width: 48px; height: 48px; border: 2px dashed green; pointer-events: none; }
|
||||
.after { top: 246px; left: 246px; }
|
||||
img { margin: 50px; border: 50px solid white; padding: 50px; }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div id="bg">
|
||||
<div id="target" class="after"></div>
|
||||
<a href="/somewhere/">
|
||||
<img src="/images/blue96x96.png" ismap>
|
||||
</a>
|
||||
</div>
|
||||
<h1>Click inside the dashed rectangle</h1>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,21 @@
|
|||
<!doctype html>
|
||||
<html>
|
||||
<head>
|
||||
<title>img ismap attribute coordinate origin</title>
|
||||
<style>
|
||||
#bg { background-color: lightgray; position: relative; }
|
||||
#target { position: absolute; width: 96px; height: 96px; border: 2px dashed green; pointer-events: none; }
|
||||
.before { top: 50px; left: 50px; }
|
||||
img { margin: 50px; border: 50px solid white; padding: 50px; }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div id="bg">
|
||||
<div id="target" class="before"></div>
|
||||
<a href="/somewhere/">
|
||||
<img src="/images/blue96x96.png" ismap>
|
||||
</a>
|
||||
</div>
|
||||
<h1>Click inside the dashed rectangle</h1>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,21 @@
|
|||
<!doctype html>
|
||||
<html>
|
||||
<head>
|
||||
<title>img ismap attribute coordinate origin</title>
|
||||
<style>
|
||||
#bg { background-color: lightgray; position: relative; }
|
||||
#target { position: absolute; width: 96px; height: 96px; border: 2px dashed green; pointer-events: none; }
|
||||
.in { top: 148px; left: 148px; }
|
||||
img { margin: 50px; border: 50px solid white; padding: 50px; }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div id="bg">
|
||||
<div id="target" class="in"></div>
|
||||
<a href="/common/blank.html">
|
||||
<img src="/images/blue96x96.png" ismap>
|
||||
</a>
|
||||
</div>
|
||||
<h1>Click inside the dashed rectangle</h1>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,78 @@
|
|||
<!doctype html>
|
||||
<html>
|
||||
<head>
|
||||
<title>img ismap attribute coordinate origin</title>
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<style>
|
||||
iframe { width: 500px; height: 500px; }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<iframe></iframe>
|
||||
<div id="log"></div>
|
||||
<script type="text/javascript">
|
||||
tests = [
|
||||
{
|
||||
file: "img-ismap-coordinates-iframe-inside.html",
|
||||
},
|
||||
{
|
||||
test: async_test("Coordinates within the content box of an image map have origin of the context box"),
|
||||
resultMinXY: 0,
|
||||
resultMaxXY: 96,
|
||||
},
|
||||
{
|
||||
file: "img-ismap-coordinates-iframe-before.html",
|
||||
},
|
||||
{
|
||||
test: async_test("Coordinates within the margin/padding (top-left) of the image map are clamped to zero"),
|
||||
resultMinXY: 0,
|
||||
resultMaxXY: 0,
|
||||
},
|
||||
{
|
||||
file: "img-ismap-coordinates-iframe-after.html",
|
||||
},
|
||||
{
|
||||
test: async_test("Coordinates within the margin/padding (bottom-right) of the image map have origin in the content box"),
|
||||
resultMinXY: 97,
|
||||
resultMaxXY: 146,
|
||||
}
|
||||
];
|
||||
testIndex = 0;
|
||||
|
||||
var iframe = document.querySelector('iframe');
|
||||
iframe.onload = function testInit() {
|
||||
if (testIndex % 2 == 0) {
|
||||
testIndex++;
|
||||
return;
|
||||
}
|
||||
// User clicked on a results...
|
||||
var url = iframe.contentWindow.location.toString();
|
||||
var test = tests[testIndex].test;
|
||||
var minXY = tests[testIndex].resultMinXY;
|
||||
var maxXY = tests[testIndex].resultMaxXY;
|
||||
testIndex++;
|
||||
if (testIndex < tests.length)
|
||||
iframe.src = tests[testIndex].file; // Advance the test...
|
||||
// Validate the last test's results...
|
||||
test.step(function () {
|
||||
var i = url.indexOf("?");
|
||||
assert_not_equals(i, -1);
|
||||
var coordsStr = url.substr(i+1);
|
||||
var i = coordsStr.indexOf(',');
|
||||
assert_not_equals(i, -1);
|
||||
var x = parseFloat(coordsStr.substring(0, i));
|
||||
var y = parseFloat(coordsStr.substring(i+1));
|
||||
assert_greater_than_equal(x, minXY);
|
||||
assert_less_than_equal(x, maxXY);
|
||||
assert_greater_than_equal(y, minXY);
|
||||
assert_less_than_equal(y, maxXY);
|
||||
test.done();
|
||||
});
|
||||
if (testIndex >= tests.length)
|
||||
iframe.style.display = "none";
|
||||
}
|
||||
iframe.src = tests[0].file;
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,61 @@
|
|||
<!DOCTYPE html>
|
||||
<meta charset="utf-8">
|
||||
<title>Resetting a form integration test</title>
|
||||
<link rel="author" title="Domenic Denicola" href="mailto:d@domenic.me">
|
||||
<link rel="help" href="https://html.spec.whatwg.org/multipage/#concept-form-reset">
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
|
||||
<script>
|
||||
"use strict";
|
||||
|
||||
test(() => {
|
||||
|
||||
const form = document.createElement("form");
|
||||
const text = document.createElement("input");
|
||||
text.type = "text";
|
||||
const checkbox = document.createElement("input");
|
||||
checkbox.type = "checkbox";
|
||||
const select = document.createElement("select");
|
||||
select.multiple = true;
|
||||
const option = document.createElement("option");
|
||||
option.value = "option";
|
||||
const textarea = document.createElement("textarea");
|
||||
|
||||
form.appendChild(text);
|
||||
form.appendChild(checkbox);
|
||||
form.appendChild(textarea);
|
||||
form.appendChild(select);
|
||||
select.appendChild(option);
|
||||
|
||||
text.defaultValue = "text default";
|
||||
checkbox.defaultChecked = true;
|
||||
option.defaultSelected = true;
|
||||
textarea.defaultValue = "textarea default";
|
||||
|
||||
text.value = "text new value";
|
||||
checkbox.checked = false;
|
||||
option.selected = false;
|
||||
textarea.value = "textarea new value";
|
||||
|
||||
form.reset();
|
||||
|
||||
assert_equals(text.value, "text default", "input should reset value to default");
|
||||
assert_equals(checkbox.checked, true, "input should reset checkedness to default");
|
||||
assert_equals(option.selected, true, "second option should reset selectedness to default");
|
||||
assert_equals(select.selectedIndex, 0, "second option should reset selectedness to default");
|
||||
assert_equals(textarea.value, "textarea default", "textarea should reset api value to default");
|
||||
|
||||
text.defaultValue = "text new default";
|
||||
checkbox.defaultChecked = false;
|
||||
option.defaultSelected = false;
|
||||
textarea.defaultValue = "textarea new default";
|
||||
|
||||
assert_equals(text.value, "text new default", "input should reset dirty value to false");
|
||||
assert_equals(checkbox.checked, false, "input should reset dirty checkedness to false");
|
||||
assert_equals(option.selected, false, "option should reset dirtyness to false");
|
||||
assert_equals(select.selectedIndex, -1, "option should reset dirtyness to false");
|
||||
assert_equals(textarea.value, "textarea new default", "textarea should reset dirty value to false");
|
||||
|
||||
}, "integration test on reset for a created-from-script form");
|
||||
</script>
|
|
@ -3,16 +3,142 @@
|
|||
<title>Selection indices after content change</title>
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
|
||||
<input id="i1" type="text" value="hello">
|
||||
<textarea id="t1">hello</textarea>
|
||||
|
||||
<script>
|
||||
test(function() {
|
||||
var input = document.createElement("input");
|
||||
input.focus();
|
||||
input.value = "something something something dark side";
|
||||
input.setSelectionRange(4,20);
|
||||
assert_equals(input.selectionStart, 4);
|
||||
assert_equals(input.selectionEnd, 20);
|
||||
input.value = "It's a trap!";
|
||||
assert_equals(input.selectionStart, input.value.length);
|
||||
assert_equals(input.selectionEnd, input.value.length);
|
||||
}, "Selection indices after reseting content");
|
||||
"use strict";
|
||||
|
||||
// This helper ensures that when the selection direction is reset, it always is reset to the same value consistently
|
||||
// (which must be one of either "none" or "forward"). This helps catch bugs like one observed in Chrome, where textareas
|
||||
// reset to "none" but inputs reset to "forward".
|
||||
let observedResetSelectionDirection;
|
||||
function assertSelectionDirectionIsReset(element) {
|
||||
if (!observedResetSelectionDirection) {
|
||||
assert_in_array(element.selectionDirection, ["none", "forward"],
|
||||
"selectionDirection must be set to either none or forward");
|
||||
observedResetSelectionDirection = element.selectionDirection;
|
||||
} else {
|
||||
assert_equals(element.selectionDirection, observedResetSelectionDirection,
|
||||
`selectionDirection must be reset to ${observedResetSelectionDirection} (which was previously observed to be ` +
|
||||
`the value after resetting the selection direction)`);
|
||||
}
|
||||
}
|
||||
|
||||
runInputTest("input out of document", () => {
|
||||
const input = document.createElement("input");
|
||||
input.value = "hello";
|
||||
return input;
|
||||
});
|
||||
|
||||
runInputTest("input in document", () => {
|
||||
const input = document.querySelector("#i1");
|
||||
input.value = "hello";
|
||||
return input;
|
||||
});
|
||||
|
||||
runInputTest("input in document, with focus", () => {
|
||||
const input = document.querySelector("#i1");
|
||||
input.value = "hello";
|
||||
input.focus();
|
||||
return input;
|
||||
});
|
||||
|
||||
runTextareaTest("textarea out of document", () => {
|
||||
const textarea = document.createElement("textarea");
|
||||
textarea.value = "hello";
|
||||
return textarea;
|
||||
});
|
||||
|
||||
runTextareaTest("textarea in document", () => {
|
||||
const textarea = document.querySelector("#t1");
|
||||
textarea.value = "hello";
|
||||
return textarea;
|
||||
});
|
||||
|
||||
runTextareaTest("textarea in document, with focus", () => {
|
||||
const textarea = document.querySelector("#t1");
|
||||
textarea.value = "hello";
|
||||
textarea.focus();
|
||||
return textarea;
|
||||
});
|
||||
|
||||
function runTest(descriptor, elementFactory) {
|
||||
test(() => {
|
||||
const element = elementFactory();
|
||||
element.setSelectionRange(1, 3, "backward");
|
||||
|
||||
assert_equals(element.selectionStart, 1, "Sanity check: selectionStart was set correctly");
|
||||
assert_equals(element.selectionEnd, 3, "Sanity check: selectionEnd was set correctly");
|
||||
assert_equals(element.selectionDirection, "backward", "Sanity check: selectionDirection was set correctly");
|
||||
|
||||
element.value = "hello";
|
||||
|
||||
assert_equals(element.selectionStart, 1, "selectionStart must not change");
|
||||
assert_equals(element.selectionEnd, 3, "selectionEnd must not change");
|
||||
assert_equals(element.selectionDirection, "backward", "selectionDirection must not change");
|
||||
}, `${descriptor}: selection must not change when setting the same value`);
|
||||
|
||||
test(() => {
|
||||
const element = elementFactory();
|
||||
element.setSelectionRange(1, 3, "backward");
|
||||
|
||||
assert_equals(element.selectionStart, 1, "Sanity check: selectionStart was set correctly");
|
||||
assert_equals(element.selectionEnd, 3, "Sanity check: selectionEnd was set correctly");
|
||||
assert_equals(element.selectionDirection, "backward", "Sanity check: selectionDirection was set correctly");
|
||||
|
||||
element.value = "hello2";
|
||||
|
||||
assert_equals(element.selectionStart, element.value.length, "selectionStart must be reset to the end");
|
||||
assert_equals(element.selectionEnd, element.value.length, "selectionEnd must be reset to the end");
|
||||
assertSelectionDirectionIsReset(element);
|
||||
}, `${descriptor}: selection must change when setting a different value`);
|
||||
}
|
||||
|
||||
function runInputTest(descriptor, elementFactory) {
|
||||
runTest(descriptor, elementFactory);
|
||||
|
||||
test(() => {
|
||||
const input = elementFactory();
|
||||
input.setSelectionRange(1, 3, "backward");
|
||||
|
||||
assert_equals(input.selectionStart, 1, "Sanity check: selectionStart was set correctly");
|
||||
assert_equals(input.selectionEnd, 3, "Sanity check: selectionEnd was set correctly");
|
||||
assert_equals(input.selectionDirection, "backward", "Sanity check: selectionDirection was set correctly");
|
||||
|
||||
input.value = "he\nllo";
|
||||
|
||||
assert_equals(input.selectionStart, 1, "selectionStart must not change");
|
||||
assert_equals(input.selectionEnd, 3, "selectionEnd must not change");
|
||||
assert_equals(input.selectionDirection, "backward", "selectionDirection must not change");
|
||||
}, `${descriptor}: selection must not change when setting a value that becomes the same after the value ` +
|
||||
`sanitization algorithm`);
|
||||
}
|
||||
|
||||
function runTextareaTest(descriptor, elementFactory) {
|
||||
runTest(descriptor, elementFactory);
|
||||
|
||||
test(() => {
|
||||
const textarea = elementFactory();
|
||||
textarea.value = "hell\no";
|
||||
textarea.setSelectionRange(1, 3, "backward");
|
||||
|
||||
assert_equals(textarea.selectionStart, 1, "Sanity check: selectionStart was set correctly");
|
||||
assert_equals(textarea.selectionEnd, 3, "Sanity check: selectionEnd was set correctly");
|
||||
assert_equals(textarea.selectionDirection, "backward", "Sanity check: selectionDirection was set correctly");
|
||||
|
||||
textarea.value = "hell\r\no";
|
||||
|
||||
assert_equals(textarea.selectionStart, 1, "selectionStart must not change when setting to CRLF");
|
||||
assert_equals(textarea.selectionEnd, 3, "selectionEnd must not change when setting to CRLF");
|
||||
assert_equals(textarea.selectionDirection, "backward", "selectionDirection must not change when setting to CRLF");
|
||||
|
||||
textarea.value = "hell\ro";
|
||||
|
||||
assert_equals(textarea.selectionStart, 1, "selectionStart must not change when setting to CR");
|
||||
assert_equals(textarea.selectionEnd, 3, "selectionEnd must not change when setting to CR");
|
||||
assert_equals(textarea.selectionDirection, "backward", "selectionDirection must not change when setting to CR");
|
||||
}, `${descriptor}: selection must not change when setting the same normalized value`);
|
||||
}
|
||||
</script>
|
||||
|
|
|
@ -0,0 +1,149 @@
|
|||
<!DOCTYPE html>
|
||||
<meta charset="utf-8">
|
||||
<title>Clicking a button should submit the form</title>
|
||||
<link rel="author" title="Domenic Denicola" href="mailto:d@domenic.me">
|
||||
<link rel="help" href="https://html.spec.whatwg.org/multipage/#attr-button-type-submit-state">
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
|
||||
<body>
|
||||
<script>
|
||||
"use strict";
|
||||
|
||||
async_test(t => {
|
||||
|
||||
const form = document.createElement("form");
|
||||
const button = document.createElement("button");
|
||||
form.appendChild(button);
|
||||
document.body.appendChild(form);
|
||||
|
||||
form.addEventListener("submit", t.step_func_done(ev => {
|
||||
ev.preventDefault();
|
||||
assert_equals(ev.target, form);
|
||||
}));
|
||||
|
||||
button.click();
|
||||
|
||||
}, "clicking a button with .click() should trigger a submit (form connected)");
|
||||
|
||||
async_test(t => {
|
||||
|
||||
const form = document.createElement("form");
|
||||
const button = document.createElement("button");
|
||||
form.appendChild(button);
|
||||
|
||||
form.addEventListener("submit", t.step_func_done(ev => {
|
||||
ev.preventDefault();
|
||||
assert_unreached("Form should not be submitted");
|
||||
}));
|
||||
|
||||
button.click();
|
||||
t.step_timeout(() => t.done(), 500);
|
||||
|
||||
}, "clicking a button with .click() should not trigger a submit (form disconnected)");
|
||||
|
||||
async_test(t => {
|
||||
|
||||
const form = document.createElement("form");
|
||||
const button = document.createElement("button");
|
||||
form.appendChild(button);
|
||||
document.body.appendChild(form);
|
||||
|
||||
form.addEventListener("submit", t.step_func_done(ev => {
|
||||
ev.preventDefault();
|
||||
assert_equals(ev.target, form);
|
||||
}));
|
||||
|
||||
const e = new MouseEvent("click");
|
||||
button.dispatchEvent(e);
|
||||
|
||||
}, "clicking a button by dispatching an event should trigger a submit (form connected)");
|
||||
|
||||
async_test(t => {
|
||||
|
||||
const form = document.createElement("form");
|
||||
const button = document.createElement("button");
|
||||
form.appendChild(button);
|
||||
|
||||
form.addEventListener("submit", t.step_func_done(ev => {
|
||||
ev.preventDefault();
|
||||
assert_unreached("Form should not be submitted");
|
||||
}));
|
||||
|
||||
const e = new MouseEvent("click");
|
||||
button.dispatchEvent(e);
|
||||
t.step_timeout(() => t.done(), 500);
|
||||
|
||||
}, "clicking a button by dispatching an event should not trigger a submit (form disconnected)");
|
||||
|
||||
async_test(t => {
|
||||
|
||||
const form = document.createElement("form");
|
||||
const button = document.createElement("button");
|
||||
form.appendChild(button);
|
||||
|
||||
form.addEventListener("submit", t.step_func_done(ev => {
|
||||
ev.preventDefault();
|
||||
assert_unreached("Form should not be submitted");
|
||||
}));
|
||||
|
||||
button.addEventListener("click", t.step_func(ev => {
|
||||
ev.preventDefault();
|
||||
t.step_timeout(() => t.done(), 500);
|
||||
}));
|
||||
button.click();
|
||||
|
||||
}, "clicking a button that cancels the event should not trigger a submit");
|
||||
|
||||
async_test(t => {
|
||||
|
||||
const form = document.createElement("form");
|
||||
const button = document.createElement("button");
|
||||
button.setAttribute("disabled", "");
|
||||
form.appendChild(button);
|
||||
document.body.appendChild(form);
|
||||
|
||||
form.addEventListener("submit", t.step_func_done(ev => {
|
||||
ev.preventDefault();
|
||||
assert_unreached("Form should not be submitted");
|
||||
}));
|
||||
|
||||
button.click();
|
||||
t.step_timeout(() => t.done(), 500);
|
||||
|
||||
}, "clicking a disabled button (via disabled attribute) should not trigger submit");
|
||||
|
||||
async_test(t => {
|
||||
|
||||
const form = document.createElement("form");
|
||||
form.innerHTML = `<fieldset disabled><button>hello</button></fieldset>`;
|
||||
const button = form.querySelector("button");
|
||||
document.body.appendChild(form);
|
||||
|
||||
form.addEventListener("submit", t.step_func_done(ev => {
|
||||
ev.preventDefault();
|
||||
assert_unreached("Form should not be submitted");
|
||||
}));
|
||||
|
||||
button.click();
|
||||
t.step_timeout(() => t.done(), 500);
|
||||
|
||||
}, "clicking a disabled button (via ancestor fieldset) should not trigger submit");
|
||||
|
||||
test(t => {
|
||||
|
||||
const form = document.createElement("form");
|
||||
form.innerHTML = `<fieldset disabled><legend><button>hello</button></legend></fieldset>`;
|
||||
const button = form.querySelector("button");
|
||||
document.body.appendChild(form);
|
||||
|
||||
form.addEventListener("submit", t.step_func_done(ev => {
|
||||
ev.preventDefault();
|
||||
assert_equals(ev.target, form);
|
||||
}));
|
||||
|
||||
button.click();
|
||||
|
||||
}, "clicking a button inside a disabled fieldset's legend *should* trigger submit");
|
||||
|
||||
</script>
|
|
@ -0,0 +1,41 @@
|
|||
<!DOCTYPE html>
|
||||
<meta charset="utf-8">
|
||||
<title>HTMLButtonElement.prototype.type</title>
|
||||
<link rel="author" title="Domenic Denicola" href="mailto:d@domenic.me">
|
||||
<link rel="help" href="https://html.spec.whatwg.org/multipage/#dom-button-type">
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
|
||||
<script>
|
||||
"use strict";
|
||||
|
||||
test(() => {
|
||||
|
||||
const button = document.createElement("button");
|
||||
assert_equals(button.type, "submit");
|
||||
|
||||
}, "a button's type should be submit by default");
|
||||
|
||||
test(() => {
|
||||
|
||||
const button = document.createElement("button");
|
||||
|
||||
for (const type of ["reset", "button", "submit"]) {
|
||||
button.type = type;
|
||||
assert_equals(button.type, type);
|
||||
|
||||
button.type = type.toUpperCase();
|
||||
assert_equals(button.type, type);
|
||||
}
|
||||
|
||||
button.type = "reset";
|
||||
button.type = "asdfgdsafd";
|
||||
assert_equals(button.type, "submit");
|
||||
|
||||
button.type = "reset";
|
||||
button.type = "";
|
||||
assert_equals(button.type, "submit");
|
||||
|
||||
}, "a button's type should stay within the range of valid values");
|
||||
|
||||
</script>
|
|
@ -0,0 +1,36 @@
|
|||
<!DOCTYPE html>
|
||||
<meta charset="utf-8">
|
||||
<title>form.action with a base URL</title>
|
||||
<link rel="author" title="Domenic Denicola" href="mailto:d@domenic.me">
|
||||
<link rel="help" href="https://html.spec.whatwg.org/multipage/forms.html#dom-fs-action">
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<base href="/common/blank.html">
|
||||
|
||||
<form id="form1" action="a.html"></form>
|
||||
<form id="form2" action=""></form>
|
||||
<form id="form3"></form>
|
||||
|
||||
<script>
|
||||
"use strict";
|
||||
|
||||
test(() => {
|
||||
|
||||
assert_equals(document.querySelector("#form1").action, (new URL("a.html", document.baseURI)).href,
|
||||
"action should equal the correct absolute URL");
|
||||
|
||||
}, "An action URL should be resolved relative to the document's base URL (not the document's URL)");
|
||||
|
||||
test(() => {
|
||||
|
||||
assert_equals(document.querySelector("#form2").action, document.URL);
|
||||
|
||||
}, "An empty-string action content attribute should cause the IDL attribute to return the document's URL (not the document's base URL)");
|
||||
|
||||
test(() => {
|
||||
|
||||
assert_equals(document.querySelector("#form3").action, document.URL);
|
||||
|
||||
}, "A missing action content attribute should cause the IDL attribute to return the document's URL (not the document's base URL)");
|
||||
|
||||
</script>
|
|
@ -0,0 +1,35 @@
|
|||
<!DOCTYPE html>
|
||||
<meta charset="utf-8">
|
||||
<title>form.action</title>
|
||||
<link rel="author" title="Domenic Denicola" href="mailto:d@domenic.me">
|
||||
<link rel="help" href="https://html.spec.whatwg.org/multipage/forms.html#dom-fs-action">
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
|
||||
<form id="form1" action="a.html"></form>
|
||||
<form id="form2" action=""></form>
|
||||
<form id="form3"></form>
|
||||
|
||||
<script>
|
||||
"use strict";
|
||||
|
||||
test(() => {
|
||||
|
||||
assert_equals(document.querySelector("#form1").action, (new URL("a.html", document.baseURI)).href,
|
||||
"action should equal the correct absolute URL");
|
||||
|
||||
}, "An action URL should be resolved relative to the document's base URL (= the document's URL in this case)");
|
||||
|
||||
test(() => {
|
||||
|
||||
assert_equals(document.querySelector("#form2").action, document.URL);
|
||||
|
||||
}, "An empty-string action content attribute should cause the IDL attribute to return the document's URL (= the document's base URL in this case)");
|
||||
|
||||
test(() => {
|
||||
|
||||
assert_equals(document.querySelector("#form3").action, document.URL);
|
||||
|
||||
}, "A missing action content attribute should cause the IDL attribute to return the document's URL (= the document's base URL in this case)");
|
||||
|
||||
</script>
|
|
@ -0,0 +1,56 @@
|
|||
<!DOCTYPE html>
|
||||
<meta charset="utf-8">
|
||||
<title>form action="" attribute effect on submission</title>
|
||||
<link rel="author" title="Domenic Denicola" href="mailto:d@domenic.me">
|
||||
<link rel="help" href="https://html.spec.whatwg.org/multipage/forms.html#dom-fs-action">
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
|
||||
<body>
|
||||
<script>
|
||||
"use strict";
|
||||
|
||||
// promise_test instead of async_test because all tests use window.success, and so can't run at the same time.
|
||||
|
||||
promise_test(t => {
|
||||
return new Promise(resolve => {
|
||||
window.success = t.step_func(locationLoaded => {
|
||||
const expected = (new URL("resources/target/form-action-url-target.html?name=value", location.href)).href;
|
||||
assert_equals(locationLoaded, expected);
|
||||
resolve();
|
||||
});
|
||||
|
||||
const iframe = document.createElement("iframe");
|
||||
iframe.src = "resources/form-with-action-and-base.sub.html?action=form-action-url-target.html";
|
||||
document.body.appendChild(iframe);
|
||||
});
|
||||
}, "An action URL should be resolved relative to the document's base URL (not document URL)");
|
||||
|
||||
promise_test(t => {
|
||||
return new Promise(resolve => {
|
||||
window.success = t.step_func(locationLoaded => {
|
||||
const expected = (new URL("resources/form-with-action-and-base.sub.html?name=value", location.href)).href;
|
||||
assert_equals(locationLoaded, expected);
|
||||
resolve();
|
||||
});
|
||||
|
||||
const iframe = document.createElement("iframe");
|
||||
iframe.src = "resources/form-with-action-and-base.sub.html?action=";
|
||||
document.body.appendChild(iframe);
|
||||
});
|
||||
}, "An empty-string action should submit the form to its containing document's URL (not its base URL)");
|
||||
|
||||
promise_test(t => {
|
||||
return new Promise(resolve => {
|
||||
window.success = t.step_func(locationLoaded => {
|
||||
const expected = (new URL("resources/form-no-action-with-base.html?name=value", location.href)).href;
|
||||
assert_equals(locationLoaded, expected);
|
||||
resolve();
|
||||
});
|
||||
|
||||
const iframe = document.createElement("iframe");
|
||||
iframe.src = "resources/form-no-action-with-base.html";
|
||||
document.body.appendChild(iframe);
|
||||
});
|
||||
}, "A missing action should submit the form to its containing document's URL (not its base URL)");
|
||||
</script>
|
|
@ -0,0 +1,56 @@
|
|||
<!DOCTYPE html>
|
||||
<meta charset="utf-8">
|
||||
<title>form action="" attribute effect on submission</title>
|
||||
<link rel="author" title="Domenic Denicola" href="mailto:d@domenic.me">
|
||||
<link rel="help" href="https://html.spec.whatwg.org/multipage/forms.html#dom-fs-action">
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
|
||||
<body>
|
||||
<script>
|
||||
"use strict";
|
||||
|
||||
// promise_test instead of async_test because all tests use window.success, and so can't run at the same time.
|
||||
|
||||
promise_test(t => {
|
||||
return new Promise(resolve => {
|
||||
window.success = t.step_func(locationLoaded => {
|
||||
const expected = (new URL("resources/target/form-action-url-target.html?name=value", location.href)).href;
|
||||
assert_equals(locationLoaded, expected);
|
||||
resolve();
|
||||
});
|
||||
|
||||
const iframe = document.createElement("iframe");
|
||||
iframe.src = "resources/form-with-action.sub.html?action=target/form-action-url-target.html";
|
||||
document.body.appendChild(iframe);
|
||||
});
|
||||
}, "An action URL should be resolved relative to the document's base URL (= document's URL in this case)");
|
||||
|
||||
promise_test(t => {
|
||||
return new Promise(resolve => {
|
||||
window.success = t.step_func(locationLoaded => {
|
||||
const expected = (new URL("resources/form-with-action.sub.html?name=value", location.href)).href;
|
||||
assert_equals(locationLoaded, expected);
|
||||
resolve();
|
||||
});
|
||||
|
||||
const iframe = document.createElement("iframe");
|
||||
iframe.src = "resources/form-with-action.sub.html?action=";
|
||||
document.body.appendChild(iframe);
|
||||
});
|
||||
}, "An empty-string action should submit the form to the document's URL (= document's base URL in this case)");
|
||||
|
||||
promise_test(t => {
|
||||
return new Promise(resolve => {
|
||||
window.success = t.step_func(locationLoaded => {
|
||||
const expected = (new URL("resources/form-no-action.html?name=value", location.href)).href;
|
||||
assert_equals(locationLoaded, expected);
|
||||
resolve();
|
||||
});
|
||||
|
||||
const iframe = document.createElement("iframe");
|
||||
iframe.src = "resources/form-no-action.html";
|
||||
document.body.appendChild(iframe);
|
||||
});
|
||||
}, "A missing action should submit the form to the document's URL (= document's base URL in this case)");
|
||||
</script>
|
|
@ -1,9 +0,0 @@
|
|||
<!doctype html>
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<script>
|
||||
var t = async_test("Submit a form from an iframe with a base url");
|
||||
var success = function() { t.done(); };
|
||||
</script>
|
||||
|
||||
<iframe src="resources/form-action-url-iframe.html">
|
|
@ -47,12 +47,14 @@
|
|||
autocompletetest(document.forms.autocomplete_off, ["off", "off", "on", "off", ""], "form autocomplete attribute off");
|
||||
autocompletetest(document.forms.autocomplete_invalid, ["on", "on", "on", "off", ""], "form autocomplete attribute invalid");
|
||||
|
||||
var keywords = [ "name", "honorific-prefix", "given-name", "additional-name", "family-name", "honorific-suffix", "nickname", "username", "new-password", "current-password", "organization-title", "organization", "street-address", "address-line1", "address-line2", "address-line3", "address-level4", "address-level3", "address-level2", "address-level1", "country", "country-name", "postal-code", "cc-name", "cc-given-name", "cc-additional-name", "cc-family-name", "cc-number", "cc-exp", "cc-exp-month", "cc-exp-year", "cc-csc", "cc-type", "transaction-currency", "transaction-amount", "language", "bday", "bday-day", "bday-month", "bday-year", "sex", "url", "photo", "tel", "tel-country-code", "tel-national", "tel-area-code", "tel-local", "tel-local-prefix", "tel-local-suffix", "tel-extension", "email", "impp" ];
|
||||
var keywords = [ "on", "off", "name", "honorific-prefix", "given-name", "additional-name", "family-name", "honorific-suffix", "nickname", "username", "new-password", "current-password", "organization-title", "organization", "street-address", "address-line1", "address-line2", "address-line3", "address-level4", "address-level3", "address-level2", "address-level1", "country", "country-name", "postal-code", "cc-name", "cc-given-name", "cc-additional-name", "cc-family-name", "cc-number", "cc-exp", "cc-exp-month", "cc-exp-year", "cc-csc", "cc-type", "transaction-currency", "transaction-amount", "language", "bday", "bday-day", "bday-month", "bday-year", "sex", "url", "photo", "tel", "tel-country-code", "tel-national", "tel-area-code", "tel-local", "tel-local-prefix", "tel-local-suffix", "tel-extension", "email", "impp" ];
|
||||
|
||||
keywords.forEach(function(keyword) {
|
||||
test(function(){
|
||||
var input = document.createElement("input");
|
||||
input.setAttribute("autocomplete", keyword);
|
||||
// Include whitespace to test splitting tokens on whitespace.
|
||||
// Convert to uppercase to ensure that the tokens are normalized to lowercase.
|
||||
input.setAttribute("autocomplete", " " + keyword.toUpperCase() + "\t");
|
||||
assert_equals(input.autocomplete, keyword);
|
||||
}, keyword + " is an allowed autocomplete field name");
|
||||
});
|
||||
|
|
|
@ -0,0 +1,172 @@
|
|||
<!DOCTYPE html>
|
||||
<meta charset="utf-8">
|
||||
<title>form.elements must contain all listed elements with the form owner</title>
|
||||
<link rel="help" href="https://html.spec.whatwg.org/multipage/#dom-form-elements">
|
||||
<link rel="author" title="Domenic Denicola" href="mailto:d@domenic.me">
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<div id="log"></div>
|
||||
|
||||
<!--
|
||||
Elements with data-in are expected to be in the form.elements collection.
|
||||
The choice of other elements besides "listed elements" (i.e. img, label, meter, progress) was
|
||||
because those are ones that appear in form-associated or labelable element categories.
|
||||
-->
|
||||
|
||||
<button data-in form="form" id="before-button1"></button>
|
||||
<fieldset data-in form="form" id="before-fieldset1"></fieldset>
|
||||
<object data-in form="form" id="before-object1"></object>
|
||||
<output data-in form="form" id="before-output1"></output>
|
||||
<select data-in form="form" id="before-select1">
|
||||
<option form="form" id="before-option1">x</option>
|
||||
</select>
|
||||
<textarea data-in form="form" id="before-textarea1"></textarea>
|
||||
|
||||
<input data-in form="form" id="before-input1">
|
||||
<input data-in type="hidden" form="form" id="before-input2">
|
||||
<input data-in type="search" form="form" id="before-input3">
|
||||
<input data-in type="tel" form="form" id="before-input4">
|
||||
<input data-in type="url" form="form" id="before-input5">
|
||||
<input data-in type="email" form="form" id="before-input6">
|
||||
<input data-in type="password" form="form" id="before-input7">
|
||||
<input data-in type="date" form="form" id="before-input8">
|
||||
<input data-in type="month" form="form" id="before-input9">
|
||||
<input data-in type="week" form="form" id="before-input10">
|
||||
<input data-in type="time" form="form" id="before-input11">
|
||||
<input data-in type="datetime-local" form="form" id="before-input12">
|
||||
<input data-in type="number" form="form" id="before-input13">
|
||||
<input data-in type="range" form="form" id="before-input14">
|
||||
<input data-in type="color" form="form" id="before-input15">
|
||||
<input data-in type="checkbox" form="form" id="before-input16">
|
||||
<input data-in type="radio" form="form" id="before-input17">
|
||||
<input data-in type="file" form="form" id="before-input18">
|
||||
<input data-in type="submit" form="form" id="before-input19">
|
||||
<input data-in type="reset" form="form" id="before-input20">
|
||||
<input data-in type="button" form="form" id="before-input21">
|
||||
|
||||
<img form="form" id="before-img1">
|
||||
<label form="form" id="before-label1"></label>
|
||||
<meter form="form" id="before-meter1"></meter>
|
||||
<progress form="form" id="before-progress1"></progress>
|
||||
|
||||
<form id="form">
|
||||
<button data-in id="button1"></button>
|
||||
<fieldset data-in id="fieldset1"></fieldset>
|
||||
<object data-in id="object1"></object>
|
||||
<output data-in id="output1"></output>
|
||||
<select data-in id="select1">
|
||||
<option id="option1">x</option>
|
||||
</select>
|
||||
<textarea data-in id="textarea1"></textarea>
|
||||
|
||||
<input data-in id="input1">
|
||||
<input data-in type="hidden" id="input2">
|
||||
<input data-in type="search" id="input3">
|
||||
<input data-in type="tel" id="input4">
|
||||
<input data-in type="url" id="input5">
|
||||
<input data-in type="email" id="input6">
|
||||
<input data-in type="password" id="input7">
|
||||
<input data-in type="date" id="input8">
|
||||
<input data-in type="month" id="input9">
|
||||
<input data-in type="week" id="input10">
|
||||
<input data-in type="time" id="input11">
|
||||
<input data-in type="datetime-local" id="input12">
|
||||
<input data-in type="number" id="input13">
|
||||
<input data-in type="range" id="input14">
|
||||
<input data-in type="color" id="input15">
|
||||
<input data-in type="checkbox" id="input16">
|
||||
<input data-in type="radio" id="input17">
|
||||
<input data-in type="file" id="input18">
|
||||
<input data-in type="submit" id="input19">
|
||||
<input data-in type="reset" id="input20">
|
||||
<input data-in type="button" id="input21">
|
||||
|
||||
<img id="img1">
|
||||
<label id="label1"></label>
|
||||
<meter id="meter1"></meter>
|
||||
<progress id="progress1"></progress>
|
||||
</form>
|
||||
|
||||
<button data-in form="form" id="after-button1"></button>
|
||||
<fieldset data-in form="form" id="after-fieldset1"></fieldset>
|
||||
<object data-in form="form" id="after-object1"></object>
|
||||
<output data-in form="form" id="after-output1"></output>
|
||||
<select data-in form="form" id="after-select1">
|
||||
<option form="form" id="after-option1">x</option>
|
||||
</select>
|
||||
<textarea data-in form="form" id="after-textarea1"></textarea>
|
||||
|
||||
<input data-in form="form" id="after-input1">
|
||||
<input data-in type="hidden" form="form" id="after-input2">
|
||||
<input data-in type="search" form="form" id="after-input3">
|
||||
<input data-in type="tel" form="form" id="after-input4">
|
||||
<input data-in type="url" form="form" id="after-input5">
|
||||
<input data-in type="email" form="form" id="after-input6">
|
||||
<input data-in type="password" form="form" id="after-input7">
|
||||
<input data-in type="date" form="form" id="after-input8">
|
||||
<input data-in type="month" form="form" id="after-input9">
|
||||
<input data-in type="week" form="form" id="after-input10">
|
||||
<input data-in type="time" form="form" id="after-input11">
|
||||
<input data-in type="datetime-local" form="form" id="after-input12">
|
||||
<input data-in type="number" form="form" id="after-input13">
|
||||
<input data-in type="range" form="form" id="after-input14">
|
||||
<input data-in type="color" form="form" id="after-input15">
|
||||
<input data-in type="checkbox" form="form" id="after-input16">
|
||||
<input data-in type="radio" form="form" id="after-input17">
|
||||
<input data-in type="file" form="form" id="after-input18">
|
||||
<input data-in type="submit" form="form" id="after-input19">
|
||||
<input data-in type="reset" form="form" id="after-input20">
|
||||
<input data-in type="button" form="form" id="after-input21">
|
||||
|
||||
<img form="form" id="after-img1">
|
||||
<label form="form" id="after-label1"></label>
|
||||
<meter form="form" id="after-meter1"></meter>
|
||||
<progress form="form" id="after-progress1"></progress>
|
||||
|
||||
<button id="after-unassociated-button1"></button>
|
||||
<fieldset id="after-unassociated-fieldset1"></fieldset>
|
||||
<object id="after-unassociated-object1"></object>
|
||||
<output id="after-unassociated-output1"></output>
|
||||
<select id="after-unassociated-select1">
|
||||
<option id="after-unassociated-option1">x</option>
|
||||
</select>
|
||||
<textarea id="after-unassociated-textarea1"></textarea>
|
||||
|
||||
<input id="after-unassociated-input1">
|
||||
<input type="hidden" id="after-unassociated-input2">
|
||||
<input type="search" id="after-unassociated-input3">
|
||||
<input type="tel" id="after-unassociated-input4">
|
||||
<input type="url" id="after-unassociated-input5">
|
||||
<input type="email" id="after-unassociated-input6">
|
||||
<input type="password" id="after-unassociated-input7">
|
||||
<input type="date" id="after-unassociated-input8">
|
||||
<input type="month" id="after-unassociated-input9">
|
||||
<input type="week" id="after-unassociated-input10">
|
||||
<input type="time" id="after-unassociated-input11">
|
||||
<input type="datetime-local" id="after-unassociated-input12">
|
||||
<input type="number" id="after-unassociated-input13">
|
||||
<input type="range" id="after-unassociated-input14">
|
||||
<input type="color" id="after-unassociated-input15">
|
||||
<input type="checkbox" id="after-unassociated-input16">
|
||||
<input type="radio" id="after-unassociated-input17">
|
||||
<input type="file" id="after-unassociated-input18">
|
||||
<input type="submit" id="after-unassociated-input19">
|
||||
<input type="reset" id="after-unassociated-input20">
|
||||
<input type="button" id="after-unassociated-input21">
|
||||
|
||||
<img id="after-unassociated-img1">
|
||||
<label id="after-unassociated-label1"></label>
|
||||
<meter id="after-unassociated-meter1"></meter>
|
||||
<progress id="after-unassociated-progress1"></progress>
|
||||
|
||||
<script>
|
||||
"use strict";
|
||||
test(() => {
|
||||
const elements = document.querySelector("#form").elements;
|
||||
const ids = Array.from(elements).map(el => el.id);
|
||||
|
||||
const allCorrectIDs = Array.from(document.querySelectorAll("[data-in]")).map(el => el.id);
|
||||
|
||||
assert_array_equals(ids, allCorrectIDs);
|
||||
});
|
||||
</script>
|
|
@ -1,11 +0,0 @@
|
|||
<!doctype html>
|
||||
<base href="target/"></base>
|
||||
|
||||
<form action="form-action-url-target.html">
|
||||
<input type="submit" value="Submit" />
|
||||
</form>
|
||||
|
||||
<script>
|
||||
var form = document.getElementsByTagName("form")[0];
|
||||
form.submit();
|
||||
</script>
|
|
@ -0,0 +1,19 @@
|
|||
<!doctype html>
|
||||
<base href="target/"></base>
|
||||
|
||||
<form>
|
||||
<input type="text" name="name" value="value">
|
||||
<input type="submit" value="Submit">
|
||||
</form>
|
||||
|
||||
<script>
|
||||
"use strict";
|
||||
|
||||
if (window.location.search.startsWith("?name=value")) {
|
||||
// The action pointed to ourself, so the form submitted something
|
||||
window.parent.success(window.location.href);
|
||||
} else {
|
||||
const form = document.querySelector("form");
|
||||
form.submit();
|
||||
}
|
||||
</script>
|
|
@ -0,0 +1,18 @@
|
|||
<!doctype html>
|
||||
|
||||
<form>
|
||||
<input type="text" name="name" value="value">
|
||||
<input type="submit" value="Submit">
|
||||
</form>
|
||||
|
||||
<script>
|
||||
"use strict";
|
||||
|
||||
if (window.location.search.startsWith("?name=value")) {
|
||||
// The action pointed to ourself, so the form submitted something
|
||||
window.parent.success(window.location.href);
|
||||
} else {
|
||||
const form = document.querySelector("form");
|
||||
form.submit();
|
||||
}
|
||||
</script>
|
|
@ -0,0 +1,19 @@
|
|||
<!doctype html>
|
||||
<base href="target/"></base>
|
||||
|
||||
<form action="{{GET[action]}}">
|
||||
<input type="text" name="name" value="value">
|
||||
<input type="submit" value="Submit">
|
||||
</form>
|
||||
|
||||
<script>
|
||||
"use strict";
|
||||
|
||||
if (window.location.search.startsWith("?name=value")) {
|
||||
// The action pointed to ourself, so the form submitted something
|
||||
window.parent.success(window.location.href);
|
||||
} else {
|
||||
const form = document.querySelector("form");
|
||||
form.submit();
|
||||
}
|
||||
</script>
|
|
@ -0,0 +1,18 @@
|
|||
<!doctype html>
|
||||
|
||||
<form action="{{GET[action]}}">
|
||||
<input type="text" name="name" value="value">
|
||||
<input type="submit" value="Submit">
|
||||
</form>
|
||||
|
||||
<script>
|
||||
"use strict";
|
||||
|
||||
if (window.location.search.startsWith("?name=value")) {
|
||||
// The action pointed to ourself, so the form submitted something
|
||||
window.parent.success(window.location.href);
|
||||
} else {
|
||||
const form = document.querySelector("form");
|
||||
form.submit();
|
||||
}
|
||||
</script>
|
|
@ -1,4 +1,5 @@
|
|||
<!doctype html>
|
||||
<script>
|
||||
window.parent.success();
|
||||
"use strict";
|
||||
window.parent.success(window.location.href);
|
||||
</script>
|
||||
|
|
|
@ -0,0 +1,109 @@
|
|||
<!DOCTYPE html>
|
||||
<meta charset="utf-8">
|
||||
<title>Checkbox click events</title>
|
||||
<link rel="author" title="jeffcarp" href="mailto:gcarpenterv@gmail.com">
|
||||
<link rel=help href="https://html.spec.whatwg.org/#checkbox-state-(type=checkbox)">
|
||||
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
|
||||
<body>
|
||||
<script>
|
||||
"use strict";
|
||||
|
||||
test(() => {
|
||||
|
||||
const input = document.createElement("input");
|
||||
input.type = "checkbox";
|
||||
|
||||
const values = [];
|
||||
|
||||
input.addEventListener("click", e => {
|
||||
values.push(input.checked);
|
||||
e.preventDefault();
|
||||
values.push(input.checked);
|
||||
});
|
||||
|
||||
input.click();
|
||||
|
||||
values.push(input.checked);
|
||||
assert_array_equals(values, [true, true, false]);
|
||||
|
||||
}, "clicking and preventDefaulting a checkbox causes the checkbox to be checked during the click handler but reverted");
|
||||
|
||||
test(() => {
|
||||
const input = document.createElement("input");
|
||||
input.type = "checkbox";
|
||||
document.body.appendChild(input);
|
||||
const events = [];
|
||||
|
||||
input.addEventListener("change", () => {
|
||||
events.push("change");
|
||||
});
|
||||
input.addEventListener("click", () => {
|
||||
events.push("click");
|
||||
});
|
||||
input.addEventListener("input", () => {
|
||||
events.push("input");
|
||||
});
|
||||
|
||||
assert_false(input.checked);
|
||||
|
||||
input.click();
|
||||
|
||||
assert_true(input.checked);
|
||||
assert_array_equals(events, ["click", "input", "change"]);
|
||||
|
||||
}, "a checkbox input emits click, input, change events in order after synthetic click");
|
||||
|
||||
test(() => {
|
||||
const input = document.createElement("input");
|
||||
input.type = "checkbox";
|
||||
document.body.appendChild(input);
|
||||
const events = [];
|
||||
|
||||
input.addEventListener("change", () => {
|
||||
events.push("change");
|
||||
});
|
||||
input.addEventListener("click", () => {
|
||||
events.push("click");
|
||||
});
|
||||
input.addEventListener("input", () => {
|
||||
events.push("input");
|
||||
});
|
||||
|
||||
assert_false(input.checked);
|
||||
|
||||
const event = new MouseEvent("click", { bubbles: true, cancelable: true });
|
||||
input.dispatchEvent(event);
|
||||
|
||||
assert_true(input.checked);
|
||||
assert_array_equals(events, ["click", "input", "change"]);
|
||||
|
||||
}, "a checkbox input emits click, input, change events in order after dispatching click event");
|
||||
|
||||
test(() => {
|
||||
const input = document.createElement("input");
|
||||
input.type = "checkbox";
|
||||
document.body.appendChild(input);
|
||||
const events = [];
|
||||
|
||||
input.addEventListener("change", () => {
|
||||
events.push("change");
|
||||
});
|
||||
input.addEventListener("click", e => {
|
||||
e.preventDefault();
|
||||
events.push("click");
|
||||
});
|
||||
input.addEventListener("input", () => {
|
||||
events.push("input");
|
||||
});
|
||||
|
||||
assert_false(input.checked);
|
||||
|
||||
input.click();
|
||||
|
||||
assert_false(input.checked);
|
||||
assert_array_equals(events, ["click"]);
|
||||
}, "checkbox input respects cancel behavior on synthetic clicks");
|
||||
</script>
|
|
@ -0,0 +1,41 @@
|
|||
<!DOCTYPE HTML>
|
||||
<title>Radio input cancel behavior reverts state</title>
|
||||
<link rel="author" title="jeffcarp" href="mailto:gcarpenterv@gmail.com">
|
||||
<link rel="help" href="https://html.spec.whatwg.org/#radio-button-state-(type=radio)">
|
||||
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
|
||||
<body>
|
||||
<script>
|
||||
"use strict";
|
||||
|
||||
test(() => {
|
||||
const input = document.createElement("input");
|
||||
input.type = "radio";
|
||||
document.body.appendChild(input);
|
||||
const events = [];
|
||||
|
||||
input.addEventListener("change", () => {
|
||||
events.push("change");
|
||||
});
|
||||
input.addEventListener("click", e => {
|
||||
// cancel click event
|
||||
e.preventDefault();
|
||||
events.push("click");
|
||||
});
|
||||
input.addEventListener("input", () => {
|
||||
events.push("input");
|
||||
});
|
||||
|
||||
assert_false(input.checked);
|
||||
|
||||
input.click();
|
||||
|
||||
assert_false(input.checked);
|
||||
|
||||
// only click event called
|
||||
assert_array_equals(events, ["click"]);
|
||||
|
||||
}, "radio input cancel behavior reverts state");
|
||||
</script>
|
|
@ -23,6 +23,11 @@
|
|||
<input type=radio name=group4 id=radio10>
|
||||
<input type=radio name=group4 id=radio11 checked>
|
||||
|
||||
<form id="testform"></form>
|
||||
<input type=radio form=testform name=group6 id=radio12 checked>
|
||||
<input type=radio form=testform name=group6 id=radio13>
|
||||
<input type=radio form=testform name=group6 id=radio14>
|
||||
|
||||
<script>
|
||||
var radio1 = document.getElementById('radio1'),
|
||||
radio2 = document.getElementById('radio2'),
|
||||
|
@ -36,6 +41,10 @@
|
|||
radio9 = document.getElementById('radio9'),
|
||||
radio10 = document.getElementById('radio10'),
|
||||
radio11 = document.getElementById('radio11'),
|
||||
radio12 = document.getElementById('radio12'),
|
||||
radio13 = document.getElementById('radio13'),
|
||||
radio14 = document.getElementById('radio14'),
|
||||
testform = document.getElementById('testform'),
|
||||
t1 = async_test("click on mutable radio fires click event, then input event, then change event"),
|
||||
t3 = async_test("click on non-mutable radio doesn't fire the input event"),
|
||||
t4 = async_test("click on non-mutable radio doesn't fire the change event"),
|
||||
|
@ -78,6 +87,31 @@
|
|||
assert_false(radio11.checked);
|
||||
}, "changing the name of a radio input element and setting its checkedness to true makes all the other elements' checkedness in the same radio button group be set to false");
|
||||
|
||||
test(function(){
|
||||
radio12.remove();
|
||||
assert_true(radio12.checked);
|
||||
assert_false(radio13.checked);
|
||||
assert_false(radio14.checked);
|
||||
radio13.checked = true;
|
||||
assert_true(radio13.checked);
|
||||
assert_false(radio14.checked);
|
||||
radio13.removeAttribute("form");
|
||||
radio14.removeAttribute("form");
|
||||
assert_true(radio13.checked);
|
||||
assert_false(radio14.checked);
|
||||
radio14.checked = true;
|
||||
assert_false(radio13.checked);
|
||||
assert_true(radio14.checked);
|
||||
radio13.setAttribute("form", "testform");
|
||||
radio14.setAttribute("form", "testform");
|
||||
radio13.checked = true;
|
||||
assert_true(radio13.checked);
|
||||
assert_false(radio14.checked);
|
||||
testform.remove();
|
||||
assert_true(radio13.checked);
|
||||
assert_false(radio14.checked);
|
||||
}, "moving radio input element out of or into a form should still work as expected");
|
||||
|
||||
radio5.onclick = t1.step_func(function(e) {
|
||||
click_fired = true;
|
||||
assert_false(input_fired, "click event should fire before input event");
|
||||
|
|
|
@ -10,296 +10,296 @@
|
|||
test(function () {
|
||||
var input = document.createElement("input");
|
||||
input.type = "hidden";
|
||||
input.value = "foo";
|
||||
assert_equals(input.value, "foo");
|
||||
input.value = "foo\r\r\n\n\0";
|
||||
assert_equals(input.value, "foo\r\r\n\n\0");
|
||||
}, "value IDL attribute of input type hidden without value attribute");
|
||||
test(function() {
|
||||
var input = document.createElement("input");
|
||||
input.type = "hidden";
|
||||
input.setAttribute("value", "bar");
|
||||
input.value = "foo";
|
||||
assert_equals(input.value, "foo");
|
||||
input.value = "foo\r\r\n\n\0";
|
||||
assert_equals(input.value, "foo\r\r\n\n\0");
|
||||
}, "value IDL attribute of input type hidden with value attribute");
|
||||
|
||||
test(function () {
|
||||
var input = document.createElement("input");
|
||||
input.type = "submit";
|
||||
input.value = "foo";
|
||||
assert_equals(input.value, "foo");
|
||||
input.value = "foo\r\r\n\n\0";
|
||||
assert_equals(input.value, "foo\r\r\n\n\0");
|
||||
}, "value IDL attribute of input type submit without value attribute");
|
||||
test(function() {
|
||||
var input = document.createElement("input");
|
||||
input.type = "submit";
|
||||
input.setAttribute("value", "bar");
|
||||
input.value = "foo";
|
||||
assert_equals(input.value, "foo");
|
||||
input.value = "foo\r\r\n\n\0";
|
||||
assert_equals(input.value, "foo\r\r\n\n\0");
|
||||
}, "value IDL attribute of input type submit with value attribute");
|
||||
|
||||
test(function () {
|
||||
var input = document.createElement("input");
|
||||
input.type = "image";
|
||||
input.value = "foo";
|
||||
assert_equals(input.value, "foo");
|
||||
input.value = "foo\r\r\n\n\0";
|
||||
assert_equals(input.value, "foo\r\r\n\n\0");
|
||||
}, "value IDL attribute of input type image without value attribute");
|
||||
test(function() {
|
||||
var input = document.createElement("input");
|
||||
input.type = "image";
|
||||
input.setAttribute("value", "bar");
|
||||
input.value = "foo";
|
||||
assert_equals(input.value, "foo");
|
||||
input.value = "foo\r\r\n\n\0";
|
||||
assert_equals(input.value, "foo\r\r\n\n\0");
|
||||
}, "value IDL attribute of input type image with value attribute");
|
||||
|
||||
test(function () {
|
||||
var input = document.createElement("input");
|
||||
input.type = "reset";
|
||||
input.value = "foo";
|
||||
assert_equals(input.value, "foo");
|
||||
input.value = "foo\r\r\n\n\0";
|
||||
assert_equals(input.value, "foo\r\r\n\n\0");
|
||||
}, "value IDL attribute of input type reset without value attribute");
|
||||
test(function() {
|
||||
var input = document.createElement("input");
|
||||
input.type = "reset";
|
||||
input.setAttribute("value", "bar");
|
||||
input.value = "foo";
|
||||
assert_equals(input.value, "foo");
|
||||
input.value = "foo\r\r\n\n\0";
|
||||
assert_equals(input.value, "foo\r\r\n\n\0");
|
||||
}, "value IDL attribute of input type reset with value attribute");
|
||||
|
||||
test(function () {
|
||||
var input = document.createElement("input");
|
||||
input.type = "button";
|
||||
input.value = "foo";
|
||||
assert_equals(input.value, "foo");
|
||||
input.value = "foo\r\r\n\n\0";
|
||||
assert_equals(input.value, "foo\r\r\n\n\0");
|
||||
}, "value IDL attribute of input type button without value attribute");
|
||||
test(function() {
|
||||
var input = document.createElement("input");
|
||||
input.type = "button";
|
||||
input.setAttribute("value", "bar");
|
||||
input.value = "foo";
|
||||
assert_equals(input.value, "foo");
|
||||
input.value = "foo\r\r\n\n\0";
|
||||
assert_equals(input.value, "foo\r\r\n\n\0");
|
||||
}, "value IDL attribute of input type button with value attribute");
|
||||
|
||||
// MODE DEFAULT/ON
|
||||
test(function () {
|
||||
var input = document.createElement("input");
|
||||
input.type = "checkbox";
|
||||
input.value = "foo";
|
||||
assert_equals(input.value, "foo");
|
||||
input.value = "foo\r\r\n\n\0";
|
||||
assert_equals(input.value, "foo\r\r\n\n\0");
|
||||
}, "value IDL attribute of input type checkbox without value attribute");
|
||||
test(function() {
|
||||
var input = document.createElement("input");
|
||||
input.type = "checkbox";
|
||||
input.setAttribute("value", "bar");
|
||||
input.value = "foo";
|
||||
assert_equals(input.value, "foo");
|
||||
input.value = "foo\r\r\n\n\0";
|
||||
assert_equals(input.value, "foo\r\r\n\n\0");
|
||||
}, "value IDL attribute of input type checkbox with value attribute");
|
||||
|
||||
test(function () {
|
||||
var input = document.createElement("input");
|
||||
input.type = "radio";
|
||||
input.value = "foo";
|
||||
assert_equals(input.value, "foo");
|
||||
input.value = "foo\r\r\n\n\0";
|
||||
assert_equals(input.value, "foo\r\r\n\n\0");
|
||||
}, "value IDL attribute of input type radio without value attribute");
|
||||
test(function() {
|
||||
var input = document.createElement("input");
|
||||
input.type = "radio";
|
||||
input.setAttribute("value", "bar");
|
||||
input.value = "foo";
|
||||
assert_equals(input.value, "foo");
|
||||
input.value = "foo\r\r\n\n\0";
|
||||
assert_equals(input.value, "foo\r\r\n\n\0");
|
||||
}, "value IDL attribute of input type radio with value attribute");
|
||||
|
||||
// MODE VALUE
|
||||
test(function () {
|
||||
var input = document.createElement("input");
|
||||
input.type = "text";
|
||||
input.value = "foo";
|
||||
assert_equals(input.value, "foo");
|
||||
input.value = "foo\r\r\n\n\0";
|
||||
assert_equals(input.value, "foo\0");
|
||||
}, "value IDL attribute of input type text without value attribute");
|
||||
test(function() {
|
||||
var input = document.createElement("input");
|
||||
input.type = "text";
|
||||
input.setAttribute("value", "bar");
|
||||
input.value = "foo";
|
||||
assert_equals(input.value, "foo");
|
||||
input.value = "foo\r\r\n\n\0";
|
||||
assert_equals(input.value, "foo\0");
|
||||
}, "value IDL attribute of input type text with value attribute");
|
||||
|
||||
test(function () {
|
||||
var input = document.createElement("input");
|
||||
input.type = "search";
|
||||
input.value = "foo";
|
||||
assert_equals(input.value, "foo");
|
||||
input.value = "foo\r\r\n\n\0";
|
||||
assert_equals(input.value, "foo\0");
|
||||
}, "value IDL attribute of input type search without value attribute");
|
||||
test(function() {
|
||||
var input = document.createElement("input");
|
||||
input.type = "search";
|
||||
input.setAttribute("value", "bar");
|
||||
input.value = "foo";
|
||||
assert_equals(input.value, "foo");
|
||||
input.value = "foo\r\r\n\n\0";
|
||||
assert_equals(input.value, "foo\0");
|
||||
}, "value IDL attribute of input type search with value attribute");
|
||||
|
||||
test(function () {
|
||||
var input = document.createElement("input");
|
||||
input.type = "tel";
|
||||
input.value = "foo";
|
||||
assert_equals(input.value, "foo");
|
||||
input.value = "foo\r\r\n\n\0";
|
||||
assert_equals(input.value, "foo\0");
|
||||
}, "value IDL attribute of input type tel without value attribute");
|
||||
test(function() {
|
||||
var input = document.createElement("input");
|
||||
input.type = "tel";
|
||||
input.setAttribute("value", "bar");
|
||||
input.value = "foo";
|
||||
assert_equals(input.value, "foo");
|
||||
input.value = "foo\r\r\n\n\0";
|
||||
assert_equals(input.value, "foo\0");
|
||||
}, "value IDL attribute of input type tel with value attribute");
|
||||
|
||||
test(function () {
|
||||
var input = document.createElement("input");
|
||||
input.type = "url";
|
||||
input.value = "foo";
|
||||
assert_equals(input.value, "foo");
|
||||
input.value = "foo\r\r\n\n\0";
|
||||
assert_equals(input.value, "foo\0");
|
||||
}, "value IDL attribute of input type url without value attribute");
|
||||
test(function() {
|
||||
var input = document.createElement("input");
|
||||
input.type = "url";
|
||||
input.setAttribute("value", "bar");
|
||||
input.value = "foo";
|
||||
assert_equals(input.value, "foo");
|
||||
input.value = "foo\r\r\n\n\0";
|
||||
assert_equals(input.value, "foo\0");
|
||||
}, "value IDL attribute of input type url with value attribute");
|
||||
|
||||
test(function () {
|
||||
var input = document.createElement("input");
|
||||
input.type = "email";
|
||||
input.value = "foo";
|
||||
assert_equals(input.value, "foo");
|
||||
input.value = "foo\r\r\n\n\0";
|
||||
assert_equals(input.value, "foo\0");
|
||||
}, "value IDL attribute of input type email without value attribute");
|
||||
test(function() {
|
||||
var input = document.createElement("input");
|
||||
input.type = "email";
|
||||
input.setAttribute("value", "bar");
|
||||
input.value = "foo";
|
||||
assert_equals(input.value, "foo");
|
||||
input.value = "foo\r\r\n\n\0";
|
||||
assert_equals(input.value, "foo\0");
|
||||
}, "value IDL attribute of input type email with value attribute");
|
||||
|
||||
test(function () {
|
||||
var input = document.createElement("input");
|
||||
input.type = "password";
|
||||
input.value = "foo";
|
||||
assert_equals(input.value, "foo");
|
||||
input.value = "foo\r\r\n\n\0";
|
||||
assert_equals(input.value, "foo\0");
|
||||
}, "value IDL attribute of input type password without value attribute");
|
||||
test(function() {
|
||||
var input = document.createElement("input");
|
||||
input.type = "password";
|
||||
input.setAttribute("value", "bar");
|
||||
input.value = "foo";
|
||||
assert_equals(input.value, "foo");
|
||||
input.value = "foo\r\r\n\n\0";
|
||||
assert_equals(input.value, "foo\0");
|
||||
}, "value IDL attribute of input type password with value attribute");
|
||||
|
||||
test(function () {
|
||||
var input = document.createElement("input");
|
||||
input.type = "datetime-local";
|
||||
input.value = "foo";
|
||||
input.value = "foo\r\r\n\n\0";
|
||||
assert_equals(input.value, "");
|
||||
}, "value IDL attribute of input type datetime-local without value attribute");
|
||||
test(function() {
|
||||
var input = document.createElement("input");
|
||||
input.type = "datetime-local";
|
||||
input.setAttribute("value", "bar");
|
||||
input.value = "foo";
|
||||
input.value = "foo\r\r\n\n\0";
|
||||
assert_equals(input.value, "");
|
||||
}, "value IDL attribute of input type datetime-local with value attribute");
|
||||
|
||||
test(function () {
|
||||
var input = document.createElement("input");
|
||||
input.type = "date";
|
||||
input.value = "foo";
|
||||
input.value = "foo\r\r\n\n\0";
|
||||
assert_equals(input.value, "");
|
||||
}, "value IDL attribute of input type date without value attribute");
|
||||
test(function() {
|
||||
var input = document.createElement("input");
|
||||
input.type = "date";
|
||||
input.setAttribute("value", "bar");
|
||||
input.value = "foo";
|
||||
input.value = "foo\r\r\n\n\0";
|
||||
assert_equals(input.value, "");
|
||||
}, "value IDL attribute of input type date with value attribute");
|
||||
|
||||
test(function () {
|
||||
var input = document.createElement("input");
|
||||
input.type = "month";
|
||||
input.value = "foo";
|
||||
input.value = "foo\r\r\n\n\0";
|
||||
assert_equals(input.value, "");
|
||||
}, "value IDL attribute of input type month without value attribute");
|
||||
test(function() {
|
||||
var input = document.createElement("input");
|
||||
input.type = "month";
|
||||
input.setAttribute("value", "bar");
|
||||
input.value = "foo";
|
||||
input.value = "foo\r\r\n\n\0";
|
||||
assert_equals(input.value, "");
|
||||
}, "value IDL attribute of input type month with value attribute");
|
||||
|
||||
test(function () {
|
||||
var input = document.createElement("input");
|
||||
input.type = "week";
|
||||
input.value = "foo";
|
||||
input.value = "foo\r\r\n\n\0";
|
||||
assert_equals(input.value, "");
|
||||
}, "value IDL attribute of input type week without value attribute");
|
||||
test(function() {
|
||||
var input = document.createElement("input");
|
||||
input.type = "week";
|
||||
input.setAttribute("value", "bar");
|
||||
input.value = "foo";
|
||||
input.value = "foo\r\r\n\n\0";
|
||||
assert_equals(input.value, "");
|
||||
}, "value IDL attribute of input type week with value attribute");
|
||||
|
||||
test(function () {
|
||||
var input = document.createElement("input");
|
||||
input.type = "time";
|
||||
input.value = "foo";
|
||||
input.value = "foo\r\r\n\n\0";
|
||||
assert_equals(input.value, "");
|
||||
}, "value IDL attribute of input type time without value attribute");
|
||||
test(function() {
|
||||
var input = document.createElement("input");
|
||||
input.type = "time";
|
||||
input.setAttribute("value", "bar");
|
||||
input.value = "foo";
|
||||
input.value = "foo\r\r\n\n\0";
|
||||
assert_equals(input.value, "");
|
||||
}, "value IDL attribute of input type time with value attribute");
|
||||
|
||||
test(function () {
|
||||
var input = document.createElement("input");
|
||||
input.type = "number";
|
||||
input.value = "foo";
|
||||
input.value = "foo\r\r\n\n\0";
|
||||
assert_equals(input.value, "");
|
||||
}, "value IDL attribute of input type number without value attribute");
|
||||
test(function() {
|
||||
var input = document.createElement("input");
|
||||
input.type = "number";
|
||||
input.setAttribute("value", "bar");
|
||||
input.value = "foo";
|
||||
input.value = "foo\r\r\n\n\0";
|
||||
assert_equals(input.value, "");
|
||||
}, "value IDL attribute of input type number with value attribute");
|
||||
|
||||
test(function () {
|
||||
var input = document.createElement("input");
|
||||
input.type = "range";
|
||||
input.value = "foo";
|
||||
input.value = "foo\r\r\n\n\0";
|
||||
assert_equals(input.value, "50");
|
||||
}, "value IDL attribute of input type range without value attribute");
|
||||
test(function() {
|
||||
var input = document.createElement("input");
|
||||
input.type = "range";
|
||||
input.setAttribute("value", "bar");
|
||||
input.value = "foo";
|
||||
input.value = "foo\r\r\n\n\0";
|
||||
assert_equals(input.value, "50");
|
||||
}, "value IDL attribute of input type range with value attribute");
|
||||
|
||||
test(function () {
|
||||
var input = document.createElement("input");
|
||||
input.type = "color";
|
||||
input.value = "foo";
|
||||
input.value = "foo\r\r\n\n\0";
|
||||
assert_equals(input.value, "#000000");
|
||||
}, "value IDL attribute of input type color without value attribute");
|
||||
test(function() {
|
||||
var input = document.createElement("input");
|
||||
input.type = "color";
|
||||
input.setAttribute("value", "bar");
|
||||
input.value = "foo";
|
||||
input.value = "foo\r\r\n\n\0";
|
||||
assert_equals(input.value, "#000000");
|
||||
}, "value IDL attribute of input type color with value attribute");
|
||||
</script>
|
||||
|
|
|
@ -0,0 +1,58 @@
|
|||
<!DOCTYPE HTML>
|
||||
<title>label element click proxying via "for" attribute or nested labelable element</title>
|
||||
<link rel="author" title="yaycmyk" href="mailto:evan@yaycmyk.com">
|
||||
<link rel="help" href="https://html.spec.whatwg.org/multipage/forms.html#the-label-element:the-label-element-10">
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<div id="log"></div>
|
||||
<form id="test">
|
||||
<input id="foo" type="checkbox" />
|
||||
<label id="foo-label" for="foo">foo</label>
|
||||
|
||||
<label id="bar-label">
|
||||
<input id="bar" type="checkbox" /> bar
|
||||
<input id="baz" type="checkbox" /> baz
|
||||
</label>
|
||||
|
||||
<input id="baz" type="checkbox" />
|
||||
<label id="baz-label" for="baz">baz</label>
|
||||
</form>
|
||||
<script>
|
||||
"use strict";
|
||||
|
||||
async_test(t => {
|
||||
const label = document.getElementById("foo-label");
|
||||
const input = document.getElementById("foo");
|
||||
|
||||
input.addEventListener("click", t.step_func_done());
|
||||
|
||||
label.click();
|
||||
|
||||
}, "label with for attribute should proxy click events to the associated element");
|
||||
|
||||
async_test(t => {
|
||||
const label = document.getElementById("bar-label");
|
||||
const input = document.getElementById("bar");
|
||||
|
||||
input.addEventListener("click", t.step_func_done());
|
||||
|
||||
label.click();
|
||||
|
||||
}, "label without for attribute should proxy click events to the first labelable child");
|
||||
|
||||
async_test(t => {
|
||||
|
||||
const label = document.getElementById("baz-label");
|
||||
const input = document.getElementById("baz");
|
||||
|
||||
input.addEventListener("click", t.unreached_func("Input should not receive click"));
|
||||
label.addEventListener("click", t.step_func(ev => {
|
||||
ev.preventDefault();
|
||||
t.step_timeout(() => t.done(), 500);
|
||||
}));
|
||||
|
||||
label.click();
|
||||
|
||||
}, "clicking a label that prevents the event's default should not proxy click events");
|
||||
|
||||
</script>
|
|
@ -0,0 +1,130 @@
|
|||
<!DOCTYPE html>
|
||||
<meta charset="utf-8">
|
||||
<title>Option element constructor</title>
|
||||
<link rel="author" title="Alex Pearson" href="mailto:alex@alexpear.com">
|
||||
<link rel="help" href="https://html.spec.whatwg.org/#the-option-element">
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
|
||||
<div id="parent">
|
||||
<div id="child" tabindex="0"></div>
|
||||
</div>
|
||||
|
||||
<body>
|
||||
<script>
|
||||
"use strict";
|
||||
|
||||
test(() => {
|
||||
const option = new Option();
|
||||
|
||||
assert_true(option instanceof HTMLOptionElement);
|
||||
|
||||
assert_false(option.hasChildNodes());
|
||||
assert_false(option.hasAttribute("value"));
|
||||
assert_false(option.hasAttribute("selected"));
|
||||
assert_false(option.selected);
|
||||
|
||||
assert_equals(option.textContent, "");
|
||||
assert_equals(option.value, "");
|
||||
}, "Option constructor with no arguments");
|
||||
|
||||
test(() => {
|
||||
const option = new Option(false, false);
|
||||
|
||||
assert_true(option instanceof HTMLOptionElement);
|
||||
|
||||
assert_true(option.hasChildNodes());
|
||||
assert_equals(option.childNodes.length, 1);
|
||||
assert_equals(option.childNodes[0].nodeType, Node.TEXT_NODE);
|
||||
assert_equals(option.childNodes[0].data, "false");
|
||||
assert_equals(option.getAttribute("value"), "false");
|
||||
assert_false(option.hasAttribute("selected"));
|
||||
assert_false(option.selected);
|
||||
|
||||
assert_equals(option.textContent, "false");
|
||||
assert_equals(option.value, "false");
|
||||
}, "Option constructor with falsy arguments");
|
||||
|
||||
test(() => {
|
||||
const option = new Option("text", "value");
|
||||
|
||||
assert_true(option.hasChildNodes());
|
||||
assert_equals(option.childNodes.length, 1);
|
||||
assert_equals(option.childNodes[0].nodeType, Node.TEXT_NODE);
|
||||
assert_equals(option.childNodes[0].data, "text");
|
||||
assert_equals(option.getAttribute("value"), "value");
|
||||
assert_false(option.hasAttribute("selected"));
|
||||
assert_false(option.selected);
|
||||
|
||||
assert_equals(option.textContent, "text");
|
||||
assert_equals(option.value, "value");
|
||||
}, "Option constructor creates HTMLOptionElement with specified text and value");
|
||||
|
||||
test(() => {
|
||||
const notSelected = new Option("text", "value", false);
|
||||
const selected = new Option("text", "value", true);
|
||||
|
||||
assert_false(notSelected.hasAttribute("selected"));
|
||||
assert_equals(notSelected.getAttribute("selected"), null);
|
||||
assert_false(notSelected.selected);
|
||||
|
||||
assert_equals(selected.getAttribute("selected"), "");
|
||||
assert_false(selected.selected);
|
||||
}, "Option constructor handles selectedness correctly when specified with defaultSelected only");
|
||||
|
||||
test(() => {
|
||||
const notSelected = new Option("text", "value", true, false);
|
||||
const selected = new Option("text", "value", false, true);
|
||||
|
||||
assert_equals(notSelected.selected, false);
|
||||
assert_equals(selected.selected, true);
|
||||
}, "Option constructor handles selectedness correctly, even when incongruous with defaultSelected");
|
||||
|
||||
test(() => {
|
||||
const option = new Option(undefined, undefined);
|
||||
|
||||
assert_false(option.hasChildNodes());
|
||||
assert_false(option.hasAttribute("value"));
|
||||
|
||||
assert_equals(option.textContent, "");
|
||||
assert_equals(option.value, "");
|
||||
}, "Option constructor treats undefined text and value correctly");
|
||||
|
||||
test(() => {
|
||||
const option = new Option("", "");
|
||||
|
||||
assert_false(option.hasChildNodes());
|
||||
assert_true(option.hasAttribute("value"));
|
||||
|
||||
assert_equals(option.textContent, "");
|
||||
assert_equals(option.value, "");
|
||||
}, "Option constructor treats empty text and value correctly");
|
||||
|
||||
test(() => {
|
||||
const option = new Option("text", "value", 0, "");
|
||||
|
||||
assert_false(option.hasAttribute("selected"));
|
||||
assert_false(option.selected);
|
||||
}, "Option constructor treats falsy selected and defaultSelected correctly");
|
||||
|
||||
test(() => {
|
||||
const option = new Option("text", "value", {}, 1);
|
||||
|
||||
assert_true(option.hasAttribute("selected"));
|
||||
assert_true(option.selected);
|
||||
}, "Option constructor treats truthy selected and defaultSelected correctly");
|
||||
|
||||
test(() => {
|
||||
const option = new Option("text", "value", false, true);
|
||||
|
||||
assert_false(option.hasAttribute("selected"));
|
||||
assert_true(option.selected);
|
||||
|
||||
option.setAttribute("selected", "");
|
||||
assert_true(option.selected);
|
||||
|
||||
option.removeAttribute("selected");
|
||||
assert_false(option.selected);
|
||||
}, "Option constructor does not set dirtiness (so, manipulating the selected content attribute still updates the " +
|
||||
"selected IDL attribute)");
|
||||
</script>
|
|
@ -0,0 +1,54 @@
|
|||
<!DOCTYPE HTML>
|
||||
<title>HTMLOptionElement.prototype.index</title>
|
||||
<link rel="author" title="Domenic Denicola" href="mailto:d@domenic.me">
|
||||
<link rel="help" href="https://html.spec.whatwg.org/multipage/#dom-option-index">
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
|
||||
<select>
|
||||
<option id="option0">hello</option>
|
||||
<option id="option1">hello</option>
|
||||
</select>
|
||||
|
||||
|
||||
<datalist>
|
||||
<option id="dl-option0">hello</option>
|
||||
<option id="dl-option1">hello</option>
|
||||
</datalist>
|
||||
|
||||
<option id="doc-option0">hello</option>
|
||||
<option id="doc-option1">hello</option>
|
||||
|
||||
<script>
|
||||
"use strict";
|
||||
|
||||
test(() => {
|
||||
|
||||
assert_equals(document.querySelector("#option0").index, 0);
|
||||
assert_equals(document.querySelector("#option1").index, 1);
|
||||
|
||||
}, "option index should work inside the document");
|
||||
|
||||
test(() => {
|
||||
|
||||
assert_equals(document.querySelector("#dl-option0").index, 0);
|
||||
assert_equals(document.querySelector("#dl-option1").index, 0);
|
||||
|
||||
}, "option index should always be 0 for options in datalists");
|
||||
|
||||
test(() => {
|
||||
|
||||
assert_equals(document.querySelector("#doc-option0").index, 0);
|
||||
assert_equals(document.querySelector("#doc-option1").index, 0);
|
||||
|
||||
}, "option index should always be 0 for options with no container");
|
||||
|
||||
test(() => {
|
||||
|
||||
assert_equals(document.createElement("option").index, 0);
|
||||
assert_equals(document.createElement("option").index, 0);
|
||||
|
||||
}, "option index should always be 0 for options not even in the document");
|
||||
|
||||
|
||||
</script>
|
|
@ -0,0 +1,36 @@
|
|||
<!doctype html>
|
||||
<meta charset=utf-8>
|
||||
<title>HTMLSelectElement ask for reset</title>
|
||||
<link rel="author" title="Sebastian Mayr" href="wpt@smayr.name">
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<select multiple id="initial-selected">
|
||||
<option selected>Test 1</option>
|
||||
<option selected>Test 2</option>
|
||||
</select>
|
||||
<select multiple id="scripted-select">
|
||||
<option selected>Test 1</option>
|
||||
<option>Test 2</option>
|
||||
</select>
|
||||
<div id=log></div>
|
||||
<script>
|
||||
"use strict";
|
||||
|
||||
test(() => {
|
||||
|
||||
const select = document.getElementById("initial-selected");
|
||||
assert_true(select.options[0].selected, "first option should be selected.");
|
||||
assert_true(select.options[1].selected, "second option should be selected.");
|
||||
|
||||
}, "multiple selected options exist, both set from markup");
|
||||
|
||||
test(() => {
|
||||
|
||||
const select = document.getElementById("initial-selected");
|
||||
select.options[1].selected = true;
|
||||
|
||||
assert_true(select.options[0].selected, "first option should be selected.");
|
||||
assert_true(select.options[1].selected, "second option should be selected.");
|
||||
|
||||
}, "multiple selected options exist, one set from script");
|
||||
</script>
|
|
@ -0,0 +1,127 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>HTMLSelectElement.selectedOptions</title>
|
||||
<link rel="help" href="https://html.spec.whatwg.org/multipage/forms.html#dom-select-selectedoptions">
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<div id="log"></div>
|
||||
|
||||
<select id="select-none-selected">
|
||||
<option>One</option>
|
||||
<option>Two</option>
|
||||
<option>Three</option>
|
||||
</select>
|
||||
|
||||
<select id="select-one-selected">
|
||||
<option>One</option>
|
||||
<option selected>Two</option>
|
||||
<option>Three</option>
|
||||
</select>
|
||||
|
||||
<select multiple id="multiple-select-none-selected">
|
||||
<option>One</option>
|
||||
<option>Two</option>
|
||||
<option>Three</option>
|
||||
</select>
|
||||
|
||||
<select multiple id="multiple-select-two-selected">
|
||||
<option>One</option>
|
||||
<option selected>Two</option>
|
||||
<option selected>Three</option>
|
||||
</select>
|
||||
|
||||
<select id="invalid-select">
|
||||
<option selected>One</option>
|
||||
<option selected>Two</option>
|
||||
<option>Three</option>
|
||||
</select>
|
||||
|
||||
<select id="select-same-object">
|
||||
<option>One</option>
|
||||
<option selected>Two</option>
|
||||
<option>Three</option>
|
||||
</select>
|
||||
|
||||
<select multiple id="select-same-object-change">
|
||||
<option selected>One</option>
|
||||
<option selected>Two</option>
|
||||
<option selected>Three</option>
|
||||
</select>
|
||||
|
||||
<script>
|
||||
"use strict";
|
||||
|
||||
test(() => {
|
||||
const select = document.getElementById("select-none-selected");
|
||||
|
||||
assert_array_equals(select.selectedOptions, [select.children[0]]);
|
||||
assert_equals(select.selectedOptions.length, 1);
|
||||
|
||||
}, ".selectedOptions with no selected option");
|
||||
|
||||
test(() => {
|
||||
const select = document.getElementById("select-one-selected");
|
||||
|
||||
assert_array_equals(select.selectedOptions, [select.children[1]]);
|
||||
assert_equals(select.selectedOptions.length, 1);
|
||||
}, ".selectedOptions with one selected option");
|
||||
|
||||
test(() => {
|
||||
const select = document.getElementById("multiple-select-none-selected");
|
||||
|
||||
assert_equals(select.selectedOptions.item(0), null);
|
||||
assert_equals(select.selectedOptions.length, 0);
|
||||
}, ".selectedOptions using the 'multiple' attribute with no selected options");
|
||||
|
||||
test(() => {
|
||||
const select = document.getElementById("multiple-select-two-selected");
|
||||
|
||||
assert_equals(select.selectedOptions.item(0), select.children[1]);
|
||||
assert_equals(select.selectedOptions.item(1), select.children[2]);
|
||||
assert_equals(select.selectedOptions.length, 2);
|
||||
}, ".selectedOptions using the 'multiple' attribute with two selected options");
|
||||
|
||||
// "A select element whose multiple attribute is not specified must not have
|
||||
// more than one descendant option element with its selected attribute set."
|
||||
// - https://html.spec.whatwg.org/multipage/forms.html#the-option-element:the-select-element-6
|
||||
|
||||
// "If two or more option elements in the select element's list of options
|
||||
// have their selectedness set to true, set the selectedness of all but
|
||||
// the last option element with its selectedness set to true in the list of
|
||||
// options in tree order to false."
|
||||
// - https://html.spec.whatwg.org/multipage/forms.html#the-select-element:the-option-element-21
|
||||
test(() => {
|
||||
const select = document.getElementById("invalid-select");
|
||||
|
||||
assert_array_equals(select.selectedOptions, [select.children[1]]);
|
||||
assert_equals(select.selectedOptions.length, 1);
|
||||
|
||||
}, ".selectedOptions without the 'multiple' attribute but " +
|
||||
"more than one selected option should return the last one");
|
||||
|
||||
test(() => {
|
||||
const select = document.getElementById("select-same-object");
|
||||
const selectAgain = document.getElementById("select-same-object");
|
||||
|
||||
assert_equals(select.selectedOptions, selectAgain.selectedOptions);
|
||||
|
||||
}, ".selectedOptions should always return the same value - [SameObject]");
|
||||
|
||||
test(() => {
|
||||
const select = document.getElementById("select-same-object-change");
|
||||
const before = select.selectedOptions;
|
||||
|
||||
select.selectedOptions[1].selected = false;
|
||||
|
||||
const after = select.selectedOptions;
|
||||
|
||||
assert_equals(before, after);
|
||||
|
||||
}, ".selectedOptions should return the same object after selection changes - [SameObject]");
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,92 @@
|
|||
<!DOCTYPE HTML>
|
||||
<title>textarea element select() functionality</title>
|
||||
<link rel="author" title="Domenic Denicola" href="mailto:d@domenic.me">
|
||||
<link rel="help" href="https://html.spec.whatwg.org/multipage/#dom-textarea-value">
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
|
||||
<script>
|
||||
"use strict";
|
||||
|
||||
test(() => {
|
||||
|
||||
const textarea = document.createElement("textarea");
|
||||
|
||||
assert_equals(textarea.defaultValue, "", "defaultValue is empty string when it has no content");
|
||||
assert_equals(textarea.value, "", "value is empty string when it has no content");
|
||||
|
||||
}, "defaultValue and value are the empty string by default");
|
||||
|
||||
test(() => {
|
||||
|
||||
const textarea = document.createElement("textarea");
|
||||
|
||||
textarea.textContent = "foo bar";
|
||||
assert_equals(textarea.defaultValue, "foo bar", "the defaultValue should reflect the textContent");
|
||||
assert_equals(textarea.value, "foo bar",
|
||||
"changing the textContent should change the raw value, and subsequently the api value");
|
||||
|
||||
}, "defaultValue and value are affected by setting textContent");
|
||||
|
||||
test(() => {
|
||||
|
||||
const textarea = document.createElement("textarea");
|
||||
|
||||
textarea.textContent = "foo bar";
|
||||
textarea.appendChild(document.createTextNode(" baz"));
|
||||
assert_equals(textarea.defaultValue, "foo bar baz", "the defaultValue should reflect the textContent");
|
||||
assert_equals(textarea.value, "foo bar baz",
|
||||
"changing the textContent should change the raw value, and subsequently the api value");
|
||||
|
||||
}, "defaultValue and value are affected by textContent in combination with appending a text node");
|
||||
|
||||
test(() => {
|
||||
|
||||
const textarea = document.createElement("textarea");
|
||||
|
||||
textarea.textContent = "foo\r\nbar\rbaz\nqux";
|
||||
assert_equals(textarea.defaultValue, "foo\r\nbar\rbaz\nqux", "the defaultValue should reflect the textContent");
|
||||
assert_equals(textarea.value, "foo\nbar\nbaz\nqux", "The value property should normalize CRLF and CR to LF");
|
||||
|
||||
}, "defaultValue and value treat CRLF differently");
|
||||
|
||||
test(() => {
|
||||
|
||||
const textarea = document.createElement("textarea");
|
||||
|
||||
textarea.textContent = "foo";
|
||||
textarea.value = "baz";
|
||||
assert_equals(textarea.defaultValue, "foo", "setting the value property should not affect the defaultValue");
|
||||
assert_equals(textarea.textContent, "foo", "setting the value property should not affect the textContent");
|
||||
assert_equals(textarea.value, "baz",
|
||||
"on setting, the value property must set the element's raw & api value to the new value");
|
||||
|
||||
textarea.value = "foo\r\nbar\rbaz\nqux";
|
||||
assert_equals(textarea.value, "foo\nbar\nbaz\nqux", "The API value should normalize CRLF and CR to LF");
|
||||
|
||||
textarea.value = null;
|
||||
assert_equals(textarea.value, "", "setting the value property to null should result in an empty string");
|
||||
|
||||
}, "tests for the value setter");
|
||||
|
||||
test(() => {
|
||||
|
||||
const textarea = document.createElement("textarea");
|
||||
|
||||
textarea.defaultValue = "foo\0";
|
||||
assert_equals(textarea.defaultValue, "foo\0", "defaultValue after setting defaultValue");
|
||||
assert_equals(textarea.textContent, "foo\0", "textContent after setting defaultValue");
|
||||
assert_equals(textarea.value, "foo\0", "value after setting defaultValue");
|
||||
|
||||
textarea.textContent = "bar\0";
|
||||
assert_equals(textarea.defaultValue, "bar\0", "defaultValue after setting textContent");
|
||||
assert_equals(textarea.textContent, "bar\0", "textContent after setting textContent");
|
||||
assert_equals(textarea.value, "bar\0", "value after setting textContent");
|
||||
|
||||
textarea.value = "baz\0";
|
||||
assert_equals(textarea.defaultValue, "bar\0", "defaultValue after setting value");
|
||||
assert_equals(textarea.textContent, "bar\0", "textContent after setting value");
|
||||
assert_equals(textarea.value, "baz\0", "value after setting value");
|
||||
|
||||
}, "tests for U+0000 NULL");
|
||||
</script>
|
|
@ -1,21 +0,0 @@
|
|||
<!doctype html>
|
||||
<html>
|
||||
<head>
|
||||
<title>HTML contextmenu event is a MouseEvent</title>
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<style>#contextmenutarget { width: 100px; height: 100px; background-color: red; }</style>
|
||||
</head>
|
||||
<body>
|
||||
<div id='contextmenutarget'>Trigger context menu in this box.</div>
|
||||
<div id="log"></div>
|
||||
<script type="text/javascript">
|
||||
var t = async_test('contextmenu event generated from user action is MouseEvent');
|
||||
document.querySelector("#contextmenutarget").addEventListener('contextmenu', t.step_func(function (e) {
|
||||
assert_equals(e.constructor, window.MouseEvent);
|
||||
document.querySelector("#contextmenutarget").style.backgroundColor = "green";
|
||||
t.done();
|
||||
}));
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,99 @@
|
|||
<!DOCTYPE html>
|
||||
<meta charset="utf-8">
|
||||
<title>menu element removed properties</title>
|
||||
<link rel="help" href="https://html.spec.whatwg.org/multipage/#the-menu-element">
|
||||
<link rel="help" href="https://github.com/whatwg/html/pull/2742">
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
|
||||
<menu type="context" label="label">
|
||||
<menuitem>Text</menuitem>
|
||||
<menuitem type="checkbox" checked>Checked</menuitem>
|
||||
<menuitem disabled>Disabled</menuitem>
|
||||
<menuitem default>Default</menuitem>
|
||||
</menu>
|
||||
|
||||
<script>
|
||||
"use strict";
|
||||
|
||||
const menu = document.querySelector("menu");
|
||||
const menuitem = document.querySelector("menuitem");
|
||||
|
||||
test(() => {
|
||||
assert_false("HTMLMenuItemElement" in window, "the HTMLMenuItemElement interface must not exist");
|
||||
assert_equals(menuitem.constructor, HTMLUnknownElement, "A <menuitem> must be HTMLUnknownElement");
|
||||
|
||||
for (const prop of ["type", "label", "icon", "disabled", "checked", "radiogroup", "default"]) {
|
||||
assert_false(prop in menuitem, `menuitem.${prop} must not be present`);
|
||||
}
|
||||
}, "HTMLMenuItemElement must not be not present");
|
||||
|
||||
test(() => {
|
||||
const potentialBadLocations = [
|
||||
window,
|
||||
document,
|
||||
HTMLElement.prototype,
|
||||
SVGElement.prototype,
|
||||
Document.prototype,
|
||||
HTMLDocument.prototype,
|
||||
Element.prototype
|
||||
];
|
||||
for (const location of potentialBadLocations) {
|
||||
assert_false("onshow" in location,
|
||||
`${location.constructor.name} must not have a property "onshow"`);
|
||||
}
|
||||
}, `onshow must not be present on the GlobalEventHandlers locations`);
|
||||
|
||||
test(() => {
|
||||
assert_false("RelatedEvent" in window);
|
||||
}, "RelatedEvent must not be present");
|
||||
|
||||
test(() => {
|
||||
assert_false("contextMenu" in HTMLElement.prototype,
|
||||
"HTMLElement's prototype must not have a property \"contextMenu\"");
|
||||
assert_false("contextMenu" in document.createElement("div"),
|
||||
"A div must not have a property \"contextMenu\"");
|
||||
}, "el.contextMenu must not be present");
|
||||
|
||||
test(() => {
|
||||
assert_false("type" in menu);
|
||||
|
||||
menu.type = "toolbar";
|
||||
assert_equals(menu.getAttribute("type"), "context");
|
||||
}, "menu.type must not exist or reflect the content attribute");
|
||||
|
||||
test(() => {
|
||||
assert_false("label" in menu);
|
||||
|
||||
menu.label = "new label";
|
||||
assert_equals(menu.getAttribute("label"), "label");
|
||||
}, "menu.label must not exist or reflect the content attribute");
|
||||
|
||||
test(() => {
|
||||
assert_array_equals(document.querySelectorAll("menuitem:enabled"), []);
|
||||
}, ":enabled must not match menuitems");
|
||||
|
||||
test(() => {
|
||||
assert_array_equals(document.querySelectorAll("menuitem:disabled"), []);
|
||||
}, ":disabled must not match menuitems");
|
||||
|
||||
test(() => {
|
||||
assert_array_equals(document.querySelectorAll("menuitem:checked"), []);
|
||||
}, ":checked must not match menuitems");
|
||||
|
||||
test(() => {
|
||||
try {
|
||||
assert_array_equals(document.querySelectorAll("menuitem:default"), []);
|
||||
} catch (e) {
|
||||
// Not everyone has implemented :default as of the time of this writing.
|
||||
if (e.name !== "SyntaxError") {
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
}, ":default must not match menuitems");
|
||||
|
||||
test(() => {
|
||||
assert_equals(getComputedStyle(menu).display, "block");
|
||||
}, "The user-agent stylesheet must leave type=\"context\" menus as block display like other menus");
|
||||
|
||||
</script>
|
|
@ -1,18 +0,0 @@
|
|||
[
|
||||
{
|
||||
"id": "menus-intro",
|
||||
"original_id": "menus-intro"
|
||||
},
|
||||
{
|
||||
"id": "building-menus-and-toolbars",
|
||||
"original_id": "building-menus-and-toolbars"
|
||||
},
|
||||
{
|
||||
"id": "context-menus",
|
||||
"original_id": "context-menus"
|
||||
},
|
||||
{
|
||||
"id": "toolbars",
|
||||
"original_id": "toolbars"
|
||||
}
|
||||
]
|
|
@ -83,7 +83,6 @@ var elements = [
|
|||
["mark", ""],
|
||||
["marquee", "Marquee"],
|
||||
["menu", "Menu"],
|
||||
["menuitem", "MenuItem"],
|
||||
["meta", "Meta"],
|
||||
["meter", "Meter"],
|
||||
["mod", "Unknown"],
|
||||
|
|
|
@ -0,0 +1,3 @@
|
|||
import "string-without-dot-slash-prefix";
|
||||
import "./this.js";
|
||||
log.push("bad-module-specifier");
|
|
@ -0,0 +1,28 @@
|
|||
<!DOCTYPE html>
|
||||
<title>Handling of compilation errors, 1</title>
|
||||
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<script>
|
||||
setup({allow_uncaught_exception: true});
|
||||
|
||||
window.log = [];
|
||||
|
||||
window.addEventListener("error", ev => log.push(ev.error));
|
||||
|
||||
const test_load = async_test(
|
||||
"Test that syntax errors lead to SyntaxError events on window, " +
|
||||
"and that exceptions are remembered.");
|
||||
window.addEventListener("load", test_load.step_func_done(ev => {
|
||||
assert_equals(log.length, 5);
|
||||
assert_equals(log[0].constructor, SyntaxError);
|
||||
assert_true(log.every(exn => exn === log[0]));
|
||||
}));
|
||||
|
||||
function unreachable() { log.push("unexpected"); }
|
||||
</script>
|
||||
<script type="module" src="./syntaxerror.js" onerror="unreachable()"></script>
|
||||
<script type="module" src="./syntaxerror.js" onerror="unreachable()"></script>
|
||||
<script type="module" src="./syntaxerror-nested.js" onerror="unreachable()"></script>
|
||||
<script type="module" src="./syntaxerror.js" onerror="unreachable()"></script>
|
||||
<script type="module" src="./syntaxerror-nested.js" onerror="unreachable()"></script>
|
|
@ -0,0 +1,28 @@
|
|||
<!DOCTYPE html>
|
||||
<title>Handling of compilation errors, 2</title>
|
||||
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<script>
|
||||
setup({allow_uncaught_exception: true});
|
||||
|
||||
window.log = [];
|
||||
|
||||
window.addEventListener("error", ev => log.push(ev.error));
|
||||
|
||||
const test_load = async_test(
|
||||
"Test that syntax errors lead to SyntaxError events on window, " +
|
||||
"and that exceptions are remembered.");
|
||||
window.addEventListener("load", test_load.step_func_done(ev => {
|
||||
assert_equals(log.length, 5);
|
||||
assert_equals(log[0].constructor, SyntaxError);
|
||||
assert_true(log.every(exn => exn === log[0]));
|
||||
}));
|
||||
|
||||
function unreachable() { log.push("unexpected"); }
|
||||
</script>
|
||||
<script type="module" src="./syntaxerror-nested.js" onerror="unreachable()"></script>
|
||||
<script type="module" src="./syntaxerror-nested.js" onerror="unreachable()"></script>
|
||||
<script type="module" src="./syntaxerror.js" onerror="unreachable()"></script>
|
||||
<script type="module" src="./syntaxerror-nested.js" onerror="unreachable()"></script>
|
||||
<script type="module" src="./syntaxerror.js" onerror="unreachable()"></script>
|
|
@ -6,7 +6,7 @@
|
|||
</head>
|
||||
<body>
|
||||
<h1>html-script-module-crossOrigin-import-NoCORS</h1>
|
||||
<script type="module">
|
||||
<script type="module" onerror="document._log.push('error');">
|
||||
|
||||
import { foo } from "http://{{domains[www2]}}:{{ports[http][0]}}/html/semantics/scripting-1/the-script-element/module/crossorigin-scripterror.js";
|
||||
|
||||
|
|
|
@ -6,6 +6,6 @@
|
|||
</head>
|
||||
<body>
|
||||
<h1>html-script-module-crossOrigin-root-NoCORS</h1>
|
||||
<script type="module" src="http://{{domains[www2]}}:{{ports[http][0]}}/html/semantics/scripting-1/the-script-element/module/crossorigin-scripterror.js"></script>
|
||||
<script type="module" src="http://{{domains[www2]}}:{{ports[http][0]}}/html/semantics/scripting-1/the-script-element/module/crossorigin-scripterror.js" onerror="document._log.push('error');"></script>
|
||||
</body>
|
||||
</html>
|
||||
|
|
|
@ -7,24 +7,24 @@
|
|||
</head>
|
||||
<body>
|
||||
<h1>html-script-module-crossOrigin</h1>
|
||||
<iframe id="root-NoCORS" src="crossorigin-root-different.sub.html"></iframe>
|
||||
<iframe id="root-WithCORS" src="crossorigin-root-same.sub.html"></iframe>
|
||||
<iframe id="root-NoCORS" src="crossorigin-root-different.sub.html"></iframe>
|
||||
<iframe id="root-BlockedMissingHeader" src="crossorigin-root-missingheader.sub.html"></iframe>
|
||||
<iframe id="root-BlockedWrongHeader" src="crossorigin-root-wrongheader.sub.html"></iframe>
|
||||
<iframe id="import-NoCORS" src="crossorigin-import-different.sub.html"></iframe>
|
||||
<iframe id="import-WithCORS" src="crossorigin-import-same.sub.html"></iframe>
|
||||
<iframe id="import-NoCORS" src="crossorigin-import-different.sub.html"></iframe>
|
||||
<iframe id="import-BlockedMissingHeader" src="crossorigin-import-missingheader.sub.html"></iframe>
|
||||
<iframe id="import-BlockedWrongHeader" src="crossorigin-import-wrongheader.sub.html"></iframe>
|
||||
<script>
|
||||
|
||||
var tests = [
|
||||
{ "obj": async_test("Root module, Error in CORS-different-origin script"), "id": "root-NoCORS", "expected": "running,0-0" },
|
||||
{ "obj": async_test("Root module, Error in CORS-same-origin script"), "id": "root-WithCORS", "expected": "running,8-1" },
|
||||
{ "obj": async_test("Root module, Blocked script download, missing CORS ACAO header"), "id": "root-BlockedMissingHeader", "expected": "error" },
|
||||
{ "obj": async_test("Root module, Blocked script download, missing CORS ACAO header"), "id": "root-NoCORS", "expected": "error" },
|
||||
{ "obj": async_test("Root module, Blocked script download, crossorigin attribute with missing CORS ACAO header"), "id": "root-BlockedMissingHeader", "expected": "error" },
|
||||
{ "obj": async_test("Root module, Blocked script download, mismatched CORS ACAO header"), "id": "root-BlockedWrongHeader", "expected": "error" },
|
||||
{ "obj": async_test("Imported module, Error in CORS-different-origin script"), "id": "import-NoCORS", "expected": "running,0-0" },
|
||||
{ "obj": async_test("Imported module, Error in CORS-same-origin script"), "id": "import-WithCORS", "expected": "running,8-1" },
|
||||
{ "obj": async_test("Imported module, Blocked script download, missing CORS ACAO header"), "id": "import-BlockedMissingHeader", "expected": "error" },
|
||||
{ "obj": async_test("Imported module, Blocked script download, missing CORS ACAO header"), "id": "import-NoCORS", "expected": "error" },
|
||||
{ "obj": async_test("Imported module, Blocked script download, crossorigin attribute with missing CORS ACAO header"), "id": "import-BlockedMissingHeader", "expected": "error" },
|
||||
{ "obj": async_test("Imported module, Blocked script download, mismatched CORS ACAO header"), "id": "import-BlockedWrongHeader", "expected": "error" },
|
||||
];
|
||||
|
||||
|
|
|
@ -0,0 +1,13 @@
|
|||
<!DOCTYPE html>
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<script type="module" src="set-currentScript-on-window.js"></script>
|
||||
<script type="module">
|
||||
import { currentScriptOnImportedModule } from "./currentscript.js";
|
||||
|
||||
test(() => {
|
||||
assert_equals(document.currentScript, null, "document.currentScript on inline scripts should be null");
|
||||
assert_equals(currentScriptOnImportedModule, null, "document.currentScript on imported scripts should be null");
|
||||
assert_equals(window.currentScriptRecorded, null, "document.currentScript on external module scripts should be null");
|
||||
}, "currentScript on script type=module should be all null");
|
||||
</script>
|
|
@ -0,0 +1 @@
|
|||
export let currentScriptOnImportedModule = window.document.currentScript;
|
|
@ -0,0 +1,3 @@
|
|||
log.push("cycle-tdz-access-a");
|
||||
import { Y } from "./cycle-tdz-access.js";
|
||||
export var X = Y;
|
|
@ -0,0 +1,3 @@
|
|||
log.push("cycle-tdz-access");
|
||||
import { X } from "./cycle-tdz-access-a.js";
|
||||
export let Y = X;
|
|
@ -0,0 +1,2 @@
|
|||
export {x} from "./cycle-unresolvable.js";
|
||||
log.push("cycle-unresolvable-a");
|
|
@ -0,0 +1,2 @@
|
|||
export {x} from "./cycle-unresolvable-a.js";
|
||||
log.push("cycle-unresolvable");
|
|
@ -0,0 +1,19 @@
|
|||
<!DOCTYPE html>
|
||||
<title>Module importing syntax error script and slow script should not crash UA</title>
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<script type="module">
|
||||
setup({allow_uncaught_exception: true});
|
||||
window.log = [];
|
||||
</script>
|
||||
<script type="module">
|
||||
import "./syntaxerror.js";
|
||||
import "./resources/delayed-modulescript.py";
|
||||
|
||||
window.loaded = true;
|
||||
</script>
|
||||
<script type="module">
|
||||
test(() => {
|
||||
assert_false(loaded);
|
||||
}, "module graph with a syntax error should not evaulate but should not crash UA.");
|
||||
</script>
|
|
@ -0,0 +1,27 @@
|
|||
<!DOCTYPE html>
|
||||
<title>Handling of evaluation errors, 1</title>
|
||||
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<script>
|
||||
setup({allow_uncaught_exception: true});
|
||||
|
||||
window.log = [];
|
||||
|
||||
window.addEventListener("error", ev => log.push(ev.error));
|
||||
|
||||
const test_load = async_test(
|
||||
"Test that exceptions during evaluation lead to error events on " +
|
||||
"window, and that exceptions are remembered.\n");
|
||||
window.addEventListener("load", test_load.step_func_done(ev => {
|
||||
const exn = log[1];
|
||||
assert_array_equals(log, ["throw", exn, exn, exn, exn]);
|
||||
assert_true(exn.foo);
|
||||
}));
|
||||
|
||||
function unreachable() { log.push("unexpected"); }
|
||||
</script>
|
||||
<script type="module" src="throw.js" onerror="unreachable()"></script>
|
||||
<script type="module" src="throw.js" onerror="unreachable()"></script>
|
||||
<script type="module" src="throw.js" async onerror="unreachable()"></script>
|
||||
<script type="module" src="throw.js" nomodule onerror="unreachable()"></script>
|
|
@ -0,0 +1,27 @@
|
|||
<!DOCTYPE html>
|
||||
<title>Handling of evaluation errors, 2</title>
|
||||
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<script>
|
||||
setup({allow_uncaught_exception: true});
|
||||
|
||||
window.log = [];
|
||||
|
||||
window.addEventListener("error", ev => log.push(ev.error));
|
||||
|
||||
const test_load = async_test(
|
||||
"Test that ill-founded cyclic dependencies cause ReferenceError " +
|
||||
"during evaluation, which leads to error events on window, and that " +
|
||||
"exceptions are remembered.\n");
|
||||
window.addEventListener("load", test_load.step_func_done(ev => {
|
||||
const exn = log[1];
|
||||
assert_array_equals(log, ["cycle-tdz-access-a", exn, exn, exn]);
|
||||
assert_equals(exn.constructor, ReferenceError);
|
||||
}));
|
||||
|
||||
function unreachable() { log.push("unexpected"); }
|
||||
</script>
|
||||
<script type="module" src="cycle-tdz-access.js" async onerror="unreachable()"></script>
|
||||
<script type="module" src="cycle-tdz-access.js" nomodule onerror="unreachable()"></script>
|
||||
<script type="module" src="cycle-tdz-access.js" onerror="unreachable()"></script>
|
|
@ -0,0 +1,28 @@
|
|||
<!DOCTYPE html>
|
||||
<title>Handling of evaluation errors, 3</title>
|
||||
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<script>
|
||||
setup({allow_uncaught_exception: true});
|
||||
|
||||
window.log = [];
|
||||
|
||||
window.addEventListener("error", ev => log.push(ev.error));
|
||||
|
||||
const test_load = async_test(
|
||||
"Test that exceptions during evaluation lead to error events on " +
|
||||
"window, and that exceptions are remembered.\n");
|
||||
window.addEventListener("load", test_load.step_func_done(ev => {
|
||||
const exn = log[1];
|
||||
assert_array_equals(log, ["throw", exn, exn, exn, exn, exn]);
|
||||
assert_true(exn.foo);
|
||||
}));
|
||||
|
||||
function unreachable() { log.push("unexpected"); }
|
||||
</script>
|
||||
<script type="module" src="./throw.js" onerror="unreachable()"></script>
|
||||
<script type="module" src="./throw.js" onerror="unreachable()"></script>
|
||||
<script type="module" src="./throw-nested.js" onerror="unreachable()"></script>
|
||||
<script type="module" src="./throw.js" onerror="unreachable()"></script>
|
||||
<script type="module" src="./throw-nested.js" onerror="unreachable()"></script>
|
|
@ -0,0 +1,28 @@
|
|||
<!DOCTYPE html>
|
||||
<title>Handling of evaluation errors, 4</title>
|
||||
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<script>
|
||||
setup({allow_uncaught_exception: true});
|
||||
|
||||
window.log = [];
|
||||
|
||||
window.addEventListener("error", ev => log.push(ev.error));
|
||||
|
||||
const test_load = async_test(
|
||||
"Test that exceptions during evaluation lead to error events on " +
|
||||
"window, and that exceptions are remembered.\n");
|
||||
window.addEventListener("load", test_load.step_func_done(ev => {
|
||||
const exn = log[1];
|
||||
assert_array_equals(log, ["throw", exn, exn, exn, exn, exn]);
|
||||
assert_true(exn.foo);
|
||||
}));
|
||||
|
||||
function unreachable() { log.push("unexpected"); }
|
||||
</script>
|
||||
<script type="module" src="./throw-nested.js" onerror="unreachable()"></script>
|
||||
<script type="module" src="./throw-nested.js" onerror="unreachable()"></script>
|
||||
<script type="module" src="./throw.js" onerror="unreachable()"></script>
|
||||
<script type="module" src="./throw-nested.js" onerror="unreachable()"></script>
|
||||
<script type="module" src="./throw.js" onerror="unreachable()"></script>
|
|
@ -41,8 +41,8 @@
|
|||
var test_parsedUnordered1 = async_test("Unordered module script execution (parsed, unordered #1)");
|
||||
var test_parsedUnordered2 = async_test("Unordered module script execution (parsed, unordered #2)");
|
||||
</script>
|
||||
<script type="module" src="execOrder-parsedUnordered1.js"></script>
|
||||
<script type="module" src="execOrder-parsedUnordered2.js"></script>
|
||||
<script type="module" src="execorder-parsedunordered1.js"></script>
|
||||
<script type="module" src="execorder-parsedunordered2.js"></script>
|
||||
<script>
|
||||
/////
|
||||
// End test_parsedUnordered*
|
||||
|
@ -53,8 +53,8 @@
|
|||
/////
|
||||
var test_dynamicUnordered1 = async_test("Unordered module script execution (dynamic, unordered #1)");
|
||||
var test_dynamicUnordered2 = async_test("Unordered module script execution (dynamic, unordered #2)");
|
||||
create_script("execOrder-dynamicUnordered1.js", { module: true });
|
||||
create_script("execOrder-dynamicUnordered2.js", { module: true });
|
||||
create_script("execorder-dynamicunordered1.js", { module: true });
|
||||
create_script("execorder-dynamicunordered2.js", { module: true });
|
||||
/////
|
||||
// End test_dynamicUnordered*
|
||||
/////
|
||||
|
@ -68,13 +68,13 @@
|
|||
test_parsedOrdered.done();
|
||||
}));
|
||||
</script>
|
||||
<script src="execOrder-parsedOrdered2.js" defer></script>
|
||||
<script src="execorder-parsedordered2.js" defer></script>
|
||||
<script type="module">
|
||||
test_parsedOrdered.step(function() {
|
||||
assert_execCount(0, 3, "Inline module-typed script element should have fired third");
|
||||
});
|
||||
</script>
|
||||
<script src="execOrder-parsedOrdered4.js" defer></script>
|
||||
<script src="execorder-parsedordered4.js" defer></script>
|
||||
<script>
|
||||
test_parsedOrdered.step(function() {
|
||||
assert_execCount(0, 1, "Inline untyped script element should have fired first");
|
||||
|
@ -91,9 +91,9 @@
|
|||
assert_execCount(1, 5, "onload should have fired fifth (last)");
|
||||
test_dynamicOrdered.done();
|
||||
}));
|
||||
create_script("execOrder-dynamicOrdered2.js", { asyncOrdered: true, module: false });
|
||||
create_script("execOrder-dynamicOrdered3.js", { asyncOrdered: true, module: true });
|
||||
create_script("execOrder-dynamicOrdered4.js", { asyncOrdered: true, module: false });
|
||||
create_script("execorder-dynamicordered2.js", { asyncOrdered: true, module: false });
|
||||
create_script("execorder-dynamicordered3.js", { asyncOrdered: true, module: true });
|
||||
create_script("execorder-dynamicordered4.js", { asyncOrdered: true, module: false });
|
||||
test_dynamicOrdered.step(function() {
|
||||
assert_execCount(1, 1, "Inline untyped script element should have fired first");
|
||||
});
|
||||
|
|
|
@ -0,0 +1,2 @@
|
|||
log.push("export-something-nested");
|
||||
export * from "./export-something.js";
|
|
@ -0,0 +1,3 @@
|
|||
log.push("export-something");
|
||||
export let foo = 42;
|
||||
export function set_foo(x) { foo = x };
|
|
@ -0,0 +1,15 @@
|
|||
<!DOCTYPE html>
|
||||
<title>Handling of fetch errors, 1</title>
|
||||
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<script>
|
||||
window.log = [];
|
||||
|
||||
const test_load = async_test(
|
||||
"Test that failure to fetch root leads to error event on script.");
|
||||
window.addEventListener("load", test_load.step_func_done(ev => {
|
||||
assert_array_equals(log, ["script"]);
|
||||
}));
|
||||
</script>
|
||||
<script type="module" src="./no-such-file.js" onerror="log.push('script')"></script>
|
|
@ -0,0 +1,15 @@
|
|||
<!DOCTYPE html>
|
||||
<title>Handling of fetch errors, 2</title>
|
||||
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<script>
|
||||
window.log = [];
|
||||
|
||||
const test_load = async_test(
|
||||
"Test that failure to fetch dependency leads to error event on script.");
|
||||
window.addEventListener("load", test_load.step_func_done(ev => {
|
||||
assert_array_equals(log, ["script"]);
|
||||
}));
|
||||
</script>
|
||||
<script type="module" src="./fetch-error-2.js" onerror="log.push('script')"></script>
|
|
@ -0,0 +1,2 @@
|
|||
import "./no-such-file.js"
|
||||
import "./this.js";
|
|
@ -0,0 +1,5 @@
|
|||
log.push("import-something-namespace");
|
||||
log.push(m.foo);
|
||||
m.set_foo(43);
|
||||
log.push(m.foo);
|
||||
import * as m from "./export-something.js";
|
|
@ -0,0 +1,14 @@
|
|||
<!DOCTYPE html>
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<script type="module">
|
||||
import { delayedLoaded } from "./resources/delayed-modulescript.py";
|
||||
import { A } from "./404.js";
|
||||
window.loadSuccess = delayedLoaded;
|
||||
</script>
|
||||
<script type="module">
|
||||
test(function () {
|
||||
assert_equals(window.loadSuccess, undefined,
|
||||
"module tree w/ its sub graph 404 should fail to load without crashing");
|
||||
}, "Import a module graph w/ sub-graph 404.");
|
||||
</script>
|
|
@ -1,5 +1,6 @@
|
|||
import { CycleA } from "./imports-cycle-a.js";
|
||||
|
||||
test_importCycle.step(function () {
|
||||
assert_unreached("This module should not have loaded!");
|
||||
assert_equals(CycleA, "CycleA");
|
||||
test_importCycle.done();
|
||||
});
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
import { SelfInner } from "./imports-self-inner.js";
|
||||
|
||||
test_importSelf.step(function () {
|
||||
assert_unreached("This module should not have loaded!");
|
||||
assert_equals(SelfInner, "SelfInner");
|
||||
test_importSelf.done();
|
||||
});
|
||||
|
|
|
@ -52,13 +52,13 @@
|
|||
</script>
|
||||
|
||||
<script>
|
||||
var test_importSelf = async_test("Import a module that tries to import itself");
|
||||
var test_importSelf = async_test("Import a module that validly imports itself");
|
||||
</script>
|
||||
<script type="module" src="imports-self.js" onerror="test_importSelf.done();"></script>
|
||||
<script type="module" src="imports-self.js"></script>
|
||||
|
||||
<script>
|
||||
var test_importCycle = async_test("Import a module with a cyclical module dependency");
|
||||
var test_importCycle = async_test("Import a module with a valid cyclical module dependency");
|
||||
</script>
|
||||
<script type="module" src="imports-cycle.js" onerror="test_importCycle.done();"></script>
|
||||
<script type="module" src="imports-cycle.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
|
|
|
@ -0,0 +1,33 @@
|
|||
<!DOCTYPE html>
|
||||
<title>Handling of instantiation errors, 1</title>
|
||||
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<script>
|
||||
setup({allow_uncaught_exception: true});
|
||||
|
||||
window.log = [];
|
||||
|
||||
window.addEventListener("error", ev => log.push(ev.error));
|
||||
|
||||
const test_load = async_test(
|
||||
"Test that missing exports lead to SyntaxError events on window and " +
|
||||
"load events on script, and that exceptions are remembered");
|
||||
window.addEventListener("load", test_load.step_func_done(ev => {
|
||||
const exn = log[0];
|
||||
assert_array_equals(log, [exn, 1, exn, 2, exn, 3, exn, 4, exn, 5]);
|
||||
assert_equals(exn.constructor, SyntaxError);
|
||||
}));
|
||||
|
||||
function unreachable() { log.push("unexpected"); }
|
||||
</script>
|
||||
<script type="module" src="./missing-export.js"
|
||||
onerror="unreachable()" onload="log.push(1)"></script>
|
||||
<script type="module" src="./missing-export.js"
|
||||
onerror="unreachable()" onload="log.push(2)"></script>
|
||||
<script type="module" src="./missing-export-nested.js"
|
||||
onerror="unreachable()" onload="log.push(3)"></script>
|
||||
<script type="module" src="./missing-export.js"
|
||||
onerror="unreachable()" onload="log.push(4)"></script>
|
||||
<script type="module" src="./missing-export-nested.js"
|
||||
onerror="unreachable()" onload="log.push(5)"></script>
|
|
@ -0,0 +1 @@
|
|||
import something from "./instantiation-error-1.js";
|
|
@ -0,0 +1,33 @@
|
|||
<!DOCTYPE html>
|
||||
<title>Handling of instantiation errors, 2</title>
|
||||
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<script>
|
||||
setup({allow_uncaught_exception: true});
|
||||
|
||||
window.log = [];
|
||||
|
||||
window.addEventListener("error", ev => log.push(ev.error));
|
||||
|
||||
const test_load = async_test(
|
||||
"Test that missing exports lead to SyntaxError events on window and " +
|
||||
"load events on script, and that exceptions are remembered");
|
||||
window.addEventListener("load", test_load.step_func_done(ev => {
|
||||
const exn = log[0];
|
||||
assert_array_equals(log, [exn, 1, exn, 2, exn, 3, exn, 4, exn, 5]);
|
||||
assert_equals(exn.constructor, SyntaxError);
|
||||
}));
|
||||
|
||||
function unreachable() { log.push("unexpected"); }
|
||||
</script>
|
||||
<script type="module" src="./missing-export-nested.js"
|
||||
onerror="unreachable()" onload="log.push(1)"></script>
|
||||
<script type="module" src="./missing-export-nested.js"
|
||||
onerror="unreachable()" onload="log.push(2)"></script>
|
||||
<script type="module" src="./missing-export.js"
|
||||
onerror="unreachable()" onload="log.push(3)"></script>
|
||||
<script type="module" src="./missing-export-nested.js"
|
||||
onerror="unreachable()" onload="log.push(4)"></script>
|
||||
<script type="module" src="./missing-export.js"
|
||||
onerror="unreachable()" onload="log.push(5)"></script>
|
|
@ -0,0 +1,29 @@
|
|||
<!DOCTYPE html>
|
||||
<title>Handling of instantiation errors, 3</title>
|
||||
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<script>
|
||||
setup({allow_uncaught_exception: true});
|
||||
|
||||
window.log = [];
|
||||
|
||||
window.addEventListener("error", ev => log.push(ev.error));
|
||||
|
||||
const test_load = async_test(
|
||||
"Test that unresolvable cycles lead to SyntaxError events on window " +
|
||||
"and load events on script, and that exceptions are remembered");
|
||||
window.addEventListener("load", test_load.step_func_done(ev => {
|
||||
const exn = log[0];
|
||||
assert_array_equals(log, [exn, 1, exn, 2, exn, 3]);
|
||||
assert_equals(exn.constructor, SyntaxError);
|
||||
}));
|
||||
|
||||
function unreachable() { log.push("unexpected"); }
|
||||
</script>
|
||||
<script type="module" src="./cycle-unresolvable.js"
|
||||
onerror="unreachable()" onload="log.push(1)" nomodule></script>
|
||||
<script type="module" src="./cycle-unresolvable-a.js"
|
||||
onerror="unreachable()" onload="log.push(2)"></script>
|
||||
<script type="module" src="./cycle-unresolvable.js"
|
||||
onerror="unreachable()" onload="log.push(3)" async></script>
|
|
@ -0,0 +1,20 @@
|
|||
<!DOCTYPE html>
|
||||
<title>Late namespace request</title>
|
||||
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<script>
|
||||
window.log = [];
|
||||
|
||||
const test_load = async_test(
|
||||
"Test the situation where a module is instantiated without the " +
|
||||
"need for a namespace object, but later on a different module " +
|
||||
"requests the namespace.");
|
||||
window.addEventListener("load", test_load.step_func_done(ev => {
|
||||
assert_array_equals(log,
|
||||
["export-something",
|
||||
"import-something-namespace", 42, 43]);
|
||||
}));
|
||||
</script>
|
||||
<script type="module" src="export-something.js"></script>
|
||||
<script type="module" src="import-something-namespace.js"></script>
|
|
@ -0,0 +1,25 @@
|
|||
<!DOCTYPE html>
|
||||
<title>Late star-export request</title>
|
||||
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<script>
|
||||
window.log = [];
|
||||
|
||||
const test_load = async_test(
|
||||
"Test the situation where a module is instantiated without a use of " +
|
||||
"its star-exports, but later on a different module requests them.");
|
||||
window.addEventListener("load", test_load.step_func_done(ev => {
|
||||
assert_array_equals(log, [
|
||||
"export-something", "export-something-nested",
|
||||
"import-something-namespace", 42, 43]);
|
||||
}));
|
||||
</script>
|
||||
<script type="module" src="export-something-nested.js"></script>
|
||||
<script type="module">
|
||||
log.push("import-something-namespace");
|
||||
log.push(foo);
|
||||
set_foo(43);
|
||||
log.push(foo);
|
||||
import {foo, set_foo} from "./export-something-nested.js";
|
||||
</script>
|
|
@ -0,0 +1,2 @@
|
|||
import "./missing-export.js";
|
||||
log.push("nested-missing-export");
|
|
@ -0,0 +1,2 @@
|
|||
import something from "./missing-export.js";
|
||||
log.push("missing-export");
|
|
@ -0,0 +1,17 @@
|
|||
<!DOCTYPE html>
|
||||
<title>Once as module script, once as classic script</title>
|
||||
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<script>
|
||||
window.log = [];
|
||||
|
||||
const test_load = async_test(
|
||||
"Test that evaluating something as classic script does not prevent " +
|
||||
"it from being evaluated as module script.");
|
||||
window.addEventListener("load", test_load.step_func_done(ev => {
|
||||
assert_array_equals(log, [window, undefined]);
|
||||
}));
|
||||
</script>
|
||||
<script type="module" src="this.js"></script>
|
||||
<script src="this.js"></script>
|
|
@ -0,0 +1,17 @@
|
|||
<!DOCTYPE html>
|
||||
<title>Once as classic script, once as module script</title>
|
||||
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<script>
|
||||
window.log = [];
|
||||
|
||||
const test_load = async_test(
|
||||
"Test that evaluating something as classic script does not prevent " +
|
||||
"it from being evaluated as module script.");
|
||||
window.addEventListener("load", test_load.step_func_done(ev => {
|
||||
assert_array_equals(log, [window, undefined]);
|
||||
}));
|
||||
</script>
|
||||
<script type="module" src="this.js"></script>
|
||||
<script src="this.js"></script>
|
|
@ -0,0 +1,2 @@
|
|||
import "./missing-export.js";
|
||||
log.push("missing-export-nested");
|
|
@ -0,0 +1,18 @@
|
|||
<!DOCTYPE html>
|
||||
<title>The 'nomodule' attribute</title>
|
||||
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<script>
|
||||
window.log = [];
|
||||
|
||||
const test_load = async_test(
|
||||
"Test that 'nomodule' has the desired effect on classic scripts, but " +
|
||||
"no effect on module scripts.");
|
||||
window.addEventListener("load", test_load.step_func_done(ev => {
|
||||
assert_array_equals(log, [undefined]);
|
||||
}));
|
||||
|
||||
</script>
|
||||
<script type="module" src="this.js" nomodule></script>
|
||||
<script src="this.js" nomodule></script>
|
|
@ -0,0 +1,7 @@
|
|||
import time
|
||||
|
||||
def main(request, response):
|
||||
delay = float(request.GET.first("ms", 500))
|
||||
time.sleep(delay / 1E3);
|
||||
|
||||
return [("Content-type", "text/javascript")], "export let delayedLoaded = true;"
|
|
@ -0,0 +1,93 @@
|
|||
<!DOCTYPE html>
|
||||
<title>Module scripts with for and event attributes</title>
|
||||
<link rel="author" title="Matheus Kerschbaum" href="mailto:matjk7@gmail.com">
|
||||
<link rel="author" title="Ms2ger" href="mailto:ms2ger@gmail.com">
|
||||
<link rel="help" href="https://html.spec.whatwg.org/multipage/#prepare-a-script">
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<div id="log"></div>
|
||||
<script>
|
||||
var expected = [
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
];
|
||||
var run = expected.map(function() { return false });
|
||||
</script>
|
||||
<script for="wİndow" event="onload" type="module">
|
||||
run[0] = true;
|
||||
</script>
|
||||
<script for="window" event="onload x" type="module">
|
||||
run[1] = true;
|
||||
</script>
|
||||
<script for="window" event="onload(x" type="module">
|
||||
run[2] = true;
|
||||
</script>
|
||||
<script for="window" event="onload(x)" type="module">
|
||||
run[3] = true;
|
||||
</script>
|
||||
<script for="window" event="onclick" type="module">
|
||||
run[4] = true;
|
||||
</script>
|
||||
<script for="" event="onload" type="module">
|
||||
run[5] = true;
|
||||
</script>
|
||||
<script for="window" event="" type="module">
|
||||
run[6] = true;
|
||||
</script>
|
||||
<script for="" event="" type="module">
|
||||
run[7] = true;
|
||||
</script>
|
||||
<script for=" window" event="onload" type="module">
|
||||
run[8] = true;
|
||||
</script>
|
||||
<script for="window " event="onload" type="module">
|
||||
run[9] = true;
|
||||
</script>
|
||||
<script for="window" event=" onload" type="module">
|
||||
run[10] = true;
|
||||
</script>
|
||||
<script for="window" event="onload " type="module">
|
||||
run[11] = true;
|
||||
</script>
|
||||
<script for=" window " event=" onload " type="module">
|
||||
run[12] = true;
|
||||
</script>
|
||||
<script for=" window " event=" onload() " type="module">
|
||||
run[13] = true;
|
||||
</script>
|
||||
<script for="object" event="handler" type="module">
|
||||
run[14] = true;
|
||||
</script>
|
||||
<script event="handler" type="module">
|
||||
run[15] = true;
|
||||
</script>
|
||||
<script for="object" type="module">
|
||||
run[16] = true;
|
||||
</script>
|
||||
<script type="module">
|
||||
test(function() {
|
||||
for (var i = 0; i < run.length; ++i) {
|
||||
test(function() {
|
||||
var script = document.querySelectorAll("script[for], script[event]")[i];
|
||||
assert_equals(run[i], expected[i],
|
||||
"script for=" + format_value(script.getAttribute("for")) +
|
||||
" event=" + format_value(script.getAttribute("event")));
|
||||
}, "Script " + i);
|
||||
}
|
||||
});
|
||||
</script>
|
|
@ -0,0 +1 @@
|
|||
window.currentScriptRecorded = document.currentScript;
|
|
@ -0,0 +1,20 @@
|
|||
<!DOCTYPE html>
|
||||
<title>Single evaluation, 1</title>
|
||||
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<script>
|
||||
window.log = [];
|
||||
|
||||
const test_load = async_test(
|
||||
"Test that a module is evaluated only once, and that 'this' is " +
|
||||
"undefined (because of strict mode).");
|
||||
window.addEventListener("load", test_load.step_func_done(ev => {
|
||||
assert_array_equals(log, [undefined, "this-nested"]);
|
||||
}));
|
||||
</script>
|
||||
<script type="module" src="this.js"></script>
|
||||
<script type="module" src="this.js"></script>
|
||||
<script type="module" src="this-nested.js"></script>
|
||||
<script type="module" src="this.js"></script>
|
||||
<script type="module" src="this-nested.js"></script>
|
|
@ -0,0 +1,20 @@
|
|||
<!DOCTYPE html>
|
||||
<title>Single evaluation, 2</title>
|
||||
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<script>
|
||||
window.log = [];
|
||||
|
||||
const test_load = async_test(
|
||||
"Test that a module is evaluated only once, and that 'this' is " +
|
||||
"undefined (because of strict mode).");
|
||||
window.addEventListener("load", test_load.step_func_done(ev => {
|
||||
assert_array_equals(log, [undefined, "this-nested"]);
|
||||
}));
|
||||
</script>
|
||||
<script type="module" src="this-nested.js"></script>
|
||||
<script type="module" src="this-nested.js"></script>
|
||||
<script type="module" src="this.js"></script>
|
||||
<script type="module" src="this-nested.js"></script>
|
||||
<script type="module" src="this.js"></script>
|
|
@ -0,0 +1,11 @@
|
|||
<!DOCTYPE html>
|
||||
<title>Cyclic graph with slow imports</title>
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<script type="module">
|
||||
import { loaded } from "./slow-module-graph-a.js";
|
||||
|
||||
test(() => {
|
||||
assert_true(loaded);
|
||||
}, "module graph with cycles load even if part of the graph loads slow");
|
||||
</script>
|
|
@ -0,0 +1,3 @@
|
|||
import "./slow-module-graph-b.js";
|
||||
import "./resources/delayed-modulescript.py"
|
||||
export let loaded = true;
|
|
@ -0,0 +1 @@
|
|||
import "./slow-module-graph-a.js";
|
|
@ -0,0 +1,22 @@
|
|||
<!DOCTYPE html>
|
||||
<title>Handling of invalid specifiers</title>
|
||||
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<script>
|
||||
setup({allow_uncaught_exception: true});
|
||||
|
||||
window.log = [];
|
||||
|
||||
window.addEventListener("error", ev => log.push(ev.error));
|
||||
|
||||
const test_load = async_test(
|
||||
"Test that invalid module specifier leads to TypeError on window.");
|
||||
window.addEventListener("load", test_load.step_func_done(ev => {
|
||||
assert_equals(log.length, 1);
|
||||
assert_equals(log[0].constructor, TypeError);
|
||||
}));
|
||||
|
||||
function unreachable() { log.push("unexpected"); }
|
||||
</script>
|
||||
<script type="module" src="./bad-module-specifier.js" onerror="unreachable()"></script>
|
|
@ -0,0 +1,2 @@
|
|||
import "./syntaxerror.js";
|
||||
log.push("nested-syntaxerror");
|
|
@ -0,0 +1,2 @@
|
|||
log.push("syntaxerror");
|
||||
%!#$@#$@#$@
|
|
@ -0,0 +1,2 @@
|
|||
import "./this.js";
|
||||
log.push("this-nested");
|
|
@ -0,0 +1 @@
|
|||
log.push(this);
|
|
@ -0,0 +1,2 @@
|
|||
import "./throw.js";
|
||||
log.push("throw-nested");
|
|
@ -0,0 +1,2 @@
|
|||
log.push("throw");
|
||||
throw {foo: true}
|
|
@ -11,31 +11,27 @@
|
|||
</head>
|
||||
<body>
|
||||
<script>
|
||||
let supportsNoModule = "noModule" in document.getElementsByTagName("script")[0];
|
||||
|
||||
waitForLoadEvent = new Promise((resolve) => {
|
||||
window.onload = resolve;
|
||||
});
|
||||
|
||||
waitForAsyncScript = () => {
|
||||
return new Promise((resolve) => {
|
||||
waitForLoadEvent.then(() => setTimeout(resolve, 200));
|
||||
});
|
||||
}
|
||||
|
||||
let readyForSecondTest;
|
||||
promise_test(() => {
|
||||
window.executed = false;
|
||||
let loaded = false;
|
||||
let errored = false;
|
||||
|
||||
let script = document.createElement('script');
|
||||
|
||||
script.src = './resources/set-script-executed.js';
|
||||
script.onload = () => loaded = true;
|
||||
script.onerror = () => errored = true;
|
||||
script.noModule = false;
|
||||
document.body.appendChild(script);
|
||||
|
||||
return waitForAsyncScript().then(() => {
|
||||
return waitForLoadEvent.then(() => {
|
||||
assert_true(supportsNoModule);
|
||||
assert_true(executed);
|
||||
assert_true(loaded);
|
||||
assert_false(errored);
|
||||
|
@ -54,7 +50,8 @@ promise_test(() => {
|
|||
script.noModule = true;
|
||||
document.body.appendChild(script);
|
||||
|
||||
return waitForAsyncScript().then(() => {
|
||||
return waitForLoadEvent.then(() => {
|
||||
assert_true(supportsNoModule);
|
||||
assert_false(executed);
|
||||
assert_false(loaded);
|
||||
assert_false(errored);
|
||||
|
|
|
@ -36,11 +36,6 @@ test(() => {
|
|||
assert_false(errored);
|
||||
}, 'A synchronously loaded external classic script with nomodule content attribute must not run');
|
||||
|
||||
|
||||
waitForLoadEvent = new Promise((resolve) => {
|
||||
window.onload = resolve;
|
||||
});
|
||||
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
|
|
|
@ -20,7 +20,8 @@
|
|||
<input type=radio id=radio2>
|
||||
<form>
|
||||
<p><input type=submit contextmenu=formmenu id="submitbutton"></p>
|
||||
<menu type=popup id=formmenu>
|
||||
<menu type=context id=formmenu>
|
||||
<!-- historical; these should *not* match -->
|
||||
<menuitem type=checkbox checked default id=menuitem1>
|
||||
<menuitem type=checkbox default id=menuitem2>
|
||||
<menuitem type=checkbox id=menuitem3>
|
||||
|
@ -30,14 +31,14 @@
|
|||
</form>
|
||||
|
||||
<script>
|
||||
testSelectorIdsMatch(":checked", ["option1", "checkbox1", "radio1", "menuitem1", "menuitem4"], "':checked' matches checked <input>/<menuitem> in checkbox and radio button states, selected <option>s");
|
||||
testSelectorIdsMatch(":checked", ["option1", "checkbox1", "radio1"], "':checked' matches checked <input>s in checkbox and radio button states, selected <option>s");
|
||||
|
||||
document.getElementById("checkbox1").removeAttribute("type"); // change type of input
|
||||
document.getElementById("radio1").removeAttribute("type"); // change type of input
|
||||
testSelectorIdsMatch(":checked", ["option1", "menuitem1", "menuitem4"], "':checked' should no longer match <input>s whose type checkbox/radio has been removed");
|
||||
testSelectorIdsMatch(":checked", ["option1"], "':checked' should no longer match <input>s whose type checkbox/radio has been removed");
|
||||
|
||||
document.getElementById("option2").selected = "selected"; // select option2
|
||||
document.getElementById("checkbox2").click(); // check chekbox2
|
||||
document.getElementById("radio2").click(); // check radio2
|
||||
testSelectorIdsMatch(":checked", ["option2", "checkbox2", "radio2", "menuitem1", "menuitem4"], "':checked' matches clicked checkbox and radio buttons");
|
||||
testSelectorIdsMatch(":checked", ["option2", "checkbox2", "radio2"], "':checked' matches clicked checkbox and radio buttons");
|
||||
</script>
|
||||
|
|
|
@ -29,7 +29,8 @@
|
|||
<textarea disabled id=textarea2>textarea2</textarea>
|
||||
<form>
|
||||
<p><input type=submit contextmenu=formmenu id=submitbutton></p>
|
||||
<menu type=popup id=formmenu>
|
||||
<menu type=context id=formmenu>
|
||||
<!-- historical; these should *not* match -->
|
||||
<menuitem command="submitbutton" default id=menuitem1>
|
||||
<menuitem command="resetbutton" disabled id=menuitem2>
|
||||
</menu>
|
||||
|
@ -38,5 +39,5 @@
|
|||
<fieldset disabled id=fieldset2></fieldset>
|
||||
|
||||
<script>
|
||||
testSelectorIdsMatch(":enabled", ["button1", "input1", "select1", "optgroup1", "option1", "textarea1", "submitbutton", "menuitem1", "fieldset1"], "':enabled' elements that are not disabled");
|
||||
testSelectorIdsMatch(":enabled", ["button1", "input1", "select1", "optgroup1", "option1", "textarea1", "submitbutton", "fieldset1"], "':enabled' elements that are not disabled");
|
||||
</script>
|
||||
|
|
|
@ -0,0 +1,59 @@
|
|||
<!DOCTYPE html>
|
||||
<title>Limits on col/colgroup.span</title>
|
||||
<script src=/resources/testharness.js></script>
|
||||
<script src=/resources/testharnessreport.js></script>
|
||||
<style>
|
||||
div.square {
|
||||
height:20px;
|
||||
width:20px;
|
||||
border:1px solid lime;
|
||||
}
|
||||
main table {
|
||||
border-collapse:collapse;
|
||||
border:1px solid blue;
|
||||
}
|
||||
main table col {
|
||||
border-left:2px solid black;
|
||||
}
|
||||
</style>
|
||||
<div id=log></div>
|
||||
<main>
|
||||
<table id=table1>
|
||||
<col span=1000>
|
||||
<tr>
|
||||
<td colspan=999><div class="square"></div></td>
|
||||
<td><div class="square"></div></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan=1000><div class="square"></div></td>
|
||||
</tr>
|
||||
</table>
|
||||
<br>
|
||||
These two must look the same, each having 2 cells in one row:
|
||||
<table id=table2>
|
||||
<col span=1000>
|
||||
<tr>
|
||||
<td colspan=1000><div class="square"></div></td>
|
||||
<td><div class="square"></div></td>
|
||||
</tr>
|
||||
</table>
|
||||
<br>
|
||||
<table id=table3>
|
||||
<col span=1001>
|
||||
<tr>
|
||||
<td colspan=1000><div class="square"></div></td>
|
||||
<td><div class="square"></div></td>
|
||||
</tr>
|
||||
</table>
|
||||
</main>
|
||||
|
||||
<script>
|
||||
test(() => {
|
||||
assert_equals(table1.offsetWidth, 53);
|
||||
}, "col span of 1000 must work");
|
||||
|
||||
test(() => {
|
||||
assert_equals(table2.offsetWidth, 51, "table2 width");
|
||||
assert_equals(table3.offsetWidth, 51, "table3 width");
|
||||
}, "col span of 1001 must be treated as 1000");
|
||||
</script>
|
|
@ -0,0 +1,65 @@
|
|||
<!DOCTYPE html>
|
||||
<title>Limits on colSpan/rowSpan</title>
|
||||
<script src=/resources/testharness.js></script>
|
||||
<script src=/resources/testharnessreport.js></script>
|
||||
<div id=log></div>
|
||||
|
||||
<table border=1>
|
||||
<tr><td colspan=500>a<td colspan=500 id=a1>a
|
||||
<!-- This cell must span the previous two -->
|
||||
<tr><td colspan=1000 id=a2>a
|
||||
</table>
|
||||
|
||||
<table border=1>
|
||||
<tr><td colspan=1000 id=b1>a<td>a
|
||||
<!-- This cell must span only the first cell in the previous row -->
|
||||
<tr><td colspan=1001 id=b2>a
|
||||
</table>
|
||||
|
||||
<table border=1 style="float:left">
|
||||
<!-- The first column must go all the way down to the bottom -->
|
||||
<tr><td rowspan=65534 id=c1>a<td>
|
||||
<!-- We'll add another 65533 rows later -->
|
||||
</table>
|
||||
|
||||
<table border=1>
|
||||
<!-- The first column must go one cell below the bottom -->
|
||||
<tr><td rowspan=65535 id=d1>a<td>
|
||||
<!-- We'll add another 65534 rows later -->
|
||||
</table>
|
||||
|
||||
<script>
|
||||
var $ = document.querySelector.bind(document);
|
||||
|
||||
test(() => {
|
||||
assert_equals($("#a2").getBoundingClientRect().right,
|
||||
$("#a1").getBoundingClientRect().right);
|
||||
}, "colspan of 1000 must work");
|
||||
|
||||
test(() => {
|
||||
assert_equals($("#b2").getBoundingClientRect().right,
|
||||
$("#b1").getBoundingClientRect().right);
|
||||
}, "colspan of 1001 must be treated as 1000");
|
||||
|
||||
test(() => {
|
||||
var s = "";
|
||||
for (var i = 0; i < 65532; i++) {
|
||||
s += "<tr><td>";
|
||||
}
|
||||
s += "<tr><td id=c2>";
|
||||
document.querySelectorAll("table")[2].firstElementChild.innerHTML += s;
|
||||
assert_equals($("#c1").getBoundingClientRect().bottom,
|
||||
$("#c2").getBoundingClientRect().bottom);
|
||||
}, "rowspan of 65534 must work");
|
||||
|
||||
test(() => {
|
||||
var s = "";
|
||||
for (var i = 0; i < 65532; i++) {
|
||||
s += "<tr><td>";
|
||||
}
|
||||
s += "<tr><td id=d2><tr><td>a<td>";
|
||||
document.querySelectorAll("table")[3].firstElementChild.innerHTML += s;
|
||||
assert_equals($("#d1").getBoundingClientRect().bottom,
|
||||
$("#d2").getBoundingClientRect().bottom);
|
||||
}, "rowspan of 65535 must be treated as 65534");
|
||||
</script>
|
Loading…
Add table
Add a link
Reference in a new issue