mirror of
https://github.com/jquery/jquery.git
synced 2024-11-23 02:54:22 +00:00
Build: migrate most grunt tasks off of grunt
Updated tasks include: - lint - npmcopy - build, minify, and process for distribution. - new custom build command using yargs - compare size of minified/gzip built files - pretest scripts, including qunit-fixture, babel transpilation, and npmcopy - node smoke tests - promises aplus tests - new watch task using `rollup.watch` directly Also: - upgraded husky and added the new lint command - updated lint config to use new "flat" config format. See https://eslint.org/docs/latest/use/configure/configuration-files-new - Temporarily disabled one lint rule until flat config is supported by eslint-plugin-import. See https://github.com/import-js/eslint-plugin-import/issues/2556 - committed package-lock.json - updated all test scripts to use the new build - added an express test server that uses middleware-mockserver (this can be used to run tests without karma) - build-all-variants is now build:all Close gh-5318
This commit is contained in:
parent
f75daab091
commit
2bdecf8b7b
@ -10,7 +10,7 @@ charset = utf-8
|
||||
trim_trailing_whitespace = true
|
||||
insert_final_newline = true
|
||||
|
||||
[package.json]
|
||||
[*.{json,yml}]
|
||||
indent_style = space
|
||||
indent_size = 2
|
||||
|
||||
|
@ -1,22 +0,0 @@
|
||||
external
|
||||
node_modules
|
||||
*.min.js
|
||||
dist/**
|
||||
!dist/jquery.js
|
||||
!dist/jquery.min.js
|
||||
!dist/jquery.slim.js
|
||||
!dist/jquery.slim.min.js
|
||||
dist-module/**
|
||||
!dist-module/jquery.module.js
|
||||
!dist-module/jquery.module.min.js
|
||||
!dist-module/jquery.slim.module.js
|
||||
!dist-module/jquery.slim.module.min.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/data/core/jquery-iterability-transpiled.js
|
@ -1,27 +0,0 @@
|
||||
{
|
||||
"root": true,
|
||||
|
||||
"extends": "jquery",
|
||||
|
||||
"reportUnusedDisableDirectives": true,
|
||||
|
||||
"parserOptions": {
|
||||
"ecmaVersion": 5
|
||||
},
|
||||
|
||||
// The browser env is not enabled on purpose so that code takes
|
||||
// all browser-only globals from window instead of assuming
|
||||
// they're available as globals. This makes it possible to use
|
||||
// jQuery with tools like jsdom which provide a custom window
|
||||
// implementation.
|
||||
"env": {},
|
||||
|
||||
"globals": {
|
||||
"window": true
|
||||
},
|
||||
|
||||
"rules": {
|
||||
"one-var": ["error", {"var": "always"}],
|
||||
"strict": ["error", "function"]
|
||||
}
|
||||
}
|
@ -1,20 +0,0 @@
|
||||
{
|
||||
"root": true,
|
||||
|
||||
"extends": "jquery",
|
||||
|
||||
"reportUnusedDisableDirectives": true,
|
||||
|
||||
"parserOptions": {
|
||||
"ecmaVersion": 2018
|
||||
},
|
||||
|
||||
"env": {
|
||||
"es6": true,
|
||||
"node": true
|
||||
},
|
||||
|
||||
"rules": {
|
||||
"strict": ["error", "global"]
|
||||
}
|
||||
}
|
@ -1,5 +0,0 @@
|
||||
{
|
||||
"root": true,
|
||||
|
||||
"extends": "./.eslintrc-node.json"
|
||||
}
|
18
.github/workflows/node.js.yml
vendored
18
.github/workflows/node.js.yml
vendored
@ -61,15 +61,25 @@ jobs:
|
||||
run: |
|
||||
export FIREFOX_SOURCE_URL='https://download.mozilla.org/?product=firefox-esr-latest&lang=en-US&os=linux64'
|
||||
wget --no-verbose $FIREFOX_SOURCE_URL -O - | tar -jx -C ${HOME}
|
||||
if: "contains(matrix.NAME, 'Firefox ESR')"
|
||||
if: contains(matrix.NAME, 'Firefox ESR')
|
||||
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
npm install
|
||||
run: npm install
|
||||
|
||||
- name: Install Playwright dependencies
|
||||
run: npx playwright-webkit install-deps
|
||||
if: "matrix.NPM_SCRIPT == 'test:browser' && contains(matrix.BROWSERS, 'WebkitHeadless')"
|
||||
if: matrix.NPM_SCRIPT == 'test:browser' && contains(matrix.BROWSERS, 'WebkitHeadless')
|
||||
|
||||
- name: Build jQuery for Lint
|
||||
run: npm run build:all
|
||||
if: matrix.NPM_SCRIPT == 'test:browserless'
|
||||
|
||||
- name: Lint code
|
||||
run: npm run lint
|
||||
if: matrix.NODE_VERSION == '18.x'
|
||||
|
||||
- name: Prepare tests
|
||||
run: npm run pretest
|
||||
|
||||
- name: Run tests
|
||||
env:
|
||||
|
7
.gitignore
vendored
7
.gitignore
vendored
@ -8,19 +8,18 @@
|
||||
.bower.json
|
||||
.sizecache.json
|
||||
yarn.lock
|
||||
package-lock.json
|
||||
.eslintcache
|
||||
|
||||
npm-debug.log*
|
||||
|
||||
# Ignore everything in `dist` folder except for the ESLint config
|
||||
# Ignore everything in `dist` folder except for
|
||||
# the ESLint config & package.json files
|
||||
/dist/*
|
||||
!/dist/.eslintrc.json
|
||||
!/dist/package.json
|
||||
|
||||
# Ignore everything in the `dist-module` folder except for the ESLint config,
|
||||
# package.json & Node module wrapper files
|
||||
/dist-module/*
|
||||
!/dist-module/.eslintrc.json
|
||||
!/dist-module/package.json
|
||||
!/dist-module/jquery.node-module-wrapper.js
|
||||
!/dist-module/jquery.node-module-wrapper.slim.js
|
||||
|
4
.husky/commit-msg
Executable file
4
.husky/commit-msg
Executable file
@ -0,0 +1,4 @@
|
||||
#!/usr/bin/env sh
|
||||
. "$(dirname -- "$0")/_/husky.sh"
|
||||
|
||||
npx commitplease .git/COMMIT_EDITMSG
|
5
.husky/pre-commit
Executable file
5
.husky/pre-commit
Executable file
@ -0,0 +1,5 @@
|
||||
#!/usr/bin/env sh
|
||||
. "$(dirname -- "$0")/_/husky.sh"
|
||||
|
||||
npm run lint
|
||||
npm run qunit-fixture
|
@ -1,5 +1,5 @@
|
||||
.eslintignore
|
||||
.eslintrc.json
|
||||
eslint.config.js
|
||||
|
||||
/.editorconfig
|
||||
/.gitattributes
|
||||
|
264
Gruntfile.cjs
264
Gruntfile.cjs
@ -1,20 +1,6 @@
|
||||
"use strict";
|
||||
|
||||
module.exports = function( grunt ) {
|
||||
function readOptionalJSON( filepath ) {
|
||||
const stripJSONComments = require( "strip-json-comments" );
|
||||
let data = {};
|
||||
try {
|
||||
data = JSON.parse( stripJSONComments(
|
||||
fs.readFileSync( filepath, { encoding: "utf8" } )
|
||||
) );
|
||||
} catch ( e ) {}
|
||||
return data;
|
||||
}
|
||||
|
||||
const fs = require( "fs" );
|
||||
const { spawn } = require( "child_process" );
|
||||
const gzip = require( "gzip-js" );
|
||||
const nodeV16OrNewer = !/^v1[0-5]\./.test( process.version );
|
||||
const nodeV17OrNewer = !/^v1[0-6]\./.test( process.version );
|
||||
const customBrowsers = process.env.BROWSERS && process.env.BROWSERS.split( "," );
|
||||
@ -34,137 +20,8 @@ module.exports = function( grunt ) {
|
||||
grunt.option( "filename", "jquery.js" );
|
||||
}
|
||||
|
||||
grunt.option( "dist-folder", grunt.option( "esm" ) ? "dist-module" : "dist" );
|
||||
|
||||
const builtJsFiles = [
|
||||
"dist/jquery.js",
|
||||
"dist/jquery.min.js",
|
||||
"dist/jquery.slim.js",
|
||||
"dist/jquery.slim.min.js",
|
||||
"dist-module/jquery.module.js",
|
||||
"dist-module/jquery.module.min.js",
|
||||
"dist-module/jquery.slim.module.js",
|
||||
"dist-module/jquery.slim.module.min.js"
|
||||
];
|
||||
|
||||
const builtJsMinFiles = builtJsFiles
|
||||
.filter( filepath => filepath.endsWith( ".min.js" ) );
|
||||
|
||||
grunt.initConfig( {
|
||||
pkg: grunt.file.readJSON( "package.json" ),
|
||||
dst: readOptionalJSON( "dist/.destination.json" ),
|
||||
compare_size: {
|
||||
files: builtJsMinFiles,
|
||||
options: {
|
||||
compress: {
|
||||
gz: function( contents ) {
|
||||
return gzip.zip( contents, {} ).length;
|
||||
}
|
||||
},
|
||||
cache: "build/.sizecache.json"
|
||||
}
|
||||
},
|
||||
babel: {
|
||||
options: {
|
||||
sourceMap: "inline",
|
||||
retainLines: true,
|
||||
plugins: [ "@babel/transform-for-of" ]
|
||||
},
|
||||
tests: {
|
||||
files: {
|
||||
"test/data/core/jquery-iterability-transpiled.js":
|
||||
"test/data/core/jquery-iterability-transpiled-es6.js"
|
||||
}
|
||||
}
|
||||
},
|
||||
build: {
|
||||
all: {
|
||||
dest: "dist/jquery.js",
|
||||
minimum: [
|
||||
"core"
|
||||
],
|
||||
|
||||
// Exclude specified modules if the module matching the key is removed
|
||||
removeWith: {
|
||||
ajax: [ "manipulation/_evalUrl", "deprecated/ajax-event-alias" ],
|
||||
callbacks: [ "deferred" ],
|
||||
css: [ "effects", "dimensions", "offset" ],
|
||||
"css/showHide": [ "effects" ],
|
||||
deferred: {
|
||||
remove: [ "ajax", "effects", "queue", "core/ready" ],
|
||||
include: [ "core/ready-no-deferred" ]
|
||||
},
|
||||
event: [ "deprecated/ajax-event-alias", "deprecated/event" ],
|
||||
selector: [ "css/hiddenVisibleSelectors", "effects/animatedSelector" ]
|
||||
}
|
||||
}
|
||||
},
|
||||
npmcopy: {
|
||||
all: {
|
||||
options: {
|
||||
destPrefix: "external"
|
||||
},
|
||||
files: {
|
||||
"bootstrap/bootstrap.css": "bootstrap/dist/css/bootstrap.css",
|
||||
"bootstrap/bootstrap.min.css": "bootstrap/dist/css/bootstrap.min.css",
|
||||
"bootstrap/bootstrap.min.css.map": "bootstrap/dist/css/bootstrap.min.css.map",
|
||||
|
||||
"core-js-bundle/core-js-bundle.js": "core-js-bundle/minified.js",
|
||||
"core-js-bundle/LICENSE": "core-js-bundle/LICENSE",
|
||||
|
||||
"npo/npo.js": "native-promise-only/lib/npo.src.js",
|
||||
|
||||
"qunit/qunit.js": "qunit/qunit/qunit.js",
|
||||
"qunit/qunit.css": "qunit/qunit/qunit.css",
|
||||
"qunit/LICENSE.txt": "qunit/LICENSE.txt",
|
||||
|
||||
"requirejs/require.js": "requirejs/require.js",
|
||||
|
||||
"sinon/sinon.js": "sinon/pkg/sinon.js",
|
||||
"sinon/LICENSE.txt": "sinon/LICENSE"
|
||||
}
|
||||
}
|
||||
},
|
||||
jsonlint: {
|
||||
pkg: {
|
||||
src: [ "package.json" ]
|
||||
}
|
||||
},
|
||||
eslint: {
|
||||
options: {
|
||||
maxWarnings: 0
|
||||
},
|
||||
|
||||
// We have to explicitly declare "src" property otherwise "newer"
|
||||
// task wouldn't work properly :/
|
||||
dist: {
|
||||
src: builtJsFiles
|
||||
},
|
||||
dev: {
|
||||
src: [
|
||||
"src/**/*.js",
|
||||
"Gruntfile.js",
|
||||
"test/**/*.js",
|
||||
"build/**/*.js",
|
||||
|
||||
// Ignore files from .eslintignore
|
||||
// See https://github.com/sindresorhus/grunt-eslint/issues/119
|
||||
...fs
|
||||
.readFileSync( `${ __dirname }/.eslintignore`, "utf-8" )
|
||||
.split( "\n" )
|
||||
.filter( filePath => filePath )
|
||||
.map( filePath => filePath[ 0 ] === "!" ?
|
||||
filePath.slice( 1 ) :
|
||||
`!${ filePath }`
|
||||
),
|
||||
|
||||
// Explicitly ignore `dist/` & `dist-module/` as it could be unignored
|
||||
// by the above `.eslintignore` parsing.
|
||||
"!dist/**/*.js",
|
||||
"!dist-module/**/*.js"
|
||||
]
|
||||
}
|
||||
},
|
||||
testswarm: {
|
||||
tests: [
|
||||
|
||||
@ -230,9 +87,14 @@ module.exports = function( grunt ) {
|
||||
"external/npo/npo.js",
|
||||
"external/requirejs/require.js",
|
||||
"test/data/testinit.js",
|
||||
|
||||
"test/jquery.js",
|
||||
|
||||
{
|
||||
pattern: "external/**",
|
||||
included: false,
|
||||
served: true,
|
||||
nocache: true
|
||||
},
|
||||
{
|
||||
pattern: "dist/jquery.*",
|
||||
included: false,
|
||||
@ -246,7 +108,6 @@ module.exports = function( grunt ) {
|
||||
served: true,
|
||||
nocache: true
|
||||
},
|
||||
{ pattern: "external/**", included: false, served: true },
|
||||
{
|
||||
pattern: "test/**/*.@(js|css|jpg|html|xml|svg)",
|
||||
included: false,
|
||||
@ -328,108 +189,27 @@ module.exports = function( grunt ) {
|
||||
browsers: [ "IE" ],
|
||||
singleRun: false
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
files: [ "<%= eslint.dev.src %>" ],
|
||||
tasks: [ "dev" ]
|
||||
},
|
||||
minify: {
|
||||
all: {
|
||||
files: {
|
||||
[ "<%= grunt.option('dist-folder') %>/" +
|
||||
"<%= grunt.option('filename').replace(/\\.js$/, '.min.js') %>" ]:
|
||||
"<%= grunt.option('dist-folder') %>/<%= grunt.option('filename') %>"
|
||||
},
|
||||
options: {
|
||||
sourceMap: {
|
||||
filename: "<%= grunt.option('dist-folder') %>/" +
|
||||
"<%= grunt.option('filename')" +
|
||||
".replace(/\\.js$/, '.min.map') %>",
|
||||
|
||||
// The map's `files` & `sources` property are set incorrectly, fix
|
||||
// them via overrides from the task config.
|
||||
// See https://github.com/swc-project/swc/issues/7588#issuecomment-1624345254
|
||||
overrides: {
|
||||
file: "jquery.min.js",
|
||||
sources: [
|
||||
"jquery.js"
|
||||
]
|
||||
}
|
||||
},
|
||||
swc: {
|
||||
format: {
|
||||
ecma: grunt.option( "esm" ) ? 2015 : 5,
|
||||
asciiOnly: true,
|
||||
comments: false,
|
||||
preamble: "/*! jQuery v4.0.0-pre | " +
|
||||
"(c) OpenJS Foundation and other contributors | " +
|
||||
"jquery.org/license */\n"
|
||||
},
|
||||
compress: {
|
||||
ecma: grunt.option( "esm" ) ? 2015 : 5,
|
||||
hoist_funs: false,
|
||||
loops: false
|
||||
},
|
||||
mangle: true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} );
|
||||
|
||||
// Load grunt tasks from NPM packages
|
||||
require( "load-grunt-tasks" )( grunt, {
|
||||
pattern: nodeV16OrNewer ? [ "grunt-*" ] : [ "grunt-*", "!grunt-eslint" ]
|
||||
pattern: [ "grunt-*" ]
|
||||
} );
|
||||
|
||||
// Integrate jQuery specific tasks
|
||||
grunt.loadTasks( "build/tasks" );
|
||||
grunt.loadTasks( "build/grunt-tasks" );
|
||||
|
||||
grunt.registerTask( "print_old_node_message", ( ...args ) => {
|
||||
var task = args.join( ":" );
|
||||
grunt.log.writeln( "Old Node.js detected, running the task \"" + task + "\" skipped..." );
|
||||
} );
|
||||
|
||||
grunt.registerTask( "build-all-variants",
|
||||
"Build all variants of the full/slim build & a script/ESM one",
|
||||
function() {
|
||||
const done = this.async();
|
||||
|
||||
spawn( "npm run build-all-variants", {
|
||||
stdio: "inherit",
|
||||
shell: true
|
||||
} )
|
||||
.on( "close", code => {
|
||||
done( code === 0 );
|
||||
} );
|
||||
} );
|
||||
|
||||
grunt.registerTask( "print_jsdom_message", () => {
|
||||
grunt.log.writeln( "Node.js 17 or newer detected, skipping jsdom tests..." );
|
||||
} );
|
||||
|
||||
grunt.registerTask( "lint", [
|
||||
"jsonlint",
|
||||
|
||||
// Running the full eslint task without breaking it down to targets
|
||||
// would run the dist target first which would point to errors in the built
|
||||
// file, making it harder to fix them. We want to check the built file only
|
||||
// if we already know the source files pass the linter.
|
||||
runIfNewNode( "eslint:dev" ),
|
||||
runIfNewNode( "eslint:dist" )
|
||||
] );
|
||||
|
||||
grunt.registerTask( "lint:newer", [
|
||||
"newer:jsonlint",
|
||||
|
||||
// Don't replace it with just the task; see the above comment.
|
||||
runIfNewNode( "newer:eslint:dev" ),
|
||||
runIfNewNode( "newer:eslint:dist" )
|
||||
] );
|
||||
|
||||
grunt.registerTask( "test:fast", [ "node_smoke_tests:commonjs:jquery" ] );
|
||||
grunt.registerTask( "test:slow", [
|
||||
runIfNewNode( "promises_aplus_tests" ),
|
||||
grunt.registerTask( "test:jsdom", [
|
||||
|
||||
// Support: Node.js 17+
|
||||
// jsdom fails to connect to the Karma server in Node 17+.
|
||||
@ -437,33 +217,11 @@ module.exports = function( grunt ) {
|
||||
nodeV17OrNewer ? "print_jsdom_message" : runIfNewNode( "karma:jsdom" )
|
||||
] );
|
||||
|
||||
grunt.registerTask( "test:prepare", [
|
||||
"npmcopy",
|
||||
"qunit_fixture",
|
||||
"babel:tests"
|
||||
] );
|
||||
|
||||
grunt.registerTask( "test", [
|
||||
"test:prepare",
|
||||
"test:fast",
|
||||
"test:slow"
|
||||
] );
|
||||
|
||||
grunt.registerTask( "dev", [
|
||||
"build:*:*",
|
||||
runIfNewNode( "newer:eslint:dev" ),
|
||||
"newer:minify",
|
||||
"dist:*",
|
||||
"qunit_fixture",
|
||||
"compare_size"
|
||||
"test:jsdom"
|
||||
] );
|
||||
|
||||
grunt.registerTask( "default", [
|
||||
runIfNewNode( "eslint:dev" ),
|
||||
"build-all-variants",
|
||||
"test:prepare",
|
||||
runIfNewNode( "eslint:dist" ),
|
||||
"test:fast",
|
||||
"compare_size"
|
||||
"test"
|
||||
] );
|
||||
};
|
||||
|
156
README.md
156
README.md
@ -47,41 +47,47 @@ How to build your own jQuery
|
||||
|
||||
First, [clone the jQuery git repo](https://help.github.com/en/github/creating-cloning-and-archiving-repositories/cloning-a-repository).
|
||||
|
||||
Then, enter the jquery directory and run the build script:
|
||||
Then, enter the jquery directory, install dependencies, and run the build script:
|
||||
|
||||
```bash
|
||||
cd jquery && npm run build
|
||||
```
|
||||
The built version of jQuery will be put in the `dist/` subdirectory, along with the minified copy and associated map file.
|
||||
|
||||
If you want to create custom build or help with jQuery development, it would be better to install [grunt command line interface](https://github.com/gruntjs/grunt-cli) as a global package:
|
||||
|
||||
```
|
||||
npm install -g grunt-cli
|
||||
```
|
||||
Make sure you have `grunt` installed by testing:
|
||||
```
|
||||
grunt -V
|
||||
cd jquery
|
||||
npm install
|
||||
npm run build
|
||||
```
|
||||
|
||||
Now by running the `grunt` command, in the jquery directory, you can build a full version of jQuery, just like with an `npm run build` command:
|
||||
```
|
||||
grunt
|
||||
The built version of jQuery will be placed in the `dist/` directory, along with a minified copy and associated map file.
|
||||
|
||||
## Build all jQuery release files
|
||||
|
||||
To build all variants of jQuery, run the following command:
|
||||
|
||||
```bash
|
||||
npm run build:all
|
||||
```
|
||||
|
||||
There are many other tasks available for jQuery Core:
|
||||
```
|
||||
grunt -help
|
||||
This will create all of the variants that jQuery includes in a release, including `jquery.js`, `jquery.slim.js`, `jquery.module.js`, and `jquery.slim.module.js` along their associated minified files and sourcemaps.
|
||||
|
||||
`jquery.module.js` and `jquery.slim.module.js` are [ECMAScript modules](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Modules) that export `jQuery` and `$` as named exports are placed in the `dist-module/` directory rather than the `dist/` directory.
|
||||
|
||||
## Building a Custom jQuery
|
||||
|
||||
The build script can be used to create a custom version of jQuery that includes only the modules you need.
|
||||
|
||||
Any module may be excluded except for `core`. When excluding `selector`, it is not removed but replaced with a small wrapper around native `querySelectorAll` (see below for more information).
|
||||
|
||||
### Build Script Help
|
||||
|
||||
To see the full list of available options for the build script, run the following:
|
||||
|
||||
```bash
|
||||
npm run build -- --help
|
||||
```
|
||||
|
||||
### Modules
|
||||
|
||||
Special builds can be created that exclude subsets of jQuery functionality.
|
||||
This allows for smaller custom builds when the builder is certain that those parts of jQuery are not being used.
|
||||
For example, an app that only used JSONP for `$.ajax()` and did not need to calculate offsets or positions of elements could exclude the offset and ajax/xhr modules.
|
||||
To exclude a module, pass its path relative to the `src` folder (without the `.js` extension) to the `--exclude` option. When using the `--include` option, the default includes are dropped and a build is created with only those modules.
|
||||
|
||||
Any module may be excluded except for `core`, and `selector`. To exclude a module, pass its path relative to the `src` folder (without the `.js` extension).
|
||||
|
||||
Some example modules that can be excluded are:
|
||||
Some example modules that can be excluded or included are:
|
||||
|
||||
- **ajax**: All AJAX functionality: `$.ajax()`, `$.get()`, `$.post()`, `$.ajaxSetup()`, `.load()`, transports, and ajax event shorthands such as `.ajaxStart()`.
|
||||
- **ajax/xhr**: The XMLHTTPRequest AJAX transport only.
|
||||
@ -97,96 +103,81 @@ Some example modules that can be excluded are:
|
||||
- **offset**: The `.offset()`, `.position()`, `.offsetParent()`, `.scrollLeft()`, and `.scrollTop()` methods.
|
||||
- **wrap**: The `.wrap()`, `.wrapAll()`, `.wrapInner()`, and `.unwrap()` methods.
|
||||
- **core/ready**: Exclude the ready module if you place your scripts at the end of the body. Any ready callbacks bound with `jQuery()` will simply be called immediately. However, `jQuery(document).ready()` will not be a function and `.on("ready", ...)` or similar will not be triggered.
|
||||
- **deferred**: Exclude jQuery.Deferred. This also removes jQuery.Callbacks. *Note* that modules that depend on jQuery.Deferred(AJAX, effects, core/ready) will not be removed and will still expect jQuery.Deferred to be there. Include your own jQuery.Deferred implementation or exclude those modules as well (`grunt custom:-deferred,-ajax,-effects,-core/ready`).
|
||||
- **deferred**: Exclude jQuery.Deferred. This also excludes all modules that rely on Deferred, including **ajax**, **effects**, and **queue**, but replaces **core/ready** with **core/ready-no-deferred**.
|
||||
- **exports/global**: Exclude the attachment of global jQuery variables ($ and jQuery) to the window.
|
||||
- **exports/amd**: Exclude the AMD definition.
|
||||
|
||||
As a special case, you may also replace the full jQuery `selector` module by using a special flag `grunt custom:-selector`.
|
||||
|
||||
- **selector**: The full jQuery selector engine. When this module is excluded, it is replaced by a rudimentary selector engine based on the browser's `querySelectorAll` method that does not support jQuery selector extensions or enhanced semantics. See the [selector-native.js](https://github.com/jquery/jquery/blob/main/src/selector-native.js) file for details.
|
||||
- **selector**: The full jQuery selector engine. When this module is excluded, it is replaced with a rudimentary selector engine based on the browser's `querySelectorAll` method that does not support jQuery selector extensions or enhanced semantics. See the [selector-native.js](https://github.com/jquery/jquery/blob/main/src/selector-native.js) file for details.
|
||||
|
||||
*Note*: Excluding the full `selector` module will also exclude all jQuery selector extensions (such as `effects/animatedSelector` and `css/hiddenVisibleSelectors`).
|
||||
|
||||
The build process shows a message for each dependent module it excludes or includes.
|
||||
|
||||
##### AMD name
|
||||
|
||||
As an option, you can set the module name for jQuery's AMD definition. By default, it is set to "jquery", which plays nicely with plugins and third-party libraries, but there may be cases where you'd like to change this. Simply pass it to the `--amd` parameter:
|
||||
You can set the module name for jQuery's AMD definition. By default, it is set to "jquery", which plays nicely with plugins and third-party libraries, but there may be cases where you'd like to change this. Pass it to the `--amd` parameter:
|
||||
|
||||
```bash
|
||||
grunt custom --amd="custom-name"
|
||||
npm run build -- --amd="custom-name"
|
||||
```
|
||||
|
||||
Or, to define anonymously, set the name to an empty string.
|
||||
Or, to define anonymously, leave the name blank.
|
||||
|
||||
```bash
|
||||
grunt custom --amd=""
|
||||
npm run build -- --amd
|
||||
```
|
||||
|
||||
##### File name
|
||||
##### File name and directory
|
||||
|
||||
The default name for the built jQuery file is `jquery.js`; it is placed under the `dist/` directory. It's possible to change the file name using the `--filename` parameter:
|
||||
The default name for the built jQuery file is `jquery.js`; it is placed under the `dist/` directory. It's possible to change the file name using `--filename` and the directory using `--dir`. `--dir` is relative to the project root.
|
||||
|
||||
```bash
|
||||
grunt custom:slim --filename="jquery.slim.js"
|
||||
npm run build -- --slim --filename="jquery.slim.js" --dir="/tmp"
|
||||
```
|
||||
|
||||
This would create a slim version of jQuery and place it under `dist/jquery.slim.js`. In fact, this is exactly the command we use to generate the slim jQuery during the release process.
|
||||
This would create a slim version of jQuery and place it under `tmp/jquery.slim.js`.
|
||||
|
||||
##### ECMAScript Module (ESM) mode
|
||||
|
||||
By default, jQuery generates a regular script JavaScript file. You can also generate an ECMAScript module exporting `jQuery` as the default export using the `--esm` parameter:
|
||||
|
||||
```bash
|
||||
grunt custom --esm
|
||||
```
|
||||
|
||||
The default is `script` but you can also pass it explicitly via `--no-esm`:
|
||||
|
||||
```bash
|
||||
grunt custom --no-esm
|
||||
npm run build -- --filename=jquery.module.js --esm
|
||||
```
|
||||
|
||||
#### Custom Build Examples
|
||||
|
||||
To create a custom build, first check out the version:
|
||||
|
||||
```bash
|
||||
git pull; git checkout VERSION
|
||||
```
|
||||
|
||||
Where VERSION is the version you want to customize. Then, make sure all Node dependencies are installed:
|
||||
|
||||
```bash
|
||||
npm install
|
||||
```
|
||||
|
||||
Create the custom build using the `grunt custom` option, listing the modules to be excluded.
|
||||
Create a custom build using `npm run build`, listing the modules to be excluded. Excluding a top-level module also excludes its corresponding directory of modules.
|
||||
|
||||
Exclude all **ajax** functionality:
|
||||
|
||||
```bash
|
||||
grunt custom:-ajax
|
||||
npm run build -- --exclude=ajax
|
||||
```
|
||||
|
||||
Excluding **css** removes modules depending on CSS: **effects**, **offset**, **dimensions**.
|
||||
|
||||
```bash
|
||||
grunt custom:-css
|
||||
npm run build -- --exclude=css
|
||||
```
|
||||
|
||||
Exclude a bunch of modules:
|
||||
Exclude a bunch of modules (`-e` is an alias for `--exclude`):
|
||||
|
||||
```bash
|
||||
grunt custom:-ajax/jsonp,-css,-deprecated,-dimensions,-effects,-offset,-wrap
|
||||
npm run build -- -e ajax/jsonp -e css -e deprecated -e dimensions -e effects -e offset -e wrap
|
||||
```
|
||||
|
||||
There is also a special alias to generate a build with the same configuration as the official jQuery Slim build is generated:
|
||||
There is a special alias to generate a build with the same configuration as the official jQuery Slim build:
|
||||
|
||||
```bash
|
||||
grunt custom:slim
|
||||
npm run build -- --filename=jquery.slim.js --slim
|
||||
```
|
||||
|
||||
For questions or requests regarding custom builds, please start a thread on the [Developing jQuery Core](https://forum.jquery.com/developing-jquery-core) section of the forum. Due to the combinatorics and custom nature of these builds, they are not regularly tested in jQuery's unit test process.
|
||||
Or, to create the slim build as an esm module:
|
||||
|
||||
```bash
|
||||
npm run build -- --filename=jquery.slim.module.js --slim --esm
|
||||
```
|
||||
|
||||
*Non-official custom builds are not regularly tested. Use them at your own risk.*
|
||||
|
||||
Running the Unit Tests
|
||||
--------------------------------------
|
||||
@ -197,10 +188,10 @@ Make sure you have the necessary dependencies:
|
||||
npm install
|
||||
```
|
||||
|
||||
Start `grunt watch` or `npm start` to auto-build jQuery as you work:
|
||||
Start `npm start` to auto-build jQuery as you work:
|
||||
|
||||
```bash
|
||||
grunt watch
|
||||
npm start
|
||||
```
|
||||
|
||||
|
||||
@ -213,35 +204,6 @@ Run the unit tests with a local server that supports PHP. Ensure that you run th
|
||||
|
||||
|
||||
|
||||
|
||||
Building to a different directory
|
||||
---------------------------------
|
||||
|
||||
To copy the built jQuery files from `/dist` to another directory:
|
||||
|
||||
```bash
|
||||
grunt && grunt dist:/path/to/special/location/
|
||||
```
|
||||
With this example, the output files would be:
|
||||
|
||||
```bash
|
||||
/path/to/special/location/jquery.js
|
||||
/path/to/special/location/jquery.min.js
|
||||
```
|
||||
|
||||
To add a permanent copy destination, create a file in `dist/` called ".destination.json". Inside the file, paste and customize the following:
|
||||
|
||||
```json
|
||||
|
||||
{
|
||||
"/Absolute/path/to/other/destination": true
|
||||
}
|
||||
```
|
||||
|
||||
Additionally, both methods can be combined.
|
||||
|
||||
|
||||
|
||||
Essential Git
|
||||
-------------
|
||||
|
||||
|
75
build/command.js
Executable file
75
build/command.js
Executable file
@ -0,0 +1,75 @@
|
||||
"use strict";
|
||||
|
||||
const { build } = require( "./tasks/build" );
|
||||
const yargs = require( "yargs/yargs" );
|
||||
const slimExclude = require( "./tasks/lib/slim-exclude" );
|
||||
|
||||
const argv = yargs( process.argv.slice( 2 ) )
|
||||
.version( false )
|
||||
.command( {
|
||||
command: "[options]",
|
||||
describe: "Build a jQuery bundle"
|
||||
} )
|
||||
.option( "filename", {
|
||||
alias: "f",
|
||||
type: "string",
|
||||
description:
|
||||
"Set the filename of the built file. Defaults to jquery.js."
|
||||
} )
|
||||
.option( "dir", {
|
||||
alias: "d",
|
||||
type: "string",
|
||||
description:
|
||||
"Set the dir to which to output the built file. Defaults to /dist."
|
||||
} )
|
||||
.option( "version", {
|
||||
alias: "v",
|
||||
type: "string",
|
||||
description:
|
||||
"Set the version to include in the built file. " +
|
||||
"Defaults to the version in package.json plus the " +
|
||||
"short commit SHA and any excluded modules."
|
||||
} )
|
||||
.option( "watch", {
|
||||
alias: "w",
|
||||
type: "boolean",
|
||||
description:
|
||||
"Watch the source files and rebuild when they change."
|
||||
} )
|
||||
.option( "exclude", {
|
||||
alias: "e",
|
||||
type: "array",
|
||||
description:
|
||||
"Modules to exclude from the build. " +
|
||||
"Specifying this option will cause the " +
|
||||
"specified modules to be excluded from the build."
|
||||
} )
|
||||
.option( "include", {
|
||||
alias: "i",
|
||||
type: "array",
|
||||
description:
|
||||
"Modules to include in the build. " +
|
||||
"Specifying this option will override the " +
|
||||
"default included modules and only include these modules."
|
||||
} )
|
||||
.option( "esm", {
|
||||
type: "boolean",
|
||||
description:
|
||||
"Build an ES module (ESM) bundle. " +
|
||||
"By default, a UMD bundle is built."
|
||||
} )
|
||||
.option( "slim", {
|
||||
alias: "s",
|
||||
type: "boolean",
|
||||
description: "Build a slim bundle, which excludes " +
|
||||
slimExclude.join( ", " )
|
||||
} )
|
||||
.option( "amd", {
|
||||
type: "string",
|
||||
description:
|
||||
"Set the name of the AMD module. Leave blank to make an anonymous module."
|
||||
} )
|
||||
.help()
|
||||
.argv;
|
||||
|
||||
build( argv );
|
@ -6,31 +6,80 @@
|
||||
|
||||
"use strict";
|
||||
|
||||
module.exports = function( grunt ) {
|
||||
const fs = require( "fs" );
|
||||
const path = require( "path" );
|
||||
const util = require( "util" );
|
||||
const exec = util.promisify( require( "child_process" ).exec );
|
||||
const rollup = require( "rollup" );
|
||||
const slimBuildFlags = require( "./lib/slim-build-flags" );
|
||||
const excludedFromSlim = require( "./lib/slim-exclude" );
|
||||
const rollupFileOverrides = require( "./lib/rollup-plugin-file-overrides" );
|
||||
const srcFolder = path.resolve( `${ __dirname }/../../src` );
|
||||
const read = function( fileName ) {
|
||||
return grunt.file.read( `${ srcFolder }/${ fileName }` );
|
||||
const pkg = require( "../../package.json" );
|
||||
const isCleanWorkingDir = require( "./lib/isCleanWorkingDir" );
|
||||
const minify = require( "./minify" );
|
||||
const getTimestamp = require( "./lib/getTimestamp" );
|
||||
const verifyNodeVersion = require( "./lib/verifyNodeVersion" );
|
||||
const srcFolder = path.resolve( __dirname, "../../src" );
|
||||
|
||||
const minimum = [ "core" ];
|
||||
|
||||
// Exclude specified modules if the module matching the key is removed
|
||||
const removeWith = {
|
||||
ajax: [ "manipulation/_evalUrl", "deprecated/ajax-event-alias" ],
|
||||
callbacks: [ "deferred" ],
|
||||
css: [ "effects", "dimensions", "offset" ],
|
||||
"css/showHide": [ "effects" ],
|
||||
deferred: {
|
||||
remove: [ "ajax", "effects", "queue", "core/ready" ],
|
||||
include: [ "core/ready-no-deferred" ]
|
||||
},
|
||||
event: [ "deprecated/ajax-event-alias", "deprecated/event" ],
|
||||
selector: [ "css/hiddenVisibleSelectors", "effects/animatedSelector" ]
|
||||
};
|
||||
|
||||
const inputFileName = "jquery.js";
|
||||
const inputRollupOptions = {
|
||||
input: `${ srcFolder }/${ inputFileName }`
|
||||
};
|
||||
async function read( filename ) {
|
||||
return fs.promises.readFile( path.join( srcFolder, filename ), "utf8" );
|
||||
}
|
||||
|
||||
function getOutputRollupOptions( {
|
||||
esm = false
|
||||
} = {} ) {
|
||||
// Remove the src folder and file extension
|
||||
// and ensure unix-style path separators
|
||||
function moduleName( filename ) {
|
||||
return filename
|
||||
.replace( `${srcFolder}${path.sep}`, "" )
|
||||
.replace( /\.js$/, "" )
|
||||
.split( path.sep )
|
||||
.join( path.posix.sep );
|
||||
}
|
||||
|
||||
async function readdirRecursive( dir, all = [] ) {
|
||||
let files;
|
||||
try {
|
||||
files = await fs.promises.readdir( path.join( srcFolder, dir ), {
|
||||
withFileTypes: true
|
||||
} );
|
||||
} catch ( e ) {
|
||||
return all;
|
||||
}
|
||||
for ( const file of files ) {
|
||||
const filepath = path.join( dir, file.name );
|
||||
|
||||
if ( file.isDirectory() ) {
|
||||
all.push( ...( await readdirRecursive( filepath ) ) );
|
||||
} else {
|
||||
all.push( moduleName( filepath ) );
|
||||
}
|
||||
}
|
||||
return all;
|
||||
}
|
||||
|
||||
async function getOutputRollupOptions( { esm = false } = {} ) {
|
||||
const wrapperFileName = `wrapper${esm ? "-esm" : ""}.js`;
|
||||
const wrapperSource = await read( wrapperFileName );
|
||||
|
||||
// Catch `// @CODE` and subsequent comment lines event if they don't start
|
||||
// in the first column.
|
||||
const wrapper = read( wrapperFileName )
|
||||
.split( /[\x20\t]*\/\/ @CODE\n(?:[\x20\t]*\/\/[^\n]+\n)*/ );
|
||||
const wrapper = wrapperSource.split(
|
||||
/[\x20\t]*\/\/ @CODE\n(?:[\x20\t]*\/\/[^\n]+\n)*/
|
||||
);
|
||||
|
||||
return {
|
||||
|
||||
@ -39,17 +88,13 @@ module.exports = function( grunt ) {
|
||||
// generate any extra wrappers so there's nothing for us to remove.
|
||||
format: "esm",
|
||||
|
||||
intro: `${ wrapper[ 0 ].replace( /\n*$/, "" ) }`,
|
||||
intro: wrapper[ 0 ].replace( /\n*$/, "" ),
|
||||
outro: wrapper[ 1 ].replace( /^\n*/, "" )
|
||||
};
|
||||
}
|
||||
|
||||
const fileOverrides = new Map();
|
||||
|
||||
function getOverride( filePath ) {
|
||||
return fileOverrides.get( path.resolve( filePath ) );
|
||||
}
|
||||
|
||||
function setOverride( filePath, source ) {
|
||||
|
||||
// We want normalized paths in overrides as they will be matched
|
||||
@ -57,218 +102,162 @@ module.exports = function( grunt ) {
|
||||
fileOverrides.set( path.resolve( filePath ), source );
|
||||
}
|
||||
|
||||
grunt.registerMultiTask(
|
||||
"build",
|
||||
"Build jQuery ECMAScript modules, " +
|
||||
"(include/exclude modules with +/- flags), embed date/version",
|
||||
async function() {
|
||||
const done = this.async();
|
||||
|
||||
try {
|
||||
const flags = this.flags;
|
||||
const optIn = flags[ "*" ];
|
||||
let name = grunt.option( "filename" );
|
||||
const esm = !!grunt.option( "esm" );
|
||||
const distFolder = grunt.option( "dist-folder" );
|
||||
const minimum = this.data.minimum;
|
||||
const removeWith = this.data.removeWith;
|
||||
const excluded = [];
|
||||
const included = [];
|
||||
let version = grunt.config( "pkg.version" );
|
||||
|
||||
// We'll skip printing the whole big exclusions for a bare `build:*:*:slim` which
|
||||
// usually comes from `custom:slim`.
|
||||
const isPureSlim = !!( flags.slim && flags[ "*" ] &&
|
||||
Object.keys( flags ).length === 2 );
|
||||
|
||||
delete flags[ "*" ];
|
||||
|
||||
if ( flags.slim ) {
|
||||
delete flags.slim;
|
||||
for ( const flag of slimBuildFlags ) {
|
||||
flags[ flag ] = true;
|
||||
}
|
||||
function unique( array ) {
|
||||
return [ ...new Set( array ) ];
|
||||
}
|
||||
|
||||
async function checkExclude( exclude, include ) {
|
||||
const included = [ ...include ];
|
||||
const excluded = [ ...exclude ];
|
||||
|
||||
/**
|
||||
* Recursively calls the excluder to remove on all modules in the list
|
||||
* @param {Array} list
|
||||
* @param {String} [prepend] Prepend this to the module name.
|
||||
* Indicates we're walking a directory
|
||||
*/
|
||||
const excludeList = ( list, prepend ) => {
|
||||
if ( list ) {
|
||||
prepend = prepend ? `${ prepend }/` : "";
|
||||
list.forEach( function( module ) {
|
||||
|
||||
// Exclude var modules as well
|
||||
if ( module === "var" ) {
|
||||
excludeList(
|
||||
fs.readdirSync( `${ srcFolder }/${ prepend }${ module }` ),
|
||||
prepend + module
|
||||
);
|
||||
return;
|
||||
}
|
||||
if ( prepend ) {
|
||||
|
||||
// Skip if this is not a js file and we're walking files in a dir
|
||||
if ( !( module = /([\w-\/]+)\.js$/.exec( module ) ) ) {
|
||||
return;
|
||||
for ( const module of exclude ) {
|
||||
if ( minimum.indexOf( module ) !== -1 ) {
|
||||
throw new Error( `Module \"${module}\" is a minimum requirement.` );
|
||||
}
|
||||
|
||||
// Prepend folder name if passed
|
||||
// Remove .js extension
|
||||
module = prepend + module[ 1 ];
|
||||
}
|
||||
|
||||
// Avoid infinite recursion
|
||||
if ( excluded.indexOf( module ) === -1 ) {
|
||||
excluder( "-" + module );
|
||||
}
|
||||
} );
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Adds the specified module to the excluded or included list, depending on the flag
|
||||
* @param {String} flag A module path relative to
|
||||
* the src directory starting with + or - to indicate
|
||||
* whether it should be included or excluded
|
||||
*/
|
||||
const excluder = flag => {
|
||||
let additional;
|
||||
const m = /^(\+|-|)([\w\/-]+)$/.exec( flag );
|
||||
const exclude = m[ 1 ] === "-";
|
||||
const module = m[ 2 ];
|
||||
|
||||
if ( exclude ) {
|
||||
|
||||
// Can't exclude certain modules
|
||||
if ( minimum.indexOf( module ) === -1 ) {
|
||||
|
||||
// Add to excluded
|
||||
if ( excluded.indexOf( module ) === -1 ) {
|
||||
grunt.log.writeln( flag );
|
||||
excluded.push( module );
|
||||
|
||||
// Exclude all files in the folder of the same name
|
||||
// Exclude all files in the dir of the same name
|
||||
// These are the removable dependencies
|
||||
// It's fine if the directory is not there
|
||||
try {
|
||||
|
||||
// `selector` is a special case as we don't just remove
|
||||
// the module, but we replace it with `selector-native`
|
||||
// which re-uses parts of the `src/selector` folder.
|
||||
// which re-uses parts of the `src/selector` dir.
|
||||
if ( module !== "selector" ) {
|
||||
excludeList(
|
||||
fs.readdirSync( `${ srcFolder }/${ module }` ),
|
||||
module
|
||||
);
|
||||
const files = await readdirRecursive( module );
|
||||
excluded.push( ...files );
|
||||
}
|
||||
} catch ( e ) {
|
||||
grunt.verbose.writeln( e );
|
||||
}
|
||||
}
|
||||
|
||||
additional = removeWith[ module ];
|
||||
|
||||
// Check removeWith list
|
||||
const additional = removeWith[ module ];
|
||||
if ( additional ) {
|
||||
excludeList( additional.remove || additional );
|
||||
if ( additional.include ) {
|
||||
included.push( ...additional.include );
|
||||
grunt.log.writeln( "+" + additional.include );
|
||||
const [ additionalExcluded, additionalIncluded ] = await checkExclude(
|
||||
additional.remove || additional,
|
||||
additional.include || []
|
||||
);
|
||||
excluded.push( ...additionalExcluded );
|
||||
included.push( ...additionalIncluded );
|
||||
}
|
||||
}
|
||||
} else {
|
||||
grunt.log.error( "Module \"" + module + "\" is a minimum requirement." );
|
||||
}
|
||||
} else {
|
||||
grunt.log.writeln( flag );
|
||||
included.push( module );
|
||||
}
|
||||
};
|
||||
|
||||
// Filename can be passed to the command line using
|
||||
// command line options
|
||||
// e.g. grunt build --filename=jquery-custom.js
|
||||
name = name ? `${ distFolder }/${ name }` : this.data.dest;
|
||||
|
||||
// append commit id to version
|
||||
if ( process.env.COMMIT ) {
|
||||
version += " " + process.env.COMMIT;
|
||||
}
|
||||
|
||||
// figure out which files to exclude based on these rules in this order:
|
||||
// dependency explicit exclude
|
||||
// > explicit exclude
|
||||
// > explicit include
|
||||
// > dependency implicit exclude
|
||||
// > implicit exclude
|
||||
// examples:
|
||||
// * none (implicit exclude)
|
||||
// *:* all (implicit include)
|
||||
// *:*:-css all except css and dependents (explicit > implicit)
|
||||
// *:*:-css:+effects same (excludes effects because explicit include is
|
||||
// trumped by explicit exclude of dependency)
|
||||
// *:+effects none except effects and its dependencies
|
||||
// (explicit include trumps implicit exclude of dependency)
|
||||
for ( const flag in flags ) {
|
||||
excluder( flag );
|
||||
return [ unique( excluded ), unique( included ) ];
|
||||
}
|
||||
|
||||
// Remove the jQuery export from the entry file, we'll use our own
|
||||
// custom wrapper.
|
||||
setOverride( inputRollupOptions.input,
|
||||
read( inputFileName ).replace( /\n*export \{ jQuery, jQuery as \$ };\n*/, "\n" ) );
|
||||
async function writeCompiled( { code, dir, filename, version } ) {
|
||||
const compiledContents = code
|
||||
|
||||
// Embed Version
|
||||
.replace( /@VERSION/g, version )
|
||||
|
||||
// Embed Date
|
||||
// yyyy-mm-ddThh:mmZ
|
||||
.replace( /@DATE/g, new Date().toISOString().replace( /:\d+\.\d+Z$/, "Z" ) );
|
||||
|
||||
await fs.promises.writeFile( path.join( dir, filename ), compiledContents );
|
||||
console.log( `[${getTimestamp()}] ${filename} v${version} created.` );
|
||||
}
|
||||
|
||||
// Build jQuery ECMAScript modules
|
||||
async function build( {
|
||||
amd,
|
||||
dir = "dist",
|
||||
exclude = [],
|
||||
filename = "jquery.js",
|
||||
include = [],
|
||||
esm = false,
|
||||
slim = false,
|
||||
version,
|
||||
watch = false
|
||||
} = {} ) {
|
||||
const pureSlim = slim && !exclude.length && !include.length;
|
||||
|
||||
// Add the short commit hash to the version string
|
||||
// when the version is not for a release.
|
||||
if ( !version ) {
|
||||
const { stdout } = await exec( "git rev-parse --short HEAD" );
|
||||
const isClean = await isCleanWorkingDir();
|
||||
|
||||
// "+[slim.]SHA" is semantically correct
|
||||
// Add ".dirty" as well if the working dir is not clean
|
||||
version = `${pkg.version}+${slim ? "slim." : ""}${stdout.trim()}${isClean ? "" : ".dirty"}`;
|
||||
} else if ( slim ) {
|
||||
version += "+slim";
|
||||
}
|
||||
|
||||
await fs.promises.mkdir( dir, { recursive: true } );
|
||||
|
||||
// Exclude slim modules when slim is true
|
||||
const [ excluded, included ] = await checkExclude(
|
||||
slim ? exclude.concat( excludedFromSlim ) : exclude,
|
||||
include
|
||||
);
|
||||
|
||||
// Replace exports/global with a noop noConflict
|
||||
if ( excluded.includes( "exports/global" ) ) {
|
||||
const index = excluded.indexOf( "exports/global" );
|
||||
setOverride( `${ srcFolder }/exports/global.js`,
|
||||
"import jQuery from \"../core.js\";\n\n" +
|
||||
"jQuery.noConflict = function() {};" );
|
||||
setOverride(
|
||||
`${srcFolder}/exports/global.js`,
|
||||
"import { jQuery } from \"../core.js\";\n\n" +
|
||||
"jQuery.noConflict = function() {};"
|
||||
);
|
||||
excluded.splice( index, 1 );
|
||||
}
|
||||
|
||||
// Set a desired AMD name.
|
||||
let amdName = grunt.option( "amd" );
|
||||
if ( amdName != null ) {
|
||||
if ( amdName ) {
|
||||
grunt.log.writeln( "Naming jQuery with AMD name: " + amdName );
|
||||
if ( amd != null ) {
|
||||
if ( amd ) {
|
||||
console.log( "Naming jQuery with AMD name: " + amd );
|
||||
} else {
|
||||
grunt.log.writeln( "AMD name now anonymous" );
|
||||
console.log( "AMD name now anonymous" );
|
||||
}
|
||||
|
||||
// Replace the AMD name in the AMD export
|
||||
// No name means an anonymous define
|
||||
const amdExportContents = await read( "exports/amd.js" );
|
||||
setOverride(
|
||||
`${srcFolder}/exports/amd.js`,
|
||||
amdExportContents.replace(
|
||||
|
||||
// Remove the comma for anonymous defines
|
||||
setOverride( `${ srcFolder }/exports/amd.js`,
|
||||
read( "exports/amd.js" )
|
||||
.replace( /(\s*)"jquery"(,\s*)/,
|
||||
amdName ? "$1\"" + amdName + "\"$2" : "" ) );
|
||||
/(\s*)"jquery"(,\s*)/,
|
||||
amd ? `$1\"${amd}\"$2` : " "
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
grunt.verbose.writeflags( excluded, "Excluded" );
|
||||
grunt.verbose.writeflags( included, "Included" );
|
||||
|
||||
// Indicate a Slim build without listing all the exclusions
|
||||
// to save space.
|
||||
if ( isPureSlim ) {
|
||||
version += " slim";
|
||||
|
||||
// Append excluded modules to version.
|
||||
} else if ( excluded.length ) {
|
||||
// Skip adding exclusions for slim builds.
|
||||
// Don't worry about semver syntax for these.
|
||||
if ( !pureSlim && excluded.length ) {
|
||||
version += " -" + excluded.join( ",-" );
|
||||
}
|
||||
|
||||
if ( excluded.length ) {
|
||||
// Append extra included modules to version.
|
||||
if ( !pureSlim && included.length ) {
|
||||
version += " +" + included.join( ",+" );
|
||||
}
|
||||
|
||||
// Set pkg.version to version with excludes or with the "slim" marker,
|
||||
// so minified file picks it up but skip the commit hash the same way
|
||||
// it's done for the full build.
|
||||
const commitlessVersion = version.replace( " " + process.env.COMMIT, "" );
|
||||
grunt.config.set( "pkg.version", commitlessVersion );
|
||||
grunt.verbose.writeln( "Version changed to " + commitlessVersion );
|
||||
const inputOptions = {
|
||||
input: `${srcFolder}/jquery.js`
|
||||
};
|
||||
|
||||
const includedImports = included
|
||||
.map( ( module ) => `import "./${module}.js";` )
|
||||
.join( "\n" );
|
||||
|
||||
const jQueryFileContents = await read( "jquery.js" );
|
||||
if ( include.length ) {
|
||||
|
||||
// If include is specified, only add those modules.
|
||||
setOverride( inputOptions.input, includedImports );
|
||||
} else {
|
||||
|
||||
// Remove the jQuery export from the entry file, we'll use our own
|
||||
// custom wrapper.
|
||||
setOverride(
|
||||
inputOptions.input,
|
||||
jQueryFileContents.replace( /\n*export \{ jQuery, jQuery as \$ };\n*/, "\n" ) +
|
||||
includedImports
|
||||
);
|
||||
}
|
||||
|
||||
// Replace excluded modules with empty sources.
|
||||
for ( const module of excluded ) {
|
||||
@ -277,79 +266,96 @@ module.exports = function( grunt ) {
|
||||
|
||||
// The `selector` module is not removed, but replaced
|
||||
// with `selector-native`.
|
||||
module === "selector" ? read( "selector-native.js" ) : ""
|
||||
module === "selector" ? await read( "selector-native.js" ) : ""
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// Turn off opt-in if necessary
|
||||
if ( !optIn ) {
|
||||
|
||||
// Remove the default inclusions, they will be overwritten with the explicitly
|
||||
// included ones.
|
||||
setOverride( inputRollupOptions.input, "" );
|
||||
|
||||
}
|
||||
|
||||
// Import the explicitly included modules.
|
||||
if ( included.length ) {
|
||||
setOverride( inputRollupOptions.input,
|
||||
getOverride( inputRollupOptions.input ) + included
|
||||
.map( module => `import "./${module}.js";` )
|
||||
.join( "\n" ) );
|
||||
}
|
||||
|
||||
const bundle = await rollup.rollup( {
|
||||
...inputRollupOptions,
|
||||
...inputOptions,
|
||||
plugins: [ rollupFileOverrides( fileOverrides ) ]
|
||||
} );
|
||||
|
||||
const outputRollupOptions =
|
||||
getOutputRollupOptions( { esm } );
|
||||
const outputOptions = await getOutputRollupOptions( { esm } );
|
||||
|
||||
const { output: [ { code } ] } = await bundle.generate( outputRollupOptions );
|
||||
|
||||
const compiledContents = code
|
||||
|
||||
// Embed Version
|
||||
.replace( /@VERSION/g, version )
|
||||
|
||||
// Embed Date
|
||||
// yyyy-mm-ddThh:mmZ
|
||||
.replace(
|
||||
/@DATE/g,
|
||||
( new Date() ).toISOString()
|
||||
.replace( /:\d+\.\d+Z$/, "Z" )
|
||||
);
|
||||
|
||||
grunt.file.write( name, compiledContents );
|
||||
grunt.log.ok( `File '${ name }' created.` );
|
||||
done();
|
||||
} catch ( err ) {
|
||||
done( err );
|
||||
if ( watch ) {
|
||||
const watcher = rollup.watch( {
|
||||
...inputOptions,
|
||||
output: [ outputOptions ],
|
||||
plugins: [ rollupFileOverrides( fileOverrides ) ],
|
||||
watch: {
|
||||
include: `${srcFolder}/**`,
|
||||
skipWrite: true
|
||||
}
|
||||
} );
|
||||
|
||||
// Special "alias" task to make custom build creation less grawlix-y
|
||||
// Translation example
|
||||
//
|
||||
// grunt custom:+ajax,-dimensions,-effects,-offset
|
||||
//
|
||||
// Becomes:
|
||||
//
|
||||
// grunt build:*:*:+ajax:-dimensions:-effects:-offset
|
||||
//
|
||||
// There's also a special "slim" alias that resolves to the jQuery Slim build
|
||||
// configuration:
|
||||
//
|
||||
// grunt custom:slim
|
||||
grunt.registerTask( "custom", function() {
|
||||
const args = this.args;
|
||||
const modules = args.length ?
|
||||
args[ 0 ].split( "," ).join( ":" ) :
|
||||
"";
|
||||
watcher.on( "event", async( event ) => {
|
||||
switch ( event.code ) {
|
||||
case "ERROR":
|
||||
console.error( event.error );
|
||||
break;
|
||||
case "BUNDLE_END":
|
||||
const {
|
||||
output: [ { code } ]
|
||||
} = await event.result.generate( outputOptions );
|
||||
|
||||
grunt.log.writeln( "Creating custom build...\n" );
|
||||
grunt.task.run( [ "build:*:*" + ( modules ? ":" + modules : "" ), "minify", "dist" ] );
|
||||
await writeCompiled( {
|
||||
code,
|
||||
dir,
|
||||
filename,
|
||||
version
|
||||
} );
|
||||
};
|
||||
|
||||
await minify( { dir, filename, esm } );
|
||||
break;
|
||||
}
|
||||
} );
|
||||
|
||||
return watcher;
|
||||
} else {
|
||||
const {
|
||||
output: [ { code } ]
|
||||
} = await bundle.generate( outputOptions );
|
||||
|
||||
await writeCompiled( { code, dir, filename, version } );
|
||||
await minify( { dir, filename, esm } );
|
||||
}
|
||||
}
|
||||
|
||||
async function buildDefaultFiles( { version, watch } = {} ) {
|
||||
await Promise.all( [
|
||||
build( { version, watch } ),
|
||||
build( { filename: "jquery.slim.js", slim: true, version, watch } ),
|
||||
build( {
|
||||
dir: "dist-module",
|
||||
filename: "jquery.module.js",
|
||||
esm: true,
|
||||
version,
|
||||
watch
|
||||
} ),
|
||||
build( {
|
||||
dir: "dist-module",
|
||||
filename: "jquery.slim.module.js",
|
||||
esm: true,
|
||||
slim: true,
|
||||
version,
|
||||
watch
|
||||
} )
|
||||
] );
|
||||
|
||||
// Earlier Node.js versions do not support the ESM format.
|
||||
if ( !verifyNodeVersion() ) {
|
||||
return;
|
||||
}
|
||||
|
||||
const { compareSize } = await import( "./compare_size.mjs" );
|
||||
return compareSize( {
|
||||
files: [
|
||||
"dist/jquery.min.js",
|
||||
"dist/jquery.slim.min.js",
|
||||
"dist-module/jquery.module.min.js",
|
||||
"dist-module/jquery.slim.module.min.js"
|
||||
]
|
||||
} );
|
||||
}
|
||||
|
||||
module.exports = { build, buildDefaultFiles };
|
||||
|
128
build/tasks/compare_size.mjs
Normal file
128
build/tasks/compare_size.mjs
Normal file
@ -0,0 +1,128 @@
|
||||
import chalk from "chalk";
|
||||
import fs from "node:fs";
|
||||
import { promisify } from "node:util";
|
||||
import zlib from "node:zlib";
|
||||
import { exec as nodeExec } from "node:child_process";
|
||||
import isCleanWorkingDir from "./lib/isCleanWorkingDir.js";
|
||||
|
||||
const gzip = promisify( zlib.gzip );
|
||||
const exec = promisify( nodeExec );
|
||||
|
||||
async function getBranchName() {
|
||||
const { stdout } = await exec( "git rev-parse --abbrev-ref HEAD" );
|
||||
return stdout.trim();
|
||||
}
|
||||
|
||||
async function getCache( loc ) {
|
||||
try {
|
||||
const contents = await fs.promises.readFile( loc, "utf8" );
|
||||
return JSON.parse( contents );
|
||||
} catch ( err ) {
|
||||
return {};
|
||||
}
|
||||
}
|
||||
|
||||
function saveCache( loc, cache ) {
|
||||
return fs.promises.writeFile( loc, JSON.stringify( cache ) );
|
||||
}
|
||||
|
||||
function compareSizes( existing, current, padLength ) {
|
||||
if ( typeof current !== "number" ) {
|
||||
return chalk.grey( `${existing}`.padStart( padLength ) );
|
||||
}
|
||||
const delta = current - existing;
|
||||
if ( delta > 0 ) {
|
||||
return chalk.red( `+${delta}`.padStart( padLength ) );
|
||||
}
|
||||
return chalk.green( `${delta}`.padStart( padLength ) );
|
||||
}
|
||||
|
||||
export async function compareSize( { cache = ".sizecache.json", files } = {} ) {
|
||||
if ( !files || !files.length ) {
|
||||
throw new Error( "No files specified" );
|
||||
}
|
||||
|
||||
const branch = await getBranchName();
|
||||
const sizeCache = await getCache( cache );
|
||||
|
||||
let rawPadLength = 0;
|
||||
let gzPadLength = 0;
|
||||
const results = await Promise.all(
|
||||
files.map( async function( filename ) {
|
||||
|
||||
let contents = await fs.promises.readFile( filename, "utf8" );
|
||||
|
||||
// Remove the banner for size comparisons.
|
||||
// The version string can vary widely by short SHA.
|
||||
contents = contents.replace( /\/\*\! jQuery[^\n]+/, "" );
|
||||
|
||||
const size = Buffer.byteLength( contents, "utf8" );
|
||||
const gzippedSize = ( await gzip( contents ) ).length;
|
||||
|
||||
// Add one to give space for the `+` or `-` in the comparison
|
||||
rawPadLength = Math.max( rawPadLength, size.toString().length + 1 );
|
||||
gzPadLength = Math.max( gzPadLength, gzippedSize.toString().length + 1 );
|
||||
|
||||
return { filename, raw: size, gz: gzippedSize };
|
||||
} )
|
||||
);
|
||||
|
||||
const header = "raw".padStart( rawPadLength ) +
|
||||
"gz".padStart( gzPadLength + 1 ) +
|
||||
" Filename";
|
||||
|
||||
const sizes = results.map( function( result ) {
|
||||
const rawSize = result.raw.toString().padStart( rawPadLength );
|
||||
const gzSize = result.gz.toString().padStart( gzPadLength );
|
||||
return `${rawSize} ${gzSize} ${result.filename}`;
|
||||
} );
|
||||
|
||||
const comparisons = Object.keys( sizeCache ).map( function( branch ) {
|
||||
const branchSizes = Object.keys( sizeCache[ branch ] ).map( function( filename ) {
|
||||
const branchResult = sizeCache[ branch ][ filename ];
|
||||
const compareResult = results.find( function( result ) {
|
||||
return result.filename === filename;
|
||||
} ) || {};
|
||||
|
||||
const compareRaw = compareSizes( branchResult.raw, compareResult.raw, rawPadLength );
|
||||
const compareGz = compareSizes( branchResult.gz, compareResult.gz, gzPadLength );
|
||||
return `${compareRaw} ${compareGz} ${filename}`;
|
||||
} );
|
||||
|
||||
return [
|
||||
"", // New line before each branch
|
||||
chalk.bold( branch ),
|
||||
header,
|
||||
...branchSizes
|
||||
].join( "\n" );
|
||||
} );
|
||||
|
||||
const output = [
|
||||
"", // Opening new line
|
||||
chalk.bold( "Sizes" ),
|
||||
header,
|
||||
...sizes,
|
||||
...comparisons,
|
||||
"" // Closing new line
|
||||
].join( "\n" );
|
||||
|
||||
console.log( output );
|
||||
|
||||
// Only save cache for the current branch
|
||||
// if the working directory is clean.
|
||||
if ( await isCleanWorkingDir() ) {
|
||||
sizeCache[ branch ] = {};
|
||||
results.forEach( function( result ) {
|
||||
sizeCache[ branch ][ result.filename ] = {
|
||||
raw: result.raw,
|
||||
gz: result.gz
|
||||
};
|
||||
} );
|
||||
|
||||
await saveCache( cache, sizeCache );
|
||||
|
||||
console.log( `Saved cache for ${branch}.` );
|
||||
}
|
||||
|
||||
return results;
|
||||
}
|
@ -1,72 +1,31 @@
|
||||
"use strict";
|
||||
|
||||
module.exports = function( grunt ) {
|
||||
const fs = require( "fs" );
|
||||
const filename = grunt.option( "filename" );
|
||||
const distFolder = grunt.option( "dist-folder" );
|
||||
const distPaths = [
|
||||
`${ distFolder }/${ filename }`,
|
||||
`${ distFolder }/${ filename.replace( ".js", ".min.js" ) }`,
|
||||
`${ distFolder }/${ filename.replace( ".js", ".min.map" ) }`
|
||||
];
|
||||
// Process files for distribution.
|
||||
module.exports = async function processForDist( text, filename ) {
|
||||
if ( !text ) {
|
||||
throw new Error( "text required for processForDist" );
|
||||
}
|
||||
|
||||
// Process files for distribution
|
||||
grunt.registerTask( "dist", function() {
|
||||
let stored, flags, paths, nonascii;
|
||||
|
||||
// Check for stored destination paths
|
||||
// ( set in dist/.destination.json )
|
||||
stored = Object.keys( grunt.config( "dst" ) );
|
||||
|
||||
// Allow command line input as well
|
||||
flags = Object.keys( this.flags );
|
||||
|
||||
// Combine all output target paths
|
||||
paths = [].concat( stored, flags ).filter( function( path ) {
|
||||
return path !== "*";
|
||||
} );
|
||||
|
||||
// Ensure the dist files are pure ASCII
|
||||
nonascii = false;
|
||||
|
||||
distPaths.forEach( function( filename ) {
|
||||
let i, c;
|
||||
const text = fs.readFileSync( filename, "utf8" );
|
||||
if ( !filename ) {
|
||||
throw new Error( "filename required for processForDist" );
|
||||
}
|
||||
|
||||
// Ensure files use only \n for line endings, not \r\n
|
||||
if ( /\x0d\x0a/.test( text ) ) {
|
||||
grunt.log.writeln( filename + ": Incorrect line endings (\\r\\n)" );
|
||||
nonascii = true;
|
||||
throw new Error( filename + ": Incorrect line endings (\\r\\n)" );
|
||||
}
|
||||
|
||||
// Ensure only ASCII chars so script tags don't need a charset attribute
|
||||
if ( text.length !== Buffer.byteLength( text, "utf8" ) ) {
|
||||
grunt.log.writeln( filename + ": Non-ASCII characters detected:" );
|
||||
for ( i = 0; i < text.length; i++ ) {
|
||||
c = text.charCodeAt( i );
|
||||
let message = filename + ": Non-ASCII characters detected:\n";
|
||||
for ( let i = 0; i < text.length; i++ ) {
|
||||
const c = text.charCodeAt( i );
|
||||
if ( c > 127 ) {
|
||||
grunt.log.writeln( "- position " + i + ": " + c );
|
||||
grunt.log.writeln( "-- " + text.substring( i - 20, i + 20 ) );
|
||||
message += "- position " + i + ": " + c + "\n";
|
||||
message += "==> " + text.substring( i - 20, i + 20 );
|
||||
break;
|
||||
}
|
||||
}
|
||||
nonascii = true;
|
||||
throw new Error( message );
|
||||
}
|
||||
|
||||
// Optionally copy dist files to other locations
|
||||
paths.forEach( function( path ) {
|
||||
let created;
|
||||
|
||||
if ( !/\/$/.test( path ) ) {
|
||||
path += "/";
|
||||
}
|
||||
|
||||
created = path + filename.replace( "dist/", "" );
|
||||
grunt.file.write( created, text );
|
||||
grunt.log.writeln( "File '" + created + "' created." );
|
||||
} );
|
||||
} );
|
||||
|
||||
return !nonascii;
|
||||
} );
|
||||
};
|
||||
|
9
build/tasks/lib/getTimestamp.js
Normal file
9
build/tasks/lib/getTimestamp.js
Normal file
@ -0,0 +1,9 @@
|
||||
"use strict";
|
||||
|
||||
module.exports = function getTimestamp() {
|
||||
const now = new Date();
|
||||
const hours = now.getHours().toString().padStart( 2, "0" );
|
||||
const minutes = now.getMinutes().toString().padStart( 2, "0" );
|
||||
const seconds = now.getSeconds().toString().padStart( 2, "0" );
|
||||
return `${hours}:${minutes}:${seconds}`;
|
||||
};
|
9
build/tasks/lib/isCleanWorkingDir.js
Normal file
9
build/tasks/lib/isCleanWorkingDir.js
Normal file
@ -0,0 +1,9 @@
|
||||
"use strict";
|
||||
|
||||
const util = require( "util" );
|
||||
const exec = util.promisify( require( "child_process" ).exec );
|
||||
|
||||
module.exports = async function isCleanWorkingDir() {
|
||||
const { stdout } = await exec( "git status --untracked-files=no --porcelain" );
|
||||
return !stdout.trim();
|
||||
};
|
@ -2,9 +2,9 @@
|
||||
|
||||
// NOTE: keep it in sync with test/data/testinit.js
|
||||
module.exports = [
|
||||
"-ajax",
|
||||
"-callbacks",
|
||||
"-deferred",
|
||||
"-effects",
|
||||
"-queue"
|
||||
"ajax",
|
||||
"callbacks",
|
||||
"deferred",
|
||||
"effects",
|
||||
"queue"
|
||||
];
|
@ -1,16 +0,0 @@
|
||||
"use strict";
|
||||
|
||||
// Run Node with provided parameters: the first one being the Grunt
|
||||
// done function and latter ones being files to be tested.
|
||||
// See the comment in ../node_smoke_tests.js for more information.
|
||||
module.exports = function spawnTest( done, command ) {
|
||||
var spawn = require( "child_process" ).spawn;
|
||||
|
||||
spawn( command, {
|
||||
stdio: "inherit",
|
||||
shell: true
|
||||
} )
|
||||
.on( "close", function( code ) {
|
||||
done( code === 0 );
|
||||
} );
|
||||
};
|
12
build/tasks/lib/verifyNodeVersion.js
Normal file
12
build/tasks/lib/verifyNodeVersion.js
Normal file
@ -0,0 +1,12 @@
|
||||
"use strict";
|
||||
|
||||
const { version } = require( "process" );
|
||||
const nodeV16OrNewer = !/^v1[0-5]\./.test( version );
|
||||
|
||||
module.exports = function verifyNodeVersion() {
|
||||
if ( !nodeV16OrNewer ) {
|
||||
console.log( "Old Node.js detected, task skipped..." );
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
};
|
@ -1,57 +1,67 @@
|
||||
/**
|
||||
* Minify JavaScript using SWC.
|
||||
*/
|
||||
|
||||
"use strict";
|
||||
|
||||
module.exports = ( grunt ) => {
|
||||
const swc = require( "@swc/core" );
|
||||
const fs = require( "fs" );
|
||||
const path = require( "path" );
|
||||
const processForDist = require( "./dist" );
|
||||
const getTimestamp = require( "./lib/getTimestamp" );
|
||||
|
||||
grunt.registerMultiTask(
|
||||
"minify",
|
||||
"Minify JavaScript using SWC",
|
||||
async function() {
|
||||
const done = this.async();
|
||||
const options = this.options();
|
||||
const sourceMapFilename = options.sourceMap && options.sourceMap.filename;
|
||||
const sourceMapOverrides = options.sourceMap && options.sourceMap.overrides || {};
|
||||
const rjs = /\.js$/;
|
||||
|
||||
await Promise.all( this.files.map( async( { src, dest } ) => {
|
||||
if ( src.length !== 1 ) {
|
||||
grunt.fatal( "The minify task requires a single source per destination" );
|
||||
}
|
||||
module.exports = async function minify( { filename, dir, esm } ) {
|
||||
const contents = await fs.promises.readFile( path.join( dir, filename ), "utf8" );
|
||||
const version = /jQuery JavaScript Library ([^\n]+)/.exec( contents )[ 1 ];
|
||||
|
||||
const { code, map: incompleteMap } = await swc.minify(
|
||||
grunt.file.read( src[ 0 ] ),
|
||||
contents,
|
||||
{
|
||||
...options.swc,
|
||||
compress: {
|
||||
ecma: esm ? 2015 : 5,
|
||||
hoist_funs: false,
|
||||
loops: false
|
||||
},
|
||||
format: {
|
||||
ecma: esm ? 2015 : 5,
|
||||
asciiOnly: true,
|
||||
comments: false,
|
||||
preamble: `/*! jQuery ${version}` +
|
||||
" | (c) OpenJS Foundation and other contributors" +
|
||||
" | jquery.org/license */\n"
|
||||
},
|
||||
mangle: true,
|
||||
inlineSourcesContent: false,
|
||||
sourceMap: sourceMapFilename ?
|
||||
{
|
||||
filename: sourceMapFilename
|
||||
} :
|
||||
false
|
||||
sourceMap: true
|
||||
}
|
||||
);
|
||||
|
||||
// Can't seem to get SWC to not use CRLF on Windows, so replace them with LF.
|
||||
grunt.file.write( dest, code.replace( /\r\n/g, "\n" ) );
|
||||
const minFilename = filename.replace( rjs, ".min.js" );
|
||||
const mapFilename = filename.replace( rjs, ".min.map" );
|
||||
|
||||
if ( sourceMapFilename ) {
|
||||
|
||||
// Apply map overrides if needed. See the task config description
|
||||
// for more details.
|
||||
const mapObject = {
|
||||
// The map's `files` & `sources` property are set incorrectly, fix
|
||||
// them via overrides from the task config.
|
||||
// See https://github.com/swc-project/swc/issues/7588#issuecomment-1624345254
|
||||
const map = JSON.stringify( {
|
||||
...JSON.parse( incompleteMap ),
|
||||
...sourceMapOverrides
|
||||
};
|
||||
const map = JSON.stringify( mapObject );
|
||||
file: minFilename,
|
||||
sources: [ filename ]
|
||||
} );
|
||||
|
||||
grunt.file.write( sourceMapFilename, map );
|
||||
}
|
||||
} ) );
|
||||
await Promise.all( [
|
||||
fs.promises.writeFile(
|
||||
path.join( dir, minFilename ),
|
||||
code
|
||||
),
|
||||
fs.promises.writeFile(
|
||||
path.join( dir, mapFilename ),
|
||||
map
|
||||
)
|
||||
] );
|
||||
|
||||
done();
|
||||
}
|
||||
);
|
||||
// Always process files for dist
|
||||
// Doing it here avoids extra file reads
|
||||
processForDist( contents, filename );
|
||||
processForDist( code, minFilename );
|
||||
processForDist( map, mapFilename );
|
||||
|
||||
console.log( `[${getTimestamp()}] ${minFilename} ${version} with ${mapFilename} created.` );
|
||||
};
|
||||
|
@ -1,51 +1,50 @@
|
||||
"use strict";
|
||||
|
||||
module.exports = ( grunt ) => {
|
||||
const fs = require( "fs" );
|
||||
const spawnTest = require( "./lib/spawn_test.js" );
|
||||
const nodeV16OrNewer = !/^v1[0-5]\./.test( process.version );
|
||||
const util = require( "util" );
|
||||
const exec = util.promisify( require( "child_process" ).exec );
|
||||
const verifyNodeVersion = require( "./lib/verifyNodeVersion" );
|
||||
|
||||
grunt.registerTask( "node_smoke_tests", function( moduleType, jQueryModuleSpecifier ) {
|
||||
if (
|
||||
( moduleType !== "commonjs" && moduleType !== "module" ) ||
|
||||
!jQueryModuleSpecifier
|
||||
) {
|
||||
grunt.fatal( "Use `node_smoke_tests:commonjs:JQUERY` " +
|
||||
"or `node_smoke_tests:module:JQUERY.\n" +
|
||||
"JQUERY can be `jquery`, `jquery/slim` or a path to any of them." );
|
||||
}
|
||||
const allowedModules = [ "commonjs", "module" ];
|
||||
|
||||
if ( !nodeV16OrNewer ) {
|
||||
grunt.log.writeln( "Old Node.js detected, running the task " +
|
||||
`"node_smoke_tests:${ moduleType }:${ jQueryModuleSpecifier }" skipped...` );
|
||||
if ( !verifyNodeVersion() ) {
|
||||
return;
|
||||
}
|
||||
|
||||
const testsDir = `./test/node_smoke_tests/${ moduleType }`;
|
||||
const nodeSmokeTests = [];
|
||||
|
||||
// Fire up all tests defined in test/node_smoke_tests/*.js in spawned sub-processes.
|
||||
// All the files under test/node_smoke_tests/*.js are supposed to exit with 0 code
|
||||
// on success or another one on failure. Spawning in sub-processes is
|
||||
// important so that the tests & the main process don't interfere with
|
||||
// each other, e.g. so that they don't share the `require` cache.
|
||||
|
||||
fs.readdirSync( testsDir )
|
||||
.filter( ( testFilePath ) =>
|
||||
fs.statSync( `${ testsDir }/${ testFilePath }` ).isFile() &&
|
||||
/\.[cm]?js$/.test( testFilePath )
|
||||
async function runTests( sourceType, module ) {
|
||||
if ( !allowedModules.includes( sourceType ) ) {
|
||||
throw new Error(
|
||||
`Usage: \`node_smoke_tests [${allowedModules.join( "|" )}]:JQUERY\``
|
||||
);
|
||||
}
|
||||
const dir = `./test/node_smoke_tests/${sourceType}`;
|
||||
const files = await fs.promises.readdir( dir, { withFileTypes: true } );
|
||||
const testFiles = files.filter( ( testFilePath ) => testFilePath.isFile() );
|
||||
await Promise.all(
|
||||
testFiles.map( ( testFile ) =>
|
||||
exec( `node "${dir}/${testFile.name}" "${module}"` )
|
||||
)
|
||||
.forEach( ( testFilePath ) => {
|
||||
const taskName = `node_${ testFilePath.replace( /\.[cm]?js$/, "" ) }:${ moduleType }:${ jQueryModuleSpecifier }`;
|
||||
);
|
||||
console.log( `Node smoke tests passed for ${sourceType} "${module}".` );
|
||||
}
|
||||
|
||||
grunt.registerTask( taskName, function() {
|
||||
spawnTest( this.async(), `node "${ testsDir }/${
|
||||
testFilePath }" ${ jQueryModuleSpecifier }` );
|
||||
} );
|
||||
async function runDefaultTests() {
|
||||
await Promise.all( [
|
||||
runTests( "commonjs", "jquery" ),
|
||||
runTests( "commonjs", "jquery/slim" ),
|
||||
runTests( "commonjs", "./dist/jquery.js" ),
|
||||
runTests( "commonjs", "./dist/jquery.slim.js" ),
|
||||
runTests( "module", "jquery" ),
|
||||
runTests( "module", "jquery/slim" ),
|
||||
runTests( "module", "./dist-module/jquery.module.js" ),
|
||||
runTests( "module", "./dist-module/jquery.slim.module.js" )
|
||||
] );
|
||||
}
|
||||
|
||||
nodeSmokeTests.push( taskName );
|
||||
} );
|
||||
|
||||
grunt.task.run( nodeSmokeTests );
|
||||
} );
|
||||
};
|
||||
runDefaultTests();
|
||||
|
42
build/tasks/npmcopy.js
Normal file
42
build/tasks/npmcopy.js
Normal file
@ -0,0 +1,42 @@
|
||||
"use strict";
|
||||
|
||||
const fs = require( "fs" );
|
||||
const path = require( "path" );
|
||||
|
||||
const projectDir = path.resolve( __dirname, "..", ".." );
|
||||
|
||||
const files = {
|
||||
"bootstrap/bootstrap.css": "bootstrap/dist/css/bootstrap.css",
|
||||
"bootstrap/bootstrap.min.css": "bootstrap/dist/css/bootstrap.min.css",
|
||||
"bootstrap/bootstrap.min.css.map": "bootstrap/dist/css/bootstrap.min.css.map",
|
||||
|
||||
"core-js-bundle/core-js-bundle.js": "core-js-bundle/minified.js",
|
||||
"core-js-bundle/LICENSE": "core-js-bundle/LICENSE",
|
||||
|
||||
"npo/npo.js": "native-promise-only/lib/npo.src.js",
|
||||
|
||||
"qunit/qunit.js": "qunit/qunit/qunit.js",
|
||||
"qunit/qunit.css": "qunit/qunit/qunit.css",
|
||||
"qunit/LICENSE.txt": "qunit/LICENSE.txt",
|
||||
|
||||
"requirejs/require.js": "requirejs/require.js",
|
||||
|
||||
"sinon/sinon.js": "sinon/pkg/sinon.js",
|
||||
"sinon/LICENSE.txt": "sinon/LICENSE"
|
||||
};
|
||||
|
||||
async function npmcopy() {
|
||||
await fs.promises.mkdir( path.resolve( projectDir, "external" ), {
|
||||
recursive: true
|
||||
} );
|
||||
for ( const [ dest, source ] of Object.entries( files ) ) {
|
||||
const from = path.resolve( projectDir, "node_modules", source );
|
||||
const to = path.resolve( projectDir, "external", dest );
|
||||
const toDir = path.dirname( to );
|
||||
await fs.promises.mkdir( toDir, { recursive: true } );
|
||||
await fs.promises.copyFile( from, to );
|
||||
console.log( `${source} → ${dest}` );
|
||||
}
|
||||
}
|
||||
|
||||
npmcopy();
|
@ -1,27 +1,32 @@
|
||||
"use strict";
|
||||
|
||||
module.exports = grunt => {
|
||||
const timeout = 2000;
|
||||
const spawnTest = require( "./lib/spawn_test.js" );
|
||||
const { spawn } = require( "child_process" );
|
||||
const verifyNodeVersion = require( "./lib/verifyNodeVersion" );
|
||||
const path = require( "path" );
|
||||
const os = require( "os" );
|
||||
|
||||
grunt.registerTask( "promises_aplus_tests",
|
||||
[ "promises_aplus_tests:deferred", "promises_aplus_tests:when" ] );
|
||||
if ( !verifyNodeVersion() ) {
|
||||
return;
|
||||
}
|
||||
|
||||
grunt.registerTask( "promises_aplus_tests:deferred", function() {
|
||||
spawnTest( this.async(),
|
||||
"\"" + __dirname + "/../../node_modules/.bin/promises-aplus-tests\"" +
|
||||
" test/promises_aplus_adapters/deferred.cjs" +
|
||||
" --reporter dot" +
|
||||
" --timeout " + timeout
|
||||
const command = path.resolve(
|
||||
__dirname,
|
||||
`../../node_modules/.bin/promises-aplus-tests${os.platform() === "win32" ? ".cmd" : ""}`
|
||||
);
|
||||
const args = [ "--reporter", "dot", "--timeout", "2000" ];
|
||||
const tests = [
|
||||
"test/promises_aplus_adapters/deferred.cjs",
|
||||
"test/promises_aplus_adapters/when.cjs"
|
||||
];
|
||||
|
||||
async function runTests() {
|
||||
tests.forEach( ( test ) => {
|
||||
spawn(
|
||||
command,
|
||||
[ test ].concat( args ),
|
||||
{ stdio: "inherit" }
|
||||
);
|
||||
} );
|
||||
}
|
||||
|
||||
grunt.registerTask( "promises_aplus_tests:when", function() {
|
||||
spawnTest( this.async(),
|
||||
"\"" + __dirname + "/../../node_modules/.bin/promises-aplus-tests\"" +
|
||||
" test/promises_aplus_adapters/when.cjs" +
|
||||
" --reporter dot" +
|
||||
" --timeout " + timeout
|
||||
);
|
||||
} );
|
||||
};
|
||||
runTests();
|
||||
|
17
build/tasks/qunit-fixture.js
Normal file
17
build/tasks/qunit-fixture.js
Normal file
@ -0,0 +1,17 @@
|
||||
"use strict";
|
||||
|
||||
const fs = require( "fs" );
|
||||
|
||||
async function generateFixture() {
|
||||
const fixture = await fs.promises.readFile( "./test/data/qunit-fixture.html", "utf8" );
|
||||
await fs.promises.writeFile(
|
||||
"./test/data/qunit-fixture.js",
|
||||
"// Generated by build/tasks/qunit-fixture.js\n" +
|
||||
"QUnit.config.fixture = " +
|
||||
JSON.stringify( fixture.replace( /\r\n/g, "\n" ) ) +
|
||||
";\n"
|
||||
);
|
||||
console.log( "Updated ./test/data/qunit-fixture.js" );
|
||||
}
|
||||
|
||||
generateFixture();
|
@ -1,22 +0,0 @@
|
||||
"use strict";
|
||||
|
||||
var fs = require( "fs" );
|
||||
|
||||
module.exports = function( grunt ) {
|
||||
grunt.registerTask( "qunit_fixture", function() {
|
||||
var dest = "./test/data/qunit-fixture.js";
|
||||
fs.writeFileSync(
|
||||
dest,
|
||||
"// Generated by build/tasks/qunit_fixture.js\n" +
|
||||
"QUnit.config.fixture = " +
|
||||
JSON.stringify(
|
||||
fs.readFileSync(
|
||||
"./test/data/qunit-fixture.html",
|
||||
"utf8"
|
||||
).toString().replace( /\r\n/g, "\n" )
|
||||
) +
|
||||
";\n"
|
||||
);
|
||||
grunt.log.ok( "Updated " + dest + "." );
|
||||
} );
|
||||
};
|
@ -1,45 +0,0 @@
|
||||
{
|
||||
"root": true,
|
||||
|
||||
"parserOptions": {
|
||||
"ecmaVersion": 2015,
|
||||
"sourceType": "module"
|
||||
},
|
||||
|
||||
"globals": {
|
||||
"define": false,
|
||||
"Symbol": false
|
||||
},
|
||||
|
||||
"overrides": [
|
||||
{
|
||||
"files": "jquery{,.slim}.module.min.js",
|
||||
|
||||
"parserOptions": {
|
||||
"ecmaVersion": 2015,
|
||||
"sourceType": "module"
|
||||
}
|
||||
},
|
||||
|
||||
{
|
||||
"files": "jquery{,.slim}.module.js",
|
||||
"extends": "../.eslintrc-browser.json",
|
||||
|
||||
"parserOptions": {
|
||||
"ecmaVersion": 2015,
|
||||
"sourceType": "module"
|
||||
},
|
||||
|
||||
"rules": {
|
||||
|
||||
// That is okay for the built version
|
||||
"no-multiple-empty-lines": "off",
|
||||
|
||||
// When custom compilation is used, the version string
|
||||
// can get large. Accept that in the built version.
|
||||
"max-len": "off",
|
||||
"one-var": "off"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
41
dist/.eslintrc.json
vendored
41
dist/.eslintrc.json
vendored
@ -1,41 +0,0 @@
|
||||
{
|
||||
"root": true,
|
||||
|
||||
"parserOptions": {
|
||||
"ecmaVersion": 5,
|
||||
"sourceType": "script"
|
||||
},
|
||||
|
||||
"globals": {
|
||||
"define": false,
|
||||
"module": true,
|
||||
"Symbol": false
|
||||
},
|
||||
|
||||
"overrides": [
|
||||
{
|
||||
"files": "jquery{,.slim}.min.js",
|
||||
|
||||
"parserOptions": {
|
||||
"ecmaVersion": 5,
|
||||
"sourceType": "script"
|
||||
}
|
||||
},
|
||||
|
||||
{
|
||||
"files": "jquery{,.slim}.js",
|
||||
"extends": "../.eslintrc-browser.json",
|
||||
|
||||
"rules": {
|
||||
|
||||
// That is okay for the built version
|
||||
"no-multiple-empty-lines": "off",
|
||||
|
||||
// When custom compilation is used, the version string
|
||||
// can get large. Accept that in the built version.
|
||||
"max-len": "off",
|
||||
"one-var": "off"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
305
eslint.config.js
Normal file
305
eslint.config.js
Normal file
@ -0,0 +1,305 @@
|
||||
import jqueryConfig from "eslint-config-jquery";
|
||||
import importPlugin from "eslint-plugin-import";
|
||||
import globals from "globals";
|
||||
|
||||
export default [
|
||||
{
|
||||
|
||||
// Only global ignores will bypass the parser
|
||||
// and avoid JS parsing errors
|
||||
// See https://github.com/eslint/eslint/discussions/17412
|
||||
ignores: [
|
||||
"external",
|
||||
"test/data/json_obj.js"
|
||||
]
|
||||
},
|
||||
|
||||
{
|
||||
files: [
|
||||
"eslint.config.js",
|
||||
"Gruntfile.cjs",
|
||||
"test/node_smoke_tests/commonjs/**",
|
||||
"test/node_smoke_tests/module/**",
|
||||
"test/promises_aplus_adapters/**",
|
||||
"test/middleware-mockserver.cjs"
|
||||
],
|
||||
languageOptions: {
|
||||
globals: {
|
||||
...globals.node
|
||||
}
|
||||
},
|
||||
rules: {
|
||||
...jqueryConfig.rules,
|
||||
strict: [ "error", "global" ]
|
||||
}
|
||||
},
|
||||
|
||||
// Source
|
||||
{
|
||||
files: [ "src/**" ],
|
||||
plugins: {
|
||||
import: importPlugin
|
||||
},
|
||||
languageOptions: {
|
||||
|
||||
// The browser env is not enabled on purpose so that code takes
|
||||
// all browser-only globals from window instead of assuming
|
||||
// they're available as globals. This makes it possible to use
|
||||
// jQuery with tools like jsdom which provide a custom window
|
||||
// implementation.
|
||||
globals: {
|
||||
window: false
|
||||
}
|
||||
},
|
||||
rules: {
|
||||
...jqueryConfig.rules,
|
||||
"import/extensions": [ "error", "always" ],
|
||||
"import/no-cycle": "error",
|
||||
|
||||
// TODO: Enable this rule when eslint-plugin-import supports
|
||||
// it when using flat config.
|
||||
// See https://github.com/import-js/eslint-plugin-import/issues/2556
|
||||
|
||||
// "import/no-unused-modules": [
|
||||
// "error",
|
||||
// {
|
||||
// unusedExports: true,
|
||||
|
||||
// // When run via WebStorm, the root path against which these paths
|
||||
// // are resolved is the path where this ESLint config file lies,
|
||||
// // i.e. `src`. When run via the command line, it's usually the root
|
||||
// // folder of the jQuery repository. This pattern intends to catch both.
|
||||
// // Note that we cannot specify two patterns here:
|
||||
// // [ "src/*.js", "*.js" ]
|
||||
// // as they're analyzed individually and the rule crashes if a pattern
|
||||
// // cannot be matched.
|
||||
// ignoreExports: [ "{src/,}*.js" ]
|
||||
// }
|
||||
// ],
|
||||
indent: [
|
||||
"error",
|
||||
"tab",
|
||||
{
|
||||
outerIIFEBody: 0
|
||||
}
|
||||
],
|
||||
"one-var": [ "error", { var: "always" } ],
|
||||
strict: [ "error", "function" ]
|
||||
}
|
||||
},
|
||||
|
||||
{
|
||||
files: [ "src/wrapper.js" ],
|
||||
languageOptions: {
|
||||
sourceType: "script",
|
||||
globals: {
|
||||
jQuery: false,
|
||||
module: true
|
||||
}
|
||||
},
|
||||
rules: {
|
||||
"no-unused-vars": "off",
|
||||
indent: [
|
||||
"error",
|
||||
"tab",
|
||||
{
|
||||
|
||||
// This makes it so code within the wrapper is not indented.
|
||||
ignoredNodes: [
|
||||
"Program > ExpressionStatement > CallExpression > :last-child > *"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
|
||||
{
|
||||
files: [ "src/wrapper-esm.js" ],
|
||||
languageOptions: {
|
||||
globals: {
|
||||
jQuery: false
|
||||
}
|
||||
},
|
||||
rules: {
|
||||
"no-unused-vars": "off",
|
||||
indent: [
|
||||
"error",
|
||||
"tab",
|
||||
{
|
||||
|
||||
// This makes it so code within the wrapper is not indented.
|
||||
ignoredNodes: [
|
||||
"Program > FunctionDeclaration > *"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
|
||||
{
|
||||
files: [ "src/exports/amd.js" ],
|
||||
languageOptions: {
|
||||
globals: {
|
||||
define: false
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
// Tests
|
||||
{
|
||||
files: [
|
||||
"test/**"
|
||||
],
|
||||
ignores: [
|
||||
"test/data/jquery-1.9.1.js",
|
||||
"test/data/badcall.js",
|
||||
"test/data/badjson.js",
|
||||
"test/data/support/csp.js",
|
||||
"test/data/support/getComputedSupport.js",
|
||||
"test/data/core/jquery-iterability-transpiled.js"
|
||||
],
|
||||
languageOptions: {
|
||||
globals: {
|
||||
...globals.browser,
|
||||
require: false,
|
||||
Promise: false,
|
||||
Symbol: false,
|
||||
trustedTypes: false,
|
||||
QUnit: false,
|
||||
ajaxTest: false,
|
||||
testIframe: false,
|
||||
createDashboardXML: false,
|
||||
createWithFriesXML: false,
|
||||
createXMLFragment: false,
|
||||
includesModule: false,
|
||||
moduleTeardown: false,
|
||||
url: false,
|
||||
q: false,
|
||||
jQuery: true,
|
||||
sinon: true,
|
||||
amdDefined: true,
|
||||
fireNative: true,
|
||||
Globals: true,
|
||||
hasPHP: true,
|
||||
isLocal: true,
|
||||
supportjQuery: true,
|
||||
originaljQuery: true,
|
||||
$: true,
|
||||
original$: true,
|
||||
baseURL: true,
|
||||
externalHost: true
|
||||
}
|
||||
},
|
||||
rules: {
|
||||
...jqueryConfig.rules,
|
||||
strict: [ "error", "function" ],
|
||||
|
||||
// See https://github.com/eslint/eslint/issues/2342
|
||||
"no-unused-vars": "off",
|
||||
|
||||
// Too many errors
|
||||
"max-len": "off",
|
||||
camelcase: "off",
|
||||
"one-var": "off"
|
||||
}
|
||||
},
|
||||
|
||||
{
|
||||
files: [
|
||||
"test/data/testrunner.js",
|
||||
"test/data/core/jquery-iterability-transpiled-es6.js"
|
||||
],
|
||||
languageOptions: {
|
||||
sourceType: "script"
|
||||
}
|
||||
},
|
||||
|
||||
{
|
||||
files: [
|
||||
"test/unit/deferred.js"
|
||||
],
|
||||
rules: {
|
||||
|
||||
// Deferred tests set strict mode for certain tests
|
||||
strict: "off"
|
||||
}
|
||||
},
|
||||
|
||||
{
|
||||
files: [
|
||||
"test/node_smoke_tests/commonjs/**",
|
||||
"test/node_smoke_tests/module/**",
|
||||
"test/promises_aplus_adapters/**",
|
||||
"test/middleware-mockserver.cjs"
|
||||
],
|
||||
languageOptions: {
|
||||
globals: {
|
||||
...globals.node,
|
||||
...globals.es2021
|
||||
}
|
||||
},
|
||||
rules: {
|
||||
strict: [ "error", "global" ]
|
||||
}
|
||||
},
|
||||
|
||||
{
|
||||
files: [
|
||||
"build/**",
|
||||
"test/data/testinit.js",
|
||||
"test/data/testinit-jsdom.js"
|
||||
],
|
||||
languageOptions: {
|
||||
globals: {
|
||||
...globals.node,
|
||||
...globals.es2021
|
||||
}
|
||||
},
|
||||
rules: {
|
||||
...jqueryConfig.rules,
|
||||
strict: [ "error", "global" ]
|
||||
}
|
||||
},
|
||||
|
||||
{
|
||||
files: [
|
||||
"build/**/*.js",
|
||||
"test/data/testinit.js",
|
||||
"test/data/testinit-jsdom.js"
|
||||
],
|
||||
languageOptions: {
|
||||
sourceType: "commonjs"
|
||||
}
|
||||
},
|
||||
|
||||
{
|
||||
files: [
|
||||
"dist/jquery.js",
|
||||
"dist/jquery.slim.js",
|
||||
"dist-module/jquery.module.js",
|
||||
"dist-module/jquery.slim.module.js"
|
||||
],
|
||||
|
||||
languageOptions: {
|
||||
globals: {
|
||||
...globals.browser,
|
||||
...globals.es2021,
|
||||
define: false,
|
||||
module: false,
|
||||
Symbol: false
|
||||
}
|
||||
},
|
||||
|
||||
rules: {
|
||||
...jqueryConfig.rules,
|
||||
|
||||
// That is okay for the built version
|
||||
"no-multiple-empty-lines": "off",
|
||||
|
||||
// When custom compilation is used, the version string
|
||||
// can get large. Accept that in the built version.
|
||||
"max-len": "off",
|
||||
"one-var": "off"
|
||||
}
|
||||
}
|
||||
];
|
8188
package-lock.json
generated
Normal file
8188
package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load Diff
75
package.json
75
package.json
@ -30,6 +30,31 @@
|
||||
"./src/*.js": "./src/*.js"
|
||||
},
|
||||
"main": "dist/jquery.js",
|
||||
"scripts": {
|
||||
"babel:tests": "babel test/data/core/jquery-iterability-transpiled-es6.js --out-file test/data/core/jquery-iterability-transpiled.js",
|
||||
"build": "node ./build/command.js",
|
||||
"build:all": "node -e \"require('./build/tasks/build.js').buildDefaultFiles()\"",
|
||||
"build:main": "node -e \"require('./build/tasks/build.js').build()\"",
|
||||
"jenkins": "npm run test:browserless",
|
||||
"lint:dev": "eslint --cache .",
|
||||
"lint:json": "jsonlint --quiet package.json",
|
||||
"lint": "concurrently -r \"npm:lint:dev\" \"npm:lint:json\"",
|
||||
"npmcopy": "node build/tasks/npmcopy.js",
|
||||
"prepare": "husky install",
|
||||
"pretest": "npm run qunit-fixture && npm run babel:tests && npm run npmcopy",
|
||||
"qunit-fixture": "node build/tasks/qunit-fixture.js",
|
||||
"start": "node -e \"require('./build/tasks/build.js').buildDefaultFiles({ watch: true })\"",
|
||||
"test:browserless": "npm run test:node_smoke_tests && npm run test:promises_aplus && npm run test:jsdom",
|
||||
"test:browser": "npm run build:all && grunt karma:main",
|
||||
"test:esmodules": "npm run build:main && grunt karma:esmodules",
|
||||
"test:jsdom": "npm run build:main && grunt test:jsdom",
|
||||
"test:no-deprecated": "npm run build -- -e deprecated && grunt karma:main",
|
||||
"test:selector-native": "npm run build -- -e selector && grunt karma:main",
|
||||
"test:slim": "npm run build -- --slim && grunt karma:main",
|
||||
"test:node_smoke_tests": "npm run build:all && node build/tasks/node_smoke_tests.js",
|
||||
"test:promises_aplus": "npm run build:main && node build/tasks/promises_aplus_tests.js",
|
||||
"test": "npm run build:all && npm run lint && npm run test:browserless && npm run test:browser && npm run test:esmodules && npm run test:slim && npm run test:no-deprecated && npm run test:selector-native"
|
||||
},
|
||||
"homepage": "https://jquery.com",
|
||||
"author": {
|
||||
"name": "OpenJS Foundation and other contributors",
|
||||
@ -50,28 +75,27 @@
|
||||
},
|
||||
"license": "MIT",
|
||||
"devDependencies": {
|
||||
"@babel/cli": "7.22.9",
|
||||
"@babel/core": "7.10.5",
|
||||
"@babel/plugin-transform-for-of": "7.10.4",
|
||||
"@swc/core": "1.3.66",
|
||||
"@prantlf/jsonlint": "14.0.3",
|
||||
"@swc/core": "1.3.78",
|
||||
"bootstrap": "5.3.0",
|
||||
"chalk": "5.3.0",
|
||||
"colors": "1.4.0",
|
||||
"commitplease": "3.2.0",
|
||||
"concurrently": "8.2.0",
|
||||
"core-js-bundle": "3.6.5",
|
||||
"eslint-config-jquery": "3.0.0",
|
||||
"eslint-plugin-import": "2.25.2",
|
||||
"eslint": "8.44.0",
|
||||
"eslint-config-jquery": "3.0.1",
|
||||
"eslint-plugin-import": "2.27.5",
|
||||
"express": "4.18.2",
|
||||
"globals": "13.20.0",
|
||||
"grunt": "1.5.3",
|
||||
"grunt-babel": "8.0.0",
|
||||
"grunt-cli": "1.4.3",
|
||||
"grunt-compare-size": "0.4.2",
|
||||
"grunt-contrib-watch": "1.1.0",
|
||||
"grunt-eslint": "24.0.0",
|
||||
"grunt-git-authors": "3.2.0",
|
||||
"grunt-jsonlint": "2.1.2",
|
||||
"grunt-karma": "4.0.2",
|
||||
"grunt-newer": "1.3.0",
|
||||
"grunt-npmcopy": "0.2.0",
|
||||
"gzip-js": "0.3.2",
|
||||
"husky": "4.2.5",
|
||||
"husky": "8.0.3",
|
||||
"jsdom": "19.0.0",
|
||||
"karma": "6.4.1",
|
||||
"karma-browserstack-launcher": "1.6.0",
|
||||
@ -94,25 +118,8 @@
|
||||
"rollup": "2.21.0",
|
||||
"sinon": "7.3.1",
|
||||
"strip-json-comments": "3.1.1",
|
||||
"testswarm": "1.1.2"
|
||||
},
|
||||
"scripts": {
|
||||
"build": "npm install && npm run build-all-variants",
|
||||
"build-all-variants": "grunt custom:slim --esm --filename=jquery.slim.module.js && grunt custom --esm --filename=jquery.module.js && grunt custom:slim --filename=jquery.slim.js && grunt custom",
|
||||
"start": "grunt watch",
|
||||
"test:browserless": "grunt && npm run test:node_smoke_tests && grunt test:slow",
|
||||
"test:browser": "grunt && grunt karma:main",
|
||||
"test:esmodules": "grunt && grunt karma:esmodules",
|
||||
"test:no-deprecated": "grunt test:prepare && grunt custom:-deprecated && grunt karma:main",
|
||||
"test:selector-native": "grunt test:prepare && grunt custom:-selector && grunt karma:main",
|
||||
"test:slim": "grunt test:prepare && grunt custom:slim && grunt karma:main",
|
||||
"test:node_smoke_tests:full-module": "grunt node_smoke_tests:module:./dist-module/jquery.module.js && grunt node_smoke_tests:module:jquery",
|
||||
"test:node_smoke_tests:full-commonjs": "grunt node_smoke_tests:commonjs:./dist/jquery.js && grunt node_smoke_tests:commonjs:jquery",
|
||||
"test:node_smoke_tests:slim-module": "grunt node_smoke_tests:module:./dist-module/jquery.slim.module.js && grunt node_smoke_tests:module:jquery/slim",
|
||||
"test:node_smoke_tests:slim-commonjs": "grunt node_smoke_tests:commonjs:./dist/jquery.slim.js && grunt node_smoke_tests:commonjs:jquery/slim",
|
||||
"test:node_smoke_tests": "npm run test:node_smoke_tests:full-module && npm run test:node_smoke_tests:slim-module && npm run test:node_smoke_tests:full-commonjs && npm run test:node_smoke_tests:slim-commonjs",
|
||||
"test": "npm run test:browserless && npm run test:slim && npm run test:no-deprecated && npm run test:selector-native && grunt && grunt test:slow && grunt karma:main && grunt karma:esmodules",
|
||||
"jenkins": "npm run test:browserless"
|
||||
"testswarm": "1.1.2",
|
||||
"yargs": "17.7.2"
|
||||
},
|
||||
"commitplease": {
|
||||
"nohook": true,
|
||||
@ -143,11 +150,5 @@
|
||||
],
|
||||
"markerPattern": "^((clos|fix|resolv)(e[sd]|ing))|^(refs?)",
|
||||
"ticketPattern": "^((Closes|Fixes) ([a-zA-Z]{2,}-)[0-9]+)|^(Refs? [^#])"
|
||||
},
|
||||
"husky": {
|
||||
"hooks": {
|
||||
"commit-msg": "commitplease .git/COMMIT_EDITMSG",
|
||||
"pre-commit": "grunt lint:newer qunit_fixture"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,102 +0,0 @@
|
||||
{
|
||||
"root": true,
|
||||
|
||||
"extends": "../.eslintrc-browser.json",
|
||||
|
||||
"parserOptions": {
|
||||
"ecmaVersion": 2015,
|
||||
"sourceType": "module"
|
||||
},
|
||||
|
||||
"plugins": [ "import" ],
|
||||
|
||||
"rules": {
|
||||
"import/extensions": [ "error", "always" ],
|
||||
"import/no-cycle": "error",
|
||||
"import/no-unused-modules": [ "error", {
|
||||
"unusedExports": true,
|
||||
|
||||
// When run via WebStorm, the root path against which these paths
|
||||
// are resolved is the path where this ESLint config file lies,
|
||||
// i.e. `src`. When run via the command line, it's usually the root
|
||||
// folder of the jQuery repository. This pattern intends to catch both.
|
||||
// Note that we cannot specify two patterns here:
|
||||
// [ "src/*.js", "*.js" ]
|
||||
// as they're analyzed individually and the rule crashes if a pattern
|
||||
// cannot be matched.
|
||||
"ignoreExports": [ "{src/,}*.js" ]
|
||||
} ],
|
||||
"indent": [ "error", "tab", {
|
||||
"outerIIFEBody": 0
|
||||
} ]
|
||||
},
|
||||
|
||||
"overrides": [
|
||||
{
|
||||
"files": "wrapper.js",
|
||||
"parserOptions": {
|
||||
"ecmaVersion": 5,
|
||||
"sourceType": "script"
|
||||
},
|
||||
"rules": {
|
||||
"no-unused-vars": "off",
|
||||
"indent": [ "error", "tab", {
|
||||
|
||||
// Unlike other codes, "wrapper.js" is implemented in UMD.
|
||||
// So it required a specific exception for jQuery's UMD
|
||||
// Code Style. This makes that indentation check is not
|
||||
// performed for 1 depth of outer FunctionExpressions
|
||||
"ignoredNodes": [
|
||||
"Program > ExpressionStatement > CallExpression > :last-child > *"
|
||||
]
|
||||
} ]
|
||||
},
|
||||
"globals": {
|
||||
"jQuery": false,
|
||||
"module": true
|
||||
}
|
||||
},
|
||||
|
||||
{
|
||||
"files": "wrapper-esm.js",
|
||||
"parserOptions": {
|
||||
"ecmaVersion": 2015,
|
||||
"sourceType": "module"
|
||||
},
|
||||
"globals": {
|
||||
"jQuery": false
|
||||
},
|
||||
"rules": {
|
||||
"no-unused-vars": "off",
|
||||
"indent": [ "error", "tab", {
|
||||
// Unlike other codes, "wrapper.js" is implemented in UMD.
|
||||
// So it required a specific exception for jQuery's UMD
|
||||
// Code Style. This makes that indentation check is not
|
||||
// performed for 1 depth of outer FunctionExpressions
|
||||
"ignoredNodes": [
|
||||
"Program > FunctionDeclaration > *"
|
||||
]
|
||||
} ],
|
||||
"import/no-unused-modules": "off"
|
||||
}
|
||||
},
|
||||
|
||||
{
|
||||
"files": "exports/amd.js",
|
||||
"globals": {
|
||||
"define": false
|
||||
}
|
||||
},
|
||||
|
||||
{
|
||||
"files": "core.js",
|
||||
"globals": {
|
||||
|
||||
// Defining Symbol globally would create a danger of using
|
||||
// it unguarded in another place, it seems safer to define
|
||||
// it only for this module.
|
||||
"Symbol": false
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
@ -1,89 +0,0 @@
|
||||
{
|
||||
"root": true,
|
||||
|
||||
"extends": "../.eslintrc-browser.json",
|
||||
|
||||
"env": {
|
||||
|
||||
// In source the browser env is not enabled but unit tests rely on them
|
||||
// too much and we don't run them in non-browser environments anyway.
|
||||
"browser": true
|
||||
},
|
||||
|
||||
"globals": {
|
||||
"require": false,
|
||||
"Promise": false,
|
||||
"Symbol": false,
|
||||
"trustedTypes": false,
|
||||
"QUnit": false,
|
||||
"ajaxTest": false,
|
||||
"testIframe": false,
|
||||
"createDashboardXML": false,
|
||||
"createWithFriesXML": false,
|
||||
"createXMLFragment": false,
|
||||
"includesModule": false,
|
||||
"moduleTeardown": false,
|
||||
"url": false,
|
||||
"q": false,
|
||||
"jQuery": true,
|
||||
"sinon": true,
|
||||
"amdDefined": true,
|
||||
"fireNative": true,
|
||||
"Globals": true,
|
||||
"hasPHP": true,
|
||||
"isLocal": true,
|
||||
"supportjQuery": true,
|
||||
"originaljQuery": true,
|
||||
"$": true,
|
||||
"original$": true,
|
||||
"baseURL": true,
|
||||
"externalHost": true
|
||||
},
|
||||
|
||||
"rules": {
|
||||
// See https://github.com/eslint/eslint/issues/2342
|
||||
"no-unused-vars": "off",
|
||||
|
||||
// Too many errors
|
||||
"max-len": "off",
|
||||
"brace-style": "off",
|
||||
"key-spacing": "off",
|
||||
"camelcase": "off",
|
||||
"one-var": "off",
|
||||
"strict": "off",
|
||||
|
||||
// Not really too many - waiting for autofix features for these rules
|
||||
"lines-around-comment": "off",
|
||||
"dot-notation": "off"
|
||||
},
|
||||
|
||||
"overrides": [
|
||||
{
|
||||
"files": [
|
||||
"middleware-mockserver.js"
|
||||
],
|
||||
|
||||
"extends": "../.eslintrc-node.json"
|
||||
},
|
||||
|
||||
{
|
||||
"files": [
|
||||
"data/core/jquery-iterability-transpiled-es6.js",
|
||||
"data/testinit-jsdom.js"
|
||||
],
|
||||
"parserOptions": {
|
||||
"ecmaVersion": 2015
|
||||
}
|
||||
},
|
||||
|
||||
{
|
||||
"files": [
|
||||
"jquery.js",
|
||||
"data/testinit.js"
|
||||
],
|
||||
"parserOptions": {
|
||||
"ecmaVersion": 2020
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
5
test/data/core/.babelrc.json
Normal file
5
test/data/core/.babelrc.json
Normal file
@ -0,0 +1,5 @@
|
||||
{
|
||||
"plugins": ["@babel/transform-for-of"],
|
||||
"retainLines": true,
|
||||
"sourceMaps": "inline"
|
||||
}
|
@ -37,10 +37,10 @@ window.original$ = this.$ = "replaced";
|
||||
* @example url("mock.php?foo=bar")
|
||||
* @result "data/mock.php?foo=bar&10538358345554"
|
||||
*/
|
||||
function url( value ) {
|
||||
this.url = function( value ) {
|
||||
return baseURL + value + ( /\?/.test( value ) ? "&" : "?" ) +
|
||||
new Date().getTime() + "" + parseInt( Math.random() * 100000, 10 );
|
||||
}
|
||||
};
|
||||
|
||||
// We only run basic tests in jsdom so we don't need to repeat the logic
|
||||
// from the regular testinit.js
|
||||
|
@ -1,5 +1,4 @@
|
||||
/* eslint no-multi-str: "off" */
|
||||
|
||||
"use strict";
|
||||
|
||||
var FILEPATH = "/test/data/testinit.js",
|
||||
@ -16,18 +15,17 @@ var FILEPATH = "/test/data/testinit.js",
|
||||
baseURL = parentUrl + "test/data/",
|
||||
supportjQuery = this.jQuery,
|
||||
|
||||
// see RFC 2606
|
||||
externalHost = "example.com",
|
||||
|
||||
// NOTE: keep it in sync with build/tasks/lib/slim-build-flags.js
|
||||
slimBuildFlags = [
|
||||
"-ajax",
|
||||
"-callbacks",
|
||||
"-deferred",
|
||||
"-effects",
|
||||
"-queue"
|
||||
excludedFromSlim = [
|
||||
"ajax",
|
||||
"callbacks",
|
||||
"deferred",
|
||||
"effects",
|
||||
"queue"
|
||||
];
|
||||
|
||||
// see RFC 2606
|
||||
this.externalHost = "example.com";
|
||||
this.hasPHP = true;
|
||||
this.isLocal = window.location.protocol === "file:";
|
||||
|
||||
@ -241,7 +239,7 @@ this.ajaxTest = function( title, expect, options, wrapper ) {
|
||||
completed = true;
|
||||
delete ajaxTest.abort;
|
||||
assert.ok( false, "aborted " + reason );
|
||||
jQuery.each( requests, function( i, request ) {
|
||||
jQuery.each( requests, function( _i, request ) {
|
||||
request.abort();
|
||||
} );
|
||||
}
|
||||
@ -319,16 +317,16 @@ this.includesModule = function( moduleName ) {
|
||||
|
||||
var excludedModulesPart, excludedModules;
|
||||
|
||||
// A short-cut for the slim build, e.g. "4.0.0-pre slim"
|
||||
if ( jQuery.fn.jquery.indexOf( " slim" ) > -1 ) {
|
||||
// A short-cut for the slim build, e.g. "4.0.0-pre+slim"
|
||||
if ( jQuery.fn.jquery.indexOf( "+slim" ) > -1 ) {
|
||||
|
||||
// The module is included if it does NOT exist on the list
|
||||
// of modules excluded in the slim build
|
||||
return slimBuildFlags.indexOf( "-" + moduleName ) === -1;
|
||||
return excludedFromSlim.indexOf( moduleName ) === -1;
|
||||
}
|
||||
|
||||
// example version for `grunt custom:-deprecated`:
|
||||
// "4.0.0-pre -deprecated,-deprecated/ajax-event-alias,-deprecated/event"
|
||||
// example version for `npm run build -- -e deprecated`:
|
||||
// "v4.0.0-pre+14dc9347 -deprecated,-deprecated/ajax-event-alias,-deprecated/event"
|
||||
excludedModulesPart = jQuery.fn.jquery
|
||||
|
||||
// Take the flags out of the version string.
|
||||
@ -393,6 +391,7 @@ this.loadTests = function() {
|
||||
|
||||
var i = 0,
|
||||
tests = [
|
||||
|
||||
// A special module with basic tests, meant for not fully
|
||||
// supported environments like jsdom. We run it everywhere,
|
||||
// though, to make sure tests are not broken.
|
||||
|
@ -1,5 +1,4 @@
|
||||
( function() {
|
||||
|
||||
"use strict";
|
||||
|
||||
// Store the old count so that we only assert on tests that have actually leaked,
|
||||
|
@ -67,16 +67,25 @@ const mocks = {
|
||||
resp.end( "<root><element /></root>" );
|
||||
},
|
||||
script: function( req, resp ) {
|
||||
const headers = {};
|
||||
if ( req.query.header === "ecma" ) {
|
||||
resp.writeHead( 200, { "content-type": "application/ecmascript" } );
|
||||
headers[ "content-type" ] = "application/ecmascript";
|
||||
} else if ( "header" in req.query ) {
|
||||
resp.writeHead( 200, { "content-type": "text/javascript" } );
|
||||
headers[ "content-type" ] = "text/javascript";
|
||||
} else {
|
||||
resp.writeHead( 200, { "content-type": "text/html" } );
|
||||
headers[ "content-type" ] = "text/html";
|
||||
}
|
||||
|
||||
if ( req.query.cors ) {
|
||||
resp.writeHead( 200, { "access-control-allow-origin": "*" } );
|
||||
headers[ "access-control-allow-origin" ] = "*";
|
||||
}
|
||||
|
||||
if ( resp.set ) {
|
||||
resp.set( headers );
|
||||
} else {
|
||||
for ( const key in headers ) {
|
||||
resp.writeHead( 200, { [ key ]: headers[ key ] } );
|
||||
}
|
||||
}
|
||||
|
||||
if ( req.query.callback ) {
|
||||
@ -165,14 +174,25 @@ const mocks = {
|
||||
}
|
||||
},
|
||||
headers: function( req, resp ) {
|
||||
resp.writeHead( 200, {
|
||||
const headers = {
|
||||
"Sample-Header": "Hello World",
|
||||
"Empty-Header": "",
|
||||
"Sample-Header2": "Hello World 2",
|
||||
"List-Header": "Item 1",
|
||||
"list-header": "Item 2",
|
||||
"constructor": "prototype collision (constructor)"
|
||||
} );
|
||||
};
|
||||
|
||||
// Use resp.append in express to
|
||||
// avoid overwriting List-Header
|
||||
if ( resp.append ) {
|
||||
|
||||
for ( const key in headers ) {
|
||||
resp.append( key, headers[ key ] );
|
||||
}
|
||||
} else {
|
||||
resp.writeHead( 200, headers );
|
||||
}
|
||||
req.query.keys.split( "|" ).forEach( function( key ) {
|
||||
if ( key.toLowerCase() in req.headers ) {
|
||||
resp.write( `${ key }: ${ req.headers[ key.toLowerCase() ] }\n` );
|
||||
@ -354,7 +374,7 @@ function MockserverMiddlewareFactory() {
|
||||
parsed: parsed
|
||||
} );
|
||||
|
||||
if ( /^test\/data\/mock.php\//.test( path ) ) {
|
||||
if ( /^\/?test\/data\/mock.php\/?/.test( path ) ) {
|
||||
|
||||
// Support REST-like Apache PathInfo
|
||||
path = "test\/data\/mock.php";
|
||||
@ -365,6 +385,7 @@ function MockserverMiddlewareFactory() {
|
||||
return;
|
||||
}
|
||||
|
||||
// console.log( "Mock handling", req.method, parsed.href );
|
||||
handlers[ path ]( subReq, resp, next );
|
||||
};
|
||||
}
|
||||
|
@ -1,13 +0,0 @@
|
||||
{
|
||||
"root": true,
|
||||
|
||||
"extends": "../../../.eslintrc-node.json",
|
||||
|
||||
"parserOptions": {
|
||||
"ecmaVersion": 2015,
|
||||
"sourceType": "script"
|
||||
},
|
||||
"env": {
|
||||
"es2022": true
|
||||
}
|
||||
}
|
@ -1,13 +0,0 @@
|
||||
{
|
||||
"root": true,
|
||||
|
||||
"extends": "../../../.eslintrc-node.json",
|
||||
|
||||
"parserOptions": {
|
||||
"ecmaVersion": 2022,
|
||||
"sourceType": "module"
|
||||
},
|
||||
"env": {
|
||||
"es2022": true
|
||||
}
|
||||
}
|
@ -5,6 +5,11 @@ const dirname = path.dirname( fileURLToPath( import.meta.url ) );
|
||||
|
||||
const ROOT_DIR = path.resolve( dirname, "..", "..", "..", ".." );
|
||||
|
||||
// import does not work with Windows-style paths
|
||||
function ensureUnixPath( path ) {
|
||||
return path.replace( /^[a-z]:/i, "" ).replace( /\\+/g, "/" );
|
||||
}
|
||||
|
||||
// If `jQueryModuleSpecifier` is a real relative path, make it absolute
|
||||
// to make sure it resolves to the same file inside utils from
|
||||
// a subdirectory. Otherwise, leave it as-is as we may be testing `exports`
|
||||
@ -16,6 +21,6 @@ export const getJQueryModuleSpecifier = () => {
|
||||
}
|
||||
|
||||
return jQueryModuleInputSpecifier.startsWith( "." ) ?
|
||||
path.resolve( ROOT_DIR, jQueryModuleInputSpecifier ) :
|
||||
ensureUnixPath( path.resolve( ROOT_DIR, jQueryModuleInputSpecifier ) ) :
|
||||
jQueryModuleInputSpecifier;
|
||||
};
|
||||
|
@ -1,5 +0,0 @@
|
||||
{
|
||||
"root": true,
|
||||
|
||||
"extends": "../../.eslintrc-node.json"
|
||||
}
|
21
test/server.js
Normal file
21
test/server.js
Normal file
@ -0,0 +1,21 @@
|
||||
import express from "express";
|
||||
import mockServer from "./middleware-mockserver.cjs";
|
||||
import fs from "fs";
|
||||
|
||||
const nameHTML = fs.readFileSync( "./test/data/name.html", "utf8" );
|
||||
const app = express();
|
||||
|
||||
app.use( mockServer() );
|
||||
|
||||
app.post( "/test/data/name.html", function( _req, res ) {
|
||||
res.send( nameHTML );
|
||||
} );
|
||||
|
||||
app.use( "/dist", express.static( "dist" ) );
|
||||
app.use( "/src", express.static( "src" ) );
|
||||
app.use( "/test", express.static( "test" ) );
|
||||
app.use( "/external", express.static( "external" ) );
|
||||
|
||||
app.listen( 3000, function() {
|
||||
console.log( "Server is running on port 3000" );
|
||||
} );
|
@ -455,6 +455,7 @@ QUnit.module( "ajax", {
|
||||
},
|
||||
cache: false,
|
||||
beforeSend: function( xhr, settings ) {
|
||||
|
||||
// Clear the cache-buster param value
|
||||
var url = settings.url.replace( /_=[^&#]+/, "_=" );
|
||||
assert.equal( url, baseURL + "name.html?abc&devo=hat&_=#brownies",
|
||||
@ -873,8 +874,8 @@ QUnit.module( "ajax", {
|
||||
success: function( data ) {
|
||||
assert.ok( data.match( /^html text/ ), "Check content for datatype html" );
|
||||
jQuery( "#ap" ).html( data );
|
||||
assert.strictEqual( window[ "testFoo" ], "foo", "Check if script was evaluated for datatype html" );
|
||||
assert.strictEqual( window[ "testBar" ], "bar", "Check if script src was evaluated for datatype html" );
|
||||
assert.strictEqual( window.testFoo, "foo", "Check if script was evaluated for datatype html" );
|
||||
assert.strictEqual( window.testBar, "bar", "Check if script src was evaluated for datatype html" );
|
||||
}
|
||||
};
|
||||
} );
|
||||
@ -884,6 +885,7 @@ QUnit.module( "ajax", {
|
||||
return {
|
||||
dataType: "jsonp",
|
||||
url: url( "mock.php?action=errorWithScript" ),
|
||||
|
||||
// error is the significant assertion
|
||||
error: function( xhr ) {
|
||||
var expected = { "status": 404, "msg": "Not Found" };
|
||||
@ -912,6 +914,7 @@ QUnit.module( "ajax", {
|
||||
complete: function() {
|
||||
jQuery.globalEval = globalEval;
|
||||
},
|
||||
|
||||
// error is the significant assertion
|
||||
error: function( xhr ) {
|
||||
assert.strictEqual( xhr.status, 404, testMsg );
|
||||
@ -1171,8 +1174,8 @@ QUnit.module( "ajax", {
|
||||
Globals.register( "functionToCleanUp" );
|
||||
Globals.register( "XXX" );
|
||||
Globals.register( "jsonpResults" );
|
||||
window[ "jsonpResults" ] = function( data ) {
|
||||
assert.ok( data[ "data" ], "JSON results returned (GET, custom callback function)" );
|
||||
window.jsonpResults = function( data ) {
|
||||
assert.ok( data.data, "JSON results returned (GET, custom callback function)" );
|
||||
};
|
||||
},
|
||||
requests: [ {
|
||||
@ -1181,7 +1184,7 @@ QUnit.module( "ajax", {
|
||||
crossDomain: crossDomain,
|
||||
jsonp: "callback",
|
||||
success: function( data ) {
|
||||
assert.ok( data[ "data" ], "JSON results returned (GET, data obj callback)" );
|
||||
assert.ok( data.data, "JSON results returned (GET, data obj callback)" );
|
||||
}
|
||||
}, {
|
||||
url: baseURL + "mock.php?action=jsonp",
|
||||
@ -1190,7 +1193,7 @@ QUnit.module( "ajax", {
|
||||
jsonpCallback: "jsonpResults",
|
||||
success: function( data ) {
|
||||
assert.strictEqual(
|
||||
typeof window[ "jsonpResults" ],
|
||||
typeof window.jsonpResults,
|
||||
"function",
|
||||
"should not rewrite original function"
|
||||
);
|
||||
@ -1202,8 +1205,8 @@ QUnit.module( "ajax", {
|
||||
crossDomain: crossDomain,
|
||||
jsonpCallback: "functionToCleanUp",
|
||||
success: function( data ) {
|
||||
assert.ok( data[ "data" ], "JSON results returned (GET, custom callback name to be cleaned up)" );
|
||||
assert.strictEqual( window[ "functionToCleanUp" ], true, "Callback was removed (GET, custom callback name to be cleaned up)" );
|
||||
assert.ok( data.data, "JSON results returned (GET, custom callback name to be cleaned up)" );
|
||||
assert.strictEqual( window.functionToCleanUp, true, "Callback was removed (GET, custom callback name to be cleaned up)" );
|
||||
var xhr;
|
||||
jQuery.ajax( {
|
||||
url: baseURL + "mock.php?action=jsonp",
|
||||
@ -1217,7 +1220,7 @@ QUnit.module( "ajax", {
|
||||
} );
|
||||
xhr.fail( function() {
|
||||
assert.ok( true, "Ajax error JSON (GET, custom callback name to be cleaned up)" );
|
||||
assert.strictEqual( window[ "functionToCleanUp" ], true, "Callback was removed after early abort (GET, custom callback name to be cleaned up)" );
|
||||
assert.strictEqual( window.functionToCleanUp, true, "Callback was removed after early abort (GET, custom callback name to be cleaned up)" );
|
||||
} );
|
||||
}
|
||||
}, {
|
||||
@ -1230,7 +1233,7 @@ QUnit.module( "ajax", {
|
||||
assert.ok( /action=jsonp&callback=XXX&_=\d+$/.test( this.url ), "The URL wasn't messed with (GET, custom callback name with no url manipulation)" );
|
||||
},
|
||||
success: function( data ) {
|
||||
assert.ok( data[ "data" ], "JSON results returned (GET, custom callback name with no url manipulation)" );
|
||||
assert.ok( data.data, "JSON results returned (GET, custom callback name with no url manipulation)" );
|
||||
}
|
||||
} ]
|
||||
};
|
||||
@ -1267,7 +1270,7 @@ QUnit.module( "ajax", {
|
||||
dataType: "jsonp",
|
||||
crossDomain: crossDomain,
|
||||
success: function( data ) {
|
||||
assert.ok( data[ "data" ], "JSON results returned (POST, no callback)" );
|
||||
assert.ok( data.data, "JSON results returned (POST, no callback)" );
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -1277,7 +1280,7 @@ QUnit.module( "ajax", {
|
||||
dataType: "jsonp",
|
||||
crossDomain: crossDomain,
|
||||
success: function( data ) {
|
||||
assert.ok( data[ "data" ], "JSON results returned (POST, data callback)" );
|
||||
assert.ok( data.data, "JSON results returned (POST, data callback)" );
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -1287,7 +1290,7 @@ QUnit.module( "ajax", {
|
||||
dataType: "jsonp",
|
||||
crossDomain: crossDomain,
|
||||
success: function( data ) {
|
||||
assert.ok( data[ "data" ], "JSON results returned (POST, data obj callback)" );
|
||||
assert.ok( data.data, "JSON results returned (POST, data obj callback)" );
|
||||
}
|
||||
}
|
||||
];
|
||||
@ -1461,7 +1464,7 @@ QUnit.module( "ajax", {
|
||||
url: url( "mock.php?action=testbar" ),
|
||||
dataType: "script",
|
||||
success: function() {
|
||||
assert.strictEqual( window[ "testBar" ], "bar", "Script results returned (GET, no callback)" );
|
||||
assert.strictEqual( window.testBar, "bar", "Script results returned (GET, no callback)" );
|
||||
}
|
||||
};
|
||||
} );
|
||||
@ -1478,7 +1481,7 @@ QUnit.module( "ajax", {
|
||||
type: "POST",
|
||||
dataType: "script",
|
||||
success: function( data, status ) {
|
||||
assert.strictEqual( window[ "testBar" ], "bar", "Script results returned (POST, no callback)" );
|
||||
assert.strictEqual( window.testBar, "bar", "Script results returned (POST, no callback)" );
|
||||
assert.strictEqual( status, "success", "Script results returned (POST, no callback)" );
|
||||
}
|
||||
};
|
||||
@ -1492,7 +1495,7 @@ QUnit.module( "ajax", {
|
||||
url: url( "mock.php?action=testbar" ),
|
||||
dataType: "script",
|
||||
success: function() {
|
||||
assert.strictEqual( window[ "testBar" ], "bar", "Script results returned (GET, no callback)" );
|
||||
assert.strictEqual( window.testBar, "bar", "Script results returned (GET, no callback)" );
|
||||
}
|
||||
};
|
||||
} );
|
||||
@ -1518,10 +1521,10 @@ QUnit.module( "ajax", {
|
||||
},
|
||||
success: function( json ) {
|
||||
assert.ok( json.length >= 2, "Check length" );
|
||||
assert.strictEqual( json[ 0 ][ "name" ], "John", "Check JSON: first, name" );
|
||||
assert.strictEqual( json[ 0 ][ "age" ], 21, "Check JSON: first, age" );
|
||||
assert.strictEqual( json[ 1 ][ "name" ], "Peter", "Check JSON: second, name" );
|
||||
assert.strictEqual( json[ 1 ][ "age" ], 25, "Check JSON: second, age" );
|
||||
assert.strictEqual( json[ 0 ].name, "John", "Check JSON: first, name" );
|
||||
assert.strictEqual( json[ 0 ].age, 21, "Check JSON: first, age" );
|
||||
assert.strictEqual( json[ 1 ].name, "Peter", "Check JSON: second, name" );
|
||||
assert.strictEqual( json[ 1 ].age, 25, "Check JSON: second, age" );
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -1538,10 +1541,10 @@ QUnit.module( "ajax", {
|
||||
],
|
||||
success: function( json ) {
|
||||
assert.ok( json.length >= 2, "Check length" );
|
||||
assert.strictEqual( json[ 0 ][ "name" ], "John", "Check JSON: first, name" );
|
||||
assert.strictEqual( json[ 0 ][ "age" ], 21, "Check JSON: first, age" );
|
||||
assert.strictEqual( json[ 1 ][ "name" ], "Peter", "Check JSON: second, name" );
|
||||
assert.strictEqual( json[ 1 ][ "age" ], 25, "Check JSON: second, age" );
|
||||
assert.strictEqual( json[ 0 ].name, "John", "Check JSON: first, name" );
|
||||
assert.strictEqual( json[ 0 ].age, 21, "Check JSON: first, age" );
|
||||
assert.strictEqual( json[ 1 ].name, "Peter", "Check JSON: second, name" );
|
||||
assert.strictEqual( json[ 1 ].age, 25, "Check JSON: second, age" );
|
||||
}
|
||||
}
|
||||
];
|
||||
@ -1562,10 +1565,10 @@ QUnit.module( "ajax", {
|
||||
assert.strictEqual( typeof text, "string", "json wasn't auto-determined" );
|
||||
var json = JSON.parse( text );
|
||||
assert.ok( json.length >= 2, "Check length" );
|
||||
assert.strictEqual( json[ 0 ][ "name" ], "John", "Check JSON: first, name" );
|
||||
assert.strictEqual( json[ 0 ][ "age" ], 21, "Check JSON: first, age" );
|
||||
assert.strictEqual( json[ 1 ][ "name" ], "Peter", "Check JSON: second, name" );
|
||||
assert.strictEqual( json[ 1 ][ "age" ], 25, "Check JSON: second, age" );
|
||||
assert.strictEqual( json[ 0 ].name, "John", "Check JSON: first, name" );
|
||||
assert.strictEqual( json[ 0 ].age, 21, "Check JSON: first, age" );
|
||||
assert.strictEqual( json[ 1 ].name, "Peter", "Check JSON: second, name" );
|
||||
assert.strictEqual( json[ 1 ].age, 25, "Check JSON: second, age" );
|
||||
}
|
||||
},
|
||||
{
|
||||
@ -1587,10 +1590,10 @@ QUnit.module( "ajax", {
|
||||
assert.strictEqual( typeof text, "string", "json wasn't auto-determined" );
|
||||
var json = JSON.parse( text );
|
||||
assert.ok( json.length >= 2, "Check length" );
|
||||
assert.strictEqual( json[ 0 ][ "name" ], "John", "Check JSON: first, name" );
|
||||
assert.strictEqual( json[ 0 ][ "age" ], 21, "Check JSON: first, age" );
|
||||
assert.strictEqual( json[ 1 ][ "name" ], "Peter", "Check JSON: second, name" );
|
||||
assert.strictEqual( json[ 1 ][ "age" ], 25, "Check JSON: second, age" );
|
||||
assert.strictEqual( json[ 0 ].name, "John", "Check JSON: first, name" );
|
||||
assert.strictEqual( json[ 0 ].age, 21, "Check JSON: first, age" );
|
||||
assert.strictEqual( json[ 1 ].name, "Peter", "Check JSON: second, name" );
|
||||
assert.strictEqual( json[ 1 ].age, 25, "Check JSON: second, age" );
|
||||
}
|
||||
}
|
||||
];
|
||||
@ -1816,6 +1819,7 @@ QUnit.module( "ajax", {
|
||||
var ifModifiedNow = new Date();
|
||||
|
||||
jQuery.each(
|
||||
|
||||
/* jQuery.each arguments start */
|
||||
{
|
||||
" (cache)": true,
|
||||
@ -1870,6 +1874,7 @@ QUnit.module( "ajax", {
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
/* jQuery.each arguments end */
|
||||
);
|
||||
|
||||
@ -1940,6 +1945,7 @@ QUnit.module( "ajax", {
|
||||
}
|
||||
|
||||
jQuery.each(
|
||||
|
||||
/* jQuery.each arguments start */
|
||||
{
|
||||
"name.html": true,
|
||||
@ -2014,6 +2020,7 @@ QUnit.module( "ajax", {
|
||||
} );
|
||||
|
||||
}
|
||||
|
||||
/* jQuery.each arguments end*/
|
||||
);
|
||||
} );
|
||||
@ -2815,10 +2822,10 @@ if ( typeof window.ArrayBuffer === "undefined" || typeof new XMLHttpRequest().re
|
||||
},
|
||||
function( json ) {
|
||||
assert.ok( json.length >= 2, "Check length" );
|
||||
assert.strictEqual( json[ 0 ][ "name" ], "John", "Check JSON: first, name" );
|
||||
assert.strictEqual( json[ 0 ][ "age" ], 21, "Check JSON: first, age" );
|
||||
assert.strictEqual( json[ 1 ][ "name" ], "Peter", "Check JSON: second, name" );
|
||||
assert.strictEqual( json[ 1 ][ "age" ], 25, "Check JSON: second, age" );
|
||||
assert.strictEqual( json[ 0 ].name, "John", "Check JSON: first, name" );
|
||||
assert.strictEqual( json[ 0 ].age, 21, "Check JSON: first, age" );
|
||||
assert.strictEqual( json[ 1 ].name, "Peter", "Check JSON: second, name" );
|
||||
assert.strictEqual( json[ 1 ].age, 25, "Check JSON: second, age" );
|
||||
done();
|
||||
}
|
||||
);
|
||||
@ -2828,9 +2835,9 @@ if ( typeof window.ArrayBuffer === "undefined" || typeof new XMLHttpRequest().re
|
||||
assert.expect( 2 );
|
||||
var done = assert.async();
|
||||
jQuery.getJSON( url( "mock.php?action=json" ), function( json ) {
|
||||
if ( json && json[ "data" ] ) {
|
||||
assert.strictEqual( json[ "data" ][ "lang" ], "en", "Check JSON: lang" );
|
||||
assert.strictEqual( json[ "data" ].length, 25, "Check JSON: length" );
|
||||
if ( json && json.data ) {
|
||||
assert.strictEqual( json.data.lang, "en", "Check JSON: lang" );
|
||||
assert.strictEqual( json.data.length, 25, "Check JSON: length" );
|
||||
done();
|
||||
}
|
||||
} );
|
||||
@ -2870,7 +2877,7 @@ if ( typeof window.ArrayBuffer === "undefined" || typeof new XMLHttpRequest().re
|
||||
|
||||
Globals.register( "testBar" );
|
||||
jQuery.getScript( url( "mock.php?action=testbar" ), function() {
|
||||
assert.strictEqual( window[ "testBar" ], "bar", "Check if script was evaluated" );
|
||||
assert.strictEqual( window.testBar, "bar", "Check if script was evaluated" );
|
||||
done();
|
||||
} );
|
||||
}
|
||||
@ -2901,7 +2908,7 @@ if ( typeof window.ArrayBuffer === "undefined" || typeof new XMLHttpRequest().re
|
||||
jQuery.getScript( {
|
||||
url: url( "mock.php?action=testbar" ),
|
||||
success: function() {
|
||||
assert.strictEqual( window[ "testBar" ], "bar", "Check if script was evaluated" );
|
||||
assert.strictEqual( window.testBar, "bar", "Check if script was evaluated" );
|
||||
done();
|
||||
}
|
||||
} );
|
||||
@ -3003,7 +3010,7 @@ if ( typeof window.ArrayBuffer === "undefined" || typeof new XMLHttpRequest().re
|
||||
assert.expect( 7 );
|
||||
var done = assert.async();
|
||||
var verifyEvaluation = function() {
|
||||
assert.strictEqual( window[ "testBar" ], "bar", "Check if script src was evaluated after load" );
|
||||
assert.strictEqual( window.testBar, "bar", "Check if script src was evaluated after load" );
|
||||
assert.strictEqual( jQuery( "#ap" ).html(), "bar", "Check if script evaluation has modified DOM" );
|
||||
done();
|
||||
};
|
||||
@ -3014,7 +3021,7 @@ if ( typeof window.ArrayBuffer === "undefined" || typeof new XMLHttpRequest().re
|
||||
jQuery( "#first" ).load( url( "mock.php?action=testHTML&baseURL=" + baseURL ), function() {
|
||||
assert.ok( jQuery( "#first" ).html().match( /^html text/ ), "Check content after loading html" );
|
||||
assert.strictEqual( jQuery( "#foo" ).html(), "foo", "Check if script evaluation has modified DOM" );
|
||||
assert.strictEqual( window[ "testFoo" ], "foo", "Check if script was evaluated after load" );
|
||||
assert.strictEqual( window.testFoo, "foo", "Check if script was evaluated after load" );
|
||||
setTimeout( verifyEvaluation, 600 );
|
||||
} );
|
||||
} );
|
||||
@ -3026,7 +3033,7 @@ if ( typeof window.ArrayBuffer === "undefined" || typeof new XMLHttpRequest().re
|
||||
|
||||
jQuery( "#first" ).load( url( "test2.html" ), function() {
|
||||
assert.strictEqual( jQuery( "#foo" ).html(), "foo", "Check if script evaluation has modified DOM" );
|
||||
assert.strictEqual( window[ "testFoo" ], "foo", "Check if script was evaluated after load" );
|
||||
assert.strictEqual( window.testFoo, "foo", "Check if script was evaluated after load" );
|
||||
done();
|
||||
} );
|
||||
} );
|
||||
|
@ -239,7 +239,7 @@ QUnit.test( "attr(Hash)", function( assert ) {
|
||||
assert.equal(
|
||||
jQuery( "#text1" ).attr( {
|
||||
"value": function() {
|
||||
return this[ "id" ];
|
||||
return this.id;
|
||||
} } ).attr( "value" ),
|
||||
"text1",
|
||||
"Set attribute to computed value #1"
|
||||
@ -394,11 +394,11 @@ QUnit.test( "attr(String, Object)", function( assert ) {
|
||||
table = jQuery( "#table" ).append( "<tr><td>cell</td></tr><tr><td>cell</td><td>cell</td></tr><tr><td>cell</td><td>cell</td></tr>" );
|
||||
td = table.find( "td" ).eq( 0 );
|
||||
td.attr( "rowspan", "2" );
|
||||
assert.equal( td[ 0 ][ "rowSpan" ], 2, "Check rowspan is correctly set" );
|
||||
assert.equal( td[ 0 ].rowSpan, 2, "Check rowspan is correctly set" );
|
||||
td.attr( "colspan", "2" );
|
||||
assert.equal( td[ 0 ][ "colSpan" ], 2, "Check colspan is correctly set" );
|
||||
assert.equal( td[ 0 ].colSpan, 2, "Check colspan is correctly set" );
|
||||
table.attr( "cellspacing", "2" );
|
||||
assert.equal( table[ 0 ][ "cellSpacing" ], "2", "Check cellspacing is correctly set" );
|
||||
assert.equal( table[ 0 ].cellSpacing, "2", "Check cellspacing is correctly set" );
|
||||
|
||||
assert.equal( jQuery( "#area1" ).attr( "value" ), undefined, "Value attribute is distinct from value property." );
|
||||
|
||||
@ -456,6 +456,7 @@ QUnit.test( "attr(String, Object)", function( assert ) {
|
||||
|
||||
$radio = jQuery( "<input>", {
|
||||
"value": "sup",
|
||||
|
||||
// Use uppercase here to ensure the type
|
||||
// attrHook is still used
|
||||
"TYPE": "radio"
|
||||
@ -701,9 +702,9 @@ QUnit.test( "prop(String, Object) on null/undefined", function( assert ) {
|
||||
$body = jQuery( body );
|
||||
|
||||
assert.ok( $body.prop( "nextSibling" ) === null, "Make sure a null expando returns null" );
|
||||
body[ "foo" ] = "bar";
|
||||
body.foo = "bar";
|
||||
assert.equal( $body.prop( "foo" ), "bar", "Make sure the expando is preferred over the dom attribute" );
|
||||
body[ "foo" ] = undefined;
|
||||
body.foo = undefined;
|
||||
assert.ok( $body.prop( "foo" ) === undefined, "Make sure the expando is preferred over the dom attribute, even if undefined" );
|
||||
|
||||
select = document.createElement( "select" );
|
||||
@ -848,7 +849,7 @@ QUnit.test( "removeProp(String)", function( assert ) {
|
||||
obj = {};
|
||||
|
||||
assert.strictEqual(
|
||||
jQuery( "#firstp" ).prop( "nonexisting", "foo" ).removeProp( "nonexisting" )[ 0 ][ "nonexisting" ],
|
||||
jQuery( "#firstp" ).prop( "nonexisting", "foo" ).removeProp( "nonexisting" )[ 0 ].nonexisting,
|
||||
undefined,
|
||||
"removeprop works correctly on DOM element nodes"
|
||||
);
|
||||
@ -856,12 +857,12 @@ QUnit.test( "removeProp(String)", function( assert ) {
|
||||
jQuery.each( [ document, obj ], function( i, ele ) {
|
||||
var $ele = jQuery( ele );
|
||||
$ele.prop( "nonexisting", "foo" ).removeProp( "nonexisting" );
|
||||
assert.strictEqual( ele[ "nonexisting" ], undefined, "removeProp works correctly on non DOM element nodes (bug trac-7500)." );
|
||||
assert.strictEqual( ele.nonexisting, undefined, "removeProp works correctly on non DOM element nodes (bug trac-7500)." );
|
||||
} );
|
||||
jQuery.each( [ commentNode, textNode, attributeNode ], function( i, ele ) {
|
||||
var $ele = jQuery( ele );
|
||||
$ele.prop( "nonexisting", "foo" ).removeProp( "nonexisting" );
|
||||
assert.strictEqual( ele[ "nonexisting" ], undefined, "removeProp works correctly on non DOM element nodes (bug trac-7500)." );
|
||||
assert.strictEqual( ele.nonexisting, undefined, "removeProp works correctly on non DOM element nodes (bug trac-7500)." );
|
||||
} );
|
||||
} );
|
||||
|
||||
@ -1116,7 +1117,7 @@ QUnit.test( "val(select) after form.reset() (Bug trac-2551)", function( assert )
|
||||
|
||||
jQuery( "#kkk" ).val( "gf" );
|
||||
|
||||
document[ "kk" ].reset();
|
||||
document.kk.reset();
|
||||
|
||||
assert.equal( jQuery( "#kkk" )[ 0 ].value, "cf", "Check value of select after form reset." );
|
||||
assert.equal( jQuery( "#kkk" ).val(), "cf", "Check value of select after form reset." );
|
||||
|
@ -19,6 +19,7 @@ var output,
|
||||
outputA = addToOutput( "A" ),
|
||||
outputB = addToOutput( "B" ),
|
||||
outputC = addToOutput( "C" ),
|
||||
/* eslint-disable key-spacing */
|
||||
tests = {
|
||||
"": "XABC X XABCABCC X XBB X XABA X XX",
|
||||
"once": "XABC X X X X X XABA X XX",
|
||||
@ -227,7 +228,9 @@ jQuery.each( tests, function( strFlags, resultString ) {
|
||||
// Return false
|
||||
output = "X";
|
||||
cblist = jQuery.Callbacks( flags );
|
||||
cblist.add( outputA, function() { return false; }, outputB );
|
||||
cblist.add( outputA, function() {
|
||||
return false;
|
||||
}, outputB );
|
||||
cblist.add( outputA );
|
||||
cblist.fire();
|
||||
assert.strictEqual( output, results.shift(), "Callback returning false" );
|
||||
@ -269,7 +272,7 @@ QUnit.test( "jQuery.Callbacks( options ) - options are copied", function( assert
|
||||
fn = function() {
|
||||
assert.ok( !( count++ ), "called once" );
|
||||
};
|
||||
options[ "unique" ] = false;
|
||||
options.unique = false;
|
||||
cb.add( fn, fn );
|
||||
cb.fire();
|
||||
} );
|
||||
@ -364,7 +367,9 @@ QUnit.test( "jQuery.Callbacks() - disabled callback doesn't fire (gh-1790)", fun
|
||||
|
||||
var cb = jQuery.Callbacks(),
|
||||
fired = false,
|
||||
shot = function() { fired = true; };
|
||||
shot = function() {
|
||||
fired = true;
|
||||
};
|
||||
|
||||
cb.disable();
|
||||
cb.empty();
|
||||
@ -379,8 +384,12 @@ QUnit.test( "jQuery.Callbacks() - list with memory stays locked (gh-3469)", func
|
||||
|
||||
var cb = jQuery.Callbacks( "memory" ),
|
||||
fired = 0,
|
||||
count1 = function() { fired += 1; },
|
||||
count2 = function() { fired += 10; };
|
||||
count1 = function() {
|
||||
fired += 1;
|
||||
},
|
||||
count2 = function() {
|
||||
fired += 10;
|
||||
};
|
||||
|
||||
cb.add( count1 );
|
||||
cb.fire();
|
||||
|
@ -38,19 +38,21 @@ QUnit.test( "jQuery()", function( assert ) {
|
||||
// few here but beware of modular builds where these methods may be excluded.
|
||||
if ( includesModule( "deprecated" ) ) {
|
||||
expected++;
|
||||
attrObj[ "click" ] = function() { assert.ok( exec, "Click executed." ); };
|
||||
attrObj.click = function() {
|
||||
assert.ok( exec, "Click executed." );
|
||||
};
|
||||
}
|
||||
if ( includesModule( "dimensions" ) ) {
|
||||
expected++;
|
||||
attrObj[ "width" ] = 10;
|
||||
attrObj.width = 10;
|
||||
}
|
||||
if ( includesModule( "offset" ) ) {
|
||||
expected++;
|
||||
attrObj[ "offset" ] = { "top": 1, "left": 1 };
|
||||
attrObj.offset = { "top": 1, "left": 1 };
|
||||
}
|
||||
if ( includesModule( "css" ) ) {
|
||||
expected += 2;
|
||||
attrObj[ "css" ] = { "paddingLeft": 1, "paddingRight": 1 };
|
||||
attrObj.css = { "paddingLeft": 1, "paddingRight": 1 };
|
||||
}
|
||||
if ( includesModule( "attributes" ) ) {
|
||||
expected++;
|
||||
@ -216,17 +218,17 @@ QUnit.test( "noConflict", function( assert ) {
|
||||
var $$ = jQuery;
|
||||
|
||||
assert.strictEqual( jQuery, jQuery.noConflict(), "noConflict returned the jQuery object" );
|
||||
assert.strictEqual( window[ "jQuery" ], $$, "Make sure jQuery wasn't touched." );
|
||||
assert.strictEqual( window[ "$" ], original$, "Make sure $ was reverted." );
|
||||
assert.strictEqual( window.jQuery, $$, "Make sure jQuery wasn't touched." );
|
||||
assert.strictEqual( window.$, original$, "Make sure $ was reverted." );
|
||||
|
||||
jQuery = $ = $$;
|
||||
|
||||
assert.strictEqual( jQuery.noConflict( true ), $$, "noConflict returned the jQuery object" );
|
||||
assert.strictEqual( window[ "jQuery" ], originaljQuery, "Make sure jQuery was reverted." );
|
||||
assert.strictEqual( window[ "$" ], original$, "Make sure $ was reverted." );
|
||||
assert.strictEqual( window.jQuery, originaljQuery, "Make sure jQuery was reverted." );
|
||||
assert.strictEqual( window.$, original$, "Make sure $ was reverted." );
|
||||
assert.ok( $$().pushStack( [] ), "Make sure that jQuery still works." );
|
||||
|
||||
window[ "jQuery" ] = jQuery = $$;
|
||||
window.jQuery = jQuery = $$;
|
||||
} );
|
||||
|
||||
QUnit.test( "isPlainObject", function( assert ) {
|
||||
@ -274,7 +276,7 @@ QUnit.test( "isPlainObject", function( assert ) {
|
||||
|
||||
// Makes the function a little more realistic
|
||||
// (and harder to detect, incidentally)
|
||||
fn.prototype[ "someMethod" ] = function() {};
|
||||
fn.prototype.someMethod = function() {};
|
||||
|
||||
// Again, instantiated objects shouldn't be matched
|
||||
assert.ok( !jQuery.isPlainObject( new fn() ), "new fn" );
|
||||
@ -431,10 +433,10 @@ QUnit.test( "XSS via location.hash", function( assert ) {
|
||||
var done = assert.async();
|
||||
assert.expect( 1 );
|
||||
|
||||
jQuery[ "_check9521" ] = function( x ) {
|
||||
jQuery._check9521 = function( x ) {
|
||||
assert.ok( x, "script called from #id-like selector with inline handler" );
|
||||
jQuery( "#check9521" ).remove();
|
||||
delete jQuery[ "_check9521" ];
|
||||
delete jQuery._check9521;
|
||||
done();
|
||||
};
|
||||
try {
|
||||
@ -442,7 +444,7 @@ QUnit.test( "XSS via location.hash", function( assert ) {
|
||||
// This throws an error because it's processed like an id
|
||||
jQuery( "#<img id='check9521' src='no-such-.gif' onerror='jQuery._check9521(false)'>" ).appendTo( "#qunit-fixture" );
|
||||
} catch ( err ) {
|
||||
jQuery[ "_check9521" ]( true );
|
||||
jQuery._check9521( true );
|
||||
}
|
||||
} );
|
||||
|
||||
@ -451,12 +453,12 @@ QUnit.test( "jQuery('html')", function( assert ) {
|
||||
|
||||
var s, div, j;
|
||||
|
||||
jQuery[ "foo" ] = false;
|
||||
jQuery.foo = false;
|
||||
s = jQuery( "<script>jQuery.foo='test';</script>" )[ 0 ];
|
||||
assert.ok( s, "Creating a script" );
|
||||
assert.ok( !jQuery[ "foo" ], "Make sure the script wasn't executed prematurely" );
|
||||
assert.ok( !jQuery.foo, "Make sure the script wasn't executed prematurely" );
|
||||
jQuery( "body" ).append( "<script>jQuery.foo='test';</script>" );
|
||||
assert.ok( jQuery[ "foo" ], "Executing a script's contents in the right context" );
|
||||
assert.ok( jQuery.foo, "Executing a script's contents in the right context" );
|
||||
|
||||
// Test multi-line HTML
|
||||
div = jQuery( "<div>\r\nsome text\n<p>some p</p>\nmore text\r\n</div>" )[ 0 ];
|
||||
@ -634,7 +636,9 @@ QUnit.test( "each(Function)", function( assert ) {
|
||||
var div, pass, i;
|
||||
|
||||
div = jQuery( "div" );
|
||||
div.each( function() {this.foo = "zoo";} );
|
||||
div.each( function() {
|
||||
this.foo = "zoo";
|
||||
} );
|
||||
pass = true;
|
||||
for ( i = 0; i < div.length; i++ ) {
|
||||
if ( div.get( i ).foo !== "zoo" ) {
|
||||
@ -740,8 +744,12 @@ QUnit.test( "jQuery.map", function( assert ) {
|
||||
|
||||
result = {
|
||||
Zero: function() {},
|
||||
One: function( a ) { a = a; },
|
||||
Two: function( a, b ) { a = a; b = b; }
|
||||
One: function( a ) {
|
||||
a = a;
|
||||
},
|
||||
Two: function( a, b ) {
|
||||
a = a; b = b;
|
||||
}
|
||||
};
|
||||
callback = function( v, k ) {
|
||||
assert.equal( k, "foo", label + "-argument function treated like object" );
|
||||
@ -999,25 +1007,25 @@ QUnit.test( "jQuery.extend(Object, Object)", function( assert ) {
|
||||
assert.deepEqual( options, optionsCopy, "Check if not modified: options must not be modified" );
|
||||
|
||||
jQuery.extend( true, deep1, deep2 );
|
||||
assert.deepEqual( deep1[ "foo" ], deepmerged[ "foo" ], "Check if foo: settings must be extended" );
|
||||
assert.deepEqual( deep2[ "foo" ], deep2copy[ "foo" ], "Check if not deep2: options must not be modified" );
|
||||
assert.equal( deep1[ "foo2" ], document, "Make sure that a deep clone was not attempted on the document" );
|
||||
assert.deepEqual( deep1.foo, deepmerged.foo, "Check if foo: settings must be extended" );
|
||||
assert.deepEqual( deep2.foo, deep2copy.foo, "Check if not deep2: options must not be modified" );
|
||||
assert.equal( deep1.foo2, document, "Make sure that a deep clone was not attempted on the document" );
|
||||
|
||||
assert.ok( jQuery.extend( true, {}, nestedarray )[ "arr" ] !== arr, "Deep extend of object must clone child array" );
|
||||
assert.ok( jQuery.extend( true, {}, nestedarray ).arr !== arr, "Deep extend of object must clone child array" );
|
||||
|
||||
// trac-5991
|
||||
assert.ok( Array.isArray( jQuery.extend( true, { "arr": {} }, nestedarray )[ "arr" ] ), "Cloned array have to be an Array" );
|
||||
assert.ok( jQuery.isPlainObject( jQuery.extend( true, { "arr": arr }, { "arr": {} } )[ "arr" ] ), "Cloned object have to be an plain object" );
|
||||
assert.ok( Array.isArray( jQuery.extend( true, { "arr": {} }, nestedarray ).arr ), "Cloned array have to be an Array" );
|
||||
assert.ok( jQuery.isPlainObject( jQuery.extend( true, { "arr": arr }, { "arr": {} } ).arr ), "Cloned object have to be an plain object" );
|
||||
|
||||
empty = {};
|
||||
optionsWithLength = { "foo": { "length": -1 } };
|
||||
jQuery.extend( true, empty, optionsWithLength );
|
||||
assert.deepEqual( empty[ "foo" ], optionsWithLength[ "foo" ], "The length property must copy correctly" );
|
||||
assert.deepEqual( empty.foo, optionsWithLength.foo, "The length property must copy correctly" );
|
||||
|
||||
empty = {};
|
||||
optionsWithDate = { "foo": { "date": new Date() } };
|
||||
jQuery.extend( true, empty, optionsWithDate );
|
||||
assert.deepEqual( empty[ "foo" ], optionsWithDate[ "foo" ], "Dates copy correctly" );
|
||||
assert.deepEqual( empty.foo, optionsWithDate.foo, "Dates copy correctly" );
|
||||
|
||||
/** @constructor */
|
||||
myKlass = function() {};
|
||||
@ -1025,13 +1033,13 @@ QUnit.test( "jQuery.extend(Object, Object)", function( assert ) {
|
||||
optionsWithCustomObject = { "foo": { "date": customObject } };
|
||||
empty = {};
|
||||
jQuery.extend( true, empty, optionsWithCustomObject );
|
||||
assert.ok( empty[ "foo" ] && empty[ "foo" ][ "date" ] === customObject, "Custom objects copy correctly (no methods)" );
|
||||
assert.ok( empty.foo && empty.foo.date === customObject, "Custom objects copy correctly (no methods)" );
|
||||
|
||||
// Makes the class a little more realistic
|
||||
myKlass.prototype = { "someMethod": function() {} };
|
||||
empty = {};
|
||||
jQuery.extend( true, empty, optionsWithCustomObject );
|
||||
assert.ok( empty[ "foo" ] && empty[ "foo" ][ "date" ] === customObject, "Custom objects copy correctly" );
|
||||
assert.ok( empty.foo && empty.foo.date === customObject, "Custom objects copy correctly" );
|
||||
|
||||
MyNumber = Number;
|
||||
|
||||
@ -1039,13 +1047,13 @@ QUnit.test( "jQuery.extend(Object, Object)", function( assert ) {
|
||||
assert.ok( parseInt( ret.foo, 10 ) === 5, "Wrapped numbers copy correctly" );
|
||||
|
||||
nullUndef = jQuery.extend( {}, options, { "xnumber2": null } );
|
||||
assert.ok( nullUndef[ "xnumber2" ] === null, "Check to make sure null values are copied" );
|
||||
assert.ok( nullUndef.xnumber2 === null, "Check to make sure null values are copied" );
|
||||
|
||||
nullUndef = jQuery.extend( {}, options, { "xnumber2": undefined } );
|
||||
assert.ok( nullUndef[ "xnumber2" ] === options[ "xnumber2" ], "Check to make sure undefined values are not copied" );
|
||||
assert.ok( nullUndef.xnumber2 === options.xnumber2, "Check to make sure undefined values are not copied" );
|
||||
|
||||
nullUndef = jQuery.extend( {}, options, { "xnumber0": null } );
|
||||
assert.ok( nullUndef[ "xnumber0" ] === null, "Check to make sure null values are inserted" );
|
||||
assert.ok( nullUndef.xnumber0 === null, "Check to make sure null values are inserted" );
|
||||
|
||||
target = {};
|
||||
recursive = { foo: target, bar: 5 };
|
||||
@ -1172,8 +1180,12 @@ QUnit.test( "jQuery.each(Object,Function)", function( assert ) {
|
||||
|
||||
seen = {
|
||||
Zero: function() {},
|
||||
One: function( a ) { a = a; },
|
||||
Two: function( a, b ) { a = a; b = b; }
|
||||
One: function( a ) {
|
||||
a = a;
|
||||
},
|
||||
Two: function( a, b ) {
|
||||
a = a; b = b;
|
||||
}
|
||||
};
|
||||
callback = function( k ) {
|
||||
assert.equal( k, "foo", label + "-argument function treated like object" );
|
||||
@ -1282,7 +1294,9 @@ QUnit.test( "jQuery.makeArray", function( assert ) {
|
||||
|
||||
assert.equal( jQuery.makeArray( document.getElementsByName( "PWD" ) ).slice( 0, 1 )[ 0 ].name, "PWD", "Pass makeArray a nodelist" );
|
||||
|
||||
assert.equal( ( function() { return jQuery.makeArray( arguments ); } )( 1, 2 ).join( "" ), "12", "Pass makeArray an arguments array" );
|
||||
assert.equal( ( function() {
|
||||
return jQuery.makeArray( arguments );
|
||||
} )( 1, 2 ).join( "" ), "12", "Pass makeArray an arguments array" );
|
||||
|
||||
assert.equal( jQuery.makeArray( [ 1, 2, 3 ] ).join( "" ), "123", "Pass makeArray a real array" );
|
||||
|
||||
@ -1301,7 +1315,9 @@ QUnit.test( "jQuery.makeArray", function( assert ) {
|
||||
assert.ok( !!jQuery.makeArray( document.documentElement.childNodes ).slice( 0, 1 )[ 0 ].nodeName, "Pass makeArray a childNodes array" );
|
||||
|
||||
// function, is tricky as it has length
|
||||
assert.equal( jQuery.makeArray( function() { return 1;} )[ 0 ](), 1, "Pass makeArray a function" );
|
||||
assert.equal( jQuery.makeArray( function() {
|
||||
return 1;
|
||||
} )[ 0 ](), 1, "Pass makeArray a function" );
|
||||
|
||||
//window, also has length
|
||||
assert.equal( jQuery.makeArray( window )[ 0 ], window, "Pass makeArray the window" );
|
||||
|
@ -321,8 +321,7 @@ QUnit.test( "css(String, Object)", function( assert ) {
|
||||
success = true;
|
||||
try {
|
||||
jQuery( "#foo" ).css( "backgroundColor", "rgba(0, 0, 0, 0.1)" );
|
||||
}
|
||||
catch ( e ) {
|
||||
} catch ( e ) {
|
||||
success = false;
|
||||
}
|
||||
assert.ok( success, "Setting RGBA values does not throw Error (trac-5509)" );
|
||||
@ -1203,6 +1202,7 @@ QUnit.test( "Do not append px (trac-9548, trac-12990, gh-2792)", function( asser
|
||||
|
||||
$div.css( "animation-iteration-count", 2 );
|
||||
if ( $div.css( "animation-iteration-count" ) !== undefined ) {
|
||||
|
||||
// if $div.css( "animation-iteration-count" ) return "1",
|
||||
// it actually return the default value of animation-iteration-count
|
||||
assert.equal( $div.css( "animation-iteration-count" ), 2, "Do not append px to 'animation-iteration-count'" );
|
||||
@ -1714,7 +1714,7 @@ QUnit.test( "Do not throw on frame elements from css method (trac-15098)", funct
|
||||
if ( transformName ) {
|
||||
assert.equal( elemStyle[ transformName ], transformVal, "setting properly-prefixed transform" );
|
||||
}
|
||||
assert.equal( elemStyle[ "undefined" ], undefined, "Nothing writes to node.style.undefined" );
|
||||
assert.equal( elemStyle.undefined, undefined, "Nothing writes to node.style.undefined" );
|
||||
} );
|
||||
|
||||
QUnit.test( "Don't detect fake set properties on a node when caching the prefixed version", function( assert ) {
|
||||
@ -1829,6 +1829,7 @@ QUnit.testUnlessIE( "Don't append px to CSS vars", function( assert ) {
|
||||
// Support: IE 11+
|
||||
// This test requires Grid to be *not supported* to work.
|
||||
if ( QUnit.isIE ) {
|
||||
|
||||
// Make sure explicitly provided IE vendor prefix (`-ms-`) is not converted
|
||||
// to a non-working `Ms` prefix in JavaScript.
|
||||
QUnit.test( "IE vendor prefixes are not mangled", function( assert ) {
|
||||
|
@ -74,14 +74,14 @@ function dataTests( elem, assert ) {
|
||||
|
||||
assert.strictEqual( jQuery.hasData( elem ), false, "jQuery.hasData agrees no data exists even when an empty data obj exists" );
|
||||
|
||||
dataObj[ "foo" ] = "bar";
|
||||
dataObj.foo = "bar";
|
||||
assert.equal( jQuery.data( elem, "foo" ), "bar", "Data is readable by jQuery.data when set directly on a returned data object" );
|
||||
|
||||
assert.strictEqual( jQuery.hasData( elem ), true, "jQuery.hasData agrees data exists when data exists" );
|
||||
|
||||
jQuery.data( elem, "foo", "baz" );
|
||||
assert.equal( jQuery.data( elem, "foo" ), "baz", "Data can be changed by jQuery.data" );
|
||||
assert.equal( dataObj[ "foo" ], "baz", "Changes made through jQuery.data propagate to referenced data object" );
|
||||
assert.equal( dataObj.foo, "baz", "Changes made through jQuery.data propagate to referenced data object" );
|
||||
|
||||
jQuery.data( elem, "foo", undefined );
|
||||
assert.equal( jQuery.data( elem, "foo" ), "baz", "Data is not unset by passing undefined to jQuery.data" );
|
||||
@ -431,8 +431,8 @@ QUnit.test( ".data(Object)", function( assert ) {
|
||||
|
||||
jqobj.data( "test", "unset" );
|
||||
jqobj.data( { "test": "in", "test2": "in2" } );
|
||||
assert.equal( jQuery.data( obj )[ "test" ], "in", "Verify setting an object on an object extends the data object" );
|
||||
assert.equal( obj[ "test2" ], undefined, "Verify setting an object on an object does not extend the object" );
|
||||
assert.equal( jQuery.data( obj ).test, "in", "Verify setting an object on an object extends the data object" );
|
||||
assert.equal( obj.test2, undefined, "Verify setting an object on an object does not extend the object" );
|
||||
|
||||
// manually clean up detached elements
|
||||
div.remove();
|
||||
@ -521,12 +521,12 @@ QUnit.test( ".data should follow html5 specification regarding camel casing", fu
|
||||
var div = jQuery( "<div id='myObject' data-w-t-f='ftw' data-big-a-little-a='bouncing-b' data-foo='a' data-foo-bar='b' data-foo-bar-baz='c'></div>" )
|
||||
.prependTo( "body" );
|
||||
|
||||
assert.equal( div.data()[ "wTF" ], "ftw", "Verify single letter data-* key" );
|
||||
assert.equal( div.data()[ "bigALittleA" ], "bouncing-b", "Verify single letter mixed data-* key" );
|
||||
assert.equal( div.data().wTF, "ftw", "Verify single letter data-* key" );
|
||||
assert.equal( div.data().bigALittleA, "bouncing-b", "Verify single letter mixed data-* key" );
|
||||
|
||||
assert.equal( div.data()[ "foo" ], "a", "Verify single word data-* key" );
|
||||
assert.equal( div.data()[ "fooBar" ], "b", "Verify multiple word data-* key" );
|
||||
assert.equal( div.data()[ "fooBarBaz" ], "c", "Verify multiple word data-* key" );
|
||||
assert.equal( div.data().foo, "a", "Verify single word data-* key" );
|
||||
assert.equal( div.data().fooBar, "b", "Verify multiple word data-* key" );
|
||||
assert.equal( div.data().fooBarBaz, "c", "Verify multiple word data-* key" );
|
||||
|
||||
assert.equal( div.data( "foo" ), "a", "Verify single word data-* key" );
|
||||
assert.equal( div.data( "fooBar" ), "b", "Verify multiple word data-* key" );
|
||||
|
@ -108,7 +108,9 @@ QUnit.test( "jQuery.Deferred.then - filtering (done)", function( assert ) {
|
||||
piped = defer.then( function( a, b ) {
|
||||
return a * b;
|
||||
} ),
|
||||
done = jQuery.map( new Array( 3 ), function() { return assert.async(); } );
|
||||
done = jQuery.map( new Array( 3 ), function() {
|
||||
return assert.async();
|
||||
} );
|
||||
|
||||
piped.done( function( result ) {
|
||||
value3 = result;
|
||||
@ -145,7 +147,9 @@ QUnit.test( "jQuery.Deferred.then - filtering (fail)", function( assert ) {
|
||||
piped = defer.then( null, function( a, b ) {
|
||||
return a * b;
|
||||
} ),
|
||||
done = jQuery.map( new Array( 3 ), function() { return assert.async(); } );
|
||||
done = jQuery.map( new Array( 3 ), function() {
|
||||
return assert.async();
|
||||
} );
|
||||
|
||||
piped.done( function( result ) {
|
||||
value3 = result;
|
||||
@ -181,7 +185,9 @@ QUnit.test( "jQuery.Deferred.catch", function( assert ) {
|
||||
piped = defer.catch( function( a, b ) {
|
||||
return a * b;
|
||||
} ),
|
||||
done = jQuery.map( new Array( 3 ), function() { return assert.async(); } );
|
||||
done = jQuery.map( new Array( 3 ), function() {
|
||||
return assert.async();
|
||||
} );
|
||||
|
||||
piped.done( function( result ) {
|
||||
value3 = result;
|
||||
@ -218,7 +224,9 @@ QUnit.test( "[PIPE ONLY] jQuery.Deferred.pipe - filtering (fail)", function( ass
|
||||
piped = defer.pipe( null, function( a, b ) {
|
||||
return a * b;
|
||||
} ),
|
||||
done = jQuery.map( new Array( 3 ), function() { return assert.async(); } );
|
||||
done = jQuery.map( new Array( 3 ), function() {
|
||||
return assert.async();
|
||||
} );
|
||||
|
||||
piped.fail( function( result ) {
|
||||
value3 = result;
|
||||
@ -416,7 +424,9 @@ QUnit.test( "jQuery.Deferred.then - context", function( assert ) {
|
||||
|
||||
var defer, piped, defer2, piped2,
|
||||
context = { custom: true },
|
||||
done = jQuery.map( new Array( 5 ), function() { return assert.async(); } );
|
||||
done = jQuery.map( new Array( 5 ), function() {
|
||||
return assert.async();
|
||||
} );
|
||||
|
||||
jQuery.Deferred().resolveWith( context, [ 2 ] ).then( function( value ) {
|
||||
assert.strictEqual( this, context, "custom context received by .then handler" );
|
||||
@ -475,7 +485,9 @@ QUnit.test( "[PIPE ONLY] jQuery.Deferred.pipe - context", function( assert ) {
|
||||
|
||||
var defer, piped, defer2, piped2,
|
||||
context = { custom: true },
|
||||
done = jQuery.map( new Array( 5 ), function() { return assert.async(); } );
|
||||
done = jQuery.map( new Array( 5 ), function() {
|
||||
return assert.async();
|
||||
} );
|
||||
|
||||
jQuery.Deferred().resolveWith( context, [ 2 ] ).pipe( function( value ) {
|
||||
assert.strictEqual( this, context, "custom context received by .pipe handler" );
|
||||
@ -642,7 +654,9 @@ QUnit.test( "jQuery.Deferred - 1.x/2.x compatibility", function( assert ) {
|
||||
|
||||
var context = { id: "callback context" },
|
||||
thenable = jQuery.Deferred().resolve( "thenable fulfillment" ).promise(),
|
||||
done = jQuery.map( new Array( 8 ), function() { return assert.async(); } );
|
||||
done = jQuery.map( new Array( 8 ), function() {
|
||||
return assert.async();
|
||||
} );
|
||||
|
||||
thenable.unwrapped = false;
|
||||
|
||||
@ -693,7 +707,9 @@ QUnit.test( "jQuery.Deferred.then - progress and thenables", function( assert )
|
||||
|
||||
var trigger = jQuery.Deferred().notify(),
|
||||
expectedProgress = [ "baz", "baz" ],
|
||||
done = jQuery.map( new Array( 2 ), function() { return assert.async(); } ),
|
||||
done = jQuery.map( new Array( 2 ), function() {
|
||||
return assert.async();
|
||||
} ),
|
||||
failer = function( evt ) {
|
||||
return function() {
|
||||
assert.ok( false, "no unexpected " + evt );
|
||||
@ -718,7 +734,9 @@ QUnit.test( "jQuery.Deferred - notify and resolve", function( assert ) {
|
||||
assert.expect( 7 );
|
||||
|
||||
var notifiedResolved = jQuery.Deferred().notify( "foo" )/*xxx .resolve( "bar" )*/,
|
||||
done = jQuery.map( new Array( 3 ), function() { return assert.async(); } );
|
||||
done = jQuery.map( new Array( 3 ), function() {
|
||||
return assert.async();
|
||||
} );
|
||||
|
||||
notifiedResolved.progress( function( v ) {
|
||||
assert.strictEqual( v, "foo", "progress value" );
|
||||
@ -798,7 +816,9 @@ QUnit.test( "jQuery.when(nonThenable) - like Promise.resolve", function( assert
|
||||
|
||||
assert.expect( 44 );
|
||||
|
||||
var defaultContext = ( function getDefaultContext() { return this; } )(),
|
||||
var defaultContext = ( function getDefaultContext() {
|
||||
return this;
|
||||
} )(),
|
||||
|
||||
done = assert.async( 20 );
|
||||
|
||||
@ -914,7 +934,9 @@ QUnit.test( "jQuery.when(thenable) - like Promise.resolve", function( assert ) {
|
||||
},
|
||||
numCases = Object.keys( willSucceed ).length + Object.keys( willError ).length,
|
||||
|
||||
defaultContext = ( function getDefaultContext() { return this; } )(),
|
||||
defaultContext = ( function getDefaultContext() {
|
||||
return this;
|
||||
} )(),
|
||||
|
||||
done = assert.async( numCases * 2 );
|
||||
|
||||
@ -992,7 +1014,9 @@ QUnit.test( "jQuery.when(a, b) - like Promise.all", function( assert ) {
|
||||
rejectedStandardPromise: true
|
||||
},
|
||||
|
||||
defaultContext = ( function getDefaultContext() { return this; } )(),
|
||||
defaultContext = ( function getDefaultContext() {
|
||||
return this;
|
||||
} )(),
|
||||
|
||||
done = assert.async( 98 );
|
||||
|
||||
|
@ -46,8 +46,12 @@ QUnit.test( "hover() mouseenter mouseleave", function( assert ) {
|
||||
assert.expect( 1 );
|
||||
|
||||
var times = 0,
|
||||
handler1 = function() { ++times; },
|
||||
handler2 = function() { ++times; };
|
||||
handler1 = function() {
|
||||
++times;
|
||||
},
|
||||
handler2 = function() {
|
||||
++times;
|
||||
};
|
||||
|
||||
jQuery( "#firstp" )
|
||||
.hover( handler1, handler2 )
|
||||
|
52
test/unit/effects.js
vendored
52
test/unit/effects.js
vendored
@ -8,8 +8,12 @@ if ( !includesModule( "effects" ) ) {
|
||||
var fxInterval = 13,
|
||||
oldRaf = window.requestAnimationFrame,
|
||||
hideOptions = {
|
||||
inline: function() { jQuery.style( this, "display", "none" ); },
|
||||
cascade: function() { this.className = "hidden"; }
|
||||
inline: function() {
|
||||
jQuery.style( this, "display", "none" );
|
||||
},
|
||||
cascade: function() {
|
||||
this.className = "hidden";
|
||||
}
|
||||
};
|
||||
|
||||
QUnit.module( "effects", {
|
||||
@ -948,15 +952,33 @@ jQuery.each( {
|
||||
num = 0;
|
||||
|
||||
// TODO: uncrowd this
|
||||
if ( t_h === "show" ) { num++; }
|
||||
if ( t_w === "show" ) { num++; }
|
||||
if ( t_w === "hide" || t_w === "show" ) { num++; }
|
||||
if ( t_h === "hide" || t_h === "show" ) { num++; }
|
||||
if ( t_o === "hide" || t_o === "show" ) { num++; }
|
||||
if ( t_w === "hide" ) { num++; }
|
||||
if ( t_o.constructor === Number ) { num += 2; }
|
||||
if ( t_w.constructor === Number ) { num += 2; }
|
||||
if ( t_h.constructor === Number ) { num += 2; }
|
||||
if ( t_h === "show" ) {
|
||||
num++;
|
||||
}
|
||||
if ( t_w === "show" ) {
|
||||
num++;
|
||||
}
|
||||
if ( t_w === "hide" || t_w === "show" ) {
|
||||
num++;
|
||||
}
|
||||
if ( t_h === "hide" || t_h === "show" ) {
|
||||
num++;
|
||||
}
|
||||
if ( t_o === "hide" || t_o === "show" ) {
|
||||
num++;
|
||||
}
|
||||
if ( t_w === "hide" ) {
|
||||
num++;
|
||||
}
|
||||
if ( t_o.constructor === Number ) {
|
||||
num += 2;
|
||||
}
|
||||
if ( t_w.constructor === Number ) {
|
||||
num += 2;
|
||||
}
|
||||
if ( t_h.constructor === Number ) {
|
||||
num += 2;
|
||||
}
|
||||
|
||||
assert.expect( num );
|
||||
|
||||
@ -2457,7 +2479,9 @@ QUnit.test( "Show/hide/toggle and display: inline", function( assert ) {
|
||||
.hide().show( N ),
|
||||
$el.clone().data( { call: "hide+toggle", done: "inline" } ).appendTo( fixture )
|
||||
.hide().toggle( N )
|
||||
], function( $clone ) { return $clone[ 0 ]; } );
|
||||
], function( $clone ) {
|
||||
return $clone[ 0 ];
|
||||
} );
|
||||
|
||||
// Animations not allowed to complete
|
||||
interrupted = jQuery.map( [
|
||||
@ -2465,7 +2489,9 @@ QUnit.test( "Show/hide/toggle and display: inline", function( assert ) {
|
||||
$el.clone().data( { call: "toggle+stop" } ).appendTo( fixture ).toggle( N ),
|
||||
$el.clone().data( { call: "hide+show+stop" } ).appendTo( fixture ).hide().show( N ),
|
||||
$el.clone().data( { call: "hide+toggle+stop" } ).appendTo( fixture ).hide().toggle( N )
|
||||
], function( $clone ) { return $clone[ 0 ]; } );
|
||||
], function( $clone ) {
|
||||
return $clone[ 0 ];
|
||||
} );
|
||||
|
||||
// All elements should be inline-block during the animation
|
||||
clock.tick( N / 2 );
|
||||
|
@ -224,12 +224,12 @@ QUnit.test( "on(), namespace with special add", function( assert ) {
|
||||
|
||||
div.on( "test.a", { x: 1 }, function( e ) {
|
||||
assert.ok( !!e.xyz, "Make sure that the data is getting passed through." );
|
||||
assert.equal( e.data[ "x" ], 1, "Make sure data is attached properly." );
|
||||
assert.equal( e.data.x, 1, "Make sure data is attached properly." );
|
||||
} );
|
||||
|
||||
div.on( "test.b", { x: 2 }, function( e ) {
|
||||
assert.ok( !!e.xyz, "Make sure that the data is getting passed through." );
|
||||
assert.equal( e.data[ "x" ], 2, "Make sure data is attached properly." );
|
||||
assert.equal( e.data.x, 2, "Make sure data is attached properly." );
|
||||
} );
|
||||
|
||||
// Should trigger 5
|
||||
@ -553,7 +553,9 @@ QUnit.test( "on(), namespaced events, cloned events", function( assert ) {
|
||||
} ).trigger( "tester" );
|
||||
|
||||
// Make sure events stick with appendTo'd elements (which are cloned) trac-2027
|
||||
jQuery( "<a href='#fail' class='test'>test</a>" ).on( "click", function() { return false; } ).appendTo( "#qunit-fixture" );
|
||||
jQuery( "<a href='#fail' class='test'>test</a>" ).on( "click", function() {
|
||||
return false;
|
||||
} ).appendTo( "#qunit-fixture" );
|
||||
assert.ok( jQuery( "a.test" ).eq( 0 ).triggerHandler( "click" ) === false, "Handler is bound to appendTo'd elements" );
|
||||
} );
|
||||
|
||||
@ -704,7 +706,9 @@ QUnit.test( "on(name, false), off(name, false)", function( assert ) {
|
||||
assert.expect( 3 );
|
||||
|
||||
var main = 0;
|
||||
jQuery( "#qunit-fixture" ).on( "click", function() { main++; } );
|
||||
jQuery( "#qunit-fixture" ).on( "click", function() {
|
||||
main++;
|
||||
} );
|
||||
jQuery( "#ap" ).trigger( "click" );
|
||||
assert.equal( main, 1, "Verify that the trigger happened correctly." );
|
||||
|
||||
@ -727,7 +731,9 @@ QUnit.test( "on(name, selector, false), off(name, selector, false)", function( a
|
||||
|
||||
var main = 0;
|
||||
|
||||
jQuery( "#qunit-fixture" ).on( "click", "#ap", function() { main++; } );
|
||||
jQuery( "#qunit-fixture" ).on( "click", "#ap", function() {
|
||||
main++;
|
||||
} );
|
||||
jQuery( "#ap" ).trigger( "click" );
|
||||
assert.equal( main, 1, "Verify that the trigger happened correctly." );
|
||||
|
||||
@ -766,7 +772,7 @@ QUnit.test( "on()/trigger()/off() on plain object", function( assert ) {
|
||||
|
||||
events = jQuery._data( obj, "events" );
|
||||
assert.ok( events, "Object has events bound." );
|
||||
assert.equal( obj[ "events" ], undefined, "Events object on plain objects is not events" );
|
||||
assert.equal( obj.events, undefined, "Events object on plain objects is not events" );
|
||||
assert.equal( obj.test, undefined, "Make sure that test event is not on the plain object." );
|
||||
assert.equal( obj.handle, undefined, "Make sure that the event handler is not on the plain object." );
|
||||
|
||||
@ -785,7 +791,7 @@ QUnit.test( "on()/trigger()/off() on plain object", function( assert ) {
|
||||
|
||||
assert.equal( obj && obj[ jQuery.expando ] &&
|
||||
obj[ jQuery.expando ][ jQuery.expando ] &&
|
||||
obj[ jQuery.expando ][ jQuery.expando ][ "events" ], undefined, "Make sure events object is removed" );
|
||||
obj[ jQuery.expando ][ jQuery.expando ].events, undefined, "Make sure events object is removed" );
|
||||
} );
|
||||
|
||||
QUnit.test( "off(type)", function( assert ) {
|
||||
@ -938,12 +944,26 @@ QUnit.test( "trigger() bubbling", function( assert ) {
|
||||
|
||||
var win = 0, doc = 0, html = 0, body = 0, main = 0, ap = 0;
|
||||
|
||||
jQuery( window ).on( "click", function() { win++; } );
|
||||
jQuery( document ).on( "click", function( e ) { if ( e.target !== document ) { doc++; } } );
|
||||
jQuery( "html" ).on( "click", function() { html++; } );
|
||||
jQuery( "body" ).on( "click", function() { body++; } );
|
||||
jQuery( "#qunit-fixture" ).on( "click", function() { main++; } );
|
||||
jQuery( "#ap" ).on( "click", function() { ap++; return false; } );
|
||||
jQuery( window ).on( "click", function() {
|
||||
win++;
|
||||
} );
|
||||
jQuery( document ).on( "click", function( e ) {
|
||||
if ( e.target !== document ) {
|
||||
doc++;
|
||||
}
|
||||
} );
|
||||
jQuery( "html" ).on( "click", function() {
|
||||
html++;
|
||||
} );
|
||||
jQuery( "body" ).on( "click", function() {
|
||||
body++;
|
||||
} );
|
||||
jQuery( "#qunit-fixture" ).on( "click", function() {
|
||||
main++;
|
||||
} );
|
||||
jQuery( "#ap" ).on( "click", function() {
|
||||
ap++; return false;
|
||||
} );
|
||||
|
||||
jQuery( "html" ).trigger( "click" );
|
||||
assert.equal( win, 1, "HTML bubble" );
|
||||
@ -1159,7 +1179,9 @@ QUnit.test( "trigger(eventObject, [data], [fn])", function( assert ) {
|
||||
event.stopPropagation();
|
||||
assert.equal( event.isPropagationStopped(), true, "Verify isPropagationStopped" );
|
||||
|
||||
event.isPropagationStopped = function() { return false; };
|
||||
event.isPropagationStopped = function() {
|
||||
return false;
|
||||
};
|
||||
event.stopImmediatePropagation();
|
||||
assert.equal( event.isPropagationStopped(), true, "Verify isPropagationStopped" );
|
||||
assert.equal( event.isImmediatePropagationStopped(), true, "Verify isPropagationStopped" );
|
||||
@ -1394,7 +1416,9 @@ QUnit.test( "Submit event can be stopped (trac-11049)", function( assert ) {
|
||||
return false;
|
||||
} )
|
||||
.find( "#myform input[type=submit]" )
|
||||
.each( function() { this.click(); } )
|
||||
.each( function() {
|
||||
this.click();
|
||||
} )
|
||||
.end()
|
||||
.on( "submit", function() {
|
||||
assert.ok( false, "submit bubbled on second handler" );
|
||||
@ -1506,10 +1530,18 @@ QUnit.test( ".on()/.off()", function( assert ) {
|
||||
var event, clicked, hash, called, livec, lived, livee,
|
||||
submit = 0, div = 0, livea = 0, liveb = 0;
|
||||
|
||||
jQuery( "#body" ).on( "submit", "#qunit-fixture div", function() { submit++; return false; } );
|
||||
jQuery( "#body" ).on( "click", "#qunit-fixture div", function() { div++; } );
|
||||
jQuery( "#body" ).on( "click", "div#nothiddendiv", function() { livea++; } );
|
||||
jQuery( "#body" ).on( "click", "div#nothiddendivchild", function() { liveb++; } );
|
||||
jQuery( "#body" ).on( "submit", "#qunit-fixture div", function() {
|
||||
submit++; return false;
|
||||
} );
|
||||
jQuery( "#body" ).on( "click", "#qunit-fixture div", function() {
|
||||
div++;
|
||||
} );
|
||||
jQuery( "#body" ).on( "click", "div#nothiddendiv", function() {
|
||||
livea++;
|
||||
} );
|
||||
jQuery( "#body" ).on( "click", "div#nothiddendivchild", function() {
|
||||
liveb++;
|
||||
} );
|
||||
|
||||
// Nothing should trigger on the body
|
||||
jQuery( "body" ).trigger( "click" );
|
||||
@ -1569,7 +1601,9 @@ QUnit.test( ".on()/.off()", function( assert ) {
|
||||
|
||||
// Make sure that stopPropagation doesn't stop live events
|
||||
submit = 0; div = 0; livea = 0; liveb = 0;
|
||||
jQuery( "#body" ).on( "click", "div#nothiddendivchild", function( e ) { liveb++; e.stopPropagation(); } );
|
||||
jQuery( "#body" ).on( "click", "div#nothiddendivchild", function( e ) {
|
||||
liveb++; e.stopPropagation();
|
||||
} );
|
||||
jQuery( "div#nothiddendivchild" ).trigger( "click" );
|
||||
assert.equal( submit, 0, "stopPropagation Click on inner div" );
|
||||
assert.equal( div, 1, "stopPropagation Click on inner div" );
|
||||
@ -1591,7 +1625,9 @@ QUnit.test( ".on()/.off()", function( assert ) {
|
||||
|
||||
// Test binding with a different context
|
||||
clicked = 0;
|
||||
jQuery( "#qunit-fixture" ).on( "click", "#foo", function() { clicked++; } );
|
||||
jQuery( "#qunit-fixture" ).on( "click", "#foo", function() {
|
||||
clicked++;
|
||||
} );
|
||||
jQuery( "#qunit-fixture div" ).trigger( "click" );
|
||||
jQuery( "#foo" ).trigger( "click" );
|
||||
jQuery( "#qunit-fixture" ).trigger( "click" );
|
||||
@ -1635,14 +1671,18 @@ QUnit.test( ".on()/.off()", function( assert ) {
|
||||
jQuery( "#body" ).off( "click", "#foo" );
|
||||
|
||||
// Verify that return false prevents default action
|
||||
jQuery( "#body" ).on( "click", "#anchor2", function() { return false; } );
|
||||
jQuery( "#body" ).on( "click", "#anchor2", function() {
|
||||
return false;
|
||||
} );
|
||||
hash = window.location.hash;
|
||||
jQuery( "#anchor2" ).trigger( "click" );
|
||||
assert.equal( window.location.hash, hash, "return false worked" );
|
||||
jQuery( "#body" ).off( "click", "#anchor2" );
|
||||
|
||||
// Verify that .preventDefault() prevents default action
|
||||
jQuery( "#body" ).on( "click", "#anchor2", function( e ) { e.preventDefault(); } );
|
||||
jQuery( "#body" ).on( "click", "#anchor2", function( e ) {
|
||||
e.preventDefault();
|
||||
} );
|
||||
hash = window.location.hash;
|
||||
jQuery( "#anchor2" ).trigger( "click" );
|
||||
assert.equal( window.location.hash, hash, "e.preventDefault() worked" );
|
||||
@ -1650,7 +1690,9 @@ QUnit.test( ".on()/.off()", function( assert ) {
|
||||
|
||||
// Test binding the same handler to multiple points
|
||||
called = 0;
|
||||
function callback() { called++; return false; }
|
||||
function callback() {
|
||||
called++; return false;
|
||||
}
|
||||
|
||||
jQuery( "#body" ).on( "click", "#nothiddendiv", callback );
|
||||
jQuery( "#body" ).on( "click", "#anchor2", callback );
|
||||
@ -1696,8 +1738,14 @@ QUnit.test( ".on()/.off()", function( assert ) {
|
||||
livec = 0;
|
||||
jQuery( "#nothiddendivchild" ).html( "<span></span>" );
|
||||
|
||||
jQuery( "#body" ).on( "click", "#nothiddendivchild", function() { jQuery( "#nothiddendivchild" ).html( "" ); } );
|
||||
jQuery( "#body" ).on( "click", "#nothiddendivchild", function( e ) { if ( e.target ) {livec++;} } );
|
||||
jQuery( "#body" ).on( "click", "#nothiddendivchild", function() {
|
||||
jQuery( "#nothiddendivchild" ).html( "" );
|
||||
} );
|
||||
jQuery( "#body" ).on( "click", "#nothiddendivchild", function( e ) {
|
||||
if ( e.target ) {
|
||||
livec++;
|
||||
}
|
||||
} );
|
||||
|
||||
jQuery( "#nothiddendiv span" ).trigger( "click" );
|
||||
assert.equal( jQuery( "#nothiddendiv span" ).length, 0, "Verify that first handler occurred and modified the DOM." );
|
||||
@ -1712,16 +1760,26 @@ QUnit.test( ".on()/.off()", function( assert ) {
|
||||
livee = 0;
|
||||
|
||||
// bind one pair in one order
|
||||
jQuery( "#body" ).on( "click", "span#liveSpan1 a", function() { lived++; return false; } );
|
||||
jQuery( "#body" ).on( "click", "span#liveSpan1", function() { livee++; } );
|
||||
jQuery( "#body" ).on( "click", "span#liveSpan1 a", function() {
|
||||
lived++;
|
||||
return false;
|
||||
} );
|
||||
jQuery( "#body" ).on( "click", "span#liveSpan1", function() {
|
||||
livee++;
|
||||
} );
|
||||
|
||||
jQuery( "span#liveSpan1 a" ).trigger( "click" );
|
||||
assert.equal( lived, 1, "Verify that only one first handler occurred." );
|
||||
assert.equal( livee, 0, "Verify that second handler doesn't." );
|
||||
|
||||
// and one pair in inverse
|
||||
jQuery( "#body" ).on( "click", "span#liveSpan2", function() { livee++; } );
|
||||
jQuery( "#body" ).on( "click", "span#liveSpan2 a", function() { lived++; return false; } );
|
||||
jQuery( "#body" ).on( "click", "span#liveSpan2", function() {
|
||||
livee++;
|
||||
} );
|
||||
jQuery( "#body" ).on( "click", "span#liveSpan2 a", function() {
|
||||
lived++;
|
||||
return false;
|
||||
} );
|
||||
|
||||
lived = 0;
|
||||
livee = 0;
|
||||
@ -1747,11 +1805,17 @@ QUnit.test( ".on()/.off()", function( assert ) {
|
||||
// Work with deep selectors
|
||||
livee = 0;
|
||||
|
||||
function clickB() { livee++; }
|
||||
function clickB() {
|
||||
livee++;
|
||||
}
|
||||
|
||||
jQuery( "#body" ).on( "click", "#nothiddendiv div", function() { livee++; } );
|
||||
jQuery( "#body" ).on( "click", "#nothiddendiv div", function() {
|
||||
livee++;
|
||||
} );
|
||||
jQuery( "#body" ).on( "click", "#nothiddendiv div", clickB );
|
||||
jQuery( "#body" ).on( "mouseover", "#nothiddendiv div", function() { livee++; } );
|
||||
jQuery( "#body" ).on( "mouseover", "#nothiddendiv div", function() {
|
||||
livee++;
|
||||
} );
|
||||
|
||||
assert.equal( livee, 0, "No clicks, deep selector." );
|
||||
|
||||
@ -1825,6 +1889,7 @@ QUnit.test( "events with type matching an Object.prototype property, cloned elem
|
||||
elem.appendTo( "#qunit-fixture" );
|
||||
|
||||
try {
|
||||
|
||||
// Make sure the original element has some event data.
|
||||
elem.on( "click", function() {} );
|
||||
|
||||
@ -1859,6 +1924,7 @@ QUnit[ QUnit.jQuerySelectors ? "test" : "skip" ]( "delegated event with delegate
|
||||
.off( "click" );
|
||||
|
||||
if ( QUnit.jQuerySelectorsPos ) {
|
||||
|
||||
// Positional selector (trac-11315)
|
||||
markup.find( "ul" ).eq( 0 )
|
||||
.on( "click", ">li>a", function() {
|
||||
@ -1954,8 +2020,12 @@ QUnit.test( "off all bound delegated events", function( assert ) {
|
||||
clicks = 0,
|
||||
div = jQuery( "#body" );
|
||||
|
||||
div.on( "click submit", "div#nothiddendivchild", function() { count++; } );
|
||||
div.on( "click", function() { clicks++; } );
|
||||
div.on( "click submit", "div#nothiddendivchild", function() {
|
||||
count++;
|
||||
} );
|
||||
div.on( "click", function() {
|
||||
clicks++;
|
||||
} );
|
||||
div.off( undefined, "**" );
|
||||
|
||||
jQuery( "div#nothiddendivchild" ).trigger( "click" );
|
||||
@ -1974,7 +2044,9 @@ QUnit.test( "on with multiple delegated events", function( assert ) {
|
||||
var count = 0,
|
||||
div = jQuery( "#body" );
|
||||
|
||||
div.on( "click submit", "div#nothiddendivchild", function() { count++; } );
|
||||
div.on( "click submit", "div#nothiddendivchild", function() {
|
||||
count++;
|
||||
} );
|
||||
|
||||
jQuery( "div#nothiddendivchild" ).trigger( "click" );
|
||||
jQuery( "div#nothiddendivchild" ).trigger( "submit" );
|
||||
@ -2329,7 +2401,7 @@ QUnit.test( ".on and .off", function( assert ) {
|
||||
|
||||
// We should have removed all the event handlers ... kinda hacky way to check this
|
||||
data = jQuery.data[ jQuery( "#onandoff" )[ 0 ].expando ] || {};
|
||||
assert.equal( data[ "events" ], undefined, "no events left" );
|
||||
assert.equal( data.events, undefined, "no events left" );
|
||||
|
||||
$onandoff.remove();
|
||||
} );
|
||||
@ -2403,7 +2475,7 @@ QUnit.test( "special on name mapping", function( assert ) {
|
||||
.trigger( "gutfeeling" ) // This one should not
|
||||
.remove();
|
||||
|
||||
delete jQuery.event.special[ "gutfeeling" ];
|
||||
delete jQuery.event.special.gutfeeling;
|
||||
} );
|
||||
|
||||
QUnit.test( ".on and .off, selective mixed removal (trac-10705)", function( assert ) {
|
||||
@ -2564,7 +2636,9 @@ QUnit.test( "addProp extensions", function( assert ) {
|
||||
fireNative( $fixture[ 0 ], "click" );
|
||||
$fixture.off( "click" );
|
||||
|
||||
jQuery.event.addProp( "testProperty", function() { return 42; } );
|
||||
jQuery.event.addProp( "testProperty", function() {
|
||||
return 42;
|
||||
} );
|
||||
|
||||
// Trigger a native click and ensure the property is set
|
||||
$fixture.on( "click", function( event ) {
|
||||
@ -3393,6 +3467,7 @@ QUnit.test( "focus change during a focus handler (gh-4382)", function( assert )
|
||||
} );
|
||||
|
||||
jQuery( document ).on( "focusin.focusTests", function( ev ) {
|
||||
|
||||
// Support: IE 11+
|
||||
// In IE focus is async so focusin on document is fired multiple times,
|
||||
// for each of the elements. In other browsers it's fired just once, for
|
||||
|
@ -1325,9 +1325,13 @@ QUnit.test( "Empty replaceWith (trac-13401; trac-13596; gh-2204)", function( ass
|
||||
jQuery.each( tests, function( label, input ) {
|
||||
$el.html( "<a></a>" ).children().replaceWith( input );
|
||||
assert.strictEqual( $el.html(), "", "replaceWith(" + label + ")" );
|
||||
$el.html( "<b></b>" ).children().replaceWith( function() { return input; } );
|
||||
$el.html( "<b></b>" ).children().replaceWith( function() {
|
||||
return input;
|
||||
} );
|
||||
assert.strictEqual( $el.html(), "", "replaceWith(function returning " + label + ")" );
|
||||
$el.html( "<i></i>" ).children().replaceWith( function( i ) { return input; } );
|
||||
$el.html( "<i></i>" ).children().replaceWith( function( i ) {
|
||||
return input;
|
||||
} );
|
||||
assert.strictEqual( $el.html(), "", "replaceWith(other function returning " + label + ")" );
|
||||
$el.html( "<p></p>" ).children().replaceWith( function( i ) {
|
||||
return i ?
|
||||
@ -1567,7 +1571,9 @@ QUnit.test( "clone(form element) (Bug trac-3879, trac-6655)", function( assert )
|
||||
|
||||
element = jQuery( "<select><option>Foo</option><option value='selected' selected>Bar</option></select>" );
|
||||
|
||||
assert.equal( element.clone().find( "option" ).filter( function() { return this.selected; } ).val(), "selected", "Selected option cloned correctly" );
|
||||
assert.equal( element.clone().find( "option" ).filter( function() {
|
||||
return this.selected;
|
||||
} ).val(), "selected", "Selected option cloned correctly" );
|
||||
|
||||
element = jQuery( "<input type='checkbox' value='foo'>" ).attr( "checked", "checked" );
|
||||
clone = element.clone();
|
||||
@ -2217,8 +2223,7 @@ QUnit.test( "domManip plain-text caching (trac-6779)", function( assert ) {
|
||||
for ( i = 0; i < bad.length; i++ ) {
|
||||
try {
|
||||
$f.append( bad[ i ] );
|
||||
}
|
||||
catch ( e ) {}
|
||||
} catch ( e ) {}
|
||||
}
|
||||
assert.equal( $f.text(), bad.join( "" ), "Cached strings that match Object properties" );
|
||||
$f.remove();
|
||||
|
@ -592,6 +592,7 @@ QUnit.test( "chaining", function( assert ) {
|
||||
// parent is not offsetParent); offset includes parent offset+border+padding
|
||||
// static: same as relative
|
||||
for ( ; parent; parent = expectations[ parent.parent ] ) {
|
||||
|
||||
// position:fixed
|
||||
if ( props.style === "fixed" ) {
|
||||
break;
|
||||
|
@ -88,7 +88,9 @@ QUnit.test( "queue() passes in the next item in the queue as a parameter to fx q
|
||||
|
||||
div.queue( function( next ) {
|
||||
assert.equal( ++counter, 1, "Dequeueing" );
|
||||
setTimeout( function() { next(); }, 500 );
|
||||
setTimeout( function() {
|
||||
next();
|
||||
}, 500 );
|
||||
} ).queue( function( next ) {
|
||||
assert.equal( ++counter, 2, "Next was called" );
|
||||
next();
|
||||
@ -187,7 +189,9 @@ QUnit.test( "clearQueue() clears the fx queue", function( assert ) {
|
||||
div.queue( function( next ) {
|
||||
counter++;
|
||||
var self = this;
|
||||
setTimeout( function() { jQuery( self ).clearQueue(); next(); }, 50 );
|
||||
setTimeout( function() {
|
||||
jQuery( self ).clearQueue(); next();
|
||||
}, 50 );
|
||||
} ).queue( function() {
|
||||
counter++;
|
||||
} );
|
||||
|
@ -35,8 +35,8 @@ QUnit.test( "empty", function( assert ) {
|
||||
QUnit.test( "star", function( assert ) {
|
||||
assert.expect( 2 );
|
||||
|
||||
var good, i;
|
||||
var all = jQuery( "*" );
|
||||
var good, i,
|
||||
all = jQuery( "*" );
|
||||
|
||||
assert.ok( all.length >= 30, "Select all" );
|
||||
good = true;
|
||||
@ -51,8 +51,8 @@ QUnit.test( "star", function( assert ) {
|
||||
QUnit.test( "element", function( assert ) {
|
||||
assert.expect( 37 );
|
||||
|
||||
var i, lengthtest, siblingTest, html;
|
||||
var fixture = document.getElementById( "qunit-fixture" );
|
||||
var i, lengthtest, siblingTest, html,
|
||||
fixture = document.getElementById( "qunit-fixture" );
|
||||
|
||||
assert.deepEqual( jQuery( "p", fixture ).get(), q( "firstp", "ap", "sndp", "en", "sap", "first" ), "Finding elements with a Node context." );
|
||||
assert.deepEqual( jQuery( "p", "#qunit-fixture" ).get(), q( "firstp", "ap", "sndp", "en", "sap", "first" ), "Finding elements with a selector context." );
|
||||
@ -848,6 +848,7 @@ QUnit.test( "pseudo - nth-child", function( assert ) {
|
||||
"Seeded nth-child"
|
||||
);
|
||||
} else {
|
||||
|
||||
// Support: Chrome 75+, Firefox 67+
|
||||
// Some browsers mark disconnected elements as matching `:nth-child(n)`
|
||||
// so let's skip the test.
|
||||
@ -901,6 +902,7 @@ QUnit.test( "pseudo - nth-last-child", function( assert ) {
|
||||
"Seeded nth-last-child"
|
||||
);
|
||||
} else {
|
||||
|
||||
// Support: Chrome 75+, Firefox 67+
|
||||
// Some browsers mark disconnected elements as matching `:nth-last-child(n)`
|
||||
// so let's skip the test.
|
||||
@ -1037,6 +1039,7 @@ QUnit.test( "pseudo - misc", function( assert ) {
|
||||
tmp = document.createElement( "div" );
|
||||
tmp.id = "tmp_input";
|
||||
tmp.innerHTML = "<span>Hello I am focusable.</span>";
|
||||
|
||||
// Setting tabIndex should make the element focusable
|
||||
// https://html.spec.whatwg.org/#the-tabindex-attribute
|
||||
document.body.appendChild( tmp );
|
||||
@ -1093,6 +1096,7 @@ QUnit.test( "pseudo - misc", function( assert ) {
|
||||
);
|
||||
|
||||
if ( QUnit.jQuerySelectors ) {
|
||||
|
||||
// Tokenization edge cases
|
||||
assert.t( "Sequential pseudos", "#qunit-fixture p:has(:contains(mark)):has(code)", [ "ap" ] );
|
||||
assert.t( "Sequential pseudos", "#qunit-fixture p:has(:contains(mark)):has(code):contains(This link)", [ "ap" ] );
|
||||
@ -1158,6 +1162,7 @@ QUnit.test( "pseudo - :not", function( assert ) {
|
||||
assert.t( ":not() failing interior", "#qunit-fixture p:not(div#blargh)", [ "firstp", "ap", "sndp", "en", "sap", "first" ] );
|
||||
assert.t( ":not() failing interior", "#qunit-fixture p:not(p#blargh)", [ "firstp", "ap", "sndp", "en", "sap", "first" ] );
|
||||
} else {
|
||||
|
||||
// Support: IE 11+
|
||||
// IE doesn't support `:not(complex selector)`.
|
||||
assert.ok( "skip", ":not(complex selector) not supported in selector-native" );
|
||||
@ -1178,6 +1183,7 @@ QUnit.test( "pseudo - :not", function( assert ) {
|
||||
assert.t( ":not Multiple", "p:not(p,a)", [] );
|
||||
assert.t( ":not Multiple", "p:not(a,p,b)", [] );
|
||||
} else {
|
||||
|
||||
// Support: IE 11+
|
||||
// IE doesn't support `:not(complex selector)`.
|
||||
assert.ok( "skip", ":not(complex selector) not supported in selector-native" );
|
||||
@ -1207,6 +1213,7 @@ QUnit.test( "pseudo - :not", function( assert ) {
|
||||
if ( QUnit.jQuerySelectors || !QUnit.isIE ) {
|
||||
assert.t( ":not() Multiple Class", "#foo a:not(.blog.link)", [ "yahoo", "anchor2" ] );
|
||||
} else {
|
||||
|
||||
// Support: IE 11+
|
||||
// IE doesn't support `:not(complex selector)`.
|
||||
assert.ok( "skip", ":not(complex selector) not supported in selector-native" );
|
||||
@ -1439,8 +1446,7 @@ QUnit.test( "pseudo - a:(dis|en)abled", function( assert ) {
|
||||
assert.expect( 2 );
|
||||
|
||||
var enabled, disabled,
|
||||
container = jQuery( "<div></div>" ),
|
||||
anchor = jQuery( "<a href='#'>Link</a>" );
|
||||
container = jQuery( "<div></div>" );
|
||||
|
||||
container.appendTo( "#qunit-fixture" );
|
||||
|
||||
@ -1754,8 +1760,8 @@ QUnit[ QUnit.jQuerySelectors ? "test" : "skip" ]( "disconnected nodes", function
|
||||
QUnit.testUnlessIE( "Shadow DOM nodes supported as root", function( assert ) {
|
||||
assert.expect( 2 );
|
||||
|
||||
var shadowHost = jQuery( "<div></div>" ).appendTo( "#qunit-fixture" )[ 0 ];
|
||||
var shadowRoot = shadowHost.attachShadow( { mode: "open" } );
|
||||
var shadowHost = jQuery( "<div></div>" ).appendTo( "#qunit-fixture" )[ 0 ],
|
||||
shadowRoot = shadowHost.attachShadow( { mode: "open" } );
|
||||
|
||||
shadowRoot.innerHTML = "<div class='vagabond'><p></p></div>";
|
||||
assert.equal( jQuery( shadowRoot ).find( ".vagabond" ).length, 1,
|
||||
@ -1767,7 +1773,7 @@ QUnit.testUnlessIE( "Shadow DOM nodes supported as root", function( assert ) {
|
||||
testIframe(
|
||||
"attributes - jQuery.attr",
|
||||
"selector/html5_selector.html",
|
||||
function( assert, jQuery, window, document ) {
|
||||
function( assert, jQuery, _window, document ) {
|
||||
assert.expect( 38 );
|
||||
|
||||
/**
|
||||
@ -1840,7 +1846,7 @@ testIframe(
|
||||
|
||||
// Enumerated attributes (these are not boolean content attributes)
|
||||
jQuery.expandedEach = jQuery.each;
|
||||
jQuery.expandedEach( [ "draggable", "contenteditable", "aria-disabled" ], function( i, val ) {
|
||||
jQuery.expandedEach( [ "draggable", "contenteditable", "aria-disabled" ], function( _i, val ) {
|
||||
t( "Enumerated attribute", "[" + val + "]", [ "div1" ] );
|
||||
} );
|
||||
t( "Enumerated attribute", "[spellcheck]", [ "span1" ] );
|
||||
@ -1984,7 +1990,7 @@ QUnit.test( "uniqueSort()", function( assert ) {
|
||||
testIframe(
|
||||
"jQuery.uniqueSort works cross-window (trac-14381)",
|
||||
"selector/mixed_sort.html",
|
||||
function( assert, jQuery, window, document, actual, expected ) {
|
||||
function( assert, _jQuery, _window, _document, actual, expected ) {
|
||||
assert.expect( 1 );
|
||||
|
||||
assert.deepEqual( actual, expected, "Mixed array was sorted correctly" );
|
||||
@ -2313,7 +2319,7 @@ QUnit[ QUnit.jQuerySelectors ? "test" : "skip" ]( "jQuery.find.select with pre-c
|
||||
"#qunit-fixture #first",
|
||||
"ol#listWithTabIndex > li[tabindex]",
|
||||
"#liveSpan1"
|
||||
], function( i, selector ) {
|
||||
], function( _i, selector ) {
|
||||
var compiled = jQuery.find.compile( selector );
|
||||
assert.equal( jQuery.find.select( compiled, document ).length,
|
||||
1, "Should match using a compiled selector function" );
|
||||
|
@ -64,7 +64,9 @@ QUnit.test( "jQuery.param()", function( assert ) {
|
||||
params = { "param1": null };
|
||||
assert.equal( jQuery.param( params ), "param1=", "Make sure that null params aren't traversed." );
|
||||
|
||||
params = { "param1": function() {}, "param2": function() { return null; } };
|
||||
params = { "param1": function() {}, "param2": function() {
|
||||
return null;
|
||||
} };
|
||||
assert.equal( jQuery.param( params, false ), "param1=¶m2=", "object with function property that returns null value" );
|
||||
|
||||
params = { "test": { "length": 3, "foo": "bar" } };
|
||||
|
@ -310,7 +310,9 @@ QUnit.test( "filter(Function)", function( assert ) {
|
||||
return !jQuery( "a", this ).length;
|
||||
} ).get(), q( "sndp", "first" ), "filter(Function)" );
|
||||
|
||||
assert.deepEqual( jQuery( "#qunit-fixture p" ).filter( function( i, elem ) { return !jQuery( "a", elem ).length; } ).get(), q( "sndp", "first" ), "filter(Function) using arg" );
|
||||
assert.deepEqual( jQuery( "#qunit-fixture p" ).filter( function( i, elem ) {
|
||||
return !jQuery( "a", elem ).length;
|
||||
} ).get(), q( "sndp", "first" ), "filter(Function) using arg" );
|
||||
} );
|
||||
|
||||
QUnit.test( "filter(Element)", function( assert ) {
|
||||
@ -511,7 +513,9 @@ QUnit.test( "not(Element)", function( assert ) {
|
||||
QUnit.test( "not(Function)", function( assert ) {
|
||||
assert.expect( 1 );
|
||||
|
||||
assert.deepEqual( jQuery( "#qunit-fixture p" ).not( function() { return jQuery( "a", this ).length; } ).get(), q( "sndp", "first" ), "not(Function)" );
|
||||
assert.deepEqual( jQuery( "#qunit-fixture p" ).not( function() {
|
||||
return jQuery( "a", this ).length;
|
||||
} ).get(), q( "sndp", "first" ), "not(Function)" );
|
||||
} );
|
||||
|
||||
QUnit.test( "not(Array)", function( assert ) {
|
||||
|
Loading…
Reference in New Issue
Block a user