Title: [266142] trunk
Revision
266142
Author
rn...@webkit.org
Date
2020-08-25 14:22:12 -0700 (Tue, 25 Aug 2020)

Log Message

Resolve with the class used to define the Custom Element
https://bugs.webkit.org/show_bug.cgi?id=215562

Reviewed by Darin Adler.

LayoutTests/imported/w3c:

Re-sync'ed the test with that in https://github.com/web-platform-tests/wpt/pull/25033.

* web-platform-tests/custom-elements/CustomElementRegistry-expected.txt:
* web-platform-tests/custom-elements/CustomElementRegistry.html:

Source/WebCore:

Implemented the new behavior to resolve customElements.whenDefined(~)
with the custom element's constructor when it's defined.

Test: imported/w3c/web-platform-tests/custom-elements/CustomElementRegistry.html

* bindings/js/JSCustomElementRegistryCustom.cpp:
(WebCore::JSCustomElementRegistry::define):
(WebCore::whenDefinedPromise):
* bindings/js/JSDOMPromiseDeferred.h:
(WebCore::DeferredPromise::resolveWithJSValue): Added.
* dom/CustomElementRegistry.cpp:
(WebCore::CustomElementRegistry::addElementDefinition): Made this return DeferredPromise.
* dom/CustomElementRegistry.h:

Modified Paths

Diff

Modified: trunk/LayoutTests/imported/w3c/ChangeLog (266141 => 266142)


--- trunk/LayoutTests/imported/w3c/ChangeLog	2020-08-25 20:20:59 UTC (rev 266141)
+++ trunk/LayoutTests/imported/w3c/ChangeLog	2020-08-25 21:22:12 UTC (rev 266142)
@@ -1,3 +1,15 @@
+2020-08-25  Ryosuke Niwa  <rn...@webkit.org>
+
+        Resolve with the class used to define the Custom Element
+        https://bugs.webkit.org/show_bug.cgi?id=215562
+
+        Reviewed by Darin Adler.
+
+        Re-sync'ed the test with that in https://github.com/web-platform-tests/wpt/pull/25033.
+
+        * web-platform-tests/custom-elements/CustomElementRegistry-expected.txt:
+        * web-platform-tests/custom-elements/CustomElementRegistry.html:
+
 2020-08-25  Youenn Fablet  <you...@apple.com>
 
         Refresh ReadableStream.pipeTo implementation up to spec

Modified: trunk/LayoutTests/imported/w3c/web-platform-tests/custom-elements/CustomElementRegistry-expected.txt (266141 => 266142)


--- trunk/LayoutTests/imported/w3c/web-platform-tests/custom-elements/CustomElementRegistry-expected.txt	2020-08-25 20:20:59 UTC (rev 266141)
+++ trunk/LayoutTests/imported/w3c/web-platform-tests/custom-elements/CustomElementRegistry-expected.txt	2020-08-25 21:22:12 UTC (rev 266142)
@@ -43,4 +43,6 @@
 PASS customElements.whenDefined must return a resolved promise when the registry contains the entry with the given name 
 PASS customElements.whenDefined must return a new resolved promise each time invoked when the registry contains the entry with the given name 
 PASS A promise returned by customElements.whenDefined must be resolved by "define" 
+PASS A promise returned by customElements.whenDefined must be resolved with the defined class 
+PASS A promise returned by customElements.whenDefined must be resolved with the defined class once such class is defined 
 

Modified: trunk/LayoutTests/imported/w3c/web-platform-tests/custom-elements/CustomElementRegistry.html (266141 => 266142)


