Skip to content

Commit

Permalink
Custom elements: add element internals
Browse files Browse the repository at this point in the history
This provides the ElementInternals interface, which can be obtained for
custom elements via the element.attachInternals() method. For now
ElementInternals is empty, but it will gain members in #4383.

This also adds the ability for custom elements to set the
disabledFeatures static property, to disable element internals and
shadow DOM. Some DOM-side infrastructure work there is necessary in
whatwg/dom#760.

Tests:
- web-platform-tests/wpt#15123
- web-platform-tests/wpt#15516
- web-platform-tests/wpt#16853

Fixes WICG/webcomponents#758.
  • Loading branch information
tkent-google authored and domenic committed May 16, 2019
1 parent 6ba1b38 commit 1d112e1
Showing 1 changed file with 97 additions and 5 deletions.
102 changes: 97 additions & 5 deletions source
Original file line number Diff line number Diff line change
Expand Up @@ -3143,6 +3143,7 @@ a.setAttribute('href', 'https://example.com/'); // change the content attribute
<li><dfn data-x-href="https://dom.spec.whatwg.org/#interface-documenttype"><code>DocumentType</code></dfn> interface</li>
<li><dfn data-x-href="https://dom.spec.whatwg.org/#interface-childnode"><code>ChildNode</code></dfn> interface</li>
<li><dfn data-x-href="https://dom.spec.whatwg.org/#interface-element"><code>Element</code></dfn> interface</li>
<li><dfn data-x="dom-element-attachshadow" data-x-href="https://dom.spec.whatwg.org/#dom-element-attachshadow"><code>attachShadow()</code></dfn> method.</li>
<li><dfn data-x-href="https://dom.spec.whatwg.org/#interface-node"><code>Node</code></dfn> interface</li>
<li><dfn data-x-href="https://dom.spec.whatwg.org/#interface-nodelist"><code>NodeList</code></dfn> interface</li>
<li><dfn data-x-href="https://dom.spec.whatwg.org/#interface-processinginstruction"><code>ProcessingInstruction</code></dfn> interface</li>
Expand Down Expand Up @@ -10180,6 +10181,8 @@ interface <dfn>HTMLElement</dfn> : <span>Element</span> {
[<span>CEReactions</span>] attribute DOMString <span data-x="dom-autocapitalize">autocapitalize</span>;

[<span>CEReactions</span>] attribute [TreatNullAs=EmptyString] DOMString <span data-x="dom-innerText">innerText</span>;

<span>ElementInternals</span> <span data-x="dom-attachInternals">attachInternals</span>();
};

<span>HTMLElement</span> includes <span>GlobalEventHandlers</span>;
Expand Down Expand Up @@ -66726,6 +66729,14 @@ document.body.append(parent);
href="#html-element-constructors">HTML element constructors</a>. Each entry in the list will be
either an element or an <dfn data-x="concept-already-constructed-marker"><i>already
constructed</i> marker</dfn>.</dd>

<dt>A <dfn data-x="concept-custom-element-definition-disable-internals">disable
internals</dfn> boolean</dt>
<dd>Controls <code data-x="dom-attachInternals">attachInternals()</code>.

<dt>A <dfn data-x="concept-custom-element-definition-disable-shadow" data-export=""
data-dfn-for="custom element definition">disable shadow</dfn> boolean</dt>
<dd>Controls <code data-x="dom-element-attachshadow">attachShadow()</code>.
</dl>

