blob: 52656ce2e1090b77e9e784ae90feccfdf40e1ef5 [file] [log] [blame]
module.exports = function (fork) {
fork.use(require("./es7"));
var types = fork.use(require("../lib/types"));
var def = types.Type.def;
var or = types.Type.or;
var defaults = fork.use(require("../lib/shared")).defaults;
def("JSXAttribute")
.bases("Node")
.build("name", "value")
.field("name", or(def("JSXIdentifier"), def("JSXNamespacedName")))
.field("value", or(
def("Literal"), // attr="value"
def("JSXExpressionContainer"), // attr={value}
null // attr= or just attr
), defaults["null"]);
def("JSXIdentifier")
.bases("Identifier")
.build("name")
.field("name", String);
def("JSXNamespacedName")
.bases("Node")
.build("namespace", "name")
.field("namespace", def("JSXIdentifier"))
.field("name", def("JSXIdentifier"));
def("JSXMemberExpression")
.bases("MemberExpression")
.build("object", "property")
.field("object", or(def("JSXIdentifier"), def("JSXMemberExpression")))
.field("property", def("JSXIdentifier"))
.field("computed", Boolean, defaults.false);
var JSXElementName = or(
def("JSXIdentifier"),
def("JSXNamespacedName"),
def("JSXMemberExpression")
);
def("JSXSpreadAttribute")
.bases("Node")
.build("argument")
.field("argument", def("Expression"));
var JSXAttributes = [or(
def("JSXAttribute"),
def("JSXSpreadAttribute")
)];
def("JSXExpressionContainer")
.bases("Expression")
.build("expression")
.field("expression", def("Expression"));
def("JSXElement")
.bases("Expression")
.build("openingElement", "closingElement", "children")
.field("openingElement", def("JSXOpeningElement"))
.field("closingElement", or(def("JSXClosingElement"), null), defaults["null"])
.field("children", [or(
def("JSXElement"),
def("JSXExpressionContainer"),
def("JSXText"),
def("Literal") // TODO Esprima should return JSXText instead.
)], defaults.emptyArray)
.field("name", JSXElementName, function () {
// Little-known fact: the `this` object inside a default function
// is none other than the partially-built object itself, and any
// fields initialized directly from builder function arguments
// (like openingElement, closingElement, and children) are
// guaranteed to be available.
return this.openingElement.name;
}, true) // hidden from traversal
.field("selfClosing", Boolean, function () {
return this.openingElement.selfClosing;
}, true) // hidden from traversal
.field("attributes", JSXAttributes, function () {
return this.openingElement.attributes;
}, true); // hidden from traversal
def("JSXOpeningElement")
.bases("Node") // TODO Does this make sense? Can't really be an JSXElement.
.build("name", "attributes", "selfClosing")
.field("name", JSXElementName)
.field("attributes", JSXAttributes, defaults.emptyArray)
.field("selfClosing", Boolean, defaults["false"]);
def("JSXClosingElement")
.bases("Node") // TODO Same concern.
.build("name")
.field("name", JSXElementName);
def("JSXText")
.bases("Literal")
.build("value")
.field("value", String);
def("JSXEmptyExpression").bases("Expression").build();
};