From 294a3698811d6aaeabc67d2a77a5ef5fac94165a Mon Sep 17 00:00:00 2001 From: Timmy Willison <4timmywil@gmail.com> Date: Sat, 20 Jan 2018 12:27:15 -0500 Subject: [PATCH 01/83] Build: Updating the master version to 3.3.2-pre. --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index e1e50e9fff..e1f4598c74 100644 --- a/package.json +++ b/package.json @@ -2,7 +2,7 @@ "name": "jquery", "title": "jQuery", "description": "JavaScript library for DOM operations", - "version": "3.3.1-pre", + "version": "3.3.2-pre", "main": "dist/jquery.js", "homepage": "https://jquery.com", "author": { From 56742491bd45650e4c8ac7981a11d4d142c265a9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Go=C5=82=C4=99biowski-Owczarek?= Date: Mon, 12 Feb 2018 19:08:36 +0100 Subject: [PATCH 02/83] Tests: Disable native abort test in Android 4.0 The test works on its own when checked manually but mysteriously fails in TestSwarm only in Android 4.0. Let's just disable it there. Closes gh-3968 --- test/unit/ajax.js | 38 ++++++++++++++++++++------------------ 1 file changed, 20 insertions(+), 18 deletions(-) diff --git a/test/unit/ajax.js b/test/unit/ajax.js index e1ecd2036f..ff9fd8e704 100644 --- a/test/unit/ajax.js +++ b/test/unit/ajax.js @@ -505,24 +505,26 @@ QUnit.module( "ajax", { }; } ); - 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" ); - } - }; - } ); + 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" ); + } + }; + } ); + } // Support: Android <= 4.0 - 4.3 only // Android 4.0-4.3 does not have ontimeout on an xhr From 4a2bcc27f9c3ee24b3effac0fbe1285d1ee23cc5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Go=C5=82=C4=99biowski-Owczarek?= Date: Mon, 12 Feb 2018 20:24:58 +0100 Subject: [PATCH 03/83] Tests: Fix Android 4.0 Deferred tests Closes gh-3967 --- test/unit/deferred.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/test/unit/deferred.js b/test/unit/deferred.js index 2e414e6423..70d1254a16 100644 --- a/test/unit/deferred.js +++ b/test/unit/deferred.js @@ -884,7 +884,9 @@ QUnit.test( "jQuery.when(thenable) - like Promise.resolve", function( assert ) { var customToStringThen = { then: function( onFulfilled ) { - onFulfilled(); + // Support: Android 4.0 only + // Strict mode functions invoked without .call/.apply get global-object context + onFulfilled.call(); } }; if ( typeof Symbol === "function" ) { From 09684ba3f210594e41ecddf369ac94c688d53ccb Mon Sep 17 00:00:00 2001 From: Oleg Gaydarenko Date: Fri, 2 Mar 2018 20:21:33 +0300 Subject: [PATCH 04/83] Build: Seasonal update of uglify and its options raw gz Compared to last run = = dist/jquery.js -294 -88 dist/jquery.min.js Closes gh-3994 --- Gruntfile.js | 2 +- package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Gruntfile.js b/Gruntfile.js index 096370a4f2..b9c0091a36 100644 --- a/Gruntfile.js +++ b/Gruntfile.js @@ -259,9 +259,9 @@ module.exports = function( grunt ) { banner: "/*! jQuery v<%= pkg.version %> | " + "(c) JS Foundation and other contributors | jquery.org/license */", compress: { + "pure_getters": true, "hoist_funs": false, loops: false, - unused: false, // Support: IE <11 // typeofs transformation is unsafe for IE9-10 diff --git a/package.json b/package.json index e1f4598c74..3603d613e3 100644 --- a/package.json +++ b/package.json @@ -63,7 +63,7 @@ "sizzle": "2.3.3", "strip-json-comments": "2.0.1", "testswarm": "1.1.0", - "uglify-js": "3.3.4" + "uglify-js": "3.3.12" }, "scripts": { "build": "npm install && grunt", From 662083ed7bfea6bad5f9cd4060dab77c1f32aacd Mon Sep 17 00:00:00 2001 From: Saptak Sengupta Date: Mon, 5 Mar 2018 23:27:03 +0530 Subject: [PATCH 05/83] Core: Use isAttached to check for attachment of element This change replaces the use of contains to check for attachment by isAttached function Closes gh-3977 Ref gh-3504 --- src/css/curCSS.js | 8 ++++---- src/css/var/isHiddenWithinTree.js | 6 +++--- src/manipulation.js | 7 ++++--- src/manipulation/buildFragment.js | 9 +++++---- src/var/isAttached.js | 11 +++++++++++ 5 files changed, 27 insertions(+), 14 deletions(-) create mode 100644 src/var/isAttached.js diff --git a/src/css/curCSS.js b/src/css/curCSS.js index aa1414d261..7fed20f17b 100644 --- a/src/css/curCSS.js +++ b/src/css/curCSS.js @@ -1,11 +1,11 @@ define( [ "../core", + "../var/isAttached", "./var/rboxStyle", "./var/rnumnonpx", "./var/getStyles", - "./support", - "../selector" // Get jQuery.contains -], function( jQuery, rboxStyle, rnumnonpx, getStyles, support ) { + "./support" +], function( jQuery, isAttached, rboxStyle, rnumnonpx, getStyles, support ) { "use strict"; @@ -26,7 +26,7 @@ function curCSS( elem, name, computed ) { if ( computed ) { ret = computed.getPropertyValue( name ) || computed[ name ]; - if ( ret === "" && !jQuery.contains( elem.ownerDocument, elem ) ) { + if ( ret === "" && !isAttached( elem ) ) { ret = jQuery.style( elem, name ); } diff --git a/src/css/var/isHiddenWithinTree.js b/src/css/var/isHiddenWithinTree.js index 3cfb93e160..fd963a0314 100644 --- a/src/css/var/isHiddenWithinTree.js +++ b/src/css/var/isHiddenWithinTree.js @@ -1,9 +1,9 @@ define( [ "../../core", - "../../selector" + "../../var/isAttached" // css is assumed -], function( jQuery ) { +], function( jQuery, isAttached ) { "use strict"; // isHiddenWithinTree reports if an element has a non-"none" display style (inline and/or @@ -27,7 +27,7 @@ define( [ // Support: Firefox <=43 - 45 // Disconnected elements can have computed display: none, so first confirm that elem is // in the document. - jQuery.contains( elem.ownerDocument, elem ) && + isAttached( elem ) && jQuery.css( elem, "display" ) === "none"; }; diff --git a/src/manipulation.js b/src/manipulation.js index 142e296ad0..3c6d592623 100644 --- a/src/manipulation.js +++ b/src/manipulation.js @@ -1,5 +1,6 @@ define( [ "./core", + "./var/isAttached", "./var/concat", "./var/isFunction", "./var/push", @@ -23,7 +24,7 @@ define( [ "./traversing", "./selector", "./event" -], function( jQuery, concat, isFunction, push, access, +], function( jQuery, isAttached, concat, isFunction, push, access, rcheckableType, rtagName, rscriptType, wrapMap, getAll, setGlobalEval, buildFragment, support, dataPriv, dataUser, acceptData, DOMEval, nodeName ) { @@ -223,7 +224,7 @@ function remove( elem, selector, keepData ) { } if ( node.parentNode ) { - if ( keepData && jQuery.contains( node.ownerDocument, node ) ) { + if ( keepData && isAttached( node ) ) { setGlobalEval( getAll( node, "script" ) ); } node.parentNode.removeChild( node ); @@ -241,7 +242,7 @@ jQuery.extend( { clone: function( elem, dataAndEvents, deepDataAndEvents ) { var i, l, srcElements, destElements, clone = elem.cloneNode( true ), - inPage = jQuery.contains( elem.ownerDocument, elem ); + inPage = isAttached( elem ); // Fix IE cloning issues if ( !support.noCloneChecked && ( elem.nodeType === 1 || elem.nodeType === 11 ) && diff --git a/src/manipulation/buildFragment.js b/src/manipulation/buildFragment.js index 782de0c611..34bcc70c21 100644 --- a/src/manipulation/buildFragment.js +++ b/src/manipulation/buildFragment.js @@ -1,19 +1,20 @@ define( [ "../core", "../core/toType", + "../var/isAttached", "./var/rtagName", "./var/rscriptType", "./wrapMap", "./getAll", "./setGlobalEval" -], function( jQuery, toType, rtagName, rscriptType, wrapMap, getAll, setGlobalEval ) { +], function( jQuery, toType, isAttached, rtagName, rscriptType, wrapMap, getAll, setGlobalEval ) { "use strict"; var rhtml = /<|&#?\w+;/; function buildFragment( elems, context, scripts, selection, ignored ) { - var elem, tmp, tag, wrap, contains, j, + var elem, tmp, tag, wrap, attached, j, fragment = context.createDocumentFragment(), nodes = [], i = 0, @@ -77,13 +78,13 @@ function buildFragment( elems, context, scripts, selection, ignored ) { continue; } - contains = jQuery.contains( elem.ownerDocument, elem ); + attached = isAttached( elem ); // Append to fragment tmp = getAll( fragment.appendChild( elem ), "script" ); // Preserve script evaluation history - if ( contains ) { + if ( attached ) { setGlobalEval( tmp ); } diff --git a/src/var/isAttached.js b/src/var/isAttached.js new file mode 100644 index 0000000000..1dd798268f --- /dev/null +++ b/src/var/isAttached.js @@ -0,0 +1,11 @@ +define( [ + "../core", + "../selector" // Get jQuery.contains +], function( jQuery ) { + "use strict"; + + return function isAttached( obj ) { + return jQuery.contains( obj.ownerDocument, obj ); + }; + +} ); From 365284240429d442c3fbe9f505c7b297425bc3a3 Mon Sep 17 00:00:00 2001 From: Oleg Gaydarenko Date: Wed, 7 Mar 2018 11:33:39 +0300 Subject: [PATCH 06/83] Build: remove artefact from previous commit Follow-up for 09684ba3f210594e41ecddf369ac94c688d53ccb --- Gruntfile.js | 1 - 1 file changed, 1 deletion(-) diff --git a/Gruntfile.js b/Gruntfile.js index b9c0091a36..a0e9077151 100644 --- a/Gruntfile.js +++ b/Gruntfile.js @@ -259,7 +259,6 @@ module.exports = function( grunt ) { banner: "/*! jQuery v<%= pkg.version %> | " + "(c) JS Foundation and other contributors | jquery.org/license */", compress: { - "pure_getters": true, "hoist_funs": false, loops: false, From b95e0da68e1e3fce59a6a54c209b893f611b0b9c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Go=C5=82=C4=99biowski-Owczarek?= Date: Mon, 19 Mar 2018 18:12:23 +0100 Subject: [PATCH 07/83] Build: Don't require sudo on Travis, use sandboxless headless Chrome The Chrome sandbox doesn't work on Travis unless sudo is enabled. Instead, we're disabling the Chrome sandbox. Closes gh-4011 --- .travis.yml | 6 +----- Gruntfile.js | 13 +++++++++++-- 2 files changed, 12 insertions(+), 7 deletions(-) diff --git a/.travis.yml b/.travis.yml index 4ac42174e6..4fa82ae7ac 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,9 +1,5 @@ language: node_js -# Temporary workaround. -# Karma can't access the binaries on travis -# without root access. -# See https://github.com/travis-ci/travis-ci/issues/8836 -sudo: required +sudo: false node_js: - "4" - "6" diff --git a/Gruntfile.js b/Gruntfile.js index a0e9077151..fbf9b56717 100644 --- a/Gruntfile.js +++ b/Gruntfile.js @@ -13,7 +13,8 @@ module.exports = function( grunt ) { } var fs = require( "fs" ), - gzip = require( "gzip-js" ); + gzip = require( "gzip-js" ), + isTravis = process.env.TRAVIS; if ( !grunt.option( "filename" ) ) { grunt.option( "filename", "jquery.js" ); @@ -151,6 +152,12 @@ module.exports = function( grunt ) { options: { customContextFile: "test/karma.context.html", customDebugFile: "test/karma.debug.html", + customLaunchers: { + ChromeHeadlessNoSandbox: { + base: "ChromeHeadless", + flags: [ "--no-sandbox" ] + } + }, frameworks: [ "qunit" ], middleware: [ "mockserver" ], plugins: [ @@ -214,7 +221,9 @@ module.exports = function( grunt ) { singleRun: true }, main: { - browsers: [ "ChromeHeadless" ] + + // The Chrome sandbox doesn't work on Travis. + browsers: [ isTravis ? "ChromeHeadlessNoSandbox" : "ChromeHeadless" ] }, // To debug tests with Karma: From 2b5f5d5e90b37f4a735738a6d0b6f22affbea340 Mon Sep 17 00:00:00 2001 From: Dave Methvin Date: Sat, 24 Feb 2018 17:17:24 -0500 Subject: [PATCH 08/83] CSS: Avoid filling jQuery.cssProps Fixes gh-3986 Closes gh-4005 Avoids filling jQuery.cssProps by introducing a second internal prop cache. This allows jQuery Migrate to detect external usage. --- src/css.js | 38 +++----------------------------------- src/css/finalPropName.js | 39 +++++++++++++++++++++++++++++++++++++++ src/effects/Tween.js | 10 ++++++---- 3 files changed, 48 insertions(+), 39 deletions(-) create mode 100644 src/css/finalPropName.js diff --git a/src/css.js b/src/css.js index 43e427472e..bef7c7b73f 100644 --- a/src/css.js +++ b/src/css.js @@ -13,12 +13,13 @@ define( [ "./css/adjustCSS", "./css/addGetHookIf", "./css/support", + "./css/finalPropName", "./core/init", "./core/ready", "./selector" // contains ], function( jQuery, pnum, access, camelCase, document, rcssNum, rnumnonpx, cssExpand, - getStyles, swap, curCSS, adjustCSS, addGetHookIf, support ) { + getStyles, swap, curCSS, adjustCSS, addGetHookIf, support, finalPropName ) { "use strict"; @@ -33,40 +34,7 @@ var cssNormalTransform = { letterSpacing: "0", fontWeight: "400" - }, - - cssPrefixes = [ "Webkit", "Moz", "ms" ], - emptyStyle = document.createElement( "div" ).style; - -// Return a css property mapped to a potentially vendor prefixed property -function vendorPropName( name ) { - - // Shortcut for names that are not vendor prefixed - if ( name in emptyStyle ) { - return name; - } - - // Check for vendor prefixed names - var capName = name[ 0 ].toUpperCase() + name.slice( 1 ), - i = cssPrefixes.length; - - while ( i-- ) { - name = cssPrefixes[ i ] + capName; - if ( name in emptyStyle ) { - return name; - } - } -} - -// Return a property mapped along what jQuery.cssProps suggests or to -// a vendor prefixed property. -function finalPropName( name ) { - var ret = jQuery.cssProps[ name ]; - if ( !ret ) { - ret = jQuery.cssProps[ name ] = vendorPropName( name ) || name; - } - return ret; -} + }; function setPositiveNumber( elem, value, subtract ) { diff --git a/src/css/finalPropName.js b/src/css/finalPropName.js new file mode 100644 index 0000000000..e5c77b0b2e --- /dev/null +++ b/src/css/finalPropName.js @@ -0,0 +1,39 @@ +define( [ "../var/document" ], function( document ) { + +"use strict"; + +var cssPrefixes = [ "Webkit", "Moz", "ms" ], + emptyStyle = document.createElement( "div" ).style, + vendorProps = {}; + +// Return a vendor-prefixed property or undefined +function vendorPropName( name ) { + + // Check for vendor prefixed names + var capName = name[ 0 ].toUpperCase() + name.slice( 1 ), + i = cssPrefixes.length; + + while ( i-- ) { + name = cssPrefixes[ i ] + capName; + if ( name in emptyStyle ) { + return name; + } + } +} + +// Return a potentially-mapped jQuery.cssProps or vendor prefixed property +function finalPropName( name ) { + var final = jQuery.cssProps[ name ] || vendorProps[ name ]; + + if ( final ) { + return final; + } + if ( name in emptyStyle ) { + return name; + } + return vendorProps[ name ] = vendorPropName( name ) || name; +} + +return finalPropName; + +} ); diff --git a/src/effects/Tween.js b/src/effects/Tween.js index 43eb8fa0b1..bf501ead07 100644 --- a/src/effects/Tween.js +++ b/src/effects/Tween.js @@ -1,7 +1,9 @@ define( [ "../core", + "../css/finalPropName", + "../css" -], function( jQuery ) { +], function( jQuery, finalPropName ) { "use strict"; @@ -84,9 +86,9 @@ Tween.propHooks = { // Use .style if available and use plain properties where available. if ( jQuery.fx.step[ tween.prop ] ) { jQuery.fx.step[ tween.prop ]( tween ); - } else if ( tween.elem.nodeType === 1 && - ( tween.elem.style[ jQuery.cssProps[ tween.prop ] ] != null || - jQuery.cssHooks[ tween.prop ] ) ) { + } else if ( tween.elem.nodeType === 1 && ( + jQuery.cssHooks[ tween.prop ] || + tween.elem.style[ finalPropName( tween.prop ) ] != null ) ) { jQuery.style( tween.elem, tween.prop, tween.now + tween.unit ); } else { tween.elem[ tween.prop ] = tween.now; From 73d7e6259c63ac45f42c6593da8c2796c6ce9281 Mon Sep 17 00:00:00 2001 From: Jason Bedard Date: Tue, 13 Mar 2018 23:05:33 -0700 Subject: [PATCH 09/83] Dimensions: avoid fetching boxSizing when setting width/height - this avoids forcing a reflow in some cases Fixes #3991 --- src/css.js | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/css.js b/src/css.js index bef7c7b73f..ea73020121 100644 --- a/src/css.js +++ b/src/css.js @@ -346,7 +346,12 @@ jQuery.each( [ "height", "width" ], function( i, dimension ) { set: function( elem, value, extra ) { var matches, styles = getStyles( elem ), - isBorderBox = jQuery.css( elem, "boxSizing", false, styles ) === "border-box", + scrollBoxSize = support.scrollboxSize() === styles.position, + + // To avoid forcing a reflow, only fetch boxSizing if we need it (gh-3991) + boxSizingNeeded = scrollBoxSize || extra, + isBorderBox = boxSizingNeeded && + jQuery.css( elem, "boxSizing", false, styles ) === "border-box", subtract = extra && boxModelAdjustment( elem, dimension, @@ -357,7 +362,7 @@ jQuery.each( [ "height", "width" ], function( i, dimension ) { // 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 && support.scrollboxSize() === styles.position ) { + if ( isBorderBox && scrollBoxSize ) { subtract -= Math.ceil( elem[ "offset" + dimension[ 0 ].toUpperCase() + dimension.slice( 1 ) ] - parseFloat( styles[ dimension ] ) - From 899c56f6ada26821e8af12d9f35fa039100e838e Mon Sep 17 00:00:00 2001 From: tmybr11 Date: Tue, 17 Apr 2018 18:29:11 -0300 Subject: [PATCH 10/83] Event: Add "code" property to Event object Fixes gh-3978 Closes gh-3998 --- src/event.js | 1 + 1 file changed, 1 insertion(+) diff --git a/src/event.js b/src/event.js index 6cbe774baf..0bf481b163 100644 --- a/src/event.js +++ b/src/event.js @@ -616,6 +616,7 @@ jQuery.each( { shiftKey: true, view: true, "char": true, + code: true, charCode: true, key: true, keyCode: true, From 9a5b3b6ed0803d816984718de23d6af451260c89 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Go=C5=82e=CC=A8biowski-Owczarek?= Date: Mon, 23 Apr 2018 14:16:21 +0200 Subject: [PATCH 11/83] Tests: ensure support tests are failed by at least one tested browser A whitelist is available so that some tests can be allowed to always succeed. This is used only for ajax for now as it can be manually disabled in IE but is enabled by default. Closes gh-4052 --- test/unit/support.js | 458 ++++++++++++++++++++++++------------------- 1 file changed, 253 insertions(+), 205 deletions(-) diff --git a/test/unit/support.js b/test/unit/support.js index a42a129f11..1990679757 100644 --- a/test/unit/support.js +++ b/test/unit/support.js @@ -56,227 +56,241 @@ testIframe( ( function() { var expected, - userAgent = window.navigator.userAgent; + userAgent = window.navigator.userAgent, + expectedMap = { + edge: { + "ajax": true, + "boxSizingReliable": true, + "checkClone": true, + "checkOn": true, + "clearCloneStyle": true, + "cors": true, + "createHTMLDocument": true, + "focusin": false, + "noCloneChecked": true, + "optSelected": true, + "pixelBoxStyles": true, + "pixelPosition": true, + "radioValue": true, + "reliableMarginLeft": true, + "scrollboxSize": true + }, + ie_10_11: { + "ajax": true, + "boxSizingReliable": false, + "checkClone": true, + "checkOn": true, + "clearCloneStyle": false, + "cors": true, + "createHTMLDocument": true, + "focusin": 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, + "focusin": true, + "noCloneChecked": false, + "optSelected": false, + "pixelBoxStyles": true, + "pixelPosition": true, + "radioValue": false, + "reliableMarginLeft": true, + "scrollboxSize": "absolute" + }, + chrome: { + "ajax": true, + "boxSizingReliable": true, + "checkClone": true, + "checkOn": true, + "clearCloneStyle": true, + "cors": true, + "createHTMLDocument": true, + "focusin": false, + "noCloneChecked": true, + "optSelected": true, + "pixelBoxStyles": true, + "pixelPosition": true, + "radioValue": true, + "reliableMarginLeft": true, + "scrollboxSize": true + }, + safari_11: { + "ajax": true, + "boxSizingReliable": true, + "checkClone": true, + "checkOn": true, + "clearCloneStyle": true, + "cors": true, + "createHTMLDocument": true, + "focusin": false, + "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, + "focusin": false, + "noCloneChecked": true, + "optSelected": true, + "pixelBoxStyles": false, + "pixelPosition": false, + "radioValue": true, + "reliableMarginLeft": true, + "scrollboxSize": true + }, + firefox: { + "ajax": true, + "boxSizingReliable": true, + "checkClone": true, + "checkOn": true, + "clearCloneStyle": true, + "cors": true, + "createHTMLDocument": true, + "focusin": false, + "noCloneChecked": true, + "optSelected": true, + "pixelBoxStyles": true, + "pixelPosition": true, + "radioValue": true, + "reliableMarginLeft": false, + "scrollboxSize": true + }, + ios_11: { + "ajax": true, + "boxSizingReliable": true, + "checkClone": true, + "checkOn": true, + "clearCloneStyle": true, + "cors": true, + "createHTMLDocument": true, + "focusin": false, + "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, + "focusin": false, + "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, + "focusin": 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, + "focusin": false, + "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, + "focusin": false, + "noCloneChecked": true, + "optSelected": true, + "pixelBoxStyles": false, + "pixelPosition": false, + "radioValue": true, + "reliableMarginLeft": false, + "scrollboxSize": true + } + }; if ( /edge\//i.test( userAgent ) ) { - expected = { - "ajax": true, - "boxSizingReliable": true, - "checkClone": true, - "checkOn": true, - "clearCloneStyle": true, - "cors": true, - "createHTMLDocument": true, - "focusin": false, - "noCloneChecked": true, - "optSelected": true, - "pixelBoxStyles": true, - "pixelPosition": true, - "radioValue": true, - "reliableMarginLeft": true, - "scrollboxSize": true - }; + expected = expectedMap.edge; } else if ( /(msie 10\.0|trident\/7\.0)/i.test( userAgent ) ) { - expected = { - "ajax": true, - "boxSizingReliable": false, - "checkClone": true, - "checkOn": true, - "clearCloneStyle": false, - "cors": true, - "createHTMLDocument": true, - "focusin": true, - "noCloneChecked": false, - "optSelected": false, - "pixelBoxStyles": true, - "pixelPosition": true, - "radioValue": false, - "reliableMarginLeft": true, - "scrollboxSize": true - }; + expected = expectedMap.ie_10_11; } else if ( /msie 9\.0/i.test( userAgent ) ) { - expected = { - "ajax": true, - "boxSizingReliable": false, - "checkClone": true, - "checkOn": true, - "clearCloneStyle": false, - "cors": false, - "createHTMLDocument": true, - "focusin": true, - "noCloneChecked": false, - "optSelected": false, - "pixelBoxStyles": true, - "pixelPosition": true, - "radioValue": false, - "reliableMarginLeft": true, - "scrollboxSize": "absolute" - }; + expected = expectedMap.ie_9; } else if ( /chrome/i.test( userAgent ) ) { // Catches Chrome on Android as well (i.e. the default // Android browser on Android >= 4.4). - expected = { - "ajax": true, - "boxSizingReliable": true, - "checkClone": true, - "checkOn": true, - "clearCloneStyle": true, - "cors": true, - "createHTMLDocument": true, - "focusin": false, - "noCloneChecked": true, - "optSelected": true, - "pixelBoxStyles": true, - "pixelPosition": true, - "radioValue": true, - "reliableMarginLeft": true, - "scrollboxSize": true - }; + expected = expectedMap.chrome; } else if ( /\b11\.\d(\.\d+)* safari/i.test( userAgent ) ) { - expected = { - "ajax": true, - "boxSizingReliable": true, - "checkClone": true, - "checkOn": true, - "clearCloneStyle": true, - "cors": true, - "createHTMLDocument": true, - "focusin": false, - "noCloneChecked": true, - "optSelected": true, - "pixelBoxStyles": true, - "pixelPosition": true, - "radioValue": true, - "reliableMarginLeft": true, - "scrollboxSize": true - }; + expected = expectedMap.safari_11; } else if ( /\b(?:9|10)\.\d(\.\d+)* safari/i.test( userAgent ) ) { - expected = { - "ajax": true, - "boxSizingReliable": true, - "checkClone": true, - "checkOn": true, - "clearCloneStyle": true, - "cors": true, - "createHTMLDocument": true, - "focusin": false, - "noCloneChecked": true, - "optSelected": true, - "pixelBoxStyles": false, - "pixelPosition": false, - "radioValue": true, - "reliableMarginLeft": true, - "scrollboxSize": true - }; + expected = expectedMap.safari_9_10; } else if ( /firefox/i.test( userAgent ) ) { - expected = { - "ajax": true, - "boxSizingReliable": true, - "checkClone": true, - "checkOn": true, - "clearCloneStyle": true, - "cors": true, - "createHTMLDocument": true, - "focusin": false, - "noCloneChecked": true, - "optSelected": true, - "pixelBoxStyles": true, - "pixelPosition": true, - "radioValue": true, - "reliableMarginLeft": false, - "scrollboxSize": true - }; + expected = expectedMap.firefox; } else if ( /iphone os 11_/i.test( userAgent ) ) { - expected = { - "ajax": true, - "boxSizingReliable": true, - "checkClone": true, - "checkOn": true, - "clearCloneStyle": true, - "cors": true, - "createHTMLDocument": true, - "focusin": false, - "noCloneChecked": true, - "optSelected": true, - "pixelBoxStyles": true, - "pixelPosition": true, - "radioValue": true, - "reliableMarginLeft": true, - "scrollboxSize": true - }; + expected = expectedMap.ios_11; } else if ( /iphone os (?:9|10)_/i.test( userAgent ) ) { - expected = { - "ajax": true, - "boxSizingReliable": true, - "checkClone": true, - "checkOn": true, - "clearCloneStyle": true, - "cors": true, - "createHTMLDocument": true, - "focusin": false, - "noCloneChecked": true, - "optSelected": true, - "pixelBoxStyles": false, - "pixelPosition": false, - "radioValue": true, - "reliableMarginLeft": true, - "scrollboxSize": true - }; + expected = expectedMap.ios_9_10; } else if ( /iphone os 8_/i.test( userAgent ) ) { - expected = { - "ajax": true, - "boxSizingReliable": true, - "checkClone": true, - "checkOn": true, - "clearCloneStyle": true, - "cors": true, - "createHTMLDocument": false, - "focusin": false, - "noCloneChecked": true, - "optSelected": true, - "pixelBoxStyles": false, - "pixelPosition": false, - "radioValue": true, - "reliableMarginLeft": true, - "scrollboxSize": true - }; + expected = expectedMap.ios_8; } else if ( /iphone os 7_/i.test( userAgent ) ) { - expected = { - "ajax": true, - "boxSizingReliable": true, - "checkClone": true, - "checkOn": true, - "clearCloneStyle": true, - "cors": true, - "createHTMLDocument": true, - "focusin": false, - "noCloneChecked": true, - "optSelected": true, - "pixelBoxStyles": false, - "pixelPosition": false, - "radioValue": true, - "reliableMarginLeft": true, - "scrollboxSize": true - }; + expected = expectedMap.ios_7; } else if ( /android 4\.[0-3]/i.test( userAgent ) ) { - expected = { - "ajax": true, - "boxSizingReliable": true, - "checkClone": false, - "checkOn": false, - "clearCloneStyle": true, - "cors": true, - "createHTMLDocument": true, - "focusin": false, - "noCloneChecked": true, - "optSelected": true, - "pixelBoxStyles": false, - "pixelPosition": false, - "radioValue": true, - "reliableMarginLeft": false, - "scrollboxSize": true - }; + expected = expectedMap.android; } QUnit.test( "Verify that support tests resolve as expected per browser", function( assert ) { @@ -305,4 +319,38 @@ testIframe( } } ); + QUnit.test( "Verify most support tests are failing in one " + + "of tested browsers", function( assert ) { + + var prop, browserKey, supportTestName, + i = 0, + supportProps = {}, + failingSupportProps = {}, + whitelist = { + ajax: true + }; + + for ( prop in computedSupport ) { + i++; + } + + 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. + for ( browserKey in expectedMap ) { + for ( supportTestName in expectedMap[ browserKey ] ) { + supportProps[ supportTestName ] = true; + if ( expectedMap[ browserKey ][ supportTestName ] !== true ) { + failingSupportProps[ supportTestName ] = true; + } + } + } + + for ( supportTestName in supportProps ) { + assert.ok( whitelist[ supportTestName ] || failingSupportProps[ supportTestName ], + "jQuery.support['" + supportTestName + "'] always succeeds; remove it?" ); + } + } ); + } )(); From 76468365779c2d07c7f25ded141e99bad97f78a7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Go=C5=82=C4=99biowski-Owczarek?= Date: Wed, 25 Apr 2018 09:55:38 +0200 Subject: [PATCH 12/83] Build: Test on Node 10, stop testing on Node 4 & 9 Node.js 4 & 9 are ending their life, Node.js 10 has just been released. Closes gh-4057 --- .travis.yml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index 4fa82ae7ac..4de56ec5f8 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,10 +1,9 @@ language: node_js sudo: false node_js: -- "4" - "6" - "8" -- "9" +- "10" addons: chrome: stable env: From f5e36bd8f2c2b28231bbed926c6c3dead94db545 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Go=C5=82=C4=99biowski-Owczarek?= Date: Mon, 30 Apr 2018 18:52:39 +0200 Subject: [PATCH 13/83] CSS: Skip the px-appending logic for animations of non-element props Without this change animating properties from jQuery.cssNumber on non-elements throws an error. Ref gh-4055 Closes gh-4061 --- src/css/adjustCSS.js | 3 ++- test/unit/effects.js | 11 +++++++++++ 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/src/css/adjustCSS.js b/src/css/adjustCSS.js index 626ec74758..8898789a7b 100644 --- a/src/css/adjustCSS.js +++ b/src/css/adjustCSS.js @@ -19,7 +19,8 @@ function adjustCSS( elem, prop, valueParts, tween ) { unit = valueParts && valueParts[ 3 ] || ( jQuery.cssNumber[ prop ] ? "" : "px" ), // Starting value computation is required for potential unit mismatches - initialInUnit = ( jQuery.cssNumber[ prop ] || unit !== "px" && +initial ) && + initialInUnit = elem.nodeType && + ( jQuery.cssNumber[ prop ] || unit !== "px" && +initial ) && rcssNum.exec( jQuery.css( elem, prop ) ); if ( initialInUnit && initialInUnit[ 3 ] !== unit ) { diff --git a/test/unit/effects.js b/test/unit/effects.js index 462524ef37..e297273e46 100644 --- a/test/unit/effects.js +++ b/test/unit/effects.js @@ -607,6 +607,17 @@ QUnit.test( "animate non-element", function( assert ) { this.clock.tick( 200 ); } ); +QUnit.test( "animate non-element's zIndex without appending \"px\"", function( assert ) { + assert.expect( 1 ); + + var obj = { zIndex: 0 }; + + jQuery( obj ).animate( { zIndex: 200 }, 200, function() { + assert.equal( obj.zIndex, 200, "The custom property should be modified without appending \"px\"." ); + } ); + this.clock.tick( 200 ); +} ); + QUnit.test( "stop()", function( assert ) { assert.expect( 4 ); From f8c1e9020c8fd0f0bb83019bfb12e9a7099599b2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Go=C5=82=C4=99biowski-Owczarek?= Date: Wed, 2 May 2018 17:08:20 +0200 Subject: [PATCH 14/83] CSS: Ensure camel- vs kebab-cased names are not collapsed for CSS vars Closes gh-4062 --- test/unit/css.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/test/unit/css.js b/test/unit/css.js index 29fa709067..fbb42c3011 100644 --- a/test/unit/css.js +++ b/test/unit/css.js @@ -1632,10 +1632,12 @@ QUnit.test( "Do not throw on frame elements from css method (#15098)", function( assert.equal( div.css( "--color" ), "red", "Modified CSS custom property using object" ); div.css( { "--mixedCase": "green" } ); + div.css( { "--mixed-case": "red" } ); assert.equal( div.css( "--mixedCase" ), "green", "Modified CSS custom property with mixed case" ); div.css( { "--theme-dark": "purple" } ); + div.css( { "--themeDark": "red" } ); assert.equal( div.css( "--theme-dark" ), "purple", "Modified CSS custom property with dashed name" ); From 821bf34353a6baf97f7944379a6459afb16badae Mon Sep 17 00:00:00 2001 From: Richard Gibson Date: Mon, 7 May 2018 09:28:18 -0400 Subject: [PATCH 15/83] CSS: Correctly detect scrollbox support with non-default zoom Fixes gh-4029 Closes gh-4030 --- src/css.js | 16 +++++++++------- src/css/support.js | 4 +++- test/data/css/cssWidthBrowserZoom.html | 6 +++++- test/unit/css.js | 7 ++++--- 4 files changed, 21 insertions(+), 12 deletions(-) diff --git a/src/css.js b/src/css.js index ea73020121..e936c8f30e 100644 --- a/src/css.js +++ b/src/css.js @@ -352,13 +352,15 @@ jQuery.each( [ "height", "width" ], function( i, dimension ) { boxSizingNeeded = scrollBoxSize || extra, isBorderBox = boxSizingNeeded && jQuery.css( elem, "boxSizing", false, styles ) === "border-box", - subtract = extra && boxModelAdjustment( - elem, - dimension, - extra, - isBorderBox, - styles - ); + subtract = extra ? + boxModelAdjustment( + elem, + dimension, + extra, + isBorderBox, + styles + ) : + 0; // Account for unreliable border-box dimensions by comparing offset* to computed and // faking a content-box to get border and padding (gh-3699) diff --git a/src/css/support.js b/src/css/support.js index dbb7ef7ce1..12706f7e9a 100644 --- a/src/css/support.js +++ b/src/css/support.js @@ -43,8 +43,10 @@ define( [ // 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 = div.offsetWidth === 36 || "absolute"; + scrollboxSizeVal = roundPixelMeasures( div.offsetWidth / 3 ) === 12 || "absolute"; documentElement.removeChild( container ); diff --git a/test/data/css/cssWidthBrowserZoom.html b/test/data/css/cssWidthBrowserZoom.html index 99f87ea292..133daf6220 100644 --- a/test/data/css/cssWidthBrowserZoom.html +++ b/test/data/css/cssWidthBrowserZoom.html @@ -7,6 +7,7 @@ zoom: 1.1; } #test { + position: absolute; width: 100px; height: 100px; padding: 10px; @@ -20,7 +21,10 @@ diff --git a/test/unit/css.js b/test/unit/css.js index fbb42c3011..626981b7d8 100644 --- a/test/unit/css.js +++ b/test/unit/css.js @@ -1167,9 +1167,10 @@ testIframe( testIframe( "css('width') should work correctly with browser zooming", "css/cssWidthBrowserZoom.html", - function( assert, jQuery, window, document, cssWidthBrowserZoom ) { - assert.expect( 1 ); - assert.strictEqual( cssWidthBrowserZoom, "100px", "elem.css('width') works correctly with browser zoom" ); + function( assert, jQuery, window, document, widthBeforeSet, widthAfterSet ) { + assert.expect( 2 ); + assert.strictEqual( widthBeforeSet, "100px", "elem.css('width') works correctly with browser zoom" ); + assert.strictEqual( widthAfterSet, "100px", "elem.css('width', val) works correctly with browser zoom" ); } ); From 0ba8e38d0c4ab4a4fb9054e7a713630be9743aff Mon Sep 17 00:00:00 2001 From: Luis Emilio Velasco Sanchez Date: Mon, 14 May 2018 13:36:30 -0400 Subject: [PATCH 16/83] Traversing: $.fn.contents() support for object Fixes gh-4045 Closes gh-4046 --- Gruntfile.js | 2 +- src/traversing.js | 24 ++++----- test/data/1x1.svg | 6 +++ test/data/frame.html | 9 ++++ test/unit/traversing.js | 106 ++++++++++++++++++++++++++-------------- 5 files changed, 96 insertions(+), 51 deletions(-) create mode 100644 test/data/1x1.svg create mode 100644 test/data/frame.html diff --git a/Gruntfile.js b/Gruntfile.js index fbf9b56717..ed2bd77537 100644 --- a/Gruntfile.js +++ b/Gruntfile.js @@ -209,7 +209,7 @@ module.exports = function( grunt ) { { pattern: "dist/*.map", included: false, served: true }, { pattern: "external/qunit/qunit.css", included: false, served: true }, { - pattern: "test/**/*.@(js|css|jpg|html|xml)", + pattern: "test/**/*.@(js|css|jpg|html|xml|svg)", included: false, served: true } diff --git a/src/traversing.js b/src/traversing.js index 64c7252b9f..426d5b6ea3 100644 --- a/src/traversing.js +++ b/src/traversing.js @@ -145,18 +145,18 @@ jQuery.each( { return siblings( elem.firstChild ); }, contents: function( elem ) { - if ( nodeName( elem, "iframe" ) ) { - return elem.contentDocument; - } - - // Support: IE 9 - 11 only, iOS 7 only, Android Browser <=4.3 only - // Treat the template element as a regular one in browsers that - // don't support it. - if ( nodeName( elem, "template" ) ) { - elem = elem.content || elem; - } - - return jQuery.merge( [], elem.childNodes ); + if ( typeof elem.contentDocument !== "undefined" ) { + return elem.contentDocument; + } + + // Support: IE 9 - 11 only, iOS 7 only, Android Browser <=4.3 only + // Treat the template element as a regular one in browsers that + // don't support it. + if ( nodeName( elem, "template" ) ) { + elem = elem.content || elem; + } + + return jQuery.merge( [], elem.childNodes ); } }, function( name, fn ) { jQuery.fn[ name ] = function( until, selector ) { diff --git a/test/data/1x1.svg b/test/data/1x1.svg new file mode 100644 index 0000000000..70b3e7412b --- /dev/null +++ b/test/data/1x1.svg @@ -0,0 +1,6 @@ + + + + diff --git a/test/data/frame.html b/test/data/frame.html new file mode 100644 index 0000000000..98107be1d8 --- /dev/null +++ b/test/data/frame.html @@ -0,0 +1,9 @@ + + + frame + + + + + + diff --git a/test/unit/traversing.js b/test/unit/traversing.js index dd05541378..9ba66959e6 100644 --- a/test/unit/traversing.js +++ b/test/unit/traversing.js @@ -744,56 +744,86 @@ QUnit.test( "contents()", function( assert ) { } ); QUnit.test( "contents() for