diff --git a/README.md b/README.md
index 247731c6..4d10a35a 100644
--- a/README.md
+++ b/README.md
@@ -18,10 +18,10 @@ Just the usual. For Node:
npm install webidl2
```
-In the browser:
+In the browser without module support:
```HTML
-
+
```
## Documentation
@@ -35,21 +35,26 @@ WebIDL2 provides two functions: `parse` and `write`.
In Node, that happens with:
```JS
-var WebIDL2 = require("webidl2");
-var tree = WebIDL2.parse("string of WebIDL");
-var text = WebIDL2.write(tree);
+const { parse, write, validate } = require("webidl2");
+const tree = parse("string of WebIDL");
+const text = write(tree);
+const validation = validate(tree);
```
In the browser:
```HTML
-
-
-
```
@@ -89,11 +94,6 @@ var result = WebIDL2.write(tree, {
* @param type The `wrap()`ed result of references and syntatic bracket strings.
*/
type: type => type,
- /**
- * Called for each value literals, e.g. `"string"` or `3.12`.
- * @param {string} lit The raw literal string.
- */
- valueLiteral: lit => lit,
/**
* Receives the return value of `reference()`. String if it's absent.
*/
@@ -121,6 +121,17 @@ var result = WebIDL2.write(tree, {
"Wrapped value" here will all be raw strings when the `wrap()` callback is absent.
+`validate()` returns semantic errors in a string array form:
+
+```js
+const validations = validate(tree);
+for (const validation of validations) {
+ console.log(validation);
+}
+// Validation error on line X: ...
+// Validation error on line Y: ...
+```
+
### Errors
When there is a syntax error in the WebIDL, it throws an exception object with the following
diff --git a/lib/validator.js b/lib/validator.js
index 8b961283..67ae58ee 100644
--- a/lib/validator.js
+++ b/lib/validator.js
@@ -89,32 +89,31 @@ function* checkInterfaceMemberDuplication(defs) {
}
function* forEachInterface(i) {
- const opNames = getOperationNames(i);
+ const opNames = new Set(getOperations(i).map(op => op.name));
const partials = defs.partials.get(i.name) || [];
const mixins = includesMap.get(i.name) || [];
- for (const partial of partials) {
- yield* forEachExtension(partial, opNames, i);
- }
- for (const mixin of mixins) {
- yield* forEachExtension(mixin, opNames, i);
+ for (const ext of [...partials, ...mixins]) {
+ const additions = getOperations(ext);
+ yield* forEachExtension(additions, opNames, ext, i);
+ for (const addition of additions) {
+ opNames.add(addition.name);
+ }
}
}
- function* forEachExtension(ext, names, base) {
- for (const op of ext.members.filter(mem => mem.type === "operation")) {
- const name = (op.body && op.body.name) ? op.body.name.value : "";
- if (name && names.has(name)) {
- const message = `The operation "${name}" has already been defined in the base interface "${base.name}"`;
- yield error(ext.source, op.body.tokens.name, ext, message);
+ function* forEachExtension(additions, existings, ext, base) {
+ for (const addition of additions) {
+ const { name } = addition;
+ if (name && existings.has(name)) {
+ const message = `The operation "${name}" has already been defined for the base interface "${base.name}" either in itself or in a mixin`;
+ yield error(ext.source, addition.body.tokens.name, ext, message);
}
}
}
- function getOperationNames(i) {
- const names = i.members
- .filter(({type}) => type === "operation")
- .map(op => (op.body && op.body.name) ? op.body.name.value : "");
- return new Set(names);
+ function getOperations(i) {
+ return i.members
+ .filter(({type}) => type === "operation");
}
function getIncludesMap() {
diff --git a/lib/webidl2.js b/lib/webidl2.js
index 3570dbec..a40d5e75 100644
--- a/lib/webidl2.js
+++ b/lib/webidl2.js
@@ -955,6 +955,9 @@ function parseByTokens(source) {
get type() {
return "operation";
}
+ get name() {
+ return (this.body && this.body.name && this.body.name.value) || "";
+ }
get special() {
return untype_token(this.tokens.special);
}
diff --git a/test/invalid/baseline/overloads.txt b/test/invalid/baseline/overloads.txt
index b51e8e1a..dc7c87f8 100644
--- a/test/invalid/baseline/overloads.txt
+++ b/test/invalid/baseline/overloads.txt
@@ -1,6 +1,18 @@
Validation error at line 7, inside `partial interface Base`:
void unique(short num)
- ^ The operation "unique" has already been defined in the base interface "Base"
+ ^ The operation "unique" has already been defined for the base interface "Base" either in itself or in a mixin
Validation error at line 11, inside `interface mixin Extension`:
void unique(string str)
- ^ The operation "unique" has already been defined in the base interface "Base"
+ ^ The operation "unique" has already been defined for the base interface "Base" either in itself or in a mixin
+Validation error at line 21, inside `interface mixin WebGL2RenderingContextBase`:
+ void bufferData(GLenum target,
+ ^ The operation "bufferData" has already been defined for the base interface "WebGL2RenderingContext" either in itself or in a mixin
+Validation error at line 22, inside `interface mixin WebGL2RenderingContextBase`:
+ void bufferData(GLenum target,
+ ^ The operation "bufferData" has already been defined for the base interface "WebGL2RenderingContext" either in itself or in a mixin
+Validation error at line 23, inside `interface mixin WebGL2RenderingContextBase`:
+ void bufferData(GLenum target,
+ ^ The operation "bufferData" has already been defined for the base interface "WebGL2RenderingContext" either in itself or in a mixin
+Validation error at line 25, inside `interface mixin WebGL2RenderingContextBase`:
+ void bufferData(GLenum target,
+ ^ The operation "bufferData" has already been defined for the base interface "WebGL2RenderingContext" either in itself or in a mixin
diff --git a/test/invalid/idl/overloads.widl b/test/invalid/idl/overloads.widl
index 3d62e633..8da22397 100644
--- a/test/invalid/idl/overloads.widl
+++ b/test/invalid/idl/overloads.widl
@@ -12,3 +12,30 @@ interface mixin Extension {
};
Base includes Extension;
Base includes Unknown;
+
+// WebGL
+
+interface mixin WebGL2RenderingContextBase
+{
+ // WebGL1:
+ void bufferData(GLenum target, GLsizeiptr size, GLenum usage);
+ void bufferData(GLenum target, ArrayBuffer? srcData, GLenum usage);
+ void bufferData(GLenum target, ArrayBufferView srcData, GLenum usage);
+ // WebGL2:
+ void bufferData(GLenum target, ArrayBufferView srcData, GLenum usage, GLuint srcOffset,
+ optional GLuint length = 0);
+};
+
+interface mixin WebGLRenderingContextBase
+{
+ void bufferData(GLenum target, GLsizeiptr size, GLenum usage);
+ void bufferData(GLenum target, ArrayBuffer? data, GLenum usage);
+ void bufferData(GLenum target, ArrayBufferView data, GLenum usage);
+};
+
+[Exposed=(Window,Worker)]
+interface WebGL2RenderingContext
+{
+};
+WebGL2RenderingContext includes WebGLRenderingContextBase;
+WebGL2RenderingContext includes WebGL2RenderingContextBase;
diff --git a/test/syntax/baseline/allowany.json b/test/syntax/baseline/allowany.json
index 36463a59..364dbfef 100644
--- a/test/syntax/baseline/allowany.json
+++ b/test/syntax/baseline/allowany.json
@@ -7,6 +7,7 @@
"members": [
{
"type": "operation",
+ "name": "g",
"body": {
"name": {
"value": "g",
@@ -43,6 +44,7 @@
},
{
"type": "operation",
+ "name": "g",
"body": {
"name": {
"value": "g",
@@ -107,6 +109,7 @@
},
{
"type": "operation",
+ "name": "g",
"body": {
"name": {
"value": "g",
diff --git a/test/syntax/baseline/callback.json b/test/syntax/baseline/callback.json
index 5164f526..8acba5fb 100644
--- a/test/syntax/baseline/callback.json
+++ b/test/syntax/baseline/callback.json
@@ -65,6 +65,7 @@
"members": [
{
"type": "operation",
+ "name": "eventOccurred",
"body": {
"name": {
"value": "eventOccurred",
diff --git a/test/syntax/baseline/enum.json b/test/syntax/baseline/enum.json
index 1ef9964e..b5e9342a 100644
--- a/test/syntax/baseline/enum.json
+++ b/test/syntax/baseline/enum.json
@@ -104,6 +104,7 @@
},
{
"type": "operation",
+ "name": "initialize",
"body": {
"name": {
"value": "initialize",
diff --git a/test/syntax/baseline/equivalent-decl.json b/test/syntax/baseline/equivalent-decl.json
index 394fa463..3aea1370 100644
--- a/test/syntax/baseline/equivalent-decl.json
+++ b/test/syntax/baseline/equivalent-decl.json
@@ -41,6 +41,7 @@
},
{
"type": "operation",
+ "name": "getProperty",
"body": {
"name": {
"value": "getProperty",
@@ -108,6 +109,7 @@
},
{
"type": "operation",
+ "name": "setProperty",
"body": {
"name": {
"value": "setProperty",
@@ -256,6 +258,7 @@
},
{
"type": "operation",
+ "name": "getProperty",
"body": {
"name": {
"value": "getProperty",
@@ -320,6 +323,7 @@
},
{
"type": "operation",
+ "name": "setProperty",
"body": {
"name": {
"value": "setProperty",
@@ -414,6 +418,7 @@
},
{
"type": "operation",
+ "name": "",
"body": {
"name": null,
"idlType": {
@@ -477,6 +482,7 @@
},
{
"type": "operation",
+ "name": "",
"body": {
"name": null,
"idlType": {
diff --git a/test/syntax/baseline/generic.json b/test/syntax/baseline/generic.json
index 476c882f..d60f886e 100644
--- a/test/syntax/baseline/generic.json
+++ b/test/syntax/baseline/generic.json
@@ -7,6 +7,7 @@
"members": [
{
"type": "operation",
+ "name": "bar",
"body": {
"name": {
"value": "bar",
@@ -185,6 +186,7 @@
"members": [
{
"type": "operation",
+ "name": "getServiced",
"body": {
"name": {
"value": "getServiced",
@@ -246,6 +248,7 @@
},
{
"type": "operation",
+ "name": "reloadAll",
"body": {
"name": {
"value": "reloadAll",
@@ -329,6 +332,7 @@
"members": [
{
"type": "operation",
+ "name": "default",
"body": {
"name": {
"value": "default",
diff --git a/test/syntax/baseline/getter-setter.json b/test/syntax/baseline/getter-setter.json
index f0a2aba6..59b9c09d 100644
--- a/test/syntax/baseline/getter-setter.json
+++ b/test/syntax/baseline/getter-setter.json
@@ -41,6 +41,7 @@
},
{
"type": "operation",
+ "name": "",
"body": {
"name": null,
"idlType": {
@@ -104,6 +105,7 @@
},
{
"type": "operation",
+ "name": "",
"body": {
"name": null,
"idlType": {
diff --git a/test/syntax/baseline/identifier-qualified-names.json b/test/syntax/baseline/identifier-qualified-names.json
index b4c24c10..3f36b4ac 100644
--- a/test/syntax/baseline/identifier-qualified-names.json
+++ b/test/syntax/baseline/identifier-qualified-names.json
@@ -34,6 +34,7 @@
"members": [
{
"type": "operation",
+ "name": "createObject",
"body": {
"name": {
"value": "createObject",
@@ -98,6 +99,7 @@
},
{
"type": "operation",
+ "name": "",
"body": {
"name": null,
"idlType": {
@@ -255,6 +257,7 @@
"members": [
{
"type": "operation",
+ "name": "addEventListener",
"body": {
"name": {
"value": "addEventListener",
diff --git a/test/syntax/baseline/indexed-properties.json b/test/syntax/baseline/indexed-properties.json
index 31112565..4a9d4cf3 100644
--- a/test/syntax/baseline/indexed-properties.json
+++ b/test/syntax/baseline/indexed-properties.json
@@ -41,6 +41,7 @@
},
{
"type": "operation",
+ "name": "getByIndex",
"body": {
"name": {
"value": "getByIndex",
@@ -111,6 +112,7 @@
},
{
"type": "operation",
+ "name": "setByIndex",
"body": {
"name": {
"value": "setByIndex",
@@ -211,6 +213,7 @@
},
{
"type": "operation",
+ "name": "removeByIndex",
"body": {
"name": {
"value": "removeByIndex",
@@ -281,6 +284,7 @@
},
{
"type": "operation",
+ "name": "get",
"body": {
"name": {
"value": "get",
@@ -348,6 +352,7 @@
},
{
"type": "operation",
+ "name": "set",
"body": {
"name": {
"value": "set",
@@ -445,6 +450,7 @@
},
{
"type": "operation",
+ "name": "remove",
"body": {
"name": {
"value": "remove",
diff --git a/test/syntax/baseline/namespace.json b/test/syntax/baseline/namespace.json
index 569cf403..6037216c 100644
--- a/test/syntax/baseline/namespace.json
+++ b/test/syntax/baseline/namespace.json
@@ -37,6 +37,7 @@
},
{
"type": "operation",
+ "name": "dotProduct",
"body": {
"name": {
"value": "dotProduct",
@@ -131,6 +132,7 @@
},
{
"type": "operation",
+ "name": "crossProduct",
"body": {
"name": {
"value": "crossProduct",
diff --git a/test/syntax/baseline/nointerfaceobject.json b/test/syntax/baseline/nointerfaceobject.json
index 4b89a1ef..fb7d4704 100644
--- a/test/syntax/baseline/nointerfaceobject.json
+++ b/test/syntax/baseline/nointerfaceobject.json
@@ -7,6 +7,7 @@
"members": [
{
"type": "operation",
+ "name": "lookupEntry",
"body": {
"name": {
"value": "lookupEntry",
diff --git a/test/syntax/baseline/nullableobjects.json b/test/syntax/baseline/nullableobjects.json
index 44dfa7c4..baec11e9 100644
--- a/test/syntax/baseline/nullableobjects.json
+++ b/test/syntax/baseline/nullableobjects.json
@@ -39,6 +39,7 @@
"members": [
{
"type": "operation",
+ "name": "f",
"body": {
"name": {
"value": "f",
@@ -105,6 +106,7 @@
},
{
"type": "operation",
+ "name": "f",
"body": {
"name": {
"value": "f",
diff --git a/test/syntax/baseline/operation-optional-arg.json b/test/syntax/baseline/operation-optional-arg.json
index b6f66ac9..3f768cf1 100644
--- a/test/syntax/baseline/operation-optional-arg.json
+++ b/test/syntax/baseline/operation-optional-arg.json
@@ -7,6 +7,7 @@
"members": [
{
"type": "operation",
+ "name": "createColor",
"body": {
"name": {
"value": "createColor",
diff --git a/test/syntax/baseline/overloading.json b/test/syntax/baseline/overloading.json
index 44c2314f..8877b4cf 100644
--- a/test/syntax/baseline/overloading.json
+++ b/test/syntax/baseline/overloading.json
@@ -39,6 +39,7 @@
"members": [
{
"type": "operation",
+ "name": "f",
"body": {
"name": {
"value": "f",
@@ -103,6 +104,7 @@
},
{
"type": "operation",
+ "name": "f",
"body": {
"name": {
"value": "f",
@@ -184,6 +186,7 @@
"members": [
{
"type": "operation",
+ "name": "f",
"body": {
"name": {
"value": "f",
@@ -248,6 +251,7 @@
},
{
"type": "operation",
+ "name": "f",
"body": {
"name": {
"value": "f",
@@ -391,6 +395,7 @@
},
{
"type": "operation",
+ "name": "f",
"body": {
"name": {
"value": "f",
@@ -427,6 +432,7 @@
},
{
"type": "operation",
+ "name": "f",
"body": {
"name": {
"value": "f",
diff --git a/test/syntax/baseline/overridebuiltins.json b/test/syntax/baseline/overridebuiltins.json
index 21aafb5f..75a1788c 100644
--- a/test/syntax/baseline/overridebuiltins.json
+++ b/test/syntax/baseline/overridebuiltins.json
@@ -41,6 +41,7 @@
},
{
"type": "operation",
+ "name": "lookup",
"body": {
"name": {
"value": "lookup",
diff --git a/test/syntax/baseline/record.json b/test/syntax/baseline/record.json
index 64c98a14..7dcc8347 100644
--- a/test/syntax/baseline/record.json
+++ b/test/syntax/baseline/record.json
@@ -7,6 +7,7 @@
"members": [
{
"type": "operation",
+ "name": "foo",
"body": {
"name": {
"value": "foo",
@@ -136,6 +137,7 @@
},
{
"type": "operation",
+ "name": "bar",
"body": {
"name": {
"value": "bar",
@@ -363,6 +365,7 @@
"members": [
{
"type": "operation",
+ "name": "bar",
"body": {
"name": {
"value": "bar",
diff --git a/test/syntax/baseline/reg-operations.json b/test/syntax/baseline/reg-operations.json
index 826f3fca..296ee6d6 100644
--- a/test/syntax/baseline/reg-operations.json
+++ b/test/syntax/baseline/reg-operations.json
@@ -88,6 +88,7 @@
"members": [
{
"type": "operation",
+ "name": "isMouseOver",
"body": {
"name": {
"value": "isMouseOver",
@@ -124,6 +125,7 @@
},
{
"type": "operation",
+ "name": "setDimensions",
"body": {
"name": {
"value": "setDimensions",
@@ -188,6 +190,7 @@
},
{
"type": "operation",
+ "name": "setDimensions",
"body": {
"name": {
"value": "setDimensions",
diff --git a/test/syntax/baseline/replaceable.json b/test/syntax/baseline/replaceable.json
index 82c77226..bb8e81df 100644
--- a/test/syntax/baseline/replaceable.json
+++ b/test/syntax/baseline/replaceable.json
@@ -58,6 +58,7 @@
},
{
"type": "operation",
+ "name": "increment",
"body": {
"name": {
"value": "increment",
diff --git a/test/syntax/baseline/sequence.json b/test/syntax/baseline/sequence.json
index 9205dd7c..ee457635 100644
--- a/test/syntax/baseline/sequence.json
+++ b/test/syntax/baseline/sequence.json
@@ -7,6 +7,7 @@
"members": [
{
"type": "operation",
+ "name": "drawPolygon",
"body": {
"name": {
"value": "drawPolygon",
@@ -94,6 +95,7 @@
},
{
"type": "operation",
+ "name": "getInflectionPoints",
"body": {
"name": {
"value": "getInflectionPoints",
@@ -170,6 +172,7 @@
"members": [
{
"type": "operation",
+ "name": "f1",
"body": {
"name": {
"value": "f1",
diff --git a/test/syntax/baseline/static.json b/test/syntax/baseline/static.json
index 42d30a6b..75175ee4 100644
--- a/test/syntax/baseline/static.json
+++ b/test/syntax/baseline/static.json
@@ -144,6 +144,7 @@
},
{
"type": "operation",
+ "name": "triangulate",
"body": {
"name": {
"value": "triangulate",
diff --git a/test/syntax/baseline/stringifier-custom.json b/test/syntax/baseline/stringifier-custom.json
index b6e33603..d4db6366 100644
--- a/test/syntax/baseline/stringifier-custom.json
+++ b/test/syntax/baseline/stringifier-custom.json
@@ -99,6 +99,7 @@
},
{
"type": "operation",
+ "name": "",
"body": {
"name": null,
"idlType": {
diff --git a/test/syntax/baseline/stringifier.json b/test/syntax/baseline/stringifier.json
index 29a64298..7c52da60 100644
--- a/test/syntax/baseline/stringifier.json
+++ b/test/syntax/baseline/stringifier.json
@@ -7,6 +7,7 @@
"members": [
{
"type": "operation",
+ "name": "",
"body": {
"name": null,
"idlType": {
@@ -59,6 +60,7 @@
"members": [
{
"type": "operation",
+ "name": "",
"body": null,
"extAttrs": null,
"special": {
diff --git a/test/syntax/baseline/treatasnull.json b/test/syntax/baseline/treatasnull.json
index 0eb063a5..511059c4 100644
--- a/test/syntax/baseline/treatasnull.json
+++ b/test/syntax/baseline/treatasnull.json
@@ -65,6 +65,7 @@
},
{
"type": "operation",
+ "name": "isMemberOfBreed",
"body": {
"name": {
"value": "isMemberOfBreed",
diff --git a/test/syntax/baseline/treatasundefined.json b/test/syntax/baseline/treatasundefined.json
index 5747e57d..f75081c2 100644
--- a/test/syntax/baseline/treatasundefined.json
+++ b/test/syntax/baseline/treatasundefined.json
@@ -65,6 +65,7 @@
},
{
"type": "operation",
+ "name": "isMemberOfBreed",
"body": {
"name": {
"value": "isMemberOfBreed",
diff --git a/test/syntax/baseline/typedef.json b/test/syntax/baseline/typedef.json
index 28f5d7af..b16ea4ec 100644
--- a/test/syntax/baseline/typedef.json
+++ b/test/syntax/baseline/typedef.json
@@ -238,6 +238,7 @@
},
{
"type": "operation",
+ "name": "pointWithinBounds",
"body": {
"name": {
"value": "pointWithinBounds",
@@ -302,6 +303,7 @@
},
{
"type": "operation",
+ "name": "allPointsWithinBounds",
"body": {
"name": {
"value": "allPointsWithinBounds",
diff --git a/test/syntax/baseline/typesuffixes.json b/test/syntax/baseline/typesuffixes.json
index 15bb661b..997ec212 100644
--- a/test/syntax/baseline/typesuffixes.json
+++ b/test/syntax/baseline/typesuffixes.json
@@ -7,6 +7,7 @@
"members": [
{
"type": "operation",
+ "name": "test",
"body": {
"name": {
"value": "test",
diff --git a/test/syntax/baseline/variadic-operations.json b/test/syntax/baseline/variadic-operations.json
index 01974c60..664e5a17 100644
--- a/test/syntax/baseline/variadic-operations.json
+++ b/test/syntax/baseline/variadic-operations.json
@@ -41,6 +41,7 @@
},
{
"type": "operation",
+ "name": "union",
"body": {
"name": {
"value": "union",
@@ -107,6 +108,7 @@
},
{
"type": "operation",
+ "name": "intersection",
"body": {
"name": {
"value": "intersection",