Skip to content

Commit

Permalink
Add logic for reflecting IDREF attributes
Browse files Browse the repository at this point in the history
This defines IDL reflection for single and FrozenArray attributes.
This work was done mostly by @alice.

This is just a rebase of the following PR:
whatwg#3917
  • Loading branch information
mrego committed May 16, 2022
1 parent 2f901a7 commit 9a82d67
Showing 1 changed file with 269 additions and 1 deletion.
270 changes: 269 additions & 1 deletion source
Original file line number Diff line number Diff line change
Expand Up @@ -2714,6 +2714,7 @@ a.setAttribute('href', 'https://example.com/'); // change the content attribute
<li><dfn data-x-href="https://webidl.spec.whatwg.org/#include">include</dfn></li>
<li><dfn data-x-href="https://webidl.spec.whatwg.org/#dfn-inherit">inherit</dfn></li>
<li><dfn data-x-href="https://webidl.spec.whatwg.org/#dfn-interface-prototype-object">interface prototype object</dfn></li>
<li><dfn data-x-href="https://webidl.spec.whatwg.org/#implements">implements</dfn></li>
<li><dfn data-x-href="https://webidl.spec.whatwg.org/#es-platform-objects">[[Realm]] field of a platform object</dfn></li>
<li><dfn data-x-href="https://webidl.spec.whatwg.org/#dfn-callback-context">callback context</dfn></li>
<li><dfn data-x-href="https://webidl.spec.whatwg.org/#dfn-frozen-array-type">frozen array</dfn> and
Expand Down Expand Up @@ -3052,6 +3053,7 @@ a.setAttribute('href', 'https://example.com/'); // change the content attribute
<li>The <dfn data-x-href="https://dom.spec.whatwg.org/#concept-tree-root">root</dfn> and <dfn data-x-href="https://dom.spec.whatwg.org/#concept-shadow-including-root">shadow-including root</dfn> concepts</li>
<li>The <dfn data-x-href="https://dom.spec.whatwg.org/#concept-tree-inclusive-ancestor">inclusive ancestor</dfn>,
<dfn data-x-href="https://dom.spec.whatwg.org/#concept-tree-descendant">descendant</dfn>,
<dfn data-x="concept-shadow-including-ancestor" data-x-href="https://dom.spec.whatwg.org/#concept-shadow-including-ancestor">shadow-including ancestor</dfn>,
<dfn data-x-href="https://dom.spec.whatwg.org/#concept-shadow-including-descendant">shadow-including descendant</dfn>,
<dfn data-x-href="https://dom.spec.whatwg.org/#concept-shadow-including-inclusive-descendant">shadow-including inclusive descendant</dfn>, and
<dfn data-x-href="https://dom.spec.whatwg.org/#concept-shadow-including-inclusive-ancestor">shadow-including inclusive ancestor</dfn> concepts</li>
Expand Down Expand Up @@ -7566,8 +7568,274 @@ a.setAttribute('href', 'https://example.com/'); // change the content attribute
return a <code>DOMTokenList</code> object whose associated element is the element in question and
whose associated attribute's local name is the name of the attribute in question.</p>

</div>
<p>If a reflecting IDL attribute <var>attr</var> has the type <code
data-x=""><var>T</var>?</code>, where <var>T</var> is either <code>Element</code> or an
interface that inherits from <code>Element</code>, then:

<ul>
<li><p>Elements of the type this IDL attribute appears on have an <dfn>explicitly set
<var>attr</var>-element</dfn>, which is an element or null. It is initially null.</p></li>

<li>
<p>Elements of the type this IDL attribute appears on have an <dfn data-export=""><var>attr</var>-associated
element</dfn>. To compute the <span><var>attr</var>-associated element</span> for such an
element <var>element</var>:</p>

<ol>
<li>
<p>If <var>element</var>'s <span>explicitly set <var>attr</var>-element</span> is not null:</p>
<ul>
<li><p>If <var>element</var>'s <span>explicitly set <var>attr</var>-element</span> is a
<span>descendant</span> of any of <var>element</var>'s <span
data-x="concept-shadow-including-ancestor">shadow-including ancestors</span>, then return
<var>element</var>'s <span>explicitly set <var>attr</var>-element</span>.</p></li>
<li><p>Otherwise, return null.</p></li>
</ul>
</li>

<li>
<p>Otherwise, if the content attribute is present on <var>element</var>, then return the first
element <var>candidate</var>, in <span>tree order</span>, that meets the following
criteria:</p>

