mirror of
https://github.com/servo/servo.git
synced 2025-08-13 17:35:36 +01:00
Update web-platform-tests to revision 4f397167b4ed552a02201c92d363cfaecfe2c7f0
This commit is contained in:
parent
73b5bf201f
commit
84b40513c3
182 changed files with 4779 additions and 1937 deletions
|
@ -1,33 +1,82 @@
|
|||
"use strict";
|
||||
|
||||
(() => {
|
||||
// These regular expressions use the sticky flag so they will only match at
|
||||
// the current location (ie. the offset of lastIndex).
|
||||
const tokenRe = {
|
||||
// This expression uses a lookahead assertion to catch false matches
|
||||
// against integers early.
|
||||
"float": /-?(?=[0-9]*\.|[0-9]+[eE])(([0-9]+\.[0-9]*|[0-9]*\.[0-9]+)([Ee][-+]?[0-9]+)?|[0-9]+[Ee][-+]?[0-9]+)/y,
|
||||
"integer": /-?(0([Xx][0-9A-Fa-f]+|[0-7]*)|[1-9][0-9]*)/y,
|
||||
"identifier": /[A-Z_a-z][0-9A-Z_a-z-]*/y,
|
||||
"string": /"[^"]*"/y,
|
||||
"whitespace": /[\t\n\r ]+/y,
|
||||
"comment": /((\/(\/.*|\*([^*]|\*[^\/])*\*\/)[\t\n\r ]*)+)/y,
|
||||
"other": /[^\t\n\r 0-9A-Z_a-z]/y
|
||||
};
|
||||
|
||||
function attemptTokenMatch(str, type, re, lastIndex, tokens) {
|
||||
re.lastIndex = lastIndex;
|
||||
const result = re.exec(str);
|
||||
if (result) {
|
||||
tokens.push({ type, value: result[0] });
|
||||
return re.lastIndex;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
function tokenise(str) {
|
||||
const tokens = [];
|
||||
const re = {
|
||||
"float": /^-?(([0-9]+\.[0-9]*|[0-9]*\.[0-9]+)([Ee][-+]?[0-9]+)?|[0-9]+[Ee][-+]?[0-9]+)/,
|
||||
"integer": /^-?(0([Xx][0-9A-Fa-f]+|[0-7]*)|[1-9][0-9]*)/,
|
||||
"identifier": /^[A-Z_a-z][0-9A-Z_a-z-]*/,
|
||||
"string": /^"[^"]*"/,
|
||||
"whitespace": /^(?:[\t\n\r ]+|[\t\n\r ]*((\/\/.*|\/\*(.|\n|\r)*?\*\/)[\t\n\r ]*))+/,
|
||||
"other": /^[^\t\n\r 0-9A-Z_a-z]/
|
||||
};
|
||||
const types = ["float", "integer", "identifier", "string", "whitespace", "other"];
|
||||
while (str.length > 0) {
|
||||
let matched = false;
|
||||
for (var i in types) {
|
||||
const type = types[i];
|
||||
str = str.replace(re[type], tok => {
|
||||
tokens.push({ type, value: tok });
|
||||
matched = true;
|
||||
return "";
|
||||
});
|
||||
if (matched) break;
|
||||
let lastIndex = 0;
|
||||
while (lastIndex < str.length) {
|
||||
const nextChar = str.charAt(lastIndex);
|
||||
let result = -1;
|
||||
if (/[-0-9.]/.test(nextChar)) {
|
||||
result = attemptTokenMatch(str, "float", tokenRe.float, lastIndex,
|
||||
tokens);
|
||||
if (result === -1) {
|
||||
result = attemptTokenMatch(str, "integer", tokenRe.integer, lastIndex,
|
||||
tokens);
|
||||
}
|
||||
if (result === -1) {
|
||||
// '-' and '.' can also match "other".
|
||||
result = attemptTokenMatch(str, "other", tokenRe.other,
|
||||
lastIndex, tokens);
|
||||
}
|
||||
} else if (/[A-Z_a-z]/.test(nextChar)) {
|
||||
result = attemptTokenMatch(str, "identifier", tokenRe.identifier,
|
||||
lastIndex, tokens);
|
||||
} else if (nextChar === '"') {
|
||||
result = attemptTokenMatch(str, "string", tokenRe.string,
|
||||
lastIndex, tokens);
|
||||
if (result === -1) {
|
||||
// '"' can also match "other".
|
||||
result = attemptTokenMatch(str, "other", tokenRe.other,
|
||||
lastIndex, tokens);
|
||||
}
|
||||
} else if (/[\t\n\r ]/.test(nextChar)) {
|
||||
result = attemptTokenMatch(str, "whitespace", tokenRe.whitespace,
|
||||
lastIndex, tokens);
|
||||
} else if (nextChar === '/') {
|
||||
// The parser expects comments to be labelled as "whitespace".
|
||||
result = attemptTokenMatch(str, "whitespace", tokenRe.comment,
|
||||
lastIndex, tokens);
|
||||
if (result === -1) {
|
||||
// '/' can also match "other".
|
||||
result = attemptTokenMatch(str, "other", tokenRe.other,
|
||||
lastIndex, tokens);
|
||||
}
|
||||
} else {
|
||||
result = attemptTokenMatch(str, "other", tokenRe.other,
|
||||
lastIndex, tokens);
|
||||
}
|
||||
if (matched) continue;
|
||||
throw new Error("Token stream not progressing");
|
||||
if (result === -1) {
|
||||
throw new Error("Token stream not progressing");
|
||||
}
|
||||
lastIndex = result;
|
||||
}
|
||||
return tokens;
|
||||
};
|
||||
}
|
||||
|
||||
class WebIDLParseError {
|
||||
constructor(str, line, input, tokens) {
|
||||
|
@ -46,6 +95,7 @@
|
|||
let line = 1;
|
||||
tokens = tokens.slice();
|
||||
const names = new Map();
|
||||
let current = null;
|
||||
|
||||
const FLOAT = "float";
|
||||
const INT = "integer";
|
||||
|
@ -58,7 +108,7 @@
|
|||
getter: false,
|
||||
setter: false,
|
||||
deleter: false,
|
||||
"static": false,
|
||||
static: false,
|
||||
stringifier: false
|
||||
});
|
||||
|
||||
|
@ -70,8 +120,18 @@
|
|||
tok += tokens[numTokens].value;
|
||||
numTokens++;
|
||||
}
|
||||
throw new WebIDLParseError(str, line, tok, tokens.slice(0, maxTokens));
|
||||
};
|
||||
|
||||
let message;
|
||||
if (current) {
|
||||
message = `Got an error during or right after parsing \`${current.partial ? "partial " : ""}${current.type} ${current.name}\`: ${str}`
|
||||
}
|
||||
else {
|
||||
// throwing before any valid definition
|
||||
message = `Got an error before parsing any named definition: ${str}`;
|
||||
}
|
||||
|
||||
throw new WebIDLParseError(message, line, tok, tokens.slice(0, maxTokens));
|
||||
}
|
||||
|
||||
function sanitize_name(name, type) {
|
||||
if (names.has(name)) {
|
||||
|
@ -87,23 +147,34 @@
|
|||
if (!tokens.length || tokens[0].type !== type) return;
|
||||
if (typeof value === "undefined" || tokens[0].value === value) {
|
||||
last_token = tokens.shift();
|
||||
if (type === ID) last_token.value = last_token.value.replace(/^_/, "");
|
||||
if (type === ID && last_token.value.startsWith('_'))
|
||||
last_token.value = last_token.value.substring(1);
|
||||
return last_token;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
function count(str, char) {
|
||||
let total = 0;
|
||||
for (let i = str.indexOf(char); i !== -1; i = str.indexOf(char, i + 1)) {
|
||||
++total;
|
||||
}
|
||||
return total;
|
||||
}
|
||||
|
||||
function ws() {
|
||||
if (!tokens.length) return;
|
||||
if (tokens[0].type === "whitespace") {
|
||||
const t = tokens.shift();
|
||||
t.value.replace(/\n/g, m => {
|
||||
line++;
|
||||
return m;
|
||||
});
|
||||
line += count(t.value, '\n');
|
||||
return t;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
const all_ws_re = {
|
||||
"ws": /([\t\n\r ]+)/y,
|
||||
"line-comment": /\/\/(.*)\r?\n?/y,
|
||||
"multiline-comment": /\/\*((?:[^*]|\*[^/])*)\*\//y
|
||||
};
|
||||
function all_ws(store, pea) { // pea == post extended attribute, tpea = same for types
|
||||
const t = { type: "whitespace", value: "" };
|
||||
while (true) {
|
||||
|
@ -114,31 +185,30 @@
|
|||
if (t.value.length > 0) {
|
||||
if (store) {
|
||||
let w = t.value;
|
||||
const re = {
|
||||
"ws": /^([\t\n\r ]+)/,
|
||||
"line-comment": /^\/\/(.*)\r?\n?/,
|
||||
"multiline-comment": /^\/\*((?:.|\n|\r)*?)\*\//
|
||||
};
|
||||
const wsTypes = [];
|
||||
for (var k in re) wsTypes.push(k);
|
||||
while (w.length) {
|
||||
let lastIndex = 0;
|
||||
while (lastIndex < w.length) {
|
||||
let matched = false;
|
||||
for (var i in wsTypes) {
|
||||
const type = wsTypes[i];
|
||||
w = w.replace(re[type], (tok, m1) => {
|
||||
store.push({ type: type + (pea ? ("-" + pea) : ""), value: m1 });
|
||||
// Servo doesn't support using "const" in this construction yet.
|
||||
// See https://github.com/servo/servo/issues/20231.
|
||||
// |type| can be made const once Servo supports it.
|
||||
for (let type in all_ws_re) {
|
||||
const re = all_ws_re[type];
|
||||
re.lastIndex = lastIndex;
|
||||
const result = re.exec(w);
|
||||
if (result) {
|
||||
store.push({ type: type + (pea ? ("-" + pea) : ""), value: result[1] });
|
||||
matched = true;
|
||||
return "";
|
||||
});
|
||||
if (matched) break;
|
||||
lastIndex = re.lastIndex;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (matched) continue;
|
||||
throw new Error("Surprising white space construct."); // this shouldn't happen
|
||||
if (!matched)
|
||||
throw new Error("Surprising white space construct."); // this shouldn't happen
|
||||
}
|
||||
}
|
||||
return t;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
function integer_type() {
|
||||
let ret = "";
|
||||
|
@ -153,7 +223,7 @@
|
|||
return ret;
|
||||
}
|
||||
if (ret) error("Failed to parse integer type");
|
||||
};
|
||||
}
|
||||
|
||||
function float_type() {
|
||||
let ret = "";
|
||||
|
@ -163,7 +233,7 @@
|
|||
if (consume(ID, "float")) return ret + "float";
|
||||
if (consume(ID, "double")) return ret + "double";
|
||||
if (ret) error("Failed to parse float type");
|
||||
};
|
||||
}
|
||||
|
||||
function primitive_type() {
|
||||
const num_type = integer_type() || float_type();
|
||||
|
@ -172,7 +242,7 @@
|
|||
if (consume(ID, "boolean")) return "boolean";
|
||||
if (consume(ID, "byte")) return "byte";
|
||||
if (consume(ID, "octet")) return "octet";
|
||||
};
|
||||
}
|
||||
|
||||
function const_value() {
|
||||
if (consume(ID, "true")) return { type: "boolean", value: true };
|
||||
|
@ -187,7 +257,7 @@
|
|||
if (consume(ID, "Infinity")) return { type: "Infinity", negative: true };
|
||||
else tokens.unshift(tok);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
function type_suffix(obj) {
|
||||
while (true) {
|
||||
|
@ -197,11 +267,11 @@
|
|||
obj.nullable = true;
|
||||
} else return;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
function single_type() {
|
||||
function single_type(typeName) {
|
||||
const prim = primitive_type();
|
||||
const ret = { sequence: false, generic: null, nullable: false, union: false };
|
||||
const ret = { type: typeName || null, sequence: false, generic: null, nullable: false, union: false };
|
||||
let name;
|
||||
let value;
|
||||
if (prim) {
|
||||
|
@ -219,7 +289,7 @@
|
|||
const types = [];
|
||||
do {
|
||||
all_ws();
|
||||
types.push(type_with_extended_attributes() || error("Error parsing generic type " + value));
|
||||
types.push(type_with_extended_attributes(typeName) || error("Error parsing generic type " + value));
|
||||
all_ws();
|
||||
}
|
||||
while (consume(OTHER, ","));
|
||||
|
@ -248,12 +318,12 @@
|
|||
type_suffix(ret);
|
||||
if (ret.nullable && ret.idlType === "any") error("Type any cannot be made nullable");
|
||||
return ret;
|
||||
};
|
||||
}
|
||||
|
||||
function union_type() {
|
||||
function union_type(typeName) {
|
||||
all_ws();
|
||||
if (!consume(OTHER, "(")) return;
|
||||
const ret = { sequence: false, generic: null, nullable: false, union: true, idlType: [] };
|
||||
const ret = { type: typeName || null, sequence: false, generic: null, nullable: false, union: true, idlType: [] };
|
||||
const fst = type_with_extended_attributes() || error("Union type with no content");
|
||||
ret.idlType.push(fst);
|
||||
while (true) {
|
||||
|
@ -265,18 +335,18 @@
|
|||
if (!consume(OTHER, ")")) error("Unterminated union type");
|
||||
type_suffix(ret);
|
||||
return ret;
|
||||
};
|
||||
}
|
||||
|
||||
function type() {
|
||||
return single_type() || union_type();
|
||||
};
|
||||
function type(typeName) {
|
||||
return single_type(typeName) || union_type(typeName);
|
||||
}
|
||||
|
||||
function type_with_extended_attributes() {
|
||||
function type_with_extended_attributes(typeName) {
|
||||
const extAttrs = extended_attrs();
|
||||
const ret = single_type() || union_type();
|
||||
const ret = single_type(typeName) || union_type(typeName);
|
||||
if (extAttrs.length && ret) ret.extAttrs = extAttrs;
|
||||
return ret;
|
||||
};
|
||||
}
|
||||
|
||||
function argument(store) {
|
||||
const ret = { optional: false, variadic: false };
|
||||
|
@ -287,7 +357,7 @@
|
|||
ret.optional = true;
|
||||
all_ws();
|
||||
}
|
||||
ret.idlType = type_with_extended_attributes();
|
||||
ret.idlType = type_with_extended_attributes("argument-type");
|
||||
if (!ret.idlType) {
|
||||
if (opt_token) tokens.unshift(opt_token);
|
||||
return;
|
||||
|
@ -322,7 +392,7 @@
|
|||
}
|
||||
}
|
||||
return ret;
|
||||
};
|
||||
}
|
||||
|
||||
function argument_list(store) {
|
||||
const ret = [];
|
||||
|
@ -335,7 +405,7 @@
|
|||
const nxt = argument(store ? ret : null) || error("Trailing comma in arguments list");
|
||||
ret.push(nxt);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
function simple_extended_attr(store) {
|
||||
all_ws();
|
||||
|
@ -386,7 +456,7 @@
|
|||
consume(OTHER, ")") || error("Unexpected token in extended attribute argument list");
|
||||
}
|
||||
return ret;
|
||||
};
|
||||
}
|
||||
|
||||
// Note: we parse something simpler than the official syntax. It's all that ever
|
||||
// seems to be used
|
||||
|
@ -406,7 +476,7 @@
|
|||
all_ws();
|
||||
consume(OTHER, "]") || error("No end of extended attribute");
|
||||
return eas;
|
||||
};
|
||||
}
|
||||
|
||||
function default_() {
|
||||
all_ws();
|
||||
|
@ -420,11 +490,11 @@
|
|||
return { type: "sequence", value: [] };
|
||||
} else {
|
||||
const str = consume(STR) || error("No value for default");
|
||||
str.value = str.value.replace(/^"/, "").replace(/"$/, "");
|
||||
str.value = str.value.slice(1, -1);
|
||||
return str;
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
function const_(store) {
|
||||
all_ws(store, "pea");
|
||||
|
@ -436,7 +506,7 @@
|
|||
typ = consume(ID) || error("No type for const");
|
||||
typ = typ.value;
|
||||
}
|
||||
ret.idlType = typ;
|
||||
ret.idlType = { type: "const-type", idlType: typ };
|
||||
all_ws();
|
||||
if (consume(OTHER, "?")) {
|
||||
ret.nullable = true;
|
||||
|
@ -453,7 +523,7 @@
|
|||
all_ws();
|
||||
consume(OTHER, ";") || error("Unterminated const");
|
||||
return ret;
|
||||
};
|
||||
}
|
||||
|
||||
function inheritance() {
|
||||
all_ws();
|
||||
|
@ -462,7 +532,7 @@
|
|||
const inh = consume(ID) || error("No type in inheritance");
|
||||
return inh.value;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
function operation_rest(ret, store) {
|
||||
all_ws();
|
||||
|
@ -477,7 +547,7 @@
|
|||
all_ws();
|
||||
consume(OTHER, ";") || error("Unterminated operation");
|
||||
return ret;
|
||||
};
|
||||
}
|
||||
|
||||
function callback(store) {
|
||||
all_ws(store, "pea");
|
||||
|
@ -486,12 +556,11 @@
|
|||
all_ws();
|
||||
const tok = consume(ID, "interface");
|
||||
if (tok) {
|
||||
ret = interface_rest();
|
||||
ret.type = "callback interface";
|
||||
ret = interface_rest(false, store, "callback interface");
|
||||
return ret;
|
||||
}
|
||||
const name = consume(ID) || error("No name for callback");
|
||||
ret = { type: "callback", name: sanitize_name(name.value, "callback") };
|
||||
ret = current = { type: "callback", name: sanitize_name(name.value, "callback") };
|
||||
all_ws();
|
||||
consume(OTHER, "=") || error("No assignment in callback");
|
||||
all_ws();
|
||||
|
@ -504,14 +573,14 @@
|
|||
all_ws();
|
||||
consume(OTHER, ";") || error("Unterminated callback");
|
||||
return ret;
|
||||
};
|
||||
}
|
||||
|
||||
function attribute(store) {
|
||||
all_ws(store, "pea");
|
||||
const grabbed = [];
|
||||
const ret = {
|
||||
type: "attribute",
|
||||
"static": false,
|
||||
static: false,
|
||||
stringifier: false,
|
||||
inherit: false,
|
||||
readonly: false
|
||||
|
@ -519,7 +588,7 @@
|
|||
const w = all_ws();
|
||||
if (w) grabbed.push(w);
|
||||
if (consume(ID, "inherit")) {
|
||||
if (ret["static"] || ret.stringifier) error("Cannot have a static or stringifier inherit");
|
||||
if (ret.static || ret.stringifier) error("Cannot have a static or stringifier inherit");
|
||||
ret.inherit = true;
|
||||
grabbed.push(last_token);
|
||||
const w = all_ws();
|
||||
|
@ -536,14 +605,14 @@
|
|||
tokens = grabbed.concat(tokens);
|
||||
}
|
||||
return rest;
|
||||
};
|
||||
}
|
||||
|
||||
function attribute_rest(ret) {
|
||||
if (!consume(ID, "attribute")) {
|
||||
return;
|
||||
}
|
||||
all_ws();
|
||||
ret.idlType = type_with_extended_attributes() || error("No type in attribute");
|
||||
ret.idlType = type_with_extended_attributes("attribute-type") || error("No type in attribute");
|
||||
if (ret.idlType.sequence) error("Attributes cannot accept sequence types");
|
||||
if (ret.idlType.generic === "record") error("Attributes cannot accept record types");
|
||||
all_ws();
|
||||
|
@ -552,17 +621,17 @@
|
|||
all_ws();
|
||||
consume(OTHER, ";") || error("Unterminated attribute");
|
||||
return ret;
|
||||
};
|
||||
}
|
||||
|
||||
function return_type() {
|
||||
const typ = type();
|
||||
const typ = type("return-type");
|
||||
if (!typ) {
|
||||
if (consume(ID, "void")) {
|
||||
return "void";
|
||||
} else error("No return type");
|
||||
}
|
||||
return typ;
|
||||
};
|
||||
}
|
||||
|
||||
function operation(store) {
|
||||
all_ws(store, "pea");
|
||||
|
@ -582,24 +651,9 @@
|
|||
}
|
||||
ret.idlType = return_type();
|
||||
all_ws();
|
||||
if (consume(ID, "iterator")) {
|
||||
all_ws();
|
||||
ret.type = "iterator";
|
||||
if (consume(ID, "object")) {
|
||||
ret.iteratorObject = "object";
|
||||
} else if (consume(OTHER, "=")) {
|
||||
all_ws();
|
||||
var name = consume(ID) || error("No right hand side in iterator");
|
||||
ret.iteratorObject = name.value;
|
||||
}
|
||||
all_ws();
|
||||
consume(OTHER, ";") || error("Unterminated iterator");
|
||||
return ret;
|
||||
} else {
|
||||
operation_rest(ret, store);
|
||||
return ret;
|
||||
}
|
||||
};
|
||||
operation_rest(ret, store);
|
||||
return ret;
|
||||
}
|
||||
|
||||
function static_member(store) {
|
||||
all_ws(store, "pea");
|
||||
|
@ -631,7 +685,7 @@
|
|||
arr.push(name.value);
|
||||
} else break;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
function iterable_type() {
|
||||
if (consume(ID, "iterable")) return "iterable";
|
||||
|
@ -639,13 +693,13 @@
|
|||
else if (consume(ID, "maplike")) return "maplike";
|
||||
else if (consume(ID, "setlike")) return "setlike";
|
||||
else return;
|
||||
};
|
||||
}
|
||||
|
||||
function readonly_iterable_type() {
|
||||
if (consume(ID, "maplike")) return "maplike";
|
||||
else if (consume(ID, "setlike")) return "setlike";
|
||||
else return;
|
||||
};
|
||||
}
|
||||
|
||||
function iterable(store) {
|
||||
all_ws(store, "pea");
|
||||
|
@ -672,17 +726,14 @@
|
|||
delete ret.readonly;
|
||||
all_ws();
|
||||
if (consume(OTHER, "<")) {
|
||||
ret.idlType = type_with_extended_attributes() || error(`Error parsing ${ittype} declaration`);
|
||||
ret.idlType = [type_with_extended_attributes()] || error(`Error parsing ${ittype} declaration`);
|
||||
all_ws();
|
||||
if (secondTypeAllowed) {
|
||||
let type2 = null;
|
||||
if (consume(OTHER, ",")) {
|
||||
all_ws();
|
||||
type2 = type_with_extended_attributes();
|
||||
ret.idlType.push(type_with_extended_attributes());
|
||||
all_ws();
|
||||
}
|
||||
if (type2)
|
||||
ret.idlType = [ret.idlType, type2];
|
||||
else if (secondTypeRequired)
|
||||
error(`Missing second type argument in ${ittype} declaration`);
|
||||
}
|
||||
|
@ -693,16 +744,16 @@
|
|||
error(`Error parsing ${ittype} declaration`);
|
||||
|
||||
return ret;
|
||||
};
|
||||
}
|
||||
|
||||
function interface_rest(isPartial, store) {
|
||||
function interface_rest(isPartial, store, typeName = "interface") {
|
||||
all_ws();
|
||||
const name = consume(ID) || error("No name for interface");
|
||||
const mems = [];
|
||||
const ret = {
|
||||
type: "interface",
|
||||
const ret = current = {
|
||||
type: typeName,
|
||||
name: isPartial ? name.value : sanitize_name(name.value, "interface"),
|
||||
partial: false,
|
||||
partial: isPartial,
|
||||
members: mems
|
||||
};
|
||||
if (!isPartial) ret.inheritance = inheritance() || null;
|
||||
|
@ -733,7 +784,7 @@
|
|||
mem.extAttrs = ea;
|
||||
ret.members.push(mem);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
function mixin_rest(isPartial, store) {
|
||||
all_ws();
|
||||
|
@ -741,10 +792,10 @@
|
|||
all_ws();
|
||||
const name = consume(ID) || error("No name for interface mixin");
|
||||
const mems = [];
|
||||
const ret = {
|
||||
const ret = current = {
|
||||
type: "interface mixin",
|
||||
name: isPartial ? name.value : sanitize_name(name.value, "interface mixin"),
|
||||
partial: false,
|
||||
partial: isPartial,
|
||||
members: mems
|
||||
};
|
||||
all_ws();
|
||||
|
@ -787,7 +838,7 @@
|
|||
all_ws();
|
||||
const name = consume(ID) || error("No name for namespace");
|
||||
const mems = [];
|
||||
const ret = {
|
||||
const ret = current = {
|
||||
type: "namespace",
|
||||
name: isPartial ? name.value : sanitize_name(name.value, "namespace"),
|
||||
partial: isPartial,
|
||||
|
@ -817,7 +868,7 @@
|
|||
const grabbed = [];
|
||||
const ret = {
|
||||
type: "attribute",
|
||||
"static": false,
|
||||
static: false,
|
||||
stringifier: false,
|
||||
inherit: false,
|
||||
readonly: false
|
||||
|
@ -856,9 +907,8 @@
|
|||
interface_(true, store) ||
|
||||
namespace(true, store) ||
|
||||
error("Partial doesn't apply to anything");
|
||||
thing.partial = true;
|
||||
return thing;
|
||||
};
|
||||
}
|
||||
|
||||
function dictionary(isPartial, store) {
|
||||
all_ws(isPartial ? null : store, "pea");
|
||||
|
@ -866,10 +916,10 @@
|
|||
all_ws();
|
||||
const name = consume(ID) || error("No name for dictionary");
|
||||
const mems = [];
|
||||
const ret = {
|
||||
const ret = current = {
|
||||
type: "dictionary",
|
||||
name: isPartial ? name.value : sanitize_name(name.value, "dictionary"),
|
||||
partial: false,
|
||||
partial: isPartial,
|
||||
members: mems
|
||||
};
|
||||
if (!isPartial) ret.inheritance = inheritance() || null;
|
||||
|
@ -885,7 +935,7 @@
|
|||
const ea = extended_attrs(store ? mems : null);
|
||||
all_ws(store ? mems : null, "pea");
|
||||
const required = consume(ID, "required");
|
||||
const typ = type_with_extended_attributes() || error("No type for dictionary member");
|
||||
const typ = type_with_extended_attributes("dictionary-type") || error("No type for dictionary member");
|
||||
all_ws();
|
||||
const name = consume(ID) || error("No name for dictionary member");
|
||||
const dflt = default_();
|
||||
|
@ -904,7 +954,7 @@
|
|||
all_ws();
|
||||
consume(OTHER, ";") || error("Unterminated dictionary member");
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
function enum_(store) {
|
||||
all_ws(store, "pea");
|
||||
|
@ -912,7 +962,7 @@
|
|||
all_ws();
|
||||
const name = consume(ID) || error("No name for enum");
|
||||
const vals = [];
|
||||
const ret = {
|
||||
const ret = current = {
|
||||
type: "enum",
|
||||
name: sanitize_name(name.value, "enum"),
|
||||
values: vals
|
||||
|
@ -928,7 +978,7 @@
|
|||
return ret;
|
||||
}
|
||||
const val = consume(STR) || error("Unexpected value in enum");
|
||||
val.value = val.value.replace(/"/g, "");
|
||||
val.value = val.value.slice(1, -1);
|
||||
ret.values.push(val);
|
||||
all_ws(store ? vals : null);
|
||||
if (consume(OTHER, ",")) {
|
||||
|
@ -939,7 +989,7 @@
|
|||
saw_comma = false;
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
function typedef(store) {
|
||||
all_ws(store, "pea");
|
||||
|
@ -948,14 +998,15 @@
|
|||
type: "typedef"
|
||||
};
|
||||
all_ws();
|
||||
ret.idlType = type_with_extended_attributes() || error("No type in typedef");
|
||||
ret.idlType = type_with_extended_attributes("typedef-type") || error("No type in typedef");
|
||||
all_ws();
|
||||
const name = consume(ID) || error("No name in typedef");
|
||||
ret.name = sanitize_name(name.value, "typedef");
|
||||
current = ret;
|
||||
all_ws();
|
||||
consume(OTHER, ";") || error("Unterminated typedef");
|
||||
return ret;
|
||||
};
|
||||
}
|
||||
|
||||
function implements_(store) {
|
||||
all_ws(store, "pea");
|
||||
|
@ -978,7 +1029,7 @@
|
|||
tokens.unshift(w);
|
||||
tokens.unshift(target);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
function includes(store) {
|
||||
all_ws(store, "pea");
|
||||
|
@ -1001,7 +1052,7 @@
|
|||
tokens.unshift(w);
|
||||
tokens.unshift(target);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
function definition(store) {
|
||||
return callback(store) ||
|
||||
|
@ -1013,7 +1064,7 @@
|
|||
implements_(store) ||
|
||||
includes(store) ||
|
||||
namespace(false, store);
|
||||
};
|
||||
}
|
||||
|
||||
function definitions(store) {
|
||||
if (!tokens.length) return [];
|
||||
|
@ -1029,11 +1080,11 @@
|
|||
defs.push(def);
|
||||
}
|
||||
return defs;
|
||||
};
|
||||
}
|
||||
const res = definitions(opt.ws);
|
||||
if (tokens.length) error("Unrecognised tokens");
|
||||
return res;
|
||||
};
|
||||
}
|
||||
|
||||
const obj = {
|
||||
parse(str, opt) {
|
||||
|
|
|
@ -1,78 +1,71 @@
|
|||
(function() {
|
||||
"use strict";
|
||||
|
||||
var write = function(ast, opt) {
|
||||
var curPea = "",
|
||||
curTPea = "",
|
||||
opt = opt || {},
|
||||
noop = function(str) {
|
||||
return str; },
|
||||
optNames = "type".split(" "),
|
||||
context = [];
|
||||
for (var i = 0, n = optNames.length; i < n; i++) {
|
||||
var o = optNames[i];
|
||||
(() => {
|
||||
function write(ast, opt = {}) {
|
||||
let curPea = "";
|
||||
let curTPea = "";
|
||||
const noop = str => str;
|
||||
const optNames = "type".split(" ");
|
||||
const context = [];
|
||||
for (const o of optNames) {
|
||||
if (!opt[o]) opt[o] = noop;
|
||||
}
|
||||
|
||||
var literal = function(it) {
|
||||
function literal(it) {
|
||||
return it.value;
|
||||
};
|
||||
var wsPea = function(it) {
|
||||
function wsPea(it) {
|
||||
curPea += it.value;
|
||||
return "";
|
||||
};
|
||||
var wsTPea = function(it) {
|
||||
function wsTPea(it) {
|
||||
curTPea += it.value;
|
||||
return "";
|
||||
};
|
||||
var lineComment = function(it) {
|
||||
return "//" + it.value + "\n";
|
||||
function lineComment(it) {
|
||||
return `//${it.value}\n`;
|
||||
};
|
||||
var multilineComment = function(it) {
|
||||
return "/*" + it.value + "*/";
|
||||
function multilineComment(it) {
|
||||
return `/*${it.value}*/`;
|
||||
};
|
||||
var type = function(it) {
|
||||
function type(it) {
|
||||
if (typeof it === "string") return opt.type(it); // XXX should maintain some context
|
||||
if (it.union) return "(" + it.idlType.map(type).join(" or ") + ")";
|
||||
var ret = "";
|
||||
if (it.generic) ret += it.generic + "<";
|
||||
else if (it.sequence) ret += "sequence<";
|
||||
if (Array.isArray(it.idlType)) ret += it.idlType.map(type).join(", ");
|
||||
else ret += type(it.idlType);
|
||||
if (it.array || it.generic === 'Array') {
|
||||
for (var i = 0, n = it.nullableArray.length; i < n; i++) {
|
||||
var val = it.nullableArray[i];
|
||||
if (val) ret += "?";
|
||||
ret += "[]";
|
||||
}
|
||||
let ret = extended_attributes(it.extAttrs, curPea);
|
||||
if (it.union) ret += `(${it.idlType.map(type).join(" or ")})`;
|
||||
else {
|
||||
if (it.generic) ret += `${it.generic}<`;
|
||||
if (Array.isArray(it.idlType)) ret += it.idlType.map(type).join(", ");
|
||||
else ret += type(it.idlType);
|
||||
if (it.generic) ret += ">";
|
||||
}
|
||||
if (it.generic || it.sequence) ret += ">";
|
||||
if (it.nullable) ret += "?";
|
||||
|
||||
return ret;
|
||||
};
|
||||
var const_value = function(it) {
|
||||
var tp = it.type;
|
||||
function const_value(it) {
|
||||
const tp = it.type;
|
||||
if (tp === "boolean") return it.value ? "true" : "false";
|
||||
else if (tp === "null") return "null";
|
||||
else if (tp === "Infinity") return (it.negative ? "-" : "") + "Infinity";
|
||||
else if (tp === "NaN") return "NaN";
|
||||
else if (tp === "number") return it.value;
|
||||
else return '"' + it.value + '"';
|
||||
else if (tp === "sequence") return "[]";
|
||||
else return `"${it.value}"`;
|
||||
};
|
||||
var argument = function(arg, pea) {
|
||||
var ret = extended_attributes(arg.extAttrs, pea);
|
||||
function argument(arg, pea) {
|
||||
let ret = extended_attributes(arg.extAttrs, pea);
|
||||
if (arg.optional) ret += "optional ";
|
||||
ret += type(arg.idlType);
|
||||
if (arg.variadic) ret += "...";
|
||||
ret += " " + arg.name;
|
||||
if (arg["default"]) ret += " = " + const_value(arg["default"]);
|
||||
ret += ` ${arg.name}`;
|
||||
if (arg["default"]) ret += ` = ${const_value(arg["default"])}`;
|
||||
return ret;
|
||||
};
|
||||
var args = function(its) {
|
||||
var res = "",
|
||||
pea = "";
|
||||
for (var i = 0, n = its.length; i < n; i++) {
|
||||
var arg = its[i];
|
||||
function args(its) {
|
||||
let res = "";
|
||||
let pea = "";
|
||||
for (let i = 0, n = its.length; i < n; i++) {
|
||||
const arg = its[i];
|
||||
if (arg.type === "ws") res += arg.value;
|
||||
else if (arg.type === "ws-pea") pea += arg.value;
|
||||
else {
|
||||
|
@ -83,182 +76,198 @@
|
|||
}
|
||||
return res;
|
||||
};
|
||||
var make_ext_at = function(it) {
|
||||
if (it["arguments"] === null) return it.name;
|
||||
function make_ext_at(it) {
|
||||
context.unshift(it);
|
||||
var ret = it.name + "(" + (it["arguments"].length ? args(it["arguments"]) : "") + ")";
|
||||
let ret = it.name;
|
||||
if (it.rhs) {
|
||||
if (it.rhs.type === "identifier-list") ret += `=(${it.rhs.value.join(',')})`;
|
||||
else ret += `=${it.rhs.value}`;
|
||||
}
|
||||
if (it.arguments) ret += `(${it["arguments"].length ? args(it["arguments"]) : ""})`;
|
||||
context.shift(); // XXX need to add more contexts, but not more than needed for ReSpec
|
||||
return ret;
|
||||
};
|
||||
var extended_attributes = function(eats, pea) {
|
||||
function extended_attributes(eats, pea) {
|
||||
if (!eats || !eats.length) return "";
|
||||
return "[" + eats.map(make_ext_at).join(", ") + "]" + pea;
|
||||
return `[${eats.map(make_ext_at).join(", ")}]${pea}`;
|
||||
};
|
||||
|
||||
var modifiers = "getter setter creator deleter legacycaller stringifier static".split(" ");
|
||||
var operation = function(it) {
|
||||
var ret = extended_attributes(it.extAttrs, curPea);
|
||||
const modifiers = "getter setter creator deleter legacycaller stringifier static".split(" ");
|
||||
function operation(it) {
|
||||
let ret = extended_attributes(it.extAttrs, curPea);
|
||||
curPea = "";
|
||||
if (it.stringifier && !it.idlType) return "stringifier;";
|
||||
for (var i = 0, n = modifiers.length; i < n; i++) {
|
||||
var mod = modifiers[i];
|
||||
for (const mod of modifiers) {
|
||||
if (it[mod]) ret += mod + " ";
|
||||
}
|
||||
ret += type(it.idlType) + " ";
|
||||
if (it.name) ret += it.name;
|
||||
ret += "(" + args(it["arguments"]) + ");";
|
||||
ret += `(${args(it["arguments"])});`;
|
||||
return ret;
|
||||
};
|
||||
|
||||
var attribute = function(it) {
|
||||
var ret = extended_attributes(it.extAttrs, curPea);
|
||||
function attribute(it) {
|
||||
let ret = extended_attributes(it.extAttrs, curPea);
|
||||
curPea = "";
|
||||
if (it["static"]) ret += "static ";
|
||||
if (it.stringifier) ret += "stringifier ";
|
||||
if (it.readonly) ret += "readonly ";
|
||||
if (it.inherit) ret += "inherit ";
|
||||
ret += "attribute " + type(it.idlType) + " " + it.name + ";";
|
||||
ret += `attribute ${type(it.idlType)} ${it.name};`;
|
||||
return ret;
|
||||
};
|
||||
|
||||
var interface_ = function(it) {
|
||||
var ret = extended_attributes(it.extAttrs, curPea);
|
||||
function interface_(it) {
|
||||
let ret = extended_attributes(it.extAttrs, curPea);
|
||||
curPea = "";
|
||||
if (it.partial) ret += "partial ";
|
||||
ret += "interface " + it.name + " ";
|
||||
if (it.inheritance) ret += ": " + it.inheritance + " ";
|
||||
ret += "{" + iterate(it.members) + "};";
|
||||
ret += `interface ${it.name} `;
|
||||
if (it.inheritance) ret += `: ${it.inheritance} `;
|
||||
ret += `{${iterate(it.members)}};`;
|
||||
return ret;
|
||||
};
|
||||
|
||||
var dictionary = function(it) {
|
||||
var ret = extended_attributes(it.extAttrs, curPea);
|
||||
function interface_mixin(it) {
|
||||
let ret = extended_attributes(it.extAttrs, curPea);
|
||||
curPea = "";
|
||||
if (it.partial) ret += "partial ";
|
||||
ret += "dictionary " + it.name + " ";
|
||||
ret += "{" + iterate(it.members) + "};";
|
||||
ret += `interface mixin ${it.name} `;
|
||||
ret += `{${iterate(it.members)}};`;
|
||||
return ret;
|
||||
}
|
||||
|
||||
function namespace(it) {
|
||||
let ret = extended_attributes(it.extAttrs, curPea);
|
||||
curPea = "";
|
||||
if (it.partial) ret += "partial ";
|
||||
ret += `namespace ${it.name} `;
|
||||
ret += `{${iterate(it.members)}};`;
|
||||
return ret;
|
||||
}
|
||||
|
||||
function dictionary(it) {
|
||||
let ret = extended_attributes(it.extAttrs, curPea);
|
||||
curPea = "";
|
||||
if (it.partial) ret += "partial ";
|
||||
ret += `dictionary ${it.name} `;
|
||||
if (it.inheritance) ret += `: ${it.inheritance} `;
|
||||
ret += `{${iterate(it.members)}};`;
|
||||
return ret;
|
||||
};
|
||||
var field = function(it) {
|
||||
var ret = extended_attributes(it.extAttrs, curPea);
|
||||
function field(it) {
|
||||
let ret = extended_attributes(it.extAttrs, curPea);
|
||||
curPea = "";
|
||||
if (it.required) ret += "required ";
|
||||
ret += type(it.idlType) + " " + it.name;
|
||||
if (it["default"]) ret += " = " + const_value(it["default"]);
|
||||
ret += `${type(it.idlType)} ${it.name}`;
|
||||
if (it["default"]) ret += ` = ${const_value(it["default"])}`;
|
||||
ret += ";";
|
||||
return ret;
|
||||
};
|
||||
var exception = function(it) {
|
||||
var ret = extended_attributes(it.extAttrs, curPea);
|
||||
function const_(it) {
|
||||
const ret = extended_attributes(it.extAttrs, curPea);
|
||||
curPea = "";
|
||||
ret += "exception " + it.name + " ";
|
||||
if (it.inheritance) ret += ": " + it.inheritance + " ";
|
||||
ret += "{" + iterate(it.members) + "};";
|
||||
return ret;
|
||||
return `${ret}const ${type(it.idlType)}${it.nullable ? "?" : ""} ${it.name} = ${const_value(it.value)};`;
|
||||
};
|
||||
var const_ = function(it) {
|
||||
var ret = extended_attributes(it.extAttrs, curPea);
|
||||
function typedef(it) {
|
||||
let ret = extended_attributes(it.extAttrs, curPea);
|
||||
curPea = "";
|
||||
return ret + "const " + type(it.idlType) + " " + it.name + " = " + const_value(it.value) + ";";
|
||||
};
|
||||
var typedef = function(it) {
|
||||
var ret = extended_attributes(it.extAttrs, curPea);
|
||||
curPea = "";
|
||||
ret += "typedef " + extended_attributes(it.typeExtAttrs, curTPea);
|
||||
ret += `typedef ${extended_attributes(it.typeExtAttrs, curTPea)}`;
|
||||
curTPea = "";
|
||||
return ret + type(it.idlType) + " " + it.name + ";";
|
||||
return `${ret}${type(it.idlType)} ${it.name};`;
|
||||
};
|
||||
var implements_ = function(it) {
|
||||
var ret = extended_attributes(it.extAttrs, curPea);
|
||||
function implements_(it) {
|
||||
const ret = extended_attributes(it.extAttrs, curPea);
|
||||
curPea = "";
|
||||
return ret + it.target + " implements " + it["implements"] + ";";
|
||||
return `${ret}${it.target} implements ${it["implements"]};`;
|
||||
};
|
||||
var callback = function(it) {
|
||||
var ret = extended_attributes(it.extAttrs, curPea);
|
||||
function includes(it) {
|
||||
const ret = extended_attributes(it.extAttrs, curPea);
|
||||
curPea = "";
|
||||
return ret + "callback " + it.name + " = " + type(it.idlType) +
|
||||
"(" + args(it["arguments"]) + ");";
|
||||
return `${ret}${it.target} includes ${it.includes};`;
|
||||
};
|
||||
var enum_ = function(it) {
|
||||
var ret = extended_attributes(it.extAttrs, curPea);
|
||||
function callback(it) {
|
||||
const ret = extended_attributes(it.extAttrs, curPea);
|
||||
curPea = "";
|
||||
ret += "enum " + it.name + " {";
|
||||
for (var i = 0, n = it.values.length; i < n; i++) {
|
||||
var v = it.values[i];
|
||||
if (typeof v === "string") ret += '"' + v + '"';
|
||||
return `${ret}callback ${it.name} = ${type(it.idlType)}(${args(it["arguments"])});`;
|
||||
};
|
||||
function enum_(it) {
|
||||
let ret = extended_attributes(it.extAttrs, curPea);
|
||||
curPea = "";
|
||||
ret += `enum ${it.name} {`;
|
||||
for (const v of it.values) {
|
||||
if (v.type === "string") ret += `"${v.value}"`;
|
||||
else if (v.type === "ws") ret += v.value;
|
||||
else if (v.type === ",") ret += ",";
|
||||
}
|
||||
return ret + "};";
|
||||
};
|
||||
var iterable = function(it) {
|
||||
return "iterable<" + (it.idlType instanceof Array ? it.idlType.map(type).join(", ") : type(it.idlType)) + ">;";
|
||||
function iterable(it) {
|
||||
return `iterable<${Array.isArray(it.idlType) ? it.idlType.map(type).join(", ") : type(it.idlType)}>;`;
|
||||
};
|
||||
var legacyiterable = function(it) {
|
||||
return "legacyiterable<" + (it.idlType instanceof Array ? it.idlType.map(type).join(", ") : type(it.idlType)) + ">;";
|
||||
function legacyiterable(it) {
|
||||
return `legacyiterable<${Array.isArray(it.idlType) ? it.idlType.map(type).join(", ") : type(it.idlType)}>;`;
|
||||
};
|
||||
var maplike = function(it) {
|
||||
return (it.readonly ? "readonly " : "") + "maplike<" +
|
||||
it.idlType.map(type).join(", ") + ">;";
|
||||
function maplike(it) {
|
||||
return `${it.readonly ? "readonly " : ""}maplike<${it.idlType.map(type).join(", ")}>;`;
|
||||
};
|
||||
var setlike = function(it) {
|
||||
return (it.readonly ? "readonly " : "") + "setlike<" +
|
||||
type(it.idlType) + ">;";
|
||||
function setlike(it) {
|
||||
return `${it.readonly ? "readonly " : ""}setlike<${type(it.idlType[0])}>;`;
|
||||
};
|
||||
var callbackInterface = function(it) {
|
||||
return 'callback ' + interface_(it);
|
||||
function callbackInterface(it) {
|
||||
return `callback ${interface_(it)}`;
|
||||
};
|
||||
|
||||
var table = {
|
||||
const table = {
|
||||
ws: literal,
|
||||
"ws-pea": wsPea,
|
||||
"ws-tpea": wsTPea,
|
||||
"line-comment": lineComment,
|
||||
"multiline-comment": multilineComment,
|
||||
"interface": interface_,
|
||||
operation: operation,
|
||||
attribute: attribute,
|
||||
dictionary: dictionary,
|
||||
field: field,
|
||||
exception: exception,
|
||||
"const": const_,
|
||||
typedef: typedef,
|
||||
"implements": implements_,
|
||||
callback: callback,
|
||||
"enum": enum_,
|
||||
iterable: iterable,
|
||||
legacyiterable: legacyiterable,
|
||||
maplike: maplike,
|
||||
setlike: setlike,
|
||||
interface: interface_,
|
||||
"interface mixin": interface_mixin,
|
||||
namespace,
|
||||
operation,
|
||||
attribute,
|
||||
dictionary,
|
||||
field,
|
||||
const: const_,
|
||||
typedef,
|
||||
implements: implements_,
|
||||
includes,
|
||||
callback,
|
||||
enum: enum_,
|
||||
iterable,
|
||||
legacyiterable,
|
||||
maplike,
|
||||
setlike,
|
||||
"callback interface": callbackInterface
|
||||
};
|
||||
var dispatch = function(it) {
|
||||
function dispatch(it) {
|
||||
const dispatcher = table[it.type];
|
||||
if (!dispatcher) {
|
||||
throw new Error(`Type "${it.type}" is unsupported`)
|
||||
}
|
||||
return table[it.type](it);
|
||||
};
|
||||
var iterate = function(things) {
|
||||
function iterate(things) {
|
||||
if (!things) return;
|
||||
var ret = "";
|
||||
for (var i = 0, n = things.length; i < n; i++) ret += dispatch(things[i]);
|
||||
let ret = "";
|
||||
for (const thing of things) ret += dispatch(thing);
|
||||
return ret;
|
||||
};
|
||||
return iterate(ast);
|
||||
};
|
||||
|
||||
|
||||
var obj = {
|
||||
write: function(ast, opt) {
|
||||
if (!opt) opt = {};
|
||||
return write(ast, opt);
|
||||
}
|
||||
const obj = {
|
||||
write
|
||||
};
|
||||
|
||||
if (typeof module !== 'undefined' && typeof module.exports !== 'undefined') {
|
||||
module.exports = obj;
|
||||
} else if (typeof define === 'function' && define.amd) {
|
||||
define([], function() {
|
||||
return obj;
|
||||
});
|
||||
define([], () => obj);
|
||||
} else {
|
||||
(self || window).WebIDL2Writer = obj;
|
||||
}
|
||||
}());
|
||||
})();
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue