diff --git a/classes/external/php/jsmin.php b/classes/external/php/jsmin.php index dd15f08f..cf4f462e 100644 --- a/classes/external/php/jsmin.php +++ b/classes/external/php/jsmin.php @@ -1,4 +1,7 @@ a !== null) { // determine next command $command = self::ACTION_KEEP_A; // default - if ($this->a === ' ') { + if ($this->isWhiteSpace($this->a)) { if (($this->lastByteOut === '+' || $this->lastByteOut === '-') && ($this->b === $this->lastByteOut)) { // Don't delete this space. If we do, the addition/subtraction @@ -131,8 +129,8 @@ public function min() } elseif (! $this->isAlphaNum($this->b)) { $command = self::ACTION_DELETE_A; } - } elseif ($this->a === "\n") { - if ($this->b === ' ') { + } elseif ($this->isLineTerminator($this->a)) { + if ($this->isWhiteSpace($this->b)) { $command = self::ACTION_DELETE_A_B; // in case of mbstring.func_overload & 2, must check for null b, @@ -143,8 +141,8 @@ public function min() $command = self::ACTION_DELETE_A; } } elseif (! $this->isAlphaNum($this->a)) { - if ($this->b === ' ' - || ($this->b === "\n" + if ($this->isWhiteSpace($this->b) + || ($this->isLineTerminator($this->b) && (false === strpos('}])+-"\'`', $this->a)))) { $command = self::ACTION_DELETE_A_B; } @@ -165,7 +163,7 @@ public function min() * ACTION_DELETE_A_B = Get the next B. * * @param int $command - * @throws JSMin_UnterminatedRegExpException|JSMin_UnterminatedStringException + * @throws JSMin_UnterminatedRegExpException|UnterminatedStringException */ protected function action($command) { @@ -207,7 +205,7 @@ protected function action($command) if ($this->a === $this->b) { // end quote break; } - if ($delimiter === '`' && $this->a === "\n") { + if ($delimiter === '`' && $this->isLineTerminator($this->a)) { // leave the newline } elseif ($this->isEOF($this->a)) { $byte = $this->inputIndex - 1; @@ -287,7 +285,7 @@ protected function isRegexpLiteral() // check if first non-ws token is "/" (see starts-regex.js) $length = strlen($this->output); - if ($this->a === ' ' || $this->a === "\n") { + if ($this->isWhiteSpace($this->a) || $this->isLineTerminator($this->a)) { if ($length < 2) { // weird edge case return true; } @@ -309,7 +307,7 @@ protected function isRegexpLiteral() } // it's a regexp. Remove unneeded whitespace after keyword - if ($this->a === ' ' || $this->a === "\n") { + if ($this->isWhiteSpace($this->a) || $this->isLineTerminator($this->a)) { $this->a = ''; } @@ -332,18 +330,13 @@ protected function get() $c = $this->input[$this->inputIndex]; $this->inputIndex += 1; } else { - return $c; + $c = null; } } - if ($c === null) { - return $c; - } else if (ord($c) >= self::ORD_SPACE || $c === "\n") { - return $c; - } if ($c === "\r") { return "\n"; } - return ' '; + return $c; } /** @@ -354,7 +347,7 @@ protected function get() */ protected function isEOF($a) { - return ord($a) <= self::ORD_LF; + return $a === null || $this->isLineTerminator($a); } /** @@ -389,7 +382,7 @@ protected function consumeSingleLineComment() while (true) { $get = $this->get(); $comment .= $get; - if (ord($get) <= self::ORD_LF) { // end of line reached + if ($this->isEOF($get)) { // if IE conditional comment if (preg_match('/^\\/@(?:cc_on|if|elif|else|end)\\b/', $comment)) { $this->keptComment .= "/{$comment}"; @@ -456,6 +449,16 @@ protected function next() } return $get; } + + protected function isWhiteSpace($s) { + // https://www.ecma-international.org/ecma-262/#sec-white-space + return $s !== null && strpos(" \t\v\f", $s) !== false; + } + + protected function isLineTerminator($s) { + // https://www.ecma-international.org/ecma-262/#sec-line-terminators + return $s !== null && strpos("\n\r", $s) !== false; + } } class JSMin_UnterminatedStringException extends Exception {}