Compare commits

...

16 Commits

Author SHA1 Message Date
Sebastian McKenzie
fea487bf91 v4.6.4 2015-03-02 15:34:10 +11:00
Sebastian McKenzie
ff2cbd5a2e Merge branch 'master' of github.com:babel/babel 2015-03-02 15:30:30 +11:00
Sebastian McKenzie
12e01f9e71 remove optional property on function params - fixes #927 2015-03-02 15:30:05 +11:00
Sebastian McKenzie
f62436909d Merge pull request #923 from mathiasbynens/patch-4
Explicitly update the regexpu dependency to v1.1.2
2015-03-02 11:32:27 +11:00
Mathias Bynens
e42c1adeb6 Explicitly update the regexpu dependency to v1.1.2 2015-03-01 18:50:17 +01:00
Sebastian McKenzie
e30dbbab94 properly replace labels in spec for of transformer - fixes #913, closes #914 2015-03-02 01:41:13 +11:00
Sebastian McKenzie
e3daa28e60 rename minification tests to utility 2015-03-02 01:28:34 +11:00
Sebastian McKenzie
9e5d94126c add base type tests 2015-03-02 01:28:17 +11:00
Sebastian McKenzie
95798bee0b add t.valueToNode 2015-03-02 01:28:10 +11:00
Sebastian McKenzie
63f25ab038 check parent for variable collisions when remapping closurified block scopes - fixes #915, closes #922 2015-03-02 01:27:58 +11:00
Sebastian McKenzie
27a8f2d2ea rename broke property to confident in t.evaluate 2015-03-01 18:16:27 +11:00
Sebastian McKenzie
78434bb404 add t.evaluate method 2015-03-01 17:01:46 +11:00
Sebastian McKenzie
82833a8901 update 4.6.3 changelog 2015-03-01 13:45:09 +11:00
Sebastian McKenzie
93d5288d71 4.6.3 2015-03-01 11:05:33 +11:00
Sebastian McKenzie
5d3074b460 v4.6.3 2015-03-01 11:03:55 +11:00
Sebastian McKenzie
a57475abc9 better rest param member expression deopt 2015-03-01 11:01:06 +11:00
25 changed files with 512 additions and 168 deletions

View File

@@ -13,6 +13,14 @@ _Note: Gaps between patch versions are faulty/broken releases._
See [CHANGELOG - 6to5](CHANGELOG-6to5.md) for the pre-4.0.0 version changelog.
## 4.6.3
* **Bug Fix**
* Fix `arguments` being incorrectly aliased in arrow function rest parameter optimisation.
* Make deoptimisation trigger safer.
* **New Feature**
* Flow types are now retained when blacklisting the `flow` transformer.
## 4.6.1
* **Bug Fix**

View File

