From b09b82a0d12df736bce83f6f898e9a374f4a53c4 Mon Sep 17 00:00:00 2001 From: Trevor Parscal Date: Fri, 22 Jun 2012 11:39:10 -0700 Subject: [PATCH] (bug 37708) mw.Uri.clone() should make a deep copy. Copies query properties (or any other object or array property) over with a deep copy by value. Change-Id: I1c5644409c089e0a864292b8bd5a757ac31daa89 --- RELEASE-NOTES-1.20 | 1 + resources/mediawiki/mediawiki.Uri.js | 18 +++++++++++++----- .../resources/mediawiki/mediawiki.Uri.test.js | 18 +++++++++++++----- 3 files changed, 27 insertions(+), 10 deletions(-) diff --git a/RELEASE-NOTES-1.20 b/RELEASE-NOTES-1.20 index 1577b149b6..e79dce2e9b 100644 --- a/RELEASE-NOTES-1.20 +++ b/RELEASE-NOTES-1.20 @@ -126,6 +126,7 @@ upgrade PHP if you have not done so prior to upgrading MediaWiki. * (bug 27283) SqlBagOStuff breaks PostgreSQL transactions. * (bug 35727) mw.Api ajax() should put token parameter last. * (bug 260) Handle
 overflow automatically with a scroll bar.
+* (bug 37708) mw.Uri.clone() should make a deep copy.
 
 === API changes in 1.20 ===
 * (bug 34316) Add ability to retrieve maximum upload size from MediaWiki API.
diff --git a/resources/mediawiki/mediawiki.Uri.js b/resources/mediawiki/mediawiki.Uri.js
index e8a01188dc..b871ac71e4 100644
--- a/resources/mediawiki/mediawiki.Uri.js
+++ b/resources/mediawiki/mediawiki.Uri.js
@@ -121,11 +121,19 @@
 				if ( typeof uri === 'string' ) {
 					this.parse( uri, options );
 				} else if ( typeof uri === 'object' ) {
-					var uriObj = this;
-					$.each( properties, function ( i, property ) {
-						uriObj[property] = uri[property];
-					} );
-					if ( this.query === undefined ) {
+					// Copy data over from existing URI object
+					for ( var prop in uri ) {
+						// Only copy direct properties, not inherited ones
+						if ( uri.hasOwnProperty( prop ) ) {
+							// Deep copy object properties
+							if ( $.isArray( uri[prop] ) || $.isPlainObject( uri[prop] ) ) {
+								this[prop] = $.extend( true, {}, uri[prop] );
+							} else {
+								this[prop] = uri[prop];
+							}
+						}
+					}
+					if ( !this.query ) {
 						this.query = {};
 					}
 				}
diff --git a/tests/qunit/suites/resources/mediawiki/mediawiki.Uri.test.js b/tests/qunit/suites/resources/mediawiki/mediawiki.Uri.test.js
index b834aeb6f3..9913fb9b25 100644
--- a/tests/qunit/suites/resources/mediawiki/mediawiki.Uri.test.js
+++ b/tests/qunit/suites/resources/mediawiki/mediawiki.Uri.test.js
@@ -229,19 +229,27 @@ test( 'All-dressed URI with everything', function () {
 
 test( 'Cloning', function () {
 	var original, clone;
-	expect( 5 );
+	expect( 6 );
 
-	original = new mw.Uri( 'http://en.wiki.local/w/api.php?action=query&foo=bar' );
+	original = new mw.Uri( 'http://foo.example.org/index.php?one=1&two=2' );
 	clone = original.clone();
 
 	deepEqual( clone, original, 'clone has equivalent properties' );
 	equal( original.toString(), clone.toString(), 'toString matches original' );
 
-	notStrictEqual( clone, original, 'clone is not the same when compared by reference' );
+	notStrictEqual( clone, original, 'clone is a different object when compared by reference' );
 
-	clone.host = 'fr.wiki.local';
+	clone.host = 'bar.example.org';
 	notEqual( original.host, clone.host, 'manipulating clone did not effect original' );
-	notEqual( original.toString(), clone.toString(), 'toString no longer matches original' );
+	notEqual( original.toString(), clone.toString(), 'Stringified url no longer matches original' );
+
+	clone.query.three = 3;
+
+	deepEqual(
+		original.query,
+		{ 'one': '1', 'two': '2' },
+		'Properties is deep cloned (bug 37708)'
+	);
 } );
 
 test( 'Constructing mw.Uri from plain object', function () {
-- 
2.20.1