r114736 MediaWiki - Code Review archive

Repository:MediaWiki
Revision:r114735‎ | r114736 | r114737 >
Date:07:58, 5 April 2012
Author:tstarling
Status:deferred
Tags:
Comment:
* Removed scriptlinks table. It just seemed the same as templatelinks to me, and tl_namespace can be used if you want to separate out modules.
* Used Parser::fetchTemplateAndTitle() to get modules and register them in templatelinks. Most of the logic was previously duplicated.
* Changed the configuration and factory functions to allow for the possibility of multiple engines coexisting on the one wiki.
* Made the $parser parameter optional, to improve debugging in the case where a parser is needed but parsing has not started. Removed all $wgParser references.
* Renamed Scripting::getEngine() to getParserEngine() and resetEngine() to resetParserEngine()
* Removed setOptions() and updateOptions(). If you want to change the options, you can always make a new instance.
* Renamed getModule() to fetchModuleFromParser()
* Simplified module constructor parameters and member variable list
* Fixed spelling error langauge -> language
* Renamed a few variables for clarity: $module -> $moduleName, $function -> $functionName
* Renamed getLimitsReport() to getLimitReport() as it is in Parser
* Use an accessor for getting LuaSandboxEngineModule::$contents
* Renamed configuration variable maxCPU to cpuLimit
* Include the full message name as a parameter to ScriptingException. This makes it easier to find messages in the i18n file, and it makes it easier to find invocation points when a translator wants to know how a message is used. Adding the message name as a comment on the same line seems like a waste of space when you can just make it an actual parameter.
* Reduce the number of formal parameters to ScriptingException::__construct(), since there is already too many and we may want to add more things later, such as backtraces with hyperlinks and other such stuff.
* Include the code location as $2 unconditionally so that there is less chance of getting the parameters wrong
* Shortened some message names. Wrote English text for messages without it.
Modified paths:
  • /trunk/extensions/Scripting/Scripting.i18n.php (modified) (history)
  • /trunk/extensions/Scripting/Scripting.php (modified) (history)
  • /trunk/extensions/Scripting/common/Base.php (modified) (history)
  • /trunk/extensions/Scripting/common/Common.php (modified) (history)
  • /trunk/extensions/Scripting/common/Hooks.php (modified) (history)
  • /trunk/extensions/Scripting/common/LinkUpdates.php (deleted) (history)
  • /trunk/extensions/Scripting/engines/LuaSandbox/Engine.php (modified) (history)
  • /trunk/extensions/Scripting/scripting.sql (deleted) (history)

Diff [purge]

Index: trunk/extensions/Scripting/scripting.sql
@@ -1,16 +0,0 @@
2 -CREATE TABLE /*_*/scriptlinks (
3 - -- Key to the page_id of the page containing the link.
4 - sl_from int unsigned NOT NULL default 0,
5 -
6 - -- Key to page_title of the target page.
7 - -- The target page may or may not exist, and due to renames
8 - -- and deletions may refer to different page records as time
9 - -- goes by.
10 - sl_to varchar(255) binary NOT NULL default ''
11 -) /*$wgDBTableOptions*/;
12 -
13 -CREATE UNIQUE INDEX /*i*/sl_from ON /*_*/scriptlinks (sl_from,sl_to);
14 -CREATE UNIQUE INDEX /*i*/sl_title ON /*_*/scriptlinks (sl_to,sl_from);
Index: trunk/extensions/Scripting/Scripting.i18n.php
@@ -13,7 +13,13 @@
1414 */
1515 $messages['en'] = array(
1616 'scripting-desc' => 'Framework for embedding scripting languages into MediaWiki pages',
17 -
18 - 'scripting-exception-luasandbox-error' => 'Lua error: $1',
19 - 'scripting-exception-common-toofewargs' => 'Lua error: Too few arguments to function $1',
 17+ 'scripting-codelocation' => 'in $1 at line $2',
 18+ 'scripting-luasandbox-error' => 'Lua error: $2',
 19+ 'scripting-common-toofewargs' => 'Lua error: Too few arguments to function $2',
 20+ 'scripting-common-nosuchmodule' => 'Script error: No such module',
 21+ 'scripting-luasandbox-noreturn' => 'Script error: The module did not return a value, it should return an export table.',
 22+ 'scripting-luasandbox-toomanyreturns' => 'Script error: The module returned multiple values, it should return an export table.',
 23+ 'scripting-luasandbox-notarrayreturn' => 'Script error: The module returned something other than a table, it should return an export table.',
 24+ 'scripting-common-nofunction' => 'Script error: You must specify a function to call.',
 25+ 'scripting-common-nosuchfunction' => 'Script error: The function you specified did not exist.',
2026 );
Index: trunk/extensions/Scripting/Scripting.php
@@ -40,48 +40,41 @@
4141 $wgAutoloadClasses['ScriptingModuleBase'] = $dir.'common/Base.php';
4242 $wgAutoloadClasses['ScriptingFunctionBase'] = $dir.'common/Base.php';
4343 $wgAutoloadClasses['ScriptingHooks'] = $dir.'common/Hooks.php';
44 -$wgAutoloadClasses['ScriptLinksUpdateHooks'] = $dir.'common/LinkUpdates.php';
4544 $wgAutoloadClasses['ScriptingException'] = $dir.'common/Common.php';
4645 $wgAutoloadClasses['Scripting'] = $dir.'common/Common.php';
4746
4847 $wgHooks['ParserFirstCallInit'][] = 'ScriptingHooks::setupParserHook';
4948 $wgHooks['ParserLimitReport'][] = 'ScriptingHooks::reportLimits';
5049 $wgHooks['ParserClearState'][] = 'ScriptingHooks::clearState';
51 -$wgHooks['ParserTestTables'][] = 'ScriptingHooks::addTestTables';
5250
5351 $wgHooks['CanonicalNamespaces'][] = 'ScriptingHooks::addCanonicalNamespaces';
5452 $wgHooks['ArticleViewCustom'][] = 'ScriptingHooks::handleScriptView';
5553 $wgHooks['TitleIsWikitextPage'][] = 'ScriptingHooks::isWikitextPage';
56 -$wgHooks['CodeEditorGetPageLanguage'][] = 'ScriptingHooks::getCodeLangauge';
 54+$wgHooks['CodeEditorGetPageLanguage'][] = 'ScriptingHooks::getCodeLanguage';
