diff --git a/composer.json b/composer.json index 70698d1..fd574d3 100644 --- a/composer.json +++ b/composer.json @@ -27,7 +27,7 @@ }, "extra": { "branch-alias": { - "dev-master": "1.16.0-dev" + "dev-master": "1.16.1-dev" } } } diff --git a/doc/changelog.md b/doc/changelog.md index f58e39c..45359d0 100644 --- a/doc/changelog.md +++ b/doc/changelog.md @@ -1,6 +1,9 @@ Changelog ========== +#### 1.16.1 +* Fixed bug where, in some situations, scanner allowed invalid characters after a slash + #### 1.16.0 * Implemented ES2024 parser, no new syntax features have been introduced * Fixed bug when parsing sequence expressions using older ES versions diff --git a/lib/Peast/Syntax/Scanner.php b/lib/Peast/Syntax/Scanner.php index 6f01589..9926469 100644 --- a/lib/Peast/Syntax/Scanner.php +++ b/lib/Peast/Syntax/Scanner.php @@ -976,22 +976,30 @@ protected function consumeCommentsForCurrentToken() } /** - * Checks if the consumed or the scanned position follow a slash. + * Checks if the given position follows a slash. * - * @param Position $position Additional position to check + * @param Position $position Position to check * * @return bool */ - protected function isAfterSlash($position = null) + protected function isAfterSlash($position) { - $consumedIndex = $this->getPosition()->getIndex(); - $checkIndices = array($consumedIndex, $consumedIndex + 1); - if ($position) { - $checkIndices[] = $position->getIndex() - 1; - } - foreach ($checkIndices as $i) { - if ($i >= 0 && $this->charAt($i) === "/") { - return true; + //Start from the previous index and loop until the begin of the file is reached + $idx = $position->getIndex() - 1; + while ($idx >= 0) { + //Get the char at the index to check + $char = $this->charAt($idx); + //If the char is actually a slash check that it's not a multiline comment closing slash + if ($char === "/") { + return $idx === 0 || $this->charAt($idx - 1) !== "*"; + } + //Skip whitespaces but not line terminators since regexps can't be multiline + elseif (in_array($char, $this->whitespaces) && !in_array($char, $this->lineTerminators)) { + $idx--; + } + //Different character, return + else { + break; } } return false; diff --git a/test/Peast/Syntax/ES2015/files/Literal/InvalidRegexp4.js b/test/Peast/Syntax/ES2015/files/Literal/InvalidRegexp4.js new file mode 100644 index 0000000..fb006b6 --- /dev/null +++ b/test/Peast/Syntax/ES2015/files/Literal/InvalidRegexp4.js @@ -0,0 +1 @@ +/**/@ \ No newline at end of file diff --git a/test/Peast/Syntax/ES2015/files/Literal/Regexp9.Render.txt b/test/Peast/Syntax/ES2015/files/Literal/Regexp9.Render.txt new file mode 100644 index 0000000..0538d65 --- /dev/null +++ b/test/Peast/Syntax/ES2015/files/Literal/Regexp9.Render.txt @@ -0,0 +1,5 @@ +/ \ /.source; +/**************************************************/ +/ \ /.source; +/**************************************************/ +/ \ /.source; \ No newline at end of file diff --git a/test/Peast/Syntax/ES2015/files/Literal/Regexp9.Tokens.json b/test/Peast/Syntax/ES2015/files/Literal/Regexp9.Tokens.json new file mode 100644 index 0000000..1fa510d --- /dev/null +++ b/test/Peast/Syntax/ES2015/files/Literal/Regexp9.Tokens.json @@ -0,0 +1,50 @@ +[ + { + "type": "RegularExpression", + "value": "/ \\ /", + "location": { + "start": { + "line": 1, + "column": 0, + "index": 0 + }, + "end": { + "line": 1, + "column": 5, + "index": 5 + } + } + }, + { + "type": "Punctuator", + "value": ".", + "location": { + "start": { + "line": 1, + "column": 5, + "index": 5 + }, + "end": { + "line": 1, + "column": 6, + "index": 6 + } + } + }, + { + "type": "Identifier", + "value": "source", + "location": { + "start": { + "line": 1, + "column": 6, + "index": 6 + }, + "end": { + "line": 1, + "column": 12, + "index": 12 + } + } + } +] \ No newline at end of file diff --git a/test/Peast/Syntax/ES2015/files/Literal/Regexp9.js b/test/Peast/Syntax/ES2015/files/Literal/Regexp9.js new file mode 100644 index 0000000..01ab194 --- /dev/null +++ b/test/Peast/Syntax/ES2015/files/Literal/Regexp9.js @@ -0,0 +1 @@ +/ \ /.source \ No newline at end of file diff --git a/test/Peast/Syntax/ES2015/files/Literal/Regexp9.json b/test/Peast/Syntax/ES2015/files/Literal/Regexp9.json new file mode 100644 index 0000000..26f18a3 --- /dev/null +++ b/test/Peast/Syntax/ES2015/files/Literal/Regexp9.json @@ -0,0 +1,96 @@ +{ + "type": "Program", + "location": { + "start": { + "line": 1, + "column": 0, + "index": 0 + }, + "end": { + "line": 1, + "column": 12, + "index": 12 + } + }, + "leadingComments": [], + "trailingComments": [], + "body": [ + { + "type": "ExpressionStatement", + "location": { + "start": { + "line": 1, + "column": 0, + "index": 0 + }, + "end": { + "line": 1, + "column": 12, + "index": 12 + } + }, + "leadingComments": [], + "trailingComments": [], + "expression": { + "type": "MemberExpression", + "location": { + "start": { + "line": 1, + "column": 0, + "index": 0 + }, + "end": { + "line": 1, + "column": 12, + "index": 12 + } + }, + "leadingComments": [], + "trailingComments": [], + "optional": false, + "object": { + "type": "RegExpLiteral", + "location": { + "start": { + "line": 1, + "column": 0, + "index": 0 + }, + "end": { + "line": 1, + "column": 5, + "index": 5 + } + }, + "leadingComments": [], + "trailingComments": [], + "value": "/ \\ /", + "raw": "/ \\ /", + "flags": "", + "pattern": " \\ " + }, + "property": { + "type": "Identifier", + "location": { + "start": { + "line": 1, + "column": 6, + "index": 6 + }, + "end": { + "line": 1, + "column": 12, + "index": 12 + } + }, + "leadingComments": [], + "trailingComments": [], + "name": "source", + "rawName": "source" + }, + "computed": false + } + } + ], + "sourceType": "script" +} \ No newline at end of file