summaryrefslogtreecommitdiffstats
path: root/testing/web-platform/tests/html/rendering/replaced-elements
diff options
context:
space:
mode:
Diffstat (limited to 'testing/web-platform/tests/html/rendering/replaced-elements')
-rw-r--r--testing/web-platform/tests/html/rendering/replaced-elements/attributes-for-embedded-content-and-images/align.html59
-rw-r--r--testing/web-platform/tests/html/rendering/replaced-elements/attributes-for-embedded-content-and-images/canvas-aspect-ratio.html52
-rw-r--r--testing/web-platform/tests/html/rendering/replaced-elements/attributes-for-embedded-content-and-images/content-aspect-ratio.html25
-rw-r--r--testing/web-platform/tests/html/rendering/replaced-elements/attributes-for-embedded-content-and-images/embedded-and-images-presentational-hints-ascii-case-insensitive.html46
-rw-r--r--testing/web-platform/tests/html/rendering/replaced-elements/attributes-for-embedded-content-and-images/img-alt-crash-001.html15
-rw-r--r--testing/web-platform/tests/html/rendering/replaced-elements/attributes-for-embedded-content-and-images/img-aspect-ratio-lazy.html36
-rw-r--r--testing/web-platform/tests/html/rendering/replaced-elements/attributes-for-embedded-content-and-images/img-aspect-ratio.html120
-rw-r--r--testing/web-platform/tests/html/rendering/replaced-elements/attributes-for-embedded-content-and-images/img-dim-ref.html11
-rw-r--r--testing/web-platform/tests/html/rendering/replaced-elements/attributes-for-embedded-content-and-images/img-dim.html12
-rw-r--r--testing/web-platform/tests/html/rendering/replaced-elements/attributes-for-embedded-content-and-images/img-empty-alt-replaced.html23
-rw-r--r--testing/web-platform/tests/html/rendering/replaced-elements/attributes-for-embedded-content-and-images/img-no-alt-replaced.html30
-rw-r--r--testing/web-platform/tests/html/rendering/replaced-elements/attributes-for-embedded-content-and-images/img-replaced-box-while-loading.html29
-rw-r--r--testing/web-platform/tests/html/rendering/replaced-elements/attributes-for-embedded-content-and-images/img-title-only-w-sizing.html25
-rw-r--r--testing/web-platform/tests/html/rendering/replaced-elements/attributes-for-embedded-content-and-images/img_border-ref.xhtml9
-rw-r--r--testing/web-platform/tests/html/rendering/replaced-elements/attributes-for-embedded-content-and-images/img_border_percent.xhtml10
-rw-r--r--testing/web-platform/tests/html/rendering/replaced-elements/attributes-for-embedded-content-and-images/input-align-right-1.html3
-rw-r--r--testing/web-platform/tests/html/rendering/replaced-elements/attributes-for-embedded-content-and-images/input-align-right-2.html3
-rw-r--r--testing/web-platform/tests/html/rendering/replaced-elements/attributes-for-embedded-content-and-images/input-align-right-ref.html2
-rw-r--r--testing/web-platform/tests/html/rendering/replaced-elements/attributes-for-embedded-content-and-images/input-image-content-crash.html15
-rw-r--r--testing/web-platform/tests/html/rendering/replaced-elements/attributes-for-embedded-content-and-images/input-image-inline-alt-ref.html18
-rw-r--r--testing/web-platform/tests/html/rendering/replaced-elements/attributes-for-embedded-content-and-images/input-image-inline-alt.html23
-rw-r--r--testing/web-platform/tests/html/rendering/replaced-elements/attributes-for-embedded-content-and-images/input-type-change-from-image-1-ref.html2
-rw-r--r--testing/web-platform/tests/html/rendering/replaced-elements/attributes-for-embedded-content-and-images/input-type-change-from-image-1.html10
-rw-r--r--testing/web-platform/tests/html/rendering/replaced-elements/attributes-for-embedded-content-and-images/number-placeholder-right-aligned-ref.html8
-rw-r--r--testing/web-platform/tests/html/rendering/replaced-elements/attributes-for-embedded-content-and-images/number-placeholder-right-aligned.html16
-rw-r--r--testing/web-platform/tests/html/rendering/replaced-elements/attributes-for-embedded-content-and-images/object_border-ref.xhtml8
-rw-r--r--testing/web-platform/tests/html/rendering/replaced-elements/attributes-for-embedded-content-and-images/object_border_perc.xhtml9
-rw-r--r--testing/web-platform/tests/html/rendering/replaced-elements/attributes-for-embedded-content-and-images/object_border_pixel.xhtml9
-rw-r--r--testing/web-platform/tests/html/rendering/replaced-elements/attributes-for-embedded-content-and-images/picture-aspect-ratio.html242
-rw-r--r--testing/web-platform/tests/html/rendering/replaced-elements/attributes-for-embedded-content-and-images/resources/aspect-ratio.js14
-rw-r--r--testing/web-platform/tests/html/rendering/replaced-elements/attributes-for-embedded-content-and-images/video-aspect-ratio.html72
-rw-r--r--testing/web-platform/tests/html/rendering/replaced-elements/attributes-for-embedded-content-and-images/video-intrinsic-width-height.html41
-rw-r--r--testing/web-platform/tests/html/rendering/replaced-elements/embedded-content-rendering-rules/audio-controls-001.html7
-rw-r--r--testing/web-platform/tests/html/rendering/replaced-elements/embedded-content-rendering-rules/audio-controls-002.html12
-rw-r--r--testing/web-platform/tests/html/rendering/replaced-elements/embedded-content-rendering-rules/audio-without-controls.html11
-rw-r--r--testing/web-platform/tests/html/rendering/replaced-elements/embedded-content-rendering-rules/canvas-fallback-ref.html4
-rw-r--r--testing/web-platform/tests/html/rendering/replaced-elements/embedded-content-rendering-rules/canvas-fallback.html26
-rw-r--r--testing/web-platform/tests/html/rendering/replaced-elements/embedded-content-rendering-rules/canvas-update-with-border-object-fit-ref.html4
-rw-r--r--testing/web-platform/tests/html/rendering/replaced-elements/embedded-content-rendering-rules/canvas-update-with-border-object-fit.html31
-rw-r--r--testing/web-platform/tests/html/rendering/replaced-elements/embedded-content-rendering-rules/canvas_scale.html23
-rw-r--r--testing/web-platform/tests/html/rendering/replaced-elements/embedded-content-rendering-rules/canvas_scale_ref.html14
-rw-r--r--testing/web-platform/tests/html/rendering/replaced-elements/embedded-content-rendering-rules/canvas_without_context_a.html15
-rw-r--r--testing/web-platform/tests/html/rendering/replaced-elements/embedded-content-rendering-rules/canvas_without_context_ref.html14
-rw-r--r--testing/web-platform/tests/html/rendering/replaced-elements/embedded-content/audio-controls-intrinsic-size.html25
-rw-r--r--testing/web-platform/tests/html/rendering/replaced-elements/embedded-content/change-src-while-not-displayed-ref.html2
-rw-r--r--testing/web-platform/tests/html/rendering/replaced-elements/embedded-content/change-src-while-not-displayed.html21
-rw-r--r--testing/web-platform/tests/html/rendering/replaced-elements/embedded-content/cross-domain-iframe-in-multicol.sub-ref.html3
-rw-r--r--testing/web-platform/tests/html/rendering/replaced-elements/embedded-content/cross-domain-iframe-in-multicol.sub.html21
-rw-r--r--testing/web-platform/tests/html/rendering/replaced-elements/embedded-content/cross-domain-iframe.sub-ref.html3
-rw-r--r--testing/web-platform/tests/html/rendering/replaced-elements/embedded-content/cross-domain-iframe.sub.html17
-rw-r--r--testing/web-platform/tests/html/rendering/replaced-elements/embedded-content/object-fallback-text-decoration-ref.html3
-rw-r--r--testing/web-platform/tests/html/rendering/replaced-elements/embedded-content/object-fallback-text-decoration.html9
-rw-r--r--testing/web-platform/tests/html/rendering/replaced-elements/embedded-content/resources/tall.html6
-rw-r--r--testing/web-platform/tests/html/rendering/replaced-elements/embedded-content/tall-cross-domain-iframe-in-scrolled.sub-ref.html9
-rw-r--r--testing/web-platform/tests/html/rendering/replaced-elements/embedded-content/tall-cross-domain-iframe-in-scrolled.sub.html20
-rw-r--r--testing/web-platform/tests/html/rendering/replaced-elements/embedded-content/video-controls-vertical-writing-mode-ref.html4
-rw-r--r--testing/web-platform/tests/html/rendering/replaced-elements/embedded-content/video-controls-vertical-writing-mode.html8
-rw-r--r--testing/web-platform/tests/html/rendering/replaced-elements/images/blocked-by-csp-ref.html5
-rw-r--r--testing/web-platform/tests/html/rendering/replaced-elements/images/blocked-by-csp.html8
-rw-r--r--testing/web-platform/tests/html/rendering/replaced-elements/images/img-sizes-auto.html53
-rw-r--r--testing/web-platform/tests/html/rendering/replaced-elements/images/input-image-content-ref.html7
-rw-r--r--testing/web-platform/tests/html/rendering/replaced-elements/images/input-image-content.html14
-rw-r--r--testing/web-platform/tests/html/rendering/replaced-elements/images/revoked-blob-print-ref.html3
-rw-r--r--testing/web-platform/tests/html/rendering/replaced-elements/images/revoked-blob-print.html24
-rw-r--r--testing/web-platform/tests/html/rendering/replaced-elements/images/space-ref.html13
-rw-r--r--testing/web-platform/tests/html/rendering/replaced-elements/images/space.html14
-rw-r--r--testing/web-platform/tests/html/rendering/replaced-elements/resources/svg-sizing.js418
-rw-r--r--testing/web-platform/tests/html/rendering/replaced-elements/svg-embedded-sizing/svg-embedded-sizing.js96
-rw-r--r--testing/web-platform/tests/html/rendering/replaced-elements/svg-embedded-sizing/svg-in-iframe-auto.html33
-rw-r--r--testing/web-platform/tests/html/rendering/replaced-elements/svg-embedded-sizing/svg-in-iframe-fixed.html33
-rw-r--r--testing/web-platform/tests/html/rendering/replaced-elements/svg-embedded-sizing/svg-in-iframe-percentage.html33
-rw-r--r--testing/web-platform/tests/html/rendering/replaced-elements/svg-embedded-sizing/svg-in-img-auto.html33
-rw-r--r--testing/web-platform/tests/html/rendering/replaced-elements/svg-embedded-sizing/svg-in-img-fixed.html33
-rw-r--r--testing/web-platform/tests/html/rendering/replaced-elements/svg-embedded-sizing/svg-in-img-percentage.html33
-rw-r--r--testing/web-platform/tests/html/rendering/replaced-elements/svg-embedded-sizing/svg-in-object-auto.html33
-rw-r--r--testing/web-platform/tests/html/rendering/replaced-elements/svg-embedded-sizing/svg-in-object-fixed.html33
-rw-r--r--testing/web-platform/tests/html/rendering/replaced-elements/svg-embedded-sizing/svg-in-object-percentage.html33
-rw-r--r--testing/web-platform/tests/html/rendering/replaced-elements/svg-inline-sizing/svg-inline.html29
-rw-r--r--testing/web-platform/tests/html/rendering/replaced-elements/svg-inline-sizing/svg-inline.js79
-rw-r--r--testing/web-platform/tests/html/rendering/replaced-elements/the-option-element/option-with-br-ref.html21
-rw-r--r--testing/web-platform/tests/html/rendering/replaced-elements/the-option-element/option-with-br.html32
-rw-r--r--testing/web-platform/tests/html/rendering/replaced-elements/the-option-element/select-multiple-covered-by-abspos-ref.html11
-rw-r--r--testing/web-platform/tests/html/rendering/replaced-elements/the-option-element/select-multiple-covered-by-abspos.html19
-rw-r--r--testing/web-platform/tests/html/rendering/replaced-elements/the-select-element/select-1-block-size-001-ref-2.html24
-rw-r--r--testing/web-platform/tests/html/rendering/replaced-elements/the-select-element/select-1-block-size-001-ref.html24
-rw-r--r--testing/web-platform/tests/html/rendering/replaced-elements/the-select-element/select-1-block-size-001.html24
-rw-r--r--testing/web-platform/tests/html/rendering/replaced-elements/the-select-element/select-1-block-size-ref.html33
-rw-r--r--testing/web-platform/tests/html/rendering/replaced-elements/the-select-element/select-1-block-size.html38
-rw-r--r--testing/web-platform/tests/html/rendering/replaced-elements/the-select-element/select-1-line-height-ref.html23
-rw-r--r--testing/web-platform/tests/html/rendering/replaced-elements/the-select-element/select-1-line-height.html36
-rw-r--r--testing/web-platform/tests/html/rendering/replaced-elements/the-select-element/select-empty-ref.html35
-rw-r--r--testing/web-platform/tests/html/rendering/replaced-elements/the-select-element/select-empty.html33
-rw-r--r--testing/web-platform/tests/html/rendering/replaced-elements/the-select-element/select-intrinsic-option-font-size-ref.html8
-rw-r--r--testing/web-platform/tests/html/rendering/replaced-elements/the-select-element/select-intrinsic-option-font-size.html9
-rw-r--r--testing/web-platform/tests/html/rendering/replaced-elements/the-select-element/select-intrinsic-text-transform-ref.html5
-rw-r--r--testing/web-platform/tests/html/rendering/replaced-elements/the-select-element/select-intrinsic-text-transform.html8
-rw-r--r--testing/web-platform/tests/html/rendering/replaced-elements/the-select-element/select-multiple-re-add-option-via-document-fragment-ref.html4
-rw-r--r--testing/web-platform/tests/html/rendering/replaced-elements/the-select-element/select-multiple-re-add-option-via-document-fragment.html12
-rw-r--r--testing/web-platform/tests/html/rendering/replaced-elements/the-textarea-element/textarea-padding-bend-overlaps-content-001-ref.html32
-rw-r--r--testing/web-platform/tests/html/rendering/replaced-elements/the-textarea-element/textarea-padding-bend-overlaps-content-001.tentative.html43
-rw-r--r--testing/web-platform/tests/html/rendering/replaced-elements/the-textarea-element/textarea-padding-bstart-moves-content-001-ref.html34
-rw-r--r--testing/web-platform/tests/html/rendering/replaced-elements/the-textarea-element/textarea-padding-bstart-moves-content-001.tentative.html46
-rw-r--r--testing/web-platform/tests/html/rendering/replaced-elements/the-textarea-element/textarea-padding-iend-overlaps-content-001-ref.html32
-rw-r--r--testing/web-platform/tests/html/rendering/replaced-elements/the-textarea-element/textarea-padding-iend-overlaps-content-001.tentative.html37
-rw-r--r--testing/web-platform/tests/html/rendering/replaced-elements/the-textarea-element/textarea-padding-istart-moves-content-001-ref.html34
-rw-r--r--testing/web-platform/tests/html/rendering/replaced-elements/the-textarea-element/textarea-padding-istart-moves-content-001.tentative.html46
-rw-r--r--testing/web-platform/tests/html/rendering/replaced-elements/tools/gen-svgsizing-tests.py55
107 files changed, 3127 insertions, 0 deletions
diff --git a/testing/web-platform/tests/html/rendering/replaced-elements/attributes-for-embedded-content-and-images/align.html b/testing/web-platform/tests/html/rendering/replaced-elements/attributes-for-embedded-content-and-images/align.html
new file mode 100644
index 0000000000..b5f3ec1aa6
--- /dev/null
+++ b/testing/web-platform/tests/html/rendering/replaced-elements/attributes-for-embedded-content-and-images/align.html
@@ -0,0 +1,59 @@
+<!doctype html>
+<title>align attribute mapping on replaced elements</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<img id="replaced" src="/images/green.png">
+<something id="non-replaced"></something>
+<script>
+const kMapping = {
+ "left": ["float", "left"],
+ "right": ["float", "right"],
+
+ "top": ["vertical-align", "top"],
+
+ // This one requires a magic value (`-moz-middle-with-baseline` on Gecko,
+ // `-webkit-baseline-middle` on WebKit-based browsers).
+ "middle": ["vertical-align", undefined],
+ // These are inconsistent across browsers. WebKit maps it to "middle", Gecko
+ // to the aforementioned value.
+ "center": ["vertical-align", undefined],
+
+ "baseline": ["vertical-align", "baseline"],
+ "bottom": ["vertical-align", "baseline"], // *shrug*
+
+ "texttop": ["vertical-align", "text-top"],
+ "absmiddle": ["vertical-align", "middle"],
+ "abscenter": ["vertical-align", "middle"],
+ "absbottom": ["vertical-align", "bottom"],
+};
+
+const kInitialValues = {
+ "vertical-align": "baseline",
+ "float": "none",
+};
+
+let replaced = document.getElementById("replaced");
+let nonReplaced = document.getElementById("non-replaced");
+let t = async_test("align attribute mapping");
+onload = t.step_func_done(function() {
+ for (const attributeValue in kMapping) {
+ for (const element of [replaced, nonReplaced]) {
+ test(function() {
+ element.setAttribute("align", attributeValue);
+ let [property, expected] = kMapping[attributeValue];
+ let actual = getComputedStyle(element).getPropertyValue(property);
+ if (element == nonReplaced) {
+ assert_equals(actual, kInitialValues[property], "align shouldn't map to non-replaced elements")
+ } else {
+ if (expected) {
+ assert_equals(actual, expected, `align=${attributeValue} should map to ${property}: ${expected}`);
+ } else {
+ assert_equals(property, "vertical-align");
+ assert_not_equals(actual, "baseline", `align=${attributeValue} should map a vertical-align value`);
+ }
+ }
+ }, `align=${attributeValue} on ${element == replaced ? "replaced" : "non-replaced"} elements`);
+ }
+ }
+});
+</script>
diff --git a/testing/web-platform/tests/html/rendering/replaced-elements/attributes-for-embedded-content-and-images/canvas-aspect-ratio.html b/testing/web-platform/tests/html/rendering/replaced-elements/attributes-for-embedded-content-and-images/canvas-aspect-ratio.html
new file mode 100644
index 0000000000..dbe4c7d9f3
--- /dev/null
+++ b/testing/web-platform/tests/html/rendering/replaced-elements/attributes-for-embedded-content-and-images/canvas-aspect-ratio.html
@@ -0,0 +1,52 @@
+<!doctype html>
+<title>Canvas width and height attributes are used as the surface size, and also to infer aspect ratio</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="resources/aspect-ratio.js"></script>
+<style>
+ canvas {
+ width: 100%;
+ max-width: 100px;
+ height: auto;
+ }
+</style>
+<body>
+<canvas id="contained" width="250" height="100" style="contain: size;"></canvas>
+<script>
+function assert_ratio(img, expected) {
+ let epsilon = 0.001;
+ assert_approx_equals(parseInt(getComputedStyle(img).width, 10) / parseInt(getComputedStyle(img).height, 10), expected, epsilon);
+}
+
+function test_computed_style(width, height, expected) {
+ test_computed_style_aspect_ratio("canvas", {width: width, height: height}, expected);
+}
+
+test(function() {
+ canvas = document.getElementById("contained");
+ assert_ratio(canvas, 2.5);
+}, "Canvas width and height attributes are used as the surface size with contain:size");
+
+// Create and append a new canvas and immediately check the ratio.
+test(function() {
+ var canvas = document.createElement("canvas");
+ canvas.setAttribute("width", "250");
+ canvas.setAttribute("height", "100");
+ document.body.appendChild(canvas);
+ // Canvases always use the aspect ratio from their surface size.
+ assert_ratio(canvas, 2.5);
+}, "Canvas width and height attributes are used as the surface size");
+
+test_computed_style("10", "20", "auto 10 / 20");
+test_computed_style("0", "1", "auto 0 / 1");
+test_computed_style("1", "0", "auto 1 / 0");
+test_computed_style("0", "0", "auto 0 / 0");
+test_computed_style("0.5", "1.5", "auto 0 / 1");
+test_computed_style("10%", "20", "auto 10 / 20");
+test_computed_style(null, null, "auto");
+test_computed_style("10", null, "auto");
+test_computed_style(null, "20", "auto");
+test_computed_style("xx", "20", "auto");
+test_computed_style("20", "xx", "auto");
+
+</script>
diff --git a/testing/web-platform/tests/html/rendering/replaced-elements/attributes-for-embedded-content-and-images/content-aspect-ratio.html b/testing/web-platform/tests/html/rendering/replaced-elements/attributes-for-embedded-content-and-images/content-aspect-ratio.html
new file mode 100644
index 0000000000..42be8ce7a8
--- /dev/null
+++ b/testing/web-platform/tests/html/rendering/replaced-elements/attributes-for-embedded-content-and-images/content-aspect-ratio.html
@@ -0,0 +1,25 @@
+<!doctype html>
+<title>div with content style's width and height attributes are not used to infer aspect-ratio</title>
+<link rel="help" href="https://bugs.webkit.org/show_bug.cgi?id=201641#c22">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<style>
+ video {
+ width: 100%;
+ max-width: 100px;
+ height: auto;
+ }
+</style>
+<body>
+<script>
+// Create and append a div with content style and immediately check the height.
+let t = test(function() {
+ var div = document.createElement("div");
+ div.setAttribute("style", "content: url('/images/blue.png')");
+ div.setAttribute("width", "250");
+ div.setAttribute("height", "100");
+ document.body.appendChild(div);
+ assert_equals(getComputedStyle(div).height, "0px");
+}, "div with content style's width and height attributes are not used to infer aspect-ratio");
+
+</script>
diff --git a/testing/web-platform/tests/html/rendering/replaced-elements/attributes-for-embedded-content-and-images/embedded-and-images-presentational-hints-ascii-case-insensitive.html b/testing/web-platform/tests/html/rendering/replaced-elements/attributes-for-embedded-content-and-images/embedded-and-images-presentational-hints-ascii-case-insensitive.html
new file mode 100644
index 0000000000..8fafb0c7f0
--- /dev/null
+++ b/testing/web-platform/tests/html/rendering/replaced-elements/attributes-for-embedded-content-and-images/embedded-and-images-presentational-hints-ascii-case-insensitive.html
@@ -0,0 +1,46 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<link rel="help" href="https://html.spec.whatwg.org/#attributes-for-embedded-content-and-images:presentational-hints">
+<link rel="help" href="https://drafts.csswg.org/selectors-4/#attribute-case">
+<meta name="assert" content="@align values on embedded content and images are ASCII case-insensitive">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<img src="fuchsia.png" align="absbottom">
+<img src="fuchsia.png" align="AbSbOtToM">
+<img src="fuchsia.png" align="abſbottom">
+<img src="fuchsia.png" align="abscenter">
+<img src="fuchsia.png" align="AbScEnTeR">
+<img src="fuchsia.png" align="abſcenter">
+<img src="fuchsia.png" align="absmiddle">
+<img src="fuchsia.png" align="AbSmIdDlE">
+<img src="fuchsia.png" align="abſmiddle">
+<script>
+const img = document.querySelectorAll("img");
+
+test(() => {
+ assert_equals(getComputedStyle(img[0]).getPropertyValue("vertical-align"),
+ "bottom", "lowercase valid");
+ assert_equals(getComputedStyle(img[1]).getPropertyValue("vertical-align"),
+ "bottom", "mixed case valid");
+ assert_equals(getComputedStyle(img[2]).getPropertyValue("vertical-align"),
+ "baseline", "non-ASCII invalid");
+}, "keyword absbottom");
+
+test(() => {
+ assert_equals(getComputedStyle(img[3]).getPropertyValue("vertical-align"),
+ "middle", "lowercase valid");
+ assert_equals(getComputedStyle(img[4]).getPropertyValue("vertical-align"),
+ "middle", "mixed case valid");
+ assert_equals(getComputedStyle(img[5]).getPropertyValue("vertical-align"),
+ "baseline", "non-ASCII invalid");
+}, "keyword abscenter");
+
+test(() => {
+ assert_equals(getComputedStyle(img[6]).getPropertyValue("vertical-align"),
+ "middle", "lowercase valid");
+ assert_equals(getComputedStyle(img[7]).getPropertyValue("vertical-align"),
+ "middle", "mixed case valid");
+ assert_equals(getComputedStyle(img[8]).getPropertyValue("vertical-align"),
+ "baseline", "non-ASCII invalid");
+}, "keyword absmiddle");
+</script>
diff --git a/testing/web-platform/tests/html/rendering/replaced-elements/attributes-for-embedded-content-and-images/img-alt-crash-001.html b/testing/web-platform/tests/html/rendering/replaced-elements/attributes-for-embedded-content-and-images/img-alt-crash-001.html
new file mode 100644
index 0000000000..b057967e7e
--- /dev/null
+++ b/testing/web-platform/tests/html/rendering/replaced-elements/attributes-for-embedded-content-and-images/img-alt-crash-001.html
@@ -0,0 +1,15 @@
+<!doctype html>
+<title>Crash test: img alt rendering in combination with style attribute selector</title>
+<link rel="help" href="https://crbug.com/1057210">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<style>
+ img { display: block; width: 100px; }
+ [style] + * {}
+</style>
+<img id="img" alt="alternative text">
+<script>
+ test(() => {
+ assert_equals(getComputedStyle(img).width, "100px");
+ }, "Should not crash.");
+</script>
diff --git a/testing/web-platform/tests/html/rendering/replaced-elements/attributes-for-embedded-content-and-images/img-aspect-ratio-lazy.html b/testing/web-platform/tests/html/rendering/replaced-elements/attributes-for-embedded-content-and-images/img-aspect-ratio-lazy.html
new file mode 100644
index 0000000000..1833efb804
--- /dev/null
+++ b/testing/web-platform/tests/html/rendering/replaced-elements/attributes-for-embedded-content-and-images/img-aspect-ratio-lazy.html
@@ -0,0 +1,36 @@
+<!doctype html>
+<title>Image width and height attributes are used to infer aspect-ratio for lazy-loaded images</title>
+<meta name="viewport" content="width=device-width">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<style>
+ img {
+ width: 100%;
+ max-width: 100px;
+ height: auto;
+ }
+</style>
+<div style="height: 600vh"></div>
+<img src="/images/green.png" loading="lazy" width=100 height=100>
+<script>
+let t = async_test("Image width and height attributes are used to infer aspect-ratio for lazy-loaded images");
+
+function assert_ratio(img, expected) {
+ let epsilon = 0.001;
+ assert_approx_equals(parseFloat(getComputedStyle(img).width, 10) / parseFloat(getComputedStyle(img).height, 10), expected, epsilon);
+}
+
+t.step(function() {
+ let img = document.querySelector("img");
+ // The initial aspect ratio is given by the width/height attributes:
+ // https://html.spec.whatwg.org/#map-to-the-aspect-ratio-property-(using-dimension-rules)
+ assert_ratio(img, 1.0);
+ img.addEventListener("load", t.step_func_done(function() {
+ // Now the element "represents an image":
+ // https://html.spec.whatwg.org/multipage/rendering.html#images-3
+ // 2.0 is the original aspect ratio of green.png
+ assert_ratio(img, 2.0);
+ }));
+ window.scrollTo(0, img.getBoundingClientRect().top);
+});
+</script>
diff --git a/testing/web-platform/tests/html/rendering/replaced-elements/attributes-for-embedded-content-and-images/img-aspect-ratio.html b/testing/web-platform/tests/html/rendering/replaced-elements/attributes-for-embedded-content-and-images/img-aspect-ratio.html
new file mode 100644
index 0000000000..4dee3cf7ad
--- /dev/null
+++ b/testing/web-platform/tests/html/rendering/replaced-elements/attributes-for-embedded-content-and-images/img-aspect-ratio.html
@@ -0,0 +1,120 @@
+<!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>
+<script src="resources/aspect-ratio.js"></script>
+<style>
+ img {
+ width: 100%;
+ max-width: 100px;
+ height: auto;
+ }
+</style>
+<img src="/images/green.png">
+<img src="/images/green.png" width=100 height=125>
+<img src="" width=100 height=125>
+<img src="error.png" width=100 height=125>
+<img src="error.png">
+<img src="error.png" alt="Alt text" width=100 height=500>
+<script>
+let guard = async_test("Image width and height attributes are used to infer aspect-ratio");
+let cookie = Math.random();
+function assert_ratio(img, expected, description) {
+ let epsilon = 0.001;
+ assert_approx_equals(parseFloat(getComputedStyle(img).width, 10) / parseFloat(getComputedStyle(img).height, 10),
+ expected, epsilon, description);
+}
+
+function test_computed_style(width, height, expected) {
+ test_computed_style_aspect_ratio("img", {width: width, height: height}, expected);
+ test_computed_style_aspect_ratio("input", {type: "image", width: width, height: height}, expected);
+ // input type=submit should not do this mapping.
+ test_computed_style_aspect_ratio("input", {type: "submit", width: width, height: height}, "auto");
+}
+
+// Create and append a new image and immediately check the ratio.
+// We append a random query to the URL(s) to avoid matching something in the 'list
+// of available images' (step 6 of the algorithm below) and thus have the actual
+// load run in a microtask.
+// https://html.spec.whatwg.org/multipage/images.html#updating-the-image-data
+test(function() {
+ // This img will be tested again after loaded. In order to locate it correctly, body should append it first.
+ var img = new Image();
+ img.width = 250;
+ img.height = 100;
+ img.src = "/images/blue.png?" + cookie;
+ document.body.appendChild(img);
+ assert_ratio(img, 2.5);
+}, "Create, append and test immediately: <img> with attributes width=250, height=100");
+
+test(function () {
+ img = new Image();
+ img.setAttribute("width", "0.8");
+ img.setAttribute("height", "0.2");
+ img.src = "/images/blue.png?" + (cookie + 1);
+ document.body.appendChild(img);
+ assert_ratio(img, 4);
+}, "Create, append and test immediately: <img> with attributes width=0.8, height=0.2");
+
+test(function () {
+ img = new Image();
+ img.setAttribute("width", "50%");
+ img.setAttribute("height", "25%");
+ img.src = "/images/blue.png?" + (cookie + 2);
+ document.body.appendChild(img);
+ // Percentages should be ignored.
+ assert_equals(getComputedStyle(img).height, "0px");
+}, "Create, append and test immediately: <img> with attributes width=50% height=25%");
+
+test(function () {
+ img = new Image();
+ img.setAttribute("width", "50pp");
+ img.setAttribute("height", "25xx");
+ img.src = "/images/blue.png?" + (cookie + 3);
+ document.body.appendChild(img);
+ assert_ratio(img, 2);
+}, "Create, append and test immediately: <img> with invalid trailing attributes width=50pp height=25xx");
+
+test_computed_style("10", "20", "auto 10 / 20");
+test_computed_style("0", "1", "auto 0 / 1");
+test_computed_style("1", "0", "auto 1 / 0");
+test_computed_style("0", "0", "auto 0 / 0");
+test_computed_style("0.5", "1.5", "auto 0.5 / 1.5");
+test_computed_style(null, null, "auto");
+test_computed_style("10", null, "auto");
+test_computed_style(null, "20", "auto");
+test_computed_style("xx", "20", "auto");
+test_computed_style("10%", "20", "auto");
+
+onload = function() {
+ let images = document.querySelectorAll("img");
+ // Tests for images finished loading.
+ test(function() {
+ assert_ratio(images[0], 2.0, "2.0 is the original aspect ratio of green.png");
+ }, "Loaded images test: <img> without width height attributes");
+
+ test(function() {
+ assert_ratio(images[1], 2.0, "Loaded image's aspect ratio, at least by default, overrides width / height ratio.");
+ }, "Loaded images test: <img> with width and height attributes, but conflicting to the original aspect ratio");
+
+ test(function () {
+ assert_ratio(images[2], 100 / 125, "aspect-ratio should override intrinsic size of images that don't have any src.");
+ }, "Loaded images test: <img> with width, height and empty src attributes");
+
+ test(function () {
+ assert_ratio(images[3], 100 / 125, "aspect-ratio should affect the size of error images.");
+ }, "Loaded images test: Error image with width and height attributes");
+
+ test(function () {
+ assert_not_equals(images[5].offsetHeight, 500, "Images with alt text should be inline and ignore the aspect ratio");
+ // Though aspect-ratio is ignored, its value does not change.
+ assert_equals(getComputedStyle(images[5]).aspectRatio, "auto 100 / 500");
+ }, "Loaded images test: Error image with width, height and alt attributes");
+
+ test(function () {
+ assert_ratio(images[6], 133 / 106, "The original aspect ratio of blue.png");
+ }, "Loaded images test: <img> with width and height attributes, but not equal to the original aspect ratio");
+
+ guard.done();
+};
+</script>
diff --git a/testing/web-platform/tests/html/rendering/replaced-elements/attributes-for-embedded-content-and-images/img-dim-ref.html b/testing/web-platform/tests/html/rendering/replaced-elements/attributes-for-embedded-content-and-images/img-dim-ref.html
new file mode 100644
index 0000000000..b1adb68307
--- /dev/null
+++ b/testing/web-platform/tests/html/rendering/replaced-elements/attributes-for-embedded-content-and-images/img-dim-ref.html
@@ -0,0 +1,11 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>img width/height - reference</title>
+<style>
+p { width: 50px; height: 50px; }
+</style>
+<p><img src=/images/green.png>
+<p><img src=/images/green.png style="width: 10px">
+<p><img src=/images/green.png style="height: 10px">
+<p><img src=/images/green.png style="width: 10%">
+<p><img src=/images/green.png style="height: 10%">
diff --git a/testing/web-platform/tests/html/rendering/replaced-elements/attributes-for-embedded-content-and-images/img-dim.html b/testing/web-platform/tests/html/rendering/replaced-elements/attributes-for-embedded-content-and-images/img-dim.html
new file mode 100644
index 0000000000..2d636c9417
--- /dev/null
+++ b/testing/web-platform/tests/html/rendering/replaced-elements/attributes-for-embedded-content-and-images/img-dim.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>img width/height</title>
+<link rel=match href=img-dim-ref.html>
+<style>
+p { width: 50px; height: 50px; }
+</style>
+<p><img src=/images/green.png>
+<p><img src=/images/green.png width=10>
+<p><img src=/images/green.png height=10>
+<p><img src=/images/green.png width=10%>
+<p><img src=/images/green.png height=10%>
diff --git a/testing/web-platform/tests/html/rendering/replaced-elements/attributes-for-embedded-content-and-images/img-empty-alt-replaced.html b/testing/web-platform/tests/html/rendering/replaced-elements/attributes-for-embedded-content-and-images/img-empty-alt-replaced.html
new file mode 100644
index 0000000000..3cc06d6c85
--- /dev/null
+++ b/testing/web-platform/tests/html/rendering/replaced-elements/attributes-for-embedded-content-and-images/img-empty-alt-replaced.html
@@ -0,0 +1,23 @@
+<!doctype html>
+<title>Images with an empty alt attribute have an intrinsic size of zero</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<style>
+ img {
+ width: 50px;
+ height: auto;
+ }
+</style>
+<img src="broken">
+<img src="broken" alt="non-empty">
+<img src="broken" alt="">
+<script>
+const t = async_test("Images with an empty alt attribute have an intrinsic size of zero");
+onload = t.step_func_done(function() {
+ for (const img of document.querySelectorAll("img")) {
+ const alt = img.getAttribute("alt");
+ const shouldTakeUpSpace = alt == null || alt.length > 0;
+ (shouldTakeUpSpace ? assert_not_equals : assert_equals)(img.offsetHeight, 0, img.outerHTML);
+ }
+});
+</script>
diff --git a/testing/web-platform/tests/html/rendering/replaced-elements/attributes-for-embedded-content-and-images/img-no-alt-replaced.html b/testing/web-platform/tests/html/rendering/replaced-elements/attributes-for-embedded-content-and-images/img-no-alt-replaced.html
new file mode 100644
index 0000000000..5f3503ae3b
--- /dev/null
+++ b/testing/web-platform/tests/html/rendering/replaced-elements/attributes-for-embedded-content-and-images/img-no-alt-replaced.html
@@ -0,0 +1,30 @@
+<!doctype html>
+<title>Images without alt attribute or with an empty alt attribute render as replaced elements regardless of src</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<link rel="author" href="mailto:emilio@crisal.io" title="Emilio Cobos Álvarez">
+<link rel="author" href="mailto:yuzhehan@chromium.org" title="Yu Han">
+<link rel="author" href="https://mozilla.org" title="Mozilla">
+<link rel="help" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1196668">
+<link rel="help" href="https://crbug.com/753868">
+<link ref="help" href="https://html.spec.whatwg.org/multipage/rendering.html#images-3">
+<style>
+ img {
+ width: 100px;
+ height: 150px;
+ }
+</style>
+<img>
+<img src="broken">
+<img alt="">
+<img alt>
+<img src="broken" alt="">
+<script>
+const t = async_test("Images without alt attribute or with an empty alt attribute render as replaced elements regardless of src");
+onload = t.step_func_done(function() {
+ for (const img of document.querySelectorAll("img")) {
+ assert_equals(img.offsetWidth, 100, `width: ${img.outerHTML}`);
+ assert_equals(img.offsetHeight, 150, `height: ${img.outerHTML}`);
+ }
+});
+</script>
diff --git a/testing/web-platform/tests/html/rendering/replaced-elements/attributes-for-embedded-content-and-images/img-replaced-box-while-loading.html b/testing/web-platform/tests/html/rendering/replaced-elements/attributes-for-embedded-content-and-images/img-replaced-box-while-loading.html
new file mode 100644
index 0000000000..48bbd36db9
--- /dev/null
+++ b/testing/web-platform/tests/html/rendering/replaced-elements/attributes-for-embedded-content-and-images/img-replaced-box-while-loading.html
@@ -0,0 +1,29 @@
+<!doctype html>
+<title>Images don't render as a non-replaced inline while loading, even when there's no concrete size specified</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<link rel="author" href="mailto:emilio@crisal.io" title="Emilio Cobos Álvarez">
+<link rel="author" href="https://mozilla.org" title="Mozilla">
+<link rel="help" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1472637">
+<style>
+ img {
+ min-width: 1000px;
+ }
+</style>
+<img alt="T">
+<script>
+// Do an async test off the onload handler to avoid waiting for the load even for too long unnecessarily.
+let t = async_test("Loading images should get a replaced box, even without specified size");
+onload = t.step_func(function() {
+ const image = document.querySelector("img");
+ // Use the trickle pipe to have 100 seconds until the image actually loads,
+ // that should be enough to run the test.
+ image.src = "../../../../../images/blue.png?pipe=trickle(d100)";
+ t.step_timeout(t.step_func_done(function() {
+ assert_equals(
+ image.offsetWidth,
+ 1000,
+ );
+ }), 0);
+});
+</script>
diff --git a/testing/web-platform/tests/html/rendering/replaced-elements/attributes-for-embedded-content-and-images/img-title-only-w-sizing.html b/testing/web-platform/tests/html/rendering/replaced-elements/attributes-for-embedded-content-and-images/img-title-only-w-sizing.html
new file mode 100644
index 0000000000..c290d9d6b1
--- /dev/null
+++ b/testing/web-platform/tests/html/rendering/replaced-elements/attributes-for-embedded-content-and-images/img-title-only-w-sizing.html
@@ -0,0 +1,25 @@
+<!doctype html>
+<title>Images with only title should be treated as a replaced element</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<link rel="author" href="mailto:yuzhehan@chromium.org" title="Yu Han">
+<link rel="help" href="https://crbug.com/958250">
+<link ref="help" href="https://html.spec.whatwg.org/multipage/rendering.html#images-3">
+<style>
+ .title-only {
+ width: 100px;
+ height: 150px;
+ }
+</style>
+<img class="title-only" title="title">
+<img width="100" height="150px" title="title">
+<script>
+async_test(t => {
+ onload = t.step_func_done(function() {
+ for (const img of document.querySelectorAll("img")) {
+ assert_equals(img.offsetWidth, 100, `width: ${img.outerHTML}`);
+ assert_equals(img.offsetHeight, 150, `height: ${img.outerHTML}`);
+ }
+ });
+});
+</script>
diff --git a/testing/web-platform/tests/html/rendering/replaced-elements/attributes-for-embedded-content-and-images/img_border-ref.xhtml b/testing/web-platform/tests/html/rendering/replaced-elements/attributes-for-embedded-content-and-images/img_border-ref.xhtml
new file mode 100644
index 0000000000..0050c542cd
--- /dev/null
+++ b/testing/web-platform/tests/html/rendering/replaced-elements/attributes-for-embedded-content-and-images/img_border-ref.xhtml
@@ -0,0 +1,9 @@
+<html xmlns='http://www.w3.org/1999/xhtml'>
+<head>
+<title>IMG - Border in CSS</title>
+</head>
+<body>
+<p><img src="../../../../../images/blue.png"/></p>
+<p><img src="../../../../../images/blue.png" style="border-width:50px; border-style:solid;"/></p>
+</body>
+</html>
diff --git a/testing/web-platform/tests/html/rendering/replaced-elements/attributes-for-embedded-content-and-images/img_border_percent.xhtml b/testing/web-platform/tests/html/rendering/replaced-elements/attributes-for-embedded-content-and-images/img_border_percent.xhtml
new file mode 100644
index 0000000000..da74fb32b9
--- /dev/null
+++ b/testing/web-platform/tests/html/rendering/replaced-elements/attributes-for-embedded-content-and-images/img_border_percent.xhtml
@@ -0,0 +1,10 @@
+<html xmlns='http://www.w3.org/1999/xhtml'>
+<head>
+<title>IMG - Border= value in percent</title>
+<link rel="match" href="img_border-ref.xhtml"/>
+</head>
+<body>
+<p><img src="../../../../../images/blue.png" border="0%"/></p>
+<p><img src="../../../../../images/blue.png" border="50%"/></p>
+</body>
+</html>
diff --git a/testing/web-platform/tests/html/rendering/replaced-elements/attributes-for-embedded-content-and-images/input-align-right-1.html b/testing/web-platform/tests/html/rendering/replaced-elements/attributes-for-embedded-content-and-images/input-align-right-1.html
new file mode 100644
index 0000000000..6e32206d91
--- /dev/null
+++ b/testing/web-platform/tests/html/rendering/replaced-elements/attributes-for-embedded-content-and-images/input-align-right-1.html
@@ -0,0 +1,3 @@
+<!DOCTYPE html>
+<link rel="match" href="input-align-right-ref.html">
+<input type="image" align="right">
diff --git a/testing/web-platform/tests/html/rendering/replaced-elements/attributes-for-embedded-content-and-images/input-align-right-2.html b/testing/web-platform/tests/html/rendering/replaced-elements/attributes-for-embedded-content-and-images/input-align-right-2.html
new file mode 100644
index 0000000000..d58848aa53
--- /dev/null
+++ b/testing/web-platform/tests/html/rendering/replaced-elements/attributes-for-embedded-content-and-images/input-align-right-2.html
@@ -0,0 +1,3 @@
+<!DOCTYPE html>
+<link rel="match" href="input-align-right-ref.html">
+<input align="right" type="image">
diff --git a/testing/web-platform/tests/html/rendering/replaced-elements/attributes-for-embedded-content-and-images/input-align-right-ref.html b/testing/web-platform/tests/html/rendering/replaced-elements/attributes-for-embedded-content-and-images/input-align-right-ref.html
new file mode 100644
index 0000000000..55f06ef96b
--- /dev/null
+++ b/testing/web-platform/tests/html/rendering/replaced-elements/attributes-for-embedded-content-and-images/input-align-right-ref.html
@@ -0,0 +1,2 @@
+<!DOCTYPE html>
+<input type="image" style="float: right">
diff --git a/testing/web-platform/tests/html/rendering/replaced-elements/attributes-for-embedded-content-and-images/input-image-content-crash.html b/testing/web-platform/tests/html/rendering/replaced-elements/attributes-for-embedded-content-and-images/input-image-content-crash.html
new file mode 100644
index 0000000000..84ef2ab153
--- /dev/null
+++ b/testing/web-platform/tests/html/rendering/replaced-elements/attributes-for-embedded-content-and-images/input-image-content-crash.html
@@ -0,0 +1,15 @@
+<!doctype html>
+<title>Crash test: asynchronously applying image content to image input</title>
+<link rel="author" href="mailto:yuzhehan@chromium.org" title="Yu Han">
+<link rel="help" href="https://crbug.com/1096002">
+<style>
+ .content { content: url(data:text/plain,aaa); }
+</style>
+<input id="input" type="image" class=content>
+<script>
+ onload = ()=> {
+ document.body.offsetTop;
+ input.setAttribute('class', '');
+ document.body.offsetTop;
+ }
+</script>
diff --git a/testing/web-platform/tests/html/rendering/replaced-elements/attributes-for-embedded-content-and-images/input-image-inline-alt-ref.html b/testing/web-platform/tests/html/rendering/replaced-elements/attributes-for-embedded-content-and-images/input-image-inline-alt-ref.html
new file mode 100644
index 0000000000..b3fdc14ef1
--- /dev/null
+++ b/testing/web-platform/tests/html/rendering/replaced-elements/attributes-for-embedded-content-and-images/input-image-inline-alt-ref.html
@@ -0,0 +1,18 @@
+<!DOCTYPE html>
+<title>Input image type fallback content should respect display property.</title>
+<meta name="author" title="Yu Han" href="mailto:yuzhehan@chromium.org">
+<style>
+ div {
+ border:1px dashed blue;
+ line-height: 1em;
+ height: 100px;
+ width: 150px;
+ }
+ input {
+ font: 1em monospace;
+ line-height: 1em;
+ }
+</style>
+<div>
+ <input alt="This is a long ALT text which takes up few lines to display. And additional text to be inlined." type="image">
+</div>
diff --git a/testing/web-platform/tests/html/rendering/replaced-elements/attributes-for-embedded-content-and-images/input-image-inline-alt.html b/testing/web-platform/tests/html/rendering/replaced-elements/attributes-for-embedded-content-and-images/input-image-inline-alt.html
new file mode 100644
index 0000000000..e05ad84191
--- /dev/null
+++ b/testing/web-platform/tests/html/rendering/replaced-elements/attributes-for-embedded-content-and-images/input-image-inline-alt.html
@@ -0,0 +1,23 @@
+<!DOCTYPE html>
+<title>Input image type fallback content should respect display property.</title>
+<meta name="author" title="Yu Han" href="mailto:yuzhehan@chromium.org">
+<link rel="match" href="input-image-inline-alt-ref.html">
+<link ref="help" href="https://html.spec.whatwg.org/multipage/rendering.html#images-3:represents-5">
+<style>
+ div {
+ border:1px dashed blue;
+ font: 1em monospace;
+ line-height: 1em;
+ height: 100px;
+ width: 150px;
+ }
+ input {
+ display: inline;
+ font: 1em monospace;
+ line-height: 1em;
+ }
+</style>
+<div>
+ <input alt="This is a long ALT text which takes up few lines to display." type="image">
+ And additional text to be inlined.
+</div>
diff --git a/testing/web-platform/tests/html/rendering/replaced-elements/attributes-for-embedded-content-and-images/input-type-change-from-image-1-ref.html b/testing/web-platform/tests/html/rendering/replaced-elements/attributes-for-embedded-content-and-images/input-type-change-from-image-1-ref.html
new file mode 100644
index 0000000000..7768379e91
--- /dev/null
+++ b/testing/web-platform/tests/html/rendering/replaced-elements/attributes-for-embedded-content-and-images/input-type-change-from-image-1-ref.html
@@ -0,0 +1,2 @@
+<!DOCTYPE html>
+<input align="right">
diff --git a/testing/web-platform/tests/html/rendering/replaced-elements/attributes-for-embedded-content-and-images/input-type-change-from-image-1.html b/testing/web-platform/tests/html/rendering/replaced-elements/attributes-for-embedded-content-and-images/input-type-change-from-image-1.html
new file mode 100644
index 0000000000..00747a5fbf
--- /dev/null
+++ b/testing/web-platform/tests/html/rendering/replaced-elements/attributes-for-embedded-content-and-images/input-type-change-from-image-1.html
@@ -0,0 +1,10 @@
+<!DOCTYPE html>
+<link rel=match href="input-type-change-from-image-1-ref.html">
+<input type="image" align="right">
+<script>
+ onload = function() {
+ var i = document.querySelector("input");
+ window.rect = i.getBoundingClientRect();
+ i.type = "text";
+ }
+</script>
diff --git a/testing/web-platform/tests/html/rendering/replaced-elements/attributes-for-embedded-content-and-images/number-placeholder-right-aligned-ref.html b/testing/web-platform/tests/html/rendering/replaced-elements/attributes-for-embedded-content-and-images/number-placeholder-right-aligned-ref.html
new file mode 100644
index 0000000000..61dff1e460
--- /dev/null
+++ b/testing/web-platform/tests/html/rendering/replaced-elements/attributes-for-embedded-content-and-images/number-placeholder-right-aligned-ref.html
@@ -0,0 +1,8 @@
+<!doctype html>
+<style>
+input {
+ color: black;
+ text-align: right;
+}
+</style>
+<input type=number value=0>
diff --git a/testing/web-platform/tests/html/rendering/replaced-elements/attributes-for-embedded-content-and-images/number-placeholder-right-aligned.html b/testing/web-platform/tests/html/rendering/replaced-elements/attributes-for-embedded-content-and-images/number-placeholder-right-aligned.html
new file mode 100644
index 0000000000..c1c695ffca
--- /dev/null
+++ b/testing/web-platform/tests/html/rendering/replaced-elements/attributes-for-embedded-content-and-images/number-placeholder-right-aligned.html
@@ -0,0 +1,16 @@
+<!doctype html>
+<link rel="author" title="Emilio Cobos Álvarez" href="mailto:emilio@crisal.io">
+<link rel="author" title="Mozilla" href="https://mozilla.org">
+<link rel="help" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1698043">
+<link rel="match" href="number-placeholder-right-aligned-ref.html">
+<style>
+input {
+ color: black;
+ text-align: right;
+}
+input::placeholder {
+ color: inherit;
+ opacity: 1;
+}
+</style>
+<input type=number placeholder=0>
diff --git a/testing/web-platform/tests/html/rendering/replaced-elements/attributes-for-embedded-content-and-images/object_border-ref.xhtml b/testing/web-platform/tests/html/rendering/replaced-elements/attributes-for-embedded-content-and-images/object_border-ref.xhtml
new file mode 100644
index 0000000000..6eaaa0ba14
--- /dev/null
+++ b/testing/web-platform/tests/html/rendering/replaced-elements/attributes-for-embedded-content-and-images/object_border-ref.xhtml
@@ -0,0 +1,8 @@
+<html xmlns='http://www.w3.org/1999/xhtml'>
+<head>
+<title>OBJECT - border in CSS</title>
+</head>
+<body>
+<p><object data="../../../../images/blue.png" type="image/png" style="border-width:50px; border-style:solid;"></object></p>
+</body>
+</html>
diff --git a/testing/web-platform/tests/html/rendering/replaced-elements/attributes-for-embedded-content-and-images/object_border_perc.xhtml b/testing/web-platform/tests/html/rendering/replaced-elements/attributes-for-embedded-content-and-images/object_border_perc.xhtml
new file mode 100644
index 0000000000..3663e9ce61
--- /dev/null
+++ b/testing/web-platform/tests/html/rendering/replaced-elements/attributes-for-embedded-content-and-images/object_border_perc.xhtml
@@ -0,0 +1,9 @@
+<html xmlns='http://www.w3.org/1999/xhtml'>
+<head>
+<title>OBJECT - border=value in %</title>
+<link rel="match" href="object_border-ref.xhtml"/>
+</head>
+<body>
+<p><object data="../../../../images/blue.png" type="image/png" border="50%"></object></p>
+</body>
+</html>
diff --git a/testing/web-platform/tests/html/rendering/replaced-elements/attributes-for-embedded-content-and-images/object_border_pixel.xhtml b/testing/web-platform/tests/html/rendering/replaced-elements/attributes-for-embedded-content-and-images/object_border_pixel.xhtml
new file mode 100644
index 0000000000..55f7f0a3bf
--- /dev/null
+++ b/testing/web-platform/tests/html/rendering/replaced-elements/attributes-for-embedded-content-and-images/object_border_pixel.xhtml
@@ -0,0 +1,9 @@
+<html xmlns='http://www.w3.org/1999/xhtml'>
+<head>
+<title>OBJECT - border=pixel</title>
+<link rel="match" href="object_border-ref.xhtml"/>
+</head>
+<body>
+<p><object data="../../../../images/blue.png" type="image/png" border="50"></object></p>
+</body>
+</html>
diff --git a/testing/web-platform/tests/html/rendering/replaced-elements/attributes-for-embedded-content-and-images/picture-aspect-ratio.html b/testing/web-platform/tests/html/rendering/replaced-elements/attributes-for-embedded-content-and-images/picture-aspect-ratio.html
new file mode 100644
index 0000000000..939d7895c3
--- /dev/null
+++ b/testing/web-platform/tests/html/rendering/replaced-elements/attributes-for-embedded-content-and-images/picture-aspect-ratio.html
@@ -0,0 +1,242 @@
+<!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:not([nowidth]) {
+ width: 100%;
+ max-width: 100px;
+ height: auto;
+ }
+</style>
+<picture>
+ <source srcset="/images/green-100x50.png"></source>
+ <img>
+</picture>
+
+<picture>
+ <source srcset="/images/green-100x50.png" width="100" height="100"></source>
+ <img>
+</picture>
+
+<picture>
+ <source srcset="/images/green-100x50.png" width="100" height="100"></source>
+ <img width="50" height="100">
+</picture>
+
+<picture>
+ <source srcset="/images/green-100x50.png" width="100" height="100" id="twosource-s1"></source>
+ <source srcset="/images/green-100x50.png" width="300" height="150"></source>
+ <img id="twosource-img">
+</picture>
+
+<div style="width: 100px;">
+ <picture>
+ <source srcset="/images/green-100x50.png" width="100%" height="50%" id="percent-src"></source>
+ <img style="contain:size;" id="percent-img" nowidth="true">
+ </picture>
+</div>
+
+<picture>
+ <source srcset="/images/green-100x50.png" width="100abc" height="50abc" id="trailing-src"></source>
+ <img style="contain:size;" id="trailing-img" nowidth="true">
+</picture>
+
+<script>
+let guard = async_test("source width and height attributes are used to infer aspect-ratio in <picture>");
+function assert_ratio(img, expected, description) {
+ let epsilon = 0.001;
+ assert_approx_equals(parseFloat(getComputedStyle(img).width, 10) / parseFloat(getComputedStyle(img).height, 10),
+ expected, epsilon, description);
+}
+
+function createPicture(width, height) {
+ var picture = document.createElement("picture");
+ var source = document.createElement("source");
+ if (width !== undefined)
+ source.setAttribute("width", width);
+ if (height !== undefined)
+ source.setAttribute("height", height);
+ source.setAttribute("srcset", "/images/green.png");
+ picture.appendChild(source);
+ var img = document.createElement("img");
+ picture.appendChild(img);
+ document.body.appendChild(picture);
+ return img;
+}
+
+function assert_cs(img, val) {
+ assert_equals(getComputedStyle(img).aspectRatio, val);
+}
+
+// Create and append a new image and immediately check the ratio.
+// This is not racy because the spec requires the user agent to queue a task:
+// https://html.spec.whatwg.org/multipage/images.html#updating-the-image-data
+test(function() {
+ var img = createPicture(100, 100);
+ assert_ratio(img, 1.0);
+ assert_cs(img, "auto 100 / 100");
+ img.style.display = "none";
+ img.setAttribute("nowidth", "true");
+ assert_equals(getComputedStyle(img).width, "100px");
+ assert_equals(getComputedStyle(img).height, "100px");
+ var source = img.previousSibling;
+ assert_equals(getComputedStyle(source).width, "auto");
+ assert_equals(getComputedStyle(source).height, "auto");
+}, "Computed style for width/height/aspect-ratio");
+
+test(function() {
+ img = createPicture(200, 100);
+ img.setAttribute("width", 250);
+ img.setAttribute("height", 50);
+ assert_ratio(img, 2.0);
+ assert_cs(img, "auto 200 / 100");
+ img.style.display = "none";
+ img.setAttribute("nowidth", "true");
+ assert_equals(getComputedStyle(img).width, "200px");
+ assert_equals(getComputedStyle(img).height, "100px");
+ source = img.previousSibling;
+ assert_equals(getComputedStyle(source).width, "auto");
+ assert_equals(getComputedStyle(source).height, "auto");
+}, "Source width/height should take precedence over img attributes.");
+
+test(function() {
+ img.parentNode.removeChild(img.previousSibling);
+ assert_cs(img, "auto 250 / 50");
+ img.src = "/images/green.png";
+ assert_ratio(img, 5.0);
+ img.style.display = "none";
+ img.setAttribute("nowidth", "true");
+ assert_equals(getComputedStyle(img).width, "250px");
+ assert_equals(getComputedStyle(img).height, "50px");
+}, "Make sure style gets invalidated correctly when the source gets removed.");
+
+test(function() {
+ img = createPicture(100, undefined);
+ img.setAttribute("width", 200);
+ img.setAttribute("height", 100);
+ assert_cs(img, "auto");
+ img.style.display = "none";
+ img.setAttribute("nowidth", "true");
+ assert_equals(getComputedStyle(img).width, "100px");
+ assert_equals(getComputedStyle(img).height, "auto");
+}, "If the <source> has only one of width/height, we don't get an aspect ratio, even if the <img> has both.");
+
+test(function() {
+ img = createPicture(undefined, undefined);
+ img.setAttribute("width", 200);
+ img.setAttribute("height", 100);
+ assert_cs(img, "auto 200 / 100");
+}, "If we don't have width/height on the source, we fall back to width/height on the <img>.");
+
+test(function() {
+ img = createPicture(100, undefined);
+ img.parentNode.style.display = "none";
+ img.setAttribute("width", "200");
+ img.setAttribute("height", "300");
+ img.setAttribute("nowidth", "true");
+ assert_cs(img, "auto");
+ assert_equals(getComputedStyle(img).width, "100px");
+ assert_equals(getComputedStyle(img).height, "auto");
+}, "If we only have one width attribute, we should get width mapped but no aspect ratio, even if <img> has attributes.");
+
+test(function() {
+ img = createPicture(undefined, 100);
+ img.parentNode.style.display = "none";
+ img.setAttribute("width", "200");
+ img.setAttribute("height", "300");
+ img.setAttribute("nowidth", "true");
+ assert_cs(img, "auto");
+ assert_equals(getComputedStyle(img).width, "auto");
+ assert_equals(getComputedStyle(img).height, "100px");
+}, "If we only have height attribute, we should get height mapped but no aspect ratio, even if <img> has attributes.");
+
+test(function() {
+ img = createPicture(100, 100);
+ assert_cs(img, "auto 100 / 100");
+ img.previousSibling.setAttribute("height", "300");
+ assert_cs(img, "auto 100 / 300");
+ img.previousSibling.setAttribute("width", "10");
+ assert_cs(img, "auto 10 / 300");
+ img.style.display = "none";
+ img.setAttribute("nowidth", "true");
+ assert_equals(getComputedStyle(img).width, "10px");
+ assert_equals(getComputedStyle(img).height, "300px");
+}, "Dynamically changing width/height should change computed style");
+
+test(function() {
+ img = document.getElementById("twosource-img");
+ assert_cs(img, "auto 100 / 100");
+ source = document.getElementById("twosource-s1");
+ source.setAttribute("type", "x-foo/x-bar");
+ // We should now match the second source
+ assert_cs(img, "auto 300 / 150");
+ img.style.display = "none";
+ img.setAttribute("nowidth", "true");
+ assert_equals(getComputedStyle(img).width, "300px");
+ assert_equals(getComputedStyle(img).height, "150px");
+}, "Changing which <source> matches should change computed style");
+
+test(function() {
+ img = document.getElementById("percent-img");
+ assert_equals(img.offsetWidth, 100);
+ assert_equals(img.offsetHeight, 0);
+ assert_cs(img, "auto");
+ source = document.getElementById("percent-src");
+ assert_equals(source.width, 100);
+ assert_equals(source.height, 50);
+ img.style.display = "none";
+ img.setAttribute("nowidth", "true");
+ assert_equals(getComputedStyle(img).width, "100%");
+ assert_equals(getComputedStyle(img).height, "50%");
+}, "Percentages on source should be ignored for aspect-ratio but used for width/height.");
+
+test(function() {
+ img = document.getElementById("trailing-img");
+ assert_equals(img.offsetWidth, 100);
+ assert_equals(img.offsetHeight, 50);
+ assert_cs(img, "auto 100 / 50");
+ source = document.getElementById("trailing-src");
+ assert_equals(source.width, 100);
+ assert_equals(source.height, 50);
+ img.style.display = "none";
+ img.setAttribute("nowidth", "true");
+ assert_equals(getComputedStyle(img).width, "100px");
+ assert_equals(getComputedStyle(img).height, "50px");
+}, "Trailing garbage should be ignored but not make the attribute invalid");
+
+onload = function() {
+ let images = document.querySelectorAll("img");
+ test(function() {
+ var img = images[0];
+ assert_ratio(img, 2.0, "2.0 is the original aspect ratio of green-100x50.png");
+ assert_cs(img, "auto");
+ img.style.display = "none";
+ img.setAttribute("nowidth", "true");
+ assert_equals(getComputedStyle(img).width, "auto");
+ assert_equals(getComputedStyle(img).height, "auto");
+ }, "Loaded picture test: Both <source> and <img> are without width and height attributes");
+
+ test(function () {
+ img = images[1];
+ assert_ratio(img, 2.0, "Loaded image's aspect ratio, at least by default, overrides width / height ratio.");
+ assert_cs(img, "auto 100 / 100");
+ img.style.display = "none";
+ img.setAttribute("nowidth", "true");
+ assert_equals(getComputedStyle(img).width, "100px");
+ assert_equals(getComputedStyle(img).height, "100px");
+ }, "Loaded picture test: <source> with width and height attributes, <img> without width and height attributes");
+
+ test(function () {
+ img = images[2];
+ assert_ratio(img, 2.0, "Loaded image's aspect ratio, at least by default, overrides width / height ratio (2).");
+ assert_cs(img, "auto 100 / 100");
+ img.style.display = "none";
+ img.setAttribute("nowidth", "true");
+ assert_equals(getComputedStyle(img).width, "100px");
+ assert_equals(getComputedStyle(img).height, "100px");
+ }, "Loaded picture test: Both <source> and <img> are with width and height attributes");
+
+ guard.done();
+};
+</script>
diff --git a/testing/web-platform/tests/html/rendering/replaced-elements/attributes-for-embedded-content-and-images/resources/aspect-ratio.js b/testing/web-platform/tests/html/rendering/replaced-elements/attributes-for-embedded-content-and-images/resources/aspect-ratio.js
new file mode 100644
index 0000000000..c6826f271a
--- /dev/null
+++ b/testing/web-platform/tests/html/rendering/replaced-elements/attributes-for-embedded-content-and-images/resources/aspect-ratio.js
@@ -0,0 +1,14 @@
+function test_computed_style_aspect_ratio(tag, attributes, expected) {
+ test(function() {
+ var elem = document.createElement(tag);
+ for (name in attributes) {
+ let val = attributes[name];
+ if (val !== null)
+ elem.setAttribute(name, val);
+ }
+ document.body.appendChild(elem);
+ let aspectRatio = getComputedStyle(elem).aspectRatio;
+ assert_equals(aspectRatio, expected);
+ elem.remove();
+ }, `Computed style test: ${tag} with ${JSON.stringify(attributes)}`);
+}
diff --git a/testing/web-platform/tests/html/rendering/replaced-elements/attributes-for-embedded-content-and-images/video-aspect-ratio.html b/testing/web-platform/tests/html/rendering/replaced-elements/attributes-for-embedded-content-and-images/video-aspect-ratio.html
new file mode 100644
index 0000000000..119523d250
--- /dev/null
+++ b/testing/web-platform/tests/html/rendering/replaced-elements/attributes-for-embedded-content-and-images/video-aspect-ratio.html
@@ -0,0 +1,72 @@
+<!doctype html>
+<title>Video width and height attributes are used to infer aspect-ratio</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/media.js"></script>
+<script src="resources/aspect-ratio.js"></script>
+<style>
+ video {
+ width: 100%;
+ max-width: 100px;
+ height: auto;
+ }
+</style>
+<body>
+<video width="250" height="100" id="contained" style="contain: size;"></video>
+<script>
+function assert_ratio(img, expected) {
+ let epsilon = 0.001;
+ assert_approx_equals(parseInt(getComputedStyle(img).width, 10) / parseInt(getComputedStyle(img).height, 10), expected, epsilon);
+}
+
+function test_computed_style(width, height, expected) {
+ test_computed_style_aspect_ratio("video", {width: width, height: height}, expected);
+}
+
+promise_test(async function() {
+ {
+ let video = document.getElementById("contained");
+ video.src = getVideoURI('/media/2x2-green');
+ assert_ratio(video, 2.5, "contain:size aspect ratio");
+ }
+
+ // Create and append a new video and immediately check the ratio.
+ // This is not racy because the spec requires the user agent to queue a task:
+ // https://html.spec.whatwg.org/multipage/media.html#concept-media-load-algorithm
+ {
+ let video = document.createElement("video");
+ video.setAttribute("width", "250");
+ video.setAttribute("height", "100");
+ video.src = getVideoURI('/media/2x2-green');
+ document.body.appendChild(video);
+ assert_ratio(video, 2.5, "aspect ratio for regular video before load");
+ await new Promise(r => video.addEventListener("loadeddata", r, { once: true }));
+ // When loaded this video is square.
+ assert_ratio(video, 1, "aspect ratio for regular video after load");
+ }
+
+ // Same but with auto width.
+ {
+ let video = document.createElement("video");
+ video.setAttribute("width", "250");
+ video.setAttribute("height", "100");
+ video.style.width = "auto";
+ video.src = getVideoURI('/media/2x2-green');
+ document.body.appendChild(video);
+ assert_ratio(video, 2.5, "aspect ratio for regular video with width: auto before load");
+ await new Promise(r => video.addEventListener("loadeddata", r, { once: true }));
+ assert_ratio(video, 1, "aspect ratio for regular video with width: auto after load");
+ }
+
+ test_computed_style("10", "20", "auto 10 / 20");
+ test_computed_style("0.5", "1.5", "auto 0.5 / 1.5");
+ test_computed_style("0", "1", "auto 0 / 1");
+ test_computed_style("1", "0", "auto 1 / 0");
+ test_computed_style("0", "0", "auto 0 / 0");
+ test_computed_style(null, null, "auto");
+ test_computed_style("10", null, "auto");
+ test_computed_style(null, "20", "auto");
+ test_computed_style("xx", "20", "auto");
+ test_computed_style("10%", "20", "auto");
+});
+</script>
diff --git a/testing/web-platform/tests/html/rendering/replaced-elements/attributes-for-embedded-content-and-images/video-intrinsic-width-height.html b/testing/web-platform/tests/html/rendering/replaced-elements/attributes-for-embedded-content-and-images/video-intrinsic-width-height.html
new file mode 100644
index 0000000000..74989be521
--- /dev/null
+++ b/testing/web-platform/tests/html/rendering/replaced-elements/attributes-for-embedded-content-and-images/video-intrinsic-width-height.html
@@ -0,0 +1,41 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>video element intrinsic width/height</title>
+ <link rel="author" title="Sammy Gill" href="sammy.gill@apple.com" />
+ <link rel="help" href="https://github.com/w3c/csswg-drafts/issues/7524" />
+ <link rel="help" href="https://html.spec.whatwg.org/multipage/rendering.html#replaced-elements" />
+ <link rel="help" href="https://drafts.csswg.org/css-sizing-4/#aspect-ratio" />
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ </head>
+ <body>
+ <div id="log"></div>
+ <video title="no width/height attributes"
+ data-expected-width="300" data-expected-height="150"></video>
+ <video title="only width attribute"
+ data-expected-width="100" data-expected-height="50"
+ width="100"></video>
+ <video title="only height attribute"
+ data-expected-width="200" data-expected-height="100"
+ height="100"></video>
+ <video title="both width/height attributes"
+ data-expected-width="100" data-expected-height="100"
+ width="100" height="100"></video>
+ <!-- A width:height ratio other than 2:1 and overriding the specified style must be used to
+ verify that width/height does not influence intrinsic ratio -->
+ <video title="both width/height attributes and style"
+ data-expected-width="300" data-expected-height="300"
+ width="100" height="100" style="width: auto; height: auto"></video>
+ <script>
+ Array.prototype.forEach.call(document.querySelectorAll('video'), function(video)
+ {
+ test(function()
+ {
+ assert_equals(video.clientWidth, parseInt(video.dataset.expectedWidth), "width");
+ assert_equals(video.clientHeight, parseInt(video.dataset.expectedHeight), "height");
+ }, video.title);
+ });
+ </script>
+ </body>
+</html>
diff --git a/testing/web-platform/tests/html/rendering/replaced-elements/embedded-content-rendering-rules/audio-controls-001.html b/testing/web-platform/tests/html/rendering/replaced-elements/embedded-content-rendering-rules/audio-controls-001.html
new file mode 100644
index 0000000000..eeb4368aaa
--- /dev/null
+++ b/testing/web-platform/tests/html/rendering/replaced-elements/embedded-content-rendering-rules/audio-controls-001.html
@@ -0,0 +1,7 @@
+<!DOCTYPE html>
+<title>HTML audio with controls</title>
+<link rel="author" title="Mozilla" href="https://www.mozilla.org/">
+<link rel="help" href="https://html.spec.whatwg.org/multipage/rendering.html#embedded-content-rendering-rules">
+<link rel="mismatch" href="/common/blank.html">
+
+<audio controls></audio>
diff --git a/testing/web-platform/tests/html/rendering/replaced-elements/embedded-content-rendering-rules/audio-controls-002.html b/testing/web-platform/tests/html/rendering/replaced-elements/embedded-content-rendering-rules/audio-controls-002.html
new file mode 100644
index 0000000000..678ba7281e
--- /dev/null
+++ b/testing/web-platform/tests/html/rendering/replaced-elements/embedded-content-rendering-rules/audio-controls-002.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<title>HTML audio with controls via Web APIs</title>
+<link rel="author" title="Mozilla" href="https://www.mozilla.org/">
+<link rel="help" href="https://html.spec.whatwg.org/multipage/rendering.html#embedded-content-rendering-rules">
+<link rel="mismatch" href="/common/blank.html">
+
+<audio id="target"></audio>
+
+<script>
+ document.body.offsetTop;
+ document.getElementById("target").setAttribute("controls", "");
+</script>
diff --git a/testing/web-platform/tests/html/rendering/replaced-elements/embedded-content-rendering-rules/audio-without-controls.html b/testing/web-platform/tests/html/rendering/replaced-elements/embedded-content-rendering-rules/audio-without-controls.html
new file mode 100644
index 0000000000..8cc134d6d6
--- /dev/null
+++ b/testing/web-platform/tests/html/rendering/replaced-elements/embedded-content-rendering-rules/audio-without-controls.html
@@ -0,0 +1,11 @@
+<!DOCTYPE html>
+<title>HTML audio without controls</title>
+<link rel="author" title="Mozilla" href="https://www.mozilla.org/">
+<link rel="help" href="https://html.spec.whatwg.org/multipage/rendering.html#embedded-content-rendering-rules">
+<link rel="match" href="../../../../css/reference/ref-filled-green-100px-square.xht" />
+
+<p>Test passes if there is a filled green square and <strong>no red</strong>.</p>
+
+<div style="width: 100px; height: 100px; background: green;">
+ <audio style="display: block; width: 100px; height: 100px; background: red;"></audio>
+</div>
diff --git a/testing/web-platform/tests/html/rendering/replaced-elements/embedded-content-rendering-rules/canvas-fallback-ref.html b/testing/web-platform/tests/html/rendering/replaced-elements/embedded-content-rendering-rules/canvas-fallback-ref.html
new file mode 100644
index 0000000000..9077591f46
--- /dev/null
+++ b/testing/web-platform/tests/html/rendering/replaced-elements/embedded-content-rendering-rules/canvas-fallback-ref.html
@@ -0,0 +1,4 @@
+<!doctype html>
+<meta charset=utf-8>
+<title>Canvas fallback content</title>
+<p>The word "FAIL" should not be visible below this line.
diff --git a/testing/web-platform/tests/html/rendering/replaced-elements/embedded-content-rendering-rules/canvas-fallback.html b/testing/web-platform/tests/html/rendering/replaced-elements/embedded-content-rendering-rules/canvas-fallback.html
new file mode 100644
index 0000000000..01df0c547a
--- /dev/null
+++ b/testing/web-platform/tests/html/rendering/replaced-elements/embedded-content-rendering-rules/canvas-fallback.html
@@ -0,0 +1,26 @@
+<!doctype html>
+<meta charset=utf-8>
+<title>Canvas fallback content</title>
+<link rel=match href=canvas-fallback-ref.html>
+<style>
+canvas {
+ height: 2em; /* avoid causing scrollbar for 600x600 viewport */
+}
+
+#canvas2 {
+ display: inline;
+}
+
+#canvas3 {
+ display: block;
+}
+
+#canvas4 {
+ display: table;
+}
+</style>
+<p>The word "FAIL" should not be visible below this line.
+<p><canvas id=canvas1>FAIL</canvas>
+<p><canvas id=canvas2>FAIL</canvas>
+<p><canvas id=canvas3>FAIL</canvas>
+<p><canvas id=canvas4>FAIL</canvas>
diff --git a/testing/web-platform/tests/html/rendering/replaced-elements/embedded-content-rendering-rules/canvas-update-with-border-object-fit-ref.html b/testing/web-platform/tests/html/rendering/replaced-elements/embedded-content-rendering-rules/canvas-update-with-border-object-fit-ref.html
new file mode 100644
index 0000000000..3133ac86f3
--- /dev/null
+++ b/testing/web-platform/tests/html/rendering/replaced-elements/embedded-content-rendering-rules/canvas-update-with-border-object-fit-ref.html
@@ -0,0 +1,4 @@
+<!doctype html>
+<div style="width: 200px; height: 100px; background: black; border: 100px solid blue; padding-left: 100px">
+ <div style="width: 100px; height: 100px; background: green"></div>
+</div>
diff --git a/testing/web-platform/tests/html/rendering/replaced-elements/embedded-content-rendering-rules/canvas-update-with-border-object-fit.html b/testing/web-platform/tests/html/rendering/replaced-elements/embedded-content-rendering-rules/canvas-update-with-border-object-fit.html
new file mode 100644
index 0000000000..b20db66eb9
--- /dev/null
+++ b/testing/web-platform/tests/html/rendering/replaced-elements/embedded-content-rendering-rules/canvas-update-with-border-object-fit.html
@@ -0,0 +1,31 @@
+<!doctype html>
+<title>Verifies canvas with object-fit and border correctly updates</title>
+<link rel="match" href="canvas-update-with-border-object-fit-ref.html">
+<html class="reftest-wait">
+ <div style="width: 300px; height: 100px; background: black; border: 100px solid blue">
+ <canvas id="target" width="1000" height="1000"
+ style="object-fit: contain; object-position: center; width: 100%; height: 100%">
+ </canvas>
+ </div>
+</html>
+<script>
+var ctx = target.getContext("2d");
+ctx.fillStyle = "red";
+ctx.fillRect(0, 0, target.width, target.height);
+
+var x=0, y=0, step=500;
+ctx.fillStyle = "green";
+function drawRect() {
+ ctx.fillRect(x, y, step, step);
+ x += step;
+ if (x >= target.width) {
+ x = 0;
+ y += step;
+ }
+ if (y >= target.height)
+ document.documentElement.classList.remove("reftest-wait");
+ else
+ requestAnimationFrame(drawRect);
+}
+drawRect();
+</script>
diff --git a/testing/web-platform/tests/html/rendering/replaced-elements/embedded-content-rendering-rules/canvas_scale.html b/testing/web-platform/tests/html/rendering/replaced-elements/embedded-content-rendering-rules/canvas_scale.html
new file mode 100644
index 0000000000..cdc4647534
--- /dev/null
+++ b/testing/web-platform/tests/html/rendering/replaced-elements/embedded-content-rendering-rules/canvas_scale.html
@@ -0,0 +1,23 @@
+<!doctype html>
+<meta charset="utf-8">
+<title>Verify that canvases are scaled up to their computed size</title>
+<link rel="match" href="canvas_scale_ref.html">
+<style>
+canvas {
+ width: 20px;
+ height: 20px;
+}
+div {
+ line-height: 0;
+}
+</style>
+<div><canvas width="16" height="16" data-color="#FF00FF"></canvas><canvas width="16" height="16" data-color="#00FF00"></canvas></div>
+<div><canvas width="16" height="16" data-color="#0000FF"></canvas><canvas width="16" height="16" data-color="#FF00FF"></canvas></div>
+<script>
+var canvases = document.getElementsByTagName('canvas');
+for (var i = 0; i < canvases.length; i++) {
+ var ctx = canvases[i].getContext('2d');
+ ctx.fillStyle = canvases[i].getAttribute('data-color');
+ ctx.fillRect(0, 0, 16, 16);
+}
+</script>
diff --git a/testing/web-platform/tests/html/rendering/replaced-elements/embedded-content-rendering-rules/canvas_scale_ref.html b/testing/web-platform/tests/html/rendering/replaced-elements/embedded-content-rendering-rules/canvas_scale_ref.html
new file mode 100644
index 0000000000..2d1756f856
--- /dev/null
+++ b/testing/web-platform/tests/html/rendering/replaced-elements/embedded-content-rendering-rules/canvas_scale_ref.html
@@ -0,0 +1,14 @@
+<!doctype html>
+<meta charset="utf-8">
+<style>
+span {
+ display: inline-block;
+ width: 20px;
+ height: 20px;
+}
+div {
+ line-height: 0;
+}
+</style>
+<div><span style="background-color: #FF00FF"></span><span style="background-color: #00FF00"></span></div>
+<div><span style="background-color: #0000FF"></span><span style="background-color: #FF00FF"></span></div>
diff --git a/testing/web-platform/tests/html/rendering/replaced-elements/embedded-content-rendering-rules/canvas_without_context_a.html b/testing/web-platform/tests/html/rendering/replaced-elements/embedded-content-rendering-rules/canvas_without_context_a.html
new file mode 100644
index 0000000000..b7398f8d59
--- /dev/null
+++ b/testing/web-platform/tests/html/rendering/replaced-elements/embedded-content-rendering-rules/canvas_without_context_a.html
@@ -0,0 +1,15 @@
+<!doctype html>
+<meta charset="utf-8">
+<link rel="match" href="canvas_without_context_ref.html">
+<style>
+ div {
+ background-color: green;
+ width: 20px;
+ height: 20px;
+ }
+</style>
+</head>
+<body>
+<div><canvas width="20" height="20"></canvas></div>
+</body>
+</html>
diff --git a/testing/web-platform/tests/html/rendering/replaced-elements/embedded-content-rendering-rules/canvas_without_context_ref.html b/testing/web-platform/tests/html/rendering/replaced-elements/embedded-content-rendering-rules/canvas_without_context_ref.html
new file mode 100644
index 0000000000..ae0c9c8c8e
--- /dev/null
+++ b/testing/web-platform/tests/html/rendering/replaced-elements/embedded-content-rendering-rules/canvas_without_context_ref.html
@@ -0,0 +1,14 @@
+<html>
+<head>
+<style>
+ div {
+ background-color: green;
+ width: 20px;
+ height: 20px;
+ }
+</style>
+</head>
+<body>
+<div></div>
+</body>
+</html>
diff --git a/testing/web-platform/tests/html/rendering/replaced-elements/embedded-content/audio-controls-intrinsic-size.html b/testing/web-platform/tests/html/rendering/replaced-elements/embedded-content/audio-controls-intrinsic-size.html
new file mode 100644
index 0000000000..6cbbcd02f5
--- /dev/null
+++ b/testing/web-platform/tests/html/rendering/replaced-elements/embedded-content/audio-controls-intrinsic-size.html
@@ -0,0 +1,25 @@
+<!doctype html>
+<title>Audio intrinsic size doesn't depend on its max size</title>
+<link rel="help" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1683979">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<div style="display: inline-block">
+ <audio controls style="max-width: 99%" id="test"></audio>
+</div>
+<script>
+let audio = document.getElementById("test");
+
+function computeSize() {
+ return audio.getBoundingClientRect().width;
+}
+
+let size = computeSize();
+async_test(function(t) {
+ requestAnimationFrame(t.step_func(function() {
+ assert_equals(computeSize(), size, "Shouldn't have changed size");
+ requestAnimationFrame(t.step_func_done(function() {
+ assert_equals(computeSize(), size, "Shouldn't have changed size");
+ }));
+ }));
+});
+</script>
diff --git a/testing/web-platform/tests/html/rendering/replaced-elements/embedded-content/change-src-while-not-displayed-ref.html b/testing/web-platform/tests/html/rendering/replaced-elements/embedded-content/change-src-while-not-displayed-ref.html
new file mode 100644
index 0000000000..96500cf0bd
--- /dev/null
+++ b/testing/web-platform/tests/html/rendering/replaced-elements/embedded-content/change-src-while-not-displayed-ref.html
@@ -0,0 +1,2 @@
+<!DOCTYPE html>
+<embed style="display:block;" src="data:text/html,PASS">
diff --git a/testing/web-platform/tests/html/rendering/replaced-elements/embedded-content/change-src-while-not-displayed.html b/testing/web-platform/tests/html/rendering/replaced-elements/embedded-content/change-src-while-not-displayed.html
new file mode 100644
index 0000000000..521a816337
--- /dev/null
+++ b/testing/web-platform/tests/html/rendering/replaced-elements/embedded-content/change-src-while-not-displayed.html
@@ -0,0 +1,21 @@
+<!DOCTYPE html>
+<html class="reftest-wait">
+<link rel="author" title="Morten Stenshorne" href="mailto:mstensho@chromium.org">
+<link rel="help" href="https://bugs.chromium.org/p/chromium/issues/detail?id=1240261">
+<link rel="match" href="change-src-while-not-displayed-ref.html">
+<embed id="embed" style="display:block;" src="data:text/html,FAIL">
+<script>
+ onload = function() {
+ document.body.offsetTop;
+ embed.style.display = "none";
+ document.body.offsetTop;
+ embed.src = "data:text/html,PASS";
+ document.body.offsetTop;
+ embed.style.display = "block";
+ requestAnimationFrame(()=> {
+ requestAnimationFrame(()=> {
+ document.documentElement.classList.remove('reftest-wait');
+ });
+ });
+ }
+</script>
diff --git a/testing/web-platform/tests/html/rendering/replaced-elements/embedded-content/cross-domain-iframe-in-multicol.sub-ref.html b/testing/web-platform/tests/html/rendering/replaced-elements/embedded-content/cross-domain-iframe-in-multicol.sub-ref.html
new file mode 100644
index 0000000000..2645ed459f
--- /dev/null
+++ b/testing/web-platform/tests/html/rendering/replaced-elements/embedded-content/cross-domain-iframe-in-multicol.sub-ref.html
@@ -0,0 +1,3 @@
+<!doctype html>
+<div style="height: 100px"></div>
+<iframe id=myframe src="/images/green.png"></iframe>
diff --git a/testing/web-platform/tests/html/rendering/replaced-elements/embedded-content/cross-domain-iframe-in-multicol.sub.html b/testing/web-platform/tests/html/rendering/replaced-elements/embedded-content/cross-domain-iframe-in-multicol.sub.html
new file mode 100644
index 0000000000..e39e2bc764
--- /dev/null
+++ b/testing/web-platform/tests/html/rendering/replaced-elements/embedded-content/cross-domain-iframe-in-multicol.sub.html
@@ -0,0 +1,21 @@
+<!doctype html>
+<html class="reftest-wait">
+<title>Rendering of cross-domain iframe element in multicol</title>
+<link rel="match" href="cross-domain-iframe-in-multicol.sub-ref.html">
+<link rel="help" href="https://html.spec.whatwg.org/multipage/rendering.html#embedded-content-rendering-rules">
+<meta name="assert" content="Checks that cross-domain iframe in multicol is correctly rendered">
+<div style="columns: 2; height: 300px">
+ <div style="height: 100px"></div>
+ <iframe id=myframe src="http://{{domains[www1]}}:{{ports[http][0]}}/images/green.png"></iframe>
+ <div style="height: 100px"></div>
+</div>
+<script>
+ myframe.onload = () => {
+ requestAnimationFrame(() => {
+ requestAnimationFrame(() => {
+ document.documentElement.classList.remove('reftest-wait');
+ });
+ });
+ }
+</script>
+</html>
diff --git a/testing/web-platform/tests/html/rendering/replaced-elements/embedded-content/cross-domain-iframe.sub-ref.html b/testing/web-platform/tests/html/rendering/replaced-elements/embedded-content/cross-domain-iframe.sub-ref.html
new file mode 100644
index 0000000000..a3579eee74
--- /dev/null
+++ b/testing/web-platform/tests/html/rendering/replaced-elements/embedded-content/cross-domain-iframe.sub-ref.html
@@ -0,0 +1,3 @@
+<!doctype html>
+<title>Test reference</title>
+<iframe src="/images/green.png"></iframe>
diff --git a/testing/web-platform/tests/html/rendering/replaced-elements/embedded-content/cross-domain-iframe.sub.html b/testing/web-platform/tests/html/rendering/replaced-elements/embedded-content/cross-domain-iframe.sub.html
new file mode 100644
index 0000000000..8d9b8cd5b4
--- /dev/null
+++ b/testing/web-platform/tests/html/rendering/replaced-elements/embedded-content/cross-domain-iframe.sub.html
@@ -0,0 +1,17 @@
+<!doctype html>
+<html class="reftest-wait">
+<title>Rendering of iframe element with src attribute from another domain</title>
+<link rel="match" href="cross-domain-iframe.sub-ref.html">
+<link rel="help" href="https://html.spec.whatwg.org/multipage/rendering.html#embedded-content-rendering-rules">
+<meta name="assert" content="Checks that iframe content is correctly rendered even if it is retrieved from a different domain.">
+<iframe id=myframe src="http://{{domains[www1]}}:{{ports[http][0]}}/images/green.png"></iframe>
+<script>
+ myframe.onload = () => {
+ requestAnimationFrame(() => {
+ requestAnimationFrame(() => {
+ document.documentElement.classList.remove('reftest-wait');
+ });
+ });
+ }
+</script>
+</html>
diff --git a/testing/web-platform/tests/html/rendering/replaced-elements/embedded-content/object-fallback-text-decoration-ref.html b/testing/web-platform/tests/html/rendering/replaced-elements/embedded-content/object-fallback-text-decoration-ref.html
new file mode 100644
index 0000000000..9481e80ac8
--- /dev/null
+++ b/testing/web-platform/tests/html/rendering/replaced-elements/embedded-content/object-fallback-text-decoration-ref.html
@@ -0,0 +1,3 @@
+<!doctype html>
+<title>Test reference</title>
+<span style="text-decoration:underline">This text should be underlined.</span>
diff --git a/testing/web-platform/tests/html/rendering/replaced-elements/embedded-content/object-fallback-text-decoration.html b/testing/web-platform/tests/html/rendering/replaced-elements/embedded-content/object-fallback-text-decoration.html
new file mode 100644
index 0000000000..89657ef8a2
--- /dev/null
+++ b/testing/web-platform/tests/html/rendering/replaced-elements/embedded-content/object-fallback-text-decoration.html
@@ -0,0 +1,9 @@
+<!doctype html>
+<title>Rendering of object element fallback with text-decoration</title>
+<link rel="match" href="object-fallback-text-decoration-ref.html">
+<link rel="help" href="https://html.spec.whatwg.org/multipage/rendering.html#embedded-content-rendering-rules">
+<meta name="assert" content="Checks that text-decoration applies to rendered object fallback.">
+<style>
+ object { text-decoration: underline; }
+</style>
+<object>This text should be underlined.</object>
diff --git a/testing/web-platform/tests/html/rendering/replaced-elements/embedded-content/resources/tall.html b/testing/web-platform/tests/html/rendering/replaced-elements/embedded-content/resources/tall.html
new file mode 100644
index 0000000000..3de84d0b3f
--- /dev/null
+++ b/testing/web-platform/tests/html/rendering/replaced-elements/embedded-content/resources/tall.html
@@ -0,0 +1,6 @@
+<!DOCTYPE html>
+<body style="background: blue">
+ <div style="position: fixed; left: 0; top: 0; width: 100%; height: 100px; background: yellow"></div>
+ <div style="position: fixed; left: 0; bottom: 0; width: 100%; height: 100px; background: green"></div>
+ <div style="height: 2000px"></div>
+</body>
diff --git a/testing/web-platform/tests/html/rendering/replaced-elements/embedded-content/tall-cross-domain-iframe-in-scrolled.sub-ref.html b/testing/web-platform/tests/html/rendering/replaced-elements/embedded-content/tall-cross-domain-iframe-in-scrolled.sub-ref.html
new file mode 100644
index 0000000000..01c1e2f86f
--- /dev/null
+++ b/testing/web-platform/tests/html/rendering/replaced-elements/embedded-content/tall-cross-domain-iframe-in-scrolled.sub-ref.html
@@ -0,0 +1,9 @@
+<!doctype html>
+<html class="reftest-wait">
+<iframe id=myframe style="width: 300px; height: 1000px" src="resources/tall.html"></iframe>
+<div style="height: 2000px"></div>
+<script>
+ window.scrollTo(0, 700);
+ myframe.onload = () => document.documentElement.classList.remove('reftest-wait');
+</script>
+</html>
diff --git a/testing/web-platform/tests/html/rendering/replaced-elements/embedded-content/tall-cross-domain-iframe-in-scrolled.sub.html b/testing/web-platform/tests/html/rendering/replaced-elements/embedded-content/tall-cross-domain-iframe-in-scrolled.sub.html
new file mode 100644
index 0000000000..865be7c883
--- /dev/null
+++ b/testing/web-platform/tests/html/rendering/replaced-elements/embedded-content/tall-cross-domain-iframe-in-scrolled.sub.html
@@ -0,0 +1,20 @@
+<!doctype html>
+<html class="reftest-wait">
+<title>Rendering of tall cross-domain iframe element in a scrolled window</title>
+<link rel="match" href="tall-cross-domain-iframe-in-scrolled.sub-ref.html">
+<link rel="help" href="https://html.spec.whatwg.org/multipage/rendering.html#embedded-content-rendering-rules">
+<meta name="assert" content="Checks that tall cross-domain iframe in a scrolled window is correctly rendered">
+<iframe id=myframe style="width: 300px; height: 1000px"
+ src="http://{{domains[www1]}}:{{ports[http][0]}}/html/rendering/replaced-elements/embedded-content/resources/tall.html"></iframe>
+<div style="height: 2000px"></div>
+<script>
+ window.scrollTo(0, 700);
+ myframe.onload = () => {
+ requestAnimationFrame(() => {
+ requestAnimationFrame(() => {
+ document.documentElement.classList.remove('reftest-wait');
+ });
+ });
+ }
+</script>
+</html>
diff --git a/testing/web-platform/tests/html/rendering/replaced-elements/embedded-content/video-controls-vertical-writing-mode-ref.html b/testing/web-platform/tests/html/rendering/replaced-elements/embedded-content/video-controls-vertical-writing-mode-ref.html
new file mode 100644
index 0000000000..e65bf6cbe8
--- /dev/null
+++ b/testing/web-platform/tests/html/rendering/replaced-elements/embedded-content/video-controls-vertical-writing-mode-ref.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<div>
+ <video controls></video>
+</div>
diff --git a/testing/web-platform/tests/html/rendering/replaced-elements/embedded-content/video-controls-vertical-writing-mode.html b/testing/web-platform/tests/html/rendering/replaced-elements/embedded-content/video-controls-vertical-writing-mode.html
new file mode 100644
index 0000000000..acd2588112
--- /dev/null
+++ b/testing/web-platform/tests/html/rendering/replaced-elements/embedded-content/video-controls-vertical-writing-mode.html
@@ -0,0 +1,8 @@
+<!DOCTYPE html>
+<meta charset=utf-8>
+<title>Video controls rendering in vertical-lr</title>
+<link rel="help" href="https://html.spec.whatwg.org/multipage/rendering.html#embedded-content-rendering-rules" />
+<link rel="match" href="video-controls-vertical-writing-mode-ref.html" />
+<div style="writing-mode:vertical-lr">
+ <video controls></video>
+</div>
diff --git a/testing/web-platform/tests/html/rendering/replaced-elements/images/blocked-by-csp-ref.html b/testing/web-platform/tests/html/rendering/replaced-elements/images/blocked-by-csp-ref.html
new file mode 100644
index 0000000000..f37d8a3ec9
--- /dev/null
+++ b/testing/web-platform/tests/html/rendering/replaced-elements/images/blocked-by-csp-ref.html
@@ -0,0 +1,5 @@
+<!doctype html>
+<title>Test reference</title>
+<style>img { border: solid; }</style>
+It should say PASS below:<br>
+<img alt="PASS">
diff --git a/testing/web-platform/tests/html/rendering/replaced-elements/images/blocked-by-csp.html b/testing/web-platform/tests/html/rendering/replaced-elements/images/blocked-by-csp.html
new file mode 100644
index 0000000000..2416e5dfd0
--- /dev/null
+++ b/testing/web-platform/tests/html/rendering/replaced-elements/images/blocked-by-csp.html
@@ -0,0 +1,8 @@
+<!doctype html>
+<title>Images behave the same when blocked by CSP as when failing to load/broken</title>
+<link rel="help" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1664156">
+<link rel="match" href="blocked-by-csp-ref.html">
+<meta http-equiv=content-security-policy content="img-src 'none'">
+<style>img { border: solid; }</style>
+It should say PASS below:<br>
+<img src=image alt="PASS">
diff --git a/testing/web-platform/tests/html/rendering/replaced-elements/images/img-sizes-auto.html b/testing/web-platform/tests/html/rendering/replaced-elements/images/img-sizes-auto.html
new file mode 100644
index 0000000000..cbdf769596
--- /dev/null
+++ b/testing/web-platform/tests/html/rendering/replaced-elements/images/img-sizes-auto.html
@@ -0,0 +1,53 @@
+<!doctype html>
+<title>default styles for &lt;img sizes=auto></title>
+<meta name="viewport" content="width=device-width">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/html/rendering/support/test-ua-stylesheet.js"></script>
+<style>
+/* Specify this bogus namespace, so the rules in this stylesheet only apply to the `fakeClone`d elements in #refs, not the HTML elements in #tests. */
+@namespace url(urn:not-html);
+
+img:is([sizes="auto" i], [sizes^="auto," i]) {
+ contain: size !important;
+ contain-intrinsic-size: 300px 150px;
+}
+</style>
+
+<style>
+/* Test !important */
+img.test-important { contain: style; contain-intrinsic-size: 30px 15px; }
+</style>
+
+<div id="log"></div>
+
+<div id="tests">
+ <img sizes=auto>
+ <img sizes=auto width=10 height=20>
+ <img sizes=AuTo>
+ <img sizes=auto,xyz>
+ <img sizes=AuTo,xyz>
+
+ <!-- UA style should not apply: -->
+ <img>
+ <img sizes>
+ <img sizes=xyz,auto>
+ <picture data-skip>
+ <source data-skip sizes=auto>
+ <img>
+ </picture>
+
+ <!-- Test !important -->
+ <img sizes=auto class=test-important>
+</div>
+
+<div id="refs"></div>
+
+<script>
+ const props = [
+ 'contain',
+ 'contain-intrinsic-size'
+ ];
+ runUAStyleTests(props);
+
+</script>
diff --git a/testing/web-platform/tests/html/rendering/replaced-elements/images/input-image-content-ref.html b/testing/web-platform/tests/html/rendering/replaced-elements/images/input-image-content-ref.html
new file mode 100644
index 0000000000..37af13329e
--- /dev/null
+++ b/testing/web-platform/tests/html/rendering/replaced-elements/images/input-image-content-ref.html
@@ -0,0 +1,7 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>Input type=image with CSS content.</title>
+<link rel="author" href="mailto:masonf@chromium.org">
+
+You should see a red dot.<br>
+<input type="image" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAHElEQVQI12P4//8/w38GIAXDIBKE0DHxgljNBAAO9TXL0Y4OHwAAAABJRU5ErkJggg==">
diff --git a/testing/web-platform/tests/html/rendering/replaced-elements/images/input-image-content.html b/testing/web-platform/tests/html/rendering/replaced-elements/images/input-image-content.html
new file mode 100644
index 0000000000..5376e8033f
--- /dev/null
+++ b/testing/web-platform/tests/html/rendering/replaced-elements/images/input-image-content.html
@@ -0,0 +1,14 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>Input type=image with CSS content.</title>
+<link rel="author" href="mailto:masonf@chromium.org">
+<link rel="match" href="input-image-content-ref.html">
+
+You should see a red dot.<br>
+<style>
+ input {
+ content: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAHElEQVQI12P4//8/w38GIAXDIBKE0DHxgljNBAAO9TXL0Y4OHwAAAABJRU5ErkJggg==);
+ }
+</style>
+
+<input type="image">
diff --git a/testing/web-platform/tests/html/rendering/replaced-elements/images/revoked-blob-print-ref.html b/testing/web-platform/tests/html/rendering/replaced-elements/images/revoked-blob-print-ref.html
new file mode 100644
index 0000000000..6b2f0bb606
--- /dev/null
+++ b/testing/web-platform/tests/html/rendering/replaced-elements/images/revoked-blob-print-ref.html
@@ -0,0 +1,3 @@
+<!doctype html>
+<title>Test reference</title>
+<img width=100 height=50 src="/images/black-rectangle.png">
diff --git a/testing/web-platform/tests/html/rendering/replaced-elements/images/revoked-blob-print.html b/testing/web-platform/tests/html/rendering/replaced-elements/images/revoked-blob-print.html
new file mode 100644
index 0000000000..fd5c2c5754
--- /dev/null
+++ b/testing/web-platform/tests/html/rendering/replaced-elements/images/revoked-blob-print.html
@@ -0,0 +1,24 @@
+<!doctype html>
+<html class="test-wait">
+<title>Printing an image with src="revoked-blob"</title>
+<link rel="author" href="mailto:emilio@crisal.io" title="Emilio Cobos Álvarez">
+<link rel="help" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1665343">
+<link rel="match" href="revoked-blob-print-ref.html">
+<img width=100 height=50>
+<script>
+ let canvas = document.createElement("canvas");
+ canvas.width = 100;
+ canvas.height = 50;
+ let ctx = canvas.getContext("2d");
+ ctx.fillRect(0, 0, 100, 50);
+ canvas.toBlob(function(blob) {
+ let img = document.querySelector("img");
+ let url = URL.createObjectURL(blob);
+ img.onload = function() {
+ URL.revokeObjectURL(url);
+ document.documentElement.className = "";
+ };
+ img.src = url;
+ });
+</script>
+</html>
diff --git a/testing/web-platform/tests/html/rendering/replaced-elements/images/space-ref.html b/testing/web-platform/tests/html/rendering/replaced-elements/images/space-ref.html
new file mode 100644
index 0000000000..0cf272e162
--- /dev/null
+++ b/testing/web-platform/tests/html/rendering/replaced-elements/images/space-ref.html
@@ -0,0 +1,13 @@
+<!doctype html>
+<meta charset=utf-8>
+<title>img hspace/vspace - reference</title>
+<style>
+span { background: blue; }
+</style>
+<div style=width:400px;>
+<p><span><img src=/images/green.png></span>
+<p><span><img src=/images/green.png style="margin: 0 10px"></span>
+<p><span><img src=/images/green.png style="margin: 10px 0"></span>
+<p><span><img src=/images/green.png style="margin: 0 10%"></span>
+<p><span><img src=/images/green.png style="margin: 10% 0"></span>
+</div>
diff --git a/testing/web-platform/tests/html/rendering/replaced-elements/images/space.html b/testing/web-platform/tests/html/rendering/replaced-elements/images/space.html
new file mode 100644
index 0000000000..fee115dfce
--- /dev/null
+++ b/testing/web-platform/tests/html/rendering/replaced-elements/images/space.html
@@ -0,0 +1,14 @@
+<!doctype html>
+<meta charset=utf-8>
+<title>img hspace/vspace</title>
+<link rel=match href=space-ref.html>
+<style>
+span { background: blue; }
+</style>
+<div style=width:400px;>
+<p><span><img src=/images/green.png></span>
+<p><span><img src=/images/green.png hspace=10></span>
+<p><span><img src=/images/green.png vspace=10></span>
+<p><span><img src=/images/green.png hspace=10%></span>
+<p><span><img src=/images/green.png vspace=10%></span>
+</div>
diff --git a/testing/web-platform/tests/html/rendering/replaced-elements/resources/svg-sizing.js b/testing/web-platform/tests/html/rendering/replaced-elements/resources/svg-sizing.js
new file mode 100644
index 0000000000..c212c6b283
--- /dev/null
+++ b/testing/web-platform/tests/html/rendering/replaced-elements/resources/svg-sizing.js
@@ -0,0 +1,418 @@
+// Simple implementation of SVG sizing
+
+setup({explicit_done: true});
+
+var SVGSizing = (function() {
+ function parseLength(l) {
+ var match = /^([-+]?[0-9]+|[-+]?[0-9]*\.[0-9]+)(px|%)?$/.exec(l);
+ if (!match)
+ return null;
+ return new Length(Number(match[1]), match[2] ? match[2] : "px");
+ }
+
+ function parseViewBox(input) {
+ if (!input)
+ return null;
+
+ var arr = input.split(' ');
+ return arr.map(function(a) { return parseInt(a); });
+ }
+
+ // Only px and % are used
+ function convertToPx(input, percentRef) {
+ if (input == null)
+ return null;
+ var length = parseLength(input);
+ if (length.amount == 0)
+ return 0;
+ if (!length.unit)
+ length.unit = "px";
+ if (length.unit == "%" && percentRef === undefined)
+ return null;
+ return length.amount * { px: 1,
+ "%": percentRef/100}[length.unit];
+ }
+
+ function Length(amount, unit) {
+ this.amount = amount;
+ this.unit = unit;
+ }
+
+ function describe(data) {
+ function dumpObject(obj) {
+ var r = "";
+ for (var property in obj) {
+ if (obj.hasOwnProperty(property)) {
+ var value = obj[property];
+ if (typeof value == 'string')
+ value = "'" + value + "'";
+ else if (value == null)
+ value = "null";
+ else if (typeof value == 'object')
+ {
+ if (value instanceof Array)
+ value = "[" + value + "]";
+ else
+ value = "{" + dumpObject(value) + "}";
+ }
+
+ if (value != "null")
+ r += property + ": " + value + ", ";
+ }
+ }
+ return r;
+ }
+ var result = dumpObject(data);
+ if (result == "")
+ return "(initial values)";
+ return result;
+ }
+
+ function mapPresentationalHintLength(testData, cssProperty, attr) {
+ if (attr) {
+ var l = parseLength(attr);
+ if (l)
+ testData.style[cssProperty] = l.amount + l.unit;
+ }
+ }
+
+ function computedWidthIsAuto(testData) {
+ return !testData.style["width"] || testData.style["width"] == 'auto';
+ }
+
+ function computedHeightIsAuto(testData) {
+ return !testData.style["height"] || testData.style["height"] == 'auto' ||
+ (parseLength(testData.style["height"]).unit == '%' &&
+ containerComputedHeightIsAuto(testData));
+ }
+
+ function containerComputedWidthIsAuto(testData) {
+ return !testData.config.containerWidthStyle ||
+ testData.config.containerWidthStyle == 'auto';
+ }
+
+ function containerComputedHeightIsAuto(testData) {
+ return !testData.config.containerHeightStyle ||
+ testData.config.containerHeightStyle == 'auto';
+ }
+
+ function intrinsicInformation(testData) {
+ if (testData.config.placeholder == 'iframe')
+ return {};
+
+ var w = convertToPx(testData.config.svgWidthAttr) || 0;
+ var h = convertToPx(testData.config.svgHeightAttr) || 0;
+ var r = 0;
+ if (w && h) {
+ r = w / h;
+ } else {
+ var vb = parseViewBox(testData.config.svgViewBoxAttr);
+ if (vb) {
+ r = vb[2] / vb[3];
+ }
+ if (r) {
+ if (!w && h)
+ w = h * r;
+ else if (!h && w)
+ h = w / r;
+ }
+ }
+ return { width: w, height: h, ratio: r };
+ };
+
+ function contentAttributeForPlaceholder(testData) {
+ if (testData.config.placeholder == 'object')
+ return "data";
+ else
+ return "src";
+ }
+
+ function TestData(config) {
+ this.config = config;
+ this.name = describe(config);
+ this.style = {};
+ if (config.placeholder) {
+ mapPresentationalHintLength(this, "width", config.placeholderWidthAttr);
+ mapPresentationalHintLength(this, "height", config.placeholderHeightAttr);
+ } else {
+ if (config.svgWidthStyle)
+ this.style["width"] = config.svgWidthStyle;
+ else
+ mapPresentationalHintLength(this, "width", config.svgWidthAttr);
+
+ if (config.svgHeightStyle)
+ this.style["height"] = config.svgHeightStyle;
+ else
+ mapPresentationalHintLength(this, "height", config.svgHeightAttr);
+ }
+ }
+
+ TestData.prototype.computeInlineReplacedSize = function(outerWidth, outerHeight) {
+ var intrinsic = intrinsicInformation(this);
+ var self = this;
+
+ // http://www.w3.org/TR/CSS2/visudet.html#inline-replaced-height
+ function calculateUsedHeight() {
+ if (computedHeightIsAuto(self)) {
+ if (computedWidthIsAuto(self) && intrinsic.height)
+ return intrinsic.height;
+ if (intrinsic.ratio)
+ return calculateUsedWidth() / intrinsic.ratio;
+ if (intrinsic.height)
+ return intrinsic.height;
+ return 150;
+ }
+
+ return convertToPx(self.style["height"],
+ convertToPx(self.config.containerHeightStyle,
+ outerHeight));
+ }
+
+ // http://www.w3.org/TR/CSS2/visudet.html#inline-replaced-width
+ function calculateUsedWidth() {
+ if (computedWidthIsAuto(self)) {
+ if (computedHeightIsAuto(self) && intrinsic.width)
+ return intrinsic.width;
+ if (!computedHeightIsAuto(self) && intrinsic.ratio)
+ return calculateUsedHeight() * intrinsic.ratio;
+ if (computedHeightIsAuto(self) && intrinsic.ratio) {
+ if (containerComputedWidthIsAuto(self)) {
+ // Note: While this is actually undefined in CSS
+ // 2.1, use the suggested value by examining the
+ // ancestor widths.
+ return outerWidth;
+ } else {
+ return convertToPx(self.config.containerWidthStyle,
+ outerWidth);
+ }
+ }
+ if (intrinsic.width)
+ return intrinsic.width;
+ return 300;
+ }
+
+ if (containerComputedWidthIsAuto(self))
+ return convertToPx(self.style["width"], outerWidth);
+ else
+ return convertToPx(self.style["width"],
+ convertToPx(self.config.containerWidthStyle,
+ outerWidth));
+ }
+ return { width: calculateUsedWidth(),
+ height: calculateUsedHeight() };
+ };
+
+ TestData.prototype.buildContainer = function (placeholder, options) {
+ options = options || {};
+
+ var container = document.createElement("div");
+
+ container.id = "container";
+ if (this.config.containerWidthStyle)
+ container.style.width = this.config.containerWidthStyle;
+
+ if (this.config.containerHeightStyle)
+ container.style.height = this.config.containerHeightStyle;
+
+ if (options.pretty)
+ container.appendChild(document.createTextNode("\n\t\t"));
+ container.appendChild(placeholder);
+ if (options.pretty)
+ container.appendChild(document.createTextNode("\n\t"));
+
+ return container;
+ };
+
+ TestData.prototype.buildSVGOrPlaceholder = function (options) {
+ options = options || {};
+ var self = this;
+
+ if (this.config.placeholder) {
+ var generateSVGURI = function(testData, encoder) {
+ var res = '<svg xmlns="http://www.w3.org/2000/svg"';
+ function addAttr(attr, prop) {
+ if (testData.config[prop])
+ res += ' ' + attr + '="' + testData.config[prop] + '"';
+ }
+ addAttr("width", "svgWidthAttr");
+ addAttr("height", "svgHeightAttr");
+ addAttr("viewBox", "svgViewBoxAttr");
+ res += '></svg>';
+ return 'data:image/svg+xml' + encoder(res);
+ };
+ var placeholder = document.createElement(this.config.placeholder);
+ if (options.pretty) {
+ placeholder.appendChild(document.createTextNode("\n\t\t\t"));
+ placeholder.appendChild(
+ document.createComment(
+ generateSVGURI(this, function(x) { return "," + x; })));
+ placeholder.appendChild(document.createTextNode("\n\t\t"));
+ }
+ placeholder.setAttribute("id", "test");
+ if (this.config.placeholderWidthAttr)
+ placeholder.setAttribute("width", this.config.placeholderWidthAttr);
+ if (this.config.placeholderHeightAttr)
+ placeholder.setAttribute("height", this.config.placeholderHeightAttr);
+ placeholder.setAttribute(contentAttributeForPlaceholder(this),
+ generateSVGURI(this, function(x) {
+ return ";base64," + btoa(x);
+ }));
+ return placeholder;
+ } else {
+ var svgElement = document.createElementNS("http://www.w3.org/2000/svg", "svg");
+ svgElement.setAttribute("id", "test");
+ if (self.config.svgWidthStyle)
+ svgElement.style.width = self.config.svgWidthStyle;
+ if (self.config.svgHeightStyle)
+ svgElement.style.height = self.config.svgHeightStyle;
+ if (self.config.svgWidthAttr)
+ svgElement.setAttribute("width", self.config.svgWidthAttr);
+ if (self.config.svgHeightAttr)
+ svgElement.setAttribute("height", self.config.svgHeightAttr);
+ if (self.config.svgViewBoxAttr)
+ svgElement.setAttribute("viewBox", self.config.svgViewBoxAttr);
+ return svgElement;
+ }
+ };
+
+ TestData.prototype.buildDemo = function (expectedRect, id) {
+ // Non-essential debugging tool
+ var self = this;
+
+ function buildDemoSerialization() {
+ var outerWidth = 800;
+ var outerHeight = 600;
+
+ var options = { pretty: true };
+ var container =
+ self.buildContainer(self.buildSVGOrPlaceholder(options), options);
+
+ var root = document.createElement("html");
+ var style = document.createElement("style");
+
+ style.textContent = "\n" +
+ "\tbody { margin: 0; font-family: sans-serif }\n" +
+ "\tiframe { border: none }\n" +
+ "\t#expected {\n" +
+ "\t\twidth: " + (expectedRect.width) + "px; height: "
+ + (expectedRect.height) + "px;\n" +
+ "\t\tborder: 10px solid lime; position: absolute;\n" +
+ "\t\tbackground-color: red }\n" +
+ "\t#testContainer { position: absolute;\n" +
+ "\t\ttop: 10px; left: 10px; width: " + outerWidth + "px;\n" +
+ "\t\theight: " + outerHeight + "px }\n" +
+ "\t#test { background-color: green }\n" +
+ "\t.result { position: absolute; top: 0; right: 0;\n" +
+ "\t\tbackground-color: hsla(0,0%, 0%, 0.85); border-radius: 0.5em;\n" +
+ "\t\tpadding: 0.5em; border: 0.25em solid black }\n" +
+ "\t.pass { color: lime }\n" +
+ "\t.fail { color: red }\n";
+
+ root.appendChild(document.createTextNode("\n"));
+ root.appendChild(style);
+ root.appendChild(document.createTextNode("\n"));
+
+ var script = document.createElement("script");
+ script.textContent = "\n" +
+ "onload = function() {\n" +
+ "\tvar svgRect =\n" +
+ "\t\tdocument.querySelector('#test').getBoundingClientRect();\n" +
+ "\tpassed = (svgRect.width == " + expectedRect.width + " && " +
+ "svgRect.height == " + expectedRect.height + ");\n" +
+ "\tdocument.body.insertAdjacentHTML('beforeEnd',\n" +
+ "\t\t'<span class=\"result '+ (passed ? 'pass' : 'fail') " +
+ "+ '\">' + (passed ? 'Pass' : 'Fail') + '</span>');\n" +
+ "};\n";
+
+ root.appendChild(script);
+ root.appendChild(document.createTextNode("\n"));
+
+ var expectedElement = document.createElement("div");
+ expectedElement.id = "expected";
+ root.appendChild(expectedElement);
+ root.appendChild(document.createTextNode("\n"));
+
+ var testContainer = document.createElement("div");
+ testContainer.id = "testContainer";
+ testContainer.appendChild(document.createTextNode("\n\t"));
+ testContainer.appendChild(container);
+ testContainer.appendChild(document.createTextNode("\n"));
+ root.appendChild(testContainer);
+ root.appendChild(document.createTextNode("\n"));
+
+ return "<!DOCTYPE html>\n" + root.outerHTML;
+ }
+
+ function pad(n, width, z) {
+ z = z || '0';
+ n = n + '';
+ return n.length >= width ? n : new Array(width - n.length + 1).join(z) + n;
+ }
+
+ function heightToDescription(height) {
+ if (!height || height == "auto")
+ return "auto";
+ if (parseLength(height).unit == '%')
+ return "percentage";
+ return "fixed";
+ }
+
+ var demoRoot = document.querySelector('#demo');
+ if (demoRoot) {
+ var demo = buildDemoSerialization();
+ var iframe = document.createElement('iframe');
+ iframe.style.width = (Math.max(900, expectedRect.width)) + "px";
+ iframe.style.height = (Math.max(400, expectedRect.height)) + "px";
+ iframe.src = "data:text/html;charset=utf-8," + encodeURIComponent(demo);
+ demoRoot.appendChild(iframe);
+ demoRoot.insertAdjacentHTML(
+ 'beforeEnd',
+ '<p><a href="data:application/octet-stream;charset=utf-8;base64,' +
+ btoa(demo) + '" download="svg-in-' + this.config.placeholder + "-" +
+ heightToDescription(this.config.placeholderHeightAttr) + "-" + pad(id, 3) +
+ '.html">Download</a></p>');
+ }
+ };
+
+ return {
+ TestData: TestData,
+ doCombinationTest: function(values, func, testSingleId) {
+ function computeConfig(id) {
+ id--;
+ var multiplier = 1;
+ var config = {};
+ for (var i=0; i<values.length; i++) {
+ // Compute offset into current array
+ var ii = (Math.floor(id / multiplier)) % values[i][1].length;
+ // Set corresponding value
+ config[values[i][0]] = values[i][1][ii];
+ // Compute new multiplier
+ multiplier *= values[i][1].length;
+ }
+ if (id >= multiplier)
+ return null;
+ return config;
+ }
+
+ function cont(id) {
+ var config = computeConfig(id);
+ if (config && (!testSingleId || testSingleId == id)) {
+ var next = function() {func(config, id, cont)};
+ // Make sure we don't blow the stack, without too much slowness
+ if (id % 20 === 0) {
+ step_timeout(next, 0);
+ } else {
+ next();
+ }
+ } else {
+ done();
+ }
+ };
+
+ if (testSingleId)
+ cont(testSingleId);
+ else
+ cont(1);
+ }
+ };
+})();
diff --git a/testing/web-platform/tests/html/rendering/replaced-elements/svg-embedded-sizing/svg-embedded-sizing.js b/testing/web-platform/tests/html/rendering/replaced-elements/svg-embedded-sizing/svg-embedded-sizing.js
new file mode 100644
index 0000000000..a502d2c747
--- /dev/null
+++ b/testing/web-platform/tests/html/rendering/replaced-elements/svg-embedded-sizing/svg-embedded-sizing.js
@@ -0,0 +1,96 @@
+// global async_test, assert_equals
+//
+// This test generates a couple of scenarios (each a
+// SVGSizing.TestData) for sizing inline <svg> and uses a simple
+// JavaScript sizing implementation for comparison.
+//
+// The tests loops through different combinations of:
+//
+// * width and height on <object>, <iframe> (input dependent)
+//
+// * width and height on <svg>
+//
+// * viewBox on <svg> (gives intrinsic ratio)
+//
+// * width and height on containing block of <object>
+//
+// All these contribute to the final size of the SVG in some way.
+//
+// The test focuses on the size of the CSS box generated by the SVG.
+// The SVG is always empty by itself so no actual SVG are tested.
+// Little focus is put on variations within an attribute that doesn't
+// affect the sizing behavior.
+//
+// To debug a specific test, append ?<test-id> to the URL. An <iframe>
+// is generated with equivalent test and the source code of the test
+// can be downloaded.
+
+var debugHint = function(id) { return "(append ?"+id+" to debug) "; };
+var testSingleId;
+if (window.location.search) {
+ testSingleId = parseInt(window.location.search.substring(1));
+ debugHint = function(id) { return ""; };
+}
+
+function testPlaceholderWithHeight(placeholder,
+ placeholderHeightAttr) {
+ var testContainer = document.querySelector('#testContainer');
+ var outerWidth = testContainer.getBoundingClientRect().width;
+ var outerHeight = testContainer.getBoundingClientRect().height;
+
+ SVGSizing.doCombinationTest(
+ [["placeholder", [ placeholder ]],
+ ["containerWidthStyle", [null, "400px"]],
+ ["containerHeightStyle", [null, "400px"]],
+ ["placeholderWidthAttr", [null, "100", "50%"]],
+ ["placeholderHeightAttr", [placeholderHeightAttr]],
+ ["svgViewBoxAttr", [ null, "0 0 100 200" ]],
+ ["svgWidthAttr", [ null, "200", "25%" ]],
+ ["svgHeightAttr", [ null, "200", "25%" ]]],
+ function (config, id, cont) {
+ var testData = new SVGSizing.TestData(config);
+ var t = async_test(testData.name);
+ var expectedRect =
+ testData.computeInlineReplacedSize(outerWidth, outerHeight);
+ var placeholder = testData.buildSVGOrPlaceholder();
+ var container =
+ testData.buildContainer(placeholder);
+
+ var checkSize = function() {
+ var placeholderRect =
+ placeholder.getBoundingClientRect();
+
+ try {
+ assert_equals(placeholderRect.width,
+ expectedRect.width,
+ debugHint(id) + "Wrong width");
+ assert_equals(placeholderRect.height,
+ expectedRect.height,
+ debugHint(id) + "Wrong height");
+ } finally {
+ testContainer.removeChild(container);
+ if (testSingleId)
+ document.body.removeChild(testContainer);
+ cont(id+1);
+ }
+ t.done();
+ };
+
+ if (!config.placeholder) {
+ testContainer.appendChild(container);
+ test(checkSize, testData.name);
+ } else {
+ t.step(function() {
+ placeholder.addEventListener('load', function() {
+ // step_timeout is a work-around to let engines
+ // finish layout of child browsing contexts even
+ // after the load event
+ step_timeout(t.step_func(checkSize), 0);
+ });
+ testContainer.appendChild(container);
+ });
+ }
+ if (testSingleId == id)
+ testData.buildDemo(expectedRect, id);
+ }, testSingleId);
+}
diff --git a/testing/web-platform/tests/html/rendering/replaced-elements/svg-embedded-sizing/svg-in-iframe-auto.html b/testing/web-platform/tests/html/rendering/replaced-elements/svg-embedded-sizing/svg-in-iframe-auto.html
new file mode 100644
index 0000000000..4c3fefe88f
--- /dev/null
+++ b/testing/web-platform/tests/html/rendering/replaced-elements/svg-embedded-sizing/svg-in-iframe-auto.html
@@ -0,0 +1,33 @@
+<!DOCTYPE html>
+<!-- This file is generated by gen-svgsizing-tests.py -->
+<html>
+ <head>
+ <title>SVG sizing: &lt;iframe></title>
+ <meta name=timeout content=long>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="../resources/svg-sizing.js"></script>
+ <style>
+ #testContainer {
+ position: absolute;
+ left: 0;
+ top: 0;
+ width: 800px;
+ height: 600px
+ }
+ iframe { border: 0 }
+ </style>
+ <link rel="help" href="http://www.w3.org/TR/CSS2/visudet.html#inline-replaced-width">
+ <link rel="help" href="http://www.w3.org/TR/CSS2/visudet.html#inline-replaced-height">
+ <link rel="help" href="https://html.spec.whatwg.org/multipage/#replaced-elements">
+ <link rel="help" href="https://html.spec.whatwg.org/multipage/#attr-dim-width">
+ <link rel="help" href="http://www.w3.org/TR/SVG/coords.html#ViewportSpace">
+ </head>
+ <body>
+ <div id="log"></div>
+ <div id="testContainer"></div>
+ <div id="demo"></div>
+ <script src="svg-embedded-sizing.js"></script>
+ <script>testPlaceholderWithHeight("iframe", null)</script>
+ </body>
+</html>
diff --git a/testing/web-platform/tests/html/rendering/replaced-elements/svg-embedded-sizing/svg-in-iframe-fixed.html b/testing/web-platform/tests/html/rendering/replaced-elements/svg-embedded-sizing/svg-in-iframe-fixed.html
new file mode 100644
index 0000000000..ae3328c6a8
--- /dev/null
+++ b/testing/web-platform/tests/html/rendering/replaced-elements/svg-embedded-sizing/svg-in-iframe-fixed.html
@@ -0,0 +1,33 @@
+<!DOCTYPE html>
+<!-- This file is generated by gen-svgsizing-tests.py -->
+<html>
+ <head>
+ <title>SVG sizing: &lt;iframe></title>
+ <meta name=timeout content=long>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="../resources/svg-sizing.js"></script>
+ <style>
+ #testContainer {
+ position: absolute;
+ left: 0;
+ top: 0;
+ width: 800px;
+ height: 600px
+ }
+ iframe { border: 0 }
+ </style>
+ <link rel="help" href="http://www.w3.org/TR/CSS2/visudet.html#inline-replaced-width">
+ <link rel="help" href="http://www.w3.org/TR/CSS2/visudet.html#inline-replaced-height">
+ <link rel="help" href="https://html.spec.whatwg.org/multipage/#replaced-elements">
+ <link rel="help" href="https://html.spec.whatwg.org/multipage/#attr-dim-width">
+ <link rel="help" href="http://www.w3.org/TR/SVG/coords.html#ViewportSpace">
+ </head>
+ <body>
+ <div id="log"></div>
+ <div id="testContainer"></div>
+ <div id="demo"></div>
+ <script src="svg-embedded-sizing.js"></script>
+ <script>testPlaceholderWithHeight("iframe", '100px')</script>
+ </body>
+</html>
diff --git a/testing/web-platform/tests/html/rendering/replaced-elements/svg-embedded-sizing/svg-in-iframe-percentage.html b/testing/web-platform/tests/html/rendering/replaced-elements/svg-embedded-sizing/svg-in-iframe-percentage.html
new file mode 100644
index 0000000000..da00c0680b
--- /dev/null
+++ b/testing/web-platform/tests/html/rendering/replaced-elements/svg-embedded-sizing/svg-in-iframe-percentage.html
@@ -0,0 +1,33 @@
+<!DOCTYPE html>
+<!-- This file is generated by gen-svgsizing-tests.py -->
+<html>
+ <head>
+ <title>SVG sizing: &lt;iframe></title>
+ <meta name=timeout content=long>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="../resources/svg-sizing.js"></script>
+ <style>
+ #testContainer {
+ position: absolute;
+ left: 0;
+ top: 0;
+ width: 800px;
+ height: 600px
+ }
+ iframe { border: 0 }
+ </style>
+ <link rel="help" href="http://www.w3.org/TR/CSS2/visudet.html#inline-replaced-width">
+ <link rel="help" href="http://www.w3.org/TR/CSS2/visudet.html#inline-replaced-height">
+ <link rel="help" href="https://html.spec.whatwg.org/multipage/#replaced-elements">
+ <link rel="help" href="https://html.spec.whatwg.org/multipage/#attr-dim-width">
+ <link rel="help" href="http://www.w3.org/TR/SVG/coords.html#ViewportSpace">
+ </head>
+ <body>
+ <div id="log"></div>
+ <div id="testContainer"></div>
+ <div id="demo"></div>
+ <script src="svg-embedded-sizing.js"></script>
+ <script>testPlaceholderWithHeight("iframe", '100%')</script>
+ </body>
+</html>
diff --git a/testing/web-platform/tests/html/rendering/replaced-elements/svg-embedded-sizing/svg-in-img-auto.html b/testing/web-platform/tests/html/rendering/replaced-elements/svg-embedded-sizing/svg-in-img-auto.html
new file mode 100644
index 0000000000..cef3530676
--- /dev/null
+++ b/testing/web-platform/tests/html/rendering/replaced-elements/svg-embedded-sizing/svg-in-img-auto.html
@@ -0,0 +1,33 @@
+<!DOCTYPE html>
+<!-- This file is generated by gen-svgsizing-tests.py -->
+<html>
+ <head>
+ <title>SVG sizing: &lt;img></title>
+ <meta name=timeout content=long>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="../resources/svg-sizing.js"></script>
+ <style>
+ #testContainer {
+ position: absolute;
+ left: 0;
+ top: 0;
+ width: 800px;
+ height: 600px
+ }
+ iframe { border: 0 }
+ </style>
+ <link rel="help" href="http://www.w3.org/TR/CSS2/visudet.html#inline-replaced-width">
+ <link rel="help" href="http://www.w3.org/TR/CSS2/visudet.html#inline-replaced-height">
+ <link rel="help" href="https://html.spec.whatwg.org/multipage/#replaced-elements">
+ <link rel="help" href="https://html.spec.whatwg.org/multipage/#attr-dim-width">
+ <link rel="help" href="http://www.w3.org/TR/SVG/coords.html#ViewportSpace">
+ </head>
+ <body>
+ <div id="log"></div>
+ <div id="testContainer"></div>
+ <div id="demo"></div>
+ <script src="svg-embedded-sizing.js"></script>
+ <script>testPlaceholderWithHeight("img", null)</script>
+ </body>
+</html>
diff --git a/testing/web-platform/tests/html/rendering/replaced-elements/svg-embedded-sizing/svg-in-img-fixed.html b/testing/web-platform/tests/html/rendering/replaced-elements/svg-embedded-sizing/svg-in-img-fixed.html
new file mode 100644
index 0000000000..e8ad0dc935
--- /dev/null
+++ b/testing/web-platform/tests/html/rendering/replaced-elements/svg-embedded-sizing/svg-in-img-fixed.html
@@ -0,0 +1,33 @@
+<!DOCTYPE html>
+<!-- This file is generated by gen-svgsizing-tests.py -->
+<html>
+ <head>
+ <title>SVG sizing: &lt;img></title>
+ <meta name=timeout content=long>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="../resources/svg-sizing.js"></script>
+ <style>
+ #testContainer {
+ position: absolute;
+ left: 0;
+ top: 0;
+ width: 800px;
+ height: 600px
+ }
+ iframe { border: 0 }
+ </style>
+ <link rel="help" href="http://www.w3.org/TR/CSS2/visudet.html#inline-replaced-width">
+ <link rel="help" href="http://www.w3.org/TR/CSS2/visudet.html#inline-replaced-height">
+ <link rel="help" href="https://html.spec.whatwg.org/multipage/#replaced-elements">
+ <link rel="help" href="https://html.spec.whatwg.org/multipage/#attr-dim-width">
+ <link rel="help" href="http://www.w3.org/TR/SVG/coords.html#ViewportSpace">
+ </head>
+ <body>
+ <div id="log"></div>
+ <div id="testContainer"></div>
+ <div id="demo"></div>
+ <script src="svg-embedded-sizing.js"></script>
+ <script>testPlaceholderWithHeight("img", '100px')</script>
+ </body>
+</html>
diff --git a/testing/web-platform/tests/html/rendering/replaced-elements/svg-embedded-sizing/svg-in-img-percentage.html b/testing/web-platform/tests/html/rendering/replaced-elements/svg-embedded-sizing/svg-in-img-percentage.html
new file mode 100644
index 0000000000..7bd5d90317
--- /dev/null
+++ b/testing/web-platform/tests/html/rendering/replaced-elements/svg-embedded-sizing/svg-in-img-percentage.html
@@ -0,0 +1,33 @@
+<!DOCTYPE html>
+<!-- This file is generated by gen-svgsizing-tests.py -->
+<html>
+ <head>
+ <title>SVG sizing: &lt;img></title>
+ <meta name=timeout content=long>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="../resources/svg-sizing.js"></script>
+ <style>
+ #testContainer {
+ position: absolute;
+ left: 0;
+ top: 0;
+ width: 800px;
+ height: 600px
+ }
+ iframe { border: 0 }
+ </style>
+ <link rel="help" href="http://www.w3.org/TR/CSS2/visudet.html#inline-replaced-width">
+ <link rel="help" href="http://www.w3.org/TR/CSS2/visudet.html#inline-replaced-height">
+ <link rel="help" href="https://html.spec.whatwg.org/multipage/#replaced-elements">
+ <link rel="help" href="https://html.spec.whatwg.org/multipage/#attr-dim-width">
+ <link rel="help" href="http://www.w3.org/TR/SVG/coords.html#ViewportSpace">
+ </head>
+ <body>
+ <div id="log"></div>
+ <div id="testContainer"></div>
+ <div id="demo"></div>
+ <script src="svg-embedded-sizing.js"></script>
+ <script>testPlaceholderWithHeight("img", '100%')</script>
+ </body>
+</html>
diff --git a/testing/web-platform/tests/html/rendering/replaced-elements/svg-embedded-sizing/svg-in-object-auto.html b/testing/web-platform/tests/html/rendering/replaced-elements/svg-embedded-sizing/svg-in-object-auto.html
new file mode 100644
index 0000000000..7d79d2a428
--- /dev/null
+++ b/testing/web-platform/tests/html/rendering/replaced-elements/svg-embedded-sizing/svg-in-object-auto.html
@@ -0,0 +1,33 @@
+<!DOCTYPE html>
+<!-- This file is generated by gen-svgsizing-tests.py -->
+<html>
+ <head>
+ <title>SVG sizing: &lt;object></title>
+ <meta name=timeout content=long>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="../resources/svg-sizing.js"></script>
+ <style>
+ #testContainer {
+ position: absolute;
+ left: 0;
+ top: 0;
+ width: 800px;
+ height: 600px
+ }
+ iframe { border: 0 }
+ </style>
+ <link rel="help" href="http://www.w3.org/TR/CSS2/visudet.html#inline-replaced-width">
+ <link rel="help" href="http://www.w3.org/TR/CSS2/visudet.html#inline-replaced-height">
+ <link rel="help" href="https://html.spec.whatwg.org/multipage/#replaced-elements">
+ <link rel="help" href="https://html.spec.whatwg.org/multipage/#attr-dim-width">
+ <link rel="help" href="http://www.w3.org/TR/SVG/coords.html#ViewportSpace">
+ </head>
+ <body>
+ <div id="log"></div>
+ <div id="testContainer"></div>
+ <div id="demo"></div>
+ <script src="svg-embedded-sizing.js"></script>
+ <script>testPlaceholderWithHeight("object", null)</script>
+ </body>
+</html>
diff --git a/testing/web-platform/tests/html/rendering/replaced-elements/svg-embedded-sizing/svg-in-object-fixed.html b/testing/web-platform/tests/html/rendering/replaced-elements/svg-embedded-sizing/svg-in-object-fixed.html
new file mode 100644
index 0000000000..75f7636258
--- /dev/null
+++ b/testing/web-platform/tests/html/rendering/replaced-elements/svg-embedded-sizing/svg-in-object-fixed.html
@@ -0,0 +1,33 @@
+<!DOCTYPE html>
+<!-- This file is generated by gen-svgsizing-tests.py -->
+<html>
+ <head>
+ <title>SVG sizing: &lt;object></title>
+ <meta name=timeout content=long>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="../resources/svg-sizing.js"></script>
+ <style>
+ #testContainer {
+ position: absolute;
+ left: 0;
+ top: 0;
+ width: 800px;
+ height: 600px
+ }
+ iframe { border: 0 }
+ </style>
+ <link rel="help" href="http://www.w3.org/TR/CSS2/visudet.html#inline-replaced-width">
+ <link rel="help" href="http://www.w3.org/TR/CSS2/visudet.html#inline-replaced-height">
+ <link rel="help" href="https://html.spec.whatwg.org/multipage/#replaced-elements">
+ <link rel="help" href="https://html.spec.whatwg.org/multipage/#attr-dim-width">
+ <link rel="help" href="http://www.w3.org/TR/SVG/coords.html#ViewportSpace">
+ </head>
+ <body>
+ <div id="log"></div>
+ <div id="testContainer"></div>
+ <div id="demo"></div>
+ <script src="svg-embedded-sizing.js"></script>
+ <script>testPlaceholderWithHeight("object", '100px')</script>
+ </body>
+</html>
diff --git a/testing/web-platform/tests/html/rendering/replaced-elements/svg-embedded-sizing/svg-in-object-percentage.html b/testing/web-platform/tests/html/rendering/replaced-elements/svg-embedded-sizing/svg-in-object-percentage.html
new file mode 100644
index 0000000000..8f82836e1b
--- /dev/null
+++ b/testing/web-platform/tests/html/rendering/replaced-elements/svg-embedded-sizing/svg-in-object-percentage.html
@@ -0,0 +1,33 @@
+<!DOCTYPE html>
+<!-- This file is generated by gen-svgsizing-tests.py -->
+<html>
+ <head>
+ <title>SVG sizing: &lt;object></title>
+ <meta name=timeout content=long>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="../resources/svg-sizing.js"></script>
+ <style>
+ #testContainer {
+ position: absolute;
+ left: 0;
+ top: 0;
+ width: 800px;
+ height: 600px
+ }
+ iframe { border: 0 }
+ </style>
+ <link rel="help" href="http://www.w3.org/TR/CSS2/visudet.html#inline-replaced-width">
+ <link rel="help" href="http://www.w3.org/TR/CSS2/visudet.html#inline-replaced-height">
+ <link rel="help" href="https://html.spec.whatwg.org/multipage/#replaced-elements">
+ <link rel="help" href="https://html.spec.whatwg.org/multipage/#attr-dim-width">
+ <link rel="help" href="http://www.w3.org/TR/SVG/coords.html#ViewportSpace">
+ </head>
+ <body>
+ <div id="log"></div>
+ <div id="testContainer"></div>
+ <div id="demo"></div>
+ <script src="svg-embedded-sizing.js"></script>
+ <script>testPlaceholderWithHeight("object", '100%')</script>
+ </body>
+</html>
diff --git a/testing/web-platform/tests/html/rendering/replaced-elements/svg-inline-sizing/svg-inline.html b/testing/web-platform/tests/html/rendering/replaced-elements/svg-inline-sizing/svg-inline.html
new file mode 100644
index 0000000000..2b3cf65366
--- /dev/null
+++ b/testing/web-platform/tests/html/rendering/replaced-elements/svg-inline-sizing/svg-inline.html
@@ -0,0 +1,29 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <title>SVG sizing: inline</title>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="../resources/svg-sizing.js"></script>
+ <style>
+ #testContainer {
+ position: absolute;
+ left: 0;
+ top: 0;
+ width: 800px;
+ height: 600px;
+ }
+ </style>
+ <link rel="help" href="http://www.w3.org/TR/CSS2/visudet.html#inline-replaced-width">
+ <link rel="help" href="http://www.w3.org/TR/CSS2/visudet.html#inline-replaced-height">
+ <link rel="help" href="https://html.spec.whatwg.org/multipage/#replaced-elements">
+ <link rel="help" href="https://html.spec.whatwg.org/multipage/#attr-dim-width">
+ <link rel="help" href="http://www.w3.org/TR/SVG/coords.html#ViewportSpace">
+ </head>
+ <body>
+ <div id="log"></div>
+ <div id="testContainer"></div>
+ <div id="demo"></div>
+ <script src="svg-inline.js"></script>
+ </body>
+</html>
diff --git a/testing/web-platform/tests/html/rendering/replaced-elements/svg-inline-sizing/svg-inline.js b/testing/web-platform/tests/html/rendering/replaced-elements/svg-inline-sizing/svg-inline.js
new file mode 100644
index 0000000000..9b7fca0502
--- /dev/null
+++ b/testing/web-platform/tests/html/rendering/replaced-elements/svg-inline-sizing/svg-inline.js
@@ -0,0 +1,79 @@
+// global async_test, assert_equals
+//
+// This test generates a couple of scenarios (each a
+// SVGSizing.TestData) for sizing inline <svg> and uses a simple
+// JavaScript sizing implementation for comparison.
+//
+// The tests loops through different combinations of:
+//
+// * width and height attributes and style on <svg>
+//
+// * viewBox on <svg> (gives intrinsic ratio)
+//
+// * width and height on containing block of <svg>
+//
+// All these may contribute to the final size of the SVG. The test
+// focuses on the size of the CSS box generated by the SVG. Little
+// focus is put on variations within an attribute that doesn't affect
+// the final size.
+//
+// To debug a specific test append ?<test-id> to the URL. An <iframe>
+// is generated with equivalent test and the source of the test is
+// added to a <pre> element.
+
+var debugHint = function(id) { return "(append ?"+id+" to debug) "; };
+var testSingleId;
+if (window.location.search) {
+ testSingleId = window.location.search.substring(1);
+ debugHint = function(id) { return ""; };
+}
+
+var testContainer = document.querySelector('#testContainer');
+var testContainerWidth = testContainer.getBoundingClientRect().width;
+var testContainerHeight = testContainer.getBoundingClientRect().height;
+
+SVGSizing.doCombinationTest(
+ [["placeholder", [ null ]],
+ ["containerWidthStyle", [null, "400px"]],
+ ["containerHeightStyle", [null, "400px"]],
+ ["svgViewBoxAttr", [ null, "0 0 100 200" ]],
+ ["svgWidthStyle", [ null, "100px", "50%" ]],
+ ["svgHeightStyle", [ null, "100px", "50%" ]],
+ ["svgWidthAttr", [ null, "200", "25%" ]],
+ ["svgHeightAttr", [ null, "200", "25%" ]]],
+ function(config, id, cont) {
+ var testData = new SVGSizing.TestData(config);
+
+ var expectedRect =
+ testData.computeInlineReplacedSize(testContainerWidth,
+ testContainerHeight);
+ var svgElement = testData.buildSVGOrPlaceholder();
+ var container =
+ testData.buildContainer(svgElement);
+
+ var checkSize = function() {
+ var svgRect =
+ svgElement.getBoundingClientRect();
+
+ try {
+ assert_equals(svgRect.width,
+ expectedRect.width,
+ debugHint(id) + "Wrong width");
+ assert_equals(svgRect.height,
+ expectedRect.height,
+ debugHint(id) + "Wrong height");
+ } finally {
+ testContainer.removeChild(container);
+ if (testSingleId)
+ document.body.removeChild(testContainer);
+ cont(id+1);
+ }
+ };
+
+ testContainer.appendChild(container);
+ test(checkSize, testData.name);
+
+ if (testSingleId == id) {
+ testData.buildDemo(expectedRect, id);
+ }
+ }, testSingleId);
diff --git a/testing/web-platform/tests/html/rendering/replaced-elements/the-option-element/option-with-br-ref.html b/testing/web-platform/tests/html/rendering/replaced-elements/the-option-element/option-with-br-ref.html
new file mode 100644
index 0000000000..954840f389
--- /dev/null
+++ b/testing/web-platform/tests/html/rendering/replaced-elements/the-option-element/option-with-br-ref.html
@@ -0,0 +1,21 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>option element with br child</title>
+<link rel="author" title="Domenic Denicola" href="mailto:d@domenic.me">
+<link rel="help" href="https://html.spec.whatwg.org/multipage/#concept-option-label">
+<link rel="help" href="https://html.spec.whatwg.org/multipage/#dom-option-text">
+<link rel="help" href="https://html.spec.whatwg.org/multipage/#the-select-element-2">
+
+<p>This test passes if the option element displays three options:</p>
+
+<pre>a
+b
+ab</pre>
+
+<p>Importantly the third option must not be split across two lines.</p>
+
+<select multiple>
+ <option>a</option>
+ <option>b</option>
+ <option>ab</option>
+</select>
diff --git a/testing/web-platform/tests/html/rendering/replaced-elements/the-option-element/option-with-br.html b/testing/web-platform/tests/html/rendering/replaced-elements/the-option-element/option-with-br.html
new file mode 100644
index 0000000000..3b8d992cc2
--- /dev/null
+++ b/testing/web-platform/tests/html/rendering/replaced-elements/the-option-element/option-with-br.html
@@ -0,0 +1,32 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>option element with br child</title>
+<link rel="author" title="Domenic Denicola" href="mailto:d@domenic.me">
+<link rel="help" href="https://html.spec.whatwg.org/multipage/#concept-option-label">
+<link rel="help" href="https://html.spec.whatwg.org/multipage/#dom-option-text">
+<link rel="help" href="https://html.spec.whatwg.org/multipage/#the-select-element-2">
+
+<link rel="match" href="option-with-br-ref.html">
+
+<p>This test passes if the option element displays three options:</p>
+
+<pre>a
+b
+ab</pre>
+
+<p>Importantly the third option must not be split across two lines.</p>
+
+<select multiple>
+ <option>a</option>
+ <option>b</option>
+ <option id="manipulate-me"></option>
+</select>
+
+<script>
+"use strict";
+const option = document.querySelector("#manipulate-me");
+
+option.appendChild(document.createTextNode("a"));
+option.appendChild(document.createElement("br"));
+option.appendChild(document.createTextNode("b"));
+</script>
diff --git a/testing/web-platform/tests/html/rendering/replaced-elements/the-option-element/select-multiple-covered-by-abspos-ref.html b/testing/web-platform/tests/html/rendering/replaced-elements/the-option-element/select-multiple-covered-by-abspos-ref.html
new file mode 100644
index 0000000000..3cb496ea1b
--- /dev/null
+++ b/testing/web-platform/tests/html/rendering/replaced-elements/the-option-element/select-multiple-covered-by-abspos-ref.html
@@ -0,0 +1,11 @@
+<!doctype html>
+<title>Test reference</title>
+<style>
+.abspos {
+ position: absolute;
+ background-color: green;
+ height: 300px;
+ width: 300px;
+}
+</style>
+<div class="abspos"></div>
diff --git a/testing/web-platform/tests/html/rendering/replaced-elements/the-option-element/select-multiple-covered-by-abspos.html b/testing/web-platform/tests/html/rendering/replaced-elements/the-option-element/select-multiple-covered-by-abspos.html
new file mode 100644
index 0000000000..ed290250da
--- /dev/null
+++ b/testing/web-platform/tests/html/rendering/replaced-elements/the-option-element/select-multiple-covered-by-abspos.html
@@ -0,0 +1,19 @@
+<!doctype html>
+<meta charset="utf-8">
+<link rel="help" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1770532">
+<link rel="author" href="mailto:dholbert@mozilla.com" title="Daniel Holbert">
+<link rel="author" href="https://mozilla.org" title="Mozilla">
+<link rel="match" href="select-multiple-covered-by-abspos-ref.html">
+<title>Combobox selects are not stacking contexts by default</title>
+<style>
+.abspos {
+ position: absolute;
+ background-color: green;
+ height: 300px;
+ width: 300px;
+}
+</style>
+<div class="abspos"></div>
+<select multiple>
+ <option>This text shouldn't be visible.</option>
+</select>
diff --git a/testing/web-platform/tests/html/rendering/replaced-elements/the-select-element/select-1-block-size-001-ref-2.html b/testing/web-platform/tests/html/rendering/replaced-elements/the-select-element/select-1-block-size-001-ref-2.html
new file mode 100644
index 0000000000..385c2a75d4
--- /dev/null
+++ b/testing/web-platform/tests/html/rendering/replaced-elements/the-select-element/select-1-block-size-001-ref-2.html
@@ -0,0 +1,24 @@
+<!doctype html>
+<title>CSS Test Reference</title>
+<link rel="author" title="Emilio Cobos Álvarez" href="mailto:emilio@crisal.io">
+<link rel="author" title="Mozilla" href="https://mozilla.org">
+<link rel="help" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1571764">
+<style>
+div {
+ -webkit-appearance: none;
+ appearance: none;
+
+ background: black;
+ color: black;
+
+ line-height: 100px;
+ width: 100px;
+
+ border: 0;
+ padding: 0;
+
+ display: inline-block;
+}
+</style>
+<div>A</div>
+<div>A</div>
diff --git a/testing/web-platform/tests/html/rendering/replaced-elements/the-select-element/select-1-block-size-001-ref.html b/testing/web-platform/tests/html/rendering/replaced-elements/the-select-element/select-1-block-size-001-ref.html
new file mode 100644
index 0000000000..3834281dd8
--- /dev/null
+++ b/testing/web-platform/tests/html/rendering/replaced-elements/the-select-element/select-1-block-size-001-ref.html
@@ -0,0 +1,24 @@
+<!doctype html>
+<title>CSS Test Reference</title>
+<link rel="author" title="Emilio Cobos Álvarez" href="mailto:emilio@crisal.io">
+<link rel="author" title="Mozilla" href="https://mozilla.org">
+<link rel="help" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1571764">
+<link rel="match" href="select-1-block-size-001-ref-2.html">
+<style>
+button {
+ -webkit-appearance: none;
+ appearance: none;
+
+ background: black;
+ color: black;
+
+ line-height: 100px;
+ width: 100px;
+
+ border: 0;
+ border-radius: 0;
+ padding: 0;
+}
+</style>
+<button>A</button>
+<button>A</button>
diff --git a/testing/web-platform/tests/html/rendering/replaced-elements/the-select-element/select-1-block-size-001.html b/testing/web-platform/tests/html/rendering/replaced-elements/the-select-element/select-1-block-size-001.html
new file mode 100644
index 0000000000..5dc0fc15dc
--- /dev/null
+++ b/testing/web-platform/tests/html/rendering/replaced-elements/the-select-element/select-1-block-size-001.html
@@ -0,0 +1,24 @@
+<!doctype html>
+<title>Select block size when line-height is specified</title>
+<link rel="author" title="Emilio Cobos Álvarez" href="mailto:emilio@crisal.io">
+<link rel="author" title="Mozilla" href="https://mozilla.org">
+<link rel="help" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1571764">
+<link rel="match" href="select-1-block-size-001-ref.html">
+<style>
+select {
+ -webkit-appearance: none;
+ appearance: none;
+
+ background: black;
+ color: black;
+
+ line-height: 100px;
+ width: 100px;
+
+ border: 0;
+ border-radius: 0;
+ padding: 0;
+}
+</style>
+<select></select>
+<select><option>A</option></select>
diff --git a/testing/web-platform/tests/html/rendering/replaced-elements/the-select-element/select-1-block-size-ref.html b/testing/web-platform/tests/html/rendering/replaced-elements/the-select-element/select-1-block-size-ref.html
new file mode 100644
index 0000000000..3e437494c0
--- /dev/null
+++ b/testing/web-platform/tests/html/rendering/replaced-elements/the-select-element/select-1-block-size-ref.html
@@ -0,0 +1,33 @@
+<!DOCTYPE HTML>
+<!--
+ Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/
+-->
+<html><head>
+ <meta charset="utf-8">
+ <title>Reference: Combobox block-size test</title>
+ <link rel="author" title="Mats Palmgren" href="mailto:mats@mozilla.com">
+ <style>
+html,body {
+ color:black; background-color:white; font:16px/1 monospace; padding:0; margin:0;
+}
+
+select { -webkit-appearance: none; }
+
+.big { font-size: 48pt; min-height: 40pt; }
+.lh { line-height: 48pt; min-height: 40pt; }
+
+.mask { position:fixed; left:20px; right:0; top:0; bottom:0; background: black; }
+ </style>
+</head>
+<body>
+
+<!-- mask off differences on the right side -->
+<div class="mask"></div>
+
+<select><optgroup label="label"><option>option</option></select><br>
+<select class="big"><optgroup label="label"><option>option</option></select><br>
+<select class="lh"><optgroup label="label"><option>option</option></select><br>
+
+</body>
+</html>
diff --git a/testing/web-platform/tests/html/rendering/replaced-elements/the-select-element/select-1-block-size.html b/testing/web-platform/tests/html/rendering/replaced-elements/the-select-element/select-1-block-size.html
new file mode 100644
index 0000000000..4aecc596ce
--- /dev/null
+++ b/testing/web-platform/tests/html/rendering/replaced-elements/the-select-element/select-1-block-size.html
@@ -0,0 +1,38 @@
+<!DOCTYPE HTML>
+<!--
+ Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/
+-->
+<html><head>
+ <meta charset="utf-8">
+ <title>Test: Combobox block-size test</title>
+ <link rel="author" title="Mats Palmgren" href="mailto:mats@mozilla.com">
+ <link rel="match" href="select-1-block-size-ref.html">
+ <link rel="help" href="https://html.spec.whatwg.org/multipage/rendering.html#the-select-element-2">
+ <link rel="help" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1499578">
+ <style>
+html,body {
+ color:black; background-color:white; font:16px/1 monospace; padding:0; margin:0;
+}
+
+select { -webkit-appearance: none; }
+
+optgroup { font-size: 32pt; }
+option { font-size: 24pt; }
+.big { font-size: 48pt; }
+.lh { line-height: 48pt; }
+
+.mask { position:fixed; left:20px; right:0; top:0; bottom:0; background: black; }
+ </style>
+</head>
+<body>
+
+<!-- mask off differences on the right side -->
+<div class="mask"></div>
+
+<select><optgroup label="label"><option>option</option></select><br>
+<select class="big"><optgroup label="label"><option>option</option></select><br>
+<select class="lh"><optgroup label="label"><option>option</option></select><br>
+
+</body>
+</html>
diff --git a/testing/web-platform/tests/html/rendering/replaced-elements/the-select-element/select-1-line-height-ref.html b/testing/web-platform/tests/html/rendering/replaced-elements/the-select-element/select-1-line-height-ref.html
new file mode 100644
index 0000000000..26e5f33282
--- /dev/null
+++ b/testing/web-platform/tests/html/rendering/replaced-elements/the-select-element/select-1-line-height-ref.html
@@ -0,0 +1,23 @@
+<!DOCTYPE HTML>
+<!--
+ Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/
+-->
+<html><head>
+ <meta charset="utf-8">
+ <title>Reference: Combobox ignores CSS 'line-height'</title>
+ <link rel="author" title="Mats Palmgren" href="mailto:mats@mozilla.com">
+ <style type="text/css">
+html,body {
+ color:black; background-color:white; font:16px/1 monospace;
+}
+
+ </style>
+</head>
+<body>
+
+<select><option>aaaaaaaaaa<option>bbbbbbbbbb</select>
+
+
+</body>
+</html>
diff --git a/testing/web-platform/tests/html/rendering/replaced-elements/the-select-element/select-1-line-height.html b/testing/web-platform/tests/html/rendering/replaced-elements/the-select-element/select-1-line-height.html
new file mode 100644
index 0000000000..605a988e25
--- /dev/null
+++ b/testing/web-platform/tests/html/rendering/replaced-elements/the-select-element/select-1-line-height.html
@@ -0,0 +1,36 @@
+<!DOCTYPE HTML>
+<!--
+ Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/
+-->
+<html><head>
+ <meta charset="utf-8">
+ <title>Test: Combobox ignores CSS 'line-height'</title>
+ <link rel="author" title="Mats Palmgren" href="mailto:mats@mozilla.com">
+ <link rel="match" href="select-1-line-height-ref.html">
+ <link rel="help" href="https://html.spec.whatwg.org/multipage/rendering.html#the-select-element-2">
+ <link rel="help" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1501908">
+ <style type="text/css">
+html,body {
+ color:black; background-color:white; font:16px/1 monospace;
+}
+
+select { line-height:100px; }
+
+ </style>
+</head>
+<body>
+
+<select><option>aaaaaaaaaa<option>bbbbbbbbbb</select>
+
+<script>
+document.body.offsetHeight;
+var cv = window.getComputedStyle(document.querySelector('select')).lineHeight;
+if (cv != "normal" && parseInt(cv) > 50) {
+ document.body.appendChild(document.createTextNode(
+ "FAIL: got computed line-height '" + cv + "', " +
+ "expected 'normal' or a length <= 50px"));
+}</script>
+
+</body>
+</html>
diff --git a/testing/web-platform/tests/html/rendering/replaced-elements/the-select-element/select-empty-ref.html b/testing/web-platform/tests/html/rendering/replaced-elements/the-select-element/select-empty-ref.html
new file mode 100644
index 0000000000..31ba23a5cf
--- /dev/null
+++ b/testing/web-platform/tests/html/rendering/replaced-elements/the-select-element/select-empty-ref.html
@@ -0,0 +1,35 @@
+<!DOCTYPE HTML>
+<!--
+ Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/
+-->
+<html><head>
+ <meta charset="utf-8">
+ <title>Reference: empty SELECT</title>
+ <link rel="author" title="Mats Palmgren" href="mailto:mats@mozilla.com">
+ <style>
+
+.none { display: none; }
+
+ </style>
+</head>
+<body>
+
+<table border="1" cellpadding="10">
+<tr>
+<td><select size="4"><option class="none"></select>
+<td><select size="4" style="-webkit-appearance: none"><option class="none">option</select>
+<td><select size="4" style="-webkit-appearance: none; border: 1px solid black"><option class="none">option</select>
+<td><select size="4" style="border: 1px solid black"><option class="none">option</select>
+</table>
+
+<table border="1" cellpadding="10">
+<tr>
+<td><select size="1"><option class="none"></select>
+<td><select size="1" style="-webkit-appearance: none"><option class="none"></select>
+<td><select size="1" style="-webkit-appearance: none; border: 1px solid black"><option class="none"></select>
+<td><select size="1" style="border: 1px solid black"><option class="none"></select>
+</table>
+
+</body>
+</html>
diff --git a/testing/web-platform/tests/html/rendering/replaced-elements/the-select-element/select-empty.html b/testing/web-platform/tests/html/rendering/replaced-elements/the-select-element/select-empty.html
new file mode 100644
index 0000000000..6568a6de34
--- /dev/null
+++ b/testing/web-platform/tests/html/rendering/replaced-elements/the-select-element/select-empty.html
@@ -0,0 +1,33 @@
+<!DOCTYPE HTML>
+<!--
+ Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/
+-->
+<html><head>
+ <meta charset="utf-8">
+ <title>Test: empty SELECT</title>
+ <link rel="author" title="Mats Palmgren" href="mailto:mats@mozilla.com">
+ <link rel="match" href="select-empty-ref.html">
+ <link rel="help" href="https://html.spec.whatwg.org/multipage/rendering.html#the-select-element-2">
+ <link rel="help" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1499230">
+</head>
+<body>
+
+<table border="1" cellpadding="10">
+<tr>
+<td><select size="4"></select>
+<td><select size="4" style="-webkit-appearance: none"></select>
+<td><select size="4" style="-webkit-appearance: none; border: 1px solid black"></select>
+<td><select size="4" style="border: 1px solid black"></select>
+</table>
+
+<table border="1" cellpadding="10">
+<tr>
+<td><select size="1"></select>
+<td><select size="1" style="-webkit-appearance: none"></select>
+<td><select size="1" style="-webkit-appearance: none; border: 1px solid black"></select>
+<td><select size="1" style="border: 1px solid black"></select>
+</table>
+
+</body>
+</html>
diff --git a/testing/web-platform/tests/html/rendering/replaced-elements/the-select-element/select-intrinsic-option-font-size-ref.html b/testing/web-platform/tests/html/rendering/replaced-elements/the-select-element/select-intrinsic-option-font-size-ref.html
new file mode 100644
index 0000000000..8b1b422176
--- /dev/null
+++ b/testing/web-platform/tests/html/rendering/replaced-elements/the-select-element/select-intrinsic-option-font-size-ref.html
@@ -0,0 +1,8 @@
+<!doctype html>
+<title>CSS Test Reference</title>
+<select>
+ <option>ABC</option>
+</select>
+<select>
+ <option>ABC</option>
+</select>
diff --git a/testing/web-platform/tests/html/rendering/replaced-elements/the-select-element/select-intrinsic-option-font-size.html b/testing/web-platform/tests/html/rendering/replaced-elements/the-select-element/select-intrinsic-option-font-size.html
new file mode 100644
index 0000000000..7f36708973
--- /dev/null
+++ b/testing/web-platform/tests/html/rendering/replaced-elements/the-select-element/select-intrinsic-option-font-size.html
@@ -0,0 +1,9 @@
+<!doctype html>
+<title>Select should be as wide as needed to fit its options regardless of option styles</title>
+<link rel=match href=select-intrinsic-option-font-size-ref.html>
+<select>
+ <option style="font-size: 5px">ABC</option>
+</select>
+<select>
+ <option style="font-size: 50px">ABC</option>
+</select>
diff --git a/testing/web-platform/tests/html/rendering/replaced-elements/the-select-element/select-intrinsic-text-transform-ref.html b/testing/web-platform/tests/html/rendering/replaced-elements/the-select-element/select-intrinsic-text-transform-ref.html
new file mode 100644
index 0000000000..18e272ba10
--- /dev/null
+++ b/testing/web-platform/tests/html/rendering/replaced-elements/the-select-element/select-intrinsic-text-transform-ref.html
@@ -0,0 +1,5 @@
+<!doctype html>
+<title>CSS Test Reference</title>
+<select>
+ <option>ABCDEFGHIJK</option>
+</select>
diff --git a/testing/web-platform/tests/html/rendering/replaced-elements/the-select-element/select-intrinsic-text-transform.html b/testing/web-platform/tests/html/rendering/replaced-elements/the-select-element/select-intrinsic-text-transform.html
new file mode 100644
index 0000000000..1026e29977
--- /dev/null
+++ b/testing/web-platform/tests/html/rendering/replaced-elements/the-select-element/select-intrinsic-text-transform.html
@@ -0,0 +1,8 @@
+<!doctype html>
+<title>text-transform in option doesn't affect combobox rendering</title>
+<link rel=match href=select-intrinsic-text-transform-ref.html>
+<link rel=help href="https://bugs.chromium.org/p/chromium/issues/detail?id=1283930">
+<link rel=author href="mailto:emilio@crisal.io" title="Emilio Cobos Álvarez">
+<select>
+ <option style="text-transform: lowercase">ABCDEFGHIJK</option>
+</select>
diff --git a/testing/web-platform/tests/html/rendering/replaced-elements/the-select-element/select-multiple-re-add-option-via-document-fragment-ref.html b/testing/web-platform/tests/html/rendering/replaced-elements/the-select-element/select-multiple-re-add-option-via-document-fragment-ref.html
new file mode 100644
index 0000000000..cb66ddaaaf
--- /dev/null
+++ b/testing/web-platform/tests/html/rendering/replaced-elements/the-select-element/select-multiple-re-add-option-via-document-fragment-ref.html
@@ -0,0 +1,4 @@
+<!doctype html>
+<title>Reference: Move option from select[multiple] into DocumentFragment and back</title>
+<p>You should see the word PASS below.</p>
+<select multiple><option>PASS</option></select>
diff --git a/testing/web-platform/tests/html/rendering/replaced-elements/the-select-element/select-multiple-re-add-option-via-document-fragment.html b/testing/web-platform/tests/html/rendering/replaced-elements/the-select-element/select-multiple-re-add-option-via-document-fragment.html
new file mode 100644
index 0000000000..844f05639c
--- /dev/null
+++ b/testing/web-platform/tests/html/rendering/replaced-elements/the-select-element/select-multiple-re-add-option-via-document-fragment.html
@@ -0,0 +1,12 @@
+<!doctype html>
+<title>Test: Move option from select[multiple] into DocumentFragment and back</title>
+<link rel="help" href="https://html.spec.whatwg.org/multipage/rendering.html#the-select-element-2">
+<link rel="match" href="select-multiple-re-add-option-via-document-fragment-ref.html">
+<p>You should see the word PASS below.</p>
+<select multiple id="sel"><option id="opt">PASS</option></select>
+<script>
+ document.body.offsetTop;
+ let rm = opt;
+ document.createDocumentFragment().appendChild(rm);
+ sel.appendChild(rm);
+</script>
diff --git a/testing/web-platform/tests/html/rendering/replaced-elements/the-textarea-element/textarea-padding-bend-overlaps-content-001-ref.html b/testing/web-platform/tests/html/rendering/replaced-elements/the-textarea-element/textarea-padding-bend-overlaps-content-001-ref.html
new file mode 100644
index 0000000000..2f479dd72a
--- /dev/null
+++ b/testing/web-platform/tests/html/rendering/replaced-elements/the-textarea-element/textarea-padding-bend-overlaps-content-001-ref.html
@@ -0,0 +1,32 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>Reference Case</title>
+
+<link rel="stylesheet" href="/fonts/ahem.css">
+<style>
+textarea {
+ font: 10px/1 Ahem;
+
+ block-size: 8em;
+ inline-size: 10em;
+
+ padding-block-end: 0;
+}
+.rtl { direction: rtl; }
+.vlr { writing-mode: vertical-lr; }
+.vrl { writing-mode: vertical-rl; }
+.slr { writing-mode: sideways-lr; }
+.srl { writing-mode: sideways-rl; }
+</style>
+<textarea>X</textarea>
+<textarea class="rtl">X</textarea>
+<br>
+<textarea class="vlr">X</textarea>
+<textarea class="vrl">X</textarea>
+<textarea class="slr">X</textarea>
+<textarea class="srl">X</textarea>
+<br>
+<textarea class="vlr rtl">X</textarea>
+<textarea class="vrl rtl">X</textarea>
+<textarea class="slr rtl">X</textarea>
+<textarea class="srl rtl">X</textarea>
diff --git a/testing/web-platform/tests/html/rendering/replaced-elements/the-textarea-element/textarea-padding-bend-overlaps-content-001.tentative.html b/testing/web-platform/tests/html/rendering/replaced-elements/the-textarea-element/textarea-padding-bend-overlaps-content-001.tentative.html
new file mode 100644
index 0000000000..d99ca1956f
--- /dev/null
+++ b/testing/web-platform/tests/html/rendering/replaced-elements/the-textarea-element/textarea-padding-bend-overlaps-content-001.tentative.html
@@ -0,0 +1,43 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>Test: padding-block-end on a textarea creates space that content can render into</title>
+<link rel="help" href="https://html.spec.whatwg.org/multipage/rendering.html#the-textarea-element-2">
+<link rel="match" href="textarea-padding-bend-overlaps-content-001-ref.html">
+
+<link rel="stylesheet" href="/fonts/ahem.css">
+<style>
+textarea {
+ font: 10px/1 Ahem;
+
+ /* Zero out the content-box, leaving the padding area as the only
+ place where the contents might get rendered. */
+ block-size: 0;
+ inline-size: 10em;
+
+ padding-block-end: 8em;
+
+ /* The textarea's padding-block-end may create overflow in the block axis,
+ and hence generate a scrollbar in the testcase that's not present in the
+ reference case (and might be hard to properly mock up there). We avoid
+ this problem by suppressing scrollbars using "overflow:hidden": */
+ overflow: hidden;
+}
+.rtl { direction: rtl; }
+.vlr { writing-mode: vertical-lr; }
+.vrl { writing-mode: vertical-rl; }
+.slr { writing-mode: sideways-lr; }
+.srl { writing-mode: sideways-rl; }
+</style>
+
+<textarea>X</textarea>
+<textarea class="rtl">X</textarea>
+<br>
+<textarea class="vlr">X</textarea>
+<textarea class="vrl">X</textarea>
+<textarea class="slr">X</textarea>
+<textarea class="srl">X</textarea>
+<br>
+<textarea class="vlr rtl">X</textarea>
+<textarea class="vrl rtl">X</textarea>
+<textarea class="slr rtl">X</textarea>
+<textarea class="srl rtl">X</textarea>
diff --git a/testing/web-platform/tests/html/rendering/replaced-elements/the-textarea-element/textarea-padding-bstart-moves-content-001-ref.html b/testing/web-platform/tests/html/rendering/replaced-elements/the-textarea-element/textarea-padding-bstart-moves-content-001-ref.html
new file mode 100644
index 0000000000..5144f18660
--- /dev/null
+++ b/testing/web-platform/tests/html/rendering/replaced-elements/the-textarea-element/textarea-padding-bstart-moves-content-001-ref.html
@@ -0,0 +1,34 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>Reference Case</title>
+
+<link rel="stylesheet" href="/fonts/ahem.css">
+<style>
+textarea {
+ font: 10px/1 Ahem;
+
+ block-size: 8em;
+ inline-size: 10em;
+
+ padding-block-start: 0;
+ padding-block-end: 0;
+}
+.rtl { direction: rtl; }
+.vlr { writing-mode: vertical-lr; }
+.vrl { writing-mode: vertical-rl; }
+.slr { writing-mode: sideways-lr; }
+.srl { writing-mode: sideways-rl; }
+</style>
+
+<textarea></textarea>
+<textarea class="rtl"></textarea>
+<br>
+<textarea class="vlr"></textarea>
+<textarea class="vrl"></textarea>
+<textarea class="slr"></textarea>
+<textarea class="srl"></textarea>
+<br>
+<textarea class="vlr rtl"></textarea>
+<textarea class="vrl rtl"></textarea>
+<textarea class="slr rtl"></textarea>
+<textarea class="srl rtl"></textarea>
diff --git a/testing/web-platform/tests/html/rendering/replaced-elements/the-textarea-element/textarea-padding-bstart-moves-content-001.tentative.html b/testing/web-platform/tests/html/rendering/replaced-elements/the-textarea-element/textarea-padding-bstart-moves-content-001.tentative.html
new file mode 100644
index 0000000000..f4643af132
--- /dev/null
+++ b/testing/web-platform/tests/html/rendering/replaced-elements/the-textarea-element/textarea-padding-bstart-moves-content-001.tentative.html
@@ -0,0 +1,46 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>Test: padding-block-start on a textarea moves the textarea content over, potentially out of the textarea's scrollport</title>
+<link rel="help" href="https://html.spec.whatwg.org/multipage/rendering.html#the-textarea-element-2">
+<link rel="match" href="textarea-padding-bstart-moves-content-001-ref.html">
+
+<link rel="stylesheet" href="/fonts/ahem.css">
+<style>
+textarea {
+ font: 10px/1 Ahem;
+
+ /* Zero out the content-box, leaving the padding area as the only
+ place where the contents might get rendered. */
+ block-size: 0;
+ inline-size: 10em;
+
+ padding-block-start: 8em;
+ padding-block-end: 0;
+
+ /* We expect the textarea's content to overflow in the block direction,
+ which makes the textarea blank, aside from any scrollbars that might get
+ created by this overflow. We use overflow:hidden here to suppress these
+ scrollbars, so that the reference case can just use a trivial empty
+ textarea (without needing to worry about mocking up scrollbars of
+ precisely the right size). */
+ overflow: hidden;
+}
+.rtl { direction: rtl; }
+.vlr { writing-mode: vertical-lr; }
+.vrl { writing-mode: vertical-rl; }
+.slr { writing-mode: sideways-lr; }
+.srl { writing-mode: sideways-rl; }
+</style>
+
+<textarea>X</textarea>
+<textarea class="rtl">X</textarea>
+<br>
+<textarea class="vlr">X</textarea>
+<textarea class="vrl">X</textarea>
+<textarea class="slr">X</textarea>
+<textarea class="srl">X</textarea>
+<br>
+<textarea class="vlr rtl">X</textarea>
+<textarea class="vrl rtl">X</textarea>
+<textarea class="slr rtl">X</textarea>
+<textarea class="srl rtl">X</textarea>
diff --git a/testing/web-platform/tests/html/rendering/replaced-elements/the-textarea-element/textarea-padding-iend-overlaps-content-001-ref.html b/testing/web-platform/tests/html/rendering/replaced-elements/the-textarea-element/textarea-padding-iend-overlaps-content-001-ref.html
new file mode 100644
index 0000000000..94473c0873
--- /dev/null
+++ b/testing/web-platform/tests/html/rendering/replaced-elements/the-textarea-element/textarea-padding-iend-overlaps-content-001-ref.html
@@ -0,0 +1,32 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>Reference Case</title>
+
+<link rel="stylesheet" href="/fonts/ahem.css">
+<style>
+textarea {
+ font: 10px/1 Ahem;
+
+ inline-size: 8em;
+ block-size: 10em;
+
+ padding-inline-end: 0;
+}
+.rtl { direction: rtl; }
+.vlr { writing-mode: vertical-lr; }
+.vrl { writing-mode: vertical-rl; }
+.slr { writing-mode: sideways-lr; }
+.srl { writing-mode: sideways-rl; }
+</style>
+<textarea>X</textarea>
+<textarea class="rtl">X</textarea>
+<br>
+<textarea class="vlr">X</textarea>
+<textarea class="vrl">X</textarea>
+<textarea class="slr">X</textarea>
+<textarea class="srl">X</textarea>
+<br>
+<textarea class="vlr rtl">X</textarea>
+<textarea class="vrl rtl">X</textarea>
+<textarea class="slr rtl">X</textarea>
+<textarea class="srl rtl">X</textarea>
diff --git a/testing/web-platform/tests/html/rendering/replaced-elements/the-textarea-element/textarea-padding-iend-overlaps-content-001.tentative.html b/testing/web-platform/tests/html/rendering/replaced-elements/the-textarea-element/textarea-padding-iend-overlaps-content-001.tentative.html
new file mode 100644
index 0000000000..80cbbe3c1e
--- /dev/null
+++ b/testing/web-platform/tests/html/rendering/replaced-elements/the-textarea-element/textarea-padding-iend-overlaps-content-001.tentative.html
@@ -0,0 +1,37 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>Test: padding-inline-end on a textarea creates space that content can render into</title>
+<link rel="help" href="https://html.spec.whatwg.org/multipage/rendering.html#the-textarea-element-2">
+<link rel="match" href="textarea-padding-iend-overlaps-content-001-ref.html">
+
+<link rel="stylesheet" href="/fonts/ahem.css">
+<style>
+textarea {
+ font: 10px/1 Ahem;
+
+ /* Zero out the content-box, leaving the padding area as the only
+ place where the contents might get rendered. */
+ inline-size: 0;
+ block-size: 10em;
+
+ padding-inline-end: 8em;
+}
+.rtl { direction: rtl; }
+.vlr { writing-mode: vertical-lr; }
+.vrl { writing-mode: vertical-rl; }
+.slr { writing-mode: sideways-lr; }
+.srl { writing-mode: sideways-rl; }
+</style>
+
+<textarea>X</textarea>
+<textarea class="rtl">X</textarea>
+<br>
+<textarea class="vlr">X</textarea>
+<textarea class="vrl">X</textarea>
+<textarea class="slr">X</textarea>
+<textarea class="srl">X</textarea>
+<br>
+<textarea class="vlr rtl">X</textarea>
+<textarea class="vrl rtl">X</textarea>
+<textarea class="slr rtl">X</textarea>
+<textarea class="srl rtl">X</textarea>
diff --git a/testing/web-platform/tests/html/rendering/replaced-elements/the-textarea-element/textarea-padding-istart-moves-content-001-ref.html b/testing/web-platform/tests/html/rendering/replaced-elements/the-textarea-element/textarea-padding-istart-moves-content-001-ref.html
new file mode 100644
index 0000000000..eb88858b87
--- /dev/null
+++ b/testing/web-platform/tests/html/rendering/replaced-elements/the-textarea-element/textarea-padding-istart-moves-content-001-ref.html
@@ -0,0 +1,34 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>Reference Case</title>
+
+<link rel="stylesheet" href="/fonts/ahem.css">
+<style>
+textarea {
+ font: 10px/1 Ahem;
+
+ inline-size: 8em;
+ block-size: 10em;
+
+ padding-inline-start: 0;
+ padding-inline-end: 0;
+}
+.rtl { direction: rtl; }
+.vlr { writing-mode: vertical-lr; }
+.vrl { writing-mode: vertical-rl; }
+.slr { writing-mode: sideways-lr; }
+.srl { writing-mode: sideways-rl; }
+</style>
+
+<textarea></textarea>
+<textarea class="rtl"></textarea>
+<br>
+<textarea class="vlr"></textarea>
+<textarea class="vrl"></textarea>
+<textarea class="slr"></textarea>
+<textarea class="srl"></textarea>
+<br>
+<textarea class="vlr rtl"></textarea>
+<textarea class="vrl rtl"></textarea>
+<textarea class="slr rtl"></textarea>
+<textarea class="srl rtl"></textarea>
diff --git a/testing/web-platform/tests/html/rendering/replaced-elements/the-textarea-element/textarea-padding-istart-moves-content-001.tentative.html b/testing/web-platform/tests/html/rendering/replaced-elements/the-textarea-element/textarea-padding-istart-moves-content-001.tentative.html
new file mode 100644
index 0000000000..f5abf84c12
--- /dev/null
+++ b/testing/web-platform/tests/html/rendering/replaced-elements/the-textarea-element/textarea-padding-istart-moves-content-001.tentative.html
@@ -0,0 +1,46 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>Test: padding-inline-start on a textarea moves the textarea content over, potentially out of the textarea's scrollport</title>
+<link rel="help" href="https://html.spec.whatwg.org/multipage/rendering.html#the-textarea-element-2">
+<link rel="match" href="textarea-padding-istart-moves-content-001-ref.html">
+
+<link rel="stylesheet" href="/fonts/ahem.css">
+<style>
+textarea {
+ font: 10px/1 Ahem;
+
+ /* Zero out the content-box, leaving the padding area as the only
+ place where the contents might get rendered. */
+ inline-size: 0;
+ block-size: 10em;
+
+ padding-inline-start: 8em;
+ padding-inline-end: 0;
+
+ /* We expect the textarea's content to overflow in the inline direction,
+ which makes the textarea blank, aside from any scrollbars that might get
+ created by this overflow. We use overflow:hidden here to suppress these
+ scrollbars, so that the reference case can just use a trivial empty
+ textarea (without needing to worry about mocking up scrollbars of
+ precisely the right size). */
+ overflow: hidden;
+}
+.rtl { direction: rtl; }
+.vlr { writing-mode: vertical-lr; }
+.vrl { writing-mode: vertical-rl; }
+.slr { writing-mode: sideways-lr; }
+.srl { writing-mode: sideways-rl; }
+</style>
+
+<textarea>X</textarea>
+<textarea class="rtl">X</textarea>
+<br>
+<textarea class="vlr">X</textarea>
+<textarea class="vrl">X</textarea>
+<textarea class="slr">X</textarea>
+<textarea class="srl">X</textarea>
+<br>
+<textarea class="vlr rtl">X</textarea>
+<textarea class="vrl rtl">X</textarea>
+<textarea class="slr rtl">X</textarea>
+<textarea class="srl rtl">X</textarea>
diff --git a/testing/web-platform/tests/html/rendering/replaced-elements/tools/gen-svgsizing-tests.py b/testing/web-platform/tests/html/rendering/replaced-elements/tools/gen-svgsizing-tests.py
new file mode 100644
index 0000000000..5ba69f8ab5
--- /dev/null
+++ b/testing/web-platform/tests/html/rendering/replaced-elements/tools/gen-svgsizing-tests.py
@@ -0,0 +1,55 @@
+from string import Template
+import os
+import sys
+
+template = Template("""<!DOCTYPE html>
+<!-- This file is generated by $generator -->
+<html>
+ <head>
+ <title>SVG sizing: &lt;$placeholder></title>
+ <meta name=timeout content=long>
+ <script src="/resources/testharness.js"></script>
+ <script src="/resources/testharnessreport.js"></script>
+ <script src="../resources/svg-sizing.js"></script>
+ <style>
+ #testContainer {
+ position: absolute;
+ left: 0;
+ top: 0;
+ width: 800px;
+ height: 600px
+ }
+ iframe { border: 0 }
+ </style>
+ <link rel="help" href="http://www.w3.org/TR/CSS2/visudet.html#inline-replaced-width">
+ <link rel="help" href="http://www.w3.org/TR/CSS2/visudet.html#inline-replaced-height">
+ <link rel="help" href="https://html.spec.whatwg.org/multipage/#replaced-elements">
+ <link rel="help" href="https://html.spec.whatwg.org/multipage/#attr-dim-width">
+ <link rel="help" href="http://www.w3.org/TR/SVG/coords.html#ViewportSpace">
+ </head>
+ <body>
+ <div id="log"></div>
+ <div id="testContainer"></div>
+ <div id="demo"></div>
+ <script src="svg-embedded-sizing.js"></script>
+ <script>testPlaceholderWithHeight("$placeholder", $placeholderHeightAttr)</script>
+ </body>
+</html>
+""")
+
+placeholders = [ "object", "iframe", "img" ]
+placeholderHeightAttrs = [ "null", "'100px'", "'100%'" ]
+placeholderHeightAttrsDescriptions = [ "auto", "fixed", "percentage" ]
+
+try:
+ os.makedirs("../svg-embedded-sizing")
+except OSError:
+ pass
+
+for placeholder in placeholders:
+ for i, placeholderHeightAttr in enumerate(placeholderHeightAttrs):
+ testContent = template.substitute(placeholder=placeholder, placeholderHeightAttr=placeholderHeightAttr, generator=sys.argv[0])
+ filename = "../svg-embedded-sizing/svg-in-%s-%s.html" % (placeholder, placeholderHeightAttrsDescriptions[i])
+ f = open(filename, "w")
+ f.write(testContent)
+ f.close()