]> source.dussan.org Git - jquery.git/commitdiff
CSS: Return `undefined` for whitespace-only CSS variable values (#5120)
authorMichał Gołębiowski-Owczarek <m.goleb@gmail.com>
Mon, 3 Oct 2022 16:10:42 +0000 (18:10 +0200)
committerGitHub <noreply@github.com>
Mon, 3 Oct 2022 16:10:42 +0000 (18:10 +0200)
The spec requires that CSS variable values are trimmed. In browsers that do
this - mainly, Safari, but also Firefox if the value only has leading
whitespace - we currently return undefined; in other browsers, we return
an empty string as the logic to fall back to undefined happens before
trimming.

This commit adds another explicit callback to `undefined` to have it consistent
across browsers.

Also, more explicit comments about behaviors we need to work around in various
browsers have been added.

Closes gh-5120
Ref gh-5106

src/css/curCSS.js
test/unit/css.js

index 25b4630a5d487cedf89383080c9f096d6c7b9aa7..72c3db9f585d90ecca7c0e783b71931d147905d9 100644 (file)
@@ -12,17 +12,37 @@ function curCSS( elem, name, computed ) {
 
        // getPropertyValue is needed for `.css('--customProperty')` (gh-3144)
        if ( computed ) {
-               ret = computed.getPropertyValue( name ) || computed[ name ];
 
-               // trim whitespace for custom property (issue gh-4926)
-               if ( isCustomProp && ret !== undefined ) {
+               // Support: IE <=9 - 11+
+               // IE only supports `"float"` in `getPropertyValue`; in computed styles
+               // it's only available as `"cssFloat"`. We no longer modify properties
+               // sent to `.css()` apart from camelCasing, so we need to check both.
+               // Normally, this would create difference in behavior: if
+               // `getPropertyValue` returns an empty string, the value returned
+               // by `.css()` would be `undefined`. This is usually the case for
+               // disconnected elements. However, in IE even disconnected elements
+               // with no styles return `"none"` for `getPropertyValue( "float" )`
+               ret = computed.getPropertyValue( name ) || computed[ name ];
 
+               if ( isCustomProp && ret ) {
+
+                       // Support: Firefox 105+, Chrome <=105+
+                       // Spec requires trimming whitespace for custom properties (gh-4926).
+                       // Firefox only trims leading whitespace. Chrome just collapses
+                       // both leading & trailing whitespace to a single space.
+                       //
+                       // Fall back to `undefined` if empty string returned.
+                       // This collapses a missing definition with property defined
+                       // and set to an empty string but there's no standard API
+                       // allowing us to differentiate them without a performance penalty
+                       // and returning `undefined` aligns with older jQuery.
+                       //
                        // rtrim treats U+000D CARRIAGE RETURN and U+000C FORM FEED
                        // as whitespace while CSS does not, but this is not a problem
                        // because CSS preprocessing replaces them with U+000A LINE FEED
                        // (which *is* CSS whitespace)
                        // https://www.w3.org/TR/css-syntax-3/#input-preprocessing
-                       ret = ret.replace( rtrim, "$1" );
+                       ret = ret.replace( rtrim, "$1" ) || undefined;
                }
 
                if ( ret === "" && !isAttached( elem ) ) {
index b692caac9e375180ac02ac1726be9236ef99d2b2..a7a501df18f276b260938910ad92174465744912 100644 (file)
@@ -1748,6 +1748,7 @@ QUnit.testUnlessIE( "css(--customProperty)", function( assert ) {
                "        --prop10:\f\r\n\t val10 \f\r\n\t;\n" +
                "        --prop11:\u000C\u000D\u000A\u0009\u0020val11\u0020\u0009\u000A\u000D\u000C;\n" +
                "        --prop12:\u000Bval12\u000B;\n" +
+               "        --space: ;\n" +
                "        --empty:;\n" +
                "    }\n" +
                "</style>"
@@ -1757,7 +1758,7 @@ QUnit.testUnlessIE( "css(--customProperty)", function( assert ) {
                $elem = jQuery( "<div>" ).addClass( "test__customProperties" )
                        .appendTo( "#qunit-fixture" ),
                webkitOrBlink = /\bsafari\b/i.test( navigator.userAgent ),
-               expected = 19;
+               expected = 20;
 
        if ( webkitOrBlink ) {
                expected -= 2;
@@ -1803,6 +1804,7 @@ QUnit.testUnlessIE( "css(--customProperty)", function( assert ) {
        assert.equal( $elem.css( "--prop10" ), "val10", "Multiple preceding and following escaped unicode whitespace trimmed" );
        assert.equal( $elem.css( "--prop11" ), "val11", "Multiple preceding and following unicode whitespace trimmed" );
        assert.equal( $elem.css( "--prop12" ), "\u000Bval12\u000B", "Multiple preceding and following non-CSS whitespace reserved" );
+       assert.equal( $elem.css( "--space" ), undefined );
        assert.equal( $elem.css( "--empty" ), undefined );
        assert.equal( $elem.css( "--nonexistent" ), undefined );
 } );