Socket
Socket
Sign inDemoInstall

babel-plugin-minify-dead-code-elimination

Package Overview
Dependencies
Maintainers
4
Versions
91
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

babel-plugin-minify-dead-code-elimination - npm Package Compare versions

Comparing version 0.1.2 to 0.1.3

240

lib/index.js

@@ -7,2 +7,25 @@ "use strict";

var _require = require("babel-helper-mark-eval-scopes"),
markEvalScopes = _require.markEvalScopes,
isEvalScopesMarked = _require.isMarked,
hasEval = _require.hasEval;
function prevSiblings(path) {
var parentPath = path.parentPath;
var siblings = [];
var key = parentPath.key;
while ((path = parentPath.getSibling(--key)).type) {
siblings.push(path);
}
return siblings;
}
function forEachAncestor(path, callback) {
while (path = path.parentPath) {
callback(path);
}
}
module.exports = function (_ref) {

@@ -182,2 +205,6 @@ var t = _ref.types,

if (hasEval(path.scope)) {
return;
}
var scope = path.scope;

@@ -196,2 +223,4 @@

var binding = scope.bindings[param.node.name];
if (!binding) continue;
if (binding.referenced) {

@@ -360,15 +389,54 @@ // when the first binding is referenced (right to left)

var _ret6 = function () {
var replacement = binding.path.node;
var replacementPath = binding.path;
var isReferencedBefore = false;
if (binding.referencePaths.length > 1) {
throw new Error("Expected only one reference");
}
var refPath = binding.referencePaths[0];
if (t.isVariableDeclarator(replacement)) {
replacement = replacement.init;
// Bail out for ArrayPattern and ObjectPattern
// TODO: maybe a more intelligent approach instead of simply bailing out
if (!replacementPath.get("id").isIdentifier()) {
return {
v: "continue"
};
}
replacementPath = replacementPath.get("init");
var _ret7 = function () {
var _prevSiblings = prevSiblings(replacementPath);
// traverse ancestors of a reference checking if it's before declaration
forEachAncestor(refPath, function (ancestor) {
if (_prevSiblings.indexOf(ancestor) > -1) {
isReferencedBefore = true;
}
});
// deopt if reference is in different scope than binding
// since we don't know if it's sync or async execition
// (i.e. whether value has been assigned to a reference or not)
if (isReferencedBefore && refPath.scope !== binding.scope) {
return {
v: {
v: "continue"
}
};
}
// simulate hoisting by replacing value
// with undefined if declaration is after reference
replacement = isReferencedBefore ? t.unaryExpression("void", t.numericLiteral(0), true) : replacement.init;
// Bail out for ArrayPattern and ObjectPattern
// TODO: maybe a more intelligent approach instead of simply bailing out
if (!replacementPath.get("id").isIdentifier()) {
return {
v: {
v: "continue"
}
};
}
replacementPath = replacementPath.get("init");
}();
if (typeof _ret7 === "object") return _ret7.v;
}
if (!replacement) {

@@ -380,3 +448,3 @@ return {

if (!scope.isPure(replacement, true)) {
if (!scope.isPure(replacement, true) && !isReferencedBefore) {
return {

@@ -387,8 +455,3 @@ v: "continue"

if (binding.referencePaths.length > 1) {
throw new Error("Expected only one reference");
}
var bail = false;
var refPath = binding.referencePaths[0];

@@ -508,3 +571,3 @@ if (replacementPath.isIdentifier()) {

// Not last in it's block? (See BlockStatement visitor)
// Not last in its block? (See BlockStatement visitor)
if (path.container.length - 1 !== path.key && !canExistAfterCompletion(path.getSibling(path.key + 1)) && path.parentPath.isBlockStatement()) {

@@ -568,61 +631,2 @@ // This is probably a new oppurtinity by some other transform

IfStatement: {
exit(path) {
var consequent = path.get("consequent");
var alternate = path.get("alternate");
var test = path.get("test");
var evaluateTest = test.evaluateTruthy();
// we can check if a test will be truthy 100% and if so then we can inline
// the consequent and completely ignore the alternate
//
// if (true) { foo; } -> { foo; }
// if ("foo") { foo; } -> { foo; }
//
if (evaluateTest === true) {
path.replaceWithMultiple([].concat(_toConsumableArray(toStatements(consequent)), _toConsumableArray(extractVars(alternate))));
return;
}
// we can check if a test will be falsy 100% and if so we can inline the
// alternate if there is one and completely remove the consequent
//
// if ("") { bar; } else { foo; } -> { foo; }
// if ("") { bar; } ->
//
if (evaluateTest === false) {
if (alternate.node) {
path.replaceWithMultiple([].concat(_toConsumableArray(toStatements(alternate)), _toConsumableArray(extractVars(consequent))));
return;
} else {
path.replaceWithMultiple(extractVars(consequent));
}
}
// remove alternate blocks that are empty
//
// if (foo) { foo; } else {} -> if (foo) { foo; }
//
if (alternate.isBlockStatement() && !alternate.node.body.length) {
alternate.remove();
// For if-statements babel-traverse replaces with an empty block
path.node.alternate = null;
}
// if the consequent block is empty turn alternate blocks into a consequent
// and flip the test
//
// if (foo) {} else { bar; } -> if (!foo) { bar; }
//
if (consequent.isBlockStatement() && !consequent.node.body.length && alternate.isBlockStatement() && alternate.node.body.length) {
consequent.replaceWith(alternate.node);
alternate.remove();
// For if-statements babel-traverse replaces with an empty block
path.node.alternate = null;
test.replaceWith(t.unaryExpression("!", test.node, true));
}
}
},
SwitchStatement: {

@@ -839,2 +843,68 @@ exit(path) {

visitor: {
IfStatement: {
exit(path) {
var consequent = path.get("consequent");
var alternate = path.get("alternate");
var test = path.get("test");
var evalResult = test.evaluate();
var isPure = test.isPure();
var replacements = [];
if (evalResult.confident && !isPure && test.isSequenceExpression()) {
replacements.push(t.expressionStatement(extractSequenceImpure(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
//
// if (true) { foo; } -> { foo; }
// if ("foo") { foo; } -> { foo; }
//
if (evalResult.confident && evalResult.value) {
path.replaceWithMultiple([].concat(replacements, _toConsumableArray(toStatements(consequent)), _toConsumableArray(extractVars(alternate))));
return;
}
// we can check if a test will be falsy 100% and if so we can inline the
// alternate if there is one and completely remove the consequent
//
// if ("") { bar; } else { foo; } -> { foo; }
// if ("") { bar; } ->
//
if (evalResult.confident && !evalResult.value) {
if (alternate.node) {
path.replaceWithMultiple([].concat(replacements, _toConsumableArray(toStatements(alternate)), _toConsumableArray(extractVars(consequent))));
return;
} else {
path.replaceWithMultiple([].concat(replacements, _toConsumableArray(extractVars(consequent))));
}
}
// remove alternate blocks that are empty
//
// if (foo) { foo; } else {} -> if (foo) { foo; }
//
if (alternate.isBlockStatement() && !alternate.node.body.length) {
alternate.remove();
// For if-statements babel-traverse replaces with an empty block
path.node.alternate = null;
}
// if the consequent block is empty turn alternate blocks into a consequent
// and flip the test
//
// if (foo) {} else { bar; } -> if (!foo) { bar; }
//
if (consequent.isBlockStatement() && !consequent.node.body.length && alternate.isBlockStatement() && alternate.node.body.length) {
consequent.replaceWith(alternate.node);
alternate.remove();
// For if-statements babel-traverse replaces with an empty block
path.node.alternate = null;
test.replaceWith(t.unaryExpression("!", test.node, true));
}
}
},
EmptyStatement(path) {

@@ -845,2 +915,3 @@ if (path.parentPath.isBlockStatement() || path.parentPath.isProgram()) {

},
Program: {

@@ -864,2 +935,6 @@ exit(path) {

if (!isEvalScopesMarked(path.scope)) {
markEvalScopes(path);
}
// We need to run this plugin in isolation.

@@ -986,3 +1061,3 @@ path.traverse(main, {

if (scope !== path.scope) {
var _ret7 = function () {
var _ret8 = function () {
if (t.isClass(replacement) || t.isFunction(replacement)) {

@@ -1012,3 +1087,3 @@ return {

if (typeof _ret7 === "object") return _ret7.v;
if (typeof _ret8 === "object") return _ret8.v;
}

@@ -1234,2 +1309,13 @@

}
function extractSequenceImpure(seq) {
var expressions = seq.get("expressions");
var result = [];
for (var i = 0; i < expressions.length; i++) {
if (!expressions[i].isPure()) {
result.push(expressions[i].node);
}
}
return t.sequenceExpression(result);
}
};
{
"name": "babel-plugin-minify-dead-code-elimination",
"version": "0.1.2",
"version": "0.1.3",
"description": "",

@@ -15,2 +15,3 @@ "homepage": "https://github.com/babel/babili#readme",

"dependencies": {
"babel-helper-mark-eval-scopes": "^0.0.2",
"babel-helper-remove-or-void": "^0.0.1",

@@ -17,0 +18,0 @@ "lodash.some": "^4.6.0"

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc