Merge branch 'master' of github.com:6to5/6to5 into amd-module-id

Conflicts:
	lib/6to5/file.js
	lib/6to5/transformation/modules/umd.js
This commit is contained in:
Lars Kappert 2014-11-19 08:39:02 +01:00
commit a37f2093bc
48 changed files with 983 additions and 655 deletions

View File

@ -1,10 +1,17 @@
# 1.12.21
* Fix unneccesary let scoping replacement.
* Add `commonInterop` module formatter. Thanks [@Naddiseo](https://github.com/Naddiseo).
* Fix `return` outside of function body bug. Thanks [@brentburg](https://github.com/brentburg).
* Add more flexible option types.
# 1.12.20 # 1.12.20
* Append `sourceMappingURL` when using `bin/6to5` and output sourcemaps. * Append `sourceMappingURL` when using `bin/6to5` and output sourcemaps.
# 1.12.19 # 1.12.19
* Add `comments` option and `--remove-comments` flag. Thanks @[webpro](htps://github.com/webpro)! * Add `comments` option and `--remove-comments` flag. Thanks [@webpro](htps://github.com/webpro).
* Embed `regenerator`. * Embed `regenerator`.
# 1.12.18 # 1.12.18
@ -13,7 +20,7 @@
# 1.12.17 # 1.12.17
* Add `moduleName`, `sourceRoot` and `filenameRelative` options - thanks @[darvelo](https://github.com/darvelo)! * Add `moduleName`, `sourceRoot` and `filenameRelative` options. Thanks [@darvelo](https://github.com/darvelo).
* Traversal optimisations. * Traversal optimisations.
# 1.12.16 # 1.12.16

View File

@ -115,10 +115,12 @@ to5.transformFile("filename.js", options, function (err, result) {
sourceFileName: "filename", sourceFileName: "filename",
// The root from which all sources are relative // The root from which all sources are relative
// Default: `moduleRoot` option.
sourceRoot: "assets/scripts", sourceRoot: "assets/scripts",
// Optional prefix for the AMD module formatter that will be prepend to the // Optional prefix for the AMD module formatter that will be prepend to the
// filename on module definitions // filename on module definitions
// Default: `sourceRoot` option.
moduleRoot: "my-app", moduleRoot: "my-app",
// Optionally replace all 6to5 helper declarations with a referenece to this // Optionally replace all 6to5 helper declarations with a referenece to this

View File

@ -19,7 +19,7 @@ function File(opts) {
} }
File.declarations = ["extends", "class-props", "slice", "apply-constructor", File.declarations = ["extends", "class-props", "slice", "apply-constructor",
"tagged-template-literal"]; "tagged-template-literal", "interop-require"];
File.normaliseOptions = function (opts) { File.normaliseOptions = function (opts) {
opts = _.cloneDeep(opts || {}); opts = _.cloneDeep(opts || {});
@ -39,6 +39,17 @@ File.normaliseOptions = function (opts) {
// normalise windows path separators to unix // normalise windows path separators to unix
opts.filename = opts.filename.replace(/\\/g, "/"); opts.filename = opts.filename.replace(/\\/g, "/");
opts.blacklist = util.arrayify(opts.blacklist);
opts.whitelist = util.arrayify(opts.whitelist);
_.defaults(opts, {
moduleRoot: opts.sourceRoot
});
_.defaults(opts, {
sourceRoot: opts.moduleRoot
});
_.defaults(opts, { _.defaults(opts, {
filenameRelative: opts.filename filenameRelative: opts.filename
}); });
@ -58,8 +69,8 @@ File.normaliseOptions = function (opts) {
return opts; return opts;
}; };
File.prototype.getModuleFormatter = function (type, opts) { File.prototype.getModuleFormatter = function (type) {
var ModuleFormatter = transform.moduleFormatters[type]; var ModuleFormatter = _.isFunction(type) ? type : transform.moduleFormatters[type];
if (!ModuleFormatter) { if (!ModuleFormatter) {
var loc = util.resolve(type); var loc = util.resolve(type);

View File

@ -165,6 +165,8 @@ CodeGenerator.prototype.print = function (node, parent, opts) {
}; };
CodeGenerator.prototype.printJoin = function (print, nodes, opts) { CodeGenerator.prototype.printJoin = function (print, nodes, opts) {
if (!nodes || !nodes.length) return;
opts = opts || {}; opts = opts || {};
var self = this; var self = this;

View File

@ -78,7 +78,7 @@ exports.Literal = function (node) {
val = JSON.stringify(val); val = JSON.stringify(val);
// escape unicode characters // escape unicode characters
val = val.replace(/[\u007f-\uffff]/g, function(c) { val = val.replace(/[\u007f-\uffff]/g, function (c) {
return "\\u" + ("0000" + c.charCodeAt(0).toString(16)).slice(-4); return "\\u" + ("0000" + c.charCodeAt(0).toString(16)).slice(-4);
}); });

View File

@ -17,6 +17,9 @@ exports.polyfill = function () {
exports.canCompile = util.canCompile; exports.canCompile = util.canCompile;
// do not use this - this is for use by official maintained 6to5 plugins
exports._util = util;
exports.transform = transform; exports.transform = transform;
exports.transformFile = function (filename, opts, callback) { exports.transformFile = function (filename, opts, callback) {

View File

@ -1,6 +1,7 @@
require("./polyfill"); require("./polyfill");
var sourceMapSupport = require("source-map-support"); var sourceMapSupport = require("source-map-support");
var util = require("./util");
var to5 = require("./index"); var to5 = require("./index");
var _ = require("lodash"); var _ = require("lodash");
@ -71,7 +72,8 @@ var loader = function (m, filename) {
var result = to5.transformFileSync(filename, { var result = to5.transformFileSync(filename, {
whitelist: whitelist, whitelist: whitelist,
blacklist: blacklist, blacklist: blacklist,
sourceMap: true sourceMap: true,
modules: "commonInterop"
}); });
maps[filename] = result.map; maps[filename] = result.map;
@ -100,11 +102,11 @@ module.exports = function (opts) {
if (_.isRegExp(opts)) opts = { ignore: opts }; if (_.isRegExp(opts)) opts = { ignore: opts };
if (opts.ignoreRegex != null) opts.ignore = opts.ignoreRegex; if (opts.ignoreRegex != null) opts.ignore = opts.ignoreRegex;
if (opts.only != null) onlyRegex = opts.only; if (opts.only != null) onlyRegex = util.regexify(opts.only);
if (opts.ignore != null) ignoreRegex = opts.ignore; if (opts.ignore != null) ignoreRegex = util.regexify(opts.ignore);
if (opts.extensions) hookExtensions(opts.extensions); if (opts.extensions) hookExtensions(util.arrayify(opts.extensions));
if (opts.blacklist) blacklist = opts.blacklist; if (opts.blacklist) blacklist = util.arrayify(opts.blacklist);
if (opts.whitelist) whitelist = opts.whitelist; if (opts.whitelist) whitelist = util.arrayify(opts.whitelist);
}; };

View File

@ -0,0 +1,3 @@
(function (obj) {
return obj && (obj["default"] || obj);
})

View File

@ -0,0 +1,29 @@
module.exports = CommonJSInteropFormatter;
var CommonJSFormatter = require("./common");
var util = require("../../util");
var t = require("../../types");
function CommonJSInteropFormatter(file) {
this.file = file;
}
util.inherits(CommonJSInteropFormatter, CommonJSFormatter);
CommonJSInteropFormatter.prototype.importSpecifier = function (specifier, node, nodes) {
var variableName = t.getSpecifierName(specifier);
// import foo from "foo";
if (specifier.default) {
nodes.push(t.variableDeclaration("var", [
t.variableDeclarator(variableName,
t.callExpression(this.file.addDeclaration("interop-require"), [util.template("require", {
MODULE_NAME: node.source.raw
})])
)
]));
return;
}
CommonJSFormatter.prototype.importSpecifier.apply(this, arguments);
};

View File

@ -5,10 +5,8 @@ var util = require("../../util");
var t = require("../../types"); var t = require("../../types");
var _ = require("lodash"); var _ = require("lodash");
function UMDFormatter(file, opts) { function UMDFormatter() {
this.file = file; AMDFormatter.apply(this, arguments);
this.ids = {};
this.insertModuleId = opts.amdModuleId;
} }
util.inherits(UMDFormatter, AMDFormatter); util.inherits(UMDFormatter, AMDFormatter);

View File

@ -20,10 +20,11 @@ transform._ensureTransformerNames = function (type, keys) {
transform.transformers = {}; transform.transformers = {};
transform.moduleFormatters = { transform.moduleFormatters = {
common: require("./modules/common"), common: require("./modules/common"),
ignore: require("./modules/ignore"), commonInterop: require("./modules/common-interop"),
amd: require("./modules/amd"), ignore: require("./modules/ignore"),
umd: require("./modules/umd") amd: require("./modules/amd"),
umd: require("./modules/umd")
}; };
_.each({ _.each({

View File

@ -0,0 +1,204 @@
/**
* Copyright (c) 2014, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* https://raw.github.com/facebook/regenerator/master/LICENSE file. An
* additional grant of patent rights can be found in the PATENTS file in
* the same directory.
*/
var assert = require("assert");
var loc = require("../util").loc;
var t = require("../../../../types");
exports.ParenthesizedExpression = function (expr, path, explodeViaTempVar, finish) {
return finish(this.explodeExpression(path.get("expression")));
};
exports.MemberExpression = function (expr, path, explodeViaTempVar, finish) {
return finish(t.memberExpression(
this.explodeExpression(path.get("object")),
expr.computed ? explodeViaTempVar(null, path.get("property")) : expr.property,
expr.computed
));
};
exports.CallExpression = function (expr, path, explodeViaTempVar, finish) {
var oldCalleePath = path.get("callee");
var newCallee = this.explodeExpression(oldCalleePath);
// If the callee was not previously a MemberExpression, then the
// CallExpression was "unqualified," meaning its `this` object should
// be the global object. If the exploded expression has become a
// MemberExpression, then we need to force it to be unqualified by
// using the (0, object.property)(...) trick; otherwise, it will
// receive the object of the MemberExpression as its `this` object.
if (!t.isMemberExpression(oldCalleePath.node) && t.isMemberExpression(newCallee)) {
newCallee = t.sequenceExpression([
t.literal(0),
newCallee
]);
}
return finish(t.callExpression(
newCallee,
path.get("arguments").map(function (argPath) {
return explodeViaTempVar(null, argPath);
})
));
};
exports.NewExpression = function (expr, path, explodeViaTempVar, finish) {
return finish(t.newExpression(
explodeViaTempVar(null, path.get("callee")),
path.get("arguments").map(function (argPath) {
return explodeViaTempVar(null, argPath);
})
));
};
exports.ObjectExpression = function (expr, path, explodeViaTempVar, finish) {
return finish(t.objectExpression(
path.get("properties").map(function (propPath) {
return t.property(
propPath.value.kind,
propPath.value.key,
explodeViaTempVar(null, propPath.get("value"))
);
})
));
};
exports.ArrayExpression = function (expr, path, explodeViaTempVar, finish) {
return finish(t.arrayExpression(
path.get("elements").map(function (elemPath) {
return explodeViaTempVar(null, elemPath);
})
));
};
exports.SequenceExpression = function (expr, path, explodeViaTempVar, finish, ignoreResult) {
var lastIndex = expr.expressions.length - 1;
var self = this;
var result;
path.get("expressions").each(function (exprPath) {
if (exprPath.name === lastIndex) {
result = self.explodeExpression(exprPath, ignoreResult);
} else {
self.explodeExpression(exprPath, true);
}
});
return result;
};
exports.LogicalExpression = function (expr, path, explodeViaTempVar, finish, ignoreResult) {
var after = loc();
var result;
if (!ignoreResult) {
result = this.makeTempVar();
}
var left = explodeViaTempVar(result, path.get("left"));
if (expr.operator === "&&") {
this.jumpIfNot(left, after);
} else {
assert.strictEqual(expr.operator, "||");
this.jumpIf(left, after);
}
explodeViaTempVar(result, path.get("right"), ignoreResult);
this.mark(after);
return result;
};
exports.ConditionalExpression = function (expr, path, explodeViaTempVar, finish, ignoreResult) {
var elseLoc = loc();
var after = loc();
var test = this.explodeExpression(path.get("test"));
var result;
this.jumpIfNot(test, elseLoc);
if (!ignoreResult) {
result = this.makeTempVar();
}
explodeViaTempVar(result, path.get("consequent"), ignoreResult);
this.jump(after);
this.mark(elseLoc);
explodeViaTempVar(result, path.get("alternate"), ignoreResult);
this.mark(after);
return result;
};
exports.UnaryExpression = function (expr, path, explodeViaTempVar, finish) {
return finish(t.unaryExpression(
expr.operator,
// Can't (and don't need to) break up the syntax of the argument.
// Think about delete a[b].
this.explodeExpression(path.get("argument")),
!!expr.prefix
));
};
exports.BinaryExpression = function (expr, path, explodeViaTempVar, finish) {
return finish(t.binaryExpression(
expr.operator,
explodeViaTempVar(null, path.get("left")),
explodeViaTempVar(null, path.get("right"))
));
};
exports.AssignmentExpression = function (expr, path, explodeViaTempVar, finish) {
return finish(t.assignmentExpression(
expr.operator,
this.explodeExpression(path.get("left")),
this.explodeExpression(path.get("right"))
));
};
exports.UpdateExpression = function (expr, path, explodeViaTempVar, finish) {
return finish(t.updateExpression(
expr.operator,
this.explodeExpression(path.get("argument")),
expr.prefix
));
};
exports.YieldExpression = function (expr, path) {
var after = loc();
var arg = expr.argument && this.explodeExpression(path.get("argument"));
var result;
if (arg && expr.delegate) {
result = this.makeTempVar();
this.emit(t.returnStatement(t.callExpression(
this.contextProperty("delegateYield"), [
arg,
t.literal(result.property.name),
after
]
)));
this.mark(after);
return result;
}
this.emitAssign(this.contextProperty("next"), after);
this.emit(t.returnStatement(arg || null));
this.mark(after);
return this.contextProperty("sent");
};

View File

@ -0,0 +1,334 @@
/**
* Copyright (c) 2014, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* https://raw.github.com/facebook/regenerator/master/LICENSE file. An
* additional grant of patent rights can be found in the PATENTS file in
* the same directory.
*/
var assert = require("assert");
var types = require("ast-types");
var leap = require("../leap");
var util = require("../util");
var t = require("../../../../types");
var runtimeKeysMethod = util.runtimeProperty("keys");
var loc = util.loc;
exports.ExpressionStatement = function (path) {
this.explodeExpression(path.get("expression"), true);
};
exports.LabeledStatement = function (path, stmt) {
this.explodeStatement(path.get("body"), stmt.label);
};
exports.WhileStatement = function (path, stmt, labelId) {
var before = loc();
var after = loc();
this.mark(before);
this.jumpIfNot(this.explodeExpression(path.get("test")), after);
this.leapManager.withEntry(
new leap.LoopEntry(after, before, labelId),
function () { this.explodeStatement(path.get("body")); }
);
this.jump(before);
this.mark(after);
};
exports.DoWhileStatement = function (path, stmt, labelId) {
var first = loc();
var test = loc();
var after = loc();
this.mark(first);
this.leapManager.withEntry(
new leap.LoopEntry(after, test, labelId),
function () { this.explode(path.get("body")); }
);
this.mark(test);
this.jumpIf(this.explodeExpression(path.get("test")), first);
this.mark(after);
};
exports.ForStatement = function (path, stmt, labelId) {
var head = loc();
var update = loc();
var after = loc();
if (stmt.init) {
// We pass true here to indicate that if stmt.init is an expression
// then we do not care about its result.
this.explode(path.get("init"), true);
}
this.mark(head);
if (stmt.test) {
this.jumpIfNot(this.explodeExpression(path.get("test")), after);
} else {
// No test means continue unconditionally.
}
this.leapManager.withEntry(
new leap.LoopEntry(after, update, labelId),
function () { this.explodeStatement(path.get("body")); }
);
this.mark(update);
if (stmt.update) {
// We pass true here to indicate that if stmt.update is an
// expression then we do not care about its result.
this.explode(path.get("update"), true);
}
this.jump(head);
this.mark(after);
};
exports.ForInStatement = function (path, stmt, labelId) {
t.assertIdentifier(stmt.left);
var head = loc();
var after = loc();
var keyIterNextFn = this.makeTempVar();
this.emitAssign(
keyIterNextFn,
t.callExpression(
runtimeKeysMethod,
[this.explodeExpression(path.get("right"))]
)
);
this.mark(head);
var keyInfoTmpVar = this.makeTempVar();
this.jumpIf(
t.memberExpression(
t.assignmentExpression(
"=",
keyInfoTmpVar,
t.callExpression(keyIterNextFn, [])
),
t.identifier("done"),
false
),
after
);
this.emitAssign(
stmt.left,
t.memberExpression(
keyInfoTmpVar,
t.identifier("value"),
false
)
);
this.leapManager.withEntry(
new leap.LoopEntry(after, head, labelId),
function () { this.explodeStatement(path.get("body")); }
);
this.jump(head);
this.mark(after);
};
exports.BreakStatement = function (path, stmt) {
this.emitAbruptCompletion({
type: "break",
target: this.leapManager.getBreakLoc(stmt.label)
});
};
exports.ContinueStatement = function (path, stmt) {
this.emitAbruptCompletion({
type: "continue",
target: this.leapManager.getContinueLoc(stmt.label)
});
};
exports.SwitchStatement = function (path, stmt) {
// Always save the discriminant into a temporary variable in case the
// test expressions overwrite values like context.sent.
var disc = this.emitAssign(
this.makeTempVar(),
this.explodeExpression(path.get("discriminant"))
);
var after = loc();
var defaultLoc = loc();
var condition = defaultLoc;
var caseLocs = [];
var self = this;
// If there are no cases, .cases might be undefined.
var cases = stmt.cases || [];
for (var i = cases.length - 1; i >= 0; --i) {
var c = cases[i];
t.assertSwitchCase(c);
if (c.test) {
condition = t.conditionalExpression(
t.binaryExpression("===", disc, c.test),
caseLocs[i] = loc(),
condition
);
} else {
caseLocs[i] = defaultLoc;
}
}
this.jump(this.explodeExpression(
new types.NodePath(condition, path, "discriminant")
));
this.leapManager.withEntry(
new leap.SwitchEntry(after),
function () {
path.get("cases").each(function (casePath) {
var i = casePath.name;
self.mark(caseLocs[i]);
casePath.get("consequent").each(
self.explodeStatement,
self
);
});
}
);
this.mark(after);
if (defaultLoc.value === -1) {
this.mark(defaultLoc);
assert.strictEqual(after.value, defaultLoc.value);
}
};
exports.IfStatement = function (path, stmt) {
var elseLoc = stmt.alternate && loc();
var after = loc();
this.jumpIfNot(
this.explodeExpression(path.get("test")),
elseLoc || after
);
this.explodeStatement(path.get("consequent"));
if (elseLoc) {
this.jump(after);
this.mark(elseLoc);
this.explodeStatement(path.get("alternate"));
}
this.mark(after);
};
exports.ReturnStatement = function (path) {
this.emitAbruptCompletion({
type: "return",
value: this.explodeExpression(path.get("argument"))
});
};
exports.TryStatement = function (path, stmt) {
var after = loc();
var self = this;
var handler = stmt.handler;
if (!handler && stmt.handlers) {
handler = stmt.handlers[0] || null;
}
var catchLoc = handler && loc();
var catchEntry = catchLoc && new leap.CatchEntry(
catchLoc,
handler.param
);
var finallyLoc = stmt.finalizer && loc();
var finallyEntry = finallyLoc && new leap.FinallyEntry(finallyLoc);
var tryEntry = new leap.TryEntry(
this.getUnmarkedCurrentLoc(),
catchEntry,
finallyEntry
);
this.tryEntries.push(tryEntry);
this.updateContextPrevLoc(tryEntry.firstLoc);
this.leapManager.withEntry(tryEntry, function () {
this.explodeStatement(path.get("block"));
if (catchLoc) {
if (finallyLoc) {
// If we have both a catch block and a finally block, then
// because we emit the catch block first, we need to jump over
// it to the finally block.
this.jump(finallyLoc);
} else {
// If there is no finally block, then we need to jump over the
// catch block to the fall-through location.
this.jump(after);
}
this.updateContextPrevLoc(self.mark(catchLoc));
var bodyPath = path.get("handler", "body");
var safeParam = this.makeTempVar();
this.clearPendingException(tryEntry.firstLoc, safeParam);
var catchScope = bodyPath.scope;
var catchParamName = handler.param.name;
t.assertCatchClause(catchScope.node);
assert.strictEqual(catchScope.lookup(catchParamName), catchScope);
types.visit(bodyPath, {
visitIdentifier: function (path) {
if (path.value.name === catchParamName &&
path.scope.lookup(catchParamName) === catchScope) {
return safeParam;
}
this.traverse(path);
}
});
this.leapManager.withEntry(catchEntry, function () {
this.explodeStatement(bodyPath);
});
}
if (finallyLoc) {
this.updateContextPrevLoc(this.mark(finallyLoc));
this.leapManager.withEntry(finallyEntry, function () {
this.explodeStatement(path.get("finalizer"));
});
this.emit(t.callExpression(
this.contextProperty("finish"),
[finallyEntry.firstLoc]
));
}
});
this.mark(after);
};
exports.ThrowStatement = function (path) {
this.emit(t.throwStatement(
this.explodeExpression(path.get("argument"))
));
};

View File

@ -10,20 +10,22 @@
exports.Emitter = Emitter; exports.Emitter = Emitter;
var runtimeProperty = require("./util").runtimeProperty; var explodeExpressions = require("./explode-expressions");
var assert = require("assert"); var explodeStatements = require("./explode-statements");
var types = require("ast-types"); var assert = require("assert");
var leap = require("./leap"); var types = require("ast-types");
var meta = require("./meta"); var leap = require("../leap");
var t = require("../../../types"); var meta = require("../meta");
var _ = require("lodash"); var util = require("../util");
var t = require("../../../../types");
var _ = require("lodash");
var runtimeKeysMethod = runtimeProperty("keys"); var loc = util.loc;
var n = types.namedTypes; var n = types.namedTypes;
function Emitter(contextId) { function Emitter(contextId) {
assert.ok(this instanceof Emitter); assert.ok(this instanceof Emitter);
n.Identifier.assert(contextId); t.assertIdentifier(contextId);
// In order to make sure the context object does not collide with // In order to make sure the context object does not collide with
// anything in the local scope, we might have to rename it, so we // anything in the local scope, we might have to rename it, so we
@ -52,19 +54,10 @@ function Emitter(contextId) {
this.leapManager = new leap.LeapManager(this); this.leapManager = new leap.LeapManager(this);
} }
// Offsets into this.listing that could be used as targets for branches or
// jumps are represented as numeric Literal nodes. This representation has
// the amazingly convenient benefit of allowing the exact value of the
// location to be determined at any time, even after generating code that
// refers to the location.
function loc() {
return t.literal(-1);
}
// Sets the exact value of the given location to the offset of the next // Sets the exact value of the given location to the offset of the next
// Statement emitted. // Statement emitted.
Emitter.prototype.mark = function(loc) { Emitter.prototype.mark = function (loc) {
n.Literal.assert(loc); t.assertLiteral(loc);
var index = this.listing.length; var index = this.listing.length;
if (loc.value === -1) { if (loc.value === -1) {
loc.value = index; loc.value = index;
@ -77,28 +70,28 @@ Emitter.prototype.mark = function(loc) {
return loc; return loc;
}; };
Emitter.prototype.emit = function(node) { Emitter.prototype.emit = function (node) {
if (t.isExpression(node)) node = t.expressionStatement(node); if (t.isExpression(node)) node = t.expressionStatement(node);
n.Statement.assert(node); t.assertStatement(node);
this.listing.push(node); this.listing.push(node);
}; };
// Shorthand for emitting assignment statements. This will come in handy // Shorthand for emitting assignment statements. This will come in handy
// for assignments to temporary variables. // for assignments to temporary variables.
Emitter.prototype.emitAssign = function(lhs, rhs) { Emitter.prototype.emitAssign = function (lhs, rhs) {
this.emit(this.assign(lhs, rhs)); this.emit(this.assign(lhs, rhs));
return lhs; return lhs;
}; };
// Shorthand for an assignment statement. // Shorthand for an assignment statement.
Emitter.prototype.assign = function(lhs, rhs) { Emitter.prototype.assign = function (lhs, rhs) {
return t.expressionStatement( return t.expressionStatement(
t.assignmentExpression("=", lhs, rhs)); t.assignmentExpression("=", lhs, rhs));
}; };
// Convenience function for generating expressions like context.next, // Convenience function for generating expressions like context.next,
// context.sent, and context.rval. // context.sent, and context.rval.
Emitter.prototype.contextProperty = function(name, computed) { Emitter.prototype.contextProperty = function (name, computed) {
return t.memberExpression( return t.memberExpression(
this.contextId, this.contextId,
computed ? t.literal(name) : t.identifier(name), computed ? t.literal(name) : t.identifier(name),
@ -116,7 +109,7 @@ var volatileContextPropertyNames = {
// A "volatile" context property is a MemberExpression like context.sent // A "volatile" context property is a MemberExpression like context.sent
// that should probably be stored in a temporary variable when there's a // that should probably be stored in a temporary variable when there's a
// possibility the property will get overwritten. // possibility the property will get overwritten.
Emitter.prototype.isVolatileContextProperty = function(expr) { Emitter.prototype.isVolatileContextProperty = function (expr) {
if (t.isMemberExpression(expr)) { if (t.isMemberExpression(expr)) {
if (expr.computed) { if (expr.computed) {
// If it's a computed property such as context[couldBeAnything], // If it's a computed property such as context[couldBeAnything],
@ -136,7 +129,7 @@ Emitter.prototype.isVolatileContextProperty = function(expr) {
}; };
// Shorthand for setting context.rval and jumping to `context.stop()`. // Shorthand for setting context.rval and jumping to `context.stop()`.
Emitter.prototype.stop = function(rval) { Emitter.prototype.stop = function (rval) {
if (rval) { if (rval) {
this.setReturnValue(rval); this.setReturnValue(rval);
} }
@ -144,8 +137,8 @@ Emitter.prototype.stop = function(rval) {
this.jump(this.finalLoc); this.jump(this.finalLoc);
}; };
Emitter.prototype.setReturnValue = function(valuePath) { Emitter.prototype.setReturnValue = function (valuePath) {
n.Expression.assert(valuePath.value); t.assertExpression(valuePath.value);
this.emitAssign( this.emitAssign(
this.contextProperty("rval"), this.contextProperty("rval"),
@ -153,8 +146,8 @@ Emitter.prototype.setReturnValue = function(valuePath) {
); );
}; };
Emitter.prototype.clearPendingException = function(tryLoc, assignee) { Emitter.prototype.clearPendingException = function (tryLoc, assignee) {
n.Literal.assert(tryLoc); t.assertLiteral(tryLoc);
var catchCall = t.callExpression( var catchCall = t.callExpression(
this.contextProperty("catch", true), this.contextProperty("catch", true),
@ -170,15 +163,15 @@ Emitter.prototype.clearPendingException = function(tryLoc, assignee) {
// Emits code for an unconditional jump to the given location, even if the // Emits code for an unconditional jump to the given location, even if the
// exact value of the location is not yet known. // exact value of the location is not yet known.
Emitter.prototype.jump = function(toLoc) { Emitter.prototype.jump = function (toLoc) {
this.emitAssign(this.contextProperty("next"), toLoc); this.emitAssign(this.contextProperty("next"), toLoc);
this.emit(t.breakStatement()); this.emit(t.breakStatement());
}; };
// Conditional jump. // Conditional jump.
Emitter.prototype.jumpIf = function(test, toLoc) { Emitter.prototype.jumpIf = function (test, toLoc) {
n.Expression.assert(test); t.assertExpression(test);
n.Literal.assert(toLoc); t.assertLiteral(toLoc);
this.emit(t.ifStatement( this.emit(t.ifStatement(
test, test,
@ -190,9 +183,9 @@ Emitter.prototype.jumpIf = function(test, toLoc) {
}; };
// Conditional jump, with the condition negated. // Conditional jump, with the condition negated.
Emitter.prototype.jumpIfNot = function(test, toLoc) { Emitter.prototype.jumpIfNot = function (test, toLoc) {
n.Expression.assert(test); t.assertExpression(test);
n.Literal.assert(toLoc); t.assertLiteral(toLoc);
var negatedTest; var negatedTest;
if (t.isUnaryExpression(test) && test.operator === "!") { if (t.isUnaryExpression(test) && test.operator === "!") {
@ -217,11 +210,11 @@ Emitter.prototype.jumpIfNot = function(test, toLoc) {
// other local variables, and since we just increment `nextTempId` // other local variables, and since we just increment `nextTempId`
// monotonically, uniqueness is assured. // monotonically, uniqueness is assured.
var nextTempId = 0; var nextTempId = 0;
Emitter.prototype.makeTempVar = function() { Emitter.prototype.makeTempVar = function () {
return this.contextProperty("t" + nextTempId++); return this.contextProperty("t" + nextTempId++);
}; };
Emitter.prototype.getContextFunction = function(id) { Emitter.prototype.getContextFunction = function (id) {
var node = t.functionExpression( var node = t.functionExpression(
id || null, id || null,
[this.contextId], [this.contextId],
@ -244,7 +237,7 @@ Emitter.prototype.getContextFunction = function(id) {
// //
// Each marked location in this.listing will correspond to one generated // Each marked location in this.listing will correspond to one generated
// case statement. // case statement.
Emitter.prototype.getDispatchLoop = function() { Emitter.prototype.getDispatchLoop = function () {
var self = this; var self = this;
var cases = []; var cases = [];
var current; var current;
@ -253,7 +246,7 @@ Emitter.prototype.getDispatchLoop = function() {
// case, we can skip the rest of the statements until the next case. // case, we can skip the rest of the statements until the next case.
var alreadyEnded = false; var alreadyEnded = false;
self.listing.forEach(function(stmt, i) { self.listing.forEach(function (stmt, i) {
if (self.marked.hasOwnProperty(i)) { if (self.marked.hasOwnProperty(i)) {
cases.push(t.switchCase(t.literal(i), current = [])); cases.push(t.switchCase(t.literal(i), current = []));
alreadyEnded = false; alreadyEnded = false;
@ -306,7 +299,7 @@ function isSwitchCaseEnder(stmt) {
t.isThrowStatement(stmt); t.isThrowStatement(stmt);
} }
Emitter.prototype.getTryEntryList = function() { Emitter.prototype.getTryEntryList = function () {
if (this.tryEntries.length === 0) { if (this.tryEntries.length === 0) {
// To avoid adding a needless [] to the majority of runtime.wrap // To avoid adding a needless [] to the majority of runtime.wrap
// argument lists, force the caller to handle this case specially. // argument lists, force the caller to handle this case specially.
@ -316,7 +309,7 @@ Emitter.prototype.getTryEntryList = function() {
var lastLocValue = 0; var lastLocValue = 0;
return t.arrayExpression( return t.arrayExpression(
this.tryEntries.map(function(tryEntry) { this.tryEntries.map(function (tryEntry) {
var thisLocValue = tryEntry.firstLoc.value; var thisLocValue = tryEntry.firstLoc.value;
assert.ok(thisLocValue >= lastLocValue, "try entries out of order"); assert.ok(thisLocValue >= lastLocValue, "try entries out of order");
lastLocValue = thisLocValue; lastLocValue = thisLocValue;
@ -346,13 +339,13 @@ Emitter.prototype.getTryEntryList = function() {
// No destructive modification of AST nodes. // No destructive modification of AST nodes.
Emitter.prototype.explode = function(path, ignoreResult) { Emitter.prototype.explode = function (path, ignoreResult) {
assert.ok(path instanceof types.NodePath); assert.ok(path instanceof types.NodePath);
var node = path.value; var node = path.value;
var self = this; var self = this;
n.Node.assert(node); n.Node.check(node);
if (t.isStatement(node)) if (t.isStatement(node))
return self.explodeStatement(path); return self.explodeStatement(path);
@ -389,17 +382,16 @@ function getDeclError(node) {
JSON.stringify(node)); JSON.stringify(node));
} }
Emitter.prototype.explodeStatement = function(path, labelId) { Emitter.prototype.explodeStatement = function (path, labelId) {
assert.ok(path instanceof types.NodePath); assert.ok(path instanceof types.NodePath);
var stmt = path.value; var stmt = path.value;
var self = this; var self = this;
var after, head;
n.Statement.assert(stmt); t.assertStatement(stmt);
if (labelId) { if (labelId) {
n.Identifier.assert(labelId); t.assertIdentifier(labelId);
} else { } else {
labelId = null; labelId = null;
} }
@ -423,338 +415,15 @@ Emitter.prototype.explodeStatement = function(path, labelId) {
return; return;
} }
switch (stmt.type) { var fn = explodeStatements[stmt.type];
case "ExpressionStatement": if (fn) {
self.explodeExpression(path.get("expression"), true); fn.call(this, path, stmt, labelId);
break; } else {
case "LabeledStatement":
self.explodeStatement(path.get("body"), stmt.label);
break;
case "WhileStatement":
var before = loc();
after = loc();
self.mark(before);
self.jumpIfNot(self.explodeExpression(path.get("test")), after);
self.leapManager.withEntry(
new leap.LoopEntry(after, before, labelId),
function() { self.explodeStatement(path.get("body")); }
);
self.jump(before);
self.mark(after);
break;
case "DoWhileStatement":
var first = loc();
var test = loc();
after = loc();
self.mark(first);
self.leapManager.withEntry(
new leap.LoopEntry(after, test, labelId),
function() { self.explode(path.get("body")); }
);
self.mark(test);
self.jumpIf(self.explodeExpression(path.get("test")), first);
self.mark(after);
break;
case "ForStatement":
head = loc();
var update = loc();
after = loc();
if (stmt.init) {
// We pass true here to indicate that if stmt.init is an expression
// then we do not care about its result.
self.explode(path.get("init"), true);
}
self.mark(head);
if (stmt.test) {
self.jumpIfNot(self.explodeExpression(path.get("test")), after);
} else {
// No test means continue unconditionally.
}
self.leapManager.withEntry(
new leap.LoopEntry(after, update, labelId),
function() { self.explodeStatement(path.get("body")); }
);
self.mark(update);
if (stmt.update) {
// We pass true here to indicate that if stmt.update is an
// expression then we do not care about its result.
self.explode(path.get("update"), true);
}
self.jump(head);
self.mark(after);
break;
case "ForInStatement":
n.Identifier.assert(stmt.left);
head = loc();
after = loc();
var keyIterNextFn = self.makeTempVar();
self.emitAssign(
keyIterNextFn,
t.callExpression(
runtimeKeysMethod,
[self.explodeExpression(path.get("right"))]
)
);
self.mark(head);
var keyInfoTmpVar = self.makeTempVar();
self.jumpIf(
t.memberExpression(
t.assignmentExpression(
"=",
keyInfoTmpVar,
t.callExpression(keyIterNextFn, [])
),
t.identifier("done"),
false
),
after
);
self.emitAssign(
stmt.left,
t.memberExpression(
keyInfoTmpVar,
t.identifier("value"),
false
)
);
self.leapManager.withEntry(
new leap.LoopEntry(after, head, labelId),
function() { self.explodeStatement(path.get("body")); }
);
self.jump(head);
self.mark(after);
break;
case "BreakStatement":
self.emitAbruptCompletion({
type: "break",
target: self.leapManager.getBreakLoc(stmt.label)
});
break;
case "ContinueStatement":
self.emitAbruptCompletion({
type: "continue",
target: self.leapManager.getContinueLoc(stmt.label)
});
break;
case "SwitchStatement":
// Always save the discriminant into a temporary variable in case the
// test expressions overwrite values like context.sent.
var disc = self.emitAssign(
self.makeTempVar(),
self.explodeExpression(path.get("discriminant"))
);
after = loc();
var defaultLoc = loc();
var condition = defaultLoc;
var caseLocs = [];
// If there are no cases, .cases might be undefined.
var cases = stmt.cases || [];
for (var i = cases.length - 1; i >= 0; --i) {
var c = cases[i];
n.SwitchCase.assert(c);
if (c.test) {
condition = t.conditionalExpression(
t.binaryExpression("===", disc, c.test),
caseLocs[i] = loc(),
condition
);
} else {
caseLocs[i] = defaultLoc;
}
}
self.jump(self.explodeExpression(
new types.NodePath(condition, path, "discriminant")
));
self.leapManager.withEntry(
new leap.SwitchEntry(after),
function() {
path.get("cases").each(function(casePath) {
var i = casePath.name;
self.mark(caseLocs[i]);
casePath.get("consequent").each(
self.explodeStatement,
self
);
});
}
);
self.mark(after);
if (defaultLoc.value === -1) {
self.mark(defaultLoc);
assert.strictEqual(after.value, defaultLoc.value);
}
break;
case "IfStatement":
var elseLoc = stmt.alternate && loc();
after = loc();
self.jumpIfNot(
self.explodeExpression(path.get("test")),
elseLoc || after
);
self.explodeStatement(path.get("consequent"));
if (elseLoc) {
self.jump(after);
self.mark(elseLoc);
self.explodeStatement(path.get("alternate"));
}
self.mark(after);
break;
case "ReturnStatement":
self.emitAbruptCompletion({
type: "return",
value: self.explodeExpression(path.get("argument"))
});
break;
case "TryStatement":
after = loc();
var handler = stmt.handler;
if (!handler && stmt.handlers) {
handler = stmt.handlers[0] || null;
}
var catchLoc = handler && loc();
var catchEntry = catchLoc && new leap.CatchEntry(
catchLoc,
handler.param
);
var finallyLoc = stmt.finalizer && loc();
var finallyEntry = finallyLoc && new leap.FinallyEntry(finallyLoc);
var tryEntry = new leap.TryEntry(
self.getUnmarkedCurrentLoc(),
catchEntry,
finallyEntry
);
self.tryEntries.push(tryEntry);
self.updateContextPrevLoc(tryEntry.firstLoc);
self.leapManager.withEntry(tryEntry, function() {
self.explodeStatement(path.get("block"));
if (catchLoc) {
if (finallyLoc) {
// If we have both a catch block and a finally block, then
// because we emit the catch block first, we need to jump over
// it to the finally block.
self.jump(finallyLoc);
} else {
// If there is no finally block, then we need to jump over the
// catch block to the fall-through location.
self.jump(after);
}
self.updateContextPrevLoc(self.mark(catchLoc));
var bodyPath = path.get("handler", "body");
var safeParam = self.makeTempVar();
self.clearPendingException(tryEntry.firstLoc, safeParam);
var catchScope = bodyPath.scope;
var catchParamName = handler.param.name;
n.CatchClause.assert(catchScope.node);
assert.strictEqual(catchScope.lookup(catchParamName), catchScope);
types.visit(bodyPath, {
visitIdentifier: function(path) {
if (path.value.name === catchParamName &&
path.scope.lookup(catchParamName) === catchScope) {
return safeParam;
}
this.traverse(path);
}
});
self.leapManager.withEntry(catchEntry, function() {
self.explodeStatement(bodyPath);
});
}
if (finallyLoc) {
self.updateContextPrevLoc(self.mark(finallyLoc));
self.leapManager.withEntry(finallyEntry, function() {
self.explodeStatement(path.get("finalizer"));
});
self.emit(t.callExpression(
self.contextProperty("finish"),
[finallyEntry.firstLoc]
));
}
});
self.mark(after);
break;
case "ThrowStatement":
self.emit(t.throwStatement(
self.explodeExpression(path.get("argument"))
));
break;
default:
throw new Error("unknown Statement of type " + JSON.stringify(stmt.type)); throw new Error("unknown Statement of type " + JSON.stringify(stmt.type));
} }
}; };
Emitter.prototype.emitAbruptCompletion = function(record) { Emitter.prototype.emitAbruptCompletion = function (record) {
if (!isValidCompletion(record)) { if (!isValidCompletion(record)) {
assert.ok( assert.ok(
false, false,
@ -770,11 +439,11 @@ Emitter.prototype.emitAbruptCompletion = function(record) {
var abruptArgs = [t.literal(record.type)]; var abruptArgs = [t.literal(record.type)];
if (record.type === "break" || record.type === "continue") { if (record.type === "break" || record.type === "continue") {
n.Literal.assert(record.target); t.assertLiteral(record.target);
abruptArgs[1] = record.target; abruptArgs[1] = record.target;
} else if (record.type === "return" || record.type === "throw") { } else if (record.type === "return" || record.type === "throw") {
if (record.value) { if (record.value) {
n.Expression.assert(record.value); t.assertExpression(record.value);
abruptArgs[1] = record.value; abruptArgs[1] = record.value;
} }
} }
@ -797,7 +466,7 @@ function isValidCompletion(record) {
} }
if (type === "break" || type === "continue") { if (type === "break" || type === "continue") {
return !_.has(record, "value") && t.isLiteral(record.target);; return !_.has(record, "value") && t.isLiteral(record.target);
} }
if (type === "return" || type === "throw") { if (type === "return" || type === "throw") {
@ -807,7 +476,6 @@ function isValidCompletion(record) {
return false; return false;
} }
// Not all offsets into emitter.listing are potential jump targets. For // Not all offsets into emitter.listing are potential jump targets. For
// example, execution typically falls into the beginning of a try block // example, execution typically falls into the beginning of a try block
// without jumping directly there. This method returns the current offset // without jumping directly there. This method returns the current offset
@ -817,7 +485,7 @@ function isValidCompletion(record) {
// statements). There's no logical harm in marking such locations as jump // statements). There's no logical harm in marking such locations as jump
// targets, but minimizing the number of switch cases keeps the generated // targets, but minimizing the number of switch cases keeps the generated
// code shorter. // code shorter.
Emitter.prototype.getUnmarkedCurrentLoc = function() { Emitter.prototype.getUnmarkedCurrentLoc = function () {
return t.literal(this.listing.length); return t.literal(this.listing.length);
}; };
@ -831,9 +499,9 @@ Emitter.prototype.getUnmarkedCurrentLoc = function() {
// would know the location of the current instruction with complete // would know the location of the current instruction with complete
// precision at all times, but we don't have that luxury here, as it would // precision at all times, but we don't have that luxury here, as it would
// be costly and verbose to set context.prev before every statement. // be costly and verbose to set context.prev before every statement.
Emitter.prototype.updateContextPrevLoc = function(loc) { Emitter.prototype.updateContextPrevLoc = function (loc) {
if (loc) { if (loc) {
n.Literal.assert(loc); t.assertLiteral(loc);
if (loc.value === -1) { if (loc.value === -1) {
// If an uninitialized location literal was passed in, set its value // If an uninitialized location literal was passed in, set its value
@ -854,21 +522,20 @@ Emitter.prototype.updateContextPrevLoc = function(loc) {
this.emitAssign(this.contextProperty("prev"), loc); this.emitAssign(this.contextProperty("prev"), loc);
}; };
Emitter.prototype.explodeExpression = function(path, ignoreResult) { Emitter.prototype.explodeExpression = function (path, ignoreResult) {
assert.ok(path instanceof types.NodePath); assert.ok(path instanceof types.NodePath);
var expr = path.value; var expr = path.value;
if (expr) { if (expr) {
n.Expression.assert(expr); t.assertExpression(expr);
} else { } else {
return expr; return expr;
} }
var self = this; var self = this;
var result, after; // Used optionally by several cases below.
function finish(expr) { function finish(expr) {
n.Expression.assert(expr); t.assertExpression(expr);
if (ignoreResult) { if (ignoreResult) {
self.emit(expr); self.emit(expr);
} else { } else {
@ -935,180 +602,10 @@ Emitter.prototype.explodeExpression = function(path, ignoreResult) {
// emitting the expression with all its side effects, and we should not // emitting the expression with all its side effects, and we should not
// return a result. // return a result.
switch (expr.type) { var fn = explodeExpressions[expr.type];
case "ParenthesizedExpression": if (fn) {
return finish(self.explodeExpression(path.get("expression"))); return fn.call(this, expr, path, explodeViaTempVar, finish, ignoreResult);
} else {
case "MemberExpression":
return finish(t.memberExpression(
self.explodeExpression(path.get("object")),
expr.computed ? explodeViaTempVar(null, path.get("property")) : expr.property,
expr.computed
));
case "CallExpression":
var oldCalleePath = path.get("callee");
var newCallee = self.explodeExpression(oldCalleePath);
// If the callee was not previously a MemberExpression, then the
// CallExpression was "unqualified," meaning its `this` object should
// be the global object. If the exploded expression has become a
// MemberExpression, then we need to force it to be unqualified by
// using the (0, object.property)(...) trick; otherwise, it will
// receive the object of the MemberExpression as its `this` object.
if (!t.isMemberExpression(oldCalleePath.node) && t.isMemberExpression(newCallee)) {
newCallee = t.sequenceExpression([
t.literal(0),
newCallee
]);
}
return finish(t.callExpression(
newCallee,
path.get("arguments").map(function(argPath) {
return explodeViaTempVar(null, argPath);
})
));
case "NewExpression":
return finish(t.newExpression(
explodeViaTempVar(null, path.get("callee")),
path.get("arguments").map(function(argPath) {
return explodeViaTempVar(null, argPath);
})
));
case "ObjectExpression":
return finish(t.objectExpression(
path.get("properties").map(function(propPath) {
return t.property(
propPath.value.kind,
propPath.value.key,
explodeViaTempVar(null, propPath.get("value"))
);
})
));
case "ArrayExpression":
return finish(t.arrayExpression(
path.get("elements").map(function(elemPath) {
return explodeViaTempVar(null, elemPath);
})
));
case "SequenceExpression":
var lastIndex = expr.expressions.length - 1;
path.get("expressions").each(function(exprPath) {
if (exprPath.name === lastIndex) {
result = self.explodeExpression(exprPath, ignoreResult);
} else {
self.explodeExpression(exprPath, true);
}
});
return result;
case "LogicalExpression":
after = loc();
if (!ignoreResult) {
result = self.makeTempVar();
}
var left = explodeViaTempVar(result, path.get("left"));
if (expr.operator === "&&") {
self.jumpIfNot(left, after);
} else {
assert.strictEqual(expr.operator, "||");
self.jumpIf(left, after);
}
explodeViaTempVar(result, path.get("right"), ignoreResult);
self.mark(after);
return result;
case "ConditionalExpression":
var elseLoc = loc();
after = loc();
var test = self.explodeExpression(path.get("test"));
self.jumpIfNot(test, elseLoc);
if (!ignoreResult) {
result = self.makeTempVar();
}
explodeViaTempVar(result, path.get("consequent"), ignoreResult);
self.jump(after);
self.mark(elseLoc);
explodeViaTempVar(result, path.get("alternate"), ignoreResult);
self.mark(after);
return result;
case "UnaryExpression":
return finish(t.unaryExpression(
expr.operator,
// Can't (and don't need to) break up the syntax of the argument.
// Think about delete a[b].
self.explodeExpression(path.get("argument")),
!!expr.prefix
));
case "BinaryExpression":
return finish(t.binaryExpression(
expr.operator,
explodeViaTempVar(null, path.get("left")),
explodeViaTempVar(null, path.get("right"))
));
case "AssignmentExpression":
return finish(t.assignmentExpression(
expr.operator,
self.explodeExpression(path.get("left")),
self.explodeExpression(path.get("right"))
));
case "UpdateExpression":
return finish(t.updateExpression(
expr.operator,
self.explodeExpression(path.get("argument")),
expr.prefix
));
case "YieldExpression":
after = loc();
var arg = expr.argument && self.explodeExpression(path.get("argument"));
if (arg && expr.delegate) {
result = self.makeTempVar();
self.emit(t.returnStatement(t.callExpression(
self.contextProperty("delegateYield"), [
arg,
t.literal(result.property.name),
after
]
)));
self.mark(after);
return result;
}
self.emitAssign(self.contextProperty("next"), after);
self.emit(t.returnStatement(arg || null));
self.mark(after);
return self.contextProperty("sent");
default:
throw new Error("unknown Expression of type " + JSON.stringify(expr.type)); throw new Error("unknown Expression of type " + JSON.stringify(expr.type));
} }
}; };

View File

@ -13,23 +13,21 @@ var types = require("ast-types");
var t = require("../../../types"); var t = require("../../../types");
var _ = require("lodash"); var _ = require("lodash");
var n = types.namedTypes;
// The hoist function takes a FunctionExpression or FunctionDeclaration // The hoist function takes a FunctionExpression or FunctionDeclaration
// and replaces any Declaration nodes in its body with assignments, then // and replaces any Declaration nodes in its body with assignments, then
// returns a VariableDeclaration containing just the names of the removed // returns a VariableDeclaration containing just the names of the removed
// declarations. // declarations.
exports.hoist = function(funPath) { exports.hoist = function (funPath) {
assert.ok(funPath instanceof types.NodePath); assert.ok(funPath instanceof types.NodePath);
n.Function.assert(funPath.value); t.assertFunction(funPath.value);
var vars = {}; var vars = {};
function varDeclToExpr(vdec, includeIdentifiers) { function varDeclToExpr(vdec, includeIdentifiers) {
n.VariableDeclaration.assert(vdec); t.assertVariableDeclaration(vdec);
var exprs = []; var exprs = [];
vdec.declarations.forEach(function(dec) { vdec.declarations.forEach(function (dec) {
vars[dec.id.name] = dec.id; vars[dec.id.name] = dec.id;
if (dec.init) { if (dec.init) {
@ -51,7 +49,7 @@ exports.hoist = function(funPath) {
} }
types.visit(funPath.get("body"), { types.visit(funPath.get("body"), {
visitVariableDeclaration: function(path) { visitVariableDeclaration: function (path) {
var expr = varDeclToExpr(path.value, false); var expr = varDeclToExpr(path.value, false);
if (expr === null) { if (expr === null) {
path.replace(); path.replace();
@ -66,7 +64,7 @@ exports.hoist = function(funPath) {
return false; return false;
}, },
visitForStatement: function(path) { visitForStatement: function (path) {
var init = path.value.init; var init = path.value.init;
if (t.isVariableDeclaration(init)) { if (t.isVariableDeclaration(init)) {
path.get("init").replace(varDeclToExpr(init, false)); path.get("init").replace(varDeclToExpr(init, false));
@ -74,7 +72,7 @@ exports.hoist = function(funPath) {
this.traverse(path); this.traverse(path);
}, },
visitForInStatement: function(path) { visitForInStatement: function (path) {
var left = path.value.left; var left = path.value.left;
if (t.isVariableDeclaration(left)) { if (t.isVariableDeclaration(left)) {
path.get("left").replace(varDeclToExpr(left, true)); path.get("left").replace(varDeclToExpr(left, true));
@ -82,7 +80,7 @@ exports.hoist = function(funPath) {
this.traverse(path); this.traverse(path);
}, },
visitFunctionDeclaration: function(path) { visitFunctionDeclaration: function (path) {
var node = path.value; var node = path.value;
vars[node.id.name] = node.id; vars[node.id.name] = node.id;
@ -120,14 +118,14 @@ exports.hoist = function(funPath) {
return false; return false;
}, },
visitFunctionExpression: function() { visitFunctionExpression: function () {
// Don't descend into nested function expressions. // Don't descend into nested function expressions.
return false; return false;
} }
}); });
var paramNames = {}; var paramNames = {};
funPath.get("params").each(function(paramPath) { funPath.get("params").each(function (paramPath) {
var param = paramPath.value; var param = paramPath.value;
if (t.isIdentifier(param)) { if (t.isIdentifier(param)) {
paramNames[param.name] = param; paramNames[param.name] = param;
@ -139,7 +137,7 @@ exports.hoist = function(funPath) {
var declarations = []; var declarations = [];
Object.keys(vars).forEach(function(name) { Object.keys(vars).forEach(function (name) {
if (!_.has(paramNames, name)) { if (!_.has(paramNames, name)) {
declarations.push(t.variableDeclarator(vars[name], null)); declarations.push(t.variableDeclarator(vars[name], null));
} }

View File

@ -17,11 +17,10 @@ exports.LoopEntry = LoopEntry;
exports.TryEntry = TryEntry; exports.TryEntry = TryEntry;
var assert = require("assert"); var assert = require("assert");
var types = require("ast-types");
var util = require("util"); var util = require("util");
var t = require("../../../types");
var inherits = util.inherits; var inherits = util.inherits;
var n = types.namedTypes;
function Entry() { function Entry() {
assert.ok(this instanceof Entry); assert.ok(this instanceof Entry);
@ -30,7 +29,7 @@ function Entry() {
function FunctionEntry(returnLoc) { function FunctionEntry(returnLoc) {
Entry.call(this); Entry.call(this);
n.Literal.assert(returnLoc); t.assertLiteral(returnLoc);
this.returnLoc = returnLoc; this.returnLoc = returnLoc;
} }
@ -40,11 +39,11 @@ inherits(FunctionEntry, Entry);
function LoopEntry(breakLoc, continueLoc, label) { function LoopEntry(breakLoc, continueLoc, label) {
Entry.call(this); Entry.call(this);
n.Literal.assert(breakLoc); t.assertLiteral(breakLoc);
n.Literal.assert(continueLoc); t.assertLiteral(continueLoc);
if (label) { if (label) {
n.Identifier.assert(label); t.assertIdentifier(label);
} else { } else {
label = null; label = null;
} }
@ -59,7 +58,7 @@ inherits(LoopEntry, Entry);
function SwitchEntry(breakLoc) { function SwitchEntry(breakLoc) {
Entry.call(this); Entry.call(this);
n.Literal.assert(breakLoc); t.assertLiteral(breakLoc);
this.breakLoc = breakLoc; this.breakLoc = breakLoc;
} }
@ -69,7 +68,7 @@ inherits(SwitchEntry, Entry);
function TryEntry(firstLoc, catchEntry, finallyEntry) { function TryEntry(firstLoc, catchEntry, finallyEntry) {
Entry.call(this); Entry.call(this);
n.Literal.assert(firstLoc); t.assertLiteral(firstLoc);
if (catchEntry) { if (catchEntry) {
assert.ok(catchEntry instanceof CatchEntry); assert.ok(catchEntry instanceof CatchEntry);
@ -96,8 +95,8 @@ inherits(TryEntry, Entry);
function CatchEntry(firstLoc, paramId) { function CatchEntry(firstLoc, paramId) {
Entry.call(this); Entry.call(this);
n.Literal.assert(firstLoc); t.assertLiteral(firstLoc);
n.Identifier.assert(paramId); t.assertIdentifier(paramId);
this.firstLoc = firstLoc; this.firstLoc = firstLoc;
this.paramId = paramId; this.paramId = paramId;
@ -108,7 +107,7 @@ inherits(CatchEntry, Entry);
function FinallyEntry(firstLoc) { function FinallyEntry(firstLoc) {
Entry.call(this); Entry.call(this);
n.Literal.assert(firstLoc); t.assertLiteral(firstLoc);
this.firstLoc = firstLoc; this.firstLoc = firstLoc;
} }
@ -125,7 +124,7 @@ function LeapManager(emitter) {
this.entryStack = [new FunctionEntry(emitter.finalLoc)]; this.entryStack = [new FunctionEntry(emitter.finalLoc)];
} }
LeapManager.prototype.withEntry = function(entry, callback) { LeapManager.prototype.withEntry = function (entry, callback) {
assert.ok(entry instanceof Entry); assert.ok(entry instanceof Entry);
this.entryStack.push(entry); this.entryStack.push(entry);
try { try {
@ -136,7 +135,7 @@ LeapManager.prototype.withEntry = function(entry, callback) {
} }
}; };
LeapManager.prototype._findLeapLocation = function(property, label) { LeapManager.prototype._findLeapLocation = function (property, label) {
for (var i = this.entryStack.length - 1; i >= 0; --i) { for (var i = this.entryStack.length - 1; i >= 0; --i) {
var entry = this.entryStack[i]; var entry = this.entryStack[i];
var loc = entry[property]; var loc = entry[property];
@ -155,10 +154,10 @@ LeapManager.prototype._findLeapLocation = function(property, label) {
return null; return null;
}; };
LeapManager.prototype.getBreakLoc = function(label) { LeapManager.prototype.getBreakLoc = function (label) {
return this._findLeapLocation("breakLoc", label); return this._findLeapLocation("breakLoc", label);
}; };
LeapManager.prototype.getContinueLoc = function(label) { LeapManager.prototype.getContinueLoc = function (label) {
return this._findLeapLocation("continueLoc", label); return this._findLeapLocation("continueLoc", label);
}; };

View File

@ -11,7 +11,6 @@
var assert = require("assert"); var assert = require("assert");
var types = require("ast-types"); var types = require("ast-types");
var m = require("private").makeAccessor(); var m = require("private").makeAccessor();
var t = require("../../../types");
var _ = require("lodash"); var _ = require("lodash");
var isArray = types.builtInTypes.array; var isArray = types.builtInTypes.array;
@ -19,7 +18,7 @@ var n = types.namedTypes;
function makePredicate(propertyName, knownTypes) { function makePredicate(propertyName, knownTypes) {
function onlyChildren(node) { function onlyChildren(node) {
n.Node.assert(node); n.Node.check(node);
// Assume no side effects until we find out otherwise. // Assume no side effects until we find out otherwise.
var result = false; var result = false;
@ -36,7 +35,7 @@ function makePredicate(propertyName, knownTypes) {
return result; return result;
} }
types.eachField(node, function(name, child) { types.eachField(node, function (name, child) {
check(child); check(child);
}); });
@ -44,7 +43,7 @@ function makePredicate(propertyName, knownTypes) {
} }
function predicate(node) { function predicate(node) {
n.Node.assert(node); n.Node.check(node);
var meta = m(node); var meta = m(node);
if (_.has(meta, propertyName)) return meta[propertyName]; if (_.has(meta, propertyName)) return meta[propertyName];

View File

@ -38,19 +38,19 @@ var GFName = "GeneratorFunction";
if (GF.name !== GFName) GF.name = GFName; if (GF.name !== GFName) GF.name = GFName;
if (GF.name !== GFName) throw new Error(GFName + " renamed?"); if (GF.name !== GFName) throw new Error(GFName + " renamed?");
runtime.isGeneratorFunction = function(genFun) { runtime.isGeneratorFunction = function (genFun) {
var ctor = genFun && genFun.constructor; var ctor = genFun && genFun.constructor;
return ctor ? GF.name === ctor.name : false; return ctor ? GF.name === ctor.name : false;
}; };
runtime.mark = function(genFun) { runtime.mark = function (genFun) {
genFun.__proto__ = GFp; genFun.__proto__ = GFp;
genFun.prototype = Object.create(Gp); genFun.prototype = Object.create(Gp);
return genFun; return genFun;
}; };
runtime.async = function(innerFn, outerFn, self, tryList) { runtime.async = function (innerFn, outerFn, self, tryList) {
return new Promise(function(resolve, reject) { return new Promise(function (resolve, reject) {
var generator = wrap(innerFn, outerFn, self, tryList); var generator = wrap(innerFn, outerFn, self, tryList);
var callNext = step.bind(generator.next); var callNext = step.bind(generator.next);
var callThrow = step.bind(generator["throw"]); var callThrow = step.bind(generator["throw"]);
@ -202,11 +202,11 @@ function Generator(innerFn, outerFn, self, tryList) {
return generator; return generator;
} }
Gp[iteratorSymbol] = function() { Gp[iteratorSymbol] = function () {
return this; return this;
}; };
Gp.toString = function() { Gp.toString = function () {
return "[object Generator]"; return "[object Generator]";
}; };
@ -240,7 +240,7 @@ function Context(tryList) {
this.reset(); this.reset();
} }
runtime.keys = function(object) { runtime.keys = function (object) {
var keys = []; var keys = [];
for (var key in object) { for (var key in object) {
keys.push(key); keys.push(key);
@ -293,7 +293,7 @@ runtime.values = values;
Context.prototype = { Context.prototype = {
constructor: Context, constructor: Context,
reset: function() { reset: function () {
this.prev = 0; this.prev = 0;
this.next = 0; this.next = 0;
this.sent = undefined; this.sent = undefined;
@ -311,7 +311,7 @@ Context.prototype = {
} }
}, },
stop: function() { stop: function () {
this.done = true; this.done = true;
var rootEntry = this.tryEntries[0]; var rootEntry = this.tryEntries[0];
@ -323,7 +323,7 @@ Context.prototype = {
return this.rval; return this.rval;
}, },
dispatchException: function(exception) { dispatchException: function (exception) {
if (this.done) { if (this.done) {
throw exception; throw exception;
} }
@ -375,7 +375,7 @@ Context.prototype = {
} }
}, },
_findFinallyEntry: function(finallyLoc) { _findFinallyEntry: function (finallyLoc) {
for (var i = this.tryEntries.length - 1; i >= 0; --i) { for (var i = this.tryEntries.length - 1; i >= 0; --i) {
var entry = this.tryEntries[i]; var entry = this.tryEntries[i];
if (entry.tryLoc <= this.prev && if (entry.tryLoc <= this.prev &&
@ -387,7 +387,7 @@ Context.prototype = {
} }
}, },
abrupt: function(type, arg) { abrupt: function (type, arg) {
var entry = this._findFinallyEntry(); var entry = this._findFinallyEntry();
var record = entry ? entry.completion : {}; var record = entry ? entry.completion : {};
@ -403,7 +403,7 @@ Context.prototype = {
return ContinueSentinel; return ContinueSentinel;
}, },
complete: function(record) { complete: function (record) {
if (record.type === "throw") { if (record.type === "throw") {
throw record.arg; throw record.arg;
} }
@ -418,12 +418,12 @@ Context.prototype = {
return ContinueSentinel; return ContinueSentinel;
}, },
finish: function(finallyLoc) { finish: function (finallyLoc) {
var entry = this._findFinallyEntry(finallyLoc); var entry = this._findFinallyEntry(finallyLoc);
return this.complete(entry.completion); return this.complete(entry.completion);
}, },
"catch": function(tryLoc) { "catch": function (tryLoc) {
for (var i = this.tryEntries.length - 1; i >= 0; --i) { for (var i = this.tryEntries.length - 1; i >= 0; --i) {
var entry = this.tryEntries[i]; var entry = this.tryEntries[i];
if (entry.tryLoc === tryLoc) { if (entry.tryLoc === tryLoc) {
@ -442,7 +442,7 @@ Context.prototype = {
throw new Error("illegal catch attempt"); throw new Error("illegal catch attempt");
}, },
delegateYield: function(iterable, resultName, nextLoc) { delegateYield: function (iterable, resultName, nextLoc) {
this.delegate = { this.delegate = {
iterator: values(iterable), iterator: values(iterable),
resultName: resultName, resultName: resultName,

View File

@ -16,3 +16,13 @@ exports.runtimeProperty = function (name) {
t.identifier(name) t.identifier(name)
); );
}; };
// Offsets into this.listing that could be used as targets for branches or
// jumps are represented as numeric Literal nodes. This representation has
// the amazingly convenient benefit of allowing the exact value of the
// location to be determined at any time, even after generating code that
// refers to the location.
exports.loc = function () {
return t.literal(-1);
};

View File

@ -14,8 +14,6 @@ var hoist = require("./hoist").hoist;
var types = require("ast-types"); var types = require("ast-types");
var t = require("../../../types"); var t = require("../../../types");
var n = types.namedTypes;
var runtimeAsyncMethod = runtimeProperty("async"); var runtimeAsyncMethod = runtimeProperty("async");
var runtimeWrapMethod = runtimeProperty("wrap"); var runtimeWrapMethod = runtimeProperty("wrap");
var runtimeMarkMethod = runtimeProperty("mark"); var runtimeMarkMethod = runtimeProperty("mark");
@ -25,7 +23,7 @@ exports.transform = function transform(node) {
}; };
var visitor = types.PathVisitor.fromMethodsObject({ var visitor = types.PathVisitor.fromMethodsObject({
visitFunction: function(path) { visitFunction: function (path) {
// Calling this.traverse(path) first makes for a post-order traversal. // Calling this.traverse(path) first makes for a post-order traversal.
this.traverse(path); this.traverse(path);
@ -179,7 +177,7 @@ var visitor = types.PathVisitor.fromMethodsObject({
bodyPath.push(varDecl); bodyPath.push(varDecl);
} else { } else {
n.FunctionExpression.assert(node); t.assertFunctionExpression(node);
return t.callExpression(runtimeMarkMethod, [node]); return t.callExpression(runtimeMarkMethod, [node]);
} }
} }
@ -187,7 +185,7 @@ var visitor = types.PathVisitor.fromMethodsObject({
function shouldNotHoistAbove(stmtPath) { function shouldNotHoistAbove(stmtPath) {
var value = stmtPath.value; var value = stmtPath.value;
n.Statement.assert(value); t.assertStatement(value);
// If the first statement is a "use strict" declaration, make sure to // If the first statement is a "use strict" declaration, make sure to
// insert hoisted declarations afterwards. // insert hoisted declarations afterwards.
@ -210,11 +208,11 @@ function shouldNotHoistAbove(stmtPath) {
} }
var awaitVisitor = types.PathVisitor.fromMethodsObject({ var awaitVisitor = types.PathVisitor.fromMethodsObject({
visitFunction: function() { visitFunction: function () {
return false; // Don't descend into nested function scopes. return false; // Don't descend into nested function scopes.
}, },
visitAwaitExpression: function(path) { visitAwaitExpression: function (path) {
// Convert await expressions to yield expressions. // Convert await expressions to yield expressions.
return t.yieldExpression(path.value.argument, false); return t.yieldExpression(path.value.argument, false);
} }

View File

@ -88,6 +88,9 @@ LetScoping.prototype.run = function () {
this.info = this.getInfo(); this.info = this.getInfo();
// remap all let references that exist in upper scopes to their uid
this.remap();
// this is a block within a `Function` so we can safely leave it be // this is a block within a `Function` so we can safely leave it be
if (t.isFunction(this.parent)) return this.noClosure(); if (t.isFunction(this.parent)) return this.noClosure();
@ -138,23 +141,29 @@ LetScoping.prototype.run = function () {
}; };
/** /**
* There are no let references accessed within a closure so we can just traverse * There are no let references accessed within a closure so we can just turn the
* through this block and replace all references that exist in a higher scope to * lets into vars.
* their uids.
*/ */
LetScoping.prototype.noClosure = function () { LetScoping.prototype.noClosure = function () {
var replacements = this.info.duplicates; standardiseLets(this.info.declarators);
var declarators = this.info.declarators; };
var block = this.block;
standardiseLets(declarators); /**
* Traverse through block and replace all references that exist in a higher
* scope to their uids.
*/
LetScoping.prototype.remap = function () {
var replacements = this.info.duplicates;
var block = this.block;
if (_.isEmpty(replacements)) return; if (_.isEmpty(replacements)) return;
var replace = function (node, parent) { var replace = function (node, parent, scope) {
if (!t.isIdentifier(node)) return; if (!t.isIdentifier(node)) return;
if (!t.isReferenced(node, parent)) return; if (!t.isReferenced(node, parent)) return;
if (scope && scope.hasOwn(node.name)) return;
node.name = replacements[node.name] || node.name; node.name = replacements[node.name] || node.name;
}; };
@ -260,7 +269,7 @@ LetScoping.prototype.checkFor = function () {
return false; return false;
} }
if (forParent && !node.label) { if (forParent && node && !node.label) {
if (t.isBreakStatement(node)) { if (t.isBreakStatement(node)) {
has.hasBreak = true; has.hasBreak = true;
replace = t.returnStatement(t.literal("break")); replace = t.returnStatement(t.literal("break"));

View File

@ -2,14 +2,25 @@ var _ = require("lodash");
var t = exports; var t = exports;
var addAssert = function (type, is) {
t["assert" + type] = function (node, opts) {
opts = opts || {};
if (!is(node, opts)) {
throw new Error("Expected type " + JSON.stringify(type) + " with option " + JSON.stringify(opts));
}
};
};
// //
t.VISITOR_KEYS = require("./visitor-keys"); t.VISITOR_KEYS = require("./visitor-keys");
_.each(t.VISITOR_KEYS, function (keys, type) { _.each(t.VISITOR_KEYS, function (keys, type) {
t["is" + type] = function (node, opts) { var is = t["is" + type] = function (node, opts) {
return node && node.type === type && t.shallowEqual(node, opts); return node && node.type === type && t.shallowEqual(node, opts);
}; };
addAssert(type, is);
}); });
// //
@ -43,17 +54,21 @@ _.each(t.ALIAS_KEYS, function (aliases, type) {
_.each(_aliases, function (types, type) { _.each(_aliases, function (types, type) {
t[type.toUpperCase() + "_TYPES"] = types; t[type.toUpperCase() + "_TYPES"] = types;
t["is" + type] = function (node, opts) { var is = t["is" + type] = function (node, opts) {
return node && _.contains(types, node.type) && t.shallowEqual(node, opts); return node && _.contains(types, node.type) && t.shallowEqual(node, opts);
}; };
addAssert(type, is);
}); });
// //
t.isExpression = function (node) { t.isExpression = function (node) {
return !t.isDeclaration(node); return !t.isStatement(node);
}; };
addAssert("Expression", t.isExpression);
// //
t.shallowEqual = function (actual, expected) { t.shallowEqual = function (actual, expected) {

View File

@ -37,6 +37,21 @@ exports.list = function (val) {
return val ? val.split(",") : []; return val ? val.split(",") : [];
}; };
exports.regexify = function (val) {
if (!val) return new RegExp;
if (_.isArray(val)) val = val.join("|");
if (_.isString(val)) return new RegExp(val || "");
if (_.isRegExp(val)) return val;
throw new TypeError("illegal type for regexify");
};
exports.arrayify = function (val) {
if (!val) return [];
if (_.isString(val)) return exports.list(val);
if (_.isArray(val)) return val;
throw new TypeError("illegal type for arrayify");
};
exports.getUid = function (parent, file) { exports.getUid = function (parent, file) {
var node; var node;

View File

@ -1,7 +1,7 @@
{ {
"name": "6to5", "name": "6to5",
"description": "Turn ES6 code into readable vanilla ES5 with source maps", "description": "Turn ES6 code into readable vanilla ES5 with source maps",
"version": "1.12.20", "version": "1.12.21",
"author": "Sebastian McKenzie <sebmck@gmail.com>", "author": "Sebastian McKenzie <sebmck@gmail.com>",
"homepage": "https://github.com/6to5/6to5", "homepage": "https://github.com/6to5/6to5",
"repository": { "repository": {
@ -37,17 +37,17 @@
"dependencies": { "dependencies": {
"ast-types": "~0.6.0", "ast-types": "~0.6.0",
"commander": "2.5.0", "commander": "2.5.0",
"fs-readdir-recursive": "0.0.2", "fs-readdir-recursive": "0.1.0",
"lodash": "2.4.1", "lodash": "2.4.1",
"mkdirp": "0.5.0", "mkdirp": "0.5.0",
"es6-shim": "0.20.2", "es6-shim": "0.20.2",
"es6-symbol": "0.1.1", "es6-symbol": "0.1.1",
"regexpu": "0.3.0", "regexpu": "0.3.0",
"source-map": "0.1.40", "source-map": "0.1.40",
"chokidar": "0.10.5", "chokidar": "0.11.0",
"source-map-support": "0.2.8", "source-map-support": "0.2.8",
"esutils": "1.1.4", "esutils": "1.1.4",
"acorn-6to5": "https://github.com/6to5/acorn-6to5/archive/74d8e9bed20ba302d3504f53d0b1c649968959e1.tar.gz", "acorn-6to5": "0.9.1-2",
"estraverse": "^1.7.0", "estraverse": "^1.7.0",
"private": "^0.1.6" "private": "^0.1.6"
}, },

View File

@ -2,5 +2,12 @@ let x = 1;
{ {
let x = 2; let x = 2;
assert.equal(x, 2); assert.equal(x, 2);
{
let x = 3;
assert.equal(x, 3);
x++;
assert.equal(x, 4);
}
} }
assert.equal(x, 1); assert.equal(x, 1);

View File

@ -0,0 +1,8 @@
export default 42;
export default {};
export default [];
export default foo;
export default function () {}
export default class {}
export default function foo () {}
export default class Foo {}

View File

@ -0,0 +1,13 @@
"use strict";
exports["default"] = 42;
exports["default"] = {};
exports["default"] = [];
exports["default"] = foo;
exports["default"] = function () {};
exports["default"] = function () {};
function foo() {}
exports["default"] = foo;
var Foo = function Foo() {};
exports["default"] = Foo;

View File

@ -0,0 +1,6 @@
export * from "foo";
export {foo} from "foo";
export {foo, bar} from "foo";
export {foo as bar} from "foo";
export {foo as default} from "foo";
export {foo as default, bar} from "foo";

View File

@ -0,0 +1,15 @@
"use strict";
(function (obj) {
for (var i in obj) {
exports[i] = obj[i];
}
})(require("foo"));
exports.foo = require("foo").foo;
exports.foo = require("foo").foo;
exports.bar = require("foo").bar;
exports.bar = require("foo").foo;
exports["default"] = require("foo").foo;
exports["default"] = require("foo").foo;
exports.bar = require("foo").bar;

View File

@ -0,0 +1,5 @@
export {foo};
export {foo, bar};
export {foo as bar};
export {foo as default};
export {foo as default, bar};

View File

@ -0,0 +1,9 @@
"use strict";
exports.foo = foo;
exports.foo = foo;
exports.bar = bar;
exports.bar = foo;
exports["default"] = foo;
exports["default"] = foo;
exports.bar = bar;

View File

@ -0,0 +1,8 @@
export var foo = 1;
export var foo2 = function () {};
export var foo3;
export let foo4 = 2;
export let foo5;
export const foo6 = 3;
export function foo7 () {}
export class foo8 {}

View File

@ -0,0 +1,13 @@
"use strict";
exports.foo7 = foo7;
var foo = exports.foo = 1;
var foo2 = exports.foo2 = function () {};
var foo3;
var foo4 = exports.foo4 = 2;
var foo5;
var foo6 = exports.foo6 = 3;
function foo7() {}
var foo8 = function foo8() {};
exports.foo8 = foo8;

View File

@ -0,0 +1,11 @@
import { isEven } from "./evens";
export function nextOdd(n) {
return isEven(n) ? n + 1 : n + 2;
}
export var isOdd = (function (isEven) {
return function (n) {
return !isEven(n);
};
})(isEven);

View File

@ -0,0 +1,13 @@
"use strict";
exports.nextOdd = nextOdd;
var isEven = require("./evens").isEven;
function nextOdd(n) {
return isEven(n) ? n + 1 : n + 2;
}
var isOdd = exports.isOdd = (function (isEven) {
return function (n) {
return !isEven(n);
};
})(isEven);

View File

@ -0,0 +1,2 @@
import foo from "foo";
import {default as foo} from "foo";

View File

@ -0,0 +1,9 @@
"use strict";
var _interopRequire = function (obj) {
return obj && (obj["default"] || obj);
};
var foo = _interopRequire(require("foo"));
var foo = require("foo")["default"];

View File

@ -0,0 +1 @@
import * as foo from "foo";

View File

@ -0,0 +1,3 @@
"use strict";
var foo = require("foo");

View File

@ -0,0 +1 @@
import foo, {baz as xyz} from "foo";

View File

@ -0,0 +1,9 @@
"use strict";
var _interopRequire = function (obj) {
return obj && (obj["default"] || obj);
};
var foo = _interopRequire(require("foo"));
var xyz = require("foo").baz;

View File

@ -0,0 +1,4 @@
import {bar} from "foo";
import {bar, baz} from "foo";
import {bar as baz} from "foo";
import {bar as baz, xyz} from "foo";

View File

@ -0,0 +1,8 @@
"use strict";
var bar = require("foo").bar;
var bar = require("foo").bar;
var baz = require("foo").baz;
var baz = require("foo").bar;
var baz = require("foo").bar;
var xyz = require("foo").xyz;

View File

@ -0,0 +1,3 @@
import "foo";
import "foo-bar";
import "./directory/foo-bar";

View File

@ -0,0 +1,7 @@
"use strict";
require("foo");
require("foo-bar");
require("./directory/foo-bar");

View File

@ -0,0 +1,3 @@
{
"modules": "commonInterop"
}

View File

@ -0,0 +1,12 @@
import "foo";
import "foo-bar";
import "./directory/foo-bar";
import foo from "foo";
import * as foo from "foo";
import {bar} from "foo";
import {foo as bar} from "foo";
export {test};
export var test = 5;
export default test;

View File

@ -0,0 +1,22 @@
"use strict";
var _interopRequire = function (obj) {
return obj && (obj["default"] || obj);
};
require("foo");
require("foo-bar");
require("./directory/foo-bar");
var foo = _interopRequire(require("foo"));
var foo = require("foo");
var bar = require("foo").bar;
var bar = require("foo").foo;
exports.test = test;
var test = exports.test = 5;
exports["default"] = test;