<ul class="brief">
<li><var>candidate</var>'s <span>root</span> is the same as <var>element</var>'s
<span>root</span>,</li>
<li><var>candidate</var>'s <span data-x="concept-ID">ID</span> is the value of the content
attribute, and</li>
<li><var>candidate</var> <span>implements</span> <var>T</var>.</li>
</ul>

<p>If no such element exists, then return null.</p>
</li>

<li><p>Return null.</p></li>
</ol>

<p class="note">Other parts of this specification, or other specifications using attribute
reflection, are generally expected to consult the <span><var>attr</var>-associated
element</span>. The <span>explicitly set <var>attr</var>-element</span> is an internal
implementation detail of the <span><var>attr</var>-associated element</span>, and is not to be
used directly.</p>
</li>

<li><p>On getting, the IDL attribute must return this element's <span><var>attr</var>-associated
element</span>.</p></li>

<li>
<p>On setting, the IDL attribute must perform the following steps:</p>
<ol>
<li><p>Let <var>id</var> be the empty string.</p></li>

<li><p>If the given value:</p>
<ul class="brief">
<li>has the same <span>root</span> as this element, and</li>
<li>has an <code data-x="attr-id">id</code> attribute, and</li>
<li>is the first element in this element's <span>node tree</span> whose <span
data-x="concept-ID">ID</span> is the value of that <code data-x="attr-id">id</code>
attribute,</li>
</ul>
<p>then set <var>id</var> to the given value's <span data-x="concept-ID">ID</span>.</p>

<li><p>Set the content attribute's value for this element to <var>id</var>.</p></li>

<li><p>Set this element's <span>explicitly set <var>attr</var>-element</span> to the given
value.</p></li>
</ol>
</li>

<li>
<p>The following <span data-x="concept-element-attributes-change-ext">attribute change
steps</span> are used to synchronize between the content attribute and the IDL attribute:</p>
<ol>
<li><p>If <var>localName</var> is not the content attribute's local name, or
<var>namespace</var> is not null, then return.</p></li>

<li><p>Set <var>element</var>'s <span>explicitly set <var>attr</var>-element</span> to
null.</p></li>
</ol>
</li>
</ul>

<p>If a reflecting IDL attribute <var>attr</var> has the type <code
data-x="">FrozenArray&lt;<var>T</var>&gt;?</code>, where <var>T</var> is either
<code>Element</code> or an interface that inherits from <code>Element</code>, then:</p>

<ul>
<li><p>Elements of the type this IDL attribute appears on have <dfn>explicitly set
<var>attr</var>-elements</dfn>, which is either a <span>list</span> of elements or null. It is
initially null.</p></li>

<li><p>Elements of the type this IDL attribute appears on have <dfn>cached
<var>attr</var>-associated elements</dfn>, which is a <code
data-x="">FrozenArray&lt;<code>Element</code>&gt;?</code>. It is initially null.</p></li>

<li>
<p>Elements of the type this IDL attribute appears on have <dfn
data-export=""><var>attr</var>-associated elements</dfn>. To compute the
<span><var>attr</var>-associated elements</span> for such an element <var>element</var>:</p>

<ol>
<li><p>Let <var>elements</var> be an empty <span>list</span>.</p></li>

<li>
<p>If <var>element</var>'s <span>explicitly set <var>attr</var>-elements</span> is not
null, then:</p>
<ol>
<li>
<p><span data-x="list iterate">For each</span> <var>attrElement</var> in the <var>element</var>'s
<span>explicitly set <var>attr</var>-elements</span>:</p>
<ol>
<li><p>If <var>attrElement</var> is not a <span>descendant</span> of any of <var>element</var>'s <span
data-x="concept-shadow-including-ancestor">shadow-including ancestors</span>, then
<span>continue</span>.</p></li>
<li><p>Add <var>attrElement</var> to <var>elements</var>.</p></li>
</ol>
</li>
</ol>
</li>
<li>
<p>Otherwise:</p>
<ol>
<li><p>If the content attribute is not present on <var>element</var>, return null.</p></li>

<li><p>Let <var>tokens</var> be the content attribute's value, <span data-x="split a string on
ASCII whitespace">split on ASCII whitespace</span>.

<li>
<p><span data-x="list iterate">For each</span> <var>id</var> in <var>tokens</var>:</p>
<ol>
<li>
<p>Let <var>candidate</var> be the first element, in <span>tree order</span>, that meets the
following criteria:</p>