5755 $wgHooks['EditFilter'][] = 'ScriptingHooks::validateScript';
5856
59 -$wgHooks['LinksUpdate'][] = 'ScriptLinksUpdateHooks::updateLinks';
60 -$wgHooks['ArticleEditUpdates'][] = 'ScriptLinksUpdateHooks::purgeCache';
61 -$wgHooks['ParserAfterTidy'][] = 'ScriptLinksUpdateHooks::appendToOutput';
62 -$wgHooks['BacklinkCacheGetPrefix'][] = 'ScriptLinksUpdateHooks::getBacklinkCachePrefix';
63 -$wgHooks['BacklinkCacheGetConditions'][] = 'ScriptLinksUpdateHooks::getBacklinkCacheConditions';
64 -
6557 /***** Individual engines and their configurations *****/
6658
67 -/**
68 - * Available scripting engines.
69 - */
70 -$wgScriptingEngines = array(
71 - 'luasandbox' => 'LuaSandboxEngine',
72 -);
73 -
7459 $wgAutoloadClasses['LuaSandboxEngine'] = $dir.'engines/LuaSandbox/Engine.php';
7560
7661 /***** Configuration *****/
7762
7863 /**
79 - * The name of the scripting engine.
 64+ * The name of the default scripting engine.
8065 */
81 -$wgScriptingEngine = false;
 66+$wgScriptingDefaultEngine = 'luasandbox';
8267
 68+/**
 69+ * Configuration for each scripting engine
 70+ */
 71+$wgScriptingEngineConf = array(
 72+ 'luasandbox' => array(
 73+ 'class' => 'LuaSandboxEngine',
 74+ 'memoryLimit' => 50 * 1024 * 1024,
 75+ 'cpuLimit' => 7,
 76+ ),
 77+);
