Skip to content

Commit 97d273e

Browse files
authored
Fix js compactor issues with regex etc.
This addresses the points mentioned in dokuwiki/dokuwiki#3645 Original commit: dokuwiki/dokuwiki@1c92adb
1 parent b4d648d commit 97d273e

File tree

1 file changed

+59
-12
lines changed

1 file changed

+59
-12
lines changed

lib/exe/js.php

Lines changed: 59 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -186,10 +186,12 @@ function js_load($file){
186186

187187
if($ifile[0] != '/') $ifile = dirname($file).'/'.$ifile;
188188

189+
$idata = '';
189190
if(file_exists($ifile)){
190-
$idata = io_readFile($ifile);
191-
}else{
192-
$idata = '';
191+
$ismin = (substr($ifile,-7) == '.min.js');;
192+
if($ismin) $idata .= "\n/* BEGIN NOCOMPRESS */\n";
193+
$idata .= io_readFile($ifile);
194+
if($ismin) $idata .= "\n/* END NOCOMPRESS */\n";
193195
}
194196
$data = str_replace($match[0],$idata,$data);
195197
}
@@ -347,14 +349,13 @@ function js_compress($s){
347349
$result = ''; // we store the final result here
348350

349351
// items that don't need spaces next to them
350-
$chars = "^&|!+\-*\/%=\?:;,{}()<>% \t\n\r'\"[]";
352+
$chars = "^&|!+\-*\/%=\?:;,{}()<>% \t\n\r'\"`[]~^";
351353

352354
// items which need a space if the sign before and after whitespace is equal.
353355
// E.g. '+ ++' may not be compressed to '+++' --> syntax error.
354-
$ops = "+-";
355-
356-
$regex_starters = array("(", "=", "[", "," , ":", "!", "&", "|");
356+
$ops = "+-/";
357357

358+
$regex_starters = array("(", "=", "<", ">", "?", "[", "{", ",", ";", ":", "!", "&", "|", "+", "-", "%", "~", "^", "return", "yield", "else", "throw", "await");
358359
$whitespaces_chars = array(" ", "\t", "\n", "\r", "\0", "\x0B");
359360

360361
while($i < $slen){
@@ -374,8 +375,22 @@ function js_compress($s){
374375

375376
// check if this is a NOCOMPRESS comment
376377
if(substr($s, $i, $endC+2-$i) == '/* BEGIN NOCOMPRESS */'){
377-
$endNC = strpos($s, '/* END NOCOMPRESS */', $endC+2);
378-
if($endNC === false) trigger_error('Found invalid NOCOMPRESS comment', E_USER_ERROR);
378+
// take nested NOCOMPRESS comments into account
379+
$depth = 0;
380+
$nextNC = $endC;
381+
do {
382+
$beginNC = strpos($s, '/* BEGIN NOCOMPRESS */', $nextNC+2);
383+
$endNC = strpos($s, '/* END NOCOMPRESS */', $nextNC+2);
384+
385+
if ($endNC === false) trigger_error('Found invalid NOCOMPRESS comment', E_USER_ERROR);
386+
if ($beginNC !== false && $beginNC < $endNC) {
387+
$depth++;
388+
$nextNC = $beginNC;
389+
} else {
390+
$depth--;
391+
$nextNC = $endNC;
392+
}
393+
} while ($depth >= 0);
379394

380395
// verbatim copy contents, trimming but putting it on its own line
381396
$result .= "\n".trim(substr($s, $i + 22, $endNC - ($i + 22)))."\n"; // BEGIN comment = 22 chars
@@ -401,13 +416,27 @@ function js_compress($s){
401416
while(in_array($s[$i-$j], $whitespaces_chars)){
402417
$j = $j + 1;
403418
}
404-
if( in_array($s[$i-$j], $regex_starters) ){
419+
if (current(array_filter(
420+
$regex_starters,
421+
function($e) use ($s, $i, $j) {
422+
$len = strlen($e);
423+
$idx = $i-$j+1-$len;
424+
return substr($s, $idx, $len) === $e;
425+
}
426+
))) {
405427
// yes, this is an re
406428
// now move forward and find the end of it
407429
$j = 1;
408-
while($s[$i+$j] != '/'){
430+
// we set this flag when inside a character class definition, enclosed by brackets [] where '/' does not terminate the re
431+
$ccd = false;
432+
while($ccd || $s[$i+$j] != '/'){
409433
if($s[$i+$j] == '\\') $j = $j + 2;
410-
else $j++;
434+
else {
435+
$j++;
436+
// check if we entered/exited a character class definition and set flag accordingly
437+
if ($s[$i+$j-1] == '[') $ccd = true;
438+
else if ($s[$i+$j-1] == ']') $ccd = false;
439+
}
411440
}
412441
$result .= substr($s,$i,$j+1);
413442
$i = $i + $j + 1;
@@ -451,6 +480,24 @@ function js_compress($s){
451480
continue;
452481
}
453482

483+
// backtick strings
484+
if($ch == "`"){
485+
$j = 1;
486+
while( ($i+$j < $slen) && $s[$i+$j] != "`" ){
487+
if( $s[$i+$j] == '\\' && ($s[$i+$j+1] == "`" || $s[$i+$j+1] == '\\') ){
488+
$j += 2;
489+
}else{
490+
$j += 1;
491+
}
492+
}
493+
$string = substr($s,$i,$j+1);
494+
// remove multiline markers:
495+
$string = str_replace("\\\n",'',$string);
496+
$result .= $string;
497+
$i = $i + $j + 1;
498+
continue;
499+
}
500+
454501
// whitespaces
455502
if( $ch == ' ' || $ch == "\r" || $ch == "\n" || $ch == "\t" ){
456503
$lch = substr($result,-1);

0 commit comments

Comments
 (0)