<ul class="brief">
<li><var>candidate</var>'s <span>root</span> is the same as <var>element</var>'s
<span>root</span>,</li>
<li><var>candidate</var>'s <span data-x="concept-ID">ID</span> is <var>id</var>, and</li>
<li><var>candidate</var> <span>implements</span> <var>T</var>.</li>
</ul>

<p>If no such element exists, then <span>continue</span>.</p>
</li>

<li><p><span data-x="list append">Append</span> <var>candidate</var> to
<var>elements</var>.</p></li>
</ol>
</li>
</ol>
</li>

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

<li>
<p class="note">Other parts of this specification, or other specifications using attribute
reflection, are generally expected to consult the <span><var>attr</var>-associated
elements</span>. The <span>explicitly set <var>attr</var>-elements</span> are an internal
implementation detail of the <span><var>attr</var>-associated elements</span>, and are not to be
used directly. Similarly, the <span>cached <var>attr</var>-associated elements</span> are an
internal implementation detail of the IDL attribute's getter.</p>
</li>

<li>
<p>On getting, the IDL attribute must perform the following steps:</p>

<ol>
<li><p>Let <var>elements</var> be this element's <span><var>attr</var>-associated
elements</span>.</p></li>

<li><p>If the contents of <var>elements</var> is equal to the contents of this element's
<span>cached <var>attr</var>-associated elements</span>, then return this element's
<span>cached <var>attr</var>-associated elements</span>.</p></li>

<li><p>Let <var>elementsAsFrozenArray</var> be <var>elements</var>, <span
data-x="concept-idl-convert">converted</span> to a <code
data-x="">FrozenArray&lt;<var>T</var>&gt;?</code>.</p></li>

<li><p>Set this element's <span>cached <var>attr</var>-associated elements</span> to
<var>elementsAsFrozenArray</var>.</p></li>

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

<p class="note">This extra caching layer is necessary to preserve the invariant that <code
data-x="">element.reflectedElements === element.reflectedElements</code>.</p>
</li>

<li>
<p>On setting, the IDL attribute must perform the following steps:</p>
<ol>
<li>
<p>If the given value is null:</p>
<ol>
<li><p>Set this element's <span>explicitly set <var>attr</var>-elements</span> to
null.</p></li>

<li><p>Remove the content attribute from this element.</p></li>

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

<li><p>Let <var>value</var> be an empty string.</p></li>

<li>
<p><span data-x="list iterate">For each</span> <var>element</var> in the given value:</p>
<ol>
<li><p>If <var>value</var> is empty and <var>elements</var> is non-empty, then <span
data-x="list append">append</span> <var>element</var> to <var>elements</var> and
<span>continue</span>.</p></li>

<li><p><span data-x="list append">Append</span> <var>element</var> to
<var>elements</var>.</p></li>

<li>
<p>If <var>element</var>:</p>

<ul class="brief">
<li>does not have the same <span>root</span> as this element, or</li>
<li>has no <code data-x="attr-id">id</code> attribute, or</li>
<li>is not the first element in this element's <span>node tree</span> whose <span
data-x="concept-ID">ID</span> is the value of that <code data-x="attr-id">id</code>
attribute,</li>
</ul>

<p>then set <var>value</var> to the empty string, and <span>continue</span>.</p>
</li>

<li><p>Let <var>id</var> be <var>element</var>'s <span
data-x="concept-ID">ID</span>.</p></li>

<li><p>If <var>value</var> is not the empty string, then append U+0020 SPACE to
<var>value</var>.</p></li>

<li><p>Append <var>id</var> to <var>value</var>.</p></li>
</ol>
</li>

<li><p>Set the content attribute's value for this element to <var>value</var>.</p></li>

<li><p>Set this element's <span>explicitly set <var>attr</var>-elements</span> to
<var>elements</var>.</p></li>
</ol>
</li>

<li>
<p>The following <span data-x="concept-element-attributes-change-ext">attribute change
steps</span> are used to synchronize between the content attribute and the IDL attribute:</p>
<ol>
<li><p>If <var>localName</var> is not the content attribute's local name, or
<var>namespace</var> is not null, then return.</p></li>

<li><p>Set <var>element</var>'s <span>explicitly set <var>attr</var>-elements</span> to
null.</p></li>
</ol>
</li>
</ul>

</div>

<h4>Collections</h4>

Expand Down

0 comments on commit 9a82d67

Please sign in to comment.