resourceloader: Make JSMinPlus allow reserved words as property name (ES5)
authorEbrahim Byagowi <ebrahim@gnu.org>
Wed, 20 Feb 2019 23:41:08 +0000 (03:11 +0330)
committerEbrahim Byagowi <ebrahim@gnu.org>
Sun, 24 Feb 2019 22:13:57 +0000 (01:43 +0330)
This makes parse of "var a = { true: 12 };" and "var a = { true: 12 };"
possible thus making JSMinPlus ES5 compatible.

Bug: T215280
Change-Id: I84bcacf26ab8900d09958b5d961cc40e1a046698

includes/libs/jsminplus.php
tests/phpunit/includes/libs/JavaScriptMinifierTest.php

index 08e9d69..3134e50 100644 (file)
@@ -1292,7 +1292,10 @@ class JSParser
 
                                        if ($tt == OP_DOT)
                                        {
-                                               $this->t->mustMatch(TOKEN_IDENTIFIER);
+                                               $tt = $this->t->get();
+                                               if (!$this->isKeyword($tt) && $tt !== TOKEN_IDENTIFIER)
+                                                       throw $this->t->newSyntaxError("Unexpected token; token identifier or keyword expected.");
+
                                                array_push($operands, new JSNode($this->t, OP_DOT, array_pop($operands), new JSNode($this->t)));
                                        }
                                        else
@@ -1427,6 +1430,11 @@ class JSParser
                                                        }
                                                        else
                                                        {
+                                                               // Accept keywords as property names by treating
+                                                               // them similarly with identifiers
+                                                               if ($this->isKeyword($tt))
+                                                                       $tt = TOKEN_IDENTIFIER;
+
                                                                switch ($tt)
                                                                {
                                                                        case TOKEN_IDENTIFIER:
@@ -1618,6 +1626,46 @@ class JSParser
 
                return $n;
        }
+
+       private function isKeyword($tt)
+       {
+               switch ($tt) {
+                       case KEYWORD_BREAK:
+                       case KEYWORD_CASE:
+                       case KEYWORD_CATCH:
+                       case KEYWORD_CONST:
+                       case KEYWORD_CONTINUE:
+                       case KEYWORD_DEBUGGER:
+                       case KEYWORD_DEFAULT:
+                       case KEYWORD_DELETE:
+                       case KEYWORD_DO:
+                       case KEYWORD_ELSE:
+                       case KEYWORD_ENUM:
+                       case KEYWORD_FALSE:
+                       case KEYWORD_FINALLY:
+                       case KEYWORD_FOR:
+                       case KEYWORD_FUNCTION:
+                       case KEYWORD_IF:
+                       case KEYWORD_IN:
+                       case KEYWORD_INSTANCEOF:
+                       case KEYWORD_NEW:
+                       case KEYWORD_NULL:
+                       case KEYWORD_RETURN:
+                       case KEYWORD_SWITCH:
+                       case KEYWORD_THIS:
+                       case KEYWORD_THROW:
+                       case KEYWORD_TRUE:
+                       case KEYWORD_TRY:
+                       case KEYWORD_TYPEOF:
+                       case KEYWORD_VAR:
+                       case KEYWORD_VOID:
+                       case KEYWORD_WHILE:
+                       case KEYWORD_WITH:
+                               return true;
+                       default:
+                               return false;
+               }
+       }
 }
 
 class JSCompilerContext
index 54dc583..d57d0dd 100644 (file)
@@ -182,8 +182,8 @@ class JavaScriptMinifierTest extends PHPUnit\Framework\TestCase {
 
                        // Boolean minification (!0 / !1)
                        [ "var a = { b: true };", "var a={b:!0};" ],
-                       [ "var a = { true: 12 };", "var a={true:12};", false ],
-                       [ "a.true = 12;", "a.true=12;", false ],
+                       [ "var a = { true: 12 };", "var a={true:12};" ],
+                       [ "a.true = 12;", "a.true=12;" ],
                        [ "a.foo = true;", "a.foo=!0;" ],
                        [ "a.foo = false;", "a.foo=!1;" ],
                ];