Merge "Disable JSONP cache breaking in jQuery"

This commit is contained in:
jenkins-bot 2014-05-01 09:50:32 +00:00 committed by Gerrit Code Review
commit 553a9f142d
2 changed files with 42 additions and 0 deletions

View file

@ -68,6 +68,8 @@
if ( repoInfo.apiUrl ) { if ( repoInfo.apiUrl ) {
ajaxOptions.url = repoInfo.apiUrl; ajaxOptions.url = repoInfo.apiUrl;
ajaxOptions.dataType = 'jsonp'; ajaxOptions.dataType = 'jsonp';
ajaxOptions.cache = true; // do not append `_=<timestamp>` to the URL
ajaxOptions.jsonpCallback = this.getCallbackName( username );
cacheKey = cacheKey + '|' + repoInfo.apiUrl; // local and remote user names could conflict cacheKey = cacheKey + '|' + repoInfo.apiUrl; // local and remote user names could conflict
} }
@ -90,5 +92,23 @@
} ); } );
}; };
/**,
* Generate JSONP callback function name.
* jQuery uses a random string by default, which would break caching.
* On the other hand the callback needs to be unique to avoid surprises when multiple
* requests run in parallel. And of course needs to be a valid JS variable name.
* @param username
*/
UserInfo.prototype.getCallbackName = function ( username ) {
// Javascript variable name charset rules are fairly lax but better safe then sorry,
// so let's encode every non-alphanumeric character.
// Per http://stackoverflow.com/questions/1809153/maximum-length-of-variable-name-in-javascript
// length should not be an issue (might add a few hundred bytes to the request & response size
// for very long usernames, but we can live with that).
return 'mmv_userinfo_' + mw.util.rawurlencode( username )// encodes all characters except -.~_
.replace( /-/g, '%2D' ).replace( /\./g, '%2E' ).replace( /~/g, '%7E' ).replace( /_/g, '%5F' )
.replace( /%/g, '_' );
};
mw.mmv.provider.UserInfo = UserInfo; mw.mmv.provider.UserInfo = UserInfo;
}( mediaWiki, jQuery, OO ) ); }( mediaWiki, jQuery, OO ) );

View file

@ -163,4 +163,26 @@
QUnit.start(); QUnit.start();
} ); } );
} ); } );
QUnit.test( 'getCallbackName()', 6, function ( assert ) {
var userInfoProvider = new mw.mmv.provider.UserInfo( {} );
function assertValidVariableName( username ) {
/*jshint evil:true */
var varName = userInfoProvider.getCallbackName( username );
try {
eval( 'var ' + varName + ';');
assert.ok( true, 'Variable name ' + varName + ' generated from ' + username + ' is valid' );
} catch ( e ) {
assert.ok( false, 'Variable name ' + varName + ' generated from ' + username + ' is invalid' );
}
}
assertValidVariableName( 'simple' );
assertValidVariableName( 'Help! I have spaces!' );
assertValidVariableName( 'oh_noes_i_has_underline' );
assertValidVariableName( '$\'"+!%/=()[]{}:;<>,.?|' );
assertValidVariableName( 'イチカワ エツヤ' );
assertValidVariableName( new Array( 256 ).join( 'イ' ) ); // longest possible name, 255*2 bytes
} );
}( mediaWiki, jQuery ) ); }( mediaWiki, jQuery ) );