Comparing version 1.0.2 to 1.0.3
# CHANGELOG | ||
## 1.0.3 | ||
- new method: ternaryOperatorReduction | ||
- improve: binaryExpressionReduction | ||
## 1.0.2 | ||
@@ -4,0 +9,0 @@ |
@@ -5,2 +5,3 @@ const binaryExpressionReduction = require('./src/binaryExpressionReduction') | ||
const logicalExpressionReduction = require('./src/logicalExpressionReduction') | ||
const ternaryOperatorReduction = require('./src/ternaryOperatorReduction') | ||
@@ -11,3 +12,4 @@ module.exports = { | ||
negationOperatorRemoval, | ||
logicalExpressionReduction | ||
logicalExpressionReduction, | ||
ternaryOperatorReduction | ||
} |
{ | ||
"name": "astoptech", | ||
"version": "1.0.2", | ||
"version": "1.0.3", | ||
"description": "abstract syntax tree optimization techniques", | ||
"main": "index.js", | ||
"scripts": { | ||
"test": "node src/binaryExpressionReduction.spec.js && node src/ifStatementRemoval.spec.js && node src/negationOperatorRemoval.spec.js && node src/logicalExpressionReduction.spec.js" | ||
"test": "node src/binaryExpressionReduction.spec.js && node src/ifStatementRemoval.spec.js && node src/negationOperatorRemoval.spec.js && node src/logicalExpressionReduction.spec.js && node src/ternaryOperatorReduction.spec.js", | ||
"lint": "standard" | ||
}, | ||
@@ -26,4 +27,7 @@ "repository": { | ||
"devDependencies": { | ||
"abstract-syntax-tree": "^2.1.0" | ||
"abstract-syntax-tree": "^2.1.0", | ||
"ava": "^1.0.1", | ||
"nyc": "^13.1.0", | ||
"standard": "^12.0.1" | ||
} | ||
} |
@@ -255,1 +255,42 @@ # astoptech | ||
``` | ||
### ternaryOperatorReduction | ||
```js | ||
const foo = true ? "bar": "baz" | ||
``` | ||
Given a known value of the conditional expression it's possible to get the right value immediately. | ||
```js | ||
const foo = "bar" | ||
``` | ||
The tree would be translated from: | ||
```json | ||
{ | ||
"type": "ConditionalExpression", | ||
"test": { | ||
"type": "Literal", | ||
"value": true | ||
}, | ||
"consequent": { | ||
"type": "Literal", | ||
"value": "bar" | ||
}, | ||
"alternate": { | ||
"type": "Literal", | ||
"value": "baz" | ||
} | ||
} | ||
``` | ||
To: | ||
```json | ||
{ | ||
"type": "Literal", | ||
"value": "bar" | ||
} | ||
``` |
@@ -1,5 +0,5 @@ | ||
const ARITHMETIC_OPERATORS = ['+', '-', '*', '/', '%', '**'] | ||
const OPERATORS = ['+', '-', '*', '/', '%', '**', '===', '==', '!=', '!==', '>', '<', '>=', '<=', '&', '|', '^', '<<', '>>'] | ||
function isArithmeticOperator (operator) { | ||
return ARITHMETIC_OPERATORS.includes(operator) | ||
function isOperatorSupported (operator) { | ||
return OPERATORS.includes(operator) | ||
} | ||
@@ -15,2 +15,15 @@ | ||
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 | ||
case '>>': return left >> right | ||
} | ||
@@ -24,3 +37,3 @@ } | ||
node.right.type === 'Literal' && | ||
isArithmeticOperator(node.operator) | ||
isOperatorSupported(node.operator) | ||
) { | ||
@@ -31,2 +44,1 @@ return { type: 'Literal', value: calculate(node.operator, node.left.value, node.right.value) } | ||
} | ||
@@ -5,25 +5,76 @@ const AbstractSyntaxTree = require('abstract-syntax-tree') | ||
var tree = new AbstractSyntaxTree('const number = 2 + 2;\n') | ||
var tree = new AbstractSyntaxTree('const foo = 2 + 2;\n') | ||
tree.replace({ enter: binaryExpressionReduction }) | ||
assert.deepEqual(tree.source, 'const number = 4;\n') | ||
assert.deepStrictEqual(tree.source, 'const foo = 4;\n') | ||
var tree = new AbstractSyntaxTree('const number = 2 - 2;\n') | ||
var tree = new AbstractSyntaxTree('const foo = 2 - 2;\n') | ||
tree.replace({ enter: binaryExpressionReduction }) | ||
assert.deepEqual(tree.source, 'const number = 0;\n') | ||
assert.deepStrictEqual(tree.source, 'const foo = 0;\n') | ||
var tree = new AbstractSyntaxTree('const number = 2 * 2;\n') | ||
var tree = new AbstractSyntaxTree('const foo = 2 * 2;\n') | ||
tree.replace({ enter: binaryExpressionReduction }) | ||
assert.deepEqual(tree.source, 'const number = 4;\n') | ||
assert.deepStrictEqual(tree.source, 'const foo = 4;\n') | ||
var tree = new AbstractSyntaxTree('const number = 2 / 2;\n') | ||
var tree = new AbstractSyntaxTree('const foo = 2 / 2;\n') | ||
tree.replace({ enter: binaryExpressionReduction }) | ||
assert.deepEqual(tree.source, 'const number = 1;\n') | ||
assert.deepStrictEqual(tree.source, 'const foo = 1;\n') | ||
var tree = new AbstractSyntaxTree('const foo = 5 % 2;\n') | ||
tree.replace({ enter: binaryExpressionReduction }) | ||
assert.deepStrictEqual(tree.source, 'const foo = 1;\n') | ||
var tree = new AbstractSyntaxTree('const number = 5 % 2;\n') | ||
var tree = new AbstractSyntaxTree('const foo = 2 ** 3;\n') | ||
tree.replace({ enter: binaryExpressionReduction }) | ||
assert.deepEqual(tree.source, 'const number = 1;\n') | ||
assert.deepStrictEqual(tree.source, 'const foo = 8;\n') | ||
var tree = new AbstractSyntaxTree('const number = 2 ** 3;\n') | ||
var tree = new AbstractSyntaxTree('const foo = 2 === 3;\n') | ||
tree.replace({ enter: binaryExpressionReduction }) | ||
assert.deepEqual(tree.source, 'const number = 8;\n') | ||
assert.deepStrictEqual(tree.source, 'const foo = false;\n') | ||
var tree = new AbstractSyntaxTree('const foo = 2 == "2";\n') | ||
tree.replace({ enter: binaryExpressionReduction }) | ||
assert.deepStrictEqual(tree.source, 'const foo = true;\n') | ||
var tree = new AbstractSyntaxTree('const foo = 2 !== 3;\n') | ||
tree.replace({ enter: binaryExpressionReduction }) | ||
assert.deepStrictEqual(tree.source, 'const foo = true;\n') | ||
var tree = new AbstractSyntaxTree('const foo = 2 != "2";\n') | ||
tree.replace({ enter: binaryExpressionReduction }) | ||
assert.deepStrictEqual(tree.source, 'const foo = false;\n') | ||
var tree = new AbstractSyntaxTree('const foo = 2 > 3;\n') | ||
tree.replace({ enter: binaryExpressionReduction }) | ||
assert.deepStrictEqual(tree.source, 'const foo = false;\n') | ||
var tree = new AbstractSyntaxTree('const foo = 2 < 3;\n') | ||
tree.replace({ enter: binaryExpressionReduction }) | ||
assert.deepStrictEqual(tree.source, 'const foo = true;\n') | ||
var tree = new AbstractSyntaxTree('const foo = 2 >= 3;\n') | ||
tree.replace({ enter: binaryExpressionReduction }) | ||
assert.deepStrictEqual(tree.source, 'const foo = false;\n') | ||
var tree = new AbstractSyntaxTree('const foo = 2 <= 3;\n') | ||
tree.replace({ enter: binaryExpressionReduction }) | ||
assert.deepStrictEqual(tree.source, 'const foo = true;\n') | ||
var tree = new AbstractSyntaxTree('const foo = 7 & 1;\n') | ||
tree.replace({ enter: binaryExpressionReduction }) | ||
assert.deepStrictEqual(tree.source, 'const foo = 1;\n') | ||
var tree = new AbstractSyntaxTree('const foo = 7 | 1;\n') | ||
tree.replace({ enter: binaryExpressionReduction }) | ||
assert.deepStrictEqual(tree.source, 'const foo = 7;\n') | ||
var tree = new AbstractSyntaxTree('const foo = 7 ^ 1;\n') | ||
tree.replace({ enter: binaryExpressionReduction }) | ||
assert.deepStrictEqual(tree.source, 'const foo = 6;\n') | ||
var tree = new AbstractSyntaxTree('const foo = 7 << 1;\n') | ||
tree.replace({ enter: binaryExpressionReduction }) | ||
assert.deepStrictEqual(tree.source, 'const foo = 14;\n') | ||
var tree = new AbstractSyntaxTree('const foo = 7 >> 1;\n') | ||
tree.replace({ enter: binaryExpressionReduction }) | ||
assert.deepStrictEqual(tree.source, 'const foo = 3;\n') |
@@ -11,9 +11,9 @@ function getBody (node) { | ||
const truthyValues = ['Infinity'] | ||
const falsyValues = ['undefined', 'NaN'] | ||
const isNodeTruthy = require('./utilities/isNodeTruthy') | ||
module.exports = function ifStatementRemoval (node) { | ||
if (node.type === 'IfStatement') { | ||
if (node.test.type === 'Literal') { | ||
if (node.test.value) { | ||
const truthy = isNodeTruthy(node.test) | ||
if (typeof truthy === 'boolean') { | ||
if (truthy) { | ||
return getBody(node.consequent) | ||
@@ -23,27 +23,2 @@ } else { | ||
} | ||
} else if (node.test.type === 'ArrayExpression' || node.test.type === 'ObjectExpression' ) { | ||
return getBody(node.consequent) | ||
} else if ( | ||
node.test.type === 'Identifier' && | ||
truthyValues.includes(node.test.name) | ||
) { | ||
return getBody(node.consequent) | ||
} else if ( | ||
node.test.type === 'Identifier' && | ||
falsyValues.includes(node.test.name) && | ||
node.alternate | ||
) { | ||
return getBody(node.alternate) | ||
} else if (node.test.type === 'UnaryExpression') { | ||
if (node.test.operator === 'void' && node.alternate) { | ||
return getBody(node.alternate) | ||
} else if (node.test.operator === '-' && node.test.argument.type === 'Identifier' && truthyValues.includes(node.test.argument.name)) { | ||
return getBody(node.consequent) | ||
} | ||
} else if (node.test.type === 'TemplateLiteral' && node.test.expressions.length === 0) { | ||
if (node.test.quasis[0].value.raw) { | ||
return getBody(node.consequent) | ||
} else { | ||
return getBody(node.alternate) | ||
} | ||
} | ||
@@ -53,2 +28,1 @@ } | ||
} | ||
@@ -7,82 +7,82 @@ const AbstractSyntaxTree = require('abstract-syntax-tree') | ||
tree.replace({ enter: ifStatementRemoval }) | ||
assert.deepEqual(tree.source, 'console.log("foo");\n') | ||
assert.deepStrictEqual(tree.source, 'console.log("foo");\n') | ||
var tree = new AbstractSyntaxTree('if (true) { console.log("foo") } else { console.log("bar") }') | ||
tree.replace({ enter: ifStatementRemoval }) | ||
assert.deepEqual(tree.source, 'console.log("foo");\n') | ||
assert.deepStrictEqual(tree.source, 'console.log("foo");\n') | ||
var tree = new AbstractSyntaxTree('if (1) { console.log("foo") } else { console.log("bar") }') | ||
tree.replace({ enter: ifStatementRemoval }) | ||
assert.deepEqual(tree.source, 'console.log("foo");\n') | ||
assert.deepStrictEqual(tree.source, 'console.log("foo");\n') | ||
var tree = new AbstractSyntaxTree('if ("foo") { console.log("foo") }') | ||
tree.replace({ enter: ifStatementRemoval }) | ||
assert.deepEqual(tree.source, 'console.log("foo");\n') | ||
assert.deepStrictEqual(tree.source, 'console.log("foo");\n') | ||
var tree = new AbstractSyntaxTree('if (`foo`) { console.log("foo") } else { console.log("bar") }') | ||
tree.replace({ enter: ifStatementRemoval }) | ||
assert.deepEqual(tree.source, 'console.log("foo");\n') | ||
assert.deepStrictEqual(tree.source, 'console.log("foo");\n') | ||
var tree = new AbstractSyntaxTree('if ([]) { console.log("foo") }') | ||
tree.replace({ enter: ifStatementRemoval }) | ||
assert.deepEqual(tree.source, 'console.log("foo");\n') | ||
assert.deepStrictEqual(tree.source, 'console.log("foo");\n') | ||
var tree = new AbstractSyntaxTree('if ({}) { console.log("foo") }') | ||
tree.replace({ enter: ifStatementRemoval }) | ||
assert.deepEqual(tree.source, 'console.log("foo");\n') | ||
assert.deepStrictEqual(tree.source, 'console.log("foo");\n') | ||
var tree = new AbstractSyntaxTree('if (Infinity) { console.log("foo") }') | ||
tree.replace({ enter: ifStatementRemoval }) | ||
assert.deepEqual(tree.source, 'console.log("foo");\n') | ||
assert.deepStrictEqual(tree.source, 'console.log("foo");\n') | ||
var tree = new AbstractSyntaxTree('if (-Infinity) { console.log("foo") }') | ||
tree.replace({ enter: ifStatementRemoval }) | ||
assert.deepEqual(tree.source, 'console.log("foo");\n') | ||
assert.deepStrictEqual(tree.source, 'console.log("foo");\n') | ||
var tree = new AbstractSyntaxTree('const foo = "foo"; if (`${foo}`) { console.log("foo") } else { console.log("bar") }') | ||
var tree = new AbstractSyntaxTree('const foo = "foo"; if (foo) { console.log("foo") } else { console.log("bar") }') | ||
tree.replace({ enter: ifStatementRemoval }) | ||
assert.deepEqual(tree.source, 'const foo = "foo";\nif (`${foo}`) {\n console.log("foo");\n} else {\n console.log("bar");\n}\n') | ||
assert.deepStrictEqual(tree.source, 'const foo = "foo";\nif (foo) {\n console.log("foo");\n} else {\n console.log("bar");\n}\n') | ||
var tree = new AbstractSyntaxTree('if (false) { console.log("foo") } else { console.log("bar") }') | ||
tree.replace({ enter: ifStatementRemoval }) | ||
assert.deepEqual(tree.source, 'console.log("bar");\n') | ||
assert.deepStrictEqual(tree.source, 'console.log("bar");\n') | ||
var tree = new AbstractSyntaxTree('if (null) { console.log("foo") } else { console.log("bar") }') | ||
tree.replace({ enter: ifStatementRemoval }) | ||
assert.deepEqual(tree.source, 'console.log("bar");\n') | ||
assert.deepStrictEqual(tree.source, 'console.log("bar");\n') | ||
var tree = new AbstractSyntaxTree('if (undefined) { console.log("foo") } else { console.log("bar") }') | ||
tree.replace({ enter: ifStatementRemoval }) | ||
assert.deepEqual(tree.source, 'console.log("bar");\n') | ||
assert.deepStrictEqual(tree.source, 'console.log("bar");\n') | ||
var tree = new AbstractSyntaxTree('if (0) { console.log("foo") } else { console.log("bar") }') | ||
tree.replace({ enter: ifStatementRemoval }) | ||
assert.deepEqual(tree.source, 'console.log("bar");\n') | ||
assert.deepStrictEqual(tree.source, 'console.log("bar");\n') | ||
var tree = new AbstractSyntaxTree('if (NaN) { console.log("foo") } else { console.log("bar") }') | ||
tree.replace({ enter: ifStatementRemoval }) | ||
assert.deepEqual(tree.source, 'console.log("bar");\n') | ||
assert.deepStrictEqual(tree.source, 'console.log("bar");\n') | ||
var tree = new AbstractSyntaxTree('if (void 0) { console.log("foo") } else { console.log("bar") }') | ||
tree.replace({ enter: ifStatementRemoval }) | ||
assert.deepEqual(tree.source, 'console.log("bar");\n') | ||
assert.deepStrictEqual(tree.source, 'console.log("bar");\n') | ||
var tree = new AbstractSyntaxTree('if (void(0)) { console.log("foo") } else { console.log("bar") }') | ||
tree.replace({ enter: ifStatementRemoval }) | ||
assert.deepEqual(tree.source, 'console.log("bar");\n') | ||
assert.deepStrictEqual(tree.source, 'console.log("bar");\n') | ||
var tree = new AbstractSyntaxTree('if (\'\') { console.log("foo") } else { console.log("bar") }') | ||
tree.replace({ enter: ifStatementRemoval }) | ||
assert.deepEqual(tree.source, 'console.log("bar");\n') | ||
assert.deepStrictEqual(tree.source, 'console.log("bar");\n') | ||
var tree = new AbstractSyntaxTree('if ("") { console.log("foo") } else { console.log("bar") }') | ||
tree.replace({ enter: ifStatementRemoval }) | ||
assert.deepEqual(tree.source, 'console.log("bar");\n') | ||
assert.deepStrictEqual(tree.source, 'console.log("bar");\n') | ||
var tree = new AbstractSyntaxTree('if (``) { console.log("foo") } else { console.log("bar") }') | ||
tree.replace({ enter: ifStatementRemoval }) | ||
assert.deepEqual(tree.source, 'console.log("bar");\n') | ||
assert.deepStrictEqual(tree.source, 'console.log("bar");\n') | ||
var tree = new AbstractSyntaxTree('if (false) { console.log("foo") }') | ||
tree.replace({ enter: ifStatementRemoval }) | ||
assert.deepEqual(tree.source, '') | ||
assert.deepStrictEqual(tree.source, '') |
@@ -1,2 +0,2 @@ | ||
const LOGICAL_OPERATORS = ["&&", "||"] | ||
const LOGICAL_OPERATORS = ['&&', '||'] | ||
@@ -3,0 +3,0 @@ function isLogicalOperator (operator) { |
@@ -7,6 +7,6 @@ const AbstractSyntaxTree = require('abstract-syntax-tree') | ||
tree.replace({ enter: logicalExpressionReduction }) | ||
assert.deepEqual(tree.source, 'const foo = "baz";\n') | ||
assert.deepStrictEqual(tree.source, 'const foo = "baz";\n') | ||
var tree = new AbstractSyntaxTree('const foo = "bar" || "baz";\n') | ||
tree.replace({ enter: logicalExpressionReduction }) | ||
assert.deepEqual(tree.source, 'const foo = "bar";\n') | ||
assert.deepStrictEqual(tree.source, 'const foo = "bar";\n') |
@@ -1,3 +0,3 @@ | ||
function isComparisonOperator(operator) { | ||
return (/^(==|===|!=|!==|<|>|<=|>=)$/).test(operator); | ||
function isComparisonOperator (operator) { | ||
return (/^(==|===|!=|!==|<|>|<=|>=)$/).test(operator) | ||
} | ||
@@ -28,2 +28,1 @@ | ||
} | ||
@@ -7,30 +7,30 @@ const AbstractSyntaxTree = require('abstract-syntax-tree') | ||
tree.replace({ enter: negationOperatorRemoval }) | ||
assert.deepEqual(tree.source, 'if (foo !== bar) {\n console.log("foo");\n}\n') | ||
assert.deepStrictEqual(tree.source, 'if (foo !== bar) {\n console.log("foo");\n}\n') | ||
var tree = new AbstractSyntaxTree('if (!(foo < bar)) { console.log("foo") }\n') | ||
tree.replace({ enter: negationOperatorRemoval }) | ||
assert.deepEqual(tree.source, 'if (foo >= bar) {\n console.log("foo");\n}\n') | ||
assert.deepStrictEqual(tree.source, 'if (foo >= bar) {\n console.log("foo");\n}\n') | ||
var tree = new AbstractSyntaxTree('if (!(foo > bar)) { console.log("foo") }\n') | ||
tree.replace({ enter: negationOperatorRemoval }) | ||
assert.deepEqual(tree.source, 'if (foo <= bar) {\n console.log("foo");\n}\n') | ||
assert.deepStrictEqual(tree.source, 'if (foo <= bar) {\n console.log("foo");\n}\n') | ||
var tree = new AbstractSyntaxTree('if (!(foo >= bar)) { console.log("foo") }\n') | ||
tree.replace({ enter: negationOperatorRemoval }) | ||
assert.deepEqual(tree.source, 'if (foo < bar) {\n console.log("foo");\n}\n') | ||
assert.deepStrictEqual(tree.source, 'if (foo < bar) {\n console.log("foo");\n}\n') | ||
var tree = new AbstractSyntaxTree('if (!(foo <= bar)) { console.log("foo") }\n') | ||
tree.replace({ enter: negationOperatorRemoval }) | ||
assert.deepEqual(tree.source, 'if (foo > bar) {\n console.log("foo");\n}\n') | ||
assert.deepStrictEqual(tree.source, 'if (foo > bar) {\n console.log("foo");\n}\n') | ||
var tree = new AbstractSyntaxTree('if (!(foo != bar)) { console.log("foo") }\n') | ||
tree.replace({ enter: negationOperatorRemoval }) | ||
assert.deepEqual(tree.source, 'if (foo == bar) {\n console.log("foo");\n}\n') | ||
assert.deepStrictEqual(tree.source, 'if (foo == bar) {\n console.log("foo");\n}\n') | ||
var tree = new AbstractSyntaxTree('if (!(foo !== bar)) { console.log("foo") }\n') | ||
tree.replace({ enter: negationOperatorRemoval }) | ||
assert.deepEqual(tree.source, 'if (foo === bar) {\n console.log("foo");\n}\n') | ||
assert.deepStrictEqual(tree.source, 'if (foo === bar) {\n console.log("foo");\n}\n') | ||
var tree = new AbstractSyntaxTree('if (!(foo == bar)) { console.log("foo") }\n') | ||
tree.replace({ enter: negationOperatorRemoval }) | ||
assert.deepEqual(tree.source, 'if (foo != bar) {\n console.log("foo");\n}\n') | ||
assert.deepStrictEqual(tree.source, 'if (foo != bar) {\n console.log("foo");\n}\n') |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
23801
16
338
296
4