OLD | NEW |
(Empty) | |
| 1 <!DOCTYPE html> |
| 2 <title>Custom Elements: [HTMLConstructor] derives prototype from NewTarget</titl
e> |
| 3 <meta name="author" title="Domenic Denicola" href="mailto:d@domenic.me"> |
| 4 <meta name="help" content="https://html.spec.whatwg.org/multipage/dom.html#htmlc
onstructor"> |
| 5 <script src="/resources/testharness.js"></script> |
| 6 <script src="/resources/testharnessreport.js"></script> |
| 7 <script src="../resources/custom-elements-helpers.js"></script> |
| 8 |
| 9 <script> |
| 10 "use strict"; |
| 11 |
| 12 test_with_window(w => { |
| 13 let afterDefinition = false; |
| 14 const proto1 = { "proto": "number one" }; |
| 15 const proto2 = { "proto": "number two" }; |
| 16 |
| 17 const TestElement = (function () { |
| 18 assert_throws({ name: "prototype throws" }, () => { |
| 19 const o = Reflect.construct(w.HTMLElement, [], new.target); |
| 20 |
| 21 assert_equals(Object.getPrototypeOf(o), proto2, |
| 22 "Must use the value returned from new.target.prototype"); |
| 23 assert_not_equals(Object.getPrototypeOf(o), proto1, |
| 24 "Must not use the prototype stored at definition time"); |
| 25 }); |
| 26 }).bind({}); |
| 27 |
| 28 Object.defineProperty(TestElement, "prototype", { |
| 29 get() { |
| 30 return beforeDefinition ? proto1 : proto2; |
| 31 } |
| 32 }); |
| 33 |
| 34 w.customElements.define("test-element", TestElement); |
| 35 |
| 36 beforeDefinition = true; |
| 37 new TestElement(); |
| 38 |
| 39 }, "Use NewTarget's prototype, not the one stored at definition time"); |
| 40 |
| 41 test_with_window(w => { |
| 42 // We have to not throw during define(), but throw during super() |
| 43 let throws = false; |
| 44 |
| 45 const TestElement = (function () { |
| 46 assert_throws({ name: "prototype throws" }, () => { |
| 47 return Reflect.construct(w.HTMLElement, [], new.target); |
| 48 }); |
| 49 }).bind({}); |
| 50 |
| 51 Object.defineProperty(TestElement, "prototype", { |
| 52 get() { |
| 53 if (throws) { |
| 54 throw { name: "prototype throws" }; |
| 55 } |
| 56 return {}; |
| 57 } |
| 58 }); |
| 59 |
| 60 w.customElements.define("test-element", TestElement); |
| 61 |
| 62 throws = true; |
| 63 new TestElement(); |
| 64 |
| 65 }, "Rethrow any exceptions thrown while getting the prototype"); |
| 66 |
| 67 test_with_window(w => { |
| 68 for (const notAnObject of [null, undefined, 5, "string"]) { |
| 69 // We have to return an object during define(), but not during super() |
| 70 let returnNotAnObject = false; |
| 71 |
| 72 const TestElement = (function () { |
| 73 const o = Reflect.construct(w.HTMLElement, [], new.target); |
| 74 |
| 75 assert_equals(Object.getPrototypeOf(o), window.HTMLElement, |
| 76 "Must use the HTMLElement from the realm of NewTarget"); |
| 77 assert_not_equals(Object.getPrototypeOf(o), w.HTMLElement, |
| 78 "Must not use the HTMLElement from the realm of the active function obje
ct (w.HTMLElement)"); |
| 79 |
| 80 return o; |
| 81 }).bind({}); |
| 82 |
| 83 Object.defineProperty(TestElement, "prototype", { |
| 84 get() { |
| 85 return returnNotAnObject ? notAnObject : {}; |
| 86 } |
| 87 }); |
| 88 |
| 89 w.customElements.define("test-element", TestElement); |
| 90 |
| 91 returnNotAnObject = true; |
| 92 new TestElement(); |
| 93 } |
| 94 }, "If prototype is not object, derives the fallback from NewTarget's realm (aut
onomous custom elements)"); |
| 95 |
| 96 test_with_window(w => { |
| 97 for (const notAnObject of [null, undefined, 5, "string"]) { |
| 98 // We have to return an object during define(), but not during super() |
| 99 let returnNotAnObject = false; |
| 100 |
| 101 const TestElement = (function () { |
| 102 const o = Reflect.construct(w.HTMLParagraphElement, [], new.target); |
| 103 |
| 104 assert_equals(Object.getPrototypeOf(o), window.HTMLParagraphElement, |
| 105 "Must use the HTMLParagraphElement from the realm of NewTarget"); |
| 106 assert_not_equals(Object.getPrototypeOf(o), w.HTMLParagraphElement, |
| 107 "Must not use the HTMLParagraphElement from the realm of the active func
tion object (w.HTMLParagraphElement)"); |
| 108 |
| 109 return o; |
| 110 }).bind({}); |
| 111 |
| 112 Object.defineProperty(TestElement, "prototype", { |
| 113 get() { |
| 114 return returnNotAnObject ? notAnObject : {}; |
| 115 } |
| 116 }); |
| 117 |
| 118 w.customElements.define("test-element", TestElement, { extends: "p" }); |
| 119 |
| 120 returnNotAnObject = true; |
| 121 new TestElement(); |
| 122 } |
| 123 }, "If prototype is not object, derives the fallback from NewTarget's realm (cus
tomized built-in elements)"); |
| 124 </script> |
OLD | NEW |