From 5662ddd16f34517e7cf54cdf60f5413e65522359 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Go=C5=82e=CC=A8biowski-Owczarek?= Date: Mon, 4 Nov 2024 00:11:21 +0100 Subject: [PATCH 1/8] Core: Remove support for jQuery 4.x --- .github/workflows/browserstack-git.yml | 68 ----- ...{browserstack-3.x.yml => browserstack.yml} | 4 +- .github/workflows/filestash.yml | 4 +- CONTRIBUTING.md | 2 +- README.md | 16 +- jtr-3.x.yml => jtr-ci.yml | 0 jtr-local.yml | 4 - src/jquery/ajax.js | 133 ++-------- src/jquery/attributes.js | 16 +- src/jquery/core.js | 101 +------- src/jquery/css.js | 71 +----- src/jquery/deferred.js | 10 +- src/jquery/selector.js | 69 +++++ src/main.js | 6 +- test/data/ajax-jsonp-callback-name.html | 2 +- test/data/event-fixHooks.html | 2 +- test/data/event-lateload.html | 2 +- test/data/event-props-concat.html | 2 +- test/data/event-props.html | 2 +- test/data/event-ready.html | 2 +- test/data/testinit.js | 16 +- test/unit/jquery/ajax.js | 240 ++++++++---------- test/unit/jquery/attributes.js | 37 +-- test/unit/jquery/core.js | 159 ------------ test/unit/jquery/css.js | 9 +- test/unit/jquery/deferred.js | 24 +- test/unit/jquery/selector.js | 103 ++++++++ warnings.md | 16 +- 28 files changed, 368 insertions(+), 752 deletions(-) delete mode 100644 .github/workflows/browserstack-git.yml rename .github/workflows/{browserstack-3.x.yml => browserstack.yml} (96%) rename jtr-3.x.yml => jtr-ci.yml (100%) diff --git a/.github/workflows/browserstack-git.yml b/.github/workflows/browserstack-git.yml deleted file mode 100644 index 0a3d2d0c..00000000 --- a/.github/workflows/browserstack-git.yml +++ /dev/null @@ -1,68 +0,0 @@ -name: Browserstack (Core git) - -on: - push: - branches: - - main - # Once a week every Tuesday - schedule: - - cron: "42 1 * * 2" - -jobs: - test: - runs-on: ubuntu-latest - environment: browserstack - env: - BROWSERSTACK_USERNAME: ${{ secrets.BROWSERSTACK_USERNAME }} - BROWSERSTACK_ACCESS_KEY: ${{ secrets.BROWSERSTACK_ACCESS_KEY }} - NODE_VERSION: 22.x - name: ${{ matrix.BROWSER }} - concurrency: - group: ${{ matrix.BROWSER }} - ${{ github.sha }} - timeout-minutes: 30 - strategy: - fail-fast: false - matrix: - BROWSER: - - 'IE_11' - - 'Safari_latest' - - 'Safari_latest-1' - - 'Chrome_latest' - - 'Chrome_latest-1' - - 'Opera_latest' - - 'Edge_latest' - - 'Edge_latest-1' - - 'Firefox_latest' - - 'Firefox_latest-1' - - 'Firefox_115' - - '__iOS_18' - - '__iOS_17' - - '__iOS_16' - steps: - - name: Checkout - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - - - name: Use Node.js ${{ env.NODE_VERSION }} - uses: actions/setup-node@39370e3970a6d050c480ffad4ff0ed4d3fdee5af # v4.1.0 - with: - node-version: ${{ env.NODE_VERSION }} - - - name: Cache - uses: actions/cache@1bd1e32a3bdc45362d1e726936510720a7c30a57 # v4.2.0 - with: - path: ~/.npm - key: ${{ runner.os }}-node-${{ env.NODE_VERSION }}-npm-lock-${{ hashFiles('**/package-lock.json') }} - restore-keys: | - ${{ runner.os }}-node-${{ env.NODE_VERSION }}-npm-lock- - - - name: Install dependencies - run: npm install - - - name: Pretest script - run: npm run pretest - - - name: Test - run: | - npm run test:unit -- -v -c jtr-git.yml \ - --browserstack "${{ matrix.BROWSER }}" \ - --run-id ${{ github.run_id }} \ diff --git a/.github/workflows/browserstack-3.x.yml b/.github/workflows/browserstack.yml similarity index 96% rename from .github/workflows/browserstack-3.x.yml rename to .github/workflows/browserstack.yml index fd62a28e..8af6a341 100644 --- a/.github/workflows/browserstack-3.x.yml +++ b/.github/workflows/browserstack.yml @@ -1,4 +1,4 @@ -name: Browserstack (Core 3.x) +name: Browserstack on: push: @@ -79,6 +79,6 @@ jobs: - name: Test run: | - npm run test:unit -- -v -c jtr-3.x.yml \ + npm run test:unit -- -v -c jtr-ci.yml \ --browserstack "${{ matrix.BROWSER }}" \ --run-id ${{ github.run_id }} \ diff --git a/.github/workflows/filestash.yml b/.github/workflows/filestash.yml index 1bd552f0..f53af800 100644 --- a/.github/workflows/filestash.yml +++ b/.github/workflows/filestash.yml @@ -47,5 +47,5 @@ jobs: - name: Upload to Filestash run: | - rsync dist/jquery-migrate.js filestash@"${{ secrets.FILESTASH_SERVER }}":jquery-migrate-git.js - rsync dist/jquery-migrate.min.js filestash@"${{ secrets.FILESTASH_SERVER }}":jquery-migrate-git.min.js + rsync dist/jquery-migrate.js filestash@"${{ secrets.FILESTASH_SERVER }}":jquery-migrate-3.x-git.js + rsync dist/jquery-migrate.min.js filestash@"${{ secrets.FILESTASH_SERVER }}":jquery-migrate-3.x-git.min.js diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index cb18176c..69865b1d 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -47,7 +47,7 @@ Make sure you have reproduced the bug with all browser extensions and add-ons di ### Try the latest version of jQuery Migrate -Bugs in old versions of jQuery Migrate may have already been fixed. In order to avoid reporting known issues, make sure you are always testing against the [latest build](https://releases.jquery.com/git/jquery-migrate-git.js). We cannot fix bugs in older released files, if a bug has been fixed in a subsequent version of jQuery Migrate the site should upgrade. +Bugs in old versions of jQuery Migrate may have already been fixed. In order to avoid reporting known issues, make sure you are always testing against the [latest build](https://releases.jquery.com/git/jquery-migrate-3.x-git.js). We cannot fix bugs in older released files, if a bug has been fixed in a subsequent version of jQuery Migrate the site should upgrade. ### Simplify the test case diff --git a/README.md b/README.md index 5512c8e4..bd615a60 100644 --- a/README.md +++ b/README.md @@ -11,14 +11,14 @@ That way you can spot and fix what otherwise would have been errors, until you n The following table indicates which jQuery Migrate versions can be used with which jQuery versions: -| jQuery version | jQuery Migrate version | -|----------------|-------------------------| -| 1.x | 1.x | -| 2.x | 1.x | -| 3.x | 3.x / 4.x[1] | -| 4.x | 3.x / 4.x[1] | +| jQuery version | jQuery Migrate version | +|----------------|------------------------| +| 1.x | 1.x | +| 2.x | 1.x | +| 3.x | 3.x | +| 4.x | 4.x | -[1] NOTE: jQuery Migrate 4.x only supports the same browser as jQuery 4.x does. If you need to support Edge Legacy, Internet Explorer 9-10 or iOS 7+ (and not just 3 latest versions), use jQuery Migrate 3.x. +Each jQuery Migrate version supports the same browsers that the jQuery version used with it. ## Usage @@ -40,7 +40,7 @@ The production build is minified and does not generate console warnings. It will | Debugging enabled |

