Browse Source

DRY out code, handle strict vs non-strict

better-aggressive
Rich-Harris 9 years ago
parent
commit
98e890986f
  1. 76
      src/ast/conditions.js
  2. 1
      test/function/skips-dead-branches-f/_config.js
  3. 8
      test/function/skips-dead-branches-g/_config.js
  4. 11
      test/function/skips-dead-branches-g/main.js

76
src/ast/conditions.js

@ -1,65 +1,39 @@
function isEqualTest ( node ) {
return node.type === 'BinaryExpression' && ( node.operator === '===' || node.operator === '==' );
export function isTruthy ( node ) {
if ( node.type === 'Literal' ) return !!node.value;
if ( node.type === 'ParenthesizedExpression' ) return isTruthy( node.expression );
if ( node.operator in operators ) return operators[ node.operator ]( node );
}
function isNotEqualTest ( node ) {
return node.type === 'BinaryExpression' && ( node.operator === '!==' || node.operator === '!=' );
export function isFalsy ( node ) {
return not( isTruthy( node ) );
}
function nodesAreEqual ( a, b ) {
if ( a.type !== b.type ) return false;
if ( a.type === 'Literal' ) return a.value === b.value
if ( a.type === 'Identifier' ) return a.name === b.name && a.name !== 'NaN';
return false;
function not ( value ) {
return value === undefined ? value : !value;
}
function nodesAreNotEqual ( a, b ) {
if ( a.type !== b.type ) return false;
if ( a.type === 'Literal' ) return a.value != b.value;
if ( a.type === 'Identifier' ) return a.name != b.name || a.name === 'NaN';
return false;
function equals ( a, b, strict ) {
if ( a.type !== b.type ) return undefined;
if ( a.type === 'Identifier' ) return a.name === b.name && a.name !== 'NaN';
if ( a.type === 'Literal' ) return strict ? a.value === b.value : a.value == b.value;
}
export function isTruthy ( node ) {
if ( node.type === 'Literal' && node.value ) return true;
if ( node.type === 'ParenthesizedExpression' ) return isTruthy( node.expression );
if ( isEqualTest( node ) ) return nodesAreEqual( node.left, node.right );
if ( isNotEqualTest( node ) ) return nodesAreNotEqual( node.left, node.right );
const operators = {
'==': x => {
return equals( x.left, x.right, false );
},
if ( node.type === 'UnaryExpression' ) {
if ( node.operator === '!' ) return isFalsy( node.argument );
return false;
}
'!=': x => not( operators['==']( x ) ),
if ( node.type === 'LogicalExpression' ) {
if ( node.operator === '&&' ) return isTruthy( node.left ) && isTruthy( node.right );
if ( node.operator === '||' ) return isTruthy( node.left ) || isTruthy( node.right );
return false;
}
'===': x => {
return equals( x.left, x.right, true );
},
return false;
}
'!==': x => not( operators['===']( x ) ),
export function isFalsy ( node ) {
if ( node.type === 'Literal' && !node.value ) return true;
if ( node.type === 'ParenthesizedExpression' ) return isFalsy( node.expression );
'!': x => isFalsy( x.argument ),
if ( isEqualTest( node ) ) return nodesAreNotEqual( node.left, node.right );
if ( isNotEqualTest( node ) ) return nodesAreEqual( node.left, node.right );
'&&': x => isTruthy( x.left ) && isTruthy( x.right ),
if ( node.type === 'UnaryExpression' ) {
if ( node.operator === '!' ) return isTruthy( node.argument );
return false;
}
if ( node.type === 'LogicalExpression' ) {
if ( node.operator === '&&' ) return isFalsy( node.left ) || isFalsy( node.right );
if ( node.operator === '||' ) return isFalsy( node.left ) && isFalsy( node.right );
return false;
}
return false;
}
'||': x => isTruthy( x.left ) || isTruthy( x.right )
};

1
test/function/skips-dead-branches-f/_config.js

@ -1,7 +1,6 @@
var assert = require( 'assert' );
module.exports = {
solo: true,
description: 'skips a dead branch (f)',
code: function ( code ) {
assert.equal( code.indexOf( 'obj.foo = function' ), -1, code );

8
test/function/skips-dead-branches-g/_config.js

@ -0,0 +1,8 @@
var assert = require( 'assert' );
module.exports = {
description: 'skips a dead branch (g)',
code: function ( code ) {
assert.equal( code.indexOf( 'obj.foo = function' ), -1, code );
}
}

11
test/function/skips-dead-branches-g/main.js

@ -0,0 +1,11 @@
var obj = {};
obj.foo = function () {
console.log( 'this should be excluded' );
}
function bar () {
console.log( 'this should be included' );
}
if ( 42 != '42' ) obj.foo();
bar();
Loading…
Cancel
Save