--- trunk/LayoutTests/imported/w3c/web-platform-tests/custom-elements/CustomElementRegistry.html	2020-08-25 20:20:59 UTC (rev 266141)
+++ trunk/LayoutTests/imported/w3c/web-platform-tests/custom-elements/CustomElementRegistry.html	2020-08-25 21:22:12 UTC (rev 266142)
@@ -655,7 +655,8 @@
 }, 'customElements.whenDefined must return a rejected promise when the given name is not a valid custom element name');
 
 promise_test(function () {
-    customElements.define('preexisting-custom-element', class extends HTMLElement { });
+    class PreexistingCustomElement extends HTMLElement { };
+    customElements.define('preexisting-custom-element', PreexistingCustomElement);
 
     var promise = customElements.whenDefined('preexisting-custom-element');
     promise.then(function (value) { promise.resolved = value; }, function (value) { promise.rejected = value; });
@@ -665,8 +666,8 @@
 
     return Promise.resolve().then(function () {
         assert_true('resolved' in promise, 'The promise returned by "whenDefined" must be resolved when a custom element is defined');
-        assert_equals(promise.resolved, undefined,
-            'The promise returned by "whenDefined" must be resolved with "undefined" when a custom element is defined');
+        assert_equals(promise.resolved, PreexistingCustomElement,
+            'The promise returned by "whenDefined" must be resolved with the constructor of the element when a custom element is defined');
         assert_false('rejected' in promise, 'The promise returned by "whenDefined" must not be rejected when a custom element is defined');
     });
 }, 'customElements.whenDefined must return a resolved promise when the registry contains the entry with the given name');
@@ -688,16 +689,17 @@
 
     return Promise.resolve().then(function () {
         assert_true('resolved' in promise1, 'The promise returned by "whenDefined" must be resolved when a custom element is defined');
-        assert_equals(promise1.resolved, undefined, 'The promise returned by "whenDefined" must be resolved with "undefined" when a custom element is defined');
+        assert_equals(promise1.resolved, AnotherExistingCustomElement, 'The promise returned by "whenDefined" must be resolved with the constructor of the element when a custom element is defined');
         assert_false('rejected' in promise1, 'The promise returned by "whenDefined" must not be rejected when a custom element is defined');
 
         assert_true('resolved' in promise2, 'The promise returned by "whenDefined" must be resolved when a custom element is defined');
-        assert_equals(promise2.resolved, undefined, 'The promise returned by "whenDefined" must be resolved with "undefined" when a custom element is defined');
+        assert_equals(promise2.resolved, AnotherExistingCustomElement, 'The promise returned by "whenDefined" must be resolved with the constructor of the element when a custom element is defined');
         assert_false('rejected' in promise2, 'The promise returned by "whenDefined" must not be rejected when a custom element is defined');
     });
 }, 'customElements.whenDefined must return a new resolved promise each time invoked when the registry contains the entry with the given name');
 
 promise_test(function () {
+    class ElementDefinedAfterWhenDefined extends HTMLElement { };
     var promise = customElements.whenDefined('element-defined-after-whendefined');
     promise.then(function (value) { promise.resolved = value; }, function (value) { promise.rejected = value; });
 
@@ -710,7 +712,7 @@
         assert_false('rejected' in promise, 'The promise returned by "whenDefined" must not be rejected until the element is defined');
         assert_equals(customElements.whenDefined('element-defined-after-whendefined'), promise,
             '"whenDefined" must return the same unresolved promise before the custom element is defined');
-        customElements.define('element-defined-after-whendefined', class extends HTMLElement { });
+        customElements.define('element-defined-after-whendefined', ElementDefinedAfterWhenDefined);
         assert_false('resolved' in promise, 'The promise returned by "whenDefined" must not be resolved until the end of the next microtask');
         assert_false('rejected' in promise, 'The promise returned by "whenDefined" must not be rejected until the end of the next microtask');
 
@@ -721,17 +723,33 @@
         assert_false('rejected' in promiseAfterDefine, 'The promise returned by "whenDefined" must not be rejected until the end of the next microtask');
     }).then(function () {
         assert_true('resolved' in promise, 'The promise returned by "whenDefined" must be resolved when a custom element is defined');
-        assert_equals(promise.resolved, undefined,
-            'The promise returned by "whenDefined" must be resolved with "undefined" when a custom element is defined');
+        assert_equals(promise.resolved, ElementDefinedAfterWhenDefined,
+            'The promise returned by "whenDefined" must be resolved with the constructor of the element when a custom element is defined');
         assert_false('rejected' in promise, 'The promise returned by "whenDefined" must not be rejected when a custom element is defined');
 
         assert_true('resolved' in promiseAfterDefine, 'The promise returned by "whenDefined" must be resolved when a custom element is defined');
-        assert_equals(promiseAfterDefine.resolved, undefined,
-            'The promise returned by "whenDefined" must be resolved with "undefined" when a custom element is defined');
+        assert_equals(promiseAfterDefine.resolved, ElementDefinedAfterWhenDefined,
+            'The promise returned by "whenDefined" must be resolved with the constructor of the element when a custom element is defined');
         assert_false('rejected' in promiseAfterDefine, 'The promise returned by "whenDefined" must not be rejected when a custom element is defined');
     });
 }, 'A promise returned by customElements.whenDefined must be resolved by "define"');
 
