UNPKG

webidl2

Version:
112 lines (107 loc) 3.29 kB
import { Base } from "./base.js"; import { return_type, argument_list, unescape, autoParenter, } from "./helpers.js"; import { validationError } from "../error.js"; export class Operation extends Base { /** * @param {import("../tokeniser.js").Tokeniser} tokeniser * @param {object} [options] * @param {import("../tokeniser.js").Token} [options.special] * @param {import("../tokeniser.js").Token} [options.regular] */ static parse(tokeniser, { special, regular } = {}) { const tokens = { special }; const ret = autoParenter( 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 = return_type(tokeniser) || tokeniser.error("Missing return type"); tokens.name = tokeniser.consumeKind("identifier") || tokeniser.consume("includes"); tokens.open = tokeniser.consume("(") || tokeniser.error("Invalid operation"); ret.arguments = argument_list(tokeniser); tokens.close = tokeniser.consume(")") || tokeniser.error("Unterminated operation"); tokens.termination = tokeniser.consume(";") || tokeniser.error("Unterminated operation, expected `;`"); return ret.this; } get type() { return "operation"; } get name() { const { name } = this.tokens; if (!name) { return ""; } return unescape(name.value); } get special() { if (!this.tokens.special) { return ""; } return this.tokens.special.value; } *validate(defs) { yield* this.extAttrs.validate(defs); if (!this.name && ["", "static"].includes(this.special)) { const message = `Regular or static operations must have both a return type and an identifier.`; yield validationError(this.tokens.open, this, "incomplete-op", message); } if (this.idlType) { if (this.idlType.generic === "async_sequence") { const message = `async_sequence types cannot be returned by an operation.`; yield validationError( this.idlType.tokens.base, this, "async-sequence-idl-to-js", message, ); } yield* this.idlType.validate(defs); } for (const argument of this.arguments) { yield* argument.validate(defs); } } /** @param {import("../writer.js").Writer} w */ write(w) { const { parent } = this; const body = this.idlType ? [ w.ts.type(this.idlType.write(w)), w.name_token(this.tokens.name, { data: this, parent }), w.token(this.tokens.open), w.ts.wrap(this.arguments.map((arg) => arg.write(w))), w.token(this.tokens.close), ] : []; return w.ts.definition( w.ts.wrap([ this.extAttrs.write(w), this.tokens.name ? w.token(this.tokens.special) : w.token(this.tokens.special, w.ts.nameless, { data: this, parent }), ...body, w.token(this.tokens.termination), ]), { data: this, parent }, ); } }