require("./core"); var types = require("../lib/types"); var def = types.Type.def; var or = types.Type.or; var builtin = types.builtInTypes; var isBoolean = builtin.boolean; var isObject = builtin.object; var isString = builtin.string; var defaults = require("../lib/shared").defaults; def("Function") .field("generator", isBoolean, defaults["false"]) .field("expression", isBoolean, defaults["false"]) .field("defaults", [or(def("Expression"), null)], defaults.emptyArray) // TODO This could be represented as a SpreadElementPattern in .params. .field("rest", or(def("Identifier"), null), defaults["null"]); def("FunctionDeclaration") .build("id", "params", "body", "generator", "expression"); def("FunctionExpression") .build("id", "params", "body", "generator", "expression"); // TODO The Parser API calls this ArrowExpression, but Esprima uses // ArrowFunctionExpression. def("ArrowFunctionExpression") .bases("Function", "Expression") .build("params", "body", "expression") // The forced null value here is compatible with the overridden // definition of the "id" field in the Function interface. .field("id", null, defaults["null"]) // Arrow function bodies are allowed to be expressions. .field("body", or(def("BlockStatement"), def("Expression"))) // The current spec forbids arrow generators, so I have taken the // liberty of enforcing that. TODO Report this. .field("generator", false, defaults["false"]); def("YieldExpression") .bases("Expression") .build("argument", "delegate") .field("argument", or(def("Expression"), null)) .field("delegate", isBoolean, defaults["false"]); def("GeneratorExpression") .bases("Expression") .build("body", "blocks", "filter") .field("body", def("Expression")) .field("blocks", [def("ComprehensionBlock")]) .field("filter", or(def("Expression"), null)); def("ComprehensionExpression") .bases("Expression") .build("body", "blocks", "filter") .field("body", def("Expression")) .field("blocks", [def("ComprehensionBlock")]) .field("filter", or(def("Expression"), null)); def("ComprehensionBlock") .bases("Node") .build("left", "right", "each") .field("left", def("Pattern")) .field("right", def("Expression")) .field("each", isBoolean); def("ModuleSpecifier") .bases("Literal") .build("value") .field("value", isString); def("Property") // Esprima extensions not mentioned in the Mozilla Parser API: .field("key", or(def("Literal"), def("Identifier"), def("Expression"))) .field("method", isBoolean, defaults["false"]) .field("shorthand", isBoolean, defaults["false"]) .field("computed", isBoolean, defaults["false"]); def("PropertyPattern") .field("key", or(def("Literal"), def("Identifier"), def("Expression"))) .field("computed", isBoolean, defaults["false"]); def("MethodDefinition") .bases("Declaration") .build("kind", "key", "value", "static") .field("kind", or("init", "get", "set", "")) .field("key", or(def("Literal"), def("Identifier"), def("Expression"))) .field("value", def("Function")) .field("computed", isBoolean, defaults["false"]) .field("static", isBoolean, defaults["false"]); def("SpreadElement") .bases("Node") .build("argument") .field("argument", def("Expression")); def("ArrayExpression") .field("elements", [or(def("Expression"), def("SpreadElement"), null)]); def("NewExpression") .field("arguments", [or(def("Expression"), def("SpreadElement"))]); def("CallExpression") .field("arguments", [or(def("Expression"), def("SpreadElement"))]); def("SpreadElementPattern") .bases("Pattern") .build("argument") .field("argument", def("Pattern")); def("ArrayPattern") .field("elements", [or( def("Pattern"), null, // used by esprima def("SpreadElement") )]); var ClassBodyElement = or( def("MethodDefinition"), def("VariableDeclarator"), def("ClassPropertyDefinition"), def("ClassProperty") ); def("ClassProperty") .bases("Declaration") .build("key") .field("key", or(def("Literal"), def("Identifier"), def("Expression"))) .field("computed", isBoolean, defaults["false"]); def("ClassPropertyDefinition") // static property .bases("Declaration") .build("definition") // Yes, Virginia, circular definitions are permitted. .field("definition", ClassBodyElement); def("ClassBody") .bases("Declaration") .build("body") .field("body", [ClassBodyElement]); def("ClassDeclaration") .bases("Declaration") .build("id", "body", "superClass") .field("id", or(def("Identifier"), null)) .field("body", def("ClassBody")) .field("superClass", or(def("Expression"), null), defaults["null"]); def("ClassExpression") .bases("Expression") .build("id", "body", "superClass") .field("id", or(def("Identifier"), null), defaults["null"]) .field("body", def("ClassBody")) .field("superClass", or(def("Expression"), null), defaults["null"]) .field("implements", [def("ClassImplements")], defaults.emptyArray); def("ClassImplements") .bases("Node") .build("id") .field("id", def("Identifier")) .field("superClass", or(def("Expression"), null), defaults["null"]); // Specifier and NamedSpecifier are abstract non-standard types that I // introduced for definitional convenience. def("Specifier").bases("Node"); def("NamedSpecifier") .bases("Specifier") // Note: this abstract type is intentionally not buildable. .field("id", def("Identifier")) .field("name", or(def("Identifier"), null), defaults["null"]); // Like NamedSpecifier, except type:"ExportSpecifier" and buildable. // export {} [from ...]; def("ExportSpecifier") .bases("NamedSpecifier") .build("id", "name"); // export <*> from ...; def("ExportBatchSpecifier") .bases("Specifier") .build(); // Like NamedSpecifier, except type:"ImportSpecifier" and buildable. // import {} from ...; def("ImportSpecifier") .bases("NamedSpecifier") .build("id", "name"); // import <* as id> from ...; def("ImportNamespaceSpecifier") .bases("Specifier") .build("id") .field("id", def("Identifier")); // import from ...; def("ImportDefaultSpecifier") .bases("Specifier") .build("id") .field("id", def("Identifier")); def("ExportDeclaration") .bases("Declaration") .build("default", "declaration", "specifiers", "source") .field("default", isBoolean) .field("declaration", or( def("Declaration"), def("Expression"), // Implies default. null )) .field("specifiers", [or( def("ExportSpecifier"), def("ExportBatchSpecifier") )], defaults.emptyArray) .field("source", or( def("Literal"), def("ModuleSpecifier"), null ), defaults["null"]); def("ImportDeclaration") .bases("Declaration") .build("specifiers", "source") .field("specifiers", [or( def("ImportSpecifier"), def("ImportNamespaceSpecifier"), def("ImportDefaultSpecifier") )], defaults.emptyArray) .field("source", or( def("Literal"), def("ModuleSpecifier") )); def("TaggedTemplateExpression") .bases("Expression") .field("tag", def("Expression")) .field("quasi", def("TemplateLiteral")); def("TemplateLiteral") .bases("Expression") .build("quasis", "expressions") .field("quasis", [def("TemplateElement")]) .field("expressions", [def("Expression")]); def("TemplateElement") .bases("Node") .build("value", "tail") .field("value", {"cooked": isString, "raw": isString}) .field("tail", isBoolean);