MediaWiki  1.34.0
LuaStandaloneEngine.php
Go to the documentation of this file.
1 <?php
2 
4 use Psr\Log\LoggerInterface;
5 use Psr\Log\NullLogger;
6 
8  protected static $clockTick;
11 
15  protected $interpreter;
16 
17  public function load() {
18  parent::load();
19  if ( php_uname( 's' ) === 'Linux' ) {
20  $this->initialStatus = $this->interpreter->getStatus();
21  } else {
22  $this->initialStatus = false;
23  }
24  }
25 
26  public function getPerformanceCharacteristics() {
27  return [
28  'phpCallsRequireSerialization' => true,
29  ];
30  }
31 
32  public function reportLimitData( ParserOutput $output ) {
33  try {
34  $this->load();
35  } catch ( Exception $e ) {
36  return;
37  }
38  if ( $this->initialStatus ) {
39  $status = $this->interpreter->getStatus();
40  $output->setLimitReportData( 'scribunto-limitreport-timeusage',
41  [
42  sprintf( "%.3f", $status['time'] / $this->getClockTick() ),
43  // Strip trailing .0s
44  rtrim( rtrim( sprintf( "%.3f", $this->options['cpuLimit'] ), '0' ), '.' )
45  ]
46  );
47  $output->setLimitReportData( 'scribunto-limitreport-virtmemusage',
48  [
49  $status['vsize'],
50  $this->options['memoryLimit']
51  ]
52  );
53  $output->setLimitReportData( 'scribunto-limitreport-estmemusage',
54  $status['vsize'] - $this->initialStatus['vsize']
55  );
56  }
57  $logs = $this->getLogBuffer();
58  if ( $logs !== '' ) {
59  $output->addModules( 'ext.scribunto.logs' );
60  $output->setLimitReportData( 'scribunto-limitreport-logs', $logs );
61  }
62  }
63 
64  public function formatLimitData( $key, &$value, &$report, $isHTML, $localize ) {
65  global $wgLang;
66  $lang = $localize ? $wgLang : Language::factory( 'en' );
67  switch ( $key ) {
68  case 'scribunto-limitreport-logs':
69  if ( $isHTML ) {
70  $report .= $this->formatHtmlLogs( $value, $localize );
71  }
72  return false;
73  case 'scribunto-limitreport-virtmemusage':
74  $value = array_map( [ $lang, 'formatSize' ], $value );
75  break;
76  case 'scribunto-limitreport-estmemusage':
77  // @phan-suppress-next-line PhanTypeMismatchArgument
78  $value = $lang->formatSize( $value );
79  break;
80  }
81  return true;
82  }
83 
87  protected function getClockTick() {
88  if ( self::$clockTick === null ) {
89  Wikimedia\suppressWarnings();
90  self::$clockTick = intval( shell_exec( 'getconf CLK_TCK' ) );
91  Wikimedia\restoreWarnings();
92  if ( !self::$clockTick ) {
93  self::$clockTick = 100;
94  }
95  }
96  return self::$clockTick;
97  }
98 
102  protected function newInterpreter() {
103  return new Scribunto_LuaStandaloneInterpreter( $this, $this->options + [
104  'logger' => LoggerFactory::getInstance( 'Scribunto' )
105  ] );
106  }
107 
108  public function getSoftwareInfo( array &$software ) {
109  $ver = Scribunto_LuaStandaloneInterpreter::getLuaVersion( $this->options );
110  if ( $ver !== null ) {
111  if ( substr( $ver, 0, 6 ) === 'LuaJIT' ) {
112  $software['[http://luajit.org/ LuaJIT]'] = str_replace( 'LuaJIT ', '', $ver );
113  } else {
114  $software['[http://www.lua.org/ Lua]'] = str_replace( 'Lua ', '', $ver );
115  }
116  }
117  }
118 }
119 
121  protected static $nextInterpreterId = 0;
122 
126  public $engine;
127 
131  public $enableDebug;
132 
136  public $proc;
137 
141  public $writePipe;
142 
146  public $readPipe;
147 
151  public $exitError;
152 
156  public $id;
157 
161  protected $logger;
162 
166  protected $callbacks;
167 
175  public function __construct( $engine, array $options ) {
176  $this->id = self::$nextInterpreterId++;
177 
178  if ( $options['errorFile'] === null ) {
179  $options['errorFile'] = wfGetNull();
180  }
181 
182  if ( $options['luaPath'] === null ) {
183  $path = false;
184 
185  // Note, if you alter these, also alter getLuaVersion() below
186  if ( PHP_OS == 'Linux' ) {
187  if ( PHP_INT_SIZE == 4 ) {
188  $path = 'lua5_1_5_linux_32_generic/lua';
189  } elseif ( PHP_INT_SIZE == 8 ) {
190  $path = 'lua5_1_5_linux_64_generic/lua';
191  }
192  } elseif ( PHP_OS == 'Windows' || PHP_OS == 'WINNT' || PHP_OS == 'Win32' ) {
193  if ( PHP_INT_SIZE == 4 ) {
194  $path = 'lua5_1_5_Win32_bin/lua5.1.exe';
195  } elseif ( PHP_INT_SIZE == 8 ) {
196  $path = 'lua5_1_5_Win64_bin/lua5.1.exe';
197  }
198  } elseif ( PHP_OS == 'Darwin' ) {
199  $path = 'lua5_1_5_mac_lion_fat_generic/lua';
200  }
201  if ( $path === false ) {
203  'No Lua interpreter was given in the configuration, ' .
204  'and no bundled binary exists for this platform.' );
205  }
206  $options['luaPath'] = __DIR__ . "/binaries/$path";
207 
208  if ( !is_executable( $options['luaPath'] ) ) {
209  throw new MWException(
210  sprintf( 'The lua binary (%s) is not executable.', $options['luaPath'] )
211  );
212  }
213  }
214 
215  $this->engine = $engine;
216  $this->enableDebug = !empty( $options['debug'] );
217  $this->logger = $options['logger'] ?? new NullLogger();
218 
219  $pipes = null;
220  $cmd = wfEscapeShellArg(
221  $options['luaPath'],
222  __DIR__ . '/mw_main.lua',
223  dirname( dirname( __DIR__ ) ),
224  $this->id,
225  PHP_INT_SIZE
226  );
227  if ( php_uname( 's' ) == 'Linux' ) {
228  // Limit memory and CPU
229  $cmd = wfEscapeShellArg(
230  'exec', # proc_open() passes $cmd to 'sh -c' on Linux, so add an 'exec' to bypass it
231  '/bin/sh',
232  __DIR__ . '/lua_ulimit.sh',
233  $options['cpuLimit'], # soft limit (SIGXCPU)
234  $options['cpuLimit'] + 1, # hard limit
235  intval( $options['memoryLimit'] / 1024 ),
236  $cmd );
237  }
238 
239  if ( php_uname( 's' ) == 'Windows NT' ) {
240  // Like the passthru() in older versions of PHP,
241  // PHP's invokation of cmd.exe in proc_open() is broken:
242  // http://news.php.net/php.internals/21796
243  // Unlike passthru(), it is not fixed in any PHP version,
244  // so we use the fix similar to one in wfShellExec()
245  $cmd = '"' . $cmd . '"';
246  }
247 
248  $this->logger->debug( __METHOD__ . ": creating interpreter: $cmd\n" );
249 
250  // Check whether proc_open is available before trying to call it (e.g.
251  // PHP's disable_functions may have removed it)
252  if ( !function_exists( 'proc_open' ) ) {
253  throw $this->engine->newException( 'scribunto-luastandalone-proc-error-proc-open' );
254  }
255 
256  // Clear the "last error", so if proc_open fails we can know any
257  // warning was generated by that.
258  Wikimedia\suppressWarnings();
259  trigger_error( '' );
260  Wikimedia\restoreWarnings();
261 
262  $this->proc = proc_open(
263  $cmd,
264  [
265  [ 'pipe', 'r' ],
266  [ 'pipe', 'w' ],
267  [ 'file', $options['errorFile'], 'a' ]
268  ],
269  $pipes );
270  if ( !$this->proc ) {
271  $err = error_get_last();
272  if ( !empty( $err['message'] ) ) {
273  throw $this->engine->newException( 'scribunto-luastandalone-proc-error-msg',
274  [ 'args' => [ $err['message'] ] ] );
275  } else {
276  throw $this->engine->newException( 'scribunto-luastandalone-proc-error' );
277  }
278  }
279  $this->writePipe = $pipes[0];
280  $this->readPipe = $pipes[1];
281  }
282 
283  public function __destruct() {
284  $this->terminate();
285  }
286 
287  public static function getLuaVersion( array $options ) {
288  if ( $options['luaPath'] === null ) {
289  // We know which versions are distributed, no need to run them.
290  if ( PHP_OS == 'Linux' ) {
291  return 'Lua 5.1.5';
292  } elseif ( PHP_OS == 'Windows' || PHP_OS == 'WINNT' || PHP_OS == 'Win32' ) {
293  return 'Lua 5.1.4';
294  } elseif ( PHP_OS == 'Darwin' ) {
295  return 'Lua 5.1.5';
296  } else {
297  return null;
298  }
299  }
300 
301  // Ask the interpreter what version it is, using the "-v" option.
302  // The output is expected to be one line, something like these:
303  // Lua 5.1.5 Copyright (C) 1994-2012 Lua.org, PUC-Rio
304  // LuaJIT 2.0.0 -- Copyright (C) 2005-2012 Mike Pall. http://luajit.org/
305  $cmd = wfEscapeShellArg( $options['luaPath'] ) . ' -v';
306  $handle = popen( $cmd, 'r' );
307  if ( $handle ) {
308  $ret = fgets( $handle, 80 );
309  pclose( $handle );
310  if ( $ret && preg_match( '/^Lua(?:JIT)? \S+/', $ret, $m ) ) {
311  return $m[0];
312  }
313  }
314  return null;
315  }
316 
317  public function terminate() {
318  if ( $this->proc ) {
319  $this->logger->debug( __METHOD__ . ": terminating\n" );
320  proc_terminate( $this->proc );
321  proc_close( $this->proc );
322  $this->proc = false;
323  }
324  }
325 
326  public function quit() {
327  if ( !$this->proc ) {
328  return;
329  }
330  $this->dispatch( [ 'op' => 'quit' ] );
331  proc_close( $this->proc );
332  }
333 
334  public function testquit() {
335  if ( !$this->proc ) {
336  return;
337  }
338  $this->dispatch( [ 'op' => 'testquit' ] );
339  proc_close( $this->proc );
340  }
341 
347  public function loadString( $text, $chunkName ) {
348  $this->cleanupLuaChunks();
349 
350  $result = $this->dispatch( [
351  'op' => 'loadString',
352  'text' => $text,
353  'chunkName' => $chunkName
354  ] );
355  return new Scribunto_LuaStandaloneInterpreterFunction( $this->id, $result[1] );
356  }
357 
358  public function callFunction( $func, ...$args ) {
359  if ( !( $func instanceof Scribunto_LuaStandaloneInterpreterFunction ) ) {
360  throw new MWException( __METHOD__ . ': invalid function type' );
361  }
362  if ( $func->interpreterId !== $this->id ) {
363  throw new MWException( __METHOD__ . ': function belongs to a different interpreter' );
364  }
365  $args = func_get_args();
366  unset( $args[0] );
367  // $args is now conveniently a 1-based array, as required by the Lua server
368 
369  $this->cleanupLuaChunks();
370 
371  $result = $this->dispatch( [
372  'op' => 'call',
373  'id' => $func->id,
374  'nargs' => count( $args ),
375  'args' => $args,
376  ] );
377  // Convert return values to zero-based
378  return array_values( $result );
379  }
380 
381  public function wrapPhpFunction( $callable ) {
382  static $uid = 0;
383  $id = "anonymous*" . ++$uid;
384  $this->callbacks[$id] = $callable;
385  $ret = $this->dispatch( [
386  'op' => 'wrapPhpFunction',
387  'id' => $id,
388  ] );
389  return $ret[1];
390  }
391 
392  public function cleanupLuaChunks() {
395  $this->dispatch( [
396  'op' => 'cleanupChunks',
398  ] );
399  }
400  }
401 
402  public function isLuaFunction( $object ) {
403  return $object instanceof Scribunto_LuaStandaloneInterpreterFunction;
404  }
405 
406  public function registerLibrary( $name, array $functions ) {
407  // Make sure all ids are unique, even when libraries share the same name
408  // which is especially relevant for "mw_interface" (T211203).
409  static $uid = 0;
410  $uid++;
411 
412  $functionIds = [];
413  foreach ( $functions as $funcName => $callback ) {
414  $id = "$name-$funcName-$uid";
415  $this->callbacks[$id] = $callback;
416  $functionIds[$funcName] = $id;
417  }
418  $this->dispatch( [
419  'op' => 'registerLibrary',
420  'name' => $name,
421  'functions' => $functionIds,
422  ] );
423  }
424 
425  public function getStatus() {
426  $result = $this->dispatch( [
427  'op' => 'getStatus',
428  ] );
429  return $result[1];
430  }
431 
432  public function pauseUsageTimer() {
433  }
434 
435  public function unpauseUsageTimer() {
436  }
437 
445  private static function fixNulls( array $array, $count ) {
446  if ( count( $array ) === $count ) {
447  return $array;
448  } else {
449  return array_replace( array_fill( 1, $count, null ), $array );
450  }
451  }
452 
453  protected function handleCall( $message ) {
454  $message['args'] = self::fixNulls( $message['args'], $message['nargs'] );
455  try {
456  $result = $this->callback( $message['id'], $message['args'] );
457  } catch ( Scribunto_LuaError $e ) {
458  return [
459  'op' => 'error',
460  'value' => $e->getLuaMessage(),
461  ];
462  }
463 
464  // Convert to a 1-based array
465  if ( $result !== null && count( $result ) ) {
466  $result = array_combine( range( 1, count( $result ) ), $result );
467  } else {
468  $result = [];
469  }
470 
471  return [
472  'op' => 'return',
473  'nvalues' => count( $result ),
474  'values' => $result
475  ];
476  }
477 
478  protected function callback( $id, array $args ) {
479  return ( $this->callbacks[$id] )( ...$args );
480  }
481 
482  protected function handleError( $message ) {
483  $opts = [];
484  if ( preg_match( '/^(.*?):(\d+): (.*)$/', $message['value'], $m ) ) {
485  $opts['module'] = $m[1];
486  $opts['line'] = $m[2];
487  $message['value'] = $m[3];
488  }
489  if ( isset( $message['trace'] ) ) {
490  $opts['trace'] = array_values( $message['trace'] );
491  }
492  throw $this->engine->newLuaError( $message['value'], $opts );
493  }
494 
495  protected function dispatch( $msgToLua ) {
496  $this->sendMessage( $msgToLua );
497  while ( true ) {
498  $msgFromLua = $this->receiveMessage();
499 
500  switch ( $msgFromLua['op'] ) {
501  case 'return':
502  return self::fixNulls( $msgFromLua['values'], $msgFromLua['nvalues'] );
503  case 'call':
504  $msgToLua = $this->handleCall( $msgFromLua );
505  $this->sendMessage( $msgToLua );
506  break;
507  case 'error':
508  $this->handleError( $msgFromLua );
509  return; // not reached
510  default:
511  $this->logger->error( __METHOD__ . ": invalid response op \"{$msgFromLua['op']}\"\n" );
512  throw $this->engine->newException( 'scribunto-luastandalone-decode-error' );
513  }
514  }
515  }
516 
517  protected function sendMessage( $msg ) {
518  $this->debug( "TX ==> {$msg['op']}" );
519  $this->checkValid();
520  // Send the message
521  $encMsg = $this->encodeMessage( $msg );
522  if ( !fwrite( $this->writePipe, $encMsg ) ) {
523  // Write error, probably the process has terminated
524  // If it has, handleIOError() will throw. If not, throw an exception ourselves.
525  $this->handleIOError();
526  throw $this->engine->newException( 'scribunto-luastandalone-write-error' );
527  }
528  }
529 
530  protected function receiveMessage() {
531  $this->checkValid();
532  // Read the header
533  $header = fread( $this->readPipe, 16 );
534  if ( strlen( $header ) !== 16 ) {
535  $this->handleIOError();
536  throw $this->engine->newException( 'scribunto-luastandalone-read-error' );
537  }
538  $length = $this->decodeHeader( $header );
539 
540  // Read the reply body
541  $body = '';
542  $lengthRemaining = $length;
543  while ( $lengthRemaining ) {
544  $buffer = fread( $this->readPipe, $lengthRemaining );
545  if ( $buffer === false || feof( $this->readPipe ) ) {
546  $this->handleIOError();
547  throw $this->engine->newException( 'scribunto-luastandalone-read-error' );
548  }
549  $body .= $buffer;
550  $lengthRemaining -= strlen( $buffer );
551  }
552  $body = strtr( $body, [
553  '\\r' => "\r",
554  '\\n' => "\n",
555  '\\\\' => '\\',
556  ] );
557  $msg = unserialize( $body );
558  $this->debug( "RX <== {$msg['op']}" );
559  return $msg;
560  }
561 
562  protected function encodeMessage( $message ) {
563  $serialized = $this->encodeLuaVar( $message );
564  $length = strlen( $serialized );
565  $check = $length * 2 - 1;
566 
567  return sprintf( '%08x%08x%s', $length, $check, $serialized );
568  }
569 
577  protected function encodeLuaVar( $var, $level = 0 ) {
578  if ( $level > 100 ) {
579  throw new MWException( __METHOD__ . ': recursion depth limit exceeded' );
580  }
581  $type = gettype( $var );
582  switch ( $type ) {
583  case 'boolean':
584  return $var ? 'true' : 'false';
585  case 'integer':
586  return $var;
587  case 'double':
588  if ( !is_finite( $var ) ) {
589  if ( is_nan( $var ) ) {
590  return '(0/0)';
591  }
592  if ( $var === INF ) {
593  return '(1/0)';
594  }
595  if ( $var === -INF ) {
596  return '(-1/0)';
597  }
598  throw new MWException( __METHOD__ . ': cannot convert non-finite number' );
599  }
600  return sprintf( '%.17g', $var );
601  case 'string':
602  return '"' .
603  strtr( $var, [
604  '"' => '\\"',
605  '\\' => '\\\\',
606  "\n" => '\\n',
607  "\r" => '\\r',
608  "\000" => '\\000',
609  ] ) .
610  '"';
611  case 'array':
612  $s = '{';
613  foreach ( $var as $key => $element ) {
614  if ( $s !== '{' ) {
615  $s .= ',';
616  }
617 
618  // Lua's number type can't represent most integers beyond 2**53, so stringify such keys
619  if ( is_int( $key ) && ( $key > 9007199254740992 || $key < -9007199254740992 ) ) {
620  $key = sprintf( '%d', $key );
621  }
622 
623  $s .= '[' . $this->encodeLuaVar( $key, $level + 1 ) . ']' .
624  '=' . $this->encodeLuaVar( $element, $level + 1 );
625  }
626  $s .= '}';
627  return $s;
628  case 'object':
629  if ( !( $var instanceof Scribunto_LuaStandaloneInterpreterFunction ) ) {
630  throw new MWException( __METHOD__ . ': unable to convert object of type ' .
631  get_class( $var ) );
632  } elseif ( $var->interpreterId !== $this->id ) {
633  throw new MWException(
634  __METHOD__ . ': unable to convert function belonging to a different interpreter'
635  );
636  } else {
637  return 'chunks[' . intval( $var->id ) . ']';
638  }
639  case 'resource':
640  throw new MWException( __METHOD__ . ': unable to convert resource' );
641  case 'NULL':
642  return 'nil';
643  default:
644  throw new MWException( __METHOD__ . ': unable to convert variable of unknown type' );
645  }
646  }
647 
648  protected function decodeHeader( $header ) {
649  $length = substr( $header, 0, 8 );
650  $check = substr( $header, 8, 8 );
651  if ( !preg_match( '/^[0-9a-f]+$/', $length ) || !preg_match( '/^[0-9a-f]+$/', $check ) ) {
652  throw $this->engine->newException( 'scribunto-luastandalone-decode-error' );
653  }
654  $length = hexdec( $length );
655  $check = hexdec( $check );
656  if ( $length * 2 - 1 !== $check ) {
657  throw $this->engine->newException( 'scribunto-luastandalone-decode-error' );
658  }
659  return $length;
660  }
661 
665  protected function checkValid() {
666  if ( !$this->proc ) {
667  $this->logger->error( __METHOD__ . ": process already terminated\n" );
668  if ( $this->exitError ) {
669  throw $this->exitError;
670  } else {
671  throw $this->engine->newException( 'scribunto-luastandalone-gone' );
672  }
673  }
674  }
675 
679  protected function handleIOError() {
680  $this->checkValid();
681 
682  // Terminate, fetch the status, then close. proc_close()'s return
683  // value isn't helpful here because there's no way to differentiate a
684  // signal-kill from a normal exit.
685  proc_terminate( $this->proc );
686  while ( true ) {
687  $status = proc_get_status( $this->proc );
688  // XXX: Should proc_get_status docs be changed so that
689  // its documented as possibly returning false?
690  // @phan-suppress-next-line PhanTypeComparisonFromArray
691  if ( $status === false ) {
692  // WTF? Let the caller throw an appropriate error.
693  return;
694  }
695  if ( !$status['running'] ) {
696  break;
697  }
698  usleep( 10000 ); // Give the killed process a chance to be scheduled
699  }
700  proc_close( $this->proc );
701  $this->proc = false;
702 
703  // proc_open() sometimes uses a shell, check for shell-style signal reporting.
704  if ( !$status['signaled'] && ( $status['exitcode'] & 0x80 ) === 0x80 ) {
705  $status['signaled'] = true;
706  $status['termsig'] = $status['exitcode'] - 128;
707  }
708 
709  if ( $status['signaled'] ) {
710  if ( defined( 'SIGXCPU' ) && $status['termsig'] === SIGXCPU ) {
711  $this->exitError = $this->engine->newException( 'scribunto-common-timeout' );
712  } else {
713  $this->exitError = $this->engine->newException( 'scribunto-luastandalone-signal',
714  [ 'args' => [ $status['termsig'] ] ] );
715  }
716  } else {
717  $this->exitError = $this->engine->newException( 'scribunto-luastandalone-exited',
718  [ 'args' => [ $status['exitcode'] ] ] );
719  }
720  throw $this->exitError;
721  }
722 
723  protected function debug( $msg ) {
724  if ( $this->enableDebug ) {
725  $this->logger->debug( "Lua: $msg\n" );
726  }
727  }
728 }
729 
731  public static $anyChunksDestroyed = [];
732  public static $activeChunkIds = [];
733 
738 
742  public $id;
743 
748  public function __construct( $interpreterId, $id ) {
749  $this->interpreterId = $interpreterId;
750  $this->id = $id;
751  $this->incrementRefCount();
752  }
753 
754  public function __clone() {
755  $this->incrementRefCount();
756  }
757 
758  public function __wakeup() {
759  $this->incrementRefCount();
760  }
761 
762  public function __destruct() {
763  $this->decrementRefCount();
764  }
765 
766  private function incrementRefCount() {
767  if ( !isset( self::$activeChunkIds[$this->interpreterId] ) ) {
768  self::$activeChunkIds[$this->interpreterId] = [ $this->id => 1 ];
769  } elseif ( !isset( self::$activeChunkIds[$this->interpreterId][$this->id] ) ) {
770  self::$activeChunkIds[$this->interpreterId][$this->id] = 1;
771  } else {
772  self::$activeChunkIds[$this->interpreterId][$this->id]++;
773  }
774  }
775 
776  private function decrementRefCount() {
777  if ( isset( self::$activeChunkIds[$this->interpreterId][$this->id] ) ) {
778  if ( --self::$activeChunkIds[$this->interpreterId][$this->id] <= 0 ) {
779  unset( self::$activeChunkIds[$this->interpreterId][$this->id] );
780  self::$anyChunksDestroyed[$this->interpreterId] = true;
781  }
782  } else {
783  self::$anyChunksDestroyed[$this->interpreterId] = true;
784  }
785  }
786 }
Scribunto_LuaStandaloneEngine\getPerformanceCharacteristics
getPerformanceCharacteristics()
Get performance characteristics of the Lua engine/interpreter.
Definition: LuaStandaloneEngine.php:26
Scribunto_LuaStandaloneInterpreter\$enableDebug
bool $enableDebug
Definition: LuaStandaloneEngine.php:131
ParserOutput
Definition: ParserOutput.php:25
Scribunto_LuaStandaloneInterpreter\wrapPhpFunction
wrapPhpFunction( $callable)
Wrap a PHP callable as a Lua function, which can be passed back into Lua.
Definition: LuaStandaloneEngine.php:381
Scribunto_LuaStandaloneInterpreter\getLuaVersion
static getLuaVersion(array $options)
Definition: LuaStandaloneEngine.php:287
Scribunto_LuaError
Definition: LuaCommon.php:992
Scribunto_LuaStandaloneEngine\reportLimitData
reportLimitData(ParserOutput $output)
Add limit report data to a ParserOutput object.
Definition: LuaStandaloneEngine.php:32
$lang
if(!isset( $args[0])) $lang
Definition: testCompression.php:33
Scribunto_LuaStandaloneInterpreter\sendMessage
sendMessage( $msg)
Definition: LuaStandaloneEngine.php:517
Scribunto_LuaStandaloneInterpreter\__construct
__construct( $engine, array $options)
Definition: LuaStandaloneEngine.php:175
Scribunto_LuaStandaloneInterpreter\debug
debug( $msg)
Definition: LuaStandaloneEngine.php:723
Scribunto_LuaStandaloneEngine\newInterpreter
newInterpreter()
Definition: LuaStandaloneEngine.php:102
Scribunto_LuaStandaloneInterpreterFunction\$anyChunksDestroyed
static $anyChunksDestroyed
Definition: LuaStandaloneEngine.php:731
Scribunto_LuaStandaloneEngine\$clockTick
static $clockTick
Definition: LuaStandaloneEngine.php:8
Scribunto_LuaStandaloneInterpreterFunction\decrementRefCount
decrementRefCount()
Definition: LuaStandaloneEngine.php:776
$serialized
foreach( $res as $row) $serialized
Definition: testCompression.php:81
Scribunto_LuaStandaloneInterpreter\$callbacks
callable[] $callbacks
Definition: LuaStandaloneEngine.php:166
Scribunto_LuaStandaloneInterpreterFunction\$activeChunkIds
static $activeChunkIds
Definition: LuaStandaloneEngine.php:732
Scribunto_LuaStandaloneInterpreter\loadString
loadString( $text, $chunkName)
Definition: LuaStandaloneEngine.php:347
Scribunto_LuaStandaloneInterpreter\$id
int $id
Definition: LuaStandaloneEngine.php:156
$s
$s
Definition: mergeMessageFileList.php:185
Scribunto_LuaStandaloneInterpreter\$logger
LoggerInterface $logger
Definition: LuaStandaloneEngine.php:161
Scribunto_LuaStandaloneInterpreter\$writePipe
resource $writePipe
Definition: LuaStandaloneEngine.php:141
Scribunto_LuaStandaloneInterpreter\handleCall
handleCall( $message)
Definition: LuaStandaloneEngine.php:453
Scribunto_LuaStandaloneInterpreter\encodeMessage
encodeMessage( $message)
Definition: LuaStandaloneEngine.php:562
Scribunto_LuaStandaloneEngine\$initialStatus
array bool $initialStatus
Definition: LuaStandaloneEngine.php:10
Scribunto_LuaStandaloneInterpreterFunction\__clone
__clone()
Definition: LuaStandaloneEngine.php:754
Scribunto_LuaStandaloneInterpreter\testquit
testquit()
Definition: LuaStandaloneEngine.php:334
Scribunto_LuaStandaloneEngine\load
load()
Initialise the interpreter and the base environment.
Definition: LuaStandaloneEngine.php:17
Scribunto_LuaInterpreterNotFoundError
Definition: LuaInterpreter.php:64
MWException
MediaWiki exception.
Definition: MWException.php:26
Scribunto_LuaStandaloneInterpreterFunction
Definition: LuaStandaloneEngine.php:730
MediaWiki\Logger\LoggerFactory
PSR-3 logger instance factory.
Definition: LoggerFactory.php:45
Scribunto_LuaStandaloneInterpreter\quit
quit()
Definition: LuaStandaloneEngine.php:326
Scribunto_LuaStandaloneInterpreter\$exitError
ScribuntoException $exitError
Definition: LuaStandaloneEngine.php:151
Scribunto_LuaEngine
Definition: LuaCommon.php:6
Scribunto_LuaStandaloneEngine
Definition: LuaStandaloneEngine.php:7
$wgLang
$wgLang
Definition: Setup.php:881
Scribunto_LuaStandaloneInterpreterFunction\__construct
__construct( $interpreterId, $id)
Definition: LuaStandaloneEngine.php:748
Scribunto_LuaStandaloneInterpreterFunction\__wakeup
__wakeup()
Definition: LuaStandaloneEngine.php:758
Scribunto_LuaStandaloneInterpreterFunction\__destruct
__destruct()
Definition: LuaStandaloneEngine.php:762
Scribunto_LuaStandaloneInterpreter\checkValid
checkValid()
Definition: LuaStandaloneEngine.php:665
Scribunto_LuaStandaloneInterpreter\pauseUsageTimer
pauseUsageTimer()
Pause CPU usage and limits.
Definition: LuaStandaloneEngine.php:432
Scribunto_LuaStandaloneInterpreterFunction\$id
int $id
Definition: LuaStandaloneEngine.php:742
Scribunto_LuaStandaloneInterpreterFunction\incrementRefCount
incrementRefCount()
Definition: LuaStandaloneEngine.php:766
Scribunto_LuaStandaloneInterpreter\$nextInterpreterId
static $nextInterpreterId
Definition: LuaStandaloneEngine.php:121
$output
$output
Definition: SyntaxHighlight.php:335
Scribunto_LuaStandaloneInterpreter\dispatch
dispatch( $msgToLua)
Definition: LuaStandaloneEngine.php:495
Scribunto_LuaStandaloneInterpreterFunction\$interpreterId
int $interpreterId
Definition: LuaStandaloneEngine.php:737
Scribunto_LuaStandaloneInterpreter\unpauseUsageTimer
unpauseUsageTimer()
Unpause CPU usage and limits.
Definition: LuaStandaloneEngine.php:435
Scribunto_LuaStandaloneInterpreter\encodeLuaVar
encodeLuaVar( $var, $level=0)
Definition: LuaStandaloneEngine.php:577
Scribunto_LuaStandaloneInterpreter\cleanupLuaChunks
cleanupLuaChunks()
Definition: LuaStandaloneEngine.php:392
Scribunto_LuaStandaloneInterpreter\callback
callback( $id, array $args)
Definition: LuaStandaloneEngine.php:478
Scribunto_LuaStandaloneInterpreter\handleIOError
handleIOError()
Definition: LuaStandaloneEngine.php:679
Scribunto_LuaStandaloneInterpreter\$engine
Scribunto_LuaStandaloneEngine $engine
Definition: LuaStandaloneEngine.php:126
$header
$header
Definition: updateCredits.php:41
Scribunto_LuaError\getLuaMessage
getLuaMessage()
Definition: LuaCommon.php:1007
Scribunto_LuaStandaloneEngine\$interpreter
Scribunto_LuaStandaloneInterpreter $interpreter
Definition: LuaStandaloneEngine.php:15
Scribunto_LuaStandaloneEngine\formatLimitData
formatLimitData( $key, &$value, &$report, $isHTML, $localize)
Format limit report data.
Definition: LuaStandaloneEngine.php:64
wfGetNull
wfGetNull()
Get a platform-independent path to the null file, e.g.
Definition: GlobalFunctions.php:2692
Scribunto_LuaStandaloneInterpreter\callFunction
callFunction( $func,... $args)
Call a Lua function.
Definition: LuaStandaloneEngine.php:358
Scribunto_LuaStandaloneInterpreter
Definition: LuaStandaloneEngine.php:120
ScribuntoException
An exception class which represents an error in the script.
Definition: Common.php:136
Scribunto_LuaStandaloneInterpreter\fixNulls
static fixNulls(array $array, $count)
Fill in missing nulls in a list received from Lua.
Definition: LuaStandaloneEngine.php:445
Scribunto_LuaStandaloneInterpreter\handleError
handleError( $message)
Definition: LuaStandaloneEngine.php:482
Scribunto_LuaStandaloneInterpreter\receiveMessage
receiveMessage()
Definition: LuaStandaloneEngine.php:530
Scribunto_LuaStandaloneInterpreter\isLuaFunction
isLuaFunction( $object)
Test whether an object is a Lua function.
Definition: LuaStandaloneEngine.php:402
unserialize
unserialize( $serialized)
Definition: ApiMessageTrait.php:146
$args
if( $line===false) $args
Definition: cdb.php:64
Scribunto_LuaInterpreter
Definition: LuaInterpreter.php:3
$status
return $status
Definition: SyntaxHighlight.php:347
Scribunto_LuaStandaloneInterpreter\registerLibrary
registerLibrary( $name, array $functions)
Register a library of functions.
Definition: LuaStandaloneEngine.php:406
$path
$path
Definition: NoLocalSettings.php:25
Scribunto_LuaEngine\getLogBuffer
getLogBuffer()
Get data logged by modules.
Definition: LuaCommon.php:303
Scribunto_LuaStandaloneInterpreter\$readPipe
resource $readPipe
Definition: LuaStandaloneEngine.php:146
Scribunto_LuaStandaloneInterpreter\__destruct
__destruct()
Definition: LuaStandaloneEngine.php:283
wfEscapeShellArg
wfEscapeShellArg(... $args)
Version of escapeshellarg() that works better on Windows.
Definition: GlobalFunctions.php:2099
Scribunto_LuaStandaloneInterpreter\getStatus
getStatus()
Definition: LuaStandaloneEngine.php:425
Language\factory
static factory( $code)
Get a cached or new language object for a given language code.
Definition: Language.php:217
Scribunto_LuaEngine\formatHtmlLogs
formatHtmlLogs( $logs, $localize)
Format the logged data for HTML output.
Definition: LuaCommon.php:322
Scribunto_LuaStandaloneInterpreter\decodeHeader
decodeHeader( $header)
Definition: LuaStandaloneEngine.php:648
Scribunto_LuaStandaloneEngine\getClockTick
getClockTick()
Definition: LuaStandaloneEngine.php:87
Scribunto_LuaStandaloneInterpreter\terminate
terminate()
Definition: LuaStandaloneEngine.php:317
Scribunto_LuaStandaloneEngine\getSoftwareInfo
getSoftwareInfo(array &$software)
Get software information for Special:Version.
Definition: LuaStandaloneEngine.php:108
Scribunto_LuaStandaloneInterpreter\$proc
resource bool $proc
Definition: LuaStandaloneEngine.php:136
$type
$type
Definition: testCompression.php:48