From e430322ba8c34b8ce56caf5b75c9586ab173afb7 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Micha=C5=82=20Go=C5=82e=CC=A8biowski-Owczarek?=
Date: Tue, 5 Nov 2024 23:52:27 +0100
Subject: [PATCH 1/6] Core: Remove support for jQuery 3.x
---
.github/workflows/browserstack-3.x.yml | 84 -
...{browserstack-git.yml => browserstack.yml} | 4 +-
README.md | 16 +-
build/tasks/minify.js | 11 +-
jtr-3.x.yml | 30 -
jtr-git.yml => jtr-ci.yml | 2 +
jtr-local.yml | 15 +-
package-lock.json | 20 +-
package.json | 4 +-
src/jquery/ajax.js | 172 +-
src/jquery/attributes.js | 24 +-
src/jquery/core.js | 310 +-
src/jquery/css.js | 112 +-
src/jquery/deferred.js | 12 +-
src/jquery/effects.js | 40 +-
src/jquery/selector.js | 106 +-
src/main.js | 13 +-
.../{core-jquery2.html => core-jquery3.html} | 2 +-
test/data/iframeTest.js | 5 -
.../data/{jquery-2.2.3.js => jquery-3.7.1.js} | 6410 ++++++++++-------
test/data/testinit.js | 41 +-
test/index.html | 5 +-
test/unit/jquery/ajax.js | 34 +-
test/unit/jquery/attributes.js | 33 +-
test/unit/jquery/core.js | 129 +-
test/unit/jquery/css.js | 81 +-
test/unit/jquery/deferred.js | 26 +-
test/unit/jquery/selector.js | 4 +-
test/unit/migrate.js | 8 +-
warnings.md | 17 +-
30 files changed, 4069 insertions(+), 3701 deletions(-)
delete mode 100644 .github/workflows/browserstack-3.x.yml
rename .github/workflows/{browserstack-git.yml => browserstack.yml} (95%)
delete mode 100644 jtr-3.x.yml
rename jtr-git.yml => jtr-ci.yml (77%)
rename test/data/{core-jquery2.html => core-jquery3.html} (92%)
rename test/data/{jquery-2.2.3.js => jquery-3.7.1.js} (60%)
diff --git a/.github/workflows/browserstack-3.x.yml b/.github/workflows/browserstack-3.x.yml
deleted file mode 100644
index a9748638..00000000
--- a/.github/workflows/browserstack-3.x.yml
+++ /dev/null
@@ -1,84 +0,0 @@
-name: Browserstack (Core 3.x)
-
-on:
- push:
- branches:
- - main
- # Once a week every Tuesday
- schedule:
- - cron: "12 2 * * 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'
- - 'IE_10'
- - 'IE_9'
- - 'Safari_latest'
- - 'Safari_latest-1'
- - 'Chrome_latest'
- - 'Chrome_latest-1'
- - 'Opera_latest'
- - 'Edge_latest'
- - 'Edge_latest-1'
- - 'Edge_18'
- - 'Firefox_latest'
- - 'Firefox_latest-1'
- - 'Firefox_115'
- - 'Firefox_102'
- - 'Firefox_91'
- - 'Firefox_78'
- - 'Firefox_60'
- - 'Firefox_48'
- - '__iOS_18'
- - '__iOS_17'
- - '__iOS_16'
- - '__iOS_15'
- - '__iOS_14'
- - '__iOS_13'
- - '__iOS_12'
- - '__iOS_11'
- - '__iOS_10'
- - '__iOS_9'
- - '__iOS_8'
- steps:
- - name: Checkout
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
-
- - name: Use Node.js ${{ env.NODE_VERSION }}
- uses: actions/setup-node@1d0ff469b7ec7b3cb9d8673fde0c81c44821de2a # v4.2.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-3.x.yml \
- --browserstack "${{ matrix.BROWSER }}" \
- --run-id ${{ github.run_id }} \
diff --git a/.github/workflows/browserstack-git.yml b/.github/workflows/browserstack.yml
similarity index 95%
rename from .github/workflows/browserstack-git.yml
rename to .github/workflows/browserstack.yml
index 40247557..f37103f9 100644
--- a/.github/workflows/browserstack-git.yml
+++ b/.github/workflows/browserstack.yml
@@ -1,4 +1,4 @@
-name: Browserstack (Core git)
+name: Browserstack
on:
push:
@@ -63,6 +63,6 @@ jobs:
- name: Test
run: |
- npm run test:unit -- -v -c jtr-git.yml \
+ npm run test:unit -- -v -c jtr-ci.yml \
--browserstack "${{ matrix.BROWSER }}" \
--run-id ${{ github.run_id }} \
diff --git a/README.md b/README.md
index 5512c8e4..34c384c6 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] |
-
-[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.
+| jQuery version | jQuery Migrate version |
+|----------------|------------------------|
+| 1.x | 1.x |
+| 2.x | 1.x |
+| 3.x | 3.x |
+| 4.x | 4.x |
+
+Each jQuery Migrate version supports the same browsers that the jQuery version used with it.
## Usage
diff --git a/build/tasks/minify.js b/build/tasks/minify.js
index 5f55d27a..6f886063 100644
--- a/build/tasks/minify.js
+++ b/build/tasks/minify.js
@@ -34,19 +34,10 @@ export async function minify( { dir, filename, version } ) {
{
compress: {
hoist_funs: false,
- loops: false,
-
- // Support: IE <11
- // typeofs transformation is unsafe for IE9-10
- // See https://github.com/mishoo/UglifyJS2/issues/2198
- typeofs: false
+ loops: false
},
output: {
ascii_only: true,
-
- // Support: Android 4.0 only, IE 9 only
- // This is in lieu of setting ie for all of mangle, compress, and output
- ie8: true,
preamble: banner
},
sourceMap: {
diff --git a/jtr-3.x.yml b/jtr-3.x.yml
deleted file mode 100644
index ecab32bc..00000000
--- a/jtr-3.x.yml
+++ /dev/null
@@ -1,30 +0,0 @@
-version: 1
-
-runs:
- jquery:
- - 3.x-git
- - 3.x-git.min
- - 3.x-git.slim
- - 3.x-git.slim.min
- - 3.7.1
- - 3.7.1.slim
- - 3.6.4
- - 3.6.4.slim
- - 3.5.1
- - 3.5.1.slim
- - 3.4.1
- - 3.4.1.slim
- - 3.3.1
- - 3.3.1.slim
- - 3.2.1
- - 3.2.1.slim
- - 3.1.1
- - 3.1.1.slim
- - 3.0.0
- - 3.0.0.slim
- plugin:
- - dev
- - min
-
-retries: 2
-hard-retries: 1
diff --git a/jtr-git.yml b/jtr-ci.yml
similarity index 77%
rename from jtr-git.yml
rename to jtr-ci.yml
index ff5ef485..eea0990a 100644
--- a/jtr-git.yml
+++ b/jtr-ci.yml
@@ -6,6 +6,8 @@ runs:
- git.min
- git.slim
- git.slim.min
+ - 4.0.0-beta.2
+ - 4.0.0-beta.2.slim
plugin:
- dev
- min
diff --git a/jtr-local.yml b/jtr-local.yml
index fa5058e1..9a7da180 100644
--- a/jtr-local.yml
+++ b/jtr-local.yml
@@ -6,18 +6,7 @@ flags:
- git.min
- git.slim
- git.slim.min
- - 3.x-git
- - 3.x-git.min
- - 3.x-git.slim
- - 3.x-git.slim.min
- - 3.7.1
- - 3.7.1.slim
- - 3.6.4
- - 3.5.1
- - 3.4.1
- - 3.3.1
- - 3.2.1
- - 3.1.1
- - 3.0.0
+ - 4.0.0-beta.2
+ - 4.0.0-beta.2.slim
retries: 1
diff --git a/package-lock.json b/package-lock.json
index 96b7569f..5dde5f02 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -17,7 +17,7 @@
"eslint-plugin-import": "2.29.1",
"globals": "15.3.0",
"husky": "9.0.11",
- "jquery": "3.7.1",
+ "jquery": "4.0.0-beta.2",
"jquery-test-runner": "0.2.1",
"jsdom": "24.1.0",
"native-promise-only": "0.8.1",
@@ -27,7 +27,7 @@
"uglify-js": "3.9.4"
},
"peerDependencies": {
- "jquery": ">=3 <4"
+ "jquery": ">=4 <5"
}
},
"node_modules/@bazel/runfiles": {
@@ -879,10 +879,11 @@
"license": "MIT"
},
"node_modules/cross-spawn": {
- "version": "7.0.3",
- "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz",
- "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==",
+ "version": "7.0.6",
+ "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz",
+ "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==",
"dev": true,
+ "license": "MIT",
"dependencies": {
"path-key": "^3.1.0",
"shebang-command": "^2.0.0",
@@ -2421,10 +2422,11 @@
"dev": true
},
"node_modules/jquery": {
- "version": "3.7.1",
- "resolved": "https://registry.npmjs.org/jquery/-/jquery-3.7.1.tgz",
- "integrity": "sha512-m4avr8yL8kmFN8psrbFFFmB/If14iN5o9nw/NgnnM+kybDJpRsAynV2BsfpTYrTRysYUdADVD7CkUUizgkpLfg==",
- "dev": true
+ "version": "4.0.0-beta.2",
+ "resolved": "https://registry.npmjs.org/jquery/-/jquery-4.0.0-beta.2.tgz",
+ "integrity": "sha512-2/cB7q2vtwltOGph8cNaNBRfVRdewrgdmYipXJ9ZYLQOPYjBKHH8+l5ZLVTFV7emKVIPXwDP3excXS0zUcx9kw==",
+ "dev": true,
+ "license": "MIT"
},
"node_modules/jquery-test-runner": {
"version": "0.2.1",
diff --git a/package.json b/package.json
index c52a71ce..e18fbd24 100644
--- a/package.json
+++ b/package.json
@@ -34,7 +34,7 @@
"test": "npm run test:node_smoke_tests && npm run test:browser"
},
"peerDependencies": {
- "jquery": ">=3 <4"
+ "jquery": ">=4 <5"
},
"devDependencies": {
"chalk": "5.4.1",
@@ -45,7 +45,7 @@
"eslint-plugin-import": "2.29.1",
"globals": "15.3.0",
"husky": "9.0.11",
- "jquery": "3.7.1",
+ "jquery": "4.0.0-beta.2",
"jquery-test-runner": "0.2.1",
"jsdom": "24.1.0",
"native-promise-only": "0.8.1",
diff --git a/src/jquery/ajax.js b/src/jquery/ajax.js
index 91555749..9dd670ca 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
@@ -45,120 +44,95 @@ 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 ) {
- // 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;
+ }
- 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;
}
- 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 ];
+ };
- // 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;
- };
+ // Force json dataType
+ s.dataTypes[ 0 ] = "json";
- // Clean-up function (fires after converters)
- jqXHR.always( function() {
+ // Install callback
+ overwritten = window[ callbackName ];
+ window[ callbackName ] = function() {
+ responseContainer = arguments;
+ };
- // If previous value didn't exist - remove it
- if ( overwritten === undefined ) {
- jQuery( window ).removeProp( callbackName );
+ // Clean-up function (fires after converters)
+ jqXHR.always( function() {
- // Otherwise restore preexisting value
- } else {
- window[ callbackName ] = overwritten;
- }
+ // If previous value didn't exist - remove it
+ if ( overwritten === undefined ) {
+ jQuery( window ).removeProp( callbackName );
- // 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 ] );
- }
+ // Otherwise restore preexisting value
+ } else {
+ window[ callbackName ] = overwritten;
+ }
- responseContainer = overwritten = undefined;
- } );
+ // Save back as free
+ if ( s[ callbackName ] ) {
- // Delegate to script
- return "script";
- }
- } );
-} else {
+ // Make sure that re-using the options doesn't screw things around
+ s.jsonpCallback = originalSettings.jsonpCallback;
- // 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 ) {
+ // Save the callback name for future use
+ oldCallbacks.push( callbackName );
+ }
- if ( !jQuery.migrateIsPatchEnabled( "jsonp-promotion" ) ) {
- return;
- }
+ // Call if it was a function and we have a response
+ if ( responseContainer && typeof overwritten === "function" ) {
+ overwritten( responseContainer[ 0 ] );
+ }
- // 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" );
- }
- } );
-}
+ responseContainer = overwritten = undefined;
+ } );
+ // Delegate to script
+ return "script";
+ }
+} );
-// 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" );
-}
+// Don't trigger the above logic 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.
+jQuery.migrateDisablePatches( "jsonp-promotion" );
}
diff --git a/src/jquery/attributes.js b/src/jquery/attributes.js
index f76b1499..28fba978 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,
@@ -37,14 +36,7 @@ jQuery.each( booleans.split( "|" ), function( _i, name ) {
"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;
+ return name.toLowerCase();
}
}
@@ -72,20 +64,6 @@ jQuery.each( booleans.split( "|" ), function( _i, name ) {
}
return name;
}
- } else if ( !jQueryVersionSince( "4.0.0" ) ) {
-
- // 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.
- if ( value === false ) {
-
- // Remove boolean attributes when set to false
- jQuery.removeAttr( elem, name );
- } else {
- elem.setAttribute( name, name );
- }
- return name;
}
}
};
diff --git a/src/jquery/core.js b/src/jquery/core.js
index 7d92fefd..171bca13 100644
--- a/src/jquery/core.js
+++ b/src/jquery/core.js
@@ -1,104 +1,17 @@
-import { jQueryVersionSince } from "../compareVersions.js";
-import {
- migratePatchFunc,
- migrateWarn,
- migratePatchAndWarnFunc,
- migrateWarnProp
-} from "../main.js";
+import { migrateWarnProp, migratePatchAndWarnFunc } from "../main.js";
import "../disablePatches.js";
-var findProp,
- arr = [],
+var arr = [],
push = arr.push,
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.
rtrim = /^[\s\uFEFF\xA0]+|([^\s\uFEFF\xA0])[\s\uFEFF\xA0]+$/g;
-function isFunction( obj ) {
-
- // Support: Chrome <=57, Firefox <=52
- // In some browsers, typeof returns "function" for HTML