Compare commits

...

52 Commits

Author SHA1 Message Date
Sebastian McKenzie
bb17571e56 v3.5.0 2015-02-08 16:35:45 +11:00
Sebastian McKenzie
9161af58c0 fix linting errors 2015-02-08 16:32:08 +11:00
Sebastian McKenzie
e39f4e8025 update 3.5.0 changelog 2015-02-08 16:31:24 +11:00
Sebastian McKenzie
f5e9909e71 Merge pull request #716 from daliwali/master
Make `__esModule` property not enumerable
2015-02-08 16:30:26 +11:00
Sebastian McKenzie
46913fc55f add 3.5.0 changelog 2015-02-08 16:22:12 +11:00
Dali Zheng
d358a86e98 make __esModule property not enumerable 2015-02-07 21:19:11 -08:00
Sebastian McKenzie
055545980c update traceur test runner 2015-02-08 16:19:05 +11:00
Sebastian McKenzie
6fd7f9868e upgrade acorn-6to5 2015-02-08 16:18:54 +11:00
Sebastian McKenzie
e8184a9bc5 fix browser api location in browser test 2015-02-08 14:34:43 +11:00
Sebastian McKenzie
f74de3ef55 move destructuring and parameters.rest transformer to above blockScoping 2015-02-08 14:34:34 +11:00
Sebastian McKenzie
9624f8287d add checkNode to block scoped functions transformer 2015-02-08 14:34:10 +11:00
Sebastian McKenzie
e42d5a889e make destructuring in catch clauses block scoped and add support for non-variable destructuring in for-in/of heads 2015-02-08 14:33:55 +11:00
Sebastian McKenzie
4c8e6481b6 make default parameters iife invocation less serious 2015-02-08 09:54:24 +11:00
Sebastian McKenzie
0867df2691 fix ForOf block body not properly inheriting declarations 2015-02-08 09:50:12 +11:00
Sebastian McKenzie
b06f99ab30 add iife detection to non-identifier params in default parameters 2015-02-08 09:37:06 +11:00
Sebastian McKenzie
9afa3f6b58 add opts param to t.isReferencedIdentifier 2015-02-08 09:31:41 +11:00
Sebastian McKenzie
785cb4b72f allow optional transformer to be set via the whitelist 2015-02-08 09:31:30 +11:00
Sebastian McKenzie
dabe69856a add additional checks to transformers 2015-02-08 09:31:19 +11:00
Sebastian McKenzie
24e70802b5 fix block scoped tracking in functions - fixes #710 2015-02-08 09:31:04 +11:00
Sebastian McKenzie
c1ba55a52d Merge pull request #714 from RReverser/master
Added complete TCO (tail call optimization).
2015-02-08 08:55:19 +11:00
Ingvar Stepanyan
4c318166e1 Added complete TCO (tail call optimization).
Works across functions and generates simpler and faster code than #701.
Works even across files when used in conjunction with `runtime` option.

Closes #256.
2015-02-07 22:22:38 +02:00
Sebastian McKenzie
c0af67eca1 add support for super in object literals - fixes #411 2015-02-08 02:01:17 +11:00
Sebastian McKenzie
eb14f1da00 implement optional TDZ - fixes #563 2015-02-08 01:27:22 +11:00
Sebastian McKenzie
3361b81658 expose parentPath 2015-02-08 01:27:00 +11:00
Sebastian McKenzie
a15f218e9b dump code to esvalid errors 2015-02-08 01:26:46 +11:00
Sebastian McKenzie
067cf43f52 fix File::addHelper unknown helper error message 2015-02-08 00:01:26 +11:00
Sebastian McKenzie
689ce048e6 remove tail call exec test 2015-02-07 23:52:41 +11:00
Sebastian McKenzie
8a143bf957 use a template in tail call transformer - @RReverser 2015-02-07 23:52:35 +11:00
Sebastian McKenzie
9f7bcf585d remove dead TraversalContext code 2015-02-07 23:51:05 +11:00
Sebastian McKenzie
f9efd8a272 fix error message in File::addHelper 2015-02-07 23:50:56 +11:00
Sebastian McKenzie
8cd2326ff9 Merge branch 'master' of github.com:6to5/6to5 2015-02-07 23:37:51 +11:00
Sebastian McKenzie
eb1ae70bfa Merge pull request #701 from RReverser/master
Add tail recursion optimization.
2015-02-07 23:37:43 +11:00
Ingvar Stepanyan
24ef81908c Increase test timeout for Travis. 2015-02-07 14:34:23 +02:00
Ingvar Stepanyan
b53b41cef3 Provide placeholders for proper function length. 2015-02-07 14:26:03 +02:00
Sebastian McKenzie
ad245ed46a 3.4.1 2015-02-07 19:48:59 +11:00
Sebastian McKenzie
3f6199493e v3.4.1 2015-02-07 19:48:28 +11:00
Sebastian McKenzie
e06aac4783 Revert "make export { foo as default }; trigger common interop"
This reverts commit 07c7b5b419.
2015-02-07 19:40:49 +11:00
Sebastian McKenzie
6a5adfe338 update 3.4.1 changelog 2015-02-07 19:40:29 +11:00
Sebastian McKenzie
07c7b5b419 make export { foo as default }; trigger common interop 2015-02-07 19:29:59 +11:00
Sebastian McKenzie
7f985fe08a fix incorrect strict module formatter variable - fixes #706 2015-02-07 19:29:32 +11:00
Sebastian McKenzie
38f02a6429 add 3.4.1 changelog 2015-02-07 19:19:55 +11:00
Sebastian McKenzie
f943bdcac0 Merge branch 'master' of github.com:6to5/6to5 2015-02-07 19:18:29 +11:00
Sebastian McKenzie
8dc634edfc add options to require cache key - fixes #707 2015-02-07 19:18:12 +11:00
Sebastian McKenzie
05b9cf17f0 Merge pull request #708 from tricknotes/avoid-conflict
Switch short option of `--module-ids` from `-i` to `-M`
2015-02-07 19:12:22 +11:00
Ryunosuke SATO
69bbe89616 Switch short option of --module-ids from -i to -M
`-i` conflicts with `--optional` option.

```
$ bin/6to5/index.js --help | grep "\-i,"
    -i, --optional [list]        List of optional transformers to enable
    -i, --module-ids             Insert module id in modules
```
2015-02-07 16:37:38 +09:00
Sebastian McKenzie
6b49958f7c Merge branch 'master' of github.com:6to5/6to5 2015-02-07 15:59:15 +11:00
Sebastian McKenzie
e75ce94578 move reactCompat option onto an optional transformer 2015-02-07 15:59:00 +11:00
Sebastian McKenzie
f666473724 Merge pull request #705 from cesarandreu/patch-2
Add 6to5-runtime README
2015-02-07 13:54:58 +11:00
Cesar Andreu
ae817e3c9c Add 6to5-runtime README 2015-02-06 18:53:42 -08:00
Sebastian McKenzie
2e9352de14 3.4.0 2015-02-07 10:44:06 +11:00
Sebastian McKenzie
1e9e55ddef fix browser build location in makefile 2015-02-07 10:42:28 +11:00
Ingvar Stepanyan
5b2216b348 Add tail recursion optimization.
As per ES6, VMs should perform tail call optimization and prevent growth of call stack.
This adds tail call optimization for recursion case (when function has explicit name and calls itself in `return`).
Cross-function optimization is not currently performed as it's more complicated and requires value tracking.
2015-02-06 16:34:35 +02:00
115 changed files with 1157 additions and 460 deletions

View File

@@ -6,6 +6,6 @@ charset = utf-8
trim_trailing_whitespace = true
insert_final_newline = true
[*.js]
[*.{js,json}]
indent_style = space
indent_size = 2

View File

