fable-compiler-netcore
Version:
F# to JavaScript compiler
88 lines (87 loc) • 3.39 kB
JavaScript
;
var types = require("babel-types");
var template = require("babel-template");
// Remove null args at the end of method or constructor calls.
// This may conflict in some situations when comparing null to undefined, see #231,
// but if disabled can cause problems with some APIs that use options to represent optional
// arguments like CanvasRenderingContext2D.fill: ?fillRule: string -> unit (fails if passed null).
function removeNullTailArgs(path) {
if (Array.isArray(path.node.arguments)) {
for (var i = path.node.arguments.length - 1; i >= 0; i--) {
if (types.isNullLiteral(path.node.arguments[i]))
path.node.arguments.splice(i, 1);
else
break;
}
}
}
/**
* Removes unnecessary null statements and null arguments at the end
* of method/constructor calls, as these usually represent optional
* arguments set to None by F# compiler and may conflict with some JS APIs.
* This plugin must come after transformMacroExpressions (see #377).
*/
exports.removeUnneededNulls = {
visitor: {
// Remove `null;` statements (e.g. at the end of constructors)
ExpressionStatement: function (path) {
if (types.isNullLiteral(path.node.expression))
path.remove();
}
}
};
/**
* When Babel compiles class methods to ES5 it keeps the function named
* even if it's a function expression, this is causing problems with Rollup.
*/
exports.removeFunctionExpressionNames = {
visitor: {
FunctionExpression: function (path) {
path.node.id = null;
}
}
};
/**
* Custom plugin to simulate macro expressions.
*/
exports.transformMacroExpressions = {
visitor: {
StringLiteral: function (path) {
var node = path.node;
if (!node.macro || !node.value) {
return;
}
var buildArgs = {}, macro = node.value;
try {
var args = node.args;
for (var i = 0; i < args.length; i++) {
buildArgs["$" + i] = args[i];
}
macro = macro
.replace(/\$(\d+)\.\.\./, function (m, i) {
var rep = [], j = parseInt(i);
for (; j < args.length; j++) {
rep.push("$" + j);
}
return rep.join(",");
})
.replace(/\{\{\$(\d+)\?(.*?)\:(.*?)\}\}/g, function (_, g1, g2, g3) {
var i = parseInt(g1);
return i < args.length && args[i].value ? g2 : g3;
})
.replace(/\{\{([^\}]*\$(\d+).*?)\}\}/g, function (_, g1, g2) {
var i = parseInt(g2);
return i < args.length ? g1 : "";
});
var buildMacro = template(macro);
path.replaceWithMultiple(buildMacro(buildArgs));
}
catch (err) {
console.log("BABEL ERROR: Failed to parse macro: " + macro);
console.log("MACRO ARGUMENTS: " + Object.getOwnPropertyNames(buildArgs).join());
console.log(err.message);
process.exit(1);
}
}
}
};