Update web-platform-tests to revision 84af6c875d378944b39d895acdcfc170736b2d3d

This commit is contained in:
WPT Sync Bot 2019-07-10 10:26:06 +00:00
parent d0bd2d5e44
commit b81cdc75ce
246 changed files with 10836 additions and 1337 deletions

View file

@ -145,7 +145,7 @@ ReflectionTests.typeMap = {
"string": {
"jsType": "string",
"defaultVal": "",
"domTests": ["", " " + binaryString + " foo ", undefined, 7, 1.5, true,
"domTests": ["", " " + binaryString + " foo ", undefined, 7, 1.5, "5%", true,
false, {"test": 6}, NaN, +Infinity, -Infinity, "\0", null,
{"toString":function(){return "test-toString";}},
{"valueOf":function(){return "test-valueOf";}, toString:null}
@ -168,7 +168,7 @@ ReflectionTests.typeMap = {
"jsType": "string",
"defaultVal": "",
"domTests": ["", " foo ", "http://site.example/",
"//site.example/path???@#l", binaryString, undefined, 7, 1.5, true,
"//site.example/path???@#l", binaryString, undefined, 7, 1.5, "5%", true,
false, {"test": 6}, NaN, +Infinity, -Infinity, "\0", null,
{"toString":function(){return "test-toString";}},
{"valueOf":function(){return "test-valueOf";}, toString:null}],
@ -233,7 +233,7 @@ ReflectionTests.typeMap = {
"enum": {
"jsType": "string",
"defaultVal": "",
"domTests": ["", " " + binaryString + " foo ", undefined, 7, 1.5, true,
"domTests": ["", " " + binaryString + " foo ", undefined, 7, 1.5, "5%", true,
false, {"test": 6}, NaN, +Infinity, -Infinity, "\0", null,
{"toString":function(){return "test-toString";}},
{"valueOf":function(){return "test-valueOf";}, toString:null}]
@ -249,7 +249,7 @@ ReflectionTests.typeMap = {
"boolean": {
"jsType": "boolean",
"defaultVal": false,
"domTests": ["", " foo ", undefined, null, 7, 1.5, true, false,
"domTests": ["", " foo ", undefined, null, 7, 1.5, "5%", true, false,
{"test": 6}, NaN, +Infinity, -Infinity, "\0",
{"toString":function(){return "test-toString";}},
{"valueOf":function(){return "test-valueOf";}, toString:null}],
@ -282,7 +282,7 @@ ReflectionTests.typeMap = {
"\u20007", "\u20017", "\u20027", "\u20037", "\u20047", "\u20057",
"\u20067", "\u20077", "\u20087", "\u20097", "\u200A7", "\u202F7",
"\u30007",
undefined, 1.5, true, false, {"test": 6}, NaN, +Infinity,
undefined, 1.5, "5%", true, false, {"test": 6}, NaN, +Infinity,
-Infinity, "\0",
{toString:function() {return 2;}, valueOf: null},
{valueOf:function() {return 3;}}],
@ -321,7 +321,7 @@ ReflectionTests.typeMap = {
"\u20007", "\u20017", "\u20027", "\u20037", "\u20047", "\u20057",
"\u20067", "\u20077", "\u20087", "\u20097", "\u200A7", "\u202F7",
"\u30007",
undefined, 1.5, true, false, {"test": 6}, NaN, +Infinity,
undefined, 1.5, "5%", true, false, {"test": 6}, NaN, +Infinity,
-Infinity, "\0",
{toString:function() {return 2;}, valueOf: null},
{valueOf:function() {return 3;}}],
@ -357,7 +357,7 @@ ReflectionTests.typeMap = {
"\u20007", "\u20017", "\u20027", "\u20037", "\u20047", "\u20057",
"\u20067", "\u20077", "\u20087", "\u20097", "\u200A7", "\u202F7",
"\u30007",
" " + binaryString + " foo ", undefined, 1.5, true, false,
" " + binaryString + " foo ", undefined, 1.5, "5%", true, false,
{"test": 6}, NaN, +Infinity, -Infinity, "\0",
{toString:function() {return 2;}, valueOf: null},
{valueOf:function() {return 3;}}],
@ -399,7 +399,7 @@ ReflectionTests.typeMap = {
"\u20007", "\u20017", "\u20027", "\u20037", "\u20047", "\u20057",
"\u20067", "\u20077", "\u20087", "\u20097", "\u200A7", "\u202F7",
"\u30007",
" " + binaryString + " foo ", undefined, 1.5, true, false,
" " + binaryString + " foo ", undefined, 1.5, "5%", true, false,
{"test": 6}, NaN, +Infinity, -Infinity, "\0",
{toString:function() {return 2;}, valueOf: null},
{valueOf:function() {return 3;}}],
@ -439,7 +439,7 @@ ReflectionTests.typeMap = {
"\u20007", "\u20017", "\u20027", "\u20037", "\u20047", "\u20057",
"\u20067", "\u20077", "\u20087", "\u20097", "\u200A7", "\u202F7",
"\u30007",
" " + binaryString + " foo ", undefined, 1.5, true, false,
" " + binaryString + " foo ", undefined, 1.5, "5%", true, false,
{"test": 6}, NaN, +Infinity, -Infinity, "\0",
{toString:function() {return 2;}, valueOf: null},
{valueOf:function() {return 3;}}],
@ -478,7 +478,7 @@ ReflectionTests.typeMap = {
"\u20007", "\u20017", "\u20027", "\u20037", "\u20047", "\u20057",
"\u20067", "\u20077", "\u20087", "\u20097", "\u200A7", "\u202F7",
"\u30007",
" " + binaryString + " foo ", undefined, 1.5, true, false,
" " + binaryString + " foo ", undefined, 1.5, "5%", true, false,
{"test": 6}, NaN, +Infinity, -Infinity, "\0",
{toString:function() {return 2;}, valueOf: null},
{valueOf:function() {return 3;}}],
@ -519,7 +519,7 @@ ReflectionTests.typeMap = {
"\u20007", "\u20017", "\u20027", "\u20037", "\u20047", "\u20057",
"\u20067", "\u20077", "\u20087", "\u20097", "\u200A7", "\u202F7",
"\u30007",
" " + binaryString + " foo ", undefined, 1.5, true, false,
" " + binaryString + " foo ", undefined, 1.5, "5%", true, false,
{"test": 6}, NaN, +Infinity, -Infinity, "\0",
{toString:function() {return 2;}, valueOf: null},
{valueOf:function() {return 3;}}],
@ -532,7 +532,7 @@ ReflectionTests.typeMap = {
null, null, null, null, null, null,
null,
// End leading whitespace tests
null, null, 1.5, null, null,
null, null, 1.5, 5, null, null,
null, null, null, null, null,
2, 3],
// I checked that ES ToString is well-defined for all of these (I

View file

@ -1 +0,0 @@
onmessage = function (ev) { postMessage(ev.data); }

View file

@ -5,6 +5,7 @@
<link rel="author" title="Domenic Denicola" href="mailto:d@domenic.me">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="/common/utils.js"></script>
<script src="resources/test-sab.js"></script>
<div id="log"></div>
@ -13,9 +14,10 @@
"use strict";
async_test(t => {
const testId = token();
const sab = new SharedArrayBuffer(1);
window.addEventListener("message", t.step_func(({ data }) => {
if (data.testId !== 1) {
if (data.testId !== testId) {
return;
}
@ -24,15 +26,16 @@ async_test(t => {
t.done();
}));
window.postMessage({ sab, testId: 1 }, "*");
window.postMessage({ testId, sab }, "*");
}, "postMessaging to this window does not give back the same SharedArrayBuffer (but does use the same backing block)");
async_test(t => {
const testId = token();
const sab = new SharedArrayBuffer();
const worker = new Worker("resources/echo-worker.js");
const worker = new Worker("../resources/echo-worker.js");
worker.addEventListener("message", t.step_func(({ data }) => {
if (data.testId !== 2) {
if (data.testId !== testId) {
return;
}
@ -40,13 +43,14 @@ async_test(t => {
t.done();
}));
worker.postMessage({ testId: 2, sab });
worker.postMessage({ testId, sab });
}, "postMessaging to a worker and back does not give back the same SharedArrayBuffer");
async_test(t => {
const testId = token();
const sab = new SharedArrayBuffer();
window.addEventListener("message", t.step_func(({ data }) => {
if (data.testId !== 3) {
if (data.testId !== testId) {
return;
}
@ -56,9 +60,9 @@ async_test(t => {
const iframe = document.createElement("iframe");
iframe.onload = t.step_func(() => {
iframe.contentWindow.postMessage({ testId: 3, sab }, "*");
iframe.contentWindow.postMessage({ testId, sab }, "*");
});
iframe.src = "resources/echo-iframe.html";
iframe.src = "../resources/echo-iframe.html";
document.body.appendChild(iframe);
}, "postMessaging to an iframe and back does not give back the same SharedArrayBuffer");
</script>

View file

@ -17,7 +17,7 @@ test(() => {
test(() => {
const sab = new SharedArrayBuffer();
const worker = new Worker("resources/echo-worker.js");
const worker = new Worker("../resources/echo-worker.js");
assert_throws("DataCloneError", () => worker.postMessage(sab, [sab]));
assert_throws("DataCloneError", () => worker.postMessage("test", [sab]));
}, "Trying to transfer a SharedArrayBuffer to a worker throws");

View file

@ -0,0 +1,85 @@
// META: script=/common/utils.js
// .stack properties on errors are unspecified, but are present in most
// browsers, most of the time. https://github.com/tc39/proposal-error-stacks/ tracks standardizing them.
// Tests will pass automatically if the .stack property isn't present.
stackTests(() => {
return new Error('some message');
}, 'page-created Error');
stackTests(() => {
return new DOMException('InvalidStateError', 'some message');
}, 'page-created DOMException');
stackTests(() => {
try {
Object.defineProperty();
} catch (e) {
return e;
}
}, 'JS-engine-created TypeError');
stackTests(() => {
try {
HTMLParagraphElement.prototype.align;
} catch (e) {
return e;
}
}, 'web API-created TypeError');
stackTests(() => {
try {
document.createElement('');
} catch (e) {
return e;
}
}, 'web API-created DOMException');
function stackTests(errorFactory, description) {
async_test(t => {
const error = errorFactory();
const originalStack = error.stack;
if (!originalStack) {
t.done();
return;
}
const worker = new Worker('resources/echo-worker.js');
worker.onmessage = t.step_func_done(e => {
assert_equals(e.data.stack, originalStack);
});
worker.postMessage(error);
}, description + ' (worker)');
async_test(t => {
const thisTestId = token();
const error = errorFactory();
const originalStack = error.stack;
if (!originalStack) {
t.done();
return;
}
const iframe = document.createElement('iframe');
window.addEventListener('message', t.step_func(e => {
if (e.data.testId === thisTestId) {
assert_equals(e.data.error.stack, originalStack);
t.done();
}
}));
iframe.onload = t.step_func(() => {
iframe.contentWindow.postMessage({ error, testId: thisTestId }, "*");
});
const crossSiteEchoIFrame = new URL('resources/echo-iframe.html', location.href);
crossSiteEchoIFrame.hostname = '{{hosts[alt][www1]}}';
iframe.src = crossSiteEchoIFrame;
document.body.append(iframe);
}, description + ' (cross-site iframe)');
}

View file

@ -23,7 +23,7 @@
//the worker is used for each test in sequence
//worker's callback will be set for each test
//worker's internal onmessage echoes the data back to this thread through postMessage
worker = new Worker("./echo.js");
worker = new Worker("./resources/echo-worker.js");
testCollection = [
function() {
var t = async_test("Primitive BigInt is cloned");

View file

@ -9,6 +9,7 @@
</head>
<body>
<div id="log"></div>
<iframe></iframe> <!-- used for grabbing an URIError from another realm -->
<script type="text/javascript">
var worker;
@ -18,7 +19,7 @@
//the worker is used for each test in sequence
//worker's callback will be set for each test
//worker's internal onmessage echoes the data back to this thread through postMessage
worker = new Worker("./echo.js");
worker = new Worker("./resources/echo-worker.js");
testCollection = [
function() {
var t = async_test("Primitive string is cloned");
@ -367,7 +368,243 @@
assert_throws('DATA_CLONE_ERR', function() {worker.postMessage(document)});
});
t.done();
}
},
function() {
var t = async_test("Empty Error objects can be cloned");
t.id = 27;
worker.onmessage = t.step_func_done(function(e) {
assert_equals(Object.getPrototypeOf(e.data), Error.prototype, "Checking prototype");
assert_equals(e.data.constructor, Error, "Checking constructor");
assert_equals(e.data.name, "Error", "Checking name");
assert_false(e.data.hasOwnProperty("message"), "Checking message");
assert_equals(e.data.foo, undefined, "Checking custom property");
});
t.step(function() {
const error = Error();
assert_false(error.hasOwnProperty("message"), "Checking message on the source realm");
worker.postMessage(error);
});
},
function() {
var t = async_test("Error objects can be cloned");
t.id = 28;
worker.onmessage = t.step_func_done(function(e) {
assert_equals(Object.getPrototypeOf(e.data), Error.prototype, "Checking prototype");
assert_equals(e.data.constructor, Error, "Checking constructor");
assert_equals(e.data.name, "Error", "Checking name");
assert_equals(e.data.message, "some message", "Checking message");
assert_equals(e.data.foo, undefined, "Checking custom property");
});
t.step(function() {
const error = Error("some message");
error.foo = "bar";
worker.postMessage(error);
});
},
function() {
var t = async_test("EvalError objects can be cloned");
t.id = 29;
worker.onmessage = t.step_func_done(function(e) {
assert_equals(Object.getPrototypeOf(e.data), EvalError.prototype, "Checking prototype");
assert_equals(e.data.constructor, EvalError, "Checking constructor");
assert_equals(e.data.name, "EvalError", "Checking name");
assert_equals(e.data.message, "some message", "Checking message");
assert_equals(e.data.foo, undefined, "Checking custom property");
});
t.step(function() {
const error = EvalError("some message");
error.foo = "bar";
worker.postMessage(error);
});
},
function() {
var t = async_test("RangeError objects can be cloned");
t.id = 30;
worker.onmessage = t.step_func_done(function(e) {
assert_equals(Object.getPrototypeOf(e.data), RangeError.prototype, "Checking prototype");
assert_equals(e.data.constructor, RangeError, "Checking constructor");
assert_equals(e.data.name, "RangeError", "Checking name");
assert_equals(e.data.message, "some message", "Checking message");
assert_equals(e.data.foo, undefined, "Checking custom property");
});
t.step(function() {
const error = RangeError("some message");
error.foo = "bar";
worker.postMessage(error);
});
},
function() {
var t = async_test("ReferenceError objects can be cloned");
t.id = 31;
worker.onmessage = t.step_func_done(function(e) {
assert_equals(Object.getPrototypeOf(e.data), ReferenceError.prototype, "Checking prototype");
assert_equals(e.data.constructor, ReferenceError, "Checking constructor");
assert_equals(e.data.name, "ReferenceError", "Checking name");
assert_equals(e.data.message, "some message", "Checking message");
assert_equals(e.data.foo, undefined, "Checking custom property");
});
t.step(function() {
const error = ReferenceError("some message");
error.foo = "bar";
worker.postMessage(error);
});
},
function() {
var t = async_test("SyntaxError objects can be cloned");
t.id = 32;
worker.onmessage = t.step_func_done(function(e) {
assert_equals(Object.getPrototypeOf(e.data), SyntaxError.prototype, "Checking prototype");
assert_equals(e.data.constructor, SyntaxError, "Checking constructor");
assert_equals(e.data.name, "SyntaxError", "Checking name");
assert_equals(e.data.message, "some message", "Checking message");
assert_equals(e.data.foo, undefined, "Checking custom property");
});
t.step(function() {
const error = SyntaxError("some message");
error.foo = "bar";
worker.postMessage(error);
});
},
function() {
var t = async_test("TypeError objects can be cloned");
t.id = 33;
worker.onmessage = t.step_func_done(function(e) {
assert_equals(Object.getPrototypeOf(e.data), TypeError.prototype, "Checking prototype");
assert_equals(e.data.constructor, TypeError, "Checking constructor");
assert_equals(e.data.name, "TypeError", "Checking name");
assert_equals(e.data.message, "some message", "Checking message");
assert_equals(e.data.foo, undefined, "Checking custom property");
});
t.step(function() {
const error = TypeError("some message");
error.foo = "bar";
worker.postMessage(error);
});
},
function() {
var t = async_test("URIError objects can be cloned");
t.id = 34;
worker.onmessage = t.step_func_done(function(e) {
assert_equals(Object.getPrototypeOf(e.data), URIError.prototype, "Checking prototype");
assert_equals(e.data.constructor, URIError, "Checking constructor");
assert_equals(e.data.name, "URIError", "Checking name");
assert_equals(e.data.message, "some message", "Checking message");
assert_equals(e.data.foo, undefined, "Checking custom property");
});
t.step(function() {
const error = URIError("some message");
error.foo = "bar";
worker.postMessage(error);
});
},
function() {
var t = async_test("URIError objects from other realms are treated as Error");
t.id = 35;
worker.onmessage = t.step_func_done(function(e) {
assert_equals(Object.getPrototypeOf(e.data), Error.prototype, "Checking prototype");
assert_equals(e.data.constructor, Error, "Checking constructor");
assert_equals(e.data.name, "Error", "Checking name");
assert_equals(e.data.message, "some message", "Checking message");
assert_equals(e.data.foo, undefined, "Checking custom property");
});
t.step(function() {
const error = frames[0].URIError("some message");
assert_equals(Object.getPrototypeOf(error), frames[0].prototype, "Checking prototype before cloning");
assert_equals(error.constructor, frames[0].URIError, "Checking constructor before cloning");
assert_equals(error.name, "URIError", "Checking name before cloning");
error.foo = "bar";
worker.postMessage(error);
});
},
function() {
var t = async_test("Cloning a modified Error");
t.id = 36;
worker.onmessage = t.step_func_done(function(e) {
assert_equals(Object.getPrototypeOf(e.data), SyntaxError.prototype, "Checking prototype");
assert_equals(e.data.constructor, SyntaxError, "Checking constructor");
assert_equals(e.data.name, "SyntaxError", "Checking name");
assert_equals(e.data.message, "another message", "Checking message");
assert_equals(e.data.foo, undefined, "Checking custom property");
});
t.step(function() {
const error = URIError("some message");
Object.setPrototypeOf(error, SyntaxError.prototype);
error.message = {toString: () => "another message" }
error.constructor = RangeError;
error.name = "TypeError";
error.foo = "bar";
worker.postMessage(error);
});
},
function() {
var t = async_test("Error.message: getter is ignored when cloning");
t.id = 37;
worker.onmessage = t.step_func_done(function(e) {
assert_equals(Object.getPrototypeOf(e.data), Error.prototype, "Checking prototype");
assert_equals(e.data.constructor, Error, "Checking constructor");
assert_equals(e.data.name, "Error", "Checking name");
assert_false(e.data.hasOwnProperty("message"), "Checking message");
assert_equals(e.data.foo, undefined, "Checking custom property");
});
t.step(function() {
const error = Error();
Object.defineProperty(error, "message", { get: () => "hello" });
assert_equals(error.message, "hello", "Checking message on the source realm");
worker.postMessage(error);
});
},
function() {
var t = async_test("Error.message: undefined property is stringified");
t.id = 38;
worker.onmessage = t.step_func_done(function(e) {
assert_equals(Object.getPrototypeOf(e.data), Error.prototype, "Checking prototype");
assert_equals(e.data.constructor, Error, "Checking constructor");
assert_equals(e.data.name, "Error", "Checking name");
assert_equals(e.data.message, "undefined", "Checking message");
assert_equals(e.data.foo, undefined, "Checking custom property");
});
t.step(function() {
const error = Error();
error.message = undefined;
assert_equals(error.message, undefined, "Checking message on the source realm");
worker.postMessage(error);
});
},
function() {
var t = async_test("DOMException objects can be cloned");
t.id = 39;
worker.onmessage = t.step_func_done(function(e) {
assert_equals(Object.getPrototypeOf(e.data), DOMException.prototype, "Checking prototype");
assert_equals(e.data.constructor, DOMException, "Checking constructor");
assert_equals(e.data.name, "IndexSizeError", "Checking name");
assert_equals(e.data.message, "some message", "Checking message");
assert_equals(e.data.code, DOMException.INDEX_SIZE_ERR, "Checking code");
assert_equals(e.data.foo, undefined, "Checking custom property");
});
t.step(function() {
const error = new DOMException("some message", "IndexSizeError");
worker.postMessage(error);
});
},
function() {
var t = async_test("DOMException objects created by the UA can be cloned");
t.id = 40;
worker.onmessage = t.step_func_done(function(e) {
assert_equals(Object.getPrototypeOf(e.data), DOMException.prototype, "Checking prototype");
assert_equals(e.data.constructor, DOMException, "Checking constructor");
assert_equals(e.data.code, DOMException.DATA_CLONE_ERR, "Checking code");
assert_equals(e.data.name, "DataCloneError", "Checking name");
});
t.step(function() {
try {
worker.postMessage(window);
} catch (error) {
worker.postMessage(error);
return;
}
assert_unreached("Window must not be clonable");
});
},
];
}, {explicit_done:true});

View file

@ -0,0 +1,180 @@
<!doctype html>
<meta charset=utf-8>
<title>Test handling of attributes that map to dimension properties</title>
<link rel="help"
href="https://html.spec.whatwg.org/multipage/rendering.html#maps-to-the-dimension-property">
<link rel="help"
href="https://html.spec.whatwg.org/multipage/rendering.html#maps-to-the-dimension-property-(ignoring-zero)">
<script src=/resources/testharness.js></script>
<script src=/resources/testharnessreport.js></script>
<body>
<!-- We need a place to put our elements so they're bound to a document and
have computed style, but we don't want percentages resolved to lengths,
so need to make sure they have no CSS boxes -->
<div id="container" style="display: none"></div>
<script>
/*
* This test tests
*
* https://html.spec.whatwg.org/multipage/rendering.html#maps-to-the-dimension-property
* and
* https://html.spec.whatwg.org/multipage/rendering.html#maps-to-the-dimension-property-(ignoring-zero)
* for various elements and various values.
*/
/*
* Array of input/output pairs. The input is the string to use as the
* attribute value. The output is the string expected as the computed style
* for the relevant CSS property.
*/
const valid_values = [
// Valid values
[ "200", "200px" ],
[ "1007", "1007px" ],
[ " 00523 ", "523px" ],
[ "200.25", "200.25px" ],
[ "200.", "200px" ],
[ "+200", "200px" ],
[ "200in", "200px" ],
[ "200.25in", "200.25px" ],
[ " +200in ", "200px" ],
[ " +200.25in ", "200.25px" ],
[ "200 %", "200px" ],
[ "200 abc", "200px" ],
[ "200%", "200%" ],
[ "200%abc", "200%" ],
[ "+200%", "200%" ],
[ "200.25%", "200.25%" ],
// https://github.com/whatwg/html/issues/4736 tracks the fact that "200.%"
// should probably be mapped as "200%", not "200px".
[ "200.%", "200px" ],
[ " +200.25% ", "200.25%" ],
[ " +200.25%abc", "200.25%" ],
];
/*
* Values that are only valid for the not-ignoring-zero case.
*/
const zero_values = [
[ "0", "0px" ],
[ "+0", "0px" ],
[ "0%", "0%" ],
[ "+0%", "0%" ],
[ "0px", "0px" ],
];
/*
* Array of invalid values. These should lead to the default value of the
* relevant CSS property.
*/
const invalid_values = [
"-0",
"-0%",
"-200",
"-200px",
" -200",
"+-200",
"-+200",
"-200%"
];
const valid_values_with_0 =
valid_values.concat(zero_values);
const invalid_values_with_0 =
invalid_values.concat(zero_values.map((v) => v[0]));
function newElem(name) {
return () => document.createElement(name);
}
function newImageInput() {
return () => {
var elem = newElem("input")();
elem.type = "image";
return elem;
}
}
/*
* Array of tests. Each test consists of the following information:
*
* 1) An element creation function.
* 2) The name of the attribute to set (and CSS property to get).
* 3) A boolean indicating whether 0 is a valid value for the dimension
* attribute.
*/
const tests = [
[ newElem("hr"), "width", true ],
[ newElem("iframe"), "width", true ],
[ newElem("iframe"), "height", true ],
[ newImageInput(), "width", true ],
[ newImageInput(), "height", true ],
[ newElem("marquee"), "width", true ],
[ newElem("marquee"), "height", true ],
[ newElem("video"), "width", true ],
[ newElem("video"), "height", true ],
[ newElem("object"), "width", true ],
[ newElem("object"), "height", true ],
[ newElem("embed"), "width", true ],
[ newElem("embed"), "height", true ],
[ newElem("img"), "width", true ],
[ newElem("img"), "height", true ],
[ newElem("td"), "width", false ],
[ newElem("td"), "height", false ],
// https://github.com/whatwg/html/issues/4715 tracks the fact that for
// <table width> and <table height> the "0 is valid" boolean should probably
// be true.
[ newElem("table"), "width", false ],
[ newElem("table"), "height", false ],
// https://github.com/whatwg/html/issues/4716 tracks the fact that for the
// <tr height> case that "0 is valid" boolean should probably be true.
[ newElem("tr"), "height", false ],
// https://github.com/whatwg/html/issues/4717 tracks the fact that for the
// <col width> case that "0 is valid" boolean should probably be true.
[ newElem("col"), "width", false ],
];
function style(element) {
return element.ownerDocument.defaultView.getComputedStyle(element);
}
const container = document.getElementById("container");
for (let [ctor, attr, zero_allowed] of tests) {
let valid, invalid;
if (zero_allowed) {
valid = valid_values_with_0;
invalid = invalid_values;
} else {
valid = valid_values;
invalid = invalid_values_with_0;
}
for (let [value, result] of valid) {
let elem = ctor();
test(function() {
this.add_cleanup(() => elem.remove());
elem.setAttribute(attr, value);
assert_equals(elem.getAttribute(attr), value);
container.appendChild(elem);
assert_equals(style(elem)[attr], result);
}, `<${elem.localName} ${attr}="${value}"> mapping`);
}
let default_elem = ctor();
container.appendChild(default_elem);
let defaultVal = style(default_elem)[attr];
default_elem.remove();
for (let value of invalid) {
let elem = ctor();
test(function() {
this.add_cleanup(() => elem.remove());
elem.setAttribute(attr, value);
assert_equals(elem.getAttribute(attr), value);
container.appendChild(elem);
assert_equals(style(elem)[attr], defaultVal);
}, `<${elem.localName} ${attr}="${value}"> mapping`);
}
}
</script>
</body>

View file

@ -0,0 +1,126 @@
<!doctype html>
<meta charset=utf-8>
<title>Test handling of attributes that map to pixel length properties</title>
<link rel="help"
href="https://html.spec.whatwg.org/multipage/rendering.html#maps-to-the-pixel-length-property">
<script src=/resources/testharness.js></script>
<script src=/resources/testharnessreport.js></script>
<body>
<script>
/*
* This test tests
* https://html.spec.whatwg.org/multipage/rendering.html#maps-to-the-pixel-length-property
* for various elements and various values.
*/
/*
* Array of input/output pairs. The input is the string to use as the
* attribute value. The output is the string expected as the computed style
* for the relevant CSS property.
*/
const valid_values = [
[ "200", "200px" ],
[ "1007", "1007px" ],
[ " 00523 ", "523px" ],
[ "200.", "200px" ],
[ "200.25", "200px" ],
[ "200.7", "200px" ],
[ "0", "0px" ],
[ "-0", "0px" ],
[ "+0", "0px" ],
[ "+200", "200px" ],
[ "200in", "200px" ],
[ "200.25in", "200px" ],
[ " +200in ", "200px" ],
[ "200%", "200px" ],
[ "200.%", "200px" ],
[ "200.25%", "200px" ],
];
/*
* Array of invalid values. These should lead to the default value of the
* relevant CSS property.
*/
const invalid_values = [
"-200",
"-200px",
" -200",
"+-200",
"-+200",
];
/*
* Array of tests. Each test consists of the following information:
*
* 1) A function to call to create the element to test. This returns a
* 3-element array: The element to set the attribute on, the element to
* compute style on, and a cleanup function to call when done.
* 2) The name of the attribute to set.
* 3) The name of the computed style property to get.
* 4) An element that can be used to determine the fallback style value for
* invalid values.
*/
const tests = [
[ createIframe, "marginwidth", "marginLeft", document.body ],
[ createIframe, "marginwidth", "marginRight", document.body ],
[ createIframe, "marginheight", "marginTop", document.body ],
[ createIframe, "marginheight", "marginBottom", document.body ],
[ createFrame, "marginwidth", "marginLeft", document.body ],
[ createFrame, "marginwidth", "marginRight", document.body ],
[ createFrame, "marginheight", "marginTop", document.body ],
[ createFrame, "marginheight", "marginBottom", document.body ],
];
function createIframe() {
let ifr = document.createElement("iframe");
document.body.appendChild(ifr);
return [ ifr, ifr.contentDocument.body, () => ifr.remove() ];
}
function createFrame() {
// We need to create a separate iframe to put our frameset into.
let ifr = document.createElement("iframe");
document.body.appendChild(ifr);
let doc = ifr.contentDocument;
let root = doc.documentElement;
while (root.firstChild) {
root.firstChild.remove();
}
let frameset = doc.createElement("frameset");
frameset.setAttribute("rows", "*");
frameset.setAttribute("cols", "*");
let frame = doc.createElement("frame");
frameset.appendChild(frame);
root.appendChild(frameset);
return [ frame, frame.contentDocument.body, () => ifr.remove() ];
}
function style(element) {
return element.ownerDocument.defaultView.getComputedStyle(element);
}
for (let [setup, attr, prop, default_elem] of tests) {
for (let [value, result] of valid_values) {
let [ attr_elem, prop_elem, cleanup ] = setup();
test(function() {
this.add_cleanup(cleanup);
attr_elem.setAttribute(attr, value);
assert_equals(attr_elem.getAttribute(attr), value);
assert_equals(style(prop_elem)[prop], result);
}, `<${attr_elem.localName} ${attr}="${value}"> mapping to ${prop}`);
}
let defaultVal = style(default_elem)[prop];
for (let value of invalid_values) {
let [ attr_elem, prop_elem, cleanup ] = setup();
test(function() {
this.add_cleanup(cleanup);
attr_elem.setAttribute(attr, value);
assert_equals(attr_elem.getAttribute(attr), value);
assert_equals(style(prop_elem)[prop], defaultVal);
}, `<${attr_elem.localName} ${attr}="${value}"> mapping to ${prop}`);
}
}
</script>
</body>

View file

@ -0,0 +1,27 @@
<!doctype html>
<title>Image width and height attributes are used to infer aspect-ratio</title>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<style>
img {
width: 100%;
max-width: 100px;
height: auto;
}
</style>
<img src=broken width=100 height=125>
<img src="/images/green.png" width=100 height=125>
<img src="/images/green.png">
<script>
let t = async_test("Image width and height attributes are used to infer aspect-ratio");
function assert_ratio(img, expected) {
let epsilon = 0.001;
assert_approx_equals(parseInt(getComputedStyle(img).width, 10) / parseInt(getComputedStyle(img).height, 10), expected, epsilon);
}
onload = t.step_func_done(function() {
let images = document.querySelectorAll("img");
assert_ratio(images[0], 0.8);
assert_ratio(images[1], 0.8);
assert_ratio(images[2], 2.0); // 2.0 is the original aspect ratio of green.png
});
</script>

View file

@ -5,7 +5,7 @@
<script src=/resources/testharnessreport.js></script>
<div id=log></div>
<script>
var canvas, context;
var canvas, context, path2d;
setup(function() {
canvas = document.createElement("canvas");
context = canvas.getContext('2d');