Skip to content

Commit

Permalink
Fix issue #385 - for(;;) without body but containig closures inside b…
Browse files Browse the repository at this point in the history
…rackets.
  • Loading branch information
Simon committed Mar 21, 2022
1 parent 37c14b9 commit dfae066
Show file tree
Hide file tree
Showing 2 changed files with 26 additions and 1 deletion.
13 changes: 12 additions & 1 deletion src/JS.php
Original file line number Diff line number Diff line change
Expand Up @@ -415,8 +415,19 @@ protected function stripWhitespace($content)
* to be the for-loop's body... Same goes for while loops.
* I'm going to double that semicolon (if any) so after the next line,
* which strips semicolons here & there, we're still left with this one.
* Note the special recursive construct in the three inner parts of the for:
* (\{([^\{\}]*(?-2))*[^\{\}]*\})? - it is intended to match inline
* functions bodies, e.g.: i<arr.map(function(e){return e}).length.
* Also note that the construct is applied only once and multiplied
* for each part of the for, otherwise it risks a catastrophic backtracking.
* The limitation is that it will not allow closures in more than one
* of the three parts for a specific for() case.
* REGEX throwing catastrophic backtracking: $content = preg_replace('/(for\([^;\{]*(\{([^\{\}]*(?-2))*[^\{\}]*\})?[^;\{]*;[^;\{]*(\{([^\{\}]*(?-2))*[^\{\}]*\})?[^;\{]*;[^;\{]*(\{([^\{\}]*(?-2))*[^\{\}]*\})?[^;\{]*\));(\}|$)/s', '\\1;;\\8', $content);
*/
$content = preg_replace('/(for\([^;\{]*;[^;\{]*;[^;\{]*\));(\}|$)/s', '\\1;;\\2', $content);
$content = preg_replace('/(for\([^;\{]*(\{([^\{\}]*(?-2))*[^\{\}]*\})?[^;\{]*;[^;\{]*;[^;\{]*\));(\}|$)/s', '\\1;;\\4', $content);
$content = preg_replace('/(for\([^;\{]*;[^;\{]*(\{([^\{\}]*(?-2))*[^\{\}]*\})?[^;\{]*;[^;\{]*\));(\}|$)/s', '\\1;;\\4', $content);
$content = preg_replace('/(for\([^;\{]*;[^;\{]*;[^;\{]*(\{([^\{\}]*(?-2))*[^\{\}]*\})?[^;\{]*\));(\}|$)/s', '\\1;;\\4', $content);

$content = preg_replace('/(for\([^;\{]+\s+in\s+[^;\{]+\));(\}|$)/s', '\\1;;\\2', $content);
/*
* Below will also keep `;` after a `do{}while();` along with `while();`
Expand Down
14 changes: 14 additions & 0 deletions tests/js/JSTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -1307,6 +1307,20 @@ function someOtherFunction() {
'/^\[(x| )\](?=\s)/i',
);

// https://github.com/matthiasmullie/minify/issues/385
$tests[] = array(
'if (l !== 3) { for (var V = w.map(function(e) { return e }).length; l < V; V++); } else var C = 3;',
'if(l!==3){for(var V=w.map(function(e){return e}).length;l<V;V++);}else var C=3'
);
$tests[] = array(
'if (l !== 3) { for (var V = w.map(function(e) { if(e > 5) { return e-5; } return e; }).length; l < V; V++); } else var C = 3;',
'if(l!==3){for(var V=w.map(function(e){if(e>5){return e-5}return e}).length;l<V;V++);}else var C=3'
);
$tests[] = array(
'if (l !== 3) { for (var V = w.length; l < V; V+=w.map(function(e) { if(e > 5) { return e-5; } return e; }).length); } else var C = 3;',
'if(l!==3){for(var V=w.length;l<V;V+=w.map(function(e){if(e>5){return e-5}return e}).length);}else var C=3'
);

// known minified files to help doublecheck changes in places not yet
// anticipated in these tests
$files = glob(__DIR__.'/sample/minified/*.js');
Expand Down

0 comments on commit dfae066

Please sign in to comment.