+promise_test(function () {
+    class ResolvedCustomElement extends HTMLElement {};
+    customElements.define('resolved-custom-element', ResolvedCustomElement);
+    return customElements.whenDefined('resolved-custom-element').then(function (value) {
+        assert_true(value === ResolvedCustomElement, 'The promise returned by "whenDefined" must resolve with the defined class');
+    });
+}, 'A promise returned by customElements.whenDefined must be resolved with the defined class');
+
+promise_test(function () {
+    var promise = customElements.whenDefined('not-resolved-yet-custom-element').then(function (value) {
+        assert_true(value === NotResolvedYetCustomElement, 'The promise returned by "whenDefined" must resolve with the defined class once such class is defined');
+    });
+    class NotResolvedYetCustomElement extends HTMLElement {};
+    customElements.define('not-resolved-yet-custom-element', NotResolvedYetCustomElement);
+    return promise;
+}, 'A promise returned by customElements.whenDefined must be resolved with the defined class once such class is defined');
 </script>
 </body>
 </html>

Modified: trunk/Source/WebCore/ChangeLog (266141 => 266142)


--- trunk/Source/WebCore/ChangeLog	2020-08-25 20:20:59 UTC (rev 266141)
+++ trunk/Source/WebCore/ChangeLog	2020-08-25 21:22:12 UTC (rev 266142)
@@ -1,3 +1,24 @@
+2020-08-25  Ryosuke Niwa  <rn...@webkit.org>
+
+        Resolve with the class used to define the Custom Element
+        https://bugs.webkit.org/show_bug.cgi?id=215562
+
+        Reviewed by Darin Adler.
+
+        Implemented the new behavior to resolve customElements.whenDefined(~)
+        with the custom element's constructor when it's defined.
+
+        Test: imported/w3c/web-platform-tests/custom-elements/CustomElementRegistry.html
+
+        * bindings/js/JSCustomElementRegistryCustom.cpp:
+        (WebCore::JSCustomElementRegistry::define):
+        (WebCore::whenDefinedPromise):
+        * bindings/js/JSDOMPromiseDeferred.h:
+        (WebCore::DeferredPromise::resolveWithJSValue): Added.
+        * dom/CustomElementRegistry.cpp:
+        (WebCore::CustomElementRegistry::addElementDefinition): Made this return DeferredPromise.
+        * dom/CustomElementRegistry.h:
+
 2020-08-25  Alex Christensen  <achristen...@webkit.org>
 
         Fix read-after-free introduced in r266087

Modified: trunk/Source/WebCore/bindings/js/JSCustomElementRegistryCustom.cpp (266141 => 266142)


--- trunk/Source/WebCore/bindings/js/JSCustomElementRegistryCustom.cpp	2020-08-25 20:20:59 UTC (rev 266141)
+++ trunk/Source/WebCore/bindings/js/JSCustomElementRegistryCustom.cpp	2020-08-25 21:22:12 UTC (rev 266142)
@@ -169,7 +169,8 @@
     addToGlobalObjectWithPrivateName(adoptedCallback);
     addToGlobalObjectWithPrivateName(attributeChangedCallback);
 
