6.0.0
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:
@@ -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)) {
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
/* @flow */
|
||||
|
||||
import path from "path";
|
||||
import fs from "fs";
|
||||
import homeOrTmp from "home-or-tmp";
|
||||
|
||||
@@ -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);
|
||||
|
||||
24
packages/babel-core/src/helpers/resolve.js
Normal file
24
packages/babel-core/src/helpers/resolve.js
Normal 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;
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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))
|
||||
));
|
||||
});
|
||||
}
|
||||
|
||||
@@ -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 };
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
@@ -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"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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];
|
||||
|
||||
@@ -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];
|
||||
});
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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])
|
||||
);
|
||||
}
|
||||
@@ -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;
|
||||
};
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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
|
||||
};
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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("");
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -1,6 +0,0 @@
|
||||
/* @flow */
|
||||
|
||||
import AMDFormatter from "./amd";
|
||||
import buildStrict from "./_strict";
|
||||
|
||||
export default buildStrict(AMDFormatter);
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -1,6 +0,0 @@
|
||||
/* @flow */
|
||||
|
||||
import CommonFormatter from "./common";
|
||||
import buildStrict from "./_strict";
|
||||
|
||||
export default buildStrict(CommonFormatter);
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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() {}
|
||||
}
|
||||
@@ -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")
|
||||
};
|
||||
@@ -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 = [];
|
||||
}
|
||||
}
|
||||
@@ -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];
|
||||
}
|
||||
}
|
||||
@@ -1,6 +0,0 @@
|
||||
/* @flow */
|
||||
|
||||
import UMDFormatter from "./umd";
|
||||
import buildStrict from "./_strict";
|
||||
|
||||
export default buildStrict(UMDFormatter);
|
||||
@@ -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])
|
||||
)];
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
|
||||
@@ -1,4 +0,0 @@
|
||||
{
|
||||
"blacklist": ["useStrict", "es6.blockScoping", "regenerator", "es6.spread"],
|
||||
"loose": ["es6.modules"]
|
||||
}
|
||||
@@ -1 +0,0 @@
|
||||
PROPERTY[Symbol.referenceGet](OBJECT).call(OBJECT)
|
||||
@@ -1 +0,0 @@
|
||||
PROPERTY[Symbol.referenceDelete](OBJECT)
|
||||
@@ -1 +0,0 @@
|
||||
PROPERTY[Symbol.referenceGet](OBJECT)
|
||||
@@ -1 +0,0 @@
|
||||
PROPERTY[Symbol.referenceSet](OBJECT, VALUE)
|
||||
@@ -1 +0,0 @@
|
||||
Array.from(VALUE);
|
||||
@@ -1 +0,0 @@
|
||||
OBJECT.call(CONTEXT);
|
||||
@@ -1 +0,0 @@
|
||||
exports.KEY = VALUE;
|
||||
@@ -1 +0,0 @@
|
||||
module.exports = VALUE;
|
||||
@@ -1,6 +0,0 @@
|
||||
Object.defineProperty(exports, ID, {
|
||||
enumerable: true,
|
||||
get: function () {
|
||||
return INIT;
|
||||
}
|
||||
});
|
||||
@@ -1 +0,0 @@
|
||||
exports.__esModule = true;
|
||||
@@ -1,3 +0,0 @@
|
||||
Object.defineProperty(exports, "__esModule", {
|
||||
value: true
|
||||
});
|
||||
@@ -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();
|
||||
});
|
||||
};
|
||||
})
|
||||
@@ -1 +0,0 @@
|
||||
Function.prototype.bind
|
||||
@@ -1,5 +0,0 @@
|
||||
(function (instance, Constructor) {
|
||||
if (!(instance instanceof Constructor)) {
|
||||
throw new TypeError("Cannot call a class as a function");
|
||||
}
|
||||
});
|
||||
@@ -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;
|
||||
};
|
||||
})()
|
||||
@@ -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;
|
||||
};
|
||||
})()
|
||||
@@ -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;
|
||||
})
|
||||
@@ -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;
|
||||
})
|
||||
@@ -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;
|
||||
})
|
||||
@@ -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);
|
||||
})
|
||||
@@ -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;
|
||||
});
|
||||
@@ -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;
|
||||
})
|
||||
@@ -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);
|
||||
}
|
||||
});
|
||||
@@ -1 +0,0 @@
|
||||
Object.prototype.hasOwnProperty;
|
||||
@@ -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;
|
||||
})
|
||||
@@ -1,7 +0,0 @@
|
||||
(function (left, right) {
|
||||
if (right != null && right[Symbol.hasInstance]) {
|
||||
return right[Symbol.hasInstance](left);
|
||||
} else {
|
||||
return left instanceof right;
|
||||
}
|
||||
});
|
||||
@@ -1,5 +0,0 @@
|
||||
(function (obj, defaults) {
|
||||
var newObj = defaults({}, obj);
|
||||
delete newObj.default;
|
||||
return newObj;
|
||||
})
|
||||
@@ -1,3 +0,0 @@
|
||||
(function (obj) {
|
||||
return obj && obj.__esModule ? obj : { default: obj };
|
||||
})
|
||||
@@ -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;
|
||||
}
|
||||
})
|
||||
@@ -1,3 +0,0 @@
|
||||
(function (obj) {
|
||||
return obj && obj.__esModule ? obj.default : obj;
|
||||
})
|
||||
@@ -1,5 +0,0 @@
|
||||
(function (innerThis, boundThis) {
|
||||
if (innerThis !== boundThis) {
|
||||
throw new TypeError("Cannot instantiate an arrow function");
|
||||
}
|
||||
});
|
||||
@@ -1,3 +0,0 @@
|
||||
(function (obj) {
|
||||
if (obj == null) throw new TypeError("Cannot destructure undefined");
|
||||
});
|
||||
@@ -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;
|
||||
})
|
||||
@@ -1 +0,0 @@
|
||||
typeof global === "undefined" ? self : global
|
||||
@@ -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;
|
||||
});
|
||||
@@ -1 +0,0 @@
|
||||
Array.prototype.slice;
|
||||
@@ -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");
|
||||
}
|
||||
});
|
||||
@@ -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");
|
||||
}
|
||||
};
|
||||
})();
|
||||
@@ -1,4 +0,0 @@
|
||||
(function (strings, raw) {
|
||||
strings.raw = raw;
|
||||
return strings;
|
||||
});
|
||||
@@ -1,5 +0,0 @@
|
||||
(function (strings, raw) {
|
||||
return Object.freeze(Object.defineProperties(strings, {
|
||||
raw: { value: Object.freeze(raw) }
|
||||
}));
|
||||
});
|
||||
@@ -1,6 +0,0 @@
|
||||
(function (val, name, undef) {
|
||||
if (val === undef) {
|
||||
throw new ReferenceError(name + " is not defined - temporal dead zone");
|
||||
}
|
||||
return true;
|
||||
})
|
||||
@@ -1 +0,0 @@
|
||||
({})
|
||||
@@ -1,3 +0,0 @@
|
||||
(function (arr) {
|
||||
return Array.isArray(arr) ? arr : Array.from(arr);
|
||||
});
|
||||
@@ -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);
|
||||
}
|
||||
});
|
||||
@@ -1,3 +0,0 @@
|
||||
(function (obj) {
|
||||
return obj && obj.constructor === Symbol ? "symbol" : typeof obj;
|
||||
});
|
||||
@@ -1,7 +0,0 @@
|
||||
(function () {
|
||||
function GET_OUTER_ID() {
|
||||
return FUNCTION_ID;
|
||||
}
|
||||
|
||||
return FUNCTION;
|
||||
})()
|
||||
@@ -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)
|
||||
@@ -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)
|
||||
@@ -1 +0,0 @@
|
||||
CLASS_NAME.prototype
|
||||
@@ -1 +0,0 @@
|
||||
var VARIABLE_NAME = require(MODULE_NAME).KEY;
|
||||
@@ -1 +0,0 @@
|
||||
require(MODULE_NAME);
|
||||
@@ -1,2 +0,0 @@
|
||||
exports.default = HELPER;
|
||||
exports.__esModule = true;
|
||||
@@ -1,6 +0,0 @@
|
||||
System.register(MODULE_NAME, MODULE_DEPENDENCIES, function (EXPORT_IDENTIFIER) {
|
||||
return {
|
||||
setters: SETTERS,
|
||||
execute: EXECUTE
|
||||
};
|
||||
});
|
||||
@@ -1 +0,0 @@
|
||||
typeof exports !== "undefined"
|
||||
@@ -1 +0,0 @@
|
||||
typeof module !== "undefined"
|
||||
@@ -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
|
||||
});
|
||||
@@ -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;
|
||||
}
|
||||
});
|
||||
@@ -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)]
|
||||
);
|
||||
}
|
||||
};
|
||||
@@ -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
Reference in New Issue
Block a user