Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
256 changes: 29 additions & 227 deletions README.md

Large diffs are not rendered by default.

121 changes: 39 additions & 82 deletions lib/webidl2.js
Original file line number Diff line number Diff line change
Expand Up @@ -218,14 +218,6 @@ function parseByTokens(source) {
}
}

function optional_consume(...args) {
const token = consume(...args);
if (token) {
token.optional = true;
}
return token;
}

function unescape(identifier) {
return identifier.startsWith('_') ? identifier.slice(1) : identifier;
}
Expand All @@ -246,7 +238,7 @@ function parseByTokens(source) {
if (!first) {
return [];
}
first.tokens.separator = optional_consume(",");
first.tokens.separator = consume(",");
const items = [first];
while (first.tokens.separator) {
const item = parser();
Expand All @@ -256,7 +248,7 @@ function parseByTokens(source) {
}
break;
}
item.tokens.separator = optional_consume(",");
item.tokens.separator = consume(",");
items.push(item);
if (!item.tokens.separator) break;
}
Expand All @@ -271,16 +263,6 @@ function parseByTokens(source) {
});
}

get trivia() {
const object = {};
for (const [key, value] of Object.entries(this.tokens)) {
if (value && !value.optional) {
object[key] = value.trivia;
}
}
return object;
}

toJSON() {
const json = { type: undefined, name: undefined };
let proto = this;
Expand All @@ -298,17 +280,17 @@ function parseByTokens(source) {
}

function integer_type() {
const prefix = optional_consume("unsigned");
const prefix = consume("unsigned");
const base = consume("short", "long");
if (base) {
const postfix = optional_consume("long");
const postfix = consume("long");
return new Type({ tokens: { prefix, base, postfix } });
}
if (prefix) error("Failed to parse integer type");
}

function float_type() {
const prefix = optional_consume("unrestricted");
const prefix = consume("unrestricted");
const base = consume("float", "double");
if (base) {
return new Type({ tokens: { prefix, base } });
Expand Down Expand Up @@ -350,7 +332,7 @@ function parseByTokens(source) {
}

function type_suffix(obj) {
const nullable = optional_consume("?");
const nullable = consume("?");
if (nullable) {
obj.tokens.nullable = nullable;
}
Expand All @@ -365,7 +347,7 @@ function parseByTokens(source) {
}

get generic() {
return null;
return "";
}
get nullable() {
return !!this.tokens.nullable;
Expand Down Expand Up @@ -394,7 +376,7 @@ function parseByTokens(source) {
return;
}
const ret = new GenericType({ tokens: { base } });
ret.tokens.open = optional_consume("<") || error(`No opening bracket after ${base.type}`);
ret.tokens.open = consume("<") || error(`No opening bracket after ${base.type}`);
switch (base.type) {
case "Promise": {
if (probe("[")) error("Promise type cannot have extended attribute");
Expand All @@ -412,26 +394,20 @@ function parseByTokens(source) {
if (probe("[")) error("Record key cannot have extended attribute");
const keyType = consume(...stringTypes) || error(`Record key must be one of: ${stringTypes.join(", ")}`);
const keyIdlType = new Type({ tokens: { base: keyType }});
keyIdlType.tokens.separator = optional_consume(",") || error("Missing comma after record key type");
keyIdlType.tokens.separator = consume(",") || error("Missing comma after record key type");
keyIdlType.type = typeName;
const valueType = type_with_extended_attributes(typeName) || error("Error parsing generic type record");
ret.subtype.push(keyIdlType, valueType);
break;
}
}
if (!ret.idlType) error(`Error parsing generic type ${base.type}`);
ret.tokens.close = optional_consume(">") || error(`Missing closing bracket after ${base.type}`);
ret.tokens.close = consume(">") || error(`Missing closing bracket after ${base.type}`);
return ret;
}

get generic() {
return {
value: this.tokens.base.value,
trivia: {
open: this.tokens.open.trivia,
close: this.tokens.close.trivia,
}
};
return this.tokens.base.value;
}
}

Expand All @@ -445,7 +421,7 @@ function parseByTokens(source) {
ret = new Type({ tokens: { base } });
if (probe("<")) error(`Unsupported generic type ${base.value}`);
}
if (ret.generic && ret.generic.value === "Promise" && probe("?")) {
if (ret.generic === "Promise" && probe("?")) {
error("Promise type cannot be nullable");
}
ret.type = typeName || null;
Expand All @@ -465,7 +441,7 @@ function parseByTokens(source) {
const typ = type_with_extended_attributes() || error("No type after open parenthesis or 'or' in union type");
if (typ.idlType === "any") error("Type `any` cannot be included in a union type");
ret.subtype.push(typ);
const or = optional_consume("or");
const or = consume("or");
if (or) {
typ.tokens.separator = or;
}
Expand Down Expand Up @@ -500,13 +476,13 @@ function parseByTokens(source) {
const start_position = consume_position;
const tokens = {};
const ret = new Argument({ tokens });
tokens.optional = optional_consume("optional");
tokens.optional = consume("optional");
ret.idlType = type_with_extended_attributes("argument-type");
if (!ret.idlType) {
return unconsume(start_position);
}
if (!tokens.optional) {
tokens.variadic = optional_consume("...");
tokens.variadic = consume("...");
}
tokens.name = consume(ID, ...argumentNameKeywords);
if (!tokens.name) {
Expand Down Expand Up @@ -547,9 +523,6 @@ function parseByTokens(source) {
get value() {
return this.tokens.value.value;
}
get trivia() {
return this.tokens.value.trivia;
}
}

function identifiers() {
Expand All @@ -565,7 +538,7 @@ function parseByTokens(source) {
const tokens = { assign: consume("=") };
const ret = new ExtendedAttributeParameters({ tokens });
if (tokens.assign) {
tokens.secondaryName = optional_consume(ID, FLOAT, INT, STR);
tokens.secondaryName = consume(ID, FLOAT, INT, STR);
}
tokens.open = consume("(");
if (tokens.open) {
Expand Down Expand Up @@ -611,24 +584,19 @@ function parseByTokens(source) {
return this.tokens.name.value;
}
get rhs() {
const { rhsType: type, tokens, list, trivia } = this.params;
const { rhsType: type, tokens, list } = this.params;
if (!type) {
return null;
}
const value = type === "identifier-list" ? list : tokens.secondaryName.value;
if (!Array.isArray(value)) {
trivia.value = tokens.secondaryName.trivia;
trivia.open = trivia.close = undefined;
}
return { type, value, trivia };
return { type, value };
}
get signature() {
const { rhsType, list, trivia } = this.params;
get arguments() {
const { rhsType, list } = this.params;
if (!list || rhsType === "identifier-list") {
return null;
return [];
}
trivia.assign = undefined;
return { arguments: list, trivia };
return list;
}
}

Expand Down Expand Up @@ -681,14 +649,6 @@ function parseByTokens(source) {
get negative() {
return const_data(this.expression[0]).negative;
}
get trivia() {
const [first, second] = this.expression;
const trivia = first.type === "[" ? {
open: first.trivia,
close: second.trivia
} : { value: first.trivia };
return Object.assign(super.trivia, trivia);
}
}

class Constant extends Definition {
Expand Down Expand Up @@ -766,9 +726,9 @@ function parseByTokens(source) {
const tokens = { special };
const ret = new Attribute({ tokens });
if (!special && !noInherit) {
tokens.special = optional_consume("inherit");
tokens.special = consume("inherit");
}
tokens.readonly = optional_consume("readonly");
tokens.readonly = consume("readonly");
if (readonly && !tokens.readonly && probe("attribute")) {
error("Attributes must be readonly in this context");
}
Expand All @@ -778,9 +738,9 @@ function parseByTokens(source) {
return;
}
ret.idlType = type_with_extended_attributes("attribute-type") || error("No type in attribute");
switch (ret.idlType.generic && ret.idlType.generic.value) {
switch (ret.idlType.generic) {
case "sequence":
case "record": error(`Attributes cannot accept ${ret.idlType.generic.value} types`);
case "record": error(`Attributes cannot accept ${ret.idlType.generic} types`);
}
tokens.name = consume(ID, "required") || error("No name in attribute");
tokens.termination = consume(";") || error("Unterminated attribute");
Expand All @@ -792,7 +752,7 @@ function parseByTokens(source) {
}
get special() {
if (!this.tokens.special) {
return null;
return "";
}
return this.tokens.special.value;
}
Expand Down Expand Up @@ -822,7 +782,7 @@ function parseByTokens(source) {
const tokens = {};
const ret = new OperationBody({ tokens });
ret.idlType = return_type() || error("Missing return type");
tokens.name = optional_consume(ID);
tokens.name = consume(ID);
tokens.open = consume("(") || error("Invalid operation");
ret.arguments = argument_list();
tokens.close = consume(")") || error("Unterminated operation");
Expand All @@ -832,12 +792,9 @@ function parseByTokens(source) {
get name() {
const { name } = this.tokens;
if (!name) {
return null;
return "";
}
return {
value: unescape(name.value),
trivia: name.trivia
};
return unescape(name.value);
}
}

Expand All @@ -853,7 +810,7 @@ function parseByTokens(source) {
}
}
if (!special && !regular) {
tokens.special = optional_consume("getter", "setter", "deleter");
tokens.special = consume("getter", "setter", "deleter");
}
ret.body = OperationBody.parse();
tokens.termination = consume(";") || error("Unterminated attribute");
Expand All @@ -864,18 +821,18 @@ function parseByTokens(source) {
return "operation";
}
get name() {
return (this.body && this.body.name && this.body.name.value) || "";
return (this.body && this.body.name) || "";
}
get special() {
if (!this.tokens.special) {
return null;
return "";
}
return this.tokens.special.value;
}
}

function static_member() {
const special = optional_consume("static");
const special = consume("static");
if (!special) return;
const member = Attribute.parse({ special }) ||
Operation.parse({ special }) ||
Expand All @@ -884,7 +841,7 @@ function parseByTokens(source) {
}

function stringifier() {
const special = optional_consume("stringifier");
const special = consume("stringifier");
if (!special) return;
const member = Attribute.parse({ special }) ||
Operation.parse({ special }) ||
Expand All @@ -897,7 +854,7 @@ function parseByTokens(source) {
const start_position = consume_position;
const tokens = {};
const ret = new IterableLike({ tokens });
tokens.readonly = optional_consume("readonly");
tokens.readonly = consume("readonly");
tokens.base = tokens.readonly ?
consume("maplike", "setlike") :
consume("iterable", "maplike", "setlike");
Expand All @@ -914,7 +871,7 @@ function parseByTokens(source) {
const first = type_with_extended_attributes() || error(`Error parsing ${type} declaration`);
ret.idlType = [first];
if (secondTypeAllowed) {
first.tokens.separator = optional_consume(",");
first.tokens.separator = consume(",");
if (first.tokens.separator) {
ret.idlType.push(type_with_extended_attributes());
}
Expand Down Expand Up @@ -1069,7 +1026,7 @@ function parseByTokens(source) {
}

function partial() {
const partial = optional_consume("partial");
const partial = consume("partial");
if (!partial) return;
return Dictionary.parse({ partial }) ||
interface_({ partial }) ||
Expand Down Expand Up @@ -1103,7 +1060,7 @@ function parseByTokens(source) {
const tokens = {};
const ret = new Field({ tokens });
ret.extAttrs = ExtendedAttributes.parse();
tokens.required = optional_consume("required");
tokens.required = consume("required");
ret.idlType = type_with_extended_attributes("dictionary-type") || error("No type for dictionary member");
tokens.name = consume(ID) || error("No name for dictionary member");
ret.default = Default.parse();
Expand Down
Loading