aboutsummaryrefslogtreecommitdiffstats
path: root/tests/wpt/web-platform-tests/resources/webidl2/lib/webidl2.js
diff options
context:
space:
mode:
authorWPT Sync Bot <josh+wptsync@joshmatthews.net>2019-08-16 10:23:22 +0000
committerWPT Sync Bot <josh+wptsync@joshmatthews.net>2019-08-16 14:22:21 +0000
commit02a68a38f02bb1b98489e5bd58cc078689e81280 (patch)
treee8c09949c32de3a5e5c5a2e640949d4c1948eb64 /tests/wpt/web-platform-tests/resources/webidl2/lib/webidl2.js
parentc585f4fff5696b4c048be2c763e27671028e83dc (diff)
downloadservo-02a68a38f02bb1b98489e5bd58cc078689e81280.tar.gz
servo-02a68a38f02bb1b98489e5bd58cc078689e81280.zip
Update web-platform-tests to revision 936827a6527f1c53051d3bc5bc79304c88c0737f
Diffstat (limited to 'tests/wpt/web-platform-tests/resources/webidl2/lib/webidl2.js')
-rw-r--r--tests/wpt/web-platform-tests/resources/webidl2/lib/webidl2.js2239
1 files changed, 1386 insertions, 853 deletions
diff --git a/tests/wpt/web-platform-tests/resources/webidl2/lib/webidl2.js b/tests/wpt/web-platform-tests/resources/webidl2/lib/webidl2.js
index 9cb975a8bb3..900694b095d 100644
--- a/tests/wpt/web-platform-tests/resources/webidl2/lib/webidl2.js
+++ b/tests/wpt/web-platform-tests/resources/webidl2/lib/webidl2.js
@@ -103,10 +103,10 @@ __webpack_require__.r(__webpack_exports__);
/* harmony import */ var _lib_webidl2_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(1);
/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "parse", function() { return _lib_webidl2_js__WEBPACK_IMPORTED_MODULE_0__["parse"]; });
-/* harmony import */ var _lib_writer_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(14);
+/* harmony import */ var _lib_writer_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(29);
/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "write", function() { return _lib_writer_js__WEBPACK_IMPORTED_MODULE_1__["write"]; });
-/* harmony import */ var _lib_validator_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(15);
+/* harmony import */ var _lib_validator_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(30);
/* harmony reexport (safe) */ __webpack_require__.d(__webpack_exports__, "validate", function() { return _lib_validator_js__WEBPACK_IMPORTED_MODULE_2__["validate"]; });
@@ -121,14 +121,20 @@ __webpack_require__.r(__webpack_exports__);
"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "parse", function() { return parse; });
-/* harmony import */ var _productions_helpers_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(2);
-/* harmony import */ var _tokeniser_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(5);
-/* harmony import */ var _productions_base_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(4);
-/* harmony import */ var _productions_default_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(8);
-/* harmony import */ var _productions_enum_js__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(12);
-/* harmony import */ var _productions_includes_js__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(13);
-/* harmony import */ var _productions_type_js__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(3);
-/* harmony import */ var _productions_extended_attributes_js__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(9);
+/* harmony import */ var _tokeniser_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(2);
+/* harmony import */ var _productions_enum_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(4);
+/* harmony import */ var _productions_includes_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(16);
+/* harmony import */ var _productions_extended_attributes_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(11);
+/* harmony import */ var _productions_typedef_js__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(17);
+/* harmony import */ var _productions_callback_js__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(18);
+/* harmony import */ var _productions_interface_js__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(19);
+/* harmony import */ var _productions_mixin_js__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(24);
+/* harmony import */ var _productions_dictionary_js__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(25);
+/* harmony import */ var _productions_namespace_js__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(27);
+/* harmony import */ var _productions_callback_interface_js__WEBPACK_IMPORTED_MODULE_10__ = __webpack_require__(28);
+
+
+
@@ -148,496 +154,502 @@ __webpack_require__.r(__webpack_exports__);
function parseByTokens(tokeniser, options) {
const source = tokeniser.source;
- const ID = "identifier";
-
function error(str) {
tokeniser.error(str);
}
- function probe(type) {
- return tokeniser.probe(type);
- }
-
function consume(...candidates) {
return tokeniser.consume(...candidates);
}
- function unconsume(position) {
- return tokeniser.unconsume(position);
+ function callback() {
+ const callback = consume("callback");
+ if (!callback) return;
+ if (tokeniser.probe("interface")) {
+ return _productions_callback_interface_js__WEBPACK_IMPORTED_MODULE_10__["CallbackInterface"].parse(tokeniser, callback);
+ }
+ return _productions_callback_js__WEBPACK_IMPORTED_MODULE_5__["CallbackFunction"].parse(tokeniser, callback);
}
- class Constant extends _productions_base_js__WEBPACK_IMPORTED_MODULE_2__["Base"] {
- static parse() {
- const tokens = {};
- tokens.base = consume("const");
- if (!tokens.base) {
- return;
- }
- let idlType = Object(_productions_helpers_js__WEBPACK_IMPORTED_MODULE_0__["primitive_type"])(tokeniser);
- if (!idlType) {
- const base = consume(ID) || error("No type for const");
- idlType = new _productions_type_js__WEBPACK_IMPORTED_MODULE_6__["Type"]({ source, tokens: { base } });
- }
- if (probe("?")) {
- error("Unexpected nullable constant type");
- }
- idlType.type = "const-type";
- tokens.name = consume(ID) || error("No name for const");
- tokens.assign = consume("=") || error("No value assignment for const");
- tokens.value = Object(_productions_helpers_js__WEBPACK_IMPORTED_MODULE_0__["const_value"])(tokeniser) || error("No value for const");
- tokens.termination = consume(";") || error("Unterminated const");
- const ret = new Constant({ source, tokens });
- ret.idlType = idlType;
- return ret;
- }
+ function interface_(opts) {
+ const base = consume("interface");
+ if (!base) return;
+ const ret = _productions_mixin_js__WEBPACK_IMPORTED_MODULE_7__["Mixin"].parse(tokeniser, base, opts) ||
+ _productions_interface_js__WEBPACK_IMPORTED_MODULE_6__["Interface"].parse(tokeniser, base, opts) ||
+ error("Interface has no proper body");
+ return ret;
+ }
- get type() {
- return "const";
- }
- get name() {
- return Object(_productions_helpers_js__WEBPACK_IMPORTED_MODULE_0__["unescape"])(this.tokens.name.value);
- }
- get value() {
- return Object(_productions_helpers_js__WEBPACK_IMPORTED_MODULE_0__["const_data"])(this.tokens.value);
- }
+ function partial() {
+ const partial = consume("partial");
+ if (!partial) return;
+ return _productions_dictionary_js__WEBPACK_IMPORTED_MODULE_8__["Dictionary"].parse(tokeniser, { partial }) ||
+ interface_({ partial }) ||
+ _productions_namespace_js__WEBPACK_IMPORTED_MODULE_9__["Namespace"].parse(tokeniser, { partial }) ||
+ error("Partial doesn't apply to anything");
}
- class CallbackFunction extends _productions_base_js__WEBPACK_IMPORTED_MODULE_2__["Base"] {
- static parse(base) {
- const tokens = { base };
- const ret = new CallbackFunction({ source, tokens });
- tokens.name = consume(ID) || error("No name for callback");
- tokeniser.current = ret;
- tokens.assign = consume("=") || error("No assignment in callback");
- ret.idlType = Object(_productions_helpers_js__WEBPACK_IMPORTED_MODULE_0__["return_type"])(tokeniser) || error("Missing return type");
- tokens.open = consume("(") || error("No arguments in callback");
- ret.arguments = Object(_productions_helpers_js__WEBPACK_IMPORTED_MODULE_0__["argument_list"])(tokeniser);
- tokens.close = consume(")") || error("Unterminated callback");
- tokens.termination = consume(";") || error("Unterminated callback");
- return ret;
- }
+ function definition() {
+ return callback() ||
+ interface_() ||
+ partial() ||
+ _productions_dictionary_js__WEBPACK_IMPORTED_MODULE_8__["Dictionary"].parse(tokeniser) ||
+ _productions_enum_js__WEBPACK_IMPORTED_MODULE_1__["Enum"].parse(tokeniser) ||
+ _productions_typedef_js__WEBPACK_IMPORTED_MODULE_4__["Typedef"].parse(tokeniser) ||
+ _productions_includes_js__WEBPACK_IMPORTED_MODULE_2__["Includes"].parse(tokeniser) ||
+ _productions_namespace_js__WEBPACK_IMPORTED_MODULE_9__["Namespace"].parse(tokeniser);
+ }
- get type() {
- return "callback";
+ function definitions() {
+ if (!source.length) return [];
+ const defs = [];
+ while (true) {
+ const ea = _productions_extended_attributes_js__WEBPACK_IMPORTED_MODULE_3__["ExtendedAttributes"].parse(tokeniser);
+ const def = definition();
+ if (!def) {
+ if (ea.length) error("Stray extended attributes");
+ break;
+ }
+ def.extAttrs = ea;
+ defs.push(def);
}
- get name() {
- return Object(_productions_helpers_js__WEBPACK_IMPORTED_MODULE_0__["unescape"])(this.tokens.name.value);
+ const eof = consume("eof");
+ if (options.concrete) {
+ defs.push(eof);
}
+ return defs;
}
+ const res = definitions();
+ if (tokeniser.position < source.length) error("Unrecognised tokens");
+ return res;
+}
- function callback() {
- const callback = consume("callback");
- if (!callback) return;
- const tok = consume("interface");
- if (tok) {
- return Interface.parse(tok, { callback });
- }
- return CallbackFunction.parse(callback);
+function parse(str, options = {}) {
+ const tokeniser = new _tokeniser_js__WEBPACK_IMPORTED_MODULE_0__["Tokeniser"](str);
+ if (typeof options.sourceName !== "undefined") {
+ tokeniser.source.name = options.sourceName;
}
+ return parseByTokens(tokeniser, options);
+}
- class Attribute extends _productions_base_js__WEBPACK_IMPORTED_MODULE_2__["Base"] {
- static parse({ special, noInherit = false, readonly = false } = {}) {
- const start_position = tokeniser.position;
- const tokens = { special };
- const ret = new Attribute({ source, tokens });
- if (!special && !noInherit) {
- tokens.special = consume("inherit");
- }
- if (ret.special === "inherit" && probe("readonly")) {
- error("Inherited attributes cannot be read-only");
- }
- tokens.readonly = consume("readonly");
- if (readonly && !tokens.readonly && probe("attribute")) {
- error("Attributes must be readonly in this context");
- }
- tokens.base = consume("attribute");
- if (!tokens.base) {
- unconsume(start_position);
- return;
- }
- ret.idlType = Object(_productions_helpers_js__WEBPACK_IMPORTED_MODULE_0__["type_with_extended_attributes"])(tokeniser, "attribute-type") || error("No type in attribute");
- switch (ret.idlType.generic) {
- case "sequence":
- 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");
- return ret;
- }
- get type() {
- return "attribute";
- }
- get special() {
- if (!this.tokens.special) {
- return "";
- }
- return this.tokens.special.value;
- }
- get readonly() {
- return !!this.tokens.readonly;
- }
- get name() {
- return Object(_productions_helpers_js__WEBPACK_IMPORTED_MODULE_0__["unescape"])(this.tokens.name.value);
- }
- }
+/***/ }),
+/* 2 */
+/***/ (function(module, __webpack_exports__, __webpack_require__) {
- class Operation extends _productions_base_js__WEBPACK_IMPORTED_MODULE_2__["Base"] {
- static parse({ special, regular } = {}) {
- const tokens = { special };
- const ret = new Operation({ source, tokens });
- if (special && special.value === "stringifier") {
- tokens.termination = consume(";");
- if (tokens.termination) {
- ret.arguments = [];
- return ret;
- }
- }
- if (!special && !regular) {
- tokens.special = consume("getter", "setter", "deleter");
- }
- ret.idlType = Object(_productions_helpers_js__WEBPACK_IMPORTED_MODULE_0__["return_type"])(tokeniser) || error("Missing return type");
- tokens.name = consume(ID);
- tokens.open = consume("(") || error("Invalid operation");
- ret.arguments = Object(_productions_helpers_js__WEBPACK_IMPORTED_MODULE_0__["argument_list"])(tokeniser);
- tokens.close = consume(")") || error("Unterminated operation");
- tokens.termination = consume(";") || error("Unterminated attribute");
- return ret;
- }
+"use strict";
+__webpack_require__.r(__webpack_exports__);
+/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "stringTypes", function() { return stringTypes; });
+/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "argumentNameKeywords", function() { return argumentNameKeywords; });
+/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "Tokeniser", function() { return Tokeniser; });
+/* harmony import */ var _error_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(3);
- get type() {
- return "operation";
- }
- get name() {
- const { name } = this.tokens;
- if (!name) {
- return "";
- }
- return Object(_productions_helpers_js__WEBPACK_IMPORTED_MODULE_0__["unescape"])(name.value);
- }
- get special() {
- if (!this.tokens.special) {
- return "";
- }
- return this.tokens.special.value;
- }
- }
-
- function static_member() {
- const special = consume("static");
- if (!special) return;
- const member = Attribute.parse({ special }) ||
- Operation.parse({ special }) ||
- error("No body in static member");
- return member;
- }
-
- function stringifier() {
- const special = consume("stringifier");
- if (!special) return;
- const member = Attribute.parse({ special }) ||
- Operation.parse({ special }) ||
- error("Unterminated stringifier");
- return member;
- }
-
- class IterableLike extends _productions_base_js__WEBPACK_IMPORTED_MODULE_2__["Base"] {
- static parse() {
- const start_position = tokeniser.position;
- const tokens = {};
- const ret = new IterableLike({ source, tokens });
- tokens.readonly = consume("readonly");
- tokens.base = tokens.readonly ?
- consume("maplike", "setlike") :
- consume("iterable", "maplike", "setlike");
- if (!tokens.base) {
- unconsume(start_position);
- return;
- }
- const { type } = ret;
- const secondTypeRequired = type === "maplike";
- const secondTypeAllowed = secondTypeRequired || type === "iterable";
-
- tokens.open = consume("<") || error(`Error parsing ${type} declaration`);
- const first = Object(_productions_helpers_js__WEBPACK_IMPORTED_MODULE_0__["type_with_extended_attributes"])(tokeniser) || error(`Error parsing ${type} declaration`);
- ret.idlType = [first];
- if (secondTypeAllowed) {
- first.tokens.separator = consume(",");
- if (first.tokens.separator) {
- ret.idlType.push(Object(_productions_helpers_js__WEBPACK_IMPORTED_MODULE_0__["type_with_extended_attributes"])(tokeniser));
- }
- else if (secondTypeRequired)
- error(`Missing second type argument in ${type} declaration`);
- }
- tokens.close = consume(">") || error(`Unterminated ${type} declaration`);
- tokens.termination = consume(";") || error(`Missing semicolon after ${type} declaration`);
+// 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.
+ "decimal": /-?(?=[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-Za-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-Za-z]/y
+};
- return ret;
- }
+const stringTypes = [
+ "ByteString",
+ "DOMString",
+ "USVString"
+];
- get type() {
- return this.tokens.base.value;
- }
- get readonly() {
- return !!this.tokens.readonly;
- }
- }
+const argumentNameKeywords = [
+ "async",
+ "attribute",
+ "callback",
+ "const",
+ "deleter",
+ "dictionary",
+ "enum",
+ "getter",
+ "includes",
+ "inherit",
+ "interface",
+ "iterable",
+ "maplike",
+ "namespace",
+ "partial",
+ "required",
+ "setlike",
+ "setter",
+ "static",
+ "stringifier",
+ "typedef",
+ "unrestricted"
+];
- function inheritance() {
- const colon = consume(":");
- if (!colon) {
- return {};
+const nonRegexTerminals = [
+ "-Infinity",
+ "FrozenArray",
+ "Infinity",
+ "NaN",
+ "Promise",
+ "async",
+ "boolean",
+ "byte",
+ "double",
+ "false",
+ "float",
+ "long",
+ "mixin",
+ "null",
+ "octet",
+ "optional",
+ "or",
+ "readonly",
+ "record",
+ "sequence",
+ "short",
+ "true",
+ "unsigned",
+ "void"
+].concat(argumentNameKeywords, stringTypes);
+
+const punctuations = [
+ "(",
+ ")",
+ ",",
+ "...",
+ ":",
+ ";",
+ "<",
+ "=",
+ ">",
+ "?",
+ "[",
+ "]",
+ "{",
+ "}"
+];
+
+/**
+ * @param {string} str
+ */
+function tokenise(str) {
+ const tokens = [];
+ let lastCharIndex = 0;
+ let trivia = "";
+ let line = 1;
+ let index = 0;
+ while (lastCharIndex < str.length) {
+ const nextChar = str.charAt(lastCharIndex);
+ let result = -1;
+
+ if (/[\t\n\r ]/.test(nextChar)) {
+ result = attemptTokenMatch("whitespace", { noFlushTrivia: true });
+ } else if (nextChar === '/') {
+ result = attemptTokenMatch("comment", { noFlushTrivia: true });
}
- const inheritance = consume(ID) || error("No type in inheritance");
- return { colon, inheritance };
- }
- class Container extends _productions_base_js__WEBPACK_IMPORTED_MODULE_2__["Base"] {
- static parse(instance, { type, inheritable, allowedMembers }) {
- const { tokens } = instance;
- tokens.name = consume(ID) || error("No name for interface");
- tokeniser.current = instance;
- if (inheritable) {
- Object.assign(tokens, inheritance());
+ if (result !== -1) {
+ const currentTrivia = tokens.pop().value;
+ line += (currentTrivia.match(/\n/g) || []).length;
+ trivia += currentTrivia;
+ index -= 1;
+ } else if (/[-0-9.A-Z_a-z]/.test(nextChar)) {
+ result = attemptTokenMatch("decimal");
+ if (result === -1) {
+ result = attemptTokenMatch("integer");
}
- tokens.open = consume("{") || error(`Bodyless ${type}`);
- instance.members = [];
- while (true) {
- tokens.close = consume("}");
- if (tokens.close) {
- tokens.termination = consume(";") || error(`Missing semicolon after ${type}`);
- return instance;
- }
- const ea = _productions_extended_attributes_js__WEBPACK_IMPORTED_MODULE_7__["ExtendedAttributes"].parse(tokeniser);
- let mem;
- for (const [parser, ...args] of allowedMembers) {
- mem = parser(...args);
- if (mem) {
- break;
- }
- }
- if (!mem) {
- error("Unknown member");
+ if (result === -1) {
+ result = attemptTokenMatch("identifier");
+ const token = tokens[tokens.length - 1];
+ if (result !== -1 && nonRegexTerminals.includes(token.value)) {
+ token.type = token.value;
}
- mem.extAttrs = ea;
- instance.members.push(mem);
}
+ } else if (nextChar === '"') {
+ result = attemptTokenMatch("string");
}
- get partial() {
- return !!this.tokens.partial;
- }
- get name() {
- return Object(_productions_helpers_js__WEBPACK_IMPORTED_MODULE_0__["unescape"])(this.tokens.name.value);
- }
- get inheritance() {
- if (!this.tokens.inheritance) {
- return null;
+ for (const punctuation of punctuations) {
+ if (str.startsWith(punctuation, lastCharIndex)) {
+ tokens.push({ type: punctuation, value: punctuation, trivia, line, index });
+ trivia = "";
+ lastCharIndex += punctuation.length;
+ result = lastCharIndex;
+ break;
}
- return Object(_productions_helpers_js__WEBPACK_IMPORTED_MODULE_0__["unescape"])(this.tokens.inheritance.value);
- }
- }
-
- class Interface extends Container {
- static parse(base, { callback = null, partial = null } = {}) {
- const tokens = { callback, partial, base };
- return Container.parse(new Interface({ source, tokens }), {
- type: "interface",
- inheritable: !partial,
- allowedMembers: [
- [Constant.parse],
- [static_member],
- [stringifier],
- [IterableLike.parse],
- [Attribute.parse],
- [Operation.parse]
- ]
- });
}
- get type() {
- if (this.tokens.callback) {
- return "callback interface";
- }
- return "interface";
+ // other as the last try
+ if (result === -1) {
+ result = attemptTokenMatch("other");
}
+ if (result === -1) {
+ throw new Error("Token stream not progressing");
+ }
+ lastCharIndex = result;
+ index += 1;
}
- class Mixin extends Container {
- static parse(base, { partial } = {}) {
- const tokens = { partial, base };
- tokens.mixin = consume("mixin");
- if (!tokens.mixin) {
- return;
+ // remaining trivia as eof
+ tokens.push({
+ type: "eof",
+ value: "",
+ trivia
+ });
+
+ return tokens;
+
+ /**
+ * @param {keyof tokenRe} type
+ * @param {object} [options]
+ * @param {boolean} [options.noFlushTrivia]
+ */
+ function attemptTokenMatch(type, { noFlushTrivia } = {}) {
+ const re = tokenRe[type];
+ re.lastIndex = lastCharIndex;
+ const result = re.exec(str);
+ if (result) {
+ tokens.push({ type, value: result[0], trivia, line, index });
+ if (!noFlushTrivia) {
+ trivia = "";
}
- return Container.parse(new Mixin({ source, tokens }), {
- type: "interface mixin",
- allowedMembers: [
- [Constant.parse],
- [stringifier],
- [Attribute.parse, { noInherit: true }],
- [Operation.parse, { regular: true }]
- ]
- });
+ return re.lastIndex;
}
+ return -1;
+ }
+}
- get type() {
- return "interface mixin";
- }
+class Tokeniser {
+ /**
+ * @param {string} idl
+ */
+ constructor(idl) {
+ this.source = tokenise(idl);
+ this.position = 0;
}
- function interface_(opts) {
- const base = consume("interface");
- if (!base) return;
- const ret = Mixin.parse(base, opts) ||
- Interface.parse(base, opts) ||
- error("Interface has no proper body");
- return ret;
+ /**
+ * @param {string} message
+ */
+ error(message) {
+ throw new WebIDLParseError(Object(_error_js__WEBPACK_IMPORTED_MODULE_0__["syntaxError"])(this.source, this.position, this.current, message));
}
- class Namespace extends Container {
- static parse({ partial } = {}) {
- const tokens = { partial };
- tokens.base = consume("namespace");
- if (!tokens.base) {
- return;
- }
- return Container.parse(new Namespace({ source, tokens }), {
- type: "namespace",
- allowedMembers: [
- [Attribute.parse, { noInherit: true, readonly: true }],
- [Operation.parse, { regular: true }]
- ]
- });
- }
+ /**
+ * @param {string} type
+ */
+ probe(type) {
+ return this.source.length > this.position && this.source[this.position].type === type;
+ }
- get type() {
- return "namespace";
+ /**
+ * @param {...string} candidates
+ */
+ consume(...candidates) {
+ for (const type of candidates) {
+ if (!this.probe(type)) continue;
+ const token = this.source[this.position];
+ this.position++;
+ return token;
}
}
- function partial() {
- const partial = consume("partial");
- if (!partial) return;
- return Dictionary.parse({ partial }) ||
- interface_({ partial }) ||
- Namespace.parse({ partial }) ||
- error("Partial doesn't apply to anything");
+ /**
+ * @param {number} position
+ */
+ unconsume(position) {
+ this.position = position;
}
+}
- class Dictionary extends Container {
- static parse({ partial } = {}) {
- const tokens = { partial };
- tokens.base = consume("dictionary");
- if (!tokens.base) {
- return;
- }
- return Container.parse(new Dictionary({ source, tokens }), {
- type: "dictionary",
- inheritable: !partial,
- allowedMembers: [
- [Field.parse],
- ]
- });
- }
+class WebIDLParseError extends Error {
+ constructor({ message, bareMessage, context, line, sourceName, input, tokens }) {
+ super(message);
- get type() {
- return "dictionary";
- }
+ this.name = "WebIDLParseError"; // not to be mangled
+ this.bareMessage = bareMessage;
+ this.context = context;
+ this.line = line;
+ this.sourceName = sourceName;
+ this.input = input;
+ this.tokens = tokens;
}
+}
- class Field extends _productions_base_js__WEBPACK_IMPORTED_MODULE_2__["Base"] {
- static parse() {
- const tokens = {};
- const ret = new Field({ source, tokens });
- ret.extAttrs = _productions_extended_attributes_js__WEBPACK_IMPORTED_MODULE_7__["ExtendedAttributes"].parse(tokeniser);
- tokens.required = consume("required");
- ret.idlType = Object(_productions_helpers_js__WEBPACK_IMPORTED_MODULE_0__["type_with_extended_attributes"])(tokeniser, "dictionary-type") || error("No type for dictionary member");
- tokens.name = consume(ID) || error("No name for dictionary member");
- ret.default = _productions_default_js__WEBPACK_IMPORTED_MODULE_3__["Default"].parse(tokeniser);
- if (tokens.required && ret.default) error("Required member must not have a default");
- tokens.termination = consume(";") || error("Unterminated dictionary member");
- return ret;
- }
- get type() {
- return "field";
- }
- get name() {
- return Object(_productions_helpers_js__WEBPACK_IMPORTED_MODULE_0__["unescape"])(this.tokens.name.value);
+/***/ }),
+/* 3 */
+/***/ (function(module, __webpack_exports__, __webpack_require__) {
+
+"use strict";
+__webpack_require__.r(__webpack_exports__);
+/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "syntaxError", function() { return syntaxError; });
+/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "validationError", function() { return validationError; });
+/**
+ * @param {string} text
+ */
+function lastLine(text) {
+ const splitted = text.split("\n");
+ return splitted[splitted.length - 1];
+}
+
+/**
+ * @typedef {object} WebIDL2ErrorOptions
+ * @property {"error" | "warning"} level
+ *
+ * @param {string} message error message
+ * @param {"Syntax" | "Validation"} kind error type
+ * @param {WebIDL2ErrorOptions} [options]
+ */
+function error(source, position, current, message, kind, { level = "error" } = {}) {
+ /**
+ * @param {number} count
+ */
+ function sliceTokens(count) {
+ return count > 0 ?
+ source.slice(position, position + count) :
+ source.slice(Math.max(position + count, 0), position);
+ }
+
+ function tokensToText(inputs, { precedes } = {}) {
+ const text = inputs.map(t => t.trivia + t.value).join("");
+ const nextToken = source[position];
+ if (nextToken.type === "eof") {
+ return text;
}
- get required() {
- return !!this.tokens.required;
+ if (precedes) {
+ return text + nextToken.trivia;
}
+ return text.slice(nextToken.trivia.length);
}
- class Typedef extends _productions_base_js__WEBPACK_IMPORTED_MODULE_2__["Base"] {
- static parse() {
- const tokens = {};
- const ret = new Typedef({ source, tokens });
- tokens.base = consume("typedef");
- if (!tokens.base) {
- return;
- }
- ret.idlType = Object(_productions_helpers_js__WEBPACK_IMPORTED_MODULE_0__["type_with_extended_attributes"])(tokeniser, "typedef-type") || error("No type in typedef");
- tokens.name = consume(ID) || error("No name in typedef");
- tokeniser.current = ret;
- tokens.termination = consume(";") || error("Unterminated typedef");
- return ret;
- }
+ const maxTokens = 5; // arbitrary but works well enough
+ const line =
+ source[position].type !== "eof" ? source[position].line :
+ source.length > 1 ? source[position - 1].line :
+ 1;
- get type() {
- return "typedef";
- }
- get name() {
- return Object(_productions_helpers_js__WEBPACK_IMPORTED_MODULE_0__["unescape"])(this.tokens.name.value);
+ const precedingLastLine = lastLine(
+ tokensToText(sliceTokens(-maxTokens), { precedes: true })
+ );
+
+ const subsequentTokens = sliceTokens(maxTokens);
+ const subsequentText = tokensToText(subsequentTokens);
+ const subsequentFirstLine = subsequentText.split("\n")[0];
+
+ const spaced = " ".repeat(precedingLastLine.length) + "^";
+ const sourceContext = precedingLastLine + subsequentFirstLine + "\n" + spaced;
+
+ const contextType = kind === "Syntax" ? "since" : "inside";
+ const inSourceName = source.name ? ` in ${source.name}` : "";
+ const grammaticalContext = (current && current.name) ? `, ${contextType} \`${current.partial ? "partial " : ""}${current.type} ${current.name}\`` : "";
+ const context = `${kind} error at line ${line}${inSourceName}${grammaticalContext}:\n${sourceContext}`;
+ return {
+ message: `${context} ${message}`,
+ bareMessage: message,
+ context,
+ line,
+ sourceName: source.name,
+ level,
+ input: subsequentText,
+ tokens: subsequentTokens
+ };
+}
+
+/**
+ * @param {string} message error message
+ */
+function syntaxError(source, position, current, message) {
+ return error(source, position, current, message, "Syntax");
+}
+
+/**
+ * @param {string} message error message
+ * @param {WebIDL2ErrorOptions} [options]
+ */
+function validationError(source, token, current, message, options) {
+ return error(source, token.index, current, message, "Validation", options);
+}
+
+
+/***/ }),
+/* 4 */
+/***/ (function(module, __webpack_exports__, __webpack_require__) {
+
+"use strict";
+__webpack_require__.r(__webpack_exports__);
+/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "Enum", function() { return Enum; });
+/* harmony import */ var _helpers_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(5);
+/* harmony import */ var _token_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(13);
+/* harmony import */ var _base_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(7);
+
+
+
+
+class EnumValue extends _token_js__WEBPACK_IMPORTED_MODULE_1__["Token"] {
+ /**
+ * @param {import("../tokeniser").Tokeniser} tokeniser
+ */
+ static parse(tokeniser) {
+ const value = tokeniser.consume("string");
+ if (value) {
+ return new EnumValue({ source: tokeniser.source, tokens: { value } });
}
}
- function definition() {
- return callback() ||
- interface_() ||
- partial() ||
- Dictionary.parse() ||
- _productions_enum_js__WEBPACK_IMPORTED_MODULE_4__["Enum"].parse(tokeniser) ||
- Typedef.parse() ||
- _productions_includes_js__WEBPACK_IMPORTED_MODULE_5__["Includes"].parse(tokeniser) ||
- Namespace.parse();
+ get type() {
+ return "enum-value";
}
+ get value() {
+ return super.value.slice(1, -1);
+ }
+}
- function definitions() {
- if (!source.length) return [];
- const defs = [];
- while (true) {
- const ea = _productions_extended_attributes_js__WEBPACK_IMPORTED_MODULE_7__["ExtendedAttributes"].parse(tokeniser);
- const def = definition();
- if (!def) {
- if (ea.length) error("Stray extended attributes");
- break;
- }
- def.extAttrs = ea;
- defs.push(def);
+class Enum extends _base_js__WEBPACK_IMPORTED_MODULE_2__["Base"] {
+ /**
+ * @param {import("../tokeniser").Tokeniser} tokeniser
+ */
+ static parse(tokeniser) {
+ const tokens = {};
+ tokens.base = tokeniser.consume("enum");
+ if (!tokens.base) {
+ return;
}
- const eof = consume("eof");
- if (options.concrete) {
- defs.push(eof);
+ tokens.name = tokeniser.consume("identifier") || tokeniser.error("No name for enum");
+ const ret = tokeniser.current = new Enum({ source: tokeniser.source, tokens });
+ tokens.open = tokeniser.consume("{") || tokeniser.error("Bodyless enum");
+ ret.values = Object(_helpers_js__WEBPACK_IMPORTED_MODULE_0__["list"])(tokeniser, {
+ parser: EnumValue.parse,
+ allowDangler: true,
+ listName: "enumeration"
+ });
+ if (tokeniser.probe("string")) {
+ tokeniser.error("No comma between enum values");
}
- return defs;
+ tokens.close = tokeniser.consume("}") || tokeniser.error("Unexpected value in enum");
+ if (!ret.values.length) {
+ tokeniser.error("No value in enum");
+ }
+ tokens.termination = tokeniser.consume(";") || tokeniser.error("No semicolon after enum");
+ return ret;
}
- const res = definitions();
- if (tokeniser.position < source.length) error("Unrecognised tokens");
- return res;
-}
-function parse(str, options = {}) {
- const tokeniser = new _tokeniser_js__WEBPACK_IMPORTED_MODULE_1__["Tokeniser"](str);
- return parseByTokens(tokeniser, options);
+ get type() {
+ return "enum";
+ }
+ get name() {
+ return Object(_helpers_js__WEBPACK_IMPORTED_MODULE_0__["unescape"])(this.tokens.name.value);
+ }
}
/***/ }),
-/* 2 */
+/* 5 */
/***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
@@ -651,10 +663,15 @@ __webpack_require__.r(__webpack_exports__);
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "argument_list", function() { return argument_list; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "type_with_extended_attributes", function() { return type_with_extended_attributes; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "return_type", function() { return return_type; });
-/* harmony import */ var _type_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(3);
-/* harmony import */ var _argument_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(7);
-/* harmony import */ var _token_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(11);
-/* harmony import */ var _extended_attributes_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(9);
+/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "stringifier", function() { return stringifier; });
+/* harmony import */ var _type_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(6);
+/* harmony import */ var _argument_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(9);
+/* harmony import */ var _token_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(13);
+/* harmony import */ var _extended_attributes_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(11);
+/* harmony import */ var _operation_js__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(14);
+/* harmony import */ var _attribute_js__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(15);
+
+
@@ -809,17 +826,33 @@ function return_type(tokeniser, typeName) {
}
}
+/**
+ * @param {import("../tokeniser").Tokeniser} tokeniser
+ */
+function stringifier(tokeniser) {
+ const special = tokeniser.consume("stringifier");
+ if (!special) return;
+ const member = _attribute_js__WEBPACK_IMPORTED_MODULE_5__["Attribute"].parse(tokeniser, { special }) ||
+ _operation_js__WEBPACK_IMPORTED_MODULE_4__["Operation"].parse(tokeniser, { special }) ||
+ tokeniser.error("Unterminated stringifier");
+ return member;
+}
+
/***/ }),
-/* 3 */
+/* 6 */
/***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "Type", function() { return Type; });
-/* harmony import */ var _base_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(4);
-/* harmony import */ var _helpers_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(2);
-/* harmony import */ var _tokeniser_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(5);
+/* harmony import */ var _base_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(7);
+/* harmony import */ var _helpers_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(5);
+/* harmony import */ var _tokeniser_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(2);
+/* harmony import */ var _error_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(3);
+/* harmony import */ var _validators_helpers_js__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(8);
+
+
@@ -965,11 +998,37 @@ class Type extends _base_js__WEBPACK_IMPORTED_MODULE_0__["Base"] {
].filter(t => t).map(t => t.value).join(" ");
return Object(_helpers_js__WEBPACK_IMPORTED_MODULE_1__["unescape"])(name);
}
+
+ *validate(defs) {
+ /*
+ * If a union is nullable, its subunions cannot include a dictionary
+ * If not, subunions may include dictionaries if each union is not nullable
+ */
+ const typedef = !this.union && defs.unique.get(this.idlType);
+ const target =
+ this.union ? this :
+ (typedef && typedef.type === "typedef") ? typedef.idlType :
+ undefined;
+ if (target && this.nullable) {
+ // do not allow any dictionary
+ const reference = Object(_validators_helpers_js__WEBPACK_IMPORTED_MODULE_4__["idlTypeIncludesDictionary"])(target, defs);
+ if (reference) {
+ const targetToken = (this.union ? reference : this).tokens.base;
+ const message = `Nullable union cannot include a dictionary type`;
+ yield Object(_error_js__WEBPACK_IMPORTED_MODULE_3__["validationError"])(this.source, targetToken, this, message);
+ }
+ } else {
+ // allow some dictionary
+ for (const subtype of this.subtype) {
+ yield* subtype.validate(defs);
+ }
+ }
+ }
}
/***/ }),
-/* 4 */
+/* 7 */
/***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
@@ -1001,346 +1060,89 @@ class Base {
/***/ }),
-/* 5 */
+/* 8 */
/***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
__webpack_require__.r(__webpack_exports__);
-/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "stringTypes", function() { return stringTypes; });
-/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "argumentNameKeywords", function() { return argumentNameKeywords; });
-/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "Tokeniser", function() { return Tokeniser; });
-/* harmony import */ var _error_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(6);
-
-
-// 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.
- "decimal": /-?(?=[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-Za-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-Za-z]/y
-};
-
-const stringTypes = [
- "ByteString",
- "DOMString",
- "USVString"
-];
-
-const argumentNameKeywords = [
- "attribute",
- "callback",
- "const",
- "deleter",
- "dictionary",
- "enum",
- "getter",
- "includes",
- "inherit",
- "interface",
- "iterable",
- "maplike",
- "namespace",
- "partial",
- "required",
- "setlike",
- "setter",
- "static",
- "stringifier",
- "typedef",
- "unrestricted"
-];
-
-const nonRegexTerminals = [
- "-Infinity",
- "FrozenArray",
- "Infinity",
- "NaN",
- "Promise",
- "boolean",
- "byte",
- "double",
- "false",
- "float",
- "implements",
- "legacyiterable",
- "long",
- "mixin",
- "null",
- "octet",
- "optional",
- "or",
- "readonly",
- "record",
- "sequence",
- "short",
- "true",
- "unsigned",
- "void"
-].concat(argumentNameKeywords, stringTypes);
-
-const punctuations = [
- "(",
- ")",
- ",",
- "...",
- ":",
- ";",
- "<",
- "=",
- ">",
- "?",
- "[",
- "]",
- "{",
- "}"
-];
-
+/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "dictionaryWithinUnion", function() { return dictionaryWithinUnion; });
+/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "idlTypeIncludesDictionary", function() { return idlTypeIncludesDictionary; });
+/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "referencesTypedef", function() { return referencesTypedef; });
/**
- * @param {string} str
+ * Yields direct references to dictionary within union.
*/
-function tokenise(str) {
- const tokens = [];
- let lastCharIndex = 0;
- let trivia = "";
- let line = 1;
- let index = 0;
- while (lastCharIndex < str.length) {
- const nextChar = str.charAt(lastCharIndex);
- let result = -1;
-
- if (/[\t\n\r ]/.test(nextChar)) {
- result = attemptTokenMatch("whitespace", { noFlushTrivia: true });
- } else if (nextChar === '/') {
- result = attemptTokenMatch("comment", { noFlushTrivia: true });
+function* dictionaryWithinUnion(subtypes, defs) {
+ for (const subtype of subtypes) {
+ const def = defs.unique.get(subtype.idlType);
+ if (def && def.type === "dictionary") {
+ yield subtype;
}
+ }
+}
- if (result !== -1) {
- const currentTrivia = tokens.pop().value;
- line += (currentTrivia.match(/\n/g) || []).length;
- trivia += currentTrivia;
- index -= 1;
- } else if (/[-0-9.A-Z_a-z]/.test(nextChar)) {
- result = attemptTokenMatch("decimal");
- if (result === -1) {
- result = attemptTokenMatch("integer");
- }
- if (result === -1) {
- result = attemptTokenMatch("identifier");
- const token = tokens[tokens.length - 1];
- if (result !== -1 && nonRegexTerminals.includes(token.value)) {
- token.type = token.value;
- }
- }
- } else if (nextChar === '"') {
- result = attemptTokenMatch("string");
+/**
+ * @return the type reference that ultimately includes dictionary.
+ */
+function idlTypeIncludesDictionary(idlType, defs) {
+ if (!idlType.union) {
+ const def = defs.unique.get(idlType.idlType);
+ if (!def) {
+ return;
}
-
- for (const punctuation of punctuations) {
- if (str.startsWith(punctuation, lastCharIndex)) {
- tokens.push({ type: punctuation, value: punctuation, trivia, line, index });
- trivia = "";
- lastCharIndex += punctuation.length;
- result = lastCharIndex;
- break;
+ if (def.type === "typedef") {
+ const { typedefIncludesDictionary} = defs.cache;
+ if (typedefIncludesDictionary.has(def)) {
+ // Note that this also halts when it met indeterminate state
+ // to prevent infinite recursion
+ return typedefIncludesDictionary.get(def);
+ }
+ defs.cache.typedefIncludesDictionary.set(def, undefined); // indeterminate state
+ const result = idlTypeIncludesDictionary(def.idlType, defs);
+ defs.cache.typedefIncludesDictionary.set(def, result);
+ if (result) {
+ return idlType;
}
}
-
- // other as the last try
- if (result === -1) {
- result = attemptTokenMatch("other");
- }
- if (result === -1) {
- throw new Error("Token stream not progressing");
+ if (def.type === "dictionary") {
+ return idlType;
}
- lastCharIndex = result;
- index += 1;
}
-
- // remaining trivia as eof
- tokens.push({
- type: "eof",
- value: "",
- trivia
- });
-
- return tokens;
-
- /**
- * @param {keyof tokenRe} type
- * @param {object} [options]
- * @param {boolean} [options.noFlushTrivia]
- */
- function attemptTokenMatch(type, { noFlushTrivia } = {}) {
- const re = tokenRe[type];
- re.lastIndex = lastCharIndex;
- const result = re.exec(str);
+ for (const subtype of idlType.subtype) {
+ const result = idlTypeIncludesDictionary(subtype, defs);
if (result) {
- tokens.push({ type, value: result[0], trivia, line, index });
- if (!noFlushTrivia) {
- trivia = "";
+ if (subtype.union) {
+ return result;
}
- return re.lastIndex;
- }
- return -1;
- }
-}
-
-class Tokeniser {
- /**
- * @param {string} idl
- */
- constructor(idl) {
- this.source = tokenise(idl);
- this.position = 0;
- }
-
- /**
- * @param {string} message
- */
- error(message) {
- throw new WebIDLParseError(Object(_error_js__WEBPACK_IMPORTED_MODULE_0__["syntaxError"])(this.source, this.position, this.current, message));
- }
-
- /**
- * @param {string} type
- */
- probe(type) {
- return this.source.length > this.position && this.source[this.position].type === type;
- }
-
- /**
- * @param {...string} candidates
- */
- consume(...candidates) {
- for (const type of candidates) {
- if (!this.probe(type)) continue;
- const token = this.source[this.position];
- this.position++;
- return token;
- }
- }
-
- /**
- * @param {number} position
- */
- unconsume(position) {
- this.position = position;
- }
-}
-
-class WebIDLParseError extends Error {
- constructor({ message, line, input, tokens }) {
- super(message);
- this.name = "WebIDLParseError"; // not to be mangled
- this.line = line;
- this.input = input;
- this.tokens = tokens;
- }
-}
-
-
-/***/ }),
-/* 6 */
-/***/ (function(module, __webpack_exports__, __webpack_require__) {
-
-"use strict";
-__webpack_require__.r(__webpack_exports__);
-/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "syntaxError", function() { return syntaxError; });
-/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "validationError", function() { return validationError; });
-/**
- * @param {string} text
- */
-function lastLine(text) {
- const splitted = text.split("\n");
- return splitted[splitted.length - 1];
-}
-
-/**
- * @param {string} message error message
- * @param {"Syntax" | "Validation"} type error type
- */
-function error(source, position, current, message, type) {
- /**
- * @param {number} count
- */
- function sliceTokens(count) {
- return count > 0 ?
- source.slice(position, position + count) :
- source.slice(Math.max(position + count, 0), position);
- }
-
- function tokensToText(inputs, { precedes } = {}) {
- const text = inputs.map(t => t.trivia + t.value).join("");
- const nextToken = source[position];
- if (nextToken.type === "eof") {
- return text;
+ return subtype;
}
- if (precedes) {
- return text + nextToken.trivia;
- }
- return text.slice(nextToken.trivia.length);
}
-
- const maxTokens = 5; // arbitrary but works well enough
- const line =
- source[position].type !== "eof" ? source[position].line :
- source.length > 1 ? source[position - 1].line :
- 1;
-
- const precedingLine = lastLine(
- tokensToText(sliceTokens(-maxTokens), { precedes: true })
- );
-
- const subsequentTokens = sliceTokens(maxTokens);
- const subsequentText = tokensToText(subsequentTokens);
- const sobsequentLine = subsequentText.split("\n")[0];
-
- const spaced = " ".repeat(precedingLine.length) + "^ " + message;
- const contextualMessage = precedingLine + sobsequentLine + "\n" + spaced;
-
- const contextType = type === "Syntax" ? "since" : "inside";
- const grammaticalContext = current ? `, ${contextType} \`${current.partial ? "partial " : ""}${current.type} ${current.name}\`` : "";
- return {
- message: `${type} error at line ${line}${grammaticalContext}:\n${contextualMessage}`,
- line,
- input: subsequentText,
- tokens: subsequentTokens
- };
}
/**
- * @param {string} message error message
+ * @return true if the idlType directly references a typedef.
*/
-function syntaxError(source, position, current, message) {
- return error(source, position, current, message, "Syntax");
-}
-
-/**
- * @param {string} message error message
- */
-function validationError(source, token, current, message) {
- return error(source, token.index, current, message, "Validation").message;
+function referencesTypedef(idlType, defs) {
+ const result = defs.unique.get(idlType.idlType);
+ return result && result.type === "typedef";
}
/***/ }),
-/* 7 */
+/* 9 */
/***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "Argument", function() { return Argument; });
-/* harmony import */ var _base_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(4);
-/* harmony import */ var _default_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(8);
-/* harmony import */ var _extended_attributes_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(9);
-/* harmony import */ var _helpers_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(2);
-/* harmony import */ var _tokeniser_js__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(5);
+/* harmony import */ var _base_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(7);
+/* harmony import */ var _default_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(10);
+/* harmony import */ var _extended_attributes_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(11);
+/* harmony import */ var _helpers_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(5);
+/* harmony import */ var _tokeniser_js__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(2);
+/* harmony import */ var _error_js__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(3);
+/* harmony import */ var _validators_helpers_js__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(8);
+
+
@@ -1372,6 +1174,9 @@ class Argument extends _base_js__WEBPACK_IMPORTED_MODULE_0__["Base"] {
return ret;
}
+ get type() {
+ return "argument";
+ }
get optional() {
return !!this.tokens.optional;
}
@@ -1381,18 +1186,32 @@ class Argument extends _base_js__WEBPACK_IMPORTED_MODULE_0__["Base"] {
get name() {
return Object(_helpers_js__WEBPACK_IMPORTED_MODULE_3__["unescape"])(this.tokens.name.value);
}
+
+ *validate(defs) {
+ yield* this.idlType.validate(defs);
+ if (Object(_validators_helpers_js__WEBPACK_IMPORTED_MODULE_6__["idlTypeIncludesDictionary"])(this.idlType, defs)) {
+ if (this.optional && !this.default) {
+ const message = `Optional dictionary arguments must have a default value of \`{}\`.`;
+ yield Object(_error_js__WEBPACK_IMPORTED_MODULE_5__["validationError"])(this.source, this.tokens.name, this, message);
+ }
+ if (this.idlType.nullable) {
+ const message = `Dictionary arguments cannot be nullable.`;
+ yield Object(_error_js__WEBPACK_IMPORTED_MODULE_5__["validationError"])(this.source, this.tokens.name, this, message);
+ }
+ }
+ }
}
/***/ }),
-/* 8 */
+/* 10 */
/***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "Default", function() { return Default; });
-/* harmony import */ var _base_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(4);
-/* harmony import */ var _helpers_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(2);
+/* harmony import */ var _base_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(7);
+/* harmony import */ var _helpers_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(5);
@@ -1435,15 +1254,17 @@ class Default extends _base_js__WEBPACK_IMPORTED_MODULE_0__["Base"] {
/***/ }),
-/* 9 */
+/* 11 */
/***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "ExtendedAttributes", function() { return ExtendedAttributes; });
-/* harmony import */ var _base_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(4);
-/* harmony import */ var _array_base_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(10);
-/* harmony import */ var _helpers_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(2);
+/* harmony import */ var _base_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(7);
+/* harmony import */ var _array_base_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(12);
+/* harmony import */ var _helpers_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(5);
+/* harmony import */ var _error_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(3);
+
@@ -1487,6 +1308,7 @@ class SimpleExtendedAttribute extends _base_js__WEBPACK_IMPORTED_MODULE_0__["Bas
const name = tokeniser.consume("identifier");
if (name) {
return new SimpleExtendedAttribute({
+ source: tokeniser.source,
tokens: { name },
params: ExtendedAttributeParameters.parse(tokeniser)
});
@@ -1519,6 +1341,19 @@ class SimpleExtendedAttribute extends _base_js__WEBPACK_IMPORTED_MODULE_0__["Bas
}
return list;
}
+
+ *validate(defs) {
+ if (this.name === "NoInterfaceObject") {
+ const message = `\`[NoInterfaceObject]\` extended attribute is an \
+undesirable feature that may be removed from Web IDL in the future. Refer to the \
+[relevant upstream PR](https://github.com/heycam/webidl/pull/609) for more \
+information.`;
+ yield Object(_error_js__WEBPACK_IMPORTED_MODULE_3__["validationError"])(this.source, this.tokens.name, this, message, { level: "warning" });
+ }
+ for (const arg of this.arguments) {
+ yield* arg.validate(defs);
+ }
+ }
}
// Note: we parse something simpler than the official syntax. It's all that ever
@@ -1530,7 +1365,7 @@ class ExtendedAttributes extends _array_base_js__WEBPACK_IMPORTED_MODULE_1__["Ar
static parse(tokeniser) {
const tokens = {};
tokens.open = tokeniser.consume("[");
- if (!tokens.open) return [];
+ if (!tokens.open) return new ExtendedAttributes({});
const ret = new ExtendedAttributes({ source: tokeniser.source, tokens });
ret.push(...Object(_helpers_js__WEBPACK_IMPORTED_MODULE_2__["list"])(tokeniser, {
parser: SimpleExtendedAttribute.parse,
@@ -1545,11 +1380,17 @@ class ExtendedAttributes extends _array_base_js__WEBPACK_IMPORTED_MODULE_1__["Ar
}
return ret;
}
+
+ *validate(defs) {
+ for (const extAttr of this) {
+ yield* extAttr.validate(defs);
+ }
+ }
}
/***/ }),
-/* 10 */
+/* 12 */
/***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
@@ -1567,13 +1408,13 @@ class ArrayBase extends Array {
/***/ }),
-/* 11 */
+/* 13 */
/***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "Token", function() { return Token; });
-/* harmony import */ var _base_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(4);
+/* harmony import */ var _base_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(7);
class Token extends _base_js__WEBPACK_IMPORTED_MODULE_0__["Base"] {
@@ -1597,85 +1438,147 @@ class Token extends _base_js__WEBPACK_IMPORTED_MODULE_0__["Base"] {
/***/ }),
-/* 12 */
+/* 14 */
/***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
__webpack_require__.r(__webpack_exports__);
-/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "Enum", function() { return Enum; });
-/* harmony import */ var _helpers_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(2);
-/* harmony import */ var _token_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(11);
-/* harmony import */ var _base_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(4);
+/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "Operation", function() { return Operation; });
+/* harmony import */ var _base_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(7);
+/* harmony import */ var _helpers_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(5);
-
-class EnumValue extends _token_js__WEBPACK_IMPORTED_MODULE_1__["Token"] {
+class Operation extends _base_js__WEBPACK_IMPORTED_MODULE_0__["Base"] {
/**
- * @param {import("../tokeniser").Tokeniser} tokeniser
+ * @param {import("../tokeniser.js").Tokeniser} tokeniser
*/
- static parse(tokeniser) {
- const value = tokeniser.consume("string");
- if (value) {
- return new EnumValue({ source: tokeniser.source, tokens: { value } });
+ static parse(tokeniser, { special, regular } = {}) {
+ const tokens = { special };
+ const ret = new Operation({ source: tokeniser.source, tokens });
+ if (special && special.value === "stringifier") {
+ tokens.termination = tokeniser.consume(";");
+ if (tokens.termination) {
+ ret.arguments = [];
+ return ret;
+ }
}
+ if (!special && !regular) {
+ tokens.special = tokeniser.consume("getter", "setter", "deleter");
+ }
+ ret.idlType = Object(_helpers_js__WEBPACK_IMPORTED_MODULE_1__["return_type"])(tokeniser) || tokeniser.error("Missing return type");
+ tokens.name = tokeniser.consume("identifier", "includes");
+ tokens.open = tokeniser.consume("(") || tokeniser.error("Invalid operation");
+ ret.arguments = Object(_helpers_js__WEBPACK_IMPORTED_MODULE_1__["argument_list"])(tokeniser);
+ tokens.close = tokeniser.consume(")") || tokeniser.error("Unterminated operation");
+ tokens.termination = tokeniser.consume(";") || tokeniser.error("Unterminated operation, expected `;`");
+ return ret;
}
get type() {
- return "enum-value";
+ return "operation";
}
- get value() {
- return super.value.slice(1, -1);
+ get name() {
+ const { name } = this.tokens;
+ if (!name) {
+ return "";
+ }
+ return Object(_helpers_js__WEBPACK_IMPORTED_MODULE_1__["unescape"])(name.value);
+ }
+ get special() {
+ if (!this.tokens.special) {
+ return "";
+ }
+ return this.tokens.special.value;
+ }
+
+ *validate(defs) {
+ if (this.idlType) {
+ yield* this.idlType.validate(defs);
+ }
+ for (const argument of this.arguments) {
+ yield* argument.validate(defs);
+ }
}
}
-class Enum extends _base_js__WEBPACK_IMPORTED_MODULE_2__["Base"] {
+
+/***/ }),
+/* 15 */
+/***/ (function(module, __webpack_exports__, __webpack_require__) {
+
+"use strict";
+__webpack_require__.r(__webpack_exports__);
+/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "Attribute", function() { return Attribute; });
+/* harmony import */ var _base_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(7);
+/* harmony import */ var _helpers_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(5);
+
+
+
+class Attribute extends _base_js__WEBPACK_IMPORTED_MODULE_0__["Base"] {
/**
- * @param {import("../tokeniser").Tokeniser} tokeniser
+ * @param {import("../tokeniser.js").Tokeniser} tokeniser
*/
- static parse(tokeniser) {
- const tokens = {};
- tokens.base = tokeniser.consume("enum");
+ static parse(tokeniser, { special, noInherit = false, readonly = false } = {}) {
+ const start_position = tokeniser.position;
+ const tokens = { special };
+ const ret = new Attribute({ source: tokeniser.source, tokens });
+ if (!special && !noInherit) {
+ tokens.special = tokeniser.consume("inherit");
+ }
+ if (ret.special === "inherit" && tokeniser.probe("readonly")) {
+ tokeniser.error("Inherited attributes cannot be read-only");
+ }
+ tokens.readonly = tokeniser.consume("readonly");
+ if (readonly && !tokens.readonly && tokeniser.probe("attribute")) {
+ tokeniser.error("Attributes must be readonly in this context");
+ }
+ tokens.base = tokeniser.consume("attribute");
if (!tokens.base) {
+ tokeniser.unconsume(start_position);
return;
}
- tokens.name = tokeniser.consume("identifier") || tokeniser.error("No name for enum");
- const ret = tokeniser.current = new Enum({ source: tokeniser.source, tokens });
- tokens.open = tokeniser.consume("{") || tokeniser.error("Bodyless enum");
- ret.values = Object(_helpers_js__WEBPACK_IMPORTED_MODULE_0__["list"])(tokeniser, {
- parser: EnumValue.parse,
- allowDangler: true,
- listName: "enumeration"
- });
- if (tokeniser.probe("string")) {
- tokeniser.error("No comma between enum values");
- }
- tokens.close = tokeniser.consume("}") || tokeniser.error("Unexpected value in enum");
- if (!ret.values.length) {
- tokeniser.error("No value in enum");
+ ret.idlType = Object(_helpers_js__WEBPACK_IMPORTED_MODULE_1__["type_with_extended_attributes"])(tokeniser, "attribute-type") || tokeniser.error("Attribute lacks a type");
+ switch (ret.idlType.generic) {
+ case "sequence":
+ case "record": tokeniser.error(`Attributes cannot accept ${ret.idlType.generic} types`);
}
- tokens.termination = tokeniser.consume(";") || tokeniser.error("No semicolon after enum");
+ tokens.name = tokeniser.consume("identifier", "async", "required") || tokeniser.error("Attribute lacks a name");
+ tokens.termination = tokeniser.consume(";") || tokeniser.error("Unterminated attribute, expected `;`");
return ret;
}
get type() {
- return "enum";
+ return "attribute";
+ }
+ get special() {
+ if (!this.tokens.special) {
+ return "";
+ }
+ return this.tokens.special.value;
+ }
+ get readonly() {
+ return !!this.tokens.readonly;
}
get name() {
- return Object(_helpers_js__WEBPACK_IMPORTED_MODULE_0__["unescape"])(this.tokens.name.value);
+ return Object(_helpers_js__WEBPACK_IMPORTED_MODULE_1__["unescape"])(this.tokens.name.value);
+ }
+
+ *validate(defs) {
+ yield* this.idlType.validate(defs);
}
}
/***/ }),
-/* 13 */
+/* 16 */
/***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "Includes", function() { return Includes; });
-/* harmony import */ var _base_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(4);
-/* harmony import */ var _helpers_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(2);
+/* harmony import */ var _base_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(7);
+/* harmony import */ var _helpers_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(5);
@@ -1712,7 +1615,647 @@ class Includes extends _base_js__WEBPACK_IMPORTED_MODULE_0__["Base"] {
/***/ }),
-/* 14 */
+/* 17 */
+/***/ (function(module, __webpack_exports__, __webpack_require__) {
+
+"use strict";
+__webpack_require__.r(__webpack_exports__);
+/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "Typedef", function() { return Typedef; });
+/* harmony import */ var _base_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(7);
+/* harmony import */ var _helpers_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(5);
+
+
+
+class Typedef extends _base_js__WEBPACK_IMPORTED_MODULE_0__["Base"] {
+ /**
+ * @param {import("../tokeniser").Tokeniser} tokeniser
+ */
+ static parse(tokeniser) {
+ const tokens = {};
+ const ret = new Typedef({ source: tokeniser.source, tokens });
+ tokens.base = tokeniser.consume("typedef");
+ if (!tokens.base) {
+ return;
+ }
+ ret.idlType = Object(_helpers_js__WEBPACK_IMPORTED_MODULE_1__["type_with_extended_attributes"])(tokeniser, "typedef-type") || tokeniser.error("Typedef lacks a type");
+ tokens.name = tokeniser.consume("identifier") || tokeniser.error("Typedef lacks a name");
+ tokeniser.current = ret;
+ tokens.termination = tokeniser.consume(";") || tokeniser.error("Unterminated typedef, expected `;`");
+ return ret;
+ }
+
+ get type() {
+ return "typedef";
+ }
+ get name() {
+ return Object(_helpers_js__WEBPACK_IMPORTED_MODULE_1__["unescape"])(this.tokens.name.value);
+ }
+
+ *validate(defs) {
+ yield* this.idlType.validate(defs);
+ }
+}
+
+
+/***/ }),
+/* 18 */
+/***/ (function(module, __webpack_exports__, __webpack_require__) {
+
+"use strict";
+__webpack_require__.r(__webpack_exports__);
+/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "CallbackFunction", function() { return CallbackFunction; });
+/* harmony import */ var _base_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(7);
+/* harmony import */ var _helpers_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(5);
+
+
+
+class CallbackFunction extends _base_js__WEBPACK_IMPORTED_MODULE_0__["Base"] {
+ /**
+ * @param {import("../tokeniser.js").Tokeniser} tokeniser
+ */
+ static parse(tokeniser, base) {
+ const tokens = { base };
+ const ret = new CallbackFunction({ source: tokeniser.source, tokens });
+ tokens.name = tokeniser.consume("identifier") || tokeniser.error("Callback lacks a name");
+ tokeniser.current = ret;
+ tokens.assign = tokeniser.consume("=") || tokeniser.error("Callback lacks an assignment");
+ ret.idlType = Object(_helpers_js__WEBPACK_IMPORTED_MODULE_1__["return_type"])(tokeniser) || tokeniser.error("Callback lacks a return type");
+ tokens.open = tokeniser.consume("(") || tokeniser.error("Callback lacks parentheses for arguments");
+ ret.arguments = Object(_helpers_js__WEBPACK_IMPORTED_MODULE_1__["argument_list"])(tokeniser);
+ tokens.close = tokeniser.consume(")") || tokeniser.error("Unterminated callback");
+ tokens.termination = tokeniser.consume(";") || tokeniser.error("Unterminated callback, expected `;`");
+ return ret;
+ }
+
+ get type() {
+ return "callback";
+ }
+ get name() {
+ return Object(_helpers_js__WEBPACK_IMPORTED_MODULE_1__["unescape"])(this.tokens.name.value);
+ }
+
+ *validate(defs) {
+ yield* this.idlType.validate(defs);
+ }
+}
+
+
+/***/ }),
+/* 19 */
+/***/ (function(module, __webpack_exports__, __webpack_require__) {
+
+"use strict";
+__webpack_require__.r(__webpack_exports__);
+/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "Interface", function() { return Interface; });
+/* harmony import */ var _container_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(20);
+/* harmony import */ var _attribute_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(15);
+/* harmony import */ var _operation_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(14);
+/* harmony import */ var _constant_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(21);
+/* harmony import */ var _iterable_js__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(22);
+/* harmony import */ var _helpers_js__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(5);
+/* harmony import */ var _error_js__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(3);
+/* harmony import */ var _validators_interface_js__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(23);
+
+
+
+
+
+
+
+
+
+/**
+ * @param {import("../tokeniser").Tokeniser} tokeniser
+ */
+function static_member(tokeniser) {
+ const special = tokeniser.consume("static");
+ if (!special) return;
+ const member = _attribute_js__WEBPACK_IMPORTED_MODULE_1__["Attribute"].parse(tokeniser, { special }) ||
+ _operation_js__WEBPACK_IMPORTED_MODULE_2__["Operation"].parse(tokeniser, { special }) ||
+ tokeniser.error("No body in static member");
+ return member;
+}
+
+class Interface extends _container_js__WEBPACK_IMPORTED_MODULE_0__["Container"] {
+ /**
+ * @param {import("../tokeniser").Tokeniser} tokeniser
+ */
+ static parse(tokeniser, base, { partial = null } = {}) {
+ const tokens = { partial, base };
+ return _container_js__WEBPACK_IMPORTED_MODULE_0__["Container"].parse(tokeniser, new Interface({ source: tokeniser.source, tokens }), {
+ type: "interface",
+ inheritable: !partial,
+ allowedMembers: [
+ [_constant_js__WEBPACK_IMPORTED_MODULE_3__["Constant"].parse],
+ [static_member],
+ [_helpers_js__WEBPACK_IMPORTED_MODULE_5__["stringifier"]],
+ [_iterable_js__WEBPACK_IMPORTED_MODULE_4__["IterableLike"].parse],
+ [_attribute_js__WEBPACK_IMPORTED_MODULE_1__["Attribute"].parse],
+ [_operation_js__WEBPACK_IMPORTED_MODULE_2__["Operation"].parse]
+ ]
+ });
+ }
+
+ get type() {
+ return "interface";
+ }
+
+ *validate(defs) {
+ yield* this.extAttrs.validate(defs);
+ if (
+ !this.partial &&
+ this.extAttrs.every(extAttr => extAttr.name !== "Exposed") &&
+ this.extAttrs.every(extAttr => extAttr.name !== "NoInterfaceObject")
+ ) {
+ const message = `Interfaces must have \`[Exposed]\` extended attribute. \
+To fix, add, for example, \`[Exposed=Window]\`. Please also consider carefully \
+if your interface should also be exposed in a Worker scope. Refer to the \
+[WebIDL spec section on Exposed](https://heycam.github.io/webidl/#Exposed) \
+for more information.`;
+ yield Object(_error_js__WEBPACK_IMPORTED_MODULE_6__["validationError"])(this.source, this.tokens.name, this, message);
+ }
+
+ yield* super.validate(defs);
+ if (!this.partial) {
+ yield* Object(_validators_interface_js__WEBPACK_IMPORTED_MODULE_7__["checkInterfaceMemberDuplication"])(defs, this);
+ }
+ }
+}
+
+
+/***/ }),
+/* 20 */
+/***/ (function(module, __webpack_exports__, __webpack_require__) {
+
+"use strict";
+__webpack_require__.r(__webpack_exports__);
+/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "Container", function() { return Container; });
+/* harmony import */ var _base_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(7);
+/* harmony import */ var _extended_attributes_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(11);
+/* harmony import */ var _helpers_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(5);
+
+
+
+
+/**
+ * @param {import("../tokeniser.js").Tokeniser} tokeniser
+ */
+function inheritance(tokeniser) {
+ const colon = tokeniser.consume(":");
+ if (!colon) {
+ return {};
+ }
+ const inheritance = tokeniser.consume("identifier") || tokeniser.error("Inheritance lacks a type");
+ return { colon, inheritance };
+}
+
+class Container extends _base_js__WEBPACK_IMPORTED_MODULE_0__["Base"] {
+ /**
+ * @param {import("../tokeniser.js").Tokeniser} tokeniser
+ * @param {*} instance
+ * @param {*} args
+ */
+ static parse(tokeniser, instance, { type, inheritable, allowedMembers }) {
+ const { tokens } = instance;
+ tokens.name = tokeniser.consume("identifier") || tokeniser.error(`Missing name in ${instance.type}`);
+ tokeniser.current = instance;
+ if (inheritable) {
+ Object.assign(tokens, inheritance(tokeniser));
+ }
+ tokens.open = tokeniser.consume("{") || tokeniser.error(`Bodyless ${type}`);
+ instance.members = [];
+ while (true) {
+ tokens.close = tokeniser.consume("}");
+ if (tokens.close) {
+ tokens.termination = tokeniser.consume(";") || tokeniser.error(`Missing semicolon after ${type}`);
+ return instance;
+ }
+ const ea = _extended_attributes_js__WEBPACK_IMPORTED_MODULE_1__["ExtendedAttributes"].parse(tokeniser);
+ let mem;
+ for (const [parser, ...args] of allowedMembers) {
+ mem = parser(tokeniser, ...args);
+ if (mem) {
+ break;
+ }
+ }
+ if (!mem) {
+ tokeniser.error("Unknown member");
+ }
+ mem.extAttrs = ea;
+ instance.members.push(mem);
+ }
+ }
+
+ get partial() {
+ return !!this.tokens.partial;
+ }
+ get name() {
+ return Object(_helpers_js__WEBPACK_IMPORTED_MODULE_2__["unescape"])(this.tokens.name.value);
+ }
+ get inheritance() {
+ if (!this.tokens.inheritance) {
+ return null;
+ }
+ return Object(_helpers_js__WEBPACK_IMPORTED_MODULE_2__["unescape"])(this.tokens.inheritance.value);
+ }
+
+ *validate(defs) {
+ for (const member of this.members) {
+ if (member.validate) {
+ yield* member.validate(defs);
+ }
+ }
+ }
+ }
+
+
+/***/ }),
+/* 21 */
+/***/ (function(module, __webpack_exports__, __webpack_require__) {
+
+"use strict";
+__webpack_require__.r(__webpack_exports__);
+/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "Constant", function() { return Constant; });
+/* harmony import */ var _base_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(7);
+/* harmony import */ var _type_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(6);
+/* harmony import */ var _helpers_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(5);
+
+
+
+
+class Constant extends _base_js__WEBPACK_IMPORTED_MODULE_0__["Base"] {
+ /**
+ * @param {import("../tokeniser.js").Tokeniser} tokeniser
+ */
+ static parse(tokeniser) {
+ const tokens = {};
+ tokens.base = tokeniser.consume("const");
+ if (!tokens.base) {
+ return;
+ }
+ let idlType = Object(_helpers_js__WEBPACK_IMPORTED_MODULE_2__["primitive_type"])(tokeniser);
+ if (!idlType) {
+ const base = tokeniser.consume("identifier") || tokeniser.error("Const lacks a type");
+ idlType = new _type_js__WEBPACK_IMPORTED_MODULE_1__["Type"]({ source: tokeniser.source, tokens: { base } });
+ }
+ if (tokeniser.probe("?")) {
+ tokeniser.error("Unexpected nullable constant type");
+ }
+ idlType.type = "const-type";
+ tokens.name = tokeniser.consume("identifier") || tokeniser.error("Const lacks a name");
+ tokens.assign = tokeniser.consume("=") || tokeniser.error("Const lacks value assignment");
+ tokens.value = Object(_helpers_js__WEBPACK_IMPORTED_MODULE_2__["const_value"])(tokeniser) || tokeniser.error("Const lacks a value");
+ tokens.termination = tokeniser.consume(";") || tokeniser.error("Unterminated const, expected `;`");
+ const ret = new Constant({ source: tokeniser.source, tokens });
+ ret.idlType = idlType;
+ return ret;
+ }
+
+ get type() {
+ return "const";
+ }
+ get name() {
+ return unescape(this.tokens.name.value);
+ }
+ get value() {
+ return Object(_helpers_js__WEBPACK_IMPORTED_MODULE_2__["const_data"])(this.tokens.value);
+ }
+}
+
+
+/***/ }),
+/* 22 */
+/***/ (function(module, __webpack_exports__, __webpack_require__) {
+
+"use strict";
+__webpack_require__.r(__webpack_exports__);
+/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "IterableLike", function() { return IterableLike; });
+/* harmony import */ var _base_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(7);
+/* harmony import */ var _helpers_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(5);
+
+
+
+class IterableLike extends _base_js__WEBPACK_IMPORTED_MODULE_0__["Base"] {
+ /**
+ * @param {import("../tokeniser.js").Tokeniser} tokeniser
+ */
+ static parse(tokeniser) {
+ const start_position = tokeniser.position;
+ const tokens = {};
+ const ret = new IterableLike({ source: tokeniser.source, tokens });
+ tokens.readonly = tokeniser.consume("readonly");
+ if (!tokens.readonly) {
+ tokens.async = tokeniser.consume("async");
+ }
+ tokens.base =
+ tokens.readonly ? tokeniser.consume("maplike", "setlike") :
+ tokens.async ? tokeniser.consume("iterable") :
+ tokeniser.consume("iterable", "maplike", "setlike");
+ if (!tokens.base) {
+ tokeniser.unconsume(start_position);
+ return;
+ }
+
+ const { type } = ret;
+ const secondTypeRequired = type === "maplike" || ret.async;
+ const secondTypeAllowed = secondTypeRequired || type === "iterable";
+
+ tokens.open = tokeniser.consume("<") || tokeniser.error(`Missing less-than sign \`<\` in ${type} declaration`);
+ const first = Object(_helpers_js__WEBPACK_IMPORTED_MODULE_1__["type_with_extended_attributes"])(tokeniser) || tokeniser.error(`Missing a type argument in ${type} declaration`);
+ ret.idlType = [first];
+ if (secondTypeAllowed) {
+ first.tokens.separator = tokeniser.consume(",");
+ if (first.tokens.separator) {
+ ret.idlType.push(Object(_helpers_js__WEBPACK_IMPORTED_MODULE_1__["type_with_extended_attributes"])(tokeniser));
+ }
+ else if (secondTypeRequired) {
+ tokeniser.error(`Missing second type argument in ${type} declaration`);
+ }
+ }
+ tokens.close = tokeniser.consume(">") || tokeniser.error(`Missing greater-than sign \`>\` in ${type} declaration`);
+ tokens.termination = tokeniser.consume(";") || tokeniser.error(`Missing semicolon after ${type} declaration`);
+
+ return ret;
+ }
+
+ get type() {
+ return this.tokens.base.value;
+ }
+ get readonly() {
+ return !!this.tokens.readonly;
+ }
+ get async() {
+ return !!this.tokens.async;
+ }
+}
+
+
+/***/ }),
+/* 23 */
+/***/ (function(module, __webpack_exports__, __webpack_require__) {
+
+"use strict";
+__webpack_require__.r(__webpack_exports__);
+/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "checkInterfaceMemberDuplication", function() { return checkInterfaceMemberDuplication; });
+/* harmony import */ var _error_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(3);
+
+
+function* checkInterfaceMemberDuplication(defs, i) {
+ const opNames = new Set(getOperations(i).map(op => op.name));
+ const partials = defs.partials.get(i.name) || [];
+ const mixins = defs.mixinMap.get(i.name) || [];
+ 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(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 Object(_error_js__WEBPACK_IMPORTED_MODULE_0__["validationError"])(ext.source, addition.tokens.name, ext, message);
+ }
+ }
+ }
+
+ function getOperations(i) {
+ return i.members
+ .filter(({type}) => type === "operation");
+ }
+}
+
+
+/***/ }),
+/* 24 */
+/***/ (function(module, __webpack_exports__, __webpack_require__) {
+
+"use strict";
+__webpack_require__.r(__webpack_exports__);
+/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "Mixin", function() { return Mixin; });
+/* harmony import */ var _container_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(20);
+/* harmony import */ var _constant_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(21);
+/* harmony import */ var _attribute_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(15);
+/* harmony import */ var _operation_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(14);
+/* harmony import */ var _helpers_js__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(5);
+
+
+
+
+
+
+class Mixin extends _container_js__WEBPACK_IMPORTED_MODULE_0__["Container"] {
+ /**
+ * @param {import("../tokeniser").Tokeniser} tokeniser
+ */
+ static parse(tokeniser, base, { partial } = {}) {
+ const tokens = { partial, base };
+ tokens.mixin = tokeniser.consume("mixin");
+ if (!tokens.mixin) {
+ return;
+ }
+ return _container_js__WEBPACK_IMPORTED_MODULE_0__["Container"].parse(tokeniser, new Mixin({ source: tokeniser.source, tokens }), {
+ type: "interface mixin",
+ allowedMembers: [
+ [_constant_js__WEBPACK_IMPORTED_MODULE_1__["Constant"].parse],
+ [_helpers_js__WEBPACK_IMPORTED_MODULE_4__["stringifier"]],
+ [_attribute_js__WEBPACK_IMPORTED_MODULE_2__["Attribute"].parse, { noInherit: true }],
+ [_operation_js__WEBPACK_IMPORTED_MODULE_3__["Operation"].parse, { regular: true }]
+ ]
+ });
+ }
+
+ get type() {
+ return "interface mixin";
+ }
+}
+
+
+/***/ }),
+/* 25 */
+/***/ (function(module, __webpack_exports__, __webpack_require__) {
+
+"use strict";
+__webpack_require__.r(__webpack_exports__);
+/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "Dictionary", function() { return Dictionary; });
+/* harmony import */ var _container_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(20);
+/* harmony import */ var _field_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(26);
+
+
+
+class Dictionary extends _container_js__WEBPACK_IMPORTED_MODULE_0__["Container"] {
+ /**
+ * @param {import("../tokeniser").Tokeniser} tokeniser
+ */
+ static parse(tokeniser, { partial } = {}) {
+ const tokens = { partial };
+ tokens.base = tokeniser.consume("dictionary");
+ if (!tokens.base) {
+ return;
+ }
+ return _container_js__WEBPACK_IMPORTED_MODULE_0__["Container"].parse(tokeniser, new Dictionary({ source: tokeniser.source, tokens }), {
+ type: "dictionary",
+ inheritable: !partial,
+ allowedMembers: [
+ [_field_js__WEBPACK_IMPORTED_MODULE_1__["Field"].parse],
+ ]
+ });
+ }
+
+ get type() {
+ return "dictionary";
+ }
+}
+
+
+/***/ }),
+/* 26 */
+/***/ (function(module, __webpack_exports__, __webpack_require__) {
+
+"use strict";
+__webpack_require__.r(__webpack_exports__);
+/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "Field", function() { return Field; });
+/* harmony import */ var _base_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(7);
+/* harmony import */ var _helpers_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(5);
+/* harmony import */ var _extended_attributes_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(11);
+/* harmony import */ var _default_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(10);
+
+
+
+
+
+class Field extends _base_js__WEBPACK_IMPORTED_MODULE_0__["Base"] {
+ /**
+ * @param {import("../tokeniser").Tokeniser} tokeniser
+ */
+ static parse(tokeniser) {
+ const tokens = {};
+ const ret = new Field({ source: tokeniser.source, tokens });
+ ret.extAttrs = _extended_attributes_js__WEBPACK_IMPORTED_MODULE_2__["ExtendedAttributes"].parse(tokeniser);
+ tokens.required = tokeniser.consume("required");
+ ret.idlType = Object(_helpers_js__WEBPACK_IMPORTED_MODULE_1__["type_with_extended_attributes"])(tokeniser, "dictionary-type") || tokeniser.error("Dictionary member lacks a type");
+ tokens.name = tokeniser.consume("identifier") || tokeniser.error("Dictionary member lacks a name");
+ ret.default = _default_js__WEBPACK_IMPORTED_MODULE_3__["Default"].parse(tokeniser);
+ if (tokens.required && ret.default) tokeniser.error("Required member must not have a default");
+ tokens.termination = tokeniser.consume(";") || tokeniser.error("Unterminated dictionary member, expected `;`");
+ return ret;
+ }
+
+ get type() {
+ return "field";
+ }
+ get name() {
+ return Object(_helpers_js__WEBPACK_IMPORTED_MODULE_1__["unescape"])(this.tokens.name.value);
+ }
+ get required() {
+ return !!this.tokens.required;
+ }
+
+ *validate(defs) {
+ yield* this.idlType.validate(defs);
+ }
+}
+
+
+/***/ }),
+/* 27 */
+/***/ (function(module, __webpack_exports__, __webpack_require__) {
+
+"use strict";
+__webpack_require__.r(__webpack_exports__);
+/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "Namespace", function() { return Namespace; });
+/* harmony import */ var _container_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(20);
+/* harmony import */ var _attribute_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(15);
+/* harmony import */ var _operation_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(14);
+/* harmony import */ var _error_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(3);
+
+
+
+
+
+class Namespace extends _container_js__WEBPACK_IMPORTED_MODULE_0__["Container"] {
+ /**
+ * @param {import("../tokeniser").Tokeniser} tokeniser
+ */
+ static parse(tokeniser, { partial } = {}) {
+ const tokens = { partial };
+ tokens.base = tokeniser.consume("namespace");
+ if (!tokens.base) {
+ return;
+ }
+ return _container_js__WEBPACK_IMPORTED_MODULE_0__["Container"].parse(tokeniser, new Namespace({ source: tokeniser.source, tokens }), {
+ type: "namespace",
+ allowedMembers: [
+ [_attribute_js__WEBPACK_IMPORTED_MODULE_1__["Attribute"].parse, { noInherit: true, readonly: true }],
+ [_operation_js__WEBPACK_IMPORTED_MODULE_2__["Operation"].parse, { regular: true }]
+ ]
+ });
+ }
+
+ get type() {
+ return "namespace";
+ }
+
+ *validate(defs) {
+ if (!this.partial && this.extAttrs.every(extAttr => extAttr.name !== "Exposed")) {
+ const message = `Namespaces must have [Exposed] extended attribute. \
+To fix, add, for example, [Exposed=Window]. Please also consider carefully \
+if your namespace should also be exposed in a Worker scope. Refer to the \
+[WebIDL spec section on Exposed](https://heycam.github.io/webidl/#Exposed) \
+for more information.`;
+ yield Object(_error_js__WEBPACK_IMPORTED_MODULE_3__["validationError"])(this.source, this.tokens.name, this, message);
+ }
+ yield* super.validate(defs);
+ }
+}
+
+
+/***/ }),
+/* 28 */
+/***/ (function(module, __webpack_exports__, __webpack_require__) {
+
+"use strict";
+__webpack_require__.r(__webpack_exports__);
+/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "CallbackInterface", function() { return CallbackInterface; });
+/* harmony import */ var _container_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(20);
+/* harmony import */ var _operation_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(14);
+/* harmony import */ var _constant_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(21);
+
+
+
+
+
+class CallbackInterface extends _container_js__WEBPACK_IMPORTED_MODULE_0__["Container"] {
+ /**
+ * @param {import("../tokeniser").Tokeniser} tokeniser
+ */
+ static parse(tokeniser, callback, { partial = null } = {}) {
+ const tokens = { callback };
+ tokens.base = tokeniser.consume("interface");
+ if (!tokens.base) {
+ return;
+ }
+ return _container_js__WEBPACK_IMPORTED_MODULE_0__["Container"].parse(tokeniser, new CallbackInterface({ source: tokeniser.source, tokens }), {
+ type: "callback interface",
+ inheritable: !partial,
+ allowedMembers: [
+ [_constant_js__WEBPACK_IMPORTED_MODULE_2__["Constant"].parse],
+ [_operation_js__WEBPACK_IMPORTED_MODULE_1__["Operation"].parse, { regular: true }]
+ ]
+ });
+ }
+
+ get type() {
+ return "callback interface";
+ }
+}
+
+
+/***/ }),
+/* 29 */
/***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
@@ -1977,6 +2520,7 @@ function write(ast, { templates: ts = templates } = {}) {
return ts.definition(ts.wrap([
extended_attributes(it.extAttrs),
token(it.tokens.readonly),
+ token(it.tokens.async),
token(it.tokens.base, ts.generic),
token(it.tokens.open),
ts.wrap(it.idlType.map(type)),
@@ -2026,16 +2570,34 @@ function write(ast, { templates: ts = templates } = {}) {
/***/ }),
-/* 15 */
+/* 30 */
/***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "validate", function() { return validate; });
-/* harmony import */ var _error_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(6);
+/* harmony import */ var _error_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(3);
+
+function getMixinMap(all, unique) {
+ const map = new Map();
+ const includes = all.filter(def => def.type === "includes");
+ for (const include of includes) {
+ const mixin = unique.get(include.includes);
+ if (!mixin) {
+ continue;
+ }
+ const array = map.get(include.target);
+ if (array) {
+ array.push(mixin);
+ } else {
+ map.set(include.target, [mixin]);
+ }
+ }
+ return map;
+}
function groupDefinitions(all) {
const unique = new Map();
@@ -2060,7 +2622,16 @@ function groupDefinitions(all) {
duplicates.add(def);
}
}
- return { all, unique, partials, duplicates };
+ return {
+ all,
+ unique,
+ partials,
+ duplicates,
+ mixinMap: getMixinMap(all, unique),
+ cache: {
+ typedefIncludesDictionary: new WeakMap()
+ },
+ };
}
function* checkDuplicatedNames({ unique, duplicates }) {
@@ -2071,67 +2642,29 @@ function* checkDuplicatedNames({ unique, duplicates }) {
}
}
-function* checkInterfaceMemberDuplication(defs) {
- const interfaces = [...defs.unique.values()].filter(def => def.type === "interface");
- const includesMap = getIncludesMap();
-
- for (const i of interfaces) {
- yield* forEachInterface(i);
- }
-
- function* forEachInterface(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 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(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 Object(_error_js__WEBPACK_IMPORTED_MODULE_0__["validationError"])(ext.source, addition.tokens.name, ext, message);
- }
+function* validateIterable(ast) {
+ const defs = groupDefinitions(ast);
+ for (const def of defs.all) {
+ if (def.validate) {
+ yield* def.validate(defs);
}
}
+ yield* checkDuplicatedNames(defs);
+}
- function getOperations(i) {
- return i.members
- .filter(({type}) => type === "operation");
- }
-
- function getIncludesMap() {
- const map = new Map();
- const includes = defs.all.filter(def => def.type === "includes");
- for (const include of includes) {
- const array = map.get(include.target);
- const mixin = defs.unique.get(include.includes);
- if (!mixin) {
- continue;
- }
- if (array) {
- array.push(mixin);
- } else {
- map.set(include.target, [mixin]);
- }
- }
- return map;
+// Remove this once all of our support targets expose `.flat()` by default
+function flatten(array) {
+ if (array.flat) {
+ return array.flat();
}
+ return [].concat(...array);
}
+/**
+ * @param {*} ast AST or array of ASTs
+ */
function validate(ast) {
- const defs = groupDefinitions(ast);
- return [
- ...checkDuplicatedNames(defs),
- ...checkInterfaceMemberDuplication(defs)
- ];
+ return [...validateIterable(flatten(ast))];
}