upgrade-custom-element-error-event.html (5157B)
1 <!DOCTYPE html> 2 <link rel="help" href="https://dom.spec.whatwg.org/#concept-create-element"> 3 <script src="/resources/testharness.js"></script> 4 <script src="/resources/testharnessreport.js"></script> 5 <script src="../resources/custom-elements-helpers.js"></script> 6 <body> 7 <script> 8 // Returns a promise which will resolve with the next error event fired at any 9 // of `windows`, after the invocation of this function. Once one does, this 10 // function removes its listeners and produces that error event so that it can 11 // be examined (most notably for which global proxy it was targeted at). 12 async function nextErrorEvent(windows) { 13 let listener; 14 let p = new Promise((resolve, reject) => { 15 listener = (event) => { resolve(event); event.preventDefault(); }; 16 }); 17 for (let w of windows) { 18 w.addEventListener('error', listener); 19 } 20 try { 21 return await p; 22 } finally { 23 for (let w of windows) { 24 w.removeEventListener('error', listener); 25 } 26 } 27 } 28 const supportsCustomizedBuiltinElements = (function() { 29 let supported = false; 30 customElements.define('feature-detect', class extends HTMLDivElement {}, { get extends() { supported = true; return "div"; } }); 31 return supported; 32 })(); 33 34 promise_test(async t => { 35 let w = await create_window_in_test(t, `<script>self.MyElement = class extends HTMLElement { constructor() { throw new Error(); } };</`+`script>`); 36 let w2 = await create_window_in_test(t); 37 w2.customElements.define('my-element', w.MyElement); 38 let nextErrorPromise = nextErrorEvent([self, w, w2]); 39 let elem = w2.document.createElement('my-element'); 40 let errorEvent = await nextErrorPromise; 41 assert_true(elem instanceof w2.HTMLUnknownElement, 'element should be an HTMLUnknownElement'); 42 if (errorEvent.error) { 43 assert_true(errorEvent.error instanceof w.Error, 'error should be an instance created inside the MyElement constructor (if it was not muted)'); 44 } 45 assert_equals(errorEvent.target, w, `error event should target definition's global but instead targets ${event.target === w2 ? 'document\'s global' : 'test harness global'}`); 46 }, 'autonomous: exception thrown in constructor is reported to definition\'s global'); 47 48 promise_test(async t => { 49 let w = await create_window_in_test(t, `<script>self.MyElement = class extends HTMLElement { constructor() { this.textContent = 'hello!'; } };</`+`script>`); 50 let w2 = await create_window_in_test(t); 51 w2.customElements.define('my-element', w.MyElement); 52 let nextErrorPromise = nextErrorEvent([self, w, w2]); 53 let elem = w2.document.createElement('my-element'); 54 let errorEvent = await nextErrorPromise; 55 assert_true(elem instanceof w2.HTMLUnknownElement, 'element should be an HTMLUnknownElement'); 56 assert_equals(errorEvent.target, w, `error event should target definition's global but instead targets ${event.currentTarget === w2 ? 'document\'s global' : 'test harness global'}`); 57 }, 'autonomous: exception thrown by spec due to invalid element state is reported to definition\'s global'); 58 59 promise_test(async t => { 60 assert_implements(supportsCustomizedBuiltinElements, 'customized built-in elements not supported'); 61 let w = await create_window_in_test(t, `<script>self.MyDivElement = class extends HTMLDivElement { constructor() { throw new Error(); } };</`+`script>`); 62 let w2 = await create_window_in_test(t); 63 w2.customElements.define('my-div', w.MyDivElement, {extends: 'div'}); 64 let nextErrorPromise = nextErrorEvent([self, w, w2]); 65 let elem = w2.document.createElement('div', {is: 'my-div'}); 66 let errorEvent = await nextErrorPromise; 67 assert_equals(Object.getPrototypeOf(elem), w2.HTMLDivElement.prototype, 'element should be an HTMLDivElement (and not inherited from it)'); 68 assert_true(errorEvent.error instanceof w.Error, 'error should be an instance created inside the MyElement constructor'); 69 assert_equals(errorEvent.target, w, `error event should target definition's global but instead targets ${event.target === w2 ? 'document\'s global' : 'test harness global'}`); 70 }, 'customized built-in: exception thrown in constructor is reported to definition\'s global'); 71 72 promise_test(async t => { 73 assert_implements(supportsCustomizedBuiltinElements, 'customized built-in elements not supported'); 74 let w = await create_window_in_test(t, `<script>self.MyDivElement = class extends HTMLDivElement { constructor() { return document.createElement('div'); } };</`+`script>`); 75 let w2 = await create_window_in_test(t); 76 w2.customElements.define('my-div', w.MyDivElement, {extends: 'div'}); 77 let nextErrorPromise = nextErrorEvent([self, w, w2]); 78 let elem = w2.document.createElement('div', {is: 'my-div'}); 79 let errorEvent = await nextErrorPromise; 80 assert_equals(Object.getPrototypeOf(elem), w2.HTMLDivElement.prototype, 'element should be an HTMLDivElement (and not inherited from it)'); 81 assert_equals(errorEvent.target, w, `error event should target definition's global but instead targets ${event.currentTarget === w2 ? 'document\'s global' : 'test harness global'}`); 82 }, 'customized built-in: exception thrown by spec due to not returning the same value is reported to definition\'s global'); 83 </script> 84 </body>