@@ -11,6 +11,25 @@
_Note: Gaps between patch versions are faulty/broken releases._
## 3.5.0
* **Bug Fix**
* Destructuring patterns as the left operator in `ForInStatement`/`ForOfStatement`.
* **Polish**
* Make default parameter IIFE invocation smarter.
* Make `__esModule` flag non-enumerable. Thanks [@daliwali](https://github.com/daliwali)!
* **New Feature**
* Optional `es6.blockScopingTDZ` is now completely functional and handles all edgecases.
* `super` in object literals.
* Tail call optimisation. Thanks [@RReverser](https://github.com/RReverser)!
## 3.4.1
* **Bug Fix**
* Fix conflicting `--module-ids` shorthand arg in `$ 6to5`.
* Add require hook options to cache key.
* Fix strict module formatter.
## 3.4.0
* **New Feature**

View File

@@ -18,7 +18,7 @@ build:
node $(BROWSERIFY_CMD) -e lib/6to5/polyfill.js >dist/polyfill.js
node $(UGLIFY_CMD) dist/polyfill.js >dist/polyfill.min.js
node $(BROWSERIFY_CMD) lib/6to5/browser.js -s to5 >dist/6to5.js
node $(BROWSERIFY_CMD) lib/6to5/api/browser.js -s to5 >dist/6to5.js
node $(UGLIFY_CMD) dist/6to5.js >dist/6to5.min.js
node bin/6to5-runtime >dist/runtime.js

View File

@@ -23,7 +23,7 @@ commander.option("-L, --loose [list]", "List of transformers to enable loose mod
commander.option("-o, --out-file [out]", "Compile all input files into a single file");
commander.option("-d, --out-dir [out]", "Compile an input directory of modules into an output directory");
commander.option("-c, --remove-comments", "Remove comments from the compiled code", false);
commander.option("-i, --module-ids", "Insert module id in modules", false);
commander.option("-M, --module-ids", "Insert module id in modules", false);
commander.option("-R, --react-compat", "Makes the react transformer produce pre-v0.12 code");
commander.option("--keep-module-id-extensions", "Keep extensions when generating module ids", false);

View File

@@ -44,8 +44,10 @@ var mtime = function (filename) {
var compile = function (filename) {
var result;
var cacheKey = filename + ":" + JSON.stringify(transformOpts);
if (cache) {
var cached = cache[filename];
var cached = cache[cacheKey];
if (cached && cached.mtime === mtime(filename)) {
result = cached;
}
@@ -60,7 +62,7 @@ var compile = function (filename) {
if (cache) {
result.mtime = mtime(filename);
cache[filename] = result;
cache[cacheKey] = result;
}
maps[filename] = result.map;

View File

@@ -54,7 +54,10 @@ File.helpers = [
"get",
"set",
"class-call-check",
"object-destructuring-empty"
"object-destructuring-empty",
"temporal-undefined",
"temporal-assert-defined",
"tail-call"
];
File.validOptions = [
@@ -163,6 +166,12 @@ File.prototype.normalizeOptions = function (opts) {
opts.optional = transform._ensureTransformerNames("optional", opts.optional);
opts.loose = transform._ensureTransformerNames("loose", opts.loose);
if (opts.reactCompat) {
opts.optional.push("reactCompat");
console.error("The reactCompat option has been moved into the optional transformer " +
"`reactCompat` - backwards compatibility will be removed in v4.0.0");
}
return opts;
};
@@ -291,7 +300,7 @@ File.prototype.isConsequenceExpressionStatement = function (node) {
File.prototype.addHelper = function (name) {
if (!contains(File.helpers, name)) {
throw new ReferenceError("unknown declaration " + name);
throw new ReferenceError("Unknown helper " + name);
}
var program = this.ast.program;

View File

@@ -0,0 +1,278 @@
"use strict";
// Based upon the excellent jsx-transpiler by Ingvar Stepanyan (RReverser)
// https://github.com/RReverser/jsx-transpiler
// jsx
var isString = require("lodash/lang/isString");
var esutils = require("esutils");
var react = require("./react");
var t = require("../../types");
module.exports = function (exports, opts) {
exports.check = function (node) {
if (t.isJSX(node)) return true;
if (react.isCreateClass(node)) return true;
return false;
};
exports.JSXIdentifier = function (node, parent) {
if (node.name === "this" && t.isReferenced(node, parent)) {
return t.thisExpression();
} else if (esutils.keyword.isIdentifierName(node.name)) {
node.type = "Identifier";
} else {
return t.literal(node.name);
}
};
exports.JSXNamespacedName = function (node, parent, scope, file) {
throw file.errorWithNode(node, "Namespace tags are not supported. ReactJSX is not XML.");
};
exports.JSXMemberExpression = {
exit: function (node) {
node.computed = t.isLiteral(node.property);
node.type = "MemberExpression";
}
};
exports.JSXExpressionContainer = function (node) {
return node.expression;
};
exports.JSXAttribute = {
exit: function (node) {
var value = node.value || t.literal(true);
return t.inherits(t.property("init", node.name, value), node);
}
};
exports.JSXOpeningElement = {
exit: function (node, parent, scope, file) {
var tagExpr = node.name;
var args = [];
var tagName;
if (t.isIdentifier(tagExpr)) {
tagName = tagExpr.name;
} else if (t.isLiteral(tagExpr)) {
tagName = tagExpr.value;
}
var state = {
tagExpr: tagExpr,
tagName: tagName,
args: args
};
if (opts.pre) {
opts.pre(state);
}
var attribs = node.attributes;
if (attribs.length) {
attribs = buildJSXOpeningElementAttributes(attribs, file);
} else {
attribs = t.literal(null);
}
args.push(attribs);
if (opts.post) {
opts.post(state);
}
return state.call || t.callExpression(state.callee, args);
}
};
/**
* The logic for this is quite terse. It's because we need to
* support spread elements. We loop over all attributes,
* breaking on spreads, we then push a new object containg
* all prior attributes to an array for later processing.
*/
var buildJSXOpeningElementAttributes = function (attribs, file) {
var _props = [];
var objs = [];
var pushProps = function () {
if (!_props.length) return;
objs.push(t.objectExpression(_props));
_props = [];
};
while (attribs.length) {
var prop = attribs.shift();
if (t.isJSXSpreadAttribute(prop)) {
pushProps();
objs.push(prop.argument);
} else {
_props.push(prop);
}
}
pushProps();
if (objs.length === 1) {
// only one object
attribs = objs[0];
} else {
// looks like we have multiple objects
if (!t.isObjectExpression(objs[0])) {
objs.unshift(t.objectExpression([]));
}
// spread it
attribs = t.callExpression(
file.addHelper("extends"),
objs
);
}
return attribs;
};
exports.JSXElement = {
exit: function (node) {
var callExpr = node.openingElement;
for (var i = 0; i < node.children.length; i++) {
var child = node.children[i];
if (t.isLiteral(child) && typeof child.value === "string") {
cleanJSXElementLiteralChild(child, callExpr.arguments);
continue;
} else if (t.isJSXEmptyExpression(child)) {
continue;
}
callExpr.arguments.push(child);
}
callExpr.arguments = flatten(callExpr.arguments);
if (callExpr.arguments.length >= 3) {
callExpr._prettyCall = true;
}
return t.inherits(callExpr, node);
}
};
var isStringLiteral = function (node) {
return t.isLiteral(node) && isString(node.value);
};
var flatten = function (args) {
var flattened = [];
var last;
for (var i = 0; i < args.length; i++) {
var arg = args[i];
if (isStringLiteral(arg) && isStringLiteral(last)) {
last.value += arg.value;
} else {
last = arg;
flattened.push(arg);
}
}
return flattened;
};
var cleanJSXElementLiteralChild = function (child, args) {
var lines = child.value.split(/\r\n|\n|\r/);
var lastNonEmptyLine = 0;
var i;
for (i = 0; i < lines.length; i++) {
if (lines[i].match(/[^ \t]/)) {
lastNonEmptyLine = i;
}
}
for (i = 0; i < lines.length; i++) {
var line = lines[i];
var isFirstLine = i === 0;
var isLastLine = i === lines.length - 1;
var isLastNonEmptyLine = i === lastNonEmptyLine;
// replace rendered whitespace tabs with spaces
var trimmedLine = line.replace(/\t/g, " ");
// trim whitespace touching a newline
if (!isFirstLine) {
trimmedLine = trimmedLine.replace(/^[ ]+/, "");
}
// trim whitespace touching an endline
if (!isLastLine) {
trimmedLine = trimmedLine.replace(/[ ]+$/, "");
}
if (trimmedLine) {
if (!isLastNonEmptyLine) {
trimmedLine += " ";
}
args.push(t.literal(trimmedLine));
}
}
};
// display names
var addDisplayName = function (id, call) {
var props = call.arguments[0].properties;
var safe = true;
for (var i = 0; i < props.length; i++) {
var prop = props[i];
if (t.isIdentifier(prop.key, { name: "displayName" })) {
safe = false;
break;
}
}
if (safe) {
props.unshift(t.property("init", t.identifier("displayName"), t.literal(id)));
}
};
exports.ExportDeclaration = function (node, parent, scope, file) {
if (node.default && react.isCreateClass(node.declaration)) {
addDisplayName(file.opts.basename, node.declaration);
}
};
exports.AssignmentExpression =
exports.Property =
exports.VariableDeclarator = function (node) {
var left, right;
if (t.isAssignmentExpression(node)) {
left = node.left;
right = node.right;
} else if (t.isProperty(node)) {
left = node.key;
right = node.value;
} else if (t.isVariableDeclarator(node)) {
left = node.id;
right = node.init;
}
if (t.isMemberExpression(left)) {
left = left.property;
}
if (t.isIdentifier(left) && react.isCreateClass(right)) {
addDisplayName(left.name, right);
}
};
};

View File

@@ -20,3 +20,7 @@ exports.isCreateClass = function (node) {
};
exports.isReactComponent = t.buildMatchMemberExpression("React.Component");
exports.isCompatTag = function (tagName) {
return tagName && /^[a-z]|\-/.test(tagName);
};

View File

@@ -8,13 +8,17 @@ var t = require("../../types");
* Description
*
* @param {Object} opts
* @param {Boolean} [inClass]
*/
function ReplaceSupers(opts) {
this.topLevelThisReference = null;
function ReplaceSupers(opts, inClass) {
this.topLevelThisReference = opts.topLevelThisReference;
this.methodNode = opts.methodNode;
this.className = opts.className;
this.superName = opts.superName;
this.isStatic = opts.isStatic;
this.hasSuper = false;
this.inClass = inClass;
this.isLoose = opts.isLoose;
this.scope = opts.scope;
this.file = opts.file;
@@ -28,19 +32,21 @@ function ReplaceSupers(opts) {
* _set(Object.getPrototypeOf(CLASS.prototype), "METHOD", "VALUE", this)
*
* @param {Node} property
* @param {boolean} isStatic
* @param {boolean} isComputed
* @param {Node} value
* @param {Boolean} isComputed
* @param {Node} thisExpression
*
* @returns {Node}
*/
ReplaceSupers.prototype.setSuperProperty = function (property, value, isStatic, isComputed, thisExpression) {
ReplaceSupers.prototype.setSuperProperty = function (property, value, isComputed, thisExpression) {
return t.callExpression(
this.file.addHelper("set"),
[
t.callExpression(
t.memberExpression(t.identifier("Object"), t.identifier("getPrototypeOf")),
[
isStatic ? this.className : t.memberExpression(this.className, t.identifier("prototype"))
this.isStatic ? this.className : t.memberExpression(this.className, t.identifier("prototype"))
]
),
isComputed ? property : t.literal(property.name),
@@ -58,20 +64,20 @@ ReplaceSupers.prototype.setSuperProperty = function (property, value, isStatic,
* _get(Object.getPrototypeOf(CLASS.prototype), "METHOD", this)
*
* @param {Node} property
* @param {boolean} isStatic
* @param {boolean} isComputed
* @param {Boolean} isComputed
* @param {Node} thisExpression
*
* @returns {Node}
*/
ReplaceSupers.prototype.getSuperProperty = function (property, isStatic, isComputed, thisExpression) {
ReplaceSupers.prototype.getSuperProperty = function (property, isComputed, thisExpression) {
return t.callExpression(
this.file.addHelper("get"),
[
t.callExpression(
t.memberExpression(t.identifier("Object"), t.identifier("getPrototypeOf")),
[
isStatic ? this.className : t.memberExpression(this.className, t.identifier("prototype"))
this.isStatic ? this.className : t.memberExpression(this.className, t.identifier("prototype"))
]
),
isComputed ? property : t.literal(property.name),
@@ -153,7 +159,8 @@ ReplaceSupers.prototype.getThisReference = function () {
* @returns {Object}
*/
ReplaceSupers.prototype.getLooseSuperProperty = function (methodNode, id, parent) {
ReplaceSupers.prototype.getLooseSuperProperty = function (id, parent) {
var methodNode = this.methodNode;
var methodName = methodNode.key;
var superName = this.superName || t.identifier("Function");
@@ -195,13 +202,15 @@ ReplaceSupers.prototype.getLooseSuperProperty = function (methodNode, id, parent
ReplaceSupers.prototype.looseHandle = function (getThisReference, node, parent) {
if (t.isIdentifier(node, { name: "super" })) {
return this.getLooseSuperProperty(this.methodNode, node, parent);
this.hasSuper = true;
return this.getLooseSuperProperty(node, parent);
} else if (t.isCallExpression(node)) {
var callee = node.callee;
if (!t.isMemberExpression(callee)) return;
if (callee.object.name !== "super") return;
// super.test(); -> ClassName.prototype.MethodName.call(this);
this.hasSuper = true;
t.appendToMemberExpression(callee, t.identifier("call"));
node.arguments.unshift(getThisReference());
}
@@ -237,7 +246,7 @@ ReplaceSupers.prototype.specHandle = function (getThisReference, node, parent) {
// bare `super` call is illegal inside non-constructors
// - https://esdiscuss.org/topic/super-call-in-methods
// - https://twitter.com/wycats/status/544553184396836864
if (methodNode.key.name !== "constructor") {
if (methodNode.key.name !== "constructor" || !this.inClass) {
var methodName = methodNode.key.name || "METHOD_NAME";
throw this.file.errorWithNode(node, "Direct super call is illegal in non-constructor, use super." + methodName + "() instead");
}
@@ -253,13 +262,16 @@ ReplaceSupers.prototype.specHandle = function (getThisReference, node, parent) {
computed = node.computed;
} else if (t.isAssignmentExpression(node) && isSuper(node.left.object, node.left) && methodNode.kind === "set") {
// super.name = "val"; -> _set(Object.getPrototypeOf(ClassName.prototype), "name", this);
return this.setSuperProperty(node.left.property, node.right, methodNode.static, node.left.computed, getThisReference());
this.hasSuper = true;
return this.setSuperProperty(node.left.property, node.right, node.left.computed, getThisReference());
}
if (!property) return;
this.hasSuper = true;
thisReference = getThisReference();
var superProperty = this.getSuperProperty(property, methodNode.static, computed, thisReference);
var superProperty = this.getSuperProperty(property, computed, thisReference);
if (args) {
if (args.length === 1 && t.isSpreadElement(args[0])) {
// super(...arguments);

View File

@@ -4,7 +4,7 @@ var util = require("../../util");
module.exports = function (Parent) {
var Constructor = function () {
this.noInteropRequire = true;
this.noInteropRequireExport = true;
Parent.apply(this, arguments);
};

View File

@@ -1 +1 @@
var VARIABLE_NAME = ARGUMENTS[ARGUMENT_KEY] === undefined ? DEFAULT_VALUE : ARGUMENTS[ARGUMENT_KEY];
let VARIABLE_NAME = ARGUMENTS[ARGUMENT_KEY] === undefined ? DEFAULT_VALUE : ARGUMENTS[ARGUMENT_KEY];

View File

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

View File

@@ -0,0 +1,21 @@
(function () {
function Tail(func, args, context) {
this.func = func;
this.args = args;
this.context = context;
}
var isRunning = false;
return function (func, args, context) {
var result = new Tail(func, args, context);
if (!isRunning) {
isRunning = true;
do {
result = result.func.apply(result.context, result.args);
} while (result instanceof Tail);
isRunning = false;
}
return result;
};
})()

View File

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

View File

@@ -0,0 +1 @@
({})

View File

@@ -29,7 +29,7 @@ TransformerPass.prototype.canRun = function () {
// whitelist
var whitelist = opts.whitelist;
if (whitelist.length && !contains(whitelist, key)) return false;
if (whitelist.length) return contains(whitelist, key);
// optional
if (transformer.optional && !contains(opts.optional, key)) return false;

View File

@@ -12,22 +12,18 @@ var visitor = {
// declared node is different in this scope
if (scope.getBinding(node.name) !== declared) return;
var declaredLoc = declared.loc;
var referenceLoc = node.loc;
var assert = t.callExpression(
state.file.addHelper("temporal-assert-defined"),
[node, t.literal(node.name), state.file.addHelper("temporal-undefined")]
);
if (!declaredLoc || !referenceLoc) return;
this.skip();
// does this reference appear on a line before the declaration?
var before = referenceLoc.start.line < declaredLoc.start.line;
if (referenceLoc.start.line === declaredLoc.start.line) {
// this reference appears on the same line
// check it appears before the declaration
before = referenceLoc.start.col < declaredLoc.start.col;
}
if (before) {
throw state.file.errorWithNode(node, "Temporal dead zone - accessing a variable before it's initialized");
if (t.isAssignmentExpression(parent) || t.isUpdateExpression(parent)) {
if (parent._ignoreBlockScopingTDZ) return;
this.parentPath.replaceNode(t.sequenceExpression([assert, parent]));
} else {
return t.logicalExpression("&&", assert, node);
}
}
};

View File

@@ -17,7 +17,7 @@ var isLet = function (node, parent) {
if (node.kind !== "let") return false;
// https://github.com/6to5/6to5/issues/255
if (!t.isFor(parent) || t.isFor(parent) && parent.left !== node) {
if (isLetInitable(node, parent)) {
for (var i = 0; i < node.declarations.length; i++) {
var declar = node.declarations[i];
declar.init = declar.init || t.identifier("undefined");
@@ -29,6 +29,10 @@ var isLet = function (node, parent) {
return true;
};
var isLetInitable = function (node, parent) {
return !t.isFor(parent) || t.isFor(parent) && parent.left !== node;
};
var isVar = function (node, parent) {
return t.isVariableDeclaration(node, { kind: "var" }) && !isLet(node, parent);
};
@@ -39,8 +43,26 @@ var standardizeLets = function (declars) {
}
};
exports.VariableDeclaration = function (node, parent) {
isLet(node, parent);
exports.VariableDeclaration = function (node, parent, scope, file) {
if (!isLet(node, parent)) return;
if (isLetInitable(node) && file.transformers["es6.blockScopingTDZ"].canRun()) {
var nodes = [node];
for (var i = 0; i < node.declarations.length; i++) {
var decl = node.declarations[i];
if (decl.init) {
var assign = t.assignmentExpression("=", decl.id, decl.init);
assign._ignoreBlockScopingTDZ = true;
nodes.push(t.expressionStatement(assign));
}
decl.init = file.addHelper("temporal-undefined");
}
node._blockHoist = 2;
return nodes;
}
};
exports.Loop = function (node, parent, scope, file) {

View File

@@ -152,10 +152,11 @@ Class.prototype.buildBody = function () {
methodNode: node,
className: this.className,
superName: this.superName,
isStatic: node.static,
isLoose: this.isLoose,
scope: this.scope,
file: this.file
});
}, true);
replaceSupers.replace();
if (node.key.name === "constructor") {

View File

@@ -179,21 +179,40 @@ Destructuring.prototype.init = function (pattern, parentId) {
exports.ForInStatement =
exports.ForOfStatement = function (node, parent, scope, file) {
var declar = node.left;
if (!t.isVariableDeclaration(declar)) return;
var left = node.left;
var pattern = declar.declarations[0].id;
if (t.isPattern(left)) {
// for ({ length: k } in { abc: 3 });
var temp = scope.generateUidIdentifier("ref");
node.left = t.variableDeclaration("var", [
t.variableDeclarator(temp)
]);
t.ensureBlock(node);
node.body.body.unshift(t.variableDeclaration("var", [
t.variableDeclarator(left, temp)
]));
return;
}
if (!t.isVariableDeclaration(left)) return;
var pattern = left.declarations[0].id;
if (!t.isPattern(pattern)) return;
var key = scope.generateUidIdentifier("ref");
node.left = t.variableDeclaration(declar.kind, [
node.left = t.variableDeclaration(left.kind, [
t.variableDeclarator(key, null)
]);
var nodes = [];
var destructuring = new Destructuring({
kind: declar.kind,
kind: left.kind,
file: file,
scope: scope,
nodes: nodes
@@ -248,7 +267,7 @@ exports.CatchClause = function (node, parent, scope, file) {
var nodes = [];
var destructuring = new Destructuring({
kind: "var",
kind: "let",
file: file,
scope: scope,
nodes: nodes
@@ -256,6 +275,8 @@ exports.CatchClause = function (node, parent, scope, file) {
destructuring.init(pattern, ref);
node.body.body = nodes.concat(node.body.body);
return node;
};
exports.ExpressionStatement = function (node, parent, scope, file) {

View File

@@ -27,6 +27,7 @@ exports.ForOfStatement = function (node, parent, scope, file) {
// push the rest of the original loop body onto our new body
block.body = block.body.concat(node.body.body);
block._declarations = node.body._declarations;
// todo: find out why this is necessary? #538
loop._scopeInfo = node._scopeInfo;

View File

@@ -0,0 +1,34 @@
"use strict";
var ReplaceSupers = require("../../helpers/replace-supers");
var t = require("../../../types");
exports.check = function (node) {
return t.isIdentifier(node, { name: "super" });
};
exports.Property = function (node, parent, scope, file) {
if (!node.method) return;
var value = node.value;
var thisExpr = scope.generateUidIdentifier("this");
var replaceSupers = new ReplaceSupers({
topLevelThisReference: thisExpr,
methodNode: node,
className: thisExpr,
isStatic: true,
scope: scope,
file: file
});
replaceSupers.replace();
if (replaceSupers.hasSuper) {
value.body.body.unshift(
t.variableDeclaration("var", [
t.variableDeclarator(thisExpr, t.thisExpression())
])
);
}
};

View File

@@ -9,21 +9,23 @@ exports.check = function (node) {
var hasDefaults = function (node) {
for (var i = 0; i < node.params.length; i++) {
if (t.isAssignmentPattern(node.params[i])) return true;
if (!t.isIdentifier(node.params[i])) return true;
}
return false;
};
var iifeVisitor = {
enter: function (node, parent, scope, state) {
if (t.isReferencedIdentifier(node, parent) && state.scope.hasOwnReference(node.name)) {
state.iife = true;
this.stop();
}
if (!t.isReferencedIdentifier(node, parent)) return;
if (!state.scope.hasOwnBinding(node.name)) return;
if (state.scope.bindingEquals(node.name, node)) return;
state.iife = true;
this.stop();
}
};
exports.Function = function (node, parent, scope) {
exports.Function = function (node, parent, scope, file) {
if (!hasDefaults(node)) return;
t.ensureBlock(node);
@@ -37,11 +39,32 @@ exports.Function = function (node, parent, scope) {
var state = { iife: false, scope: scope };
var pushDefNode = function (left, right, i) {
var defNode = util.template("default-parameter", {
VARIABLE_NAME: left,
DEFAULT_VALUE: right,
ARGUMENT_KEY: t.literal(i),
ARGUMENTS: argsIdentifier
}, true);
file.checkNode(defNode);
defNode._blockHoist = node.params.length - i;
body.push(defNode);
};
for (var i = 0; i < node.params.length; i++) {
var param = node.params[i];
if (!t.isAssignmentPattern(param)) {
lastNonDefaultParam = +i + 1;
lastNonDefaultParam = i + 1;
if (!t.isIdentifier(param)) {
scope.traverse(param, iifeVisitor, state);
}
if (file.transformers["es6.blockScopingTDZ"].canRun()) {
pushDefNode(param, t.identifier("undefined"), i);
}
continue;
}
@@ -58,14 +81,7 @@ exports.Function = function (node, parent, scope) {
}
}
var defNode = util.template("default-parameter", {
VARIABLE_NAME: left,
DEFAULT_VALUE: right,
ARGUMENT_KEY: t.literal(+i),
ARGUMENTS: argsIdentifier
}, true);
defNode._blockHoist = node.params.length - i;
body.push(defNode);
pushDefNode(left, right, i);
}
// we need to cut off all trailing default parameters

View File

@@ -73,8 +73,8 @@ exports.CallExpression = function (node, parent, scope, file) {
} else {
nodes = build(args, file);
}
var first = nodes.shift();
var first = nodes.shift();
if (nodes.length) {
node.arguments.push(t.callExpression(t.memberExpression(first, t.identifier("concat")), nodes));
} else {

View File

@@ -0,0 +1,153 @@
"use strict";
var t = require("../../../types");
function returnBlock(expr) {
return t.blockStatement([t.returnStatement(expr)]);
}
function transformExpression(node, scope, state) {
if (!node) return;
return (function subTransform(node) {
switch (node.type) {
case "ConditionalExpression":
var callConsequent = subTransform(node.consequent);
var callAlternate = subTransform(node.alternate);
if (!callConsequent && !callAlternate) {
return;
}
// if ternary operator had tail recursion in value, convert to optimized if-statement
node.type = "IfStatement";
node.consequent = callConsequent ? t.toBlock(callConsequent) : returnBlock(node.consequent);
if (callAlternate) {
node.alternate = t.isIfStatement(callAlternate) ? callAlternate : t.toBlock(callAlternate);
} else {
node.alternate = returnBlock(node.alternate);
}
return [node];
case "LogicalExpression":
// only call in right-value of can be optimized
var callRight = subTransform(node.right);
if (!callRight) {
return;
}
var test = state.wrapSideEffect(node.left);
if (node.operator === "&&") {
test.expr = t.unaryExpression("!", test.expr);
}
return [t.ifStatement(test.expr, returnBlock(test.ref))].concat(callRight);
case "SequenceExpression":
var seq = node.expressions;
// only last element can be optimized
var lastCall = subTransform(seq[seq.length - 1]);
if (!lastCall) {
return;
}
// remove converted expression from sequence
// and convert to regular expression if needed
if (--seq.length === 1) {
node = seq[0];
}
return [t.expressionStatement(node)].concat(lastCall);
case "CallExpression":
var callee = node.callee, thisBinding;
var args = [callee];
// bind `this` to object in member expressions
if (t.isMemberExpression(callee)) {
var object = state.wrapSideEffect(callee.object);
callee.object = object.expr;
thisBinding = object.ref;
}
if (node.arguments.length > 0 || thisBinding) {
args.push(t.arrayExpression(node.arguments));
}
if (thisBinding) {
args.push(thisBinding);
}
return [t.returnStatement(t.callExpression(
state.getHelperRef(),
args
))];
}
})(node);
}
var functionChildrenVisitor = {
enter: function (node, parent, scope, state) {
if (t.isReturnStatement(node)) {
// prevent entrance by current visitor
this.skip();
// transform return argument into statement if
// it contains tail recursion
return transformExpression(node.argument, scope, state);
} else if (t.isFunction(node)) {
return this.skip();
} else if (t.isTryStatement(parent)) {
if (node === parent.block) {
return this.skip();
} else if (node === parent.finalizer) {
return;
} else {
if (parent.finalizer) {
this.skip();
}
return;
}
}
}
};
var functionVisitor = {
enter: function (node, parent, scope, state) {
// traverse all child nodes of this function and find `arguments` and `this`
scope.traverse(node, functionChildrenVisitor, state);
return this.skip();
}
};
exports.FunctionDeclaration =
exports.FunctionExpression = function (node, parent, scope, file) {
var tempId, helperRef;
var state = {
ownerId: node.id,
getHelperRef: function () {
return helperRef = helperRef || file.addHelper("tail-call");
},
wrapSideEffect: function (node) {
if (t.isIdentifier(node) || t.isLiteral(node)) {
return {expr: node, ref: node};
}
tempId = tempId || scope.generateUidIdentifier("temp");
return {
expr: t.assignmentExpression("=", tempId, node),
ref: tempId
};
}
};
// traverse the function and look for tail recursion
scope.traverse(node, functionVisitor, state);
if (tempId) {
t.ensureBlock(node).body.unshift(t.variableDeclaration("var", [
t.variableDeclarator(tempId)
]));
}
};

View File

@@ -11,6 +11,7 @@ module.exports = {
"playground.memoizationOperator": require("./playground/memoization-operator"),
"playground.objectGetterMemoization": require("./playground/object-getter-memoization"),
reactCompat: require("./other/react-compat"),
react: require("./other/react"),
_modules: require("./internal/modules"),
@@ -27,6 +28,7 @@ module.exports = {
asyncToGenerator: require("./other/async-to-generator"),
bluebirdCoroutines: require("./other/bluebird-coroutines"),
"es6.objectSuper": require("./es6/object-super"),
"es7.objectRestSpread": require("./es7/object-rest-spread"),
"es7.exponentiationOperator": require("./es7/exponentiation-operator"),
"es6.spread": require("./es6/spread"),
@@ -45,6 +47,14 @@ module.exports = {
"es6.constants": require("./es6/constants"),
// needs to be before `es6.blockScoping` as default parameters have a TDZ
"es6.parameters.default": require("./es6/parameters.default"),
"es6.parameters.rest": require("./es6/parameters.rest"),
// needs to be before `es6.blockScoping` as let variables may be produced
"es6.destructuring": require("./es6/destructuring"),
// needs to be before `_aliasFunction` due to block scopes sometimes being wrapped in a
// closure
"es6.blockScoping": require("./es6/block-scoping"),
@@ -52,10 +62,7 @@ module.exports = {
// needs to be after `es6.blockScoping` due to needing `letReferences` set on blocks
"es6.blockScopingTDZ": require("./es6/block-scoping-tdz"),
"es6.parameters.default": require("./es6/parameters.default"),
"es6.parameters.rest": require("./es6/parameters.rest"),
"es6.destructuring": require("./es6/destructuring"),
"es6.tailCall": require("./es6/tail-call"),
regenerator: require("./other/regenerator"),

View File

@@ -0,0 +1,29 @@
"use strict";
var react = require("../../helpers/react");
var t = require("../../../types");
exports.manipulateOptions = function (opts) {
opts.blacklist.push("react");
};
exports.optional = true;
require("../../helpers/build-react-transformer")(exports, {
pre: function (state) {
state.callee = state.tagExpr;
},
post: function (state) {
if (react.isCompatTag(state.tagName)) {
state.call = t.callExpression(
t.memberExpression(
t.memberExpression(t.identifier("React"), t.identifier("DOM")),
state.tagExpr,
t.isLiteral(state.tagExpr)
),
state.args
);
}
}
});

View File

@@ -1,291 +1,20 @@
"use strict";
// Based upon the excellent jsx-transpiler by Ingvar Stepanyan (RReverser)
// https://github.com/RReverser/jsx-transpiler
var react = require("../../helpers/react");
var t = require("../../../types");
// jsx
var isString = require("lodash/lang/isString");
var esutils = require("esutils");
var react = require("../../helpers/react");
var t = require("../../../types");
exports.check = function (node) {
if (t.isJSX(node)) return true;
if (react.isCreateClass(node)) return true;
return false;
};
exports.JSXIdentifier = function (node, parent) {
if (node.name === "this" && t.isReferenced(node, parent)) {
return t.thisExpression();
} else if (esutils.keyword.isIdentifierName(node.name)) {
node.type = "Identifier";
} else {
return t.literal(node.name);
}
};
exports.JSXNamespacedName = function (node, parent, scope, file) {
throw file.errorWithNode(node, "Namespace tags are not supported. ReactJSX is not XML.");
};
exports.JSXMemberExpression = {
exit: function (node) {
node.computed = t.isLiteral(node.property);
node.type = "MemberExpression";
}
};
exports.JSXExpressionContainer = function (node) {
return node.expression;
};
exports.JSXAttribute = {
exit: function (node) {
var value = node.value || t.literal(true);
return t.inherits(t.property("init", node.name, value), node);
}
};
var isCompatTag = function (tagName) {
return /^[a-z]|\-/.test(tagName);
};
exports.JSXOpeningElement = {
exit: function (node, parent, scope, file) {
var reactCompat = file.opts.reactCompat;
var tagExpr = node.name;
var args = [];
var tagName;
if (t.isIdentifier(tagExpr)) {
tagName = tagExpr.name;
} else if (t.isLiteral(tagExpr)) {
tagName = tagExpr.value;
}
if (!reactCompat) {
if (tagName && isCompatTag(tagName)) {
args.push(t.literal(tagName));
} else {
args.push(tagExpr);
}
}
var attribs = node.attributes;
if (attribs.length) {
attribs = buildJSXOpeningElementAttributes(attribs, file);
require("../../helpers/build-react-transformer")(exports, {
pre: function (state) {
var tagName = state.tagName;
var args = state.args;
if (react.isCompatTag(tagName)) {
args.push(t.literal(tagName));
} else {
attribs = t.literal(null);
args.push(state.tagExpr);
}
},
args.push(attribs);
if (reactCompat) {
if (tagName && isCompatTag(tagName)) {
return t.callExpression(
t.memberExpression(
t.memberExpression(t.identifier("React"), t.identifier("DOM")),
tagExpr,
t.isLiteral(tagExpr)
),
args
);
}
} else {
tagExpr = t.memberExpression(t.identifier("React"), t.identifier("createElement"));
}
return t.callExpression(tagExpr, args);
post: function (state) {
state.callee = t.memberExpression(t.identifier("React"), t.identifier("createElement"));
}
};
/**
* The logic for this is quite terse. It's because we need to
* support spread elements. We loop over all attributes,
* breaking on spreads, we then push a new object containg
* all prior attributes to an array for later processing.
*/
var buildJSXOpeningElementAttributes = function (attribs, file) {
var _props = [];
var objs = [];
var pushProps = function () {
if (!_props.length) return;
objs.push(t.objectExpression(_props));
_props = [];
};
while (attribs.length) {
var prop = attribs.shift();
if (t.isJSXSpreadAttribute(prop)) {
pushProps();
objs.push(prop.argument);
} else {
_props.push(prop);
}
}
pushProps();
if (objs.length === 1) {
// only one object
attribs = objs[0];
} else {
// looks like we have multiple objects
if (!t.isObjectExpression(objs[0])) {
objs.unshift(t.objectExpression([]));
}
// spread it
attribs = t.callExpression(
file.addHelper("extends"),
objs
);
}
return attribs;
};
exports.JSXElement = {
exit: function (node) {
var callExpr = node.openingElement;
for (var i = 0; i < node.children.length; i++) {
var child = node.children[i];
if (t.isLiteral(child) && typeof child.value === "string") {
cleanJSXElementLiteralChild(child, callExpr.arguments);
continue;
} else if (t.isJSXEmptyExpression(child)) {
continue;
}
callExpr.arguments.push(child);
}
callExpr.arguments = flatten(callExpr.arguments);
if (callExpr.arguments.length >= 3) {
callExpr._prettyCall = true;
}
return t.inherits(callExpr, node);
}
};
var isStringLiteral = function (node) {
return t.isLiteral(node) && isString(node.value);
};
var flatten = function (args) {
var flattened = [];
var last;
for (var i = 0; i < args.length; i++) {
var arg = args[i];
if (isStringLiteral(arg) && isStringLiteral(last)) {
last.value += arg.value;
} else {
last = arg;
flattened.push(arg);
}
}
return flattened;
};
var cleanJSXElementLiteralChild = function (child, args) {
var lines = child.value.split(/\r\n|\n|\r/);
var lastNonEmptyLine = 0;
var i;
for (i = 0; i < lines.length; i++) {
if (lines[i].match(/[^ \t]/)) {
lastNonEmptyLine = i;
}
}
for (i = 0; i < lines.length; i++) {
var line = lines[i];
var isFirstLine = i === 0;
var isLastLine = i === lines.length - 1;
var isLastNonEmptyLine = i === lastNonEmptyLine;
// replace rendered whitespace tabs with spaces
var trimmedLine = line.replace(/\t/g, " ");
// trim whitespace touching a newline
if (!isFirstLine) {
trimmedLine = trimmedLine.replace(/^[ ]+/, "");
}
// trim whitespace touching an endline
if (!isLastLine) {
trimmedLine = trimmedLine.replace(/[ ]+$/, "");
}
if (trimmedLine) {
if (!isLastNonEmptyLine) {
trimmedLine += " ";
}
args.push(t.literal(trimmedLine));
}
}
};
// display names
var addDisplayName = function (id, call) {
var props = call.arguments[0].properties;
var safe = true;
for (var i = 0; i < props.length; i++) {
var prop = props[i];
if (t.isIdentifier(prop.key, { name: "displayName" })) {
safe = false;
break;
}
}
if (safe) {
props.unshift(t.property("init", t.identifier("displayName"), t.literal(id)));
}
};
exports.ExportDeclaration = function (node, parent, scope, file) {
if (node.default && react.isCreateClass(node.declaration)) {
addDisplayName(file.opts.basename, node.declaration);
}
};
exports.AssignmentExpression =
exports.Property =
exports.VariableDeclarator = function (node) {
var left, right;
if (t.isAssignmentExpression(node)) {
left = node.left;
right = node.right;
} else if (t.isProperty(node)) {
left = node.key;
right = node.value;
} else if (t.isVariableDeclarator(node)) {
left = node.id;
right = node.init;
}
if (t.isMemberExpression(left)) {
left = left.property;
}
if (t.isIdentifier(left) && react.isCreateClass(right)) {
addDisplayName(left.name, right);
}
};
});

View File

@@ -2,7 +2,7 @@
var t = require("../../../types");
exports.BlockStatement = function (node, parent) {
exports.BlockStatement = function (node, parent, scope, file) {
if ((t.isFunction(parent) && parent.body === node) || t.isExportDeclaration(parent)) {
return;
}
@@ -22,5 +22,7 @@ exports.BlockStatement = function (node, parent) {
func.id = null;
node.body[i] = declar;
file.checkNode(declar);
}
};

View File

@@ -2,6 +2,8 @@
var t = require("../../../types");
exports.check = t.isFor;
exports.ForInStatement =
exports.ForOfStatement = function (node, parent, scope, file) {
var left = node.left;

View File

@@ -1,5 +1,9 @@
"use strict";
exports.check = function (node) {
return node.kind === "set";
};
exports.MethodDefinition =
exports.Property = function (node, parent, scope, file) {
if (node.kind === "set" && node.value.params.length !== 1) {

View File

@@ -8,42 +8,20 @@ var TraversalPath = require("./path");
var flatten = require("lodash/array/flatten");
var compact = require("lodash/array/compact");
function TraversalContext(scope, opts, state) {
function TraversalContext(scope, opts, state, parentPath) {
this.shouldFlatten = false;
this.parentPath = parentPath;
this.scope = scope;
this.state = state;
this.opts = opts;
this.reset();
}
TraversalContext.prototype.flatten = function () {
this.shouldFlatten = true;
};
TraversalContext.prototype.remove = function () {
this.shouldRemove = true;
this.shouldSkip = true;
};
TraversalContext.prototype.skip = function () {
this.shouldSkip = true;
};
TraversalContext.prototype.stop = function () {
this.shouldStop = true;
this.shouldSkip = true;
};
TraversalContext.prototype.reset = function () {
this.shouldRemove = false;
this.shouldSkip = false;
this.shouldStop = false;
};
TraversalContext.prototype.visitNode = function (node, obj, key) {
this.reset();
var iteration = new TraversalPath(this, node, obj, key);
return iteration.visit();
};

View File

@@ -29,11 +29,11 @@ function traverse(parent, opts, scope, state) {
}
}
traverse.node = function (node, opts, scope, state) {
traverse.node = function (node, opts, scope, state, parentPath) {
var keys = t.VISITOR_KEYS[node.type];
if (!keys) return;
var context = new TraversalContext(scope, opts, state);
var context = new TraversalContext(scope, opts, state, parentPath);
for (var i = 0; i < keys.length; i++) {
if (context.visit(node, keys[i])) {
return;

View File

@@ -14,16 +14,17 @@ function TraversalPath(context, parent, obj, key) {
this.shouldSkip = false;
this.shouldStop = false;
this.context = context;
this.state = this.context.state;
this.opts = this.context.opts;
this.parentPath = context.parentPath;
this.context = context;
this.state = this.context.state;
this.opts = this.context.opts;
this.key = key;
this.obj = obj;
this.parent = parent;
this.scope = TraversalPath.getScope(this.getNode(), parent, context.scope);
this.state = context.state;
this.parent = parent;
this.scope = TraversalPath.getScope(this.getNode(), parent, context.scope);
this.state = context.state;
}
TraversalPath.prototype.remove = function () {
@@ -70,7 +71,7 @@ TraversalPath.prototype.getNode = function () {
return this.obj[this.key];
};
TraversalPath.prototype.replaceNode = function (replacement, scope) {
TraversalPath.prototype.replaceNode = function (replacement) {
var isArray = Array.isArray(replacement);
// inherit comments from original node to the first replacement node
@@ -85,10 +86,10 @@ TraversalPath.prototype.replaceNode = function (replacement, scope) {
if (file) {
if (isArray) {
for (var i = 0; i < replacement.length; i++) {
file.checkNode(replacement[i], scope);
file.checkNode(replacement[i], this.scope);
}
} else {
file.checkNode(replacement, scope);
file.checkNode(replacement, this.scope);
}
}
@@ -144,10 +145,10 @@ TraversalPath.prototype.visit = function () {
// traverse over these replacement nodes we purposely don't call exitNode
// as the original node has been destroyed
for (var i = 0; i < node.length; i++) {
traverse.node(node[i], opts, this.scope, this.state);
traverse.node(node[i], opts, this.scope, this.state, this);
}
} else {
traverse.node(node, opts, this.scope, this.state);
traverse.node(node, opts, this.scope, this.state, this);
this.call("exit");
}

View File

@@ -320,11 +320,12 @@ Scope.prototype.crawl = function () {
for (i = 0; i < block.params.length; i++) {
this.register(block.params[i]);
}
this.traverse(block.body, blockVariableVisitor, this);
}
// Program, BlockStatement, Function - let variables
if (t.isBlockStatement(block) || t.isProgram(block) || t.isFunction(block)) {
if (t.isBlockStatement(block) || t.isProgram(block)) {
this.traverse(block, blockVariableVisitor, this);
}

View File

@@ -340,8 +340,8 @@ t.isReferenced = function (node, parent) {
* @returns {Boolean}
*/
t.isReferencedIdentifier = function (node, parent) {
return t.isIdentifier(node) && t.isReferenced(node, parent);
t.isReferencedIdentifier = function (node, parent, opts) {
return t.isIdentifier(node, opts) && t.isReferenced(node, parent);
};
/**
@@ -395,7 +395,7 @@ t.toIdentifier = function (name) {
t.ensureBlock = function (node, key) {
key = key || "body";
node[key] = t.toBlock(node[key], node);
return node[key] = t.toBlock(node[key], node);
};
/**

View File

@@ -1,7 +1,7 @@
{
"name": "6to5",
"description": "Turn ES6 code into readable vanilla ES5 with source maps",
"version": "3.4.0",
"version": "3.5.0",
"author": "Sebastian McKenzie <sebmck@gmail.com>",
"homepage": "https://6to5.org/",
"repository": "6to5/6to5",
@@ -33,7 +33,7 @@
"test": "make test"
},
"dependencies": {
"acorn-6to5": "0.11.1-25",
"acorn-6to5": "0.11.1-27",
"ast-types": "~0.6.1",
"chalk": "^0.5.1",
"chokidar": "0.12.6",

View File

@@ -0,0 +1,5 @@
# 6to5-runtime
6to5 self-contained runtime
For more information please look at [6to5](https://github.com/6to5/6to5).

View File

@@ -1,7 +1,7 @@
{
"name": "6to5-runtime",
"description": "6to5 selfContained runtime",
"version": "3.3.12",
"version": "3.4.1",
"repository": "6to5/6to5",
"author": "Sebastian McKenzie <sebmck@gmail.com>"
}

View File

@@ -1,5 +1,5 @@
if (process.browser) {
require("../lib/6to5/browser");
require("../lib/6to5/api/browser");
require("./generation");
require("./transformation");
require("./traverse");

View File

@@ -19,14 +19,14 @@ var readFile = exports.readFile = function (filename) {
}
};
exports.esvalid = function (ast, loc) {
exports.esvalid = function (ast, code, loc) {
var errors = esvalid.errors(ast);
if (errors.length) {
var msg = [];
_.each(errors, function (err) {
msg.push(err.message + " - " + JSON.stringify(err.node));
});
throw new Error(loc + ": " + msg.join(". "));
throw new Error(loc + ": " + msg.join(". ") + "\n" + code);
}
};

View File

@@ -16,6 +16,14 @@ global.assertNoOwnProperties = function (obj) {
assert.equal(Object.getOwnPropertyNames(obj).length, 0);
};
global.assertHasOwnProperty = function () {
};
global.assertLacksOwnProperty = function () {
};
global.assertArrayEquals = assert.deepEqual;
global.assert = chai.assert;
global.chai = chai;
@@ -54,7 +62,7 @@ var run = function (task, done) {
var checkAst = function (result, opts) {
if (noCheckAst) return;
helper.esvalid(result.ast.program, opts.loc);
helper.esvalid(result.ast.program, result.code, opts.loc);
};
if (execCode) {
@@ -129,12 +137,7 @@ module.exports = function (suiteOpts, taskOpts, dynamicOpts) {
var runTest = function (done) {
var runTask = function () {
try {
run(task, done);
} catch (err) {
if (task.options.after) task.options.after();
throw err;
}
run(task, done);
};
_.extend(task.options, taskOpts);

View File

@@ -17,6 +17,6 @@ suite("api", function () {
var file = new File;
assert.throws(function () {
file.addHelper("foob");
}, /unknown declaration foob/);
}, /Unknown helper foob/);
});
});

View File

@@ -0,0 +1,3 @@
{
"blacklist": ["es6.tailCall"]
}

View File

@@ -0,0 +1,3 @@
a = 1;
let a = 2;

View File

@@ -0,0 +1,7 @@
function b() {
assert.equals(a, 1);
}
let a = 1;
b();

View File

@@ -0,0 +1,7 @@
function b() {
assert.equals(a, 1);
}
b();
let a = 1;

View File

@@ -0,0 +1,3 @@
a;
let a = 1;

View File

@@ -0,0 +1,3 @@
function foo(bar = bar2, bar2) {}
foo();

View File

@@ -0,0 +1,4 @@
{
"optional": "es6.blockScopingTDZ",
"throws": "is not defined - temporal dead zone"
}

View File

@@ -0,0 +1,3 @@
a++;
let a = 1;

View File

@@ -0,0 +1,3 @@
let a = 1;
a = 2;
assert.equal(a, 2);

View File

@@ -0,0 +1,7 @@
let a = 1;
function b() {
return a + 1;
}
assert.equal(b(), 2);

View File

@@ -0,0 +1,3 @@
function foo(bar, bar2 = bar) {}
foo();

View File

@@ -0,0 +1,3 @@
{
"optional": "es6.blockScopingTDZ"
}

View File

@@ -0,0 +1,3 @@
let a = 1;
a++;
assert.equal(a, 2);

View File

@@ -1,2 +0,0 @@
qux;
let qux = 456;

View File

@@ -1,4 +0,0 @@
{
"throws": "Temporal dead zone - accessing a variable before it's initialized",
"optional": ["es6.blockScopingTDZ"]
}

View File

@@ -1,3 +1,4 @@
{
"loose": ["es6.classes"]
"loose": ["es6.classes"],
"blacklist": ["es6.tailCall"]
}

View File

@@ -0,0 +1,3 @@
{
"blacklist": ["es6.tailCall"]
}

View File

@@ -0,0 +1,3 @@
{
"blacklist": ["es6.tailCall"]
}

View File

@@ -14,5 +14,7 @@ define(["exports", "foo"], function (exports, _foo) {
exports["default"] = _foo.foo;
exports["default"] = _foo.foo;
exports.bar = _foo.bar;
exports.__esModule = true;
Object.defineProperty(exports, "__esModule", {
value: true
});
});

View File

@@ -8,5 +8,7 @@ define(["exports"], function (exports) {
exports["default"] = foo;
exports["default"] = foo;
exports.bar = bar;
exports.__esModule = true;
Object.defineProperty(exports, "__esModule", {
value: true
});
});

View File

@@ -17,5 +17,7 @@ define(["exports"], function (exports) {
_classCallCheck(this, foo8);
};
exports.__esModule = true;
Object.defineProperty(exports, "__esModule", {
value: true
});
});

View File

@@ -12,5 +12,7 @@ define(["exports", "./evens"], function (exports, _evens) {
return !isEven(n);
};
})(isEven);
exports.__esModule = true;
Object.defineProperty(exports, "__esModule", {
value: true
});
});

View File

@@ -12,5 +12,7 @@ define(["exports", "foo", "foo-bar", "./directory/foo-bar"], function (exports,
var test2 = exports.test2 = 5;
exports["default"] = test;
exports.__esModule = true;
Object.defineProperty(exports, "__esModule", {
value: true
});
});

View File

@@ -10,5 +10,7 @@ define(["exports"], function (exports) {
test = 3;
test++;
})();
exports.__esModule = true;
Object.defineProperty(exports, "__esModule", {
value: true
});
});

View File

@@ -0,0 +1 @@
export default foo;

View File

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

View File

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

View File

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

View File

@@ -1,3 +1 @@
export function foo() {}
export default foo;
export { foo as default, foo };

View File

@@ -2,6 +2,3 @@
exports.foo = foo;
function foo() {}
exports["default"] = foo;
exports["default"] = foo;
exports.foo = foo;

View File

@@ -3,4 +3,6 @@
exports.Cachier = Cachier;
exports["default"] = new Cachier();
function Cachier(databaseName) {}
exports.__esModule = true;
Object.defineProperty(exports, "__esModule", {
value: true
});

View File

@@ -15,4 +15,6 @@ exports.bar = _foo.foo;
exports["default"] = _foo.foo;
exports["default"] = _foo.foo;
exports.bar = _foo.bar;
exports.__esModule = true;
Object.defineProperty(exports, "__esModule", {
value: true
});

View File

@@ -7,4 +7,6 @@ exports.bar = foo;
exports["default"] = foo;
exports["default"] = foo;
exports.bar = bar;
exports.__esModule = true;
Object.defineProperty(exports, "__esModule", {
value: true
});

View File

@@ -16,4 +16,6 @@ var foo8 = exports.foo8 = function foo8() {
_classCallCheck(this, foo8);
};
exports.__esModule = true;
Object.defineProperty(exports, "__esModule", {
value: true
});

View File

@@ -11,4 +11,6 @@ var isOdd = exports.isOdd = (function (isEven) {
return !isEven(n);
};
})(isEven);
exports.__esModule = true;
Object.defineProperty(exports, "__esModule", {
value: true
});

View File

@@ -18,4 +18,6 @@ var bar = require("foo4").bar;
var bar2 = require("foo5").foo;
exports.test = test;
var test = exports.test = 5;
exports.__esModule = true;
Object.defineProperty(exports, "__esModule", {
value: true
});

View File

@@ -9,4 +9,6 @@ test = exports.test += 1;
test = 3;
test++;
})();
exports.__esModule = true;
Object.defineProperty(exports, "__esModule", {
value: true
});

View File

@@ -0,0 +1,3 @@
{
"blacklist": ["es6.tailCall"]
}

View File

@@ -20,5 +20,7 @@
exports["default"] = _foo.foo;
exports["default"] = _foo.foo;
exports.bar = _foo.bar;
exports.__esModule = true;
Object.defineProperty(exports, "__esModule", {
value: true
});
});

View File

@@ -14,5 +14,7 @@
exports["default"] = foo;
exports["default"] = foo;
exports.bar = bar;
exports.__esModule = true;
Object.defineProperty(exports, "__esModule", {
value: true
});
});

View File

@@ -23,5 +23,7 @@
_classCallCheck(this, foo8);
};
exports.__esModule = true;
Object.defineProperty(exports, "__esModule", {
value: true
});
});

View File

@@ -18,5 +18,7 @@
return !isEven(n);
};
})(isEven);
exports.__esModule = true;
Object.defineProperty(exports, "__esModule", {
value: true
});
});

View File

@@ -18,5 +18,7 @@
var test2 = exports.test2 = 5;
exports["default"] = test;
exports.__esModule = true;
Object.defineProperty(exports, "__esModule", {
value: true
});
});

View File

@@ -16,5 +16,7 @@
test = 3;
test++;
})();
exports.__esModule = true;
Object.defineProperty(exports, "__esModule", {
value: true
});
});

View File

@@ -0,0 +1,15 @@
var a = {
name() {
return "Suyash";
}
};
var b = {
name() {
return super.name() + " Verma";
}
};
Object.setPrototypeOf(b, a);
assert.equal(b.name(), "Suyash Verma");

View File

@@ -0,0 +1,3 @@
{
"blacklist": ["es6.tailCall"]
}

View File

@@ -0,0 +1,3 @@
{
"blacklist": ["es6.tailCall"]
}

View File

@@ -0,0 +1,7 @@
(function f(n) {
if (n <= 0) {
console.log(this, arguments);
return "foo";
}
return Math.random() > 0.5 ? f.call(this, n - 1) : f.apply(this, [n - 1]);
})(1e6) === "foo";

View File

@@ -0,0 +1,13 @@
"use strict";
(function f(n) {
if (n <= 0) {
console.log(this, arguments);
return "foo";
}
if (Math.random() > 0.5) {
return to5Runtime.tailCall(f.call, [this, n - 1], f);
} else {
return to5Runtime.tailCall(f.apply, [this, [n - 1]], f);
}
})(1000000) === "foo";

View File

@@ -0,0 +1,7 @@
function f(n) {
return n <= 0 ? "foo" : g(n - 1);
}
function g(n) {
return n <= 0 ? "goo" : f(n - 1);
}

View File

@@ -0,0 +1,17 @@
"use strict";
function f(n) {
if (n <= 0) {
return "foo";
} else {
return to5Runtime.tailCall(g, [n - 1]);
}
}
function g(n) {
if (n <= 0) {
return "goo";
} else {
return to5Runtime.tailCall(f, [n - 1]);
}
}

View File

@@ -0,0 +1,3 @@
(function f(n) {
return n <= 0 ? "foo" : (doSmth(), getTrueValue() && (getFalseValue() || f(n - 1)));
})(1e6, true) === "foo";

View File

@@ -0,0 +1,18 @@
"use strict";
(function f(n) {
var _temp;
if (n <= 0) {
return "foo";
} else {
doSmth();
if (!(_temp = getTrueValue())) {
return _temp;
}
if (_temp = getFalseValue()) {
return _temp;
}
return to5Runtime.tailCall(f, [n - 1]);
}
})(1000000, true) === "foo";

View File

@@ -0,0 +1,4 @@
{
"runtime": true,
"blacklist": []
}

View File

@@ -0,0 +1,8 @@
(function f(n = getDefaultValue(), /* should be undefined after first pass */ m) {
if (n <= 0) {
return "foo";
}
// Should be clean (undefined) on each pass
var local;
return f(n - 1);
})(1e6, true) === "foo";

View File

@@ -0,0 +1,11 @@
"use strict";
(function f(_x, /* should be undefined after first pass */m) {
var n = arguments[0] === undefined ? getDefaultValue() : arguments[0];
if (n <= 0) {
return "foo";
}
// Should be clean (undefined) on each pass
var local;
return to5Runtime.tailCall(f, [n - 1]);
})(1000000, true) === "foo";

View File

@@ -0,0 +1,7 @@
function f() {
return getObj().method();
}
function g() {
return getFalseValue() || getValue();
}

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