UNPKG

motion

Version:

motion - moving development forward

162 lines (130 loc) 4.01 kB
/** * Copyright (c) 2014, Facebook, Inc. * All rights reserved. * * This source code is licensed under the BSD-style license found in the * https://raw.github.com/facebook/regenerator/master/LICENSE file. An * additional grant of patent rights can be found in the PATENTS file in * the same directory. */ var assert = require("assert"); var path = require("path"); var fs = require("fs"); var through = require("through"); var transform = require("./lib/visit").transform; var utils = require("./lib/util"); var recast = require("recast"); var types = recast.types; var genOrAsyncFunExp = /\bfunction\s*\*|\basync\b/; var blockBindingExp = /\b(let|const)\s+/; function exports(file, options) { var data = []; return through(write, end); function write(buf) { data.push(buf); } function end() { this.queue(compile(data.join(""), options).code); this.queue(null); } } // To get a writable stream for use as a browserify transform, call // require("regenerator")(). module.exports = exports; // To include the runtime globally in the current node process, call // require("regenerator").runtime(). function runtime() { require("./runtime"); } exports.runtime = runtime; runtime.path = path.join(__dirname, "runtime.js"); function compile(source, options) { options = normalizeOptions(options); if (!genOrAsyncFunExp.test(source)) { return { // Shortcut: no generators or async functions to transform. code: (options.includeRuntime === true ? fs.readFileSync( path.join(__dirname, "runtime.js"), "utf-8" ) + "\n" : "") + source }; } var recastOptions = getRecastOptions(options); var ast = recast.parse(source, recastOptions); var nodePath = new types.NodePath(ast); var programPath = nodePath.get("program"); if (shouldVarify(source, options)) { // Transpile let/const into var declarations. varifyAst(programPath.node); } transform(programPath, options); return recast.print(nodePath, recastOptions); } function normalizeOptions(options) { options = utils.defaults(options || {}, { includeRuntime: false, supportBlockBinding: true }); if (!options.esprima) { options.esprima = require("esprima-fb"); } assert.ok( /harmony/.test(options.esprima.version), "Bad esprima version: " + options.esprima.version ); return options; } function getRecastOptions(options) { var recastOptions = { range: true }; function copy(name) { if (name in options) { recastOptions[name] = options[name]; } } copy("esprima"); copy("sourceFileName"); copy("sourceMapName"); copy("inputSourceMap"); copy("sourceRoot"); return recastOptions; } function shouldVarify(source, options) { var supportBlockBinding = !!options.supportBlockBinding; if (supportBlockBinding) { if (!blockBindingExp.test(source)) { supportBlockBinding = false; } } return supportBlockBinding; } function varify(source, options) { var recastOptions = getRecastOptions(normalizeOptions(options)); var ast = recast.parse(source, recastOptions); varifyAst(ast.program); return recast.print(ast, recastOptions).code; } function varifyAst(ast) { types.namedTypes.Program.assert(ast); var defsResult = require("defs")(ast, { ast: true, disallowUnknownReferences: false, disallowDuplicated: false, disallowVars: false, loopClosures: "iife" }); if (defsResult.errors) { throw new Error(defsResult.errors.join("\n")) } return ast; } // Convenience for just translating let/const to var declarations. exports.varify = varify; // Allow packages that depend on Regenerator to use the same copy of // ast-types, in case multiple versions are installed by NPM. exports.types = types; // Transforms a string of source code, returning the { code, map? } result // from recast.print. exports.compile = compile; // To modify an AST directly, call require("regenerator").transform(ast). exports.transform = transform;