| <!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 match most browsers; see https://github.com/whatwg/html/issues/1698. |
| // However, as explained in https://github.com/whatwg/html/issues/1698#issuecomment-298748641 |
| // the custom element registry will be replaced after document-open-steps. |
| contentDocument.write('<my-custom-element></my-custom-element>'); |
| |
| var instance = contentDocument.querySelector('my-custom-element'); |
| |
| assert_true(instance instanceof contentWindow.HTMLElement); |
| assert_false(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 match most browsers; see https://github.com/whatwg/html/issues/1698. |
| // However, as explained in https://github.com/whatwg/html/issues/1698#issuecomment-298748641 |
| // the custom element registry will be replaced after document-open-steps. |
| contentDocument.writeln('<my-custom-element></my-custom-element>'); |
| |
| var instance = contentDocument.querySelector('my-custom-element'); |
| |
| assert_true(instance instanceof contentWindow.HTMLElement); |
| assert_false(instance instanceof element.class); |
| |
| }, 'document.writeln() must not instantiate a custom element without a defined insertion point'); |
| |
| </script> |
| </body> |
| </html> |