Jump to content

MediaWiki Engineering/Runbook/Module source

From Wikitech

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);
};