Chris@18: /** Chris@18: * For jQuery versions less than 3.4.0, this replaces the jQuery.extend Chris@18: * function with the one from jQuery 3.4.0, slightly modified (documented Chris@18: * below) to be compatible with older jQuery versions. Chris@18: * Chris@18: * This provides the Object.prototype pollution vulnerability fix to Drupal Chris@18: * installations running older jQuery versions, including the version (3.2.1) Chris@18: * shipped with Drupal core. Chris@18: * Chris@18: * @see https://github.com/jquery/jquery/pull/4333 Chris@18: */ Chris@18: Chris@18: (function (jQuery) { Chris@18: Chris@18: // Do not override jQuery.extend() if the jQuery version is already >=3.4.0. Chris@18: var versionParts = jQuery.fn.jquery.split('.'); Chris@18: var majorVersion = parseInt(versionParts[0]); Chris@18: var minorVersion = parseInt(versionParts[1]); Chris@18: var patchVersion = parseInt(versionParts[2]); Chris@18: var isPreReleaseVersion = (patchVersion.toString() !== versionParts[2]); Chris@18: if ( Chris@18: (majorVersion > 3) || Chris@18: (majorVersion === 3 && minorVersion > 4) || Chris@18: (majorVersion === 3 && minorVersion === 4 && patchVersion > 0) || Chris@18: (majorVersion === 3 && minorVersion === 4 && patchVersion === 0 && !isPreReleaseVersion) Chris@18: ) { Chris@18: return; Chris@18: } Chris@18: Chris@18: /** Chris@18: * This is almost verbatim copied from jQuery 3.4.0. Chris@18: * Chris@18: * Only one minor change has been made: Chris@18: * - The call to isFunction() is changed to jQuery.isFunction(). Chris@18: * Chris@18: * The above change ensures compatibility with older jQuery versions, Chris@18: * including 3.2.1 which is shipped with Drupal core. Chris@18: */ Chris@18: jQuery.extend = jQuery.fn.extend = function() { Chris@18: var options, name, src, copy, copyIsArray, clone, Chris@18: target = arguments[ 0 ] || {}, Chris@18: i = 1, Chris@18: length = arguments.length, Chris@18: deep = false; Chris@18: Chris@18: // Handle a deep copy situation Chris@18: if ( typeof target === "boolean" ) { Chris@18: deep = target; Chris@18: Chris@18: // Skip the boolean and the target Chris@18: target = arguments[ i ] || {}; Chris@18: i++; Chris@18: } Chris@18: Chris@18: // Handle case when target is a string or something (possible in deep copy) Chris@18: if ( typeof target !== "object" && !jQuery.isFunction( target ) ) { Chris@18: target = {}; Chris@18: } Chris@18: Chris@18: // Extend jQuery itself if only one argument is passed Chris@18: if ( i === length ) { Chris@18: target = this; Chris@18: i--; Chris@18: } Chris@18: Chris@18: for ( ; i < length; i++ ) { Chris@18: Chris@18: // Only deal with non-null/undefined values Chris@18: if ( ( options = arguments[ i ] ) != null ) { Chris@18: Chris@18: // Extend the base object Chris@18: for ( name in options ) { Chris@18: copy = options[ name ]; Chris@18: Chris@18: // Prevent Object.prototype pollution Chris@18: // Prevent never-ending loop Chris@18: if ( name === "__proto__" || target === copy ) { Chris@18: continue; Chris@18: } Chris@18: Chris@18: // Recurse if we're merging plain objects or arrays Chris@18: if ( deep && copy && ( jQuery.isPlainObject( copy ) || Chris@18: ( copyIsArray = Array.isArray( copy ) ) ) ) { Chris@18: src = target[ name ]; Chris@18: Chris@18: // Ensure proper type for the source value Chris@18: if ( copyIsArray && !Array.isArray( src ) ) { Chris@18: clone = []; Chris@18: } else if ( !copyIsArray && !jQuery.isPlainObject( src ) ) { Chris@18: clone = {}; Chris@18: } else { Chris@18: clone = src; Chris@18: } Chris@18: copyIsArray = false; Chris@18: Chris@18: // Never move original objects, clone them Chris@18: target[ name ] = jQuery.extend( deep, clone, copy ); Chris@18: Chris@18: // Don't bring in undefined values Chris@18: } else if ( copy !== undefined ) { Chris@18: target[ name ] = copy; Chris@18: } Chris@18: } Chris@18: } Chris@18: } Chris@18: Chris@18: // Return the modified object Chris@18: return target; Chris@18: }; Chris@18: Chris@18: })(jQuery);