2012-04-13 10:38:12 +00:00
|
|
|
<?php
|
|
|
|
|
|
|
|
abstract class Scribunto_LuaEngine extends ScribuntoEngineBase {
|
2013-02-15 23:41:20 +00:00
|
|
|
/**
|
|
|
|
* Libraries to load. See also the 'ScribuntoExternalLibraries' hook.
|
|
|
|
* @var array Maps module names to PHP classes
|
|
|
|
*/
|
2013-02-14 17:38:03 +00:00
|
|
|
protected static $libraryClasses = array(
|
2013-02-01 20:48:18 +00:00
|
|
|
'mw.site' => 'Scribunto_LuaSiteLibrary',
|
2013-01-26 00:09:50 +00:00
|
|
|
'mw.uri' => 'Scribunto_LuaUriLibrary',
|
2012-12-11 02:53:43 +00:00
|
|
|
'mw.ustring' => 'Scribunto_LuaUstringLibrary',
|
2013-01-25 19:03:04 +00:00
|
|
|
'mw.language' => 'Scribunto_LuaLanguageLibrary',
|
2013-02-08 14:56:44 +00:00
|
|
|
'mw.message' => 'Scribunto_LuaMessageLibrary',
|
2013-02-07 17:50:21 +00:00
|
|
|
'mw.title' => 'Scribunto_LuaTitleLibrary',
|
2013-03-04 20:00:59 +00:00
|
|
|
'mw.text' => 'Scribunto_LuaTextLibrary',
|
2013-12-16 15:00:37 +00:00
|
|
|
'mw.html' => 'Scribunto_LuaHtmlLibrary',
|
2013-01-25 17:53:18 +00:00
|
|
|
);
|
|
|
|
|
2013-02-15 23:41:20 +00:00
|
|
|
/**
|
|
|
|
* Paths for modules that may be loaded from Lua. See also the
|
|
|
|
* 'ScribuntoExternalLibraryPaths' hook.
|
|
|
|
* @var array Paths
|
|
|
|
*/
|
2013-02-14 17:38:03 +00:00
|
|
|
protected static $libraryPaths = array(
|
|
|
|
'.',
|
|
|
|
'luabit',
|
|
|
|
'ustring',
|
|
|
|
);
|
|
|
|
|
Added more Lua environment features
Package library:
* Added a simulation of the Lua 5.1 package library.
* Removed mw.import(), replaced it with a package loader. Packages can be
retrieved from the wiki, using require('Module:Foo'), or from files
distributed with Scribunto, using require('foo'). The "Module:" prefix allows
for source compatibility with existing Lua code.
* Added a couple of libraries from LuaForge: luabit and stringtools.
* Made fetchModuleFromParser() return null on error instead of throwing an
exception, to more easily support the desired behaviour of the package loader,
which needs to return null on error.
* Renamed mw.setupEnvironment() to mw.setup() since it is setting up things
other than the environment now.
* In MWServer:handleRegisterLibrary(), remove the feature which interprets dots
in library names, since LuaSandbox doesn't support this.
Improved module isolation and related refactoring:
* Expose restricted versions of getfenv() and setfenv() to user Lua code.
Requires luasandbox r114952.
* Don't cache the export list returned by module execution for later function
calls. This breaks isolation of #invoke calls, since the local variables are
persistent.
* Removed ScribuntoFunctionBase and its children, since it doesn't really have
a purpose if it can't cache anything. Instead, invoke functions using a module
method called invoke().
* Removed Module::initialize(), replaced it with a validate() function. This is
a more elegant interface and works better with the new module caching scheme.
* Use a Status object for the return value of Engine::validate() instead of an
array. Use the formatting facilities of the Status class.
Other:
* Removed "too many returns" error, doesn't fit in with Lua conventions.
* Use the standalone engine by default, so that the extension will work without
configuration for more people.
* Added an accessor for $engine->interpreter
* Fix mw.clone() to correctly clone metatables
* If the standalone interpreter exits due to an error, there are some contexts
where the initial error will be caught and ignored, and the user will see the
error from checkValid() instead. In this case, rethrow the original error for
a more informative message.
* Load mw.lua into the initial standalone environment, to reduce code
duplication between mw.lua and MWServer.lua.
* Fixed a bug in Scribunto_LuaStandaloneInterpreter::handleCall() for functions
that return no results.
* Fixed a bug in encodeLuaVar() for strings with "\r". Added test case.
* In MWServer.lua, don't call error() for internal errors, instead just print
the error and exit. This avoids a protocol violation when an error is
encountered from within handleCall().
* Added lots of documentation. Lua doc comments are in LuaDoc format.
Change-Id: Ie2fd572c362bedf02f45d3fa5352a5280e034740
2012-04-18 03:46:18 +00:00
|
|
|
protected $loaded = false;
|
2014-06-18 17:17:04 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* @var Scribunto_LuaInterpreter
|
|
|
|
*/
|
2013-04-12 14:38:14 +00:00
|
|
|
protected $interpreter;
|
2014-06-18 17:17:04 +00:00
|
|
|
|
2012-05-22 03:56:07 +00:00
|
|
|
protected $mw;
|
2013-02-19 00:49:08 +00:00
|
|
|
protected $currentFrames = array();
|
2012-05-22 03:56:07 +00:00
|
|
|
protected $expandCache = array();
|
2013-01-25 17:53:18 +00:00
|
|
|
protected $loadedLibraries = array();
|
2012-05-22 03:56:07 +00:00
|
|
|
|
|
|
|
const MAX_EXPAND_CACHE_SIZE = 100;
|
2012-04-13 10:38:12 +00:00
|
|
|
|
Added more Lua environment features
Package library:
* Added a simulation of the Lua 5.1 package library.
* Removed mw.import(), replaced it with a package loader. Packages can be
retrieved from the wiki, using require('Module:Foo'), or from files
distributed with Scribunto, using require('foo'). The "Module:" prefix allows
for source compatibility with existing Lua code.
* Added a couple of libraries from LuaForge: luabit and stringtools.
* Made fetchModuleFromParser() return null on error instead of throwing an
exception, to more easily support the desired behaviour of the package loader,
which needs to return null on error.
* Renamed mw.setupEnvironment() to mw.setup() since it is setting up things
other than the environment now.
* In MWServer:handleRegisterLibrary(), remove the feature which interprets dots
in library names, since LuaSandbox doesn't support this.
Improved module isolation and related refactoring:
* Expose restricted versions of getfenv() and setfenv() to user Lua code.
Requires luasandbox r114952.
* Don't cache the export list returned by module execution for later function
calls. This breaks isolation of #invoke calls, since the local variables are
persistent.
* Removed ScribuntoFunctionBase and its children, since it doesn't really have
a purpose if it can't cache anything. Instead, invoke functions using a module
method called invoke().
* Removed Module::initialize(), replaced it with a validate() function. This is
a more elegant interface and works better with the new module caching scheme.
* Use a Status object for the return value of Engine::validate() instead of an
array. Use the formatting facilities of the Status class.
Other:
* Removed "too many returns" error, doesn't fit in with Lua conventions.
* Use the standalone engine by default, so that the extension will work without
configuration for more people.
* Added an accessor for $engine->interpreter
* Fix mw.clone() to correctly clone metatables
* If the standalone interpreter exits due to an error, there are some contexts
where the initial error will be caught and ignored, and the user will see the
error from checkValid() instead. In this case, rethrow the original error for
a more informative message.
* Load mw.lua into the initial standalone environment, to reduce code
duplication between mw.lua and MWServer.lua.
* Fixed a bug in Scribunto_LuaStandaloneInterpreter::handleCall() for functions
that return no results.
* Fixed a bug in encodeLuaVar() for strings with "\r". Added test case.
* In MWServer.lua, don't call error() for internal errors, instead just print
the error and exit. This avoids a protocol violation when an error is
encountered from within handleCall().
* Added lots of documentation. Lua doc comments are in LuaDoc format.
Change-Id: Ie2fd572c362bedf02f45d3fa5352a5280e034740
2012-04-18 03:46:18 +00:00
|
|
|
/**
|
|
|
|
* Create a new interpreter object
|
2013-02-15 23:41:20 +00:00
|
|
|
* @return Scribunto_LuaInterpreter
|
Added more Lua environment features
Package library:
* Added a simulation of the Lua 5.1 package library.
* Removed mw.import(), replaced it with a package loader. Packages can be
retrieved from the wiki, using require('Module:Foo'), or from files
distributed with Scribunto, using require('foo'). The "Module:" prefix allows
for source compatibility with existing Lua code.
* Added a couple of libraries from LuaForge: luabit and stringtools.
* Made fetchModuleFromParser() return null on error instead of throwing an
exception, to more easily support the desired behaviour of the package loader,
which needs to return null on error.
* Renamed mw.setupEnvironment() to mw.setup() since it is setting up things
other than the environment now.
* In MWServer:handleRegisterLibrary(), remove the feature which interprets dots
in library names, since LuaSandbox doesn't support this.
Improved module isolation and related refactoring:
* Expose restricted versions of getfenv() and setfenv() to user Lua code.
Requires luasandbox r114952.
* Don't cache the export list returned by module execution for later function
calls. This breaks isolation of #invoke calls, since the local variables are
persistent.
* Removed ScribuntoFunctionBase and its children, since it doesn't really have
a purpose if it can't cache anything. Instead, invoke functions using a module
method called invoke().
* Removed Module::initialize(), replaced it with a validate() function. This is
a more elegant interface and works better with the new module caching scheme.
* Use a Status object for the return value of Engine::validate() instead of an
array. Use the formatting facilities of the Status class.
Other:
* Removed "too many returns" error, doesn't fit in with Lua conventions.
* Use the standalone engine by default, so that the extension will work without
configuration for more people.
* Added an accessor for $engine->interpreter
* Fix mw.clone() to correctly clone metatables
* If the standalone interpreter exits due to an error, there are some contexts
where the initial error will be caught and ignored, and the user will see the
error from checkValid() instead. In this case, rethrow the original error for
a more informative message.
* Load mw.lua into the initial standalone environment, to reduce code
duplication between mw.lua and MWServer.lua.
* Fixed a bug in Scribunto_LuaStandaloneInterpreter::handleCall() for functions
that return no results.
* Fixed a bug in encodeLuaVar() for strings with "\r". Added test case.
* In MWServer.lua, don't call error() for internal errors, instead just print
the error and exit. This avoids a protocol violation when an error is
encountered from within handleCall().
* Added lots of documentation. Lua doc comments are in LuaDoc format.
Change-Id: Ie2fd572c362bedf02f45d3fa5352a5280e034740
2012-04-18 03:46:18 +00:00
|
|
|
*/
|
2012-04-13 10:38:12 +00:00
|
|
|
abstract function newInterpreter();
|
|
|
|
|
2014-06-18 17:17:04 +00:00
|
|
|
/**
|
|
|
|
* @param $text
|
|
|
|
* @param $chunkName
|
|
|
|
* @return Scribunto_LuaModule
|
|
|
|
*/
|
2012-04-13 10:38:12 +00:00
|
|
|
protected function newModule( $text, $chunkName ) {
|
|
|
|
return new Scribunto_LuaModule( $this, $text, $chunkName );
|
|
|
|
}
|
|
|
|
|
2014-06-18 17:17:04 +00:00
|
|
|
/**
|
|
|
|
* @param $message
|
|
|
|
* @param array $params
|
|
|
|
* @return Scribunto_LuaError
|
|
|
|
*/
|
2012-04-23 11:36:13 +00:00
|
|
|
public function newLuaError( $message, $params = array() ) {
|
|
|
|
return new Scribunto_LuaError( $message, $this->getDefaultExceptionParams() + $params );
|
|
|
|
}
|
|
|
|
|
2012-09-05 09:39:58 +00:00
|
|
|
public function destroy() {
|
|
|
|
// Break reference cycles
|
|
|
|
$this->interpreter = null;
|
|
|
|
$this->mw = null;
|
|
|
|
$this->expandCache = null;
|
2013-02-17 23:38:48 +00:00
|
|
|
$this->loadedLibraries = null;
|
2012-09-05 09:39:58 +00:00
|
|
|
parent::destroy();
|
|
|
|
}
|
|
|
|
|
Added more Lua environment features
Package library:
* Added a simulation of the Lua 5.1 package library.
* Removed mw.import(), replaced it with a package loader. Packages can be
retrieved from the wiki, using require('Module:Foo'), or from files
distributed with Scribunto, using require('foo'). The "Module:" prefix allows
for source compatibility with existing Lua code.
* Added a couple of libraries from LuaForge: luabit and stringtools.
* Made fetchModuleFromParser() return null on error instead of throwing an
exception, to more easily support the desired behaviour of the package loader,
which needs to return null on error.
* Renamed mw.setupEnvironment() to mw.setup() since it is setting up things
other than the environment now.
* In MWServer:handleRegisterLibrary(), remove the feature which interprets dots
in library names, since LuaSandbox doesn't support this.
Improved module isolation and related refactoring:
* Expose restricted versions of getfenv() and setfenv() to user Lua code.
Requires luasandbox r114952.
* Don't cache the export list returned by module execution for later function
calls. This breaks isolation of #invoke calls, since the local variables are
persistent.
* Removed ScribuntoFunctionBase and its children, since it doesn't really have
a purpose if it can't cache anything. Instead, invoke functions using a module
method called invoke().
* Removed Module::initialize(), replaced it with a validate() function. This is
a more elegant interface and works better with the new module caching scheme.
* Use a Status object for the return value of Engine::validate() instead of an
array. Use the formatting facilities of the Status class.
Other:
* Removed "too many returns" error, doesn't fit in with Lua conventions.
* Use the standalone engine by default, so that the extension will work without
configuration for more people.
* Added an accessor for $engine->interpreter
* Fix mw.clone() to correctly clone metatables
* If the standalone interpreter exits due to an error, there are some contexts
where the initial error will be caught and ignored, and the user will see the
error from checkValid() instead. In this case, rethrow the original error for
a more informative message.
* Load mw.lua into the initial standalone environment, to reduce code
duplication between mw.lua and MWServer.lua.
* Fixed a bug in Scribunto_LuaStandaloneInterpreter::handleCall() for functions
that return no results.
* Fixed a bug in encodeLuaVar() for strings with "\r". Added test case.
* In MWServer.lua, don't call error() for internal errors, instead just print
the error and exit. This avoids a protocol violation when an error is
encountered from within handleCall().
* Added lots of documentation. Lua doc comments are in LuaDoc format.
Change-Id: Ie2fd572c362bedf02f45d3fa5352a5280e034740
2012-04-18 03:46:18 +00:00
|
|
|
/**
|
|
|
|
* Initialise the interpreter and the base environment
|
|
|
|
*/
|
2012-04-13 10:38:12 +00:00
|
|
|
public function load() {
|
|
|
|
if( $this->loaded ) {
|
|
|
|
return;
|
|
|
|
}
|
Added more Lua environment features
Package library:
* Added a simulation of the Lua 5.1 package library.
* Removed mw.import(), replaced it with a package loader. Packages can be
retrieved from the wiki, using require('Module:Foo'), or from files
distributed with Scribunto, using require('foo'). The "Module:" prefix allows
for source compatibility with existing Lua code.
* Added a couple of libraries from LuaForge: luabit and stringtools.
* Made fetchModuleFromParser() return null on error instead of throwing an
exception, to more easily support the desired behaviour of the package loader,
which needs to return null on error.
* Renamed mw.setupEnvironment() to mw.setup() since it is setting up things
other than the environment now.
* In MWServer:handleRegisterLibrary(), remove the feature which interprets dots
in library names, since LuaSandbox doesn't support this.
Improved module isolation and related refactoring:
* Expose restricted versions of getfenv() and setfenv() to user Lua code.
Requires luasandbox r114952.
* Don't cache the export list returned by module execution for later function
calls. This breaks isolation of #invoke calls, since the local variables are
persistent.
* Removed ScribuntoFunctionBase and its children, since it doesn't really have
a purpose if it can't cache anything. Instead, invoke functions using a module
method called invoke().
* Removed Module::initialize(), replaced it with a validate() function. This is
a more elegant interface and works better with the new module caching scheme.
* Use a Status object for the return value of Engine::validate() instead of an
array. Use the formatting facilities of the Status class.
Other:
* Removed "too many returns" error, doesn't fit in with Lua conventions.
* Use the standalone engine by default, so that the extension will work without
configuration for more people.
* Added an accessor for $engine->interpreter
* Fix mw.clone() to correctly clone metatables
* If the standalone interpreter exits due to an error, there are some contexts
where the initial error will be caught and ignored, and the user will see the
error from checkValid() instead. In this case, rethrow the original error for
a more informative message.
* Load mw.lua into the initial standalone environment, to reduce code
duplication between mw.lua and MWServer.lua.
* Fixed a bug in Scribunto_LuaStandaloneInterpreter::handleCall() for functions
that return no results.
* Fixed a bug in encodeLuaVar() for strings with "\r". Added test case.
* In MWServer.lua, don't call error() for internal errors, instead just print
the error and exit. This avoids a protocol violation when an error is
encountered from within handleCall().
* Added lots of documentation. Lua doc comments are in LuaDoc format.
Change-Id: Ie2fd572c362bedf02f45d3fa5352a5280e034740
2012-04-18 03:46:18 +00:00
|
|
|
$this->loaded = true;
|
2012-04-13 10:38:12 +00:00
|
|
|
|
2013-07-05 14:05:12 +00:00
|
|
|
try {
|
|
|
|
$this->interpreter = $this->newInterpreter();
|
Added more Lua environment features
Package library:
* Added a simulation of the Lua 5.1 package library.
* Removed mw.import(), replaced it with a package loader. Packages can be
retrieved from the wiki, using require('Module:Foo'), or from files
distributed with Scribunto, using require('foo'). The "Module:" prefix allows
for source compatibility with existing Lua code.
* Added a couple of libraries from LuaForge: luabit and stringtools.
* Made fetchModuleFromParser() return null on error instead of throwing an
exception, to more easily support the desired behaviour of the package loader,
which needs to return null on error.
* Renamed mw.setupEnvironment() to mw.setup() since it is setting up things
other than the environment now.
* In MWServer:handleRegisterLibrary(), remove the feature which interprets dots
in library names, since LuaSandbox doesn't support this.
Improved module isolation and related refactoring:
* Expose restricted versions of getfenv() and setfenv() to user Lua code.
Requires luasandbox r114952.
* Don't cache the export list returned by module execution for later function
calls. This breaks isolation of #invoke calls, since the local variables are
persistent.
* Removed ScribuntoFunctionBase and its children, since it doesn't really have
a purpose if it can't cache anything. Instead, invoke functions using a module
method called invoke().
* Removed Module::initialize(), replaced it with a validate() function. This is
a more elegant interface and works better with the new module caching scheme.
* Use a Status object for the return value of Engine::validate() instead of an
array. Use the formatting facilities of the Status class.
Other:
* Removed "too many returns" error, doesn't fit in with Lua conventions.
* Use the standalone engine by default, so that the extension will work without
configuration for more people.
* Added an accessor for $engine->interpreter
* Fix mw.clone() to correctly clone metatables
* If the standalone interpreter exits due to an error, there are some contexts
where the initial error will be caught and ignored, and the user will see the
error from checkValid() instead. In this case, rethrow the original error for
a more informative message.
* Load mw.lua into the initial standalone environment, to reduce code
duplication between mw.lua and MWServer.lua.
* Fixed a bug in Scribunto_LuaStandaloneInterpreter::handleCall() for functions
that return no results.
* Fixed a bug in encodeLuaVar() for strings with "\r". Added test case.
* In MWServer.lua, don't call error() for internal errors, instead just print
the error and exit. This avoids a protocol violation when an error is
encountered from within handleCall().
* Added lots of documentation. Lua doc comments are in LuaDoc format.
Change-Id: Ie2fd572c362bedf02f45d3fa5352a5280e034740
2012-04-18 03:46:18 +00:00
|
|
|
|
2013-07-05 14:05:12 +00:00
|
|
|
$funcs = array(
|
|
|
|
'loadPackage',
|
|
|
|
'frameExists',
|
|
|
|
'newChildFrame',
|
|
|
|
'getExpandedArgument',
|
|
|
|
'getAllExpandedArguments',
|
|
|
|
'expandTemplate',
|
|
|
|
'callParserFunction',
|
|
|
|
'preprocess',
|
|
|
|
'incrementExpensiveFunctionCount',
|
2013-11-01 02:05:00 +00:00
|
|
|
'isSubsting',
|
2013-12-06 18:10:39 +00:00
|
|
|
'getFrameTitle',
|
2014-06-01 03:15:42 +00:00
|
|
|
'setTTL',
|
2013-07-05 14:05:12 +00:00
|
|
|
);
|
2013-01-25 17:53:18 +00:00
|
|
|
|
2013-07-05 14:05:12 +00:00
|
|
|
$lib = array();
|
|
|
|
foreach ( $funcs as $name ) {
|
|
|
|
$lib[$name] = array( $this, $name );
|
|
|
|
}
|
2012-05-22 03:56:07 +00:00
|
|
|
|
2014-05-15 18:13:16 +00:00
|
|
|
$this->registerInterface( 'mwInit.lua', array() );
|
2013-07-05 14:05:12 +00:00
|
|
|
$this->mw = $this->registerInterface( 'mw.lua', $lib,
|
|
|
|
array( 'allowEnvFuncs' => $this->options['allowEnvFuncs'] ) );
|
2013-01-25 17:53:18 +00:00
|
|
|
|
2013-07-05 14:05:12 +00:00
|
|
|
$libraries = $this->getLibraries( 'lua', self::$libraryClasses );
|
|
|
|
foreach ( $libraries as $name => $class ) {
|
|
|
|
$this->loadedLibraries[$name] = new $class( $this );
|
|
|
|
$this->loadedLibraries[$name]->register();
|
|
|
|
}
|
|
|
|
} catch ( Exception $ex ) {
|
|
|
|
$this->loaded = false;
|
|
|
|
$this->interpreter = null;
|
|
|
|
throw $ex;
|
2013-01-25 17:53:18 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-02-15 23:41:20 +00:00
|
|
|
/**
|
|
|
|
* Register a Lua Library
|
|
|
|
*
|
|
|
|
* This should be called from the library's PHP module's register() method.
|
|
|
|
*
|
|
|
|
* The value for $interfaceFuncs is used to populate the mw_interface
|
|
|
|
* global that is defined when the library's Lua module is loaded. Values
|
|
|
|
* must be PHP callables, which will be seen in Lua as functions.
|
|
|
|
*
|
|
|
|
* @param $moduleFileName string The path to the Lua portion of the library
|
|
|
|
* (absolute, or relative to $this->getLuaLibDir())
|
|
|
|
* @param $interfaceFuncs array Populates mw_interface
|
|
|
|
* @param $setupOptions array Passed to the modules setupInterface() method.
|
|
|
|
* @return Lua package
|
|
|
|
*/
|
2013-01-25 17:53:18 +00:00
|
|
|
public function registerInterface( $moduleFileName, $interfaceFuncs, $setupOptions = array() ) {
|
|
|
|
$this->interpreter->registerLibrary( 'mw_interface', $interfaceFuncs );
|
2013-02-14 17:38:03 +00:00
|
|
|
$moduleFileName = $this->normalizeModuleFileName( $moduleFileName );
|
|
|
|
$package = $this->loadLibraryFromFile( $moduleFileName );
|
2013-12-09 00:39:13 +00:00
|
|
|
if ( !empty( $package['setupInterface'] ) ) {
|
2013-01-25 17:53:18 +00:00
|
|
|
$this->interpreter->callFunction( $package['setupInterface'], $setupOptions );
|
|
|
|
}
|
|
|
|
return $package;
|
2012-04-13 10:38:12 +00:00
|
|
|
}
|
|
|
|
|
2013-02-15 23:41:20 +00:00
|
|
|
/**
|
|
|
|
* Return the base path for Lua modules.
|
|
|
|
* @return string
|
|
|
|
*/
|
2012-09-05 09:39:58 +00:00
|
|
|
public function getLuaLibDir() {
|
2013-12-16 15:00:37 +00:00
|
|
|
return __DIR__ . '/lualib';
|
2012-09-05 09:39:58 +00:00
|
|
|
}
|
|
|
|
|
2013-02-14 17:38:03 +00:00
|
|
|
/**
|
2013-03-29 11:28:08 +00:00
|
|
|
* Normalize a lua module to its full path. If path does not look like an
|
|
|
|
* absolute path (i.e. begins with DIRECTORY_SEPARATOR or "X:"), prepend
|
|
|
|
* getLuaLibDir()
|
2013-02-14 17:38:03 +00:00
|
|
|
*
|
|
|
|
* @param $file String name of the lua module file
|
|
|
|
* @return string
|
|
|
|
*/
|
|
|
|
protected function normalizeModuleFileName( $fileName ) {
|
2013-03-29 11:28:08 +00:00
|
|
|
if ( !preg_match( '<^(?:[a-zA-Z]:)?' . preg_quote( DIRECTORY_SEPARATOR ) . '>', $fileName ) ) {
|
|
|
|
$fileName = "{$this->getLuaLibDir()}/{$fileName}";
|
|
|
|
}
|
|
|
|
return $fileName;
|
2013-02-14 17:38:03 +00:00
|
|
|
}
|
|
|
|
|
2013-01-25 17:53:18 +00:00
|
|
|
/**
|
|
|
|
* Get performance characteristics of the Lua engine/interpreter
|
|
|
|
*
|
|
|
|
* phpCallsRequireSerialization: boolean
|
|
|
|
* whether calls between PHP and Lua functions require (slow)
|
|
|
|
* serialization of parameters and return values
|
2013-02-15 23:41:20 +00:00
|
|
|
*
|
|
|
|
* @return array
|
2013-01-25 17:53:18 +00:00
|
|
|
*/
|
|
|
|
public abstract function getPerformanceCharacteristics();
|
|
|
|
|
Added more Lua environment features
Package library:
* Added a simulation of the Lua 5.1 package library.
* Removed mw.import(), replaced it with a package loader. Packages can be
retrieved from the wiki, using require('Module:Foo'), or from files
distributed with Scribunto, using require('foo'). The "Module:" prefix allows
for source compatibility with existing Lua code.
* Added a couple of libraries from LuaForge: luabit and stringtools.
* Made fetchModuleFromParser() return null on error instead of throwing an
exception, to more easily support the desired behaviour of the package loader,
which needs to return null on error.
* Renamed mw.setupEnvironment() to mw.setup() since it is setting up things
other than the environment now.
* In MWServer:handleRegisterLibrary(), remove the feature which interprets dots
in library names, since LuaSandbox doesn't support this.
Improved module isolation and related refactoring:
* Expose restricted versions of getfenv() and setfenv() to user Lua code.
Requires luasandbox r114952.
* Don't cache the export list returned by module execution for later function
calls. This breaks isolation of #invoke calls, since the local variables are
persistent.
* Removed ScribuntoFunctionBase and its children, since it doesn't really have
a purpose if it can't cache anything. Instead, invoke functions using a module
method called invoke().
* Removed Module::initialize(), replaced it with a validate() function. This is
a more elegant interface and works better with the new module caching scheme.
* Use a Status object for the return value of Engine::validate() instead of an
array. Use the formatting facilities of the Status class.
Other:
* Removed "too many returns" error, doesn't fit in with Lua conventions.
* Use the standalone engine by default, so that the extension will work without
configuration for more people.
* Added an accessor for $engine->interpreter
* Fix mw.clone() to correctly clone metatables
* If the standalone interpreter exits due to an error, there are some contexts
where the initial error will be caught and ignored, and the user will see the
error from checkValid() instead. In this case, rethrow the original error for
a more informative message.
* Load mw.lua into the initial standalone environment, to reduce code
duplication between mw.lua and MWServer.lua.
* Fixed a bug in Scribunto_LuaStandaloneInterpreter::handleCall() for functions
that return no results.
* Fixed a bug in encodeLuaVar() for strings with "\r". Added test case.
* In MWServer.lua, don't call error() for internal errors, instead just print
the error and exit. This avoids a protocol violation when an error is
encountered from within handleCall().
* Added lots of documentation. Lua doc comments are in LuaDoc format.
Change-Id: Ie2fd572c362bedf02f45d3fa5352a5280e034740
2012-04-18 03:46:18 +00:00
|
|
|
/**
|
|
|
|
* Get the current interpreter object
|
2013-02-15 23:41:20 +00:00
|
|
|
* @return Scribunto_LuaInterpreter
|
Added more Lua environment features
Package library:
* Added a simulation of the Lua 5.1 package library.
* Removed mw.import(), replaced it with a package loader. Packages can be
retrieved from the wiki, using require('Module:Foo'), or from files
distributed with Scribunto, using require('foo'). The "Module:" prefix allows
for source compatibility with existing Lua code.
* Added a couple of libraries from LuaForge: luabit and stringtools.
* Made fetchModuleFromParser() return null on error instead of throwing an
exception, to more easily support the desired behaviour of the package loader,
which needs to return null on error.
* Renamed mw.setupEnvironment() to mw.setup() since it is setting up things
other than the environment now.
* In MWServer:handleRegisterLibrary(), remove the feature which interprets dots
in library names, since LuaSandbox doesn't support this.
Improved module isolation and related refactoring:
* Expose restricted versions of getfenv() and setfenv() to user Lua code.
Requires luasandbox r114952.
* Don't cache the export list returned by module execution for later function
calls. This breaks isolation of #invoke calls, since the local variables are
persistent.
* Removed ScribuntoFunctionBase and its children, since it doesn't really have
a purpose if it can't cache anything. Instead, invoke functions using a module
method called invoke().
* Removed Module::initialize(), replaced it with a validate() function. This is
a more elegant interface and works better with the new module caching scheme.
* Use a Status object for the return value of Engine::validate() instead of an
array. Use the formatting facilities of the Status class.
Other:
* Removed "too many returns" error, doesn't fit in with Lua conventions.
* Use the standalone engine by default, so that the extension will work without
configuration for more people.
* Added an accessor for $engine->interpreter
* Fix mw.clone() to correctly clone metatables
* If the standalone interpreter exits due to an error, there are some contexts
where the initial error will be caught and ignored, and the user will see the
error from checkValid() instead. In this case, rethrow the original error for
a more informative message.
* Load mw.lua into the initial standalone environment, to reduce code
duplication between mw.lua and MWServer.lua.
* Fixed a bug in Scribunto_LuaStandaloneInterpreter::handleCall() for functions
that return no results.
* Fixed a bug in encodeLuaVar() for strings with "\r". Added test case.
* In MWServer.lua, don't call error() for internal errors, instead just print
the error and exit. This avoids a protocol violation when an error is
encountered from within handleCall().
* Added lots of documentation. Lua doc comments are in LuaDoc format.
Change-Id: Ie2fd572c362bedf02f45d3fa5352a5280e034740
2012-04-18 03:46:18 +00:00
|
|
|
*/
|
|
|
|
public function getInterpreter() {
|
|
|
|
$this->load();
|
|
|
|
return $this->interpreter;
|
|
|
|
}
|
|
|
|
|
2014-07-07 16:30:44 +00:00
|
|
|
/**
|
|
|
|
* Replaces the list of current frames, and return a ScopedCallback that
|
|
|
|
* will reset them when it goes out of scope.
|
|
|
|
*
|
|
|
|
* @param PPFrame|null $frame If null, an empty frame with no parent will be used
|
|
|
|
* @return ScopedCallback
|
|
|
|
*/
|
|
|
|
private function setupCurrentFrames( PPFrame $frame = null ) {
|
|
|
|
if ( !$frame ) {
|
|
|
|
$frame = $this->getParser()->getPreprocessor()->newFrame();
|
|
|
|
}
|
|
|
|
|
|
|
|
$oldFrames = $this->currentFrames;
|
|
|
|
$this->currentFrames = array(
|
|
|
|
'current' => $frame,
|
|
|
|
'parent' => isset( $frame->parent ) ? $frame->parent : null,
|
|
|
|
);
|
|
|
|
|
|
|
|
// @todo Once support for PHP 5.3 is dropped, lose $ref and just use
|
|
|
|
// $this->currentFrames directly in the callback.
|
|
|
|
$ref = &$this->currentFrames;
|
|
|
|
return new ScopedCallback( function () use ( &$ref, $oldFrames ) {
|
|
|
|
$ref = $oldFrames;
|
|
|
|
} );
|
|
|
|
}
|
|
|
|
|
Added more Lua environment features
Package library:
* Added a simulation of the Lua 5.1 package library.
* Removed mw.import(), replaced it with a package loader. Packages can be
retrieved from the wiki, using require('Module:Foo'), or from files
distributed with Scribunto, using require('foo'). The "Module:" prefix allows
for source compatibility with existing Lua code.
* Added a couple of libraries from LuaForge: luabit and stringtools.
* Made fetchModuleFromParser() return null on error instead of throwing an
exception, to more easily support the desired behaviour of the package loader,
which needs to return null on error.
* Renamed mw.setupEnvironment() to mw.setup() since it is setting up things
other than the environment now.
* In MWServer:handleRegisterLibrary(), remove the feature which interprets dots
in library names, since LuaSandbox doesn't support this.
Improved module isolation and related refactoring:
* Expose restricted versions of getfenv() and setfenv() to user Lua code.
Requires luasandbox r114952.
* Don't cache the export list returned by module execution for later function
calls. This breaks isolation of #invoke calls, since the local variables are
persistent.
* Removed ScribuntoFunctionBase and its children, since it doesn't really have
a purpose if it can't cache anything. Instead, invoke functions using a module
method called invoke().
* Removed Module::initialize(), replaced it with a validate() function. This is
a more elegant interface and works better with the new module caching scheme.
* Use a Status object for the return value of Engine::validate() instead of an
array. Use the formatting facilities of the Status class.
Other:
* Removed "too many returns" error, doesn't fit in with Lua conventions.
* Use the standalone engine by default, so that the extension will work without
configuration for more people.
* Added an accessor for $engine->interpreter
* Fix mw.clone() to correctly clone metatables
* If the standalone interpreter exits due to an error, there are some contexts
where the initial error will be caught and ignored, and the user will see the
error from checkValid() instead. In this case, rethrow the original error for
a more informative message.
* Load mw.lua into the initial standalone environment, to reduce code
duplication between mw.lua and MWServer.lua.
* Fixed a bug in Scribunto_LuaStandaloneInterpreter::handleCall() for functions
that return no results.
* Fixed a bug in encodeLuaVar() for strings with "\r". Added test case.
* In MWServer.lua, don't call error() for internal errors, instead just print
the error and exit. This avoids a protocol violation when an error is
encountered from within handleCall().
* Added lots of documentation. Lua doc comments are in LuaDoc format.
Change-Id: Ie2fd572c362bedf02f45d3fa5352a5280e034740
2012-04-18 03:46:18 +00:00
|
|
|
/**
|
2014-05-23 15:43:22 +00:00
|
|
|
* Execute a module chunk in a new isolated environment, and return the specified function
|
Added more Lua environment features
Package library:
* Added a simulation of the Lua 5.1 package library.
* Removed mw.import(), replaced it with a package loader. Packages can be
retrieved from the wiki, using require('Module:Foo'), or from files
distributed with Scribunto, using require('foo'). The "Module:" prefix allows
for source compatibility with existing Lua code.
* Added a couple of libraries from LuaForge: luabit and stringtools.
* Made fetchModuleFromParser() return null on error instead of throwing an
exception, to more easily support the desired behaviour of the package loader,
which needs to return null on error.
* Renamed mw.setupEnvironment() to mw.setup() since it is setting up things
other than the environment now.
* In MWServer:handleRegisterLibrary(), remove the feature which interprets dots
in library names, since LuaSandbox doesn't support this.
Improved module isolation and related refactoring:
* Expose restricted versions of getfenv() and setfenv() to user Lua code.
Requires luasandbox r114952.
* Don't cache the export list returned by module execution for later function
calls. This breaks isolation of #invoke calls, since the local variables are
persistent.
* Removed ScribuntoFunctionBase and its children, since it doesn't really have
a purpose if it can't cache anything. Instead, invoke functions using a module
method called invoke().
* Removed Module::initialize(), replaced it with a validate() function. This is
a more elegant interface and works better with the new module caching scheme.
* Use a Status object for the return value of Engine::validate() instead of an
array. Use the formatting facilities of the Status class.
Other:
* Removed "too many returns" error, doesn't fit in with Lua conventions.
* Use the standalone engine by default, so that the extension will work without
configuration for more people.
* Added an accessor for $engine->interpreter
* Fix mw.clone() to correctly clone metatables
* If the standalone interpreter exits due to an error, there are some contexts
where the initial error will be caught and ignored, and the user will see the
error from checkValid() instead. In this case, rethrow the original error for
a more informative message.
* Load mw.lua into the initial standalone environment, to reduce code
duplication between mw.lua and MWServer.lua.
* Fixed a bug in Scribunto_LuaStandaloneInterpreter::handleCall() for functions
that return no results.
* Fixed a bug in encodeLuaVar() for strings with "\r". Added test case.
* In MWServer.lua, don't call error() for internal errors, instead just print
the error and exit. This avoids a protocol violation when an error is
encountered from within handleCall().
* Added lots of documentation. Lua doc comments are in LuaDoc format.
Change-Id: Ie2fd572c362bedf02f45d3fa5352a5280e034740
2012-04-18 03:46:18 +00:00
|
|
|
*/
|
2014-07-07 16:30:44 +00:00
|
|
|
public function executeModule( $chunk, $functionName, $frame ) {
|
|
|
|
$resetFrames = null;
|
|
|
|
if ( !$this->currentFrames || !isset( $this->currentFrames['current'] ) ) {
|
|
|
|
// Only reset frames if there isn't already current frame
|
2014-07-07 18:46:59 +00:00
|
|
|
// $resetFrames is a ScopedCallback, so it has a purpose even though it appears unused.
|
2014-07-07 16:30:44 +00:00
|
|
|
$resetFrames = $this->setupCurrentFrames( $frame );
|
|
|
|
}
|
|
|
|
|
2014-05-23 15:43:22 +00:00
|
|
|
$retval = $this->getInterpreter()->callFunction( $this->mw['executeModule'], $chunk, $functionName );
|
|
|
|
if ( !$retval[0] ) {
|
|
|
|
// If we get here, it means we asked for an element from the table the module returned,
|
|
|
|
// but it returned something other than a table. In this case, $retval[1] contains the type
|
|
|
|
// of what it did returned, instead of the value we asked for.
|
|
|
|
throw $this->newException( 'scribunto-lua-notarrayreturn', array( 'args' => array( $retval[1] ) ) );
|
|
|
|
}
|
|
|
|
return $retval[1];
|
2012-05-22 03:56:07 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Execute a module function chunk
|
|
|
|
*/
|
|
|
|
public function executeFunctionChunk( $chunk, $frame ) {
|
2014-07-07 18:46:59 +00:00
|
|
|
// $resetFrames is a ScopedCallback, so it has a purpose even though it appears unused.
|
2014-07-07 16:30:44 +00:00
|
|
|
$resetFrames = $this->setupCurrentFrames( $frame );
|
|
|
|
|
|
|
|
return $this->getInterpreter()->callFunction(
|
|
|
|
$this->mw['executeFunction'],
|
|
|
|
$chunk );
|
2012-04-13 10:38:12 +00:00
|
|
|
}
|
|
|
|
|
Added more Lua environment features
Package library:
* Added a simulation of the Lua 5.1 package library.
* Removed mw.import(), replaced it with a package loader. Packages can be
retrieved from the wiki, using require('Module:Foo'), or from files
distributed with Scribunto, using require('foo'). The "Module:" prefix allows
for source compatibility with existing Lua code.
* Added a couple of libraries from LuaForge: luabit and stringtools.
* Made fetchModuleFromParser() return null on error instead of throwing an
exception, to more easily support the desired behaviour of the package loader,
which needs to return null on error.
* Renamed mw.setupEnvironment() to mw.setup() since it is setting up things
other than the environment now.
* In MWServer:handleRegisterLibrary(), remove the feature which interprets dots
in library names, since LuaSandbox doesn't support this.
Improved module isolation and related refactoring:
* Expose restricted versions of getfenv() and setfenv() to user Lua code.
Requires luasandbox r114952.
* Don't cache the export list returned by module execution for later function
calls. This breaks isolation of #invoke calls, since the local variables are
persistent.
* Removed ScribuntoFunctionBase and its children, since it doesn't really have
a purpose if it can't cache anything. Instead, invoke functions using a module
method called invoke().
* Removed Module::initialize(), replaced it with a validate() function. This is
a more elegant interface and works better with the new module caching scheme.
* Use a Status object for the return value of Engine::validate() instead of an
array. Use the formatting facilities of the Status class.
Other:
* Removed "too many returns" error, doesn't fit in with Lua conventions.
* Use the standalone engine by default, so that the extension will work without
configuration for more people.
* Added an accessor for $engine->interpreter
* Fix mw.clone() to correctly clone metatables
* If the standalone interpreter exits due to an error, there are some contexts
where the initial error will be caught and ignored, and the user will see the
error from checkValid() instead. In this case, rethrow the original error for
a more informative message.
* Load mw.lua into the initial standalone environment, to reduce code
duplication between mw.lua and MWServer.lua.
* Fixed a bug in Scribunto_LuaStandaloneInterpreter::handleCall() for functions
that return no results.
* Fixed a bug in encodeLuaVar() for strings with "\r". Added test case.
* In MWServer.lua, don't call error() for internal errors, instead just print
the error and exit. This avoids a protocol violation when an error is
encountered from within handleCall().
* Added lots of documentation. Lua doc comments are in LuaDoc format.
Change-Id: Ie2fd572c362bedf02f45d3fa5352a5280e034740
2012-04-18 03:46:18 +00:00
|
|
|
/**
|
|
|
|
* Load a library from the given file and execute it in the base environment.
|
2013-02-15 23:41:20 +00:00
|
|
|
* @param string File name/path to load
|
|
|
|
* @return mixed the export list, or null if there isn't one.
|
Added more Lua environment features
Package library:
* Added a simulation of the Lua 5.1 package library.
* Removed mw.import(), replaced it with a package loader. Packages can be
retrieved from the wiki, using require('Module:Foo'), or from files
distributed with Scribunto, using require('foo'). The "Module:" prefix allows
for source compatibility with existing Lua code.
* Added a couple of libraries from LuaForge: luabit and stringtools.
* Made fetchModuleFromParser() return null on error instead of throwing an
exception, to more easily support the desired behaviour of the package loader,
which needs to return null on error.
* Renamed mw.setupEnvironment() to mw.setup() since it is setting up things
other than the environment now.
* In MWServer:handleRegisterLibrary(), remove the feature which interprets dots
in library names, since LuaSandbox doesn't support this.
Improved module isolation and related refactoring:
* Expose restricted versions of getfenv() and setfenv() to user Lua code.
Requires luasandbox r114952.
* Don't cache the export list returned by module execution for later function
calls. This breaks isolation of #invoke calls, since the local variables are
persistent.
* Removed ScribuntoFunctionBase and its children, since it doesn't really have
a purpose if it can't cache anything. Instead, invoke functions using a module
method called invoke().
* Removed Module::initialize(), replaced it with a validate() function. This is
a more elegant interface and works better with the new module caching scheme.
* Use a Status object for the return value of Engine::validate() instead of an
array. Use the formatting facilities of the Status class.
Other:
* Removed "too many returns" error, doesn't fit in with Lua conventions.
* Use the standalone engine by default, so that the extension will work without
configuration for more people.
* Added an accessor for $engine->interpreter
* Fix mw.clone() to correctly clone metatables
* If the standalone interpreter exits due to an error, there are some contexts
where the initial error will be caught and ignored, and the user will see the
error from checkValid() instead. In this case, rethrow the original error for
a more informative message.
* Load mw.lua into the initial standalone environment, to reduce code
duplication between mw.lua and MWServer.lua.
* Fixed a bug in Scribunto_LuaStandaloneInterpreter::handleCall() for functions
that return no results.
* Fixed a bug in encodeLuaVar() for strings with "\r". Added test case.
* In MWServer.lua, don't call error() for internal errors, instead just print
the error and exit. This avoids a protocol violation when an error is
encountered from within handleCall().
* Added lots of documentation. Lua doc comments are in LuaDoc format.
Change-Id: Ie2fd572c362bedf02f45d3fa5352a5280e034740
2012-04-18 03:46:18 +00:00
|
|
|
*/
|
2012-04-13 10:38:12 +00:00
|
|
|
protected function loadLibraryFromFile( $fileName ) {
|
|
|
|
$code = file_get_contents( $fileName );
|
|
|
|
if ( $code === false ) {
|
|
|
|
throw new MWException( 'Lua file does not exist: ' . $fileName );
|
|
|
|
}
|
2012-04-19 07:40:56 +00:00
|
|
|
# Prepending an "@" to the chunk name makes Lua think it is a filename
|
|
|
|
$module = $this->getInterpreter()->loadString( $code, '@' . basename( $fileName ) );
|
|
|
|
$ret = $this->getInterpreter()->callFunction( $module );
|
Added more Lua environment features
Package library:
* Added a simulation of the Lua 5.1 package library.
* Removed mw.import(), replaced it with a package loader. Packages can be
retrieved from the wiki, using require('Module:Foo'), or from files
distributed with Scribunto, using require('foo'). The "Module:" prefix allows
for source compatibility with existing Lua code.
* Added a couple of libraries from LuaForge: luabit and stringtools.
* Made fetchModuleFromParser() return null on error instead of throwing an
exception, to more easily support the desired behaviour of the package loader,
which needs to return null on error.
* Renamed mw.setupEnvironment() to mw.setup() since it is setting up things
other than the environment now.
* In MWServer:handleRegisterLibrary(), remove the feature which interprets dots
in library names, since LuaSandbox doesn't support this.
Improved module isolation and related refactoring:
* Expose restricted versions of getfenv() and setfenv() to user Lua code.
Requires luasandbox r114952.
* Don't cache the export list returned by module execution for later function
calls. This breaks isolation of #invoke calls, since the local variables are
persistent.
* Removed ScribuntoFunctionBase and its children, since it doesn't really have
a purpose if it can't cache anything. Instead, invoke functions using a module
method called invoke().
* Removed Module::initialize(), replaced it with a validate() function. This is
a more elegant interface and works better with the new module caching scheme.
* Use a Status object for the return value of Engine::validate() instead of an
array. Use the formatting facilities of the Status class.
Other:
* Removed "too many returns" error, doesn't fit in with Lua conventions.
* Use the standalone engine by default, so that the extension will work without
configuration for more people.
* Added an accessor for $engine->interpreter
* Fix mw.clone() to correctly clone metatables
* If the standalone interpreter exits due to an error, there are some contexts
where the initial error will be caught and ignored, and the user will see the
error from checkValid() instead. In this case, rethrow the original error for
a more informative message.
* Load mw.lua into the initial standalone environment, to reduce code
duplication between mw.lua and MWServer.lua.
* Fixed a bug in Scribunto_LuaStandaloneInterpreter::handleCall() for functions
that return no results.
* Fixed a bug in encodeLuaVar() for strings with "\r". Added test case.
* In MWServer.lua, don't call error() for internal errors, instead just print
the error and exit. This avoids a protocol violation when an error is
encountered from within handleCall().
* Added lots of documentation. Lua doc comments are in LuaDoc format.
Change-Id: Ie2fd572c362bedf02f45d3fa5352a5280e034740
2012-04-18 03:46:18 +00:00
|
|
|
return isset( $ret[0] ) ? $ret[0] : null;
|
2012-04-13 10:38:12 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
public function getGeSHiLanguage() {
|
|
|
|
return 'lua';
|
|
|
|
}
|
2012-05-22 03:56:07 +00:00
|
|
|
|
2012-04-13 10:38:12 +00:00
|
|
|
public function getCodeEditorLanguage() {
|
|
|
|
return 'lua';
|
|
|
|
}
|
|
|
|
|
2012-07-14 04:23:42 +00:00
|
|
|
public function runConsole( $params ) {
|
2014-07-07 18:46:59 +00:00
|
|
|
// $resetFrames is a ScopedCallback, so it has a purpose even though it appears unused.
|
2014-07-07 16:30:44 +00:00
|
|
|
$resetFrames = $this->setupCurrentFrames();
|
|
|
|
|
|
|
|
/**
|
|
|
|
* TODO: provide some means for giving correct line numbers for errors
|
|
|
|
* in console input, and for producing an informative error message
|
|
|
|
* if there is an error in prevQuestions.
|
|
|
|
*
|
2014-07-07 18:46:59 +00:00
|
|
|
* Maybe each console line could be evaluated as a different chunk,
|
2014-07-07 16:30:44 +00:00
|
|
|
* apparently that's what lua.c does.
|
|
|
|
*/
|
|
|
|
$code = "return function (__init, exe)\n" .
|
|
|
|
"local _, p = exe(__init)\n" .
|
|
|
|
"_, __init, exe = nil, nil, nil\n" .
|
|
|
|
"local print = mw.log\n";
|
|
|
|
foreach ( $params['prevQuestions'] as $q ) {
|
|
|
|
if ( substr( $q, 0, 1 ) === '=' ) {
|
|
|
|
$code .= "print(" . substr( $q, 1 ) . ")";
|
2012-07-14 04:23:42 +00:00
|
|
|
} else {
|
2014-07-07 16:30:44 +00:00
|
|
|
$code .= $q;
|
2012-07-14 04:23:42 +00:00
|
|
|
}
|
2014-07-07 16:30:44 +00:00
|
|
|
$code .= "\n";
|
|
|
|
}
|
|
|
|
$code .= "mw.clearLogBuffer()\n";
|
|
|
|
if ( substr( $params['question'], 0, 1 ) === '=' ) {
|
|
|
|
// Treat a statement starting with "=" as a return statement, like in lua.c
|
|
|
|
$code .= "local ret = mw.allToString(" . substr( $params['question'], 1 ) . ")\n" .
|
|
|
|
"return ret, mw.getLogBuffer()\n";
|
|
|
|
} else {
|
|
|
|
$code .= $params['question'] . "\n" .
|
|
|
|
"return nil, mw.getLogBuffer()\n";
|
|
|
|
}
|
|
|
|
$code .= "end\n";
|
2013-02-19 00:49:08 +00:00
|
|
|
|
2014-07-07 18:46:59 +00:00
|
|
|
$contentModule = $this->newModule(
|
2014-07-07 16:30:44 +00:00
|
|
|
$params['content'], $params['title']->getPrefixedDBkey() );
|
|
|
|
$contentInit = $contentModule->getInitChunk();
|
2013-02-19 00:49:08 +00:00
|
|
|
|
2014-07-07 16:30:44 +00:00
|
|
|
$consoleModule = $this->newModule(
|
|
|
|
$code,
|
|
|
|
wfMessage( 'scribunto-console-current-src' )->text()
|
|
|
|
);
|
|
|
|
$consoleInit = $consoleModule->getInitChunk();
|
|
|
|
$ret = $this->getInterpreter()->callFunction( $this->mw['executeModule'], $consoleInit, false );
|
|
|
|
$func = $ret[1];
|
|
|
|
$ret = $this->getInterpreter()->callFunction( $func, $contentInit, $this->mw['executeModule'] );
|
2012-07-14 04:23:42 +00:00
|
|
|
|
|
|
|
return array(
|
|
|
|
'return' => isset( $ret[0] ) ? $ret[0] : null,
|
|
|
|
'print' => isset( $ret[1] ) ? $ret[1] : '',
|
|
|
|
);
|
|
|
|
}
|
2014-06-18 17:17:04 +00:00
|
|
|
|
2012-04-13 10:38:12 +00:00
|
|
|
/**
|
|
|
|
* Workalike for luaL_checktype()
|
|
|
|
*
|
2014-06-18 17:17:04 +00:00
|
|
|
* @param string $funcName The Lua function name, for use in error messages
|
|
|
|
* @param array $args The argument array
|
|
|
|
* @param int $index0 The zero-based argument index
|
|
|
|
* @param string $type The type name as given by gettype()
|
|
|
|
* @param string $msgType The type name used in the error message
|
|
|
|
* @throws Scribunto_LuaError
|
2012-04-13 10:38:12 +00:00
|
|
|
*/
|
|
|
|
public function checkType( $funcName, $args, $index0, $type, $msgType ) {
|
2014-06-01 03:15:42 +00:00
|
|
|
if ( !is_array( $type ) ) {
|
|
|
|
$type = array( $type );
|
|
|
|
}
|
|
|
|
if ( !isset( $args[$index0] ) || !in_array( gettype( $args[$index0] ), $type, true ) ) {
|
2012-04-13 10:38:12 +00:00
|
|
|
$index1 = $index0 + 1;
|
|
|
|
throw new Scribunto_LuaError( "bad argument #$index1 to '$funcName' ($msgType expected)" );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Workalike for luaL_checkstring()
|
|
|
|
*
|
2014-06-18 17:17:04 +00:00
|
|
|
* @param string $funcName The Lua function name, for use in error messages
|
|
|
|
* @param array $args The argument array
|
|
|
|
* @param int $index0 The zero-based argument index
|
2012-04-13 10:38:12 +00:00
|
|
|
*/
|
|
|
|
public function checkString( $funcName, $args, $index0 ) {
|
|
|
|
$this->checkType( $funcName, $args, $index0, 'string', 'string' );
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Workalike for luaL_checknumber()
|
|
|
|
*
|
2014-06-18 17:17:04 +00:00
|
|
|
* @param string $funcName The Lua function name, for use in error messages
|
|
|
|
* @param array $args The argument array
|
|
|
|
* @param int $index0 The zero-based argument index
|
2012-04-13 10:38:12 +00:00
|
|
|
*/
|
|
|
|
public function checkNumber( $funcName, $args, $index0 ) {
|
2014-06-01 03:15:42 +00:00
|
|
|
$this->checkType( $funcName, $args, $index0, array( 'integer', 'double' ), 'number' );
|
2012-04-13 10:38:12 +00:00
|
|
|
}
|
|
|
|
|
Added more Lua environment features
Package library:
* Added a simulation of the Lua 5.1 package library.
* Removed mw.import(), replaced it with a package loader. Packages can be
retrieved from the wiki, using require('Module:Foo'), or from files
distributed with Scribunto, using require('foo'). The "Module:" prefix allows
for source compatibility with existing Lua code.
* Added a couple of libraries from LuaForge: luabit and stringtools.
* Made fetchModuleFromParser() return null on error instead of throwing an
exception, to more easily support the desired behaviour of the package loader,
which needs to return null on error.
* Renamed mw.setupEnvironment() to mw.setup() since it is setting up things
other than the environment now.
* In MWServer:handleRegisterLibrary(), remove the feature which interprets dots
in library names, since LuaSandbox doesn't support this.
Improved module isolation and related refactoring:
* Expose restricted versions of getfenv() and setfenv() to user Lua code.
Requires luasandbox r114952.
* Don't cache the export list returned by module execution for later function
calls. This breaks isolation of #invoke calls, since the local variables are
persistent.
* Removed ScribuntoFunctionBase and its children, since it doesn't really have
a purpose if it can't cache anything. Instead, invoke functions using a module
method called invoke().
* Removed Module::initialize(), replaced it with a validate() function. This is
a more elegant interface and works better with the new module caching scheme.
* Use a Status object for the return value of Engine::validate() instead of an
array. Use the formatting facilities of the Status class.
Other:
* Removed "too many returns" error, doesn't fit in with Lua conventions.
* Use the standalone engine by default, so that the extension will work without
configuration for more people.
* Added an accessor for $engine->interpreter
* Fix mw.clone() to correctly clone metatables
* If the standalone interpreter exits due to an error, there are some contexts
where the initial error will be caught and ignored, and the user will see the
error from checkValid() instead. In this case, rethrow the original error for
a more informative message.
* Load mw.lua into the initial standalone environment, to reduce code
duplication between mw.lua and MWServer.lua.
* Fixed a bug in Scribunto_LuaStandaloneInterpreter::handleCall() for functions
that return no results.
* Fixed a bug in encodeLuaVar() for strings with "\r". Added test case.
* In MWServer.lua, don't call error() for internal errors, instead just print
the error and exit. This avoids a protocol violation when an error is
encountered from within handleCall().
* Added lots of documentation. Lua doc comments are in LuaDoc format.
Change-Id: Ie2fd572c362bedf02f45d3fa5352a5280e034740
2012-04-18 03:46:18 +00:00
|
|
|
/**
|
2013-01-25 17:53:18 +00:00
|
|
|
* Handler for the loadPackage() callback. Load the specified
|
Added more Lua environment features
Package library:
* Added a simulation of the Lua 5.1 package library.
* Removed mw.import(), replaced it with a package loader. Packages can be
retrieved from the wiki, using require('Module:Foo'), or from files
distributed with Scribunto, using require('foo'). The "Module:" prefix allows
for source compatibility with existing Lua code.
* Added a couple of libraries from LuaForge: luabit and stringtools.
* Made fetchModuleFromParser() return null on error instead of throwing an
exception, to more easily support the desired behaviour of the package loader,
which needs to return null on error.
* Renamed mw.setupEnvironment() to mw.setup() since it is setting up things
other than the environment now.
* In MWServer:handleRegisterLibrary(), remove the feature which interprets dots
in library names, since LuaSandbox doesn't support this.
Improved module isolation and related refactoring:
* Expose restricted versions of getfenv() and setfenv() to user Lua code.
Requires luasandbox r114952.
* Don't cache the export list returned by module execution for later function
calls. This breaks isolation of #invoke calls, since the local variables are
persistent.
* Removed ScribuntoFunctionBase and its children, since it doesn't really have
a purpose if it can't cache anything. Instead, invoke functions using a module
method called invoke().
* Removed Module::initialize(), replaced it with a validate() function. This is
a more elegant interface and works better with the new module caching scheme.
* Use a Status object for the return value of Engine::validate() instead of an
array. Use the formatting facilities of the Status class.
Other:
* Removed "too many returns" error, doesn't fit in with Lua conventions.
* Use the standalone engine by default, so that the extension will work without
configuration for more people.
* Added an accessor for $engine->interpreter
* Fix mw.clone() to correctly clone metatables
* If the standalone interpreter exits due to an error, there are some contexts
where the initial error will be caught and ignored, and the user will see the
error from checkValid() instead. In this case, rethrow the original error for
a more informative message.
* Load mw.lua into the initial standalone environment, to reduce code
duplication between mw.lua and MWServer.lua.
* Fixed a bug in Scribunto_LuaStandaloneInterpreter::handleCall() for functions
that return no results.
* Fixed a bug in encodeLuaVar() for strings with "\r". Added test case.
* In MWServer.lua, don't call error() for internal errors, instead just print
the error and exit. This avoids a protocol violation when an error is
encountered from within handleCall().
* Added lots of documentation. Lua doc comments are in LuaDoc format.
Change-Id: Ie2fd572c362bedf02f45d3fa5352a5280e034740
2012-04-18 03:46:18 +00:00
|
|
|
* module and return its chunk. It's not necessary to cache the resulting
|
|
|
|
* chunk in the object instance, since there is caching in a wrapper on the
|
|
|
|
* Lua side.
|
|
|
|
*/
|
|
|
|
function loadPackage( $name ) {
|
2012-04-13 10:38:12 +00:00
|
|
|
$args = func_get_args();
|
Added more Lua environment features
Package library:
* Added a simulation of the Lua 5.1 package library.
* Removed mw.import(), replaced it with a package loader. Packages can be
retrieved from the wiki, using require('Module:Foo'), or from files
distributed with Scribunto, using require('foo'). The "Module:" prefix allows
for source compatibility with existing Lua code.
* Added a couple of libraries from LuaForge: luabit and stringtools.
* Made fetchModuleFromParser() return null on error instead of throwing an
exception, to more easily support the desired behaviour of the package loader,
which needs to return null on error.
* Renamed mw.setupEnvironment() to mw.setup() since it is setting up things
other than the environment now.
* In MWServer:handleRegisterLibrary(), remove the feature which interprets dots
in library names, since LuaSandbox doesn't support this.
Improved module isolation and related refactoring:
* Expose restricted versions of getfenv() and setfenv() to user Lua code.
Requires luasandbox r114952.
* Don't cache the export list returned by module execution for later function
calls. This breaks isolation of #invoke calls, since the local variables are
persistent.
* Removed ScribuntoFunctionBase and its children, since it doesn't really have
a purpose if it can't cache anything. Instead, invoke functions using a module
method called invoke().
* Removed Module::initialize(), replaced it with a validate() function. This is
a more elegant interface and works better with the new module caching scheme.
* Use a Status object for the return value of Engine::validate() instead of an
array. Use the formatting facilities of the Status class.
Other:
* Removed "too many returns" error, doesn't fit in with Lua conventions.
* Use the standalone engine by default, so that the extension will work without
configuration for more people.
* Added an accessor for $engine->interpreter
* Fix mw.clone() to correctly clone metatables
* If the standalone interpreter exits due to an error, there are some contexts
where the initial error will be caught and ignored, and the user will see the
error from checkValid() instead. In this case, rethrow the original error for
a more informative message.
* Load mw.lua into the initial standalone environment, to reduce code
duplication between mw.lua and MWServer.lua.
* Fixed a bug in Scribunto_LuaStandaloneInterpreter::handleCall() for functions
that return no results.
* Fixed a bug in encodeLuaVar() for strings with "\r". Added test case.
* In MWServer.lua, don't call error() for internal errors, instead just print
the error and exit. This avoids a protocol violation when an error is
encountered from within handleCall().
* Added lots of documentation. Lua doc comments are in LuaDoc format.
Change-Id: Ie2fd572c362bedf02f45d3fa5352a5280e034740
2012-04-18 03:46:18 +00:00
|
|
|
$this->checkString( 'loadPackage', $args, 0 );
|
|
|
|
|
2013-02-08 19:20:32 +00:00
|
|
|
# This is what Lua does for its built-in loaders
|
|
|
|
$luaName = str_replace( '.', '/', $name ) . '.lua';
|
2013-02-14 17:38:03 +00:00
|
|
|
$paths = $this->getLibraryPaths( 'lua', self::$libraryPaths );
|
|
|
|
foreach ( $paths as $path ) {
|
|
|
|
$fileName = $this->normalizeModuleFileName( "$path/$luaName" );
|
Added more Lua environment features
Package library:
* Added a simulation of the Lua 5.1 package library.
* Removed mw.import(), replaced it with a package loader. Packages can be
retrieved from the wiki, using require('Module:Foo'), or from files
distributed with Scribunto, using require('foo'). The "Module:" prefix allows
for source compatibility with existing Lua code.
* Added a couple of libraries from LuaForge: luabit and stringtools.
* Made fetchModuleFromParser() return null on error instead of throwing an
exception, to more easily support the desired behaviour of the package loader,
which needs to return null on error.
* Renamed mw.setupEnvironment() to mw.setup() since it is setting up things
other than the environment now.
* In MWServer:handleRegisterLibrary(), remove the feature which interprets dots
in library names, since LuaSandbox doesn't support this.
Improved module isolation and related refactoring:
* Expose restricted versions of getfenv() and setfenv() to user Lua code.
Requires luasandbox r114952.
* Don't cache the export list returned by module execution for later function
calls. This breaks isolation of #invoke calls, since the local variables are
persistent.
* Removed ScribuntoFunctionBase and its children, since it doesn't really have
a purpose if it can't cache anything. Instead, invoke functions using a module
method called invoke().
* Removed Module::initialize(), replaced it with a validate() function. This is
a more elegant interface and works better with the new module caching scheme.
* Use a Status object for the return value of Engine::validate() instead of an
array. Use the formatting facilities of the Status class.
Other:
* Removed "too many returns" error, doesn't fit in with Lua conventions.
* Use the standalone engine by default, so that the extension will work without
configuration for more people.
* Added an accessor for $engine->interpreter
* Fix mw.clone() to correctly clone metatables
* If the standalone interpreter exits due to an error, there are some contexts
where the initial error will be caught and ignored, and the user will see the
error from checkValid() instead. In this case, rethrow the original error for
a more informative message.
* Load mw.lua into the initial standalone environment, to reduce code
duplication between mw.lua and MWServer.lua.
* Fixed a bug in Scribunto_LuaStandaloneInterpreter::handleCall() for functions
that return no results.
* Fixed a bug in encodeLuaVar() for strings with "\r". Added test case.
* In MWServer.lua, don't call error() for internal errors, instead just print
the error and exit. This avoids a protocol violation when an error is
encountered from within handleCall().
* Added lots of documentation. Lua doc comments are in LuaDoc format.
Change-Id: Ie2fd572c362bedf02f45d3fa5352a5280e034740
2012-04-18 03:46:18 +00:00
|
|
|
if ( !file_exists( $fileName ) ) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
$code = file_get_contents( $fileName );
|
2013-02-08 19:20:32 +00:00
|
|
|
$init = $this->interpreter->loadString( $code, "@$luaName" );
|
Added more Lua environment features
Package library:
* Added a simulation of the Lua 5.1 package library.
* Removed mw.import(), replaced it with a package loader. Packages can be
retrieved from the wiki, using require('Module:Foo'), or from files
distributed with Scribunto, using require('foo'). The "Module:" prefix allows
for source compatibility with existing Lua code.
* Added a couple of libraries from LuaForge: luabit and stringtools.
* Made fetchModuleFromParser() return null on error instead of throwing an
exception, to more easily support the desired behaviour of the package loader,
which needs to return null on error.
* Renamed mw.setupEnvironment() to mw.setup() since it is setting up things
other than the environment now.
* In MWServer:handleRegisterLibrary(), remove the feature which interprets dots
in library names, since LuaSandbox doesn't support this.
Improved module isolation and related refactoring:
* Expose restricted versions of getfenv() and setfenv() to user Lua code.
Requires luasandbox r114952.
* Don't cache the export list returned by module execution for later function
calls. This breaks isolation of #invoke calls, since the local variables are
persistent.
* Removed ScribuntoFunctionBase and its children, since it doesn't really have
a purpose if it can't cache anything. Instead, invoke functions using a module
method called invoke().
* Removed Module::initialize(), replaced it with a validate() function. This is
a more elegant interface and works better with the new module caching scheme.
* Use a Status object for the return value of Engine::validate() instead of an
array. Use the formatting facilities of the Status class.
Other:
* Removed "too many returns" error, doesn't fit in with Lua conventions.
* Use the standalone engine by default, so that the extension will work without
configuration for more people.
* Added an accessor for $engine->interpreter
* Fix mw.clone() to correctly clone metatables
* If the standalone interpreter exits due to an error, there are some contexts
where the initial error will be caught and ignored, and the user will see the
error from checkValid() instead. In this case, rethrow the original error for
a more informative message.
* Load mw.lua into the initial standalone environment, to reduce code
duplication between mw.lua and MWServer.lua.
* Fixed a bug in Scribunto_LuaStandaloneInterpreter::handleCall() for functions
that return no results.
* Fixed a bug in encodeLuaVar() for strings with "\r". Added test case.
* In MWServer.lua, don't call error() for internal errors, instead just print
the error and exit. This avoids a protocol violation when an error is
encountered from within handleCall().
* Added lots of documentation. Lua doc comments are in LuaDoc format.
Change-Id: Ie2fd572c362bedf02f45d3fa5352a5280e034740
2012-04-18 03:46:18 +00:00
|
|
|
return array( $init );
|
2012-04-13 10:38:12 +00:00
|
|
|
}
|
Added more Lua environment features
Package library:
* Added a simulation of the Lua 5.1 package library.
* Removed mw.import(), replaced it with a package loader. Packages can be
retrieved from the wiki, using require('Module:Foo'), or from files
distributed with Scribunto, using require('foo'). The "Module:" prefix allows
for source compatibility with existing Lua code.
* Added a couple of libraries from LuaForge: luabit and stringtools.
* Made fetchModuleFromParser() return null on error instead of throwing an
exception, to more easily support the desired behaviour of the package loader,
which needs to return null on error.
* Renamed mw.setupEnvironment() to mw.setup() since it is setting up things
other than the environment now.
* In MWServer:handleRegisterLibrary(), remove the feature which interprets dots
in library names, since LuaSandbox doesn't support this.
Improved module isolation and related refactoring:
* Expose restricted versions of getfenv() and setfenv() to user Lua code.
Requires luasandbox r114952.
* Don't cache the export list returned by module execution for later function
calls. This breaks isolation of #invoke calls, since the local variables are
persistent.
* Removed ScribuntoFunctionBase and its children, since it doesn't really have
a purpose if it can't cache anything. Instead, invoke functions using a module
method called invoke().
* Removed Module::initialize(), replaced it with a validate() function. This is
a more elegant interface and works better with the new module caching scheme.
* Use a Status object for the return value of Engine::validate() instead of an
array. Use the formatting facilities of the Status class.
Other:
* Removed "too many returns" error, doesn't fit in with Lua conventions.
* Use the standalone engine by default, so that the extension will work without
configuration for more people.
* Added an accessor for $engine->interpreter
* Fix mw.clone() to correctly clone metatables
* If the standalone interpreter exits due to an error, there are some contexts
where the initial error will be caught and ignored, and the user will see the
error from checkValid() instead. In this case, rethrow the original error for
a more informative message.
* Load mw.lua into the initial standalone environment, to reduce code
duplication between mw.lua and MWServer.lua.
* Fixed a bug in Scribunto_LuaStandaloneInterpreter::handleCall() for functions
that return no results.
* Fixed a bug in encodeLuaVar() for strings with "\r". Added test case.
* In MWServer.lua, don't call error() for internal errors, instead just print
the error and exit. This avoids a protocol violation when an error is
encountered from within handleCall().
* Added lots of documentation. Lua doc comments are in LuaDoc format.
Change-Id: Ie2fd572c362bedf02f45d3fa5352a5280e034740
2012-04-18 03:46:18 +00:00
|
|
|
|
|
|
|
$title = Title::newFromText( $name );
|
|
|
|
if ( !$title || $title->getNamespace() != NS_MODULE ) {
|
|
|
|
return array();
|
|
|
|
}
|
|
|
|
|
2012-04-13 10:38:12 +00:00
|
|
|
$module = $this->fetchModuleFromParser( $title );
|
Added more Lua environment features
Package library:
* Added a simulation of the Lua 5.1 package library.
* Removed mw.import(), replaced it with a package loader. Packages can be
retrieved from the wiki, using require('Module:Foo'), or from files
distributed with Scribunto, using require('foo'). The "Module:" prefix allows
for source compatibility with existing Lua code.
* Added a couple of libraries from LuaForge: luabit and stringtools.
* Made fetchModuleFromParser() return null on error instead of throwing an
exception, to more easily support the desired behaviour of the package loader,
which needs to return null on error.
* Renamed mw.setupEnvironment() to mw.setup() since it is setting up things
other than the environment now.
* In MWServer:handleRegisterLibrary(), remove the feature which interprets dots
in library names, since LuaSandbox doesn't support this.
Improved module isolation and related refactoring:
* Expose restricted versions of getfenv() and setfenv() to user Lua code.
Requires luasandbox r114952.
* Don't cache the export list returned by module execution for later function
calls. This breaks isolation of #invoke calls, since the local variables are
persistent.
* Removed ScribuntoFunctionBase and its children, since it doesn't really have
a purpose if it can't cache anything. Instead, invoke functions using a module
method called invoke().
* Removed Module::initialize(), replaced it with a validate() function. This is
a more elegant interface and works better with the new module caching scheme.
* Use a Status object for the return value of Engine::validate() instead of an
array. Use the formatting facilities of the Status class.
Other:
* Removed "too many returns" error, doesn't fit in with Lua conventions.
* Use the standalone engine by default, so that the extension will work without
configuration for more people.
* Added an accessor for $engine->interpreter
* Fix mw.clone() to correctly clone metatables
* If the standalone interpreter exits due to an error, there are some contexts
where the initial error will be caught and ignored, and the user will see the
error from checkValid() instead. In this case, rethrow the original error for
a more informative message.
* Load mw.lua into the initial standalone environment, to reduce code
duplication between mw.lua and MWServer.lua.
* Fixed a bug in Scribunto_LuaStandaloneInterpreter::handleCall() for functions
that return no results.
* Fixed a bug in encodeLuaVar() for strings with "\r". Added test case.
* In MWServer.lua, don't call error() for internal errors, instead just print
the error and exit. This avoids a protocol violation when an error is
encountered from within handleCall().
* Added lots of documentation. Lua doc comments are in LuaDoc format.
Change-Id: Ie2fd572c362bedf02f45d3fa5352a5280e034740
2012-04-18 03:46:18 +00:00
|
|
|
if ( $module ) {
|
|
|
|
return array( $module->getInitChunk() );
|
|
|
|
} else {
|
|
|
|
return array();
|
|
|
|
}
|
2012-04-13 10:38:12 +00:00
|
|
|
}
|
2012-05-22 03:56:07 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Helper function for the implementation of frame methods
|
2014-06-18 17:17:04 +00:00
|
|
|
*
|
|
|
|
* @param $frameId
|
|
|
|
* @return PPFrame
|
|
|
|
*
|
|
|
|
* @throws Scribunto_LuaError
|
2012-05-22 03:56:07 +00:00
|
|
|
*/
|
|
|
|
protected function getFrameById( $frameId ) {
|
2014-07-07 16:30:44 +00:00
|
|
|
if ( $frameId === 'empty' ) {
|
|
|
|
return $this->getParser()->getPreprocessor()->newFrame();
|
|
|
|
} elseif ( isset( $this->currentFrames[$frameId] ) ) {
|
2013-02-19 00:49:08 +00:00
|
|
|
return $this->currentFrames[$frameId];
|
2012-05-22 03:56:07 +00:00
|
|
|
} else {
|
|
|
|
throw new Scribunto_LuaError( 'invalid frame ID' );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2013-02-19 00:49:08 +00:00
|
|
|
* Handler for frameExists()
|
2014-06-18 17:17:04 +00:00
|
|
|
* @return array
|
2013-02-19 00:49:08 +00:00
|
|
|
*/
|
|
|
|
function frameExists( $frameId ) {
|
2014-07-07 16:30:44 +00:00
|
|
|
return array( $frameId === 'empty' || isset( $this->currentFrames[$frameId] ) );
|
2013-02-19 00:49:08 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Handler for newChildFrame()
|
2014-06-18 17:17:04 +00:00
|
|
|
*
|
|
|
|
* @throws Scribunto_LuaError
|
2012-05-22 03:56:07 +00:00
|
|
|
*/
|
2013-02-19 00:49:08 +00:00
|
|
|
function newChildFrame( $frameId, $title, $args ) {
|
|
|
|
if ( count( $this->currentFrames ) > 100 ) {
|
|
|
|
throw new Scribunto_LuaError( 'newChild: too many frames' );
|
|
|
|
}
|
|
|
|
|
|
|
|
$frame = $this->getFrameById( $frameId );
|
|
|
|
if ( $title === false ) {
|
|
|
|
$title = $frame->getTitle();
|
|
|
|
} else {
|
|
|
|
$title = Title::newFromText( $title );
|
|
|
|
if ( !$title ) {
|
|
|
|
throw new Scribunto_LuaError( 'newChild: invalid title' );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
$args = $this->getParser()->getPreprocessor()->newPartNodeArray( $args );
|
|
|
|
$newFrame = $frame->newChild( $args, $title );
|
|
|
|
$newFrameId = 'frame' . count( $this->currentFrames );
|
|
|
|
$this->currentFrames[$newFrameId] = $newFrame;
|
|
|
|
return array( $newFrameId );
|
2012-05-22 03:56:07 +00:00
|
|
|
}
|
|
|
|
|
2013-12-06 18:10:39 +00:00
|
|
|
/**
|
|
|
|
* Handler for getTitle()
|
2014-06-18 17:17:04 +00:00
|
|
|
*
|
|
|
|
* @param $frameId
|
|
|
|
*
|
|
|
|
* @return array
|
2013-12-06 18:10:39 +00:00
|
|
|
*/
|
|
|
|
function getFrameTitle( $frameId ) {
|
|
|
|
$frame = $this->getFrameById( $frameId );
|
|
|
|
return array( $frame->getTitle()->getPrefixedText() );
|
|
|
|
}
|
|
|
|
|
2014-06-01 03:15:42 +00:00
|
|
|
/**
|
|
|
|
* Handler for setTTL()
|
|
|
|
*/
|
|
|
|
function setTTL( $ttl ) {
|
|
|
|
$args = func_get_args();
|
|
|
|
$this->checkNumber( 'setTTL', $args, 0 );
|
|
|
|
|
|
|
|
$frame = $this->getFrameById( 'current' );
|
|
|
|
if ( is_callable( array( $frame, 'setTTL' ) ) ) {
|
|
|
|
$frame->setTTL( $ttl );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-05-22 03:56:07 +00:00
|
|
|
/**
|
2013-01-25 17:53:18 +00:00
|
|
|
* Handler for getExpandedArgument()
|
2012-05-22 03:56:07 +00:00
|
|
|
*/
|
|
|
|
function getExpandedArgument( $frameId, $name ) {
|
|
|
|
$args = func_get_args();
|
|
|
|
$this->checkString( 'getExpandedArgument', $args, 0 );
|
|
|
|
|
|
|
|
$frame = $this->getFrameById( $frameId );
|
2013-03-06 23:28:24 +00:00
|
|
|
$this->getInterpreter()->pauseUsageTimer();
|
2012-05-22 03:56:07 +00:00
|
|
|
$result = $frame->getArgument( $name );
|
|
|
|
if ( $result === false ) {
|
|
|
|
return array();
|
|
|
|
} else {
|
|
|
|
return array( $result );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2013-01-25 17:53:18 +00:00
|
|
|
* Handler for getAllExpandedArguments()
|
2012-05-22 03:56:07 +00:00
|
|
|
*/
|
|
|
|
function getAllExpandedArguments( $frameId ) {
|
|
|
|
$frame = $this->getFrameById( $frameId );
|
2013-03-06 23:28:24 +00:00
|
|
|
$this->getInterpreter()->pauseUsageTimer();
|
2012-05-22 03:56:07 +00:00
|
|
|
return array( $frame->getArguments() );
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2013-01-25 17:53:18 +00:00
|
|
|
* Handler for expandTemplate()
|
2012-05-22 03:56:07 +00:00
|
|
|
*/
|
|
|
|
function expandTemplate( $frameId, $titleText, $args ) {
|
|
|
|
$frame = $this->getFrameById( $frameId );
|
|
|
|
$title = Title::newFromText( $titleText, NS_TEMPLATE );
|
|
|
|
if ( !$title ) {
|
2014-03-11 17:01:25 +00:00
|
|
|
throw new Scribunto_LuaError( "expandTemplate: invalid title \"$titleText\"" );
|
2012-05-22 03:56:07 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if ( $frame->depth >= $this->parser->mOptions->getMaxTemplateDepth() ) {
|
|
|
|
throw new Scribunto_LuaError( 'expandTemplate: template depth limit exceeded' );
|
|
|
|
}
|
|
|
|
if ( MWNamespace::isNonincludable( $title->getNamespace() ) ) {
|
|
|
|
throw new Scribunto_LuaError( 'expandTemplate: template inclusion denied' );
|
|
|
|
}
|
|
|
|
|
|
|
|
list( $dom, $finalTitle ) = $this->parser->getTemplateDom( $title );
|
|
|
|
if ( $dom === false ) {
|
2012-07-09 03:23:31 +00:00
|
|
|
throw new Scribunto_LuaError( "expandTemplate: template \"$titleText\" does not exist" );
|
2012-05-22 03:56:07 +00:00
|
|
|
}
|
|
|
|
if ( !$frame->loopCheck( $finalTitle ) ) {
|
|
|
|
throw new Scribunto_LuaError( 'expandTemplate: template loop detected' );
|
|
|
|
}
|
|
|
|
|
2013-10-10 15:18:13 +00:00
|
|
|
$fargs = $this->getParser()->getPreprocessor()->newPartNodeArray( $args );
|
|
|
|
$newFrame = $frame->newChild( $fargs, $finalTitle );
|
2014-07-07 18:46:59 +00:00
|
|
|
$text = $this->doCachedExpansion( $newFrame, $dom,
|
2012-05-22 03:56:07 +00:00
|
|
|
array(
|
|
|
|
'template' => $finalTitle->getPrefixedDBkey(),
|
|
|
|
'args' => $args
|
|
|
|
) );
|
|
|
|
return array( $text );
|
|
|
|
}
|
|
|
|
|
2013-03-04 05:42:17 +00:00
|
|
|
/**
|
|
|
|
* Handler for callParserFunction()
|
2014-06-18 17:17:04 +00:00
|
|
|
* @param $frameId
|
|
|
|
* @param $function
|
|
|
|
* @param $args
|
|
|
|
* @throws MWException
|
|
|
|
* @throws Scribunto_LuaError
|
|
|
|
* @return array
|
2013-03-04 05:42:17 +00:00
|
|
|
*/
|
|
|
|
function callParserFunction( $frameId, $function, $args ) {
|
|
|
|
$frame = $this->getFrameById( $frameId );
|
|
|
|
|
|
|
|
# Make zero-based, without screwing up named args
|
|
|
|
$args = array_merge( array(), $args );
|
|
|
|
|
|
|
|
# Sort, since we can't rely on the order coming in from Lua
|
|
|
|
uksort( $args, function ( $a, $b ) {
|
|
|
|
if ( is_int( $a ) !== is_int( $b ) ) {
|
|
|
|
return is_int( $a ) ? -1 : 1;
|
|
|
|
}
|
|
|
|
if ( is_int( $a ) ) {
|
|
|
|
return $a - $b;
|
|
|
|
}
|
|
|
|
return strcmp( $a, $b );
|
|
|
|
} );
|
|
|
|
|
|
|
|
# Be user-friendly
|
|
|
|
$colonPos = strpos( $function, ':' );
|
|
|
|
if ( $colonPos !== false ) {
|
|
|
|
array_unshift( $args, trim( substr( $function, $colonPos + 1 ) ) );
|
|
|
|
$function = substr( $function, 0, $colonPos );
|
|
|
|
}
|
2014-04-07 16:23:16 +00:00
|
|
|
if ( !isset( $args[0] ) ) {
|
|
|
|
# It's impossible to call a parser function from wikitext without
|
|
|
|
# supplying an arg 0. Insist that one be provided via Lua, too.
|
|
|
|
throw new Scribunto_LuaError( 'callParserFunction: At least one unnamed parameter ' .
|
|
|
|
'(the parameter that comes after the colon in wikitext) ' .
|
|
|
|
'must be provided'
|
|
|
|
);
|
|
|
|
}
|
2013-03-04 05:42:17 +00:00
|
|
|
|
|
|
|
$result = $this->parser->callParserFunction( $frame, $function, $args );
|
|
|
|
if ( !$result['found'] ) {
|
|
|
|
throw new Scribunto_LuaError( "callParserFunction: function \"$function\" was not found" );
|
|
|
|
}
|
|
|
|
|
|
|
|
# Set defaults for various flags
|
|
|
|
$result += array(
|
|
|
|
'nowiki' => false,
|
|
|
|
'isChildObj' => false,
|
|
|
|
'isLocalObj' => false,
|
|
|
|
'isHTML' => false,
|
|
|
|
'title' => false,
|
|
|
|
);
|
|
|
|
|
|
|
|
$text = $result['text'];
|
|
|
|
if ( $result['isChildObj'] ) {
|
2013-07-07 11:39:52 +00:00
|
|
|
$fargs = $this->getParser()->getPreprocessor()->newPartNodeArray( $args );
|
|
|
|
$newFrame = $frame->newChild( $fargs, $result['title'] );
|
2013-03-04 05:42:17 +00:00
|
|
|
if ( $result['nowiki'] ) {
|
|
|
|
$text = $newFrame->expand( $text, PPFrame::RECOVER_ORIG );
|
|
|
|
} else {
|
|
|
|
$text = $newFrame->expand( $text );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if ( $result['isLocalObj'] && $result['nowiki'] ) {
|
|
|
|
$text = $frame->expand( $text, PPFrame::RECOVER_ORIG );
|
|
|
|
$result['isLocalObj'] = false;
|
|
|
|
}
|
|
|
|
|
|
|
|
# Replace raw HTML by a placeholder
|
|
|
|
if ( $result['isHTML'] ) {
|
|
|
|
$text = $this->parser->insertStripItem( $text );
|
|
|
|
} elseif ( $result['nowiki'] ) {
|
|
|
|
# Escape nowiki-style return values
|
|
|
|
$text = wfEscapeWikiText( $text );
|
|
|
|
}
|
|
|
|
|
|
|
|
if ( $result['isLocalObj'] ) {
|
|
|
|
$text = $frame->expand( $text );
|
|
|
|
}
|
|
|
|
|
|
|
|
return array( "$text" );
|
|
|
|
}
|
|
|
|
|
2012-05-22 03:56:07 +00:00
|
|
|
/**
|
2013-01-25 17:53:18 +00:00
|
|
|
* Handler for preprocess()
|
2012-05-22 03:56:07 +00:00
|
|
|
*/
|
|
|
|
function preprocess( $frameId, $text ) {
|
|
|
|
$args = func_get_args();
|
|
|
|
$this->checkString( 'preprocess', $args, 0 );
|
|
|
|
|
|
|
|
$frame = $this->getFrameById( $frameId );
|
|
|
|
|
|
|
|
if ( !$frame ) {
|
|
|
|
throw new Scribunto_LuaError( 'attempt to call mw.preprocess with no frame' );
|
|
|
|
}
|
2013-03-06 23:28:24 +00:00
|
|
|
|
|
|
|
// Don't count the time for expanding all the frame arguments against
|
|
|
|
// the Lua time limit.
|
|
|
|
$this->getInterpreter()->pauseUsageTimer();
|
|
|
|
$args = $frame->getArguments();
|
|
|
|
$this->getInterpreter()->unpauseUsageTimer();
|
|
|
|
|
2012-08-27 01:11:32 +00:00
|
|
|
$text = $this->doCachedExpansion( $frame, $text,
|
2012-05-22 03:56:07 +00:00
|
|
|
array(
|
|
|
|
'inputText' => $text,
|
2013-03-06 23:28:24 +00:00
|
|
|
'args' => $args,
|
2012-05-22 03:56:07 +00:00
|
|
|
) );
|
|
|
|
return array( $text );
|
|
|
|
}
|
|
|
|
|
2013-02-01 20:43:32 +00:00
|
|
|
/**
|
|
|
|
* Increment the expensive function count, and throw if limit exceeded
|
|
|
|
*
|
2014-06-18 17:17:04 +00:00
|
|
|
* @throws Scribunto_LuaError
|
2013-02-01 20:43:32 +00:00
|
|
|
* @return null
|
|
|
|
*/
|
|
|
|
public function incrementExpensiveFunctionCount() {
|
|
|
|
if ( !$this->getParser()->incrementExpensiveFunctionCount() ) {
|
|
|
|
throw new Scribunto_LuaError( "too many expensive function calls" );
|
|
|
|
}
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
|
2013-11-01 02:05:00 +00:00
|
|
|
/**
|
|
|
|
* Return whether the parser is currently substing
|
|
|
|
*
|
|
|
|
* @return array
|
|
|
|
*/
|
|
|
|
public function isSubsting() {
|
|
|
|
// See Parser::braceSubstitution, OT_WIKI is the switch
|
|
|
|
return array( $this->getParser()->OutputType() === Parser::OT_WIKI );
|
|
|
|
}
|
|
|
|
|
2012-08-27 01:11:32 +00:00
|
|
|
function doCachedExpansion( $frame, $input, $cacheKey ) {
|
2012-05-22 03:56:07 +00:00
|
|
|
$hash = md5( serialize( $cacheKey ) );
|
2013-12-06 23:25:58 +00:00
|
|
|
if ( isset( $this->expandCache[$hash] ) ) {
|
|
|
|
return $this->expandCache[$hash];
|
|
|
|
}
|
|
|
|
|
|
|
|
if ( is_scalar( $input ) ) {
|
|
|
|
$dom = $this->parser->getPreprocessor()->preprocessToObj(
|
|
|
|
$input, Parser::PTD_FOR_INCLUSION );
|
|
|
|
} else {
|
|
|
|
$dom = $input;
|
|
|
|
}
|
|
|
|
$ret = $frame->expand( $dom );
|
|
|
|
if ( !is_callable( array( $frame, 'isVolatile' ) ) || !$frame->isVolatile() ) {
|
2012-05-22 03:56:07 +00:00
|
|
|
if ( count( $this->expandCache ) > self::MAX_EXPAND_CACHE_SIZE ) {
|
|
|
|
reset( $this->expandCache );
|
|
|
|
$oldHash = key( $this->expandCache );
|
|
|
|
unset( $this->expandCache[$oldHash] );
|
|
|
|
}
|
2013-12-06 23:25:58 +00:00
|
|
|
$this->expandCache[$hash] = $ret;
|
2012-05-22 03:56:07 +00:00
|
|
|
}
|
2013-12-06 23:25:58 +00:00
|
|
|
return $ret;
|
2012-05-22 03:56:07 +00:00
|
|
|
}
|
2012-04-13 10:38:12 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
class Scribunto_LuaModule extends ScribuntoModuleBase {
|
Added more Lua environment features
Package library:
* Added a simulation of the Lua 5.1 package library.
* Removed mw.import(), replaced it with a package loader. Packages can be
retrieved from the wiki, using require('Module:Foo'), or from files
distributed with Scribunto, using require('foo'). The "Module:" prefix allows
for source compatibility with existing Lua code.
* Added a couple of libraries from LuaForge: luabit and stringtools.
* Made fetchModuleFromParser() return null on error instead of throwing an
exception, to more easily support the desired behaviour of the package loader,
which needs to return null on error.
* Renamed mw.setupEnvironment() to mw.setup() since it is setting up things
other than the environment now.
* In MWServer:handleRegisterLibrary(), remove the feature which interprets dots
in library names, since LuaSandbox doesn't support this.
Improved module isolation and related refactoring:
* Expose restricted versions of getfenv() and setfenv() to user Lua code.
Requires luasandbox r114952.
* Don't cache the export list returned by module execution for later function
calls. This breaks isolation of #invoke calls, since the local variables are
persistent.
* Removed ScribuntoFunctionBase and its children, since it doesn't really have
a purpose if it can't cache anything. Instead, invoke functions using a module
method called invoke().
* Removed Module::initialize(), replaced it with a validate() function. This is
a more elegant interface and works better with the new module caching scheme.
* Use a Status object for the return value of Engine::validate() instead of an
array. Use the formatting facilities of the Status class.
Other:
* Removed "too many returns" error, doesn't fit in with Lua conventions.
* Use the standalone engine by default, so that the extension will work without
configuration for more people.
* Added an accessor for $engine->interpreter
* Fix mw.clone() to correctly clone metatables
* If the standalone interpreter exits due to an error, there are some contexts
where the initial error will be caught and ignored, and the user will see the
error from checkValid() instead. In this case, rethrow the original error for
a more informative message.
* Load mw.lua into the initial standalone environment, to reduce code
duplication between mw.lua and MWServer.lua.
* Fixed a bug in Scribunto_LuaStandaloneInterpreter::handleCall() for functions
that return no results.
* Fixed a bug in encodeLuaVar() for strings with "\r". Added test case.
* In MWServer.lua, don't call error() for internal errors, instead just print
the error and exit. This avoids a protocol violation when an error is
encountered from within handleCall().
* Added lots of documentation. Lua doc comments are in LuaDoc format.
Change-Id: Ie2fd572c362bedf02f45d3fa5352a5280e034740
2012-04-18 03:46:18 +00:00
|
|
|
protected $initChunk;
|
2012-04-13 10:38:12 +00:00
|
|
|
|
Added more Lua environment features
Package library:
* Added a simulation of the Lua 5.1 package library.
* Removed mw.import(), replaced it with a package loader. Packages can be
retrieved from the wiki, using require('Module:Foo'), or from files
distributed with Scribunto, using require('foo'). The "Module:" prefix allows
for source compatibility with existing Lua code.
* Added a couple of libraries from LuaForge: luabit and stringtools.
* Made fetchModuleFromParser() return null on error instead of throwing an
exception, to more easily support the desired behaviour of the package loader,
which needs to return null on error.
* Renamed mw.setupEnvironment() to mw.setup() since it is setting up things
other than the environment now.
* In MWServer:handleRegisterLibrary(), remove the feature which interprets dots
in library names, since LuaSandbox doesn't support this.
Improved module isolation and related refactoring:
* Expose restricted versions of getfenv() and setfenv() to user Lua code.
Requires luasandbox r114952.
* Don't cache the export list returned by module execution for later function
calls. This breaks isolation of #invoke calls, since the local variables are
persistent.
* Removed ScribuntoFunctionBase and its children, since it doesn't really have
a purpose if it can't cache anything. Instead, invoke functions using a module
method called invoke().
* Removed Module::initialize(), replaced it with a validate() function. This is
a more elegant interface and works better with the new module caching scheme.
* Use a Status object for the return value of Engine::validate() instead of an
array. Use the formatting facilities of the Status class.
Other:
* Removed "too many returns" error, doesn't fit in with Lua conventions.
* Use the standalone engine by default, so that the extension will work without
configuration for more people.
* Added an accessor for $engine->interpreter
* Fix mw.clone() to correctly clone metatables
* If the standalone interpreter exits due to an error, there are some contexts
where the initial error will be caught and ignored, and the user will see the
error from checkValid() instead. In this case, rethrow the original error for
a more informative message.
* Load mw.lua into the initial standalone environment, to reduce code
duplication between mw.lua and MWServer.lua.
* Fixed a bug in Scribunto_LuaStandaloneInterpreter::handleCall() for functions
that return no results.
* Fixed a bug in encodeLuaVar() for strings with "\r". Added test case.
* In MWServer.lua, don't call error() for internal errors, instead just print
the error and exit. This avoids a protocol violation when an error is
encountered from within handleCall().
* Added lots of documentation. Lua doc comments are in LuaDoc format.
Change-Id: Ie2fd572c362bedf02f45d3fa5352a5280e034740
2012-04-18 03:46:18 +00:00
|
|
|
public function validate() {
|
|
|
|
try {
|
2012-04-23 11:36:13 +00:00
|
|
|
$this->getInitChunk();
|
Added more Lua environment features
Package library:
* Added a simulation of the Lua 5.1 package library.
* Removed mw.import(), replaced it with a package loader. Packages can be
retrieved from the wiki, using require('Module:Foo'), or from files
distributed with Scribunto, using require('foo'). The "Module:" prefix allows
for source compatibility with existing Lua code.
* Added a couple of libraries from LuaForge: luabit and stringtools.
* Made fetchModuleFromParser() return null on error instead of throwing an
exception, to more easily support the desired behaviour of the package loader,
which needs to return null on error.
* Renamed mw.setupEnvironment() to mw.setup() since it is setting up things
other than the environment now.
* In MWServer:handleRegisterLibrary(), remove the feature which interprets dots
in library names, since LuaSandbox doesn't support this.
Improved module isolation and related refactoring:
* Expose restricted versions of getfenv() and setfenv() to user Lua code.
Requires luasandbox r114952.
* Don't cache the export list returned by module execution for later function
calls. This breaks isolation of #invoke calls, since the local variables are
persistent.
* Removed ScribuntoFunctionBase and its children, since it doesn't really have
a purpose if it can't cache anything. Instead, invoke functions using a module
method called invoke().
* Removed Module::initialize(), replaced it with a validate() function. This is
a more elegant interface and works better with the new module caching scheme.
* Use a Status object for the return value of Engine::validate() instead of an
array. Use the formatting facilities of the Status class.
Other:
* Removed "too many returns" error, doesn't fit in with Lua conventions.
* Use the standalone engine by default, so that the extension will work without
configuration for more people.
* Added an accessor for $engine->interpreter
* Fix mw.clone() to correctly clone metatables
* If the standalone interpreter exits due to an error, there are some contexts
where the initial error will be caught and ignored, and the user will see the
error from checkValid() instead. In this case, rethrow the original error for
a more informative message.
* Load mw.lua into the initial standalone environment, to reduce code
duplication between mw.lua and MWServer.lua.
* Fixed a bug in Scribunto_LuaStandaloneInterpreter::handleCall() for functions
that return no results.
* Fixed a bug in encodeLuaVar() for strings with "\r". Added test case.
* In MWServer.lua, don't call error() for internal errors, instead just print
the error and exit. This avoids a protocol violation when an error is
encountered from within handleCall().
* Added lots of documentation. Lua doc comments are in LuaDoc format.
Change-Id: Ie2fd572c362bedf02f45d3fa5352a5280e034740
2012-04-18 03:46:18 +00:00
|
|
|
} catch ( ScribuntoException $e ) {
|
|
|
|
return $e->toStatus();
|
2012-04-13 10:38:12 +00:00
|
|
|
}
|
Added more Lua environment features
Package library:
* Added a simulation of the Lua 5.1 package library.
* Removed mw.import(), replaced it with a package loader. Packages can be
retrieved from the wiki, using require('Module:Foo'), or from files
distributed with Scribunto, using require('foo'). The "Module:" prefix allows
for source compatibility with existing Lua code.
* Added a couple of libraries from LuaForge: luabit and stringtools.
* Made fetchModuleFromParser() return null on error instead of throwing an
exception, to more easily support the desired behaviour of the package loader,
which needs to return null on error.
* Renamed mw.setupEnvironment() to mw.setup() since it is setting up things
other than the environment now.
* In MWServer:handleRegisterLibrary(), remove the feature which interprets dots
in library names, since LuaSandbox doesn't support this.
Improved module isolation and related refactoring:
* Expose restricted versions of getfenv() and setfenv() to user Lua code.
Requires luasandbox r114952.
* Don't cache the export list returned by module execution for later function
calls. This breaks isolation of #invoke calls, since the local variables are
persistent.
* Removed ScribuntoFunctionBase and its children, since it doesn't really have
a purpose if it can't cache anything. Instead, invoke functions using a module
method called invoke().
* Removed Module::initialize(), replaced it with a validate() function. This is
a more elegant interface and works better with the new module caching scheme.
* Use a Status object for the return value of Engine::validate() instead of an
array. Use the formatting facilities of the Status class.
Other:
* Removed "too many returns" error, doesn't fit in with Lua conventions.
* Use the standalone engine by default, so that the extension will work without
configuration for more people.
* Added an accessor for $engine->interpreter
* Fix mw.clone() to correctly clone metatables
* If the standalone interpreter exits due to an error, there are some contexts
where the initial error will be caught and ignored, and the user will see the
error from checkValid() instead. In this case, rethrow the original error for
a more informative message.
* Load mw.lua into the initial standalone environment, to reduce code
duplication between mw.lua and MWServer.lua.
* Fixed a bug in Scribunto_LuaStandaloneInterpreter::handleCall() for functions
that return no results.
* Fixed a bug in encodeLuaVar() for strings with "\r". Added test case.
* In MWServer.lua, don't call error() for internal errors, instead just print
the error and exit. This avoids a protocol violation when an error is
encountered from within handleCall().
* Added lots of documentation. Lua doc comments are in LuaDoc format.
Change-Id: Ie2fd572c362bedf02f45d3fa5352a5280e034740
2012-04-18 03:46:18 +00:00
|
|
|
return Status::newGood();
|
2012-04-13 10:38:12 +00:00
|
|
|
}
|
|
|
|
|
Added more Lua environment features
Package library:
* Added a simulation of the Lua 5.1 package library.
* Removed mw.import(), replaced it with a package loader. Packages can be
retrieved from the wiki, using require('Module:Foo'), or from files
distributed with Scribunto, using require('foo'). The "Module:" prefix allows
for source compatibility with existing Lua code.
* Added a couple of libraries from LuaForge: luabit and stringtools.
* Made fetchModuleFromParser() return null on error instead of throwing an
exception, to more easily support the desired behaviour of the package loader,
which needs to return null on error.
* Renamed mw.setupEnvironment() to mw.setup() since it is setting up things
other than the environment now.
* In MWServer:handleRegisterLibrary(), remove the feature which interprets dots
in library names, since LuaSandbox doesn't support this.
Improved module isolation and related refactoring:
* Expose restricted versions of getfenv() and setfenv() to user Lua code.
Requires luasandbox r114952.
* Don't cache the export list returned by module execution for later function
calls. This breaks isolation of #invoke calls, since the local variables are
persistent.
* Removed ScribuntoFunctionBase and its children, since it doesn't really have
a purpose if it can't cache anything. Instead, invoke functions using a module
method called invoke().
* Removed Module::initialize(), replaced it with a validate() function. This is
a more elegant interface and works better with the new module caching scheme.
* Use a Status object for the return value of Engine::validate() instead of an
array. Use the formatting facilities of the Status class.
Other:
* Removed "too many returns" error, doesn't fit in with Lua conventions.
* Use the standalone engine by default, so that the extension will work without
configuration for more people.
* Added an accessor for $engine->interpreter
* Fix mw.clone() to correctly clone metatables
* If the standalone interpreter exits due to an error, there are some contexts
where the initial error will be caught and ignored, and the user will see the
error from checkValid() instead. In this case, rethrow the original error for
a more informative message.
* Load mw.lua into the initial standalone environment, to reduce code
duplication between mw.lua and MWServer.lua.
* Fixed a bug in Scribunto_LuaStandaloneInterpreter::handleCall() for functions
that return no results.
* Fixed a bug in encodeLuaVar() for strings with "\r". Added test case.
* In MWServer.lua, don't call error() for internal errors, instead just print
the error and exit. This avoids a protocol violation when an error is
encountered from within handleCall().
* Added lots of documentation. Lua doc comments are in LuaDoc format.
Change-Id: Ie2fd572c362bedf02f45d3fa5352a5280e034740
2012-04-18 03:46:18 +00:00
|
|
|
/**
|
|
|
|
* Get the chunk which, when called, will return the export table.
|
|
|
|
*/
|
|
|
|
public function getInitChunk() {
|
|
|
|
if ( !$this->initChunk ) {
|
|
|
|
$this->initChunk = $this->engine->getInterpreter()->loadString(
|
2014-07-07 18:46:59 +00:00
|
|
|
$this->code,
|
2012-04-19 07:40:56 +00:00
|
|
|
// Prepending an "=" to the chunk name avoids truncation or a "[string" prefix
|
|
|
|
'=' . $this->chunkName );
|
Added more Lua environment features
Package library:
* Added a simulation of the Lua 5.1 package library.
* Removed mw.import(), replaced it with a package loader. Packages can be
retrieved from the wiki, using require('Module:Foo'), or from files
distributed with Scribunto, using require('foo'). The "Module:" prefix allows
for source compatibility with existing Lua code.
* Added a couple of libraries from LuaForge: luabit and stringtools.
* Made fetchModuleFromParser() return null on error instead of throwing an
exception, to more easily support the desired behaviour of the package loader,
which needs to return null on error.
* Renamed mw.setupEnvironment() to mw.setup() since it is setting up things
other than the environment now.
* In MWServer:handleRegisterLibrary(), remove the feature which interprets dots
in library names, since LuaSandbox doesn't support this.
Improved module isolation and related refactoring:
* Expose restricted versions of getfenv() and setfenv() to user Lua code.
Requires luasandbox r114952.
* Don't cache the export list returned by module execution for later function
calls. This breaks isolation of #invoke calls, since the local variables are
persistent.
* Removed ScribuntoFunctionBase and its children, since it doesn't really have
a purpose if it can't cache anything. Instead, invoke functions using a module
method called invoke().
* Removed Module::initialize(), replaced it with a validate() function. This is
a more elegant interface and works better with the new module caching scheme.
* Use a Status object for the return value of Engine::validate() instead of an
array. Use the formatting facilities of the Status class.
Other:
* Removed "too many returns" error, doesn't fit in with Lua conventions.
* Use the standalone engine by default, so that the extension will work without
configuration for more people.
* Added an accessor for $engine->interpreter
* Fix mw.clone() to correctly clone metatables
* If the standalone interpreter exits due to an error, there are some contexts
where the initial error will be caught and ignored, and the user will see the
error from checkValid() instead. In this case, rethrow the original error for
a more informative message.
* Load mw.lua into the initial standalone environment, to reduce code
duplication between mw.lua and MWServer.lua.
* Fixed a bug in Scribunto_LuaStandaloneInterpreter::handleCall() for functions
that return no results.
* Fixed a bug in encodeLuaVar() for strings with "\r". Added test case.
* In MWServer.lua, don't call error() for internal errors, instead just print
the error and exit. This avoids a protocol violation when an error is
encountered from within handleCall().
* Added lots of documentation. Lua doc comments are in LuaDoc format.
Change-Id: Ie2fd572c362bedf02f45d3fa5352a5280e034740
2012-04-18 03:46:18 +00:00
|
|
|
}
|
|
|
|
return $this->initChunk;
|
2012-04-13 10:38:12 +00:00
|
|
|
}
|
|
|
|
|
Added more Lua environment features
Package library:
* Added a simulation of the Lua 5.1 package library.
* Removed mw.import(), replaced it with a package loader. Packages can be
retrieved from the wiki, using require('Module:Foo'), or from files
distributed with Scribunto, using require('foo'). The "Module:" prefix allows
for source compatibility with existing Lua code.
* Added a couple of libraries from LuaForge: luabit and stringtools.
* Made fetchModuleFromParser() return null on error instead of throwing an
exception, to more easily support the desired behaviour of the package loader,
which needs to return null on error.
* Renamed mw.setupEnvironment() to mw.setup() since it is setting up things
other than the environment now.
* In MWServer:handleRegisterLibrary(), remove the feature which interprets dots
in library names, since LuaSandbox doesn't support this.
Improved module isolation and related refactoring:
* Expose restricted versions of getfenv() and setfenv() to user Lua code.
Requires luasandbox r114952.
* Don't cache the export list returned by module execution for later function
calls. This breaks isolation of #invoke calls, since the local variables are
persistent.
* Removed ScribuntoFunctionBase and its children, since it doesn't really have
a purpose if it can't cache anything. Instead, invoke functions using a module
method called invoke().
* Removed Module::initialize(), replaced it with a validate() function. This is
a more elegant interface and works better with the new module caching scheme.
* Use a Status object for the return value of Engine::validate() instead of an
array. Use the formatting facilities of the Status class.
Other:
* Removed "too many returns" error, doesn't fit in with Lua conventions.
* Use the standalone engine by default, so that the extension will work without
configuration for more people.
* Added an accessor for $engine->interpreter
* Fix mw.clone() to correctly clone metatables
* If the standalone interpreter exits due to an error, there are some contexts
where the initial error will be caught and ignored, and the user will see the
error from checkValid() instead. In this case, rethrow the original error for
a more informative message.
* Load mw.lua into the initial standalone environment, to reduce code
duplication between mw.lua and MWServer.lua.
* Fixed a bug in Scribunto_LuaStandaloneInterpreter::handleCall() for functions
that return no results.
* Fixed a bug in encodeLuaVar() for strings with "\r". Added test case.
* In MWServer.lua, don't call error() for internal errors, instead just print
the error and exit. This avoids a protocol violation when an error is
encountered from within handleCall().
* Added lots of documentation. Lua doc comments are in LuaDoc format.
Change-Id: Ie2fd572c362bedf02f45d3fa5352a5280e034740
2012-04-18 03:46:18 +00:00
|
|
|
/**
|
2012-05-22 03:56:07 +00:00
|
|
|
* Invoke a function within the module. Return the expanded wikitext result.
|
Added more Lua environment features
Package library:
* Added a simulation of the Lua 5.1 package library.
* Removed mw.import(), replaced it with a package loader. Packages can be
retrieved from the wiki, using require('Module:Foo'), or from files
distributed with Scribunto, using require('foo'). The "Module:" prefix allows
for source compatibility with existing Lua code.
* Added a couple of libraries from LuaForge: luabit and stringtools.
* Made fetchModuleFromParser() return null on error instead of throwing an
exception, to more easily support the desired behaviour of the package loader,
which needs to return null on error.
* Renamed mw.setupEnvironment() to mw.setup() since it is setting up things
other than the environment now.
* In MWServer:handleRegisterLibrary(), remove the feature which interprets dots
in library names, since LuaSandbox doesn't support this.
Improved module isolation and related refactoring:
* Expose restricted versions of getfenv() and setfenv() to user Lua code.
Requires luasandbox r114952.
* Don't cache the export list returned by module execution for later function
calls. This breaks isolation of #invoke calls, since the local variables are
persistent.
* Removed ScribuntoFunctionBase and its children, since it doesn't really have
a purpose if it can't cache anything. Instead, invoke functions using a module
method called invoke().
* Removed Module::initialize(), replaced it with a validate() function. This is
a more elegant interface and works better with the new module caching scheme.
* Use a Status object for the return value of Engine::validate() instead of an
array. Use the formatting facilities of the Status class.
Other:
* Removed "too many returns" error, doesn't fit in with Lua conventions.
* Use the standalone engine by default, so that the extension will work without
configuration for more people.
* Added an accessor for $engine->interpreter
* Fix mw.clone() to correctly clone metatables
* If the standalone interpreter exits due to an error, there are some contexts
where the initial error will be caught and ignored, and the user will see the
error from checkValid() instead. In this case, rethrow the original error for
a more informative message.
* Load mw.lua into the initial standalone environment, to reduce code
duplication between mw.lua and MWServer.lua.
* Fixed a bug in Scribunto_LuaStandaloneInterpreter::handleCall() for functions
that return no results.
* Fixed a bug in encodeLuaVar() for strings with "\r". Added test case.
* In MWServer.lua, don't call error() for internal errors, instead just print
the error and exit. This avoids a protocol violation when an error is
encountered from within handleCall().
* Added lots of documentation. Lua doc comments are in LuaDoc format.
Change-Id: Ie2fd572c362bedf02f45d3fa5352a5280e034740
2012-04-18 03:46:18 +00:00
|
|
|
*/
|
2012-05-22 03:56:07 +00:00
|
|
|
public function invoke( $name, $frame ) {
|
2014-07-07 16:30:44 +00:00
|
|
|
$ret = $this->engine->executeModule( $this->getInitChunk(), $name, $frame );
|
2014-05-23 15:43:22 +00:00
|
|
|
|
|
|
|
if ( !isset( $ret ) ) {
|
2014-04-14 01:24:21 +00:00
|
|
|
throw $this->engine->newException( 'scribunto-common-nosuchfunction', array( 'args' => array( $name ) ) );
|
Added more Lua environment features
Package library:
* Added a simulation of the Lua 5.1 package library.
* Removed mw.import(), replaced it with a package loader. Packages can be
retrieved from the wiki, using require('Module:Foo'), or from files
distributed with Scribunto, using require('foo'). The "Module:" prefix allows
for source compatibility with existing Lua code.
* Added a couple of libraries from LuaForge: luabit and stringtools.
* Made fetchModuleFromParser() return null on error instead of throwing an
exception, to more easily support the desired behaviour of the package loader,
which needs to return null on error.
* Renamed mw.setupEnvironment() to mw.setup() since it is setting up things
other than the environment now.
* In MWServer:handleRegisterLibrary(), remove the feature which interprets dots
in library names, since LuaSandbox doesn't support this.
Improved module isolation and related refactoring:
* Expose restricted versions of getfenv() and setfenv() to user Lua code.
Requires luasandbox r114952.
* Don't cache the export list returned by module execution for later function
calls. This breaks isolation of #invoke calls, since the local variables are
persistent.
* Removed ScribuntoFunctionBase and its children, since it doesn't really have
a purpose if it can't cache anything. Instead, invoke functions using a module
method called invoke().
* Removed Module::initialize(), replaced it with a validate() function. This is
a more elegant interface and works better with the new module caching scheme.
* Use a Status object for the return value of Engine::validate() instead of an
array. Use the formatting facilities of the Status class.
Other:
* Removed "too many returns" error, doesn't fit in with Lua conventions.
* Use the standalone engine by default, so that the extension will work without
configuration for more people.
* Added an accessor for $engine->interpreter
* Fix mw.clone() to correctly clone metatables
* If the standalone interpreter exits due to an error, there are some contexts
where the initial error will be caught and ignored, and the user will see the
error from checkValid() instead. In this case, rethrow the original error for
a more informative message.
* Load mw.lua into the initial standalone environment, to reduce code
duplication between mw.lua and MWServer.lua.
* Fixed a bug in Scribunto_LuaStandaloneInterpreter::handleCall() for functions
that return no results.
* Fixed a bug in encodeLuaVar() for strings with "\r". Added test case.
* In MWServer.lua, don't call error() for internal errors, instead just print
the error and exit. This avoids a protocol violation when an error is
encountered from within handleCall().
* Added lots of documentation. Lua doc comments are in LuaDoc format.
Change-Id: Ie2fd572c362bedf02f45d3fa5352a5280e034740
2012-04-18 03:46:18 +00:00
|
|
|
}
|
2014-05-23 15:43:22 +00:00
|
|
|
if ( !$this->engine->getInterpreter()->isLuaFunction( $ret ) ) {
|
|
|
|
throw $this->engine->newException( 'scribunto-common-notafunction', array( 'args' => array( $name ) ) );
|
|
|
|
}
|
2012-04-13 10:38:12 +00:00
|
|
|
|
2014-05-23 15:43:22 +00:00
|
|
|
$result = $this->engine->executeFunctionChunk( $ret, $frame );
|
2012-04-13 10:38:12 +00:00
|
|
|
if ( isset( $result[0] ) ) {
|
|
|
|
return $result[0];
|
|
|
|
} else {
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
class Scribunto_LuaError extends ScribuntoException {
|
2012-07-14 04:23:42 +00:00
|
|
|
var $luaMessage, $lineMap = array();
|
2012-04-13 10:38:12 +00:00
|
|
|
|
2012-04-23 11:36:13 +00:00
|
|
|
function __construct( $message, $options = array() ) {
|
2012-04-13 10:38:12 +00:00
|
|
|
$this->luaMessage = $message;
|
2012-04-23 11:36:13 +00:00
|
|
|
$options = $options + array( 'args' => array( $message ) );
|
|
|
|
if ( isset( $options['module'] ) && isset( $options['line'] ) ) {
|
|
|
|
$msg = 'scribunto-lua-error-location';
|
|
|
|
} else {
|
|
|
|
$msg = 'scribunto-lua-error';
|
|
|
|
}
|
|
|
|
|
|
|
|
parent::__construct( $msg, $options );
|
2012-04-13 10:38:12 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
function getLuaMessage() {
|
|
|
|
return $this->luaMessage;
|
|
|
|
}
|
2012-04-23 11:36:13 +00:00
|
|
|
|
2012-07-14 04:23:42 +00:00
|
|
|
function setLineMap( $map ) {
|
|
|
|
$this->lineMap = $map;
|
|
|
|
}
|
|
|
|
|
2012-10-07 00:11:21 +00:00
|
|
|
/**
|
|
|
|
* @param array $options Options for message processing. Currently supports:
|
|
|
|
* $options['msgOptions']['content'] to use content language.
|
|
|
|
* @return bool|string
|
|
|
|
*/
|
2012-04-23 11:36:13 +00:00
|
|
|
function getScriptTraceHtml( $options = array() ) {
|
2012-04-24 10:40:40 +00:00
|
|
|
if ( !isset( $this->params['trace'] ) ) {
|
|
|
|
return false;
|
|
|
|
}
|
2012-04-23 11:36:13 +00:00
|
|
|
if ( isset( $options['msgOptions'] ) ){
|
|
|
|
$msgOptions = $options['msgOptions'];
|
|
|
|
} else {
|
|
|
|
$msgOptions = array();
|
|
|
|
}
|
|
|
|
|
|
|
|
$s = '<ol class="scribunto-trace">';
|
|
|
|
foreach ( $this->params['trace'] as $info ) {
|
2012-07-14 04:23:42 +00:00
|
|
|
$short_src = $srcdefined = $info['short_src'];
|
|
|
|
$currentline = $info['currentline'];
|
|
|
|
|
|
|
|
$src = htmlspecialchars( $short_src );
|
|
|
|
if ( $currentline > 0 ) {
|
|
|
|
$src .= ':' . htmlspecialchars( $currentline );
|
2012-04-23 11:36:13 +00:00
|
|
|
|
2012-07-14 04:23:42 +00:00
|
|
|
$title = Title::newFromText( $short_src );
|
2012-04-23 11:36:13 +00:00
|
|
|
if ( $title && $title->getNamespace() === NS_MODULE ) {
|
2012-07-14 04:23:42 +00:00
|
|
|
$title->setFragment( '#mw-ce-l' . $currentline );
|
2014-07-07 18:46:59 +00:00
|
|
|
$src = Html::rawElement( 'a',
|
2012-04-23 11:36:13 +00:00
|
|
|
array( 'href' => $title->getFullURL( 'action=edit' ) ),
|
|
|
|
$src );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if ( strval( $info['namewhat'] ) !== '' ) {
|
2012-10-07 00:11:21 +00:00
|
|
|
$function = wfMessage( 'scribunto-lua-in-function', $info['name'] );
|
|
|
|
in_array( 'content', $msgOptions ) ?
|
|
|
|
$function = $function->inContentLanguage()->text() :
|
|
|
|
$function = $function->text();
|
2012-04-23 11:36:13 +00:00
|
|
|
} elseif ( $info['what'] == 'main' ) {
|
2012-10-07 00:11:21 +00:00
|
|
|
$function = wfMessage( 'scribunto-lua-in-main' );
|
|
|
|
in_array( 'content', $msgOptions ) ?
|
|
|
|
$function = $function->inContentLanguage()->text() :
|
|
|
|
$function = $function->text();
|
2013-08-28 15:55:55 +00:00
|
|
|
} else {
|
|
|
|
// C function, tail call, or a Lua function where Lua can't
|
|
|
|
// guess the name
|
2012-04-23 11:36:13 +00:00
|
|
|
$function = '?';
|
|
|
|
}
|
2012-10-07 00:11:21 +00:00
|
|
|
|
|
|
|
$backtraceLine = wfMessage( 'scribunto-lua-backtrace-line', "<strong>$src</strong>", $function );
|
|
|
|
in_array( 'content', $msgOptions ) ?
|
|
|
|
$backtraceLine = $backtraceLine->inContentLanguage()->text() :
|
|
|
|
$backtraceLine = $backtraceLine->text();
|
|
|
|
|
|
|
|
$s .= "<li>\n\t" . $backtraceLine . "\n</li>\n";
|
2012-04-23 11:36:13 +00:00
|
|
|
}
|
|
|
|
$s .= '</ol>';
|
|
|
|
return $s;
|
|
|
|
}
|
2012-04-13 10:38:12 +00:00
|
|
|
}
|