From: Timo Tijhof Date: Tue, 2 Dec 2014 21:07:40 +0000 (+0000) Subject: mediawiki.Uri: Implement support for a mutable defaultUri X-Git-Tag: 1.31.0-rc.0~13074^2 X-Git-Url: http://git.cyclocoop.org/%22%20.%20generer_url_ecrire%28%22statistiques_visites%22%2C%22%22%29%20.%20%22?a=commitdiff_plain;h=bece0d14c1253ae6421f842b9d98996f33be8d60;p=lhc%2Fweb%2Fwiklou.git mediawiki.Uri: Implement support for a mutable defaultUri Bug: T74334 Change-Id: Ib512774091626c810b25af03c15f84efaca1c633 --- diff --git a/resources/src/mediawiki/mediawiki.Uri.js b/resources/src/mediawiki/mediawiki.Uri.js index bb5ddfc0d8..abfb27904f 100644 --- a/resources/src/mediawiki/mediawiki.Uri.js +++ b/resources/src/mediawiki/mediawiki.Uri.js @@ -127,15 +127,29 @@ */ /** - * A factory method to create a variation of mw.Uri with a different default location (for - * relative URLs, including protocol-relative URLs). Used so the library is still testable & - * purely functional. + * A factory method to create a Uri class with a default location to resolve relative URLs + * against (including protocol-relative URLs). * * @method + * @param {string|Function} documentLocation A full url, or function returning one. + * If passed a function, the return value may change over time and this will be honoured. (T74334) * @member mw */ mw.UriRelative = function ( documentLocation ) { - var defaultUri; + var getDefaultUri = ( function () { + // Cache + var href, uri; + + return function () { + var hrefCur = typeof documentLocation === 'string' ? documentLocation : documentLocation(); + if ( href === hrefCur ) { + return uri; + } + href = hrefCur; + uri = new Uri( href ); + return uri; + }; + }() ); /** * @class mw.Uri @@ -156,6 +170,9 @@ * override each other (`true`) or automagically convert them to an array (`false`). */ function Uri( uri, options ) { + var prop, + defaultUri = getDefaultUri(); + options = typeof options === 'object' ? options : { strictMode: !!options }; options = $.extend( { strictMode: false, @@ -167,7 +184,7 @@ this.parse( uri, options ); } else if ( typeof uri === 'object' ) { // Copy data over from existing URI object - for ( var prop in uri ) { + for ( prop in uri ) { // Only copy direct properties, not inherited ones if ( uri.hasOwnProperty( prop ) ) { // Deep copy object properties @@ -390,12 +407,12 @@ } }; - defaultUri = new Uri( documentLocation ); - return Uri; }; // Default to the current browsing location (for relative URLs). - mw.Uri = mw.UriRelative( location.href ); + mw.Uri = mw.UriRelative( function () { + return location.href; + } ); }( mediaWiki, jQuery ) ); diff --git a/tests/qunit/suites/resources/mediawiki/mediawiki.Uri.test.js b/tests/qunit/suites/resources/mediawiki/mediawiki.Uri.test.js index 7a58d38ddc..ba36655382 100644 --- a/tests/qunit/suites/resources/mediawiki/mediawiki.Uri.test.js +++ b/tests/qunit/suites/resources/mediawiki/mediawiki.Uri.test.js @@ -314,6 +314,66 @@ assert.equal( uri.toString(), 'http://www.example.com/dir/', 'empty array value is ommitted' ); } ); + QUnit.test( 'Variable defaultUri', 2, function ( assert ) { + var uri, + href = 'http://example.org/w/index.php#here', + UriClass = mw.UriRelative( function () { + return href; + } ); + + uri = new UriClass(); + assert.deepEqual( + { + protocol: uri.protocol, + user: uri.user, + password: uri.password, + host: uri.host, + port: uri.port, + path: uri.path, + query: uri.query, + fragment: uri.fragment + }, + { + protocol: 'http', + user: undefined, + password: undefined, + host: 'example.org', + port: undefined, + path: '/w/index.php', + query: {}, + fragment: 'here' + }, + 'basic object properties' + ); + + // Default URI may change, e.g. via history.replaceState, pushState or location.hash (T74334) + href = 'https://example.com/wiki/Foo?v=2'; + uri = new UriClass(); + assert.deepEqual( + { + protocol: uri.protocol, + user: uri.user, + password: uri.password, + host: uri.host, + port: uri.port, + path: uri.path, + query: uri.query, + fragment: uri.fragment + }, + { + protocol: 'https', + user: undefined, + password: undefined, + host: 'example.com', + port: undefined, + path: '/wiki/Foo', + query: { 'v': '2' }, + fragment: undefined + }, + 'basic object properties' + ); + } ); + QUnit.test( 'Advanced URL', 11, function ( assert ) { var uri, queryString, relativePath; @@ -429,6 +489,5 @@ uri = new UriClass( testPath ); href = uri.toString(); assert.equal( href, testProtocol + testServer + ':' + testPort + testPath, 'Root-relative URL gets host, protocol, and port supplied' ); - } ); }( mediaWiki, jQuery ) );