Jump to content

MediaWiki Engineering/Runbook/Module source

From Wikitech
The printable version is no longer supported and may have rendering errors. Please update your browser bookmarks and please use the default browser print function instead.

View source

This snippet shows how to get the source code of a module from a web browser, for a module registered on that page.

mw.loader._getSource = function ( module ) {
	if ( !mw.loader.getState( module ) ) {
		console.warn( 'Unknown module: ' + module );
		return false;
	}
	var path = mw.util.wikiScript('load') + '?' + $.param({
		debug: true,
		only: 'scripts',
		modules: module,
		lang: mw.config.get('wgUserLanguage'),
		skin: mw.config.get('skin'),
		raw: 1
	});
	console.log( new URL( path, location ).href );
	$.ajax( { url: path, dataType: 'text' } ).then( function ( data ) {
		console.log( data );
	} );
};

Find dependencies

Run the below snippet from the console (or save it to Special:Mypage/global.js).

/**
 * Find where and how a certain module is used.
 *
 * This finds which modules depend or load a given module.
 *
 * The first array are modules that directly depend on the given module.
 *
 * The second and third array represent higher-level features that are probably
 * more recognisable and well-known, which use the module indirectly through
 * a dependency on a module in the previous array.
 *
 * Usage:
 *
 *   mw.loader.findAll('mediawiki.util')
 *   //> 0: [ modules that load mediawiki.util ]
 *   //> 1: [ modules that load one of the modules in 0 ]
 *   //> 2: [ modules that load one of the modules in 1 ]
 *
 * @source https://wikitech.wikimedia.org/wiki/MediaWiki_Engineering/Runbook/Module_source
 *
 * @param {string} needle Module name, part of a module name, or a part of the module's script content.
 * @param {Object} [options]
 * @param {string|undefined} [options.state] Only consider modules having this state on the current page.
 * @param {boolean} [options.strict=false] If true, needle is only used to find exact module names.
 * @return {Array} An array of arrays. The first array contains the modules that directly contain or depend on `needle`, the second array contains modules containing or depending on modules from the first array, and so on.
 */
mw.loader.findAll = function findAll(needle, options) {
	var depth = 0;
	var seen = [];
	var ret = [];
	var prev;
	var results;
	function find(needle) {
		return mw.loader.getModuleNames().filter(function (moduleName) {
			var obj = mw.loader.moduleRegistry[moduleName];
			if (moduleName === needle) {
				return false;
			}
			if (options && options.state && obj.state !== options.state) {
				return false;
			}
			if (!options || !options.strict) {
				// Loose matching in the scripts' contents.
				if (obj.script && obj.script.toString().indexOf(needle) !== -1) {
					return true;
				}
			}
			// Direct dependencies
			return obj.dependencies.indexOf(needle) !== -1;
		});
	}
	while (depth < 3) {
		depth++;
		if (!prev) {
			results = find(needle);
			ret.push(results);
			seen.push.apply(seen, results);
		} else {
			results = [];
			prev.slice().forEach(function (result) {
				var subResults = find(result).filter(function (item) {
					return seen.indexOf(item) === -1;
				});
				results.push.apply(results, subResults);
				seen.push.apply(seen, subResults);
			});
			ret.push(results);
		}
		prev = results;
	}
	return ret;
};

/**
 * Like findAll(), but only considering dependencies of modules loaded on the current page.
 *
 * Useful for tracing warnings, such as "This page is using the deprecated module <name>."
 *
 * @source https://wikitech.wikimedia.org/wiki/MediaWiki_Engineering/Runbook/Module_source
 * @param {string} needle Module name
 * @param {Object} [options]
 * @return {Array}
 */
mw.loader.findReady = function findReady(needle, options) {
	var allOptions = Object.create(options || null);
	allOptions.state = 'ready';
	allOptions.strict = true;
	return mw.loader.findAll(needle, allOptions);
};