From e2748d7c56a29d295d71552e3d999d7b51ca037e Mon Sep 17 00:00:00 2001 From: Ryosuke Niwa Date: Sat, 22 Apr 2023 12:26:17 -0700 Subject: [PATCH] Add customElements.getName method https://bugs.webkit.org/show_bug.cgi?id=255778 Reviewed by Alexey Shvayka and Chris Dumez. Implement https://github.com/whatwg/html/pull/9195 with test cases added in https://github.com/web-platform-tests/wpt/pull/39640. * LayoutTests/imported/w3c/web-platform-tests/custom-elements/CustomElementRegistry-expected.txt: * LayoutTests/imported/w3c/web-platform-tests/custom-elements/CustomElementRegistry.html: * Source/WebCore/dom/CustomElementRegistry.cpp: (WebCore::CustomElementRegistry::getName): Added. * Source/WebCore/dom/CustomElementRegistry.h: * Source/WebCore/dom/CustomElementRegistry.idl: Canonical link: https://commits.webkit.org/263281@main --- .../CustomElementRegistry-expected.txt | 5 ++++ .../CustomElementRegistry.html | 23 +++++++++++++++++++ Source/WebCore/dom/CustomElementRegistry.cpp | 11 +++++++++ Source/WebCore/dom/CustomElementRegistry.h | 4 +++- Source/WebCore/dom/CustomElementRegistry.idl | 4 ++++ 5 files changed, 46 insertions(+), 1 deletion(-) diff --git a/LayoutTests/imported/w3c/web-platform-tests/custom-elements/CustomElementRegistry-expected.txt b/LayoutTests/imported/w3c/web-platform-tests/custom-elements/CustomElementRegistry-expected.txt index 665c66ecde06..b5d3c3ae99df 100644 --- a/LayoutTests/imported/w3c/web-platform-tests/custom-elements/CustomElementRegistry-expected.txt +++ b/LayoutTests/imported/w3c/web-platform-tests/custom-elements/CustomElementRegistry-expected.txt @@ -36,6 +36,11 @@ PASS CustomElementRegistry interface must have get as a method PASS customElements.get must return undefined when the registry does not contain an entry with the given name 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 PASS customElements.get return the constructor of the entry with the given name when there is a matching entry. +PASS customElements.getName must return undefined when called with undefined +PASS customElements.getName must return undefined when called with null +PASS customElements.getName must return undefined when called with a string +PASS customElements.getName must return undefined when the registry does not contain an entry with the given constructor +PASS customElements.getName returns the name of the entry with the given constructor when there is a matching entry. PASS customElements.whenDefined must return a promise for a valid custom element name PASS customElements.whenDefined must return the same promise each time invoked for a valid custom element name which has not been defined PASS customElements.whenDefined must return an unresolved promise when the registry does not contain the entry with the given name diff --git a/LayoutTests/imported/w3c/web-platform-tests/custom-elements/CustomElementRegistry.html b/LayoutTests/imported/w3c/web-platform-tests/custom-elements/CustomElementRegistry.html index 5b75fc651fcf..fddb3be999fe 100644 --- a/LayoutTests/imported/w3c/web-platform-tests/custom-elements/CustomElementRegistry.html +++ b/LayoutTests/imported/w3c/web-platform-tests/custom-elements/CustomElementRegistry.html @@ -623,6 +623,29 @@ assert_equals(customElements.get('existing-custom-element'), ExistingCustomElement); }, 'customElements.get return the constructor of the entry with the given name when there is a matching entry.'); +test(function () { + assert_equals(customElements.getName(undefined), undefined); +}, 'customElements.getName must return undefined when called with undefined'); + +test(function () { + assert_equals(customElements.getName(null), undefined); +}, 'customElements.getName must return undefined when called with null'); + +test(function () { + assert_equals(customElements.getName(''), undefined); +}, 'customElements.getName must return undefined when called with a string'); + +test(function () { + assert_equals(customElements.getName(class extends HTMLElement {}), undefined); +}, 'customElements.getName must return undefined when the registry does not contain an entry with the given constructor'); + +test(function () { + class ExistingCustomElement extends HTMLElement {}; + assert_equals(customElements.getName(ExistingCustomElement), undefined); + customElements.define('other-custom-element', ExistingCustomElement); + assert_equals(customElements.getName(ExistingCustomElement), 'other-custom-element'); +}, 'customElements.getName returns the name of the entry with the given constructor when there is a matching entry.'); + test(function () { assert_true(customElements.whenDefined('some-name') instanceof Promise); }, 'customElements.whenDefined must return a promise for a valid custom element name'); diff --git a/Source/WebCore/dom/CustomElementRegistry.cpp b/Source/WebCore/dom/CustomElementRegistry.cpp index ae3fff7ebef3..d0527835a160 100644 --- a/Source/WebCore/dom/CustomElementRegistry.cpp +++ b/Source/WebCore/dom/CustomElementRegistry.cpp @@ -128,6 +128,17 @@ JSC::JSValue CustomElementRegistry::get(const AtomString& name) return JSC::jsUndefined(); } +JSC::JSValue CustomElementRegistry::getName(JSC::JSGlobalObject& globalObject, JSC::JSValue constructorValue) +{ + auto* constructor = constructorValue.getObject(); + if (!constructor) + return JSC::jsUndefined(); + auto* elementInterface = findInterface(constructor); + if (!elementInterface) + return JSC::jsUndefined(); + return JSC::jsString(globalObject.vm(), elementInterface->name().localName()); +} + static void upgradeElementsInShadowIncludingDescendants(ContainerNode& root) { for (auto& element : descendantsOfType(root)) { diff --git a/Source/WebCore/dom/CustomElementRegistry.h b/Source/WebCore/dom/CustomElementRegistry.h index a4443e421de5..917ddb0fce75 100644 --- a/Source/WebCore/dom/CustomElementRegistry.h +++ b/Source/WebCore/dom/CustomElementRegistry.h @@ -35,9 +35,10 @@ namespace JSC { +class JSGlobalObject; class JSObject; class JSValue; - + } namespace WebCore { @@ -69,6 +70,7 @@ class CustomElementRegistry : public RefCounted, public C bool containsConstructor(const JSC::JSObject*) const; JSC::JSValue get(const AtomString&); + JSC::JSValue getName(JSC::JSGlobalObject&, JSC::JSValue); void upgrade(Node& root); MemoryCompactRobinHoodHashMap>& promiseMap() { return m_promiseMap; } diff --git a/Source/WebCore/dom/CustomElementRegistry.idl b/Source/WebCore/dom/CustomElementRegistry.idl index 2c17cc6ba46e..d282742d37a2 100644 --- a/Source/WebCore/dom/CustomElementRegistry.idl +++ b/Source/WebCore/dom/CustomElementRegistry.idl @@ -31,6 +31,10 @@ ] interface CustomElementRegistry { [CEReactions, Custom] undefined define(DOMString name, Function constructor); any get([AtomString] DOMString name); + + // FIXME: This should return (DOMString or undefined). See webkit.org/b/232734. + [CallWith=CurrentGlobalObject] any getName(any constructor); + [Custom, ReturnsOwnPromise] Promise whenDefined(DOMString name); [CEReactions] undefined upgrade(Node root); };