diff options
author | Michał Gołębiowski-Owczarek <m.goleb@gmail.com> | 2019-04-29 22:56:09 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2019-04-29 22:56:09 +0200 |
commit | cf84696fd1d7fe314a11492606529b5a658ee9e3 (patch) | |
tree | 8fd4a45dd755e5f1215adbc82e7870727c8164e8 | |
parent | bde53edcf4bd6c975d068eed4eb16c5ba09c1cff (diff) | |
download | jquery-cf84696fd1d7fe314a11492606529b5a658ee9e3.tar.gz jquery-cf84696fd1d7fe314a11492606529b5a658ee9e3.zip |
Core: Drop support for IE <11, iOS <11, Firefox <65, Android Browser & PhantomJS
Also, update support comments format to match format described in:
https://github.com/jquery/contribute.jquery.org/issues/95#issuecomment-69379197
with the change from:
https://github.com/jquery/contribute.jquery.org/issues/95#issuecomment-448998379
(open-ended ranges end with `+`).
Fixes gh-3950
Fixes gh-4299
Closes gh-4347
67 files changed, 515 insertions, 1431 deletions
diff --git a/.eslintrc-browser.json b/.eslintrc-browser.json index ffd5b6467..146745d0e 100644 --- a/.eslintrc-browser.json +++ b/.eslintrc-browser.json @@ -3,11 +3,8 @@ "extends": "jquery", - // Support: IE <=9 only, Android <=4.0 only - // The above browsers are failing a lot of tests in the ES5 - // test suite at http://test262.ecmascript.org. "parserOptions": { - "ecmaVersion": 3 + "ecmaVersion": 5 }, // The browser env is not enabled on purpose so that code takes diff --git a/Gruntfile.js b/Gruntfile.js index 7fa324399..7db56b260 100644 --- a/Gruntfile.js +++ b/Gruntfile.js @@ -14,15 +14,7 @@ module.exports = function( grunt ) { var fs = require( "fs" ), gzip = require( "gzip-js" ), - isTravis = process.env.TRAVIS, - oldNode = /^v6\./.test( process.version ); - - // Support: Node.js <8 - // Skip running tasks that dropped support for Node.js 6 - // in those Node versions. - function runIfNewNode( task ) { - return oldNode ? "print_old_node_message:" + task : task; - } + isTravis = process.env.TRAVIS; if ( !grunt.option( "filename" ) ) { grunt.option( "filename", "jquery.js" ); @@ -123,10 +115,9 @@ module.exports = function( grunt ) { testswarm: { tests: [ - // A special module with basic tests, meant for - // not fully supported environments like Android 2.3, - // jsdom or PhantomJS. We run it everywhere, though, - // to make sure tests are not broken. + // 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. "basic", "ajax", @@ -291,23 +282,13 @@ module.exports = function( grunt ) { "dist/<%= grunt.option('filename').replace('.js', '.min.map') %>", report: "min", output: { - "ascii_only": true, - - // Support: Android 4.0 only - // UglifyJS 3 breaks Android 4.0 if this option is not enabled. - // This is in lieu of setting ie8 for all of mangle, compress, and output - "ie8": true + "ascii_only": true }, banner: "/*! jQuery v<%= pkg.version %> | " + "(c) JS Foundation and other contributors | jquery.org/license */", compress: { "hoist_funs": false, - loops: false, - - // Support: IE <11 - // typeofs transformation is unsafe for IE9-10 - // See https://github.com/mishoo/UglifyJS2/issues/2198 - typeofs: false + loops: false } } } @@ -320,13 +301,6 @@ module.exports = function( grunt ) { // Integrate jQuery specific tasks grunt.loadTasks( "build/tasks" ); - // Support: Node.js <8 - // Print a message on Node.js <8 notifying the task is skipped there. - grunt.registerTask( "print_old_node_message", function() { - var task = [].slice.call( arguments ).join( ":" ); - grunt.log.writeln( "Old Node.js detected, running the task \"" + task + "\" skipped..." ); - } ); - grunt.registerTask( "lint", [ "jsonlint", @@ -349,10 +323,7 @@ module.exports = function( grunt ) { grunt.registerTask( "test:fast", "node_smoke_tests" ); grunt.registerTask( "test:slow", [ "promises_aplus_tests", - - // Support: Node.js <8 - // Karma no longer supports Node.js <8 as it relies on async-await internally. - runIfNewNode( "karma:jsdom" ) + "karma:jsdom" ] ); grunt.registerTask( "test", [ diff --git a/src/ajax.js b/src/ajax.js index 4cbefabaa..9db26f66c 100644 --- a/src/ajax.js +++ b/src/ajax.js @@ -1,7 +1,6 @@ define( [ "./core", "./var/document", - "./var/isFunction", "./var/rnothtmlwhite", "./ajax/var/location", "./ajax/var/nonce", @@ -12,7 +11,7 @@ define( [ "./event/trigger", "./deferred", "./serialize" // jQuery.param -], function( jQuery, document, isFunction, rnothtmlwhite, location, nonce, rquery ) { +], function( jQuery, document, rnothtmlwhite, location, nonce, rquery ) { "use strict"; @@ -67,7 +66,7 @@ function addToPrefiltersOrTransports( structure ) { i = 0, dataTypes = dataTypeExpression.toLowerCase().match( rnothtmlwhite ) || []; - if ( isFunction( func ) ) { + if ( typeof func === "function" ) { // For each dataType in the dataTypeExpression while ( ( dataType = dataTypes[ i++ ] ) ) { @@ -541,13 +540,13 @@ jQuery.extend( { if ( s.crossDomain == null ) { urlAnchor = document.createElement( "a" ); - // Support: IE <=8 - 11, Edge 12 - 15 + // Support: IE <=8 - 11+, Edge 12 - 17 only // IE throws exception on accessing the href property if url is malformed, // e.g. http://example.com:80x/ try { urlAnchor.href = s.url; - // Support: IE <=8 - 11 only + // Support: IE <=8 - 11+ // Anchor's host property isn't correctly set when s.url is relative urlAnchor.href = urlAnchor.href; s.crossDomain = originAnchor.protocol + "//" + originAnchor.host !== @@ -837,7 +836,7 @@ jQuery.each( [ "get", "post" ], function( i, method ) { jQuery[ method ] = function( url, data, callback, type ) { // Shift arguments if data argument was omitted - if ( isFunction( data ) ) { + if ( typeof data === "function" ) { type = type || callback; callback = data; data = undefined; diff --git a/src/ajax/jsonp.js b/src/ajax/jsonp.js index 28ae0365d..dbdb4dbb8 100644 --- a/src/ajax/jsonp.js +++ b/src/ajax/jsonp.js @@ -1,10 +1,9 @@ define( [ "../core", - "../var/isFunction", "./var/nonce", "./var/rquery", "../ajax" -], function( jQuery, isFunction, nonce, rquery ) { +], function( jQuery, nonce, rquery ) { "use strict"; @@ -37,7 +36,7 @@ jQuery.ajaxPrefilter( "json jsonp", function( s, originalSettings, jqXHR ) { if ( jsonProp || s.dataTypes[ 0 ] === "jsonp" ) { // Get callback name, remembering preexisting value associated with it - callbackName = s.jsonpCallback = isFunction( s.jsonpCallback ) ? + callbackName = s.jsonpCallback = typeof s.jsonpCallback === "function" ? s.jsonpCallback() : s.jsonpCallback; @@ -88,7 +87,7 @@ jQuery.ajaxPrefilter( "json jsonp", function( s, originalSettings, jqXHR ) { } // Call if it was a function and we have a response - if ( responseContainer && isFunction( overwritten ) ) { + if ( responseContainer && typeof overwritten === "function" ) { overwritten( responseContainer[ 0 ] ); } diff --git a/src/ajax/load.js b/src/ajax/load.js index defdb0174..574d6b4a7 100644 --- a/src/ajax/load.js +++ b/src/ajax/load.js @@ -1,13 +1,12 @@ define( [ "../core", "../core/stripAndCollapse", - "../var/isFunction", "../core/parseHTML", "../ajax", "../traversing", "../manipulation", "../selector" -], function( jQuery, stripAndCollapse, isFunction ) { +], function( jQuery, stripAndCollapse ) { "use strict"; @@ -25,7 +24,7 @@ jQuery.fn.load = function( url, params, callback ) { } // If it's a function - if ( isFunction( params ) ) { + if ( typeof params === "function" ) { // We assume that it's the callback callback = params; diff --git a/src/ajax/parseXML.js b/src/ajax/parseXML.js index acf7ab259..0bdc49a7c 100644 --- a/src/ajax/parseXML.js +++ b/src/ajax/parseXML.js @@ -11,7 +11,7 @@ jQuery.parseXML = function( data ) { return null; } - // Support: IE 9 - 11 only + // Support: IE 9 - 11+ // IE throws on parseFromString with invalid input. try { xml = ( new window.DOMParser() ).parseFromString( data, "text/xml" ); diff --git a/src/ajax/xhr.js b/src/ajax/xhr.js index 4a31171ac..16a2ac3d8 100644 --- a/src/ajax/xhr.js +++ b/src/ajax/xhr.js @@ -1,8 +1,7 @@ define( [ "../core", - "../var/support", "../ajax" -], function( jQuery, support ) { +], function( jQuery ) { "use strict"; @@ -15,156 +14,109 @@ jQuery.ajaxSettings.xhr = function() { var xhrSuccessStatus = { // File protocol always yields status code 0, assume 200 - 0: 200, - - // Support: IE <=9 only - // #1450: sometimes IE returns 1223 when it should be 204 - 1223: 204 - }, - xhrSupported = jQuery.ajaxSettings.xhr(); - -support.cors = !!xhrSupported && ( "withCredentials" in xhrSupported ); -support.ajax = xhrSupported = !!xhrSupported; + 0: 200 + }; jQuery.ajaxTransport( function( options ) { - var callback, errorCallback; + var callback; // Cross domain only allowed if supported through XMLHttpRequest - if ( support.cors || xhrSupported && !options.crossDomain ) { - return { - send: function( headers, complete ) { - var i, - xhr = options.xhr(); - - xhr.open( - options.type, - options.url, - options.async, - options.username, - options.password - ); - - // Apply custom fields if provided - if ( options.xhrFields ) { - for ( i in options.xhrFields ) { - xhr[ i ] = options.xhrFields[ i ]; - } + return { + send: function( headers, complete ) { + var i, + xhr = options.xhr(); + + xhr.open( + options.type, + options.url, + options.async, + options.username, + options.password + ); + + // Apply custom fields if provided + if ( options.xhrFields ) { + for ( i in options.xhrFields ) { + xhr[ i ] = options.xhrFields[ i ]; } + } - // Override mime type if needed - if ( options.mimeType && xhr.overrideMimeType ) { - xhr.overrideMimeType( options.mimeType ); - } + // Override mime type if needed + if ( options.mimeType && xhr.overrideMimeType ) { + xhr.overrideMimeType( options.mimeType ); + } - // X-Requested-With header - // For cross-domain requests, seeing as conditions for a preflight are - // akin to a jigsaw puzzle, we simply never set it to be sure. - // (it can always be set on a per-request basis or even using ajaxSetup) - // For same-domain requests, won't change header if already provided. - if ( !options.crossDomain && !headers[ "X-Requested-With" ] ) { - headers[ "X-Requested-With" ] = "XMLHttpRequest"; - } + // X-Requested-With header + // For cross-domain requests, seeing as conditions for a preflight are + // akin to a jigsaw puzzle, we simply never set it to be sure. + // (it can always be set on a per-request basis or even using ajaxSetup) + // For same-domain requests, won't change header if already provided. + if ( !options.crossDomain && !headers[ "X-Requested-With" ] ) { + headers[ "X-Requested-With" ] = "XMLHttpRequest"; + } - // Set headers - for ( i in headers ) { - xhr.setRequestHeader( i, headers[ i ] ); - } + // Set headers + for ( i in headers ) { + xhr.setRequestHeader( i, headers[ i ] ); + } - // Callback - callback = function( type ) { - return function() { - if ( callback ) { - callback = errorCallback = xhr.onload = - xhr.onerror = xhr.onabort = xhr.ontimeout = - xhr.onreadystatechange = null; - - if ( type === "abort" ) { - xhr.abort(); - } else if ( type === "error" ) { - - // Support: IE <=9 only - // On a manual native abort, IE9 throws - // errors on any property access that is not readyState - if ( typeof xhr.status !== "number" ) { - complete( 0, "error" ); - } else { - complete( - - // File: protocol always yields status 0; see #8605, #14207 - xhr.status, - xhr.statusText - ); - } - } else { - complete( - xhrSuccessStatus[ xhr.status ] || xhr.status, - xhr.statusText, - - // Support: IE <=9 only - // IE9 has no XHR2 but throws on binary (trac-11426) - // For XHR2 non-text, let the caller handle it (gh-2498) - ( xhr.responseType || "text" ) !== "text" || - typeof xhr.responseText !== "string" ? - { binary: xhr.response } : - { text: xhr.responseText }, - xhr.getAllResponseHeaders() - ); - } + // Callback + callback = function( type ) { + return function() { + if ( callback ) { + callback = xhr.onload = xhr.onerror = xhr.onabort = xhr.ontimeout = null; + + if ( type === "abort" ) { + xhr.abort(); + } else if ( type === "error" ) { + complete( + + // File: protocol always yields status 0; see #8605, #14207 + xhr.status, + xhr.statusText + ); + } else { + complete( + xhrSuccessStatus[ xhr.status ] || xhr.status, + xhr.statusText, + + // For XHR2 non-text, let the caller handle it (gh-2498) + ( xhr.responseType || "text" ) === "text" ? + { text: xhr.responseText } : + { binary: xhr.response }, + xhr.getAllResponseHeaders() + ); } - }; + } }; + }; - // Listen to events - xhr.onload = callback(); - errorCallback = xhr.onerror = xhr.ontimeout = callback( "error" ); - - // Support: IE 9 only - // Use onreadystatechange to replace onabort - // to handle uncaught aborts - if ( xhr.onabort !== undefined ) { - xhr.onabort = errorCallback; - } else { - xhr.onreadystatechange = function() { - - // Check readyState before timeout as it changes - if ( xhr.readyState === 4 ) { - - // Allow onerror to be called first, - // but that will not handle a native abort - // Also, save errorCallback to a variable - // as xhr.onerror cannot be accessed - window.setTimeout( function() { - if ( callback ) { - errorCallback(); - } - } ); - } - }; - } - - // Create the abort callback - callback = callback( "abort" ); + // Listen to events + xhr.onload = callback(); + xhr.onabort = xhr.onerror = xhr.ontimeout = callback( "error" ); - try { + // Create the abort callback + callback = callback( "abort" ); - // Do send the request (this may raise an exception) - xhr.send( options.hasContent && options.data || null ); - } catch ( e ) { + try { - // #14683: Only rethrow if this hasn't been notified as an error yet - if ( callback ) { - throw e; - } - } - }, + // Do send the request (this may raise an exception) + xhr.send( options.hasContent && options.data || null ); + } catch ( e ) { - abort: function() { + // #14683: Only rethrow if this hasn't been notified as an error yet if ( callback ) { - callback(); + throw e; } } - }; - } + }, + + abort: function() { + if ( callback ) { + callback(); + } + } + }; } ); } ); diff --git a/src/attributes/classes.js b/src/attributes/classes.js index 0c90a8dff..f1571eb5d 100644 --- a/src/attributes/classes.js +++ b/src/attributes/classes.js @@ -1,11 +1,10 @@ define( [ "../core", "../core/stripAndCollapse", - "../var/isFunction", "../var/rnothtmlwhite", "../data/var/dataPriv", "../core/init" -], function( jQuery, stripAndCollapse, isFunction, rnothtmlwhite, dataPriv ) { +], function( jQuery, stripAndCollapse, rnothtmlwhite, dataPriv ) { "use strict"; @@ -28,7 +27,7 @@ jQuery.fn.extend( { var classes, elem, cur, curValue, clazz, j, finalValue, i = 0; - if ( isFunction( value ) ) { + if ( typeof value === "function" ) { return this.each( function( j ) { jQuery( this ).addClass( value.call( this, j, getClass( this ) ) ); } ); @@ -65,7 +64,7 @@ jQuery.fn.extend( { var classes, elem, cur, curValue, clazz, j, finalValue, i = 0; - if ( isFunction( value ) ) { + if ( typeof value === "function" ) { return this.each( function( j ) { jQuery( this ).removeClass( value.call( this, j, getClass( this ) ) ); } ); @@ -114,7 +113,7 @@ jQuery.fn.extend( { return stateVal ? this.addClass( value ) : this.removeClass( value ); } - if ( isFunction( value ) ) { + if ( typeof value === "function" ) { return this.each( function( i ) { jQuery( this ).toggleClass( value.call( this, i, getClass( this ), stateVal ), diff --git a/src/attributes/prop.js b/src/attributes/prop.js index 49ac244df..8ada707f4 100644 --- a/src/attributes/prop.js +++ b/src/attributes/prop.js @@ -59,7 +59,7 @@ jQuery.extend( { tabIndex: { get: function( elem ) { - // Support: IE <=9 - 11 only + // Support: IE <=9 - 11+ // elem.tabIndex doesn't always return the // correct value when it hasn't been explicitly set // https://web.archive.org/web/20141116233347/http://fluidproject.org/blog/2008/01/09/getting-setting-and-removing-tabindex-values-with-javascript/ @@ -89,7 +89,7 @@ jQuery.extend( { } } ); -// Support: IE <=11 only +// Support: IE <=11+ // Accessing the selectedIndex property // forces the browser to respect setting selected // on the option @@ -101,23 +101,23 @@ if ( !support.optSelected ) { jQuery.propHooks.selected = { get: function( elem ) { - /* eslint no-unused-expressions: "off" */ - var parent = elem.parentNode; if ( parent && parent.parentNode ) { + // eslint-disable-next-line no-unused-expressions parent.parentNode.selectedIndex; } return null; }, set: function( elem ) { - /* eslint no-unused-expressions: "off" */ var parent = elem.parentNode; if ( parent ) { + // eslint-disable-next-line no-unused-expressions parent.selectedIndex; if ( parent.parentNode ) { + // eslint-disable-next-line no-unused-expressions parent.parentNode.selectedIndex; } } diff --git a/src/attributes/support.js b/src/attributes/support.js index af60e9694..78d0040a9 100644 --- a/src/attributes/support.js +++ b/src/attributes/support.js @@ -12,15 +12,11 @@ define( [ input.type = "checkbox"; - // Support: Android <=4.3 only - // Default value for a checkbox should be "on" - support.checkOn = input.value !== ""; - - // Support: IE <=11 only + // Support: IE <=11+ // Must access selectedIndex to make default options select support.optSelected = opt.selected; - // Support: IE <=11 only + // Support: IE <=11+ // An input loses its value after becoming a radio input = document.createElement( "input" ); input.value = "t"; diff --git a/src/attributes/val.js b/src/attributes/val.js index c719b34b3..f7d6cf190 100644 --- a/src/attributes/val.js +++ b/src/attributes/val.js @@ -1,12 +1,10 @@ define( [ "../core", "../core/stripAndCollapse", - "./support", "../core/nodeName", - "../var/isFunction", "../core/init" -], function( jQuery, stripAndCollapse, support, nodeName, isFunction ) { +], function( jQuery, stripAndCollapse, nodeName ) { "use strict"; @@ -43,7 +41,7 @@ jQuery.fn.extend( { return; } - valueIsFunction = isFunction( value ); + valueIsFunction = typeof value === "function"; return this.each( function( i ) { var val; @@ -90,7 +88,7 @@ jQuery.extend( { return val != null ? val : - // Support: IE <=10 - 11 only + // Support: IE <=10 - 11+ // option.text throws exceptions (#14686, #14858) // Strip and collapse whitespace // https://html.spec.whatwg.org/#strip-and-collapse-whitespace @@ -117,9 +115,7 @@ jQuery.extend( { for ( ; i < max; i++ ) { option = options[ i ]; - // Support: IE <=9 only - // IE8-9 doesn't update selected after form reset (#2551) - if ( ( option.selected || i === index ) && + if ( option.selected && // Don't return options that are disabled or in a disabled optgroup !option.disabled && @@ -181,11 +177,6 @@ jQuery.each( [ "radio", "checkbox" ], function() { } } }; - if ( !support.checkOn ) { - jQuery.valHooks[ this ].get = function( elem ) { - return elem.getAttribute( "value" ) === null ? "on" : elem.value; - }; - } } ); } ); diff --git a/src/callbacks.js b/src/callbacks.js index 6cf54031e..140c4979e 100644 --- a/src/callbacks.js +++ b/src/callbacks.js @@ -1,9 +1,8 @@ define( [ "./core", "./core/toType", - "./var/isFunction", "./var/rnothtmlwhite" -], function( jQuery, toType, isFunction, rnothtmlwhite ) { +], function( jQuery, toType, rnothtmlwhite ) { "use strict"; @@ -127,7 +126,7 @@ jQuery.Callbacks = function( options ) { ( function add( args ) { jQuery.each( args, function( _, arg ) { - if ( isFunction( arg ) ) { + if ( typeof arg === "function" ) { if ( !options.unique || !self.has( arg ) ) { list.push( arg ); } diff --git a/src/core.js b/src/core.js index 3ef92d48f..5a5c7469e 100644 --- a/src/core.js +++ b/src/core.js @@ -15,14 +15,14 @@ define( [ "./var/hasOwn", "./var/fnToString", "./var/ObjectFunctionString", + "./var/trim", "./var/support", - "./var/isFunction", "./var/isWindow", "./core/DOMEval", "./core/toType" ], function( arr, document, getProto, slice, concat, push, indexOf, class2type, toString, hasOwn, fnToString, ObjectFunctionString, - support, isFunction, isWindow, DOMEval, toType ) { + trim, support, isWindow, DOMEval, toType ) { "use strict"; @@ -35,11 +35,7 @@ var // The jQuery object is actually just the init constructor 'enhanced' // Need init if jQuery is called (just allow error to be thrown if not included) return new jQuery.fn.init( selector, context ); - }, - - // Support: Android <=4.0 only - // Make sure we trim BOM and NBSP - rtrim = /^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g; + }; jQuery.fn = jQuery.prototype = { @@ -139,7 +135,7 @@ jQuery.extend = jQuery.fn.extend = function() { } // Handle case when target is a string or something (possible in deep copy) - if ( typeof target !== "object" && !isFunction( target ) ) { + if ( typeof target !== "object" && typeof target !== "function" ) { target = {}; } @@ -264,11 +260,8 @@ jQuery.extend( { return obj; }, - // Support: Android <=4.0 only trim: function( text ) { - return text == null ? - "" : - ( text + "" ).replace( rtrim, "" ); + return text == null ? "" : trim.call( text ); }, // results is for internal usage only @@ -293,8 +286,6 @@ jQuery.extend( { return arr == null ? -1 : indexOf.call( arr, elem, i ); }, - // Support: Android <=4.0 only, PhantomJS 1 only - // push.apply(_, arraylike) throws on ancient WebKit merge: function( first, second ) { var len = +second.length, j = 0, @@ -380,14 +371,10 @@ function( i, name ) { function isArrayLike( obj ) { - // Support: real iOS 8.2 only (not reproducible in simulator) - // `in` check used to prevent JIT error (gh-2145) - // hasOwn isn't used here due to false negatives - // regarding Nodelist length in IE - var length = !!obj && "length" in obj && obj.length, + var length = !!obj && obj.length, type = toType( obj ); - if ( isFunction( obj ) || isWindow( obj ) ) { + if ( typeof obj === "function" || isWindow( obj ) ) { return false; } diff --git a/src/core/DOMEval.js b/src/core/DOMEval.js index 59f6e0247..df83cca52 100644 --- a/src/core/DOMEval.js +++ b/src/core/DOMEval.js @@ -20,7 +20,7 @@ define( [ if ( node ) { for ( i in preservedScriptAttributes ) { - // Support: Firefox 64+, Edge 18+ + // Support: Firefox <=64 - 66+, Edge <=18+ // Some browsers don't support the "nonce" property on scripts. // On the other hand, just using `getAttribute` is not enough as // the `nonce` attribute is reset to an empty string whenever it diff --git a/src/core/access.js b/src/core/access.js index 842c4a42b..f600600d5 100644 --- a/src/core/access.js +++ b/src/core/access.js @@ -1,8 +1,7 @@ define( [ "../core", - "../core/toType", - "../var/isFunction" -], function( jQuery, toType, isFunction ) { + "../core/toType" +], function( jQuery, toType ) { "use strict"; @@ -24,7 +23,7 @@ var access = function( elems, fn, key, value, chainable, emptyGet, raw ) { } else if ( value !== undefined ) { chainable = true; - if ( !isFunction( value ) ) { + if ( typeof value !== "function" ) { raw = true; } diff --git a/src/core/init.js b/src/core/init.js index 8865238c8..71f30e926 100644 --- a/src/core/init.js +++ b/src/core/init.js @@ -2,11 +2,10 @@ define( [ "../core", "../var/document", - "../var/isFunction", "./var/rsingleTag", "../traversing/findFilter" -], function( jQuery, document, isFunction, rsingleTag ) { +], function( jQuery, document, rsingleTag ) { "use strict"; @@ -64,7 +63,7 @@ var rootjQuery, for ( match in context ) { // Properties of context are called as methods if possible - if ( isFunction( this[ match ] ) ) { + if ( typeof this[ match ] === "function" ) { this[ match ]( context[ match ] ); // ...and otherwise set as attributes @@ -107,7 +106,7 @@ var rootjQuery, // HANDLE: $(function) // Shortcut for document ready - } else if ( isFunction( selector ) ) { + } else if ( typeof selector === "function" ) { return root.ready !== undefined ? root.ready( selector ) : diff --git a/src/core/isAttached.js b/src/core/isAttached.js index efa2465a9..1acf15714 100644 --- a/src/core/isAttached.js +++ b/src/core/isAttached.js @@ -10,8 +10,9 @@ define( [ }, composed = { composed: true }; + // Support: IE 9 - 11+, Edge 12 - 18+ // Check attachment across shadow DOM boundaries when possible (gh-3504) - if ( documentElement.attachShadow ) { + if ( documentElement.getRootNode ) { isAttached = function( elem ) { return jQuery.contains( elem.ownerDocument, elem ) || elem.getRootNode( composed ) === elem.ownerDocument; diff --git a/src/core/parseHTML.js b/src/core/parseHTML.js index 21ff6bfa7..8c5268fb1 100644 --- a/src/core/parseHTML.js +++ b/src/core/parseHTML.js @@ -2,11 +2,8 @@ define( [ "../core", "../var/document", "./var/rsingleTag", - "../manipulation/buildFragment", - - // This is the only module that needs core/support - "./support" -], function( jQuery, document, rsingleTag, buildFragment, support ) { + "../manipulation/buildFragment" +], function( jQuery, document, rsingleTag, buildFragment ) { "use strict"; @@ -29,18 +26,14 @@ jQuery.parseHTML = function( data, context, keepScripts ) { // Stop scripts or inline event handlers from being executed immediately // by using document.implementation - if ( support.createHTMLDocument ) { - context = document.implementation.createHTMLDocument( "" ); - - // Set the base href for the created document - // so any parsed elements with URLs - // are based on the document's URL (gh-2965) - base = context.createElement( "base" ); - base.href = document.location.href; - context.head.appendChild( base ); - } else { - context = document; - } + context = document.implementation.createHTMLDocument( "" ); + + // Set the base href for the created document + // so any parsed elements with URLs + // are based on the document's URL (gh-2965) + base = context.createElement( "base" ); + base.href = document.location.href; + context.head.appendChild( base ); } parsed = rsingleTag.exec( data ); diff --git a/src/core/ready-no-deferred.js b/src/core/ready-no-deferred.js index 4428020ef..2c3fc1b84 100644 --- a/src/core/ready-no-deferred.js +++ b/src/core/ready-no-deferred.js @@ -1,8 +1,7 @@ define( [ "../core", - "../var/document", - "../var/isFunction" -], function( jQuery, document, isFunction ) { + "../var/document" +], function( jQuery, document ) { "use strict"; @@ -53,7 +52,7 @@ jQuery.extend( { while ( readyCallbacks.length ) { fn = readyCallbacks.shift(); - if ( isFunction( fn ) ) { + if ( typeof fn === "function" ) { executeReady( fn ); } } @@ -77,10 +76,7 @@ function completed() { // Catch cases where $(document).ready() is called // after the browser event has already occurred. -// Support: IE9-10 only -// Older IE sometimes signals "interactive" too soon -if ( document.readyState === "complete" || - ( document.readyState !== "loading" && !document.documentElement.doScroll ) ) { +if ( document.readyState !== "loading" ) { // Handle it asynchronously to allow scripts the opportunity to delay ready window.setTimeout( jQuery.ready ); diff --git a/src/core/ready.js b/src/core/ready.js index 794feeec0..3abb6c03a 100644 --- a/src/core/ready.js +++ b/src/core/ready.js @@ -66,10 +66,7 @@ function completed() { // Catch cases where $(document).ready() is called // after the browser event has already occurred. -// Support: IE <=9 - 10 only -// Older IE sometimes signals "interactive" too soon -if ( document.readyState === "complete" || - ( document.readyState !== "loading" && !document.documentElement.doScroll ) ) { +if ( document.readyState !== "loading" ) { // Handle it asynchronously to allow scripts the opportunity to delay ready window.setTimeout( jQuery.ready ); diff --git a/src/core/support.js b/src/core/support.js deleted file mode 100644 index 13ae02f08..000000000 --- a/src/core/support.js +++ /dev/null @@ -1,20 +0,0 @@ -define( [ - "../var/document", - "../var/support" -], function( document, support ) { - -"use strict"; - -// Support: Safari 8 only -// In Safari 8 documents created via document.implementation.createHTMLDocument -// collapse sibling forms: the second one becomes a child of the first one. -// Because of that, this security measure has to be disabled in Safari 8. -// https://bugs.webkit.org/show_bug.cgi?id=137337 -support.createHTMLDocument = ( function() { - var body = document.implementation.createHTMLDocument( "" ).body; - body.innerHTML = "<form></form><form></form>"; - return body.childNodes.length === 2; -} )(); - -return support; -} ); diff --git a/src/core/toType.js b/src/core/toType.js index c77ba95ad..c555ef9df 100644 --- a/src/core/toType.js +++ b/src/core/toType.js @@ -10,8 +10,7 @@ function toType( obj ) { return obj + ""; } - // Support: Android <=2.3 only (functionish RegExp) - return typeof obj === "object" || typeof obj === "function" ? + return typeof obj === "object" ? class2type[ toString.call( obj ) ] || "object" : typeof obj; } diff --git a/src/css.js b/src/css.js index c92fc684a..91c42624e 100644 --- a/src/css.js +++ b/src/css.js @@ -10,7 +10,6 @@ define( [ "./css/var/swap", "./css/curCSS", "./css/adjustCSS", - "./css/addGetHookIf", "./css/support", "./css/finalPropName", @@ -18,7 +17,7 @@ define( [ "./core/ready", "./selector" // contains ], function( jQuery, access, rcssNum, rnumnonpx, cssExpand, isAutoPx, cssCamelCase, - getStyles, swap, curCSS, adjustCSS, addGetHookIf, support, finalPropName ) { + getStyles, swap, curCSS, adjustCSS, support, finalPropName ) { "use strict"; @@ -130,7 +129,6 @@ function getWidthOrHeight( elem, dimension, extra ) { val = curCSS( elem, dimension, styles ), offsetProp = "offset" + dimension[ 0 ].toUpperCase() + dimension.slice( 1 ); - // Support: Firefox <=54 // Return a confounding non-pixel value or feign ignorance, as appropriate. if ( rnumnonpx.test( val ) ) { if ( !extra ) { @@ -142,15 +140,11 @@ function getWidthOrHeight( elem, dimension, extra ) { // Fall back to offsetWidth/offsetHeight when value is "auto" // This happens for inline elements with no explicit setting (gh-3571) - // Support: Android <=4.1 - 4.3 only - // Also use offsetWidth/offsetHeight for misreported inline dimensions (gh-3602) - // Support: IE 9-11 only + // Support: IE 9 - 11+ // Also use offsetWidth/offsetHeight for when box sizing is unreliable // We use getClientRects() to check for hidden/disconnected. // In those cases, the computed value can be trusted to be border-box - if ( ( !support.boxSizingReliable() && isBorderBox || - val === "auto" || - !parseFloat( val ) && jQuery.css( elem, "display", false, styles ) === "inline" ) && + if ( ( !support.boxSizingReliable() && isBorderBox || val === "auto" ) && elem.getClientRects().length ) { isBorderBox = jQuery.css( elem, "boxSizing", false, styles ) === "border-box"; @@ -324,10 +318,10 @@ jQuery.each( [ "height", "width" ], function( i, dimension ) { // but it must have a current display style that would benefit return rdisplayswap.test( jQuery.css( elem, "display" ) ) && - // Support: Safari 8+ - // Table columns in Safari have non-zero offsetWidth & zero + // Support: Safari <=8 - 12+, Chrome <=73+ + // Table columns in WebKit/Blink have non-zero offsetWidth & zero // getBoundingClientRect().width unless display is changed. - // Support: IE <=11 only + // Support: IE <=11+ // Running getBoundingClientRect on a disconnected node // in IE throws an error. ( !elem.getClientRects().length || !elem.getBoundingClientRect().width ) ? @@ -342,14 +336,8 @@ jQuery.each( [ "height", "width" ], function( i, dimension ) { var matches, styles = getStyles( elem ), - // Only read styles.position if the test has a chance to fail - // to avoid forcing a reflow. - scrollboxSizeBuggy = !support.scrollboxSize() && - styles.position === "absolute", - // To avoid forcing a reflow, only fetch boxSizing if we need it (gh-3991) - boxSizingNeeded = scrollboxSizeBuggy || extra, - isBorderBox = boxSizingNeeded && + isBorderBox = extra && jQuery.css( elem, "boxSizing", false, styles ) === "border-box", subtract = extra ? boxModelAdjustment( @@ -361,17 +349,6 @@ jQuery.each( [ "height", "width" ], function( i, dimension ) { ) : 0; - // Account for unreliable border-box dimensions by comparing offset* to computed and - // faking a content-box to get border and padding (gh-3699) - if ( isBorderBox && scrollboxSizeBuggy ) { - subtract -= Math.ceil( - elem[ "offset" + dimension[ 0 ].toUpperCase() + dimension.slice( 1 ) ] - - parseFloat( styles[ dimension ] ) - - boxModelAdjustment( elem, dimension, "border", false, styles ) - - 0.5 - ); - } - // Convert to pixels if value adjustment is needed if ( subtract && ( matches = rcssNum.exec( value ) ) && ( matches[ 3 ] || "px" ) !== "px" ) { @@ -385,19 +362,6 @@ jQuery.each( [ "height", "width" ], function( i, dimension ) { }; } ); -jQuery.cssHooks.marginLeft = addGetHookIf( support.reliableMarginLeft, - function( elem, computed ) { - if ( computed ) { - return ( parseFloat( curCSS( elem, "marginLeft" ) ) || - elem.getBoundingClientRect().left - - swap( elem, { marginLeft: 0 }, function() { - return elem.getBoundingClientRect().left; - } ) - ) + "px"; - } - } -); - // These hooks are used by animate to expand properties jQuery.each( { margin: "", diff --git a/src/css/addGetHookIf.js b/src/css/addGetHookIf.js deleted file mode 100644 index e4bb49a67..000000000 --- a/src/css/addGetHookIf.js +++ /dev/null @@ -1,26 +0,0 @@ -define( function() { - -"use strict"; - -function addGetHookIf( conditionFn, hookFn ) { - - // Define the hook, we'll check on the first run if it's really needed. - return { - get: function() { - if ( conditionFn() ) { - - // Hook not needed (or it's not possible to use it due - // to missing dependency), remove it. - delete this.get; - return; - } - - // Hook needed; redefine it so that the support test is not executed again. - return ( this.get = hookFn ).apply( this, arguments ); - } - }; -} - -return addGetHookIf; - -} ); diff --git a/src/css/adjustCSS.js b/src/css/adjustCSS.js index 4e3e6c37a..5341a7890 100644 --- a/src/css/adjustCSS.js +++ b/src/css/adjustCSS.js @@ -26,7 +26,7 @@ function adjustCSS( elem, prop, valueParts, tween ) { if ( initialInUnit && initialInUnit[ 3 ] !== unit ) { - // Support: Firefox <=54 + // Support: Firefox <=54 - 66+ // Halve the iteration target value to prevent interference from CSS upper bounds (gh-2144) initial = initial / 2; diff --git a/src/css/curCSS.js b/src/css/curCSS.js index 98a594a77..111285b2e 100644 --- a/src/css/curCSS.js +++ b/src/css/curCSS.js @@ -1,61 +1,28 @@ define( [ "../core", "../core/isAttached", - "./var/rboxStyle", - "./var/rnumnonpx", - "./var/getStyles", - "./support" -], function( jQuery, isAttached, rboxStyle, rnumnonpx, getStyles, support ) { + "./var/getStyles" +], function( jQuery, isAttached, rboxStyle, getStyles ) { "use strict"; function curCSS( elem, name, computed ) { - var width, minWidth, maxWidth, ret, - - // Support: Firefox 51+ - // Retrieving style before computed somehow - // fixes an issue with getting wrong values - // on detached elements - style = elem.style; + var ret; computed = computed || getStyles( elem ); - // getPropertyValue is needed for: - // .css('filter') (IE 9 only, #12537) - // .css('--customProperty) (#3144) + // getPropertyValue is needed for `.css('--customProperty')` (gh-3144) if ( computed ) { ret = computed.getPropertyValue( name ) || computed[ name ]; if ( ret === "" && !isAttached( elem ) ) { ret = jQuery.style( elem, name ); } - - // A tribute to the "awesome hack by Dean Edwards" - // Android Browser returns percentage for some values, - // but width seems to be reliably pixels. - // This is against the CSSOM draft spec: - // https://drafts.csswg.org/cssom/#resolved-values - if ( !support.pixelBoxStyles() && rnumnonpx.test( ret ) && rboxStyle.test( name ) ) { - - // Remember the original values - width = style.width; - minWidth = style.minWidth; - maxWidth = style.maxWidth; - - // Put in the new values to get a computed value out - style.minWidth = style.maxWidth = style.width = ret; - ret = computed.width; - - // Revert the changed values - style.width = width; - style.minWidth = minWidth; - style.maxWidth = maxWidth; - } } return ret !== undefined ? - // Support: IE <=9 - 11 only + // Support: IE <=9 - 11+ // IE returns zIndex value as an integer. ret + "" : ret; diff --git a/src/css/support.js b/src/css/support.js index 9c4da57d9..65763baec 100644 --- a/src/css/support.js +++ b/src/css/support.js @@ -9,58 +9,7 @@ define( [ ( function() { - // Executing both pixelPosition & boxSizingReliable tests require only one layout - // so they're executed at the same time to save the second computation. - function computeStyleTests() { - - // This is a singleton, we need to execute it only once - if ( !div ) { - return; - } - - container.style.cssText = "position:absolute;left:-11111px;width:60px;" + - "margin-top:1px;padding:0;border:0"; - div.style.cssText = - "position:relative;display:block;box-sizing:border-box;overflow:scroll;" + - "margin:auto;border:1px;padding:1px;" + - "width:60%;top:1%"; - documentElement.appendChild( container ).appendChild( div ); - - var divStyle = window.getComputedStyle( div ); - pixelPositionVal = divStyle.top !== "1%"; - - // Support: Android 4.0 - 4.3 only, Firefox <=3 - 44 - reliableMarginLeftVal = roundPixelMeasures( divStyle.marginLeft ) === 12; - - // Support: Android 4.0 - 4.3 only, Safari <=9.1 - 10.1, iOS <=7.0 - 9.3 - // Some styles come back with percentage values, even though they shouldn't - div.style.right = "60%"; - pixelBoxStylesVal = roundPixelMeasures( divStyle.right ) === 36; - - // Support: IE 9 - 11 only - // Detect misreporting of content dimensions for box-sizing:border-box elements - boxSizingReliableVal = roundPixelMeasures( divStyle.width ) === 36; - - // Support: IE 9 only - // Detect overflow:scroll screwiness (gh-3699) - // Support: Chrome <=64 - // Don't get tricked when zoom affects offsetWidth (gh-4029) - div.style.position = "absolute"; - scrollboxSizeVal = roundPixelMeasures( div.offsetWidth / 3 ) === 12; - - documentElement.removeChild( container ); - - // Nullify the div so it wouldn't be stored in the memory and - // it will also be a sign that checks already performed - div = null; - } - - function roundPixelMeasures( measure ) { - return Math.round( parseFloat( measure ) ); - } - - var pixelPositionVal, boxSizingReliableVal, scrollboxSizeVal, pixelBoxStylesVal, - reliableMarginLeftVal, + var boxSizingReliableVal, container = document.createElement( "div" ), div = document.createElement( "div" ); @@ -69,7 +18,7 @@ define( [ return; } - // Support: IE <=9 - 11 only + // Support: IE <=9 - 11+ // Style of cloned element affects source element cloned (#8908) div.style.backgroundClip = "content-box"; div.cloneNode( true ).style.backgroundClip = ""; @@ -77,24 +26,31 @@ define( [ jQuery.extend( support, { boxSizingReliable: function() { - computeStyleTests(); + + // This is a singleton, we need to execute it only once + if ( div ) { + container.style.cssText = "position:absolute;left:-11111px;width:60px;" + + "margin-top:1px;padding:0;border:0"; + div.style.cssText = + "position:relative;display:block;box-sizing:border-box;overflow:scroll;" + + "margin:auto;border:1px;padding:1px;" + + "width:60%;top:1%"; + documentElement.appendChild( container ).appendChild( div ); + + var divStyle = window.getComputedStyle( div ); + + // Support: IE 9 - 11+ + // Detect misreporting of content dimensions for box-sizing:border-box elements + boxSizingReliableVal = Math.round( parseFloat( divStyle.width ) ) === 36; + + documentElement.removeChild( container ); + + // Nullify the div so it wouldn't be stored in the memory and + // it will also be a sign that checks already performed + div = null; + } + return boxSizingReliableVal; - }, - pixelBoxStyles: function() { - computeStyleTests(); - return pixelBoxStylesVal; - }, - pixelPosition: function() { - computeStyleTests(); - return pixelPositionVal; - }, - reliableMarginLeft: function() { - computeStyleTests(); - return reliableMarginLeftVal; - }, - scrollboxSize: function() { - computeStyleTests(); - return scrollboxSizeVal; } } ); } )(); diff --git a/src/css/var/getStyles.js b/src/css/var/getStyles.js index 0b893acf0..7adbdcfb5 100644 --- a/src/css/var/getStyles.js +++ b/src/css/var/getStyles.js @@ -3,12 +3,14 @@ define( function() { return function( elem ) { - // Support: IE <=11 only, Firefox <=30 (#15098, #14150) - // IE throws on elements created in popups - // FF meanwhile throws on frame elements through "defaultView.getComputedStyle" + // Support: IE <=11+ (trac-14150) + // In IE popup's `window` is the opener window which makes `window.getComputedStyle( elem )` + // break. Using `elem.ownerDocument.defaultView` avoids the issue. var view = elem.ownerDocument.defaultView; - if ( !view || !view.opener ) { + // `document.implementation.createHTMLDocument( "" )` has a `null` `defaultView` + // property; check `defaultView` truthiness to fallback to window in such a case. + if ( !view ) { view = window; } diff --git a/src/css/var/isHiddenWithinTree.js b/src/css/var/isHiddenWithinTree.js index 0ab610e29..1e99b96d3 100644 --- a/src/css/var/isHiddenWithinTree.js +++ b/src/css/var/isHiddenWithinTree.js @@ -1,9 +1,8 @@ define( [ - "../../core", - "../../core/isAttached" + "../../core" // css is assumed -], function( jQuery, isAttached ) { +], function( jQuery ) { "use strict"; // isHiddenWithinTree reports if an element has a non-"none" display style (inline and/or @@ -22,13 +21,6 @@ define( [ // Inline style trumps all return elem.style.display === "none" || elem.style.display === "" && - - // Otherwise, check computed style - // Support: Firefox <=43 - 45 - // Disconnected elements can have computed display: none, so first confirm that elem is - // in the document. - isAttached( elem ) && - jQuery.css( elem, "display" ) === "none"; }; } ); diff --git a/src/data.js b/src/data.js index 95c365a5a..d6706493a 100644 --- a/src/data.js +++ b/src/data.js @@ -108,7 +108,7 @@ jQuery.fn.extend( { i = attrs.length; while ( i-- ) { - // Support: IE 11 only + // Support: IE 11+ // The attrs elements can be null (#14894) if ( attrs[ i ] ) { name = attrs[ i ].name; diff --git a/src/data/Data.js b/src/data/Data.js index 31ff4318c..c94480fcd 100644 --- a/src/data/Data.js +++ b/src/data/Data.js @@ -141,7 +141,7 @@ Data.prototype = { // Remove the expando if there's no more data if ( key === undefined || jQuery.isEmptyObject( cache ) ) { - // Support: Chrome <=35 - 45 + // Support: Chrome <=35 - 45+ // Webkit & Blink performance suffers when deleting properties // from DOM nodes, so set to undefined instead // https://bugs.chromium.org/p/chromium/issues/detail?id=378607 (bug restricted) diff --git a/src/deferred.js b/src/deferred.js index 0425d3631..81a1d0140 100644 --- a/src/deferred.js +++ b/src/deferred.js @@ -1,9 +1,8 @@ define( [ "./core", - "./var/isFunction", "./var/slice", "./callbacks" -], function( jQuery, isFunction, slice ) { +], function( jQuery, slice ) { "use strict"; @@ -20,11 +19,11 @@ function adoptValue( value, resolve, reject, noValue ) { try { // Check for promise aspect first to privilege synchronous behavior - if ( value && isFunction( ( method = value.promise ) ) ) { + if ( value && typeof( method = value.promise ) === "function" ) { method.call( value ).done( resolve ).fail( reject ); // Other thenables - } else if ( value && isFunction( ( method = value.then ) ) ) { + } else if ( value && typeof( method = value.then ) === "function" ) { method.call( value, resolve, reject ); // Other non-thenables @@ -40,10 +39,7 @@ function adoptValue( value, resolve, reject, noValue ) { // Since jQuery.when doesn't unwrap thenables, we can skip the extra checks appearing in // Deferred#then to conditionally suppress rejection. } catch ( value ) { - - // Support: Android 4.0 only - // Strict mode functions invoked without .call/.apply get global-object context - reject.apply( undefined, [ value ] ); + reject( value ); } } @@ -70,7 +66,7 @@ jQuery.extend( { deferred.done( arguments ).fail( arguments ); return this; }, - "catch": function( fn ) { + catch: function( fn ) { return promise.then( null, fn ); }, @@ -82,14 +78,15 @@ jQuery.extend( { jQuery.each( tuples, function( i, tuple ) { // Map tuples (progress, done, fail) to arguments (done, fail, progress) - var fn = isFunction( fns[ tuple[ 4 ] ] ) && fns[ tuple[ 4 ] ]; + var fn = typeof fns[ tuple[ 4 ] ] === "function" && + fns[ tuple[ 4 ] ]; // deferred.progress(function() { bind to newDefer or newDefer.notify }) // deferred.done(function() { bind to newDefer or newDefer.resolve }) // deferred.fail(function() { bind to newDefer or newDefer.reject }) deferred[ tuple[ 1 ] ]( function() { var returned = fn && fn.apply( this, arguments ); - if ( returned && isFunction( returned.promise ) ) { + if ( returned && typeof returned.promise === "function" ) { returned.promise() .progress( newDefer.notify ) .done( newDefer.resolve ) @@ -143,7 +140,7 @@ jQuery.extend( { returned.then; // Handle a returned thenable - if ( isFunction( then ) ) { + if ( typeof then === "function" ) { // Special processors (notify) just wait for resolution if ( special ) { @@ -239,7 +236,7 @@ jQuery.extend( { resolve( 0, newDefer, - isFunction( onProgress ) ? + typeof onProgress === "function" ? onProgress : Identity, newDefer.notifyWith @@ -251,7 +248,7 @@ jQuery.extend( { resolve( 0, newDefer, - isFunction( onFulfilled ) ? + typeof onFulfilled === "function" ? onFulfilled : Identity ) @@ -262,7 +259,7 @@ jQuery.extend( { resolve( 0, newDefer, - isFunction( onRejected ) ? + typeof onRejected === "function" ? onRejected : Thrower ) @@ -380,7 +377,7 @@ jQuery.extend( { // Use .then() to unwrap secondary thenables (cf. gh-3000) if ( master.state() === "pending" || - isFunction( resolveValues[ i ] && resolveValues[ i ].then ) ) { + typeof( resolveValues[ i ] && resolveValues[ i ].then ) === "function" ) { return master.then(); } diff --git a/src/deferred/exceptionHook.js b/src/deferred/exceptionHook.js index 6dbdc8520..f6faf4123 100644 --- a/src/deferred/exceptionHook.js +++ b/src/deferred/exceptionHook.js @@ -11,10 +11,12 @@ var rerrorNames = /^(Eval|Internal|Range|Reference|Syntax|Type|URI)Error$/; jQuery.Deferred.exceptionHook = function( error, stack ) { - // Support: IE 8 - 9 only - // Console exists when dev tools are open, which can happen at any time - if ( window.console && window.console.warn && error && rerrorNames.test( error.name ) ) { - window.console.warn( "jQuery.Deferred exception: " + error.message, error.stack, stack ); + if ( error && rerrorNames.test( error.name ) ) { + window.console.warn( + "jQuery.Deferred exception: " + error.message, + error.stack, + stack + ); } }; diff --git a/src/deprecated.js b/src/deprecated.js index ecdf9f450..10d708ce2 100644 --- a/src/deprecated.js +++ b/src/deprecated.js @@ -3,12 +3,11 @@ define( [ "./core/nodeName", "./core/toType", "./css/cssCamelCase", - "./var/isFunction", "./var/isWindow", "./var/slice", "./event/alias" -], function( jQuery, nodeName, toType, cssCamelCase, isFunction, isWindow, slice ) { +], function( jQuery, nodeName, toType, cssCamelCase, isWindow, slice ) { "use strict"; @@ -48,7 +47,7 @@ jQuery.proxy = function( fn, context ) { // Quick check to determine if target is callable, in the spec // this throws a TypeError, but we will just return undefined. - if ( !isFunction( fn ) ) { + if ( typeof fn !== "function" ) { return undefined; } diff --git a/src/effects.js b/src/effects.js index c9332f7d7..147aa065f 100644 --- a/src/effects.js +++ b/src/effects.js @@ -1,7 +1,6 @@ define( [ "./core", "./var/document", - "./var/isFunction", "./var/rcssNum", "./var/rnothtmlwhite", "./css/var/cssExpand", @@ -19,7 +18,7 @@ define( [ "./manipulation", "./css", "./effects/Tween" -], function( jQuery, document, isFunction, rcssNum, rnothtmlwhite, cssExpand, +], function( jQuery, document, rcssNum, rnothtmlwhite, cssExpand, isHiddenWithinTree, swap, adjustCSS, cssCamelCase, dataPriv, showHide ) { "use strict"; @@ -150,7 +149,7 @@ function defaultPrefilter( elem, props, opts ) { // Restrict "overflow" and "display" styles during box animations if ( isBox && elem.nodeType === 1 ) { - // Support: IE <=9 - 11, Edge 12 - 15 + // Support: IE <=9 - 11+, Edge 12 - 18+ // Record all 3 overflow attributes because IE does not infer the shorthand // from identically-valued overflowX and overflowY and Edge just mirrors // the overflowX value there. @@ -310,10 +309,7 @@ function Animation( elem, properties, options ) { var currentTime = fxNow || createFxNow(), remaining = Math.max( 0, animation.startTime + animation.duration - currentTime ), - // Support: Android 2.3 only - // Archaic crash bug won't allow us to use `1 - ( 0.5 || 0 )` (#12497) - temp = remaining / animation.duration || 0, - percent = 1 - temp, + percent = 1 - ( remaining / animation.duration || 0 ), index = 0, length = animation.tweens.length; @@ -386,7 +382,7 @@ function Animation( elem, properties, options ) { for ( ; index < length; index++ ) { result = Animation.prefilters[ index ].call( animation, elem, props, animation.opts ); if ( result ) { - if ( isFunction( result.stop ) ) { + if ( typeof result.stop === "function" ) { jQuery._queueHooks( animation.elem, animation.opts.queue ).stop = result.stop.bind( result ); } @@ -396,7 +392,7 @@ function Animation( elem, properties, options ) { jQuery.map( props, createTween, animation ); - if ( isFunction( animation.opts.start ) ) { + if ( typeof animation.opts.start === "function" ) { animation.opts.start.call( elem, animation ); } @@ -429,7 +425,7 @@ jQuery.Animation = jQuery.extend( Animation, { }, tweener: function( props, callback ) { - if ( isFunction( props ) ) { + if ( typeof props === "function" ) { callback = props; props = [ "*" ]; } else { @@ -461,9 +457,9 @@ jQuery.Animation = jQuery.extend( Animation, { jQuery.speed = function( speed, easing, fn ) { var opt = speed && typeof speed === "object" ? jQuery.extend( {}, speed ) : { complete: fn || !fn && easing || - isFunction( speed ) && speed, + typeof speed === "function" && speed, duration: speed, - easing: fn && easing || easing && !isFunction( easing ) && easing + easing: fn && easing || easing && typeof easing !== "function" && easing }; // Go to the end state if fx are off @@ -490,7 +486,7 @@ jQuery.speed = function( speed, easing, fn ) { opt.old = opt.complete; opt.complete = function() { - if ( isFunction( opt.old ) ) { + if ( typeof opt.old === "function" ) { opt.old.call( this ); } diff --git a/src/effects/Tween.js b/src/effects/Tween.js index f8c847f97..0c5fe67d3 100644 --- a/src/effects/Tween.js +++ b/src/effects/Tween.js @@ -98,16 +98,6 @@ Tween.propHooks = { } }; -// Support: IE <=9 only -// Panic based approach to setting things on disconnected nodes -Tween.propHooks.scrollTop = Tween.propHooks.scrollLeft = { - set: function( tween ) { - if ( tween.elem.nodeType && tween.elem.parentNode ) { - tween.elem[ tween.prop ] = tween.now; - } - } -}; - jQuery.easing = { linear: function( p ) { return p; diff --git a/src/event.js b/src/event.js index 3ff11ad0b..405d176a0 100644 --- a/src/event.js +++ b/src/event.js @@ -2,7 +2,6 @@ define( [ "./core", "./var/document", "./var/documentElement", - "./var/isFunction", "./var/rnothtmlwhite", "./var/rcheckableType", "./var/slice", @@ -11,7 +10,7 @@ define( [ "./core/init", "./selector" -], function( jQuery, document, documentElement, isFunction, rnothtmlwhite, +], function( jQuery, document, documentElement, rnothtmlwhite, rcheckableType, slice, dataPriv, nodeName ) { "use strict"; @@ -36,16 +35,7 @@ function returnFalse() { // (focus and blur are always synchronous in other supported browsers, // this just defines when we can count on it). function expectSync( elem, type ) { - return ( elem === safeActiveElement() ) === ( type === "focus" ); -} - -// Support: IE <=9 only -// Accessing document.activeElement can throw unexpectedly -// https://bugs.jquery.com/ticket/13393 -function safeActiveElement() { - try { - return document.activeElement; - } catch ( err ) { } + return ( elem === document.activeElement ) === ( type === "focus" ); } function on( elem, types, selector, data, fn, one ) { @@ -379,14 +369,10 @@ jQuery.event = { // Find delegate handlers if ( delegateCount && - // Support: IE <=9 - // Black-hole SVG <use> instance trees (trac-13180) - cur.nodeType && - - // Support: Firefox <=42 + // Support: Firefox <=42 - 66+ // Suppress spec-violating clicks indicating a non-primary pointer button (trac-3861) // https://www.w3.org/TR/DOM-Level-3-Events/#event-type-click - // Support: IE 11 only + // Support: IE 11+ // ...but not arrow key "clicks" of radio inputs, which can have `button` -1 (gh-2343) !( event.type === "click" && event.button >= 1 ) ) { @@ -433,7 +419,7 @@ jQuery.event = { enumerable: true, configurable: true, - get: isFunction( hook ) ? + get: typeof hook === "function" ? function() { if ( this.originalEvent ) { return hook( this.originalEvent ); @@ -519,8 +505,9 @@ jQuery.event = { beforeunload: { postDispatch: function( event ) { - // Support: Firefox 20+ - // Firefox doesn't alert if the returnValue field is not set. + // Support: Chrome <=73+ + // Chrome doesn't alert on `event.preventDefault()` + // as the standard mandates. if ( event.result !== undefined && event.originalEvent ) { event.originalEvent.returnValue = event.result; } @@ -638,21 +625,12 @@ jQuery.Event = function( src, props ) { // Events bubbling up the document may have been marked as prevented // by a handler lower down the tree; reflect the correct value. - this.isDefaultPrevented = src.defaultPrevented || - src.defaultPrevented === undefined && - - // Support: Android <=2.3 only - src.returnValue === false ? + this.isDefaultPrevented = src.defaultPrevented ? returnTrue : returnFalse; // Create target properties - // Support: Safari <=6 - 7 only - // Target should not be a text node (#504, #13143) - this.target = ( src.target && src.target.nodeType === 3 ) ? - src.target.parentNode : - src.target; - + this.target = src.target; this.currentTarget = src.currentTarget; this.relatedTarget = src.relatedTarget; @@ -805,11 +783,6 @@ jQuery.each( { focus: "focusin", blur: "focusout" }, function( type, delegateTyp // Create mouseenter/leave events using mouseover/out and event-time checks // so that event delegation works in jQuery. // Do the same for pointerenter/pointerleave and pointerover/pointerout -// -// Support: Safari 7 only -// Safari sends mouseenter too often; see: -// https://bugs.chromium.org/p/chromium/issues/detail?id=470258 -// for the description of the bug (it existed in older Chrome versions as well). jQuery.each( { mouseenter: "mouseover", mouseleave: "mouseout", diff --git a/src/event/trigger.js b/src/event/trigger.js index cf40b4faa..39f641b70 100644 --- a/src/event/trigger.js +++ b/src/event/trigger.js @@ -4,10 +4,9 @@ define( [ "../data/var/dataPriv", "../data/var/acceptData", "../var/hasOwn", - "../var/isFunction", "../var/isWindow", "../event" -], function( jQuery, document, dataPriv, acceptData, hasOwn, isFunction, isWindow ) { +], function( jQuery, document, dataPriv, acceptData, hasOwn, isWindow ) { "use strict"; @@ -129,7 +128,7 @@ jQuery.extend( jQuery.event, { // Call a native DOM method on the target with the same name as the event. // Don't do default actions on window, that's where global variables be (#6170) - if ( ontype && isFunction( elem[ type ] ) && !isWindow( elem ) ) { + if ( ontype && typeof elem[ type ] === "function" && !isWindow( elem ) ) { // Don't re-trigger an onFOO event when we call its FOO() method tmp = elem[ ontype ]; diff --git a/src/manipulation.js b/src/manipulation.js index ab19d8b3c..fb10ef5c2 100644 --- a/src/manipulation.js +++ b/src/manipulation.js @@ -2,7 +2,6 @@ define( [ "./core", "./core/isAttached", "./var/concat", - "./var/isFunction", "./var/push", "./var/rcheckableType", "./core/access", @@ -24,7 +23,7 @@ define( [ "./traversing", "./selector", "./event" -], function( jQuery, isAttached, concat, isFunction, push, rcheckableType, +], function( jQuery, isAttached, concat, push, rcheckableType, access, rtagName, rscriptType, wrapMap, getAll, setGlobalEval, buildFragment, support, dataPriv, dataUser, acceptData, DOMEval, nodeName ) { @@ -40,13 +39,11 @@ var /* eslint-enable */ - // Support: IE <=10 - 11, Edge 12 - 13 only + // Support: IE <=10 - 11+, Edge 12 - 13 only // In IE/Edge using regex groups here causes severe slowdowns. // See https://connect.microsoft.com/IE/feedback/details/1736512/ rnoInnerhtml = /<script|<style|<link/i, - // checked="checked" or checked - rchecked = /checked\s*(?:[^=]|=\s*.checked.)/i, rcleanScript = /^\s*<!(?:\[CDATA\[|--)|(?:\]\]|--)>\s*$/g; // Prefer a tbody over its parent table for containing new rows @@ -109,20 +106,6 @@ function cloneCopyEvent( src, dest ) { } } -// Fix IE bugs, see support tests -function fixInput( src, dest ) { - var nodeName = dest.nodeName.toLowerCase(); - - // Fails to persist the checked state of a cloned checkbox or radio button. - if ( nodeName === "input" && rcheckableType.test( src.type ) ) { - dest.checked = src.checked; - - // Fails to return the selected option to the default selected state when cloning options - } else if ( nodeName === "input" || nodeName === "textarea" ) { - dest.defaultValue = src.defaultValue; - } -} - function domManip( collection, args, callback, ignored ) { // Flatten any nested arrays @@ -133,17 +116,12 @@ function domManip( collection, args, callback, ignored ) { l = collection.length, iNoClone = l - 1, value = args[ 0 ], - valueIsFunction = isFunction( value ); + valueIsFunction = typeof value === "function"; - // We can't cloneNode fragments that contain checked, in WebKit - if ( valueIsFunction || - ( l > 1 && typeof value === "string" && - !support.checkClone && rchecked.test( value ) ) ) { + if ( valueIsFunction ) { return collection.each( function( index ) { var self = collection.eq( index ); - if ( valueIsFunction ) { - args[ 0 ] = value.call( this, index, self.html() ); - } + args[ 0 ] = value.call( this, index, self.html() ); domManip( self, args, callback, ignored ); } ); } @@ -172,9 +150,6 @@ function domManip( collection, args, callback, ignored ) { // Keep references to cloned scripts for later restoration if ( hasScripts ) { - - // Support: Android <=4.0 only, PhantomJS 1 only - // push.apply(_, arraylike) throws on ancient WebKit jQuery.merge( scripts, getAll( node, "script" ) ); } } @@ -255,7 +230,13 @@ jQuery.extend( { srcElements = getAll( elem ); for ( i = 0, l = srcElements.length; i < l; i++ ) { - fixInput( srcElements[ i ], destElements[ i ] ); + + // Support: IE <=11+ + // IE fails to set the defaultValue to the correct value when + // cloning other types of input fields + if ( destElements[ i ].nodeName.toLowerCase() === "textarea" ) { + destElements[ i ].defaultValue = srcElements[ i ].defaultValue; + } } } @@ -475,9 +456,6 @@ jQuery.each( { for ( ; i <= last; i++ ) { elems = i === last ? this : this.clone( true ); jQuery( insert[ i ] )[ original ]( elems ); - - // Support: Android <=4.0 only, PhantomJS 1 only - // .get() because push.apply(_, arraylike) throws on ancient WebKit push.apply( ret, elems.get() ); } diff --git a/src/manipulation/buildFragment.js b/src/manipulation/buildFragment.js index 40c2ed1dc..01dcff6e5 100644 --- a/src/manipulation/buildFragment.js +++ b/src/manipulation/buildFragment.js @@ -27,9 +27,6 @@ function buildFragment( elems, context, scripts, selection, ignored ) { // Add nodes directly if ( toType( elem ) === "object" ) { - - // Support: Android <=4.0 only, PhantomJS 1 only - // push.apply(_, arraylike) throws on ancient WebKit jQuery.merge( nodes, elem.nodeType ? [ elem ] : elem ); // Convert non-html into a text node @@ -51,8 +48,6 @@ function buildFragment( elems, context, scripts, selection, ignored ) { tmp = tmp.lastChild; } - // Support: Android <=4.0 only, PhantomJS 1 only - // push.apply(_, arraylike) throws on ancient WebKit jQuery.merge( nodes, tmp.childNodes ); // Remember the top-level container diff --git a/src/manipulation/getAll.js b/src/manipulation/getAll.js index fede6c78a..89634d694 100644 --- a/src/manipulation/getAll.js +++ b/src/manipulation/getAll.js @@ -7,7 +7,7 @@ define( [ function getAll( context, tag ) { - // Support: IE <=9 - 11 only + // Support: IE <=9 - 11+ // Use typeof to avoid zero-argument method invocation on host objects (#15151) var ret; diff --git a/src/manipulation/support.js b/src/manipulation/support.js index 4a5d9af4c..f2ff88e17 100644 --- a/src/manipulation/support.js +++ b/src/manipulation/support.js @@ -10,21 +10,14 @@ define( [ div = fragment.appendChild( document.createElement( "div" ) ), input = document.createElement( "input" ); - // Support: Android 4.0 - 4.3 only - // Check state lost if the name is set (#11217) // Support: Windows Web Apps (WWA) // `name` and `type` must use .setAttribute for WWA (#14901) input.setAttribute( "type", "radio" ); input.setAttribute( "checked", "checked" ); - input.setAttribute( "name", "t" ); div.appendChild( input ); - // Support: Android <=4.1 only - // Older WebKit doesn't clone checked state correctly in fragments - support.checkClone = div.cloneNode( true ).cloneNode( true ).lastChild.checked; - - // Support: IE <=11 only + // Support: IE <=11+ // Make sure textarea (and checkbox) defaultValue is properly cloned div.innerHTML = "<textarea>x</textarea>"; support.noCloneChecked = !!div.cloneNode( true ).lastChild.defaultValue; diff --git a/src/manipulation/wrapMap.js b/src/manipulation/wrapMap.js index 1f446f7d7..065225928 100644 --- a/src/manipulation/wrapMap.js +++ b/src/manipulation/wrapMap.js @@ -5,11 +5,10 @@ define( function() { // We have to close these tags to support XHTML (#13200) var wrapMap = { - // Support: IE <=9 only - option: [ 1, "<select multiple='multiple'>", "</select>" ], - + // Table parts need to be wrapped with `<table>` or they're + // stripped to their contents when put in a div. // XHTML parsers do not magically insert elements in the - // same way that tag soup parsers do. So we cannot shorten + // same way that tag soup parsers do, so we cannot shorten // this by omitting <tbody> or other required elements. thead: [ 1, "<table>", "</table>" ], col: [ 2, "<table><colgroup>", "</colgroup></table>" ], @@ -19,9 +18,6 @@ var wrapMap = { _default: [ 0, "", "" ] }; -// Support: IE <=9 only -wrapMap.optgroup = wrapMap.option; - wrapMap.tbody = wrapMap.tfoot = wrapMap.colgroup = wrapMap.caption = wrapMap.thead; wrapMap.th = wrapMap.td; diff --git a/src/offset.js b/src/offset.js index 83b1c3a53..531b75ff2 100644 --- a/src/offset.js +++ b/src/offset.js @@ -3,17 +3,13 @@ define( [ "./core/access", "./var/document", "./var/documentElement", - "./var/isFunction", "./css/var/rnumnonpx", "./css/curCSS", - "./css/addGetHookIf", - "./css/support", "./var/isWindow", "./core/init", "./css", "./selector" // contains -], function( jQuery, access, document, documentElement, isFunction, rnumnonpx, - curCSS, addGetHookIf, support, isWindow ) { +], function( jQuery, access, document, documentElement, rnumnonpx, curCSS, isWindow ) { "use strict"; @@ -47,7 +43,7 @@ jQuery.offset = { curLeft = parseFloat( curCSSLeft ) || 0; } - if ( isFunction( options ) ) { + if ( typeof options === "function" ) { // Use jQuery.extend here to allow modification of coordinates argument (gh-1848) options = options.call( elem, i, jQuery.extend( {}, curOffset ) ); @@ -91,7 +87,7 @@ jQuery.fn.extend( { } // Return zeros for disconnected and hidden (display: none) elements (gh-2310) - // Support: IE <=11 only + // Support: IE <=11+ // Running getBoundingClientRect on a // disconnected node in IE throws an error if ( !elem.getClientRects().length ) { @@ -208,26 +204,5 @@ jQuery.each( { scrollLeft: "pageXOffset", scrollTop: "pageYOffset" }, function( }; } ); -// Support: Safari <=7 - 9.1, Chrome <=37 - 49 -// Add the top/left cssHooks using jQuery.fn.position -// Webkit bug: https://bugs.webkit.org/show_bug.cgi?id=29084 -// Blink bug: https://bugs.chromium.org/p/chromium/issues/detail?id=589347 -// getComputedStyle returns percent when specified for top/left/bottom/right; -// rather than make the css module depend on the offset module, just check for it here -jQuery.each( [ "top", "left" ], function( i, prop ) { - jQuery.cssHooks[ prop ] = addGetHookIf( support.pixelPosition, - function( elem, computed ) { - if ( computed ) { - computed = curCSS( elem, prop ); - - // If curCSS returns percentage, fallback to offset - return rnumnonpx.test( computed ) ? - jQuery( elem ).position()[ prop ] + "px" : - computed; - } - } - ); -} ); - return jQuery; } ); diff --git a/src/selector-native.js b/src/selector-native.js index da837a004..20c37f4fa 100644 --- a/src/selector-native.js +++ b/src/selector-native.js @@ -35,11 +35,10 @@ define( [ var hasDuplicate, sortInput, sortStable = jQuery.expando.split( "" ).sort( sortOrder ).join( "" ) === jQuery.expando, - matches = documentElement.matches || - documentElement.webkitMatchesSelector || - documentElement.mozMatchesSelector || - documentElement.oMatchesSelector || - documentElement.msMatchesSelector, + + // Support: IE 9 - 11+ + // IE requires a prefix. + matches = documentElement.matches || documentElement.msMatchesSelector, // CSS string/identifier serialization // https://drafts.csswg.org/cssom/#common-serializing-idioms diff --git a/src/selector-sizzle.js b/src/selector-sizzle.js index ff7bc70ee..1a30d7ded 100644 --- a/src/selector-sizzle.js +++ b/src/selector-sizzle.js @@ -10,6 +10,7 @@ jQuery.expr = Sizzle.selectors; // Deprecated jQuery.expr[ ":" ] = jQuery.expr.pseudos; + jQuery.uniqueSort = jQuery.unique = Sizzle.uniqueSort; jQuery.text = Sizzle.getText; jQuery.isXMLDoc = Sizzle.isXML; diff --git a/src/serialize.js b/src/serialize.js index d8a9a36a4..0cf5ddb44 100644 --- a/src/serialize.js +++ b/src/serialize.js @@ -2,11 +2,10 @@ define( [ "./core", "./core/toType", "./var/rcheckableType", - "./var/isFunction", "./core/init", "./traversing", // filter "./attributes/prop" -], function( jQuery, toType, rcheckableType, isFunction ) { +], function( jQuery, toType, rcheckableType ) { "use strict"; @@ -62,7 +61,7 @@ jQuery.param = function( a, traditional ) { add = function( key, valueOrFunction ) { // If value is a function, invoke it and use its return value - var value = isFunction( valueOrFunction ) ? + var value = typeof valueOrFunction === "function" ? valueOrFunction() : valueOrFunction; diff --git a/src/traversing.js b/src/traversing.js index 426d5b6ea..18b964a49 100644 --- a/src/traversing.js +++ b/src/traversing.js @@ -149,7 +149,7 @@ jQuery.each( { return elem.contentDocument; } - // Support: IE 9 - 11 only, iOS 7 only, Android Browser <=4.3 only + // Support: IE 9 - 11+ // Treat the template element as a regular one in browsers that // don't support it. if ( nodeName( elem, "template" ) ) { diff --git a/src/traversing/findFilter.js b/src/traversing/findFilter.js index 268dad796..2f526b713 100644 --- a/src/traversing/findFilter.js +++ b/src/traversing/findFilter.js @@ -1,16 +1,15 @@ define( [ "../core", "../var/indexOf", - "../var/isFunction", "./var/rneedsContext", "../selector" -], function( jQuery, indexOf, isFunction, rneedsContext ) { +], function( jQuery, indexOf, rneedsContext ) { "use strict"; // Implement the identical functionality for filter and not function winnow( elements, qualifier, not ) { - if ( isFunction( qualifier ) ) { + if ( typeof qualifier === "function" ) { return jQuery.grep( elements, function( elem, i ) { return !!qualifier.call( elem, i, elem ) !== not; } ); diff --git a/src/var/isFunction.js b/src/var/isFunction.js deleted file mode 100644 index dad662e4f..000000000 --- a/src/var/isFunction.js +++ /dev/null @@ -1,13 +0,0 @@ -define( function() { - "use strict"; - - return function isFunction( obj ) { - - // Support: Chrome <=57, Firefox <=52 - // In some browsers, typeof returns "function" for HTML <object> elements - // (i.e., `typeof document.createElement( "object" ) === "function"`). - // We don't want to classify *any* DOM node as a function. - return typeof obj === "function" && typeof obj.nodeType !== "number"; - }; - -} ); diff --git a/src/var/trim.js b/src/var/trim.js new file mode 100644 index 000000000..a5e75af36 --- /dev/null +++ b/src/var/trim.js @@ -0,0 +1,5 @@ +define( function() { + "use strict"; + + return "".trim; +} ); diff --git a/src/wrap.js b/src/wrap.js index 41b716f9f..a42c04da7 100644 --- a/src/wrap.js +++ b/src/wrap.js @@ -1,10 +1,9 @@ define( [ "./core", - "./var/isFunction", "./core/init", "./manipulation", // clone "./traversing" // parent, contents -], function( jQuery, isFunction ) { +], function( jQuery ) { "use strict"; @@ -13,7 +12,7 @@ jQuery.fn.extend( { var wrap; if ( this[ 0 ] ) { - if ( isFunction( html ) ) { + if ( typeof html === "function" ) { html = html.call( this[ 0 ] ); } @@ -39,7 +38,7 @@ jQuery.fn.extend( { }, wrapInner: function( html ) { - if ( isFunction( html ) ) { + if ( typeof html === "function" ) { return this.each( function( i ) { jQuery( this ).wrapInner( html.call( this, i ) ); } ); @@ -59,7 +58,7 @@ jQuery.fn.extend( { }, wrap: function( html ) { - var htmlIsFunction = isFunction( html ); + var htmlIsFunction = typeof html === "function"; return this.each( function( i ) { jQuery( this ).wrapAll( htmlIsFunction ? html.call( this, i ) : html ); diff --git a/src/wrapper.js b/src/wrapper.js index 0af1f4964..7af4ad75e 100644 --- a/src/wrapper.js +++ b/src/wrapper.js @@ -40,10 +40,6 @@ // Pass this if window is not defined yet } )( typeof window !== "undefined" ? window : this, function( window, noGlobal ) { -// Edge <= 12 - 13+, Firefox <=18 - 45+, IE 10 - 11, Safari 5.1 - 9+, iOS 6 - 9.1 -// throw exceptions when non-strict code (e.g., ASP.NET 4.5) accesses strict mode -// arguments.callee.caller (trac-13335). But as of jQuery 3.0 (2016), strict mode should be common -// enough that all such attempts are guarded in a try block. "use strict"; // @CODE diff --git a/test/data/core/cc_on.html b/test/data/core/cc_on.html deleted file mode 100644 index 5db18916c..000000000 --- a/test/data/core/cc_on.html +++ /dev/null @@ -1,23 +0,0 @@ -<!DOCTYPE html> -<html lang="en"> -<head> - <meta http-equiv="Content-Type" content="text/html; charset=utf-8"> - <script> - var cc_on = false, - errors = []; -/*@cc_on - cc_on = true; -@*/ - window.onerror = function( errorMessage, filePath, lineNumber ) { - errors.push( errorMessage ); - }; - </script> - <script src="../../jquery.js"></script> - <script src="../iframeTest.js"></script> -</head> -<body> - <script> - startIframeTest( cc_on, errors ); - </script> -</body> -</html> diff --git a/test/data/testinit.js b/test/data/testinit.js index e1d81c5c7..eb4901062 100644 --- a/test/data/testinit.js +++ b/test/data/testinit.js @@ -1,5 +1,7 @@ /* eslint no-multi-str: "off" */ +"use strict"; + var FILEPATH = "/test/data/testinit.js", activeScript = [].slice.call( document.getElementsByTagName( "script" ), -1 )[ 0 ], parentUrl = activeScript && activeScript.src ? @@ -100,43 +102,9 @@ this.createDashboardXML = function() { return jQuery.parseXML( string ); }; -this.createWithFriesXML = function() { - var string = "<?xml version='1.0' encoding='UTF-8'?> \ - <soap:Envelope xmlns:soap='http://schemas.xmlsoap.org/soap/envelope/' \ - xmlns:xsd='http://www.w3.org/2001/XMLSchema' \ - xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance'> \ - <soap:Body> \ - <jsconf xmlns='http://{{ externalHost }}/ns1'> \ - <response xmlns:ab='http://{{ externalHost }}/ns2'> \ - <meta> \ - <component id='seite1' class='component'> \ - <properties xmlns:cd='http://{{ externalHost }}/ns3'> \ - <property name='prop1'> \ - <thing /> \ - <value>1</value> \ - </property> \ - <property name='prop2'> \ - <thing att='something' /> \ - </property> \ - <foo_bar>foo</foo_bar> \ - </properties> \ - </component> \ - </meta> \ - </response> \ - </jsconf> \ - </soap:Body> \ - </soap:Envelope>"; - - return jQuery.parseXML( string.replace( /\{\{\s*externalHost\s*\}\}/g, externalHost ) ); -}; - this.createXMLFragment = function() { - var xml, frag; - if ( window.ActiveXObject ) { - xml = new window.ActiveXObject( "msxml2.domdocument" ); - } else { + var frag, xml = document.implementation.createDocument( "", "", null ); - } if ( xml ) { frag = xml.createElement( "data" ); @@ -314,10 +282,9 @@ this.loadTests = function() { require( [ parentUrl + "test/data/testrunner.js" ], function() { var i = 0, tests = [ - // A special module with basic tests, meant for - // not fully supported environments like Android 2.3, - // jsdom or PhantomJS. We run it everywhere, though, - // to make sure tests are not broken. + // 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. "unit/basic.js", "unit/core.js", @@ -351,7 +318,6 @@ this.loadTests = function() { if ( !QUnit.basicTests || i === 1 ) { require( [ parentUrl + "test/" + dep ], loadDep ); - // Support: Android 2.3 only // When running basic tests, replace other modules with dummies to avoid overloading // impaired clients. } else { diff --git a/test/data/testrunner.js b/test/data/testrunner.js index 39000c33b..c4fa5d378 100644 --- a/test/data/testrunner.js +++ b/test/data/testrunner.js @@ -1,5 +1,7 @@ ( function() { +"use strict"; + // Store the old counts so that we only assert on tests that have actually leaked, // instead of asserting every time a test has leaked sometime in the past var oldCacheLength = 0, diff --git a/test/unit/ajax.js b/test/unit/ajax.js index 7bf3f686b..9b151988d 100644 --- a/test/unit/ajax.js +++ b/test/unit/ajax.js @@ -120,9 +120,7 @@ QUnit.module( "ajax", { assert.ok( true, "success" ); }, fail: function() { - if ( jQuery.support.cors === false ) { - assert.ok( true, "fail" ); - } + assert.ok( false, "fail" ); }, complete: function() { assert.ok( true, "complete" ); @@ -269,13 +267,12 @@ QUnit.module( "ajax", { "Nullable": null, "undefined": undefined - // Support: IE 9 - 11, Edge 12 - 14 only + // Support: IE 9 - 11+, Edge 12 - 14 only // Not all browsers allow empty-string headers //"Empty": "" }, success: function( data, _, xhr ) { var i, emptyHeader, - isAndroid = /android 4\.[0-3]/i.test( navigator.userAgent ), requestHeaders = jQuery.extend( this.headers, { "ajax-send": "test" } ), @@ -296,25 +293,8 @@ QUnit.module( "ajax", { assert.strictEqual( emptyHeader, "", "Empty header received" ); } assert.strictEqual( xhr.getResponseHeader( "Sample-Header2" ), "Hello World 2", "Second sample header received" ); - - if ( isAndroid ) { - // Support: Android 4.0-4.3 only - // Android Browser only returns the last value for each header - // so there's no way for jQuery get all parts. - assert.ok( true, "Android doesn't support repeated header names" ); - } else { - assert.strictEqual( xhr.getResponseHeader( "List-Header" ), "Item 1, Item 2", "List header received" ); - } - - if ( isAndroid && QUnit.isSwarm ) { - // Support: Android 4.0-4.3 on BrowserStack only - // Android Browser versions provided by BrowserStack fail this test - // while locally fired emulators don't, even when they connect - // to TestSwarm. Just skip the test there to avoid a red build. - assert.ok( true, "BrowserStack's Android fails the \"prototype collision (constructor)\" test" ); - } else { - assert.strictEqual( xhr.getResponseHeader( "constructor" ), "prototype collision (constructor)", "constructor header received" ); - } + assert.strictEqual( xhr.getResponseHeader( "List-Header" ), "Item 1, Item 2", "List header received" ); + assert.strictEqual( xhr.getResponseHeader( "constructor" ), "prototype collision (constructor)", "constructor header received" ); assert.strictEqual( xhr.getResponseHeader( "__proto__" ), null, "Undefined __proto__ header not received" ); } }; @@ -553,47 +533,41 @@ QUnit.module( "ajax", { }; } ); - if ( !/android 4\.0/i.test( navigator.userAgent ) ) { - ajaxTest( "jQuery.ajax() - native abort", 2, function( assert ) { - return { - url: url( "mock.php?action=wait&wait=1" ), - xhr: function() { - var xhr = new window.XMLHttpRequest(); - setTimeout( function() { - xhr.abort(); - }, 100 ); - return xhr; - }, - error: function( xhr, msg ) { - assert.strictEqual( msg, "error", "Native abort triggers error callback" ); - }, - complete: function() { - assert.ok( true, "complete" ); - } - }; - } ); - } + ajaxTest( "jQuery.ajax() - native abort", 2, function( assert ) { + return { + url: url( "mock.php?action=wait&wait=1" ), + xhr: function() { + var xhr = new window.XMLHttpRequest(); + setTimeout( function() { + xhr.abort(); + }, 100 ); + return xhr; + }, + error: function( xhr, msg ) { + assert.strictEqual( msg, "error", "Native abort triggers error callback" ); + }, + complete: function() { + assert.ok( true, "complete" ); + } + }; + } ); - // Support: Android <= 4.0 - 4.3 only - // Android 4.0-4.3 does not have ontimeout on an xhr - if ( "ontimeout" in new window.XMLHttpRequest() ) { - ajaxTest( "jQuery.ajax() - native timeout", 2, function( assert ) { - return { - url: url( "mock.php?action=wait&wait=1" ), - xhr: function() { - var xhr = new window.XMLHttpRequest(); - xhr.timeout = 1; - return xhr; - }, - error: function( xhr, msg ) { - assert.strictEqual( msg, "error", "Native timeout triggers error callback" ); - }, - complete: function() { - assert.ok( true, "complete" ); - } - }; - } ); - } + ajaxTest( "jQuery.ajax() - native timeout", 2, function( assert ) { + return { + url: url( "mock.php?action=wait&wait=1" ), + xhr: function() { + var xhr = new window.XMLHttpRequest(); + xhr.timeout = 1; + return xhr; + }, + error: function( xhr, msg ) { + assert.strictEqual( msg, "error", "Native timeout triggers error callback" ); + }, + complete: function() { + assert.ok( true, "complete" ); + } + }; + } ); ajaxTest( "jQuery.ajax() - events with context", 12, function( assert ) { var context = document.createElement( "div" ); diff --git a/test/unit/basic.js b/test/unit/basic.js index bed27dcba..8b567f195 100644 --- a/test/unit/basic.js +++ b/test/unit/basic.js @@ -179,7 +179,11 @@ QUnit.test( "manipulation", function( assert ) { ".html getter/setter" ); - assert.strictEqual( elem1.append( elem2 )[ 0 ].childNodes[ 1 ], elem2[ 0 ], ".append" ); + assert.strictEqual( + elem1.append( elem2 )[ 0 ].childNodes[ elem1[ 0 ].childNodes.length - 1 ], + elem2[ 0 ], + ".append" + ); assert.strictEqual( elem1.prepend( elem2 )[ 0 ].childNodes[ 0 ], elem2[ 0 ], ".prepend" ); child = elem1.find( "span" ); diff --git a/test/unit/core.js b/test/unit/core.js index 3cb2d3951..6c331349a 100644 --- a/test/unit/core.js +++ b/test/unit/core.js @@ -1319,22 +1319,20 @@ QUnit.test( "jQuery.parseHTML(<a href>) - gh-2965", function( assert ) { assert.ok( /\/example\.html$/.test( href ), "href is not lost after parsing anchor" ); } ); -if ( jQuery.support.createHTMLDocument ) { - QUnit.test( "jQuery.parseHTML", function( assert ) { - var done = assert.async(); - assert.expect( 1 ); +QUnit.test( "jQuery.parseHTML", function( assert ) { + var done = assert.async(); + assert.expect( 1 ); - Globals.register( "parseHTMLError" ); + Globals.register( "parseHTMLError" ); - jQuery.globalEval( "parseHTMLError = false;" ); - jQuery.parseHTML( "<img src=x onerror='parseHTMLError = true'>" ); + jQuery.globalEval( "parseHTMLError = false;" ); + jQuery.parseHTML( "<img src=x onerror='parseHTMLError = true'>" ); - window.setTimeout( function() { - assert.equal( window.parseHTMLError, false, "onerror eventhandler has not been called." ); - done(); - }, 2000 ); - } ); -} + window.setTimeout( function() { + assert.equal( window.parseHTMLError, false, "onerror eventhandler has not been called." ); + done(); + }, 2000 ); +} ); QUnit.test( "jQuery.parseXML", function( assert ) { assert.expect( 8 ); @@ -1371,30 +1369,14 @@ QUnit.test( "jQuery.parseXML", function( assert ) { } ); testIframe( - "Conditional compilation compatibility (#13274)", - "core/cc_on.html", - function( assert, jQuery, window, document, cc_on, errors ) { - assert.expect( 3 ); - assert.ok( true, "JScript conditional compilation " + ( cc_on ? "supported" : "not supported" ) ); - assert.deepEqual( errors, [], "No errors" ); - assert.ok( jQuery(), "jQuery executes" ); + "document ready when jQuery loaded asynchronously (#13655)", + "core/dynamic_ready.html", + function( assert, jQuery, window, document, ready ) { + assert.expect( 1 ); + assert.equal( true, ready, "document ready correctly fired when jQuery is loaded after DOMContentLoaded" ); } ); -// iOS7 doesn't fire the load event if the long-loading iframe gets its source reset to about:blank. -// This makes this test fail but it doesn't seem to cause any real-life problems so blacklisting -// this test there is preferred to complicating the hard-to-test core/ready code further. -if ( !/iphone os 7_/i.test( navigator.userAgent ) ) { - testIframe( - "document ready when jQuery loaded asynchronously (#13655)", - "core/dynamic_ready.html", - function( assert, jQuery, window, document, ready ) { - assert.expect( 1 ); - assert.equal( true, ready, "document ready correctly fired when jQuery is loaded after DOMContentLoaded" ); - } - ); -} - testIframe( "Tolerating alias-masked DOM properties (#14074)", "core/aliased.html", diff --git a/test/unit/css.js b/test/unit/css.js index 74daa2b2d..75b1cc7ef 100644 --- a/test/unit/css.js +++ b/test/unit/css.js @@ -641,7 +641,7 @@ QUnit.test( "show/hide detached nodes", function( assert ) { span.remove(); } ); -QUnit[ document.body.attachShadow ? "test" : "skip" ]( "show/hide shadow child nodes", function( assert ) { +QUnit[ document.body.getRootNode ? "test" : "skip" ]( "show/hide shadow child nodes", function( assert ) { assert.expect( 28 ); jQuery( "<div id='shadowHost'></div>" ).appendTo( "#qunit-fixture" ); var shadowHost = document.querySelector( "#shadowHost" ); @@ -1023,7 +1023,7 @@ QUnit[ jQuery.find.compile && jQuery.fn.toggle ? "test" : "skip" ]( "detached to "cascade-hidden element in detached tree" ); } ); -QUnit[ jQuery.find.compile && jQuery.fn.toggle && document.body.attachShadow ? "test" : "skip" ]( "shadow toggle()", function( assert ) { +QUnit[ jQuery.find.compile && jQuery.fn.toggle && document.body.getRootNode ? "test" : "skip" ]( "shadow toggle()", function( assert ) { assert.expect( 4 ); jQuery( "<div id='shadowHost'></div>" ).appendTo( "#qunit-fixture" ); var shadowHost = document.querySelector( "#shadowHost" ); @@ -1420,16 +1420,6 @@ QUnit.test( "certain css values of 'normal' should be convertable to a number, s assert.equal( typeof el.css( "fontWeight" ), "string", ".css() returns a string" ); } ); -// Support: IE 9 only -// Only run this test in IE9 -if ( document.documentMode === 9 ) { - QUnit.test( ".css('filter') returns a string in IE9, see #12537", function( assert ) { - assert.expect( 1 ); - - assert.equal( jQuery( "<div style='-ms-filter:\"progid:DXImageTransform.Microsoft.gradient(startColorstr=#FFFFFF, endColorstr=#ECECEC)\";'></div>" ).css( "filter" ), "progid:DXImageTransform.Microsoft.gradient(startColorstr=#FFFFFF, endColorstr=#ECECEC)", "IE9 returns the correct value from css('filter')." ); - } ); -} - QUnit.test( "cssHooks - expand", function( assert ) { assert.expect( 15 ); var result, @@ -1489,9 +1479,9 @@ QUnit.test( "css opacity consistency across browsers (#12685)", function( assert } ); QUnit[ jQuery.find.compile ? "test" : "skip" ]( ":visible/:hidden selectors", function( assert ) { - assert.expect( 17 ); + assert.expect( 18 ); - var $div, $table, $a; + var $div, $table, $a, $br; assert.ok( jQuery( "#nothiddendiv" ).is( ":visible" ), "Modifying CSS display: Assert element is visible" ); jQuery( "#nothiddendiv" ).css( { display: "none" } ); @@ -1513,10 +1503,8 @@ QUnit[ jQuery.find.compile ? "test" : "skip" ]( ":visible/:hidden selectors", fu $div.css( { width: 0, height: 0, overflow: "hidden" } ); assert.ok( $div.is( ":visible" ), "Div with width and height of 0 is still visible (gh-2227)" ); - // Safari 6-7 and iOS 6-7 report 0 width for br elements - // When newer browsers propagate, re-enable this test - // $br = jQuery( "<br/>" ).appendTo( "#qunit-fixture" ); - // assert.ok( $br.is( ":visible" ), "br element is visible" ); + $br = jQuery( "<br/>" ).appendTo( "#qunit-fixture" ); + assert.ok( $br.is( ":visible" ), "br element is visible" ); $table = jQuery( "#table" ); $table.html( "<tr><td style='display:none'>cell</td><td>cell</td></tr>" ); @@ -1539,11 +1527,7 @@ QUnit.test( "Keep the last style if the new one isn't recognized by the browser assert.equal( el.css( "position" ), "absolute", "The old style is kept when setting an unrecognized value" ); } ); -// Support: Edge 14 - 16 only -// Edge collapses whitespace-only values when setting a style property and -// there is no easy way for us to work around it. Just skip the test there -// and hope for the better future. -QUnit[ /\bedge\/16\./i.test( navigator.userAgent ) ? "skip" : "test" ]( +QUnit.test( "Keep the last style if the new one is a non-empty whitespace (gh-3204)", function( assert ) { assert.expect( 1 ); @@ -1648,25 +1632,14 @@ QUnit.test( } ); -// Support: IE <=10 only -// We have to jump through the hoops here in order to test work with "order" CSS property, -// that some browsers do not support. This test is not, strictly speaking, correct, -// but it's the best that we can do. -( function() { - var style = document.createElement( "div" ).style, - exist = "order" in style || "WebkitOrder" in style; - - if ( exist ) { - QUnit.test( "Don't append px to CSS \"order\" value (#14049)", function( assert ) { - assert.expect( 1 ); +QUnit.test( "Don't append px to CSS \"order\" value (#14049)", function( assert ) { + assert.expect( 1 ); - var $elem = jQuery( "<div/>" ); + var $elem = jQuery( "<div/>" ); - $elem.css( "order", 2 ); - assert.equal( $elem.css( "order" ), "2", "2 on order" ); - } ); - } -} )(); + $elem.css( "order", 2 ); + assert.equal( $elem.css( "order" ), "2", "2 on order" ); +} ); QUnit.test( "Do not throw on frame elements from css method (#15098)", function( assert ) { assert.expect( 1 ); @@ -1788,18 +1761,12 @@ QUnit.test( "Do not throw on frame elements from css method (#15098)", function( var div = jQuery( "<div>" ).appendTo( "#qunit-fixture" ), $elem = jQuery( "<div>" ).addClass( "test__customProperties" ) .appendTo( "#qunit-fixture" ), - webkit = /\bsafari\b/i.test( navigator.userAgent ) && - !/\firefox\b/i.test( navigator.userAgent ) && - !/\edge\b/i.test( navigator.userAgent ), - oldSafari = webkit && ( /\b9\.\d(\.\d+)* safari/i.test( navigator.userAgent ) || - /\b10\.0(\.\d+)* safari/i.test( navigator.userAgent ) || - /iphone os (?:9|10)_/i.test( navigator.userAgent ) ), + webkitOrBlink = /\bsafari\b/i.test( navigator.userAgent ) && + !/\bfirefox\b/i.test( navigator.userAgent ) && + !/\bedge\b/i.test( navigator.userAgent ), expected = 10; - if ( webkit ) { - expected -= 2; - } - if ( oldSafari ) { + if ( webkitOrBlink ) { expected -= 2; } assert.expect( expected ); @@ -1825,17 +1792,13 @@ QUnit.test( "Do not throw on frame elements from css method (#15098)", function( assert.equal( $elem.css( "--prop1" ), "val1", "Basic CSS custom property" ); - // Support: Safari 9.1-10.0 only - // Safari collapses whitespaces & quotes. Ignore it. - if ( !oldSafari ) { - assert.equal( $elem.css( "--prop2" ), " val2", "Preceding whitespace maintained" ); - assert.equal( $elem.css( "--prop3" ), "val3 ", "Following whitespace maintained" ); - } + assert.equal( $elem.css( "--prop2" ), " val2", "Preceding whitespace maintained" ); + assert.equal( $elem.css( "--prop3" ), "val3 ", "Following whitespace maintained" ); - // Support: Chrome 49-55, Safari 9.1-10.0 + // Support: Chrome <=49 - 73+, Safari <=9.1 - 12.1+ // Chrome treats single quotes as double ones. // Safari treats double quotes as single ones. - if ( !webkit ) { + if ( !webkitOrBlink ) { assert.equal( $elem.css( "--prop4" ), "\"val4\"", "Works with double quotes" ); assert.equal( $elem.css( "--prop5" ), "'val5'", "Works with single quotes" ); } diff --git a/test/unit/deferred.js b/test/unit/deferred.js index c704f905f..936a57524 100644 --- a/test/unit/deferred.js +++ b/test/unit/deferred.js @@ -172,7 +172,7 @@ QUnit.test( "jQuery.Deferred.catch", function( assert ) { var value1, value2, value3, defer = jQuery.Deferred(), - piped = defer[ "catch" ]( function( a, b ) { + piped = defer.catch( function( a, b ) { return a * b; } ), done = jQuery.map( new Array( 3 ), function() { return assert.async(); } ); @@ -186,18 +186,18 @@ QUnit.test( "jQuery.Deferred.catch", function( assert ) { value2 = b; } ); - defer.reject( 2, 3 )[ "catch" ]( function() { + defer.reject( 2, 3 ).catch( function() { assert.strictEqual( value1, 2, "first reject value ok" ); assert.strictEqual( value2, 3, "second reject value ok" ); assert.strictEqual( value3, 6, "result of filter ok" ); done.pop().call(); } ); - jQuery.Deferred().resolve()[ "catch" ]( function() { + jQuery.Deferred().resolve().catch( function() { assert.ok( false, "then should not be called on resolve" ); } ).then( done.pop() ); - jQuery.Deferred().reject()[ "catch" ]( jQuery.noop ).done( function( value ) { + jQuery.Deferred().reject().catch( jQuery.noop ).done( function( value ) { assert.strictEqual( value, undefined, "then fail callback can return undefined/null" ); done.pop().call(); } ); @@ -563,8 +563,7 @@ QUnit[ typeof Symbol === "function" && Symbol.toStringTag ? "test" : "skip" ]( } ); -// Test fails in IE9 but is skipped there because console is not active -QUnit[ window.console ? "test" : "skip" ]( "jQuery.Deferred.exceptionHook", function( assert ) { +QUnit.test( "jQuery.Deferred.exceptionHook", function( assert ) { assert.expect( 2 ); @@ -573,24 +572,10 @@ QUnit[ window.console ? "test" : "skip" ]( "jQuery.Deferred.exceptionHook", func oldWarn = window.console.warn; window.console.warn = function() { - - // Support: Chrome <=41 only - // Some Chrome versions newer than 30 but older than 42 display the "undefined is - // not a function" error, not mentioning the function name. This has been fixed - // in Chrome 42. Relax this test there. - // This affects our Android 5.0 & Yandex.Browser testing. - var msg = Array.prototype.join.call( arguments, " " ), - oldChromium = false; - if ( /chrome/i.test( navigator.userAgent ) ) { - oldChromium = parseInt( - navigator.userAgent.match( /chrome\/(\d+)/i )[ 1 ], 10 ) < 42; - } - if ( oldChromium ) { - assert.ok( /(?:barf|undefined)/.test( msg ), "Message (weak assertion): " + msg ); - } else { - assert.ok( /barf/.test( msg ), "Message: " + msg ); - } + var msg = Array.prototype.join.call( arguments, " " ); + assert.ok( /barf/.test( msg ), "Message: " + msg ); }; + jQuery.when( defer.then( function() { @@ -613,8 +598,7 @@ QUnit[ window.console ? "test" : "skip" ]( "jQuery.Deferred.exceptionHook", func defer.resolve(); } ); -// Test fails in IE9 but is skipped there because console is not active -QUnit[ window.console ? "test" : "skip" ]( "jQuery.Deferred.exceptionHook with stack hooks", function( assert ) { +QUnit.test( "jQuery.Deferred.exceptionHook with stack hooks", function( assert ) { assert.expect( 2 ); @@ -632,26 +616,11 @@ QUnit[ window.console ? "test" : "skip" ]( "jQuery.Deferred.exceptionHook with s }; window.console.warn = function() { - - // Support: Chrome <=41 only - // Some Chrome versions newer than 30 but older than 42 display the "undefined is - // not a function" error, not mentioning the function name. This has been fixed - // in Chrome 42. Relax this test there. - // This affects our Android 5.0 & Yandex.Browser testing. - var msg = Array.prototype.join.call( arguments, " " ), - oldChromium = false; - if ( /chrome/i.test( navigator.userAgent ) ) { - oldChromium = parseInt( - navigator.userAgent.match( /chrome\/(\d+)/i )[ 1 ], 10 ) < 42; - } - if ( oldChromium ) { - assert.ok( /(?:cough_up_hairball|undefined)/.test( msg ), - "Function mentioned (weak assertion): " + msg ); - } else { - assert.ok( /cough_up_hairball/.test( msg ), "Function mentioned: " + msg ); - } + var msg = Array.prototype.join.call( arguments, " " ); + assert.ok( /cough_up_hairball/.test( msg ), "Function mentioned: " + msg ); assert.ok( /NO STACK FOR YOU/.test( msg ), "Stack trace included: " + msg ); }; + defer.then( function() { jQuery.cough_up_hairball(); } ).then( null, function( ) { @@ -825,11 +794,7 @@ QUnit.test( "jQuery.when(nonThenable) - like Promise.resolve", function( assert assert.expect( 44 ); - var - - // Support: Android 4.0 only - // Strict mode functions invoked without .call/.apply get global-object context - defaultContext = ( function getDefaultContext() { return this; } ).call(), + var defaultContext = ( function getDefaultContext() { return this; } )(), done = assert.async( 20 ); @@ -884,9 +849,7 @@ QUnit.test( "jQuery.when(thenable) - like Promise.resolve", function( assert ) { var customToStringThen = { then: function( onFulfilled ) { - // Support: Android 4.0 only - // Strict mode functions invoked without .call/.apply get global-object context - onFulfilled.call(); + onFulfilled(); } }; if ( typeof Symbol === "function" ) { @@ -947,9 +910,7 @@ QUnit.test( "jQuery.when(thenable) - like Promise.resolve", function( assert ) { }, numCases = Object.keys( willSucceed ).length + Object.keys( willError ).length, - // Support: Android 4.0 only - // Strict mode functions invoked without .call/.apply get global-object context - defaultContext = ( function getDefaultContext() { return this; } ).call(), + defaultContext = ( function getDefaultContext() { return this; } )(), done = assert.async( numCases * 2 ); @@ -1027,9 +988,7 @@ QUnit.test( "jQuery.when(a, b) - like Promise.all", function( assert ) { rejectedStandardPromise: true }, - // Support: Android 4.0 only - // Strict mode functions invoked without .call/.apply get global-object context - defaultContext = ( function getDefaultContext() { return this; } ).call(), + defaultContext = ( function getDefaultContext() { return this; } )(), done = assert.async( 98 ); diff --git a/test/unit/dimensions.js b/test/unit/dimensions.js index 23a58523c..4a3ad5ecb 100644 --- a/test/unit/dimensions.js +++ b/test/unit/dimensions.js @@ -687,19 +687,7 @@ QUnit.test( "interaction with scrollbars (gh-3589)", function( assert ) { .css( { position: "relative" } ), $boxes = jQuery( [ plainBox[ 0 ], contentBox[ 0 ], borderBox[ 0 ], relativeBorderBox[ 0 ] ] - ).appendTo( parent ), - - // Support: IE 9 only - // Computed width seems to report content width even with "box-sizing: border-box", and - // "overflow: scroll" actually _shrinks_ the element (gh-3699). - borderBoxLoss = - borderBox.clone().css( { overflow: "auto" } ).appendTo( parent )[ 0 ].offsetWidth - - borderBox[ 0 ].offsetWidth; - - if ( borderBoxLoss > 0 ) { - borderBox[ 0 ].style.width = ( size + borderBoxLoss ) + "px"; - borderBox[ 0 ].style.height = ( size + borderBoxLoss ) + "px"; - } + ).appendTo( parent ); for ( i = 0; i < 3; i++ ) { if ( i === 1 ) { @@ -758,10 +746,9 @@ QUnit.test( "outerWidth/Height for table cells and textarea with border-box in I $secondTh = jQuery( "<th style='width: 190px;padding: 5px' />" ), $thirdTh = jQuery( "<th style='width: 180px;padding: 5px' />" ), - // Support: Firefox 63, Edge 16-17, Android 8, iOS 7-11 - // These browsers completely ignore the border-box and height settings - // The computed height is instead just line-height + border - // Either way, what we're doing in css.js is correct + // Most browsers completely ignore the border-box and height settings. + // The computed height is instead just line-height + border. + // Either way, what we're doing in css.js is correct. $td = jQuery( "<td style='height: 20px;padding: 5px;border: 1px solid;line-height:18px'>text</td>" ), $tbody = jQuery( "<tbody />" ).appendTo( $table ), @@ -775,18 +762,7 @@ QUnit.test( "outerWidth/Height for table cells and textarea with border-box in I assert.strictEqual( $firstTh.outerWidth(), 200, "First th has outerWidth 200." ); assert.strictEqual( $secondTh.outerWidth(), 200, "Second th has outerWidth 200." ); assert.strictEqual( $thirdTh.outerWidth(), 200, "Third th has outerWidth 200." ); - - // Support: Android 4.0-4.3 only - // Android Browser disregards td's box-sizing, treating it like it was content-box. - // Unlike in IE, offsetHeight shares the same issue so there's no easy way to workaround - // the issue without incurring high size penalty. Let's at least check we get the size - // as the browser sees it. - if ( /android 4\.[0-3]/i.test( navigator.userAgent ) ) { - assert.ok( [ 30, 32 ].indexOf( $td.outerHeight() ) > -1, - "outerHeight of td with border-box should include padding." ); - } else { - assert.strictEqual( $td.outerHeight(), 30, "outerHeight of td with border-box should include padding." ); - } + assert.strictEqual( $td.outerHeight(), 30, "outerHeight of td with border-box should include padding." ); assert.strictEqual( $textarea.outerHeight(), 6, "outerHeight of textarea with border-box should include padding and border." ); } ); diff --git a/test/unit/effects.js b/test/unit/effects.js index 05fd1283e..9f9f34514 100644 --- a/test/unit/effects.js +++ b/test/unit/effects.js @@ -221,7 +221,7 @@ supportjQuery.each( hideOptions, function( type, setup ) { assert.expectJqData( this, $span, "olddisplay" ); } ); - QUnit[ document.body.attachShadow ? "test" : "skip" ]( + QUnit[ document.body.getRootNode ? "test" : "skip" ]( "Persist correct display value - " + type + " hidden, shadow child", function( assert ) { assert.expect( 3 ); @@ -690,44 +690,35 @@ QUnit.test( "stop()", function( assert ) { this.clock.tick( 100 ); } ); -// In IE9 inside testswarm this test doesn't work properly -( function() { - var type = "test"; - - if ( QUnit.isSwarm && /msie 9\.0/i.test( window.navigator.userAgent ) ) { - type = "skip"; - } - - QUnit[ type ]( "stop() - several in queue", function( assert ) { - assert.expect( 5 ); +QUnit.test( "stop() - several in queue", function( assert ) { + assert.expect( 5 ); - var nw, $foo = jQuery( "#foo" ); + var nw, $foo = jQuery( "#foo" ); - // default duration is 400ms, so 800px ensures we aren't 0 or 1 after 1ms - $foo.hide().css( "width", 800 ); + // default duration is 400ms, so 800px ensures we aren't 0 or 1 after 1ms + $foo.hide().css( "width", 800 ); - $foo.animate( { "width": "show" }, 400, "linear" ); - $foo.animate( { "width": "hide" } ); - $foo.animate( { "width": "show" } ); + $foo.animate( { "width": "show" }, 400, "linear" ); + $foo.animate( { "width": "hide" } ); + $foo.animate( { "width": "show" } ); - this.clock.tick( 1 ); + this.clock.tick( 1 ); - jQuery.fx.tick(); - assert.equal( $foo.queue().length, 3, "3 in the queue" ); + jQuery.fx.tick(); + assert.equal( $foo.queue().length, 3, "3 in the queue" ); - nw = $foo.css( "width" ); - assert.notEqual( parseFloat( nw ), 1, "An animation occurred " + nw ); - $foo.stop(); + nw = $foo.css( "width" ); + assert.notEqual( parseFloat( nw ), 1, "An animation occurred " + nw ); + $foo.stop(); - assert.equal( $foo.queue().length, 2, "2 in the queue" ); - nw = $foo.css( "width" ); - assert.notEqual( parseFloat( nw ), 1, "Stop didn't reset the animation " + nw ); + assert.equal( $foo.queue().length, 2, "2 in the queue" ); + nw = $foo.css( "width" ); + assert.notEqual( parseFloat( nw ), 1, "Stop didn't reset the animation " + nw ); - $foo.stop( true ); + $foo.stop( true ); - assert.equal( $foo.queue().length, 0, "0 in the queue" ); - } ); -} )(); + assert.equal( $foo.queue().length, 0, "0 in the queue" ); +} ); QUnit.test( "stop(clearQueue)", function( assert ) { assert.expect( 4 ); diff --git a/test/unit/event.js b/test/unit/event.js index b77da465e..756c8838b 100644 --- a/test/unit/event.js +++ b/test/unit/event.js @@ -1414,7 +1414,7 @@ QUnit.test( "Submit event can be stopped (#11049)", function( assert ) { form.remove(); } ); -// Support: iOS 7 - 9 +// Support: iOS <=7 - 12+ // iOS has the window.onbeforeunload field but doesn't support the beforeunload // handler making it impossible to feature-detect the support. QUnit[ /(ipad|iphone|ipod)/i.test( navigator.userAgent ) ? "skip" : "test" ]( @@ -2434,7 +2434,7 @@ QUnit.test( "event object properties on natively-triggered event", function( ass $link = jQuery( link ), evt = document.createEvent( "MouseEvents" ); - // Support: IE <=9 - 11 only + // Support: IE <=9 - 11+ // IE requires element to be in the body before it will dispatch $link.appendTo( "body" ).on( "click", function( e ) { @@ -2931,21 +2931,6 @@ QUnit.test( "trigger('click') on radio passes extra params", function( assert ) $radio.trigger( "click", [ true ] ); } ); -// Support: IE <=9 only -// https://msdn.microsoft.com/en-us/library/hh801223(v=vs.85).aspx -QUnit.test( "VML with special event handlers (trac-7071)", function( assert ) { - assert.expect( 1 ); - - var ns = jQuery( "<xml:namespace ns='urn:schemas-microsoft-com:vml' prefix='v' />" ).appendTo( "head" ); - - jQuery( "<v:oval id='oval' style='width:100pt;height:75pt;' fillcolor='red'> </v:oval>" ).appendTo( "#form" ); - jQuery( "#form" ).on( "keydown", function() { - assert.ok( true, "no error was thrown" ); - } ); - jQuery( "#oval" ).trigger( "click" ).trigger( "keydown" ); - ns.remove(); -} ); - QUnit.test( "focusout/focusin support", function( assert ) { assert.expect( 6 ); diff --git a/test/unit/manipulation.js b/test/unit/manipulation.js index b0d3e3a88..e5cf856ec 100644 --- a/test/unit/manipulation.js +++ b/test/unit/manipulation.js @@ -511,18 +511,6 @@ QUnit.test( "Tag name processing respects the HTML Standard (gh-2005)", function } function assertSpecialCharsSupport( method, characters ) { - // Support: Android 4.4 only - // Chromium < 35 incorrectly upper-cases µ; Android 4.4 uses such a version by default - // (and its WebView, being un-updatable, will use it for eternity) so we need to blacklist - // that one for the tests to pass. - if ( characters === "µ" && /chrome/i.test( navigator.userAgent ) && - navigator.userAgent.match( /chrome\/(\d+)/i )[ 1 ] < 35 ) { - assert.ok( true, "This Chromium version upper-cases µ incorrectly; skip test" ); - assert.ok( true, "This Chromium version upper-cases µ incorrectly; skip test" ); - assert.ok( true, "This Chromium version upper-cases µ incorrectly; skip test" ); - return; - } - var child, codepoint = characters.charCodeAt( 0 ).toString( 16 ).toUpperCase(), description = characters.length === 1 ? @@ -592,28 +580,7 @@ QUnit.test( "append(xml)", function( assert ) { var xmlDoc, xml1, xml2; function createXMLDoc() { - - // Initialize DOM based upon latest installed MSXML or Netscape - var elem, n, len, - aActiveX = - [ "MSXML6.DomDocument", - "MSXML3.DomDocument", - "MSXML2.DomDocument", - "MSXML.DomDocument", - "Microsoft.XmlDom" ]; - - if ( document.implementation && "createDocument" in document.implementation ) { - return document.implementation.createDocument( "", "", null ); - } else { - - // IE - for ( n = 0, len = aActiveX.length; n < len; n++ ) { - try { - elem = new window.ActiveXObject( aActiveX[ n ] ); - return elem; - } catch ( _ ) {} - } - } + return document.implementation.createDocument( "", "", null ); } xmlDoc = createXMLDoc(); @@ -1798,7 +1765,7 @@ QUnit.test( "html(Function)", function( assert ) { } ); QUnit[ - // Support: Edge 16-18+ + // Support: Edge 16 - 18+ // Edge sometimes doesn't execute module scripts so skip the test there. ( QUnit.moduleTypeSupported && !/edge\//i.test( navigator.userAgent ) ) ? "test" : @@ -1825,15 +1792,10 @@ QUnit[ }, 1000 ); } ); -QUnit[ - // Support: IE 9-11 only, Android 4.0-4.4 only, iOS 7-10 only +QUnit.test( "html(script nomodule)", function( assert ) { + + // Support: IE 9 - 11+ // `nomodule` scripts should be executed by legacy browsers only. - // iOS 10 supports `<script type="module">` but doesn't support the nomodule attribute - // so let's skip it here; sites supporting it must handle `nomodule` in a custom way anyway. - !/iphone os 10_/i.test( navigator.userAgent ) ? - "test" : - "skip" -]( "html(script nomodule)", function( assert ) { assert.expect( QUnit.moduleTypeSupported ? 0 : 4 ); var done = assert.async(), $fixture = jQuery( "#qunit-fixture" ); @@ -2676,14 +2638,18 @@ QUnit.test( "Make sure specific elements with content created correctly (#13232) jQuery.each( elems, function( name, value ) { var html = "<" + name + ">" + value + "</" + name + ">"; - assert.ok( jQuery.parseHTML( "<" + name + ">" + value + "</" + name + ">" )[ 0 ].nodeName.toLowerCase() === name, name + " is created correctly" ); + assert.strictEqual( + jQuery.parseHTML( "<" + name + ">" + value + "</" + name + ">" )[ 0 ].nodeName.toLowerCase(), + name, + name + " is created correctly" + ); results.push( name ); args.push( html ); } ); jQuery.fn.append.apply( jQuery( "<div/>" ), args ).children().each( function( i ) { - assert.ok( this.nodeName.toLowerCase() === results[ i ] ); + assert.strictEqual( this.nodeName.toLowerCase(), results[ i ] ); } ); } ); @@ -2827,6 +2793,7 @@ QUnit.test( "Make sure tags with single-character names are found (gh-4124)", fu QUnit.test( "Insert script with data-URI (gh-1887)", function( assert ) { assert.expect( 1 ); + Globals.register( "testFoo" ); Globals.register( "testSrcFoo" ); @@ -2885,36 +2852,30 @@ testIframe( } ); }, - // Support: Edge 18+, iOS 7-9 only, Android 4.0-4.4 only + // Support: Edge <=18+ // Edge doesn't support nonce in non-inline scripts. // See https://developer.microsoft.com/en-us/microsoft-edge/platform/issues/13246371/ - // Old iOS & Android Browser versions support script-src but not nonce, making this test - // impossible to run. Browsers not supporting CSP at all are not a problem as they'll skip - // script-src restrictions completely. - QUnit[ /\bedge\/|iphone os [789]|android 4\./i.test( navigator.userAgent ) ? "skip" : "test" ] + QUnit[ /\bedge\//i.test( navigator.userAgent ) ? "skip" : "test" ] ); testIframe( - "Check if CSP nonce is preserved for external scripts with src attribute", - "mock.php?action=cspNonce&test=external", - function( assert, jQuery, window, document ) { - var done = assert.async(); - - assert.expect( 1 ); - - supportjQuery.get( baseURL + "support/csp.log" ).done( function( data ) { - assert.equal( data, "", "No log request should be sent" ); - supportjQuery.get( baseURL + "mock.php?action=cspClean" ).done( done ); - } ); - }, - - // Support: Edge 18+, iOS 7-9 only, Android 4.0-4.4 only - // Edge doesn't support nonce in non-inline scripts. - // See https://developer.microsoft.com/en-us/microsoft-edge/platform/issues/13246371/ - // Old iOS & Android Browser versions support script-src but not nonce, making this test - // impossible to run. Browsers not supporting CSP at all are not a problem as they'll skip - // script-src restrictions completely. - QUnit[ /\bedge\/|iphone os [789]|android 4\./i.test( navigator.userAgent ) ? "skip" : "test" ] + "Check if CSP nonce is preserved for external scripts with src attribute", + "mock.php?action=cspNonce&test=external", + function( assert, jQuery, window, document ) { + var done = assert.async(); + + assert.expect( 1 ); + + supportjQuery.get( baseURL + "support/csp.log" ).done( function( data ) { + assert.equal( data, "", "No log request should be sent" ); + supportjQuery.get( baseURL + "mock.php?action=cspClean" ).done( done ); + } ); + }, + + // Support: Edge <=18+ + // Edge doesn't support nonce in non-inline scripts. + // See https://developer.microsoft.com/en-us/microsoft-edge/platform/issues/13246371/ + QUnit[ /\bedge\//i.test( navigator.userAgent ) ? "skip" : "test" ] ); testIframe( @@ -2931,11 +2892,8 @@ testIframe( } ); }, - // Support: Edge 18+, iOS 7-9 only, Android 4.0-4.4 only + // Support: Edge <=18+ // Edge doesn't support nonce in non-inline scripts. // See https://developer.microsoft.com/en-us/microsoft-edge/platform/issues/13246371/ - // Old iOS & Android Browser versions support script-src but not nonce, making this test - // impossible to run. Browsers not supporting CSP at all are not a problem as they'll skip - // script-src restrictions completely. - QUnit[ /\bedge\/|iphone os [789]|android 4\./i.test( navigator.userAgent ) ? "skip" : "test" ] + QUnit[ /\bedge\//i.test( navigator.userAgent ) ? "skip" : "test" ] ); diff --git a/test/unit/offset.js b/test/unit/offset.js index 2b63ccbd9..d18e6032f 100644 --- a/test/unit/offset.js +++ b/test/unit/offset.js @@ -4,26 +4,20 @@ if ( !jQuery.fn.offset ) { return; } -var supportsFixedPosition, supportsScroll, alwaysScrollable, +var supportsScroll, alwaysScrollable, forceScroll = supportjQuery( "<div/>" ).css( { width: 2000, height: 2000 } ), checkSupport = function( assert ) { // Only run once checkSupport = false; - var checkFixed = supportjQuery( "<div/>" ) - .css( { position: "fixed", top: "20px" } ) - .appendTo( "#qunit-fixture" ); - supportsFixedPosition = checkFixed[ 0 ].offsetTop === 20; - checkFixed.remove(); - // Append forceScroll to the body instead of #qunit-fixture because the latter is hidden forceScroll.appendTo( "body" ); window.scrollTo( 200, 200 ); supportsScroll = document.documentElement.scrollTop || document.body.scrollTop; forceScroll.detach(); - // Support: iOS <=7 + // Support: iOS <=7 - 12+ // Hijack the iframe test infrastructure to detect viewport scrollability // for pages with position:fixed document element var done = assert.async(); @@ -400,22 +394,13 @@ testIframe( "fixed", "offset/fixed.html", function( assert, $, window ) { assert.ok( true, "Browser doesn't support scroll position." ); assert.ok( true, "Browser doesn't support scroll position." ); - } else if ( window.supportsFixedPosition ) { + } else { assert.equal( jQuery.isPlainObject( $( this.id ).offset() ), true, "jQuery('" + this.id + "').offset() is plain object" ); assert.equal( jQuery.isPlainObject( $( this.id ).position() ), true, "jQuery('" + this.id + "').position() is plain object" ); assert.equal( $( this.id ).offset().top, this.offsetTop, "jQuery('" + this.id + "').offset().top" ); assert.equal( $( this.id ).position().top, this.positionTop, "jQuery('" + this.id + "').position().top" ); assert.equal( $( this.id ).offset().left, this.offsetLeft, "jQuery('" + this.id + "').offset().left" ); assert.equal( $( this.id ).position().left, this.positionLeft, "jQuery('" + this.id + "').position().left" ); - } else { - - // need to have same number of assertions - assert.ok( true, "Fixed position is not supported" ); - assert.ok( true, "Fixed position is not supported" ); - assert.ok( true, "Fixed position is not supported" ); - assert.ok( true, "Fixed position is not supported" ); - assert.ok( true, "Fixed position is not supported" ); - assert.ok( true, "Fixed position is not supported" ); } } ); @@ -429,40 +414,25 @@ testIframe( "fixed", "offset/fixed.html", function( assert, $, window ) { ]; jQuery.each( tests, function() { - if ( window.supportsFixedPosition ) { - $( this.id ).offset( { "top": this.top, "left": this.left } ); - assert.equal( $( this.id ).offset().top, this.top, "jQuery('" + this.id + "').offset({ top: " + this.top + " })" ); - assert.equal( $( this.id ).offset().left, this.left, "jQuery('" + this.id + "').offset({ left: " + this.left + " })" ); - - $( this.id ).offset( { "top": this.top, "left": this.left, "using": function( props ) { - $( this ).css( { - "top": props.top + 1, - "left": props.left + 1 - } ); - } } ); - assert.equal( $( this.id ).offset().top, this.top + 1, "jQuery('" + this.id + "').offset({ top: " + ( this.top + 1 ) + ", using: fn })" ); - assert.equal( $( this.id ).offset().left, this.left + 1, "jQuery('" + this.id + "').offset({ left: " + ( this.left + 1 ) + ", using: fn })" ); - } else { + $( this.id ).offset( { "top": this.top, "left": this.left } ); + assert.equal( $( this.id ).offset().top, this.top, "jQuery('" + this.id + "').offset({ top: " + this.top + " })" ); + assert.equal( $( this.id ).offset().left, this.left, "jQuery('" + this.id + "').offset({ left: " + this.left + " })" ); - // need to have same number of assertions - assert.ok( true, "Fixed position is not supported" ); - assert.ok( true, "Fixed position is not supported" ); - assert.ok( true, "Fixed position is not supported" ); - assert.ok( true, "Fixed position is not supported" ); - } + $( this.id ).offset( { "top": this.top, "left": this.left, "using": function( props ) { + $( this ).css( { + "top": props.top + 1, + "left": props.left + 1 + } ); + } } ); + assert.equal( $( this.id ).offset().top, this.top + 1, "jQuery('" + this.id + "').offset({ top: " + ( this.top + 1 ) + ", using: fn })" ); + assert.equal( $( this.id ).offset().left, this.left + 1, "jQuery('" + this.id + "').offset({ left: " + ( this.left + 1 ) + ", using: fn })" ); } ); // Bug 8316 $noTopLeft = $( "#fixed-no-top-left" ); - if ( window.supportsFixedPosition ) { - assert.equal( $noTopLeft.offset().top, 1007, "Check offset top for fixed element with no top set" ); - assert.equal( $noTopLeft.offset().left, 1007, "Check offset left for fixed element with no left set" ); - } else { - // need to have same number of assertions - assert.ok( true, "Fixed position is not supported" ); - assert.ok( true, "Fixed position is not supported" ); - } + assert.equal( $noTopLeft.offset().top, 1007, "Check offset top for fixed element with no top set" ); + assert.equal( $noTopLeft.offset().left, 1007, "Check offset left for fixed element with no left set" ); } ); testIframe( "table", "offset/table.html", function( assert, $ ) { @@ -660,25 +630,6 @@ QUnit.test( "chaining", function( assert ) { } } ); - // Support: IE<=10 only - // Fudge the tests to work around <html>.gBCR() erroneously including margins - if ( /MSIE (?:9|10)\./.test( navigator.userAgent ) ) { - expectations.documentElement.pos.top -= expectations.documentElement.marginTop - - scrollTop; - expectations.documentElement.offset.top -= expectations.documentElement.marginTop - - scrollTop; - expectations.documentElement.pos.left -= expectations.documentElement.marginLeft - - scrollLeft; - expectations.documentElement.offset.left -= expectations.documentElement.marginLeft - - scrollLeft; - if ( htmlPos !== "static" ) { - delete expectations.documentElement; - delete expectations.body; - delete expectations.relative; - delete expectations.absolute; - } - } - return expectations; } @@ -803,10 +754,10 @@ QUnit.test( "fractions (see #7730 and #7885)", function( assert ) { result = div.offset(); - // Support: Chrome <=45 - 46 + // Support: Chrome <=45 - 73+ // In recent Chrome these values differ a little. assert.ok( Math.abs( result.top - expected.top ) < 0.25, "Check top within 0.25 of expected" ); - assert.equal( result.left, expected.left, "Check left" ); + assert.ok( Math.abs( result.left - expected.left ) < 0.25, "Check left within 0.25 of expected" ); div.remove(); } ); @@ -816,13 +767,10 @@ QUnit.test( "iframe scrollTop/Left (see gh-1945)", function( assert ) { var ifDoc = jQuery( "#iframe" )[ 0 ].contentDocument; - // Mobile Safari resize the iframe by its content meaning it's not possible to scroll + // Support: iOS <=8 - 12+ + // Mobile Safari resizes the iframe by its content meaning it's not possible to scroll // the iframe but only its parent element. - // It seems (not confirmed) in android 4.0 it's not possible to scroll iframes from the code. - if ( - /iphone os|ipad/i.test( navigator.userAgent ) || - /android 4\.0/i.test( navigator.userAgent ) - ) { + if ( /iphone os|ipad/i.test( navigator.userAgent ) ) { assert.equal( true, true, "Can't scroll iframes in this environment" ); assert.equal( true, true, "Can't scroll iframes in this environment" ); diff --git a/test/unit/support.js b/test/unit/support.js index b0309ffe7..e81e60c5d 100644 --- a/test/unit/support.js +++ b/test/unit/support.js @@ -36,7 +36,7 @@ if ( jQuery.css ) { } // This test checks CSP only for browsers with "Content-Security-Policy" header support -// i.e. no old WebKit or old Firefox +// i.e. no IE testIframe( "Check CSP (https://developer.mozilla.org/en-US/docs/Security/CSP) restrictions", "mock.php?action=cspFrame", @@ -59,244 +59,63 @@ testIframe( userAgent = window.navigator.userAgent, expectedMap = { edge: { - "ajax": true, - "boxSizingReliable": true, - "checkClone": true, - "checkOn": true, - "clearCloneStyle": true, - "cors": true, - "createHTMLDocument": true, - "noCloneChecked": true, - "optSelected": true, - "pixelBoxStyles": true, - "pixelPosition": true, - "radioValue": true, - "reliableMarginLeft": true, - "scrollboxSize": true + boxSizingReliable: true, + clearCloneStyle: true, + noCloneChecked: true, + optSelected: true, + radioValue: true }, - ie_10_11: { - "ajax": true, - "boxSizingReliable": false, - "checkClone": true, - "checkOn": true, - "clearCloneStyle": false, - "cors": true, - "createHTMLDocument": true, - "noCloneChecked": false, - "optSelected": false, - "pixelBoxStyles": true, - "pixelPosition": true, - "radioValue": false, - "reliableMarginLeft": true, - "scrollboxSize": true - }, - ie_9: { - "ajax": true, - "boxSizingReliable": false, - "checkClone": true, - "checkOn": true, - "clearCloneStyle": false, - "cors": false, - "createHTMLDocument": true, - "noCloneChecked": false, - "optSelected": false, - "pixelBoxStyles": true, - "pixelPosition": true, - "radioValue": false, - "reliableMarginLeft": true, - "scrollboxSize": false + ie_11: { + boxSizingReliable: false, + clearCloneStyle: false, + noCloneChecked: false, + optSelected: false, + radioValue: false }, chrome: { - "ajax": true, - "boxSizingReliable": true, - "checkClone": true, - "checkOn": true, - "clearCloneStyle": true, - "cors": true, - "createHTMLDocument": true, - "noCloneChecked": true, - "optSelected": true, - "pixelBoxStyles": true, - "pixelPosition": true, - "radioValue": true, - "reliableMarginLeft": true, - "scrollboxSize": true + boxSizingReliable: true, + clearCloneStyle: true, + noCloneChecked: true, + optSelected: true, + radioValue: true }, safari: { - "ajax": true, - "boxSizingReliable": true, - "checkClone": true, - "checkOn": true, - "clearCloneStyle": true, - "cors": true, - "createHTMLDocument": true, - "noCloneChecked": true, - "optSelected": true, - "pixelBoxStyles": true, - "pixelPosition": true, - "radioValue": true, - "reliableMarginLeft": true, - "scrollboxSize": true - }, - safari_9_10: { - "ajax": true, - "boxSizingReliable": true, - "checkClone": true, - "checkOn": true, - "clearCloneStyle": true, - "cors": true, - "createHTMLDocument": true, - "noCloneChecked": true, - "optSelected": true, - "pixelBoxStyles": false, - "pixelPosition": false, - "radioValue": true, - "reliableMarginLeft": true, - "scrollboxSize": true + boxSizingReliable: true, + clearCloneStyle: true, + noCloneChecked: true, + optSelected: true, + radioValue: true }, firefox: { - "ajax": true, - "boxSizingReliable": true, - "checkClone": true, - "checkOn": true, - "clearCloneStyle": true, - "cors": true, - "createHTMLDocument": true, - "noCloneChecked": true, - "optSelected": true, - "pixelBoxStyles": true, - "pixelPosition": true, - "radioValue": true, - "reliableMarginLeft": true, - "scrollboxSize": true - }, - firefox_60: { - "ajax": true, - "boxSizingReliable": true, - "checkClone": true, - "checkOn": true, - "clearCloneStyle": true, - "cors": true, - "createHTMLDocument": true, - "noCloneChecked": true, - "optSelected": true, - "pixelBoxStyles": true, - "pixelPosition": true, - "radioValue": true, - "reliableMarginLeft": false, - "scrollboxSize": true + boxSizingReliable: true, + clearCloneStyle: true, + noCloneChecked: true, + optSelected: true, + radioValue: true }, ios: { - "ajax": true, - "boxSizingReliable": true, - "checkClone": true, - "checkOn": true, - "clearCloneStyle": true, - "cors": true, - "createHTMLDocument": true, - "noCloneChecked": true, - "optSelected": true, - "pixelBoxStyles": true, - "pixelPosition": true, - "radioValue": true, - "reliableMarginLeft": true, - "scrollboxSize": true - }, - ios_9_10: { - "ajax": true, - "boxSizingReliable": true, - "checkClone": true, - "checkOn": true, - "clearCloneStyle": true, - "cors": true, - "createHTMLDocument": true, - "noCloneChecked": true, - "optSelected": true, - "pixelBoxStyles": false, - "pixelPosition": false, - "radioValue": true, - "reliableMarginLeft": true, - "scrollboxSize": true - }, - ios_8: { - "ajax": true, - "boxSizingReliable": true, - "checkClone": true, - "checkOn": true, - "clearCloneStyle": true, - "cors": true, - "createHTMLDocument": false, - "noCloneChecked": true, - "optSelected": true, - "pixelBoxStyles": false, - "pixelPosition": false, - "radioValue": true, - "reliableMarginLeft": true, - "scrollboxSize": true - }, - ios_7: { - "ajax": true, - "boxSizingReliable": true, - "checkClone": true, - "checkOn": true, - "clearCloneStyle": true, - "cors": true, - "createHTMLDocument": true, - "noCloneChecked": true, - "optSelected": true, - "pixelBoxStyles": false, - "pixelPosition": false, - "radioValue": true, - "reliableMarginLeft": true, - "scrollboxSize": true - }, - android: { - "ajax": true, - "boxSizingReliable": true, - "checkClone": false, - "checkOn": false, - "clearCloneStyle": true, - "cors": true, - "createHTMLDocument": true, - "noCloneChecked": true, - "optSelected": true, - "pixelBoxStyles": false, - "pixelPosition": false, - "radioValue": true, - "reliableMarginLeft": false, - "scrollboxSize": true + boxSizingReliable: true, + clearCloneStyle: true, + noCloneChecked: true, + optSelected: true, + radioValue: true } }; if ( /edge\//i.test( userAgent ) ) { expected = expectedMap.edge; - } else if ( /(msie 10\.0|trident\/7\.0)/i.test( userAgent ) ) { - expected = expectedMap.ie_10_11; - } else if ( /msie 9\.0/i.test( userAgent ) ) { - expected = expectedMap.ie_9; + } else if ( document.documentMode ) { + expected = expectedMap.ie_11; } else if ( /chrome/i.test( userAgent ) ) { - // Catches Chrome on Android as well (i.e. the default - // Android browser on Android >= 4.4). + // Catches Chrome on Android & Opera as well. expected = expectedMap.chrome; - } else if ( /\b(?:11|12)\.\d(\.\d+)* safari/i.test( userAgent ) ) { + } else if ( /\b\d+(\.\d+)+ safari/i.test( userAgent ) ) { expected = expectedMap.safari; - } else if ( /\b(?:9|10)\.\d(\.\d+)* safari/i.test( userAgent ) ) { - expected = expectedMap.safari_9_10; - } else if ( /firefox\/(?:52|60)/i.test( userAgent ) ) { - expected = expectedMap.firefox_60; } else if ( /firefox/i.test( userAgent ) ) { expected = expectedMap.firefox; - } else if ( /(?:iphone|ipad);.*(?:iphone)? os (?:11|12)_/i.test( userAgent ) ) { + } else if ( /(?:iphone|ipad);.*(?:iphone)? os \d+_/i.test( userAgent ) ) { expected = expectedMap.ios; - } else if ( /iphone os (?:9|10)_/i.test( userAgent ) ) { - expected = expectedMap.ios_9_10; - } else if ( /iphone os 8_/i.test( userAgent ) ) { - expected = expectedMap.ios_8; - } else if ( /iphone os 7_/i.test( userAgent ) ) { - expected = expectedMap.ios_7; - } else if ( /android 4\.[0-3]/i.test( userAgent ) ) { - expected = expectedMap.android; } QUnit.test( "Verify that support tests resolve as expected per browser", function( assert ) { @@ -315,13 +134,9 @@ testIframe( assert.expect( j ); for ( i in expected ) { - if ( jQuery.ajax || i !== "ajax" && i !== "cors" ) { - assert.equal( computedSupport[ i ], expected[ i ], - "jQuery.support['" + i + "']: " + computedSupport[ i ] + - ", expected['" + i + "']: " + expected[ i ] ); - } else { - assert.ok( true, "no ajax; skipping jQuery.support['" + i + "']" ); - } + assert.equal( computedSupport[ i ], expected[ i ], + "jQuery.support['" + i + "']: " + computedSupport[ i ] + + ", expected['" + i + "']: " + expected[ i ] ); } } ); @@ -331,10 +146,7 @@ testIframe( var prop, browserKey, supportTestName, i = 0, supportProps = {}, - failingSupportProps = {}, - whitelist = { - ajax: true - }; + failingSupportProps = {}; for ( prop in computedSupport ) { i++; @@ -342,8 +154,8 @@ testIframe( assert.expect( i ); - // Record all support props and the failing ones and ensure everyone - // except a few on a whitelist are failing at least once. + // Record all support props and the failing ones and ensure every test + // is failing at least once. for ( browserKey in expectedMap ) { for ( supportTestName in expectedMap[ browserKey ] ) { supportProps[ supportTestName ] = true; @@ -354,8 +166,9 @@ testIframe( } for ( supportTestName in supportProps ) { - assert.ok( whitelist[ supportTestName ] || failingSupportProps[ supportTestName ], - "jQuery.support['" + supportTestName + "'] always succeeds; remove it?" ); + assert.ok( failingSupportProps[ supportTestName ], + "jQuery.support['" + supportTestName + + "'] is expected to fail at least in one browser" ); } } ); |