<p>To <dfn data-export="">look up a custom element definition</dfn>, given a <var>document</var>,
Expand Down Expand Up @@ -66899,6 +66910,13 @@ dictionary <dfn>ElementDefinitionOptions</dfn> {
<li><p>Set this <code>CustomElementRegistry</code>'s <span>element definition is running</span>
flag.</p></li>

<li><p>Let <var>disableInternals</var> be false.

<li><p>Let <var>disableShadow</var> be false.

<li><p>Let <var>observedAttributes</var> be an empty <code
data-x="">sequence&lt;DOMString></code>.</p></li>

<li>
<p>Run the following substeps while catching any exceptions:</p>

Expand Down Expand Up @@ -66930,9 +66948,6 @@ dictionary <dfn>ElementDefinitionOptions</dfn> {
</ol>
</li>

<li><p>Let <var>observedAttributes</var> be an empty <code
data-x="">sequence&lt;DOMString></code>.</p></li>

<li>
<p>If the value of the entry in <var>lifecycleCallbacks</var> with key "<code
data-x="">attributeChangedCallback</code>" is not null, then:</p>
Expand All @@ -66948,6 +66963,24 @@ dictionary <dfn>ElementDefinitionOptions</dfn> {
<code data-x="">sequence&lt;DOMString></code>. Rethrow any exceptions from the
conversion.</p></li>
</ol>

<li><p>Let <var>disabledFeatures</var> be an empty <code
data-x="">sequence&lt;DOMString></code>.</p></li>

<li><p>Let <var>disabledFeaturesIterable</var> be <span
data-x="js-Get">Get</span>(<var>constructor</var>, "disabledFeatures"). Rethrow any
exceptions.</p></li>

<li><p>If <var>disabledFeaturesIterable</var> is not undefined, then set
<var>disabledFeatures</var> to the result of <span
data-x="concept-idl-convert">converting</span> <var>disabledFeaturesIterable</var> to a <code
data-x="">sequence&lt;DOMString></code>. Rethrow any exceptions from the conversion.</p></li>

<li><p>Set <var>disableInternals</var> to true if <var>disabledFeaturesSequence</var>
<span data-x="list contains">contains</span> "<code data-x="">internals</code>".</p></li>

<li><p>Set <var>disableShadow</var> to true if <var>disabledFeaturesSequence</var>
<span data-x="list contains">contains</span> "<code data-x="">shadow</code>".</p></li>
</ol>

<p>Then, perform the following substep, regardless of whether the above steps threw an exception
Expand All @@ -66968,9 +67001,13 @@ dictionary <dfn>ElementDefinitionOptions</dfn> {
<span data-x="concept-custom-element-definition-constructor">constructor</span>
<var>constructor</var>, <span
data-x="concept-custom-element-definition-observed-attributes">observed attributes</span>
<var>observedAttributes</var>, and <span
<var>observedAttributes</var>, <span
data-x="concept-custom-element-definition-lifecycle-callbacks">lifecycle callbacks</span>
<var>lifecycleCallbacks</var>.</p></li>
<var>lifecycleCallbacks</var>, <span
data-x="concept-custom-element-definition-disable-internals">disable internals</span>
<var>disableInternals</var>, and <span
data-x="concept-custom-element-definition-disable-shadow">disable shadow</span>
<var>disableShadow</var>.</p></li>

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

Expand Down Expand Up @@ -67543,6 +67580,61 @@ customElements.define("x-foo", class extends HTMLElement {

</div>

<h4>The <code>ElementInternals</code> interface</h4>

<dl class="domintro">
<dt><var>element</var> . <code subdfn data-x="dom-attachInternals">attachInternals()</code></dt>

<dd><p>Returns an <code>ElementInternals</code> object targeting the <span>custom element</span>
<var>element</var>. Throws an exception if <var>element</var> is not a <span>custom
element</span>, if the "<code data-x="">internals</code>" feature was disabled as part of the
element definition, or if it is called twice on the same element.</p></dd>
</dl>

<pre><code class="idl" data-x="">[Exposed=Window]
interface <dfn>ElementInternals</dfn> {
<!-- We'll add some stuff here -->
};</code></pre>

<!-- We should have a domintro block for ElementInternals -->

<p>Each <code>ElementInternals</code> has a <dfn data-x="internals-target">target element</dfn>,
which is a <span>custom element</span>. <code>ElementInternals</code> provides various operations
and attributes to allow control over internal features which the user agent provides to all
elements.</p>

<p>Each <code>HTMLElement</code> has an <dfn>attached internals</dfn> boolean, initially
false.</p>

<p>The <dfn><code data-x="dom-attachInternals">attachInternals()</code></dfn> method on
an <code>HTMLElement</code> <var>element</var>, when invoked, must run the following steps:</p>

<ol>
<!-- We could lift this restriction in the future. -->
<li><p>If <var>element</var>'s <span data-x="concept-element-is-value"><code
data-x="">is</code> value</span> is not null, then throw a
<span>"<code>NotSupportedError</code>"</span> <code>DOMException</code>.</p></li>

<li><p>Let <var>definition</var> be the result of <span
data-x="look up a custom element definition">looking up a custom element definition</span> given
<var>element</var>'s <span>node document</span>, its namespace, its local name, and null as
<span data-x="concept-element-is-value"><code data-x="">is</code> value</span>.</p></li>

<li><p>If <var>definition</var> is null, then throw an
<span>"<code>NotSupportedError</code>"</span> <code>DOMException</code>.</p></li>

<li><p>If <var>definition</var>'s <span
data-x="concept-custom-element-definition-disable-internals">disable internals</span> is true,
then throw a <span>"<code>NotSupportedError</code>"</span> <code>DOMException</code>.</p></li>

<li><p>If <var>element</var>'s <span>attached internals</span> is true, then throw an
<span>"<code>NotSupportedError</code>"</span> <code>DOMException</code>.</p></li>

<li><p>Set <var>element</var>'s <span>attached internals</span> to true.</p></li>

<li><p>Create a new <code>ElementInternals</code> instance
<span data-x="internals-target">targeting</span> <var>element</var>, and return it.</p></li>
</ol>

<h3 split-filename="semantics-other" id="common-idioms">Common idioms without dedicated elements</h3>

Expand Down

0 comments on commit 1d112e1

Please sign in to comment.