Skip to content

Commit

Permalink
Add customElements.whenDefined() API
Browse files Browse the repository at this point in the history
Fixes WICG/webcomponents#427. This adds the ability for authors to wait for a given custom element name to become defined.
  • Loading branch information
domenic authored and annevk committed Apr 16, 2016
1 parent 7bfca70 commit db8899b
Showing 1 changed file with 84 additions and 1 deletion.
85 changes: 84 additions & 1 deletion source
Expand Up @@ -67004,7 +67004,7 @@ console.log(plasticButton2.getAttribute("is")); // will output "plastic-button"<
is truly one-time will need a guard to prevent it from running twice.</p></li>

<li><p>In general, the constructor should be used to set up initial state and default values, and
to set up event listeners and possibly a shadow root</p>.</li>
to set up event listeners and possibly a shadow root.</p></li>
</ul>

<p>Several of these requirements are checked during <span data-x="create an element">element
Expand Down Expand Up @@ -67229,6 +67229,7 @@ console.log(plasticButton2.getAttribute("is")); // will output "plastic-button"<
<pre class="idl">interface <dfn>CustomElementsRegistry</dfn> {
void <span data-x="dom-CustomElementsRegistry-define">define</span>(DOMString name, Function constructor, optional ElementRegistrationOptions options);
any <span data-x="dom-CustomElementsRegistry-get">get</span>(DOMString name);
[NewObject] Promise&lt;void&gt; <span data-x="dom-CustomElementsRegistry-whenDefined">whenDefined</span>(DOMString name);
};

dictionary <dfn>ElementRegistrationOptions</dfn> {
Expand All @@ -67242,6 +67243,12 @@ dictionary <dfn>ElementRegistrationOptions</dfn> {
data-x="concept-custom-element-definition-local-name">local name</span>, or <span
data-x="concept-custom-element-definition-constructor">constructor</span>.</p>

<p>Every <code>CustomElementsRegistry</code> also has a <dfn>when-defined promise map</dfn>,
mapping <span data-x="valid custom element name">valid custom element names</span> to lists of
promises. It is used to implement the <code
data-x="dom-CustomElementsRegistry-whenDefined">whenDefined()</code> method. Storing a promise in
the <span>when-defined promise map</span> must not create a strong reference to that promise.</p>

<dl class="domintro">
<dt><var>window</var> . <code data-x="dom-window-customElements">customElements</code> . <code
subdfn data-x="dom-CustomElementsRegistry-define">define</code>(<var>name</var>,
Expand All @@ -67267,6 +67274,14 @@ dictionary <dfn>ElementRegistrationOptions</dfn> {
data-x="concept-custom-element-definition-name">name</span>. Returns undefined if there is no
<span>custom element definition</span> with the given <span
data-x="concept-custom-element-definition-name">name</span>.</dd>

<dt><var>window</var> . <code data-x="dom-window-customElements">customElements</code> . <code
subdfn data-x="dom-CustomElementsRegistry-whenDefined">whenDefined</code>(<var>name</var>)</dt>

<dd>Returns a promise that will be fulfilled when a <span>custom element</span> becomes defined
with the given name. (If such a <span>custom element</span> is already defined, the returned
promise will be immediately fulfilled.) Returns a promise rejected with a
<code>SyntaxError</code> if not given a <span>valid custom element name</span>.</dd>
</dl>

<p><dfn>Element definition</dfn> is a process of adding a <span>custom element definition</span>
Expand Down Expand Up @@ -67363,6 +67378,21 @@ dictionary <dfn>ElementRegistrationOptions</dfn> {
<var>attributeChangedCallback</var> (stored by their corresponding name).</p></li>

<li><p>Add <var>definition</var> to this <code>CustomElementsRegistry</code>.</p></li>

<li>
<p>If this <code>CustomElementsRegistry</code>'s <span>when-defined promise map</span>
contains an entry with key <var>name</var>:</p>

<ol>
<li><p>Let <var>promiseList</var> be the value of that entry.</p></li>

<li><p>For each <var>promise</var> in <var>promiseList</var>, resolve <var>promise</var> with
undefined.</p></li>

<li><p>Delete the entry with key <var>name</var> from this
<code>CustomElementsRegistry</code>'s <span>when-defined promise map</span>.</p></li>
</ol>
</li>
</ol>

<p>When invoked, the <dfn><code
Expand All @@ -67377,6 +67407,58 @@ dictionary <dfn>ElementRegistrationOptions</dfn> {
<li><p>Otherwise, return undefined.</p></li>
</ol>

<p>When invoked, the <dfn><code
data-x="dom-CustomElementsRegistry-whenDefined">whenDefined(<var>name</var>)</code></dfn> method
must run these steps:</p>

<ol>
<li><p>If <var>name</var> is not a <span>valid custom element name</span>, then return a new
promise rejected with a <code>SyntaxError</code> exception and abort these steps.</p></li>

<li><p>If this <code>CustomElementsRegistry</code> contains an entry with <span
data-x="concept-custom-element-definition-name">name</span> <var>name</var>, then return a new
promise resolved with undefined and abort these steps.</p></li>

<li><p>Let <var>map</var> be this <code>CustomElementsRegistry</code>'s <span>when-defined
promise map</span>.</p></li>

<li><p>If <var>map</var> does not contain an entry with key <var>name</var>, create an entry in
<var>map</var> with key <var>name</var> and whose value is an empty list.</p></li>

<li><p>Let <var>promiseList</var> be the value of the entry in <var>map</var> with key
<var>name</var>.</p></li>

<li><p>Let <var>promise</var> be a new promise, and append <var>promise</var> to
<var>promiseList</var>.</p></li>

<li><p>Return <var>promise</var>.</p></li>
</ol>

<div class="example">
<p>The <code data-x="dom-CustomElementsRegistry-whenDefined">whenDefined()</code> method can be
used to avoid performing an action until all appropriate <span data-x="custom element">custom
elements</span> are <span data-x="concept-element-defined">defined</span>. In this example, we
combine it with the <code data-x="selector-defined">:defined</code> pseudo-class to hide a
dynamically-loaded article's contents until we're sure that all of the <span data-x="autonomous
custom element">autonomous custom elements</span> it uses are defined.</p>

<pre>articleContainer.hidden = true;

fetch(articleURL)
.then(response => response.text())
.then(text => {
articleContainer.innerHTML = text;

return Promise.all(
[...articleContainer.querySelectorAll(":not(:defined)")]
.map(el => customElements.whenDefined(el.localName))
);
})
.then(() => {
articleContainer.hidden = false;
});</pre>
</div>

<h4><dfn data-x="custom-element-upgrades">Upgrades</dfn></h4>

<p>To <dfn data-x="concept-upgrade-an-element" data-export="">upgrade an element</dfn>, given as
Expand Down Expand Up @@ -119337,6 +119419,7 @@ INSERT INTERFACES HERE
J. King,
Jacob Davies,
Jacques Distler,
Jake Archibald,
Jake Verbaten,
Jakub &#321;opusza&#324;ski,
Jakub Wilk,
Expand Down

0 comments on commit db8899b

Please sign in to comment.