Merge pull request #1897 from babel/code-docs

Code docs
This commit is contained in:
Sebastian McKenzie 2015-07-11 22:56:24 +01:00
commit ef275da1c2
169 changed files with 4066 additions and 219 deletions

27
src/README.md Normal file
View File

@ -0,0 +1,27 @@
## Welcome to the Babel Codebase
Babel is broken down into three parts:
- Parsing
- Transformation
- Generation
**Parsing** is the process of turning a piece of code into an AST (Abstract
Syntax Tree) which is a tree-like object of nodes that _describes_ the code.
This makes it easier to transform the code over direct string manpulation.
**Transformation** is the process of taking an AST and manipulating it into
a new one. For example, Babel might take an ES2015 ArrowFunction and transform
it into a normal Function which will work in ES5 environments.
**Generation** is the process of turning an AST back into code. After Babel is
done transforming the AST, the generation takes over to return normal code.
---
Babel's parsing step is done by Acorn. However, because Babel is implementing
future standards it maintains a fork of Acorn in order to do it's job. You can
see that fork in the "acorn" folder.
The transformation and generation steps are both handled inside of the Babel
codebase itself, which is in the "babel" folder here.

4
src/babel/README.md Normal file
View File

@ -0,0 +1,4 @@
## Diving into Babel
If you look around in the various directories in here you'll find some details
about the organization of the Babel codebase.

18
src/babel/api/README.md Normal file
View File

@ -0,0 +1,18 @@
## API
In this directory you'll find all the public interfaces to using Babel for both
node and the browser.
### Node
There are two ways people use Babel within Node, they either are manipulating
strings of code with `babel.transform` or `babel.parse`, they also might be
running their code through Babel before execution via `register` or `polyfill`.
### Browser
Usage of Babel in the browser is extremely uncommon and in most cases
considered A Bad Idea™. However it works by loading `<script>`'s with XHR,
transforming them and then executing them. These `<script>`'s need to have a
`type` of "text/ecmascript-6", "text/babel", or "module" ("text/6to5" exists as
well for legacy reasons).

View File