@@ -1,7 +1,7 @@
{
"name": "babel",
"description": "Turn ES6 code into readable vanilla ES5 with source maps",
"version": "4.6.2",
"version": "4.6.4",
"author": "Sebastian McKenzie <sebmck@gmail.com>",
"homepage": "https://babeljs.io/",
"repository": "babel/babel",
@@ -57,7 +57,7 @@
"path-is-absolute": "^1.0.0",
"private": "^0.1.6",
"regenerator-babel": "0.8.13-1",
"regexpu": "^1.1.1",
"regexpu": "^1.1.2",
"repeating": "^1.1.2",
"shebang-regex": "^1.0.0",
"slash": "^1.0.0",

View File

@@ -1,7 +1,7 @@
{
"name": "babel-runtime",
"description": "babel selfContained runtime",
"version": "4.6.1",
"version": "4.6.3",
"repository": "babel/babel",
"author": "Sebastian McKenzie <sebmck@gmail.com>"
}

View File

@@ -1,4 +1,8 @@
{
"selfContained": "runtime",
"unicode-regex": "regex.unicode"
"unicode-regex": "regex.unicode",
"minification.deadCodeElimination": "utility.deadCodeElimination",
"minification.removeConsoleCalls": "utility.removeConsole",
"minification.removeDebugger": "utility.removeDebugger"
}

View File

@@ -327,7 +327,7 @@ class BlockScoping {
for (var name in outsideRefs) {
var id = outsideRefs[name];
if (this.scope.hasGlobal(id.name)) {
if (this.scope.hasGlobal(id.name) || this.scope.parentHasBinding(id.name)) {
delete outsideRefs[id.name];
delete this.letReferences[id.name];

View File

@@ -182,7 +182,7 @@ class ClassTransformer {
}
// we have no constructor, we have a super, and the super doesn't appear to be falsy
if (!this.hasConstructor && this.hasSuper && !t.isFalsyExpression(superName)) {
if (!this.hasConstructor && this.hasSuper && t.evaluateTruthy(superName) !== false) {
var helperName = "class-super-constructor-call";
if (this.isLoose) helperName += "-loose";
constructor.body.body.push(util.template(helperName, {

View File

@@ -32,7 +32,11 @@ export function ForOfStatement(node, parent, scope, file) {
// todo: find out why this is necessary? #538
loop._scopeInfo = node._scopeInfo;
return build.node;
if (build.replaceParent) {
this.parentPath.node = build.node;
} else {
return build.node;
}
}
var breakVisitor = {
@@ -97,7 +101,9 @@ var loose = function (node, parent, scope, file) {
scope.traverse(node, breakVisitor, {
iteratorKey: iteratorKey,
wrapReturn: function (node) {
label: t.isLabeledStatement(parent) && parent.label.name,
wrapReturn: function (node) {
return t.ifStatement(
t.logicalExpression(
"&&",
@@ -105,8 +111,7 @@ var loose = function (node, parent, scope, file) {
t.memberExpression(iteratorKey, t.identifier("return")
)
), node);
},
label: t.isLabeledStatement(parent) && parent.label.name
}
});
//
@@ -119,6 +124,8 @@ var loose = function (node, parent, scope, file) {
};
var spec = function (node, parent, scope, file) {
var left = node.left;
var declar;
@@ -151,14 +158,22 @@ var spec = function (node, parent, scope, file) {
BODY: null
});
var loop = template[3].block.body[0];
var isLabeledParent = t.isLabeledStatement(parent);
var tryBody = template[3].block.body;
var loop = tryBody[0];
if (isLabeledParent) {
tryBody[0] = t.labeledStatement(parent.label, loop);
}
//
scope.traverse(node, breakVisitor, {
iteratorKey: iteratorKey,
label: t.isLabeledStatement(parent) && parent.label.name,
wrapReturn: function (node) {
label: isLabeledParent && parent.label.name,
wrapReturn: function (node) {
return t.ifStatement(t.memberExpression(iteratorKey, t.identifier("return")), node);
}
});
@@ -166,8 +181,9 @@ var spec = function (node, parent, scope, file) {
//
return {
declar: declar,
loop: loop,
node: template
replaceParent: isLabeledParent,
declar: declar,
loop: loop,
node: template
};
};

View File

@@ -29,7 +29,6 @@ var memberExpressionOptimisationVisitor = {
var prop = parent.property;
if (isNumber(prop.value) || t.isUnaryExpression(prop) || t.isBinaryExpression(prop)) {
state.candidates.push(this);
state.canOptimise = true;
return;
}
}
@@ -81,7 +80,7 @@ exports.Function = function (node, parent, scope) {
var state = {
outerBinding: scope.getBindingIdentifier(rest.name),
canOptimise: false,
canOptimise: true,
candidates: [],
method: node,
name: rest.name
@@ -90,7 +89,7 @@ exports.Function = function (node, parent, scope) {
scope.traverse(node, memberExpressionOptimisationVisitor, state);
// we only have shorthands and there's no other references
if (state.canOptimise) {
if (state.canOptimise && state.candidates.length) {
for (var i = 0; i < state.candidates.length; i++) {
var candidate = state.candidates[i];
candidate.node = argsId;

View File

@@ -103,10 +103,12 @@ export default {
"es3.propertyLiterals": require("./es3/property-literals"),
"es3.memberExpressionLiterals": require("./es3/member-expression-literals"),
"minification.removeDebugger": require("./minification/remove-debugger"),
"minification.removeConsoleCalls": require("./minification/remove-console-calls"),
"minification.deadCodeElimination": require("./minification/dead-code-elimination"),
"minification.renameLocalVariables": require("./minification/rename-local-variables"),
"utility.removeDebugger": require("./utility/remove-debugger"),
"utility.removeConsole": require("./utility/remove-console"),
"utility.inlineEnvironmentVariables": require("./utility/inline-environment-variables"),
"utility.inlineExpressions": require("./utility/inline-expressions"),
"utility.deadCodeElimination": require("./utility/dead-code-elimination"),
_cleanUp: require("./internal/cleanup")
};

View File

@@ -1,9 +0,0 @@
//import t from "../../../types";
export var optional = true;
export function Scopable() {
//for (var name in scope.bindings) {
// scope.rename(name, scope.generateUidIdentifier("a").name);
//}
}

View File

@@ -13,6 +13,13 @@ export function Class(node) {
node.implements = null;
}
export function Function(node) {
for (var i = 0; i < node.params.length; i++) {
var param = node.params[i];
param.optional = false;
}
}
export function TypeCastExpression(node) {
return node.expression;
}

View File

@@ -1,31 +1,41 @@
import t from "../../../types";
function toStatements(node) {
if (t.isBlockStatement(node)) {
var hasBlockScoped = false;
for (var i = 0; i < node.body.length; i++) {
var bodyNode = node.body[i];
if (t.isBlockScoped(bodyNode)) hasBlockScoped = true;
}
if (!hasBlockScoped) {
return node.body;
}
}
return node;
}
export var optional = true;
export function ExpressionStatement(node) {
// remove consequence-less expressions such as local variables and literals
// note: will remove directives
//
// var foo = true; foo; -> var foo = true;
// "foo"; ->
//
var expr = node.expression;
if (t.isLiteral(expr) || (t.isIdentifier(node) && t.hasBinding(node.name))) {
this.remove();
export function ConditionalExpression(node) {
var evaluateTest = t.evaluateTruthy(node.test);
if (evaluateTest === true) {
return node.consequent;
} else if (evaluateTest === false) {
return node.alternate;
}
}
export var IfStatement = {
exit(node) {
// todo: in scenarios where we can just return the consequent or
// alternate we should drop the block statement if it contains no
// block scoped variables
var consequent = node.consequent;
var alternate = node.alternate;
var test = node.test;
var evaluateTest = t.evaluateTruthy(test);
// we can check if a test will be truthy 100% and if so then we can inline
// the consequent and completely ignore the alternate
//
@@ -33,8 +43,8 @@ export var IfStatement = {
// if ("foo") { foo; } -> { foo; }
//
if (t.isLiteral(test) && test.value) {
return consequent;
if (evaluateTest === true) {
return toStatements(consequent);
}
// we can check if a test will be falsy 100% and if so we can inline the
@@ -44,9 +54,9 @@ export var IfStatement = {
// if ("") { bar; } ->
//
if (t.isFalsyExpression(test)) {
if (evaluateTest === false) {
if (alternate) {
return alternate;
return toStatements(alternate);
} else {
return this.remove();
}

View File

@@ -0,0 +1,14 @@
import t from "../../../types";
export var optional = true;
var match = t.buildMatchMemberExpression("process.env");
export function MemberExpression(node) {
if (match(node.object)) {
var key = t.toComputedKey(node, node.property);
if (t.isLiteral(key)) {
return t.valueToNode(process.env[key.value]);
}
}
}

View File

@@ -0,0 +1,8 @@
import t from "../../../types";
export var optional = true;
export function Expression(node) {
var res = t.evaluate(node);
if (res.confident) return t.valueToNode(res.value);
}

View File

@@ -84,6 +84,11 @@
"name": null
},
"LabeledStatement": {
"label": null,
"body": null
},
"Literal": {
"value": null
},

View File

@@ -1,4 +1,7 @@
import toFastProperties from "../helpers/to-fast-properties";
import isPlainObject from "lodash/lang/isPlainObject";
import isNumber from "lodash/lang/isNumber";
import isRegExp from "lodash/lang/isRegExp";
import isString from "lodash/lang/isString";
import compact from "lodash/array/compact";
import esutils from "esutils";
@@ -804,5 +807,178 @@ t.isScope = function (node, parent) {
return t.isScopable(node);
};
/**
* Walk the input `node` and statically evaluate if it's truthy.
*
* Returning `true` when we're sure that the expression will evaluate to a
* truthy value, `false` if we're sure that it will evaluate to a falsy
* value and `undefined` if we aren't sure. Because of this please do not
* rely on coercion when using this method and check with === if it's false.
*
* For example do:
*
* if (t.evaluateTruthy(node) === false) falsyLogic();
*
* **AND NOT**
*
* if (!t.evaluateTruthy(node)) falsyLogic();
*
* @param {Node} node
* @returns {Boolean}
*/
t.evaluateTruthy = function (node) {
var res = t.evaluate(node);
if (res.confident) return !!res.value;
};
/**
* Walk the input `node` and statically evaluate it.
*
* Returns an pbject in the form `{ confident, value }`. `confident` indicates
* whether or not we had to drop out of evaluating the expression because of
* hitting an unknown node that we couldn't confidently find the value of.
*
* Example:
*
* t.evaluate(parse("5 + 5")) // { confident: true, value: 10 }
* t.evaluate(parse("!true")) // { confident: true, value: false }
* t.evaluate(parse("foo + foo")) // { confident: false, value: undefined }
*
* @param {Node} node
* @returns {Object}
*/
t.evaluate = function (node) {
var confident = true;
var value = evaluate(node);
if (!confident) value = undefined;
return {
confident: confident,
value: value
};
function evaluate(node) {
if (!confident) return;
if (t.isSequenceExpression(node)) {
return evaluate(node.expressions[node.expressions.length - 1]);
}
if (t.isLiteral(node)) {
if (node.regex && node.value === null) {
// we have a regex and we can't represent it natively
} else {
return node.value;
}
}
if (t.isConditionalExpression(node)) {
if (evaluate(node.test)) {
return evaluate(node.consequent);
} else {
return evaluate(node.alternate);
}
}
if (t.isIdentifier(node, { name: "undefined" })) {
return undefined;
}
if (t.isUnaryExpression(node, { prefix: true })) {
switch (node.operator) {
case "void": return undefined;
case "!": return !evaluate(node.argument);
case "+": return +evaluate(node.argument);
case "-": return -evaluate(node.argument);
}
}
if (t.isArrayExpression(node)) {
// possible perf issues - could deopt on X elements
var values = [];
for (var i = 0; i < node.elements.length; i++) {
values.push(evaluate(node.elements[i]));
}
return values;
}
if (t.isObjectExpression(node)) {
// todo: deopt on mutable computed property keys etc
}
if (t.isLogicalExpression(node)) {
var left = evaluate(node.left);
var right = evaluate(node.right);
switch (node.operator) {
case "||": return left || right;
case "&&": return left && right;
}
}
if (t.isBinaryExpression(node)) {
var left = evaluate(node.left);
var right = evaluate(node.right);
switch (node.operator) {
case "-": return left - right;
case "+": return left + right;
case "/": return left / right;
case "*": return left * right;
case "%": return left % right;
case "<": return left < right;
case ">": return left > right;
case "<=": return left <= right;
case ">=": return left >= right;
case "==": return left == right;
case "!=": return left != right;
case "===": return left === right;
case "!==": return left !== right;
}
}
confident = false;
}
};
/**
* Description
*
* @param value
* @returns {Node}
*/
t.valueToNode = function (value) {
if (value === undefined) {
return t.identifier("undefined");
}
if (value === true || value === false || value === null || isString(value) || isNumber(value) || isRegExp(value)) {
return t.literal(value);
}
if (Array.isArray(value)) {
return t.arrayExpression(value.map(t.valueToNode));
}
if (isPlainObject(value)) {
var props = [];
for (var key in value) {
var nodeKey;
if (t.isValidIdentifier(key)) {
nodeKey = t.identifier(key);
} else {
nodeKey = t.literal(key);
}
props.push(t.property("init", nodeKey, t.valueToNode(value[key])));
}
return t.objectExpression(props);
}
throw new Error("don't know how to turn this value into a node");
};
toFastProperties(t);
toFastProperties(t.VISITOR_KEYS);

View File

@@ -0,0 +1,5 @@
let a = 1;
for (let a = 1; a < 100; a++) {
items.forEach(item => a);
}
console.log(a);

View File

@@ -0,0 +1,11 @@
"use strict";
var a = 1;
for (var _a = 1; _a < 100; _a++) {
(function (_a) {
items.forEach(function (item) {
return _a;
});
})(_a);
}
console.log(a);

View File

@@ -2,89 +2,89 @@
// labels
foo: {
var _iteratorNormalCompletion = true;
var _didIteratorError = false;
var _iteratorError = undefined;
var _iteratorNormalCompletion = true;
var _didIteratorError = false;
var _iteratorError = undefined;
try {
for (var _iterator = foo()[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) {
var x = _step.value;
try {
foo: for (var _iterator = foo()[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) {
var x = _step.value;
while (true) {
if (_iterator["return"]) _iterator["return"]();
break foo;
}
}
} catch (err) {
_didIteratorError = true;
_iteratorError = err;
} finally {
try {
if (!_iteratorNormalCompletion && _iterator["return"]) {
_iterator["return"]();
}
} finally {
if (_didIteratorError) {
throw _iteratorError;
}
}
}
}foo: {
var _iteratorNormalCompletion2 = true;
var _didIteratorError2 = false;
var _iteratorError2 = undefined;
try {
for (var _iterator2 = foo()[Symbol.iterator](), _step2; !(_iteratorNormalCompletion2 = (_step2 = _iterator2.next()).done); _iteratorNormalCompletion2 = true) {
var x = _step2.value;
while (true) {
break;
}
}
} catch (err) {
_didIteratorError2 = true;
_iteratorError2 = err;
} finally {
try {
if (!_iteratorNormalCompletion2 && _iterator2["return"]) {
_iterator2["return"]();
}
} finally {
if (_didIteratorError2) {
throw _iteratorError2;
}
}
}
}foo: {
var _iteratorNormalCompletion3 = true;
var _didIteratorError3 = false;
var _iteratorError3 = undefined;
try {
for (var _iterator3 = foo()[Symbol.iterator](), _step3; !(_iteratorNormalCompletion3 = (_step3 = _iterator3.next()).done); _iteratorNormalCompletion3 = true) {
var x = _step3.value;
if (_iterator3["return"]) _iterator3["return"]();
while (true) {
if (_iterator["return"]) _iterator["return"]();
break foo;
}
} catch (err) {
_didIteratorError3 = true;
_iteratorError3 = err;
}
} catch (err) {
_didIteratorError = true;
_iteratorError = err;
} finally {
try {
if (!_iteratorNormalCompletion && _iterator["return"]) {
_iterator["return"]();
}
} finally {
try {
if (!_iteratorNormalCompletion3 && _iterator3["return"]) {
_iterator3["return"]();
}
} finally {
if (_didIteratorError3) {
throw _iteratorError3;
}
if (_didIteratorError) {
throw _iteratorError;
}
}
} // basic
}
var _iteratorNormalCompletion2 = true;
var _didIteratorError2 = false;
var _iteratorError2 = undefined;
try {
foo: for (var _iterator2 = foo()[Symbol.iterator](), _step2; !(_iteratorNormalCompletion2 = (_step2 = _iterator2.next()).done); _iteratorNormalCompletion2 = true) {
var x = _step2.value;
while (true) {
break;
}
}
} catch (err) {
_didIteratorError2 = true;
_iteratorError2 = err;
} finally {
try {
if (!_iteratorNormalCompletion2 && _iterator2["return"]) {
_iterator2["return"]();
}
} finally {
if (_didIteratorError2) {
throw _iteratorError2;
}
}
}
var _iteratorNormalCompletion3 = true;
var _didIteratorError3 = false;
var _iteratorError3 = undefined;
try {
foo: for (var _iterator3 = foo()[Symbol.iterator](), _step3; !(_iteratorNormalCompletion3 = (_step3 = _iterator3.next()).done); _iteratorNormalCompletion3 = true) {
var x = _step3.value;
if (_iterator3["return"]) _iterator3["return"]();
break foo;
}
} catch (err) {
_didIteratorError3 = true;
_iteratorError3 = err;
} finally {
try {
if (!_iteratorNormalCompletion3 && _iterator3["return"]) {
_iterator3["return"]();
}
} finally {
if (_didIteratorError3) {
throw _iteratorError3;
}
}
}
// basic
var _iteratorNormalCompletion4 = true;
var _didIteratorError4 = false;
@@ -137,4 +137,4 @@ try {
throw _iteratorError5;
}
}
}
}

View File

@@ -8,17 +8,23 @@ var y = function (foo, ...bar) {
};
};
var b = function (x, y, ...args) {
console.log(args[0]);
args.pop();
console.log(args[1]);
};
var z = function (foo, ...bar) {
var x = function () {
bar[1] = 5;
};
var x = function () {
bar[1] = 5;
};
};
var a = function (foo, ...bar) {
return bar.join(',');
return bar.join(',');
};
var b = function (foo, ...bar) {
var join = "join";
return bar[join];
var join = "join";
return bar[join];
};

View File

@@ -1,47 +1,56 @@
"use strict";
var x = function x(foo) {
for (var _len = arguments.length, bar = Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
bar[_key - 1] = arguments[_key];
}
for (var _len = arguments.length, bar = Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
bar[_key - 1] = arguments[_key];
}
console.log(bar);
console.log(bar);
};
var y = function y(foo) {
for (var _len = arguments.length, bar = Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
bar[_key - 1] = arguments[_key];
}
for (var _len = arguments.length, bar = Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
bar[_key - 1] = arguments[_key];
}
var x = function z(bar) {
bar[1] = 5;
};
var x = function z(bar) {
bar[1] = 5;
};
};
var b = function b(x, y) {
for (var _len = arguments.length, args = Array(_len > 2 ? _len - 2 : 0), _key = 2; _key < _len; _key++) {
args[_key - 2] = arguments[_key];
}
console.log(args[0]);
args.pop();
console.log(args[1]);
};
var z = function z(foo) {
for (var _len = arguments.length, bar = Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
bar[_key - 1] = arguments[_key];
}
for (var _len = arguments.length, bar = Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
bar[_key - 1] = arguments[_key];
}
var x = function x() {
bar[1] = 5;
};
var x = function x() {
bar[1] = 5;
};
};
var a = function a(foo) {
for (var _len = arguments.length, bar = Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
bar[_key - 1] = arguments[_key];
}
for (var _len = arguments.length, bar = Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
bar[_key - 1] = arguments[_key];
}
return bar.join(",");
return bar.join(",");
};
var b = function b(foo) {
for (var _len = arguments.length, bar = Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
bar[_key - 1] = arguments[_key];
}
for (var _len = arguments.length, bar = Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
bar[_key - 1] = arguments[_key];
}
var join = "join";
return bar[join];
var join = "join";
return bar[join];
};

View File

@@ -61,7 +61,7 @@ class Foo7 {
class Foo8 {
"bar"() {}
}
function foo(requiredParam, optParam?) {}
function foo(requiredParam, optParam) {}
class Foo9 {}
class Foo10 {}
var x = 4;

View File

@@ -1,15 +1,88 @@
var assert = require("assert");
var parse = require("../lib/babel/helpers/parse");
var t = require("../lib/babel/types");
suite("types", function () {
test("isFalsyExpression", function () {
assert.ok(t.isFalsyExpression(t.literal("")));
assert.ok(t.isFalsyExpression(t.literal(null)));
assert.ok(t.isFalsyExpression(t.literal(0)));
assert.ok(t.isFalsyExpression(t.identifier("undefined")));
test("evaluate", function () {
var evaluateAssert = function (code, expect) {
var res = t.evaluate(parse({}, code).program.body[0].expression);
assert.ok(res.confident, "Not confident");
assert.equal(res.value, expect);
assert.equal(res.value, eval(code));
};
// Literal
evaluateAssert("5", 5);
evaluateAssert("true", true);
evaluateAssert("false", false);
evaluateAssert("null", null);
evaluateAssert("'foo'", "foo");
// SequenceExpression
evaluateAssert("(false, true)", true);
evaluateAssert("(false, false)", false);
// Identifier
evaluateAssert("undefined", undefined);
// ConditionalExpression
evaluateAssert("true ? 'foo' : 'bar'", "foo");
evaluateAssert("false ? 'foo' : 'bar'", "bar");
evaluateAssert("'' ? 'foo' : 'bar'", "bar");
evaluateAssert("'foobar' ? 'foo' : 'bar'", "foo");
evaluateAssert("5 < 22 ? 'foo' : 'bar'", "foo");
evaluateAssert("22 < 5 ? 'foo' : 'bar'", "bar");
// BinaryExpression -
evaluateAssert("5 - 5", 0);
evaluateAssert("5 - 6", -1);
evaluateAssert("5.5 - 6", -0.5);
// BinaryExpression +
evaluateAssert("5 + 5", 10);
evaluateAssert("5 + 6", 11);
evaluateAssert("5.5 + 6", 11.5);
evaluateAssert("-5 + 5", 0);
// BinaryExpression /
// BinaryExpression *
// BinaryExpression %
// BinaryExpression <
// BinaryExpression >
// BinaryExpression <=
// BinaryExpression >=
// BinaryExpression ==
// BinaryExpression !=
// BinaryExpression ===
// BinaryExpression !==
// UnaryExpression void
// UnaryExpression !
// UnaryExpression +
// UnaryExpression -
// LogicalExpression ||
// LogicalExpression &&
evaluateAssert("true && true", true);
evaluateAssert("true && false", false);
evaluateAssert("false && false", false);
});
test("evaluateTruthy", function () {
assert.ok(!t.isFalsyExpression(t.literal("foobar")));
assert.ok(!t.isFalsyExpression(t.literal(5)));
assert.ok(!t.isFalsyExpression(t.identifier("foobar")));
});
});