Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

butternut

Package Overview
Dependencies
Maintainers
1
Versions
15
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

butternut - npm Package Compare versions

Comparing version 0.4.5 to 0.4.6

src/program/types/ImportDeclaration.js

4

CHANGELOG.md
# butternut changelog
## 0.4.6
* Too many fixes to list individually!
## 0.4.5

@@ -4,0 +8,0 @@

4

package.json
{
"name": "butternut",
"version": "0.4.5",
"version": "0.4.6",
"description": "Experimental ES2015-aware minifier",

@@ -95,3 +95,3 @@ "main": "dist/butternut.cjs.js",

"chalk": "^1.1.3",
"magic-string": "^0.19.0",
"magic-string": "^0.20.0",
"minimist": "^1.2.0",

@@ -98,0 +98,0 @@ "sourcemap-codec": "^1.3.1"

@@ -53,3 +53,3 @@ import Node from './Node.js';

export default class BlockStatement extends Node {
attachScope ( parent ) {
attachScope ( program, parent ) {
this.parentIsFunction = /Function/.test( this.parent.type );

@@ -67,3 +67,3 @@

for ( let i = 0; i < this.body.length; i += 1 ) {
this.body[i].attachScope( this.scope );
this.body[i].attachScope( program, this.scope );
}

@@ -115,3 +115,3 @@ }

initialise ( scope ) {
initialise ( program, scope ) {
let executionIsBroken = false;

@@ -130,3 +130,3 @@ let maybeReturnNode;

hasDeclarationsAfterBreak = true;
node.initialise( this.scope || scope );
node.initialise( program, this.scope || scope );
}

@@ -140,3 +140,3 @@

node.initialise( this.scope || scope );
node.initialise( program, this.scope || scope );

@@ -175,4 +175,6 @@ if ( canCollapseReturns ) {

minify ( code ) {
if ( this.scope ) this.scope.mangle( code );
minify ( code, chars ) {
if ( this.scope ) {
this.scope.mangle( code, chars );
}

@@ -230,3 +232,3 @@ let insertedVarDeclaration = '';

statement.minify( code );
statement.minify( code, chars );

@@ -308,5 +310,5 @@ if ( !statement.collapsed ) {

// statements.forEach( statement => {
// statement.minify( code );
// statement.minify( code, chars );
// });
// }
}

@@ -19,3 +19,3 @@ import { UNKNOWN } from '../utils/sentinels.js';

attachScope ( scope ) {
attachScope ( program, scope ) {
for ( var key of this.keys ) {

@@ -28,6 +28,6 @@ const value = this[ key ];

while ( i-- ) {
if ( value[i] ) value[i].attachScope( scope );
if ( value[i] ) value[i].attachScope( program, scope );
}
} else {
value.attachScope( scope );
value.attachScope( program, scope );
}

@@ -71,3 +71,3 @@ }

initialise ( scope ) {
initialise ( program, scope ) {
this.skip = false;

@@ -82,6 +82,6 @@

while ( i-- ) {
if ( value[i] ) value[i].initialise( scope );
if ( value[i] ) value[i].initialise( program, scope );
}
} else {
value.initialise( scope );
value.initialise( program, scope );
}

@@ -117,3 +117,3 @@ }

minify ( code ) {
minify ( code, chars ) {
for ( var key of this.keys ) {

@@ -126,6 +126,6 @@ const value = this[ key ];

while ( i-- ) {
if ( value[i] ) value[i].minify( code );
if ( value[i] ) value[i].minify( code, chars );
}
} else {
value.minify( code );
value.minify( code, chars );
}

@@ -132,0 +132,0 @@ }

@@ -7,2 +7,10 @@ import MagicString from 'magic-string';

const chars = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_$0123456789'.split('');
const digit = /\d/;
const naturalOrder = {};
chars.forEach( ( char, i ) => {
naturalOrder[char] = i;
});
export default function Program ( source, ast, options, stats ) {

@@ -34,10 +42,21 @@ this.options = options;

this.body.body.forEach( node => {
node.attachScope( this.body.scope );
node.attachScope( this, this.body.scope );
});
this.body.initialise( this.body.scope );
this.charFrequency = {};
chars.forEach( char => {
this.charFrequency[char] = 0;
});
this.body.initialise( this, this.body.scope );
if ( DEBUG ) stats.timeEnd( 'init body' );
chars.sort( ( a, b ) => {
if ( digit.test( a ) && !digit.test( b ) ) return 1;
if ( digit.test( b ) && !digit.test( a ) ) return -1;
return ( this.charFrequency[b] - this.charFrequency[a] ) || ( naturalOrder[a] - naturalOrder[b] );
});
if ( DEBUG ) stats.time( 'minify' );
this.body.minify( this.magicString );
this.body.minify( this.magicString, chars );
if ( DEBUG ) stats.timeEnd( 'minify' );

@@ -47,2 +66,8 @@ }

Program.prototype = {
addWord ( word ) {
for ( let i = 0; i < word.length; i += 1 ) {
this.charFrequency[word[i]] += 1;
}
},
export ( options ) {

@@ -49,0 +74,0 @@ const stats = this.stats;

@@ -1,2 +0,2 @@

import reserved from '../utils/reserved.js';
import { reserved } from '../utils/reserved.js';
import CompileError from '../utils/CompileError.js';

@@ -6,4 +6,2 @@

const validChars = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_$';
export default function Scope ( options ) {

@@ -40,7 +38,2 @@ options = options || {};

Scope.prototype = {
addAlias ( alias ) {
this.aliases[ alias ] = true;
if ( this.parent ) this.parent.addAlias( alias );
},
addDeclaration ( identifier, kind ) {

@@ -65,3 +58,3 @@ if ( kind === 'var' && this.isBlockScope ) {

// to keep function names — https://github.com/Rich-Harris/butternut/issues/17)
if ( existingDeclaration.node.parent.type === 'FunctionExpression' ) {
if ( existingDeclaration.kind === 'FunctionExpression' ) {
existingDeclaration.node.parent.shadowed = true;

@@ -134,28 +127,2 @@ }

containsAlias ( alias ) {
return this.aliases[ alias ] || ( this.parent && this.parent.containsAlias( alias ) );
},
createIdentifier ( used ) {
let alias;
do {
alias = this.idCounter.map( i => validChars[i] ).join( '' );
let i = this.idCounter.length;
while ( i-- ) {
this.idCounter[i] += 1;
if ( this.idCounter[i] === validChars.length ) {
this.idCounter[i] = 0;
if ( i === 0 ) this.idCounter.push( 0 );
} else {
break;
}
}
} while ( used[ alias ] || reserved[ alias ] );
return alias;
},
deopt () {

@@ -179,6 +146,9 @@ if ( !this.deopted ) {

mangle ( code ) {
mangle ( code, chars ) {
if ( !this.canMangle ) return;
let used = Object.create( null );
reserved.forEach( word => {
used[ word ] = true;
});

@@ -190,2 +160,16 @@ Object.keys( this.references ).forEach( reference => {

let i = -1;
function getNextAlias () {
let alias;
do {
i += 1;
alias = getAlias( chars, i );
} while ( alias in used );
return alias;
}
// TODO sort declarations by number of instances?
Object.keys( this.declarations ).forEach( name => {

@@ -200,3 +184,3 @@ const declaration = this.declarations[ name ];

declaration.alias = this.createIdentifier( used );
declaration.alias = getNextAlias();

@@ -213,1 +197,17 @@ declaration.instances.forEach( instance => {

};
// adapted from https://github.com/mishoo/UglifyJS2/blob/master/lib/scope.js
function getAlias ( chars, i ) {
let alias = '';
let base = 54;
i++;
do {
i--;
alias += chars[ i % base ];
i = Math.floor( i / base );
base = 64;
} while ( i > 0 );
return alias;
}

@@ -6,3 +6,3 @@ import Node from '../Node.js';

export default class ArrowFunctionExpression extends Node {
attachScope ( parent ) {
attachScope ( program, parent ) {
this.scope = new Scope({

@@ -14,3 +14,3 @@ block: false,

this.params.forEach( param => {
param.attachScope( this.scope );
param.attachScope( program, this.scope );

@@ -25,6 +25,6 @@ extractNames( param ).forEach( node => {

this.body.body.forEach( node => {
node.attachScope( this.scope );
node.attachScope( program, this.scope );
});
} else {
this.body.attachScope( this.scope );
this.body.attachScope( program, this.scope );
}

@@ -34,4 +34,4 @@

initialise () {
super.initialise( this.scope );
initialise ( program ) {
super.initialise( program, this.scope );
}

@@ -47,4 +47,4 @@

minify ( code ) {
this.scope.mangle( code );
minify ( code, chars ) {
this.scope.mangle( code, chars );

@@ -61,3 +61,3 @@ let c = this.start;

else if ( this.params.length === 1 ) {
this.params[0].minify( code );
this.params[0].minify( code, chars );

@@ -88,3 +88,3 @@ if ( this.params[0].type === 'Identifier' ) {

this.params.forEach( ( param, i ) => {
param.minify( code );
param.minify( code, chars );
if ( param.start > c + 1 ) code.overwrite( c, param.start, i ? ',' : '(' );

@@ -99,4 +99,4 @@ c = param.end;

this.body.minify( code );
this.body.minify( code, chars );
}
}

@@ -20,3 +20,3 @@ import Node from '../Node.js';

initialise ( scope ) {
initialise ( program, scope ) {
if ( this.left.type === 'Identifier' ) {

@@ -29,6 +29,6 @@ const declaration = scope.findDeclaration( this.left.name );

super.initialise( scope );
super.initialise( program, scope );
}
minify ( code ) {
minify ( code, chars ) {
if ( this.right.start > this.left.end + this.operator.length ) {

@@ -44,3 +44,3 @@ code.overwrite( this.left.end, this.right.start, this.operator );

this.right.right.minify( code );
this.right.right.minify( code, chars );
return;

@@ -54,3 +54,3 @@ }

this.right.left.minify( code );
this.right.left.minify( code, chars );
return;

@@ -60,4 +60,4 @@ }

super.minify( code );
super.minify( code, chars );
}
}

@@ -59,2 +59,3 @@ import Node from '../Node.js';

// TODO `program.addWord( stringify( this.getValue() ) )`...
getValue () {

@@ -69,3 +70,3 @@ const left = this.left.getValue();

minify ( code ) {
minify ( code, chars ) {
const value = this.getValue();

@@ -88,9 +89,7 @@

if ( this.right.start > this.left.end + operator.length ) {
code.overwrite( this.left.end, this.right.start, operator );
}
code.overwrite( this.left.end, this.right.start, operator );
super.minify( code );
super.minify( code, chars );
}
}
}

@@ -92,3 +92,3 @@ import Node from '../Node.js';

initialise ( scope ) {
initialise ( program, scope ) {
if ( this.callee.type === 'Identifier' && this.callee.name === 'eval' && !scope.contains( 'eval' ) ) {

@@ -101,6 +101,6 @@ if ( this.program.options.allowDangerousEval ) {

}
super.initialise( scope );
super.initialise( program, scope );
}
minify ( code ) {
minify ( code, chars ) {
const value = this.getValue();

@@ -134,4 +134,4 @@

super.minify( code );
super.minify( code, chars );
}
}

@@ -6,3 +6,3 @@ import Node from '../Node.js';

export default class CatchClause extends Node {
attachScope ( parent ) {
attachScope ( program, parent ) {
this.scope = new Scope({

@@ -18,16 +18,17 @@ block: true,

for ( let i = 0; i < this.body.body.length; i += 1 ) {
this.body.body[i].attachScope( this.scope );
this.body.body[i].attachScope( program, this.scope );
}
if ( this.finalizer ) {
this.finalizer.attachScope( this.scope );
this.finalizer.attachScope( program, this.scope );
}
}
initialise () {
super.initialise( this.scope );
initialise ( program ) {
program.addWord( 'catch' );
super.initialise( program, this.scope );
}
minify ( code ) {
this.scope.mangle( code );
minify ( code, chars ) {
this.scope.mangle( code, chars );

@@ -42,4 +43,4 @@ if ( this.param.start > this.start + 6 ) {

super.minify( code );
super.minify( code, chars );
}
}
import Node from '../Node.js';
export default class ClassBody extends Node {
attachScope ( parent ) {
attachScope ( program, parent ) {
for ( let i = 0; i < this.body.length; i += 1 ) {
this.body[i].attachScope( parent );
this.body[i].attachScope( program, parent );
}
}
minify ( code ) {
minify ( code, chars ) {
let c = this.start + 1;

@@ -17,3 +17,3 @@

method.minify( code );
method.minify( code, chars );

@@ -20,0 +20,0 @@ c = method.end;

@@ -9,6 +9,7 @@ import Class from './shared/Class.js';

this.skip = false;
super.initialise( this.scope );
super.initialise( this.program, this.scope );
}
attachScope ( scope ) {
attachScope ( program, scope ) {
this.program = program;
this.scope = scope;

@@ -21,14 +22,14 @@

this.id.attachScope( this.scope );
if ( this.superClass ) this.superClass.attachScope( this.scope );
this.body.attachScope( scope );
this.id.attachScope( program, this.scope );
if ( this.superClass ) this.superClass.attachScope( program, this.scope );
this.body.attachScope( program, scope );
}
initialise ( scope ) {
initialise ( program, scope ) {
if ( scope.parent ) {
// noop — we wait for this declaration to be activated
} else {
super.initialise( scope );
super.initialise( program, scope );
}
}
}

@@ -5,3 +5,3 @@ import Class from './shared/Class.js';

export default class ClassExpression extends Class {
attachScope ( parent ) {
attachScope ( program, parent ) {
this.scope = new Scope({

@@ -12,8 +12,8 @@ block: true,

if ( this.id ) this.id.attachScope( this.scope );
if ( this.superClass ) this.superClass.attachScope( this.scope );
this.body.attachScope( this.scope );
if ( this.id ) this.id.attachScope( program, this.scope );
if ( this.superClass ) this.superClass.attachScope( program, this.scope );
this.body.attachScope( program, this.scope );
}
initialise ( scope ) {
initialise ( program, scope ) {
if ( this.id ) {

@@ -27,9 +27,9 @@ this.id.declaration = this;

super.initialise( scope );
super.initialise( program, scope );
}
minify ( code ) {
this.scope.mangle( code );
super.minify( code );
minify ( code, chars ) {
this.scope.mangle( code, chars );
super.minify( code, chars );
}
}

@@ -34,15 +34,15 @@ import Node from '../Node.js';

initialise ( scope ) {
initialise ( program, scope ) {
const testValue = this.test.getValue();
if ( testValue === UNKNOWN ) {
super.initialise( scope );
super.initialise( program, scope );
} else if ( testValue ) {
this.consequent.initialise( scope );
this.consequent.initialise( program, scope );
} else {
this.alternate.initialise( scope );
this.alternate.initialise( program, scope );
}
}
minify ( code ) {
minify ( code, chars ) {
const testValue = this.test.getValue();

@@ -62,3 +62,3 @@

super.minify( code );
super.minify( code, chars );
} else if ( testValue ) {

@@ -69,3 +69,3 @@ // remove test and alternate

this.consequent.minify( code );
this.consequent.minify( code, chars );
} else {

@@ -75,5 +75,5 @@ // remove test and consequent

this.alternate.minify( code );
this.alternate.minify( code, chars );
}
}
}
import Node from '../Node.js';
export default class DoWhileStatement extends Node {
minify ( code ) {
initialise ( program, scope ) {
program.addWord( 'dowhile' );
super.initialise( program, scope );
}
minify ( code, chars ) {
// special case

@@ -11,2 +16,4 @@ if ( this.body.isEmpty() ) {

else {
this.body.minify( code, chars );
if ( this.body.type === 'BlockStatement' ) {

@@ -23,4 +30,2 @@ code.remove( this.start + 2, this.body.start );

}
this.body.minify( code );
}

@@ -34,4 +39,4 @@

this.test.minify( code );
this.test.minify( code, chars );
}
}

@@ -21,3 +21,3 @@ import Node from '../Node.js';

initialise ( scope ) {
initialise ( program, scope ) {
if ( this.expression.type === 'Literal' || this.expression.getValue() !== UNKNOWN ) {

@@ -28,4 +28,4 @@ // remove side-effect-free statements (TODO others, not just literals)...

super.initialise( scope );
super.initialise( program, scope );
}
}

@@ -12,3 +12,3 @@ import LoopStatement from './shared/LoopStatement.js';

minify ( code ) {
minify ( code, chars ) {
let c = this.start + 3;

@@ -19,3 +19,3 @@

[ this.init, this.test, this.update ].forEach( ( statement, i ) => {
if ( statement && !statement.skip ) {
if ( statement && ( !statement.skip || statement === this.test ) ) {
if ( statement.start > c + replacement.length ) {

@@ -25,3 +25,3 @@ code.overwrite( c, statement.start, replacement );

statement.minify( code );
statement.minify( code, chars );

@@ -39,4 +39,4 @@ c = statement.end;

super.minify( code );
super.minify( code, chars );
}
}

@@ -10,16 +10,17 @@ import FunctionNode from './shared/FunctionNode.js';

if ( this.id ) this.id.initialise( this.scope.parent );
this.program.addWord( 'function' );
if ( this.id ) this.id.initialise( this.program, this.scope.parent );
this.params.forEach( param => {
param.initialise( this.scope );
param.initialise( this.program, this.scope );
});
this.body.initialise( this.scope );
this.body.initialise( this.program, this.scope );
}
initialise ( scope ) {
initialise ( program, scope ) {
if ( scope.parent ) {
// noop — we wait for this declaration to be activated
} else {
this.activate();
this.activate( program );
}
}
}

@@ -8,5 +8,6 @@ import FunctionNode from './shared/FunctionNode.js';

initialise () {
super.initialise( this.scope );
initialise ( program ) {
program.addWord( 'function' ); // TODO only if has function keyword
super.initialise( program, this.scope );
}
}

@@ -15,3 +15,3 @@ import Node from '../Node.js';

attachScope ( scope ) {
attachScope ( program, scope ) {
this.scope = scope;

@@ -36,3 +36,3 @@ }

initialise ( scope ) {
initialise ( program, scope ) {
// special case

@@ -43,2 +43,4 @@ if ( ( this.parent.type === 'FunctionExpression' || this.parent.type === 'ClassExpression' ) && this === this.parent.id ) {

// TODO add global/top-level identifiers to frequency count
if ( this.isReference() ) {

@@ -45,0 +47,0 @@ scope.addReference( this );

@@ -52,7 +52,9 @@ import Node from '../Node.js';

if ( testValue ) return this.consequent.getRightHandSide();
if ( testValue || !this.alternate ) return this.consequent.getRightHandSide();
return this.alternate.getRightHandSide();
}
initialise ( scope ) {
initialise ( program, scope ) {
// TODO add 'if/else' to character frequency, but only if not rewriting as sequence
this.skip = false; // TODO skip if known to be safe

@@ -64,9 +66,9 @@

// initialise everything
this.test.initialise( scope );
this.consequent.initialise( scope );
if ( this.alternate ) this.alternate.initialise( scope );
this.test.initialise( program, scope );
this.consequent.initialise( program, scope );
if ( this.alternate ) this.alternate.initialise( program, scope );
}
else if ( testValue ) { // if ( true ) {...}
this.consequent.initialise( scope );
this.consequent.initialise( program, scope );

@@ -82,3 +84,3 @@ if ( this.alternate && this.alternate.type === 'BlockStatement' ) {

if ( this.alternate ) {
this.alternate.initialise( scope );
this.alternate.initialise( program, scope );
} else {

@@ -98,3 +100,3 @@ this.skip = true;

minify ( code ) {
minify ( code, chars ) {
const testValue = this.test.getValue();

@@ -110,6 +112,6 @@

code.remove( this.start, this.consequent.start );
this.consequent.minify( code );
this.consequent.minify( code, chars );
} else { // if ( false ) {...}
// we know there's an alternate, otherwise we wouldn't be here
this.alternate.minify( code );
this.alternate.minify( code, chars );
code.remove( this.start, this.alternate.start );

@@ -121,3 +123,3 @@ }

this.test.minify( code );
this.test.minify( code, chars );

@@ -145,3 +147,3 @@ // if we're rewriting as &&, test must be higher precedence than 6

if ( this.alternate && !this.alternate.isEmpty() ) {
this.alternate.minify( code );
this.alternate.minify( code, chars );

@@ -212,3 +214,3 @@ if ( this.alternate.type === 'BlockStatement' && this.alternate.body.length === 0 ) {

// don't minify alternate
this.consequent.minify( code );
this.consequent.minify( code, chars );
code.remove( this.consequent.end, this.end );

@@ -235,4 +237,4 @@

this.consequent.minify( code );
if ( this.alternate ) this.alternate.minify( code );
this.consequent.minify( code, chars );
if ( this.alternate ) this.alternate.minify( code, chars );

@@ -239,0 +241,0 @@ if ( this.canSequentialise() ) {

import Node from '../Node.js';
export default class ImportDefaultSpecifier extends Node {
initialise ( scope ) {
initialise ( program, scope ) {
this.local.declaration = this;
scope.addDeclaration( this.local, 'import' );
super.initialise( scope );
super.initialise( program, scope );
}
}
import Node from '../Node.js';
export default class ImportSpecifier extends Node {
initialise ( scope ) {
initialise ( program, scope ) {
this.local.declaration = this;
scope.addDeclaration( this.local, 'import' );
super.initialise( scope );
super.initialise( program, scope );
}
}

@@ -20,2 +20,3 @@ import Array from './shared/Array.js';

import IfStatement from './IfStatement.js';
import ImportDeclaration from './ImportDeclaration.js';
import ImportDefaultSpecifier from './ImportDefaultSpecifier.js';

@@ -68,2 +69,3 @@ import ImportSpecifier from './ImportSpecifier.js';

IfStatement,
ImportDeclaration,
ImportDefaultSpecifier,

@@ -70,0 +72,0 @@ ImportSpecifier,

import Node from '../Node.js';
export default class LabeledStatement extends Node {
minify ( code ) {
getRightHandSide () {
return this.body.getRightHandSide();
}
initialise ( program, scope ) {
program.addWord( this.label.name );
super.initialise( program, scope );
}
minify ( code, chars ) {
// TODO can we mangle labels?
if ( this.body.start > this.label.end + 1 ) {

@@ -14,5 +25,5 @@ code.overwrite( this.label.end, this.body.start, ':' );

} else {
this.body.minify( code );
this.body.minify( code, chars );
}
}
}

@@ -5,3 +5,3 @@ import Node from '../Node.js';

export default class Literal extends Node {
attachScope ( scope ) {
attachScope ( program, scope ) {
if ( this.value === 'use strict' ) {

@@ -27,4 +27,4 @@ const block = this.parent.parent;

initialise () {
// noop
initialise ( program ) {
program.addWord( stringify( this.value ) );
}

@@ -34,9 +34,13 @@

if ( this.value === true || this.value === false ) {
code.overwrite( this.start, this.end, this.value ? '!0' : '!1' );
code.overwrite( this.start, this.end, this.value ? '!0' : '!1', {
contentOnly: true
});
}
else if ( typeof this.value === 'number' ) {
code.overwrite( this.start, this.end, stringify( this.value ) );
code.overwrite( this.start, this.end, stringify( this.value ), {
contentOnly: true
});
}
}
}

@@ -50,3 +50,3 @@ import Node from '../Node.js';

minify ( code ) {
minify ( code, chars ) {
const leftValue = this.left.getValue();

@@ -59,3 +59,3 @@

super.minify( code );
super.minify( code, chars );
}

@@ -66,6 +66,6 @@

code.remove( this.start, this.right.start );
this.right.minify( code );
this.right.minify( code, chars );
} else {
code.remove( this.left.end, this.end );
this.left.minify( code );
this.left.minify( code, chars );
}

@@ -77,6 +77,6 @@ }

code.remove( this.left.end, this.end );
this.left.minify( code );
this.left.minify( code, chars );
} else {
code.remove( this.start, this.right.start );
this.right.minify( code );
this.right.minify( code, chars );
}

@@ -83,0 +83,0 @@ }

import Node from '../Node.js';
import reserved from '../../utils/reserved.js';
import { reservedLookup } from '../../utils/reserved.js';
import { UNKNOWN } from '../../utils/sentinels.js';

@@ -9,3 +9,3 @@ import stringify from '../../utils/stringify.js';

// TODO there's probably a bit more to it than this
return !reserved[ str ] && /^[a-zA-Z_$][a-zA-Z_$0-9]*$/.test( str );
return !reservedLookup[ str ] && /^[a-zA-Z_$][a-zA-Z_$0-9]*$/.test( str );
}

@@ -53,6 +53,11 @@

minify ( code ) {
initialise ( program, scope ) {
if ( !this.computed ) program.addWord( this.property.name );
super.initialise( program, scope );
}
minify ( code, chars ) {
const value = this.getValue();
if ( value !== UNKNOWN && canFold( this, this.parent ) ) {
if ( value && value !== UNKNOWN && canFold( this, this.parent ) ) {
const str = stringify( value );

@@ -66,2 +71,8 @@

// special case — numbers
const objectValue = this.object.getValue();
if ( typeof objectValue === 'number' && objectValue === parseInt( objectValue, 10 ) ) {
this.object.append( code, '.' );
}
if ( this.computed ) {

@@ -87,3 +98,3 @@ const value = this.property.getValue();

this.property.minify( code );
this.property.minify( code, chars );
}

@@ -98,4 +109,4 @@ }

this.object.minify( code );
this.object.minify( code, chars );
}
}

@@ -5,6 +5,11 @@ import Node from '../Node.js';

export default class MethodDefinition extends Node {
minify ( code ) {
minifyPropertyKey( code, this, false );
this.value.minify( code );
initialise ( program, scope ) {
if ( !this.computed ) program.addWord( this.key.name );
super.initialise( program, scope );
}
minify ( code, chars ) {
minifyPropertyKey( code, chars, this, false );
this.value.minify( code, chars );
}
}

@@ -8,3 +8,8 @@ import Node from '../Node.js';

minify ( code ) {
initialise ( program, scope ) {
program.addWord( 'new' );
super.initialise( program, scope );
}
minify ( code, chars ) {
if ( this.arguments.length ) {

@@ -27,4 +32,4 @@ let lastNode = this.callee;

super.minify( code );
super.minify( code, chars );
}
}

@@ -10,3 +10,3 @@ import Node from '../Node.js';

minify ( code ) {
minify ( code, chars ) {
let c = this.start;

@@ -20,4 +20,4 @@

minifyPropertyKey( code, p, true );
p.value.minify( code );
minifyPropertyKey( code, chars, p, true );
p.value.minify( code, chars );

@@ -24,0 +24,0 @@ c = p.end;

import Node from '../Node.js';
export default class ObjectPattern extends Node {
minify ( code ) {
minify ( code, chars ) {
let c = this.start + 1;

@@ -9,3 +9,3 @@ for ( let i = 0; i < this.properties.length; i += 1 ) {

const property = this.properties[i];
property.minify( code );
property.minify( code, chars );

@@ -12,0 +12,0 @@ if ( property.start > c ) code.overwrite( c, property.start, i ? ',' : '' );

@@ -49,2 +49,13 @@ import Node from '../Node.js';

getRightHandSide () {
let node = this;
while ( node.type === 'ParenthesizedExpression' ) {
node = node.expression;
}
if ( shouldRemoveParens( node, this.parent ) ) return node.getRightHandSide();
return node.parent;
}
getPrecedence () {

@@ -58,3 +69,3 @@ return 20;

minify ( code ) {
minify ( code, chars ) {
let start = this.start;

@@ -91,4 +102,4 @@ let end = this.end;

expression.minify( code );
expression.minify( code, chars );
}
}

@@ -8,3 +8,8 @@ import Node from '../Node.js';

export default class ReturnStatement extends Node {
minify ( code ) {
initialise ( program, scope ) {
program.addWord( 'return' );
super.initialise( program, scope );
}
minify ( code, chars ) {
if ( !this.argument ) return;

@@ -28,4 +33,4 @@

this.argument.minify( code );
this.argument.minify( code, chars );
}
}

@@ -22,3 +22,3 @@ import Node from '../../Node.js';

minify ( code ) {
minify ( code, chars ) {
let c = this.start;

@@ -47,4 +47,4 @@

super.minify( code );
super.minify( code, chars );
}
}

@@ -15,3 +15,8 @@ import Node from '../../Node.js';

export default class Class extends Node {
minify ( code ) {
initialise ( program, scope ) {
program.addWord( 'class' );
super.initialise( program, scope );
}
minify ( code, chars ) {
let c = this.start + 5;

@@ -40,4 +45,4 @@

super.minify( code );
super.minify( code, chars );
}
}

@@ -12,3 +12,3 @@ import LoopStatement from './LoopStatement.js';

minify ( code, transforms ) {
minify ( code, chars ) {
if ( this.left.start > this.start + 4 ) {

@@ -26,6 +26,6 @@ code.overwrite( this.start + 3, this.left.start, '(' );

this.left.minify( code );
this.right.minify( code );
super.minify( code, transforms );
this.left.minify( code, chars );
this.right.minify( code, chars );
super.minify( code, chars );
}
}

@@ -28,3 +28,4 @@ import Node from '../../Node.js';

export default class FunctionNode extends Node {
attachScope ( parent ) {
attachScope ( program, parent ) {
this.program = program;
this.scope = new Scope({

@@ -40,6 +41,6 @@ block: false,

if ( this.type === 'FunctionExpression' ) {
this.scope.addDeclaration( this.id, 'function' );
this.scope.addDeclaration( this.id, this.type );
this.scope.addReference( this.id );
} else {
parent.addDeclaration( this.id, 'function' );
parent.addDeclaration( this.id, this.type );
}

@@ -49,3 +50,3 @@ }

this.params.forEach( param => {
param.attachScope( this.scope );
param.attachScope( program, this.scope );

@@ -58,3 +59,3 @@ extractNames( param ).forEach( node => {

this.body.attachScope( this.scope );
this.body.attachScope( program, this.scope );
}

@@ -66,3 +67,5 @@

minify ( code ) {
// TODO `program.addWord('async')` if necessary
minify ( code, chars ) {
let c = this.start;

@@ -99,3 +102,3 @@

const param = this.params[i];
param.minify( code );
param.minify( code, chars );

@@ -111,4 +114,4 @@ if ( param.start > c + 1 ) code.overwrite( c, param.start, i ? ',' : '(' );

this.body.minify( code );
this.body.minify( code, chars );
}
}

@@ -5,3 +5,3 @@ import Node from '../../Node.js';

export default class LoopStatement extends Node {
attachScope ( parent ) {
attachScope ( program, parent ) {
if ( this.hasVariableDeclaration() ) {

@@ -13,14 +13,18 @@ this.scope = new Scope({

super.attachScope( this.scope );
super.attachScope( program, this.scope );
} else {
super.attachScope( parent );
super.attachScope( program, parent );
}
}
initialise ( scope ) {
super.initialise( this.scope || scope );
initialise ( program, scope ) {
program.addWord( 'for' );
if ( this.type === 'ForInStatement' ) program.addWord( 'in' );
else if ( this.type === 'ForOfStatement' ) program.addWord( 'of' );
super.initialise( program, this.scope || scope );
}
minify ( code ) {
if ( this.scope ) this.scope.mangle( code );
minify ( code, chars ) {
if ( this.scope ) this.scope.mangle( code, chars );

@@ -32,5 +36,5 @@ // special case — empty body

} else {
this.body.minify( code );
this.body.minify( code, chars );
}
}
}

@@ -5,3 +5,3 @@ function isAccessor ( property ) {

export default function minifyPropertyKey ( code, property, isObject ) {
export default function minifyPropertyKey ( code, chars, property, isObject ) {
if ( property.shorthand ) return;

@@ -43,3 +43,3 @@

property.key.minify( code );
property.key.minify( code, chars );
}
import Node from '../Node.js';
export default class SwitchCase extends Node {
minify ( code ) {
getRightHandSide () {
if ( this.consequent.length > 0 ) {
return this.consequent[ this.consequent.length - 1 ].getRightHandSide();
}
return this;
}
initialise ( program, scope ) {
program.addWord( this.test ? 'case' : 'default' );
super.initialise( program, scope );
}
minify ( code, chars ) {
let c;
if ( this.test ) {
this.test.minify( code );
this.test.minify( code, chars );

@@ -21,3 +34,3 @@ if ( this.test.start > this.start + 5 ) {

this.consequent.forEach( ( statement, i ) => {
statement.minify( code );
statement.minify( code, chars );

@@ -24,0 +37,0 @@ const separator = i ? ';' : ':'; // TODO can consequents be written as sequences?

@@ -5,4 +5,4 @@ import Node from '../Node.js';

export default class SwitchStatement extends Node {
initialise ( scope ) {
super.initialise( scope );
initialise ( program, scope ) {
super.initialise( program, scope );

@@ -13,8 +13,12 @@ if ( this.cases.length === 0 ) {

}
if ( !this.skip ) {
program.addWord( 'switch' );
}
}
minify ( code ) {
minify ( code, chars ) {
// special (and unlikely!) case — no cases, but a non-removable discriminant
if ( this.cases.length === 0 ) {
this.discriminant.minify( code );
this.discriminant.minify( code, chars );
code.remove( this.start, this.discriminant.start );

@@ -32,5 +36,4 @@ code.remove( this.discriminant.end, this.end );

this.cases.forEach( ( switchCase, i ) => {
if ( switchCase.start > c + ( i ? 1 : 2 ) ) {
code.overwrite( c, switchCase.start, i ? ';' : '){' );
}
code.remove( c, switchCase.start );
switchCase.prepend( code, i > 0 ? ';' : '){' );

@@ -43,5 +46,5 @@ c = switchCase.end;

super.minify( code );
super.minify( code, chars );
}
}
}
import Node from '../Node.js';
export default class TaggedTemplateExpression extends Node {
minify ( code ) {
minify ( code, chars ) {
if ( this.quasi.start > this.tag.end ) code.remove( this.tag.end, this.quasi.start );
this.quasi.minify( code );
this.quasi.minify( code, chars );
}
}

@@ -33,3 +33,3 @@ import Node from '../Node.js';

minify ( code ) {
minify ( code, chars ) {
if ( this.parent.type !== 'TaggedTemplateExpression' ) {

@@ -53,3 +53,3 @@ const value = this.getValue();

if ( typeof value === 'object' ) { // includes both UNKNOWN and known non-primitives
expression.minify( code );
expression.minify( code, chars );

@@ -56,0 +56,0 @@ if ( expression.start > quasi.end + 2 ) {

import Node from '../Node.js';
export default class TryStatement extends Node {
minify ( code ) {
initialise ( program, scope ) {
program.addWord( 'try' );
if ( this.finalizer ) program.addWord( 'finally' );
super.initialise( program, scope );
}
minify ( code, chars ) {
if ( this.block.start > this.start + 3 ) code.remove( this.start + 3, this.block.start );

@@ -21,4 +28,4 @@

super.minify( code );
super.minify( code, chars );
}
}

@@ -29,3 +29,3 @@ import Node from '../Node.js';

minify ( code ) {
minify ( code, chars ) {
const value = this.getValue();

@@ -45,5 +45,5 @@ if ( value !== UNKNOWN ) {

super.minify( code );
super.minify( code, chars );
}
}
}

@@ -9,3 +9,3 @@ import Node from '../Node.js';

initialise ( scope ) {
initialise ( program, scope ) {
if ( this.argument.type === 'Identifier' ) {

@@ -18,4 +18,4 @@ const declaration = scope.findDeclaration( this.argument.name );

super.initialise( scope );
super.initialise( program, scope );
}
}

@@ -11,5 +11,5 @@ import Node from '../Node.js';

export default class VariableDeclaration extends Node {
attachScope ( scope ) {
attachScope ( program, scope ) {
this.declarations.forEach( declarator => {
declarator.attachScope( scope );
declarator.attachScope( program, scope );
});

@@ -20,3 +20,5 @@

initialise ( scope ) {
initialise ( program, scope ) {
// TODO `program.addWord(kind)`, but only if this declaration is included...
let _scope = scope;

@@ -32,5 +34,5 @@ if ( this.kind === 'var' ) while ( _scope.isBlockScope ) _scope = _scope.parent;

// only initialise top-level variables. TODO unless we're in e.g. module mode
declarator.initialise( scope );
declarator.initialise( program, scope );
} else {
if ( declarator.init ) declarator.init.initialise( scope );
if ( declarator.init ) declarator.init.initialise( program, scope );
}

@@ -40,3 +42,3 @@ });

minify ( code ) {
minify ( code, chars ) {
if ( this.collapsed ) return;

@@ -82,3 +84,3 @@

declarator.init.minify( code );
declarator.init.minify( code, chars );

@@ -89,3 +91,3 @@ // we have a situation like `var unused = x()` — need to preserve `x()`

} else {
declarator.minify( code );
declarator.minify( code, chars );

@@ -92,0 +94,0 @@ let separator = needsKeyword ?

@@ -6,3 +6,3 @@ import Node from '../Node.js';

// TODO this can get way more sophisticated
if ( node.type === 'Identifier' || node.type === 'Literal' ) return false;
if ( node.type === 'Identifier' || node.type === 'Literal' || /FunctionExpression/.test( node.type ) ) return false;
return true;

@@ -17,14 +17,16 @@ }

this.skip = this.parent.skip = false;
this.id.initialise( this.scope );
if ( this.init ) this.init.initialise( this.scope );
this.id.initialise( this.program, this.scope );
if ( this.init ) this.init.initialise( this.program, this.scope );
}
attachScope ( scope ) {
attachScope ( program, scope ) {
this.program = program;
this.scope = scope;
const kind = this.parent.kind;
this.id.attachScope( scope );
this.id.attachScope( program, scope );
if ( this.init ) {
this.init.attachScope( scope );
this.init.attachScope( program, scope );

@@ -42,3 +44,3 @@ if ( mightHaveSideEffects( this.init ) ) {

minify ( code ) {
minify ( code, chars ) {
if ( this.init ) {

@@ -48,4 +50,4 @@ if ( this.init.start > this.id.end + 1 ) code.overwrite( this.id.end, this.init.start, '=' );

super.minify( code );
super.minify( code, chars );
}
}

@@ -8,3 +8,8 @@ import Node from '../Node.js';

minify ( code ) {
initialise ( program, scope ) {
program.addWord( 'while' );
super.initialise( program, scope );
}
minify ( code, chars ) {
if ( this.test.start > this.start + 6 ) {

@@ -24,4 +29,4 @@ code.overwrite( this.start + 5, this.test.start, '(' );

super.minify( code );
super.minify( code, chars );
}
}

@@ -7,2 +7,7 @@ import Node from '../Node.js';

}
initialise ( program, scope ) {
program.addWord( 'yield' );
super.initialise( program, scope );
}
}

@@ -1,5 +0,6 @@

let reserved = Object.create( null );
'do if in for let new try var case else enum eval null this true void with await break catch class const false super throw while yield delete export import public return static switch typeof default extends finally package private continue debugger function arguments interface protected implements instanceof'.split( ' ' )
.forEach( word => reserved[ word ] = true );
export const reserved = 'do if in for let new try var case else enum eval null this true void with await break catch class const false super throw while yield delete export import public return static switch typeof default extends finally package private continue debugger function arguments interface protected implements instanceof'.split( ' ' );
export default reserved;
export const reservedLookup = Object.create( null );
reserved.forEach( word => {
reservedLookup[ word ] = true;
});

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is not supported yet

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