summaryrefslogtreecommitdiffstats
path: root/testing/web-platform/tests/custom-elements/parser
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-07 09:22:09 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-07 09:22:09 +0000
commit43a97878ce14b72f0981164f87f2e35e14151312 (patch)
tree620249daf56c0258faa40cbdcf9cfba06de2a846 /testing/web-platform/tests/custom-elements/parser
parentInitial commit. (diff)
downloadfirefox-43a97878ce14b72f0981164f87f2e35e14151312.tar.xz
firefox-43a97878ce14b72f0981164f87f2e35e14151312.zip
Adding upstream version 110.0.1.upstream/110.0.1upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'testing/web-platform/tests/custom-elements/parser')
-rw-r--r--testing/web-platform/tests/custom-elements/parser/parser-constructs-custom-element-in-document-write.html43
-rw-r--r--testing/web-platform/tests/custom-elements/parser/parser-constructs-custom-element-synchronously.html51
-rw-r--r--testing/web-platform/tests/custom-elements/parser/parser-constructs-custom-elements-with-is.html51
-rw-r--r--testing/web-platform/tests/custom-elements/parser/parser-constructs-custom-elements.html48
-rw-r--r--testing/web-platform/tests/custom-elements/parser/parser-custom-element-in-foreign-content.html28
-rw-r--r--testing/web-platform/tests/custom-elements/parser/parser-fallsback-to-unknown-element.html91
-rw-r--r--testing/web-platform/tests/custom-elements/parser/parser-sets-attributes-and-children.html95
-rw-r--r--testing/web-platform/tests/custom-elements/parser/parser-uses-constructed-element.html75
-rw-r--r--testing/web-platform/tests/custom-elements/parser/parser-uses-create-an-element-for-a-token-svg.svg27
-rw-r--r--testing/web-platform/tests/custom-elements/parser/parser-uses-registry-of-owner-document.html154
-rw-r--r--testing/web-platform/tests/custom-elements/parser/serializing-html-fragments-customized-builtins.html37
11 files changed, 700 insertions, 0 deletions
diff --git a/testing/web-platform/tests/custom-elements/parser/parser-constructs-custom-element-in-document-write.html b/testing/web-platform/tests/custom-elements/parser/parser-constructs-custom-element-in-document-write.html
new file mode 100644
index 0000000000..14c830b9ba
--- /dev/null
+++ b/testing/web-platform/tests/custom-elements/parser/parser-constructs-custom-element-in-document-write.html
@@ -0,0 +1,43 @@
+<!DOCTYPE html>
+<html>
+<head>
+<title>Custom Elements: Changes to the HTML parser</title>
+<meta name="author" title="Ryosuke Niwa" href="mailto:rniwa@webkit.org">
+<meta name="assert" content="HTML parser must construct custom elements inside document.write">
+<link rel="help" href="https://html.spec.whatwg.org/#create-an-element-for-the-token">
+<link rel="help" href="https://dom.spec.whatwg.org/#concept-create-element">
+<link rel="help" href="https://html.spec.whatwg.org/#document.write()">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+</head>
+<body>
+<div id="log"></div>
+<script>
+
+var numberOfChildNodesInConnectedCallback = 0;
+
+class MyCustomElement extends HTMLElement {
+ connectedCallback() {
+ numberOfChildNodesInConnectedCallback = this.childNodes.length;
+ }
+}
+customElements.define('my-custom-element', MyCustomElement);
+
+document.write('<my-custom-element>hello <b>world</b></my-custom-element>');
+
+test(function () {
+ var instance = document.querySelector('my-custom-element');
+
+ assert_true(instance instanceof HTMLElement);
+ assert_true(instance instanceof MyCustomElement);
+
+}, 'HTML parser must instantiate custom elements inside document.write');
+
+test(function () {
+ assert_equals(numberOfChildNodesInConnectedCallback, 0);
+
+}, 'HTML parser should call connectedCallback before appending child nodes inside document.write');
+
+</script>
+</body>
+</html>
diff --git a/testing/web-platform/tests/custom-elements/parser/parser-constructs-custom-element-synchronously.html b/testing/web-platform/tests/custom-elements/parser/parser-constructs-custom-element-synchronously.html
new file mode 100644
index 0000000000..206aa17f20
--- /dev/null
+++ b/testing/web-platform/tests/custom-elements/parser/parser-constructs-custom-element-synchronously.html
@@ -0,0 +1,51 @@
+<!DOCTYPE html>
+<html>
+<head>
+<title>Custom Elements: Changes to the HTML parser</title>
+<meta name="author" title="Ryosuke Niwa" href="mailto:rniwa@webkit.org">
+<meta name="assert" content="HTML parser must construct a custom element synchronously">
+<link rel="help" href="https://html.spec.whatwg.org/#create-an-element-for-the-token">
+<link rel="help" href="https://dom.spec.whatwg.org/#concept-create-element">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+</head>
+<body>
+<div id="log"></div>
+<script>
+
+var childElementCountInConstructor;
+var containerChildNodesInConstructor = [];
+var containerNextSiblingInConstructor;
+class MyCustomElement extends HTMLElement {
+ constructor() {
+ super();
+ var container = document.getElementById('custom-element-container');
+ for (var i = 0; i < container.childNodes.length; i++)
+ containerChildNodesInConstructor.push(container.childNodes[i]);
+ containerNextSiblingInConstructor = container.nextSibling;
+ }
+};
+customElements.define('my-custom-element', MyCustomElement);
+
+</script>
+<div id="custom-element-container">
+ <span id="custom-element-previous-element"></span>
+ <my-custom-element></my-custom-element>
+ <div id="custom-element-next-element"></div>
+</div>
+<script>
+
+test(function () {
+ var instance = document.querySelector('my-custom-element');
+
+ assert_equals(containerChildNodesInConstructor.length, 3);
+ assert_equals(containerChildNodesInConstructor[0], instance.parentNode.firstChild);
+ assert_equals(containerChildNodesInConstructor[1], document.getElementById('custom-element-previous-element'));
+ assert_equals(containerChildNodesInConstructor[2], instance.previousSibling);
+ assert_equals(containerNextSiblingInConstructor, null);
+
+}, 'HTML parser must only append nodes that appear before a custom element before instantiating the custom element');
+
+</script>
+</body>
+</html>
diff --git a/testing/web-platform/tests/custom-elements/parser/parser-constructs-custom-elements-with-is.html b/testing/web-platform/tests/custom-elements/parser/parser-constructs-custom-elements-with-is.html
new file mode 100644
index 0000000000..96c00278a3
--- /dev/null
+++ b/testing/web-platform/tests/custom-elements/parser/parser-constructs-custom-elements-with-is.html
@@ -0,0 +1,51 @@
+<!DOCTYPE html>
+<html>
+<head>
+<title>Custom Elements: Changes to the HTML parser</title>
+<meta name="author" title="John Dai" href="mailto:jdai@mozilla.com">
+<meta name="assert" content="HTML parser creates a custom element which contains is attribute">
+<link rel="help" href="https://html.spec.whatwg.org/#create-an-element-for-the-token">
+<link rel="help" href="https://dom.spec.whatwg.org/#concept-create-element">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+</head>
+<body>
+<div id="log"></div>
+<autonomous-custom-element id="instance1" is="is-custom-element"></autonomous-custom-element>
+<script>
+
+class AutonomousCustomElement extends HTMLElement { };
+class IsCustomElement extends HTMLElement { };
+
+customElements.define('autonomous-custom-element', AutonomousCustomElement);
+customElements.define('is-custom-element', IsCustomElement);
+
+test(function () {
+ var customElement = document.getElementById('instance1');
+
+ assert_true(customElement instanceof HTMLElement, 'A resolved custom element must be an instance of HTMLElement');
+ assert_false(customElement instanceof HTMLUnknownElement, 'A resolved custom element must NOT be an instance of HTMLUnknownElement');
+ assert_true(customElement instanceof AutonomousCustomElement, 'A resolved custom element must be an instance of that custom element');
+ assert_equals(customElement.localName, 'autonomous-custom-element');
+ assert_equals(customElement.namespaceURI, 'http://www.w3.org/1999/xhtml', 'A custom element HTML must use HTML namespace');
+
+}, 'HTML parser must create a defined autonomous custom element when customElements.define comes after HTML parser creation');
+
+</script>
+<autonomous-custom-element id="instance2" is="is-custom-element"></autonomous-custom-element>
+<script>
+
+test(function () {
+ var customElement = document.getElementById('instance2');
+
+ assert_true(customElement instanceof HTMLElement, 'A resolved custom element must be an instance of HTMLElement');
+ assert_false(customElement instanceof HTMLUnknownElement, 'A resolved custom element must NOT be an instance of HTMLUnknownElement');
+ assert_true(customElement instanceof AutonomousCustomElement, 'A resolved custom element must be an instance of that custom element');
+ assert_equals(customElement.localName, 'autonomous-custom-element');
+ assert_equals(customElement.namespaceURI, 'http://www.w3.org/1999/xhtml', 'A custom element HTML must use HTML namespace');
+
+}, 'HTML parser must create a defined autonomous custom element when customElements.define comes before HTML parser creation');
+
+</script>
+</body>
+</html>
diff --git a/testing/web-platform/tests/custom-elements/parser/parser-constructs-custom-elements.html b/testing/web-platform/tests/custom-elements/parser/parser-constructs-custom-elements.html
new file mode 100644
index 0000000000..3f13c50a0e
--- /dev/null
+++ b/testing/web-platform/tests/custom-elements/parser/parser-constructs-custom-elements.html
@@ -0,0 +1,48 @@
+<!DOCTYPE html>
+<html>
+<head>
+<title>Custom Elements: Changes to the HTML parser</title>
+<meta name="author" title="Ryosuke Niwa" href="mailto:rniwa@webkit.org">
+<meta name="assert" content="HTML parser creates a custom element">
+<link rel="help" href="https://html.spec.whatwg.org/#create-an-element-for-the-token">
+<link rel="help" href="https://dom.spec.whatwg.org/#concept-create-element">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+</head>
+<body>
+<div id="log"></div>
+<my-custom-element id="instance1"></my-custom-element>
+<script>
+
+class MyCustomElement extends HTMLElement { };
+
+test(function () {
+ var customElement = document.getElementById('instance1');
+
+ assert_true(customElement instanceof HTMLElement, 'An unresolved custom element must be an instance of HTMLElement');
+ assert_false(customElement instanceof MyCustomElement, 'An unresolved custom element must NOT be an instance of that custom element');
+ assert_equals(customElement.localName, 'my-custom-element');
+ assert_equals(customElement.namespaceURI, 'http://www.w3.org/1999/xhtml', 'A custom element HTML must use HTML namespace');
+
+}, 'HTML parser must NOT create a custom element before customElements.define is called');
+
+customElements.define('my-custom-element', MyCustomElement);
+
+</script>
+<my-custom-element id="instance2"></my-custom-element>
+<script>
+
+test(function () {
+ var customElement = document.getElementById('instance2');
+
+ assert_true(customElement instanceof HTMLElement, 'A resolved custom element must be an instance of HTMLElement');
+ assert_false(customElement instanceof HTMLUnknownElement, 'A resolved custom element must NOT be an instance of HTMLUnknownElement');
+ assert_true(customElement instanceof MyCustomElement, 'A resolved custom element must be an instance of that custom element');
+ assert_equals(customElement.localName, 'my-custom-element');
+ assert_equals(customElement.namespaceURI, 'http://www.w3.org/1999/xhtml', 'A custom element HTML must use HTML namespace');
+
+}, 'HTML parser must create a defined custom element before executing inline scripts');
+
+</script>
+</body>
+</html>
diff --git a/testing/web-platform/tests/custom-elements/parser/parser-custom-element-in-foreign-content.html b/testing/web-platform/tests/custom-elements/parser/parser-custom-element-in-foreign-content.html
new file mode 100644
index 0000000000..2ae0f1309c
--- /dev/null
+++ b/testing/web-platform/tests/custom-elements/parser/parser-custom-element-in-foreign-content.html
@@ -0,0 +1,28 @@
+<!DOCTYPE html>
+<title>Custom Elements: Custom element in foreign content</title>
+<meta name="assert" content="HTML parser should not create non-HTML namespace custom elements">
+<link rel="help" href="https://html.spec.whatwg.org/#create-an-element-for-the-token">
+<link rel="help" href="https://dom.spec.whatwg.org/#concept-create-element">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script>
+class ThrowsException extends HTMLElement {
+ constructor() {
+ throw 'Bad';
+ }
+};
+customElements.define('throws-exception', ThrowsException);
+</script>
+<svg>
+ <throws-exception/>
+</svg>
+<script>
+test(function () {
+ var instance = document.querySelector('throws-exception');
+ assert_false(instance instanceof ThrowsException,
+ 'The HTML parser must NOT instantiate a custom element in non-HTML namespaces');
+ assert_false(instance instanceof HTMLUnknownElement, 'The HTML parser should not fallback');
+ assert_true(instance instanceof SVGElement,
+ 'The element created by the HTML parser must be an instance of SVGElement');
+}, 'HTML parser should not create custom elements in non-HTML namespaces');
+</script>
diff --git a/testing/web-platform/tests/custom-elements/parser/parser-fallsback-to-unknown-element.html b/testing/web-platform/tests/custom-elements/parser/parser-fallsback-to-unknown-element.html
new file mode 100644
index 0000000000..82e970f1ae
--- /dev/null
+++ b/testing/web-platform/tests/custom-elements/parser/parser-fallsback-to-unknown-element.html
@@ -0,0 +1,91 @@
+<!DOCTYPE html>
+<html>
+<head>
+<title>Custom Elements: Changes to the HTML parser</title>
+<meta name="author" title="Ryosuke Niwa" href="mailto:rniwa@webkit.org">
+<meta name="assert" content="HTML parser must fallback to creating a HTMLUnknownElement when a custom element construction fails">
+<link rel="help" href="https://html.spec.whatwg.org/#create-an-element-for-the-token">
+<link rel="help" href="https://dom.spec.whatwg.org/#concept-create-element">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+</head>
+<body>
+<div id="log"></div>
+<script>
+
+setup({allow_uncaught_exception:true});
+
+class ReturnsTextNode extends HTMLElement {
+ constructor() {
+ super();
+ return document.createTextNode('some text');
+ }
+};
+customElements.define('returns-text', ReturnsTextNode);
+
+class ReturnsNonElementObject extends HTMLElement {
+ constructor() {
+ super();
+ return {};
+ }
+};
+customElements.define('returns-non-element-object', ReturnsNonElementObject);
+
+class LacksSuperCall extends HTMLElement {
+ constructor() { }
+};
+customElements.define('lacks-super-call', LacksSuperCall);
+
+class ThrowsException extends HTMLElement {
+ constructor() {
+ throw 'Bad';
+ }
+};
+customElements.define('throws-exception', ThrowsException);
+
+</script>
+<returns-text></returns-text>
+<returns-non-element-object></returns-non-element-object>
+<lacks-super-call></lacks-super-call>
+<throws-exception></throws-exception>
+<script>
+
+test(function () {
+ var instance = document.querySelector('returns-text');
+
+ assert_false(instance instanceof ReturnsTextNode, 'HTML parser must NOT instantiate a custom element when the constructor returns a Text node');
+ assert_true(instance instanceof HTMLElement, 'The fallback element created by HTML parser must be an instance of HTMLElement');
+ assert_true(instance instanceof HTMLUnknownElement, 'The fallback element created by HTML parser must be an instance of HTMLUnknownElement');
+
+}, 'HTML parser must create a fallback HTMLUnknownElement when a custom element constructor returns a Text node');
+
+test(function () {
+ var instance = document.querySelector('returns-non-element-object');
+
+ assert_false(instance instanceof ReturnsNonElementObject, 'HTML parser must NOT instantiate a custom element when the constructor returns a non-Element object');
+ assert_true(instance instanceof HTMLElement, 'The fallback element created by HTML parser must be an instance of HTMLElement');
+ assert_true(instance instanceof HTMLUnknownElement, 'The fallback element created by HTML parser must be an instance of HTMLUnknownElement');
+
+}, 'HTML parser must create a fallback HTMLUnknownElement when a custom element constructor returns non-Element object');
+
+test(function () {
+ var instance = document.querySelector('lacks-super-call');
+
+ assert_false(instance instanceof LacksSuperCall, 'HTML parser must NOT instantiate a custom element when the constructor does not call super()');
+ assert_true(instance instanceof HTMLElement, 'The fallback element created by HTML parser must be an instance of HTMLElement');
+ assert_true(instance instanceof HTMLUnknownElement, 'The fallback element created by HTML parser must be an instance of HTMLUnknownElement');
+
+}, 'HTML parser must create a fallback HTMLUnknownElement when a custom element constructor does not call super()');
+
+test(function () {
+ var instance = document.querySelector('throws-exception');
+
+ assert_false(instance instanceof ThrowsException, 'HTML parser must NOT instantiate a custom element when the constructor throws an exception');
+ assert_true(instance instanceof HTMLElement, 'The fallback element created by HTML parser must be an instance of HTMLElement');
+ assert_true(instance instanceof HTMLUnknownElement, 'The fallback element created by HTML parser must be an instance of HTMLUnknownElement');
+
+}, 'HTML parser must create a fallback HTMLUnknownElement when a custom element constructor throws an exception');
+
+</script>
+</body>
+</html>
diff --git a/testing/web-platform/tests/custom-elements/parser/parser-sets-attributes-and-children.html b/testing/web-platform/tests/custom-elements/parser/parser-sets-attributes-and-children.html
new file mode 100644
index 0000000000..987bf8525f
--- /dev/null
+++ b/testing/web-platform/tests/custom-elements/parser/parser-sets-attributes-and-children.html
@@ -0,0 +1,95 @@
+<!DOCTYPE html>
+<html>
+<head>
+<title>Custom Elements: Changes to the HTML parser</title>
+<meta name="author" title="Ryosuke Niwa" href="mailto:rniwa@webkit.org">
+<meta name="assert" content="HTML parser must set the attributes and append the children on a custom element">
+<link rel="help" href="https://html.spec.whatwg.org/#create-an-element-for-the-token">
+<link rel="help" href="https://html.spec.whatwg.org/multipage/parsing.html#insert-a-foreign-element">
+<link rel="help" href="https://dom.spec.whatwg.org/#concept-create-element">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="../resources/custom-elements-helpers.js"></script>
+</head>
+<body>
+<div id="log"></div>
+<script>
+
+var numberOfAttributesInConstructor = 0;
+var numberOfChildNodesInConstructor = 0;
+var numberOfChildNodesInAttributeChangedCallback = 0;
+var numberOfChildNodesInConnectedCallback = 0;
+var attributesChangedCalls = [];
+
+class MyCustomElement extends HTMLElement {
+ constructor(...args) {
+ super(...args);
+ numberOfAttributesInConstructor = this.attributes.length;
+ numberOfChildNodesInConstructor = this.childNodes.length;
+ }
+
+ attributeChangedCallback(...args) {
+ attributesChangedCalls.push(create_attribute_changed_callback_log(this, ...args));
+ numberOfChildNodesInAttributeChangedCallback = this.childNodes.length;
+ }
+
+ static get observedAttributes() {
+ return ['id', 'class'];
+ }
+
+ connectedCallback() {
+ numberOfChildNodesInConnectedCallback = this.childNodes.length;
+ }
+};
+customElements.define('my-custom-element', MyCustomElement);
+
+</script>
+<my-custom-element id="custom-element-id" class="class1 class2">hello <b>world</b></my-custom-element>
+<script>
+
+var customElement = document.querySelector('my-custom-element');
+
+test(function () {
+ assert_equals(customElement.getAttribute('id'), 'custom-element-id', 'HTML parser must preserve the id attribute');
+ assert_equals(customElement.id, 'custom-element-id', 'HTML parser must preserve the semantics of reflect for the id attribute');
+ assert_equals(customElement.getAttribute('class'), 'class1 class2', 'HTML parser must preserve the class attribute');
+ assert_equals(customElement.classList.length, 2, 'HTML parser must initialize classList on custom elements');
+ assert_equals(customElement.classList[0], 'class1', 'HTML parser must initialize classList on custom elements');
+ assert_equals(customElement.classList[1], 'class2', 'HTML parser must initialize classList on custom elements');
+}, 'HTML parser must set the attributes');
+
+test(function () {
+ assert_equals(customElement.childNodes.length, 2, 'HTML parser must append child nodes');
+ assert_true(customElement.firstChild instanceof Text, 'HTML parser must append Text node child to a custom element');
+ assert_equals(customElement.firstChild.data, 'hello ', 'HTML parser must append Text node child to a custom element');
+ assert_true(customElement.lastChild instanceof HTMLElement, 'HTML parser must append a builtin element child to a custom element');
+ assert_true(customElement.lastChild.firstChild instanceof Text, 'HTML parser must preserve grandchild nodes of a custom element');
+ assert_equals(customElement.lastChild.firstChild.data, 'world', 'HTML parser must preserve grandchild nodes of a custom element');
+}, 'HTML parser must append child nodes');
+
+test(function () {
+ assert_equals(numberOfAttributesInConstructor, 0, 'HTML parser must not set attributes on a custom element before invoking the constructor');
+ assert_equals(numberOfChildNodesInConstructor, 0, 'HTML parser must not append child nodes to a custom element before invoking the constructor');
+}, 'HTML parser must set the attributes or append children before calling constructor');
+
+test(function () {
+ // https://html.spec.whatwg.org/multipage/parsing.html#insert-a-foreign-element
+ // 3.3. Pop the element queue from the custom element reactions
+ // stack, and invoke custom element reactions in that queue.
+ assert_equals(numberOfChildNodesInConnectedCallback, 0);
+}, 'HTML parser should call connectedCallback before appending child nodes.');
+
+test(function () {
+ assert_equals(attributesChangedCalls.length, 2);
+ assert_attribute_log_entry(attributesChangedCalls[0], {name: 'id', oldValue: null, newValue: 'custom-element-id', namespace: null});
+ assert_attribute_log_entry(attributesChangedCalls[1], {name: 'class', oldValue: null, newValue: 'class1 class2', namespace: null});
+ // https://html.spec.whatwg.org/multipage/parsing.html#create-an-element-for-the-token
+ // 9.2. Invoke custom element reactions in queue.
+ assert_equals(numberOfChildNodesInAttributeChangedCallback, 0,
+ 'attributeChangedCallback should be called ' +
+ 'before appending a child');
+}, 'HTML parser must enqueue attributeChanged reactions');
+
+</script>
+</body>
+</html>
diff --git a/testing/web-platform/tests/custom-elements/parser/parser-uses-constructed-element.html b/testing/web-platform/tests/custom-elements/parser/parser-uses-constructed-element.html
new file mode 100644
index 0000000000..dd98f15cd9
--- /dev/null
+++ b/testing/web-platform/tests/custom-elements/parser/parser-uses-constructed-element.html
@@ -0,0 +1,75 @@
+<!DOCTYPE html>
+<html>
+<head>
+<title>Custom Elements: HTML parser must construct a custom element instead of upgrading</title>
+<meta name="author" title="Ryosuke Niwa" href="mailto:rniwa@webkit.org">
+<meta name="assert" content="HTML parser must construct a custom element instead of upgrading">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<link rel="help" href="https://html.spec.whatwg.org/#create-an-element-for-the-token">
+<link rel="help" href="https://dom.spec.whatwg.org/#concept-create-element">
+</head>
+<body>
+<div id="log"></div>
+<script>
+
+let anotherElementCreatedBeforeSuperCall = undefined;
+let elementCreatedBySuperCall = undefined;
+let shouldCreateElementBeforeSuperCall = true;
+class InstantiatesItselfBeforeSuper extends HTMLElement {
+ constructor() {
+ if (shouldCreateElementBeforeSuperCall) {
+ shouldCreateElementBeforeSuperCall = false;
+ anotherElementCreatedBeforeSuperCall = new InstantiatesItselfBeforeSuper();
+ }
+ super();
+ elementCreatedBySuperCall = this;
+ }
+};
+customElements.define('instantiates-itself-before-super', InstantiatesItselfBeforeSuper);
+
+let shouldCreateAnotherInstance = true;
+let anotherInstance = undefined;
+let firstInstance = undefined;
+class ReturnsAnotherInstance extends HTMLElement {
+ constructor() {
+ super();
+ if (shouldCreateAnotherInstance) {
+ shouldCreateAnotherInstance = false;
+ firstInstance = this;
+ anotherInstance = new ReturnsAnotherInstance;
+ return anotherInstance;
+ } else
+ return this;
+ }
+};
+customElements.define('returns-another-instance', ReturnsAnotherInstance);
+
+</script>
+<instantiates-itself-before-super></instantiates-itself-before-super>
+<returns-another-instance></returns-another-instance>
+<script>
+
+test(function () {
+ var instance = document.querySelector('instantiates-itself-before-super');
+
+ assert_true(instance instanceof InstantiatesItselfBeforeSuper, 'HTML parser must insert the synchronously constructed custom element');
+ assert_equals(instance, elementCreatedBySuperCall, 'HTML parser must insert the element returned by the custom element constructor');
+ assert_not_equals(instance, anotherElementCreatedBeforeSuperCall, 'HTML parser must not insert another instance of the custom element created before super() call');
+ assert_equals(anotherElementCreatedBeforeSuperCall.parentNode, null, 'HTML parser must not insert another instance of the custom element created before super() call');
+
+}, 'HTML parser must use the returned value of the custom element constructor instead of the one created before super() call');
+
+test(function () {
+ var instance = document.querySelector('returns-another-instance');
+
+ assert_true(instance instanceof ReturnsAnotherInstance, 'HTML parser must insert the synchronously constructed custom element');
+ assert_equals(instance, anotherInstance, 'HTML parser must insert the element returned by the custom element constructor');
+ assert_not_equals(instance, firstInstance, 'HTML parser must not insert the element created by super() call if the constructor returned another element');
+ assert_equals(firstInstance.parentNode, null, 'HTML parser must not insert the element created by super() call if the constructor returned another element');
+
+}, 'HTML parser must use the returned value of the custom element constructor instead using the one created in super() call');
+
+</script>
+</body>
+</html>
diff --git a/testing/web-platform/tests/custom-elements/parser/parser-uses-create-an-element-for-a-token-svg.svg b/testing/web-platform/tests/custom-elements/parser/parser-uses-create-an-element-for-a-token-svg.svg
new file mode 100644
index 0000000000..526de0f63f
--- /dev/null
+++ b/testing/web-platform/tests/custom-elements/parser/parser-uses-create-an-element-for-a-token-svg.svg
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg:svg xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/1999/xhtml"
+ width="100%" height="100%" viewBox="0 0 800 600">
+<svg:title>XML parser should use "create an element for a token"</svg:title>
+<link rel="help" href="https://html.spec.whatwg.org/multipage/xhtml.html#parsing-xhtml-documents:create-an-element-for-the-token"/>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script><![CDATA[
+class MyElement1 extends HTMLElement {}
+customElements.define('my-element', MyElement1);
+class MyElement2 extends HTMLDivElement {}
+customElements.define('my-div', MyElement2, { extends: 'div' });
+
+var test1 = async_test('XML parser should create autonomous custom elements.');
+window.addEventListener('load', test1.step_func_done(() => {
+ assert_true(document.getElementById('me1') instanceof MyElement1);
+}));
+
+var test2 = async_test('XML parser should create custom built-in elements.');
+window.addEventListener('load', test2.step_func_done(() => {
+ assert_true(document.getElementById('me2') instanceof MyElement2);
+}));
+]]></script>
+<my-element id="me1"></my-element>
+<div is="my-div" id="me2"></div>
+</svg:svg>
diff --git a/testing/web-platform/tests/custom-elements/parser/parser-uses-registry-of-owner-document.html b/testing/web-platform/tests/custom-elements/parser/parser-uses-registry-of-owner-document.html
new file mode 100644
index 0000000000..bb256da295
--- /dev/null
+++ b/testing/web-platform/tests/custom-elements/parser/parser-uses-registry-of-owner-document.html
@@ -0,0 +1,154 @@
+<!DOCTYPE html>
+<html>
+<head>
+<title>Custom Elements: HTML parser must use the owner document's custom element registry</title>
+<meta name="author" title="Ryosuke Niwa" href="mailto:rniwa@webkit.org">
+<meta name="assert" content="HTML parser must use the owner document's custom element registry">
+<link rel="help" href="https://html.spec.whatwg.org/#create-an-element-for-the-token">
+<link rel="help" href="https://dom.spec.whatwg.org/#concept-create-element">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="../resources/custom-elements-helpers.js"></script>
+</head>
+<body>
+<div id="log"></div>
+<script>
+
+class MyCustomElement extends HTMLElement { };
+customElements.define('my-custom-element', MyCustomElement);
+
+document.write('<template><my-custom-element></my-custom-element></template>');
+
+test(function () {
+ var template = document.querySelector('template');
+ var instance = template.content.firstChild;
+
+ assert_true(instance instanceof HTMLElement,
+ 'A custom element inside a template element must be an instance of HTMLElement');
+ assert_false(instance instanceof MyCustomElement,
+ 'A custom element must not be instantiated inside a template element using the registry of the template element\'s owner document');
+ assert_equals(instance.ownerDocument, template.content.ownerDocument,
+ 'Custom elements inside a template must use the appropriate template contents owner document as the owner document');
+
+}, 'HTML parser must not instantiate custom elements inside template elements');
+
+var iframe = document.createElement('iframe');
+document.body.appendChild(iframe);
+iframe.contentDocument.body.innerHTML = '<my-custom-element></my-custom-element>';
+
+test(function () {
+ var instance = iframe.contentDocument.querySelector('my-custom-element');
+
+ assert_true(instance instanceof iframe.contentWindow.HTMLElement);
+ assert_false(instance instanceof MyCustomElement);
+
+}, 'HTML parser must not use the registry of the owner element\'s document inside an iframe');
+
+class ElementInIFrame extends iframe.contentWindow.HTMLElement { };
+iframe.contentWindow.customElements.define('element-in-iframe', ElementInIFrame);
+iframe.contentDocument.body.innerHTML = '<element-in-iframe></element-in-iframe>';
+
+test(function () {
+ var instance = iframe.contentDocument.querySelector('element-in-iframe');
+
+ assert_true(instance instanceof iframe.contentWindow.HTMLElement, 'A custom element inside an iframe must be an instance of HTMLElement');
+ assert_true(instance instanceof ElementInIFrame,
+ 'A custom element must be instantiated inside an iframe using the registry of the content document');
+ assert_equals(instance.ownerDocument, iframe.contentDocument,
+ 'The owner document of custom elements inside an iframe must be the content document of the iframe');
+
+}, 'HTML parser must use the registry of the content document inside an iframe');
+
+document.write('<element-in-iframe></element-in-iframe>');
+
+test(function () {
+ var instance = document.querySelector('element-in-iframe');
+
+ assert_true(instance instanceof HTMLElement);
+ assert_false(instance instanceof ElementInIFrame);
+
+}, 'HTML parser must not instantiate a custom element defined inside an frame in frame element\'s owner document');
+
+document.body.removeChild(iframe);
+
+test(function () {
+ var windowlessDocument = (new DOMParser()).parseFromString('<my-custom-element></my-custom-element>', "text/html");
+
+ var instance = windowlessDocument.querySelector('my-custom-element');
+
+ assert_true(instance instanceof HTMLElement);
+ assert_false(instance instanceof MyCustomElement);
+
+}, 'HTML parser must use the registry of window.document in a document created by DOMParser');
+
+test(function () {
+ var windowlessDocument = document.implementation.createDocument ('http://www.w3.org/1999/xhtml', 'html', null);
+ windowlessDocument.documentElement.innerHTML = '<my-custom-element></my-custom-element>';
+
+ var instance = windowlessDocument.querySelector('my-custom-element');
+ assert_true(instance instanceof HTMLElement);
+ assert_false(instance instanceof MyCustomElement);
+
+}, 'HTML parser must use the registry of window.document in a document created by document.implementation.createXHTMLDocument()');
+
+test(function () {
+ var windowlessDocument = new Document;
+ windowlessDocument.appendChild(windowlessDocument.createElement('html'));
+ windowlessDocument.documentElement.innerHTML = '<my-custom-element></my-custom-element>';
+
+ var instance = windowlessDocument.querySelector('my-custom-element');
+
+ assert_true(instance instanceof Element);
+ assert_false(instance instanceof MyCustomElement);
+
+}, 'HTML parser must use the registry of window.document in a document created by new Document');
+
+promise_test(function () {
+ return new Promise(function (resolve, reject) {
+ var xhr = new XMLHttpRequest();
+ xhr.open('GET', '../resources/my-custom-element-html-document.html');
+ xhr.overrideMimeType('text/xml');
+ xhr.onload = function () { resolve(xhr.responseXML); }
+ xhr.onerror = function () { reject('Failed to fetch the document'); }
+ xhr.send();
+ }).then(function (doc) {
+ var instance = doc.querySelector('my-custom-element');
+ assert_true(instance instanceof Element);
+ assert_false(instance instanceof MyCustomElement);
+
+ doc.documentElement.innerHTML = '<my-custom-element></my-custom-element>';
+ var instance2 = doc.querySelector('my-custom-element');
+ assert_true(instance2 instanceof Element);
+ assert_false(instance2 instanceof MyCustomElement);
+ });
+}, 'HTML parser must use the registry of window.document in a document created by XMLHttpRequest');
+
+test_with_window(function (contentWindow, contentDocument) {
+ const element = define_custom_element_in_window(contentWindow, 'my-custom-element', []);
+ // document-open-steps spec doesn't do anything with the custom element
+ // registry, so it should just stick around.
+ contentDocument.write('<my-custom-element></my-custom-element>');
+
+ var instance = contentDocument.querySelector('my-custom-element');
+
+ assert_true(instance instanceof contentWindow.HTMLElement);
+ assert_true(instance instanceof element.class);
+
+}, 'document.write() must not instantiate a custom element without a defined insertion point');
+
+test_with_window(function (contentWindow, contentDocument) {
+ const element = define_custom_element_in_window(contentWindow, 'my-custom-element', []);
+ // document-open-steps spec doesn't do anything with the custom element
+ // registry, so it should just stick around.
+ contentDocument.writeln('<my-custom-element></my-custom-element>');
+
+ var instance = contentDocument.querySelector('my-custom-element');
+
+ assert_true(instance instanceof contentWindow.HTMLElement);
+ assert_true(instance instanceof element.class);
+
+}, 'document.writeln() must not instantiate a custom element without a defined insertion point');
+
+</script>
+</body>
+</html>
diff --git a/testing/web-platform/tests/custom-elements/parser/serializing-html-fragments-customized-builtins.html b/testing/web-platform/tests/custom-elements/parser/serializing-html-fragments-customized-builtins.html
new file mode 100644
index 0000000000..6992dd6df6
--- /dev/null
+++ b/testing/web-platform/tests/custom-elements/parser/serializing-html-fragments-customized-builtins.html
@@ -0,0 +1,37 @@
+<!DOCTYPE html>
+<link rel="help" href="https://html.spec.whatwg.org/multipage/parsing.html#serialising-html-fragments">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<body>
+<div id="container"></div>
+<script>
+test(() => {
+ class MyParagraph extends HTMLParagraphElement {}
+ customElements.define('my-p', MyParagraph, { extends: 'p' });
+
+ let p = new MyParagraph();
+ p.setAttribute('class', 'foo');
+ assert_equals(p.outerHTML, '<p is="my-p" class="foo"></p>');
+
+ let container = document.querySelector('#container');
+ container.appendChild(p);
+ container.innerHTML = container.innerHTML;
+ assert_not_equals(container.firstChild, p);
+ assert_true(container.firstChild instanceof MyParagraph);
+}, '"is" value should be serialized if the custom element has no "is" content attribute');
+
+test(() => {
+ let p = document.createElement('p', { is: 'your-p' });
+ assert_equals(p.outerHTML, '<p is="your-p"></p>');
+}, '"is" value should be serialized even for an undefined element');
+
+test(() => {
+ class MyDiv extends HTMLDivElement {}
+ customElements.define('my-div', MyDiv, { extends: 'div' });
+
+ let div = document.createElement('div', { is: 'my-div' });
+ div.setAttribute('is', 'foo"bar\n');
+ assert_equals(div.outerHTML, '<div is="foo&quot;bar\n"></div>');
+}, '"is" content attribute should be serialized even if the element is a customized built-in element');
+</script>
+</body>