I'm extremely stupid and didn't commit as I go. To anyone reading this
I'm extremely sorry. A lot of these changes are very broad and I plan on
releasing Babel 6.0.0 today live on stage at Ember Camp London so I'm
afraid I couldn't wait. If you're ever in London I'll buy you a beer
(or assorted beverage!) to make up for it, also I'll kiss your feet and
give you a back massage, maybe.
This commit is contained in:
Sebastian McKenzie
2015-10-29 17:51:24 +00:00
parent 3974dd762d
commit ae7d5367f1
1501 changed files with 16477 additions and 19786 deletions

View File

@@ -1,29 +1,36 @@
/* @flow */
import isFunction from "lodash/lang/isFunction";
import transform from "../transformation";
import * as babylon from "babylon";
import * as util from "../util";
import fs from "fs";
export { util, transform };
export { pipeline, lint } from "../transformation";
export { canCompile } from "../util";
export { default as File } from "../transformation/file";
export { default as options } from "../transformation/file/options/config";
export { default as Plugin } from "../transformation/plugin";
export { default as Pipeline } from "../transformation/pipeline";
export { default as buildExternalHelpers } from "../tools/build-external-helpers";
export { default as template } from "babel-template";
export { version } from "../../package";
//
import * as util from "../util";
export { util };
import * as messages from "babel-messages";
export { messages };
import * as t from "babel-types";
export { t as types };
//
import Pipeline from "../transformation/pipeline";
export { Pipeline };
let pipeline = new Pipeline;
export let transform = pipeline.transform.bind(pipeline);
export let transformFromAst = pipeline.transformFromAst.bind(pipeline);
//
export function transformFile(filename: string, opts?: Object, callback: Function) {
if (isFunction(opts)) {

View File

@@ -1,3 +1,5 @@
/* @flow */
import path from "path";
import fs from "fs";
import homeOrTmp from "home-or-tmp";

View File

@@ -1,5 +1,6 @@
/* @flow */
import deepClone from "lodash/lang/cloneDeep";
import sourceMapSupport from "source-map-support";
import * as registerCache from "./cache";
import OptionManager from "../../transformation/file/options/option-manager";
@@ -10,10 +11,6 @@ import * as util from "../../util";
import fs from "fs";
import path from "path";
/**
* Install sourcemaps into node.
*/
sourceMapSupport.install({
handleUncaughtExceptions: false,
retrieveSourceMap(source) {
@@ -29,17 +26,9 @@ sourceMapSupport.install({
}
});
/**
* Load and setup cache.
*/
registerCache.load();
let cache = registerCache.get();
/**
* Store options.
*/
let transformOpts = {};
let ignore;
@@ -50,33 +39,21 @@ let maps = {};
let cwd = process.cwd();
/**
* Get path from `filename` relative to the current working directory.
*/
function getRelativePath(filename){
return path.relative(cwd, filename);
}
/**
* Get last modified time for a `filename`.
*/
function mtime(filename) {
return +fs.statSync(filename).mtime;
}
/**
* Compile a `filename` with optional `opts`.
*/
function compile(filename, opts = {}) {
let result;
opts.filename = filename;
let optsManager = new OptionManager;
optsManager.mergeOptions(transformOpts);
optsManager.mergeOptions(deepClone(transformOpts));
opts = optsManager.init(opts);
let cacheKey = `${JSON.stringify(opts)}:${babel.version}`;
@@ -108,10 +85,6 @@ function compile(filename, opts = {}) {
return result.code;
}
/**
* Test if a `filename` should be ignored by Babel.
*/
function shouldIgnore(filename) {
if (!ignore && !only) {
return getRelativePath(filename).split(path.sep).indexOf("node_modules") >= 0;
@@ -120,58 +93,13 @@ function shouldIgnore(filename) {
}
}
/**
* Monkey patch istanbul if it is running so that it works properly.
*/
let istanbulMonkey = {};
if (process.env.running_under_istanbul) {
// we need to monkey patch fs.readFileSync so we can hook into
// what istanbul gets, it's extremely dirty but it's the only way
let _readFileSync = fs.readFileSync;
fs.readFileSync = function (filename) {
if (istanbulMonkey[filename]) {
delete istanbulMonkey[filename];
let code = compile(filename, {
auxiliaryCommentBefore: "istanbul ignore next"
});
istanbulMonkey[filename] = true;
return code;
} else {
return _readFileSync.apply(this, arguments);
}
};
}
/**
* Replacement for the loader for istanbul.
*/
function istanbulLoader(m, filename, old) {
istanbulMonkey[filename] = true;
old(m, filename);
}
/**
* Default loader.
*/
function normalLoader(m, filename) {
function loader(m, filename) {
m._compile(compile(filename), filename);
}
/**
* Register a loader for an extension.
*/
function registerExtension(ext) {
let old = oldHandlers[ext] || oldHandlers[".js"] || require.extensions[".js"];
let loader = normalLoader;
if (process.env.running_under_istanbul) loader = istanbulLoader;
require.extensions[ext] = function (m, filename) {
if (shouldIgnore(filename)) {
old(m, filename);
@@ -181,10 +109,6 @@ function registerExtension(ext) {
};
}
/**
* Register loader for given extensions.
*/
function hookExtensions(_exts) {
each(oldHandlers, function (old, ext) {
if (old === undefined) {
@@ -202,16 +126,8 @@ function hookExtensions(_exts) {
});
}
/**
* Register loader for default extensions.
*/
hookExtensions(util.canCompile.EXTENSIONS);
/**
* Update options at runtime.
*/
export default function (opts?: Object = {}) {
if (opts.only != null) only = util.arrayify(opts.only, util.regexify);
if (opts.ignore != null) ignore = util.arrayify(opts.ignore, util.regexify);

View File

@@ -0,0 +1,24 @@
/* @flow */
import Module from "module";
let relativeModules = {};
export default function (loc: string, relative: string = process.cwd()): ?string {
// we're in the browser, probably
if (typeof Module === "object") return null;
let relativeMod = relativeModules[relative];
if (!relativeMod) {
relativeMod = new Module;
relativeMod.paths = Module._nodeModulePaths(relative);
relativeModules[relative] = relativeMod;
}
try {
return Module._resolveFilename(loc, relativeMod);
} catch (err) {
return null;
}
}

View File

@@ -16,9 +16,10 @@ export default class Store extends Map {
if (this.has(key)) {
return super.get(key);
} else {
let dynamic = this.dynamicData[key];
if (dynamic) {
return this.set(key, dynamic());
if (Object.prototype.hasOwnProperty.call(this.dynamicData, key)) {
let val = this.dynamicData[key]();
this.set(key, val);
return val;
}
}
}

View File

@@ -1,16 +1,30 @@
/* @flow */
import * as helpers from "babel-helpers";
import generator from "babel-generator";
import * as messages from "babel-messages";
import * as util from "../util";
import File from "../transformation/file";
import template from "babel-template";
import each from "lodash/collection/each";
import * as t from "babel-types";
let buildUmdWrapper = template(`
(function (root, factory) {
if (typeof define === "function" && define.amd) {
define(AMD_ARGUMENTS, factory);
} else if (typeof exports === "object") {
factory(COMMON_ARGUMENTS);
} else {
factory(BROWSER_ARGUMENTS);
}
})(UMD_ROOT, function (FACTORY_PARAMETERS) {
FACTORY_BODY
});
`);
function buildGlobal(namespace, builder) {
let body = [];
let container = t.functionExpression(null, [t.identifier("global")], t.blockStatement(body));
let tree = t.program([t.expressionStatement(t.callExpression(container, [util.template("helper-self-global")]))]);
let tree = t.program([t.expressionStatement(t.callExpression(container, [helpers.get("selfGlobal")]))]);
body.push(t.variableDeclaration("var", [
t.variableDeclarator(
@@ -32,33 +46,38 @@ function buildUmd(namespace, builder) {
builder(body);
let container = util.template("umd-commonjs-strict", {
FACTORY_PARAMETERS: t.identifier("global"),
BROWSER_ARGUMENTS: t.assignmentExpression("=", t.memberExpression(t.identifier("root"), namespace), t.objectExpression({})),
COMMON_ARGUMENTS: t.identifier("exports"),
AMD_ARGUMENTS: t.arrayExpression([t.stringLiteral("exports")]),
FACTORY_BODY: body,
UMD_ROOT: t.identifier("this")
});
return t.program([container]);
return t.program([
buildUmdWrapper({
FACTORY_PARAMETERS: t.identifier("global"),
BROWSER_ARGUMENTS: t.assignmentExpression(
"=",
t.memberExpression(t.identifier("root"), namespace),
t.objectExpression([])
),
COMMON_ARGUMENTS: t.identifier("exports"),
AMD_ARGUMENTS: t.arrayExpression([t.stringLiteral("exports")]),
FACTORY_BODY: body,
UMD_ROOT: t.identifier("this")
})
]);
}
function buildVar(namespace, builder) {
let body = [];
body.push(t.variableDeclaration("var", [
t.variableDeclarator(namespace, t.objectExpression({}))
t.variableDeclarator(namespace, t.objectExpression([]))
]));
builder(body);
return t.program(body);
}
function buildHelpers(body, namespace, whitelist) {
each(File.helpers, function (name) {
each(helpers.list, function (name) {
if (whitelist && whitelist.indexOf(name) === -1) return;
let key = t.identifier(t.toIdentifier(name));
body.push(t.expressionStatement(
t.assignmentExpression("=", t.memberExpression(namespace, key), util.template("helper-" + name))
t.assignmentExpression("=", t.memberExpression(namespace, key), helpers.get(name))
));
});
}

View File

@@ -1,26 +1,37 @@
/* @flow */
/* global BabelParserOptions */
/* global BabelFileMetadata */
/* global BabelFileResult */
import getHelper from "babel-helpers";
import * as metadataVisitor from "./metadata";
import convertSourceMap from "convert-source-map";
import moduleFormatters from "../modules";
import OptionManager from "./options/option-manager";
import PluginManager from "./plugin-manager";
import type Pipeline from "../pipeline";
import type Plugin from "../plugin";
import PluginPass from "../plugin-pass";
import shebangRegex from "shebang-regex";
import { NodePath, Hub } from "babel-traverse";
import isFunction from "lodash/lang/isFunction";
import { NodePath, Hub, Scope } from "babel-traverse";
import sourceMap from "source-map";
import generate from "babel-generator";
import codeFrame from "babel-code-frame";
import shuffle from "lodash/collection/shuffle";
import defaults from "lodash/object/defaults";
import includes from "lodash/collection/includes";
import traverse from "babel-traverse";
import resolve from "try-resolve";
import Logger from "./logger";
import Store from "../../store";
import Plugin from "../plugin";
import parse from "../../helpers/parse";
import { parse } from "babylon";
import * as util from "../../util";
import path from "path";
import * as t from "babel-types";
import blockHoistPlugin from "../internal-plugins/block-hoist";
import shadowFunctionsPlugin from "../internal-plugins/shadow-functions";
const INTERNAL_PLUGINS = [
[blockHoistPlugin],
[shadowFunctionsPlugin]
];
let errorVisitor = {
enter(path, state) {
let loc = path.node.loc;
@@ -32,80 +43,88 @@ let errorVisitor = {
};
export default class File extends Store {
constructor(opts = {}, pipeline) {
constructor(opts: Object = {}, pipeline: Pipeline) {
super();
this.pipeline = pipeline;
this.log = new Logger(this, opts.filename || "unknown");
this.opts = this.initOptions(opts);
this.buildTransformers();
this.parserOpts = {
highlightCode: this.opts.highlightCode,
nonStandard: this.opts.nonStandard,
sourceType: this.opts.sourceType,
filename: this.opts.filename,
plugins: []
};
this.pluginVisitors = [];
this.pluginPasses = [];
this.pluginStack = [];
this.buildPlugins();
this.metadata = {
usedHelpers: [],
marked: [],
modules: {
imports: [],
exports: {
exported: [],
specifiers: []
}
}
};
this.dynamicImportTypes = {};
this.dynamicImportIds = {};
this.dynamicImports = [];
this.declarations = {};
this.usedHelpers = {};
this.path = null;
this.ast = {};
this.code = "";
this.shebang = "";
this.hub = new Hub(this);
}
transformerDependencies = {};
dynamicImportTypes = {};
dynamicImportIds = {};
dynamicImports = [];
declarations = {};
usedHelpers = {};
dynamicData = {};
data = {};
ast = {};
static helpers: Array<string>;
metadata = {
marked: [],
pluginVisitors: Array<Object>;
pluginPasses: Array<PluginPass>;
pluginStack: Array<Plugin>;
pipeline: Pipeline;
parserOpts: BabelParserOptions;
log: Logger;
opts: Object;
dynamicImportTypes: Object;
dynamicImportIds: Object;
dynamicImports: Array<Object>;
declarations: Object;
usedHelpers: Object;
path: NodePath;
ast: Object;
scope: Scope;
metadata: BabelFileMetadata;
hub: Hub;
code: string;
shebang: string;
modules: {
imports: [],
exports: {
exported: [],
specifiers: []
getMetadata() {
let has = false;
for (let node of (this.ast.program.body: Array<Object>)) {
if (t.isModuleDeclaration(node)) {
has = true;
break;
}
}
};
hub = new Hub(this);
static helpers = [
"inherits",
"defaults",
"create-class",
"create-decorated-class",
"create-decorated-object",
"define-decorated-property-descriptor",
"tagged-template-literal",
"tagged-template-literal-loose",
"to-array",
"to-consumable-array",
"sliced-to-array",
"sliced-to-array-loose",
"object-without-properties",
"has-own",
"slice",
"bind",
"define-property",
"async-to-generator",
"interop-export-wildcard",
"interop-require-wildcard",
"interop-require-default",
"typeof",
"extends",
"get",
"set",
"new-arrow-check",
"class-call-check",
"object-destructuring-empty",
"temporal-undefined",
"temporal-assert-defined",
"self-global",
"default-props",
"instanceof",
// legacy
"interop-require"
];
static soloHelpers = [];
if (has) {
this.path.traverse(metadataVisitor, this);
}
}
initOptions(opts) {
opts = new OptionManager(this.log, this.pipeline).init(opts);
@@ -143,130 +162,67 @@ export default class File extends Store {
sourceMapTarget: basenameRelative
});
//
if (opts.externalHelpers) {
this.set("helpersNamespace", t.identifier("babelHelpers"));
}
return opts;
}
isLoose(key: string) {
return includes(this.opts.loose, key);
}
buildTransformers() {
let file = this;
let transformers = this.transformers = {};
let secondaryStack = [];
let stack = [];
// build internal transformers
for (let key in this.pipeline.transformers) {
let transformer = this.pipeline.transformers[key];
let pass = transformers[key] = transformer.buildPass(file);
if (pass.canTransform()) {
stack.push(pass);
if (transformer.metadata.secondPass) {
secondaryStack.push(pass);
}
if (transformer.manipulateOptions) {
transformer.manipulateOptions(file.opts, file);
}
}
}
buildPlugins() {
let plugins: Array<[PluginPass, Object]> = this.opts.plugins.concat(INTERNAL_PLUGINS);
// init plugins!
let beforePlugins = [];
let afterPlugins = [];
let pluginManager = new PluginManager({
file: this,
transformers: this.transformers,
before: beforePlugins,
after: afterPlugins
});
for (let i = 0; i < file.opts.plugins.length; i++) {
pluginManager.add(file.opts.plugins[i]);
}
stack = beforePlugins.concat(stack, afterPlugins);
for (let ref of plugins) {
let [plugin, pluginOpts] = ref; // todo: fix - can't embed in loop head because of flow bug
// build transformer stack
this.uncollapsedTransformerStack = stack = stack.concat(secondaryStack);
this.pluginStack.push(plugin);
this.pluginVisitors.push(plugin.visitor);
this.pluginPasses.push(new PluginPass(this, plugin, pluginOpts));
// build dependency graph
for (let pass of (stack: Array)) {
for (let dep of (pass.plugin.dependencies: Array)) {
this.transformerDependencies[dep] = pass.key;
if (plugin.manipulateOptions) {
plugin.manipulateOptions(this.opts, this.parserOpts, this);
}
}
// collapse stack categories
this.transformerStack = this.collapseStack(stack);
}
collapseStack(_stack) {
let stack = [];
let ignore = [];
for (let pass of (_stack: Array)) {
// been merged
if (ignore.indexOf(pass) >= 0) continue;
let group = pass.plugin.metadata.group;
// can't merge
if (!pass.canTransform() || !group) {
stack.push(pass);
continue;
}
let mergeStack = [];
for (let pass of (_stack: Array)) {
if (pass.plugin.metadata.group === group) {
mergeStack.push(pass);
ignore.push(pass);
} else {
//break;
}
}
shuffle;
//mergeStack = shuffle(mergeStack);
let visitors = [];
for (let pass of (mergeStack: Array)) {
visitors.push(pass.plugin.visitor);
}
let visitor = traverse.visitors.merge(visitors);
let mergePlugin = new Plugin(group, { visitor });
stack.push(mergePlugin.buildPass(this));
getModuleName(): ?string {
let opts = this.opts;
if (!opts.moduleIds) {
return null;
}
return stack;
}
// moduleId is n/a if a `getModuleId()` is provided
if (opts.moduleId != null && !opts.getModuleId) {
return opts.moduleId;
}
set(key: string, val): any {
return this.data[key] = val;
}
let filenameRelative = opts.filenameRelative;
let moduleName = "";
setDynamic(key: string, fn: Function) {
this.dynamicData[key] = fn;
}
if (opts.moduleRoot != null) {
moduleName = opts.moduleRoot + "/";
}
get(key: string): any {
let data = this.data[key];
if (data) {
return data;
if (!opts.filenameRelative) {
return moduleName + opts.filename.replace(/^\//, "");
}
if (opts.sourceRoot != null) {
// remove sourceRoot from filename
let sourceRootRegEx = new RegExp("^" + opts.sourceRoot + "\/?");
filenameRelative = filenameRelative.replace(sourceRootRegEx, "");
}
// remove extension
filenameRelative = filenameRelative.replace(/\.(\w*?)$/, "");
moduleName += filenameRelative;
// normalize path separators
moduleName = moduleName.replace(/\\/g, "/");
if (opts.getModuleId) {
// If return is falsy, assume they want us to use our generated default name
return opts.getModuleId(moduleName) || moduleName;
} else {
let dynamic = this.dynamicData[key];
if (dynamic) {
return this.set(key, dynamic());
}
return moduleName;
}
}
@@ -276,81 +232,52 @@ export default class File extends Store {
return source;
}
addImport(source: string, name?: string, type?: string): Object {
name = name || source;
let id = this.dynamicImportIds[name];
addImport(source: string, imported: string, name?: string = imported): Object {
let alias = `${source}:${imported}`;
let id = this.dynamicImportIds[alias];
if (!id) {
source = this.resolveModuleSource(source);
id = this.dynamicImportIds[name] = this.scope.generateUidIdentifier(name);
id = this.dynamicImportIds[alias] = this.scope.generateUidIdentifier(name);
let specifiers = [];
if (imported === "*") {
specifiers.push(t.importNamespaceSpecifier(id));
} else if (imported === "default") {
specifiers.push(t.importDefaultSpecifier(id));
} else {
specifiers.push(t.importSpecifier(id, t.identifier(imported)));
}
let specifiers = [t.importDefaultSpecifier(id)];
let declar = t.importDeclaration(specifiers, t.stringLiteral(source));
declar._blockHoist = 3;
if (type) {
let modules = this.dynamicImportTypes[type] = this.dynamicImportTypes[type] || [];
modules.push(declar);
}
if (this.transformers["es6.modules"].canTransform()) {
this.moduleFormatter.importSpecifier(specifiers[0], declar, this.dynamicImports, this.scope);
this.moduleFormatter.hasLocalImports = true;
} else {
this.dynamicImports.push(declar);
}
this.path.unshiftContainer("body", declar);
}
return id;
}
attachAuxiliaryComment(node: Object): Object {
let beforeComment = this.opts.auxiliaryCommentBefore;
if (beforeComment) {
node.leadingComments = node.leadingComments || [];
node.leadingComments.push({
type: "CommentLine",
value: " " + beforeComment
});
}
let afterComment = this.opts.auxiliaryCommentAfter;
if (afterComment) {
node.trailingComments = node.trailingComments || [];
node.trailingComments.push({
type: "CommentLine",
value: " " + afterComment
});
}
return node;
}
addHelper(name: string): Object {
let isSolo = includes(File.soloHelpers, name);
if (!isSolo && !includes(File.helpers, name)) {
throw new ReferenceError(`Unknown helper ${name}`);
}
let declar = this.declarations[name];
if (declar) return declar;
this.usedHelpers[name] = true;
if (!isSolo) {
let generator = this.get("helperGenerator");
let runtime = this.get("helpersNamespace");
if (generator) {
return generator(name);
} else if (runtime) {
let id = t.identifier(t.toIdentifier(name));
return t.memberExpression(runtime, id);
}
if (!this.usedHelpers[name]) {
this.metadata.usedHelpers.push(name);
this.usedHelpers[name] = true;
}
let ref = util.template("helper-" + name);
let generator = this.get("helperGenerator");
let runtime = this.get("helpersNamespace");
if (generator) {
return generator(name);
} else if (runtime) {
let id = t.identifier(t.toIdentifier(name));
return t.memberExpression(runtime, id);
}
let ref = getHelper(name);
let uid = this.declarations[name] = this.scope.generateUidIdentifier(name);
if (t.isFunctionExpression(ref) && !ref.id) {
@@ -358,7 +285,6 @@ export default class File extends Store {
ref._generated = true;
ref.id = uid;
ref.type = "FunctionDeclaration";
this.attachAuxiliaryComment(ref);
this.path.unshiftContainer("body", ref);
} else {
ref._compact = true;
@@ -372,7 +298,11 @@ export default class File extends Store {
return uid;
}
addTemplateObject(helperName: string, strings: Array, raw: Array): Object {
addTemplateObject(
helperName: string,
strings: Array<Object>,
raw: Object,
): Object {
// Generate a unique name based on the string literals so we dedupe
// identical strings used in the program.
let stringIds = raw.elements.map(function(string) {
@@ -396,7 +326,7 @@ export default class File extends Store {
return uid;
}
buildCodeFrameError(node, msg, Error = SyntaxError) {
buildCodeFrameError(node: Object, msg: string, Error: typeof Error = SyntaxError): Error {
let loc = node && (node.loc || node._loc);
let err = new Error(msg);
@@ -404,7 +334,7 @@ export default class File extends Store {
if (loc) {
err.loc = loc.start;
} else {
traverse(node, errorVisitor, err);
traverse(node, errorVisitor, this.scope, err);
err.message += " (This is an error on an internal node. Probably an internal error";
@@ -436,49 +366,9 @@ export default class File extends Store {
}
}
getModuleFormatter(type: string) {
if (isFunction(type) || !moduleFormatters[type]) {
this.log.deprecate("Custom module formatters are deprecated and will be removed in the next major. Please use Babel plugins instead.");
}
let ModuleFormatter = isFunction(type) ? type : moduleFormatters[type];
if (!ModuleFormatter) {
let loc = resolve.relative(type);
if (loc) ModuleFormatter = require(loc);
}
if (!ModuleFormatter) {
throw new ReferenceError(`Unknown module formatter type ${JSON.stringify(type)}`);
}
return new ModuleFormatter(this);
}
parse(code: string) {
let opts = this.opts;
//
let parseOpts = {
highlightCode: opts.highlightCode,
nonStandard: opts.nonStandard,
sourceType: opts.sourceType,
filename: opts.filename,
plugins: {}
};
let features = parseOpts.features = {};
for (let key in this.transformers) {
let transformer = this.transformers[key];
features[key] = transformer.canRun();
}
parseOpts.looseModules = this.isLoose("es6.modules");
parseOpts.strictMode = features.strict;
this.log.debug("Parse start");
let ast = parse(code, parseOpts);
let ast = parse(code, this.parserOpts);
this.log.debug("Parse stop");
return ast;
}
@@ -493,32 +383,25 @@ export default class File extends Store {
}).setContext();
this.scope = this.path.scope;
this.ast = ast;
this.getMetadata();
}
addAst(ast) {
this.log.debug("Start set AST");
this._addAst(ast);
this.log.debug("End set AST");
this.log.debug("Start module formatter init");
let modFormatter = this.moduleFormatter = this.getModuleFormatter(this.opts.modules);
if (modFormatter.init && this.transformers["es6.modules"].canTransform()) {
modFormatter.init();
}
this.log.debug("End module formatter init");
}
transform() {
transform(): BabelFileResult {
this.call("pre");
for (let pass of (this.transformerStack: Array)) {
pass.transform();
}
this.log.debug(`Start transform traverse`);
traverse(this.ast, traverse.visitors.merge(this.pluginVisitors, this.pluginPasses), this.scope);
this.log.debug(`End transform traverse`);
this.call("post");
return this.generate();
}
wrap(code, callback) {
wrap(code: string, callback: Function): BabelFileResult {
code = code + "";
try {
@@ -578,14 +461,15 @@ export default class File extends Store {
return util.shouldIgnore(opts.filename, opts.ignore, opts.only);
}
call(key: string) {
for (let pass of (this.uncollapsedTransformerStack: Array)) {
let fn = pass.plugin[key];
if (fn) fn.call(pass, this);
call(key: "pre" | "post") {
for (let pass of (this.pluginPasses: Array<PluginPass>)) {
let plugin = pass.plugin;
let fn = plugin[key];
if (fn) fn.call(pass, this, pass);
}
}
parseInputSourceMap(code: string) {
parseInputSourceMap(code: string): string {
let opts = this.opts;
if (opts.inputSourceMap !== false) {
@@ -607,13 +491,14 @@ export default class File extends Store {
}
}
makeResult({ code, map = null, ast, ignored }) {
makeResult({ code, map, ast, ignored }: BabelFileResult): BabelFileResult {
let result = {
metadata: null,
options: this.opts,
ignored: !!ignored,
code: null,
ast: null,
map: map
map: map || null
};
if (this.opts.code) {
@@ -626,17 +511,16 @@ export default class File extends Store {
if (this.opts.metadata) {
result.metadata = this.metadata;
result.metadata.usedHelpers = Object.keys(this.usedHelpers);
}
return result;
}
generate() {
generate(): BabelFileResult {
let opts = this.opts;
let ast = this.ast;
let result = { ast };
let result: BabelFileResult = { ast };
if (!opts.code) return this.makeResult(result);
this.log.debug("Generation start");
@@ -649,7 +533,7 @@ export default class File extends Store {
if (this.shebang) {
// add back shebang
result.code = `${this.shebang}\n${result.code}`;
result.code = `${this.shebang}${result.code}`;
}
if (result.map) {
@@ -667,3 +551,5 @@ export default class File extends Store {
return this.makeResult(result);
}
}
export { File };

View File

@@ -1,33 +1,29 @@
/* @flow */
import extend from "lodash/object/extend";
import * as t from "babel-types";
export let ModuleDeclaration = {
enter(node, parent, scope, formatter) {
enter(path, file) {
let { node } = path;
if (node.source) {
node.source.value = formatter.file.resolveModuleSource(node.source.value);
formatter.addScope(this);
node.source.value = file.resolveModuleSource(node.source.value);
}
}
};
export let ImportDeclaration = {
exit(node, parent, scope, formatter) {
formatter.hasLocalImports = true;
exit(path, file) {
let { node } = path;
let specifiers = [];
let imported = [];
formatter.metadata.imports.push({
file.metadata.modules.imports.push({
source: node.source.value,
imported,
specifiers
});
for (let specifier of (this.get("specifiers"): Array)) {
let ids = specifier.getBindingIdentifiers();
extend(formatter.localImports, ids);
for (let specifier of (path.get("specifiers"): Array<Object>)) {
let local = specifier.node.local.name;
if (specifier.isImportDefaultSpecifier()) {
@@ -60,33 +56,30 @@ export let ImportDeclaration = {
}
};
export function ExportDeclaration(node, parent, scope, formatter) {
formatter.hasLocalExports = true;
export function ExportDeclaration(path, file) {
let { node } = path;
let source = node.source ? node.source.value : null;
let exports = formatter.metadata.exports;
let exports = file.metadata.modules.exports;
// export function foo() {}
// export let foo = "bar";
let declar = this.get("declaration");
let declar = path.get("declaration");
if (declar.isStatement()) {
let bindings = declar.getBindingIdentifiers();
for (let name in bindings) {
let binding = bindings[name];
formatter._addExport(name, binding);
exports.exported.push(name);
exports.specifiers.push({
kind: "local",
local: name,
exported: this.isExportDefaultDeclaration() ? "default" : name
exported: path.isExportDefaultDeclaration() ? "default" : name
});
}
}
if (this.isExportNamedDeclaration() && node.specifiers) {
for (let specifier of (node.specifiers: Array)) {
if (path.isExportNamedDeclaration() && node.specifiers) {
for (let specifier of (node.specifiers: Array<Object>)) {
let exported = specifier.exported.name;
exports.exported.push(exported);
@@ -112,8 +105,6 @@ export function ExportDeclaration(node, parent, scope, formatter) {
let local = specifier.local;
if (!local) continue;
formatter._addExport(local.name, specifier.exported);
// export { foo } from "bar";
// export { foo as bar } from "bar";
if (source) {
@@ -138,23 +129,14 @@ export function ExportDeclaration(node, parent, scope, formatter) {
}
// export * from "bar";
if (this.isExportAllDeclaration()) {
if (path.isExportAllDeclaration()) {
exports.specifiers.push({
kind: "external-all",
source
});
}
if (!t.isExportDefaultDeclaration(node) && !declar.isTypeAlias()) {
let onlyDefault = node.specifiers && node.specifiers.length === 1 && t.isSpecifierDefault(node.specifiers[0]);
if (!onlyDefault) {
formatter.hasNonDefaultExports = true;
}
}
}
export function Scope(node, parent, scope, formatter) {
if (!formatter.isLoose()) {
this.skip();
}
export function Scope(path) {
path.skip();
}

View File

@@ -51,8 +51,8 @@
"plugins": {
"type": "list",
"description": "",
"default": []
"default": [],
"description": ""
},
"ignore": {
@@ -137,5 +137,35 @@
"sourceType": {
"description": "",
"default": "module"
},
"auxiliaryComment": {
"description": "",
"type": "string"
},
"resolveModuleSource": {
"hidden": true
},
"getModuleId": {
"hidden": true
},
"moduleRoot": {
"type": "filename",
"description": "optional prefix for the AMD module formatter that will be prepend to the filename on module definitions"
},
"moduleIds": {
"type": "boolean",
"default": false,
"shorthand": "M",
"description": "insert an explicit id for modules"
},
"moduleId": {
"description": "specify a custom name for module ids",
"type": "string"
}
}

View File

@@ -11,6 +11,7 @@ export function normaliseOptions(options: Object = {}): Object {
if (val == null) continue;
let opt = config[key];
if (opt && opt.alias) opt = config[opt.alias];
if (!opt) continue;
let parser = parsers[opt.type];

View File

@@ -1,9 +1,9 @@
/* @flow */
import * as context from "../../../api/node";
import type Logger from "../logger";
import Plugin from "../../plugin";
import * as messages from "babel-messages";
import * as context from "../../../api/node";
import { normaliseOptions } from "./index";
import resolve from "../../../helpers/resolve";
import json5 from "json5";
@@ -53,7 +53,13 @@ export default class OptionManager {
if (cache.container === fn) return cache.plugin;
}
let obj = fn(context);
let obj;
if (typeof fn === "function") {
obj = fn(context);
} else {
obj = fn;
}
if (typeof obj === "object") {
let plugin = new Plugin(obj);
@@ -63,7 +69,7 @@ export default class OptionManager {
});
return plugin;
} else {
throw new TypeError(messages.get("pluginNotObject", loc, i, typeof obj));
throw new TypeError(messages.get("pluginNotObject", loc, i, typeof obj) + loc + i);
}
}
@@ -78,6 +84,21 @@ export default class OptionManager {
return opts;
}
static normalisePlugin(plugin, loc, i) {
if (!(plugin instanceof Plugin)) {
// allow plugin containers to be specified so they don't have to manually require
if (typeof plugin === "function" || typeof plugin === "object") {
plugin = OptionManager.memoisePluginContainer(plugin, loc, i);
} else {
throw new TypeError(messages.get("pluginNotFunction", loc, i, typeof plugin));
}
}
plugin.init(loc, i);
return plugin;
}
static normalisePlugins(loc, dirname, plugins) {
return plugins.map(function (val, i) {
let plugin, options;
@@ -99,17 +120,7 @@ export default class OptionManager {
}
}
if (!(plugin instanceof Plugin)) {
// allow plugin containers to be specified so they don't have to manually require
if (typeof plugin === "function") {
plugin = OptionManager.memoisePluginContainer(plugin, loc, i);
} else {
throw new TypeError(messages.get("pluginNotFunction", loc, i));
}
}
// validate
plugin.validate(loc, i);
plugin = OptionManager.normalisePlugin(plugin, loc, i);
return [plugin, options];
});

View File

@@ -1,52 +0,0 @@
/* @flow */
import explode from "./explode-assignable-expression";
import * as t from "babel-types";
export default function (opts: {
build: Function;
operator: string;
}): Object {
let exports = {};
let isAssignment = function (node) {
return node.operator === opts.operator + "=";
};
let buildAssignment = function (left, right) {
return t.assignmentExpression("=", left, right);
};
exports.ExpressionStatement = function (path, file) {
// hit the `AssignmentExpression` one below
if (path.isCompletionRecord()) return;
let expr = path.node.expression;
if (!isAssignment(expr)) return;
let nodes = [];
let exploded = explode(expr.left, nodes, file, path.scope, true);
nodes.push(t.expressionStatement(
buildAssignment(exploded.ref, opts.build(exploded.uid, expr.right))
));
return nodes;
};
exports.AssignmentExpression = function ({ node, scope }, file) {
if (!isAssignment(node)) return;
let nodes = [];
let exploded = explode(node.left, nodes, file, scope);
nodes.push(buildAssignment(exploded.ref, opts.build(exploded.uid, node.right)));
return nodes;
};
exports.BinaryExpression = function ({ node }) {
if (node.operator !== opts.operator) return;
return opts.build(node.left, node.right);
};
return exports;
}

View File

@@ -1,25 +0,0 @@
/* @flow */
import * as t from "babel-types";
export default function build(node: Object, buildBody: Function): ?Object {
let self = node.blocks.shift();
if (!self) return;
let child = build(node, buildBody);
if (!child) {
// last item
child = buildBody();
// add a filter as this is our final stop
if (node.filter) {
child = t.ifStatement(node.filter, t.blockStatement([child]));
}
}
return t.forOfStatement(
t.variableDeclaration("let", [t.variableDeclarator(self.left)]),
self.right,
t.blockStatement([child])
);
}

View File

@@ -1,54 +0,0 @@
/* @flow */
import explode from "./explode-assignable-expression";
import * as t from "babel-types";
export default function (
exports: Object,
opts: {
build: Function;
is: Function;
},
) {
let buildAssignment = function (left, right) {
return t.assignmentExpression("=", left, right);
};
exports.ExpressionStatement = function (path, file) {
// hit the `AssignmentExpression` one below
if (path.isCompletionRecord()) return;
let expr = path.node.expression;
if (!opts.is(expr, file)) return;
let nodes = [];
let exploded = explode(expr.left, nodes, file, path.scope);
nodes.push(t.ifStatement(
opts.build(exploded.uid, file),
t.expressionStatement(buildAssignment(exploded.ref, expr.right))
));
return nodes;
};
exports.AssignmentExpression = function (path, file) {
let node = path.node;
if (!opts.is(node, file)) return;
let nodes = [];
let exploded = explode(node.left, nodes, file, path.scope);
nodes.push(t.logicalExpression(
"&&",
opts.build(exploded.uid, file),
buildAssignment(exploded.ref, node.right)
));
// todo: duplicate expression node
nodes.push(exploded.ref);
return nodes;
};
}

View File

@@ -1,159 +0,0 @@
// Based upon the excellent jsx-transpiler by Inglet Stepanyan (RReverser)
// https://github.com/RReverser/jsx-transpiler
// jsx
import isString from "lodash/lang/isString";
import * as messages from "babel-messages";
import esutils from "esutils";
import { react } from "babel-types";
import * as t from "babel-types";
export default function (opts) {
let visitor = {};
visitor.JSXIdentifier = function (node) {
if (node.name === "this" && this.isReferenced()) {
return t.thisExpression();
} else if (esutils.keyword.isIdentifierNameES6(node.name)) {
node.type = "Identifier";
} else {
return t.stringLiteral(node.name);
}
};
visitor.JSXNamespacedName = function () {
throw this.errorWithNode(messages.get("JSXNamespacedTags"));
};
visitor.JSXMemberExpression = {
exit(node) {
node.computed = t.isLiteral(node.property);
node.type = "MemberExpression";
}
};
visitor.JSXExpressionContainer = function (node) {
return node.expression;
};
visitor.JSXAttribute = {
enter(node) {
let value = node.value;
if (t.isLiteral(value) && isString(value.value)) {
value.value = value.value.replace(/\n\s+/g, " ");
}
},
exit(node) {
let value = node.value || t.booleanLiteral(true);
return t.inherits(t.property("init", node.name, value), node);
}
};
visitor.JSXOpeningElement = {
exit(node, parent, scope, file) {
parent.children = react.buildChildren(parent);
let tagExpr = node.name;
let args = [];
let tagName;
if (t.isIdentifier(tagExpr)) {
tagName = tagExpr.name;
} else if (t.isLiteral(tagExpr)) {
tagName = tagExpr.value;
}
let state = {
tagExpr: tagExpr,
tagName: tagName,
args: args
};
if (opts.pre) {
opts.pre(state, file);
}
let attribs = node.attributes;
if (attribs.length) {
attribs = buildJSXOpeningElementAttributes(attribs, file);
} else {
attribs = t.nullLiteral();
}
args.push(attribs);
if (opts.post) {
opts.post(state, file);
}
return state.call || t.callExpression(state.callee, args);
}
};
/**
* The logic for this is quite terse. It's because we need to
* support spread elements. We loop over all attributes,
* breaking on spreads, we then push a new object containg
* all prior attributes to an array for later processing.
*/
let buildJSXOpeningElementAttributes = function (attribs, file) {
let _props = [];
let objs = [];
let pushProps = function () {
if (!_props.length) return;
objs.push(t.objectExpression(_props));
_props = [];
};
while (attribs.length) {
let prop = attribs.shift();
if (t.isJSXSpreadAttribute(prop)) {
pushProps();
objs.push(prop.argument);
} else {
_props.push(prop);
}
}
pushProps();
if (objs.length === 1) {
// only one object
attribs = objs[0];
} else {
// looks like we have multiple objects
if (!t.isObjectExpression(objs[0])) {
objs.unshift(t.objectExpression([]));
}
// spread it
attribs = t.callExpression(
file.addHelper("extends"),
objs
);
}
return attribs;
};
visitor.JSXElement = {
exit(node) {
let callExpr = node.openingElement;
callExpr.arguments = callExpr.arguments.concat(node.children);
if (callExpr.arguments.length >= 3) {
callExpr._prettyCall = true;
}
return t.inherits(callExpr, node);
}
};
return visitor;
}

View File

@@ -1,36 +0,0 @@
/* @flow */
import type { Scope } from "babel-traverse";
import * as t from "babel-types";
let visitor = {
enter(path, state) {
if (path.isThisExpression() || path.isReferencedIdentifier({ name: "arguments" })) {
state.found = true;
path.stop();
}
},
Function(path) {
path.skip();
}
};
export default function (node: Object, scope: Scope) {
let container = t.functionExpression(null, [], node.body, node.generator, node.async);
let callee = container;
let args = [];
let state = { found: false };
scope.traverse(node, visitor, state);
if (state.found) {
callee = t.memberExpression(container, t.identifier("apply"));
args = [t.thisExpression(), t.identifier("arguments")];
}
let call = t.callExpression(callee, args);
if (node.generator) call = t.yieldExpression(call, true);
return t.returnStatement(call);
}

View File

@@ -1,106 +0,0 @@
/* @flow */
import type File from "../file";
import each from "lodash/collection/each";
import has from "lodash/object/has";
import * as t from "babel-types";
export function push(mutatorMap: Object, node: Object, kind: string, file: File): Object {
let alias = t.toKeyAlias(node);
//
let map = {};
if (has(mutatorMap, alias)) map = mutatorMap[alias];
mutatorMap[alias] = map;
//
map._inherits = map._inherits || [];
map._inherits.push(node);
map._key = node.key;
if (node.computed) {
map._computed = true;
}
if (node.decorators) {
let decorators = map.decorators = map.decorators || t.arrayExpression([]);
decorators.elements = decorators.elements.concat(node.decorators.map(dec => dec.expression).reverse());
}
if (map.value || map.initializer) {
throw file.buildCodeFrameError(node, "Key conflict with sibling node");
}
if (node.value) {
if (node.kind === "init") kind = "value";
if (node.kind === "get") kind = "get";
if (node.kind === "set") kind = "set";
t.inheritsComments(node.value, node);
map[kind] = node.value;
}
return map;
}
export function hasComputed(mutatorMap: Object): boolean {
for (let key in mutatorMap) {
if (mutatorMap[key]._computed) {
return true;
}
}
return false;
}
export function toComputedObjectFromClass(obj: Object): Object {
let objExpr = t.arrayExpression([]);
for (let i = 0; i < obj.properties.length; i++) {
let prop = obj.properties[i];
let val = prop.value;
val.properties.unshift(t.property("init", t.identifier("key"), t.toComputedKey(prop)));
objExpr.elements.push(val);
}
return objExpr;
}
export function toClassObject(mutatorMap: Object): Object {
let objExpr = t.objectExpression([]);
each(mutatorMap, function (map) {
let mapNode = t.objectExpression([]);
let propNode = t.property("init", map._key, mapNode, map._computed);
each(map, function (node, key) {
if (key[0] === "_") return;
let inheritNode = node;
if (t.isMethodDefinition(node) || t.isClassProperty(node)) node = node.value;
let prop = t.property("init", t.identifier(key), node);
t.inheritsComments(prop, inheritNode);
t.removeComments(inheritNode);
mapNode.properties.push(prop);
});
objExpr.properties.push(propNode);
});
return objExpr;
}
export function toDefineObject(mutatorMap: Object): Object {
each(mutatorMap, function (map) {
if (map.value) map.writable = t.booleanLiteral(true);
map.configurable = t.booleanLiteral(true);
map.enumerable = t.booleanLiteral(true);
});
return toClassObject(mutatorMap);
}

View File

@@ -1,84 +0,0 @@
/* @flow */
import type { Scope } from "babel-traverse";
import type File from "../file";
import * as t from "babel-types";
function getObjRef(node, nodes, file, scope) {
let ref;
if (t.isIdentifier(node)) {
if (scope.hasBinding(node.name)) {
// this variable is declared in scope so we can be 100% sure
// that evaluating it multiple times wont trigger a getter
// or something else
return node;
} else {
// could possibly trigger a getter so we need to only evaluate
// it once
ref = node;
}
} else if (t.isMemberExpression(node)) {
ref = node.object;
if (t.isIdentifier(ref) && scope.hasGlobal(ref.name)) {
// the object reference that we need to save is locally declared
// so as per the previous comment we can be 100% sure evaluating
// it multiple times will be safe
return ref;
}
} else {
throw new Error(`We can't explode this node type ${node.type}`);
}
let temp = scope.generateUidIdentifierBasedOnNode(ref);
nodes.push(t.variableDeclaration("var", [
t.variableDeclarator(temp, ref)
]));
return temp;
}
function getPropRef(node, nodes, file, scope) {
let prop = node.property;
let key = t.toComputedKey(node, prop);
if (t.isLiteral(key)) return key;
let temp = scope.generateUidIdentifierBasedOnNode(prop);
nodes.push(t.variableDeclaration("var", [
t.variableDeclarator(temp, prop)
]));
return temp;
}
export default function (
node: Object,
nodes: Array<Object>,
file: File,
scope: Scope,
allowedSingleIdent?: boolean,
): {
uid: Object;
ref: Object;
} {
let obj;
if (t.isIdentifier(node) && allowedSingleIdent) {
obj = node;
} else {
obj = getObjRef(node, nodes, file, scope);
}
let ref, uid;
if (t.isIdentifier(node)) {
ref = node;
uid = obj;
} else {
let prop = getPropRef(node, nodes, file, scope);
let computed = node.computed || t.isLiteral(prop);
uid = ref = t.memberExpression(obj, prop, computed);
}
return {
uid: uid,
ref: ref
};
}

View File

@@ -1,13 +0,0 @@
/* @flow */
import * as t from "babel-types";
export default function ({ params }: { params: Array<Object> }): number {
for (let i = 0; i < params.length; i++) {
let param = params[i];
if (t.isAssignmentPattern(param) || t.isRestElement(param)) {
return i;
}
}
return params.length;
}

View File

@@ -1,39 +0,0 @@
/* @flow */
import type { Scope } from "babel-traverse";
import * as t from "babel-types";
export default function (decorators: Array<Object>, scope: Scope): Array<Object> {
for (let decorator of decorators) {
let expression = decorator.expression;
if (!t.isMemberExpression(expression)) continue;
let temp = scope.maybeGenerateMemoised(expression.object);
let ref;
let nodes = [];
if (temp) {
ref = temp;
nodes.push(t.assignmentExpression("=", temp, expression.object));
} else {
ref = expression.object;
}
nodes.push(t.callExpression(
t.memberExpression(
t.memberExpression(ref, expression.property, expression.computed),
t.identifier("bind")
),
[ref]
));
if (nodes.length === 1) {
decorator.expression = nodes[0];
} else {
decorator.expression = t.sequenceExpression(nodes);
}
}
return decorators;
}

View File

@@ -1,156 +0,0 @@
/* @flow */
import type { Scope } from "babel-traverse";
import type File from "../file";
import getFunctionArity from "./get-function-arity";
import * as util from "../../util";
import * as t from "babel-types";
let visitor = {
"ReferencedIdentifier|BindingIdentifier"(path, state) {
// check if this node matches our function id
if (path.node.name !== state.name) return;
// check that we don't have a local variable declared as that removes the need
// for the wrapper
let localDeclar = path.scope.getBindingIdentifier(state.name);
if (localDeclar !== state.outerDeclar) return;
state.selfReference = true;
path.stop();
}
};
function wrap(state, method, id, scope) {
if (state.selfReference) {
if (scope.hasBinding(id.name) && !scope.hasGlobal(id.name)) {
// we can just munge the local binding
scope.rename(id.name);
} else {
// need to add a wrapper since we can't change the references
let templateName = "property-method-assignment-wrapper";
if (method.generator) templateName += "-generator";
let template = util.template(templateName, {
FUNCTION: method,
FUNCTION_ID: id,
FUNCTION_KEY: scope.generateUidIdentifier(id.name)
});
template.callee._skipModulesRemap = true;
// shim in dummy params to retain function arity, if you try to read the
// source then you'll get the original since it's proxied so it's all good
let params = template.callee.body.body[0].params;
for (let i = 0, len = getFunctionArity(method); i < len; i++) {
params.push(scope.generateUidIdentifier("x"));
}
return template;
}
}
method.id = id;
scope.getProgramParent().references[id.name] = true;
}
function visit(node, name, scope) {
let state = {
selfAssignment: false,
selfReference: false,
outerDeclar: scope.getBindingIdentifier(name),
references: [],
name: name
};
// check to see if we have a local binding of the id we're setting inside of
// the function, this is important as there are caveats associated
let binding = scope.getOwnBinding(name);
if (binding) {
if (binding.kind === "param") {
// safari will blow up in strict mode with code like:
//
// let t = function t(t) {};
//
// with the error:
//
// Cannot declare a parameter named 't' as it shadows the name of a
// strict mode function.
//
// this isn't to the spec and they've invented this behaviour which is
// **extremely** annoying so we avoid setting the name if it has a param
// with the same id
state.selfReference = true;
} else {
// otherwise it's defined somewhere in scope like:
//
// let t = function () {
// let t = 2;
// };
//
// so we can safely just set the id and move along as it shadows the
// bound function id
}
} else if (state.outerDeclar || scope.hasGlobal(name)) {
scope.traverse(node, visitor, state);
}
return state;
}
export function custom(node: Object, id: Object, scope: Scope) {
let state = visit(node, id.name, scope);
return wrap(state, node, id, scope);
}
export function property(node: Object, file: File, scope: Scope) {
let key = t.toComputedKey(node, node.key);
if (!t.isLiteral(key)) return; // we can't set a function id with this
let name = t.toBindingIdentifierName(key.value);
let id = t.identifier(name);
let method = node.value;
let state = visit(method, name, scope);
node.value = wrap(state, method, id, scope) || method;
}
export function bare(node: Object, parent: Object, scope: Scope) {
// has an `id` so we don't need to infer one
if (node.id) return;
let id;
if (t.isProperty(parent) && parent.kind === "init" && (!parent.computed || t.isLiteral(parent.key))) {
// { foo() {} };
id = parent.key;
} else if (t.isVariableDeclarator(parent)) {
// let foo = function () {};
id = parent.id;
if (t.isIdentifier(id)) {
let binding = scope.parent.getBinding(id.name);
if (binding && binding.constant && scope.getBinding(id.name) === binding) {
// always going to reference this method
node.id = id;
return;
}
}
} else {
return;
}
let name;
if (id && t.isLiteral(id)) {
name = id.value;
} else if (id && t.isIdentifier(id)) {
name = id.name;
} else {
return;
}
name = t.toBindingIdentifierName(name);
id = t.identifier(name);
let state = visit(node, name, scope);
return wrap(state, node, id, scope);
}

View File

@@ -1,15 +0,0 @@
/* @flow */
import pull from "lodash/array/pull";
import * as t from "babel-types";
export function is(node: Object, flag: string): boolean {
return t.isRegexLiteral(node) && node.flags.indexOf(flag) >= 0;
}
export function pullFlag(node: Object, flag: string) {
let flags = node.flags.split("");
if (node.flags.indexOf(flag) < 0) return;
pull(flags, flag);
node.flags = flags.join("");
}

View File

@@ -1,66 +0,0 @@
/* @flow */
import type { NodePath } from "babel-traverse";
import * as t from "babel-types";
let awaitVisitor = {
Function(path) {
path.skip();
},
AwaitExpression({ node }) {
node.type = "YieldExpression";
if (node.all) {
// await* foo; -> yield Promise.all(foo);
node.all = false;
node.argument = t.callExpression(t.memberExpression(t.identifier("Promise"), t.identifier("all")), [node.argument]);
}
}
};
let referenceVisitor = {
ReferencedIdentifier({ node, scope }, state) {
let name = state.id.name;
if (node.name === name && scope.bindingIdentifierEquals(name, state.id)) {
return state.ref = state.ref || scope.generateUidIdentifier(name);
}
}
};
export default function (path: NodePath, callId: Object) {
let node = path.node;
node.async = false;
node.generator = true;
path.traverse(awaitVisitor);
let call = t.callExpression(callId, [node]);
let id = node.id;
node.id = null;
if (t.isFunctionDeclaration(node)) {
let declar = t.variableDeclaration("let", [
t.variableDeclarator(id, call)
]);
declar._blockHoist = true;
return declar;
} else {
node.type = "FunctionExpression";
if (id) {
let state = { id, ref: null };
path.traverse(referenceVisitor, state);
if (state.ref) {
path.scope.parent.push({ id: state.ref });
return t.assignmentExpression("=", state.ref, call);
}
}
return call;
}
}

View File

@@ -1,310 +0,0 @@
/* @flow */
import type File from "../file";
import type { NodePath, Scope } from "babel-traverse";
import * as messages from "babel-messages";
import * as t from "babel-types";
function isIllegalBareSuper(node, parent) {
if (!t.isSuper(node)) return false;
if (t.isMemberExpression(parent, { computed: false })) return false;
if (t.isCallExpression(parent, { callee: node })) return false;
return true;
}
function isMemberExpressionSuper(node) {
return t.isMemberExpression(node) && t.isSuper(node.object);
}
let visitor = {
enter(path, state) {
let topLevel = state.topLevel;
let self = state.self;
if (path.isFunction() && !path.isArrowFunctionExpression()) {
// we need to call traverseLevel again so we're context aware
self.traverseLevel(path, false);
return path.skip();
}
if (path.isProperty({ method: true }) || path.isMethodDefinition()) {
// break on object methods
return path.skip();
}
let getThisReference = topLevel ?
// top level so `this` is the instance
t.thisExpression :
// not in the top level so we need to create a reference
self.getThisReference.bind(self);
let callback = self.specHandle;
if (self.isLoose) callback = self.looseHandle;
let result = callback.call(self, path, getThisReference);
if (result) path.hasSuper = true;
if (result === true) return;
return result;
}
};
export default class ReplaceSupers {
constructor(opts: Object, inClass?: boolean = false) {
this.topLevelThisReference = opts.topLevelThisReference;
this.methodPath = opts.methodPath;
this.methodNode = opts.methodNode;
this.superRef = opts.superRef;
this.isStatic = opts.isStatic;
this.hasSuper = false;
this.inClass = inClass;
this.isLoose = opts.isLoose;
this.scope = opts.scope;
this.file = opts.file;
this.opts = opts;
}
topLevelThisReference: ?Object;
methodPath: NodePath;
methodNode: Object;
superRef: Object;
isStatic: boolean;
hasSuper: boolean;
inClass: boolean;
isLoose: boolean;
scope: Scope;
file: File;
opts: {
getObjetRef: Function;
topLevelThisReference: Object;
methodPath: NodePath;
methodNode: Object;
superRef: Object;
isStatic: boolean;
isLoose: boolean;
scope: Scope;
file: File;
};
getObjectRef() {
return this.opts.objectRef || this.opts.getObjectRef();
}
/**
* Sets a super class value of the named property.
*
* @example
*
* _set(Object.getPrototypeOf(CLASS.prototype), "METHOD", "VALUE", this)
*
*/
setSuperProperty(property: Object, value: Object, isComputed: boolean, thisExpression: Object): Object {
return t.callExpression(
this.file.addHelper("set"),
[
t.callExpression(
t.memberExpression(t.identifier("Object"), t.identifier("getPrototypeOf")),
[
this.isStatic ? this.getObjectRef() : t.memberExpression(this.getObjectRef(), t.identifier("prototype"))
]
),
isComputed ? property : t.stringLiteral(property.name),
value,
thisExpression
]
);
}
/**
* Gets a node representing the super class value of the named property.
*
* @example
*
* _get(Object.getPrototypeOf(CLASS.prototype), "METHOD", this)
*
*/
getSuperProperty(property: Object, isComputed: boolean, thisExpression: Object): Object {
return t.callExpression(
this.file.addHelper("get"),
[
t.callExpression(
t.memberExpression(t.identifier("Object"), t.identifier("getPrototypeOf")),
[
this.isStatic ? this.getObjectRef() : t.memberExpression(this.getObjectRef(), t.identifier("prototype"))
]
),
isComputed ? property : t.stringLiteral(property.name),
thisExpression
]
);
}
replace() {
this.traverseLevel(this.methodPath.get("value"), true);
}
traverseLevel(path: NodePath, topLevel: boolean) {
let state = { self: this, topLevel: topLevel };
path.traverse(visitor, state);
}
getThisReference() {
if (this.topLevelThisReference) {
return this.topLevelThisReference;
} else {
let ref = this.topLevelThisReference = this.scope.generateUidIdentifier("this");
this.methodNode.value.body.body.unshift(t.variableDeclaration("var", [
t.variableDeclarator(this.topLevelThisReference, t.thisExpression())
]));
return ref;
}
}
getLooseSuperProperty(id: Object, parent: Object) {
let methodNode = this.methodNode;
let methodName = methodNode.key;
let superRef = this.superRef || t.identifier("Function");
if (parent.property === id) {
return;
} else if (t.isCallExpression(parent, { callee: id })) {
// super(); -> objectRef.prototype.MethodName.call(this);
parent.arguments.unshift(t.thisExpression());
if (methodName.name === "constructor") {
// constructor() { super(); }
if (parent.arguments.length === 2 && t.isSpreadElement(parent.arguments[1]) && t.isIdentifier(parent.arguments[1].argument, { name: "arguments" })) {
// special case single arguments spread
parent.arguments[1] = parent.arguments[1].argument;
return t.memberExpression(superRef, t.identifier("apply"));
} else {
return t.memberExpression(superRef, t.identifier("call"));
}
} else {
id = superRef;
// foo() { super(); }
if (!methodNode.static) {
id = t.memberExpression(id, t.identifier("prototype"));
}
id = t.memberExpression(id, methodName, methodNode.computed);
return t.memberExpression(id, t.identifier("call"));
}
} else if (t.isMemberExpression(parent) && !methodNode.static) {
// super.test -> objectRef.prototype.test
return t.memberExpression(superRef, t.identifier("prototype"));
} else {
return superRef;
}
}
looseHandle(path: NodePath, getThisReference: Function) {
let node = path.node;
if (path.isSuper()) {
return this.getLooseSuperProperty(node, path.parent);
} else if (path.isCallExpression()) {
let callee = node.callee;
if (!t.isMemberExpression(callee)) return;
if (!t.isSuper(callee.object)) return;
// super.test(); -> objectRef.prototype.MethodName.call(this);
t.appendToMemberExpression(callee, t.identifier("call"));
node.arguments.unshift(getThisReference());
return true;
}
}
specHandleAssignmentExpression(ref, path, node, getThisReference) {
if (node.operator === "=") {
// super.name = "val"; -> _set(Object.getPrototypeOf(objectRef.prototype), "name", this);
return this.setSuperProperty(node.left.property, node.right, node.left.computed, getThisReference());
} else {
// super.age += 2; -> let _ref = super.age; super.age = _ref + 2;
ref = ref || path.scope.generateUidIdentifier("ref");
return [
t.variableDeclaration("var", [
t.variableDeclarator(ref, node.left)
]),
t.expressionStatement(
t.assignmentExpression("=", node.left, t.binaryExpression(node.operator[0], ref, node.right))
)
];
}
}
specHandle(path: NodePath, getThisReference: Function) {
let methodNode = this.methodNode;
let property;
let computed;
let args;
let thisReference;
let parent = path.parent;
let node = path.node;
if (isIllegalBareSuper(node, parent)) {
throw path.buildCodeFrameError(messages.get("classesIllegalBareSuper"));
}
if (t.isCallExpression(node)) {
let callee = node.callee;
if (t.isSuper(callee)) {
// super(); -> _get(Object.getPrototypeOf(objectRef), "MethodName", this).call(this);
property = methodNode.key;
computed = methodNode.computed;
args = node.arguments;
// bare `super` call is illegal inside non-constructors
// - https://esdiscuss.org/topic/super-call-in-methods
// - https://twitter.com/wycats/status/544553184396836864
if (methodNode.key.name !== "constructor" || !this.inClass) {
let methodName = methodNode.key.name || "METHOD_NAME";
throw this.file.buildCodeFrameError(node, messages.get("classesIllegalSuperCall", methodName));
}
} else if (isMemberExpressionSuper(callee)) {
// super.test(); -> _get(Object.getPrototypeOf(objectRef.prototype), "test", this).call(this);
property = callee.property;
computed = callee.computed;
args = node.arguments;
}
} else if (t.isMemberExpression(node) && t.isSuper(node.object)) {
// super.name; -> _get(Object.getPrototypeOf(objectRef.prototype), "name", this);
property = node.property;
computed = node.computed;
} else if (t.isUpdateExpression(node) && isMemberExpressionSuper(node.argument)) {
let binary = t.binaryExpression(node.operator[0], node.argument, t.numberLiteral(1));
if (node.prefix) {
// ++super.foo; -> super.foo += 1;
return this.specHandleAssignmentExpression(null, path, binary, getThisReference);
} else {
// super.foo++; -> let _ref = super.foo; super.foo = _ref + 1;
let ref = path.scope.generateUidIdentifier("ref");
return this.specHandleAssignmentExpression(ref, path, binary, getThisReference).concat(t.expressionStatement(ref));
}
} else if (t.isAssignmentExpression(node) && isMemberExpressionSuper(node.left)) {
return this.specHandleAssignmentExpression(null, path, node, getThisReference);
}
if (!property) return;
thisReference = getThisReference();
let superProperty = this.getSuperProperty(property, computed, thisReference);
if (args) {
if (args.length === 1 && t.isSpreadElement(args[0])) {
// super(...arguments);
return t.callExpression(
t.memberExpression(superProperty, t.identifier("apply")),
[thisReference, args[0].argument]
);
} else {
return t.callExpression(
t.memberExpression(superProperty, t.identifier("call")),
[thisReference, ...args]
);
}
} else {
return superProperty;
}
}
}

View File

@@ -1,10 +0,0 @@
/* @flow */
import Pipeline from "./pipeline";
let pipeline = new Pipeline;
let transform = pipeline.transform.bind(pipeline);
transform.fromAst = pipeline.transformFromAst.bind(pipeline);
transform.lint = pipeline.lint.bind(pipeline);
transform.pipeline = pipeline;
export default transform;

View File

@@ -6,12 +6,12 @@ import * as t from "babel-types";
export default new Plugin({
visitor: {
ThisExpression(path) {
return remap(path, "this", () => t.thisExpression());
remap(path, "this", () => t.thisExpression());
},
ReferencedIdentifier(path) {
if (path.node.name === "arguments") {
return remap(path, "arguments", () => t.identifier("arguments"));
remap(path, "arguments", () => t.identifier("arguments"));
}
}
}
@@ -56,7 +56,7 @@ function remap(path, key, create) {
if (fnPath === currentFunction) return;
let cached = fnPath.getData(key);
if (cached) return cached;
if (cached) return path.replaceWith(cached);
let init = create();
let id = path.scope.generateUidIdentifier(key);
@@ -64,5 +64,5 @@ function remap(path, key, create) {
fnPath.setData(key, id);
fnPath.scope.push({ id, init });
return id;
return path.replaceWith(id);
}

View File

@@ -1,298 +0,0 @@
/* @flow */
import type { File, FileModulesMetadata } from "../file";
import type { Scope, NodePath } from "babel-traverse";
import * as metadataVisitor from "./lib/metadata";
import * as messages from "babel-messages";
import Remaps from "./lib/remaps";
import * as util from "../../util";
import * as t from "babel-types";
export default class DefaultFormatter {
constructor(file: File) {
// object containg all module sources with the scope that they're contained in
this.sourceScopes = Object.create(null);
// ids for use in module ids
this.defaultIds = Object.create(null);
this.ids = Object.create(null);
// contains reference aliases for live bindings
this.remaps = new Remaps(file, this);
this.scope = file.scope;
this.file = file;
this.hasNonDefaultExports = false;
this.hasLocalExports = false;
this.hasLocalImports = false;
this.localExports = Object.create(null);
this.localImports = Object.create(null);
this.metadata = file.metadata.modules;
this.getMetadata();
}
sourceScopes: Object;
defaultIds: Object;
ids: Object;
remaps: Remaps;
scope: Scope;
file: File;
hasNonDefaultExports: boolean;
hasLocalExports: boolean;
hasLocalImports: boolean;
localExports: Object;
localImports: Object;
metadata: FileModulesMetadata;
addScope(path: NodePath) {
let source = path.node.source && path.node.source.value;
if (!source) return;
let existingScope = this.sourceScopes[source];
if (existingScope && existingScope !== path.scope) {
throw path.buildCodeFrameError(messages.get("modulesDuplicateDeclarations"));
}
this.sourceScopes[source] = path.scope;
}
isModuleType(node: Object, type: string): boolean {
let modules = this.file.dynamicImportTypes[type];
return modules && modules.indexOf(node) >= 0;
}
transform() {
this.remapAssignments();
}
doDefaultExportInterop(node: Object): Object {
return (t.isExportDefaultDeclaration(node) || t.isSpecifierDefault(node)) && !this.noInteropRequireExport && !this.hasNonDefaultExports;
}
getMetadata() {
let has = false;
for (let node of (this.file.ast.program.body: Array<Object>)) {
if (t.isModuleDeclaration(node)) {
has = true;
break;
}
}
if (has) {
this.file.path.traverse(metadataVisitor, this);
}
}
remapAssignments() {
if (this.hasLocalExports || this.hasLocalImports) {
this.remaps.run();
}
}
remapExportAssignment(node: Object, exported: Array<Object>) {
let assign = node;
for (let prop of exported) {
assign = t.assignmentExpression(
"=",
t.memberExpression(t.identifier("exports"), prop),
assign
);
}
return assign;
}
_addExport(name: string, exported: Array<Object>) {
let info = this.localExports[name] = this.localExports[name] || {
binding: this.scope.getBindingIdentifier(name),
exported: []
};
info.exported.push(exported);
}
getExport(node: Object, scope: Scope) {
if (!t.isIdentifier(node)) return;
let local = this.localExports[node.name];
if (local && local.binding === scope.getBindingIdentifier(node.name)) {
return local.exported;
}
}
getModuleName(): string {
let opts = this.file.opts;
// moduleId is n/a if a `getModuleId()` is provided
if (opts.moduleId != null && !opts.getModuleId) {
return opts.moduleId;
}
let filenameRelative = opts.filenameRelative;
let moduleName = "";
if (opts.moduleRoot != null) {
moduleName = opts.moduleRoot + "/";
}
if (!opts.filenameRelative) {
return moduleName + opts.filename.replace(/^\//, "");
}
if (opts.sourceRoot != null) {
// remove sourceRoot from filename
let sourceRootRegEx = new RegExp("^" + opts.sourceRoot + "\/?");
filenameRelative = filenameRelative.replace(sourceRootRegEx, "");
}
if (!opts.keepModuleIdExtensions) {
// remove extension
filenameRelative = filenameRelative.replace(/\.(\w*?)$/, "");
}
moduleName += filenameRelative;
// normalize path separators
moduleName = moduleName.replace(/\\/g, "/");
if (opts.getModuleId) {
// If return is falsy, assume they want us to use our generated default name
return opts.getModuleId(moduleName) || moduleName;
} else {
return moduleName;
}
}
_pushStatement(ref: Object, nodes: Array<Object>): Object {
if (t.isClass(ref) || t.isFunction(ref)) {
if (ref.id) {
nodes.push(t.toStatement(ref));
ref = ref.id;
}
}
return ref;
}
_hoistExport(declar: Object, assign: Object, priority?: number): Object {
if (t.isFunctionDeclaration(declar)) {
assign._blockHoist = priority || 2;
}
return assign;
}
getExternalReference(node: Object, nodes: Array<Object>): Object {
let ids = this.ids;
let id = node.source.value;
if (ids[id]) {
return ids[id];
} else {
return this.ids[id] = this._getExternalReference(node, nodes);
}
}
_getExternalReference() {
throw new Error("Should be implemented");
}
checkExportIdentifier(node) {
if (t.isIdentifier(node, { name: "__esModule" })) {
throw this.file.buildCodeFrameError(node, messages.get("modulesIllegalExportName", node.name));
}
}
exportAllDeclaration(node: Object, nodes: Array<Object>) {
let ref = this.getExternalReference(node, nodes);
nodes.push(this.buildExportsWildcard(ref, node));
}
exportSpecifier(specifier: Object, node: Object, nodes: Array<Object>) {
if (node.source) {
let ref = this.getExternalReference(node, nodes);
if (specifier.local.name === "default" && !this.noInteropRequireExport) {
// importing a default so we need to normalize it
ref = t.callExpression(this.file.addHelper("interop-require"), [ref]);
} else {
ref = t.memberExpression(ref, specifier.local);
nodes.push(this.buildExportsFromAssignment(specifier.exported, ref, node));
return;
}
// export { foo } from "test";
nodes.push(this.buildExportsAssignment(specifier.exported, ref, node));
} else {
// export { foo };
nodes.push(this.buildExportsAssignment(specifier.exported, specifier.local, node));
}
}
buildExportsWildcard(objectIdentifier: Object) {
return t.expressionStatement(t.callExpression(this.file.addHelper("defaults"), [
t.identifier("exports"),
t.callExpression(this.file.addHelper("interop-export-wildcard"), [
objectIdentifier,
this.file.addHelper("defaults")
])
]));
}
buildExportsFromAssignment(id: Object, init: Object) {
this.checkExportIdentifier(id);
return util.template("exports-from-assign", {
INIT: init,
ID: t.stringLiteral(id.name)
}, true);
}
buildExportsAssignment(id, init) {
this.checkExportIdentifier(id);
return util.template("exports-assign", {
VALUE: init,
KEY: id
}, true);
}
exportDeclaration(node: Object, nodes: Array<Object>) {
let declar = node.declaration;
let id = declar.id;
if (t.isExportDefaultDeclaration(node)) {
id = t.identifier("default");
}
let assign;
if (t.isVariableDeclaration(declar)) {
for (let i = 0; i < declar.declarations.length; i++) {
let decl = declar.declarations[i];
decl.init = this.buildExportsAssignment(decl.id, decl.init, node).expression;
let newDeclar = t.variableDeclaration(declar.kind, [decl]);
if (i === 0) t.inherits(newDeclar, declar);
nodes.push(newDeclar);
}
} else {
let ref = declar;
if (t.isFunctionDeclaration(declar) || t.isClassDeclaration(declar)) {
ref = declar.id;
nodes.push(declar);
}
assign = this.buildExportsAssignment(id, ref, node);
nodes.push(assign);
this._hoistExport(declar, assign);
}
}
}

View File

@@ -1,15 +0,0 @@
/* @flow */
import * as util from "../../util";
export default function (Parent: Function): Function {
function Constructor() {
this.noInteropRequireImport = true;
this.noInteropRequireExport = true;
Parent.apply(this, arguments);
}
util.inherits(Constructor, Parent);
return Constructor;
}

View File

@@ -1,6 +0,0 @@
/* @flow */
import AMDFormatter from "./amd";
import buildStrict from "./_strict";
export default buildStrict(AMDFormatter);

View File

@@ -1,145 +0,0 @@
/* @flow */
import DefaultFormatter from "./_default";
import CommonFormatter from "./common";
import includes from "lodash/collection/includes";
import values from "lodash/object/values";
import * as util from "../../util";
import * as t from "babel-types";
export default class AMDFormatter extends DefaultFormatter {
setup() {
CommonFormatter.prototype._setup.call(this, this.hasNonDefaultExports);
}
buildDependencyLiterals() {
let names = [];
for (let name in this.ids) {
names.push(t.stringLiteral(name));
}
return names;
}
/**
* Wrap the entire body in a `define` wrapper.
*/
transform(program) {
CommonFormatter.prototype.transform.apply(this, arguments);
let body = program.body;
// build an array of module names
let names = [t.stringLiteral("exports")];
if (this.passModuleArg) names.push(t.stringLiteral("module"));
names = names.concat(this.buildDependencyLiterals());
names = t.arrayExpression(names);
// build up define container
let params = values(this.ids);
if (this.passModuleArg) params.unshift(t.identifier("module"));
params.unshift(t.identifier("exports"));
let container = t.functionExpression(null, params, t.blockStatement(body));
let defineArgs = [names, container];
let moduleName = this.getModuleName();
if (moduleName) defineArgs.unshift(t.stringLiteral(moduleName));
let call = t.callExpression(t.identifier("define"), defineArgs);
program.body = [t.expressionStatement(call)];
}
/**
* Get the AMD module name that we'll prepend to the wrapper
* to define this module
*/
getModuleName() {
if (this.file.opts.moduleIds) {
return DefaultFormatter.prototype.getModuleName.apply(this, arguments);
} else {
return null;
}
}
_getExternalReference(node) {
return this.scope.generateUidIdentifier(node.source.value);
}
importDeclaration(node) {
this.getExternalReference(node);
}
importSpecifier(specifier, node, nodes, scope) {
let key = node.source.value;
let ref = this.getExternalReference(node);
if (t.isImportNamespaceSpecifier(specifier) || t.isImportDefaultSpecifier(specifier)) {
this.defaultIds[key] = specifier.local;
}
if (this.isModuleType(node, "absolute")) {
// absolute module reference
} else if (this.isModuleType(node, "absoluteDefault")) {
// prevent unnecessary renaming of dynamic imports
this.ids[node.source.value] = ref;
ref = t.memberExpression(ref, t.identifier("default"));
} else if (t.isImportNamespaceSpecifier(specifier)) {
// import * as bar from "foo";
} else if (!includes(this.file.dynamicImported, node) && t.isSpecifierDefault(specifier) && !this.noInteropRequireImport) {
// import foo from "foo";
let uid = scope.generateUidIdentifier(specifier.local.name);
nodes.push(t.variableDeclaration("var", [
t.variableDeclarator(uid, t.callExpression(this.file.addHelper("interop-require-default"), [ref]))
]));
ref = t.memberExpression(uid, t.identifier("default"));
} else {
// import { foo } from "foo";
let imported = specifier.imported;
if (t.isSpecifierDefault(specifier)) imported = t.identifier("default");
ref = t.memberExpression(ref, imported);
}
this.remaps.add(scope, specifier.local.name, ref);
}
exportSpecifier(specifier, node, nodes) {
if (this.doDefaultExportInterop(specifier)) {
this.passModuleArg = true;
if (specifier.exported !== specifier.local && !node.source) {
nodes.push(util.template("exports-default-assign", {
VALUE: specifier.local
}, true));
return;
}
}
CommonFormatter.prototype.exportSpecifier.apply(this, arguments);
}
exportDeclaration(node, nodes) {
if (this.doDefaultExportInterop(node)) {
this.passModuleArg = true;
let declar = node.declaration;
let assign = util.template("exports-default-assign", {
VALUE: this._pushStatement(declar, nodes)
}, true);
if (t.isFunctionDeclaration(declar)) {
// we can hoist this assignment to the top of the file
assign._blockHoist = 3;
}
nodes.push(assign);
return;
}
DefaultFormatter.prototype.exportDeclaration.apply(this, arguments);
}
}

View File

@@ -1,6 +0,0 @@
/* @flow */
import CommonFormatter from "./common";
import buildStrict from "./_strict";
export default buildStrict(CommonFormatter);

View File

@@ -1,123 +0,0 @@
import DefaultFormatter from "./_default";
import * as util from "../../util";
import * as t from "babel-types";
export default class CommonJSFormatter extends DefaultFormatter {
setup() {
this._setup(this.hasLocalExports);
}
_setup(conditional) {
let file = this.file;
let scope = file.scope;
scope.rename("module");
scope.rename("exports");
if (!this.noInteropRequireImport && conditional) {
let templateName = "exports-module-declaration";
if (this.file.isLoose("es6.modules")) templateName += "-loose";
let declar = util.template(templateName, true);
declar._blockHoist = 3;
file.path.unshiftContainer("body", [declar]);
}
}
transform(program) {
DefaultFormatter.prototype.transform.apply(this, arguments);
if (this.hasDefaultOnlyExport) {
program.body.push(
t.expressionStatement(t.assignmentExpression(
"=",
t.memberExpression(t.identifier("module"), t.identifier("exports")),
t.memberExpression(t.identifier("exports"), t.identifier("default"))
))
);
}
}
importSpecifier(specifier, node, nodes, scope) {
let variableName = specifier.local;
let ref = this.getExternalReference(node, nodes);
// import foo from "foo";
if (t.isSpecifierDefault(specifier)) {
if (this.isModuleType(node, "absolute")) {
// absolute module reference
} else if (this.isModuleType(node, "absoluteDefault")) {
this.remaps.add(scope, variableName.name, ref);
} else if (this.noInteropRequireImport) {
this.remaps.add(scope, variableName.name, t.memberExpression(ref, t.identifier("default")));
} else {
let uid = this.scope.generateUidIdentifierBasedOnNode(node, "import");
nodes.push(t.variableDeclaration("var", [
t.variableDeclarator(uid, t.callExpression(this.file.addHelper("interop-require-default"), [ref]))
]));
this.remaps.add(scope, variableName.name, t.memberExpression(uid, t.identifier("default")));
}
} else {
if (t.isImportNamespaceSpecifier(specifier)) {
if (!this.noInteropRequireImport) {
ref = t.callExpression(this.file.addHelper("interop-require-wildcard"), [ref]);
}
// import * as bar from "foo";
nodes.push(t.variableDeclaration("var", [
t.variableDeclarator(variableName, ref)
]));
} else {
// import { foo } from "foo";
this.remaps.add(scope, variableName.name,
t.memberExpression(ref, t.identifier(specifier.imported.name)));
}
}
}
importDeclaration(node, nodes) {
// import "foo";
nodes.push(util.template("require", {
MODULE_NAME: node.source
}, true));
}
exportSpecifier(specifier) {
if (this.doDefaultExportInterop(specifier)) {
this.hasDefaultOnlyExport = true;
}
DefaultFormatter.prototype.exportSpecifier.apply(this, arguments);
}
exportDeclaration(node) {
if (this.doDefaultExportInterop(node)) {
this.hasDefaultOnlyExport = true;
}
DefaultFormatter.prototype.exportDeclaration.apply(this, arguments);
}
_getExternalReference(node, nodes) {
let call = t.callExpression(t.identifier("require"), [node.source]);
let uid;
if (this.isModuleType(node, "absolute")) {
// absolute module reference
} else if (this.isModuleType(node, "absoluteDefault")) {
call = t.memberExpression(call, t.identifier("default"));
} else {
uid = this.scope.generateUidIdentifierBasedOnNode(node, "import");
}
uid = uid || node.specifiers[0].local;
let declar = t.variableDeclaration("var", [
t.variableDeclarator(uid, call)
]);
nodes.push(declar);
return uid;
}
}

View File

@@ -1,17 +0,0 @@
/* @flow */
import DefaultFormatter from "./_default";
import * as t from "babel-types";
export default class IgnoreFormatter extends DefaultFormatter {
exportDeclaration(node, nodes) {
let declar = t.toStatement(node.declaration, true);
if (declar) nodes.push(t.inherits(declar, node));
}
exportAllDeclaration() {}
importDeclaration() {}
importSpecifier() {}
exportSpecifier() {}
transform() {}
}

View File

@@ -1,16 +0,0 @@
/* @flow */
/**
* [Please add a description.]
*/
export default {
commonStrict: require("./common-strict"),
amdStrict: require("./amd-strict"),
umdStrict: require("./umd-strict"),
common: require("./common"),
system: require("./system"),
ignore: require("./ignore"),
amd: require("./amd"),
umd: require("./umd")
};

View File

@@ -1,124 +0,0 @@
/* @flow */
import * as t from "babel-types";
let remapVisitor = {
enter(node) {
if (node._skipModulesRemap) {
return this.skip();
}
},
ReferencedIdentifier(node, parent, scope, remaps) {
let { formatter } = remaps;
let remap = remaps.get(scope, node.name);
if (!remap || node === remap) return;
if (!scope.hasBinding(node.name) ||
scope.bindingIdentifierEquals(node.name, formatter.localImports[node.name])) {
if (!formatter.isLoose() && this.key === "callee" && this.parentPath.isCallExpression()) {
return t.sequenceExpression([t.numberLiteral(0), remap]);
} else {
return remap;
}
}
},
AssignmentExpression: {
exit(node, parent, scope, { formatter }) {
if (!node._ignoreModulesRemap) {
let exported = formatter.getExport(node.left, scope);
if (exported) {
return formatter.remapExportAssignment(node, exported);
}
}
}
},
UpdateExpression(node, parent, scope, { formatter }) {
let exported = formatter.getExport(node.argument, scope);
if (!exported) return;
this.skip();
// expand to long file assignment expression
let assign = t.assignmentExpression(node.operator[0] + "=", node.argument, t.numberLiteral(1));
// remap this assignment expression
let remapped = formatter.remapExportAssignment(assign, exported);
// we don't need to change the result
if (t.isExpressionStatement(parent) || node.prefix) {
return remapped;
}
let nodes = [];
nodes.push(remapped);
let operator;
if (node.operator === "--") {
operator = "+";
} else { // "++"
operator = "-";
}
nodes.push(t.binaryExpression(operator, node.argument, t.numberLiteral(1)));
return t.sequenceExpression(nodes);
}
};
export default class Remaps {
constructor(file, formatter) {
this.formatter = formatter;
this.file = file;
}
run() {
this.file.path.traverse(remapVisitor, this);
}
_getKey(name) {
return `${name}:moduleRemap`;
}
get(scope, name) {
return scope.getData(this._getKey(name));
}
add(scope, name, val) {
if (this.all) {
this.all.push({
name,
scope,
node: val
});
}
return scope.setData(this._getKey(name), val);
}
remove(scope, name) {
return scope.removeData(this._getKey(name));
}
/**
* These methods are used by the system module formatter who needs access to all the remaps
* so it can process them into it's specific setter method. We don't do this by default since
* no other module formatters need access to this.
*/
getAll() {
return this.all;
}
clearAll() {
if (this.all) {
for (let remap of (this.all: Array)) {
remap.scope.removeData(this._getKey(remap.name));
}
}
this.all = [];
}
}

View File

@@ -1,226 +0,0 @@
/* @flow */
import DefaultFormatter from "./_default";
import AMDFormatter from "./amd";
import * as util from "../../util";
import last from "lodash/array/last";
import map from "lodash/collection/map";
import * as t from "babel-types";
let hoistVariablesVisitor = {
Function(path) {
// nothing inside is accessible
path.skip();
},
VariableDeclaration({ node, parent }, state) {
if (node.kind !== "var" && !t.isProgram(parent)) { // let, const
// can't be accessed
return;
}
// ignore block hoisted nodes as these can be left in
if (state.formatter._canHoist(node)) return;
let nodes = [];
for (let i = 0; i < node.declarations.length; i++) {
let declar = node.declarations[i];
state.hoistDeclarators.push(t.variableDeclarator(declar.id));
if (declar.init) {
// no initializer so we can just hoist it as-is
let assign = t.expressionStatement(t.assignmentExpression("=", declar.id, declar.init));
nodes.push(assign);
}
}
// for (let i in test)
if (t.isFor(parent) && parent.left === node) {
return node.declarations[0].id;
}
return nodes;
}
};
let hoistFunctionsVisitor = {
Function(path) {
path.skip();
},
enter(path, state) {
if (path.isFunctionDeclaration() || state.formatter._canHoist(path.node)) {
state.handlerBody.push(path.node);
path.remove();
}
}
};
let runnerSettersVisitor = {
enter(path, state) {
let { node } = path;
if (node._importSource === state.source) {
if (t.isVariableDeclaration(node)) {
for (let declar of (node.declarations: Array)) {
state.hoistDeclarators.push(t.variableDeclarator(declar.id));
state.nodes.push(t.expressionStatement(
t.assignmentExpression("=", declar.id, declar.init)
));
}
} else {
state.nodes.push(node);
}
path.remove();
}
}
};
export default class SystemFormatter extends AMDFormatter {
constructor(file) {
super(file);
this._setters = null;
this.exportIdentifier = file.scope.generateUidIdentifier("export");
this.noInteropRequireExport = true;
this.noInteropRequireImport = true;
this.remaps.clearAll();
}
_addImportSource(node, exportNode) {
if (node) node._importSource = exportNode.source && exportNode.source.value;
return node;
}
buildExportsWildcard(objectIdentifier, node) {
let leftIdentifier = this.scope.generateUidIdentifier("key");
let valIdentifier = t.memberExpression(objectIdentifier, leftIdentifier, true);
let left = t.variableDeclaration("var", [
t.variableDeclarator(leftIdentifier)
]);
let right = objectIdentifier;
let block = t.blockStatement([
t.ifStatement(
t.binaryExpression("!==", leftIdentifier, t.stringLiteral("default")),
t.expressionStatement(this._buildExportCall(leftIdentifier, valIdentifier))
)
]);
return this._addImportSource(t.forInStatement(left, right, block), node);
}
buildExportsAssignment(id, init, node) {
let call = this._buildExportCall(t.stringLiteral(id.name), init, true);
return this._addImportSource(call, node);
}
buildExportsFromAssignment() {
return this.buildExportsAssignment(...arguments);
}
remapExportAssignment(node, exported) {
let assign = node;
for (let i = 0; i < exported.length; i++) {
assign = this._buildExportCall(t.stringLiteral(exported[i].name), assign);
}
return assign;
}
_buildExportCall(id, init, isStatement) {
let call = t.callExpression(this.exportIdentifier, [id, init]);
if (isStatement) {
return t.expressionStatement(call);
} else {
return call;
}
}
importSpecifier(specifier, node, nodes) {
AMDFormatter.prototype.importSpecifier.apply(this, arguments);
for (let remap of (this.remaps.getAll(): Array)) {
nodes.push(t.variableDeclaration("var", [
t.variableDeclarator(t.identifier(remap.name), remap.node)
]));
}
this.remaps.clearAll();
this._addImportSource(last(nodes), node);
}
_buildRunnerSetters(block, hoistDeclarators) {
let scope = this.file.scope;
return t.arrayExpression(map(this.ids, function (uid, source) {
let state = {
hoistDeclarators: hoistDeclarators,
source: source,
nodes: []
};
scope.traverse(block, runnerSettersVisitor, state);
return t.functionExpression(null, [uid], t.blockStatement(state.nodes));
}));
}
_canHoist(node) {
return node._blockHoist && !this.file.dynamicImports.length;
}
transform(program) {
DefaultFormatter.prototype.transform.apply(this, arguments);
let hoistDeclarators = [];
let moduleName = this.getModuleName();
let moduleNameLiteral = t.stringLiteral(moduleName);
let block = t.blockStatement(program.body);
let setterListNode = this._buildRunnerSetters(block, hoistDeclarators);
this._setters = setterListNode;
let runner = util.template("system", {
MODULE_DEPENDENCIES: t.arrayExpression(this.buildDependencyLiterals()),
EXPORT_IDENTIFIER: this.exportIdentifier,
MODULE_NAME: moduleNameLiteral,
SETTERS: setterListNode,
EXECUTE: t.functionExpression(null, [], block)
}, true);
let handlerBody = runner.expression.arguments[2].body.body;
if (!moduleName) runner.expression.arguments.shift();
let returnStatement = handlerBody.pop();
// hoist up all variable declarations
this.file.scope.traverse(block, hoistVariablesVisitor, {
formatter: this,
hoistDeclarators: hoistDeclarators
});
if (hoistDeclarators.length) {
let hoistDeclar = t.variableDeclaration("var", hoistDeclarators);
hoistDeclar._blockHoist = true;
handlerBody.unshift(hoistDeclar);
}
// hoist up function declarations for circular references
this.file.scope.traverse(block, hoistFunctionsVisitor, {
formatter: this,
handlerBody: handlerBody
});
handlerBody.push(returnStatement);
program.body = [runner];
}
}

View File

@@ -1,6 +0,0 @@
/* @flow */
import UMDFormatter from "./umd";
import buildStrict from "./_strict";
export default buildStrict(UMDFormatter);

View File

@@ -1,85 +0,0 @@
/* @flow */
import DefaultFormatter from "./_default";
import AMDFormatter from "./amd";
import values from "lodash/object/values";
import path from "path";
import * as util from "../../util";
import * as t from "babel-types";
export default class UMDFormatter extends AMDFormatter {
transform(program) {
DefaultFormatter.prototype.transform.apply(this, arguments);
let body = program.body;
// build an array of module names
let names = [];
for (let name in this.ids) {
names.push(t.stringLiteral(name));
}
// factory
let ids = values(this.ids);
let args = [t.identifier("exports")];
if (this.passModuleArg) args.push(t.identifier("module"));
args = args.concat(ids);
let factory = t.functionExpression(null, args, t.blockStatement(body));
// amd
let defineArgs = [t.stringLiteral("exports")];
if (this.passModuleArg) defineArgs.push(t.stringLiteral("module"));
defineArgs = defineArgs.concat(names);
defineArgs = [t.arrayExpression(defineArgs)];
// common
let testExports = util.template("test-exports");
let testModule = util.template("test-module");
let commonTests = this.passModuleArg ? t.logicalExpression("&&", testExports, testModule) : testExports;
let commonArgs = [t.identifier("exports")];
if (this.passModuleArg) commonArgs.push(t.identifier("module"));
commonArgs = commonArgs.concat(names.map(function (name) {
return t.callExpression(t.identifier("require"), [name]);
}));
// globals
let browserArgs = [];
if (this.passModuleArg) browserArgs.push(t.identifier("mod"));
for (let name in this.ids) {
let id = this.defaultIds[name] || t.identifier(t.toIdentifier(path.basename(name, path.extname(name))));
browserArgs.push(t.memberExpression(t.identifier("global"), id));
}
//
let moduleName = this.getModuleName();
if (moduleName) defineArgs.unshift(t.stringLiteral(moduleName));
//
let globalArg = this.file.opts.basename;
if (moduleName) globalArg = moduleName;
globalArg = t.identifier(t.toIdentifier(globalArg));
let runner = util.template("umd-runner-body", {
AMD_ARGUMENTS: defineArgs,
COMMON_TEST: commonTests,
COMMON_ARGUMENTS: commonArgs,
BROWSER_ARGUMENTS: browserArgs,
GLOBAL_ARG: globalArg
});
//
program.body = [t.expressionStatement(
t.callExpression(runner, [t.thisExpression(), factory])
)];
}
}

View File

@@ -1,11 +1,13 @@
/* @flow */
import type Plugin from "./plugin";
import Store from "../store";
import traverse from "babel-traverse";
import File from "./file";
export default class PluginPass {
export default class PluginPass extends Store {
constructor(file: File, plugin: Plugin, options: Object = {}) {
super();
this.plugin = plugin;
this.file = file;
this.opts = options;
@@ -25,4 +27,16 @@ export default class PluginPass {
addHelper(...args) {
return this.file.addHelper(...args);
}
addImport(...args) {
return this.file.addImport(...args);
}
getModuleName(...args) {
return this.file.getModuleName(...args);
}
buildCodeFrameError(...args) {
return this.file.buildCodeFrameError(...args);
}
}

View File

@@ -1,33 +1,79 @@
/* @flow */
import OptionManager from "./file/options/option-manager"
import * as messages from "babel-messages";
import Store from "../store";
import traverse from "babel-traverse";
import assign from "lodash/object/assign";
import clone from "lodash/lang/clone";
export default class Plugin {
export default class Plugin extends Store {
constructor(plugin: Object) {
plugin = this.raw = assign({}, plugin);
super();
function take(key) {
let val = plugin[key];
delete plugin[key];
return val;
}
this.initialized = false;
this.raw = assign({}, plugin);
this.manipulateOptions = take("manipulateOptions");
this.post = take("post");
this.pre = take("pre");
this.visitor = this.normalize(clone(take("visitor")) || {});
this.manipulateOptions = this.take("manipulateOptions");
this.post = this.take("post");
this.pre = this.take("pre");
this.visitor = this.normalize(clone(this.take("visitor")) || {});
}
initialized: boolean;
raw: Object;
manipulateOptions: ?Function;
post: ?Function;
pre: ?Function;
visitor: Object;
validate(loc: string, i: number) {
take(key) {
let val = this.raw[key];
delete this.raw[key];
return val;
}
chain(target, key) {
if (!target[key]) return this[key];
if (!this[key]) return target[key];
let fns: Array<?Function> = [target[key], this[key]];
return function (...args) {
let val;
for (let fn of fns) {
if (fn) {
let ret = fn.apply(this, args);
if (ret != null) val = ret;
}
}
return val;
};
}
maybeInherit(loc: string) {
let inherits = this.take("inherits");
if (!inherits) return;
inherits = OptionManager.normalisePlugin(inherits, loc, "inherits");
this.manipulateOptions = this.chain(inherits, "manipulateOptions");
this.post = this.chain(inherits, "post");
this.pre = this.chain(inherits, "pre");
this.visitor = traverse.visitors.merge([inherits.visitor, this.visitor]);
}
/**
* We lazy initialise parts of a plugin that rely on contextual information such as
* position on disk and how it was specified.
*/
init(loc: string, i: number) {
if (this.initialized) return;
this.initialized = true;
this.maybeInherit(loc);
for (let key in this.raw) {
throw new Error(messages.get("pluginInvalidProperty", loc, i, key));
}

View File

@@ -1,4 +0,0 @@
{
"blacklist": ["useStrict", "es6.blockScoping", "regenerator", "es6.spread"],
"loose": ["es6.modules"]
}

View File

@@ -1 +0,0 @@
PROPERTY[Symbol.referenceGet](OBJECT).call(OBJECT)

View File

@@ -1 +0,0 @@
PROPERTY[Symbol.referenceDelete](OBJECT)

View File

@@ -1 +0,0 @@
PROPERTY[Symbol.referenceGet](OBJECT)

View File

@@ -1 +0,0 @@
PROPERTY[Symbol.referenceSet](OBJECT, VALUE)

View File

@@ -1 +0,0 @@
Array.from(VALUE);

View File

@@ -1 +0,0 @@
OBJECT.call(CONTEXT);

View File

@@ -1 +0,0 @@
exports.KEY = VALUE;

View File

@@ -1 +0,0 @@
module.exports = VALUE;

View File

@@ -1,6 +0,0 @@
Object.defineProperty(exports, ID, {
enumerable: true,
get: function () {
return INIT;
}
});

View File

@@ -1 +0,0 @@
exports.__esModule = true;

View File

@@ -1,3 +0,0 @@
Object.defineProperty(exports, "__esModule", {
value: true
});

View File

@@ -1,28 +0,0 @@
(function (fn) {
return function () {
var gen = fn.apply(this, arguments);
return new Promise(function (resolve, reject) {
var callNext = step.bind(null, "next");
var callThrow = step.bind(null, "throw");
function step(key, arg) {
try {
var info = gen[key](arg);
var value = info.value;
} catch (error) {
reject(error);
return;
}
if (info.done) {
resolve(value);
} else {
Promise.resolve(value).then(callNext, callThrow);
}
}
callNext();
});
};
})

View File

@@ -1 +0,0 @@
Function.prototype.bind

View File

@@ -1,5 +0,0 @@
(function (instance, Constructor) {
if (!(instance instanceof Constructor)) {
throw new TypeError("Cannot call a class as a function");
}
});

View File

@@ -1,17 +0,0 @@
(function() {
function defineProperties(target, props) {
for (var i = 0; i < props.length; i ++) {
var descriptor = props[i];
descriptor.enumerable = descriptor.enumerable || false;
descriptor.configurable = true;
if ("value" in descriptor) descriptor.writable = true;
Object.defineProperty(target, descriptor.key, descriptor);
}
}
return function (Constructor, protoProps, staticProps) {
if (protoProps) defineProperties(Constructor.prototype, protoProps);
if (staticProps) defineProperties(Constructor, staticProps);
return Constructor;
};
})()

View File

@@ -1,42 +0,0 @@
(function() {
function defineProperties(target, descriptors, initializers) {
for (var i = 0; i < descriptors.length; i ++) {
var descriptor = descriptors[i];
var decorators = descriptor.decorators;
var key = descriptor.key;
// don't want to expose these to userland since i know people will rely on them
// and think it's spec behaviour
delete descriptor.key;
delete descriptor.decorators;
descriptor.enumerable = descriptor.enumerable || false;
descriptor.configurable = true;
if ("value" in descriptor || descriptor.initializer) descriptor.writable = true;
if (decorators) {
for (var f = 0; f < decorators.length; f++) {
var decorator = decorators[f];
if (typeof decorator === "function") {
descriptor = decorator(target, key, descriptor) || descriptor;
} else {
throw new TypeError("The decorator for method " + descriptor.key + " is of the invalid type " + typeof decorator);
}
}
if (descriptor.initializer !== undefined) {
initializers[key] = descriptor;
continue;
}
}
Object.defineProperty(target, key, descriptor);
}
}
return function (Constructor, protoProps, staticProps, protoInitializers, staticInitializers) {
if (protoProps) defineProperties(Constructor.prototype, protoProps, protoInitializers);
if (staticProps) defineProperties(Constructor, staticProps, staticInitializers);
return Constructor;
};
})()

View File

@@ -1,37 +0,0 @@
(function (descriptors) {
var target = {};
for (var i = 0; i < descriptors.length; i ++) {
var descriptor = descriptors[i];
var decorators = descriptor.decorators;
var key = descriptor.key;
// don't want to expose these to userland since i know people will rely on them
// and think it's spec behaviour
delete descriptor.key;
delete descriptor.decorators;
descriptor.enumerable = true;
descriptor.configurable = true;
if ("value" in descriptor || descriptor.initializer) descriptor.writable = true;
if (decorators) {
for (var f = 0; f < decorators.length; f++) {
var decorator = decorators[f];
if (typeof decorator === "function") {
descriptor = decorator(target, key, descriptor) || descriptor;
} else {
throw new TypeError("The decorator for method " + descriptor.key + " is of the invalid type " + typeof decorator);
}
}
}
if (descriptor.initializer) {
descriptor.value = descriptor.initializer.call(target);
}
Object.defineProperty(target, key, descriptor);
}
return target;
})

View File

@@ -1,10 +0,0 @@
(function (defaultProps, props) {
if (defaultProps) {
for (var propName in defaultProps) {
if (typeof props[propName] === "undefined") {
props[propName] = defaultProps[propName];
}
}
}
return props;
})

View File

@@ -1,11 +0,0 @@
(function (obj, defaults) {
var keys = Object.getOwnPropertyNames(defaults);
for (var i = 0; i < keys.length; i++) {
var key = keys[i];
var value = Object.getOwnPropertyDescriptor(defaults, key);
if (value && value.configurable && obj[key] === undefined) {
Object.defineProperty(obj, key, value);
}
}
return obj;
})

View File

@@ -1,13 +0,0 @@
(function (target, key, descriptors) {
var _descriptor = descriptors[key];
if (!_descriptor) return;
// clone it
var descriptor = {};
for (var _key in _descriptor) descriptor[_key] = _descriptor[_key];
// initialize it
descriptor.value = descriptor.initializer ? descriptor.initializer.call(target) : undefined;
Object.defineProperty(target, key, descriptor);
})

View File

@@ -1,18 +0,0 @@
(function (obj, key, value) {
// Shortcircuit the slow defineProperty path when possible.
// We are trying to avoid issues where setters defined on the
// prototype cause side effects under the fast path of simple
// assignment. By checking for existence of the property with
// the in operator, we can optimize most of this overhead away.
if (key in obj) {
Object.defineProperty(obj, key, {
value: value,
enumerable: true,
configurable: true,
writable: true
});
} else {
obj[key] = value;
}
return obj;
});

View File

@@ -1,11 +0,0 @@
Object.assign || (function (target) {
for (var i = 1; i < arguments.length; i++) {
var source = arguments[i];
for (var key in source) {
if (Object.prototype.hasOwnProperty.call(source, key)) {
target[key] = source[key];
}
}
}
return target;
})

View File

@@ -1,25 +0,0 @@
(function get(object, property, receiver) {
if (object === null) object = Function.prototype;
var desc = Object.getOwnPropertyDescriptor(object, property);
if (desc === undefined) {
var parent = Object.getPrototypeOf(object);
if (parent === null) {
return undefined;
} else {
return get(parent, property, receiver);
}
} else if ("value" in desc) {
return desc.value;
} else {
var getter = desc.get;
if (getter === undefined) {
return undefined;
}
return getter.call(receiver);
}
});

View File

@@ -1 +0,0 @@
Object.prototype.hasOwnProperty;

View File

@@ -1,14 +0,0 @@
(function (subClass, superClass) {
if (typeof superClass !== "function" && superClass !== null) {
throw new TypeError("Super expression must either be null or a function, not " + typeof superClass);
}
subClass.prototype = Object.create(superClass && superClass.prototype, {
constructor: {
value: subClass,
enumerable: false,
writable: true,
configurable: true
}
});
if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass;
})

View File

@@ -1,7 +0,0 @@
(function (left, right) {
if (right != null && right[Symbol.hasInstance]) {
return right[Symbol.hasInstance](left);
} else {
return left instanceof right;
}
});

View File

@@ -1,5 +0,0 @@
(function (obj, defaults) {
var newObj = defaults({}, obj);
delete newObj.default;
return newObj;
})

View File

@@ -1,3 +0,0 @@
(function (obj) {
return obj && obj.__esModule ? obj : { default: obj };
})

View File

@@ -1,14 +0,0 @@
(function (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)) newObj[key] = obj[key];
}
}
newObj.default = obj;
return newObj;
}
})

View File

@@ -1,3 +0,0 @@
(function (obj) {
return obj && obj.__esModule ? obj.default : obj;
})

View File

@@ -1,5 +0,0 @@
(function (innerThis, boundThis) {
if (innerThis !== boundThis) {
throw new TypeError("Cannot instantiate an arrow function");
}
});

View File

@@ -1,3 +0,0 @@
(function (obj) {
if (obj == null) throw new TypeError("Cannot destructure undefined");
});

View File

@@ -1,9 +0,0 @@
(function (obj, keys) {
var target = {};
for (var i in obj) {
if (keys.indexOf(i) >= 0) continue;
if (!Object.prototype.hasOwnProperty.call(obj, i)) continue;
target[i] = obj[i];
}
return target;
})

View File

@@ -1 +0,0 @@
typeof global === "undefined" ? self : global

View File

@@ -1,21 +0,0 @@
(function set(object, property, value, receiver) {
var desc = Object.getOwnPropertyDescriptor(object, property);
if (desc === undefined) {
var parent = Object.getPrototypeOf(object);
if (parent !== null) {
set(parent, property, value, receiver);
}
} else if ("value" in desc && desc.writable) {
desc.value = value;
} else {
var setter = desc.set;
if (setter !== undefined) {
setter.call(receiver, value);
}
}
return value;
});

View File

@@ -1 +0,0 @@
Array.prototype.slice;

View File

@@ -1,14 +0,0 @@
(function (arr, i) {
if (Array.isArray(arr)) {
return arr;
} else if (Symbol.iterator in Object(arr)) {
var _arr = [];
for (var _iterator = arr[Symbol.iterator](), _step; !(_step = _iterator.next()).done;) {
_arr.push(_step.value);
if (i && _arr.length === i) break;
}
return _arr;
} else {
throw new TypeError("Invalid attempt to destructure non-iterable instance");
}
});

View File

@@ -1,46 +0,0 @@
(function () {
// Broken out into a separate function to avoid deoptimizations due to the try/catch for the
// array iterator case.
function sliceIterator(arr, i) {
// this is an expanded form of `for...of` that properly supports abrupt completions of
// iterators etc. variable names have been minimised to reduce the size of this massive
// helper. sometimes spec compliancy is annoying :(
//
// _n = _iteratorNormalCompletion
// _d = _didIteratorError
// _e = _iteratorError
// _i = _iterator
// _s = _step
var _arr = [];
var _n = true;
var _d = false;
var _e = undefined;
try {
for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) {
_arr.push(_s.value);
if (i && _arr.length === i) break;
}
} catch (err) {
_d = true;
_e = err;
} finally {
try {
if (!_n && _i["return"]) _i["return"]();
} finally {
if (_d) throw _e;
}
}
return _arr;
}
return function (arr, i) {
if (Array.isArray(arr)) {
return arr;
} else if (Symbol.iterator in Object(arr)) {
return sliceIterator(arr, i);
} else {
throw new TypeError("Invalid attempt to destructure non-iterable instance");
}
};
})();

View File

@@ -1,4 +0,0 @@
(function (strings, raw) {
strings.raw = raw;
return strings;
});

View File

@@ -1,5 +0,0 @@
(function (strings, raw) {
return Object.freeze(Object.defineProperties(strings, {
raw: { value: Object.freeze(raw) }
}));
});

View File

@@ -1,6 +0,0 @@
(function (val, name, undef) {
if (val === undef) {
throw new ReferenceError(name + " is not defined - temporal dead zone");
}
return true;
})

View File

@@ -1,3 +0,0 @@
(function (arr) {
return Array.isArray(arr) ? arr : Array.from(arr);
});

View File

@@ -1,8 +0,0 @@
(function (arr) {
if (Array.isArray(arr)) {
for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) arr2[i] = arr[i];
return arr2;
} else {
return Array.from(arr);
}
});

View File

@@ -1,3 +0,0 @@
(function (obj) {
return obj && obj.constructor === Symbol ? "symbol" : typeof obj;
});

View File

@@ -1,7 +0,0 @@
(function () {
function GET_OUTER_ID() {
return FUNCTION_ID;
}
return FUNCTION;
})()

View File

@@ -1,11 +0,0 @@
(function (FUNCTION_KEY) {
function* FUNCTION_ID() {
return yield* FUNCTION_KEY.apply(this, arguments);
}
FUNCTION_ID.toString = function () {
return FUNCTION_KEY.toString();
};
return FUNCTION_ID;
})(FUNCTION)

View File

@@ -1,11 +0,0 @@
(function (FUNCTION_KEY) {
function FUNCTION_ID() {
return FUNCTION_KEY.apply(this, arguments);
}
FUNCTION_ID.toString = function () {
return FUNCTION_KEY.toString();
}
return FUNCTION_ID;
})(FUNCTION)

View File

@@ -1 +0,0 @@
CLASS_NAME.prototype

View File

@@ -1 +0,0 @@
var VARIABLE_NAME = require(MODULE_NAME).KEY;

View File

@@ -1 +0,0 @@
require(MODULE_NAME);

View File

@@ -1,2 +0,0 @@
exports.default = HELPER;
exports.__esModule = true;

View File

@@ -1,6 +0,0 @@
System.register(MODULE_NAME, MODULE_DEPENDENCIES, function (EXPORT_IDENTIFIER) {
return {
setters: SETTERS,
execute: EXECUTE
};
});

View File

@@ -1 +0,0 @@
typeof exports !== "undefined"

View File

@@ -1 +0,0 @@
typeof module !== "undefined"

View File

@@ -1,11 +0,0 @@
(function (root, factory) {
if (typeof define === "function" && define.amd) {
define(AMD_ARGUMENTS, factory);
} else if (typeof exports === "object") {
factory(COMMON_ARGUMENTS);
} else {
factory(BROWSER_ARGUMENTS);
}
})(UMD_ROOT, function (FACTORY_PARAMETERS) {
FACTORY_BODY
});

View File

@@ -1,11 +0,0 @@
(function (global, factory) {
if (typeof define === "function" && define.amd) {
define(AMD_ARGUMENTS, factory);
} else if (COMMON_TEST) {
factory(COMMON_ARGUMENTS);
} else {
var mod = { exports: {} };
factory(mod.exports, BROWSER_ARGUMENTS);
global.GLOBAL_ARG = mod.exports;
}
});

View File

@@ -1,31 +0,0 @@
import * as defineMap from "../../helpers/define-map";
import * as t from "babel-types";
export let visitor = {
ObjectExpression({ node }, file) {
var hasAny = false;
for (var prop of (node.properties: Array)) {
if (prop.kind === "get" || prop.kind === "set") {
hasAny = true;
break;
}
}
if (!hasAny) return;
let mutatorMap = {};
node.properties = node.properties.filter(function (prop) {
if (prop.kind === "get" || prop.kind === "set") {
defineMap.push(mutatorMap, prop, prop.kind, file);
return false;
} else {
return true;
}
});
return t.callExpression(
t.memberExpression(t.identifier("Object"), t.identifier("defineProperties")),
[node, defineMap.toDefineObject(mutatorMap)]
);
}
};

View File

@@ -1,640 +0,0 @@
import type NodePath from "babel-traverse";
import type Scope from "babel-traverse";
import type File from "../../../file";
import traverse from "babel-traverse";
import { visitor as tdzVisitor } from "./tdz";
import * as util from "../../../../util";
import * as t from "babel-types";
import values from "lodash/object/values";
import extend from "lodash/object/extend";
function isLet(node, parent) {
if (!t.isVariableDeclaration(node)) return false;
if (node._let) return true;
if (node.kind !== "let") return false;
// https://github.com/babel/babel/issues/255
if (isLetInitable(node, parent)) {
for (let i = 0; i < node.declarations.length; i++) {
let declar = node.declarations[i];
declar.init = declar.init || scope.buildUndefinedNode();
}
}
node._let = true;
node.kind = "var";
return true;
}
function isLetInitable(node, parent) {
return !t.isFor(parent) || !t.isFor(parent, { left: node });
}
function isVar(node, parent, scope) {
return t.isVariableDeclaration(node, { kind: "var" }) && !isLet(node, parent, scope);
}
function standardizeLets(declars) {
for (let declar of (declars: Array)) {
delete declar._let;
}
}
export let metadata = {
group: "builtin-advanced"
};
export let visitor = {
VariableDeclaration(node, parent, scope, file) {
if (!isLet(node, parent, scope)) return;
if (isLetInitable(node) && node._tdzThis) {
let nodes = [node];
for (let i = 0; i < node.declarations.length; i++) {
let decl = node.declarations[i];
if (decl.init) {
let assign = t.assignmentExpression("=", decl.id, decl.init);
assign._ignoreBlockScopingTDZ = true;
nodes.push(t.expressionStatement(assign));
}
decl.init = file.addHelper("temporal-undefined");
}
node._blockHoist = 2;
if (this.isCompletionRecord()) {
// ensure we don't break completion record semantics by returning
// the initialiser of the last declarator
nodes.push(t.expressionStatement(scope.buildUndefinedNode()));
}
return nodes;
}
},
Loop(node, parent, scope, file) {
let init = node.left || node.init;
if (isLet(init, node, scope)) {
t.ensureBlock(node);
node.body._letDeclarators = [init];
}
let blockScoping = new BlockScoping(this, this.get("body"), parent, scope, file);
return blockScoping.run();
},
"BlockStatement|Program"(block, parent, scope, file) {
if (!t.isLoop(parent)) {
let blockScoping = new BlockScoping(null, this, parent, scope, file);
blockScoping.run();
}
}
};
function replace(node, parent, scope, remaps) {
let remap = remaps[node.name];
if (!remap) return;
let ownBinding = scope.getBindingIdentifier(node.name);
if (ownBinding === remap.binding) {
node.name = remap.uid;
} else {
// scope already has it's own binding that doesn't
// match the one we have a stored replacement for
if (this) this.skip();
}
}
let replaceVisitor = {
ReferencedIdentifier: replace,
AssignmentExpression(node, parent, scope, remaps) {
let ids = this.getBindingIdentifiers();
for (let name in ids) {
replace(ids[name], node, scope, remaps);
}
},
};
function traverseReplace(node, parent, scope, remaps) {
if (t.isIdentifier(node)) {
replace(node, parent, scope, remaps);
}
if (t.isAssignmentExpression(node)) {
let ids = t.getBindingIdentifiers(node);
for (let name in ids) {
replace(ids[name], parent, scope, remaps);
}
}
scope.traverse(node, replaceVisitor, remaps);
}
let letReferenceBlockVisitor = traverse.visitors.merge([{
Function(node, parent, scope, state) {
this.traverse(letReferenceFunctionVisitor, state);
return this.skip();
}
}, tdzVisitor]);
let letReferenceFunctionVisitor = traverse.visitors.merge([{
ReferencedIdentifier(node, parent, scope, state) {
let ref = state.letReferences[node.name];
// not a part of our scope
if (!ref) return;
// this scope has a variable with the same name so it couldn't belong
// to our let scope
let localBinding = scope.getBindingIdentifier(node.name);
if (localBinding && localBinding !== ref) return;
state.closurify = true;
}
}, tdzVisitor]);
let hoistVarDeclarationsVisitor = {
enter(node, parent, scope, self) {
if (this.isForStatement()) {
if (isVar(node.init, node, scope)) {
let nodes = self.pushDeclar(node.init);
if (nodes.length === 1) {
node.init = nodes[0];
} else {
node.init = t.sequenceExpression(nodes);
}
}
} else if (this.isFor()) {
if (isVar(node.left, node, scope)) {
self.pushDeclar(node.left);
node.left = node.left.declarations[0].id;
}
} else if (isVar(node, parent, scope)) {
return self.pushDeclar(node).map(t.expressionStatement);
} else if (this.isFunction()) {
return this.skip();
}
}
};
let loopLabelVisitor = {
LabeledStatement(node, parent, scope, state) {
state.innerLabels.push(node.label.name);
}
};
let continuationVisitor = {
enter(node, parent, scope, state) {
if (this.isAssignmentExpression() || this.isUpdateExpression()) {
let bindings = this.getBindingIdentifiers();
for (let name in bindings) {
if (state.outsideReferences[name] !== scope.getBindingIdentifier(name)) continue;
state.reassignments[name] = true;
}
}
}
};
function loopNodeTo(node) {
if (t.isBreakStatement(node)) {
return "break";
} else if (t.isContinueStatement(node)) {
return "continue";
}
}
let loopVisitor = {
Loop(node, parent, scope, state) {
let oldIgnoreLabeless = state.ignoreLabeless;
state.ignoreLabeless = true;
this.traverse(loopVisitor, state);
state.ignoreLabeless = oldIgnoreLabeless;
this.skip();
},
Function() {
this.skip();
},
SwitchCase(node, parent, scope, state) {
let oldInSwitchCase = state.inSwitchCase;
state.inSwitchCase = true;
this.traverse(loopVisitor, state);
state.inSwitchCase = oldInSwitchCase;
this.skip();
},
"BreakStatement|ContinueStatement|ReturnStatement"(node, parent, scope, state) {
let replace;
let loopText = loopNodeTo(node);
if (loopText) {
if (node.label) {
// we shouldn't be transforming this because it exists somewhere inside
if (state.innerLabels.indexOf(node.label.name) >= 0) {
return;
}
loopText = `${loopText}|${node.label.name}`;
} else {
// we shouldn't be transforming these statements because
// they don't refer to the actual loop we're scopifying
if (state.ignoreLabeless) return;
//
if (state.inSwitchCase) return;
// break statements mean something different in this context
if (t.isBreakStatement(node) && t.isSwitchCase(parent)) return;
}
state.hasBreakContinue = true;
state.map[loopText] = node;
replace = t.stringLiteral(loopText);
}
if (this.isReturnStatement()) {
state.hasReturn = true;
replace = t.objectExpression([
t.property("init", t.identifier("v"), node.argument || scope.buildUndefinedNode())
]);
}
if (replace) {
replace = t.returnStatement(replace);
this.skip();
return t.inherits(replace, node);
}
}
};
class BlockScoping {
constructor(loopPath?: NodePath, blockPath: NodePath, parent: Object, scope: Scope, file: File) {
this.parent = parent;
this.scope = scope;
this.file = file;
this.blockPath = blockPath;
this.block = blockPath.node;
this.outsideLetReferences = Object.create(null);
this.hasLetReferences = false;
this.letReferences = Object.create(null);
this.body = [];
if (loopPath) {
this.loopParent = loopPath.parent;
this.loopLabel = t.isLabeledStatement(this.loopParent) && this.loopParent.label;
this.loopPath = loopPath;
this.loop = loopPath.node;
}
}
/**
* Start the ball rolling.
*/
run() {
let block = this.block;
if (block._letDone) return;
block._letDone = true;
let needsClosure = this.getLetReferences();
// this is a block within a `Function/Program` so we can safely leave it be
if (t.isFunction(this.parent) || t.isProgram(this.block)) return;
// we can skip everything
if (!this.hasLetReferences) return;
if (needsClosure) {
this.wrapClosure();
} else {
this.remap();
}
if (this.loopLabel && !t.isLabeledStatement(this.loopParent)) {
return t.labeledStatement(this.loopLabel, this.loop);
}
}
remap() {
let hasRemaps = false;
let letRefs = this.letReferences;
let scope = this.scope;
// alright, so since we aren't wrapping this block in a closure
// we have to check if any of our let variables collide with
// those in upper scopes and then if they do, generate a uid
// for them and replace all references with it
let remaps = Object.create(null);
for (let key in letRefs) {
// just an Identifier node we collected in `getLetReferences`
// this is the defining identifier of a declaration
let ref = letRefs[key];
// todo: could skip this if the colliding binding is in another function
if (scope.parentHasBinding(key) || scope.hasGlobal(key)) {
let uid = scope.generateUidIdentifier(ref.name).name;
ref.name = uid;
hasRemaps = true;
remaps[key] = remaps[uid] = {
binding: ref,
uid: uid
};
}
}
if (!hasRemaps) return;
//
let loop = this.loop;
if (loop) {
traverseReplace(loop.right, loop, scope, remaps);
traverseReplace(loop.test, loop, scope, remaps);
traverseReplace(loop.update, loop, scope, remaps);
}
this.blockPath.traverse(replaceVisitor, remaps);
}
wrapClosure() {
let block = this.block;
let outsideRefs = this.outsideLetReferences;
// remap loop heads with colliding variables
if (this.loop) {
for (let name in outsideRefs) {
let id = outsideRefs[name];
if (this.scope.hasGlobal(id.name) || this.scope.parentHasBinding(id.name)) {
delete outsideRefs[id.name];
delete this.letReferences[id.name];
this.scope.rename(id.name);
this.letReferences[id.name] = id;
outsideRefs[id.name] = id;
}
}
}
// if we're inside of a for loop then we search to see if there are any
// `break`s, `continue`s, `return`s etc
this.has = this.checkLoop();
// hoist let references to retain scope
this.hoistVarDeclarations();
// turn outsideLetReferences into an array
let params = values(outsideRefs);
let args = values(outsideRefs);
// build the closure that we're going to wrap the block with
let fn = t.functionExpression(null, params, t.blockStatement(block.body));
fn.shadow = true;
// continuation
this.addContinuations(fn);
// replace the current block body with the one we're going to build
block.body = this.body;
let ref = fn;
if (this.loop) {
ref = this.scope.generateUidIdentifier("loop");
this.loopPath.insertBefore(t.variableDeclaration("var", [
t.variableDeclarator(ref, fn)
]));
}
// build a call and a unique id that we can assign the return value to
let call = t.callExpression(ref, args);
let ret = this.scope.generateUidIdentifier("ret");
// handle generators
let hasYield = traverse.hasType(fn.body, this.scope, "YieldExpression", t.FUNCTION_TYPES);
if (hasYield) {
fn.generator = true;
call = t.yieldExpression(call, true);
}
// handlers async functions
let hasAsync = traverse.hasType(fn.body, this.scope, "AwaitExpression", t.FUNCTION_TYPES);
if (hasAsync) {
fn.async = true;
call = t.awaitExpression(call);
}
this.buildClosure(ret, call);
}
/**
* Push the closure to the body.
*/
buildClosure(ret: { type: "Identifier" }, call: { type: "CallExpression" }) {
let has = this.has;
if (has.hasReturn || has.hasBreakContinue) {
this.buildHas(ret, call);
} else {
this.body.push(t.expressionStatement(call));
}
}
/**
* If any of the outer let variables are reassigned then we need to rename them in
* the closure so we can get direct access to the outer variable to continue the
* iteration with bindings based on each iteration.
*
* Reference: https://github.com/babel/babel/issues/1078
*/
addContinuations(fn) {
let state = {
reassignments: {},
outsideReferences: this.outsideLetReferences
};
this.scope.traverse(fn, continuationVisitor, state);
for (let i = 0; i < fn.params.length; i++) {
let param = fn.params[i];
if (!state.reassignments[param.name]) continue;
let newParam = this.scope.generateUidIdentifier(param.name);
fn.params[i] = newParam;
this.scope.rename(param.name, newParam.name, fn);
// assign outer reference as it's been modified internally and needs to be retained
fn.body.body.push(t.expressionStatement(t.assignmentExpression("=", param, newParam)));
}
}
getLetReferences() {
let block = this.block;
let declarators = block._letDeclarators || [];
//
for (let i = 0; i < declarators.length; i++) {
let declar = declarators[i];
extend(this.outsideLetReferences, t.getBindingIdentifiers(declar));
}
//
if (block.body) {
for (let i = 0; i < block.body.length; i++) {
let declar = block.body[i];
if (isLet(declar, block, this.scope)) {
declarators = declarators.concat(declar.declarations);
}
}
}
//
for (let i = 0; i < declarators.length; i++) {
let declar = declarators[i];
let keys = t.getBindingIdentifiers(declar);
extend(this.letReferences, keys);
this.hasLetReferences = true;
}
// no let references so we can just quit
if (!this.hasLetReferences) return;
// set let references to plain let references
standardizeLets(declarators);
let state = {
letReferences: this.letReferences,
closurify: false,
file: this.file
};
// traverse through this block, stopping on functions and checking if they
// contain any local let references
this.blockPath.traverse(letReferenceBlockVisitor, state);
return state.closurify;
}
/**
* If we're inside of a loop then traverse it and check if it has one of
* the following node types `ReturnStatement`, `BreakStatement`,
* `ContinueStatement` and replace it with a return value that we can track
* later on.
*/
checkLoop(): Object {
let state = {
hasBreakContinue: false,
ignoreLabeless: false,
inSwitchCase: false,
innerLabels: [],
hasReturn: false,
isLoop: !!this.loop,
map: {}
};
this.blockPath.traverse(loopLabelVisitor, state);
this.blockPath.traverse(loopVisitor, state);
return state;
}
/**
* Hoist all let declarations in this block to before it so they retain scope
* once we wrap everything in a closure.
*/
hoistVarDeclarations() {
this.blockPath.traverse(hoistVarDeclarationsVisitor, this);
}
/**
* Turn a `VariableDeclaration` into an array of `AssignmentExpressions` with
* their declarations hoisted to before the closure wrapper.
*/
pushDeclar(node: { type: "VariableDeclaration" }): Array<Object> {
let declars = [];
let names = t.getBindingIdentifiers(node);
for (let name in names) {
declars.push(t.variableDeclarator(names[name]));
}
this.body.push(t.variableDeclaration(node.kind, declars));
let replace = [];
for (let i = 0; i < node.declarations.length; i++) {
let declar = node.declarations[i];
if (!declar.init) continue;
let expr = t.assignmentExpression("=", declar.id, declar.init);
replace.push(t.inherits(expr, declar));
}
return replace;
}
buildHas(ret: { type: "Identifier" }, call: { type: "CallExpression" }) {
let body = this.body;
body.push(t.variableDeclaration("var", [
t.variableDeclarator(ret, call)
]));
let retCheck;
let has = this.has;
let cases = [];
if (has.hasReturn) {
// typeof ret === "object"
retCheck = util.template("let-scoping-return", {
RETURN: ret
});
}
if (has.hasBreakContinue) {
for (let key in has.map) {
cases.push(t.switchCase(t.stringLiteral(key), [has.map[key]]));
}
if (has.hasReturn) {
cases.push(t.switchCase(null, [retCheck]));
}
if (cases.length === 1) {
let single = cases[0];
body.push(this.file.attachAuxiliaryComment(t.ifStatement(
t.binaryExpression("===", ret, single.test),
single.consequent[0]
)));
} else {
// https://github.com/babel/babel/issues/998
for (let i = 0; i < cases.length; i++) {
let caseConsequent = cases[i].consequent[0];
if (t.isBreakStatement(caseConsequent) && !caseConsequent.label) {
caseConsequent.label = this.loopLabel = this.loopLabel || this.file.scope.generateUidIdentifier("loop");
}
}
body.push(this.file.attachAuxiliaryComment(t.switchStatement(ret, cases)));
}
} else {
if (has.hasReturn) {
body.push(this.file.attachAuxiliaryComment(retCheck));
}
}
}
}

Some files were not shown because too many files have changed in this diff Show More