Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Specify outerText #6653

Merged
merged 5 commits into from
May 7, 2021
Merged
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
143 changes: 103 additions & 40 deletions source
Original file line number Diff line number Diff line change
Expand Up @@ -2691,6 +2691,7 @@ a.setAttribute('href', 'https://example.com/'); // change the content attribute
<li><dfn data-x-href="https://heycam.github.io/webidl/#indexsizeerror">"<code>IndexSizeError</code>"</dfn></li>
<li><dfn data-x-href="https://heycam.github.io/webidl/#hierarchyrequesterror">"<code>HierarchyRequestError</code>"</dfn></li>
<li><dfn data-x-href="https://heycam.github.io/webidl/#invalidcharactererror">"<code>InvalidCharacterError</code>"</dfn></li>
<li><dfn data-x-href="https://heycam.github.io/webidl/#nomodificationallowederror">"<code>NoModificationAllowedError</code>"</dfn></li>
<li><dfn data-x-href="https://heycam.github.io/webidl/#notfounderror">"<code>NotFoundError</code>"</dfn></li>
<li><dfn data-x-href="https://heycam.github.io/webidl/#notsupportederror">"<code>NotSupportedError</code>"</dfn></li>
<li><dfn data-x-href="https://heycam.github.io/webidl/#invalidstateerror">"<code>InvalidStateError</code>"</dfn></li>
Expand Down Expand Up @@ -2960,7 +2961,9 @@ a.setAttribute('href', 'https://example.com/'); // change the content attribute
<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>
<li>The <dfn data-x-href="https://dom.spec.whatwg.org/#concept-tree-first-child">first child</dfn> and <dfn data-x-href="https://dom.spec.whatwg.org/#concept-tree-next-sibling">next sibling</dfn> concepts</li>
<li>The <dfn data-x-href="https://dom.spec.whatwg.org/#concept-tree-first-child">first child</dfn>,
<dfn data-x-href="https://dom.spec.whatwg.org/#concept-tree-next-sibling">next sibling</dfn>, and
<dfn data-x-href="https://dom.spec.whatwg.org/#concept-tree-previous-sibling">previous sibling</dfn> concepts</li>
<li>The <dfn data-x-href="https://dom.spec.whatwg.org/#document-element">document element</dfn> concept</li>
<li>The <dfn data-x-href="https://dom.spec.whatwg.org/#in-a-document-tree">in a document tree</dfn>, <dfn data-x-href="https://dom.spec.whatwg.org/#in-a-document">in a document</dfn> (legacy), and <dfn data-x-href="https://dom.spec.whatwg.org/#connected">connected</dfn> concepts</li>
<li>The <dfn data-x="concept-slot" data-x-href="https://dom.spec.whatwg.org/#concept-slot">slot</dfn> concept, and its <dfn data-x="slot-name" data-x-href="https://dom.spec.whatwg.org/#slot-name">name</dfn> and <dfn data-x-href="https://dom.spec.whatwg.org/#slot-assigned-nodes">assigned nodes</dfn></li>
Expand All @@ -2981,7 +2984,8 @@ a.setAttribute('href', 'https://example.com/'); // change the content attribute
<li>The <dfn data-x="concept-element-attributes-change" data-x-href="https://dom.spec.whatwg.org/#concept-element-attributes-change">change</dfn>, <dfn data-x="concept-element-attributes-append" data-x-href="https://dom.spec.whatwg.org/#concept-element-attributes-append">append</dfn>, <dfn data-x="concept-element-attributes-remove" data-x-href="https://dom.spec.whatwg.org/#concept-element-attributes-remove">remove</dfn>, <dfn data-x="concept-element-attributes-replace" data-x-href="https://dom.spec.whatwg.org/#concept-element-attributes-replace">replace</dfn>, and <dfn data-x="concept-element-attributes-set-value" data-x-href="https://dom.spec.whatwg.org/#concept-element-attributes-set-value">set value</dfn> algorithms for attributes</li>
<li>The <dfn data-x="concept-element-attributes-change-ext" data-x-href="https://dom.spec.whatwg.org/#concept-element-attributes-change-ext">attribute change steps</dfn> hook for attributes</li>
<li>The <dfn data-x-href="https://dom.spec.whatwg.org/#concept-element-attribute">attribute list</dfn> concept</li>
<li>The <dfn data-x="concept-cd-data" data-x-href="https://dom.spec.whatwg.org/#concept-cd-data">data</dfn> of a text node</li>
<li>The <dfn data-x="concept-cd-data" data-x-href="https://dom.spec.whatwg.org/#concept-cd-data">data</dfn> of a text node and its
<dfn data-x-href="https://dom.spec.whatwg.org/#concept-cd-replace">replace data</dfn> algorithm</li>
<li>The <dfn data-x-href="https://dom.spec.whatwg.org/#concept-child-text-content">child text content</dfn> of a node</li>
<li>The <dfn data-x-href="https://dom.spec.whatwg.org/#concept-descendant-text-content">descendant text content</dfn> of a node</li>
<li><dfn data-x-href="https://dom.spec.whatwg.org/#interface-event"><code>Event</code></dfn> interface</li>
Expand Down Expand Up @@ -10173,6 +10177,7 @@ interface <dfn>HTMLElement</dfn> : <span>Element</span> {
[<span>CEReactions</span>] attribute DOMString <span data-x="dom-autocapitalize">autocapitalize</span>;

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

<span>ElementInternals</span> <span data-x="dom-attachInternals">attachInternals</span>();
};
Expand Down Expand Up @@ -12570,8 +12575,8 @@ interface <dfn>DOMStringMap</dfn> {
</div>


<h4 id="the-innertext-idl-attribute">The <code data-x="dom-innerText">innerText</code> getter and
setter</h4>
<h4 id="the-innertext-idl-attribute">The <code data-x="dom-innerText">innerText</code> and <code
data-x="dom-outerText">outerText</code> properties</h4>
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not getters and setters?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It was getting too long so I thought this'd be nicer.


<dl class="domintro">
<dt><var>element</var> . <code subdfn data-x="dom-innerText">innerText</code> [ = <var>value</var> ]</dt>
Expand All @@ -12580,17 +12585,32 @@ interface <dfn>DOMStringMap</dfn> {

<p>Can be set, to replace the element's children with the given value, but with line breaks
converted to <code>br</code> elements.</p>
</dd>

<dt><var>element</var> . <code subdfn data-x="dom-outerText">outerText</code> [ = <var>value</var> ]</dt>
<dd>
<p>Returns the element's text content "as rendered".</p>

<p>Can be set, to replace the element with the given value, but with line breaks converted to
<code>br</code> elements.</p>
</dd>
</dl>

<div w-nodev>

<p>The <dfn attribute for="HTMLElement"><code data-x="dom-innerText">innerText</code></dfn> getter
steps are:</p>
steps are to return the <span>rendered text</span> of <span>this</span>.</p>

<p>The <dfn attribute for="HTMLElement"><code data-x="dom-outerText">outerText</code></dfn> getter
steps are to return the <span>rendered text</span> of <span>this</span>.</p>
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Optional: one thing we could do to make it even clearer they are identical is write this as

The innerText and outerText getter steps are to ...


<p>The <dfn>rendered text</dfn> of an <code>HTMLElement</code> <var>element</var> is the result
domenic marked this conversation as resolved.
Show resolved Hide resolved
of running the following steps:</p>

<ol>
<li>
<p>If <span>this</span> is not <span>being rendered</span> or if the user agent is a non-CSS
user agent, then return <span>this</span>'s <span>descendant text content</span>.</p>
<p>If <var>element</var> is not <span>being rendered</span> or if the user agent is a non-CSS
user agent, then return <var>element</var>'s <span>descendant text content</span>.</p>

<p class="note">This step can produce surprising results, as when the <code
data-x="dom-innerText">innerText</code> getter is invoked on an element not <span>being
Expand All @@ -12602,12 +12622,13 @@ interface <dfn>DOMStringMap</dfn> {
<li><p>Let <var>results</var> be a new empty <span>list</span>.</p></li>

<li>
<p>For each child node <var>node</var> of <span>this</span>:</p>
<p>For each child node <var>node</var> of <var>element</var>:</p>

<ol>
<li><p>Let <var>current</var> be the <span>list</span> resulting in running the <span>inner
text collection steps</span> with <var>node</var>. Each item in <var>results</var> will either
be a <span>string</span> or a positive integer (a <i>required line break count</i>).</p>
<li><p>Let <var>current</var> be the <span>list</span> resulting in running the
<span>rendered text collection steps</span> with <var>node</var>. Each item in
<var>results</var> will either be a <span>string</span> or a positive integer (a <i>required
line break count</i>).</p>

<p class="note">Intuitively, a <i>required line break count</i> item means that a certain
number of line breaks appear at that point, but they can be collapsed with the line breaks
Expand All @@ -12632,13 +12653,13 @@ interface <dfn>DOMStringMap</dfn> {
<li><p>Return the concatenation of the string items in <var>results</var>.</p></li>
</ol>

<p>The <dfn>inner text collection steps</dfn>, given a <span>node</span> <var>node</var>, are
as follows:</p>
<p>The <dfn>rendered text collection steps</dfn>, given a <span>node</span> <var>node</var>,
are as follows:</p>

<ol>
<li><p>Let <var>items</var> be the result of running the <span>inner text collection steps</span>
with each child node of <var>node</var> in <span>tree order</span>, and then concatenating
the results to a single <span>list</span>.</p></li>
<li><p>Let <var>items</var> be the result of running the <span>rendered text collection
steps</span> with each child node of <var>node</var> in <span>tree order</span>, and then
concatenating the results to a single <span>list</span>.</p></li>

<li><p>If <var>node</var>'s <span>computed value</span> of <span>'visibility'</span> is not
'visible', then return <var>items</var>.</p></li>
Expand Down Expand Up @@ -12716,28 +12737,58 @@ interface <dfn>DOMStringMap</dfn> {
stringifier and maybe expose it directly on <span data-x="concept-range">ranges</span>. See <a
href="https://www.w3.org/Bugs/Public/show_bug.cgi?id=10583">Bugzilla bug 10583</a>.</p>

<hr>

<p>The <code data-x="dom-innerText">innerText</code> setter steps are:</p>

<ol>
<li><p>Let <var>document</var> be <span>this</span>'s <span>node document</span>.</p></li>
<li><p>Let <var>fragment</var> be the <span>rendered text fragment</span> for the given value
given <span>this</span>'s <span>node document</span>.</p></li>

<li><p><span data-x="concept-node-replace-all">Replace all</span> with <var>fragment</var> within
<span>this</span>.</p></li>
</ol>

<p>The <code data-x="dom-outerText">outerText</code> setter steps are:</p>

<ol>
<li><p>If <span>this</span>'s parent is null, then throw a
<span>"<code>NoModificationAllowedError</code>"</span> <code>DOMException</code>.</p></li>

<li><p>Let <var>next</var> be <span>this</span>'s <span>next sibling</span>.</p></li>

<li><p>Let <var>previous</var> be <span>this</span>'s <span>previous sibling</span>.</p></li>

<li><p>Let <var>fragment</var> be a new <code>DocumentFragment</code> object whose <span>node
document</span> is <var>document</var>.</p></li>
<li><p>Let <var>fragment</var> be the <span>rendered text fragment</span> for the given value
given <span>this</span>'s <span>node document</span>.</p></li>
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Both Chromium and WebKit have a check after this point to see if the parent has disappeared due to mutation events. However I don't see how that'd be possible; no mutation events can fire due to the fragment creation, I am pretty sure. I'll see if any tests show that I'm wrong...

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I couldn't find any tests in Chromium's corpus that tried to trigger the corresponding if statement.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've confirmed that not only could I not find them, they do not exist, according to our code coverage metrics. I' m not sure how much time I really want to devote to this, but I think the right thing to do would be to omit such a check from the spec, and have Chromium convert the check into an assert or use counter and see if it triggers anywhere in the wild.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As discussed, I've added a NOTREACHED to that branch, and I'll wait a few milestones to see if it ever gets triggered (by fuzzers or tests or whatever).


<li><p>Let <var>input</var> be the given value.</p></li>
<li><p><span data-x="concept-node-replace">Replace</span> <span>this</span> with
<var>fragment</var> within <span>this</span>'s parent.</p></li>

<li><p>Let <var>position</var> be a pointer into <var>input</var>, initially pointing at the start
of the string.</p></li>
<li><p>If <var>next</var> is non-null and <var>next</var>'s <span>previous sibling</span> is a
<code>Text</code> node, then <span>merge with the next text node</span> given <var>next</var>'s
<span>previous sibling</span>.</p></li>
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The previous sibling here could basically be anything at this point, if we're accounting for mutation events. But I guess this is how it works?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, we bail out if previous sibling (or previous sibling's next sibling) is not a Text node.


<li><p>If <var>previous</var> is a <code>Text</code> node, then <span>merge with the next text
node</span> given <var>previous</var>.</p></li>
</ol>

<p>The <dfn>rendered text fragment</dfn> for a string <var>input</var> given a
<code>Document</code> <var>document</var> is the result of running the following steps:</p>

<ol>
<li><p>Let <var>position</var> be a <span>position variable</span> for <var>input</var>,
initially pointing at the start of <var>input</var>.</p></li>

<li><p>Let <var>text</var> be the empty string.</p></li>

<li>
<p>While <var>position</var> is not past the end of <var>input</var>:</p>

<ol>
<li><p><span>Collect a sequence of code points</span> that are not U+000A LINE FEED (LF) or
U+000D CARRIAGE RETURN (CR) characters from <var>input</var> given <var>position</var>. Set
<var>text</var> to the collected characters.</p></li>
<li><p><span>Collect a sequence of code points</span> that are not U+000A (LF) or U+000D (CR)
from <var>input</var> given <var>position</var>, and set <var>text</var> to the
domenic marked this conversation as resolved.
Show resolved Hide resolved
result.</p></li>

<li><p>If <var>text</var> is not the empty string, then <span
data-x="concept-node-append">append</span> a new <code>Text</code> node whose <span
Expand All @@ -12746,26 +12797,42 @@ interface <dfn>DOMStringMap</dfn> {

<li>
<p>While <var>position</var> is not past the end of <var>input</var>, and the character at
<var>position</var> is either a U+000A LINE FEED (LF) or U+000D CARRIAGE RETURN (CR)
character:</p>
<var>position</var> is either a U+000A (LF) or U+000D (CR) character:</p>

<ol>
<li><p>If the character at <var>position</var> is a U+000D CARRIAGE RETURN (CR) character and
the next character is a U+000A LINE FEED (LF) character, then advance <var>position</var> to
the next character in <var>input</var>.</p></li>
<li><p>If the code point at <var>position</var> is U+000D (CR) and the next code point is
U+000A (LF), then advance <var>position</var> to the next code point in
<var>input</var>.</p></li>

<li><p>Advance <var>position</var> to the next character in <var>input</var>.</p></li>
<li><p>Advance <var>position</var> to the next code point in <var>input</var>.</p></li>

<li><p><span data-x="concept-node-append">Append</span> the result of <span
data-x="create an element">creating an element</span> given <var>document</var>,
<code>br</code>, and the <span>HTML namespace</span> to <var>fragment</var>.</p></li>
<li><p><span data-x="concept-node-append">Append</span> the result of <span data-x="create an
element">creating an element</span> given <var>document</var>, <code>br</code>, and the
<span>HTML namespace</span> to <var>fragment</var>.</p></li>
</ol>
</li>
</ol>
</li>
</ol>

<li><p><span data-x="concept-node-replace-all">Replace all</span> with <var>fragment</var> within
<span>this</span>.</p></li>
<p>To <dfn>merge with the next text node</dfn> given a <code>Text</code> node <var>node</var>:</p>

<ol>
<li><p>Let <var>next</var> be <var>node</var>'s <span>next sibling</span>.</p></li>

<li><p>If <var>next</var> is not a <code>Text</code> node, then return.</p></li>

<li><p><span>Replace data</span> with <var>node</var>, <var>node</var>'s <span
data-x="concept-cd-data">data</span>'s <span>length</span>, 0, and <var>next</var>'s <span
data-x="concept-cd-data">data</span>.</p></li>

<li>
<p>If <var>next</var>'s parent is non-null, then <span
data-x="concept-node-remove">remove</span> <var>next</var>.</p>

<p class="note">The parent check is necessary as the previous step might have triggered mutation
events.</p>
</li>
</ol>

</div>
Expand Down Expand Up @@ -68205,14 +68272,10 @@ customElements.define("x-foo", class extends HTMLElement {
known to fall into this category:</p>

<ul>
<li><p><code>HTMLElement</code>'s <code data-x="">outerText</code> IDL attribute</p></li>

<li><p><code>HTMLInputElement</code>'s <code data-x="">webkitdirectory</code> and <code
data-x="">incremental</code> IDL attributes</p></li>

<li><p><code>HTMLLinkElement</code>'s <code data-x="">scope</code> IDL attribute</p></li>

<li><p><code>ShadowRoot</code>'s <code data-x="">innerHTML</code> IDL attribute</p></li>
</ul>
</div>

Expand Down