throw-on-dynamic-markup-insertion-counter-reactions-xml-parser.xhtml (7602B)
1 <?xml version="1.0" encoding="utf-8"?> 2 <html xmlns="http://www.w3.org/1999/xhtml"> 3 <head> 4 <title>Custom Elements: create an element for a token must increment and decrement document's throw-on-dynamic-markup-insertion counter</title> 5 <meta name="author" title="Ryosuke Niwa" href="mailto:rniwa@webkit.org" /> 6 <meta name="assert" content="Invoking document.open, document.write, document.writeln, and document.write must throw an exception when the HTML parser is creating a custom element for a token" /> 7 <meta name="help" content="https://html.spec.whatwg.org/multipage/parsing.html#create-an-element-for-the-token" /> 8 <meta name="help" content="https://html.spec.whatwg.org/multipage/dynamic-markup-insertion.html#throw-on-dynamic-markup-insertion-counter" /> 9 <script src="/resources/testharness.js"></script> 10 <script src="/resources/testharnessreport.js"></script> 11 <script src="resources/custom-elements-helpers.js"></script> 12 </head> 13 <body> 14 <div id="log"></div> 15 <script> 16 <![CDATA[ 17 18 async function custom_element_reactions_in_parser(test, code) 19 { 20 window.executed = false; 21 window.exception = null; 22 const content_window = await create_window_in_test_async(test, 'application/xml', `<?xml version="1.0" encoding="utf-8"?> 23 <html xmlns="http://www.w3.org/1999/xhtml"> 24 <head> 25 <script> 26 <![CDATA[ 27 class CustomElement extends window.HTMLElement { 28 constructor() { 29 super(); 30 let exception = null; 31 try { 32 ${code} 33 } catch (error) { 34 exception = error; 35 } 36 top.executed = true; 37 top.exception = exception; 38 } 39 } 40 CustomElement.observedAttributes = ['title']; 41 customElements.define('some-element', CustomElement); 42 ]]` + `> 43 </` + `script> 44 </head> 45 <body> 46 <some-element title="some title"></some-element> 47 </body> 48 </html>`); 49 let content_document; 50 try { 51 content_document = content_window.document; 52 } catch (error) { } 53 assert_true(executed, 'Must immediately process custom element reactions for setting attributes'); 54 return {window: content_window, document: content_document, exception}; 55 } 56 57 promise_test(async function () { 58 const result = await custom_element_reactions_in_parser(this, `document.open()`); 59 assert_throws_dom('InvalidStateError', result.window.DOMException, () => { throw result.exception; }, 'Must throw an InvalidStateError'); 60 }, 'document.open() must throw an InvalidStateError when processing custom element reactions for a synchronous constructed custom element'); 61 62 promise_test(async function () { 63 const result = await custom_element_reactions_in_parser(this, `document.open('text/html')`); 64 assert_throws_dom('InvalidStateError', result.window.DOMException, () => { throw result.exception; }, 'Must throw an InvalidStateError'); 65 }, 'document.open("text/html") must throw an InvalidStateError when processing custom element reactions for a synchronous constructed custom element'); 66 67 // https://html.spec.whatwg.org/multipage/dynamic-markup-insertion.html#dom-document-open-window 68 promise_test(async function () { 69 let load_promise = new Promise((resolve) => window.onmessage = (event) => resolve(event.data)); 70 const url = top.location.href.substring(0, top.location.href.lastIndexOf('/')) + '/resources/navigation-destination.html'; 71 const result = await custom_element_reactions_in_parser(this, `document.open('${url}', '_self', '')`); 72 assert_equals(result.exception, null); 73 assert_equals(await load_promise, 'didNavigate'); 74 }, 'document.open(URL) must NOT throw an InvalidStateError when processing custom element reactions for a synchronous constructed custom element'); 75 76 promise_test(async function () { 77 const result = await custom_element_reactions_in_parser(this, `document.close()`); 78 assert_throws_dom('InvalidStateError', result.window.DOMException, () => { throw result.exception; }, 'Must throw an InvalidStateError'); 79 }, 'document.close() must throw an InvalidStateError when processing custom element reactions for a synchronous constructed custom element'); 80 81 promise_test(async function () { 82 const result = await custom_element_reactions_in_parser(this, `document.write('<b>some text</b>')`); 83 assert_throws_dom('InvalidStateError', result.window.DOMException, () => { throw result.exception; }, 'Must throw an InvalidStateError'); 84 assert_equals(result.document.querySelector('b'), null, 'Must not insert new content'); 85 assert_false(result.document.body.innerHTML.includes('some text'), 'Must not insert new content'); 86 }, 'document.write must throw an InvalidStateError when processing custom element reactions for a synchronous constructed custom element'); 87 88 promise_test(async function () { 89 const result = await custom_element_reactions_in_parser(this, `document.writeln('<b>some text</b>')`); 90 assert_throws_dom('InvalidStateError', result.window.DOMException, () => { throw result.exception; }, 'Must throw an InvalidStateError'); 91 assert_equals(result.document.querySelector('b'), null, 'Must not insert new content'); 92 assert_false(result.document.body.innerHTML.includes('some text'), 'Must not insert new content'); 93 }, 'document.writeln must throw an InvalidStateError when processing custom element reactions for a synchronous constructed custom element'); 94 95 promise_test(async function () { 96 window.another_window = await create_window_in_test(this); 97 const result = await custom_element_reactions_in_parser(this, `top.another_window.document.open()`); 98 assert_equals(result.exception, null); 99 }, 'document.open() of another document must not throw an InvalidStateError when processing custom element reactions for a synchronous constructed custom element'); 100 101 promise_test(async function () { 102 window.another_window = await create_window_in_test(this); 103 const result = await custom_element_reactions_in_parser(this, `top.another_window.document.open('text/html')`); 104 assert_equals(result.exception, null); 105 }, 'document.open("text/html") of another document must not throw an InvalidStateError when processing custom element reactions for a synchronous constructed custom element'); 106 107 promise_test(async function () { 108 window.another_window = await create_window_in_test(this); 109 const result = await custom_element_reactions_in_parser(this, `top.another_window.document.close()`); 110 assert_equals(result.exception, null); 111 }, 'document.close() of another document must not throw an InvalidStateError when processing custom element reactions for a synchronous constructed custom element'); 112 113 promise_test(async function () { 114 window.another_window = await create_window_in_test(this); 115 const result = await custom_element_reactions_in_parser(this, `top.another_window.document.write('<b>some text</b>')`); 116 assert_equals(result.exception, null); 117 assert_equals(another_window.document.querySelector('b').outerHTML, '<b>some text</b>'); 118 }, 'document.write of another document must not throw an InvalidStateError when processing custom element reactions for a synchronous constructed custom element'); 119 120 promise_test(async function () { 121 window.another_window = await create_window_in_test(this); 122 const result = await custom_element_reactions_in_parser(this, `top.another_window.document.writeln('<b>some text</b>')`); 123 assert_equals(result.exception, null); 124 assert_equals(another_window.document.querySelector('b').outerHTML, '<b>some text</b>'); 125 }, 'document.writeln of another document must not throw an InvalidStateError when processing custom element reactions for a synchronous constructed custom element'); 126 127 ]]> 128 </script> 129 </body> 130 </html>