Repository: w3c/webidl2.js
Pull request #151 (2018-05-09 14:03:55)

Prevent incorrect enums
The current implementation is more permissive than [the spec](https://heycam.github.io/webidl/#idl-enums) allows, so this PR fixes it:

```
Enum ::
    enum identifier { EnumValueList } ;
EnumValueList ::
    string EnumValueListComma
EnumValueListComma ::
    , EnumValueListString
    ε
EnumValueListString ::
    string EnumValueListComma
    ε
```

```
enum Empty {}; // shouldn't pass
enum NoComma { "value1" "value2" }; // shouldn't pass
```

(Should we mark this as a breaking change?)

marcoscaceres: There are “bugs”, not breaking changes imo. 

Patch:
diff --git a/lib/webidl2.js b/lib/webidl2.js
index aafc089..1bf64a5 100644
--- a/lib/webidl2.js
+++ b/lib/webidl2.js
@@ -936,23 +936,27 @@
       };
       all_ws();
       consume(OTHER, "{") || error("No curly for enum");
-      let saw_comma = false;
+      let value_expected = true;
       while (true) {
         all_ws();
         if (consume(OTHER, "}")) {
+          if (!ret.values.length) error("No value in enum");
           all_ws();
           consume(OTHER, ";") || error("No semicolon after enum");
           return ret;
         }
+        else if (!value_expected) {
+          error("No comma between enum values");
+        }
         const val = consume(STR) || error("Unexpected value in enum");
         val.value = val.value.slice(1, -1);
         ret.values.push(val);
         all_ws();
         if (consume(OTHER, ",")) {
           all_ws();
-          saw_comma = true;
+          value_expected = true;
         } else {
-          saw_comma = false;
+          value_expected = false;
         }
       }
     }
diff --git a/lib/writer.js b/lib/writer.js
index b126423..ac7da3f 100644
--- a/lib/writer.js
+++ b/lib/writer.js
@@ -159,8 +159,7 @@
       let ret = extended_attributes(it.extAttrs);
       ret += `enum ${it.name} {`;
       for (const v of it.values) {
-        if (v.type === "string") ret += `"${v.value}"`;
-        else if (v.type === ",") ret += ",";
+        ret += `"${v.value}",`;
       }
       return ret + "};";
     };


Test patch:
diff --git a/test/invalid/idl/enum-empty.widl b/test/invalid/idl/enum-empty.widl
new file mode 100644
index 0000000..7f189eb
--- /dev/null
+++ b/test/invalid/idl/enum-empty.widl
@@ -0,0 +1,1 @@
+enum Empty {};
diff --git a/test/invalid/idl/enum-wo-comma.widl b/test/invalid/idl/enum-wo-comma.widl
new file mode 100644
index 0000000..ebc5306
--- /dev/null
+++ b/test/invalid/idl/enum-wo-comma.widl
@@ -0,0 +1,1 @@
+enum NoComma { "value1" "value2" };
diff --git a/test/invalid/json/enum-empty.json b/test/invalid/json/enum-empty.json
new file mode 100644
index 0000000..734bc67
--- /dev/null
+++ b/test/invalid/json/enum-empty.json
@@ -0,0 +1,4 @@
+{
+    "message": "Got an error during or right after parsing `enum Empty`: No value in enum",
+    "line": 1
+}
diff --git a/test/invalid/json/enum-wo-comma.json b/test/invalid/json/enum-wo-comma.json
new file mode 100644
index 0000000..bfd0b09
--- /dev/null
+++ b/test/invalid/json/enum-wo-comma.json
@@ -0,0 +1,4 @@
+{
+    "message": "Got an error during or right after parsing `enum NoComma`: No comma between enum values",
+    "line": 1
+}