Changeset 205340 in webkit
- Timestamp:
- Sep 1, 2016 11:17:17 PM (8 years ago)
- Location:
- trunk
- Files:
-
- 2 added
- 17 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/LayoutTests/ChangeLog
r205339 r205340 1 2016-09-01 Ryosuke Niwa <rniwa@webkit.org> 2 3 Only update connected custom elements 4 https://bugs.webkit.org/show_bug.cgi?id=161480 5 6 Reviewed by Yusuke Suzuki. 7 8 Added a W3c-style testharness.js test for https://html.spec.whatwg.org/#enqueue-a-custom-element-upgrade-reaction 9 and added more test cases for :defined and customElements.define. 10 11 * fast/custom-elements/CustomElementRegistry.html: Revised descriptions for "get" and "whenDefined" test cases consistent 12 with ones for "define". 13 * fast/custom-elements/defined-pseudo-class-expected.txt: 14 * fast/custom-elements/defined-pseudo-class.html: 15 * fast/custom-elements/enqueue-custom-element-upgrade-reaction-expected.txt: Added. 16 * fast/custom-elements/enqueue-custom-element-upgrade-reaction.html: Added. 17 * fast/custom-elements/resources/document-types.js: 18 (create): 19 1 20 2016-09-01 Gyuyoung Kim <gyuyoung.kim@webkit.org> 2 21 -
trunk/LayoutTests/fast/custom-elements/CustomElementRegistry-expected.txt
r205316 r205340 9 9 PASS customElements.define must check IsConstructor on the constructor before checking the element definition is running flag 10 10 PASS customElements.define must validate the custom element name before checking the element definition is running flag 11 PASS customElements.define unset the element definition is running flag before upgrading custom elements 11 12 PASS customElements.define must not throw when defining another custom element in a different global object during Get(constructor, "prototype") 12 13 PASS Custom Elements: CustomElementRegistry interface … … 24 25 PASS customElements.define must not throw even if "observedAttributes" fails to convert if "attributeChangedCallback" is not defined 25 26 PASS customElements.define must define an instantiatable custom element 27 PASS customElements.define must upgrade elements in the shadow-including tree order 26 28 PASS CustomElementRegistry interface must have get as a method 27 PASS "get"must return undefined when the registry does not contain an entry with the given name28 PASS "get"must return undefined when the registry does not contain an entry with the given name even if the name was not a valid custom element name29 PASS "get"return the constructor of the entry with the given name when there is a matching entry.30 PASS "whenDefined"must return a promise for a valid custom element name31 PASS "whenDefined"must return the same promise each time invoked for a valid custom element name which has not been defined32 PASS "whenDefined"must return an unresolved promise when the registry does not contain the entry with the given name33 PASS "whenDefined"must return a rejected promise when the given name is not a valid custom element name34 PASS "whenDefined"must return a resolved promise when the registry contains the entry with the given name35 PASS "whenDefined"must return a new resolved promise each time invoked when the registry contains the entry with the given name36 PASS A promise returned by "whenDefined"must be resolved by "define"29 PASS customElements.get must return undefined when the registry does not contain an entry with the given name 30 PASS customElements.get must return undefined when the registry does not contain an entry with the given name even if the name was not a valid custom element name 31 PASS customElements.get return the constructor of the entry with the given name when there is a matching entry. 32 PASS customElements.whenDefined must return a promise for a valid custom element name 33 PASS customElements.whenDefined must return the same promise each time invoked for a valid custom element name which has not been defined 34 PASS customElements.whenDefined must return an unresolved promise when the registry does not contain the entry with the given name 35 PASS customElements.whenDefined must return a rejected promise when the given name is not a valid custom element name 36 PASS customElements.whenDefined must return a resolved promise when the registry contains the entry with the given name 37 PASS customElements.whenDefined must return a new resolved promise each time invoked when the registry contains the entry with the given name 38 PASS A promise returned by customElements.whenDefined must be resolved by "define" 37 39 -
trunk/LayoutTests/fast/custom-elements/CustomElementRegistry.html
r205316 r205340 149 149 assert_array_equals(calls, ['prototype'], 'customElements.define must get "prototype"'); 150 150 }, 'customElements.define must validate the custom element name before checking the element definition is running flag'); 151 152 test(function () { 153 var unresolvedElement = document.createElement('constructor-calls-define'); 154 document.body.appendChild(unresolvedElement); 155 var elementUpgradedDuringUpgrade = document.createElement('defined-during-upgrade'); 156 document.body.appendChild(elementUpgradedDuringUpgrade); 157 158 var DefinedDuringUpgrade = class extends HTMLElement { }; 159 160 class ConstructorCallsDefine extends HTMLElement { 161 constructor() { 162 customElements.define('defined-during-upgrade', DefinedDuringUpgrade); 163 assert_false(unresolvedElement instanceof ConstructorCallsDefine); 164 assert_true(elementUpgradedDuringUpgrade instanceof DefinedDuringUpgrade); 165 super(); 166 assert_true(unresolvedElement instanceof ConstructorCallsDefine); 167 assert_true(elementUpgradedDuringUpgrade instanceof DefinedDuringUpgrade); 168 } 169 } 170 171 assert_false(unresolvedElement instanceof ConstructorCallsDefine); 172 assert_false(elementUpgradedDuringUpgrade instanceof DefinedDuringUpgrade); 173 174 customElements.define('constructor-calls-define', ConstructorCallsDefine); 175 }, 'customElements.define unset the element definition is running flag before upgrading custom elements'); 151 176 152 177 (function () { … … 385 410 386 411 test(function () { 412 var disconnectedElement = document.createElement('some-custom'); 413 var connectedElementBeforeShadowHost = document.createElement('some-custom'); 414 var connectedElementAfterShadowHost = document.createElement('some-custom'); 415 var elementInShadowTree = document.createElement('some-custom'); 416 var childElementOfShadowHost = document.createElement('some-custom'); 417 var customShadowHost = document.createElement('some-custom'); 418 var elementInNestedShadowTree = document.createElement('some-custom'); 419 420 var container = document.createElement('div'); 421 var shadowHost = document.createElement('div'); 422 var shadowRoot = shadowHost.attachShadow({mode: 'closed'}); 423 container.appendChild(connectedElementBeforeShadowHost); 424 container.appendChild(shadowHost); 425 container.appendChild(connectedElementAfterShadowHost); 426 shadowHost.appendChild(childElementOfShadowHost); 427 shadowRoot.appendChild(elementInShadowTree); 428 shadowRoot.appendChild(customShadowHost); 429 430 var innerShadowRoot = customShadowHost.attachShadow({mode: 'closed'}); 431 innerShadowRoot.appendChild(elementInNestedShadowTree); 432 433 var calls = []; 434 class SomeCustomElement extends HTMLElement { 435 constructor() { 436 super(); 437 calls.push(this); 438 } 439 }; 440 441 document.body.appendChild(container); 442 customElements.define('some-custom', SomeCustomElement); 443 assert_array_equals(calls, [connectedElementBeforeShadowHost, elementInShadowTree, customShadowHost, elementInNestedShadowTree, childElementOfShadowHost, connectedElementAfterShadowHost]); 444 }, 'customElements.define must upgrade elements in the shadow-including tree order'); 445 446 test(function () { 387 447 assert_true('get' in CustomElementRegistry.prototype, '"get" exists on CustomElementRegistry.prototype'); 388 448 assert_true('get' in customElements, '"get" exists on window.customElements'); … … 391 451 test(function () { 392 452 assert_equals(customElements.get('a-b'), undefined); 393 }, ' "get"must return undefined when the registry does not contain an entry with the given name');453 }, 'customElements.get must return undefined when the registry does not contain an entry with the given name'); 394 454 395 455 test(function () { … … 399 459 assert_equals(customElements.get('g'), undefined); 400 460 assert_equals(customElements.get('ab'), undefined); 401 }, ' "get"must return undefined when the registry does not contain an entry with the given name even if the name was not a valid custom element name');461 }, 'customElements.get must return undefined when the registry does not contain an entry with the given name even if the name was not a valid custom element name'); 402 462 403 463 test(function () { … … 406 466 customElements.define('existing-custom-element', ExistingCustomElement); 407 467 assert_equals(customElements.get('existing-custom-element'), ExistingCustomElement); 408 }, ' "get"return the constructor of the entry with the given name when there is a matching entry.');468 }, 'customElements.get return the constructor of the entry with the given name when there is a matching entry.'); 409 469 410 470 test(function () { 411 471 assert_true(customElements.whenDefined('some-name') instanceof Promise); 412 }, ' "whenDefined"must return a promise for a valid custom element name');472 }, 'customElements.whenDefined must return a promise for a valid custom element name'); 413 473 414 474 test(function () { 415 475 assert_equals(customElements.whenDefined('some-name'), customElements.whenDefined('some-name')); 416 }, ' "whenDefined"must return the same promise each time invoked for a valid custom element name which has not been defined');476 }, 'customElements.whenDefined must return the same promise each time invoked for a valid custom element name which has not been defined'); 417 477 418 478 promise_test(function () { … … 424 484 assert_false(rejected, 'The promise returned by "whenDefined" must not be rejected until a custom element is defined'); 425 485 }); 426 }, ' "whenDefined"must return an unresolved promise when the registry does not contain the entry with the given name')486 }, 'customElements.whenDefined must return an unresolved promise when the registry does not contain the entry with the given name') 427 487 428 488 promise_test(function () { … … 437 497 assert_true('rejected' in promise, 'The promise returned by "whenDefined" must not be rejected when a custom element is defined'); 438 498 }); 439 }, ' "whenDefined"must return a rejected promise when the given name is not a valid custom element name');499 }, 'customElements.whenDefined must return a rejected promise when the given name is not a valid custom element name'); 440 500 441 501 promise_test(function () { … … 454 514 assert_false('rejected' in promise, 'The promise returned by "whenDefined" must not be rejected when a custom element is defined'); 455 515 }); 456 }, ' "whenDefined"must return a resolved promise when the registry contains the entry with the given name');516 }, 'customElements.whenDefined must return a resolved promise when the registry contains the entry with the given name'); 457 517 458 518 promise_test(function () { … … 480 540 assert_false('rejected' in promise2, 'The promise returned by "whenDefined" must not be rejected when a custom element is defined'); 481 541 }); 482 }, ' "whenDefined"must return a new resolved promise each time invoked when the registry contains the entry with the given name');542 }, 'customElements.whenDefined must return a new resolved promise each time invoked when the registry contains the entry with the given name'); 483 543 484 544 promise_test(function () { … … 515 575 assert_false('rejected' in promiseAfterDefine, 'The promise returned by "whenDefined" must not be rejected when a custom element is defined'); 516 576 }); 517 }, 'A promise returned by "whenDefined"must be resolved by "define"');577 }, 'A promise returned by customElements.whenDefined must be resolved by "define"'); 518 578 519 579 </script> -
trunk/LayoutTests/fast/custom-elements/defined-pseudo-class-expected.txt
r205060 r205340 1 1 2 2 PASS The defined flag of a custom element must not be set if a custom element has not been upgraded yet 3 PASS The defined flag of a custom element must not be set if a custom element has not been upgraded yet even if the element has been defined 3 4 PASS The defined flag of a custom element must be set when a custom element is successfully upgraded 4 5 PASS The defined flag of a custom element must be set if there is a matching definition 6 PASS The defined flag of an upgraded custom element must be set 5 7 PASS The defined flag of a custom element created by HTML parser must be unset if there is no matching definition 6 8 PASS The defined flag of a custom element created by HTML parser must be set if there is a matching definition -
trunk/LayoutTests/fast/custom-elements/defined-pseudo-class.html
r205060 r205340 29 29 30 30 test(function () { 31 assert_false(upgradeCandidate.matches(':defined')); 32 }, 'The defined flag of a custom element must not be set if a custom element has not been upgraded yet even if the element has been defined'); 33 34 test(function () { 35 document.body.appendChild(upgradeCandidate); 31 36 assert_true(upgradeCandidate.matches(':defined')); 32 37 assert_false(matchInsideConstructor, 'Upgrading a custom element must set defined flag after invoking the constructor'); … … 38 43 assert_false(matchInsideConstructor, 'Creating a custom element must set defined flag after invoking the constructor'); 39 44 }, 'The defined flag of a custom element must be set if there is a matching definition'); 45 46 test(function () { 47 var upgradedElement = document.createElement('my-element').cloneNode(true); 48 assert_true(upgradedElement.matches(':defined')); 49 assert_false(matchInsideConstructor, 'Creating a custom element must set defined flag after invoking the constructor'); 50 }, 'The defined flag of an upgraded custom element must be set'); 40 51 41 52 document.write('<my-other-element></my-other-element>'); -
trunk/LayoutTests/fast/custom-elements/resources/document-types.js
r205085 r205340 4 4 create: function () { return Promise.resolve(document); }, 5 5 isOwner: true, 6 hasBrowsingContext: true, 6 7 }, 7 8 { … … 15 16 resolve(doc); 16 17 }); 17 } 18 }, 19 hasBrowsingContext: false, 18 20 }, 19 21 { … … 25 27 resolve(doc); 26 28 }); 27 } 29 }, 30 hasBrowsingContext: false, 28 31 }, 29 32 { … … 35 38 resolve(doc); 36 39 }); 37 } 40 }, 41 hasBrowsingContext: false, 38 42 }, 39 43 { … … 41 45 create: function () { 42 46 return Promise.resolve(document.implementation.createHTMLDocument()); 43 } 47 }, 48 hasBrowsingContext: false, 44 49 }, 45 50 { … … 47 52 create: function () { 48 53 return Promise.resolve(document.implementation.createDocument('http://www.w3.org/1999/xhtml', 'html', null)); 49 } 54 }, 55 hasBrowsingContext: false, 50 56 }, 51 57 { … … 58 64 document.body.appendChild(iframe); 59 65 }); 60 } 66 }, 67 hasBrowsingContext: true, 61 68 }, 62 69 { … … 71 78 xhr.send(); 72 79 }); 73 } 80 }, 81 hasBrowsingContext: false, 74 82 } 75 83 ]; -
trunk/Source/WebCore/ChangeLog
r205335 r205340 1 2016-09-01 Ryosuke Niwa <rniwa@webkit.org> 2 3 Only update connected custom elements 4 https://bugs.webkit.org/show_bug.cgi?id=161480 5 6 Reviewed by Yusuke Suzuki. 7 8 In the latest specs, creating an element only upgrades an element if the custom element had already been defined: 9 https://dom.spec.whatwg.org/#concept-create-element 10 11 Otherwise, an element remains unresolved until it gets connected to the document associated with the global object: 12 https://dom.spec.whatwg.org/#concept-node-insert 13 14 This patch removes the upgrade candidate map in CustomElementRegistry, and traverses the entire document associated 15 with global object (DOMWindow) in addElementDefinition: https://html.spec.whatwg.org/#dom-customelementregistry-define 16 17 The traversal is done in the shadow-including tree order (different from depth-first preorder traversal of flat tree) 18 since it doesn't enter slots and children of shadow hosts are always visited even if they are not assigned to a slot: 19 https://dom.spec.whatwg.org/#concept-shadow-including-tree-order 20 21 Test: fast/custom-elements/enqueue-custom-element-upgrade-reaction.html 22 23 * bindings/js/JSCustomElementInterface.cpp: 24 (WebCore::JSCustomElementInterface::upgradeElement): Assert that the element being upgraded as the same qualified name 25 as the custom element interface. 26 * bindings/js/JSCustomElementRegistryCustom.cpp: 27 (WebCore::JSCustomElementRegistry::define): Moved the code to resolve the promise from here to addElementDefinition. 28 Also cleaned up the code to extract callbacks a little. 29 * dom/CustomElementReactionQueue.cpp: 30 (WebCore::CustomElementReactionQueue::enqueueElementUpgrade): Added an assertion. 31 (WebCore::CustomElementReactionQueue::enqueueElementUpgradeIfDefined): Added. Upgrade an element if the custom element 32 had already been defined. 33 * dom/CustomElementReactionQueue.h: 34 * dom/CustomElementRegistry.cpp: 35 (WebCore::CustomElementRegistry::create): Stores the reference to DOMWindow to find its document in addElementDefinition. 36 (WebCore::CustomElementRegistry::CustomElementRegistry): Ditto. 37 (WebCore::enqueueUpgradeInShadowIncludingTreeOrder): Added. Enqueue upgrade reactions in shadow-including tree order. 38 (WebCore::CustomElementRegistry::addElementDefinition): Upgrade all unresolved elements that matches this definition and 39 resolve the the promise returned by "whenDefined" if there is any. 40 (WebCore::CustomElementRegistry::addUpgradeCandidate): Deleted. 41 (WebCore::CustomElementRegistry::findInterface): Added a new variant that takes an element. 42 * dom/CustomElementRegistry.h: 43 * dom/Document.cpp: 44 (WebCore::createUpgradeCandidateElement): No longer takes DOMWindow since we don't upgrade synchronously here. It's also 45 wrong not to mark the element as unresolved custom element in a document without a browsing context per new semantics. 46 (WebCore::createHTMLElementWithNameValidation): Ditto. 47 (WebCore::createFallbackHTMLElement): Ditto. 48 * dom/Element.cpp: 49 (WebCore::Element::insertedInto): Enqueue an upgrade reaction if this is an unsolved custom element and there is now 50 a definition for it (the latter condition is checked in enqueueElementUpgradeIfDefined). 51 * html/parser/HTMLConstructionSite.cpp: 52 (WebCore::HTMLConstructionSite::createHTMLElementOrFindCustomElementInterface): Don't upgrade this element until it gets 53 connected to a document in Element::insertedInto. 54 * page/DOMWindow.cpp: 55 (WebCore::DOMWindow::ensureCustomElementRegistry): 56 1 57 2016-09-01 Yusuke Suzuki <utatane.tea@gmail.com> 2 58 -
trunk/Source/WebCore/bindings/js/JSCustomElementInterface.cpp
r205198 r205340 105 105 void JSCustomElementInterface::upgradeElement(Element& element) 106 106 { 107 ASSERT(element.tagQName() == name()); 107 108 ASSERT(element.isUnresolvedCustomElement()); 108 109 if (!canInvokeCallback()) -
trunk/Source/WebCore/bindings/js/JSCustomElementRegistryCustom.cpp
r205315 r205340 128 128 auto elementInterface = JSCustomElementInterface::create(name, constructor, globalObject()); 129 129 130 auto* connectedCallback = getCustomElementCallback(state, prototypeObject, Identifier::fromString(&vm, "connectedCallback")); 131 if (state.hadException()) 132 return jsUndefined(); 133 if (connectedCallback) 130 if (auto* connectedCallback = getCustomElementCallback(state, prototypeObject, Identifier::fromString(&vm, "connectedCallback"))) 134 131 elementInterface->setConnectedCallback(connectedCallback); 135 136 auto* disconnectedCallback = getCustomElementCallback(state, prototypeObject, Identifier::fromString(&vm, "disconnectedCallback")); 137 if (state.hadException()) 138 return jsUndefined(); 139 if (disconnectedCallback) 132 if (state.hadException()) 133 return jsUndefined(); 134 135 if (auto* disconnectedCallback = getCustomElementCallback(state, prototypeObject, Identifier::fromString(&vm, "disconnectedCallback"))) 140 136 elementInterface->setDisconnectedCallback(disconnectedCallback); 141 142 auto* adoptedCallback = getCustomElementCallback(state, prototypeObject, Identifier::fromString(&vm, "adoptedCallback")); 143 if (state.hadException()) 144 return jsUndefined(); 145 if (adoptedCallback) 137 if (state.hadException()) 138 return jsUndefined(); 139 140 if (auto* adoptedCallback = getCustomElementCallback(state, prototypeObject, Identifier::fromString(&vm, "adoptedCallback"))) 146 141 elementInterface->setAdoptedCallback(adoptedCallback); 142 if (state.hadException()) 143 return jsUndefined(); 147 144 148 145 auto* attributeChangedCallback = getCustomElementCallback(state, prototypeObject, Identifier::fromString(&vm, "attributeChangedCallback")); … … 162 159 registry.addElementDefinition(WTFMove(elementInterface)); 163 160 164 // FIXME: 17. Let map be registry's upgrade candidates map.165 // FIXME: 18. Upgrade a newly-defined element given map and definition.166 167 auto& promiseMap = registry.promiseMap();168 auto promise = promiseMap.take(localName);169 if (promise)170 promise.value()->resolve(nullptr);171 172 161 return jsUndefined(); 173 162 } -
trunk/Source/WebCore/dom/CustomElementReactionQueue.cpp
r205085 r205340 117 117 void CustomElementReactionQueue::enqueueElementUpgrade(Element& element, JSCustomElementInterface& elementInterface) 118 118 { 119 ASSERT(element.tagQName() == elementInterface.name()); 119 120 if (auto* queue = CustomElementReactionStack::ensureCurrentQueue()) 120 121 queue->m_items.append({CustomElementReactionQueueItem::Type::ElementUpgrade, element, elementInterface}); 122 } 123 124 void CustomElementReactionQueue::enqueueElementUpgradeIfDefined(Element& element) 125 { 126 ASSERT(element.inDocument()); 127 ASSERT(element.isUnresolvedCustomElement()); 128 auto* window = element.document().domWindow(); 129 if (!window) 130 return; 131 132 auto* registry = window->customElementRegistry(); 133 if (!registry) 134 return; 135 136 auto* elementInterface = registry->findInterface(element); 137 if (!elementInterface) 138 return; 139 140 enqueueElementUpgrade(element, *elementInterface); 121 141 } 122 142 -
trunk/Source/WebCore/dom/CustomElementReactionQueue.h
r205085 r205340 47 47 48 48 static void enqueueElementUpgrade(Element&, JSCustomElementInterface&); 49 static void enqueueElementUpgradeIfDefined(Element&); 49 50 static void enqueueConnectedCallbackIfNeeded(Element&); 50 51 static void enqueueDisconnectedCallbackIfNeeded(Element&); -
trunk/Source/WebCore/dom/CustomElementRegistry.cpp
r205315 r205340 29 29 #if ENABLE(CUSTOM_ELEMENTS) 30 30 31 #include "CustomElementReactionQueue.h" 32 #include "DOMWindow.h" 31 33 #include "Document.h" 32 34 #include "Element.h" 35 #include "ElementTraversal.h" 33 36 #include "JSCustomElementInterface.h" 34 37 #include "JSDOMPromise.h" … … 36 39 #include "QualifiedName.h" 37 40 #include "SVGNames.h" 41 #include "ShadowRoot.h" 38 42 #include <runtime/JSCJSValueInlines.h> 39 43 #include <wtf/text/AtomicString.h> … … 41 45 namespace WebCore { 42 46 43 Ref<CustomElementRegistry> CustomElementRegistry::create( )47 Ref<CustomElementRegistry> CustomElementRegistry::create(DOMWindow& window) 44 48 { 45 return adoptRef(*new CustomElementRegistry( ));49 return adoptRef(*new CustomElementRegistry(window)); 46 50 } 47 51 48 CustomElementRegistry::CustomElementRegistry() 52 CustomElementRegistry::CustomElementRegistry(DOMWindow& window) 53 : m_window(window) 49 54 { } 50 55 51 56 CustomElementRegistry::~CustomElementRegistry() 52 57 { } 58 59 // https://dom.spec.whatwg.org/#concept-shadow-including-tree-order 60 static void enqueueUpgradeInShadowIncludingTreeOrder(ContainerNode& node, JSCustomElementInterface& elementInterface) 61 { 62 for (Element* element = ElementTraversal::firstWithin(node); element; element = ElementTraversal::next(*element)) { 63 if (element->isUnresolvedCustomElement() && element->tagQName() == elementInterface.name()) 64 CustomElementReactionQueue::enqueueElementUpgrade(*element, elementInterface); 65 if (auto* shadowRoot = element->shadowRoot()) { 66 if (shadowRoot->mode() != ShadowRoot::Mode::UserAgent) 67 enqueueUpgradeInShadowIncludingTreeOrder(*shadowRoot, elementInterface); 68 } 69 } 70 } 53 71 54 72 void CustomElementRegistry::addElementDefinition(Ref<JSCustomElementInterface>&& elementInterface) … … 59 77 m_nameMap.add(localName, elementInterface.copyRef()); 60 78 61 auto candidateList = m_upgradeCandidatesMap.find(localName); 62 if (candidateList == m_upgradeCandidatesMap.end()) 63 return; 79 if (auto* document = m_window.document()) 80 enqueueUpgradeInShadowIncludingTreeOrder(*document, elementInterface.get()); 64 81 65 Vector<RefPtr<Element>> list(WTFMove(candidateList->value)); 66 67 m_upgradeCandidatesMap.remove(localName); 68 69 for (auto& candidate : list) { 70 ASSERT(candidate); 71 elementInterface->upgradeElement(*candidate); 72 } 73 74 // We should not be adding more upgrade candidate for this local name. 75 ASSERT(!m_upgradeCandidatesMap.contains(localName)); 82 if (auto promise = m_promiseMap.take(localName)) 83 promise.value()->resolve(nullptr); 76 84 } 77 85 78 void CustomElementRegistry::addUpgradeCandidate(Element& candidate) 86 JSCustomElementInterface* CustomElementRegistry::findInterface(const Element& element) const 79 87 { 80 auto result = m_upgradeCandidatesMap.ensure(candidate.localName(), [] { 81 return Vector<RefPtr<Element>>(); 82 }); 83 auto& nodeVector = result.iterator->value; 84 ASSERT(!nodeVector.contains(&candidate)); 85 nodeVector.append(&candidate); 88 return findInterface(element.tagQName()); 86 89 } 87 90 88 91 JSCustomElementInterface* CustomElementRegistry::findInterface(const QualifiedName& name) const 89 92 { 93 ASSERT(!name.hasPrefix()); 94 if (name.namespaceURI() != HTMLNames::xhtmlNamespaceURI) 95 return nullptr; 90 96 auto it = m_nameMap.find(name.localName()); 91 97 return it == m_nameMap.end() || it->value->name() != name ? nullptr : const_cast<JSCustomElementInterface*>(it->value.ptr()); -
trunk/Source/WebCore/dom/CustomElementRegistry.h
r205315 r205340 44 44 45 45 class CustomElementRegistry; 46 class DOMWindow; 46 47 class DeferredWrapper; 47 48 class Element; … … 51 52 class CustomElementRegistry : public RefCounted<CustomElementRegistry> { 52 53 public: 53 static Ref<CustomElementRegistry> create( );54 static Ref<CustomElementRegistry> create(DOMWindow&); 54 55 ~CustomElementRegistry(); 55 56 56 57 void addElementDefinition(Ref<JSCustomElementInterface>&&); 57 void addUpgradeCandidate(Element&);58 58 59 59 bool& elementDefinitionIsRunning() { return m_elementDefinitionIsRunning; } 60 60 61 JSCustomElementInterface* findInterface(const Element&) const; 61 62 JSCustomElementInterface* findInterface(const QualifiedName&) const; 62 63 JSCustomElementInterface* findInterface(const AtomicString&) const; … … 69 70 70 71 private: 71 CustomElementRegistry( );72 CustomElementRegistry(DOMWindow&); 72 73 73 HashMap<AtomicString, Vector<RefPtr<Element>>> m_upgradeCandidatesMap;74 DOMWindow& m_window; 74 75 HashMap<AtomicString, Ref<JSCustomElementInterface>> m_nameMap; 75 76 HashMap<const JSC::JSObject*, JSCustomElementInterface*> m_constructorMap; -
trunk/Source/WebCore/dom/Document.cpp
r205278 r205340 882 882 883 883 #if ENABLE(CUSTOM_ELEMENTS) 884 static ALWAYS_INLINE RefPtr<HTMLElement> createUpgradeCandidateElement(Document& document, DOMWindow* window,const QualifiedName& name)885 { 886 if (! window || !RuntimeEnabledFeatures::sharedFeatures().customElementsEnabled())884 static ALWAYS_INLINE RefPtr<HTMLElement> createUpgradeCandidateElement(Document& document, const QualifiedName& name) 885 { 886 if (!RuntimeEnabledFeatures::sharedFeatures().customElementsEnabled()) 887 887 return nullptr; 888 888 … … 892 892 auto element = HTMLElement::create(name, document); 893 893 element->setIsUnresolvedCustomElement(); 894 window->ensureCustomElementRegistry().addUpgradeCandidate(element.get());895 894 return WTFMove(element); 896 895 } … … 922 921 923 922 #if ENABLE(CUSTOM_ELEMENTS) 924 if (auto element = createUpgradeCandidateElement(document, window,qualifiedName))923 if (auto element = createUpgradeCandidateElement(document, qualifiedName)) 925 924 return WTFMove(element); 926 925 #endif … … 1100 1099 } 1101 1100 // FIXME: Should we also check the equality of prefix between the custom element and name? 1102 if (auto element = createUpgradeCandidateElement(document, window,name))1101 if (auto element = createUpgradeCandidateElement(document, name)) 1103 1102 return element.releaseNonNull(); 1104 1103 #endif -
trunk/Source/WebCore/dom/Element.cpp
r205249 r205340 1607 1607 1608 1608 #if ENABLE(CUSTOM_ELEMENTS) 1609 if (becomeConnected && UNLIKELY(isCustomElement())) 1610 CustomElementReactionQueue::enqueueConnectedCallbackIfNeeded(*this); 1609 if (becomeConnected) { 1610 if (UNLIKELY(isUnresolvedCustomElement())) 1611 CustomElementReactionQueue::enqueueElementUpgradeIfDefined(*this); 1612 if (UNLIKELY(isCustomElement())) 1613 CustomElementReactionQueue::enqueueConnectedCallbackIfNeeded(*this); 1614 } 1615 1611 1616 #endif 1612 1617 -
trunk/Source/WebCore/html/parser/HTMLConstructionSite.cpp
r204732 r205340 679 679 element = HTMLElement::create(qualifiedName, ownerDocument); 680 680 element->setIsUnresolvedCustomElement(); 681 window->ensureCustomElementRegistry().addUpgradeCandidate(*element);682 681 } else 683 682 #endif -
trunk/Source/WebCore/page/DOMWindow.cpp
r204986 r205340 626 626 { 627 627 if (!m_customElementRegistry) 628 m_customElementRegistry = CustomElementRegistry::create( );628 m_customElementRegistry = CustomElementRegistry::create(*this); 629 629 return *m_customElementRegistry; 630 630 }
Note: See TracChangeset
for help on using the changeset viewer.