1
0
mirror of https://github.com/mrclay/minify.git synced 2025-08-22 13:42:48 +02:00

Fixes #73: Handles regex literals directly following return/typeof

This commit is contained in:
Steve Clay
2013-09-20 20:09:51 -04:00
parent db7fe24493
commit 681885762d
4 changed files with 61 additions and 29 deletions

View File

@@ -272,23 +272,33 @@ class JSMin {
// we obviously aren't dividing // we obviously aren't dividing
return true; return true;
} }
if ($this->a === ' ' || $this->a === "\n") {
$length = strlen($this->output); // we have to check for a preceding keyword, and we don't need to pattern
if ($length < 2) { // weird edge case // match over the whole output.
return true; $recentOutput = substr($this->output, -10);
// check if return/typeof directly precede a pattern without a space
foreach (array('return', 'typeof') as $keyword) {
if ($this->a !== substr($keyword, -1)) {
// certainly wasn't keyword
continue;
} }
// you can't divide a keyword if (preg_match("~(^|[\\s\\S])" . substr($keyword, 0, -1) . "$~", $recentOutput, $m)) {
if (preg_match('/(?:case|else|in|return|typeof)$/', $this->output, $m)) { if ($m[1] === '' || !$this->isAlphaNum($m[1])) {
if ($this->output === $m[0]) { // odd but could happen
return true;
}
// make sure it's a keyword, not end of an identifier
$charBeforeKeyword = substr($this->output, $length - strlen($m[0]) - 1, 1);
if (! $this->isAlphaNum($charBeforeKeyword)) {
return true; return true;
} }
} }
} }
// check all keywords
if ($this->a === ' ' || $this->a === "\n") {
if (preg_match('~(^|[\\s\\S])(?:case|else|in|return|typeof)$~', $recentOutput, $m)) {
if ($m[1] === '' || !$this->isAlphaNum($m[1])) {
return true;
}
}
}
return false; return false;
} }

View File

@@ -18,3 +18,7 @@ x = / [/] /;
(2) (2)
/ foo; / foo;
function(){return/foo/};
function(){return typeof/foo/};

View File

@@ -1,3 +1,3 @@
function testIssue74(){return /'/;} function testIssue74(){return /'/;}
!function(s){return /^[£$€?.]/.test(s);}();typeof !function(s){return /^[£$€?.]/.test(s);}();typeof
/ ' /;x=/ [/] /;1/foo;(2)/foo; / ' /;x=/ [/] /;1/foo;(2)/foo;function(){return/foo/};function(){return typeof/foo/};

View File

@@ -55,21 +55,39 @@ function test_JSMin()
echo "\n---Output: " .countBytes($minOutput). " bytes\n\n{$minOutput}\n\n"; echo "\n---Output: " .countBytes($minOutput). " bytes\n\n{$minOutput}\n\n";
echo "---Expected: " .countBytes($minExpected). " bytes\n\n{$minExpected}\n\n"; echo "---Expected: " .countBytes($minExpected). " bytes\n\n{$minExpected}\n\n";
echo "---Source: " .countBytes($src). " bytes\n\n{$src}\n\n\n"; echo "---Source: " .countBytes($src). " bytes\n\n{$src}\n\n\n";
// only test exceptions on this page
test_JSMin_exception('"Hello'
,'Unterminated String'
,'JSMin_UnterminatedStringException'
,"JSMin: Unterminated String at byte 6: \"Hello");
test_JSMin_exception("return /regexp\n}"
,'Unterminated RegExp'
,'JSMin_UnterminatedRegExpException'
,"JSMin: Unterminated RegExp at byte 15: /regexp\n");
test_JSMin_exception("/* Comment "
,'Unterminated Comment'
,'JSMin_UnterminatedCommentException'
,"JSMin: Unterminated comment at byte 11: /* Comment ");
} }
test_JSMin_exception('"Hello'
,'Unterminated String'
,'JSMin_UnterminatedStringException'
,"JSMin: Unterminated String at byte 6: \"Hello");
test_JSMin_exception("return /regexp\n}"
,'Unterminated RegExp'
,'JSMin_UnterminatedRegExpException'
,"JSMin: Unterminated RegExp at byte 15: /regexp\n");
test_JSMin_exception("return/regexp\n}"
,'Unterminated RegExp'
,'JSMin_UnterminatedRegExpException'
,"JSMin: Unterminated RegExp at byte 14: /regexp\n");
test_JSMin_exception(";return/regexp\n}"
,'Unterminated RegExp'
,'JSMin_UnterminatedRegExpException'
,"JSMin: Unterminated RegExp at byte 15: /regexp\n");
test_JSMin_exception(";return /regexp\n}"
,'Unterminated RegExp'
,'JSMin_UnterminatedRegExpException'
,"JSMin: Unterminated RegExp at byte 16: /regexp\n");
test_JSMin_exception("typeof/regexp\n}"
,'Unterminated RegExp'
,'JSMin_UnterminatedRegExpException'
,"JSMin: Unterminated RegExp at byte 14: /regexp\n");
test_JSMin_exception("/* Comment "
,'Unterminated Comment'
,'JSMin_UnterminatedCommentException'
,"JSMin: Unterminated comment at byte 11: /* Comment ");
} }
function test_JSMin_exception($js, $label, $expClass, $expMessage) { function test_JSMin_exception($js, $label, $expClass, $expMessage) {
@@ -82,7 +100,7 @@ function test_JSMin_exception($js, $label, $expClass, $expMessage) {
} }
$passed = assertTrue($eClass === $expClass && $eMsg === $expMessage, $passed = assertTrue($eClass === $expClass && $eMsg === $expMessage,
'JSMin : throw on ' . $label); 'JSMin : throw on ' . $label);
if (! $passed && __FILE__ === realpath($_SERVER['SCRIPT_FILENAME'])) { if (! $passed && isset($e) && (__FILE__ === realpath($_SERVER['SCRIPT_FILENAME']))) {
echo "\n ---" , $e, "\n\n"; echo "\n ---" , $e, "\n\n";
} }
} }