68 define(
'TOKEN_END', 1);
69 define(
'TOKEN_NUMBER', 2);
70 define(
'TOKEN_IDENTIFIER', 3);
71 define(
'TOKEN_STRING', 4);
72 define(
'TOKEN_REGEXP', 5);
73 define(
'TOKEN_NEWLINE', 6);
74 define(
'TOKEN_CONDCOMMENT_START', 7);
75 define(
'TOKEN_CONDCOMMENT_END', 8);
77 define(
'JS_SCRIPT', 100);
78 define(
'JS_BLOCK', 101);
79 define(
'JS_LABEL', 102);
80 define(
'JS_FOR_IN', 103);
81 define(
'JS_CALL', 104);
82 define(
'JS_NEW_WITH_ARGS', 105);
83 define(
'JS_INDEX', 106);
84 define(
'JS_ARRAY_INIT', 107);
85 define(
'JS_OBJECT_INIT', 108);
86 define(
'JS_PROPERTY_INIT', 109);
87 define(
'JS_GETTER', 110);
88 define(
'JS_SETTER', 111);
89 define(
'JS_GROUP', 112);
90 define(
'JS_LIST', 113);
92 define(
'JS_MINIFIED', 999);
94 define(
'DECLARED_FORM', 0);
95 define(
'EXPRESSED_FORM', 1);
96 define(
'STATEMENT_FORM', 2);
99 define(
'OP_SEMICOLON',
';');
100 define(
'OP_COMMA',
',');
101 define(
'OP_HOOK',
'?');
102 define(
'OP_COLON',
':');
103 define(
'OP_OR',
'||');
104 define(
'OP_AND',
'&&');
105 define(
'OP_BITWISE_OR',
'|');
106 define(
'OP_BITWISE_XOR',
'^');
107 define(
'OP_BITWISE_AND',
'&');
108 define(
'OP_STRICT_EQ',
'===');
109 define(
'OP_EQ',
'==');
110 define(
'OP_ASSIGN',
'=');
111 define(
'OP_STRICT_NE',
'!==');
112 define(
'OP_NE',
'!=');
113 define(
'OP_LSH',
'<<');
114 define(
'OP_LE',
'<=');
115 define(
'OP_LT',
'<');
116 define(
'OP_URSH',
'>>>');
117 define(
'OP_RSH',
'>>');
118 define(
'OP_GE',
'>=');
119 define(
'OP_GT',
'>');
120 define(
'OP_INCREMENT',
'++');
121 define(
'OP_DECREMENT',
'--');
122 define(
'OP_PLUS',
'+');
123 define(
'OP_MINUS',
'-');
124 define(
'OP_MUL',
'*');
125 define(
'OP_DIV',
'/');
126 define(
'OP_MOD',
'%');
127 define(
'OP_NOT',
'!');
128 define(
'OP_BITWISE_NOT',
'~');
129 define(
'OP_DOT',
'.');
130 define(
'OP_LEFT_BRACKET',
'[');
131 define(
'OP_RIGHT_BRACKET',
']');
132 define(
'OP_LEFT_CURLY',
'{');
133 define(
'OP_RIGHT_CURLY',
'}');
134 define(
'OP_LEFT_PAREN',
'(');
135 define(
'OP_RIGHT_PAREN',
')');
136 define(
'OP_CONDCOMMENT_END',
'@*/');
138 define(
'OP_UNARY_PLUS',
'U+');
139 define(
'OP_UNARY_MINUS',
'U-');
142 define(
'KEYWORD_BREAK',
'break');
143 define(
'KEYWORD_CASE',
'case');
144 define(
'KEYWORD_CATCH',
'catch');
145 define(
'KEYWORD_CONST',
'const');
146 define(
'KEYWORD_CONTINUE',
'continue');
147 define(
'KEYWORD_DEBUGGER',
'debugger');
148 define(
'KEYWORD_DEFAULT',
'default');
149 define(
'KEYWORD_DELETE',
'delete');
150 define(
'KEYWORD_DO',
'do');
151 define(
'KEYWORD_ELSE',
'else');
152 define(
'KEYWORD_ENUM',
'enum');
153 define(
'KEYWORD_FALSE',
'false');
154 define(
'KEYWORD_FINALLY',
'finally');
155 define(
'KEYWORD_FOR',
'for');
156 define(
'KEYWORD_FUNCTION',
'function');
157 define(
'KEYWORD_IF',
'if');
158 define(
'KEYWORD_IN',
'in');
159 define(
'KEYWORD_INSTANCEOF',
'instanceof');
160 define(
'KEYWORD_NEW',
'new');
161 define(
'KEYWORD_NULL',
'null');
162 define(
'KEYWORD_RETURN',
'return');
163 define(
'KEYWORD_SWITCH',
'switch');
164 define(
'KEYWORD_THIS',
'this');
165 define(
'KEYWORD_THROW',
'throw');
166 define(
'KEYWORD_TRUE',
'true');
167 define(
'KEYWORD_TRY',
'try');
168 define(
'KEYWORD_TYPEOF',
'typeof');
169 define(
'KEYWORD_VAR',
'var');
170 define(
'KEYWORD_VOID',
'void');
171 define(
'KEYWORD_WHILE',
'while');
172 define(
'KEYWORD_WITH',
'with');
179 'break',
'case',
'catch',
'continue',
'default',
'delete',
'do',
180 'else',
'finally',
'for',
'function',
'if',
'in',
'instanceof',
181 'new',
'return',
'switch',
'this',
'throw',
'try',
'typeof',
'var',
182 'void',
'while',
'with',
184 'abstract',
'boolean',
'byte',
'char',
'class',
'const',
'debugger',
185 'double',
'enum',
'export',
'extends',
'final',
'float',
'goto',
186 'implements',
'import',
'int',
'interface',
'long',
'native',
187 'package',
'private',
'protected',
'public',
'short',
'static',
188 'super',
'synchronized',
'throws',
'transient',
'volatile',
191 'arguments',
'eval',
'true',
'false',
'Infinity',
'NaN',
'null',
'undefined'
196 $this->parser =
new JSParser($this);
199 public static function minify($js, $filename=
'')
207 return $instance->min($js, $filename);
210 private function min($js, $filename)
214 $n = $this->parser->parse($js, $filename, 1);
219 echo $e->getMessage() .
"\n";
237 $noBlockGrouping =
true;
241 $childs = $n->treeNodes;
243 for ($c = 0, $i = 0, $j = count($childs); $i < $j; $i++)
245 $type = $childs[$i]->type;
261 $t =
',' . substr(
$t, 4);
277 if ($c > 1 && !$noBlockGrouping)
284 $s .=
'function' . ($n->name ?
' ' . $n->name :
'') .
'(';
286 for ($i = 0, $j = count(
$params); $i < $j; $i++)
288 $s .=
'){' . $this->
parseTree($n->body,
true) .
'}';
292 $s =
'if(' . $this->
parseTree($n->condition) .
')';
293 $thenPart = $this->
parseTree($n->thenPart);
294 $elsePart = $n->elsePart ? $this->
parseTree($n->elsePart) : null;
303 if ($thenPart !=
';' && $thenPart[0] !=
'{')
304 $thenPart =
'{' . $thenPart .
'}';
306 $s .= $thenPart .
'else';
309 if ($elsePart[0] !=
'{')
321 $s =
'switch(' . $this->
parseTree($n->discriminant) .
'){';
323 for ($i = 0, $j = count($cases); $i < $j; $i++)
331 $statement = $this->
parseTree($case->statements,
true);
344 $s =
'for(' . ($n->setup ? $this->
parseTree($n->setup) :
'')
345 .
';' . ($n->condition ? $this->parseTree($n->condition) :
'')
346 .
';' . ($n->update ? $this->parseTree($n->update) :
'') .
')';
356 $s =
'while(' . $this->
parseTree($n->condition) .
')';
376 $s =
'do{' . $this->
parseTree($n->body,
true) .
'}while(' . $this->
parseTree($n->condition) .
')';
381 $s = $n->value . ($n->label ?
' ' . $n->label :
'');
385 $s =
'try{' . $this->
parseTree($n->tryBlock,
true) .
'}';
386 $catchClauses = $n->catchClauses;
387 for ($i = 0, $j = count($catchClauses); $i < $j; $i++)
389 $t = $catchClauses[$i];
390 $s .=
'catch(' .
$t->varName . (
$t->guard ?
' if ' . $this->
parseTree(
$t->guard) :
'') .
'){' . $this->
parseTree(
$t->block,
true) .
'}';
392 if ($n->finallyBlock)
393 $s .=
'finally{' . $this->
parseTree($n->finallyBlock,
true) .
'}';
418 $s = $n->value .
' ';
419 $childs = $n->treeNodes;
420 for ($i = 0, $j = count($childs); $i < $j; $i++)
423 $s .= ($i ?
',' :
'') .
$t->name;
424 $u =
$t->initializer;
432 $left = $this->
parseTree($n->treeNodes[0]);
433 $right = $this->
parseTree($n->treeNodes[1]);
442 if ($this->
isWordChar($right[0]) || $right[0] ==
'\\')
450 $right = $this->
parseTree($n->treeNodes[0]);
454 if ($this->
isWordChar($right[0]) || $right[0] ==
'\\')
461 $s =
'void(' . $this->
parseTree($n->treeNodes[0]) .
')';
465 throw new Exception(
'NOT IMPLEMENTED: DEBUGGER');
471 $childs = $n->treeNodes;
472 for ($i = 0, $j = count($childs); $i < $j; $i++)
477 if ($expression = $n->expression)
482 $s = $n->label .
':' . $this->
parseTree($n->statement);
486 $childs = $n->treeNodes;
487 for ($i = 0, $j = count($childs); $i < $j; $i++)
488 $s .= ($i ?
',' :
'') . $this->
parseTree($childs[$i]);
510 $left = $this->
parseTree($n->treeNodes[0]);
511 $right = $this->
parseTree($n->treeNodes[1]);
513 switch ($n->treeNodes[1]->type)
521 $s = $left . $n->type .
' ' . $right;
526 if ($n->type ==
OP_PLUS && substr($left, -1) == $right[0])
528 $s = substr($left, 0, -1) . substr($right, 1);
534 $s = $left . $n->type . $right;
542 $s = $n->value . $this->
parseTree($n->treeNodes[0]);
548 $s = $this->
parseTree($n->treeNodes[0]) . $n->value;
550 $s = $n->value . $this->
parseTree($n->treeNodes[0]);
562 $this->isValidIdentifier(substr($n->treeNodes[1]->value, 1, -1))
564 $s .=
'.' . substr($n->treeNodes[1]->value, 1, -1);
566 $s .=
'[' . $this->
parseTree($n->treeNodes[1]) .
']';
570 $childs = $n->treeNodes;
571 for ($i = 0, $j = count($childs); $i < $j; $i++)
572 $s .= ($i ?
',' :
'') . $this->
parseTree($childs[$i]);
586 $childs = $n->treeNodes;
587 for ($i = 0, $j = count($childs); $i < $j; $i++)
589 $s .= ($i ?
',' :
'') . $this->
parseTree($childs[$i]);
596 $childs = $n->treeNodes;
597 for ($i = 0, $j = count($childs); $i < $j; $i++)
606 $this->isValidIdentifier(substr(
$t->treeNodes[0]->value, 1, -1))
608 $s .= substr(
$t->treeNodes[0]->value, 1, -1);
610 $s .=
$t->treeNodes[0]->value;
617 $s .=
' ' .
$t->name .
'(';
619 for ($i = 0, $j = count(
$params); $i < $j; $i++)
629 if (preg_match(
'/^([1-9]+)(0{3,})$/',
$s, $m))
630 $s = $m[1] .
'e' . strlen($m[2]);
640 $n->treeNodes[0]->type,
652 $s =
'(' . $this->
parseTree($n->treeNodes[0]) .
')';
657 throw new Exception(
'UNKNOWN TOKEN TYPE: ' . $n->type);
665 return preg_match(
'/^[a-zA-Z_][a-zA-Z0-9_]*$/', $string) && !in_array($string, $this->reserved);
670 return $char ==
'_' || $char ==
'$' || ctype_alnum($char);
682 '=' => 2,
'?' => 2,
':' => 2,
689 '==' => 9,
'!=' => 9,
'===' => 9,
'!==' => 9,
690 '<' => 10,
'<=' => 10,
'>=' => 10,
'>' => 10,
'in' => 10,
'instanceof' => 10,
691 '<<' => 11,
'>>' => 11,
'>>>' => 11,
692 '+' => 12,
'-' => 12,
693 '*' => 13,
'/' => 13,
'%' => 13,
694 'delete' => 14,
'void' => 14,
'typeof' => 14,
695 '!' => 14,
'~' => 14,
'U+' => 14,
'U-' => 14,
696 '++' => 15,
'--' => 15,
712 '==' => 2,
'!=' => 2,
'===' => 2,
'!==' => 2,
713 '<' => 2,
'<=' => 2,
'>=' => 2,
'>' => 2,
'in' => 2,
'instanceof' => 2,
714 '<<' => 2,
'>>' => 2,
'>>>' => 2,
716 '*' => 2,
'/' => 2,
'%' => 2,
717 'delete' => 1,
'void' => 1,
'typeof' => 1,
718 '!' => 1,
'~' => 1,
'U+' => 1,
'U-' => 1,
719 '++' => 1,
'--' => 1,
736 $this->t->init(
$s, $f, $l);
740 if (!$this->t->isDone())
741 throw $this->t->newSyntaxError(
'Syntax error');
750 $n->funDecls = $x->funDecls;
751 $n->varDecls = $x->varDecls;
756 $n->value = $this->minifier->parseTree($n);
759 $n->treeNodes = null;
772 array_push($x->stmtStack, $n);
775 $n->addNode($this->Statement($x));
777 array_pop($x->stmtStack);
793 $tt = $this->t->get();
814 $n =
new JSNode($this->t);
816 array_push($x->stmtStack, $n);
819 array_pop($x->stmtStack);
823 $n =
new JSNode($this->t);
828 $n->defaultIndex = -1;
830 array_push($x->stmtStack, $n);
839 if ($n->defaultIndex >= 0)
840 throw $this->t->newSyntaxError(
'More than one switch default');
843 $n2 =
new JSNode($this->t);
845 $n->defaultIndex = count($n->cases);
850 throw $this->t->newSyntaxError(
'Invalid switch case');
856 $n2->statements->addNode($this->
Statement($x));
858 array_push($n->cases, $n2);
861 array_pop($x->stmtStack);
865 $n =
new JSNode($this->t);
871 $x->inForLoopInit =
true;
881 $x->inForLoopInit =
false;
889 if (count($n2->treeNodes) != 1)
891 throw $this->t->SyntaxError(
892 'Invalid for..in left-hand side',
899 $n->iterator = $n2->treeNodes[0];
912 $n->setup = $n2 ? $n2 : null;
920 $n->body = $this->
nest($x, $n);
924 $n =
new JSNode($this->t);
927 $n->body = $this->
nest($x, $n);
931 $n =
new JSNode($this->t);
935 if (!$x->ecmaStrictMode)
947 $n =
new JSNode($this->t);
952 $n->label = $this->t->currentToken()->value;
963 throw $this->t->newSyntaxError(
'Label not found');
965 while ($ss[$i]->label != $label);
972 throw $this->t->newSyntaxError(
'Invalid ' . $tt);
977 $n->target = $ss[$i];
981 $n =
new JSNode($this->t);
982 $n->tryBlock = $this->
Block($x);
983 $n->catchClauses =
array();
987 $n2 =
new JSNode($this->t);
993 if ($x->ecmaStrictMode)
994 throw $this->t->newSyntaxError(
'Illegal catch guard');
996 if (count($n->catchClauses) && !end($n->catchClauses)->guard)
997 throw $this->t->newSyntaxError(
'Guarded catch after unguarded');
1007 $n2->block = $this->
Block($x);
1008 array_push($n->catchClauses, $n2);
1012 $n->finallyBlock = $this->Block($x);
1014 if (!count($n->catchClauses) && !$n->finallyBlock)
1015 throw $this->t->newSyntaxError(
'Invalid try statement');
1020 throw $this->t->newSyntaxError($tt .
' without preceding try');
1023 $n =
new JSNode($this->t);
1028 if (!$x->inFunction)
1029 throw $this->t->newSyntaxError(
'Invalid return');
1031 $n =
new JSNode($this->t);
1032 $tt = $this->t->peekOnSameLine();
1040 $n =
new JSNode($this->t);
1042 $n->body = $this->
nest($x, $n);
1052 $n =
new JSNode($this->t);
1056 $n =
new JSNode($this->t);
1062 $n->expression = null;
1068 $this->t->scanOperand =
false;
1069 $tt = $this->t->peek();
1070 $this->t->scanOperand =
true;
1073 $label = $this->t->currentToken()->value;
1074 $ss = $x->stmtStack;
1075 for ($i = count($ss) - 1; $i >= 0; --$i)
1077 if ($ss[$i]->label == $label)
1078 throw $this->t->newSyntaxError(
'Duplicate label');
1084 $n->statement = $this->
nest($x, $n);
1093 $n->end = $n->expression->end;
1097 if ($this->t->lineno == $this->t->currentToken()->lineno)
1099 $tt = $this->t->peekOnSameLine();
1101 throw $this->t->newSyntaxError(
'Missing ; before statement');
1111 $f =
new JSNode($this->t);
1117 $f->name = $this->t->currentToken()->value;
1118 elseif ($requireName)
1119 throw $this->t->newSyntaxError(
'Missing function identifier');
1122 $f->params =
array();
1127 throw $this->t->newSyntaxError(
'Missing formal parameter');
1129 array_push($f->params, $this->t->currentToken()->value);
1138 $f->body = $this->
Script($x2);
1141 $f->end = $this->t->currentToken()->end;
1143 $f->functionForm = $functionForm;
1145 array_push($x->funDecls, $f);
1152 $n =
new JSNode($this->t);
1158 $n2 =
new JSNode($this->t);
1159 $n2->name = $n2->value;
1163 if ($this->t->currentToken()->assignOp)
1164 throw $this->t->newSyntaxError(
'Invalid variable initialization');
1172 array_push($x->varDecls, $n2);
1181 $operators =
array();
1182 $operands =
array();
1185 $bl = $x->bracketLevel;
1186 $cl = $x->curlyLevel;
1187 $pl = $x->parenLevel;
1188 $hl = $x->hookLevel;
1190 while (($tt = $this->t->get()) !=
TOKEN_END)
1193 $x->bracketLevel == $bl &&
1194 $x->curlyLevel == $cl &&
1195 $x->parenLevel == $pl &&
1196 $x->hookLevel == $hl
1211 if ($this->t->scanOperand)
1214 while ( !empty($operators) &&
1215 $this->opPrecedence[end($operators)->type] > $this->opPrecedence[$tt]
1217 $this->
reduce($operators, $operands);
1219 array_push($operators,
new JSNode($this->t));
1222 $this->t->scanOperand =
true;
1229 array_push($operands, $n);
1236 throw $this->t->newSyntaxError(
'Invalid label');
1240 if ($this->t->scanOperand)
1244 while ( !empty($operators) &&
1245 $this->opPrecedence[end($operators)->
type] > $this->opPrecedence[$tt]
1247 $this->
reduce($operators, $operands);
1249 array_push($operators,
new JSNode($this->t));
1250 end($operands)->assignOp = $this->t->currentToken()->assignOp;
1251 $this->t->scanOperand =
true;
1258 if ($x->inForLoopInit && !$x->hookLevel &&
1259 !$x->bracketLevel && !$x->curlyLevel &&
1267 if ($tt ==
OP_COMMA && $x->hookLevel &&
1268 !$x->bracketLevel && !$x->curlyLevel &&
1287 if ($this->t->scanOperand)
1290 while ( !empty($operators) &&
1291 $this->opPrecedence[end($operators)->
type] >= $this->opPrecedence[$tt]
1293 $this->
reduce($operators, $operands);
1298 array_push($operands,
new JSNode($this->t,
OP_DOT, array_pop($operands),
new JSNode($this->t)));
1302 array_push($operators,
new JSNode($this->t));
1303 $this->t->scanOperand =
true;
1310 if (!$this->t->scanOperand)
1313 array_push($operators,
new JSNode($this->t));
1317 if ($this->t->scanOperand)
1319 array_push($operators,
new JSNode($this->t));
1324 $t = $this->t->tokens[($this->t->tokenIndex + $this->t->lookahead - 1) & 3];
1325 if (
$t &&
$t->lineno != $this->t->lineno)
1328 if (!empty($operators))
1331 while ($this->opPrecedence[end($operators)->type] > $this->opPrecedence[$tt])
1332 $this->
reduce($operators, $operands);
1335 $n =
new JSNode($this->t, $tt, array_pop($operands));
1337 array_push($operands, $n);
1342 if (!$this->t->scanOperand)
1346 $this->t->scanOperand =
false;
1351 if (!$this->t->scanOperand)
1354 array_push($operands,
new JSNode($this->t));
1355 $this->t->scanOperand =
false;
1360 if ($this->t->scanOperand)
1361 array_push($operators,
new JSNode($this->t));
1363 array_push($operands,
new JSNode($this->t));
1367 if ($this->t->scanOperand)
1387 array_push($operands, $n);
1388 $this->t->scanOperand =
false;
1394 $this->t->scanOperand =
true;
1400 if ($this->t->scanOperand || $x->bracketLevel == $bl)
1410 if (!$this->t->scanOperand)
1421 $tt = $this->t->get();
1422 $tv = $this->t->currentToken()->value;
1423 if (($tv ==
'get' || $tv ==
'set') && $this->t->peek() ==
TOKEN_IDENTIFIER)
1425 if ($x->ecmaStrictMode)
1426 throw $this->t->newSyntaxError(
'Illegal property accessor');
1437 $id =
new JSNode($this->t);
1441 if ($x->ecmaStrictMode)
1442 throw $this->t->newSyntaxError(
'Illegal trailing ,');
1446 throw $this->t->newSyntaxError(
'Invalid property name');
1459 array_push($operands, $n);
1460 $this->t->scanOperand =
false;
1465 if (!$this->t->scanOperand && $x->curlyLevel != $cl)
1466 throw new Exception(
'PANIC: right curly botch');
1470 if ($this->t->scanOperand)
1476 while ( !empty($operators) &&
1477 $this->opPrecedence[end($operators)->
type] > $this->opPrecedence[
KEYWORD_NEW]
1479 $this->
reduce($operators, $operands);
1484 $n = end($operators);
1485 $this->t->scanOperand =
true;
1488 if ($n && $n->type == KEYWORD_NEW)
1490 array_pop($operators);
1491 $n->addNode(array_pop($operands));
1498 array_push($operands, $n);
1499 $this->t->scanOperand =
false;
1503 if ($n && $n->type == KEYWORD_NEW)
1513 if ($this->t->scanOperand || $x->parenLevel == $pl)
1525 $n = end($operands);
1526 if ($n->treeNodes[1]->type !=
OP_COMMA)
1527 $n->treeNodes[1] =
new JSNode($this->t,
JS_LIST, $n->treeNodes[1]);
1529 $n->treeNodes[1]->type =
JS_LIST;
1543 if ($x->hookLevel != $hl)
1544 throw $this->t->newSyntaxError(
'Missing : in conditional expression');
1546 if ($x->parenLevel != $pl)
1547 throw $this->t->newSyntaxError(
'Missing ) in parenthetical');
1549 if ($x->bracketLevel != $bl)
1550 throw $this->t->newSyntaxError(
'Missing ] in index expression');
1552 if ($this->t->scanOperand)
1553 throw $this->t->newSyntaxError(
'Missing operand');
1556 $this->t->scanOperand =
true;
1559 while (count($operators))
1560 $this->
reduce($operators, $operands);
1562 return array_pop($operands);
1575 private function nest($x, $node, $end =
false)
1577 array_push($x->stmtStack, $node);
1578 $n = $this->statement($x);
1579 array_pop($x->stmtStack);
1582 $this->t->mustMatch($end);
1587 private function reduce(&$operators, &$operands)
1589 $n = array_pop($operators);
1591 $arity = $this->opArity[$op];
1592 $c = count($operands);
1598 $left = $operands[$c - 2];
1599 if ($left->type == $op)
1601 $right = array_pop($operands);
1602 $left->addNode($right);
1610 $a = array_splice($operands, $c - $arity);
1611 for ($i = 0; $i < $arity; $i++)
1612 $n->addNode($a[$i]);
1615 $te = $this->t->currentToken()->end;
1619 array_push($operands, $n);
1659 if ($token =
$t->currentToken())
1662 $this->value = $token->value;
1663 $this->lineno = $token->lineno;
1664 $this->start = $token->start;
1665 $this->end = $token->end;
1670 $this->lineno =
$t->lineno;
1673 if (($numargs = func_num_args()) > 2)
1675 $args = func_get_args();
1676 for ($i = 2; $i < $numargs; $i++)
1689 if (isset($this->
$name))
1690 return $this->$name;
1699 if ($node->start < $this->start)
1700 $this->start = $node->start;
1701 if ($this->end < $node->end)
1702 $this->end = $node->end;
1705 $this->treeNodes[] = $node;
1725 'case',
'catch',
'const',
'continue',
1726 'debugger',
'default',
'delete',
'do',
1728 'false',
'finally',
'for',
'function',
1729 'if',
'in',
'instanceof',
1733 'this',
'throw',
'true',
'try',
'typeof',
1739 ';',
',',
'?',
':',
'||',
'&&',
'|',
'^',
1740 '&',
'===',
'==',
'=',
'!==',
'!=',
'<<',
'<=',
1741 '<',
'>>>',
'>>',
'>=',
'>',
'++',
'--',
'+',
1742 '-',
'*',
'/',
'%',
'!',
'~',
'.',
'[',
1743 ']',
'{',
'}',
'(',
')',
'@*/'
1746 private $assignOps =
array(
'|',
'^',
'&',
'<<',
'>>',
'>>>',
'+',
'-',
'*',
'/',
'%');
1751 $this->opRegExp =
'#^(' . implode(
'|', array_map(
'preg_quote', $this->opTypeNames)) .
')#';
1761 $this->tokens =
array();
1762 $this->tokenIndex = 0;
1763 $this->lookahead = 0;
1764 $this->scanNewlines =
false;
1765 $this->scanOperand =
true;
1771 return substr($this->
source, $this->cursor, $chunksize);
1773 return substr($this->
source, $this->cursor);
1783 return $this->
get() == $tt || $this->
unget();
1788 if (!$this->
match($tt))
1789 throw $this->
newSyntaxError(
'Unexpected token; token ' . $tt .
' expected');
1796 if ($this->lookahead)
1799 if ($this->scanNewlines && $next->lineno != $this->lineno)
1815 $this->scanNewlines =
true;
1816 $tt = $this->
peek();
1817 $this->scanNewlines =
false;
1824 if (!empty($this->tokens))
1828 public function get($chunksize = 1000)
1830 while($this->lookahead)
1833 $this->tokenIndex = ($this->tokenIndex + 1) & 3;
1836 return $token->type;
1839 $conditional_comment =
false;
1844 $input = $this->
getInput($chunksize);
1847 $re = $this->scanNewlines ?
'/^[ \r\t]+/' :
'/^\s+/';
1848 if (preg_match($re, $input, $match))
1850 $spaces = $match[0];
1851 $spacelen = strlen($spaces);
1852 $this->cursor += $spacelen;
1853 if (!$this->scanNewlines)
1854 $this->lineno += substr_count($spaces,
"\n");
1856 if ($spacelen == $chunksize)
1859 $input = $this->
getInput($chunksize);
1860 if ($input ==
'' || $input[0] !=
'/')
1865 if (!preg_match(
'/^\/(?:\*(@(?:cc_on|if|elif|else|end))?.*?\*\/|\/[^\n]*)/s', $input, $match))
1876 if (!empty($match[1]))
1878 $match[0] =
'/*' . $match[1];
1879 $conditional_comment =
true;
1884 $this->cursor += strlen($match[0]);
1885 $this->lineno += substr_count($match[0],
"\n");
1894 elseif ($conditional_comment)
1904 if (($input[1] ==
'x' || $input[1] ==
'X') && preg_match(
'/^0x[0-9a-f]+/i', $input, $match))
1911 case '1':
case '2':
case '3':
case '4':
case '5':
1912 case '6':
case '7':
case '8':
case '9':
1914 preg_match(
'/^\d+(?:\.\d*)?(?:[eE][-+]?\d+)?/', $input, $match);
1919 if (preg_match(
'/^\'(?:[^\\\\\'\r\n]++|\\\\(?:.|\r?\n))*\'/', $input, $match))
1926 return $this->
get(null);
1933 if (preg_match(
'/^"(?:[^\\\\"\r\n]++|\\\\(?:.|\r?\n))*"/', $input, $match))
1940 return $this->
get(null);
1947 if ($this->scanOperand && preg_match(
'/^\/((?:\\\\.|\[(?:\\\\.|[^\]])*\]|[^\/])+)\/([gimy]*)/', $input, $match))
1966 preg_match($this->opRegExp, $input, $match);
1968 if (in_array($op, $this->assignOps) && $input[strlen($op)] ==
'=')
1976 if ($this->scanOperand)
1988 if (preg_match(
'/^\.\d+(?:[eE][-+]?\d+)?/', $input, $match))
2007 $match =
array($input[0]);
2013 if (substr($input, 0, 3) ==
'@*/')
2015 $match =
array(
'@*/');
2023 if ($this->scanNewlines)
2025 $match =
array(
"\n");
2036 if (!preg_match(
'/^[$\w]+(?=[\s\/\|\^\&<>\+\-\*%=!.;,\?:~\[\]\{\}\(\)@])/', $input, $match))
2041 $identifierStartChars =
"\\p{L}\\p{Nl}" . # UnicodeLetter
2044 $identifierPartChars = $identifierStartChars .
2045 "\\p{Mn}\\p{Mc}" . # UnicodeCombiningMark
2046 "\\p{Nd}" . # UnicodeDigit
2047 "\\p{Pc}"; # UnicodeConnectorPunctuation
2048 $unicodeEscape =
"\\\\u[0-9A-F-a-f]{4}";
2049 $identifierRegex =
"/^" .
2050 "(?:[$identifierStartChars]|$unicodeEscape)" .
2051 "(?:[$identifierPartChars]|$unicodeEscape)*" .
2053 if (preg_match($identifierRegex, $input, $match))
2055 if (strpos($match[0],
'\\') !==
false) {
2058 $decoded = preg_replace_callback(
'/\\\\u([0-9A-Fa-f]{4})/',
2059 array(__CLASS__,
'unicodeEscapeCallback'),
2064 if (!preg_match(
"/^[$identifierStartChars][$identifierPartChars]*$/u", $decoded)) {
2071 if (in_array($decoded, $this->keywords)) {
2085 $this->tokenIndex = ($this->tokenIndex + 1) & 3;
2087 if (!isset($this->tokens[$this->tokenIndex]))
2088 $this->tokens[$this->tokenIndex] =
new JSToken();
2094 $token->assignOp = $op;
2098 $token->value = $match[0];
2099 $this->cursor += strlen($match[0]);
2109 if (++$this->lookahead == 4)
2112 $this->tokenIndex = ($this->tokenIndex - 1) & 3;
2117 return new Exception(
'Parse error: ' . $m .
' in file \'' . $this->filename .
'\' on line ' . $this->lineno);
2120 public static function unicodeEscapeCallback($m)
2122 return html_entity_decode('&#x
' . $m[1]. ';
', ENT_QUOTES, 'UTF-8
');
the array() calling protocol came about after MediaWiki 1.4rc1.
init($source, $filename= '', $lineno=1)
__construct($minifier=null)
div flags Integer display flags(NO_ACTION_LINK, NO_EXTRA_USER_LINKS) 'LogException'returning false will NOT prevent logging $e
const TOKEN_CONDCOMMENT_END
parseTree($n, $noBlockGrouping=false)
Expression($x, $stop=false)
nest($x, $node, $end=false)
FunctionDefinition($x, $requireName, $functionForm)
isValidIdentifier($string)
injection txt This is an overview of how MediaWiki makes use of dependency injection The design described here grew from the discussion of RFC T384 The term dependency this means that anything an object needs to operate should be injected from the the object itself should only know narrow no concrete implementation of the logic it relies on The requirement to inject everything typically results in an architecture that based on two main types of and essentially stateless service objects that use other service objects to operate on the value objects As of the beginning MediaWiki is only starting to use the DI approach Much of the code still relies on global state or direct resulting in a highly cyclical dependency which acts as the top level factory for services in MediaWiki which can be used to gain access to default instances of various services MediaWikiServices however also allows new services to be defined and default services to be redefined Services are defined or redefined by providing a callback the instantiator that will return a new instance of the service When it will create an instance of MediaWikiServices and populate it with the services defined in the files listed by thereby bootstrapping the DI framework Per $wgServiceWiringFiles lists includes ServiceWiring php
This document describes the state of Postgres support in and is fairly well maintained The main code is very well while extensions are very hit and miss it is probably the most supported database after MySQL Much of the work in making MediaWiki database agnostic came about through the work of creating Postgres as and are nearing end of but without copying over all the usage comments General notes on the but these can almost always be programmed around *Although Postgres has a true BOOLEAN type
null for the local wiki Added should default to null in handler for backwards compatibility add a value to it if you want to add a cookie that have to vary cache options can modify prev or next refreshes the diff cache allow viewing deleted revs difference engine object to be used for diff source
I won t presume to tell you how to I m just describing the methods I chose to use for myself If you do choose to follow these it will probably be easier for you to collaborate with others on the but if you want to contribute without by all means do which work well I also use K &R brace matching style I know that s a religious issue for so if you want to use a style that puts opening braces on the next line
We ve cleaned up the code here by removing clumps of infrequently used code and moving them off somewhere else It s much easier for someone working with this code to see what s _really_ going on
const TOKEN_CONDCOMMENT_START
do that in ParserLimitReportFormat instead use this to modify the parameters of the image and a DIV can begin in one section and end in another Make sure your code can handle that case gracefully See the EditSectionClearerLink extension for an example zero but section is usually empty its values are the globals values before the output is cached one of or reset my talk my contributions etc etc otherwise the built in rate limiting checks are if enabled allows for interception of redirect as a string mapping parameter names to values & $type
reduce(&$operators, &$operands)
static minify($js, $filename='')
Allows to change the fields on the form that will be generated $name