throw-on-dynamic-markup-insertion-counter-reactions.html (7414B)
1 <!DOCTYPE html> 2 <html> 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 17 async function custom_element_reactions_in_parser(test, call_function) 18 { 19 const window = await create_window_in_test(test); 20 const document = window.document; 21 22 document.open(); 23 24 let executed = false; 25 let exception = null; 26 class CustomElement extends window.HTMLElement { 27 attributeChangedCallback(name, oldValue, newValue) { 28 try { 29 call_function(document, window); 30 } catch (error) { 31 exception = error; 32 } 33 executed = true; 34 } 35 } 36 CustomElement.observedAttributes = ['title']; 37 window.customElements.define('some-element', CustomElement); 38 39 document.write('<!DOCTYPE html><html><body><some-element title="some title"></some-element></body></html>'); 40 document.close(); 41 42 assert_true(executed, 'Must immediately process custom element reactions for setting attributes'); 43 return {frameElement, window, document, exception}; 44 } 45 46 promise_test(async function () { 47 const result = await custom_element_reactions_in_parser(this, (document) => document.open()); 48 assert_throws_dom('InvalidStateError', result.window.DOMException, () => { throw result.exception; }, 'Must throw an InvalidStateError'); 49 }, 'document.open() must throw an InvalidStateError when processing custom element reactions for a synchronous constructed custom element'); 50 51 promise_test(async function () { 52 const result = await custom_element_reactions_in_parser(this, (document) => document.open('text/html')); 53 assert_throws_dom('InvalidStateError', result.window.DOMException, () => { throw result.exception; }, 'Must throw an InvalidStateError'); 54 }, 'document.open("text/html") must throw an InvalidStateError when processing custom element reactions for a synchronous constructed custom element'); 55 56 // https://html.spec.whatwg.org/multipage/dynamic-markup-insertion.html#dom-document-open-window 57 promise_test(async function () { 58 let load_promise = new Promise((resolve) => window.onmessage = (event) => resolve(event.data)); 59 const result = await custom_element_reactions_in_parser(this, (document, window) => document.open('resources/navigation-destination.html', '_self', '')); 60 assert_equals(result.exception, null); 61 assert_equals(await load_promise, 'didNavigate'); 62 }, 'document.open(URL) must NOT throw an InvalidStateError when processing custom element reactions for a synchronous constructed custom element'); 63 64 promise_test(async function () { 65 const result = await custom_element_reactions_in_parser(this, (document) => document.close()); 66 assert_throws_dom('InvalidStateError', result.window.DOMException, () => { throw result.exception; }, 'Must throw an InvalidStateError'); 67 }, 'document.close() must throw an InvalidStateError when processing custom element reactions for a synchronous constructed custom element'); 68 69 promise_test(async function () { 70 const result = await custom_element_reactions_in_parser(this, (document) => document.write('<b>some text</b>')); 71 assert_throws_dom('InvalidStateError', result.window.DOMException, () => { throw result.exception; }, 'Must throw an InvalidStateError'); 72 assert_equals(result.document.querySelector('b'), null, 'Must not insert new content'); 73 assert_false(result.document.documentElement.innerHTML.includes('some text'), 'Must not insert new content'); 74 }, 'document.write must 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) => document.writeln('<b>some text</b>')); 78 assert_throws_dom('InvalidStateError', result.window.DOMException, () => { throw result.exception; }, 'Must throw an InvalidStateError'); 79 assert_equals(result.document.querySelector('b'), null, 'Must not insert new content'); 80 assert_false(result.document.documentElement.innerHTML.includes('some text'), 'Must not insert new content'); 81 }, 'document.writeln must throw an InvalidStateError when processing custom element reactions for a synchronous constructed custom element'); 82 83 promise_test(async function () { 84 const another_window = await create_window_in_test(this); 85 const result = await custom_element_reactions_in_parser(this, (document) => another_window.document.open()); 86 assert_equals(result.exception, null); 87 }, 'document.open() of another document must not throw an InvalidStateError when processing custom element reactions for a synchronous constructed custom element'); 88 89 promise_test(async function () { 90 const another_window = await create_window_in_test(this); 91 const result = await custom_element_reactions_in_parser(this, (document) => another_window.document.open('text/html')); 92 assert_equals(result.exception, null); 93 }, 'document.open("text/html") of another document must not throw an InvalidStateError when processing custom element reactions for a synchronous constructed custom element'); 94 95 promise_test(async function () { 96 const another_window = await create_window_in_test(this); 97 const result = await custom_element_reactions_in_parser(this, (document) => another_window.document.close()); 98 assert_equals(result.exception, null); 99 }, 'document.close() 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 const another_window = await create_window_in_test(this); 103 const result = await custom_element_reactions_in_parser(this, (document) => another_window.document.write('<b>some text</b>')); 104 assert_equals(result.exception, null); 105 assert_equals(another_window.document.querySelector('b').outerHTML, '<b>some text</b>'); 106 }, 'document.write of another document must not throw an InvalidStateError when processing custom element reactions for a synchronous constructed custom element'); 107 108 promise_test(async function () { 109 const another_window = await create_window_in_test(this); 110 const result = await custom_element_reactions_in_parser(this, (document) => another_window.document.writeln('<b>some text</b>')); 111 assert_equals(result.exception, null); 112 assert_equals(another_window.document.querySelector('b').outerHTML, '<b>some text</b>'); 113 }, 'document.writeln of another document must not throw an InvalidStateError when processing custom element reactions for a synchronous constructed custom element'); 114 115 </script> 116 </body> 117 </html>