OLD | NEW |
| (Empty) |
1 <!DOCTYPE html> | |
2 <title>Custom Elements: upgrade element</title> | |
3 <link rel="help" href="https://html.spec.whatwg.org/multipage/scripting.html#con
cept-upgrade-an-element"> | |
4 <script src="../../resources/testharness.js"></script> | |
5 <script src="../../resources/testharnessreport.js"></script> | |
6 <script src="resources/custom-elements-helpers.js"></script> | |
7 <body> | |
8 <script> | |
9 | |
10 'use strict' | |
11 // 6. "attributeChangedCallback" and "connectedCallback" should execute after C
and | |
12 // the rest of the upgrade process finishes. | |
13 test_with_window((w) => { | |
14 let invocations = []; | |
15 let changedCallbackArgs; | |
16 let a = w.document.createElement('a-a'); | |
17 w.document.body.appendChild(a); | |
18 a.setAttribute('x', '1'); | |
19 class X extends w.HTMLElement { | |
20 constructor() { | |
21 super(); | |
22 invocations.push(['constructor', this]); | |
23 } | |
24 connectedCallback() { invocations.push(['connected', this]); } | |
25 static get observedAttributes() { return ['x']; } | |
26 attributeChangedCallback() { | |
27 invocations.push(['attributeChanged', this]); | |
28 changedCallbackArgs = arguments; | |
29 } | |
30 } | |
31 w.customElements.define('a-a', X); | |
32 assert_equals(invocations.length, 3); | |
33 assert_array_equals(invocations[0], ['constructor', a], 'constructor should ex
ecute first'); | |
34 assert_array_equals(invocations[1], ['attributeChanged', a], 'attributeChanged
Callback should execute after the constructor'); | |
35 assert_array_equals(changedCallbackArgs, ['x', null, '1', '']); | |
36 assert_array_equals(invocations[2], ['connected', a], 'connectedCallback shoul
d execute after the constructor'); | |
37 }, '"connectedCallback", "attributeChangedCallback" reactions should execute aft
er the constructor'); | |
38 | |
39 // 6. If C non-conformantly uses an API decorated with the [CEReactions] extende
d attribute, | |
40 // then the reactions enqueued at the beginning of upgrade will execute during t
his step, | |
41 // before C finishes and control returns to this algorithm. | |
42 test_with_window((w) => { | |
43 let invocations = []; | |
44 let changedCallbackArgs; | |
45 let a = w.document.createElement('a-a'); | |
46 w.document.body.appendChild(a); | |
47 class X extends w.HTMLElement { | |
48 constructor() { | |
49 super(); | |
50 this.setAttribute('x', '1'); | |
51 invocations.push(['constructor', this]); | |
52 } | |
53 connectedCallback() { invocations.push(['connected', this]); } | |
54 static get observedAttributes() { return ['x']; } | |
55 attributeChangedCallback() { | |
56 invocations.push(['attributeChanged', this]); | |
57 changedCallbackArgs = arguments; | |
58 } | |
59 } | |
60 w.customElements.define('a-a', X); | |
61 assert_equals(invocations.length, 3); | |
62 assert_array_equals(invocations[0], ['connected', a], 'connectedCallback execu
tes before the constructor'); | |
63 assert_array_equals(invocations[1], ['attributeChanged', a], 'attributeChanged
Callback executes before the constructor'); | |
64 assert_array_equals(changedCallbackArgs, ['x', null, '1', '']); | |
65 assert_array_equals(invocations[2], ['constructor', a], 'constructor executes
last'); | |
66 }, 'The constructor non-conformatly uses API decorated with the [CEReactions]'); | |
67 | |
68 // 8. If constructResult is an abrupt completion, then return constructResult | |
69 // (i.e., rethrow the exception). | |
70 test_with_window((w) => { | |
71 let error_log = []; | |
72 let doc = w.document; | |
73 doc.body.appendChild(doc.createElement('a-a')); | |
74 w.onerror = function (msg, url, lineNo, columnNo, error) { | |
75 error_log.push(error); | |
76 return true; | |
77 }; | |
78 class X extends w.HTMLElement { | |
79 constructor() { | |
80 super(); | |
81 assert_false(this.matches(':defined'), 'calling super() with non-empty con
struction stack should not define the element'); | |
82 throw 'constructor throws'; | |
83 } | |
84 } | |
85 w.customElements.define('a-a', X); | |
86 assert_array_equals(error_log, ['constructor throws'], 'rethrow any exception
thrown from constructor'); | |
87 }, 'Upgrading an element with a throwing constructor should rethrow that excepti
on'); | |
88 | |
89 // 9. If SameValue(constructResult.[[value]], element) is false, then throw an | |
90 // "InvalidStateError" DOMException and terminate these steps. | |
91 test_with_window((w) => { | |
92 let error_log = []; | |
93 w.onerror = function (msg, url, lineNo, columnNo, error) { | |
94 error_log.push(error); | |
95 return true; | |
96 }; | |
97 let a = w.document.createElement('a-a'); | |
98 w.document.body.appendChild(a); | |
99 class X extends w.HTMLElement { | |
100 constructor() { | |
101 super(); | |
102 return ['aaaa']; | |
103 } | |
104 } | |
105 w.customElements.define('a-a', X); | |
106 assert_array_equals(error_log, ['InvalidStateError'], 'returning object that i
s different from element should throw "InvalidStateError"'); | |
107 }, 'Upgrading an element with invalid constructor'); | |
108 </script> | |
109 </body> | |
OLD | NEW |