<?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>261656</bug_id>
          
          <creation_ts>2023-09-17 12:39:28 -0700</creation_ts>
          <short_desc>[SVG2] Allow leading and trailing whitespace in svg attributes using &lt;integer&gt;, &lt;angle&gt;, &lt;number&gt;, &lt;length&gt; and &lt;percentage&gt;</short_desc>
          <delta_ts>2025-11-27 17:00:12 -0800</delta_ts>
          <reporter_accessible>1</reporter_accessible>
          <cclist_accessible>1</cclist_accessible>
          <classification_id>1</classification_id>
          <classification>Unclassified</classification>
          <product>WebKit</product>
          <component>SVG</component>
          <version>WebKit Nightly Build</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=267873</see_also>
    
    <see_also>https://bugs.webkit.org/show_bug.cgi?id=303218</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>
          <dependson>267560</dependson>
          
          <everconfirmed>1</everconfirmed>
          <reporter name="Ahmad Saleem">ahmad.saleem792</reporter>
          <assigned_to name="Ahmad Saleem">ahmad.saleem792</assigned_to>
          <cc>cdumez</cc>
    
    <cc>heycam</cc>
    
    <cc>karlcow</cc>
    
    <cc>rbuis</cc>
    
    <cc>sabouhallawa</cc>
    
    <cc>simon.fraser</cc>
    
    <cc>webkit-bug-importer</cc>
    
    <cc>zakr</cc>
    
    <cc>zimmermann</cc>
          

      

      

      

          <comment_sort_order>oldest_to_newest</comment_sort_order>  
          <long_desc isprivate="0" >
    <commentid>1977933</commentid>
    <comment_count>0</comment_count>
    <who name="Ahmad Saleem">ahmad.saleem792</who>
    <bug_when>2023-09-17 12:39:28 -0700</bug_when>
    <thetext>Hi Team,

This is another Blink&apos;s commit, where we are failing test cases:

Blink Commit: https://src.chromium.org/viewvc/blink?view=revision&amp;revision=175785

Test Case (svg/parser/whitespace-number.html) - https://jsfiddle.net/34nqh1uy/show

Test Case (svg/parser/whitespace-length.html) - https://jsfiddle.net/34nqh1uy/1/show

and there are others as well.

^ We are failing lot of these tests on WebKit ToT as well. Chrome Canary 119 and Firefox Nightly 119 both pass these test case.

Just wanted to raise so we can track it.

Thanks!</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>1978606</commentid>
    <comment_count>1</comment_count>
    <who name="Karl Dubost">karlcow</who>
    <bug_when>2023-09-20 02:30:28 -0700</bug_when>
    <thetext>The test:

data:text/html,&lt;svg id=&quot;testcontainer&quot;&gt;&lt;defs&gt;&lt;marker&gt;&lt;/marker&gt;&lt;stop&gt;&lt;/stop&gt;&lt;filter&gt;&lt;feTurbulence&gt;&lt;/feTurbulence&gt;&lt;/filter&gt;&lt;/defs&gt;&lt;/svg&gt;


document.getElementsByTagName(&apos;stop&apos;)[0].setAttribute(&apos;offset&apos;, &apos;-47a&apos;)


Then they try to 
document.getElementsByTagName(&apos;stop&apos;)[0].getAttribute(&apos;offset&apos;)

which returns &apos;-47a&apos; in all browsers.

Where it differs is when requesting:
document.getElementsByTagName(&apos;stop&apos;)[0].offset.baseVal 

it returns 

-47 in Safari 
0   in Firefox
0   in Chrome

It seems Safari is normalizing the value by ignoring the trailing garbage.
While the others are saying bad values let&apos;s reset it.

In fact
document.getElementsByTagName(&apos;stop&apos;)[0].offset returns on Safari.

{animVal: -47, baseVal: -47}


https://svgwg.org/svg2-draft/pservers.html#GradientStopAttributes
the initial value is indeed 0.
The values

&lt;number&gt;
A number usually ranging from 0 to 1.
&lt;percentage&gt;
A percentage usually ranging from 0% to 100%.


I don&apos;t remember where are the processing rules for the invalid values in CSS. 

