sucrase
Version:
Super-fast alternative to Babel for when you can target modern JS runtimes
141 lines (105 loc) • 4.69 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.getTokens = getTokens;
exports.parse = parse;
exports.parseExpression = parseExpression;
Object.defineProperty(exports, "tokTypes", {
enumerable: true,
get: function () {
return _types.types;
}
});
var _parser = _interopRequireWildcard(require("./parser"));
var _types = require("./tokenizer/types");
require("./tokenizer/context");
var _estree = _interopRequireDefault(require("./plugins/estree"));
var _flow = _interopRequireDefault(require("./plugins/flow"));
var _jsx = _interopRequireDefault(require("./plugins/jsx"));
var _typescript = _interopRequireDefault(require("./plugins/typescript"));
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = Object.defineProperty && Object.getOwnPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : {}; if (desc.get || desc.set) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } } newObj.default = obj; return newObj; } }
_parser.plugins.estree = _estree.default;
_parser.plugins.flow = _flow.default;
_parser.plugins.jsx = _jsx.default;
_parser.plugins.typescript = _typescript.default;
function getTokens(input, options) {
const parser = getParser(options, input);
parser.next();
while (parser.state.type.label !== 'eof') {
parser.next();
}
parser.next();
return parser.state.tokens;
}
function parse(input, options) {
if (options && options.sourceType === "unambiguous") {
options = Object.assign({}, options);
try {
options.sourceType = "module";
const ast = getParser(options, input).parse(); // Rather than try to parse as a script first, we opt to parse as a module and convert back
// to a script where possible to avoid having to do a full re-parse of the input content.
if (!hasModuleSyntax(ast)) ast.program.sourceType = "script";
return ast;
} catch (moduleError) {
try {
options.sourceType = "script";
return getParser(options, input).parse();
} catch (scriptError) {}
throw moduleError;
}
} else {
return getParser(options, input).parse();
}
}
function parseExpression(input, options) {
const parser = getParser(options, input);
if (parser.options.strictMode) {
parser.state.strict = true;
}
return parser.getExpression();
}
function getParser(options, input) {
const cls = options && options.plugins ? getParserClass(options.plugins) : _parser.default;
return new cls(options, input);
}
const parserClassCache = {};
/** Get a Parser class with plugins applied. */
function getParserClass(pluginsFromOptions) {
if (pluginsFromOptions.indexOf("decorators") >= 0 && pluginsFromOptions.indexOf("decorators2") >= 0) {
throw new Error("Cannot use decorators and decorators2 plugin together");
} // Filter out just the plugins that have an actual mixin associated with them.
let pluginList = pluginsFromOptions.filter(p => p === "estree" || p === "flow" || p === "jsx" || p === "typescript");
if (pluginList.indexOf("flow") >= 0) {
// ensure flow plugin loads last
pluginList = pluginList.filter(plugin => plugin !== "flow");
pluginList.push("flow");
}
if (pluginList.indexOf("flow") >= 0 && pluginList.indexOf("typescript") >= 0) {
throw new Error("Cannot combine flow and typescript plugins.");
}
if (pluginList.indexOf("typescript") >= 0) {
// ensure typescript plugin loads last
pluginList = pluginList.filter(plugin => plugin !== "typescript");
pluginList.push("typescript");
}
if (pluginList.indexOf("estree") >= 0) {
// ensure estree plugin loads first
pluginList = pluginList.filter(plugin => plugin !== "estree");
pluginList.unshift("estree");
}
const key = pluginList.join("/");
let cls = parserClassCache[key];
if (!cls) {
cls = _parser.default;
for (const plugin of pluginList) {
cls = _parser.plugins[plugin](cls);
}
parserClassCache[key] = cls;
}
return cls;
}
function hasModuleSyntax(ast) {
return ast.program.body.some(child => child.type === "ImportDeclaration" && (!child.importKind || child.importKind === "value") || child.type === "ExportNamedDeclaration" && (!child.exportKind || child.exportKind === "value") || child.type === "ExportAllDeclaration" && (!child.exportKind || child.exportKind === "value") || child.type === "ExportDefaultDeclaration");
}