Skip to content

Commit

Permalink
Fixes Gcode issue 256, improve readability
Browse files Browse the repository at this point in the history
  • Loading branch information
mrclay committed Mar 29, 2013
1 parent faec60f commit c95d6ba
Show file tree
Hide file tree
Showing 4 changed files with 73 additions and 22 deletions.
69 changes: 51 additions & 18 deletions min/lib/JSMin.php
Expand Up @@ -116,8 +116,8 @@ public function min()
// determine next command
$command = self::ACTION_KEEP_A; // default
if ($this->a === ' ') {
if (($this->lastByteOut === '+' || $this->lastByteOut === '-')
&& ($this->b === $this->lastByteOut)) {
if (($this->lastByteOut === '+' || $this->lastByteOut === '-')
&& ($this->b === $this->lastByteOut)) {
// Don't delete this space. If we do, the addition/subtraction
// could be parsed as a post-increment
} elseif (! $this->isAlphaNum($this->b)) {
Expand All @@ -129,13 +129,13 @@ public function min()
// in case of mbstring.func_overload & 2, must check for null b,
// otherwise mb_strpos will give WARNING
} elseif ($this->b === null
|| (false === strpos('{[(+-', $this->b)
|| (false === strpos('{[(+-!~', $this->b)
&& ! $this->isAlphaNum($this->b))) {
$command = self::ACTION_DELETE_A;
}
} elseif (! $this->isAlphaNum($this->a)) {
if ($this->b === ' '
|| ($this->b === "\n"
|| ($this->b === "\n"
&& (false === strpos('}])+-"\'', $this->a)))) {
$command = self::ACTION_DELETE_A_B;
}
Expand All @@ -160,7 +160,7 @@ public function min()
*/
protected function action($command)
{
if ($command === self::ACTION_DELETE_A_B
if ($command === self::ACTION_DELETE_A_B
&& $this->b === ' '
&& ($this->a === '+' || $this->a === '-')) {
// Note: we're at an addition/substraction operator; the inputIndex
Expand All @@ -175,20 +175,20 @@ protected function action($command)
$this->output .= $this->a;
$this->lastByteOut = $this->a;

// fallthrough
// fallthrough intentional
case self::ACTION_DELETE_A:
$this->a = $this->b;
if ($this->a === "'" || $this->a === '"') { // string literal
$str = $this->a; // in case needed for exception
while (true) {
for(;;) {
$this->output .= $this->a;
$this->lastByteOut = $this->a;

$this->a = $this->get();
$this->a = $this->get();
if ($this->a === $this->b) { // end quote
break;
}
if (ord($this->a) <= self::ORD_LF) {
if ($this->isEOF($this->a)) {
throw new JSMin_UnterminatedStringException(
"JSMin: Unterminated String at byte "
. $this->inputIndex . ": {$str}");
Expand All @@ -198,27 +198,49 @@ protected function action($command)
$this->output .= $this->a;
$this->lastByteOut = $this->a;

$this->a = $this->get();
$this->a = $this->get();
$str .= $this->a;
}
}
}
// fallthrough

// fallthrough intentional
case self::ACTION_DELETE_A_B:
$this->b = $this->next();
if ($this->b === '/' && $this->isRegexpLiteral()) { // RegExp literal
if ($this->b === '/' && $this->isRegexpLiteral()) {
$this->output .= $this->a . $this->b;
$pattern = '/'; // in case needed for exception
while (true) {
$pattern = '/'; // keep entire pattern in case we need to report it in the exception
for(;;) {
$this->a = $this->get();
$pattern .= $this->a;
if ($this->a === '[') {
for(;;) {
$this->output .= $this->a;
$this->a = $this->get();
$pattern .= $this->a;
if ($this->a === ']') {
break;
}
if ($this->a === '\\') {
$this->output .= $this->a;
$this->a = $this->get();
$pattern .= $this->a;
}
if ($this->isEOF($this->a)) {
throw new JSMin_UnterminatedRegExpException(
"JSMin: Unterminated set in RegExp at byte "
. $this->inputIndex .": {$pattern}");
}
}
}

if ($this->a === '/') { // end pattern
break; // while (true)
} elseif ($this->a === '\\') {
$this->output .= $this->a;
$this->a = $this->get();
$pattern .= $this->a;
} elseif (ord($this->a) <= self::ORD_LF) {
$this->a = $this->get();
$pattern .= $this->a;
} elseif ($this->isEOF($this->a)) {
throw new JSMin_UnterminatedRegExpException(
"JSMin: Unterminated RegExp at byte "
. $this->inputIndex .": {$pattern}");
Expand Down Expand Up @@ -286,6 +308,17 @@ protected function get()
return $c;
}

/**
* Does $a indicate end of input?
*
* @param string $a
* @return bool
*/
protected function isEOF($a)
{
return ord($a) <= self::ORD_LF;
}

/**
* Get next char. If is ctrl character, translate to a space or newline.
*
Expand Down Expand Up @@ -336,7 +369,7 @@ protected function multipleLineComment()
{
$this->get();
$comment = '';
while (true) {
for(;;) {
$get = $this->get();
if ($get === '*') {
if ($this->peek() === '/') { // end of comment reached
Expand Down
5 changes: 5 additions & 0 deletions min_unit_tests/_test_files/js/issue256.js
@@ -0,0 +1,5 @@
!function(){}(window)

!function(){}(window)

x = / [/] /;
3 changes: 3 additions & 0 deletions min_unit_tests/_test_files/js/issue256.min.js
@@ -0,0 +1,3 @@
!function(){}(window)
!function(){}(window)
x=/ [/] /;
18 changes: 14 additions & 4 deletions min_unit_tests/test_JSMin.php
Expand Up @@ -8,7 +8,7 @@ function test_JSMin()
$src = file_get_contents($thisDir . '/_test_files/js/before.js');
$minExpected = file_get_contents($thisDir . '/_test_files/js/before.min.js');
$minOutput = JSMin::minify($src);
$passed = assertTrue($minExpected == $minOutput, 'JSMin : Overall');
assertTrue($minExpected == $minOutput, 'JSMin : Overall');
if (__FILE__ === realpath($_SERVER['SCRIPT_FILENAME'])) {
echo "\n---Output: " .countBytes($minOutput). " bytes\n\n{$minOutput}\n\n";
echo "---Expected: " .countBytes($minExpected). " bytes\n\n{$minExpected}\n\n";
Expand All @@ -18,7 +18,17 @@ function test_JSMin()
$src = file_get_contents($thisDir . '/_test_files/js/issue144.js');
$minExpected = file_get_contents($thisDir . '/_test_files/js/issue144.min.js');
$minOutput = JSMin::minify($src);
$passed = assertTrue($minExpected == $minOutput, 'JSMin : Handle "+ ++a" syntax (Issue 144)');
assertTrue($minExpected == $minOutput, 'JSMin : Handle "+ ++a" syntax (Issue 144)');
if (__FILE__ === realpath($_SERVER['SCRIPT_FILENAME'])) {
echo "\n---Output: " .countBytes($minOutput). " bytes\n\n{$minOutput}\n\n";
echo "---Expected: " .countBytes($minExpected). " bytes\n\n{$minExpected}\n\n";
echo "---Source: " .countBytes($src). " bytes\n\n{$src}\n\n\n";
}

$src = file_get_contents($thisDir . '/_test_files/js/issue256.js');
$minExpected = file_get_contents($thisDir . '/_test_files/js/issue256.min.js');
$minOutput = JSMin::minify($src);
assertTrue($minExpected == $minOutput, 'JSMin : Handle \n!function()... (Issue 256)');
if (__FILE__ === realpath($_SERVER['SCRIPT_FILENAME'])) {
echo "\n---Output: " .countBytes($minOutput). " bytes\n\n{$minOutput}\n\n";
echo "---Expected: " .countBytes($minExpected). " bytes\n\n{$minExpected}\n\n";
Expand All @@ -29,7 +39,7 @@ function test_JSMin()
$src = file_get_contents($thisDir . '/_test_files/js/issue132.js');
$minExpected = file_get_contents($thisDir . '/_test_files/js/issue132.min.js');
$minOutput = JSMin::minify($src);
$passed = assertTrue($minExpected == $minOutput, 'JSMin : mbstring.func_overload shouldn\'t cause failure (Issue 132)');
assertTrue($minExpected == $minOutput, 'JSMin : mbstring.func_overload shouldn\'t cause failure (Issue 132)');
if (__FILE__ === realpath($_SERVER['SCRIPT_FILENAME'])) {
echo "\n---Output: " .countBytes($minOutput). " bytes\n\n{$minOutput}\n\n";
echo "---Expected: " .countBytes($minExpected). " bytes\n\n{$minExpected}\n\n";
Expand All @@ -40,7 +50,7 @@ function test_JSMin()
$src = file_get_contents($thisDir . '/_test_files/js/issue74.js');
$minExpected = file_get_contents($thisDir . '/_test_files/js/issue74.min.js');
$minOutput = JSMin::minify($src);
$passed = assertTrue($minExpected == $minOutput, 'JSMin : Quotes in RegExp literals (Issue 74)');
assertTrue($minExpected == $minOutput, 'JSMin : Quotes in RegExp literals (Issue 74)');
if (__FILE__ === realpath($_SERVER['SCRIPT_FILENAME'])) {
echo "\n---Output: " .countBytes($minOutput). " bytes\n\n{$minOutput}\n\n";
echo "---Expected: " .countBytes($minExpected). " bytes\n\n{$minExpected}\n\n";
Expand Down

0 comments on commit c95d6ba

Please sign in to comment.