203 lines
5.5 KiB
JavaScript
203 lines
5.5 KiB
JavaScript
module.exports = SystemFormatter;
|
|
|
|
var util = require("../../util");
|
|
var t = require("../../types");
|
|
var _ = require("lodash");
|
|
|
|
var SETTER_MODULE_NAMESPACE = t.identifier("m");
|
|
var DEFAULT_IDENTIFIER = t.identifier("default");
|
|
var NULL_SETTER = t.literal(null);
|
|
|
|
function SystemFormatter(file) {
|
|
this.exportedStatements = [];
|
|
this.importedModule = {};
|
|
|
|
this.exportIdentifier = file.generateUidIdentifier("export");
|
|
this.file = file;
|
|
}
|
|
|
|
SystemFormatter.prototype.transform = function (ast) {
|
|
var program = ast.program;
|
|
var body = program.body;
|
|
|
|
// extract the module name
|
|
var moduleName = this.file.opts.filename
|
|
.replace(/^.*\//, "").replace(/\..*$/, "");
|
|
|
|
// build an array of module names
|
|
var dependencies = Object.keys(this.importedModule).map(t.literal);
|
|
|
|
// generate the __moduleName variable
|
|
var moduleNameVariableNode = t.variableDeclaration("var", [
|
|
t.variableDeclarator(
|
|
t.identifier("__moduleName"),
|
|
t.literal(moduleName)
|
|
)
|
|
]);
|
|
body.splice(1, 0, moduleNameVariableNode);
|
|
|
|
// generate an array of import variables
|
|
|
|
var declaredSetters = _(this.importedModule)
|
|
.map()
|
|
.flatten()
|
|
.pluck("variableName")
|
|
.pluck("name")
|
|
.uniq()
|
|
.map(t.identifier)
|
|
.map(function (name) {
|
|
return t.variableDeclarator(name);
|
|
})
|
|
.value();
|
|
|
|
if (declaredSetters.length) {
|
|
body.splice(2, 0, t.variableDeclaration("var", declaredSetters));
|
|
}
|
|
|
|
// generate the execute function expression
|
|
var executeFunctionExpression = t.functionExpression(
|
|
null, [], t.blockStatement(this.exportedStatements)
|
|
);
|
|
|
|
// generate the execute function expression
|
|
var settersArrayExpression = t.arrayExpression(this._buildSetters());
|
|
|
|
// generate the return statement
|
|
var moduleReturnStatement = t.returnStatement(t.objectExpression([
|
|
t.property("init", t.identifier("setters"), settersArrayExpression),
|
|
t.property("init", t.identifier("execute"), executeFunctionExpression)
|
|
]));
|
|
body.push(moduleReturnStatement);
|
|
|
|
// runner
|
|
var runner = util.template("register", {
|
|
MODULE_NAME: t.literal(moduleName),
|
|
MODULE_DEPENDENCIES: t.arrayExpression(dependencies),
|
|
MODULE_BODY: t.functionExpression(
|
|
null,
|
|
[this.exportIdentifier],
|
|
t.blockStatement(body)
|
|
)
|
|
});
|
|
|
|
program.body = [t.expressionStatement(runner)];
|
|
};
|
|
|
|
SystemFormatter.prototype._buildSetters = function () {
|
|
// generate setters array expression elements
|
|
return _.map(this.importedModule, function (specs) {
|
|
if (!specs.length) {
|
|
return NULL_SETTER;
|
|
}
|
|
|
|
var expressionStatements = _.map(specs, function (spec) {
|
|
var right = SETTER_MODULE_NAMESPACE;
|
|
if (!spec.isBatch) {
|
|
right = t.memberExpression(right, spec.key);
|
|
}
|
|
|
|
return t.expressionStatement(
|
|
t.assignmentExpression("=", spec.variableName, right
|
|
)
|
|
);
|
|
});
|
|
|
|
return t.functionExpression(
|
|
null, [SETTER_MODULE_NAMESPACE], t.blockStatement(expressionStatements)
|
|
);
|
|
});
|
|
};
|
|
|
|
SystemFormatter.prototype.import = function (node) {
|
|
var MODULE_NAME = node.source.value;
|
|
this.importedModule[MODULE_NAME] = this.importedModule[MODULE_NAME] || [];
|
|
};
|
|
|
|
SystemFormatter.prototype.importSpecifier = function (specifier, node) {
|
|
var variableName = t.getSpecifierName(specifier);
|
|
|
|
// import foo from "foo";
|
|
if (specifier.default) {
|
|
specifier.id = DEFAULT_IDENTIFIER;
|
|
}
|
|
|
|
var MODULE_NAME = node.source.value;
|
|
|
|
this.importedModule[MODULE_NAME] = this.importedModule[MODULE_NAME] || [];
|
|
|
|
this.importedModule[MODULE_NAME].push({
|
|
variableName: variableName,
|
|
isBatch: specifier.type === "ImportBatchSpecifier",
|
|
key: specifier.id
|
|
});
|
|
};
|
|
|
|
SystemFormatter.prototype._export = function (name, identifier) {
|
|
this.exportedStatements.push(t.expressionStatement(
|
|
t.callExpression(this.exportIdentifier, [t.literal(name), identifier])
|
|
));
|
|
};
|
|
|
|
SystemFormatter.prototype.export = function (node, nodes) {
|
|
var declar = node.declaration;
|
|
var variableName, identifier;
|
|
|
|
if (node.default) {
|
|
// export default foo
|
|
variableName = DEFAULT_IDENTIFIER.name;
|
|
if (t.isClass(declar) || t.isFunction(declar)) {
|
|
if (!declar.id) {
|
|
declar.id = this.file.generateUidIdentifier("anonymous");
|
|
}
|
|
|
|
nodes.push(t.toStatement(declar));
|
|
declar = declar.id;
|
|
}
|
|
|
|
identifier = declar;
|
|
} else if (t.isVariableDeclaration(declar)) {
|
|
// export var foo
|
|
variableName = declar.declarations[0].id.name;
|
|
identifier = declar.declarations[0].id;
|
|
|
|
nodes.push(declar);
|
|
} else {
|
|
// export function foo () {}
|
|
variableName = declar.id.name;
|
|
identifier = declar.id;
|
|
|
|
nodes.push(declar);
|
|
}
|
|
|
|
this._export(variableName, identifier);
|
|
};
|
|
|
|
SystemFormatter.prototype.exportSpecifier = function (specifier, node) {
|
|
var variableName = t.getSpecifierName(specifier);
|
|
|
|
if (node.source) {
|
|
if (t.isExportBatchSpecifier(specifier)) {
|
|
// export * from "foo";
|
|
var exportIdentifier = t.identifier("exports");
|
|
this.exportedStatements.push(
|
|
t.variableDeclaration("var", [
|
|
t.variableDeclarator(exportIdentifier, this.exportIdentifier)
|
|
])
|
|
);
|
|
|
|
this.exportedStatements.push(util.template("exports-wildcard", {
|
|
OBJECT: t.identifier(node.source.value)
|
|
}, true));
|
|
} else {
|
|
// export { foo } from "test";
|
|
this._export(variableName.name, t.memberExpression(
|
|
t.identifier(node.source.value),
|
|
specifier.id
|
|
));
|
|
}
|
|
} else {
|
|
// export { foo };
|
|
this._export(variableName.name, specifier.id);
|
|
}
|
|
};
|