Skip to content

Commit

Permalink
Add customElements.getName method
Browse files Browse the repository at this point in the history
https://bugs.webkit.org/show_bug.cgi?id=255778

Reviewed by Alexey Shvayka and Chris Dumez.

Implement whatwg/html#9195 with test cases added in
web-platform-tests/wpt#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
  • Loading branch information
rniwa committed Apr 22, 2023
1 parent b6892f5 commit e2748d7
Show file tree
Hide file tree
Showing 5 changed files with 46 additions and 1 deletion.
Expand Up @@ -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
Expand Down
Expand Up @@ -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');
Expand Down
11 changes: 11 additions & 0 deletions Source/WebCore/dom/CustomElementRegistry.cpp
Expand Up @@ -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<Element>(root)) {
Expand Down
4 changes: 3 additions & 1 deletion Source/WebCore/dom/CustomElementRegistry.h
Expand Up @@ -35,9 +35,10 @@

namespace JSC {

class JSGlobalObject;
class JSObject;
class JSValue;

}

namespace WebCore {
Expand Down Expand Up @@ -69,6 +70,7 @@ class CustomElementRegistry : public RefCounted<CustomElementRegistry>, 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<AtomString, Ref<DeferredPromise>>& promiseMap() { return m_promiseMap; }
Expand Down
4 changes: 4 additions & 0 deletions Source/WebCore/dom/CustomElementRegistry.idl
Expand Up @@ -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<undefined> whenDefined(DOMString name);
[CEReactions] undefined upgrade(Node root);
};

0 comments on commit e2748d7

Please sign in to comment.