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:
commit
a37f2093bc
11
CHANGELOG.md
11
CHANGELOG.md
@ -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
|
||||||
|
|||||||
@ -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
|
||||||
|
|||||||
@ -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);
|
||||||
|
|||||||
@ -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;
|
||||||
|
|||||||
@ -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);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@ -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) {
|
||||||
|
|||||||
@ -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);
|
||||||
};
|
};
|
||||||
|
|||||||
3
lib/6to5/templates/interop-require.js
Normal file
3
lib/6to5/templates/interop-require.js
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
(function (obj) {
|
||||||
|
return obj && (obj["default"] || obj);
|
||||||
|
})
|
||||||
29
lib/6to5/transformation/modules/common-interop.js
Normal file
29
lib/6to5/transformation/modules/common-interop.js
Normal 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);
|
||||||
|
};
|
||||||
@ -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);
|
||||||
|
|||||||
@ -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({
|
||||||
|
|||||||
@ -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");
|
||||||
|
};
|
||||||
@ -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"))
|
||||||
|
));
|
||||||
|
};
|
||||||
@ -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));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -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));
|
||||||
}
|
}
|
||||||
|
|||||||
@ -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);
|
||||||
};
|
};
|
||||||
|
|||||||
@ -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];
|
||||||
|
|||||||
@ -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,
|
||||||
|
|||||||
@ -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);
|
||||||
|
};
|
||||||
|
|||||||
@ -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);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -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"));
|
||||||
|
|||||||
@ -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) {
|
||||||
|
|||||||
@ -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;
|
||||||
|
|
||||||
|
|||||||
@ -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"
|
||||||
},
|
},
|
||||||
|
|||||||
@ -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);
|
||||||
|
|||||||
8
test/fixtures/transformation/modules-common-interop/exports-default/actual.js
vendored
Normal file
8
test/fixtures/transformation/modules-common-interop/exports-default/actual.js
vendored
Normal 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 {}
|
||||||
13
test/fixtures/transformation/modules-common-interop/exports-default/expected.js
vendored
Normal file
13
test/fixtures/transformation/modules-common-interop/exports-default/expected.js
vendored
Normal 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;
|
||||||
6
test/fixtures/transformation/modules-common-interop/exports-from/actual.js
vendored
Normal file
6
test/fixtures/transformation/modules-common-interop/exports-from/actual.js
vendored
Normal 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";
|
||||||
15
test/fixtures/transformation/modules-common-interop/exports-from/expected.js
vendored
Normal file
15
test/fixtures/transformation/modules-common-interop/exports-from/expected.js
vendored
Normal 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;
|
||||||
5
test/fixtures/transformation/modules-common-interop/exports-named/actual.js
vendored
Normal file
5
test/fixtures/transformation/modules-common-interop/exports-named/actual.js
vendored
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
export {foo};
|
||||||
|
export {foo, bar};
|
||||||
|
export {foo as bar};
|
||||||
|
export {foo as default};
|
||||||
|
export {foo as default, bar};
|
||||||
9
test/fixtures/transformation/modules-common-interop/exports-named/expected.js
vendored
Normal file
9
test/fixtures/transformation/modules-common-interop/exports-named/expected.js
vendored
Normal 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;
|
||||||
8
test/fixtures/transformation/modules-common-interop/exports-variable/actual.js
vendored
Normal file
8
test/fixtures/transformation/modules-common-interop/exports-variable/actual.js
vendored
Normal 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 {}
|
||||||
13
test/fixtures/transformation/modules-common-interop/exports-variable/expected.js
vendored
Normal file
13
test/fixtures/transformation/modules-common-interop/exports-variable/expected.js
vendored
Normal 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;
|
||||||
11
test/fixtures/transformation/modules-common-interop/hoist-function-exports/actual.js
vendored
Normal file
11
test/fixtures/transformation/modules-common-interop/hoist-function-exports/actual.js
vendored
Normal 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);
|
||||||
13
test/fixtures/transformation/modules-common-interop/hoist-function-exports/expected.js
vendored
Normal file
13
test/fixtures/transformation/modules-common-interop/hoist-function-exports/expected.js
vendored
Normal 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);
|
||||||
2
test/fixtures/transformation/modules-common-interop/imports-default/actual.js
vendored
Normal file
2
test/fixtures/transformation/modules-common-interop/imports-default/actual.js
vendored
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
import foo from "foo";
|
||||||
|
import {default as foo} from "foo";
|
||||||
9
test/fixtures/transformation/modules-common-interop/imports-default/expected.js
vendored
Normal file
9
test/fixtures/transformation/modules-common-interop/imports-default/expected.js
vendored
Normal 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"];
|
||||||
1
test/fixtures/transformation/modules-common-interop/imports-glob/actual.js
vendored
Normal file
1
test/fixtures/transformation/modules-common-interop/imports-glob/actual.js
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
import * as foo from "foo";
|
||||||
3
test/fixtures/transformation/modules-common-interop/imports-glob/expected.js
vendored
Normal file
3
test/fixtures/transformation/modules-common-interop/imports-glob/expected.js
vendored
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
"use strict";
|
||||||
|
|
||||||
|
var foo = require("foo");
|
||||||
1
test/fixtures/transformation/modules-common-interop/imports-mixing/actual.js
vendored
Normal file
1
test/fixtures/transformation/modules-common-interop/imports-mixing/actual.js
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
import foo, {baz as xyz} from "foo";
|
||||||
9
test/fixtures/transformation/modules-common-interop/imports-mixing/expected.js
vendored
Normal file
9
test/fixtures/transformation/modules-common-interop/imports-mixing/expected.js
vendored
Normal 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;
|
||||||
4
test/fixtures/transformation/modules-common-interop/imports-named/actual.js
vendored
Normal file
4
test/fixtures/transformation/modules-common-interop/imports-named/actual.js
vendored
Normal 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";
|
||||||
8
test/fixtures/transformation/modules-common-interop/imports-named/expected.js
vendored
Normal file
8
test/fixtures/transformation/modules-common-interop/imports-named/expected.js
vendored
Normal 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;
|
||||||
3
test/fixtures/transformation/modules-common-interop/imports/actual.js
vendored
Normal file
3
test/fixtures/transformation/modules-common-interop/imports/actual.js
vendored
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
import "foo";
|
||||||
|
import "foo-bar";
|
||||||
|
import "./directory/foo-bar";
|
||||||
7
test/fixtures/transformation/modules-common-interop/imports/expected.js
vendored
Normal file
7
test/fixtures/transformation/modules-common-interop/imports/expected.js
vendored
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
"use strict";
|
||||||
|
|
||||||
|
require("foo");
|
||||||
|
|
||||||
|
require("foo-bar");
|
||||||
|
|
||||||
|
require("./directory/foo-bar");
|
||||||
3
test/fixtures/transformation/modules-common-interop/options.json
vendored
Normal file
3
test/fixtures/transformation/modules-common-interop/options.json
vendored
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
{
|
||||||
|
"modules": "commonInterop"
|
||||||
|
}
|
||||||
12
test/fixtures/transformation/modules-common-interop/overview/actual.js
vendored
Normal file
12
test/fixtures/transformation/modules-common-interop/overview/actual.js
vendored
Normal 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;
|
||||||
22
test/fixtures/transformation/modules-common-interop/overview/expected.js
vendored
Normal file
22
test/fixtures/transformation/modules-common-interop/overview/expected.js
vendored
Normal 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;
|
||||||
Loading…
x
Reference in New Issue
Block a user