-    registry.addElementDefinition(WTFMove(elementInterface));
+    if (auto promise = registry.addElementDefinition(WTFMove(elementInterface)))
+        promise->resolveWithJSValue(constructor);
 
     return jsUndefined();
 }
@@ -190,8 +191,8 @@
         return jsUndefined();
     }
 
-    if (registry.findInterface(localName)) {
-        DeferredPromise::create(globalObject, promise)->resolve();
+    if (auto* elementInterface = registry.findInterface(localName)) {
+        DeferredPromise::create(globalObject, promise)->resolveWithJSValue(elementInterface->constructor());
         return &promise;
     }
 

Modified: trunk/Source/WebCore/bindings/js/JSDOMPromiseDeferred.h (266141 => 266142)


--- trunk/Source/WebCore/bindings/js/JSDOMPromiseDeferred.h	2020-08-25 20:20:59 UTC (rev 266141)
+++ trunk/Source/WebCore/bindings/js/JSDOMPromiseDeferred.h	2020-08-25 21:22:12 UTC (rev 266142)
@@ -70,6 +70,18 @@
         resolve(*lexicalGlobalObject, toJS<IDLType>(*lexicalGlobalObject, *globalObject(), std::forward<typename IDLType::ParameterType>(value)));
     }
 
+    void resolveWithJSValue(JSC::JSValue resolution)
+    {
+        if (shouldIgnoreRequestToFulfill())
+            return;
+
+        ASSERT(deferred());
+        ASSERT(globalObject());
+        JSC::JSGlobalObject* lexicalGlobalObject = globalObject();
+        JSC::JSLockHolder locker(lexicalGlobalObject);
+        resolve(*lexicalGlobalObject, resolution);
+    }
+
     void resolve()
     {
         if (shouldIgnoreRequestToFulfill())

Modified: trunk/Source/WebCore/dom/CustomElementRegistry.cpp (266141 => 266142)


--- trunk/Source/WebCore/dom/CustomElementRegistry.cpp	2020-08-25 20:20:59 UTC (rev 266141)
+++ trunk/Source/WebCore/dom/CustomElementRegistry.cpp	2020-08-25 21:22:12 UTC (rev 266142)
@@ -66,7 +66,7 @@
     }
 }
 
-void CustomElementRegistry::addElementDefinition(Ref<JSCustomElementInterface>&& elementInterface)
+RefPtr<DeferredPromise> CustomElementRegistry::addElementDefinition(Ref<JSCustomElementInterface>&& elementInterface)
 {
     AtomString localName = elementInterface->name().localName();
     ASSERT(!m_nameMap.contains(localName));
@@ -77,7 +77,8 @@
         enqueueUpgradeInShadowIncludingTreeOrder(*document, elementInterface.get());
 
     if (auto promise = m_promiseMap.take(localName))
-        promise.value()->resolve();
+        return WTFMove(*promise);
+    return nullptr;
 }
 
 JSCustomElementInterface* CustomElementRegistry::findInterface(const Element& element) const

Modified: trunk/Source/WebCore/dom/CustomElementRegistry.h (266141 => 266142)


--- trunk/Source/WebCore/dom/CustomElementRegistry.h	2020-08-25 20:20:59 UTC (rev 266141)
+++ trunk/Source/WebCore/dom/CustomElementRegistry.h	2020-08-25 21:22:12 UTC (rev 266142)
@@ -53,7 +53,7 @@
     static Ref<CustomElementRegistry> create(DOMWindow&, ScriptExecutionContext*);
     ~CustomElementRegistry();
 
-    void addElementDefinition(Ref<JSCustomElementInterface>&&);
+    RefPtr<DeferredPromise> addElementDefinition(Ref<JSCustomElementInterface>&&);
 
     bool& elementDefinitionIsRunning() { return m_elementDefinitionIsRunning; }
 
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to