<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
<!DOCTYPE bugzilla SYSTEM "https://bugs.webkit.org/page.cgi?id=bugzilla.dtd">

<bugzilla version="5.0.4.1"
          urlbase="https://bugs.webkit.org/"
          
          maintainer="admin@webkit.org"
>

    <bug>
          <bug_id>276365</bug_id>
          
          <creation_ts>2024-07-09 06:31:13 -0700</creation_ts>
          <short_desc>script.innerText interop issues with new lines</short_desc>
          <delta_ts>2025-03-11 22:04:44 -0700</delta_ts>
          <reporter_accessible>1</reporter_accessible>
          <cclist_accessible>1</cclist_accessible>
          <classification_id>1</classification_id>
          <classification>Unclassified</classification>
          <product>WebKit</product>
          <component>DOM</component>
          <version>Safari 17</version>
          <rep_platform>Unspecified</rep_platform>
          <op_sys>Unspecified</op_sys>
          <bug_status>NEW</bug_status>
          <resolution></resolution>
          
          <see_also>https://bugs.webkit.org/show_bug.cgi?id=289076</see_also>
          <bug_file_loc></bug_file_loc>
          <status_whiteboard></status_whiteboard>
          <keywords>BrowserCompat, InRadar</keywords>
          <priority>P2</priority>
          <bug_severity>Normal</bug_severity>
          <target_milestone>---</target_milestone>
          
          <blocked>289597</blocked>
          <everconfirmed>1</everconfirmed>
          <reporter name="Luke Warlow">lwarlow</reporter>
          <assigned_to name="Nobody">webkit-unassigned</assigned_to>
          <cc>ahmad.saleem792</cc>
    
    <cc>annevk</cc>
    
    <cc>cdumez</cc>
    
    <cc>karlcow</cc>
    
    <cc>rniwa</cc>
    
    <cc>webkit-bug-importer</cc>
          

      

      

      

          <comment_sort_order>oldest_to_newest</comment_sort_order>  
          <long_desc isprivate="0" >
    <commentid>2045294</commentid>
    <comment_count>0</comment_count>
    <who name="Luke Warlow">lwarlow</who>
    <bug_when>2024-07-09 06:31:13 -0700</bug_when>
    <thetext>There&apos;s an interop issue with WebKit and its newline handling inside of script.innerText setter.

1. Load data:text/html,&lt;body&gt;&lt;script&gt;const script = document.createElement(&apos;script&apos;); document.body.appendChild(script); script.innerText = `console.log(&apos;line 1&apos;);\nconsole.log(&apos;line 2&apos;);`&lt;/script&gt; in Safari.
2. See only &apos;line 1&apos; is logged.


Repeat in Chromium and Firefox and see line 2 is logged as well.</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>2045295</commentid>
    <comment_count>1</comment_count>
    <who name="Luke Warlow">lwarlow</who>
    <bug_when>2024-07-09 06:32:57 -0700</bug_when>
    <thetext>It&apos;s worth pointing out this only happens when the script is attached to the document *before* setting innerText to the value.

If I had to hazard a guess the innerText setter is probably resulting in HTMLScriptElement::childrenChanged() being called after the first text node is inserted which executes the script early.</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>2045341</commentid>
    <comment_count>2</comment_count>
    <who name="Ryosuke Niwa">rniwa</who>
    <bug_when>2024-07-09 10:29:31 -0700</bug_when>
    <thetext>Such an interesting bug!</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>2045354</commentid>
    <comment_count>3</comment_count>
    <who name="Ahmad Saleem">ahmad.saleem792</who>
    <bug_when>2024-07-09 10:46:57 -0700</bug_when>
    <thetext>We don&apos;t have this test on WPT - since all browsers pass all &apos;setter&apos; test: https://wpt.fyi/results/html/dom/elements/the-innertext-and-outertext-properties/innertext-setter.html?label=master&amp;label=experimental&amp;aligned&amp;q=setter

Would be good to add test coverage on WPT as well.</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>2046460</commentid>
    <comment_count>4</comment_count>
    <who name="Radar WebKit Bug Importer">webkit-bug-importer</who>
    <bug_when>2024-07-16 06:32:13 -0700</bug_when>
    <thetext>&lt;rdar://problem/131835109&gt;</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>2050864</commentid>
    <comment_count>5</comment_count>
    <who name="Karl Dubost">karlcow</who>
    <bug_when>2024-08-06 00:27:53 -0700</bug_when>
    <thetext>I wonder if it is related to some of the failures in 
https://wpt.fyi/results/dom/nodes/insertion-removing-steps

To note that this is working with textContent

data:text/html,&lt;body&gt;&lt;script&gt;const script = document.createElement(&apos;script&apos;); document.body.appendChild(script); script.textContent = `console.log(&apos;line 1&apos;);\nconsole.log(&apos;line 2&apos;);`&lt;/script&gt;

And this is working if we do innerText without \n


