diff --git a/.editorconfig b/.editorconfig
index a7ed4a83a5..0fe2cbbba5 100644
--- a/.editorconfig
+++ b/.editorconfig
@@ -3,26 +3,13 @@
root = true
-
[*]
+indent_style = tab
end_of_line = lf
charset = utf-8
trim_trailing_whitespace = true
insert_final_newline = true
-# Tabs in JS unless otherwise specified
-[**.js]
-indent_style = tab
-
-[test/**.xml]
-indent_style = tab
-
-[test/**.php]
-indent_style = tab
-
-[test/**.html]
-indent_style = tab
-
-[test/**.css]
+[*.{json,yml}]
indent_style = space
-indent_size = 8
+indent_size = 2
diff --git a/.gitattributes b/.gitattributes
index b7ca95b5b7..5832a0194d 100644
--- a/.gitattributes
+++ b/.gitattributes
@@ -2,4 +2,7 @@
* text=auto
# JS files must always use LF for tools to work
+# JS files may have mjs or cjs extensions now as well
*.js eol=lf
+*.cjs eol=lf
+*.mjs eol=lf
diff --git a/.github/ISSUE_TEMPLATE.md b/.github/ISSUE_TEMPLATE.md
new file mode 100644
index 0000000000..bd4bae5ef8
--- /dev/null
+++ b/.github/ISSUE_TEMPLATE.md
@@ -0,0 +1,24 @@
+
+
+### Description ###
+
+
+### Link to test case ###
+
diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md
new file mode 100644
index 0000000000..ec0910b10e
--- /dev/null
+++ b/.github/PULL_REQUEST_TEMPLATE.md
@@ -0,0 +1,18 @@
+### Summary ###
+
+
+
+### Checklist ###
+
+
+* [ ] New tests have been added to show the fix or feature works
+* [ ] If needed, a docs issue/PR was created at https://github.com/jquery/api.jquery.com
+
+
diff --git a/.github/dependabot.yml b/.github/dependabot.yml
new file mode 100644
index 0000000000..aa2f745652
--- /dev/null
+++ b/.github/dependabot.yml
@@ -0,0 +1,13 @@
+version: 2
+updates:
+ - package-ecosystem: github-actions
+ directory: "/"
+ schedule:
+ interval: monthly
+
+ # Group all dependabot version update PRs into one
+ groups:
+ github-actions:
+ applies-to: version-updates
+ patterns:
+ - "*"
diff --git a/.github/workflows/browser-tests-beta.yml b/.github/workflows/browser-tests-beta.yml
new file mode 100644
index 0000000000..c8aab022c7
--- /dev/null
+++ b/.github/workflows/browser-tests-beta.yml
@@ -0,0 +1,253 @@
+name: Browser Tests (Beta)
+
+on:
+ schedule:
+ # Run weekly on Sunday at 3 AM UTC to catch beta browser updates
+ - cron: '0 3 * * 0'
+ workflow_dispatch:
+ # Allow manual triggering from the Actions tab
+
+permissions:
+ contents: read # to fetch code (actions/checkout)
+
+env:
+ NODE_VERSION: 24.x
+
+jobs:
+ chrome-beta:
+ runs-on: ubuntu-latest
+ name: Chrome Beta
+ steps:
+ - name: Checkout
+ uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
+
+ - name: Use Node.js ${{ env.NODE_VERSION }}
+ uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
+ with:
+ node-version: ${{ env.NODE_VERSION }}
+ cache: npm
+ cache-dependency-path: '**/package-lock.json'
+
+ - name: Install Chrome Beta
+ run: |
+ # Chrome Beta from `@puppeteer/browsers` is a Chrome for Testing build.
+ # This version lacks the sandbox setup that the APT-packaged Chrome has,
+ # causing crashes on Ubuntu 23.10+ due to AppArmor restrictions.
+ # Because of that, install Chrome Beta from Google's official APT repo.
+ wget -q -O - https://dl-ssl.google.com/linux/linux_signing_key.pub | sudo apt-key add -
+ echo "deb [arch=amd64] http://dl.google.com/linux/chrome/deb/ stable main" | sudo tee /etc/apt/sources.list.d/google-chrome.list
+ sudo apt-get update
+ sudo apt-get install -y google-chrome-beta
+
+ - name: Install ChromeDriver Beta
+ run: |
+ # ChromeDriver is not available in the APT repo, so let's install
+ # it using `@puppeteer/browsers`.
+ CHROME_VERSION=$(google-chrome-beta --version | grep -oP '\d+\.\d+\.\d+\.\d+')
+ echo "Chrome Beta version: $CHROME_VERSION"
+
+ # Install matching ChromeDriver using @puppeteer/browsers
+ # The output format is: "chromedriver@ "
+ INSTALL_OUTPUT=$(npx @puppeteer/browsers install chromedriver@$CHROME_VERSION)
+ CHROMEDRIVER_PATH=$(echo "$INSTALL_OUTPUT" | grep "^chromedriver@" | cut -d' ' -f2)
+ echo "ChromeDriver installed at: $CHROMEDRIVER_PATH"
+
+ # Add ChromeDriver directory to PATH (prepend to override system chromedriver)
+ CHROMEDRIVER_DIR=$(dirname "$CHROMEDRIVER_PATH")
+ echo "PATH=$CHROMEDRIVER_DIR:$PATH" >> "$GITHUB_ENV"
+
+ # Set Chrome binary
+ echo "CHROME_BIN=$(which google-chrome-beta)" >> "$GITHUB_ENV"
+
+ # Verify installations
+ google-chrome-beta --version
+ "$CHROMEDRIVER_PATH" --version
+
+ - name: Install dependencies
+ run: npm ci
+
+ - name: Run Chrome Beta tests
+ id: run-chrome-tests
+ run: npm run test:chrome
+ continue-on-error: true # Beta browsers may have bugs
+
+ outputs:
+ test-result: ${{ steps.run-chrome-tests.outcome }}
+
+ firefox-beta:
+ runs-on: ubuntu-latest
+ name: Firefox Beta
+ steps:
+ - name: Checkout
+ uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
+
+ - name: Use Node.js ${{ env.NODE_VERSION }}
+ uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
+ with:
+ node-version: ${{ env.NODE_VERSION }}
+ cache: npm
+ cache-dependency-path: '**/package-lock.json'
+
+ - name: Install Firefox Beta
+ run: |
+ wget --no-verbose "https://download.mozilla.org/?product=firefox-beta-latest-ssl&lang=en-US&os=linux64" -O - | tar -Jx -C "$HOME"
+
+ - name: Set Firefox Beta as default
+ run: |
+ echo "PATH=${HOME}/firefox:$PATH" >> "$GITHUB_ENV"
+ echo "FIREFOX_BIN=${HOME}/firefox/firefox" >> "$GITHUB_ENV"
+ "$HOME/firefox/firefox" --version
+ echo "Firefox Beta installed at: $HOME/firefox/firefox"
+
+ - name: Install dependencies
+ run: npm ci
+
+ - name: Run Firefox Beta tests
+ id: run-firefox-tests
+ run: npm run test:firefox
+ continue-on-error: true # Beta browsers may have bugs
+
+ outputs:
+ test-result: ${{ steps.run-firefox-tests.outcome }}
+
+ safari-tp:
+ runs-on: macos-latest
+ name: Safari Technology Preview
+ steps:
+ - name: Checkout
+ uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
+
+ - name: Use Node.js ${{ env.NODE_VERSION }}
+ uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
+ with:
+ node-version: ${{ env.NODE_VERSION }}
+ cache: npm
+ cache-dependency-path: '**/package-lock.json'
+
+ - name: Install Safari Technology Preview
+ run: |
+ # Install Safari Technology Preview via Homebrew Cask
+ brew install --cask safari-technology-preview
+
+ # Verify installation
+ if [ -d "/Applications/Safari Technology Preview.app" ]; then
+ echo "Safari Technology Preview installed successfully"
+ else
+ echo "Safari TP installation verification failed"
+ exit 1
+ fi
+
+ - name: Enable Safari Technology Preview driver
+ run: sudo /Applications/Safari\ Technology\ Preview.app/Contents/MacOS/safaridriver --enable
+
+ - name: Install dependencies
+ run: npm ci
+
+ - name: Run Safari Technology Preview tests
+ id: run-safari-tests
+ run: npm run test:safari -- --safari-tp
+ continue-on-error: true # Beta browsers may have bugs
+
+ outputs:
+ test-result: ${{ steps.run-safari-tests.outcome }}
+
+ notify:
+ runs-on: ubuntu-latest
+ name: Notify on Failure
+ needs: [chrome-beta, firefox-beta, safari-tp]
+ environment: matrix-notifications
+
+ # `always()` is needed because jobs with `needs` are skipped if any
+ # dependency fails - and we need it exactly in such cases.
+ if: >-
+ always() && (
+ needs.chrome-beta.outputs.test-result == 'failure' ||
+ needs.firefox-beta.outputs.test-result == 'failure' ||
+ needs.safari-tp.outputs.test-result == 'failure'
+ )
+ steps:
+ - name: Prepare failure message
+ id: prepare-message
+ run: |
+ FAILED_BROWSERS=()
+ if [ "${{ needs.chrome-beta.outputs.test-result }}" == "failure" ]; then
+ FAILED_BROWSERS+=("Chrome Beta")
+ fi
+ if [ "${{ needs.firefox-beta.outputs.test-result }}" == "failure" ]; then
+ FAILED_BROWSERS+=("Firefox Beta")
+ fi
+ if [ "${{ needs.safari-tp.outputs.test-result }}" == "failure" ]; then
+ FAILED_BROWSERS+=("Safari Technology Preview")
+ fi
+ # Join array elements with ", "
+ printf -v FAILED_BROWSERS_STR '%s, ' "${FAILED_BROWSERS[@]}"
+ FAILED_BROWSERS_STR="${FAILED_BROWSERS_STR%, }"
+ echo "failed_browsers=$FAILED_BROWSERS_STR" >> "$GITHUB_OUTPUT"
+
+ - name: Send Matrix notification
+ env:
+ MATRIX_USER: jquerybot
+ MATRIX_PASSWORD: ${{ secrets.MATRIX_PASSWORD }}
+ MATRIX_ROOM_ID: ${{ secrets.MATRIX_ROOM_ID }}
+ run: |
+ # Skip if credentials are not configured (e.g., on forks)
+ if [ -z "$MATRIX_PASSWORD" ] || [ -z "$MATRIX_ROOM_ID" ]; then
+ echo "Matrix credentials not configured, skipping notification"
+ exit 0
+ fi
+
+ # Log in to Matrix to get an access token
+ LOGIN_DATA=$(jq -n \
+ --arg user "$MATRIX_USER" \
+ --arg password "$MATRIX_PASSWORD" \
+ '{
+ type: "m.login.password",
+ identifier: {
+ type: "m.id.user",
+ user: $user
+ },
+ password: $password
+ }')
+
+ # See https://spec.matrix.org/latest/client-server-api/#post_matrixclientv3login
+ LOGIN_RESPONSE=$(curl -sf -X POST \
+ -H "Content-Type: application/json" \
+ --data "$LOGIN_DATA" \
+ "https://matrix.org/_matrix/client/v3/login")
+
+ ACCESS_TOKEN=$(echo "$LOGIN_RESPONSE" | jq -r '.access_token')
+
+ if [ -z "$ACCESS_TOKEN" ] || [ "$ACCESS_TOKEN" == "null" ]; then
+ echo "Failed to log in to Matrix"
+ echo "$LOGIN_RESPONSE"
+ exit 1
+ fi
+
+ MESSAGE="⚠️ jQuery tests failed in beta browser(s): ${{ steps.prepare-message.outputs.failed_browsers }}
+
+ View workflow run: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}"
+
+ MESSAGE_HTML="⚠️ jQuery tests failed in beta browser(s): ${{ steps.prepare-message.outputs.failed_browsers }}
View workflow run
"
+
+ MESSAGE_DATA=$(jq -n \
+ --arg body "$MESSAGE" \
+ --arg formatted_body "$MESSAGE_HTML" \
+ '{
+ msgtype: "m.text",
+ body: $body,
+ format: "org.matrix.custom.html",
+ formatted_body: $formatted_body
+ }')
+
+ # Send message to Matrix room
+ curl -sf -X PUT \
+ -H "Authorization: Bearer $ACCESS_TOKEN" \
+ -H "Content-Type: application/json" \
+ --data "$MESSAGE_DATA" \
+ "https://matrix.org/_matrix/client/v3/rooms/$MATRIX_ROOM_ID/send/m.room.message/$(date +%s%N)"
+
+ # Log out to invalidate the access token
+ curl -sf -X POST \
+ -H "Authorization: Bearer $ACCESS_TOKEN" \
+ "https://matrix.org/_matrix/client/v3/logout"
+
diff --git a/.github/workflows/browser-tests.yml b/.github/workflows/browser-tests.yml
new file mode 100644
index 0000000000..227085cece
--- /dev/null
+++ b/.github/workflows/browser-tests.yml
@@ -0,0 +1,102 @@
+name: Browser Tests
+
+on:
+ pull_request:
+ push:
+ branches-ignore: "dependabot/**"
+
+permissions:
+ contents: read # to fetch code (actions/checkout)
+
+env:
+ NODE_VERSION: 24.x
+
+jobs:
+ build-and-test:
+ runs-on: ubuntu-latest
+ name: ${{ matrix.NPM_SCRIPT }} - ${{ matrix.NAME }}
+ strategy:
+ fail-fast: false
+ matrix:
+ NAME: ["Chrome"]
+ NPM_SCRIPT: ["test:slim", "test:no-deprecated", "test:selector-native", "test:esm"]
+ include:
+ - NAME: "Chrome/Firefox"
+ NPM_SCRIPT: "test:browser"
+ - NAME: "Firefox ESR (new)"
+ NPM_SCRIPT: "test:firefox"
+ - NAME: "Firefox ESR (old)"
+ NPM_SCRIPT: "test:firefox"
+ steps:
+ - name: Checkout
+ uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
+
+ - name: Use Node.js ${{ env.NODE_VERSION }}
+ uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
+ with:
+ node-version: ${{ env.NODE_VERSION }}
+ cache: npm
+ cache-dependency-path: '**/package-lock.json'
+
+ - name: Set download URL for Firefox ESR (old)
+ run: |
+ echo "FIREFOX_SOURCE_URL=https://download.mozilla.org/?product=firefox-esr-latest-ssl&lang=en-US&os=linux64" >> "$GITHUB_ENV"
+ if: contains(matrix.NAME, 'Firefox ESR (old)')
+
+ - name: Set download URL for Firefox ESR (new)
+ run: |
+ echo "FIREFOX_SOURCE_URL=https://download.mozilla.org/?product=firefox-esr-next-latest-ssl&lang=en-US&os=linux64" >> "$GITHUB_ENV"
+ if: contains(matrix.NAME, 'Firefox ESR (new)')
+
+ - name: Install Firefox ESR
+ run: |
+ wget --no-verbose "$FIREFOX_SOURCE_URL" -O - | tar -Jx -C "$HOME"
+ echo "PATH=${HOME}/firefox:$PATH" >> "$GITHUB_ENV"
+ echo "FIREFOX_BIN=${HOME}/firefox/firefox" >> "$GITHUB_ENV"
+ if: contains(matrix.NAME, 'Firefox ESR')
+
+ - name: Install dependencies
+ run: npm ci
+
+ - name: Run tests
+ run: npm run ${{ matrix.NPM_SCRIPT }}
+
+ ie:
+ runs-on: windows-latest
+ name: test:ie - IE
+ steps:
+ - name: Checkout
+ uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
+
+ - name: Use Node.js ${{ env.NODE_VERSION }}
+ uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
+ with:
+ node-version: ${{ env.NODE_VERSION }}
+ cache: npm
+ cache-dependency-path: '**/package-lock.json'
+
+ - name: Install dependencies
+ run: npm ci
+
+ - name: Run tests in Edge in IE mode
+ run: npm run test:ie
+
+ safari:
+ runs-on: macos-latest
+ name: test:safari - Safari
+ steps:
+ - name: Checkout
+ uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
+
+ - name: Use Node.js ${{ env.NODE_VERSION }}
+ uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
+ with:
+ node-version: ${{ env.NODE_VERSION }}
+ cache: npm
+ cache-dependency-path: '**/package-lock.json'
+
+ - name: Install dependencies
+ run: npm ci
+
+ - name: Run tests
+ run: npm run test:safari
diff --git a/.github/workflows/browserstack-dispatch.yml b/.github/workflows/browserstack-dispatch.yml
new file mode 100644
index 0000000000..156fa79196
--- /dev/null
+++ b/.github/workflows/browserstack-dispatch.yml
@@ -0,0 +1,70 @@
+name: Browserstack (Manual Dispatch)
+
+on:
+ workflow_dispatch:
+ inputs:
+ module:
+ description: 'Module to test'
+ required: true
+ type: choice
+ options:
+ - 'basic'
+ - 'ajax'
+ - 'animation'
+ - 'attributes'
+ - 'callbacks'
+ - 'core'
+ - 'css'
+ - 'data'
+ - 'deferred'
+ - 'deprecated'
+ - 'dimensions'
+ - 'effects'
+ - 'event'
+ - 'manipulation'
+ - 'offset'
+ - 'queue'
+ - 'selector'
+ - 'serialize'
+ - 'support'
+ - 'traversing'
+ - 'tween'
+ browser:
+ description: 'Browser to test, in form of \"browser_[browserVersion | :device]_os_osVersion\"'
+ required: false
+ type: string
+ default: 'chrome__windows_11'
+
+permissions:
+ contents: read # to fetch code (actions/checkout)
+
+jobs:
+ test:
+ runs-on: ubuntu-latest
+ environment: browserstack
+ env:
+ BROWSERSTACK_USERNAME: ${{ secrets.BROWSERSTACK_USERNAME }}
+ BROWSERSTACK_ACCESS_KEY: ${{ secrets.BROWSERSTACK_ACCESS_KEY }}
+ steps:
+ - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
+
+ - uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
+ with:
+ node-version: 20
+
+ - name: Install dependencies
+ run: npm ci
+
+ - name: Build jQuery
+ run: npm run build:all
+
+ - name: Pretest script
+ run: npm run pretest
+
+ - name: Run tests
+ env:
+ BROWSER: ${{ inputs.browser }}
+ MODULE: ${{ inputs.module }}
+ run: npm run test:unit -- \
+ -v --browserstack "$BROWSER" \
+ -f "module=$MODULE"
diff --git a/.github/workflows/browserstack.yml b/.github/workflows/browserstack.yml
new file mode 100644
index 0000000000..78af50f223
--- /dev/null
+++ b/.github/workflows/browserstack.yml
@@ -0,0 +1,69 @@
+name: Browserstack
+
+on:
+ push:
+ branches:
+ - main
+
+permissions:
+ contents: read # to fetch code (actions/checkout)
+
+jobs:
+ test:
+ runs-on: ubuntu-latest
+ environment: browserstack
+ env:
+ BROWSERSTACK_USERNAME: ${{ secrets.BROWSERSTACK_USERNAME }}
+ BROWSERSTACK_ACCESS_KEY: ${{ secrets.BROWSERSTACK_ACCESS_KEY }}
+ NODE_VERSION: 24.x
+ name: ${{ matrix.BROWSER }}
+ concurrency:
+ group: ${{ github.workflow }}-${{ matrix.BROWSER }}
+ timeout-minutes: 30
+ strategy:
+ fail-fast: false
+ matrix:
+ BROWSER:
+ - 'IE_11'
+ - 'Safari_latest'
+ # JTR doesn't take into account the jump from Safari 18 to 26,
+ # so we need to specify versions explicitly.
+ # See https://github.com/jquery/jquery-test-runner/issues/17
+ - 'Safari_18'
+ - 'Chrome_latest'
+ - 'Chrome_latest-1'
+ - 'Opera_latest'
+ - 'Edge_latest'
+ - 'Edge_latest-1'
+ - 'Firefox_latest'
+ - 'Firefox_latest-1'
+ - '_:iPhone 17_iOS_26'
+ - '_:iPhone 16_iOS_18'
+ - '_:iPhone 15 Pro_iOS_17'
+ - '_:iPad Air 13 2025_iOS_26'
+ - '_:iPad Air 13 2025_iOS_18'
+ steps:
+ - name: Checkout
+ uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
+
+ - name: Use Node.js ${{ env.NODE_VERSION }}
+ uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
+ with:
+ node-version: ${{ env.NODE_VERSION }}
+ cache: npm
+ cache-dependency-path: '**/package-lock.json'
+
+ - name: Install dependencies
+ run: npm ci
+
+ - name: Build jQuery
+ run: npm run build:all
+
+ - name: Pretest script
+ run: npm run pretest
+
+ - name: Run tests
+ run: |
+ npm run test:unit -- -v -c jtr-isolate.yml \
+ --browserstack "${{ matrix.BROWSER }}" \
+ --run-id ${{ github.run_id }}
diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml
new file mode 100644
index 0000000000..d20c378a78
--- /dev/null
+++ b/.github/workflows/codeql-analysis.yml
@@ -0,0 +1,58 @@
+name: "Code scanning - action"
+
+on:
+ pull_request:
+ push:
+ branches-ignore: "dependabot/**"
+ schedule:
+ - cron: "0 4 * * 6"
+
+permissions:
+ contents: read # to fetch code (actions/checkout)
+
+jobs:
+ CodeQL-Build:
+ permissions:
+ contents: read # to fetch code (actions/checkout)
+ security-events: write # (github/codeql-action/autobuild)
+
+ runs-on: ubuntu-latest
+
+ steps:
+ - name: Checkout repository
+ uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
+ with:
+ # We must fetch at least the immediate parents so that if this is
+ # a pull request then we can checkout the head.
+ fetch-depth: 2
+
+ # If this run was triggered by a pull request event, then checkout
+ # the head of the pull request instead of the merge commit.
+ - run: git checkout HEAD^2
+ if: ${{ github.event_name == 'pull_request' }}
+
+ # Initializes the CodeQL tools for scanning.
+ - name: Initialize CodeQL
+ uses: github/codeql-action/init@7211b7c8077ea37d8641b6271f6a365a22a5fbfa # v4.36.0
+ # Override language selection by uncommenting this and choosing your languages
+ # with:
+ # languages: go, javascript, csharp, python, cpp, java
+
+ # Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
+ # If this step fails, then you should remove it and run the build manually (see below)
+ - name: Autobuild
+ uses: github/codeql-action/autobuild@7211b7c8077ea37d8641b6271f6a365a22a5fbfa # v4.36.0
+
+ # ℹ️ Command-line programs to run using the OS shell.
+ # 📚 https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun
+
+ # ✏️ If the Autobuild fails above, remove it and uncomment the following three lines
+ # and modify them (or add more) to build your code if your project
+ # uses a compiled language
+
+ #- run: |
+ # make bootstrap
+ # make release
+
+ - name: Perform CodeQL Analysis
+ uses: github/codeql-action/analyze@7211b7c8077ea37d8641b6271f6a365a22a5fbfa # v4.36.0
diff --git a/.github/workflows/filestash.yml b/.github/workflows/filestash.yml
new file mode 100644
index 0000000000..a7b2f8d98e
--- /dev/null
+++ b/.github/workflows/filestash.yml
@@ -0,0 +1,60 @@
+name: Filestash
+
+on:
+ push:
+ branches:
+ - main
+
+permissions:
+ contents: read # to fetch code (actions/checkout)
+
+jobs:
+ update:
+ name: Update Filestash
+ runs-on: ubuntu-latest
+ # skip on forks
+ if: ${{ github.repository == 'jquery/jquery' }}
+ environment: filestash
+ env:
+ NODE_VERSION: 24.x
+ steps:
+ - name: Checkout
+ uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
+
+ - name: Use Node.js ${{ env.NODE_VERSION }}
+ uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
+ with:
+ node-version: ${{ env.NODE_VERSION }}
+ cache: npm
+ cache-dependency-path: '**/package-lock.json'
+
+ - name: Install dependencies
+ run: npm ci
+
+ - name: Build
+ run: npm run build:all
+
+ - name: Set up SSH
+ run: |
+ install --directory ~/.ssh --mode 700
+ base64 --decode <<< "${{ secrets.SSH_PRIVATE_KEY }}" > ~/.ssh/id_ed25519
+ chmod 600 ~/.ssh/id_ed25519
+ ssh-keyscan -t ed25519 -H "${{ secrets.FILESTASH_SERVER }}" >> ~/.ssh/known_hosts
+
+ - name: Upload to Filestash
+ run: |
+ rsync dist/jquery.js filestash@"${{ secrets.FILESTASH_SERVER }}":jquery-git.js
+ rsync dist/jquery.min.js filestash@"${{ secrets.FILESTASH_SERVER }}":jquery-git.min.js
+ rsync dist/jquery.min.map filestash@"${{ secrets.FILESTASH_SERVER }}":jquery-git.min.map
+
+ rsync dist/jquery.slim.js filestash@"${{ secrets.FILESTASH_SERVER }}":jquery-git.slim.js
+ rsync dist/jquery.slim.min.js filestash@"${{ secrets.FILESTASH_SERVER }}":jquery-git.slim.min.js
+ rsync dist/jquery.slim.min.map filestash@"${{ secrets.FILESTASH_SERVER }}":jquery-git.slim.min.map
+
+ rsync dist-module/jquery.module.js filestash@"${{ secrets.FILESTASH_SERVER }}":jquery-git.module.js
+ rsync dist-module/jquery.module.min.js filestash@"${{ secrets.FILESTASH_SERVER }}":jquery-git.module.min.js
+ rsync dist-module/jquery.module.min.map filestash@"${{ secrets.FILESTASH_SERVER }}":jquery-git.module.min.map
+
+ rsync dist-module/jquery.slim.module.js filestash@"${{ secrets.FILESTASH_SERVER }}":jquery-git.slim.module.js
+ rsync dist-module/jquery.slim.module.min.js filestash@"${{ secrets.FILESTASH_SERVER }}":jquery-git.slim.module.min.js
+ rsync dist-module/jquery.slim.module.min.map filestash@"${{ secrets.FILESTASH_SERVER }}":jquery-git.slim.module.min.map
diff --git a/.github/workflows/lock-threads.yml b/.github/workflows/lock-threads.yml
new file mode 100644
index 0000000000..94027a25c8
--- /dev/null
+++ b/.github/workflows/lock-threads.yml
@@ -0,0 +1,24 @@
+name: 'Lock Threads'
+
+on:
+ schedule:
+ - cron: '0 2 7 * *'
+ workflow_dispatch:
+
+permissions:
+ issues: write
+ pull-requests: write
+ discussions: write
+
+concurrency:
+ group: lock-threads
+
+jobs:
+ action:
+ runs-on: ubuntu-latest
+ steps:
+ - uses: dessant/lock-threads@89ae32b08ed1a541efecbab17912962a5e38981c # v6.0.2
+ with:
+ issue-inactive-days: 180
+ pr-inactive-days: 180
+ discussion-inactive-days: 180
diff --git a/.github/workflows/node.js.yml b/.github/workflows/node.js.yml
new file mode 100644
index 0000000000..527f149a39
--- /dev/null
+++ b/.github/workflows/node.js.yml
@@ -0,0 +1,44 @@
+name: Node
+
+on:
+ pull_request:
+ push:
+ branches-ignore: "dependabot/**"
+
+permissions:
+ contents: read # to fetch code (actions/checkout)
+
+jobs:
+ build-and-test:
+ runs-on: ubuntu-latest
+ name: ${{ matrix.NPM_SCRIPT }} - ${{ matrix.NAME }} (${{ matrix.NODE_VERSION }})
+ strategy:
+ fail-fast: false
+ matrix:
+ NAME: ["Node"]
+ NODE_VERSION: [20.x, 22.x, 24.x]
+ NPM_SCRIPT: ["test:browserless"]
+ include:
+ - NAME: "Node"
+ NODE_VERSION: "24.x"
+ NPM_SCRIPT: "lint"
+ steps:
+ - name: Checkout
+ uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
+
+ - name: Use Node.js ${{ matrix.NODE_VERSION }}
+ uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
+ with:
+ node-version: ${{ matrix.NODE_VERSION }}
+ cache: npm
+ cache-dependency-path: '**/package-lock.json'
+
+ - name: Install dependencies
+ run: npm ci
+
+ - name: Build all for linting
+ run: npm run build:all
+ if: contains(matrix.NPM_SCRIPT, 'lint')
+
+ - name: Run tests
+ run: npm run ${{ matrix.NPM_SCRIPT }}
diff --git a/.github/workflows/verify-release.yml b/.github/workflows/verify-release.yml
new file mode 100644
index 0000000000..30037f672d
--- /dev/null
+++ b/.github/workflows/verify-release.yml
@@ -0,0 +1,46 @@
+name: Reproducible Builds
+on:
+ push:
+ # On tags
+ tags:
+ - '*'
+ # Or manually
+ workflow_dispatch:
+ inputs:
+ version:
+ description: 'Version to verify (>= 4.0.0-rc.1)'
+ required: false
+
+permissions:
+ contents: read # to fetch code (actions/checkout)
+
+jobs:
+ run:
+ name: Verify release
+ runs-on: ubuntu-latest
+ # skip on forks
+ if: ${{ github.repository == 'jquery/jquery' }}
+ env:
+ NODE_VERSION: 24.x
+ steps:
+ - name: Checkout
+ uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
+
+ - name: Use Node.js ${{ env.NODE_VERSION }}
+ uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
+ with:
+ node-version: ${{ env.NODE_VERSION }}
+
+ - name: Install dependencies
+ run: npm ci
+
+ - name: Verify release
+ uses: nick-fields/retry@ad984534de44a9489a53aefd81eb77f87c70dc60 # v4.0.0
+ with:
+ timeout_minutes: 10
+ max_attempts: 3
+ retry_on: error
+ retry_wait_seconds: 60
+ command: npm run release:verify
+ env:
+ VERSION: ${{ github.event.inputs.version || github.ref_name }}
diff --git a/.gitignore b/.gitignore
index eae5df6e6c..2b984efe70 100644
--- a/.gitignore
+++ b/.gitignore
@@ -3,12 +3,37 @@
*~
*.diff
*.patch
-/*.html
.DS_Store
.bower.json
.sizecache.json
+yarn.lock
+.eslintcache
+tmp
-/dist
+npm-debug.log*
+
+# Ignore built files in `dist` folder
+# Leave the package.json and wrappers
+/dist/*
+!/dist/package.json
+!/dist/wrappers
+
+# Ignore built files in `dist-module` folder
+# Leave the package.json and wrappers
+/dist-module/*
+!/dist-module/package.json
+!/dist-module/wrappers
+
+/external
/node_modules
-/test/node_smoke_tests/lib/ensure_iterability.js
+/test/data/core/jquery-iterability-transpiled.js
+/test/data/qunit-fixture.js
+
+# Release artifacts
+changelog.html
+contributors.html
+
+# Ignore BrowserStack testing files
+local.log
+browserstack.err
diff --git a/.husky/commit-msg b/.husky/commit-msg
new file mode 100755
index 0000000000..199b8aa3ea
--- /dev/null
+++ b/.husky/commit-msg
@@ -0,0 +1,2 @@
+
+npx commitplease .git/COMMIT_EDITMSG
diff --git a/.husky/pre-push b/.husky/pre-push
new file mode 100644
index 0000000000..f9543cf3cc
--- /dev/null
+++ b/.husky/pre-push
@@ -0,0 +1,3 @@
+
+npm run lint
+npm run qunit-fixture
diff --git a/.jscsrc b/.jscsrc
deleted file mode 100644
index c460130a49..0000000000
--- a/.jscsrc
+++ /dev/null
@@ -1,10 +0,0 @@
-{
- "preset": "jquery",
-
- // remove after https://github.com/jscs-dev/node-jscs/issues/1685
- // and https://github.com/jscs-dev/node-jscs/issues/1686
- "requireCapitalizedComments": null,
-
- "excludeFiles": [ "external", "src/intro.js", "src/outro.js",
- "test/node_smoke_tests/lib/ensure_iterability.js", "node_modules" ]
-}
diff --git a/.jshintignore b/.jshintignore
deleted file mode 100644
index 1ddafd635a..0000000000
--- a/.jshintignore
+++ /dev/null
@@ -1,12 +0,0 @@
-external
-src/intro.js
-src/outro.js
-test/data/jquery-1.9.1.js
-test/data/badcall.js
-test/data/badjson.js
-test/data/json_obj.js
-test/data/readywaitasset.js
-test/data/readywaitloader.js
-test/data/support/csp.js
-test/data/support/getComputedSupport.js
-test/node_smoke_tests/lib/ensure_iterability.js
diff --git a/.jshintrc b/.jshintrc
deleted file mode 100644
index 1445c7b18b..0000000000
--- a/.jshintrc
+++ /dev/null
@@ -1,14 +0,0 @@
-{
- "boss": true,
- "curly": true,
- "eqeqeq": true,
- "eqnull": true,
- "expr": true,
- "immed": true,
- "noarg": true,
- "quotmark": "double",
- "undef": true,
- "unused": true,
-
- "node": true
-}
diff --git a/.mailmap b/.mailmap
index 2949a51591..898b77d78b 100644
--- a/.mailmap
+++ b/.mailmap
@@ -4,6 +4,8 @@ Alexander Farkas
Alexander Farkas
Alexis Abril
Andrew E Monat
+Andrey Meshkov
+Andrey Meshkov
Anton Matzneller
Anton Matzneller
Batiste Bieler
@@ -13,6 +15,10 @@ Carl Danley
Carl Fürstenberg
Carl Fürstenberg
Charles McNulty
+Chris Rebert
+Chris Rebert
+Christian Oliff
+Christian Oliff
Christopher Jones cjqed
Colin Snover
Corey Frang
@@ -29,6 +35,7 @@ Devin Cooper
Douglas Neiner
Dmitry Gusev
Earle Castledine
+Ed Sanders
Erick Ruiz de Chávez
Gianni Alessandro Chiappetta
Heungsub Lee
@@ -52,6 +59,8 @@ Josh Varner
Julian Aubourg
Julian Aubourg
Julian Aubourg
+John Firebaugh
+John Firebaugh
Jörn Zaefferer
Jörn Zaefferer
Jörn Zaefferer
@@ -67,13 +76,15 @@ Louis-Rémi Babé
Marcel Greter
Matthias Jäggli
Michael Murray
-Michał Gołębiowski
-Michał Gołębiowski
+Michał Gołębiowski-Owczarek
+Michał Gołębiowski-Owczarek
Mike Alsup
+nanto_vi
Nguyen Phuc Lam
Oleg Gaidarenko
Paul Bakaus
Rafaël Blais Masson
+Renato Oliveira dos Santos
Richard D. Worth
Rick Waldron
Rick Waldron
@@ -85,10 +96,14 @@ Scott González
Scott Jehl
Sebastian Burkhard
Senya Pugach
+Shashanka Nataraj
+Shashanka Nataraj
Thomas Tortorini Mr21
-Timmy Willison
-Timmy Willison
-Timo Tijhof
+Timmy Willison
+Timmy Willison <4timmywil@gmail.com>
+Timmy Willison
+Timmy Willison
+Timo Tijhof
TJ Holowaychuk
Tom H Fuertes
Tom H Fuertes Tom H Fuertes
diff --git a/.npmignore b/.npmignore
index d510949524..2de60f956b 100644
--- a/.npmignore
+++ b/.npmignore
@@ -1,17 +1,15 @@
-.jshintignore
-.jshintrc
+.eslintignore
+.eslintcache
+eslint.config.js
/.editorconfig
/.gitattributes
-/.jscs.json
/.mailmap
-/.travis.yml
+/.sizecache.json
/build
-/speed
+/external
/test
-/Gruntfile.js
-
-/external/qunit
-/external/requirejs
-/external/sinon
+/tmp
+/changelog.html
+/contributors.html
diff --git a/.npmrc b/.npmrc
new file mode 100644
index 0000000000..cffe8cdef1
--- /dev/null
+++ b/.npmrc
@@ -0,0 +1 @@
+save-exact=true
diff --git a/.release-it.cjs b/.release-it.cjs
new file mode 100644
index 0000000000..b4f0128201
--- /dev/null
+++ b/.release-it.cjs
@@ -0,0 +1,49 @@
+"use strict";
+
+const blogURL = process.env.BLOG_URL;
+
+if ( !blogURL || !blogURL.startsWith( "https://blog.jquery.com/" ) ) {
+ throw new Error( "A valid BLOG_URL must be set in the environment" );
+}
+
+module.exports = {
+ preReleaseBase: 1,
+ hooks: {
+ "before:init": "./build/release/pre-release.sh",
+ "after:version:bump":
+ "sed -i '' -e 's|main/AUTHORS.txt|${version}/AUTHORS.txt|' package.json",
+ "after:bump": "cross-env VERSION=${version} npm run build:all",
+ "before:git:release": "git add -f dist/ dist-module/ changelog.md",
+ "after:release": "echo 'Run the following to complete the release:' && " +
+ `echo './build/release/post-release.sh $\{version} ${ blogURL }'`
+ },
+ git: {
+
+ // Use the node script directly to avoid an npm script
+ // command log entry in the GH release notes
+ changelog: "node build/release/changelog.js ${from} ${to}",
+ commitMessage: "Release: ${version}",
+ getLatestTagFromAllRefs: true,
+ pushRepo: "git@github.com:jquery/jquery.git",
+ requireBranch: "main",
+ requireCleanWorkingDir: true,
+ commit: true,
+ commitArgs: [ "-S" ],
+ tag: true,
+ tagName: "${version}",
+ tagAnnotation: "Release: ${version}",
+ tagArgs: [ "-s" ]
+ },
+ github: {
+ pushRepo: "git@github.com:jquery/jquery.git",
+ release: true,
+ tokenRef: "JQUERY_GITHUB_TOKEN"
+ },
+ npm: {
+
+ // We're publishing from a dist folder generated in the post-release
+ // step, so we also need to publish by ourselves; release-it would
+ // do it too early.
+ publish: false
+ }
+};
diff --git a/.travis.yml b/.travis.yml
deleted file mode 100644
index 19136e9407..0000000000
--- a/.travis.yml
+++ /dev/null
@@ -1,6 +0,0 @@
-language: node_js
-sudo: false
-node_js:
-- "0.10"
-- "0.12"
-- "4"
diff --git a/AUTHORS.txt b/AUTHORS.txt
index 58c73afbc9..4e295ee268 100644
--- a/AUTHORS.txt
+++ b/AUTHORS.txt
@@ -20,16 +20,23 @@ David Serduke
Richard D. Worth
Scott González
Ariel Flesler
+Cheah Chu Yeow
+Andrew Chalkley
+Fabio Buffoni
+Stefan Bauckmeier
Jon Evans
TJ Holowaychuk
+Riccardo De Agostini
Michael Bensoussan
-Robert Katić
Louis-Rémi Babé
-Earle Castledine
+Robert Katić
Damian Janowski
+Dušan B. Jovanovic
+Earle Castledine
Rich Dougherty
Kim Dalsgaard
Andrea Giammarchi
+Fabian Jakobs
Mark Gibson
Karl Swedberg
Justin Meyer
@@ -37,9 +44,10 @@ Ben Alman
James Padolsey
David Petersen
Batiste Bieler
+Jake Archibald
Alexander Farkas
-Rick Waldron
Filipe Fortes
+Rick Waldron
Neeraj Singh
Paul Irish
Iraê Carvalho
@@ -47,17 +55,18 @@ Matt Curry
Michael Monteleone
Noah Sloan
Tom Viner
+J. Ryan Stinnett
Douglas Neiner
Adam J. Sontag
+Heungsub Lee
Dave Reed
-Ralph Whitbeck
Carl Fürstenberg
Jacob Wright
-J. Ryan Stinnett
+Ralph Whitbeck
unknown
temp01
-Heungsub Lee
Colin Snover
+Jared Grippe
Ryan W Tenney
Pinhook
Ron Otten
@@ -73,11 +82,11 @@ Scott Jehl
James Burke
Jonas Pfenniger
Xavi Ramirez
-Jared Grippe
Sylvester Keil
Brandon Sterne
Mathias Bynens
-Timmy Willison
+Lee Carpenter
+Timmy Willison
Corey Frang
Digitalxero
Anton Kovalyov
@@ -87,7 +96,6 @@ Charles McNulty
Jordan Boesch
Jess Thrysoee
Michael Murray
-Lee Carpenter
Alexis Abril
Rob Morgan
John Firebaugh
@@ -103,16 +111,17 @@ Mike Sherov
Greg Hazel
Schalk Neethling
Denis Knauf
-Timo Tijhof
+Timo Tijhof
Steen Nielsen
Anton Ryzhov
Shi Chuan
+Matt Mueller
Berker Peksag
Toby Brain
-Matt Mueller
Justin
Daniel Herman
Oleg Gaidarenko
+Rock Hymas
Richard Gibson
Rafaël Blais Masson
cmc3cn <59194618@qq.com>
@@ -124,6 +133,7 @@ Andrew E Monat
Oskari
Joao Henrique de Andrade Bruni
tsinha
+Dominik D. Geyer
Matt Farmer
Trey Hunner
Jason Moon
@@ -132,22 +142,29 @@ Kris Borchers
Vladimir Zhuravlev
Jacob Thornton
Chad Killingsworth
+Vitya Muhachev
Nowres Rafid
David Benjamin
+Alan Plum
Uri Gilad
Chris Faulkner
+Marcel Greter
Elijah Manor
Daniel Chatfield
Nikita Govorov
Wesley Walser
Mike Pennisi
+Matthias Jäggli
+Devin Cooper
Markus Staab
Dave Riddle
Callum Macrae
+Jonathan Sampson
Benjamin Truyman
James Huston
Erick Ruiz de Chávez
David Bonner
+Allen J Schmidt Jr
Akintayo Akinwunmi
MORGAN
Ismail Khair
@@ -159,24 +176,19 @@ Sai Lung Wong
Tom H Fuertes
Roland Eckl
Jay Merrifield
-Allen J Schmidt Jr
-Jonathan Sampson
-Marcel Greter