But baseVal and animVal are defined in
https://svgwg.org/svg2-draft/types.html#__svg__SVGAnimatedString__baseVal</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>1979246</commentid>
    <comment_count>2</comment_count>
    <who name="Karl Dubost">karlcow</who>
    <bug_when>2023-09-21 19:15:11 -0700</bug_when>
    <thetext>Related(?) to
https://searchfox.org/wubkat/rev/f997a9edb80cd79caeb1d0a1b87610ffd7a56e88/Source/WebCore/svg/SVGStopElement.cpp#53-63

It converts to float but doesn&apos;t to check if the input value if the value looks like a float before converting it to a float. 

The patch from Chromium contains a parseNumber 
https://src.chromium.org/viewvc/blink/trunk/Source/core/svg/SVGParserUtilities.cpp?annotate=175785&amp;pathrev=175785#l230


I wonder if it exists in WebKit?</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>1979247</commentid>
    <comment_count>3</comment_count>
    <who name="Karl Dubost">karlcow</who>
    <bug_when>2023-09-21 19:16:29 -0700</bug_when>
    <thetext>Maybe around 
https://searchfox.org/wubkat/source/Source/WebCore/svg/SVGParserUtilities.cpp#142</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>1979252</commentid>
    <comment_count>4</comment_count>
    <who name="Karl Dubost">karlcow</who>
    <bug_when>2023-09-21 19:38:43 -0700</bug_when>
    <thetext>So Chris Dumez helped me understand better


    WTF_EXPORT_PRIVATE float toFloat(bool* ok = nullptr) const;

So we could do something like

bool success = false;
float result = attribute.toFloat(&amp;success);
if (success)
   // use result.
else
  // ...</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>1979265</commentid>
    <comment_count>5</comment_count>
    <who name="Karl Dubost">karlcow</who>
    <bug_when>2023-09-21 21:27:35 -0700</bug_when>
    <thetext>Ahmad, I think I have a patch for this. It needs a bit more work but It&apos;s passing a lot more tests.</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>1979268</commentid>
    <comment_count>6</comment_count>
    <who name="Karl Dubost">karlcow</who>
    <bug_when>2023-09-21 22:16:16 -0700</bug_when>
    <thetext>OK My patch gets all green for 
Test Case (svg/parser/whitespace-number.html) - https://jsfiddle.net/34nqh1uy/show



Now let&apos;s see the other. :) 
Test Case (svg/parser/whitespace-length.html) - https://jsfiddle.net/34nqh1uy/1/show</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>1979656</commentid>
    <comment_count>7</comment_count>
    <who name="Radar WebKit Bug Importer">webkit-bug-importer</who>
    <bug_when>2023-09-24 12:40:14 -0700</bug_when>
    <thetext>&lt;rdar://problem/115963075&gt;</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>2037867</commentid>
    <comment_count>8</comment_count>
    <who name="Ahmad Saleem">ahmad.saleem792</who>
    <bug_when>2024-05-25 06:11:59 -0700</bug_when>
    <thetext>Blink Commit - https://github.com/chromium/chromium/commit/77c8625da85bd956992b81233d451b87c39e7dea</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>2052393</commentid>
    <comment_count>9</comment_count>
    <who name="Ahmad Saleem">ahmad.saleem792</who>
    <bug_when>2024-08-13 10:19:39 -0700</bug_when>
    <thetext>&gt; Source/WebCore/svg/SVGTransformable.cpp:

From: auto parsedNumber = parseNumber(buffer, SuffixSkippingPolicy::DontSkip);
To: auto parsedNumber = parseNumber(buffer, SVGWhitespaceMode::DisallowWhitespace);

and

From: auto parsedNumber = parseNumber(buffer, SuffixSkippingPolicy::DontSkip);
To: auto parsedNumber = parseNumber(buffer, SVGWhitespaceMode::DisallowWhitespace);

___

&gt; Source/WebCore/svg/SVGPointList.cpp:

From: auto yPos = parseNumber(buffer, SuffixSkippingPolicy::DontSkip);
To: auto yPos = parseNumber(buffer, SVGWhitespaceMode::DisallowWhitespace);

___

&gt; Source/WebCore/svg/SVGLengthValue.cpp:

