OLD | NEW |
1 // Copyright 2016 The Chromium Authors. All rights reserved. | 1 // Copyright 2016 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "core/dom/custom/CustomElementsRegistry.h" | 5 #include "core/dom/custom/CustomElementRegistry.h" |
6 | 6 |
7 #include "bindings/core/v8/ExceptionState.h" | 7 #include "bindings/core/v8/ExceptionState.h" |
8 #include "bindings/core/v8/ScriptValue.h" | 8 #include "bindings/core/v8/ScriptValue.h" |
9 #include "core/dom/Document.h" | 9 #include "core/dom/Document.h" |
10 #include "core/dom/Element.h" | 10 #include "core/dom/Element.h" |
11 #include "core/dom/ElementRegistrationOptions.h" | 11 #include "core/dom/ElementRegistrationOptions.h" |
12 #include "core/dom/custom/CEReactionsScope.h" | 12 #include "core/dom/custom/CEReactionsScope.h" |
13 #include "core/dom/custom/CustomElementDefinition.h" | 13 #include "core/dom/custom/CustomElementDefinition.h" |
14 #include "core/dom/custom/CustomElementDefinitionBuilder.h" | 14 #include "core/dom/custom/CustomElementDefinitionBuilder.h" |
15 #include "core/dom/custom/CustomElementDescriptor.h" | 15 #include "core/dom/custom/CustomElementDescriptor.h" |
16 #include "core/dom/custom/CustomElementTestHelpers.h" | 16 #include "core/dom/custom/CustomElementTestHelpers.h" |
17 #include "core/dom/shadow/ShadowRoot.h" | 17 #include "core/dom/shadow/ShadowRoot.h" |
18 #include "core/dom/shadow/ShadowRootInit.h" | 18 #include "core/dom/shadow/ShadowRootInit.h" |
19 #include "core/testing/DummyPageHolder.h" | 19 #include "core/testing/DummyPageHolder.h" |
20 #include "platform/ScriptForbiddenScope.h" | 20 #include "platform/ScriptForbiddenScope.h" |
21 #include "platform/heap/Handle.h" | 21 #include "platform/heap/Handle.h" |
22 #include "testing/gtest/include/gtest/gtest.h" | 22 #include "testing/gtest/include/gtest/gtest.h" |
23 #include "wtf/text/AtomicString.h" | 23 #include "wtf/text/AtomicString.h" |
24 #include <memory> | 24 #include <memory> |
25 | 25 |
26 namespace blink { | 26 namespace blink { |
27 | 27 |
28 class CustomElementsRegistryTest : public ::testing::Test { | 28 class CustomElementRegistryTest : public ::testing::Test { |
29 protected: | 29 protected: |
30 void SetUp() | 30 void SetUp() |
31 { | 31 { |
32 m_page.reset(DummyPageHolder::create(IntSize(1, 1)).release()); | 32 m_page.reset(DummyPageHolder::create(IntSize(1, 1)).release()); |
33 } | 33 } |
34 | 34 |
35 void TearDown() | 35 void TearDown() |
36 { | 36 { |
37 m_page = nullptr; | 37 m_page = nullptr; |
38 } | 38 } |
39 | 39 |
40 Document& document() { return m_page->document(); } | 40 Document& document() { return m_page->document(); } |
41 | 41 |
42 CustomElementsRegistry& registry() | 42 CustomElementRegistry& registry() |
43 { | 43 { |
44 return *m_page->frame().localDOMWindow()->customElements(); | 44 return *m_page->frame().localDOMWindow()->customElements(); |
45 } | 45 } |
46 | 46 |
47 ScriptState* scriptState() | 47 ScriptState* scriptState() |
48 { | 48 { |
49 return ScriptState::forMainWorld(&m_page->frame()); | 49 return ScriptState::forMainWorld(&m_page->frame()); |
50 } | 50 } |
51 | 51 |
52 void collectCandidates( | 52 void collectCandidates( |
53 const CustomElementDescriptor& desc, | 53 const CustomElementDescriptor& desc, |
54 HeapVector<Member<Element>>* elements) | 54 HeapVector<Member<Element>>* elements) |
55 { | 55 { |
56 registry().collectCandidates(desc, elements); | 56 registry().collectCandidates(desc, elements); |
57 } | 57 } |
58 | 58 |
59 ShadowRoot* attachShadowTo(Element* element) | 59 ShadowRoot* attachShadowTo(Element* element) |
60 { | 60 { |
61 NonThrowableExceptionState noExceptions; | 61 NonThrowableExceptionState noExceptions; |
62 ShadowRootInit shadowRootInit; | 62 ShadowRootInit shadowRootInit; |
63 return | 63 return |
64 element->attachShadow(scriptState(), shadowRootInit, noExceptions); | 64 element->attachShadow(scriptState(), shadowRootInit, noExceptions); |
65 } | 65 } |
66 | 66 |
67 private: | 67 private: |
68 std::unique_ptr<DummyPageHolder> m_page; | 68 std::unique_ptr<DummyPageHolder> m_page; |
69 }; | 69 }; |
70 | 70 |
71 TEST_F( | 71 TEST_F( |
72 CustomElementsRegistryTest, | 72 CustomElementRegistryTest, |
73 collectCandidates_shouldNotIncludeElementsRemovedFromDocument) | 73 collectCandidates_shouldNotIncludeElementsRemovedFromDocument) |
74 { | 74 { |
75 Element* element = CreateElement("a-a").inDocument(&document()); | 75 Element* element = CreateElement("a-a").inDocument(&document()); |
76 registry().addCandidate(element); | 76 registry().addCandidate(element); |
77 | 77 |
78 HeapVector<Member<Element>> elements; | 78 HeapVector<Member<Element>> elements; |
79 collectCandidates( | 79 collectCandidates( |
80 CustomElementDescriptor("a-a", "a-a"), | 80 CustomElementDescriptor("a-a", "a-a"), |
81 &elements); | 81 &elements); |
82 | 82 |
83 EXPECT_TRUE(elements.isEmpty()) | 83 EXPECT_TRUE(elements.isEmpty()) |
84 << "no candidates should have been found, but we have " | 84 << "no candidates should have been found, but we have " |
85 << elements.size(); | 85 << elements.size(); |
86 EXPECT_FALSE(elements.contains(element)) | 86 EXPECT_FALSE(elements.contains(element)) |
87 << "the out-of-document candidate should not have been found"; | 87 << "the out-of-document candidate should not have been found"; |
88 } | 88 } |
89 | 89 |
90 TEST_F( | 90 TEST_F( |
91 CustomElementsRegistryTest, | 91 CustomElementRegistryTest, |
92 collectCandidates_shouldNotIncludeElementsInDifferentDocument) | 92 collectCandidates_shouldNotIncludeElementsInDifferentDocument) |
93 { | 93 { |
94 Element* element = CreateElement("a-a").inDocument(&document()); | 94 Element* element = CreateElement("a-a").inDocument(&document()); |
95 registry().addCandidate(element); | 95 registry().addCandidate(element); |
96 | 96 |
97 Document* otherDocument = HTMLDocument::create(); | 97 Document* otherDocument = HTMLDocument::create(); |
98 otherDocument->appendChild(element); | 98 otherDocument->appendChild(element); |
99 EXPECT_EQ(otherDocument, element->ownerDocument()) | 99 EXPECT_EQ(otherDocument, element->ownerDocument()) |
100 << "sanity: another document should have adopted an element on append"; | 100 << "sanity: another document should have adopted an element on append"; |
101 | 101 |
102 HeapVector<Member<Element>> elements; | 102 HeapVector<Member<Element>> elements; |
103 collectCandidates( | 103 collectCandidates( |
104 CustomElementDescriptor("a-a", "a-a"), | 104 CustomElementDescriptor("a-a", "a-a"), |
105 &elements); | 105 &elements); |
106 | 106 |
107 EXPECT_TRUE(elements.isEmpty()) | 107 EXPECT_TRUE(elements.isEmpty()) |
108 << "no candidates should have been found, but we have " | 108 << "no candidates should have been found, but we have " |
109 << elements.size(); | 109 << elements.size(); |
110 EXPECT_FALSE(elements.contains(element)) | 110 EXPECT_FALSE(elements.contains(element)) |
111 << "the adopted-away candidate should not have been found"; | 111 << "the adopted-away candidate should not have been found"; |
112 } | 112 } |
113 | 113 |
114 TEST_F( | 114 TEST_F( |
115 CustomElementsRegistryTest, | 115 CustomElementRegistryTest, |
116 collectCandidates_shouldOnlyIncludeCandidatesMatchingDescriptor) | 116 collectCandidates_shouldOnlyIncludeCandidatesMatchingDescriptor) |
117 { | 117 { |
118 CustomElementDescriptor descriptor("hello-world", "hello-world"); | 118 CustomElementDescriptor descriptor("hello-world", "hello-world"); |
119 | 119 |
120 // Does not match: namespace is not HTML | 120 // Does not match: namespace is not HTML |
121 Element* elementA = CreateElement("hello-world") | 121 Element* elementA = CreateElement("hello-world") |
122 .inDocument(&document()) | 122 .inDocument(&document()) |
123 .inNamespace("data:text/date,1981-03-10"); | 123 .inNamespace("data:text/date,1981-03-10"); |
124 // Matches | 124 // Matches |
125 Element* elementB = CreateElement("hello-world").inDocument(&document()); | 125 Element* elementB = CreateElement("hello-world").inDocument(&document()); |
(...skipping 11 matching lines...) Expand all Loading... |
137 | 137 |
138 HeapVector<Member<Element>> elements; | 138 HeapVector<Member<Element>> elements; |
139 collectCandidates(descriptor, &elements); | 139 collectCandidates(descriptor, &elements); |
140 | 140 |
141 EXPECT_EQ(1u, elements.size()) | 141 EXPECT_EQ(1u, elements.size()) |
142 << "only one candidates should have been found"; | 142 << "only one candidates should have been found"; |
143 EXPECT_EQ(elementB, elements[0]) | 143 EXPECT_EQ(elementB, elements[0]) |
144 << "the matching element should have been found"; | 144 << "the matching element should have been found"; |
145 } | 145 } |
146 | 146 |
147 TEST_F(CustomElementsRegistryTest, collectCandidates_oneCandidate) | 147 TEST_F(CustomElementRegistryTest, collectCandidates_oneCandidate) |
148 { | 148 { |
149 Element* element = CreateElement("a-a").inDocument(&document()); | 149 Element* element = CreateElement("a-a").inDocument(&document()); |
150 registry().addCandidate(element); | 150 registry().addCandidate(element); |
151 document().documentElement()->appendChild(element); | 151 document().documentElement()->appendChild(element); |
152 | 152 |
153 HeapVector<Member<Element>> elements; | 153 HeapVector<Member<Element>> elements; |
154 collectCandidates( | 154 collectCandidates( |
155 CustomElementDescriptor("a-a", "a-a"), | 155 CustomElementDescriptor("a-a", "a-a"), |
156 &elements); | 156 &elements); |
157 | 157 |
158 EXPECT_EQ(1u, elements.size()) | 158 EXPECT_EQ(1u, elements.size()) |
159 << "exactly one candidate should have been found"; | 159 << "exactly one candidate should have been found"; |
160 EXPECT_TRUE(elements.contains(element)) | 160 EXPECT_TRUE(elements.contains(element)) |
161 << "the candidate should be the element that was added"; | 161 << "the candidate should be the element that was added"; |
162 } | 162 } |
163 | 163 |
164 TEST_F(CustomElementsRegistryTest, collectCandidates_shouldBeInDocumentOrder) | 164 TEST_F(CustomElementRegistryTest, collectCandidates_shouldBeInDocumentOrder) |
165 { | 165 { |
166 CreateElement factory = CreateElement("a-a"); | 166 CreateElement factory = CreateElement("a-a"); |
167 factory.inDocument(&document()); | 167 factory.inDocument(&document()); |
168 Element* elementA = factory.withId("a"); | 168 Element* elementA = factory.withId("a"); |
169 Element* elementB = factory.withId("b"); | 169 Element* elementB = factory.withId("b"); |
170 Element* elementC = factory.withId("c"); | 170 Element* elementC = factory.withId("c"); |
171 | 171 |
172 registry().addCandidate(elementB); | 172 registry().addCandidate(elementB); |
173 registry().addCandidate(elementA); | 173 registry().addCandidate(elementA); |
174 registry().addCandidate(elementC); | 174 registry().addCandidate(elementC); |
(...skipping 144 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
319 bool checkConstructorIntrinsics() override { return true; } | 319 bool checkConstructorIntrinsics() override { return true; } |
320 bool checkConstructorNotRegistered() override { return true; } | 320 bool checkConstructorNotRegistered() override { return true; } |
321 bool checkPrototype() override { return true; } | 321 bool checkPrototype() override { return true; } |
322 bool rememberOriginalProperties() override { return true; } | 322 bool rememberOriginalProperties() override { return true; } |
323 CustomElementDefinition* build( | 323 CustomElementDefinition* build( |
324 const CustomElementDescriptor& descriptor) { | 324 const CustomElementDescriptor& descriptor) { |
325 return new LogUpgradeDefinition(descriptor); | 325 return new LogUpgradeDefinition(descriptor); |
326 } | 326 } |
327 }; | 327 }; |
328 | 328 |
329 TEST_F(CustomElementsRegistryTest, define_upgradesInDocumentElements) | 329 TEST_F(CustomElementRegistryTest, define_upgradesInDocumentElements) |
330 { | 330 { |
331 ScriptForbiddenScope doNotRelyOnScript; | 331 ScriptForbiddenScope doNotRelyOnScript; |
332 | 332 |
333 Element* element = CreateElement("a-a").inDocument(&document()); | 333 Element* element = CreateElement("a-a").inDocument(&document()); |
334 element->setAttribute(QualifiedName(nullAtom, "attr1", HTMLNames::xhtmlNames
paceURI), "v1"); | 334 element->setAttribute(QualifiedName(nullAtom, "attr1", HTMLNames::xhtmlNames
paceURI), "v1"); |
335 element->setBooleanAttribute(HTMLNames::contenteditableAttr, true); | 335 element->setBooleanAttribute(HTMLNames::contenteditableAttr, true); |
336 document().documentElement()->appendChild(element); | 336 document().documentElement()->appendChild(element); |
337 | 337 |
338 LogUpgradeBuilder builder; | 338 LogUpgradeBuilder builder; |
339 NonThrowableExceptionState shouldNotThrow; | 339 NonThrowableExceptionState shouldNotThrow; |
(...skipping 26 matching lines...) Expand all Loading... |
366 EXPECT_EQ(2u, definition->m_attributeChanged.size()) | 366 EXPECT_EQ(2u, definition->m_attributeChanged.size()) |
367 << "Upgrade should invoke attributeChangedCallback for all attributes"; | 367 << "Upgrade should invoke attributeChangedCallback for all attributes"; |
368 | 368 |
369 EXPECT_EQ(LogUpgradeDefinition::ConnectedCallback, definition->m_logs[3]) | 369 EXPECT_EQ(LogUpgradeDefinition::ConnectedCallback, definition->m_logs[3]) |
370 << "upgrade should invoke connectedCallback"; | 370 << "upgrade should invoke connectedCallback"; |
371 | 371 |
372 EXPECT_EQ(4u, definition->m_logs.size()) | 372 EXPECT_EQ(4u, definition->m_logs.size()) |
373 << "upgrade should not invoke other callbacks"; | 373 << "upgrade should not invoke other callbacks"; |
374 } | 374 } |
375 | 375 |
376 TEST_F(CustomElementsRegistryTest, attributeChangedCallback) | 376 TEST_F(CustomElementRegistryTest, attributeChangedCallback) |
377 { | 377 { |
378 ScriptForbiddenScope doNotRelyOnScript; | 378 ScriptForbiddenScope doNotRelyOnScript; |
379 | 379 |
380 Element* element = CreateElement("a-a").inDocument(&document()); | 380 Element* element = CreateElement("a-a").inDocument(&document()); |
381 document().documentElement()->appendChild(element); | 381 document().documentElement()->appendChild(element); |
382 | 382 |
383 LogUpgradeBuilder builder; | 383 LogUpgradeBuilder builder; |
384 NonThrowableExceptionState shouldNotThrow; | 384 NonThrowableExceptionState shouldNotThrow; |
385 { | 385 { |
386 CEReactionsScope reactions; | 386 CEReactionsScope reactions; |
(...skipping 16 matching lines...) Expand all Loading... |
403 EXPECT_EQ(1u, definition->m_attributeChanged.size()) | 403 EXPECT_EQ(1u, definition->m_attributeChanged.size()) |
404 << "Adding an attribute should invoke attributeChangedCallback"; | 404 << "Adding an attribute should invoke attributeChangedCallback"; |
405 EXPECT_EQ("attr2", definition->m_attributeChanged[0].name); | 405 EXPECT_EQ("attr2", definition->m_attributeChanged[0].name); |
406 EXPECT_EQ(nullAtom, definition->m_attributeChanged[0].oldValue); | 406 EXPECT_EQ(nullAtom, definition->m_attributeChanged[0].oldValue); |
407 EXPECT_EQ("v2", definition->m_attributeChanged[0].newValue); | 407 EXPECT_EQ("v2", definition->m_attributeChanged[0].newValue); |
408 | 408 |
409 EXPECT_EQ(1u, definition->m_logs.size()) | 409 EXPECT_EQ(1u, definition->m_logs.size()) |
410 << "upgrade should not invoke other callbacks"; | 410 << "upgrade should not invoke other callbacks"; |
411 } | 411 } |
412 | 412 |
413 TEST_F(CustomElementsRegistryTest, disconnectedCallback) | 413 TEST_F(CustomElementRegistryTest, disconnectedCallback) |
414 { | 414 { |
415 ScriptForbiddenScope doNotRelyOnScript; | 415 ScriptForbiddenScope doNotRelyOnScript; |
416 | 416 |
417 Element* element = CreateElement("a-a").inDocument(&document()); | 417 Element* element = CreateElement("a-a").inDocument(&document()); |
418 document().documentElement()->appendChild(element); | 418 document().documentElement()->appendChild(element); |
419 | 419 |
420 LogUpgradeBuilder builder; | 420 LogUpgradeBuilder builder; |
421 NonThrowableExceptionState shouldNotThrow; | 421 NonThrowableExceptionState shouldNotThrow; |
422 { | 422 { |
423 CEReactionsScope reactions; | 423 CEReactionsScope reactions; |
(...skipping 11 matching lines...) Expand all Loading... |
435 CEReactionsScope reactions; | 435 CEReactionsScope reactions; |
436 element->remove(shouldNotThrow); | 436 element->remove(shouldNotThrow); |
437 } | 437 } |
438 EXPECT_EQ(LogUpgradeDefinition::DisconnectedCallback, definition->m_logs[0]) | 438 EXPECT_EQ(LogUpgradeDefinition::DisconnectedCallback, definition->m_logs[0]) |
439 << "remove() should invoke disconnectedCallback"; | 439 << "remove() should invoke disconnectedCallback"; |
440 | 440 |
441 EXPECT_EQ(1u, definition->m_logs.size()) | 441 EXPECT_EQ(1u, definition->m_logs.size()) |
442 << "remove() should not invoke other callbacks"; | 442 << "remove() should not invoke other callbacks"; |
443 } | 443 } |
444 | 444 |
445 TEST_F(CustomElementsRegistryTest, adoptedCallback) | 445 TEST_F(CustomElementRegistryTest, adoptedCallback) |
446 { | 446 { |
447 ScriptForbiddenScope doNotRelyOnScript; | 447 ScriptForbiddenScope doNotRelyOnScript; |
448 | 448 |
449 Element* element = CreateElement("a-a").inDocument(&document()); | 449 Element* element = CreateElement("a-a").inDocument(&document()); |
450 document().documentElement()->appendChild(element); | 450 document().documentElement()->appendChild(element); |
451 | 451 |
452 LogUpgradeBuilder builder; | 452 LogUpgradeBuilder builder; |
453 NonThrowableExceptionState shouldNotThrow; | 453 NonThrowableExceptionState shouldNotThrow; |
454 { | 454 { |
455 CEReactionsScope reactions; | 455 CEReactionsScope reactions; |
(...skipping 19 matching lines...) Expand all Loading... |
475 << "adoptNode() should invoke adoptedCallback"; | 475 << "adoptNode() should invoke adoptedCallback"; |
476 | 476 |
477 EXPECT_EQ(2u, definition->m_logs.size()) | 477 EXPECT_EQ(2u, definition->m_logs.size()) |
478 << "adoptNode() should not invoke other callbacks"; | 478 << "adoptNode() should not invoke other callbacks"; |
479 } | 479 } |
480 | 480 |
481 // TODO(dominicc): Add tests which adjust the "is" attribute when type | 481 // TODO(dominicc): Add tests which adjust the "is" attribute when type |
482 // extensions are implemented. | 482 // extensions are implemented. |
483 | 483 |
484 } // namespace blink | 484 } // namespace blink |
OLD | NEW |