Repository: w3c/webidl2.js (js)

Issue:
Trailing comma in arguments list with valid IDL
Parsing https://github.com/w3c/web-platform-tests/blob/master/interfaces/dom.idl is broken in the latest version, not sure when it broke.

```
Got an error during or right after parsing `interface EventTarget`: Trailing comma in arguments list, line 54 (tokens: "? callback, optional (")
[
    {
        "type": "other",
        "value": "?",
        "trivia": ""
    },
    {
        "type": "callback",
        "value": "callback",
        "trivia": " "
    },
    {
        "type": "other",
        "value": ",",
        "trivia": ""
    },
    {
        "type": "optional",
        "value": "optional",
        "trivia": " "
    },
    {
        "type": "other",
        "value": "(",
        "trivia": " "
    }
]
```

This is referencing parsing:

```
[Constructor,
 Exposed=(Window,Worker)]
interface EventTarget {
  void addEventListener(DOMString type, EventListener? callback, optional (EventListenerOptions or boolean) options);
  void removeEventListener(DOMString type, EventListener? callback, optional (EventListenerOptions or boolean) options);
  boolean dispatchEvent(Event event);
};
```

Pull request:
fix: allow selected keywords in argument name
https://heycam.github.io/webidl/#index-prod-ArgumentNameKeyword

>Operation arguments can take a slightly wider set of identifiers. In an operation declaration, the identifier of an argument is specified immediately after its type and is given by either an identifier token or by one of the keywords that match the ArgumentNameKeyword symbol. If one of these keywords is used, it need not be escaped with a leading underscore.

Closes #169. This was a regression from #157.

Patch:
diff --git a/lib/webidl2.js b/lib/webidl2.js
index 080f629..641f012 100644
--- a/lib/webidl2.js
+++ b/lib/webidl2.js
@@ -15,49 +15,52 @@
     "other": /[^\t\n\r 0-9A-Za-z]/y
   };
 
-  const nonRegexTerminals = [
-    "Infinity",
-    "NaN",
+  const argumentNameKeywords = [
     "attribute",
-    "boolean",
-    "byte",
     "callback",
     "const",
     "deleter",
     "dictionary",
-    "double",
     "enum",
-    "false",
-    "float",
     "getter",
-    "implements",
     "includes",
     "inherit",
     "interface",
     "iterable",
+    "maplike",
+    "namespace",
+    "partial",
+    "required",
+    "setlike",
+    "setter",
+    "static",
+    "stringifier",
+    "typedef",
+    "unrestricted"
+  ]
+
+  const nonRegexTerminals = [
+    "Infinity",
+    "NaN",
+    "boolean",
+    "byte",
+    "double",
+    "false",
+    "float",
+    "implements",
     "legacyiterable",
     "long",
-    "maplike",
     "mixin",
-    "namespace",
     "null",
     "octet",
     "optional",
     "or",
-    "partial",
     "readonly",
-    "required",
-    "setlike",
-    "setter",
     "short",
-    "static",
-    "stringifier",
     "true",
-    "typedef",
-    "unrestricted",
     "unsigned",
     "void"
-  ];
+  ].concat(argumentNameKeywords);
 
   function tokenise(str) {
     const tokens = [];
@@ -375,7 +378,7 @@
           ret.variadic = true;
         }
       }
-      const name = consume(ID);
+      const name = argument_name(ID);
       if (!name) {
         if (opt_token) unconsume(opt_token);
         unconsume(type_token);
@@ -391,6 +394,19 @@
       }
       return ret;
     }
+    
+    function argument_name() {
+      let name = consume(ID);
+      if (name) {
+        return name;
+      }
+      for (const keyword of argumentNameKeywords) {
+        name = consume(keyword);
+        if (name) {
+          return name;
+        }
+      }
+    }
 
     function argument_list() {
       const ret = [];


Test patch:
diff --git a/test/syntax/idl/identifier-qualified-names.widl b/test/syntax/idl/identifier-qualified-names.widl
index 18137c4..c39f84b 100644
--- a/test/syntax/idl/identifier-qualified-names.widl
+++ b/test/syntax/idl/identifier-qualified-names.widl
@@ -26,3 +26,8 @@
       // Attribute identifier: "value"
       attribute DOMString? _value;
     };
+
+interface FooEventTarget {
+  // Argument names allow some selected keywords
+  void addEventListener(EventListener? callback);
+};
diff --git a/test/syntax/json/identifier-qualified-names.json b/test/syntax/json/identifier-qualified-names.json
index 6015dff..e202a00 100644
--- a/test/syntax/json/identifier-qualified-names.json
+++ b/test/syntax/json/identifier-qualified-names.json
@@ -144,5 +144,52 @@
         ],
         "inheritance": null,
         "extAttrs": []
+    },
+    {
+        "type": "interface",
+        "name": "FooEventTarget",
+        "partial": false,
+        "members": [
+            {
+                "type": "operation",
+                "getter": false,
+                "setter": false,
+                "deleter": false,
+                "static": false,
+                "stringifier": false,
+                "idlType": {
+                    "type": "return-type",
+                    "sequence": false,
+                    "generic": null,
+                    "nullable": false,
+                    "union": false,
+                    "idlType": "void",
+                    "extAttrs": []
+                },
+                "name": "addEventListener",
+                "escapedName": "addEventListener",
+                "arguments": [
+                    {
+                        "optional": false,
+                        "variadic": false,
+                        "extAttrs": [],
+                        "idlType": {
+                            "type": "argument-type",
+                            "sequence": false,
+                            "generic": null,
+                            "nullable": true,
+                            "union": false,
+                            "idlType": "EventListener",
+                            "extAttrs": []
+                        },
+                        "name": "callback",
+                        "escapedName": "callback"
+                    }
+                ],
+                "extAttrs": []
+            }
+        ],
+        "inheritance": null,
+        "extAttrs": []
     }
 ]