| | | Minified | |

| | Latest release (*may be hotlinked if desired*) | [jquery-migrate-3.5.2.js](https://code.jquery.com/jquery-migrate-3.5.2.js) | [jquery-migrate-3.5.2.min.js](https://code.jquery.com/jquery-migrate-3.5.2.min.js) | -| \* Latest work-in-progress build | [jquery-migrate-git.js](https://releases.jquery.com/git/jquery-migrate-git.js) | [jquery-migrate-git.min.js](https://releases.jquery.com/git/jquery-migrate-git.min.js) | +| \* Latest work-in-progress build | [jquery-migrate-3.x-git.js](https://releases.jquery.com/git/jquery-migrate-3.x-git.js) | [jquery-migrate-3.x-git.min.js](https://releases.jquery.com/git/jquery-migrate-3.x-git.min.js) | \* **Work-in-progress build:** Although this file represents the most recent updates to the plugin, it may not have been thoroughly tested. We do not recommend using this file on production sites since it may be unstable; use the released production version instead. diff --git a/jtr-3.x.yml b/jtr-ci.yml similarity index 100% rename from jtr-3.x.yml rename to jtr-ci.yml diff --git a/jtr-local.yml b/jtr-local.yml index fa5058e1..2fdfd1c8 100644 --- a/jtr-local.yml +++ b/jtr-local.yml @@ -2,10 +2,6 @@ version: 1 flags: jquery: - - git - - git.min - - git.slim - - git.slim.min - 3.x-git - 3.x-git.min - 3.x-git.slim diff --git a/src/jquery/ajax.js b/src/jquery/ajax.js index 91555749..9c2bf679 100644 --- a/src/jquery/ajax.js +++ b/src/jquery/ajax.js @@ -1,4 +1,3 @@ -import { jQueryVersionSince } from "../compareVersions.js"; import { migrateWarn, migratePatchAndWarnFunc, migratePatchFunc } from "../main.js"; // Support jQuery slim which excludes the ajax module @@ -8,8 +7,7 @@ var oldAjax = jQuery.ajax, oldCallbacks = [], guid = "migrate-" + Date.now(), origJsonpCallback = jQuery.ajaxSettings.jsonpCallback, - rjsonp = /(=)\?(?=&|$)|\?\?/, - rquery = /\?/; + rjsonp = /(=)\?(?=&|$)|\?\?/; migratePatchFunc( jQuery, "ajax", function() { var jQXHR = oldAjax.apply( this, arguments ); @@ -45,120 +43,23 @@ jQuery.ajaxSetup( { // Register this prefilter before the jQuery one. Otherwise, a promoted // request is transformed into one with the script dataType, and we can't // catch it anymore. -if ( jQueryVersionSince( "4.0.0" ) ) { - - // Code mostly from: - // https://github.com/jquery/jquery/blob/fa0058af426c4e482059214c29c29f004254d9a1/src/ajax/jsonp.js#L20-L97 - jQuery.ajaxPrefilter( "+json", function( s, originalSettings, jqXHR ) { - - if ( !jQuery.migrateIsPatchEnabled( "jsonp-promotion" ) ) { - return; - } - - var callbackName, overwritten, responseContainer, - jsonProp = s.jsonp !== false && ( rjsonp.test( s.url ) ? - "url" : - typeof s.data === "string" && - ( s.contentType || "" ) - .indexOf( "application/x-www-form-urlencoded" ) === 0 && - rjsonp.test( s.data ) && "data" - ); - - // Handle iff the expected data type is "jsonp" or we have a parameter to set - if ( jsonProp || s.dataTypes[ 0 ] === "jsonp" ) { - migrateWarn( "jsonp-promotion", "JSON-to-JSONP auto-promotion is deprecated" ); - - // Get callback name, remembering preexisting value associated with it - callbackName = s.jsonpCallback = typeof s.jsonpCallback === "function" ? - s.jsonpCallback() : - s.jsonpCallback; - - // Insert callback into url or form data - if ( jsonProp ) { - s[ jsonProp ] = s[ jsonProp ].replace( rjsonp, "$1" + callbackName ); - } else if ( s.jsonp !== false ) { - s.url += ( rquery.test( s.url ) ? "&" : "?" ) + s.jsonp + "=" + callbackName; - } - - // Use data converter to retrieve json after script execution - s.converters[ "script json" ] = function() { - if ( !responseContainer ) { - jQuery.error( callbackName + " was not called" ); - } - return responseContainer[ 0 ]; - }; - - // Force json dataType - s.dataTypes[ 0 ] = "json"; - - // Install callback - overwritten = window[ callbackName ]; - window[ callbackName ] = function() { - responseContainer = arguments; - }; - - // Clean-up function (fires after converters) - jqXHR.always( function() { - - // If previous value didn't exist - remove it - if ( overwritten === undefined ) { - jQuery( window ).removeProp( callbackName ); - - // Otherwise restore preexisting value - } else { - window[ callbackName ] = overwritten; - } - - // Save back as free - if ( s[ callbackName ] ) { - - // Make sure that re-using the options doesn't screw things around - s.jsonpCallback = originalSettings.jsonpCallback; - - // Save the callback name for future use - oldCallbacks.push( callbackName ); - } - - // Call if it was a function and we have a response - if ( responseContainer && typeof overwritten === "function" ) { - overwritten( responseContainer[ 0 ] ); - } - - responseContainer = overwritten = undefined; - } ); - - // Delegate to script - return "script"; - } - } ); -} else { - - // jQuery <4 already contains this prefixer; don't duplicate the whole logic, - // but only enough to know when to warn. - jQuery.ajaxPrefilter( "+json", function( s ) { - - if ( !jQuery.migrateIsPatchEnabled( "jsonp-promotion" ) ) { - return; - } - - // Warn if JSON-to-JSONP auto-promotion happens. - if ( s.jsonp !== false && ( rjsonp.test( s.url ) || - typeof s.data === "string" && - ( s.contentType || "" ) - .indexOf( "application/x-www-form-urlencoded" ) === 0 && - rjsonp.test( s.data ) - ) ) { - migrateWarn( "jsonp-promotion", "JSON-to-JSONP auto-promotion is deprecated" ); - } - } ); -} +// jQuery <4 already contains this prefixer; don't duplicate the whole logic, +// but only enough to know when to warn. +jQuery.ajaxPrefilter( "+json", function( s ) { + if ( !jQuery.migrateIsPatchEnabled( "jsonp-promotion" ) ) { + return; + } -// Don't trigger the above logic in jQuery >=4 by default as the JSON-to-JSONP -// auto-promotion behavior is gone in jQuery 4.0 and as it has security implications, -// we don't want to restore the legacy behavior by default. -if ( jQueryVersionSince( "4.0.0" ) ) { - jQuery.migrateDisablePatches( "jsonp-promotion" ); -} + // Warn if JSON-to-JSONP auto-promotion happens. + if ( s.jsonp !== false && ( rjsonp.test( s.url ) || + typeof s.data === "string" && + ( s.contentType || "" ) + .indexOf( "application/x-www-form-urlencoded" ) === 0 && + rjsonp.test( s.data ) + ) ) { + migrateWarn( "jsonp-promotion", "JSON-to-JSONP auto-promotion is deprecated" ); + } +} ); } diff --git a/src/jquery/attributes.js b/src/jquery/attributes.js index f76b1499..be029948 100644 --- a/src/jquery/attributes.js +++ b/src/jquery/attributes.js @@ -1,5 +1,4 @@ import { migratePatchFunc, migrateWarn } from "../main.js"; -import { jQueryVersionSince } from "../compareVersions.js"; var oldRemoveAttr = jQuery.fn.removeAttr, oldJQueryAttr = jQuery.attr, @@ -36,15 +35,6 @@ jQuery.each( booleans.split( "|" ), function( _i, name ) { migrateWarn( "boolean-attributes", "Boolean attribute '" + name + "' value is different from its lowercased name" ); - - // jQuery <4 attr hooks setup is complex: there are attr - // hooks, bool hooks and selector attr handles. Only - // implement the logic in jQuery >=4 where it's missing - // and there are only attr hooks. - if ( jQueryVersionSince( "4.0.0" ) ) { - return name.toLowerCase(); - } - return null; } } @@ -72,12 +62,12 @@ jQuery.each( booleans.split( "|" ), function( _i, name ) { } return name; } - } else if ( !jQueryVersionSince( "4.0.0" ) ) { + } else { // jQuery <4 uses a private `boolHook` for the boolean attribute // setter. It's only activated if `attrHook` is not set, but we set - // it here in Migrate. Since we cannot access it, let's just repeat - // its contents here. + // it here in Migrate so jQuery would not use it. Since we cannot + // access it, let's just repeat its contents here. if ( value === false ) { // Remove boolean attributes when set to false diff --git a/src/jquery/core.js b/src/jquery/core.js index 7d92fefd..c1f8b311 100644 --- a/src/jquery/core.js +++ b/src/jquery/core.js @@ -1,24 +1,10 @@ import { jQueryVersionSince } from "../compareVersions.js"; -import { - migratePatchFunc, - migrateWarn, - migratePatchAndWarnFunc, - migrateWarnProp -} from "../main.js"; +import { migratePatchAndWarnFunc } from "../main.js"; import "../disablePatches.js"; -var findProp, - arr = [], - push = arr.push, +var arr = [], slice = arr.slice, - sort = arr.sort, - splice = arr.splice, class2type = {}, - oldInit = jQuery.fn.init, - oldFind = jQuery.find, - - rattrHashTest = /\[(\s*[-\w]+\s*)([~|^$*]?=)\s*([-\w#]*?#[-\w#]*)\s*\]/, - rattrHashGlob = /\[(\s*[-\w]+\s*)([~|^$*]?=)\s*([-\w#]*?#[-\w#]*)\s*\]/g, // Require that the "whitespace run" starts from a non-whitespace // to avoid O(N^2) behavior when the engine would try matching "\s+$" at each space position. @@ -37,68 +23,6 @@ function isFunction( obj ) { typeof obj.item !== "function"; } -migratePatchFunc( jQuery.fn, "init", function( arg1 ) { - var args = Array.prototype.slice.call( arguments ); - - if ( jQuery.migrateIsPatchEnabled( "selector-empty-id" ) && - typeof arg1 === "string" && arg1 === "#" ) { - - // JQuery( "#" ) is a bogus ID selector, but it returned an empty set - // before jQuery 3.0 - migrateWarn( "selector-empty-id", "jQuery( '#' ) is not a valid selector" ); - args[ 0 ] = []; - } - - return oldInit.apply( this, args ); -}, "selector-empty-id" ); - -// This is already done in Core but the above patch will lose this assignment -// so we need to redo it. It doesn't matter whether the patch is enabled or not -// as the method is always going to be a Migrate-created wrapper. -jQuery.fn.init.prototype = jQuery.fn; - -migratePatchFunc( jQuery, "find", function( selector ) { - var args = Array.prototype.slice.call( arguments ); - - // Support: PhantomJS 1.x - // String#match fails to match when used with a //g RegExp, only on some strings - if ( typeof selector === "string" && rattrHashTest.test( selector ) ) { - - // The nonstandard and undocumented unquoted-hash was removed in jQuery 1.12.0 - // First see if qS thinks it's a valid selector, if so avoid a false positive - try { - window.document.querySelector( selector ); - } catch ( err1 ) { - - // Didn't *look* valid to qSA, warn and try quoting what we think is the value - selector = selector.replace( rattrHashGlob, function( _, attr, op, value ) { - return "[" + attr + op + "\"" + value + "\"]"; - } ); - - // If the regexp *may* have created an invalid selector, don't update it - // Note that there may be false alarms if selector uses jQuery extensions - try { - window.document.querySelector( selector ); - migrateWarn( "selector-hash", - "Attribute selector with '#' must be quoted: " + args[ 0 ] ); - args[ 0 ] = selector; - } catch ( err2 ) { - migrateWarn( "selector-hash", - "Attribute selector with '#' was not fixed: " + args[ 0 ] ); - } - } - } - - return oldFind.apply( this, args ); -}, "selector-hash" ); - -// Copy properties attached to original jQuery.find method (e.g. .attr, .isXML) -for ( findProp in oldFind ) { - if ( Object.prototype.hasOwnProperty.call( oldFind, findProp ) ) { - jQuery.find[ findProp ] = oldFind[ findProp ]; - } -} - // The number of elements contained in the matched element set migratePatchAndWarnFunc( jQuery.fn, "size", function() { return this.length; @@ -176,11 +100,10 @@ if ( jQueryVersionSince( "3.3.0" ) ) { }, "type", "jQuery.type is deprecated" ); - migratePatchAndWarnFunc( jQuery, "isFunction", - function( obj ) { - return typeof obj === "function"; - }, "isFunction", - "jQuery.isFunction() is deprecated" ); + migratePatchAndWarnFunc( jQuery, "isFunction", function( obj ) { + return isFunction( obj ); + }, "isFunction", + "jQuery.isFunction() is deprecated" ); migratePatchAndWarnFunc( jQuery, "isWindow", function( obj ) { @@ -224,15 +147,3 @@ if ( jQueryVersionSince( "3.3.0" ) ) { ); } - -if ( jQueryVersionSince( "4.0.0" ) ) { - - // `push`, `sort` & `splice` are used internally by jQuery <4, so we only - // warn in jQuery 4+. - migrateWarnProp( jQuery.fn, "push", push, "push", - "jQuery.fn.push() is deprecated and removed; use .add or convert to an array" ); - migrateWarnProp( jQuery.fn, "sort", sort, "sort", - "jQuery.fn.sort() is deprecated and removed; convert to an array before sorting" ); - migrateWarnProp( jQuery.fn, "splice", splice, "splice", - "jQuery.fn.splice() is deprecated and removed; use .slice or .not with .eq" ); -} diff --git a/src/jquery/css.js b/src/jquery/css.js index 2ae10feb..f06853fc 100644 --- a/src/jquery/css.js +++ b/src/jquery/css.js @@ -2,7 +2,7 @@ import { jQueryVersionSince } from "../compareVersions.js"; import { migrateWarn, migratePatchFunc } from "../main.js"; import { camelCase } from "../utils.js"; -var origFnCss, internalCssNumber, +var origFnCss, internalSwapCall = false, ralphaStart = /^[a-z]/, @@ -80,71 +80,6 @@ if ( jQueryVersionSince( "3.4.0" ) && typeof Proxy !== "undefined" ) { } ); } -// In jQuery >=4 where jQuery.cssNumber is missing fill it with the latest 3.x version: -// https://github.com/jquery/jquery/blob/3.7.1/src/css.js#L216-L246 -// This way, number values for the CSS properties below won't start triggering -// Migrate warnings when jQuery gets updated to >=4.0.0 (gh-438). -if ( jQueryVersionSince( "4.0.0" ) ) { - - // We need to keep this as a local variable as we need it internally - // in a `jQuery.fn.css` patch and this usage shouldn't warn. - internalCssNumber = { - animationIterationCount: true, - aspectRatio: true, - borderImageSlice: true, - columnCount: true, - flexGrow: true, - flexShrink: true, - fontWeight: true, - gridArea: true, - gridColumn: true, - gridColumnEnd: true, - gridColumnStart: true, - gridRow: true, - gridRowEnd: true, - gridRowStart: true, - lineHeight: true, - opacity: true, - order: true, - orphans: true, - scale: true, - widows: true, - zIndex: true, - zoom: true, - - // SVG-related - fillOpacity: true, - floodOpacity: true, - stopOpacity: true, - strokeMiterlimit: true, - strokeOpacity: true - }; - - if ( typeof Proxy !== "undefined" ) { - jQuery.cssNumber = new Proxy( internalCssNumber, { - get: function() { - migrateWarn( "css-number", "jQuery.cssNumber is deprecated" ); - return Reflect.get.apply( this, arguments ); - }, - set: function() { - migrateWarn( "css-number", "jQuery.cssNumber is deprecated" ); - return Reflect.set.apply( this, arguments ); - } - } ); - } else { - - // Support: IE 9-11+ - // IE doesn't support proxies, but we still want to restore the legacy - // jQuery.cssNumber there. - jQuery.cssNumber = internalCssNumber; - } -} else { - - // Make `internalCssNumber` defined for jQuery <4 as well as it's needed - // in the `jQuery.fn.css` patch below. - internalCssNumber = jQuery.cssNumber; -} - function isAutoPx( prop ) { // The first test is used to ensure that: @@ -170,9 +105,7 @@ migratePatchFunc( jQuery.fn, "css", function( name, value ) { if ( typeof value === "number" ) { camelName = camelCase( name ); - // Use `internalCssNumber` to avoid triggering our warnings in this - // internal check. - if ( !isAutoPx( camelName ) && !internalCssNumber[ camelName ] ) { + if ( !isAutoPx( camelName ) && !jQuery.cssNumber[ camelName ] ) { migrateWarn( "css-number", "Number-typed values are deprecated for jQuery.fn.css( \"" + name + "\", value )" ); diff --git a/src/jquery/deferred.js b/src/jquery/deferred.js index 7f036efe..bb78cd3e 100644 --- a/src/jquery/deferred.js +++ b/src/jquery/deferred.js @@ -3,7 +3,6 @@ import { migratePatchAndWarnFunc, migrateWarn } from "../main.js"; -import { jQueryVersionSince } from "../compareVersions.js"; // Support jQuery slim which excludes the deferred module in jQuery 4.0+ if ( jQuery.Deferred ) { @@ -80,13 +79,8 @@ Object.defineProperty( jQuery.Deferred, "getStackHook", { get: function() { if ( jQuery.migrateIsPatchEnabled( "deferred-getStackHook" ) ) { - // jQuery 3.x checks `getStackHook` if `getErrorHook` missing; - // don't warn on the getter there. - if ( jQueryVersionSince( "4.0.0" ) ) { - migrateWarn( "deferred-getStackHook", - "jQuery.Deferred.getStackHook is deprecated; " + - "use jQuery.Deferred.getErrorHook" ); - } + // jQuery 3.x checks `getStackHook` if `getErrorHook` is missing, + // so don't warn on the getter. return jQuery.Deferred.getErrorHook; } else { return unpatchedGetStackHookValue; diff --git a/src/jquery/selector.js b/src/jquery/selector.js index 44237d30..c1625a12 100644 --- a/src/jquery/selector.js +++ b/src/jquery/selector.js @@ -1,6 +1,75 @@ import { jQueryVersionSince } from "../compareVersions.js"; import { migratePatchFunc, migrateWarnProp, migrateWarn } from "../main.js"; +var findProp, + oldInit = jQuery.fn.init, + oldFind = jQuery.find, + + rattrHashTest = /\[(\s*[-\w]+\s*)([~|^$*]?=)\s*([-\w#]*?#[-\w#]*)\s*\]/, + rattrHashGlob = /\[(\s*[-\w]+\s*)([~|^$*]?=)\s*([-\w#]*?#[-\w#]*)\s*\]/g; + +migratePatchFunc( jQuery.fn, "init", function( arg1 ) { + var args = Array.prototype.slice.call( arguments ); + + if ( jQuery.migrateIsPatchEnabled( "selector-empty-id" ) && + typeof arg1 === "string" && arg1 === "#" ) { + + // JQuery( "#" ) is a bogus ID selector, but it returned an empty set + // before jQuery 3.0 + migrateWarn( "selector-empty-id", "jQuery( '#' ) is not a valid selector" ); + args[ 0 ] = []; + } + + return oldInit.apply( this, args ); +}, "selector-empty-id" ); + +// This is already done in Core but the above patch will lose this assignment +// so we need to redo it. It doesn't matter whether the patch is enabled or not +// as the method is always going to be a Migrate-created wrapper. +jQuery.fn.init.prototype = jQuery.fn; + +migratePatchFunc( jQuery, "find", function( selector ) { + var args = Array.prototype.slice.call( arguments ); + + // Support: PhantomJS 1.x + // String#match fails to match when used with a //g RegExp, only on some strings + if ( typeof selector === "string" && rattrHashTest.test( selector ) ) { + + // The nonstandard and undocumented unquoted-hash was removed in jQuery 1.12.0 + // First see if qS thinks it's a valid selector, if so avoid a false positive + try { + window.document.querySelector( selector ); + } catch ( err1 ) { + + // Didn't *look* valid to qSA, warn and try quoting what we think is the value + selector = selector.replace( rattrHashGlob, function( _, attr, op, value ) { + return "[" + attr + op + "\"" + value + "\"]"; + } ); + + // If the regexp *may* have created an invalid selector, don't update it + // Note that there may be false alarms if selector uses jQuery extensions + try { + window.document.querySelector( selector ); + migrateWarn( "selector-hash", + "Attribute selector with '#' must be quoted: " + args[ 0 ] ); + args[ 0 ] = selector; + } catch ( err2 ) { + migrateWarn( "selector-hash", + "Attribute selector with '#' was not fixed: " + args[ 0 ] ); + } + } + } + + return oldFind.apply( this, args ); +}, "selector-hash" ); + +// Copy properties attached to original jQuery.find method (e.g. .attr, .isXML) +for ( findProp in oldFind ) { + if ( Object.prototype.hasOwnProperty.call( oldFind, findProp ) ) { + jQuery.find[ findProp ] = oldFind[ findProp ]; + } +} + // Now jQuery.expr.pseudos is the standard incantation migrateWarnProp( jQuery.expr, "filters", jQuery.expr.pseudos, "expr-pre-pseudos", "jQuery.expr.filters is deprecated; use jQuery.expr.pseudos" ); diff --git a/src/main.js b/src/main.js index ca6ce5c7..909b6203 100644 --- a/src/main.js +++ b/src/main.js @@ -10,10 +10,10 @@ if ( !window.console || !window.console.log ) { return; } -// Need jQuery 3.x-4.x and no older Migrate loaded +// Need jQuery 3.x and no older Migrate loaded if ( !jQuery || !jQueryVersionSince( "3.0.0" ) || - jQueryVersionSince( "5.0.0" ) ) { - window.console.log( "JQMIGRATE: jQuery 3.x-4.x REQUIRED" ); + jQueryVersionSince( "4.0.0" ) ) { + window.console.log( "JQMIGRATE: jQuery 3.x REQUIRED" ); } if ( jQuery.migrateWarnings ) { window.console.log( "JQMIGRATE: Migrate plugin loaded multiple times" ); diff --git a/test/data/ajax-jsonp-callback-name.html b/test/data/ajax-jsonp-callback-name.html index 2d10331a..fd9766b9 100644 --- a/test/data/ajax-jsonp-callback-name.html +++ b/test/data/ajax-jsonp-callback-name.html @@ -7,7 +7,7 @@