Merge branch 'master' into 3.0.0

Conflicts:
	CHANGELOG.md
	package.json
This commit is contained in:
Sebastian McKenzie
2015-01-14 14:56:55 +11:00
87 changed files with 1196 additions and 350 deletions

View File

@@ -24,6 +24,7 @@ File.helpers = [
"prototype-properties",
"apply-constructor",
"tagged-template-literal",
"tagged-template-literal-loose",
"interop-require",
"to-array",
"sliced-to-array",
@@ -41,29 +42,32 @@ File.helpers = [
File.excludeHelpersFromRuntime = [
"async-to-generator",
"typeof"
"typeof",
"tagged-template-literal-loose"
];
File.normaliseOptions = function (opts) {
opts = _.cloneDeep(opts || {});
_.defaults(opts, {
includeRegenerator: false,
experimental: false,
reactCompat: false,
playground: false,
whitespace: true,
moduleIds: opts.amdModuleIds || false,
blacklist: [],
whitelist: [],
sourceMap: false,
optional: [],
comments: true,
filename: "unknown",
modules: "common",
runtime: false,
code: true,
ast: true
keepModuleIdExtensions: false,
includeRegenerator: false,
experimental: false,
reactCompat: false,
playground: false,
whitespace: true,
moduleIds: opts.amdModuleIds || false,
blacklist: [],
whitelist: [],
sourceMap: false,
optional: [],
comments: true,
filename: "unknown",
modules: "common",
runtime: false,
loose: [],
code: true,
ast: true
});
// normalise windows path separators to unix
@@ -71,6 +75,19 @@ File.normaliseOptions = function (opts) {
opts.blacklist = util.arrayify(opts.blacklist);
opts.whitelist = util.arrayify(opts.whitelist);
opts.optional = util.arrayify(opts.optional);
opts.loose = util.arrayify(opts.loose);
// todo: remove in 3.0.0
_.each({
fastForOf: "forOf",
classesFastSuper: "classes"
}, function (newTransformer, oldTransformer) {
if (_.contains(opts.optional, oldTransformer)) {
_.pull(opts.optional, oldTransformer);
opts.loose.push(newTransformer);
}
});
_.defaults(opts, {
moduleRoot: opts.sourceRoot
@@ -100,10 +117,15 @@ File.normaliseOptions = function (opts) {
transform._ensureTransformerNames("blacklist", opts.blacklist);
transform._ensureTransformerNames("whitelist", opts.whitelist);
transform._ensureTransformerNames("optional", opts.optional);
transform._ensureTransformerNames("loose", opts.loose);
return opts;
};
File.prototype.isLoose = function (key) {
return _.contains(this.opts.loose, key);
};
File.prototype.getTransformers = function () {
var file = this;
var transformers = [];

View File

@@ -107,7 +107,16 @@ exports.TryStatement = function (node, print) {
this.keyword("try");
print(node.block);
this.space();
print(node.handler);
// Esprima bug puts the catch clause in a `handlers` array.
// see https://code.google.com/p/esprima/issues/detail?id=433
// We run into this from regenerator generated ast.
if (node.handlers) {
print(node.handlers[0]);
} else {
print(node.handler);
}
if (node.finalizer) {
this.space();
this.push("finally ");

View File

@@ -72,5 +72,5 @@ _.each({
return amount;
};
});
})
});
});

View File

@@ -47,7 +47,13 @@ Whitespace.prototype.getNewlinesAfter = function (node) {
if (endToken.type.type === "eof") {
return 1;
} else {
return this.getNewlinesBetween(startToken, endToken);
var lines = this.getNewlinesBetween(startToken, endToken);
if (node.type === "Line" && !lines) {
// line comment
return 1;
} else {
return lines;
}
}
};

View File

@@ -1,4 +1,5 @@
// Required to safely use 6to5/register within a browserify codebase.
// required to safely use 6to5/register within a browserify codebase
module.exports = function () {};
require("./polyfill");

View File

@@ -156,8 +156,10 @@ DefaultFormatter.prototype.getModuleName = function () {
filenameRelative = filenameRelative.replace(sourceRootRegEx, "");
}
// remove extension
filenameRelative = filenameRelative.replace(/\.(.*?)$/, "");
if (!opts.keepModuleIdExtensions) {
// remove extension
filenameRelative = filenameRelative.replace(/\.(.*?)$/, "");
}
moduleName += filenameRelative;

View File

@@ -31,15 +31,17 @@ UMDFormatter.prototype.transform = function (ast) {
var factory = t.functionExpression(null, args, t.blockStatement(body));
// runner
// amd
var defineArgs = [t.literal("exports")];
if (this.passModuleArg) defineArgs.push(t.literal("module"));
defineArgs = defineArgs.concat(names);
defineArgs = [t.arrayExpression(defineArgs)];
// common
var testExports = util.template("test-exports");
var testModule = util.template("test-module");
var testModule = util.template("test-module");
var commonTests = this.passModuleArg ? t.logicalExpression("&&", testExports, testModule) : testExports;
var commonArgs = [t.identifier("exports")];
@@ -48,6 +50,12 @@ UMDFormatter.prototype.transform = function (ast) {
return t.callExpression(t.identifier("require"), [name]);
}));
// globals
//var umdArgs = [];
//
var moduleName = this.getModuleName();
if (moduleName) defineArgs.unshift(t.literal(moduleName));

View File

@@ -1,5 +0,0 @@
(function () {
if (SUPER_NAME != null) {
SUPER_NAME.apply(this, arguments);
}
});

View File

@@ -0,0 +1,3 @@
if (SUPER_NAME != null) {
SUPER_NAME.apply(this, arguments);
}

View File

@@ -0,0 +1,4 @@
(function (strings, raw) {
strings.raw = raw;
return strings;
});

View File

@@ -59,7 +59,6 @@ _.each({
arrayComprehension: require("./transformers/es7-array-comprehension"),
generatorComprehension: require("./transformers/es7-generator-comprehension"),
arrowFunctions: require("./transformers/es6-arrow-functions"),
classesFastSuper: require("./transformers/optional-classes-fast-super"),
classes: require("./transformers/es6-classes"),
objectSpread: require("./transformers/es7-object-spread"),
@@ -70,7 +69,6 @@ _.each({
computedPropertyNames: require("./transformers/es6-computed-property-names"),
destructuring: require("./transformers/es6-destructuring"),
defaultParameters: require("./transformers/es6-default-parameters"),
forOfFast: require("./transformers/optional-for-of-fast"),
forOf: require("./transformers/es6-for-of"),
unicodeRegex: require("./transformers/es6-unicode-regex"),
abstractReferences: require("./transformers/es7-abstract-references"),

View File

@@ -33,6 +33,7 @@ function Class(node, file, scope, isStatement) {
this.hasConstructor = false;
this.className = node.id || file.generateUidIdentifier("class", scope);
this.superName = node.superClass;
this.isLoose = file.isLoose("classes");
}
/**
@@ -62,8 +63,8 @@ Class.prototype.run = function () {
}
this.constructor = constructor;
var closureArgs = [];
var closureParams = [];
var closureArgs = [];
//
@@ -117,27 +118,31 @@ Class.prototype.buildBody = function () {
var superName = this.superName;
var classBody = this.node.body.body;
var body = this.body;
var self = this;
for (var i in classBody) {
var node = classBody[i];
if (t.isMethodDefinition(node)) {
self.replaceInstanceSuperReferences(node);
this.replaceInstanceSuperReferences(node);
if (node.key.name === "constructor") {
self.pushConstructor(node);
this.pushConstructor(node);
} else {
self.pushMethod(node);
this.pushMethod(node);
}
} else if (t.isPrivateDeclaration(node)) {
self.closure = true;
this.closure = true;
body.unshift(node);
}
}
// we have no constructor, we have a super, and the super doesn't appear to be falsy
if (!this.hasConstructor && superName && !t.isFalsyExpression(superName)) {
constructor.body.body.push(util.template("class-super-constructor-call", {
CLASS_NAME: className
var defaultConstructorTemplate = "class-super-constructor-call";
if (this.isLoose) defaultConstructorTemplate += "-loose";
constructor.body.body.push(util.template(defaultConstructorTemplate, {
CLASS_NAME: className,
SUPER_NAME: this.superName
}, true));
}
@@ -183,6 +188,19 @@ Class.prototype.pushMethod = function (node) {
}
if (kind === "") {
if (this.isLoose) {
// use assignments instead of define properties for loose classes
var className = this.className;
if (!node.static) className = t.memberExpression(className, t.identifier("prototype"));
methodName = t.memberExpression(className, methodName, node.computed);
var expr = t.expressionStatement(t.assignmentExpression("=", methodName, node.value));
t.inheritsComments(expr, node);
this.body.push(expr);
return;
}
kind = "value";
}
@@ -219,6 +237,47 @@ Class.prototype.superProperty = function (property, isStatic, isComputed, thisEx
);
};
/**
* Description
*
* @param {Object} node
* @param {Object} id
* @param {Object} parent
* @returns {Object}
*/
Class.prototype.looseSuperProperty = function (methodNode, id, parent) {
var methodName = methodNode.key;
var superName = this.superName || t.identifier("Function");
if (parent.property === id) {
return;
} else if (t.isCallExpression(parent, { callee: id })) {
// super(); -> ClassName.prototype.MethodName.call(this);
parent.arguments.unshift(t.thisExpression());
if (methodName.name === "constructor") {
// constructor() { super(); }
return t.memberExpression(superName, t.identifier("call"));
} else {
id = superName;
// foo() { super(); }
if (!methodNode.static) {
id = t.memberExpression(id, t.identifier("prototype"));
}
id = t.memberExpression(id, methodName, methodNode.computed);
return t.memberExpression(id, t.identifier("call"));
}
} else if (t.isMemberExpression(parent) && !methodNode.static) {
// super.test -> ClassName.prototype.test
return t.memberExpression(superName, t.identifier("prototype"));
} else {
return superName;
}
};
/**
* Replace all `super` references with a reference to our `superClass`.
*
@@ -229,54 +288,110 @@ Class.prototype.replaceInstanceSuperReferences = function (methodNode) {
var method = methodNode.value;
var self = this;
traverse(method, {
enter: function (node, parent) {
var property;
var computed;
var args;
var topLevelThisReference;
if (t.isIdentifier(node, { name: "super" })) {
if (!(t.isMemberExpression(parent) && !parent.computed && parent.property === node)) {
throw self.file.errorWithNode(node, "illegal use of bare super");
traverseLevel(method, true);
if (topLevelThisReference) {
method.body.body.unshift(t.variableDeclaration("var", [
t.variableDeclarator(topLevelThisReference, t.thisExpression())
]));
}
function traverseLevel(node, topLevel) {
traverse(node, {
enter: function (node, parent) {
if (t.isFunction(node) && !t.isArrowFunctionExpression(node)) {
// we need to call traverseLevel again so we're context aware
traverseLevel(node, false);
return this.skip();
}
} else if (t.isCallExpression(node)) {
var callee = node.callee;
if (t.isIdentifier(callee, { name: "super" })) {
// super(); -> _get(Object.getPrototypeOf(ClassName), "MethodName", this).call(this);
property = methodNode.key;
computed = methodNode.computed;
args = node.arguments;
} else {
if (!t.isMemberExpression(callee)) return;
if (callee.object.name !== "super") return;
// super.test(); -> _get(Object.getPrototypeOf(ClassName.prototype), "test", this).call(this);
property = callee.property;
computed = callee.computed;
args = node.arguments;
}
} else if (t.isMemberExpression(node)) {
if (!t.isIdentifier(node.object, { name: "super" })) return;
var getThisReference = function () {
if (topLevel) {
// top level so `this` is the instance
return t.thisExpression();
} else {
// not in the top level so we need to create a reference
return topLevelThisReference = topLevelThisReference || self.file.generateUidIdentifier("this");
}
};
// super.name; -> _get(Object.getPrototypeOf(ClassName.prototype), "name", this);
property = node.property;
computed = node.computed;
var callback = specHandle;
if (self.isLoose) callback = looseHandle;
return callback(getThisReference, node, parent);
}
});
}
if (property) {
var thisExpression = t.thisExpression();
var superProperty = self.superProperty(property, methodNode.static, computed, thisExpression);
if (args) {
return t.callExpression(
t.memberExpression(superProperty, t.identifier("call"), false),
[thisExpression].concat(args)
);
} else {
return superProperty;
}
}
function looseHandle(getThisReference, node, parent) {
if (t.isIdentifier(node, { name: "super" })) {
return self.looseSuperProperty(methodNode, 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);
t.appendToMemberExpression(callee, t.identifier("call"));
node.arguments.unshift(getThisReference());
}
});
}
function specHandle(getThisReference, node, parent) {
var property;
var computed;
var args;
if (t.isIdentifier(node, { name: "super" })) {
if (!(t.isMemberExpression(parent) && !parent.computed && parent.property === node)) {
throw self.file.errorWithNode(node, "illegal use of bare super");
}
} else if (t.isCallExpression(node)) {
var callee = node.callee;
if (t.isIdentifier(callee, { name: "super" })) {
// super(); -> _get(Object.getPrototypeOf(ClassName), "MethodName", this).call(this);
property = methodNode.key;
computed = methodNode.computed;
args = node.arguments;
} else {
if (!t.isMemberExpression(callee)) return;
if (callee.object.name !== "super") return;
// super.test(); -> _get(Object.getPrototypeOf(ClassName.prototype), "test", this).call(this);
property = callee.property;
computed = callee.computed;
args = node.arguments;
}
} else if (t.isMemberExpression(node)) {
if (!t.isIdentifier(node.object, { name: "super" })) return;
// super.name; -> _get(Object.getPrototypeOf(ClassName.prototype), "name", this);
property = node.property;
computed = node.computed;
}
if (!property) return;
var thisReference = getThisReference();
var superProperty = self.superProperty(property, methodNode.static, computed, thisReference);
if (args) {
if (args.length === 1 && t.isSpreadElement(args[0])) {
// super(...arguments);
return t.callExpression(
t.memberExpression(superProperty, t.identifier("apply")),
[thisReference, args[0].argument]
);
} else {
return t.callExpression(
t.memberExpression(superProperty, t.identifier("call")),
[thisReference].concat(args)
);
}
} else {
return superProperty;
}
}
};
/**

View File

@@ -2,28 +2,63 @@ var t = require("../../types");
exports.ObjectExpression = function (node, parent, file, scope) {
var hasComputed = false;
var prop;
var key;
var i;
for (i in node.properties) {
for (var i in node.properties) {
hasComputed = t.isProperty(node.properties[i], { computed: true, kind: "init" });
if (hasComputed) break;
}
if (!hasComputed) return;
var initProps = [];
var objId = scope.generateUidBasedOnNode(parent, file);
//
var body = [];
var container = t.functionExpression(null, [], t.blockStatement(body));
container._aliasFunction = true;
//
var callback = spec;
if (file.isLoose("computedPropertyNames")) callback = loose;
var result = callback(node, body, objId, initProps, file);
if (result) return result;
//
body.unshift(t.variableDeclaration("var", [
t.variableDeclarator(objId, t.objectExpression(initProps))
]));
body.push(t.returnStatement(objId));
return t.callExpression(container, []);
};
var loose = function (node, body, objId) {
for (var i in node.properties) {
var prop = node.properties[i];
body.push(t.expressionStatement(
t.assignmentExpression(
"=",
t.memberExpression(objId, prop.key, prop.computed),
prop.value
)
));
}
};
var spec = function (node, body, objId, initProps, file) {
var props = node.properties;
var prop, key;
// normalise key
for (i in props) {
for (var i in props) {
prop = props[i];
if (prop.kind !== "init") continue;
@@ -36,7 +71,6 @@ exports.ObjectExpression = function (node, parent, file, scope) {
// add all non-computed properties and `__proto__` properties to the initializer
var initProps = [];
var broken = false;
for (i in props) {
@@ -86,14 +120,4 @@ exports.ObjectExpression = function (node, parent, file, scope) {
return first;
}
}
//
body.unshift(t.variableDeclaration("var", [
t.variableDeclarator(objId, t.objectExpression(initProps))
]));
body.push(t.returnStatement(objId));
return t.callExpression(container, []);
};

View File

@@ -1,7 +1,6 @@
var traverse = require("../../traverse");
var util = require("../../util");
var t = require("../../types");
var _ = require("lodash");
exports.Function = function (node, parent, file, scope) {
if (!node.defaults || !node.defaults.length) return;
@@ -15,6 +14,23 @@ exports.Function = function (node, parent, file, scope) {
var i;
var def;
var checkTDZ = function (ids) {
var check = function (node, parent) {
if (!t.isIdentifier(node) || !t.isReferenced(node, parent)) return;
if (ids.indexOf(node.name) >= 0) {
throw file.errorWithNode(node, "Temporal dead zone - accessing a variable before it's initialized");
}
if (scope.has(node.name, true)) {
iife = true;
}
};
check(def, node);
traverse(def, { enter: check });
};
for (i in node.defaults) {
def = node.defaults[i];
if (!def) continue;
@@ -23,22 +39,10 @@ exports.Function = function (node, parent, file, scope) {
// temporal dead zone check - here we prevent accessing of params that
// are to the right - ie. uninitialized parameters
_.each(ids.slice(i), function (ids) {
var check = function (node, parent) {
if (!t.isIdentifier(node) || !t.isReferenced(node, parent)) return;
if (ids.indexOf(node.name) >= 0) {
throw file.errorWithNode(node, "Temporal dead zone - accessing a variable before it's initialized");
}
if (scope.has(node.name)) {
iife = true;
}
};
check(def, node);
traverse(def, { enter: check });
});
var rightIds = ids.slice(i);
for (i in rightIds) {
checkTDZ(rightIds[i]);
}
// we're accessing a variable that's already defined within this function
var has = scope.get(param.name);

View File

@@ -2,6 +2,68 @@ var util = require("../../util");
var t = require("../../types");
exports.ForOfStatement = function (node, parent, file, scope) {
var callback = spec;
if (file.isLoose("forOf")) callback = loose;
var build = callback(node, parent, file, scope);
var declar = build.declar;
var loop = build.loop;
var block = loop.body;
// inherit comments from the original loop
t.inheritsComments(loop, node);
// ensure that it's a block so we can take all it's statemetns
t.ensureBlock(node);
// add the value declaration to the new loop body
if (declar){
if (build.shouldUnshift) {
block.body.unshift(declar);
} else {
block.body.push(declar);
}
}
// push the rest of the original loop body onto our new body
block.body = block.body.concat(node.body.body);
return loop;
};
var loose = function (node, parent, file, scope) {
var left = node.left;
var declar, id;
if (t.isIdentifier(left) || t.isPattern(left)) {
// for (i of test), for ({ i } of test)
id = left;
} else if (t.isVariableDeclaration(left)) {
// for (var i of test)
id = left.declarations[0].id;
declar = t.variableDeclaration(left.kind, [
t.variableDeclarator(id)
]);
} else {
throw file.errorWithNode(left, "Unknown node type " + left.type + " in ForOfStatement");
}
var loop = util.template("for-of-loose", {
LOOP_OBJECT: file.generateUidIdentifier("iterator", scope),
IS_ARRAY: file.generateUidIdentifier("isArray", scope),
OBJECT: node.right,
INDEX: file.generateUidIdentifier("i", scope),
ID: id
});
return {
shouldUnshift: true,
declar: declar,
loop: loop
};
};
var spec = function (node, parent, file, scope) {
var left = node.left;
var declar;
@@ -9,8 +71,10 @@ exports.ForOfStatement = function (node, parent, file, scope) {
var stepValue = t.memberExpression(stepKey, t.identifier("value"));
if (t.isIdentifier(left) || t.isPattern(left)) {
// for (i of test), for ({ i } of test)
declar = t.expressionStatement(t.assignmentExpression("=", left, stepValue));
} else if (t.isVariableDeclaration(left)) {
// for (var i of test)
declar = t.variableDeclaration(left.kind, [
t.variableDeclarator(left.declarations[0].id, stepValue)
]);
@@ -18,18 +82,14 @@ exports.ForOfStatement = function (node, parent, file, scope) {
throw file.errorWithNode(left, "Unknown node type " + left.type + " in ForOfStatement");
}
var node2 = util.template("for-of", {
var loop = util.template("for-of", {
ITERATOR_KEY: file.generateUidIdentifier("iterator", scope),
STEP_KEY: stepKey,
OBJECT: node.right
});
t.inheritsComments(node2, node);
t.ensureBlock(node);
var block = node2.body;
block.body.push(declar);
block.body = block.body.concat(node.body.body);
return node2;
return {
declar: declar,
loop: loop
};
};

View File

@@ -250,10 +250,11 @@ LetScoping.prototype.getInfo = function () {
declar = block.body[i];
if (!isLet(declar, block)) continue;
_.each(t.getIds(declar, true), function (id, key) {
duplicates(id, key);
var declars = t.getIds(declar, true);
for (var key in declars) {
duplicates(declars[key], key);
opts.keys.push(key);
});
}
}
return opts;

View File

@@ -17,10 +17,12 @@ exports.TaggedTemplateExpression = function (node, parent, file) {
raw.push(t.literal(elem.value.raw));
}
args.push(t.callExpression(file.addHelper("tagged-template-literal"), [
t.arrayExpression(strings),
t.arrayExpression(raw)
]));
strings = t.arrayExpression(strings);
raw = t.arrayExpression(raw);
var templateName = "tagged-template-literal";
if (file.isLoose("templateLiterals")) templateName += "-loose";
args.push(t.callExpression(file.addHelper(templateName), [strings, raw]));
args = args.concat(quasi.expressions);

View File

@@ -1,74 +0,0 @@
var traverse = require("../../traverse");
var util = require("../../util");
var t = require("../../types");
exports.optional = true;
exports.Class = function (node) {
var superClass = node.superClass || t.identifier("Function");
var hasConstructor = false;
var body = node.body.body;
for (var i in body) {
var methodNode = body[i];
hasConstructor = hasConstructor || methodNode.key.name === "constructor";
traverse(methodNode, {
enter: function (node, parent) {
if (t.isIdentifier(node, { name: "super" })) {
return superIdentifier(superClass, methodNode, 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);
t.appendToMemberExpression(callee, t.identifier("call"));
node.arguments.unshift(t.thisExpression());
}
}
});
}
if (node.superClass && !hasConstructor) {
body.unshift(t.methodDefinition(
t.identifier("constructor"),
util.template("class-super-constructor-call-fast", {
SUPER_NAME: superClass
})
));
}
};
var superIdentifier = function (superClass, methodNode, id, parent) {
var methodName = methodNode.key;
if (parent.property === id) {
return;
} else if (t.isCallExpression(parent, { callee: id })) {
// super(); -> ClassName.prototype.MethodName.call(this);
parent.arguments.unshift(t.thisExpression());
if (methodName.name === "constructor") {
// constructor() { super(); }
return t.memberExpression(superClass, t.identifier("call"));
} else {
id = superClass;
// foo() { super(); }
if (!methodNode.static) {
id = t.memberExpression(id, t.identifier("prototype"));
}
id = t.memberExpression(id, methodName, methodNode.computed);
return t.memberExpression(id, t.identifier("call"));
}
} else if (t.isMemberExpression(parent) && !methodNode.static) {
// super.test -> ClassName.prototype.test
return t.memberExpression(superClass, t.identifier("prototype"));
} else {
return superClass;
}
};

View File

@@ -8,6 +8,15 @@ var coreHas = function (node) {
return node.name !== "_" && _.has(core, node.name);
};
var ALIASABLE_CONSTRUCTORS = [
"Symbol",
"Promise",
"Map",
"WeakMap",
"Set",
"WeakSet"
];
exports.optional = true;
exports.ast = {
@@ -31,8 +40,8 @@ exports.ast = {
this.skip();
return t.prependToMemberExpression(node, file._coreId);
}
} else if (t.isIdentifier(node) && !t.isMemberExpression(parent) && t.isReferenced(node, parent) && node.name === "Symbol") {
// new Symbol -> new _core.Symbol
} else if (t.isIdentifier(node) && !t.isMemberExpression(parent) && t.isReferenced(node, parent) && _.contains(ALIASABLE_CONSTRUCTORS, node.name)) {
// Symbol() -> _core.Symbol(); new Promise -> new _core.Promise
return t.memberExpression(file._coreId, node);
} else if (t.isCallExpression(node)) {
// arr[Symbol.iterator]() -> _core.$for.getIterator(arr)

View File

@@ -1,37 +0,0 @@
var util = require("../../util");
var t = require("../../types");
exports.optional = true;
exports.ForOfStatement = function (node, parent, file, scope) {
var left = node.left;
var declar, id;
if (t.isIdentifier(left) || t.isPattern(left)) {
id = left;
} else if (t.isVariableDeclaration(left)) {
id = left.declarations[0].id;
declar = t.variableDeclaration(left.kind, [
t.variableDeclarator(id)
]);
} else {
throw file.errorWithNode(left, "Unknown node type " + left.type + " in ForOfStatement");
}
var node2 = util.template("for-of-fast", {
LOOP_OBJECT: file.generateUidIdentifier("loopObject", scope),
IS_ARRAY: file.generateUidIdentifier("isArray", scope),
OBJECT: node.right,
INDEX: file.generateUidIdentifier("i", scope),
ID: id
});
t.inheritsComments(node2, node);
t.ensureBlock(node);
var block = node2.body;
if (declar) block.body.unshift(declar);
block.body = block.body.concat(node.body.body);
return node2;
};

View File

@@ -5,6 +5,7 @@
var esutils = require("esutils");
var t = require("../../types");
var _ = require("lodash");
exports.XJSIdentifier = function (node) {
if (esutils.keyword.isIdentifierName(node.name)) {
@@ -61,11 +62,16 @@ exports.XJSOpeningElement = {
}
}
var props = node.attributes;
if (props.length) {
var attribs = node.attributes;
if (attribs.length) {
var _props = [];
var objs = [];
// so basically in order to support spread elements we
// loop over all the attributes, breaking on spreads
// we then push a new object containing all prior attributes
// to an array for later processing
var pushProps = function () {
if (!_props.length) return;
@@ -73,8 +79,8 @@ exports.XJSOpeningElement = {
_props = [];
};
while (props.length) {
var prop = props.shift();
while (attribs.length) {
var prop = attribs.shift();
if (t.isXJSSpreadAttribute(prop)) {
pushProps();
objs.push(prop.argument);
@@ -86,22 +92,25 @@ exports.XJSOpeningElement = {
pushProps();
if (objs.length === 1) {
props = objs[0];
// only one object
attribs = objs[0];
} else {
// looks like we have multiple objects
if (!t.isObjectExpression(objs[0])) {
objs.unshift(t.objectExpression([]));
}
props = t.callExpression(
// spread it
attribs = t.callExpression(
t.memberExpression(t.identifier("React"), t.identifier("__spread")),
objs
);
}
} else {
props = t.literal(null);
attribs = t.literal(null);
}
args.push(props);
args.push(attribs);
if (reactCompat) {
if (tagName && isTag(tagName)) {
@@ -130,7 +139,7 @@ exports.XJSElement = {
for (i in node.children) {
var child = node.children[i];
if (t.isLiteral(child)) {
if (t.isLiteral(child) && _.isString(child.value)) {
var lines = child.value.split(/\r\n|\n|\r/);
for (i in lines) {