Repository: w3c/webidl2.js
Pull request #165 (2018-05-21 06:16:50)

fix: prevent readwrite attributes on namespaces 
https://heycam.github.io/webidl/#index-prod-NamespaceMember

```
NamespaceMember ::
    RegularOperation
    readonly AttributeRest
```

A namespace attribute must be readonly, but currently readwrite attributes are allowed. This PR fixes it.


Patch:
diff --git a/lib/webidl2.js b/lib/webidl2.js
index a1b6927..d253cb9 100644
--- a/lib/webidl2.js
+++ b/lib/webidl2.js
@@ -168,7 +168,7 @@
     function error(str) {
       const maxTokens = 5;
       const tok = tokens.slice(0, maxTokens).map(t => t.trivia + t.value).join("");
-      // Count newlines preceding the actual errorneous token
+      // Count newlines preceding the actual erroneous token
       if (tokens.length) {
         line += count(tokens[0].trivia, "\n");
       }
@@ -543,7 +543,6 @@
         readonly: false
       };
       if (consume("inherit")) {
-        if (ret.static || ret.stringifier) error("Cannot have a static or stringifier inherit");
         ret.inherit = true;
         grabbed.push(last_token);
       }
@@ -590,11 +589,6 @@
         else if (consume("deleter")) ret.deleter = true;
         else break;
       }
-      if (ret.getter || ret.setter || ret.deleter) {
-        ret.idlType = return_type();
-        operation_rest(ret);
-        return ret;
-      }
       ret.idlType = return_type();
       operation_rest(ret);
       return ret;
@@ -602,9 +596,11 @@
 
     function static_member() {
       if (!consume("static")) return;
-      return noninherited_attribute("static") ||
-        regular_operation("static") ||
+      const member = noninherited_attribute() ||
+        regular_operation() ||
         error("No body in static member");
+      member.static = true;
+      return member;
     }
 
     function stringifier() {
@@ -612,9 +608,11 @@
       if (consume(OTHER, ";")) {
         return Object.assign({}, EMPTY_OPERATION, { stringifier: true });
       }
-      return noninherited_attribute("stringifier") ||
-        regular_operation("stringifier") ||
+      const member = noninherited_attribute() ||
+        regular_operation() ||
         error("Unterminated stringifier");
+      member.stringifier = true;
+      return member;
     }
 
     function identifiers() {
@@ -774,7 +772,7 @@
           return ret;
         }
         const ea = extended_attrs();
-        const mem = noninherited_attribute() ||
+        const mem = noninherited_attribute({ readonly: true }) ||
           regular_operation() ||
           error("Unknown member");
         mem.extAttrs = ea;
@@ -782,7 +780,7 @@
       }
     }
 
-    function noninherited_attribute(prefix) {
+    function noninherited_attribute({ readonly = false } = {}) {
       const grabbed = [];
       const ret = {
         type: "attribute",
@@ -791,12 +789,11 @@
         inherit: false,
         readonly: false
       };
-      if (prefix) {
-        ret[prefix] = true;
-      }
       if (consume("readonly")) {
         ret.readonly = true;
         grabbed.push(last_token);
+      } else if (readonly && tokens[0] && tokens[0].type === "attribute") {
+        error("Attributes must be readonly in this context");
       }
       const rest = attribute_rest(ret);
       if (!rest) {
@@ -805,11 +802,8 @@
       return rest;
     }
 
-    function regular_operation(prefix) {
+    function regular_operation() {
       const ret = Object.assign({}, EMPTY_OPERATION);
-      if (prefix) {
-        ret[prefix] = true;
-      }
       ret.idlType = return_type();
       return operation_rest(ret);
     }
@@ -887,11 +881,7 @@
         // No trivia exposure yet
         val.trivia = undefined;
         ret.values.push(val);
-        if (consume(OTHER, ",")) {
-          value_expected = true;
-        } else {
-          value_expected = false;
-        }
+        value_expected = !!consume(OTHER, ",");
       }
     }
 


Test patch:
diff --git a/test/invalid/idl/namespace-readwrite.widl b/test/invalid/idl/namespace-readwrite.widl
new file mode 100644
index 0000000..e184133
--- /dev/null
+++ b/test/invalid/idl/namespace-readwrite.widl
@@ -0,0 +1,3 @@
+namespace CSS {
+  attribute object readwrite;
+};
diff --git a/test/invalid/json/namespace-readwrite.json b/test/invalid/json/namespace-readwrite.json
new file mode 100644
index 0000000..d212151
--- /dev/null
+++ b/test/invalid/json/namespace-readwrite.json
@@ -0,0 +1,4 @@
+{
+    "message": "Got an error during or right after parsing `namespace CSS`: Attributes must be readonly in this context",
+    "line": 2
+}