UNPKG

webidl2

Version:
128 lines (119 loc) 3.44 kB
import { Base } from "./base.js"; import { ExtendedAttributes } from "./extended-attributes.js"; import { unescape, autoParenter } from "./helpers.js"; /** * @param {import("../tokeniser.js").Tokeniser} tokeniser */ function inheritance(tokeniser) { const colon = tokeniser.consume(":"); if (!colon) { return {}; } const inheritance = tokeniser.consumeKind("identifier") || tokeniser.error("Inheritance lacks a type"); return { colon, inheritance }; } /** * Parser callback. * @callback ParserCallback * @param {import("../tokeniser.js").Tokeniser} tokeniser * @param {...*} args */ /** * A parser callback and optional option object. * @typedef AllowedMember * @type {[ParserCallback, object?]} */ export class Container extends Base { /** * @param {import("../tokeniser.js").Tokeniser} tokeniser * @param {*} instance TODO: This should be {T extends Container}, but see https://github.com/microsoft/TypeScript/issues/4628 * @param {*} args */ static parse(tokeniser, instance, { inheritable, allowedMembers }) { const { tokens, type } = instance; tokens.name = tokeniser.consumeKind("identifier") || tokeniser.error(`Missing name in ${type}`); tokeniser.current = instance; instance = autoParenter(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.this; } const ea = ExtendedAttributes.parse(tokeniser); let mem; for (const [parser, ...args] of allowedMembers) { mem = autoParenter(parser(tokeniser, ...args)); if (mem) { break; } } if (!mem) { tokeniser.error("Unknown member"); } mem.extAttrs = ea; instance.members.push(mem.this); } } get partial() { return !!this.tokens.partial; } get name() { return unescape(this.tokens.name.value); } get inheritance() { if (!this.tokens.inheritance) { return null; } return unescape(this.tokens.inheritance.value); } *validate(defs) { for (const member of this.members) { if (member.validate) { yield* member.validate(defs); } } } /** @param {import("../writer.js").Writer} w */ write(w) { const inheritance = () => { if (!this.tokens.inheritance) { return ""; } return w.ts.wrap([ w.token(this.tokens.colon), w.ts.trivia(this.tokens.inheritance.trivia), w.ts.inheritance( w.reference(this.tokens.inheritance.value, { context: this }), ), ]); }; return w.ts.definition( w.ts.wrap([ this.extAttrs.write(w), w.token(this.tokens.callback), w.token(this.tokens.partial), w.token(this.tokens.base), w.token(this.tokens.mixin), w.name_token(this.tokens.name, { data: this }), inheritance(), w.token(this.tokens.open), w.ts.wrap(this.members.map((m) => m.write(w))), w.token(this.tokens.close), w.token(this.tokens.termination), ]), { data: this }, ); } }