@ -3,16 +3,32 @@
require("./node");
var transform = module.exports = require("../transformation");
/**
* Add `options` and `version` to `babel` global.
*/
transform.options = require("../transformation/file/options");
transform.version = require("../../../package").version;
/**
* Add `transform` api to `babel` global.
*/
transform.transform = transform;
/**
* Tranform and execute script, adding in inline sourcemaps.
*/
transform.run = function (code, opts = {}) {
opts.sourceMaps = "inline";
return new Function(transform(code, opts).code)();
};
/**
* Load scripts via xhr, and `transform` when complete (optional).
*/
transform.load = function (url, callback, opts = {}, hold) {
opts.filename = opts.filename || url;
@ -20,6 +36,10 @@ transform.load = function (url, callback, opts = {}, hold) {
xhr.open("GET", url, true);
if ("overrideMimeType" in xhr) xhr.overrideMimeType("text/plain");
/**
* When successfully loaded, transform (optional), and call `callback`.
*/
xhr.onreadystatechange = function () {
if (xhr.readyState !== 4) return;
@ -36,11 +56,22 @@ transform.load = function (url, callback, opts = {}, hold) {
xhr.send(null);
};
/**
* Load and transform all scripts of `types`.
*
* @example
* <script type="module"></script>
*/
var runScripts = function () {
var scripts = [];
var types = ["text/ecmascript-6", "text/6to5", "text/babel", "module"];
var index = 0;
/**
* Transform and execute script. Ensures correct load order.
*/
var exec = function () {
var param = scripts[index];
if (param instanceof Array) {
@ -50,6 +81,10 @@ var runScripts = function () {
}
};
/**
* Load, transform, and execute all scripts.
*/
var run = function (script, i) {
var opts = {};
@ -64,7 +99,9 @@ var runScripts = function () {
}
};
var _scripts = global.document .getElementsByTagName("script");
// Collect scripts with Babel `types`.
var _scripts = global.document.getElementsByTagName("script");
for (var i = 0; i < _scripts.length; ++i) {
var _script = _scripts[i];
@ -78,6 +115,10 @@ var runScripts = function () {
exec();
};
/**
* Register load event to transform and execute scripts.
*/
if (global.addEventListener) {
global.addEventListener("DOMContentLoaded", runScripts, false);
} else if (global.attachEvent) {

View File

@ -19,16 +19,28 @@ export { version } from "../../../package";
import * as t from "../types";
export { t as types };
/**
* Register Babel and polyfill globally.
*/
export function register(opts?: Object) {
var callback = require("./register/node-polyfill");
if (opts != null) callback(opts);
return callback;
}
/**
* Register polyfill globally.
*/
export function polyfill() {
require("../polyfill");
}
/**
* Asynchronously transform `filename` with optional `opts`, calls `callback` when complete.
*/
export function transformFile(filename: string, opts?: Object, callback: Function) {
if (isFunction(opts)) {
callback = opts;
@ -52,11 +64,19 @@ export function transformFile(filename: string, opts?: Object, callback: Functio
});
}
/**
* Synchronous form of `transformFile`.
*/
export function transformFileSync(filename: string, opts?: Object = {}) {
opts.filename = filename;
return transform(fs.readFileSync(filename, "utf8"), opts);
}
/**
* Parse script with Babel's parser.
*/
export function parse(code, opts = {}) {
opts.allowHashBang = true;
opts.sourceType = "module";

View File

@ -6,10 +6,18 @@ import pathExists from "path-exists";
const FILENAME = process.env.BABEL_CACHE_PATH || path.join(homeOrTmp, ".babel.json");
var data = {};
/**
* Write stringified cache to disk.
*/
export function save() {
fs.writeFileSync(FILENAME, JSON.stringify(data, null, " "));
}
/**
* Load cache from disk and parse.
*/
export function load() {
if (process.env.BABEL_DISABLE_CACHE) return;
@ -25,6 +33,10 @@ export function load() {
}
}
/**
* Retrieve data from cache.
*/
export function get() {
return data;
}

View File

@ -8,6 +8,10 @@ import * as util from "../../util";
import fs from "fs";
import path from "path";
/**
* Install sourcemaps into node.
*/
sourceMapSupport.install({
handleUncaughtExceptions: false,
retrieveSourceMap(source) {
@ -23,12 +27,16 @@ sourceMapSupport.install({
}
});
//
/**
* Load and setup cache.
*/
registerCache.load();
var cache = registerCache.get();
//
/**
* Store options.
*/
var transformOpts = {};
@ -40,14 +48,26 @@ var maps = {};
var cwd = process.cwd();
/**
* Get path from `filename` relative to the current working directory.
*/
var getRelativePath = function (filename){
return path.relative(cwd, filename);
};
/**
* Get last modified time for a `filename`.
*/
var mtime = function (filename) {
return +fs.statSync(filename).mtime;
};
/**
* Compile a `filename` with optional `opts`.
*/
var compile = function (filename, opts = {}) {
var result;
@ -84,6 +104,10 @@ var compile = function (filename, opts = {}) {
return result.code;
};
/**
* Test if a `filename` should be ignored by Babel.
*/
var shouldIgnore = function (filename) {
if (!ignore && !only) {
return getRelativePath(filename).split(path.sep).indexOf("node_modules") >= 0;
@ -92,6 +116,10 @@ var shouldIgnore = function (filename) {
}
};
/**
* Monkey patch istanbul if it is running so that it works properly.
*/
var istanbulMonkey = {};
if (process.env.running_under_istanbul) {
@ -113,15 +141,27 @@ if (process.env.running_under_istanbul) {
};
}
/**
* Replacement for the loader for istanbul.
*/
var istanbulLoader = function (m, filename, old) {
istanbulMonkey[filename] = true;
old(m, filename);
};
/**
* Default loader.
*/
var normalLoader = function (m, filename) {
m._compile(compile(filename), filename);
};
/**
* Register a loader for an extension.
*/
var registerExtension = function (ext) {
var old = oldHandlers[ext] || oldHandlers[".js"] || require.extensions[".js"];
@ -137,6 +177,10 @@ var registerExtension = function (ext) {
};
};
/**
* Register loader for given extensions.
*/
var hookExtensions = function (_exts) {
each(oldHandlers, function (old, ext) {
if (old === undefined) {
@ -154,8 +198,16 @@ var hookExtensions = function (_exts) {
});
};
/**
* Register loader for default extensions.
*/
hookExtensions(util.canCompile.EXTENSIONS);
/**
* Update options at runtime.
*/
export default function (opts = {}) {
if (opts.only != null) only = util.arrayify(opts.only, util.regexify);
if (opts.ignore != null) ignore = util.arrayify(opts.ignore, util.regexify);

View File

@ -0,0 +1,16 @@
## Generation
Here is Babel's code generator, here you'll find all of the code to turn an AST
back into a string of code.
[TBD: To Be Documented:]
- Code Generator
- Buffer
- Source Maps
- Position
- Printer
- Code Style
- Whitespace
- Parenthesis
- Generators

View File

@ -4,6 +4,10 @@ import isBoolean from "lodash/lang/isBoolean";
import includes from "lodash/collection/includes";
import isNumber from "lodash/lang/isNumber";
/**
* Buffer for collecting generated output.
*/
export default class Buffer {
constructor(position, format) {
this.position = position;
@ -12,10 +16,18 @@ export default class Buffer {
this.buf = "";
}
/**
* Get the current trimmed buffer.
*/
get() {
return trimRight(this.buf);
}
/**
* Get the current indent.
*/
getIndent() {
if (this.format.compact || this.format.concise) {
return "";
@ -24,36 +36,68 @@ export default class Buffer {
}
}
/**
* Get the current indent size.
*/
indentSize() {
return this.getIndent().length;
}
/**
* Increment indent size.
*/
indent() {
this._indent++;
}
/**
* Decrement indent size.
*/
dedent() {
this._indent--;
}
/**
* Add a semicolon to the buffer.
*/
semicolon() {
this.push(";");
}
/**
* Ensure last character is a semicolon.
*/
ensureSemicolon() {
if (!this.isLast(";")) this.semicolon();
}
/**
* Add a right brace to the buffer.
*/
rightBrace() {
this.newline(true);
this.push("}");
}
/**
* Add a keyword to the buffer.
*/
keyword(name) {
this.push(name);
this.space();
}
/**
* Add a space to the buffer unless it is compact (override with force).
*/
space(force?) {
if (!force && this.format.compact) return;
@ -62,6 +106,10 @@ export default class Buffer {
}
}
/**
* Remove the last character.
*/
removeLast(cha) {
if (this.format.compact) return;
if (!this.isLast(cha)) return;
@ -70,6 +118,11 @@ export default class Buffer {
this.position.unshift(cha);
}
/**
* Add a newline (or many newlines), maintaining formatting.
* Strips multiple newlines if removeLast is true.
*/
newline(i, removeLast) {
if (this.format.compact || this.format.retainLines) return;
@ -100,6 +153,10 @@ export default class Buffer {
this._newline(removeLast);
}
/**
* Adds a newline unless there is already two previous newlines.
*/
_newline(removeLast) {
// never allow more than two lines
if (this.endsWith("\n\n")) return;
@ -136,6 +193,10 @@ export default class Buffer {
}
}
/**
* Push a string to the buffer, maintaining indentation and newlines.
*/
push(str, noIndent) {
if (!this.format.compact && this._indent && !noIndent && str !== "\n") {
// we have an indent level and we aren't pushing a newline
@ -151,11 +212,19 @@ export default class Buffer {
this._push(str);
}
/**
* Push a string to the buffer.
*/
_push(str) {
this.position.push(str);
this.buf += str;
}
/**
* Test if the buffer ends with a string.
*/
endsWith(str, buf = this.buf) {
if (str.length === 1) {
return buf[buf.length - 1] === str;
@ -164,6 +233,10 @@ export default class Buffer {
}
}
/**
* Test if a character is last in the buffer.
*/
isLast(cha) {
if (this.format.compact) return false;

View File

@ -0,0 +1,10 @@
## Generators
Code generation in Babel is broken down into generators by node type, they all
live in this directory.
[TBD: To Be Documented:]
- How generators work
- How to print a node
- How generators related to one another

View File

@ -1,11 +1,23 @@
/**
* Print File.program
*/
export function File(node, print) {
print.plain(node.program);
}
/**
* Print all nodes in a Program.body.
*/
export function Program(node, print) {
print.sequence(node.body);
}
/**
* Print BlockStatement, collapses empty blocks, prints body.
*/
export function BlockStatement(node, print) {
if (node.body.length === 0) {
this.push("{}");
@ -18,6 +30,13 @@ export function BlockStatement(node, print) {
}
}
/**
* What is my purpose?
* Why am I here?
* Why are any of us here?
* Does any of this really matter?
*/
export function Noop() {
}

View File

@ -1,3 +1,7 @@
/**
* Print ClassDeclaration, prints decorators, typeParameters, extends, implements, and body.
*/
export function ClassDeclaration(node, print) {
print.list(node.decorators, { separator: "" });
this.push("class");
@ -24,8 +28,16 @@ export function ClassDeclaration(node, print) {
print.plain(node.body);
}
/**
* Alias ClassDeclaration printer as ClassExpression.
*/
export { ClassDeclaration as ClassExpression };
/**
* Print ClassBody, collapses empty blocks, prints body.
*/
export function ClassBody(node, print) {
if (node.body.length === 0) {
this.push("{}");
@ -41,6 +53,10 @@ export function ClassBody(node, print) {
}
}
/**
* Print ClassProperty, prints decorators, static, key, typeAnnotation, and value.
* Also: semicolons, deal with it.
*/
export function ClassProperty(node, print) {
print.list(node.decorators, { separator: "" });
@ -57,6 +73,10 @@ export function ClassProperty(node, print) {
this.semicolon();
}
/**
* Print MethodDefinition, prints decorations, static, and method.
*/
export function MethodDefinition(node, print) {
print.list(node.decorators, { separator: "" });

View File

@ -1,3 +1,7 @@
/**
* Prints ComprehensionBlock, prints left and right.
*/
export function ComprehensionBlock(node, print) {
this.keyword("for");
this.push("(");
@ -7,6 +11,10 @@ export function ComprehensionBlock(node, print) {
this.push(")");
}
/**
* Prints ComprehensionExpression, prints blocks, filter, and body. Handles generators.
*/
export function ComprehensionExpression(node, print) {
this.push(node.generator ? "(" : "[");

View File

@ -1,6 +1,10 @@
import isNumber from "lodash/lang/isNumber";
import * as t from "../../types";
/**
* Prints UnaryExpression, prints operator and argument.
*/
export function UnaryExpression(node, print) {
var needsSpace = /[a-z]$/.test(node.operator);
var arg = node.argument;
@ -18,18 +22,30 @@ export function UnaryExpression(node, print) {
print.plain(node.argument);
}
/**
* Prints DoExpression, prints body.
*/
export function DoExpression(node, print) {
this.push("do");
this.space();
print.plain(node.body);
}
/**
* Prints ParenthesizedExpression, prints expression.
*/
export function ParenthesizedExpression(node, print) {
this.push("(");
print.plain(node.expression);
this.push(")");
}
/**
* Prints UpdateExpression, prints operator and argument.
*/
export function UpdateExpression(node, print) {
if (node.prefix) {
this.push(node.operator);
@ -40,6 +56,10 @@ export function UpdateExpression(node, print) {
}
}
/**
* Prints ConditionalExpression, prints test, consequent, and alternate.
*/
export function ConditionalExpression(node, print) {
print.plain(node.test);
this.space();
@ -52,6 +72,10 @@ export function ConditionalExpression(node, print) {
print.plain(node.alternate);
}
/**
* Prints NewExpression, prints callee and arguments.
*/
export function NewExpression(node, print) {
this.push("new ");
print.plain(node.callee);
@ -60,24 +84,44 @@ export function NewExpression(node, print) {
this.push(")");
}
/**
* Prints SequenceExpression.expressions.
*/
export function SequenceExpression(node, print) {
print.list(node.expressions);
}
/**
* Prints ThisExpression.
*/
export function ThisExpression() {
this.push("this");
}
/**
* Prints Super.
*/
export function Super() {
this.push("super");
}
/**
* Prints Decorator, prints expression.
*/
export function Decorator(node, print) {
this.push("@");
print.plain(node.expression);
this.newline();
}
/**
* Prints CallExpression, prints callee and arguments.
*/
export function CallExpression(node, print) {
print.plain(node.callee);
@ -102,6 +146,11 @@ export function CallExpression(node, print) {
this.push(")");
}
/**
* Builds yield or await expression printer.
* Prints delegate, all, and argument.
*/
var buildYieldAwait = function (keyword) {
return function (node, print) {
this.push(keyword);
@ -117,24 +166,44 @@ var buildYieldAwait = function (keyword) {
};
};
/**
* Create YieldExpression and AwaitExpression printers.
*/
export var YieldExpression = buildYieldAwait("yield");
export var AwaitExpression = buildYieldAwait("await");
/**
* Prints EmptyStatement.
*/
export function EmptyStatement() {
this.semicolon();
}
/**
* Prints ExpressionStatement, prints expression.
*/
export function ExpressionStatement(node, print) {
print.plain(node.expression);
this.semicolon();
}
/**
* Prints AssignmentPattern, prints left and right.
*/
export function AssignmentPattern(node, print) {
print.plain(node.left);
this.push(" = ");
print.plain(node.right);
}
/**
* Prints AssignmentExpression, prints left, operator, and right.
*/
export function AssignmentExpression(node, print) {
// todo: add cases where the spaces can be dropped when in compact mode
print.plain(node.left);
@ -158,17 +227,30 @@ export function AssignmentExpression(node, print) {
print.plain(node.right);
}
/**
* Prints BindExpression, prints object and callee.
*/
export function BindExpression(node, print) {
print.plain(node.object);
this.push("::");
print.plain(node.callee);
}
/**
* Alias ClassDeclaration printer as ClassExpression,
* and AssignmentExpression printer as LogicalExpression.
*/
export {
AssignmentExpression as BinaryExpression,
AssignmentExpression as LogicalExpression
};
/**
* Print MemberExpression, prints object, property, and value. Handles computed.
*/
export function MemberExpression(node, print) {
var obj = node.object;
print.plain(obj);
@ -192,6 +274,10 @@ export function MemberExpression(node, print) {
}
}
/**
* Print MetaProperty, prints meta and property.
*/
export function MetaProperty(node, print) {
print.plain(node.meta);
this.push(".");

View File

@ -1,24 +1,44 @@
import * as t from "../../types";
/**
* Prints AnyTypeAnnotation.
*/
export function AnyTypeAnnotation() {
this.push("any");
}
/**
* Prints ArrayTypeAnnotation, prints elementType.
*/
export function ArrayTypeAnnotation(node, print) {
print.plain(node.elementType);
this.push("[");
this.push("]");
}
/**
* Prints BooleanTypeAnnotation.
*/
export function BooleanTypeAnnotation(node) {
this.push("bool");
}
/**
* Prints DeclareClass, prints node.
*/
export function DeclareClass(node, print) {
this.push("declare class ");
this._interfaceish(node, print);
}
/**
* Prints DeclareFunction, prints id and id.typeAnnotation.
*/
export function DeclareFunction(node, print) {
this.push("declare function ");
print.plain(node.id);
@ -26,6 +46,10 @@ export function DeclareFunction(node, print) {
this.semicolon();
}
/**
* Prints DeclareModule, prints id and body.
*/
export function DeclareModule(node, print) {
this.push("declare module ");
print.plain(node.id);
@ -33,6 +57,10 @@ export function DeclareModule(node, print) {
print.plain(node.body);
}
/**
* Prints DeclareVariable, prints id and id.typeAnnotation.
*/
export function DeclareVariable(node, print) {
this.push("declare var ");
print.plain(node.id);
@ -40,6 +68,10 @@ export function DeclareVariable(node, print) {
this.semicolon();
}
/**
* Prints FunctionTypeAnnotation, prints typeParameters, params, and rest.
*/
export function FunctionTypeAnnotation(node, print, parent) {
print.plain(node.typeParameters);
this.push("(");
@ -68,6 +100,10 @@ export function FunctionTypeAnnotation(node, print, parent) {
print.plain(node.returnType);
}
/**
* Prints FunctionTypeParam, prints name and typeAnnotation, handles optional.
*/
export function FunctionTypeParam(node, print) {
print.plain(node.name);
if (node.optional) this.push("?");
@ -76,13 +112,26 @@ export function FunctionTypeParam(node, print) {
print.plain(node.typeAnnotation);
}
/**
* Prints InterfaceExtends, prints id and typeParameters.
*/
export function InterfaceExtends(node, print) {
print.plain(node.id);
print.plain(node.typeParameters);
}
/**
* Alias InterfaceExtends printer as ClassImplements,
* and InterfaceExtends printer as GenericTypeAnnotation.
*/
export { InterfaceExtends as ClassImplements, InterfaceExtends as GenericTypeAnnotation };
/**
* Prints interface-like node, prints id, typeParameters, extends, and body.
*/
export function _interfaceish(node, print) {
print.plain(node.id);
print.plain(node.typeParameters);
@ -94,47 +143,87 @@ export function _interfaceish(node, print) {
print.plain(node.body);
}
/**
* Prints InterfaceDeclaration, prints node.
*/
export function InterfaceDeclaration(node, print) {
this.push("interface ");
this._interfaceish(node, print);
}
/**
* Prints IntersectionTypeAnnotation, prints types.
*/
export function IntersectionTypeAnnotation(node, print) {
print.join(node.types, { separator: " & " });
}
/**
* Prints MixedTypeAnnotation.
*/
export function MixedTypeAnnotation() {
this.push("mixed");
}
/**
* Prints NullableTypeAnnotation, prints typeAnnotation.
*/
export function NullableTypeAnnotation(node, print) {
this.push("?");
print.plain(node.typeAnnotation);
}
/**
* Prints NumberTypeAnnotation.
*/
export function NumberTypeAnnotation() {
this.push("number");
}
/**
* Prints StringLiteralTypeAnnotation, prints value.
*/
export function StringLiteralTypeAnnotation(node) {
this._stringLiteral(node.value);
}
/**
* Prints StringTypeAnnotation.
*/
export function StringTypeAnnotation() {
this.push("string");
}
/**
* Prints TupleTypeAnnotation, prints types.
*/
export function TupleTypeAnnotation(node, print) {
this.push("[");
print.join(node.types, { separator: ", " });
this.push("]");
}
/**
* Prints TypeofTypeAnnotation, prints argument.
*/
export function TypeofTypeAnnotation(node, print) {
this.push("typeof ");
print.plain(node.argument);
}
/**
* Prints TypeAlias, prints id, typeParameters, and right.
*/
export function TypeAlias(node, print) {
this.push("type ");
print.plain(node.id);
@ -146,6 +235,10 @@ export function TypeAlias(node, print) {
this.semicolon();
}
/**
* Prints TypeAnnotation, prints typeAnnotation, handles optional.
*/
export function TypeAnnotation(node, print) {
this.push(":");
this.space();
@ -153,14 +246,26 @@ export function TypeAnnotation(node, print) {
print.plain(node.typeAnnotation);
}
/**
* Prints TypeParameterInstantiation, prints params.
*/
export function TypeParameterInstantiation(node, print) {
this.push("<");
print.join(node.params, { separator: ", " });
this.push(">");
}
/**
* Alias TypeParameterInstantiation printer as TypeParameterDeclaration
*/
export { TypeParameterInstantiation as TypeParameterDeclaration };
/**
* Prints ObjectTypeAnnotation, prints properties, callProperties, and indexers.
*/
export function ObjectTypeAnnotation(node, print) {
this.push("{");
var props = node.properties.concat(node.callProperties, node.indexers);
@ -185,11 +290,19 @@ export function ObjectTypeAnnotation(node, print) {
this.push("}");
}
/**
* Prints ObjectTypeCallProperty, prints value, handles static.
*/
export function ObjectTypeCallProperty(node, print) {
if (node.static) this.push("static ");
print.plain(node.value);
}
/**
* Prints ObjectTypeIndexer, prints id, key, and value, handles static.
*/
export function ObjectTypeIndexer(node, print) {
if (node.static) this.push("static ");
this.push("[");
@ -203,6 +316,10 @@ export function ObjectTypeIndexer(node, print) {
print.plain(node.value);
}
/**
* Prints ObjectTypeProperty, prints static, key, and value.
*/
export function ObjectTypeProperty(node, print) {
if (node.static) this.push("static ");
print.plain(node.key);
@ -214,16 +331,28 @@ export function ObjectTypeProperty(node, print) {
print.plain(node.value);
}
/**
* Prints QualifiedTypeIdentifier, prints qualification and id.
*/
export function QualifiedTypeIdentifier(node, print) {
print.plain(node.qualification);
this.push(".");
print.plain(node.id);
}
/**
* Prints UnionTypeAnnotation, prints types.
*/
export function UnionTypeAnnotation(node, print) {
print.join(node.types, { separator: " | " });
}
/**
* Prints TypeCastExpression, prints expression and typeAnnotation.
*/
export function TypeCastExpression(node, print) {
this.push("(");
print.plain(node.expression);
@ -231,6 +360,10 @@ export function TypeCastExpression(node, print) {
this.push(")");
}
/**
* Prints VoidTypeAnnotation.
*/
export function VoidTypeAnnotation(node) {
this.push("void");
}

View File

@ -1,5 +1,9 @@
import * as t from "../../types";
/**
* Prints JSXAttribute, prints name and value.
*/
export function JSXAttribute(node, print) {
print.plain(node.name);
if (node.value) {
@ -8,34 +12,58 @@ export function JSXAttribute(node, print) {
}
}
/**
* Prints JSXIdentifier, prints name.
*/
export function JSXIdentifier(node) {
this.push(node.name);
}
/**
* Prints JSXNamespacedName, prints namespace and name.
*/
export function JSXNamespacedName(node, print) {
print.plain(node.namespace);
this.push(":");
print.plain(node.name);
}
/**
* Prints JSXMemberExpression, prints object and property.
*/
export function JSXMemberExpression(node, print) {
print.plain(node.object);
this.push(".");
print.plain(node.property);
}
/**
* Prints JSXSpreadAttribute, prints argument.
*/
export function JSXSpreadAttribute(node, print) {
this.push("{...");
print.plain(node.argument);
this.push("}");
}
/**
* Prints JSXExpressionContainer, prints expression.
*/
export function JSXExpressionContainer(node, print) {
this.push("{");
print.plain(node.expression);
this.push("}");
}
/**
* Prints JSXElement, prints openingElement, children, and closingElement.
*/
export function JSXElement(node, print) {
var open = node.openingElement;
print.plain(open);
@ -54,6 +82,10 @@ export function JSXElement(node, print) {
print.plain(node.closingElement);
}
/**
* Prints JSXOpeningElement, prints name and attributes, handles selfClosing.
*/
export function JSXOpeningElement(node, print) {
this.push("<");
print.plain(node.name);
@ -64,10 +96,18 @@ export function JSXOpeningElement(node, print) {
this.push(node.selfClosing ? " />" : ">");
}
/**
* Prints JSXClosingElement, prints name.
*/
export function JSXClosingElement(node, print) {
this.push("</");
print.plain(node.name);
this.push(">");
}
/**
* Prints JSXEmptyExpression.
*/
export function JSXEmptyExpression() {}

View File

@ -1,5 +1,9 @@
import * as t from "../../types";
/**
* Prints nodes with params, prints typeParameters, params, and returnType, handles optional params.
*/
export function _params(node, print) {
print.plain(node.typeParameters);
this.push("(");
@ -16,6 +20,10 @@ export function _params(node, print) {
}
}
/**
* Prints method-like nodes, prints key, value, and body, handles async, generator, computed, and get or set.
*/
export function _method(node, print) {
var value = node.value;
var kind = node.kind;
@ -46,6 +54,10 @@ export function _method(node, print) {
print.plain(value.body);
}
/**
* Prints FunctionExpression, prints id and body, handles async and generator.
*/
export function FunctionExpression(node, print) {
if (node.async) this.push("async ");
this.push("function");
@ -63,8 +75,17 @@ export function FunctionExpression(node, print) {
print.plain(node.body);
}
/**
* Alias FunctionExpression printer as FunctionDeclaration.
*/
export { FunctionExpression as FunctionDeclaration };
/**
* Prints ArrowFunctionExpression, prints params and body, handles async.
* Leaves out parentheses when single param.
*/
export function ArrowFunctionExpression(node, print) {
if (node.async) this.push("async ");

View File

@ -1,5 +1,9 @@
import * as t from "../../types";
/**
* Prints ImportSpecifier, prints imported and local.
*/
export function ImportSpecifier(node, print) {
print.plain(node.imported);
if (node.local && node.local.name !== node.imported.name) {
@ -8,14 +12,26 @@ export function ImportSpecifier(node, print) {
}
}
/**
* Prints ImportDefaultSpecifier, prints local.
*/
export function ImportDefaultSpecifier(node, print) {
print.plain(node.local);
}
/**
* Prints ExportDefaultSpecifier, prints exported.
*/
export function ExportDefaultSpecifier(node, print) {
print.plain(node.exported);
}
/**
* Prints ExportSpecifier, prints local and exported.
*/
export function ExportSpecifier(node, print) {
print.plain(node.local);
if (node.exported && node.local.name !== node.exported.name) {
@ -24,11 +40,19 @@ export function ExportSpecifier(node, print) {
}
}
/**
* Prints ExportNamespaceSpecifier, prints exported.
*/
export function ExportNamespaceSpecifier(node, print) {
this.push("* as ");
print.plain(node.exported);
}
/**
* Prints ExportAllDeclaration, prints exported and source.
*/
export function ExportAllDeclaration(node, print) {
this.push("export *");
if (node.exported) {
@ -40,16 +64,28 @@ export function ExportAllDeclaration(node, print) {
this.semicolon();
}
/**
* Prints ExportNamedDeclaration, delegates to ExportDeclaration.
*/
export function ExportNamedDeclaration(node, print) {
this.push("export ");
ExportDeclaration.call(this, node, print);
}
/**
* Prints ExportDefaultDeclaration, delegates to ExportDeclaration.
*/
export function ExportDefaultDeclaration(node, print) {
this.push("export default ");
ExportDeclaration.call(this, node, print);
}
/**
* Prints ExportDeclaration, prints specifiers, declration, and source.
*/
function ExportDeclaration(node, print) {
var specifiers = node.specifiers;
@ -87,6 +123,10 @@ function ExportDeclaration(node, print) {
this.ensureSemicolon();
}
/**
* Prints ImportDeclaration, prints specifiers and source, handles isType.
*/
export function ImportDeclaration(node, print) {
this.push("import ");
@ -119,6 +159,10 @@ export function ImportDeclaration(node, print) {
this.semicolon();
}
/**
* Prints ImportNamespaceSpecifier, prints local.
*/
export function ImportNamespaceSpecifier(node, print) {
this.push("* as ");
print.plain(node.local);

View File

@ -1,6 +1,10 @@
import repeating from "repeating";
import * as t from "../../types";
/**
* Prints WithStatement, prints object and body.
*/
export function WithStatement(node, print) {
this.keyword("with");
this.push("(");
@ -9,6 +13,10 @@ export function WithStatement(node, print) {
print.block(node.body);
}
/**
* Prints IfStatement, prints test, consequent, and alternate.
*/
export function IfStatement(node, print) {
this.keyword("if");
this.push("(");
@ -25,6 +33,10 @@ export function IfStatement(node, print) {
}
}
/**
* Prints ForStatement, prints init, test, update, and body.
*/
export function ForStatement(node, print) {
this.keyword("for");
this.push("(");
@ -47,6 +59,10 @@ export function ForStatement(node, print) {
print.block(node.body);
}
/**
* Prints WhileStatement, prints test and body.
*/
export function WhileStatement(node, print) {
this.keyword("while");
this.push("(");
@ -55,6 +71,11 @@ export function WhileStatement(node, print) {
print.block(node.body);
}
/**
* Builds ForIn or ForOf statement printers.
* Prints left, right, and body.
*/
var buildForXStatement = function (op) {
return function (node, print) {
this.keyword("for");
@ -67,9 +88,17 @@ var buildForXStatement = function (op) {
};
};
/**
* Create ForInStatement and ForOfStatement printers.
*/
export var ForInStatement = buildForXStatement("in");
export var ForOfStatement = buildForXStatement("of");
/**
* Prints DoWhileStatement, prints body and test.
*/
export function DoWhileStatement(node, print) {
this.push("do ");
print.plain(node.body);
@ -80,6 +109,11 @@ export function DoWhileStatement(node, print) {
this.push(");");
}
/**
* Builds continue, return, or break statement printers.
* Prints label (or key).
*/
var buildLabelStatement = function (prefix, key) {
return function (node, print) {
this.push(prefix);
@ -94,16 +128,28 @@ var buildLabelStatement = function (prefix, key) {
};
};
/**
* Create ContinueStatement, ReturnStatement, and BreakStatement printers.
*/
export var ContinueStatement = buildLabelStatement("continue");
export var ReturnStatement = buildLabelStatement("return", "argument");
export var BreakStatement = buildLabelStatement("break");
/**
* Prints LabeledStatement, prints label and body.
*/
export function LabeledStatement(node, print) {
print.plain(node.label);
this.push(": ");
print.plain(node.body);
}
/**
* Prints TryStatement, prints block, handlers, and finalizer.
*/
export function TryStatement(node, print) {
this.keyword("try");
print.plain(node.block);
@ -125,6 +171,10 @@ export function TryStatement(node, print) {
}
}
/**
* Prints CatchClause, prints param and body.
*/
export function CatchClause(node, print) {
this.keyword("catch");
this.push("(");
@ -133,12 +183,20 @@ export function CatchClause(node, print) {
print.plain(node.body);
}
/**
* Prints ThrowStatement, prints argument.
*/
export function ThrowStatement(node, print) {
this.push("throw ");
print.plain(node.argument);
this.semicolon();
}
/**
* Prints SwitchStatement, prints discriminant and cases.
*/
export function SwitchStatement(node, print) {
this.keyword("switch");
this.push("(");
@ -157,6 +215,10 @@ export function SwitchStatement(node, print) {
this.push("}");
}
/**
* Prints SwitchCase, prints test and consequent.
*/
export function SwitchCase(node, print) {
if (node.test) {
this.push("case ");
@ -172,10 +234,18 @@ export function SwitchCase(node, print) {
}
}
/**
* Prints DebuggerStatement.
*/
export function DebuggerStatement() {
this.push("debugger;");
}
/**
* Prints VariableDeclaration, prints declarations, handles kind and format.
*/
export function VariableDeclaration(node, print, parent) {
this.push(node.kind + " ");
@ -219,6 +289,10 @@ export function VariableDeclaration(node, print, parent) {
this.semicolon();
}
/**
* Prints VariableDeclarator, handles id, id.typeAnnotation, and init.
*/
export function VariableDeclarator(node, print) {
print.plain(node.id);
print.plain(node.id.typeAnnotation);

View File

@ -1,12 +1,24 @@
/**
* Prints TaggedTemplateExpression, prints tag and quasi.
*/
export function TaggedTemplateExpression(node, print) {
print.plain(node.tag);
print.plain(node.quasi);
}
/**
* Prints TemplateElement, prints value.
*/
export function TemplateElement(node) {
this._push(node.value.raw);
}
/**
* Prints TemplateLiteral, prints quasis, and expressions.
*/
export function TemplateLiteral(node, print) {
this.push("`");

View File

@ -3,17 +3,34 @@
import isInteger from "is-integer";
import * as t from "../../types";
/**
* Prints Identifier, prints name.
*/
export function Identifier(node) {
this.push(node.name);
}
/**
* Prints RestElement, prints argument.
*/
export function RestElement(node, print) {
this.push("...");
print.plain(node.argument);
}
/**
* Alias RestElement printer as SpreadElement,
* and RestElement printer as SpreadProperty.
*/
export { RestElement as SpreadElement, RestElement as SpreadProperty };
/**
* Prints ObjectExpression, prints properties.
*/
export function ObjectExpression(node, print) {
var props = node.properties;
@ -30,8 +47,16 @@ export function ObjectExpression(node, print) {
}
}
/**
* Alias ObjectExpression printer as ObjectPattern.
*/
export { ObjectExpression as ObjectPattern };
/**
* Prints Property, prints decorators, key, and value, handles kind, computed, and shorthand.
*/
export function Property(node, print) {
print.list(node.decorators, { separator: "" });
@ -66,6 +91,10 @@ export function Property(node, print) {
}
}
/**
* Prints ArrayExpression, prints elements.
*/
export function ArrayExpression(node, print) {
var elems = node.elements;
var len = elems.length;
@ -91,10 +120,22 @@ export function ArrayExpression(node, print) {
this.push("]");
}
/**
* Alias ArrayExpression printer as ArrayPattern.
*/
export { ArrayExpression as ArrayPattern };
/**
* RegExp for testing scientific notation in literals.
*/
const SCIENTIFIC_NOTATION = /e/i;
/**
* Prints Literal, prints value, regex, raw, handles val type.
*/
export function Literal(node, print, parent) {
var val = node.value;
var type = typeof val;
@ -125,6 +166,10 @@ export function Literal(node, print, parent) {
}
}
/**
* Prints string literals, handles format.
*/
export function _stringLiteral(val) {
val = JSON.stringify(val);

View File

@ -11,6 +11,11 @@ import each from "lodash/collection/each";
import n from "./node";
import * as t from "../types";
/**
* Babel's code generator, turns an ast into code, maintaining sourcemaps,
* user preferences, and valid output.
*/
class CodeGenerator {
constructor(ast, opts, code) {
opts = opts || {};
@ -27,6 +32,13 @@ class CodeGenerator {
this.buffer = new Buffer(this.position, this.format);
}
/**
* Normalize generator options, setting defaults.
*
* - Detects code indentation.
* - If `opts.compact = "auto"` and the code is over 100KB, `compact` will be set to `true`.
*/
static normalizeOptions(code, opts, tokens) {
var style = " ";
if (code) {
@ -57,6 +69,9 @@ class CodeGenerator {
return format;
}
/**
* Determine if input code uses more single or double quotes.
*/
static findCommonStringDelimiter(code, tokens) {
var occurences = {
single: 0,
@ -86,6 +101,10 @@ class CodeGenerator {
}
}
/**
* All node generators.
*/
static generators = {
templateLiterals: require("./generators/template-literals"),
comprehensions: require("./generators/comprehensions"),
@ -100,6 +119,12 @@ class CodeGenerator {
jsx: require("./generators/jsx")
};
/**
* Generate code and sourcemap from ast.
*
* Appends comments that weren't attached to any node to the end of the generated output.
*/
generate() {
var ast = this.ast;
@ -119,10 +144,18 @@ class CodeGenerator {
};
}
/**
* Build NodePrinter.
*/
buildPrint(parent) {
return new NodePrinter(this, parent);
}
/**
* [Please add a description.]
*/
catchUp(node, parent, leftParenPrinted) {
// catch up to this nodes newline if we're behind
if (node.loc && this.format.retainLines && this.buffer.buf) {
@ -139,6 +172,10 @@ class CodeGenerator {
return false;
}
/**
* [Please add a description.]
*/
_printNewline(leading, node, parent, opts) {
if (!opts.statement && !n.isUserWhitespacable(node, parent)) {
return;
@ -169,6 +206,10 @@ class CodeGenerator {
this.newline(lines);
}
/**
* [Please add a description.]
*/
print(node, parent, opts = {}) {
if (!node) return;
@ -218,6 +259,10 @@ class CodeGenerator {
}
}
/**
* [Please add a description.]
*/
printJoin(print, nodes, opts = {}) {
if (!nodes || !nodes.length) return;
@ -247,6 +292,10 @@ class CodeGenerator {
if (opts.indent) this.dedent();
}
/**
* [Please add a description.]
*/
printAndIndentOnComments(print, node) {
var indent = !!node.leadingComments;
if (indent) this.indent();
@ -254,6 +303,10 @@ class CodeGenerator {
if (indent) this.dedent();
}
/**
* [Please add a description.]
*/
printBlock(print, node) {
if (t.isEmptyStatement(node)) {
this.semicolon();
@ -263,6 +316,10 @@ class CodeGenerator {
}
}
/**
* [Please add a description.]
*/
generateComment(comment) {
var val = comment.value;
if (comment.type === "CommentLine") {
@ -273,14 +330,26 @@ class CodeGenerator {
return val;
}
/**
* [Please add a description.]
*/
printTrailingComments(node, parent) {
this._printComments(this.getComments("trailingComments", node, parent));
}
/**
* [Please add a description.]
*/
printLeadingComments(node, parent) {
this._printComments(this.getComments("leadingComments", node, parent));
}
/**
* [Please add a description.]
*/
getComments(key, node, parent) {
if (t.isExpressionStatement(parent)) {
return [];
@ -300,10 +369,18 @@ class CodeGenerator {
return comments;
}
/**
* [Please add a description.]
*/
_getComments(key, node) {
return (node && node[key]) || [];
}
/**
* [Please add a description.]
*/
_printComments(comments) {
if (this.format.compact) return;
if (!this.format.comments) return;
@ -371,16 +448,28 @@ class CodeGenerator {
}
}
/**
* [Please add a description.]
*/
each(Buffer.prototype, function (fn, key) {
CodeGenerator.prototype[key] = function () {
return fn.apply(this.buffer, arguments);
};
});
/**
* [Please add a description.]
*/
each(CodeGenerator.generators, function (generator) {
extend(CodeGenerator.prototype, generator);
});
/**
* [Please add a description.]
*/
module.exports = function (ast, opts, code) {
var gen = new CodeGenerator(ast, opts, code);
return gen.generate();

View File

@ -4,6 +4,16 @@ import each from "lodash/collection/each";
import some from "lodash/collection/some";
import * as t from "../../types";
/**
* Test if node matches a set of type-matcher pairs.
* @example
* find({
* VariableDeclaration(node, parent) {
* return true;
* }
* }, node, parent);
*/
var find = function (obj, node, parent) {
if (!obj) return;
var result;
@ -22,16 +32,28 @@ var find = function (obj, node, parent) {
return result;
};
/**
* Whitespace and Parenthesis related methods for nodes.
*/
export default class Node {
constructor(node, parent) {
this.parent = parent;
this.node = node;
}
/**
* Test if `node` can have whitespace set by the user.
*/
static isUserWhitespacable(node) {
return t.isUserWhitespacable(node);
}
/**
* Test if a `node` requires whitespace.
*/
static needsWhitespace(node, parent, type) {
if (!node) return 0;
@ -54,14 +76,26 @@ export default class Node {
return (linesInfo && linesInfo[type]) || 0;
}
/**
* Test if a `node` requires whitespace before it.
*/
static needsWhitespaceBefore(node, parent) {
return Node.needsWhitespace(node, parent, "before");
}
/**
* Test if a `note` requires whitespace after it.
*/
static needsWhitespaceAfter(node, parent) {
return Node.needsWhitespace(node, parent, "after");
}
/**
* Test if a `node` needs parentheses around it.
*/
static needsParens(node, parent) {
if (!parent) return false;
@ -77,6 +111,10 @@ export default class Node {
return find(parens, node, parent);
}
/**
* [Please add a description.]
*/
static needsParensNoLineTerminator(node, parent) {
if (!parent) return false;
@ -89,6 +127,10 @@ export default class Node {
}
}
/**
* Add all static methods from `Node` to `Node.prototype`.
*/
each(Node, function (fn, key) {
Node.prototype[key] = function () {
// Avoid leaking arguments to prevent deoptimization

View File

@ -1,6 +1,12 @@
import each from "lodash/collection/each";
import * as t from "../../types";
/**
* Create a mapping of operators to precendence.
*
* @example
* { "==": 6, "+": 9 }
*/
const PRECEDENCE = {};
each([
@ -21,12 +27,24 @@ each([
});
});
/**
* Test if NullableTypeAnnotation needs parentheses.
*/
export function NullableTypeAnnotation(node, parent) {
return t.isArrayTypeAnnotation(parent);
}
/**
* Alias NullableTypeAnnotation test as FunctionTypeAnnotation.
*/
export { NullableTypeAnnotation as FunctionTypeAnnotation };
/**
* Test if UpdateExpression needs parentheses.
*/
export function UpdateExpression(node, parent) {
if (t.isMemberExpression(parent) && parent.object === node) {
// (foo++).test()
@ -34,6 +52,10 @@ export function UpdateExpression(node, parent) {
}
}
/**
* Test if ObjectExpression needs parentheses.
*/
export function ObjectExpression(node, parent) {
if (t.isExpressionStatement(parent)) {
// ({ foo: "bar" });
@ -48,6 +70,10 @@ export function ObjectExpression(node, parent) {
return false;
}
/**
* Test if Binary needs parentheses.
*/
export function Binary(node, parent) {
if ((t.isCallExpression(parent) || t.isNewExpression(parent)) && parent.callee === node) {
return true;
@ -78,6 +104,10 @@ export function Binary(node, parent) {
}
}
/**
* Test if BinaryExpression needs parentheses.
*/
export function BinaryExpression(node, parent) {
if (node.operator === "in") {
// var i = (1 in []);
@ -92,6 +122,10 @@ export function BinaryExpression(node, parent) {
}
}
/**
* Test if SequenceExpression needs parentheses.
*/
export function SequenceExpression(node, parent) {
if (t.isForStatement(parent)) {
// Although parentheses wouldn't hurt around sequence
@ -110,6 +144,10 @@ export function SequenceExpression(node, parent) {
return true;
}
/**
* Test if YieldExpression needs parentheses.
*/
export function YieldExpression(node, parent) {
return t.isBinary(parent) ||
t.isUnaryLike(parent) ||
@ -120,14 +158,26 @@ export function YieldExpression(node, parent) {
t.isYieldExpression(parent);
}
/**
* Test if ClassExpression needs parentheses.
*/
export function ClassExpression(node, parent) {
return t.isExpressionStatement(parent);
}
/**
* Test if UnaryLike needs parentheses.
*/
export function UnaryLike(node, parent) {
return t.isMemberExpression(parent) && parent.object === node;
}
/**
* Test if FunctionExpression needs parentheses.
*/
export function FunctionExpression(node, parent) {
// function () {};
if (t.isExpressionStatement(parent)) {
@ -145,6 +195,10 @@ export function FunctionExpression(node, parent) {
}
}
/**
* Test if ConditionalExpression needs parentheses.
*/
export function ConditionalExpression(node, parent) {
if (t.isUnaryLike(parent)) {
return true;
@ -171,6 +225,10 @@ export function ConditionalExpression(node, parent) {
return false;
}
/**
* Test if AssignmentExpression needs parentheses.
*/
export function AssignmentExpression(node) {
if (t.isObjectPattern(node.left)) {
return true;

View File

@ -1,22 +1,42 @@
/**
* Printer for nodes, needs a `generator` and a `parent`.
*/
export default class NodePrinter {
constructor(generator, parent) {
this.generator = generator;
this.parent = parent;
}
/**
* Print a plain node.
*/
plain(node, opts) {
return this.generator.print(node, this.parent, opts);
}
/**
* Print a sequence of nodes as statements.
*/
sequence(nodes, opts = {}) {
opts.statement = true;
return this.generator.printJoin(this, nodes, opts);
}
/**
* Print a sequence of nodes as expressions.
*/
join(nodes, opts) {
return this.generator.printJoin(this, nodes, opts);
}
/**
* Print a list of nodes, with a customizable separator (defaults to ",").
*/
list(items, opts = {}) {
if (opts.separator == null) {
opts.separator = ",";
@ -26,10 +46,18 @@ export default class NodePrinter {
return this.join(items, opts);
}
/**
* Print a block-like node.
*/
block(node) {
return this.generator.printBlock(this, node);
}
/**
* Print node and indent comments.
*/
indentOnComments(node) {
return this.generator.printAndIndentOnComments(this, node);
}

View File

@ -3,6 +3,14 @@ import each from "lodash/collection/each";
import map from "lodash/collection/map";
import * as t from "../../types";
/**
* Crawl a node to test if it contains a CallExpression, a Function, or a Helper.
*
* @example
* crawl(node)
* // { hasCall: false, hasFunction: true, hasHelper: false }
*/
function crawl(node, state = {}) {
if (t.isMemberExpression(node)) {
crawl(node.object, state);
@ -22,6 +30,10 @@ function crawl(node, state = {}) {
return state;
}
/**
* Test if a node is or has a helper.
*/
function isHelper(node) {
if (t.isMemberExpression(node)) {
return isHelper(node.object) || isHelper(node.property);
@ -36,12 +48,25 @@ function isHelper(node) {
}
}
/**
* [Please add a description.]
*/
function isType(node) {
return t.isLiteral(node) || t.isObjectExpression(node) || t.isArrayExpression(node) ||
t.isIdentifier(node) || t.isMemberExpression(node);
}
/**
* Tests for node types that need whitespace.
*/
exports.nodes = {
/**
* Test if AssignmentExpression needs whitespace.
*/
AssignmentExpression(node) {
var state = crawl(node.right);
if ((state.hasCall && state.hasHelper) || state.hasFunction) {
@ -52,12 +77,20 @@ exports.nodes = {
}
},
/**
* Test if SwitchCase needs whitespace.
*/
SwitchCase(node, parent) {
return {
before: node.consequent.length || parent.cases[0] === node
};
},
/**
* Test if LogicalExpression needs whitespace.
*/
LogicalExpression(node) {
if (t.isFunction(node.left) || t.isFunction(node.right)) {
return {
@ -66,6 +99,10 @@ exports.nodes = {
}
},
/**
* Test if Literal needs whitespace.
*/
Literal(node) {
if (node.value === "use strict") {
return {
@ -74,6 +111,10 @@ exports.nodes = {
}
},
/**
* Test if CallExpression needs whitespace.
*/
CallExpression(node) {
if (t.isFunction(node.callee) || isHelper(node)) {
return {
@ -83,6 +124,10 @@ exports.nodes = {
}
},
/**
* Test if VariableDeclaration needs whitespace.
*/
VariableDeclaration(node) {
for (var i = 0; i < node.declarations.length; i++) {
var declar = node.declarations[i];
@ -102,6 +147,10 @@ exports.nodes = {
}
},
/**
* Test if IfStatement needs whitespace.
*/
IfStatement(node) {
if (t.isBlockStatement(node.consequent)) {
return {
@ -112,6 +161,10 @@ exports.nodes = {
}
};
/**
* Test if Property or SpreadProperty needs whitespace.
*/
exports.nodes.Property =
exports.nodes.SpreadProperty = function (node, parent) {
if (parent.properties[0] === node) {
@ -121,20 +174,41 @@ exports.nodes.SpreadProperty = function (node, parent) {
}
};
/**
* Returns lists from node types that need whitespace.
*/
exports.list = {
/**
* Return VariableDeclaration declarations init properties.
*/
VariableDeclaration(node) {
return map(node.declarations, "init");
},
/**
* Return VariableDeclaration elements.
*/
ArrayExpression(node) {
return node.elements;
},
/**
* Return VariableDeclaration properties.
*/
ObjectExpression(node) {
return node.properties;
}
};
/**
* Add whitespace tests for nodes and their aliases.
*/
each({
Function: true,
Class: true,

View File

@ -1,9 +1,17 @@
/**
* Track current position in code generation.
*/
export default class Position {
constructor() {
this.line = 1;
this.column = 0;
}
/**
* Push a string to the current position, mantaining the current line and column.
*/
push(str) {
for (var i = 0; i < str.length; i++) {
if (str[i] === "\n") {
@ -15,6 +23,10 @@ export default class Position {
}
}
/**
* Unshift a string from the current position, mantaining the current line and column.
*/
unshift(str) {
for (var i = 0; i < str.length; i++) {
if (str[i] === "\n") {

View File

@ -1,6 +1,10 @@
import sourceMap from "source-map";
import * as t from "../types";
/**
* Build a sourcemap.
*/
export default class SourceMap {
constructor(position, opts, code) {
this.position = position;
@ -18,6 +22,10 @@ export default class SourceMap {
}
}
/**
* Get the sourcemap.
*/
get() {
var map = this.map;
if (map) {
@ -27,6 +35,10 @@ export default class SourceMap {
}
}
/**
* Mark a node's generated position, and add it to the sourcemap.
*/
mark(node, type) {
var loc = node.loc;
if (!loc) return; // no location info

View File

@ -18,6 +18,10 @@ function getLookupIndex(i, base, max) {
return i;
}
/**
* Get whitespace around tokens.
*/
export default class Whitespace {
constructor(tokens) {
this.tokens = tokens;
@ -34,6 +38,10 @@ export default class Whitespace {
this._lastFoundIndex = 0;
}
/**
* Count all the newlines before a node.
*/
getNewlinesBefore(node) {
var startToken;
var endToken;
@ -57,6 +65,10 @@ export default class Whitespace {
return this.getNewlinesBetween(startToken, endToken);
}
/**
* Count all the newlines after a node.
*/
getNewlinesAfter(node) {
var startToken;
var endToken;
@ -91,6 +103,10 @@ export default class Whitespace {
}
}
/**
* Count all the newlines between two tokens.
*/
getNewlinesBetween(startToken, endToken) {
if (!endToken || !endToken.loc) return 0;

View File

@ -0,0 +1,4 @@
## Helpers
Utilities for Babel, which is just another way to say "helpers", but I wrote it
anyways, so deal with it.

View File

@ -4,6 +4,10 @@ import jsTokens from "js-tokens";
import esutils from "esutils";
import chalk from "chalk";
/**
* Chalk styles for token types.
*/
var defs = {
string: chalk.red,
punctuator: chalk.bold,
@ -17,8 +21,16 @@ var defs = {
invalid: chalk.inverse
};
/**
* RegExp to test for newlines in terminal.
*/
const NEWLINE = /\r\n|[\n\r\u2028\u2029]/;
/**
* Get the type of token, specifying punctuator type.
*/
function getTokenType(match) {
var token = jsTokens.matchToToken(match);
if (token.type === "name" && esutils.keyword.isReservedWordES6(token.value)) {
@ -42,6 +54,10 @@ function getTokenType(match) {
return token.type;
}
/**
* Highlight `text`.
*/
function highlight(text) {
return text.replace(jsTokens, function (...args) {
var type = getTokenType(args);
@ -54,6 +70,10 @@ function highlight(text) {
});
}
/**
* Create a code frame, adding line numbers, code highlighting, and pointing to a given position.
*/
export default function (lines: number, lineNumber: number, colNumber: number, opts = {}): string {
colNumber = Math.max(colNumber, 0);

View File

@ -1,5 +1,9 @@
import merge from "lodash/object/merge";
/**
* Merge options.
*/
export default function (dest, src) {
if (!dest || !src) return;

View File

@ -1,5 +1,11 @@
import * as t from "../types";
/**
* Normalize an AST.
*
* - Wrap `Program` node with a `File` node.
*/
export default function (ast, comments, tokens) {
if (ast && ast.type === "Program") {
return t.file(ast, comments || [], tokens || []);

View File

@ -1,3 +1,7 @@
/**
* Create an object with a `null` prototype.
*/
export default function () {
return Object.create(null);
}

View File

@ -2,6 +2,10 @@ import normalizeAst from "./normalize-ast";
import estraverse from "estraverse";
import * as acorn from "../../acorn";
/**
* Parse `code` with normalized options, collecting tokens and comments.
*/
export default function (code, opts = {}) {
var commentsAndTokens = [];
var comments = [];
@ -21,11 +25,17 @@ export default function (code, opts = {}) {
ranges: true
};
/**
* Collect all tokens.
*/
parseOpts.onToken = function (token) {
tokens.push(token);
commentsAndTokens.push(token);
};
/**
* Collection all comments.
*/
parseOpts.onComment = function (block, text, start, end, startLoc, endLoc) {
var comment = {
type: block ? "CommentBlock" : "CommentLine",

View File

@ -1,5 +1,10 @@
import * as util from "util";
/**
* Mapping of messages to be used in Babel.
* Messages can include $0-style placeholders.
*/
export const MESSAGES = {
tailCallReassignmentDeopt: "Function reference has been reassigned, so it will probably be dereferenced, therefore we can't optimise this with confidence",
JSXNamespacedTags: "Namespace tags are not supported. ReactJSX is not XML.",
@ -50,18 +55,28 @@ export const MESSAGES = {
`
};
export function get(key: String, ...args) {
/**
* Get a message with $0 placeholders replaced by arguments.
*/
export function get(key: string, ...args): string {
var msg = MESSAGES[key];
if (!msg) throw new ReferenceError(`Unknown message ${JSON.stringify(key)}`);
// stringify args
args = parseArgs(args);
// replace $0 placeholders with args
return msg.replace(/\$(\d+)/g, function (str, i) {
return args[--i];
});
}
export function parseArgs(args: Array<any>) {
/**
* Stingify arguments to be used inside messages.
*/
export function parseArgs(args: Array<any>): Array<string> {
return args.map(function (val) {
if (val != null && val.inspect) {
return val.inspect();

15
src/babel/tools/README.md Normal file
View File

@ -0,0 +1,15 @@
## Tools
> This directory is best browsed while listening to
> https://www.youtube.com/watch?v=hglVqACd1C8.
### Protect Babel
The protect script seen here is to throw errors if someone ever tries to
include internal babel files in their script. If you need something to be
exposed, you should ask for it, not try to hack your way into getting it.
### External Helpers
You'll also find the script for building the external helpers file, this is
the Babel "runtime" where all helper functions go instead of the top of a file.

View File

@ -5,6 +5,10 @@ import File from "../transformation/file";
import each from "lodash/collection/each";
import * as t from "../types";
/**
* [Please add a description.]
*/
function buildGlobal(namespace, builder) {
var body = [];
var container = t.functionExpression(null, [t.identifier("global")], t.blockStatement(body));
@ -22,6 +26,10 @@ function buildGlobal(namespace, builder) {
return tree;
}
/**
* [Please add a description.]
*/
function buildUmd(namespace, builder) {
var body = [];
body.push(t.variableDeclaration("var", [
@ -41,6 +49,10 @@ function buildUmd(namespace, builder) {
return t.program([container]);
}
/**
* [Please add a description.]
*/
function buildVar(namespace, builder) {
var body = [];
body.push(t.variableDeclaration("var", [
@ -50,6 +62,10 @@ function buildVar(namespace, builder) {
return t.program(body);
}
/**
* [Please add a description.]
*/
function buildHelpers(body, namespace, whitelist) {
each(File.helpers, function (name) {
if (whitelist && whitelist.indexOf(name) === -1) return;
@ -61,6 +77,10 @@ function buildHelpers(body, namespace, whitelist) {
});
}
/**
* [Please add a description.]
*/
export default function (whitelist, outputType = "global") {
var namespace = t.identifier("babelHelpers");

View File

@ -2,6 +2,11 @@ import path from "path";
var root = path.resolve(__dirname, "../../../");
/**
* Protect Babel internals from being hotlinked by other tools.
* Sorry, not sorry.
*/
export default function (module) {
if (module.parent && module.parent.filename.indexOf(root) !== 0) {
throw new Error("Don't hotlink internal Babel files.");

View File

@ -0,0 +1,3 @@
## Transformation
This is the Transformation directory.

View File

@ -0,0 +1,3 @@
## File Transformation
This is the File Transformation directory.

View File

@ -19,6 +19,10 @@ import * as util from "../../util";
import path from "path";
import * as t from "../../types";
/**
* [Please add a description.]
*/
export default class File {
constructor(opts = {}, pipeline) {
this.transformerDependencies = {};
@ -52,6 +56,10 @@ export default class File {
this.hub = new Hub(this);
}
/**
* [Please add a description.]
*/
static helpers = [
"inherits",
"defaults",
@ -89,8 +97,17 @@ export default class File {
"interop-require"
];
/**
* [Please add a description.]
*/
static soloHelpers = [];
/**
* [Please add a description.]
*/
initOptions(opts) {
opts = new OptionManager(this.log, this.pipeline).init(opts);
@ -134,10 +151,18 @@ export default class File {
return opts;
}
/**
* [Please add a description.]
*/
isLoose(key: string) {
return includes(this.opts.loose, key);
}
/**
* [Please add a description.]
*/
buildTransformers() {
var file = this;
@ -192,6 +217,10 @@ export default class File {
this.transformerStack = this.collapseStack(stack);
}
/**
* [Please add a description.]
*/
collapseStack(_stack) {
var stack = [];
var ignore = [];
@ -228,14 +257,26 @@ export default class File {
return stack;
}
/**
* [Please add a description.]
*/
set(key: string, val): any {
return this.data[key] = val;
};
}
/**
* [Please add a description.]
*/
setDynamic(key: string, fn: Function) {
this.dynamicData[key] = fn;
}
/**
* [Please add a description.]
*/
get(key: string): any {
var data = this.data[key];
if (data) {
@ -248,12 +289,20 @@ export default class File {
}
}
/**
* [Please add a description.]
*/
resolveModuleSource(source: string): string {
var resolveModuleSource = this.opts.resolveModuleSource;
if (resolveModuleSource) source = resolveModuleSource(source, this.opts.filename);
return source;
}
/**
* [Please add a description.]
*/
addImport(source: string, name?: string, type?: string): Object {
name = name || source;
var id = this.dynamicImportIds[name];
@ -282,6 +331,10 @@ export default class File {
return id;
}
/**
* [Please add a description.]
*/
attachAuxiliaryComment(node: Object): Object {
var beforeComment = this.opts.auxiliaryCommentBefore;
if (beforeComment) {
@ -304,6 +357,10 @@ export default class File {
return node;
}
/**
* [Please add a description.]
*/
addHelper(name: string): Object {
var isSolo = includes(File.soloHelpers, name);
@ -350,6 +407,10 @@ export default class File {
return uid;
}
/**
* [Please add a description.]
*/
errorWithNode(node, msg, Error = SyntaxError) {
var err;
if (node && node.loc) {
@ -363,6 +424,10 @@ export default class File {
return err;
}
/**
* [Please add a description.]
*/
mergeSourceMap(map: Object) {
var opts = this.opts;
@ -385,6 +450,9 @@ export default class File {
return map;
}
/**
* [Please add a description.]
*/
getModuleFormatter(type: string) {
if (isFunction(type) || !moduleFormatters[type]) {
@ -405,6 +473,10 @@ export default class File {
return new ModuleFormatter(this);
}
/**
* [Please add a description.]
*/
parse(code: string) {
var opts = this.opts;
@ -433,6 +505,10 @@ export default class File {
return tree;
}
/**
* [Please add a description.]
*/
_addAst(ast) {
this.path = NodePath.get({
hub: this.hub,
@ -445,6 +521,10 @@ export default class File {
this.ast = ast;
}
/**
* [Please add a description.]
*/
addAst(ast) {
this.log.debug("Start set AST");
this._addAst(ast);
@ -458,6 +538,10 @@ export default class File {
this.log.debug("End module formatter init");
}
/**
* [Please add a description.]
*/
transform() {
this.call("pre");
for (var pass of (this.transformerStack: Array)) {
@ -468,6 +552,10 @@ export default class File {
return this.generate();
}
/**
* [Please add a description.]
*/
wrap(code, callback) {
code = code + "";
@ -505,22 +593,38 @@ export default class File {
}
}
/**
* [Please add a description.]
*/
addCode(code: string) {
code = (code || "") + "";
code = this.parseInputSourceMap(code);
this.code = code;
}
/**
* [Please add a description.]
*/
parseCode() {
this.parseShebang();
this.addAst(this.parse(this.code));
}
/**
* [Please add a description.]
*/
shouldIgnore() {
var opts = this.opts;
return util.shouldIgnore(opts.filename, opts.ignore, opts.only);
}
/**
* [Please add a description.]
*/
call(key: string) {
for (var pass of (this.uncollapsedTransformerStack: Array)) {
var fn = pass.plugin[key];
@ -528,6 +632,10 @@ export default class File {
}
}
/**
* [Please add a description.]
*/
parseInputSourceMap(code: string) {
var opts = this.opts;
@ -542,6 +650,10 @@ export default class File {
return code;
}
/**
* [Please add a description.]
*/
parseShebang() {
var shebangMatch = shebangRegex.exec(this.code);
if (shebangMatch) {
@ -550,6 +662,10 @@ export default class File {
}
}
/**
* [Please add a description.]
*/
makeResult({ code, map = null, ast, ignored }) {
var result = {
metadata: null,
@ -575,6 +691,10 @@ export default class File {
return result;
}
/**
* [Please add a description.]
*/
generate() {
var opts = this.opts;
var ast = this.ast;

View File

@ -6,26 +6,46 @@ var generalDebug = buildDebug("babel");
var seenDeprecatedMessages = [];
/**
* [Please add a description.]
*/
export default class Logger {
constructor(file: File, filename: string) {
this.filename = filename;
this.file = file;
}
/**
* [Please add a description.]
*/
_buildMessage(msg: string): string {
var parts = `[BABEL] ${this.filename}`;
if (msg) parts += `: ${msg}`;
return parts;
}
/**
* [Please add a description.]
*/
warn(msg) {
console.warn(this._buildMessage(msg));
}
/**
* [Please add a description.]
*/
error(msg: string, Constructor = Error) {
throw new Constructor(this._buildMessage(msg));
}
/**
* [Please add a description.]
*/
deprecate(msg) {
if (this.file.opts.suppressDeprecationMessages) return;
@ -40,14 +60,26 @@ export default class Logger {
console.error(msg);
}
/**
* [Please add a description.]
*/
verbose(msg: string) {
if (verboseDebug.enabled) verboseDebug(this._buildMessage(msg));
}
/**
* [Please add a description.]
*/
debug(msg: string) {
if (generalDebug.enabled) generalDebug(this._buildMessage(msg));
}
/**
* [Please add a description.]
*/
deopt(node: Object, msg: string) {
this.debug(msg);
}

View File

@ -0,0 +1,3 @@
## File Options
This is the File Options directory.

View File

@ -3,6 +3,10 @@ import config from "./config";
export { config };
/**
* Validate an option.
*/
export function validateOption(key, val, pipeline) {
var opt = config[key];
var parser = opt && parsers[opt.type];
@ -13,6 +17,10 @@ export function validateOption(key, val, pipeline) {
}
}
/**
* Normalize all options.
*/
export function normaliseOptions(options = {}) {
for (var key in options) {
var val = options[key];

View File

@ -31,7 +31,7 @@ export default class OptionManager {
}
/**
* Description
* [Please add a description.]
*/
static createBareOptions() {
@ -46,7 +46,7 @@ export default class OptionManager {
}
/**
* Description
* [Please add a description.]
*/
addConfig(loc) {
@ -67,7 +67,7 @@ export default class OptionManager {
}
/**
* Description
* [Please add a description.]
*/
mergeOptions(opts, alias = "foreign") {
@ -90,7 +90,7 @@ export default class OptionManager {
}
/**
* Description
* [Please add a description.]
*/
findConfigs(loc) {
@ -109,7 +109,7 @@ export default class OptionManager {
}
/**
* Description
* [Please add a description.]
*/
normaliseOptions() {
@ -142,7 +142,7 @@ export default class OptionManager {
}
/**
* Description
* [Please add a description.]
*/
init(opts) {

View File

@ -1,10 +1,18 @@
import slash from "slash";
import * as util from "../../../util";
/**
* Get a transformer list from a value.
*/
export function transformerList(val) {
return util.arrayify(val);
}
/**
* Validate transformer list. Maps "all" to all transformer names.
*/
transformerList.validate = function (key, val, pipeline) {
if (val.indexOf("all") >= 0 || val.indexOf(true) >= 0) {
val = Object.keys(pipeline.transformers);
@ -13,20 +21,40 @@ transformerList.validate = function (key, val, pipeline) {
return pipeline._ensureTransformerNames(key, val);
};
/**
* Cast a value to a number.
*/
export function number(val) {
return +val;
}
/**
* Cast a value to a boolean.
*/
export var filename = slash;
/**
* [Please add a description.]
*/
export function boolean(val) {
return !!val;
}
/**
* Cast a boolean-like string to a boolean.
*/
export function booleanString(val) {
return util.booleanify(val);
}
/**
* Cast a value to an array, splitting strings by ",".
*/
export function list(val) {
return util.list(val);
}

View File

@ -5,6 +5,10 @@ import * as messages from "../../messages";
import traverse from "../../traversal";
import parse from "../../helpers/parse";
/**
* [Please add a description.]
*/
var context = {
messages,
Transformer,
@ -16,9 +20,22 @@ var context = {
import * as util from "../../util";
/**
* [Please add a description.]
*/
export default class PluginManager {
/**
* [Please add a description.]
*/
static memoisedPlugins = [];
/**
* [Please add a description.]
*/
static memoisePluginContainer(fn) {
for (var i = 0; i < PluginManager.memoisedPlugins.length; i++) {
var plugin = PluginManager.memoisedPlugins[i];
@ -33,8 +50,16 @@ export default class PluginManager {
return transformer;
}
/**
* [Please add a description.]
*/
static positions = ["before", "after"];
/**
* [Please add a description.]
*/
constructor({ file, transformers, before, after } = { transformers: {}, before: [], after: [] }) {
this.transformers = transformers;
this.file = file;
@ -42,6 +67,10 @@ export default class PluginManager {
this.after = after;
}
/**
* [Please add a description.]
*/
subnormaliseString(name, position) {
// this is a plugin in the form of "foobar" or "foobar:after"
// where the optional colon is the delimiter for plugin position in the transformer stack
@ -61,6 +90,10 @@ export default class PluginManager {
}
}
/**
* [Please add a description.]
*/
validate(name, plugin) {
// validate transformer key
var key = plugin.key;
@ -77,6 +110,10 @@ export default class PluginManager {
plugin.metadata.plugin = true;
}
/**
* [Please add a description.]
*/
add(name) {
var position;
var plugin;

View File

@ -0,0 +1,3 @@
## Transformation Helpers
This is the Transformation Helpers directory.

View File

@ -1,17 +1,33 @@
import explode from "./explode-assignable-expression";
import * as t from "../../types";
/**
* [Please add a description.]
*/
export default function (opts) {
var exports = {};
/**
* [Please add a description.]
*/
var isAssignment = function (node) {
return node.operator === opts.operator + "=";
};
/**
* [Please add a description.]
*/
var buildAssignment = function (left, right) {
return t.assignmentExpression("=", left, right);
};
/**
* [Please add a description.]
*/
exports.ExpressionStatement = function (node, parent, scope, file) {
// hit the `AssignmentExpression` one below
if (this.isCompletionRecord()) return;
@ -29,6 +45,10 @@ export default function (opts) {
return nodes;
};
/**
* [Please add a description.]
*/
exports.AssignmentExpression = function (node, parent, scope, file) {
if (!isAssignment(node)) return;
@ -38,6 +58,10 @@ export default function (opts) {
return nodes;
};
/**
* [Please add a description.]
*/
exports.BinaryExpression = function (node) {
if (node.operator !== opts.operator) return;
return opts.build(node.left, node.right);

View File

@ -1,5 +1,9 @@
import * as t from "../../types";
/**
* [Please add a description.]
*/
export default function build(node, buildBody) {
var self = node.blocks.shift();
if (!self) return;

View File

@ -1,11 +1,24 @@
import explode from "./explode-assignable-expression";
import * as t from "../../types";
/**
* [Please add a description.]
*/
export default function (exports, opts) {
/**
* [Please add a description.]
*/
var buildAssignment = function (left, right) {
return t.assignmentExpression("=", left, right);
};
/**
* [Please add a description.]
*/
exports.ExpressionStatement = function (node, parent, scope, file) {
// hit the `AssignmentExpression` one below
if (this.isCompletionRecord()) return;
@ -25,6 +38,10 @@ export default function (exports, opts) {
return nodes;
};
/**
* [Please add a description.]
*/
exports.AssignmentExpression = function (node, parent, scope, file) {
if (!opts.is(node, file)) return;

View File

@ -9,9 +9,17 @@ import esutils from "esutils";
import * as react from "./react";
import * as t from "../../types";
/**
* [Please add a description.]
*/
export default function (opts) {
var visitor = {};
/**
* [Please add a description.]
*/
visitor.JSXIdentifier = function (node) {
if (node.name === "this" && this.isReferenced()) {
return t.thisExpression();
@ -22,10 +30,18 @@ export default function (opts) {
}
};
/**
* [Please add a description.]
*/
visitor.JSXNamespacedName = function () {
throw this.errorWithNode(messages.get("JSXNamespacedTags"));
};
/**
* [Please add a description.]
*/
visitor.JSXMemberExpression = {
exit(node) {
node.computed = t.isLiteral(node.property);
@ -33,10 +49,18 @@ export default function (opts) {
}
};
/**
* [Please add a description.]
*/
visitor.JSXExpressionContainer = function (node) {
return node.expression;
};
/**
* [Please add a description.]
*/
visitor.JSXAttribute = {
enter(node) {
var value = node.value;
@ -51,6 +75,10 @@ export default function (opts) {
}
};
/**
* [Please add a description.]
*/
visitor.JSXOpeningElement = {
exit(node, parent, scope, file) {
parent.children = react.buildChildren(parent);
@ -141,6 +169,10 @@ export default function (opts) {
return attribs;
};
/**
* [Please add a description.]
*/
visitor.JSXElement = {
exit(node) {
var callExpr = node.openingElement;

View File

@ -1,6 +1,15 @@
import * as t from "../../types";
/**
* [Please add a description.]
*/
var visitor = {
/**
* [Please add a description.]
*/
enter(node, parent, scope, state) {
if (this.isThisExpression() || this.isReferencedIdentifier({ name: "arguments" })) {
state.found = true;
@ -8,11 +17,19 @@ var visitor = {
}
},
/**
* [Please add a description.]
*/
Function() {
this.skip();
}
};
/**
* [Please add a description.]
*/
export default function (node, scope) {
var container = t.functionExpression(null, [], node.body, node.generator, node.async);

View File

@ -2,6 +2,10 @@ import each from "lodash/collection/each";
import has from "lodash/object/has";
import * as t from "../../types";
/**
* [Please add a description.]
*/
export function push(mutatorMap, node, kind, file) {
var alias = t.toKeyAlias(node);
@ -43,6 +47,10 @@ export function push(mutatorMap, node, kind, file) {
return map;
}
/**
* [Please add a description.]
*/
export function hasComputed(mutatorMap) {
for (var key in mutatorMap) {
if (mutatorMap[key]._computed) {
@ -52,6 +60,10 @@ export function hasComputed(mutatorMap) {
return false;
}
/**
* [Please add a description.]
*/
export function toComputedObjectFromClass(obj) {
var objExpr = t.arrayExpression([]);
@ -65,6 +77,10 @@ export function toComputedObjectFromClass(obj) {
return objExpr;
}
/**
* [Please add a description.]
*/
export function toClassObject(mutatorMap) {
var objExpr = t.objectExpression([]);
@ -92,6 +108,10 @@ export function toClassObject(mutatorMap) {
return objExpr;
}
/**
* [Please add a description.]
*/
export function toDefineObject(mutatorMap) {
each(mutatorMap, function (map) {
if (map.value) map.writable = t.literal(true);

View File

@ -1,5 +1,9 @@
import * as t from "../../types";
/**
* [Please add a description.]
*/
var getObjRef = function (node, nodes, file, scope) {
var ref;
if (t.isIdentifier(node)) {
@ -33,6 +37,10 @@ var getObjRef = function (node, nodes, file, scope) {
return temp;
};
/**
* [Please add a description.]
*/
var getPropRef = function (node, nodes, file, scope) {
var prop = node.property;
var key = t.toComputedKey(node, prop);
@ -45,6 +53,10 @@ var getPropRef = function (node, nodes, file, scope) {
return temp;
};
/**
* [Please add a description.]
*/
export default function (node, nodes, file, scope, allowedSingleIdent) {
var obj;
if (t.isIdentifier(node) && allowedSingleIdent) {

View File

@ -1,5 +1,9 @@
import * as t from "../../types";
/**
* [Please add a description.]
*/
export default function (node) {
var lastNonDefault = 0;
for (var i = 0; i < node.params.length; i++) {

View File

@ -1,5 +1,9 @@
import * as t from "../../types";
/**
* [Please add a description.]
*/
export default function (decorators, scope) {
for (var i = 0; i < decorators.length; i++) {
var decorator = decorators[i];

View File

@ -2,6 +2,10 @@ import getFunctionArity from "./get-function-arity";
import * as util from "../../util";
import * as t from "../../types";
/**
* [Please add a description.]
*/
function visitIdentifier(context, node, scope, state) {
// check if this node matches our function id
if (node.name !== state.name) return;
@ -15,16 +19,33 @@ function visitIdentifier(context, node, scope, state) {
context.stop();
}
/**
* [Please add a description.]
*/
var visitor = {
/**
* [Please add a description.]
*/
ReferencedIdentifier(node, parent, scope, state) {
visitIdentifier(this, node, scope, state);
},
/**
* [Please add a description.]
*/
BindingIdentifier(node, parent, scope, state) {
visitIdentifier(this, node, scope, state);
}
};
/**
* [Please add a description.]
*/
var wrap = function (state, method, id, scope) {
if (state.selfReference) {
if (scope.hasBinding(id.name) && !scope.hasGlobal(id.name)) {
@ -56,6 +77,10 @@ var wrap = function (state, method, id, scope) {
scope.getProgramParent().references[id.name] = true;
};
/**
* [Please add a description.]
*/
var visit = function (node, name, scope) {
var state = {
selfAssignment: false,
@ -102,11 +127,19 @@ var visit = function (node, name, scope) {
return state;
};
/**
* [Please add a description.]
*/
export function custom(node, id, scope) {
var state = visit(node, id.name, scope);
return wrap(state, node, id, scope);
}
/**
* [Please add a description.]
*/
export function property(node, file, scope) {
var key = t.toComputedKey(node, node.key);
if (!t.isLiteral(key)) return; // we can't set a function id with this
@ -119,6 +152,10 @@ export function property(node, file, scope) {
node.value = wrap(state, method, id, scope) || method;
}
/**
* [Please add a description.]
*/
export function bare(node, parent, scope) {
// has an `id` so we don't need to infer one
if (node.id) return;

View File

@ -2,10 +2,18 @@ import * as t from "../../types";
export var isReactComponent = t.buildMatchMemberExpression("React.Component");
/**
* [Please add a description.]
*/
export function isCompatTag(tagName) {
return tagName && /^[a-z]|\-/.test(tagName);
}
/**
* [Please add a description.]
*/
function cleanJSXElementLiteralChild(child, args) {
var lines = child.value.split(/\r\n|\n|\r/);
@ -51,6 +59,10 @@ function cleanJSXElementLiteralChild(child, args) {
if (str) args.push(t.literal(str));
}
/**
* [Please add a description.]
*/
export function buildChildren(node) {
var elems = [];

View File

@ -1,10 +1,18 @@
import pull from "lodash/array/pull";
import * as t from "../../types";
/**
* [Please add a description.]
*/
export function is(node, flag) {
return t.isLiteral(node) && node.regex && node.regex.flags.indexOf(flag) >= 0;
}
/**
* [Please add a description.]
*/
export function pullFlag(node, flag) {
var flags = node.regex.flags.split("");
if (node.regex.flags.indexOf(flag) < 0) return;

View File

@ -1,10 +1,23 @@
import * as t from "../../types";
/**
* [Please add a description.]
*/
var awaitVisitor = {
/**
* [Please add a description.]
*/
Function() {
this.skip();
},
/**
* [Please add a description.]
*/
AwaitExpression(node) {
node.type = "YieldExpression";
@ -16,7 +29,16 @@ var awaitVisitor = {
}
};
/**
* [Please add a description.]
*/
var referenceVisitor = {
/**
* [Please add a description.]
*/
ReferencedIdentifier(node, parent, scope, state) {
var name = state.id.name;
if (node.name === name && scope.bindingIdentifierEquals(name, state.id)) {
@ -25,6 +47,10 @@ var referenceVisitor = {
}
};
/**
* [Please add a description.]
*/
export default function (path, callId) {
var node = path.node;

View File

@ -2,6 +2,10 @@ import type NodePath from "../../traversal/path";
import * as messages from "../../messages";
import * as t from "../../types";
/**
* [Please add a description.]
*/
function isIllegalBareSuper(node, parent) {
if (!t.isSuper(node)) return false;
if (t.isMemberExpression(parent, { computed: false })) return false;
@ -9,11 +13,24 @@ function isIllegalBareSuper(node, parent) {
return true;
}
/**
* [Please add a description.]
*/
function isMemberExpressionSuper(node) {
return t.isMemberExpression(node) && t.isSuper(node.object);
}
/**
* [Please add a description.]
*/
var visitor = {
/**
* [Please add a description.]
*/
enter(node, parent, scope, state) {
var topLevel = state.topLevel;
var self = state.self;
@ -44,12 +61,11 @@ var visitor = {
}
};
/**
* [Please add a description.]
*/
export default class ReplaceSupers {
/**
* Description
*/
constructor(opts: Object, inClass?: boolean = false) {
this.topLevelThisReference = opts.topLevelThisReference;
this.methodPath = opts.methodPath;
@ -64,6 +80,10 @@ export default class ReplaceSupers {
this.opts = opts;
}
/**
* [Please add a description.]
*/
getObjectRef() {
return this.opts.objectRef || this.opts.getObjectRef();
}
@ -120,7 +140,7 @@ export default class ReplaceSupers {
}
/**
* Description
* [Please add a description.]
*/
replace() {
@ -128,7 +148,7 @@ export default class ReplaceSupers {
}
/**
* Description
* [Please add a description.]
*/
traverseLevel(path: NodePath, topLevel: boolean) {
@ -137,7 +157,7 @@ export default class ReplaceSupers {
}
/**
* Description
* [Please add a description.]
*/
getThisReference() {
@ -153,7 +173,7 @@ export default class ReplaceSupers {
}
/**
* Description
* [Please add a description.]
*/
getLooseSuperProperty(id: Object, parent: Object) {
@ -196,7 +216,7 @@ export default class ReplaceSupers {
}
/**
* Description
* [Please add a description.]
*/
looseHandle(path: NodePath, getThisReference: Function) {
@ -216,7 +236,7 @@ export default class ReplaceSupers {
}
/**
* Description
* [Please add a description.]
*/
specHandleAssignmentExpression(ref, path, node, getThisReference) {
@ -238,7 +258,7 @@ export default class ReplaceSupers {
}
/**
* Description
* [Please add a description.]
*/
specHandle(path: NodePath, getThisReference: Function) {

View File

@ -1,8 +1,14 @@
import Pipeline from "./pipeline";
/**
* [Please add a description.]
*/
var pipeline = new Pipeline;
//
/**
* [Please add a description.]
*/
import transformers from "./transformers";
@ -17,17 +23,23 @@ for (var key in transformers) {
pipeline.addTransformers(transformers);
//
/**
* [Please add a description.]
*/
import deprecated from "./transformers/deprecated";
pipeline.addDeprecated(deprecated);
//
/**
* [Please add a description.]
*/
import aliases from "./transformers/aliases";
pipeline.addAliases(aliases);
//
/**
* [Please add a description.]
*/
import * as filters from "./transformers/filters";
pipeline.addFilter(filters.internal);
@ -36,7 +48,9 @@ pipeline.addFilter(filters.whitelist);
pipeline.addFilter(filters.stage);
pipeline.addFilter(filters.optional);
//
/**
* [Please add a description.]
*/
var transform = pipeline.transform.bind(pipeline);
transform.fromAst = pipeline.transformFromAst.bind(pipeline);

View File

@ -0,0 +1,3 @@
## Module Transformation
This is the Module Transformation directory.

View File

@ -5,7 +5,16 @@ import object from "../../helpers/object";
import * as util from "../../util";
import * as t from "../../types";
/**
* [Please add a description.]
*/
var metadataVisitor = {
/**
* [Please add a description.]
*/
ModuleDeclaration: {
enter(node, parent, scope, formatter) {
if (node.source) {
@ -15,6 +24,10 @@ var metadataVisitor = {
}
},
/**
* [Please add a description.]
*/
ImportDeclaration: {
exit(node, parent, scope, formatter) {
formatter.hasLocalImports = true;
@ -63,6 +76,10 @@ var metadataVisitor = {
}
},
/**
* [Please add a description.]
*/
ExportDeclaration(node, parent, scope, formatter) {
formatter.hasLocalExports = true;
@ -156,6 +173,10 @@ var metadataVisitor = {
}
},
/**
* [Please add a description.]
*/
Scope(node, parent, scope, formatter) {
if (!formatter.isLoose()) {
this.skip();
@ -163,6 +184,10 @@ var metadataVisitor = {
}
};
/**
* [Please add a description.]
*/
export default class DefaultFormatter {
constructor(file) {
// object containg all module sources with the scope that they're contained in
@ -190,6 +215,10 @@ export default class DefaultFormatter {
this.getMetadata();
}
/**
* [Please add a description.]
*/
addScope(path) {
var source = path.node.source && path.node.source.value;
if (!source) return;
@ -202,19 +231,35 @@ export default class DefaultFormatter {
this.sourceScopes[source] = path.scope;
}
/**
* [Please add a description.]
*/
isModuleType(node, type) {
var modules = this.file.dynamicImportTypes[type];
return modules && modules.indexOf(node) >= 0;
}
/**
* [Please add a description.]
*/
transform() {
this.remapAssignments();
}
/**
* [Please add a description.]
*/
doDefaultExportInterop(node) {
return (t.isExportDefaultDeclaration(node) || t.isSpecifierDefault(node)) && !this.noInteropRequireExport && !this.hasNonDefaultExports;
}
/**
* [Please add a description.]
*/
getMetadata() {
var has = false;
for (var node of (this.file.ast.program.body: Array)) {
@ -228,12 +273,20 @@ export default class DefaultFormatter {
}
}
/**
* [Please add a description.]
*/
remapAssignments() {
if (this.hasLocalExports || this.hasLocalImports) {
this.remaps.run();
}
}
/**
* [Please add a description.]
*/
remapExportAssignment(node, exported) {
var assign = node;
@ -248,6 +301,10 @@ export default class DefaultFormatter {
return assign;
}
/**
* [Please add a description.]
*/
_addExport(name, exported) {
var info = this.localExports[name] = this.localExports[name] || {
binding: this.scope.getBindingIdentifier(name),
@ -256,6 +313,10 @@ export default class DefaultFormatter {
info.exported.push(exported);
}
/**
* [Please add a description.]
*/
getExport(node, scope) {
if (!t.isIdentifier(node)) return;
@ -265,6 +326,10 @@ export default class DefaultFormatter {
}
}
/**
* [Please add a description.]
*/
getModuleName() {
var opts = this.file.opts;
// moduleId is n/a if a `getModuleId()` is provided
@ -307,6 +372,10 @@ export default class DefaultFormatter {
}
}
/**
* [Please add a description.]
*/
_pushStatement(ref, nodes) {
if (t.isClass(ref) || t.isFunction(ref)) {
if (ref.id) {
@ -318,6 +387,10 @@ export default class DefaultFormatter {
return ref;
}
/**
* [Please add a description.]
*/
_hoistExport(declar, assign, priority) {
if (t.isFunctionDeclaration(declar)) {
assign._blockHoist = priority || 2;
@ -326,6 +399,10 @@ export default class DefaultFormatter {
return assign;
}
/**
* [Please add a description.]
*/
getExternalReference(node, nodes) {
var ids = this.ids;
var id = node.source.value;
@ -337,21 +414,37 @@ export default class DefaultFormatter {
}
}
/**
* [Please add a description.]
*/
checkExportIdentifier(node) {
if (t.isIdentifier(node, { name: "__esModule" })) {
throw this.file.errorWithNode(node, messages.get("modulesIllegalExportName", node.name));
}
}
/**
* [Please add a description.]
*/
exportAllDeclaration(node, nodes) {
var ref = this.getExternalReference(node, nodes);
nodes.push(this.buildExportsWildcard(ref, node));
}
/**
* [Please add a description.]
*/
isLoose() {
return this.file.isLoose("es6.modules");
}
/**
* [Please add a description.]
*/
exportSpecifier(specifier, node, nodes) {
if (node.source) {
var ref = this.getExternalReference(node, nodes);
@ -376,6 +469,10 @@ export default class DefaultFormatter {
}
}
/**
* [Please add a description.]
*/
buildExportsWildcard(objectIdentifier) {
return t.expressionStatement(t.callExpression(this.file.addHelper("defaults"), [
t.identifier("exports"),
@ -383,6 +480,10 @@ export default class DefaultFormatter {
]));
}
/**
* [Please add a description.]
*/
buildExportsFromAssignment(id, init) {
this.checkExportIdentifier(id);
return util.template("exports-from-assign", {
@ -391,6 +492,10 @@ export default class DefaultFormatter {
}, true);
}
/**
* [Please add a description.]
*/
buildExportsAssignment(id, init) {
this.checkExportIdentifier(id);
return util.template("exports-assign", {
@ -399,6 +504,10 @@ export default class DefaultFormatter {
}, true);
}
/**
* [Please add a description.]
*/
exportDeclaration(node, nodes) {
var declar = node.declaration;

View File

@ -1,5 +1,9 @@
import * as util from "../../util";
/**
* [Please add a description.]
*/
export default function (Parent) {
var Constructor = function () {
this.noInteropRequireImport = true;

View File

@ -1,3 +1,8 @@
import AMDFormatter from "./amd";
import buildStrict from "./_strict";
/**
* [Please add a description.]
*/
export default buildStrict(AMDFormatter);

View File

@ -5,11 +5,24 @@ import values from "lodash/object/values";
import * as util from "../../util";
import * as t from "../../types";
/**
* [Please add a description.]
*/
export default class AMDFormatter extends DefaultFormatter {
/**
* [Please add a description.]
*/
setup() {
CommonFormatter.prototype._setup.call(this, this.hasNonDefaultExports);
}
/**
* [Please add a description.]
*/
buildDependencyLiterals() {
var names = [];
for (var name in this.ids) {
@ -64,14 +77,26 @@ export default class AMDFormatter extends DefaultFormatter {
}
}
/**
* [Please add a description.]
*/
_getExternalReference(node) {
return this.scope.generateUidIdentifier(node.source.value);
}
/**
* [Please add a description.]
*/
importDeclaration(node) {
this.getExternalReference(node);
}
/**
* [Please add a description.]
*/
importSpecifier(specifier, node, nodes, scope) {
var key = node.source.value;
var ref = this.getExternalReference(node);
@ -105,6 +130,10 @@ export default class AMDFormatter extends DefaultFormatter {
this.remaps.add(scope, specifier.local.name, ref);
}
/**
* [Please add a description.]
*/
exportSpecifier(specifier, node, nodes) {
if (this.doDefaultExportInterop(specifier)) {
this.passModuleArg = true;
@ -120,6 +149,10 @@ export default class AMDFormatter extends DefaultFormatter {
CommonFormatter.prototype.exportSpecifier.apply(this, arguments);
}
/**
* [Please add a description.]
*/
exportDeclaration(node, nodes) {
if (this.doDefaultExportInterop(node)) {
this.passModuleArg = true;

View File

@ -1,3 +1,8 @@
import CommonFormatter from "./common";
import buildStrict from "./_strict";
/**
* [Please add a description.]
*/
export default buildStrict(CommonFormatter);

View File

@ -2,11 +2,24 @@ import DefaultFormatter from "./_default";
import * as util from "../../util";
import * as t from "../../types";
/**
* [Please add a description.]
*/
export default class CommonJSFormatter extends DefaultFormatter {
/**
* [Please add a description.]
*/
setup() {
this._setup(this.hasLocalExports);
}
/**
* [Please add a description.]
*/
_setup(conditional) {
var file = this.file;
var scope = file.scope;
@ -23,6 +36,10 @@ export default class CommonJSFormatter extends DefaultFormatter {
}
}
/**
* [Please add a description.]
*/
transform(program) {
DefaultFormatter.prototype.transform.apply(this, arguments);
@ -37,6 +54,10 @@ export default class CommonJSFormatter extends DefaultFormatter {
}
}
/**
* [Please add a description.]
*/
importSpecifier(specifier, node, nodes, scope) {
var variableName = specifier.local;
@ -76,6 +97,10 @@ export default class CommonJSFormatter extends DefaultFormatter {
}
}
/**
* [Please add a description.]
*/
importDeclaration(node, nodes) {
// import "foo";
nodes.push(util.template("require", {
@ -83,6 +108,10 @@ export default class CommonJSFormatter extends DefaultFormatter {
}, true));
}
/**
* [Please add a description.]
*/
exportSpecifier(specifier) {
if (this.doDefaultExportInterop(specifier)) {
this.hasDefaultOnlyExport = true;
@ -91,6 +120,10 @@ export default class CommonJSFormatter extends DefaultFormatter {
DefaultFormatter.prototype.exportSpecifier.apply(this, arguments);
}
/**
* [Please add a description.]
*/
exportDeclaration(node) {
if (this.doDefaultExportInterop(node)) {
this.hasDefaultOnlyExport = true;
@ -99,6 +132,10 @@ export default class CommonJSFormatter extends DefaultFormatter {
DefaultFormatter.prototype.exportDeclaration.apply(this, arguments);
}
/**
* [Please add a description.]
*/
_getExternalReference(node, nodes) {
var call = t.callExpression(t.identifier("require"), [node.source]);
var uid;

View File

@ -1,12 +1,25 @@
import DefaultFormatter from "./_default";
import * as t from "../../types";
/**
* [Please add a description.]
*/
export default class IgnoreFormatter extends DefaultFormatter {
/**
* [Please add a description.]
*/
exportDeclaration(node, nodes) {
var declar = t.toStatement(node.declaration, true);
if (declar) nodes.push(t.inherits(declar, node));
}
/**
* [Please add a description.]
*/
exportAllDeclaration() {}
importDeclaration() {}
importSpecifier() {}

View File

@ -1,3 +1,7 @@
/**
* [Please add a description.]
*/
export default {
commonStrict: require("./common-strict"),
amdStrict: require("./amd-strict"),

View File

@ -1,12 +1,25 @@
import * as t from "../../../types";
/**
* [Please add a description.]
*/
var remapVisitor = {
/**
* [Please add a description.]
*/
enter(node) {
if (node._skipModulesRemap) {
return this.skip();
}
},
/**
* [Please add a description.]
*/
ReferencedIdentifier(node, parent, scope, remaps) {
var { formatter } = remaps;
@ -23,6 +36,10 @@ var remapVisitor = {
}
},
/**
* [Please add a description.]
*/
AssignmentExpression: {
exit(node, parent, scope, { formatter }) {
if (!node._ignoreModulesRemap) {
@ -34,6 +51,10 @@ var remapVisitor = {
}
},
/**
* [Please add a description.]
*/
UpdateExpression(node, parent, scope, { formatter }) {
var exported = formatter.getExport(node.argument, scope);
if (!exported) return;
@ -65,24 +86,45 @@ var remapVisitor = {
return t.sequenceExpression(nodes);
}
};
/**
* [Please add a description.]
*/
export default class Remaps {
constructor(file, formatter) {
this.formatter = formatter;
this.file = file;
}
/**
* [Please add a description.]
*/
run() {
this.file.path.traverse(remapVisitor, this);
}
/**
* [Please add a description.]
*/
_getKey(name) {
return `${name}:moduleRemap`;
}
/**
* [Please add a description.]
*/
get(scope, name) {
return scope.getData(this._getKey(name));
}
/**
* [Please add a description.]
*/
add(scope, name, val) {
if (this.all) {
this.all.push({
@ -95,6 +137,10 @@ export default class Remaps {
return scope.setData(this._getKey(name), val);
}
/**
* [Please add a description.]
*/
remove(scope, name) {
return scope.removeData(this._getKey(name));
}
@ -109,6 +155,10 @@ export default class Remaps {
return this.all;
}
/**
* [Please add a description.]
*/
clearAll() {
if (this.all) {
for (var remap of (this.all: Array)) {

View File

@ -5,12 +5,25 @@ import last from "lodash/array/last";
import map from "lodash/collection/map";
import * as t from "../../types";
/**
* [Please add a description.]
*/
var hoistVariablesVisitor = {
/**
* [Please add a description.]
*/
Function() {
// nothing inside is accessible
this.skip();
},
/**
* [Please add a description.]
*/
VariableDeclaration(node, parent, scope, state) {
if (node.kind !== "var" && !t.isProgram(parent)) { // let, const
// can't be accessed
@ -41,11 +54,24 @@ var hoistVariablesVisitor = {
}
};
/**
* [Please add a description.]
*/
var hoistFunctionsVisitor = {
/**
* [Please add a description.]
*/
Function() {
this.skip();
},
/**
* [Please add a description.]
*/
enter(node, parent, scope, state) {
if (t.isFunctionDeclaration(node) || state.formatter._canHoist(node)) {
state.handlerBody.push(node);
@ -54,7 +80,16 @@ var hoistFunctionsVisitor = {
}
};
/**
* [Please add a description.]
*/
var runnerSettersVisitor = {
/**
* [Please add a description.]
*/
enter(node, parent, scope, state) {
if (node._importSource === state.source) {
if (t.isVariableDeclaration(node)) {
@ -73,6 +108,10 @@ var runnerSettersVisitor = {
}
};
/**
* [Please add a description.]
*/
export default class SystemFormatter extends AMDFormatter {
constructor(file) {
super(file);
@ -85,11 +124,19 @@ export default class SystemFormatter extends AMDFormatter {
this.remaps.clearAll();
}
/**
* [Please add a description.]
*/
_addImportSource(node, exportNode) {
if (node) node._importSource = exportNode.source && exportNode.source.value;
return node;
}
/**
* [Please add a description.]
*/
buildExportsWildcard(objectIdentifier, node) {
var leftIdentifier = this.scope.generateUidIdentifier("key");
var valIdentifier = t.memberExpression(objectIdentifier, leftIdentifier, true);
@ -107,15 +154,27 @@ export default class SystemFormatter extends AMDFormatter {
return this._addImportSource(t.forInStatement(left, right, block), node);
}
/**
* [Please add a description.]
*/
buildExportsAssignment(id, init, node) {
var call = this._buildExportCall(t.literal(id.name), init, true);
return this._addImportSource(call, node);
}
/**
* [Please add a description.]
*/
buildExportsFromAssignment() {
return this.buildExportsAssignment(...arguments);
}
/**
* [Please add a description.]
*/
remapExportAssignment(node, exported) {
var assign = node;
@ -126,6 +185,10 @@ export default class SystemFormatter extends AMDFormatter {
return assign;
}
/**
* [Please add a description.]
*/
_buildExportCall(id, init, isStatement) {
var call = t.callExpression(this.exportIdentifier, [id, init]);
if (isStatement) {
@ -135,6 +198,10 @@ export default class SystemFormatter extends AMDFormatter {
}
}
/**
* [Please add a description.]
*/
importSpecifier(specifier, node, nodes) {
AMDFormatter.prototype.importSpecifier.apply(this, arguments);
@ -149,6 +216,10 @@ export default class SystemFormatter extends AMDFormatter {
this._addImportSource(last(nodes), node);
}
/**
* [Please add a description.]
*/
_buildRunnerSetters(block, hoistDeclarators) {
var scope = this.file.scope;
@ -165,10 +236,18 @@ export default class SystemFormatter extends AMDFormatter {
}));
}
/**
* [Please add a description.]
*/
_canHoist(node) {
return node._blockHoist && !this.file.dynamicImports.length;
}
/**
* [Please add a description.]
*/
transform(program) {
DefaultFormatter.prototype.transform.apply(this, arguments);

View File

@ -1,3 +1,8 @@
import UMDFormatter from "./umd";
import buildStrict from "./_strict";
/**
* [Please add a description.]
*/
export default buildStrict(UMDFormatter);

View File

@ -5,7 +5,16 @@ import path from "path";
import * as util from "../../util";
import * as t from "../../types";
/**
* [Please add a description.]
*/
export default class UMDFormatter extends AMDFormatter {
/**
* [Please add a description.]
*/
transform(program) {
DefaultFormatter.prototype.transform.apply(this, arguments);

View File

@ -5,6 +5,10 @@ import assign from "lodash/object/assign";
import object from "../helpers/object";
import File from "./file";
/**
* [Please add a description.]
*/
export default class Pipeline {
constructor() {
this.transformers = object();
@ -14,6 +18,10 @@ export default class Pipeline {
this.filters = [];
}
/**
* [Please add a description.]
*/
addTransformers(transformers) {
for (var key in transformers) {
this.addTransformer(key, transformers[key]);
@ -21,6 +29,10 @@ export default class Pipeline {
return this;
}
/**
* [Please add a description.]
*/
addTransformer(key, plugin) {
if (this.transformers[key]) throw new Error(); // todo: error
@ -44,21 +56,37 @@ export default class Pipeline {
this.transformers[key] = plugin;
}
/**
* [Please add a description.]
*/
addAliases(names) {
assign(this.aliases, names);
return this;
}
/**
* [Please add a description.]
*/
addDeprecated(names) {
assign(this.deprecated, names);
return this;
}
/**
* [Please add a description.]
*/
addFilter(filter: Function) {
this.filters.push(filter);
return this;
}
/**
* [Please add a description.]
*/
canTransform(plugin, fileOpts) {
if (plugin.metadata.plugin) {
return true;
@ -72,11 +100,19 @@ export default class Pipeline {
return true;
}
/**
* [Please add a description.]
*/
analyze(code: string, opts?: Object = {}) {
opts.code = false;
return this.transform(code, opts);
}
/**
* [Please add a description.]
*/
pretransform(code: string, opts?: Object) {
var file = new File(opts, this);
return file.wrap(code, function () {
@ -86,6 +122,10 @@ export default class Pipeline {
});
}
/**
* [Please add a description.]
*/
transform(code: string, opts?: Object) {
var file = new File(opts, this);
return file.wrap(code, function () {
@ -95,6 +135,10 @@ export default class Pipeline {
});
}
/**
* [Please add a description.]
*/
transformFromAst(ast, code, opts) {
ast = normalizeAst(ast);
@ -106,6 +150,10 @@ export default class Pipeline {
});
}
/**
* [Please add a description.]
*/
_ensureTransformerNames(type: string, rawKeys: Array<string>) {
var keys = [];

View File

@ -20,11 +20,19 @@ export default class PluginPass {
}
}
/**
* [Please add a description.]
*/
canTransform(): boolean {
return this.file.transformerDependencies[this.key] ||
this.file.pipeline.canTransform(this.plugin, this.file.opts);
}
/**
* [Please add a description.]
*/
transform() {
var file = this.file;
file.log.debug(`Start transformer ${this.key}`);

View File

@ -21,6 +21,10 @@ const VALID_METADATA_PROPERTES = [
"secondPass"
];
/**
* [Please add a description.]
*/
export default class Plugin {
constructor(key: string, plugin: Object) {
Plugin.validate(key, plugin);
@ -51,6 +55,10 @@ export default class Plugin {
this.key = key;
}
/**
* [Please add a description.]
*/
static validate(name, plugin) {
for (let key in plugin) {
if (key[0] === "_") continue;
@ -68,11 +76,19 @@ export default class Plugin {
}
}
/**
* [Please add a description.]
*/
normalize(visitor: Object): Object {
traverse.explode(visitor);
return visitor;
}
/**
* [Please add a description.]
*/
buildPass(file: File): PluginPass {
// validate Transformer instance
if (!(file instanceof File)) {

View File

@ -0,0 +1,3 @@
## Transformation Templates
This is the Transformation Templates directory.

View File

@ -1,5 +1,9 @@
import Plugin from "./plugin";
/**
* [Please add a description.]
*/
export default class Transformer {
constructor(key, obj) {
var plugin = {};

View File

@ -0,0 +1,3 @@
## Transformers
This is the Transformers directory.

View File

@ -4,7 +4,31 @@ export var metadata = {
group: "builtin-trailing"
};
/**
* Turn member expression reserved word properties into literals.
*
* @example
*
* **In**
*
* ```javascript
* foo.catch;
* ```
*
* **Out**
*
* ```javascript
* foo["catch"];
* ```
*/
export var visitor = {
/**
* Look for non-computed properties with names that are not valid identifiers.
* Turn them into computed properties with literal names.
*/
MemberExpression: {
exit(node) {
var prop = node.property;

View File

@ -4,7 +4,33 @@ export var metadata = {
group: "builtin-trailing"
};
/**
* Turn reserved word properties into literals.
*
* **In**
*
* ```javascript
* var foo = {
* catch: function () {}
* };
* ```
*
* **Out**
*
* ```javascript
* var foo = {
* "catch": function () {}
* };
* ```
*/
export var visitor = {
/**
* Look for non-computed keys with names that are not valid identifiers.
* Turn them into literals.
*/
Property: {
exit(node) {
var key = node.key;

View File

@ -1,7 +1,43 @@
import * as defineMap from "../../helpers/define-map";
import * as t from "../../../types";
/**
* Turn [object initializer mutators](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Object_initializer#Method_definitions)
* into `Object.defineProperties`.
*
* **In**
*
* ```javascript
* var foo = {
* get bar() {
* return "bar";
* }
* };
* ```
*
* **Out**
*
* ```javascript
* var foo = Object.defineProperties({}, {
* bar: {
* get: function () {
* return "bar";
* },
* enumerable: true,
* configurable: true
* }
* });
* ```
*/
export var visitor = {
/**
* Look for getters and setters on an object.
* Filter them out and wrap the object with an `Object.defineProperties` that
* defines the getters and setters.
*/
ObjectExpression(node, parent, scope, file) {
var hasAny = false;
for (var prop of (node.properties: Array)) {

View File

@ -1,4 +1,29 @@
/**
* Turn arrow functions into normal functions.
*
* @example
*
* **In**
*
* ```javascript
* arr.map(x => x * x);
* ```
*
* **Out**
*
* ```javascript
* arr.map(function (x) {
* return x * x;
* });
*/
export var visitor = {
/**
* Look for arrow functions and mark them as "shadow functions".
* @see /transformation/transformers/internal/shadow-functions.js
*/
ArrowFunctionExpression(node) {
this.ensureBlock();
node.expression = false;

View File

@ -8,6 +8,10 @@ import * as t from "../../../types";
import values from "lodash/object/values";
import extend from "lodash/object/extend";
/**
* [Please add a description.]
*/
function isLet(node, parent) {
if (!t.isVariableDeclaration(node)) return false;
if (node._let) return true;
@ -26,14 +30,26 @@ function isLet(node, parent) {
return true;
}
/**
* [Please add a description.]
*/
function isLetInitable(node, parent) {
return !t.isFor(parent) || !t.isFor(parent, { left: node });
}
/**
* [Please add a description.]
*/
function isVar(node, parent) {
return t.isVariableDeclaration(node, { kind: "var" }) && !isLet(node, parent);
}
/**
* [Please add a description.]
*/
function standardizeLets(declars) {
for (var declar of (declars: Array)) {
delete declar._let;
@ -44,7 +60,16 @@ export var metadata = {
group: "builtin-advanced"
};
/**
* [Please add a description.]
*/
export var visitor = {
/**
* [Please add a description.]
*/
VariableDeclaration(node, parent, scope, file) {
if (!isLet(node, parent)) return;
@ -67,6 +92,10 @@ export var visitor = {
}
},
/**
* [Please add a description.]
*/
Loop(node, parent, scope, file) {
var init = node.left || node.init;
if (isLet(init, node)) {
@ -78,6 +107,10 @@ export var visitor = {
return blockScoping.run();
},
/**
* [Please add a description.]
*/
"BlockStatement|Program"(block, parent, scope, file) {
if (!t.isLoop(parent)) {
var blockScoping = new BlockScoping(null, this, parent, scope, file);
@ -86,6 +119,10 @@ export var visitor = {
}
};
/**
* [Please add a description.]
*/
function replace(node, parent, scope, remaps) {
var remap = remaps[node.name];
if (!remap) return;
@ -100,9 +137,17 @@ function replace(node, parent, scope, remaps) {
}
}
/**
* [Please add a description.]
*/
var replaceVisitor = {
ReferencedIdentifier: replace,
/**
* [Please add a description.]
*/
AssignmentExpression(node, parent, scope, remaps) {
var ids = this.getBindingIdentifiers();
for (var name in ids) {
@ -111,6 +156,10 @@ var replaceVisitor = {
},
};
/**
* [Please add a description.]
*/
function traverseReplace(node, parent, scope, remaps) {
if (t.isIdentifier(node)) {
replace(node, parent, scope, remaps);
@ -126,14 +175,32 @@ function traverseReplace(node, parent, scope, remaps) {
scope.traverse(node, replaceVisitor, remaps);
}
/**
* [Please add a description.]
*/
var letReferenceBlockVisitor = {
/**
* [Please add a description.]
*/
Function(node, parent, scope, state) {
this.traverse(letReferenceFunctionVisitor, state);
return this.skip();
}
};
/**
* [Please add a description.]
*/
var letReferenceFunctionVisitor = {
/**
* [Please add a description.]
*/
ReferencedIdentifier(node, parent, scope, state) {
var ref = state.letReferences[node.name];
@ -148,6 +215,10 @@ var letReferenceFunctionVisitor = {
}
};
/**
* [Please add a description.]
*/
var hoistVarDeclarationsVisitor = {
enter(node, parent, scope, self) {
if (this.isForStatement()) {
@ -172,12 +243,20 @@ var hoistVarDeclarationsVisitor = {
}
};
/**
* [Please add a description.]
*/
var loopLabelVisitor = {
LabeledStatement(node, parent, scope, state) {
state.innerLabels.push(node.label.name);
}
};
/**
* [Please add a description.]
*/
var continuationVisitor = {
enter(node, parent, scope, state) {
if (this.isAssignmentExpression() || this.isUpdateExpression()) {
@ -190,6 +269,10 @@ var continuationVisitor = {
}
};
/**
* [Please add a description.]
*/
var loopNodeTo = function (node) {
if (t.isBreakStatement(node)) {
return "break";
@ -198,7 +281,16 @@ var loopNodeTo = function (node) {
}
};
/**
* [Please add a description.]
*/
var loopVisitor = {
/**
* [Please add a description.]
*/
Loop(node, parent, scope, state) {
var oldIgnoreLabeless = state.ignoreLabeless;
state.ignoreLabeless = true;
@ -207,10 +299,18 @@ var loopVisitor = {
this.skip();
},
/**
* [Please add a description.]
*/
Function() {
this.skip();
},
/**
* [Please add a description.]
*/
SwitchCase(node, parent, scope, state) {
var oldInSwitchCase = state.inSwitchCase;
state.inSwitchCase = true;
@ -219,6 +319,10 @@ var loopVisitor = {
this.skip();
},
/**
* [Please add a description.]
*/
enter(node, parent, scope, state) {
var replace;
var loopText = loopNodeTo(node);
@ -263,12 +367,11 @@ var loopVisitor = {
}
};
/**
* [Please add a description.]
*/
class BlockScoping {
/**
* Description
*/
constructor(loopPath?: NodePath, blockPath: NodePath, parent: Object, scope: Scope, file: File) {
this.parent = parent;
this.scope = scope;
@ -319,7 +422,7 @@ class BlockScoping {
}
/**
* Description
* [Please add a description.]
*/
remap() {
@ -366,7 +469,7 @@ class BlockScoping {
}
/**
* Description
* [Please add a description.]
*/
wrapClosure() {
@ -486,7 +589,7 @@ class BlockScoping {
}
/**
* Description
* [Please add a description.]
*/
getLetReferences() {
@ -599,7 +702,7 @@ class BlockScoping {
}
/**
* Description
* [Please add a description.]
*/
buildHas(ret: { type: "Identifier" }, call: { type: "CallExpression" }) {

View File

@ -3,13 +3,26 @@ import VanillaTransformer from "./vanilla";
import * as t from "../../../../types";
import { bare } from "../../../helpers/name-method";
/**
* [Please add a description.]
*/
export var visitor = {
/**
* [Please add a description.]
*/
ClassDeclaration(node) {
return t.variableDeclaration("let", [
t.variableDeclarator(node.id, t.toExpression(node))
]);
},
/**
* [Please add a description.]
*/
ClassExpression(node, parent, scope, file) {
var inferred = bare(node, parent, scope);
if (inferred) return inferred;

View File

@ -1,12 +1,20 @@
import VanillaTransformer from "./vanilla";
import * as t from "../../../../types";
/**
* [Please add a description.]
*/
export default class LooseClassTransformer extends VanillaTransformer {
constructor() {
super(...arguments);
this.isLoose = true;
}
/**
* [Please add a description.]
*/
_processMethod(node) {
if (!node.decorators) {
// use assignments instead of define properties for loose classes

View File

@ -10,7 +10,16 @@ import * as t from "../../../../types";
const PROPERTY_COLLISION_METHOD_NAME = "__initializeProperties";
/**
* [Please add a description.]
*/
var collectPropertyReferencesVisitor = {
/**
* [Please add a description.]
*/
Identifier: {
enter(node, parent, scope, state) {
if (this.parentPath.isClassProperty({ key: node })) {
@ -24,15 +33,32 @@ var collectPropertyReferencesVisitor = {
}
};
/**
* [Please add a description.]
*/
var verifyConstructorVisitor = {
/**
* [Please add a description.]
*/
MethodDefinition() {
this.skip();
},
/**
* [Please add a description.]
*/
Property(node) {
if (node.method) this.skip();
},
/**
* [Please add a description.]
*/
CallExpression: {
exit(node, parent, scope, state) {
if (this.get("callee").isSuper()) {
@ -46,10 +72,18 @@ var verifyConstructorVisitor = {
}
},
/**
* [Please add a description.]
*/
"FunctionDeclaration|FunctionExpression"() {
this.skip();
},
/**
* [Please add a description.]
*/
ThisExpression(node, parent, scope, state) {
if (state.isDerived && !state.hasBareSuper) {
if (this.inShadow()) {
@ -70,6 +104,10 @@ var verifyConstructorVisitor = {
}
},
/**
* [Please add a description.]
*/
Super(node, parent, scope, state) {
if (state.isDerived && !state.hasBareSuper && !this.parentPath.isCallExpression({ callee: node })) {
throw this.errorWithNode("'super.*' is not allowed before super()");
@ -77,12 +115,11 @@ var verifyConstructorVisitor = {
}
};
/**
* [Please add a description.]
*/
export default class ClassTransformer {
/**
* Description
*/
constructor(path: NodePath, file: File) {
this.parent = path.parent;
this.scope = path.scope;
@ -116,8 +153,7 @@ export default class ClassTransformer {
}
/**
* Description
*
* [Please add a description.]
* @returns {Array}
*/
@ -187,7 +223,7 @@ export default class ClassTransformer {
}
/**
* Description
* [Please add a description.]
*/
buildConstructor() {
@ -195,7 +231,7 @@ export default class ClassTransformer {
}
/**
* Description
* [Please add a description.]
*/
pushToMap(node, enumerable, kind = "value") {
@ -220,6 +256,7 @@ export default class ClassTransformer {
}
/**
* [Please add a description.]
* https://www.youtube.com/watch?v=fWNaR-rxAic
*/
@ -247,7 +284,7 @@ export default class ClassTransformer {
}
/**
* Description
* [Please add a description.]
*/
buildBody() {
@ -266,7 +303,7 @@ export default class ClassTransformer {
}
/**
* Description
* [Please add a description.]
*/
pushBody() {
@ -308,7 +345,7 @@ export default class ClassTransformer {
}
/**
* Description
* [Please add a description.]
*/
clearDescriptors() {
@ -320,7 +357,7 @@ export default class ClassTransformer {
}
/**
* Description
* [Please add a description.]
*/
pushDescriptors() {
@ -379,7 +416,7 @@ export default class ClassTransformer {
}
/**
* Description
* [Please add a description.]
*/
buildObjectAssignment(id) {
@ -389,7 +426,7 @@ export default class ClassTransformer {
}
/**
* Description
* [Please add a description.]
*/
placePropertyInitializers() {
@ -422,7 +459,7 @@ export default class ClassTransformer {
}
/**
* Description
* [Please add a description.]
*/
hasPropertyCollision(): boolean {
@ -438,7 +475,7 @@ export default class ClassTransformer {
}
/**
* Description
* [Please add a description.]
*/
verifyConstructor(path: NodePath) {
@ -483,12 +520,16 @@ export default class ClassTransformer {
this.pushToMap(node);
}
/**
* [Please add a description.]
*/
_processMethod() {
return false;
}
/**
* Description
* [Please add a description.]
*/
pushProperty(node: { type: "ClassProperty" }, path: NodePath) {
@ -571,6 +612,10 @@ export default class ClassTransformer {
this._pushConstructor();
}
/**
* [Please add a description.]
*/
_pushConstructor() {
if (this.pushedConstructor) return;
this.pushedConstructor = true;

View File

@ -1,6 +1,31 @@
import * as messages from "../../../messages";
/**
* Turn constants into variables.
* Ensure there are no constant violations in any scope.
*
* @example
*
* **In**
*
* ```javascript
* const MULTIPLIER = 5;
* ```
*
* **Out**
*
* ```javascript
* var MULTIPLIER = 5;
* ```
*/
export var visitor = {
/**
* Look for any constants (or modules) in scope.
* If they have any `constantViolations` throw an error.
*/
Scope(node, parent, scope) {
for (var name in scope.bindings) {
var binding = scope.bindings[name];
@ -14,6 +39,11 @@ export var visitor = {
}
},
/**
* Look for constants.
* Turn them into `let` variables.
*/
VariableDeclaration(node) {
if (node.kind === "const") node.kind = "let";
}

View File

@ -5,7 +5,16 @@ export var metadata = {
group: "builtin-advanced"
};
/**
* [Please add a description.]
*/
export var visitor = {
/**
* [Please add a description.]
*/
ForXStatement(node, parent, scope, file) {
var left = node.left;
@ -54,6 +63,10 @@ export var visitor = {
block.body = nodes.concat(block.body);
},
/**
* [Please add a description.]
*/
Function(node, parent, scope, file) {
var hasDestructuring = false;
for (let pattern of (node.params: Array)) {
@ -98,6 +111,10 @@ export var visitor = {
block.body = nodes.concat(block.body);
},
/**
* [Please add a description.]
*/
CatchClause(node, parent, scope, file) {
var pattern = node.param;
if (!t.isPattern(pattern)) return;
@ -118,6 +135,10 @@ export var visitor = {
node.body.body = nodes.concat(node.body.body);
},
/**
* [Please add a description.]
*/
AssignmentExpression(node, parent, scope, file) {
if (!t.isPattern(node.left)) return;
@ -152,6 +173,10 @@ export var visitor = {
return nodes;
},
/**
* [Please add a description.]
*/
VariableDeclaration(node, parent, scope, file) {
if (t.isForXStatement(parent)) return;
if (!variableDeclarationHasPattern(node)) return;
@ -209,6 +234,10 @@ export var visitor = {
}
};
/**
* Test if a VariableDeclaration's declarations contains any Patterns.
*/
function variableDeclarationHasPattern(node) {
for (var i = 0; i < node.declarations.length; i++) {
if (t.isPattern(node.declarations[i].id)) {
@ -218,6 +247,10 @@ function variableDeclarationHasPattern(node) {
return false;
}
/**
* Test if an ArrayPattern's elements contain any RestElements.
*/
function hasRest(pattern) {
for (var i = 0; i < pattern.elements.length; i++) {
if (t.isRestElement(pattern.elements[i])) {
@ -227,7 +260,16 @@ function hasRest(pattern) {
return false;
}
/**
* [Please add a description.]
*/
var arrayUnpackVisitor = {
/**
* [Please add a description.]
*/
ReferencedIdentifier(node, parent, scope, state) {
if (state.bindings[node.name]) {
state.deopt = true;
@ -236,6 +278,10 @@ var arrayUnpackVisitor = {
}
};
/**
* [Please add a description.]
*/
class DestructuringTransformer {
constructor(opts) {
this.blockHoist = opts.blockHoist;
@ -247,6 +293,10 @@ class DestructuringTransformer {
this.kind = opts.kind;
}
/**
* [Please add a description.]
*/
buildVariableAssignment(id, init) {
var op = this.operator;
if (t.isMemberExpression(id)) op = "=";
@ -266,6 +316,10 @@ class DestructuringTransformer {
return node;
}
/**
* [Please add a description.]
*/
buildVariableDeclaration(id, init) {
var declar = t.variableDeclaration("var", [
t.variableDeclarator(id, init)
@ -274,6 +328,10 @@ class DestructuringTransformer {
return declar;
}
/**
* [Please add a description.]
*/
push(id, init) {
if (t.isObjectPattern(id)) {
this.pushObjectPattern(id, init);
@ -286,6 +344,10 @@ class DestructuringTransformer {
}
}
/**
* [Please add a description.]
*/
toArray(node, count) {
if (this.file.isLoose("es6.destructuring") || (t.isIdentifier(node) && this.arrays[node.name])) {
return node;
@ -294,6 +356,10 @@ class DestructuringTransformer {
}
}
/**
* [Please add a description.]
*/
pushAssignmentPattern(pattern, valueRef) {
// we need to assign the current value of the assignment to avoid evaluating
// it more than once
@ -328,6 +394,10 @@ class DestructuringTransformer {
}
}
/**
* [Please add a description.]
*/
pushObjectSpread(pattern, objRef, spreadProp, spreadPropIndex) {
// get all the keys that appear in this object before the current spread
@ -356,6 +426,10 @@ class DestructuringTransformer {
this.nodes.push(this.buildVariableAssignment(spreadProp.argument, value));
}
/**
* [Please add a description.]
*/
pushObjectProperty(prop, propRef) {
if (t.isLiteral(prop.key)) prop.computed = true;
@ -369,6 +443,10 @@ class DestructuringTransformer {
}
}
/**
* [Please add a description.]
*/
pushObjectPattern(pattern, objRef) {
// https://github.com/babel/babel/issues/681
@ -400,6 +478,10 @@ class DestructuringTransformer {
}
}
/**
* [Please add a description.]
*/
canUnpackArrayPattern(pattern, arr) {
// not an array so there's no way we can deal with this
if (!t.isArrayExpression(arr)) return false;
@ -426,6 +508,10 @@ class DestructuringTransformer {
return !state.deopt;
}
/**
* [Please add a description.]
*/
pushUnpackedArrayPattern(pattern, arr) {
for (var i = 0; i < pattern.elements.length; i++) {
var elem = pattern.elements[i];
@ -437,6 +523,10 @@ class DestructuringTransformer {
}
}
/**
* [Please add a description.]
*/
pushArrayPattern(pattern, arrayRef) {
if (!pattern.elements) return;
@ -500,6 +590,10 @@ class DestructuringTransformer {
}
}
/**
* [Please add a description.]
*/
init(pattern, ref) {
// trying to destructure a value that we can't evaluate more than once so we
// need to save it to a variable

View File

@ -2,7 +2,16 @@ import * as messages from "../../../messages";
import * as util from "../../../util";
import * as t from "../../../types";
/**
* [Please add a description.]
*/
export var visitor = {
/**
* [Please add a description.]
*/
ForOfStatement(node, parent, scope, file) {
if (this.get("right").isArrayExpression()) {
return _ForOfStatementArray.call(this, node, scope, file);
@ -39,6 +48,10 @@ export var visitor = {
}
};
/**
* [Please add a description.]
*/
export function _ForOfStatementArray(node, scope, file) {
var nodes = [];
var right = node.right;
@ -81,6 +94,10 @@ export function _ForOfStatementArray(node, scope, file) {
return nodes;
}
/**
* [Please add a description.]
*/
var loose = function (node, parent, scope, file) {
var left = node.left;
var declar, id;
@ -124,6 +141,10 @@ var loose = function (node, parent, scope, file) {
};
};
/**
* [Please add a description.]
*/
var spec = function (node, parent, scope, file) {
var left = node.left;
var declar;

View File

@ -12,7 +12,16 @@ export var metadata = {
group: "builtin-modules"
};
/**
* [Please add a description.]
*/
export var visitor = {
/**
* [Please add a description.]
*/
ImportDeclaration(node, parent, scope, file) {
// flow type
if (node.importKind === "type" || node.importKind === "typeof") return;
@ -35,6 +44,10 @@ export var visitor = {
return nodes;
},
/**
* [Please add a description.]
*/
ExportAllDeclaration(node, parent, scope, file) {
var nodes = [];
file.moduleFormatter.exportAllDeclaration(node, nodes, scope);
@ -42,6 +55,10 @@ export var visitor = {
return nodes;
},
/**
* [Please add a description.]
*/
ExportDefaultDeclaration(node, parent, scope, file) {
var nodes = [];
file.moduleFormatter.exportDeclaration(node, nodes, scope);
@ -49,6 +66,10 @@ export var visitor = {
return nodes;
},
/**
* [Please add a description.]
*/
ExportNamedDeclaration(node, parent, scope, file) {
// flow type
if (this.get("declaration").isTypeAlias()) return;

View File

@ -1,6 +1,10 @@
import ReplaceSupers from "../../helpers/replace-supers";
import * as t from "../../../types";
/**
* [Please add a description.]
*/
function Property(path, node, scope, getObjectRef, file) {
if (!node.method && node.kind === "init") return;
if (!t.isFunction(node.value)) return;
@ -17,7 +21,16 @@ function Property(path, node, scope, getObjectRef, file) {
replaceSupers.replace();
}
/**
* [Please add a description.]
*/
export var visitor = {
/**
* [Please add a description.]
*/
ObjectExpression(node, parent, scope, file) {
var objectRef;
var getObjectRef = () => objectRef = objectRef || scope.generateUidIdentifier("obj");

View File

@ -3,6 +3,10 @@ import getFunctionArity from "../../../helpers/get-function-arity";
import * as util from "../../../../util";
import * as t from "../../../../types";
/**
* [Please add a description.]
*/
var hasDefaults = function (node) {
for (var i = 0; i < node.params.length; i++) {
if (!t.isIdentifier(node.params[i])) return true;
@ -10,7 +14,16 @@ var hasDefaults = function (node) {
return false;
};
/**
* [Please add a description.]
*/
var iifeVisitor = {
/**
* [Please add a description.]
*/
ReferencedIdentifier(node, parent, scope, state) {
if (node.name !== "eval") {
if (!state.scope.hasOwnBinding(node.name)) return;
@ -22,7 +35,16 @@ var iifeVisitor = {
}
};
/**
* [Please add a description.]
*/
export var visitor = {
/**
* [Please add a description.]
*/
Function(node, parent, scope, file) {
if (!hasDefaults(node)) return;

View File

@ -7,4 +7,8 @@ export var metadata = {
group: "builtin-advanced"
};
/**
* [Please add a description.]
*/
export var visitor = visitors.merge([rest.visitor, def.visitor]);

View File

@ -1,7 +1,16 @@
import * as util from "../../../../util";
import * as t from "../../../../types";
/**
* [Please add a description.]
*/
var memberExpressionOptimisationVisitor = {
/**
* [Please add a description.]
*/
Scope(node, parent, scope, state) {
// check if this scope has a local binding that will shadow the rest parameter
if (!scope.bindingIdentifierEquals(state.name, state.outerBinding)) {
@ -9,11 +18,19 @@ var memberExpressionOptimisationVisitor = {
}
},
/**
* [Please add a description.]
*/
Flow() {
// don't touch reference in type annotations
this.skip();
},
/**
* [Please add a description.]
*/
Function(node, parent, scope, state) {
// skip over functions as whatever `arguments` we reference inside will refer
// to the wrong function
@ -24,6 +41,10 @@ var memberExpressionOptimisationVisitor = {
this.skip();
},
/**
* [Please add a description.]
*/
ReferencedIdentifier(node, parent, scope, state) {
// we can't guarantee the purity of arguments
if (node.name === "arguments") {
@ -60,6 +81,10 @@ var memberExpressionOptimisationVisitor = {
}
};
/**
* [Please add a description.]
*/
function optimiseMemberExpression(parent, offset) {
if (offset === 0) return;
@ -75,11 +100,24 @@ function optimiseMemberExpression(parent, offset) {
}
}
/**
* [Please add a description.]
*/
function hasRest(node) {
return t.isRestElement(node.params[node.params.length - 1]);
}
/**
* [Please add a description.]
*/
export var visitor = {
/**
* [Please add a description.]
*/
Function(node, parent, scope) {
if (!hasRest(node)) return;

View File

@ -1,5 +1,9 @@
import * as t from "../../../types";
/**
* [Please add a description.]
*/
function loose(node, body, objId) {
for (var prop of (node.properties: Array)) {
body.push(t.expressionStatement(
@ -12,6 +16,10 @@ function loose(node, body, objId) {
}
}
/**
* [Please add a description.]
*/
function spec(node, body, objId, initProps, file) {
// add a simple assignment for all Symbol member expressions due to symbol polyfill limitations
// otherwise use Object.defineProperty
@ -45,7 +53,16 @@ function spec(node, body, objId, initProps, file) {
}
}
/**
* [Please add a description.]
*/
export var visitor = {
/**
* [Please add a description.]
*/
ObjectExpression: {
exit(node, parent, scope, file) {
var hasComputed = false;

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