8378
84 -$wgScriptingEngineConf = array();
85 -
8679 /**
8780 * Script namespace numbers.
8881 */
Index: trunk/extensions/Scripting/common/LinkUpdates.php
@@ -1,209 +0,0 @@
2 -<?php
3 -/**
4 - * Wikitext scripting infrastructure for MediaWiki: link updating code
5 - * Copyright (C) 2011-2012 Victor Vasiliev <vasilvv@gmail.com> et al
6 - * Based on MediaWiki file LinksUpdate.php
7 - * http://www.mediawiki.org/
8 - *
9 - * This program is free software; you can redistribute it and/or modify
10 - * it under the terms of the GNU General Public License as published by
11 - * the Free Software Foundation; either version 2 of the License, or
12 - * (at your option) any later version.
13 - *
14 - * This program is distributed in the hope that it will be useful,
15 - * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 - * GNU General Public License for more details.
18 - *
19 - * You should have received a copy of the GNU General Public License along
20 - * with this program; if not, write to the Free Software Foundation, Inc.,
21 - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
22 - * http://www.gnu.org/copyleft/gpl.html
23 - */
24 -
25 -if( !defined( 'MEDIAWIKI' ) )
26 - die();
27 -
28 -
29 -/**
30 - * Class that contains hooks related to tracking links to scripts and invalidating
31 - * pages on script change.
32 - */
33 -class ScriptLinksUpdateHooks {
34 - /**
35 - * Append script links to the output.
36 - */
37 - public static function appendToOutput( &$parser, &$text ) {
38 - if( isset( $parser->scripting_engine ) ) {
39 - $parser->mOutput->scripting_links = $parser->scripting_engine->getUsedModules();
40 - }
41 - return true;
42 - }
43 -
44 - /**
45 - * Run the link updater.
46 - */
47 - public static function updateLinks( &$update ) {
48 - $output = $update->mParserOutput;
49 - if( isset( $output->scripting_links ) ) {
50 - $new = $output->scripting_links;
51 - } else {
52 - $new = array();
53 - }
54 -
55 - $isupdate = new ScriptLinksUpdate( $update, $new );
56 - $isupdate->run();
57 - return true;
58 - }
59 -
60 - /**
61 - * Purge cache for all the pages where the script is used.
62 - * @param $article Article
63 - * @param $editInfo
64 - * @param $changed
65 - * @return bool
66 - */
67 - public static function purgeCache( &$article, &$editInfo, $changed ) {
68 - global $wgDeferredUpdateList, $wgParser;
69 -
70 - if( $article->getTitle()->getNamespace() == NS_MODULE ) {
71 - // Invalidate the script cache
72 - $engine = Scripting::getEngine( $wgParser );
73 - $engine->invalidateModuleCache( $article->getTitle() );
74 -
75 - // Invalidate the caches of articles which include the script
76 - $wgDeferredUpdateList[] = new HTMLCacheUpdate( $article->getTitle(), 'scriptlinks' );
77 - }
78 -
79 - return true;
80 - }
81 -
82 - /**
83 - * Add scriptlinks to the list of tables supported by BacklinkCache.
84 - */
85 - public static function getBacklinkCachePrefix( $table, &$prefix ) {
86 - if( $table == 'scriptlinks' ) {
87 - $prefix = 'sl';
88 - return false;
89 - } else {
90 - return true;
91 - }
92 - }
93 -
94 - /**
95 - * Add scriptlinks to the list of tables supported by BacklinkCache.
96 - * @param $table
97 - * @param $title Title
98 - * @param $conds
99 - * @return bool
100 - */
101 - public static function getBacklinkCacheConditions( $table, $title, &$conds ) {
102 - if( $table == 'scriptlinks' ) {
103 - $conds = array(
104 - 'sl_to' => $title->getDBkey(),
105 - 'page_id=sl_from'
106 - );
107 - return false;
108 - } else {
109 - return true;
110 - }
111 - }
112 -}
113 -
114 -/**
115 - * A class that updates links on scripts like what phase3/includes/LinksUpdate.php does
116 - * with templates.
117 - */
118 -class ScriptLinksUpdate {
119 - var $update, $id, $new;
120 -
121 - public function __construct( $update, $new ) {
122 - $this->update = $update;
123 - $this->id = $update->mId;
124 - $this->new = $new;
125 - }
126 -
127 - public function run() {
128 - global $wgUseDumbLinkUpdate;
129 -
130 - wfProfileIn( __METHOD__ );
131 -
132 - if( $wgUseDumbLinkUpdate ) {
133 - $this->update->dumbTableUpdate( 'scriptlinks', $this->getScriptInsertions(), 'sl_from' );
134 - } else {
135 - $existing = $this->getExistingScripts();
136 - $this->update->incrTableUpdate( 'scriptlinks', 'sl', $this->getScriptDeletions( $existing ),
137 - $this->getScriptInsertions( $existing ) );
138 - }
139 -
140 - if( $this->update->mRecursive && $this->update->mTitle->getNamespace() == NS_MODULE ) {
141 - $this->queueRecursiveJobs();
142 - }
143 -
144 - wfProfileOut( __METHOD__ );
145 - }
146 -
147 - protected function getExistingScripts() {
148 - $result = array();
149 -
150 - $res = $this->update->mDb->select( 'scriptlinks', array( 'sl_to' ),
151 - array( 'sl_from' => $this->id ), __METHOD__, $this->update->mOptions );
152 - foreach ( $res as $row ) {
153 - $result[] = $row->sl_to;
154 - }
155 -
156 - return $result;
157 - }
158 -
159 - protected function getScriptInsertions( $existing = array() ) {
160 - $result = array();
161 -
162 - foreach( array_diff( $this->new, $existing ) as $module ) {
163 - $result[] = array(
164 - 'sl_from' => $this->id,
165 - 'sl_to' => $module,
166 - );
167 - }
168 -
169 - return $result;
170 - }
171 -
172 - protected function getScriptDeletions( $existing = array() ) {
173 - $result = array();
174 -
175 - foreach( array_diff( $existing, $this->new ) as $module ) {
176 - $result[] = array(
177 - 'sl_from' => $this->id,
178 - 'sl_to' => $module,
179 - );
180 - }
181 -
182 - return $result;
183 - }
184 -
185 - protected function queueRecursiveJobs() {
186 - global $wgUpdateRowsPerJob;
187 - wfProfileIn( __METHOD__ );
188 -
189 - $cache = $this->update->mTitle->getBacklinkCache();
190 - $batches = $cache->partition( 'scriptlinks', $wgUpdateRowsPerJob );
191 - if ( !$batches ) {
192 - wfProfileOut( __METHOD__ );
193 - return;
194 - }
195 - $jobs = array();
196 - foreach ( $batches as $batch ) {
197 - list( $start, $end ) = $batch;
198 - $params = array(
199 - 'table' => 'scriptlinks',
200 - 'start' => $start,
201 - 'end' => $end,
202 - );
203 - $jobs[] = new RefreshLinksJob2( $this->update->mTitle, $params );
204 - }
205 - Job::batchInsert( $jobs );
206 -
207 - wfProfileOut( __METHOD__ );
208 - }
209 -}
210 -
Index: trunk/extensions/Scripting/common/Common.php
@@ -6,32 +6,49 @@
77 class Scripting {
88 const LOCAL = 'local';
99
10 - protected static function getEngineClass() {
11 - global $wgScriptingEngine, $wgScriptingEngines;
 10+ /**
 11+ * Create a new engine object with specified parameters.
 12+ */
 13+ public static function newEngine( $options ) {
 14+ $class = $options['class'];
 15+ return new $class( $options );
 16+ }
1217
13 - if( !$wgScriptingEngine ) {
14 - throw new MWException( 'Scripting extension is enabled but $wgScriptingEngine is not set' );
 18+ /**
 19+ * Create a new engine object with default parameters
 20+ * @param $extraOptions Extra options to pass to the constructor, in addition to the configured options
 21+ */
 22+ public static function newDefaultEngine( $extraOptions = array() ) {
 23+ global $wgScriptingDefaultEngine, $wgScriptingEngineConf;
 24+ if( !$wgScriptingDefaultEngine ) {
 25+ throw new MWException( 'Scripting extension is enabled but $wgScriptingDefaultEngine is not set' );
1526 }
1627
17 - if( !isset( $wgScriptingEngines[$wgScriptingEngine] ) ) {
18 - throw new MWException( 'Invalid scripting engine is specified in $wgScriptingEngine' );
 28+ if( !isset( $wgScriptingEngineConf[$wgScriptingDefaultEngine] ) ) {
 29+ throw new MWException( 'Invalid scripting engine is specified in $wgScriptingDefaultEngine' );
1930 }
20 -
21 - return $wgScriptingEngines[$wgScriptingEngine];
 31+ $options = $extraOptions + $wgScriptingEngineConf[$wgScriptingDefaultEngine];
 32+ return self::newEngine( $options );
2233 }
2334
24 - public static function getEngine( $parser ) {
25 - global $wgScriptingEngineConf;
26 -
 35+ /**
 36+ * Get an engine instance for the given parser, and cache it in the parser
 37+ * so that subsequent calls to this function for the same parser will return
 38+ * the same engine.
 39+ *
 40+ * @param Parser $parser
 41+ */
 42+ public static function getParserEngine( $parser ) {
2743 if( !isset( $parser->scripting_engine ) || !$parser->scripting_engine ) {
28 - $class = self::getEngineClass();
29 - $parser->scripting_engine = new $class( $parser );
30 - $parser->scripting_engine->setOptions( $wgScriptingEngineConf );
 44+ $parser->scripting_engine = self::newDefaultEngine( array( 'parser' => $parser ) );
3145 }
3246 return $parser->scripting_engine;
3347 }
3448
35 - public static function resetEngine( $parser ) {
 49+ /**
 50+ * Remove the current engine instance from the parser
 51+ */
 52+ public static function resetParserEngine( $parser ) {
3653 $parser->scripting_engine = null;
3754 }
3855 }
@@ -41,22 +58,28 @@
4259 * normally abort the request, instead it is caught and shown to the user.
4360 */
4461 class ScriptingException extends MWException {
45 - function __construct( $exceptionID, $engine, $module = null, $line = null, $params = array() ) {
46 - if( $module ) {
47 - $codelocation = wfMsg( 'scripting-codelocation', $module, $line );
48 - $msg = wfMsgExt( "scripting-exception-{$engine}-{$exceptionID}", array(), array_merge( array( $codelocation ), $params ) );
 62+ var $messageName, $params;
 63+
 64+ function __construct( $messageName, $params = array() ) {
 65+ if ( isset( $params['args'] ) ) {
 66+ $args = $params['args'];
4967 } else {
50 - $msg = wfMsgExt( "scripting-exception-{$engine}-{$exceptionID}", array(), $params );
 68+ $args = array();
5169 }
 70+ if ( isset( $params['module'] ) && isset( $params['line'] ) ) {
 71+ $codelocation = wfMsg( 'scripting-codelocation', $params['module'], $params['line'] );
 72+ } else {
 73+ $codelocation = '[UNKNOWN]'; // should never happen
 74+ }
 75+ array_unshift( $args, $codelocation );
 76+ $msg = wfMsgExt( $messageName, array(), $args );
5277 parent::__construct( $msg );
5378
54 - $this->exceptionID = $exceptionID;
55 - $this->line = $line;
56 - $this->module = $module;
 79+ $this->messageName = $messageName;
5780 $this->params = $params;
5881 }
5982
60 - public function getExceptionID() {
61 - return $this->exceptionID;
 83+ public function getMessageName() {
 84+ return $this->messageName;
6285 }
6386 }
Index: trunk/extensions/Scripting/common/Base.php
@@ -29,98 +29,51 @@
3030 abstract class ScriptingEngineBase {
3131 protected
3232 $parser,
33 - $modules = array(),
34 - $moduleTitles = array();
 33+ $options,
 34+ $modules = array();
3535
3636 /**
3737 * Creates a new module object within this engine
3838 */
39 - abstract protected function newModule( $title, $code, $revisionID, $source );
 39+ abstract protected function newModule( $text, $chunkName );
4040
4141 /**
42 - * Returns the default options of the engine.
43 - */
44 - public function getDefaultOptions() {
45 - return array();
46 - }
47 -
48 - /**
49 - * Is called by setOptions() in order to notify the engine
50 - * that the options were changed.
51 - */
52 - protected function updateOptions() { /* No-op */ }
53 -
54 - /**
5542 * Constructor.
5643 *
57 - * @param $parser Parser Wikitext parser
 44+ * @param $options Associative array of options:
 45+ * - parser: A Parser object
5846 */
59 - public function __construct( $parser ) {
60 - $this->parser = $parser;
 47+ public function __construct( $options ) {
 48+ $this->options = $options;
 49+ if ( isset( $options['parser'] ) ) {
 50+ $this->parser = $options['parser'];
 51+ }
6152 }
6253
6354 /**
64 - * Loads the module either from instance cache or from the actual revision.
 55+ * Load a module from some parser-defined template loading mechanism and
 56+ * register a parser output dependency.
 57+ *
6558 * Does not initialize the module, i.e. do not expect it to complain if the module
6659 * text is garbage or has syntax error. Returns a module or throws an exception.
67 - *
68 - * @param $title Title/string The title or the name of the module.
69 - * @param $source string Source of the module
 60+ *
 61+ * @param $title The title of the module
7062 * @return ScriptingEngineModule
7163 */
72 - public function getModule( $title, $source = Scripting::LOCAL ) {
73 - // Convert string to title
74 - if( !$title instanceof Title ) {
75 - $titleobj = Title::newFromText( (string)$title, NS_MODULE );
76 - if( !$titleobj || $titleobj->getNamespace() != NS_MODULE ) {
77 - throw new ScriptingException( 'badtitle', 'common' ); // scripting-exceptions-common-badtitle
78 - }
79 - $title = $titleobj;
 64+ function fetchModuleFromParser( Title $title ) {
 65+ list( $text, $finalTitle ) = $this->parser->fetchTemplateAndTitle( $title );
 66+ if ( $text === false ) {
 67+ throw new ScriptingException( 'scripting-common-nosuchmodule' );
8068 }
8169
82 - // Check if it is already loaded
83 - $key = $title->getPrefixedText();
84 - if( !isset( $this->modules[$key] ) ) {
85 - // Fetch the text
86 - $rev = $this->getModuleRev( $title, $source );
87 - if( !$rev ) {
88 - throw new ScriptingException( 'nosuchmodule', 'common' ); // scripting-exceptions-common-nosuchmodule
89 - }
90 - if( $rev->getTitle()->getNamespace() != NS_MODULE ) {
91 - throw new ScriptingException( 'badnamespace', 'common' ); // scripting-exceptions-common-badnamespace
92 - }
93 -
94 - // Create the class
95 - $this->modules[$key] = $this->newModule( $title, $rev->getText(), $rev->getID(), $source );
96 - $this->moduleTitles[] = $title;
 70+ $key = $finalTitle->getPrefixedDBkey();
 71+ if ( !isset( $this->modules[$key] ) ) {
 72+ $this->modules[$key] = $this->newModule( $text, $key );
9773 }
9874 return $this->modules[$key];
9975 }
10076
10177 /**
102 - * Fetches the revision for given module title.
103 - */
104 - private function getModuleRev( $title, $source ) {
105 - if( $source != Scripting::LOCAL ) {
106 - throw new MWException( 'Non-local scripts are not supported at this point' );
107 - }
108 -
109 - $rev = Revision::newFromTitle( $title );
110 - if( $rev && $real = Title::newFromRedirect( $rev->getText() ) ) {
111 - $rev = Revision::newFromTitle( $real );
112 - }
113 - return $rev;
114 - }
115 -
116 - /**
117 - * Sets the engine-specific options from $wgScriptingEngineConf.
118 - */
119 - function setOptions( $options ) {
120 - $this->options = array_merge( $this->getDefaultOptions(), $options );
121 - $this->updateOptions();
122 - }
123 -
124 - /**
12578 * Validates the script and returns an array of the syntax errors for the
12679 * given code.
12780 *
@@ -128,8 +81,8 @@
12982 * @param $title Title of the code page
13083 * @return array
13184 */
132 - function validate( $code, $title ) {
133 - $module = $this->newModule( $title, $code, 0, Scripting::LOCAL );
 85+ function validate( $text, $chunkName = false ) {
 86+ $module = $this->newModule( $text, $chunkName );
13487
13588 try {
13689 $module->initialize();
@@ -150,30 +103,14 @@
151104 }
152105
153106 /**
154 - * Returns the titles of all the modules used by this instance of the
155 - * engine.
156 - */
157 - public function getUsedModules() {
158 - return $this->moduleTitles;
159 - }
160 -
161 - /**
162 - * Invalidates the cache of the given module by its title. Should be
163 - * redefined if the engine uses any form of bytecode or other cache.
164 - */
165 - function invalidateModuleCache( $title ) {
166 - /* No-op by default */
167 - }
168 -
169 - /**
170107 * Get the language for GeSHi syntax highlighter.
171108 */
172 - function getGeSHiLangauge() {
 109+ function getGeSHiLanguage() {
173110 return false;
174111 }
175112
176113 /**
177 - * Get the langauge for Ace code editor.
 114+ * Get the language for Ace code editor.
178115 */
179116 function getCodeEditorLanguage() {
180117 return false;
@@ -185,23 +122,19 @@
186123 * and maintaining the contents of the module.
187124 */
188125 abstract class ScriptingModuleBase {
189 - var $engine, $title, $code, $revisionID, $source;
 126+ var $engine, $code, $chunkName;
190127
191 - public function __construct( $engine, $title, $code, $revisionID, $source ) {
 128+ public function __construct( $engine, $code, $chunkName ) {
192129 $this->engine = $engine;
193 - $this->title = $title;
194130 $this->code = $code;
195 - $this->revisionID = $revisionID;
196 - $this->source = $source;
 131+ $this->chunkName = $chunkName;
197132 }
198133
199134 /** Accessors **/
200135 public function getEngine() { return $this->engine; }
201 - public function getTitle() { return $this->title; }
202136 public function getCode() { return $this->code; }
203 - public function getRevisionID() { return $this->revisionID; }
204 - public function getSource() { return $this->source; }
205 -
 137+ public function getChunkName() { return $this->chunkName; }
 138+
206139 /**
207140 * Initialize the module. That means parse it and load the
208141 * functions/constants/whatever into the object.
Index: trunk/extensions/Scripting/common/Hooks.php
@@ -42,19 +42,11 @@
4343 * @return bool
4444 */
4545 public static function clearState( &$parser ) {
46 - Scripting::resetEngine( $parser );
 46+ Scripting::resetParserEngine( $parser );
4747 return true;
4848 }
4949
5050 /**
51 - * Add scriptlinks table to parser tests.
52 - */
53 - public static function addTestTables( &$tables ) {
54 - $tables[] = 'scriptlinks';
55 - return true;
56 - }
57 -
58 - /**
5951 * Hook function for {{#invoke:module|func}}
6052 *
6153 * @param $parser Parser
@@ -64,7 +56,7 @@
6557 */
6658 public static function callHook( &$parser, $frame, $args ) {
6759 if( count( $args ) < 2 ) {
68 - throw new ScriptingException( 'nofunction', 'common' ); // scripting-exceptions-common-nofunction
 60+ throw new ScriptingException( 'scripting-common-nofunction' );
6961 }
7062
7163 $module = $parser->mStripState->unstripBoth( array_shift( $args ) );
@@ -88,29 +80,32 @@
8981 /**
9082 * @param $parser Parser
9183 * @param $frame PPFrame
92 - * @param $module
93 - * @param $function
 84+ * @param $moduleName
 85+ * @param $functionName
9486 * @param $args
9587 * @return string
9688 * @throws ScriptingException
9789 */
98 - private static function doRunHook( $parser, $frame, $module, $function, $args ) {
 90+ private static function doRunHook( $parser, $frame, $moduleName, $functionName, $args ) {
9991 wfProfileIn( __METHOD__ );
100 -
 92+
10193 try {
102 - $engine = Scripting::getEngine( $parser );
103 -
104 - foreach( $args as &$arg ) {
105 - $arg = $frame->expand( $arg );
 94+ $engine = Scripting::getParserEngine( $parser );
 95+ $title = Title::makeTitleSafe( NS_MODULE, $moduleName );
 96+ if ( !$title ) {
 97+ throw new ScriptingException( 'scripting-common-nosuchmodule' );
10698 }
 99+ $module = $engine->fetchModuleFromParser( $title );
107100
108 - $module = $engine->getModule( $module, Scripting::LOCAL );
109 -
110 - $functionObj = $module->getFunction( $function );
 101+ $functionObj = $module->getFunction( $functionName );
111102 if( !$functionObj ) {
112 - throw new ScriptingException( 'nosuchfunction', 'common' ); // scripting-exceptions-common-nosuchfunction
 103+ throw new ScriptingException( 'scripting-common-nosuchfunction' );
113104 }
114105
 106+ foreach( $args as &$arg ) {
 107+ $arg = $frame->expand( $arg );
 108+ }
 109+
115110 $result = $functionObj->call( $args, $frame );
116111
117112 wfProfileOut( __METHOD__ );
@@ -132,11 +127,11 @@
133128 * @return bool
134129 */
135130 public static function handleScriptView( $text, $title, $output ) {
136 - global $wgScriptingUseGeSHi, $wgParser;
 131+ global $wgScriptingUseGeSHi;
137132
138133 if( $title->getNamespace() == NS_MODULE ) {
139 - $engine = Scripting::getEngine( $wgParser );
140 - $language = $engine->getGeSHiLangauge();
 134+ $engine = Scripting::newDefaultEngine();
 135+ $language = $engine->getGeSHiLanguage();
141136
142137 if( $wgScriptingUseGeSHi && $language ) {
143138 $geshi = SyntaxHighlight_GeSHi::prepare( $text, $language );
@@ -161,10 +156,10 @@
162157 }
163158 }
164159
165 - public static function getCodeLangauge( $title, &$lang ) {
166 - global $wgParser, $wgScriptingUseCodeEditor;
 160+ public static function getCodeLanguage( $title, &$lang ) {
 161+ global $wgScriptingUseCodeEditor;
167162 if( $wgScriptingUseCodeEditor && $title->getNamespace() == NS_MODULE ) {
168 - $engine = Scripting::getEngine( $wgParser );
 163+ $engine = Scripting::newDefaultEngine();
169164 if( $engine->getCodeEditorLanguage() ) {
170165 $lang = $engine->getCodeEditorLanguage();
171166 return false;
@@ -198,8 +193,8 @@
199194 public static function reportLimits( $parser, &$report ) {
200195 # FIXME
201196 global $wgScriptsLimits;
202 - $engine = Scripting::getEngine( $parser );
203 - $report .= $engine->getLimitsReport();
 197+ $engine = Scripting::getParserEngine( $parser );
 198+ $report .= $engine->getLimitReport();
204199 return true;
205200 }
206201
@@ -213,12 +208,12 @@
214209 }
215210
216211 public static function validateScript( $editor, $text, $section, &$error ) {
217 - global $wgUser, $wgParser;
 212+ global $wgUser;
218213 $title = $editor->mTitle;
219214
220215 if( $title->getNamespace() == NS_MODULE ) {
221 - $engine = Scripting::getEngine( $wgParser );
222 - $errors = $engine->validate( $text, $title );
 216+ $engine = Scripting::newDefaultEngine();
 217+ $errors = $engine->validate( $text, $title->getPrefixedDBkey() );
223218 if( !$errors ) {
224219 return true;
225220 }
Index: trunk/extensions/Scripting/engines/LuaSandbox/Engine.php
@@ -1,10 +1,10 @@
22 <?php
33
44 class LuaSandboxEngine extends ScriptingEngineBase {
5 - public $sandbox, $loaded = false;
 5+ public $sandbox, $options, $loaded = false;
66
7 - public function newModule( $title, $code, $revisionID, $source ) {
8 - return new LuaSandboxEngineModule( $this, $title, $code, $revisionID, $source );
 7+ public function newModule( $text, $chunkName ) {
 8+ return new LuaSandboxEngineModule( $this, $text, $chunkName );
99 }
1010
1111 public function load() {
@@ -18,31 +18,17 @@
1919
2020 $this->sandbox = new LuaSandbox;
2121 $this->sandbox->setMemoryLimit( $this->options['memoryLimit'] );
22 - $this->sandbox->setCPULimit( $this->options['maxCPU'] );
 22+ $this->sandbox->setCPULimit( $this->options['cpuLimit'] );
2323 $this->sandbox->registerLibrary( 'mw', array( 'import' => array( $this, 'importModule' ) ) );
2424
2525 $this->loaded = true;
2626 }
2727
28 - protected function updateOptions() {
29 - if( $this->loaded ) {
30 - $this->sandbox->setMemoryLimit( $this->options['memoryLimit'] );
31 - $this->sandbox->setCPULimit( $this->options['maxCPU'] );
32 - }
33 - }
34 -
3528 protected function getModuleClassName() {
3629 return 'LuaSandboxEngineModule';
3730 }
3831
39 - public function getDefaultOptions() {
40 - return array(
41 - 'memoryLimit' => 50 * 1024 * 1024,
42 - 'maxCPU' => 7,
43 - );
44 - }
45 -
46 - public function getGeSHiLangauge() {
 32+ public function getGeSHiLanguage() {
4733 return 'lua';
4834 }
4935
@@ -50,7 +36,7 @@
5137 return 'lua';
5238 }
5339
54 - public function getLimitsReport() {
 40+ public function getLimitReport() {
5541 $this->load();
5642
5743 $usage = $this->sandbox->getMemoryUsage();
@@ -69,12 +55,16 @@
7056 $args = func_get_args();
7157 if( count( $args ) < 1 ) {
7258 // FIXME: LuaSandbox PHP extension should provide proper context
73 - throw new ScriptingException( 'toofewargs', 'common', null, null, array( 'mw.import' ) );
 59+ throw new ScriptingException( 'scripting-common-toofewargs',
 60+ array( 'args' => array( 'mw.import' ) ) );
7461 }
7562
76 - $module = $this->getModule( $args[0] );
77 - $module->initialize();
78 - return $module->contents;
 63+ $title = Title::makeTitleSafe( NS_MODULE, $args[0] );
 64+ if ( !$title ) {
 65+ throw new ScriptingException( 'scripting-common-nosuchmodule' );
 66+ }
 67+ $module = $this->fetchModuleFromParser( $title );
 68+ return $module->getContents();
7969 }
8070 }
8171
@@ -93,20 +83,21 @@
9484 $this->body = $this->engine->sandbox->loadString(
9585 $this->code,
9686 // Prepending an "@" to the chunk name makes Lua think it is a file name
97 - '@' . $this->getTitle()->getPrefixedDBkey() );
 87+ '@' . $this->chunkName );
9888 $output = $this->body->call();
9989 } catch( LuaSandboxError $e ) {
100 - throw new ScriptingException( 'error', 'luasandbox', null, null, array( $e->getMessage() ) );
 90+ throw new ScriptingException( 'scripting-luasandbox-error',
 91+ array( 'args' => array( $e->getMessage() ) ) );
10192 }
10293
10394 if( !$output ) {
104 - throw new ScriptingException( 'noreturn', 'luasandbox' );
 95+ throw new ScriptingException( 'scripting-luasandbox-noreturn' );
10596 }
10697 if( count( $output ) > 2 ) {
107 - throw new ScriptingException( 'toomanyreturns', 'luasandbox' );
 98+ throw new ScriptingException( 'scripting-luasandbox-toomanyreturns' );
10899 }
109100 if( !is_array( $output[0] ) ) {
110 - throw new ScriptingException( 'notarrayreturn', 'luasandbox' );
 101+ throw new ScriptingException( 'scripting-luasandbox-notarrayreturn' );
111102 }
112103
113104 $this->contents = $output[0];
@@ -133,6 +124,11 @@
134125 $this->initialize();
135126 return $this->functions;
136127 }
 128+
 129+ function getContents() {
 130+ $this->initialize();
 131+ return $this->contents;
 132+ }
137133 }
138134
139135 class LuaSandboxEngineFunction extends ScriptingFunctionBase {
@@ -140,7 +136,8 @@
141137 try {
142138 $result = call_user_func_array( array( $this->contents, 'call' ), $args );
143139 } catch( LuaSandboxError $e ) {
144 - throw new ScriptingException( 'error', 'luasandbox', null, null, array( $e->getMessage() ) );
 140+ throw new ScriptingException( 'scripting-luasandbox-error',
 141+ array( 'args' => array( $e->getMessage() ) ) );
145142 }
146143
147144 if ( isset( $result[0] ) ) {

Status & tagging log