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 all 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
149 changes: 103 additions & 46 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,12 +12585,22 @@ 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>
<p>The <dfn attribute for="HTMLElement"><code data-x="dom-innerText">innerText</code></dfn> and
<dfn attribute for="HTMLElement"><code data-x="dom-outerText">outerText</code></dfn> getter steps
are:</p>

<ol>
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 ...

<li>
Expand All @@ -12605,9 +12620,10 @@ interface <dfn>DOMStringMap</dfn> {
<p>For each child node <var>node</var> of <span>this</span>:</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 @@ -12626,19 +12642,19 @@ interface <dfn>DOMStringMap</dfn> {
count</i> items at the start or end of <var>results</var>.</p></li>

<li><p><span data-x="list replace">Replace</span> each remaining run of consecutive <i>required
line break count</i> items with a string consisting of as many U+000A LINE FEED (LF) characters
as the maximum of the values in the <i>required line break count</i> items.</p></li>
line break count</i> items with a string consisting of as many U+000A LF code points as the
maximum of the values in the <i>required line break count</i> items.</p></li>

<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 @@ -12675,20 +12691,20 @@ interface <dfn>DOMStringMap</dfn> {
spec=CSSTEXT></p></li>

<li><p>If <var>node</var> is a <code>br</code> element, then <span data-x="list
append">append</span> a string containing a single U+000A LINE FEED (LF) character to
append">append</span> a string containing a single U+000A LF code point to
<var>items</var>.</p></li>

<li><p>If <var>node</var>'s <span>computed value</span> of <span>'display'</span> is
<span>'table-cell'</span>, and <var>node</var>'s <span>CSS box</span> is not the last
<span>'table-cell'</span> box of its enclosing <span>'table-row'</span> box, then <span
data-x="list append">append</span> a string containing a single U+0009 CHARACTER TABULATION (tab)
character to <var>items</var>.</p></li>
data-x="list append">append</span> a string containing a single U+0009 TAB code point to
<var>items</var>.</p></li>

<li><p>If <var>node</var>'s <span>computed value</span> of <span>'display'</span> is
<span>'table-row'</span>, and <var>node</var>'s <span>CSS box</span> is not the last
<span>'table-row'</span> box of the nearest ancestor <span>'table'</span> box, then <span
data-x="list append">append</span> a string containing a single U+000A LINE FEED (LF) character
to <var>items</var>.</p></li>
data-x="list append">append</span> a string containing a single U+000A LF code point to
<var>items</var>.</p></li>

<li><p>If <var>node</var> is a <code>p</code> element, then <span data-x="list
append">append</span> 2 (a <i>required line break count</i>) at the beginning and end of
Expand Down Expand Up @@ -12716,56 +12732,101 @@ 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>fragment</var> be a new <code>DocumentFragment</code> object whose <span>node
document</span> is <var>document</var>.</p></li>
<li><p>Let <var>previous</var> be <span>this</span>'s <span>previous sibling</span>.</p></li>

<li><p>Let <var>input</var> be the given value.</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>Let <var>position</var> be a pointer into <var>input</var>, initially pointing at the start
of the string.</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>If <var>next</var> is non-null and <var>next</var>'s <span>previous sibling</span> is a
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).

<code>Text</code> node, then <span>merge with the next text node</span> given <var>next</var>'s
<span>previous sibling</span>.</p></li>

<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>

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.

<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 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
data-x="concept-cd-data">data</span> is <var>text</var> and <span>node document</span> is
<var>document</var> to <var>fragment</var>.</p></li>
domenic marked this conversation as resolved.
Show resolved Hide resolved

<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>
<p>While <var>position</var> is not past the end of <var>input</var>, and the code point at
<var>position</var> is either U+000A LF or U+000D CR:</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 +68266,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