From: auto convertedNumber = parseNumber(buffer, SuffixSkippingPolicy::DontSkip);
To: auto convertedNumber = parseNumber(buffer, SVGWhitespaceMode::AllowLeadingWhitespace);

___

&gt; Source/WebCore/svg/SVGFitToViewBox.cpp:

From: auto height = parseNumber(buffer, SuffixSkippingPolicy::DontSkip);
To: auto height = parseNumber(buffer, SVGWhitespaceMode::AllowLeadingAndTrailingWhitespace);

___

&gt; Source/WebCore/svg/SVGAnimationElement.cpp:

From: auto posD = parseNumber(buffer, SuffixSkippingPolicy::DontSkip);
To: auto posD = parseNumber(buffer, SVGWhitespaceMode::DisallowWhitespace);

____

&gt; Source/WebCore/svg/SVGAngleValue.cpp:

From: auto valueInSpecifiedUnits = parseNumber(buffer, SuffixSkippingPolicy::DontSkip);
To: uto valueInSpecifiedUnits = parseNumber(buffer, SVGWhitespaceMode::AllowLeadingWhitespace);

___

&gt; Source/WebCore/svg/SVGParserUtilities.h:

Delete below:

enum class SuffixSkippingPolicy {
    DontSkip,
    Skip
};

and add this:

enum class SVGWhitespaceMode {
    DisallowWhitespace = 0,
    AllowLeadingWhitespace = 0x1,
    AllowTrailingWhitespace = 0x2,
    AllowLeadingAndTrailingWhitespace = AllowLeadingWhitespace | AllowTrailingWhitespace
};

Change:

std::optional&lt;float&gt; parseNumber(StringParsingBuffer&lt;LChar&gt;&amp;, SuffixSkippingPolicy = SuffixSkippingPolicy::Skip);

std::optional&lt;float&gt; parseNumber(StringParsingBuffer&lt;LChar&gt;&amp;, SVGWhitespaceMode mode = SVGWhitespaceMode::AllowLeadingAndTrailingWhitespace);

and


std::optional&lt;float&gt; parseNumber(StringParsingBuffer&lt;UChar&gt;&amp;, SuffixSkippingPolicy = SuffixSkippingPolicy::Skip);

std::optional&lt;float&gt; parseNumber(StringParsingBuffer&lt;UChar&gt;&amp;, SVGWhitespaceMode mode = SVGWhitespaceMode::AllowLeadingAndTrailingWhitespace);

and

std::optional&lt;float&gt; parseNumber(StringView, SuffixSkippingPolicy = SuffixSkippingPolicy::Skip);

std::optional&lt;float&gt; parseNumber(StringView, SVGWhitespaceMode mode = SVGWhitespaceMode::AllowLeadingAndTrailingWhitespace);

____

&gt; Source/WebCore/svg/SVGParserUtilities.cpp:

Function definition:

template &lt;typename CharacterType, typename FloatType = float&gt; static std::optional&lt;FloatType&gt; genericParseNumber(StringParsingBuffer&lt;CharacterType&gt;&amp; buffer, SuffixSkippingPolicy skip = SuffixSkippingPolicy::Skip)

to:

template &lt;typename CharacterType, typename FloatType = float&gt; static std::optional&lt;FloatType&gt; genericParseNumber(StringParsingBuffer&lt;CharacterType&gt;&amp; buffer, SVGWhitespaceMode mode = SVGWhitespaceMode::AllowLeadingAndTrailingWhitespace)

and in below:

if (mode == SVGWhitespaceMode::AllowLeadingWhitespace)
        skipOptionalSVGSpaces(buffer);

and

if (mode == SVGWhitespaceMode::AllowTrailingWhitespace)
        skipOptionalSVGSpacesOrDelimiter(buffer);

Another function definition:

std::optional&lt;float&gt; parseNumber(StringView string, SuffixSkippingPolicy skip)

to:

std::optional&lt;float&gt; parseNumber(StringView string, SVGWhitespaceMode mode)

and