data:text/html,&lt;body&gt;&lt;script&gt;const script = document.createElement(&apos;script&apos;); document.body.appendChild(script); script.innerText = `console.log(&apos;line 1&apos;);console.log(&apos;line 2&apos;);`&lt;/script&gt;


So this is the processing of `\n` in the innerText setter which screws up things.</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>2050870</commentid>
    <comment_count>6</comment_count>
    <who name="Karl Dubost">karlcow</who>
    <bug_when>2024-08-06 00:38:07 -0700</bug_when>
    <thetext>https://searchfox.org/wubkat/rev/b36cbce69fddb7da33823f316bd8ead5bebee970/Source/WebCore/html/HTMLScriptElement.cpp#112-135

HTMLScriptElement::setTextContent()
calls    setTextContent(WTFMove(newValue));
https://searchfox.org/wubkat/rev/b36cbce69fddb7da33823f316bd8ead5bebee970/Source/WebCore/dom/Node.cpp#1774


HTMLScriptElement::setInnerText()
calls    setInnerText(WTFMove(newValue));
https://searchfox.org/wubkat/rev/b36cbce69fddb7da33823f316bd8ead5bebee970/Source/WebCore/html/HTMLElement.cpp#542


These two are very different.

ExceptionOr&lt;void&gt; HTMLElement::setInnerText(String&amp;&amp; text)
{
    // FIXME: This doesn&apos;t take whitespace collapsing into account at all.

    if (!text.contains([](UChar c) { return c == &apos;\n&apos; || c == &apos;\r&apos;; })) {
        stringReplaceAll(WTFMove(text));
        return { };
    }

    if (isConnected() &amp;&amp; isTextControlInnerTextElement()) {
        if (!text.contains(&apos;\r&apos;)) {
            stringReplaceAll(WTFMove(text));
            return { };
        }
        String textWithConsistentLineBreaks = makeStringBySimplifyingNewLines(text);
        stringReplaceAll(WTFMove(textWithConsistentLineBreaks));
        return { };
    }

    // FIXME: This should use replaceAll(), after we fix that to work properly for DocumentFragment.
    // Add text nodes and &lt;br&gt; elements.
    Ref fragment = textToFragment(document(), WTFMove(text));
    // It&apos;s safe to dispatch events on the new fragment since author scripts have no access to it yet.
    ScriptDisallowedScope::EventAllowedScope allowedScope(fragment.get());
    return replaceChildrenWithFragment(*this, WTFMove(fragment));
}



I wonder what 
String textWithConsistentLineBreaks = makeStringBySimplifyingNewLines(text);

does to the string.</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>2051073</commentid>
    <comment_count>7</comment_count>
    <who name="Karl Dubost">karlcow</who>
    <bug_when>2024-08-06 18:05:56 -0700</bug_when>
    <thetext>The OUTPUT is 
-------
line 1
-------

for:
console.log(&apos;line 1&apos;);\nconsole.log(&apos;line 2&apos;);
console.log(&apos;line 1&apos;);\rconsole.log(&apos;line 2&apos;);


The OUTPUT is
-------
line 1
line 2
-------

for:
console.log(&apos;line 1&apos;);console.log(&apos;line 2&apos;);
console.log(&apos;line 1&apos;);\fconsole.log(&apos;line 2&apos;);
console.log(&apos;line 1&apos;);\tconsole.log(&apos;line 2&apos;);
console.log(&apos;line 1&apos;);\vconsole.log(&apos;line 2&apos;);</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>2054878</commentid>
    <comment_count>8</comment_count>
    <who name="Karl Dubost">karlcow</who>
    <bug_when>2024-08-22 22:06:24 -0700</bug_when>
    <thetext>https://github.com/WebKit/WebKit/blob/501b962b3159b23f860841c5b2dd0931df79f186/Source/WTF/wtf/text/StringView.cpp#L461-L481


template&lt;typename CharacterType&gt; static String makeStringBySimplifyingNewLinesSlowCase(const String&amp; string, unsigned firstCarriageReturn)
{
    unsigned length = string.length();
    unsigned resultLength = firstCarriageReturn;
    auto characters = string.span&lt;CharacterType&gt;();
    CharacterType* resultCharacters;
    auto result = String::createUninitialized(length, resultCharacters);
    memcpy(resultCharacters, characters.data(), firstCarriageReturn * sizeof(CharacterType));
    for (unsigned i = firstCarriageReturn; i &lt; length; ++i) {
        if (characters[i] != &apos;\r&apos;)
            resultCharacters[resultLength++] = characters[i];
        else {
            resultCharacters[resultLength++] = &apos;\n&apos;;
            if (i + 1 &lt; length &amp;&amp; characters[i + 1] == &apos;\n&apos;)
                ++i;
        }
    }
    if (resultLength &lt; length)
        result = StringImpl::createSubstringSharingImpl(*result.impl(), 0, resultLength);
    return result;
}</thetext>
  </long_desc>
      
      

    </bug>

</bugzilla>