return readCharactersForParsing(string, [skip](auto buffer) -&gt; std::optional&lt;float&gt; {
        auto result = genericParseNumber(buffer, skip);

to:

return readCharactersForParsing(string, [mode](auto buffer) -&gt; std::optional&lt;float&gt; {
        auto result = genericParseNumber(buffer, mode);

Another function definition:

std::optional&lt;float&gt; parseNumber(StringParsingBuffer&lt;LChar&gt;&amp; buffer, SuffixSkippingPolicy skip)

to:

std::optional&lt;float&gt; parseNumber(StringParsingBuffer&lt;LChar&gt;&amp; buffer, SVGWhitespaceMode mode)

and change return to:  return genericParseNumber(buffer, mode);

Another function definition:

std::optional&lt;float&gt; parseNumber(StringParsingBuffer&lt;UChar&gt;&amp; buffer, SuffixSkippingPolicy skip)

to:

std::optional&lt;float&gt; parseNumber(StringParsingBuffer&lt;UChar&gt;&amp; buffer, SVGWhitespaceMode mode)

and change return: return genericParseNumber(buffer, mode);

___

&gt; Source/WebCore/svg/SVGParserUtilities.cpp:

parseNumberOptionalNumber:

auto y = parseNumber(buffer, SuffixSkippingPolicy::DontSkip); to auto y = parseNumber(buffer, SVGWhitespaceMode::AllowLeadingAndTrailingWhitespace);


parseRect:

auto height = parseNumber(buffer, SuffixSkippingPolicy::DontSkip); to auto height = parseNumber(buffer, SVGWhitespaceMode::DisallowWhitespace);

___

It does progress test cases but not where we have have scientific notations.</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>2052601</commentid>
    <comment_count>10</comment_count>
    <who name="Karl Dubost">karlcow</who>
    <bug_when>2024-08-13 19:26:46 -0700</bug_when>
    <thetext>Ahmad, I think scientific notations are still not yet a spec thing.</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>2052602</commentid>
    <comment_count>11</comment_count>
    <who name="Karl Dubost">karlcow</who>
    <bug_when>2024-08-13 19:33:21 -0700</bug_when>
    <thetext>If there are WPT tests relying on scientific notations they should be removed. 
A bit like it was done in https://github.com/web-platform-tests/wpt/commit/06e103ad6136bf0988f9d1614db05d8a652e0570</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>2112049</commentid>
    <comment_count>12</comment_count>
    <who name="Ahmad Saleem">ahmad.saleem792</who>
    <bug_when>2025-04-20 04:26:13 -0700</bug_when>
    <thetext>Syncing some passing tests here - https://github.com/WebKit/WebKit/pull/44306

At least, it would give some coverage while we try to progress remaining cases. I do have patch to make some progress more without any regression, so I think eve n partial progression is better than nothing. So might end-up doing PR later.</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>2112149</commentid>
    <comment_count>13</comment_count>
    <who name="Ahmad Saleem">ahmad.saleem792</who>
    <bug_when>2025-04-21 04:22:01 -0700</bug_when>
    <thetext>Pull request: https://github.com/WebKit/WebKit/pull/44323</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>2112150</commentid>
    <comment_count>14</comment_count>
    <who name="Ahmad Saleem">ahmad.saleem792</who>
    <bug_when>2025-04-21 04:23:21 -0700</bug_when>
    <thetext>(In reply to Ahmad Saleem from comment #13)
&gt; Pull request: https://github.com/WebKit/WebKit/pull/44323

NOTE - I am changing it to to draft, it still progress test cases without regression:

https://jsfiddle.net/maseh9v7/ -&gt; whitespace-angle-2.html (105 -&gt; 156)
https://jsfiddle.net/pad9c3mo/ -&gt; whitespace-angle-1.html (108 -&gt; 288)
https://jsfiddle.net/2639xdzs/ -&gt; whitespace-integer.html (27 - no change)
https://jsfiddle.net/6bf32qhk/ -&gt; whitespace-number.html (1074 - no change)
https://jsfiddle.net/2b43fprz/ -&gt; whitespace-length.html (704 -&gt; 942)

Plus it is partial merge, I will try to do remaining bit and hopefully can progress it fully but either way - even landing as is for partial progression like above wouldn&apos;t be so bad.</thetext>
  </long_desc>
      
      

    </bug>

</bugzilla>