Socket
Socket
Sign inDemoInstall

buble

Package Overview
Dependencies
Maintainers
1
Versions
109
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

buble - npm Package Compare versions

Comparing version 0.8.5 to 0.9.0

src/utils/destructure.js

5

CHANGELOG.md
# buble changelog
## 0.9.0
* More complete and robust destructuring support ([#37](https://gitlab.com/Rich-Harris/buble/issues/37), [#43](https://gitlab.com/Rich-Harris/buble/issues/43))
* Correct `this`/`arguments` references inside for-of loop
## 0.8.5

@@ -4,0 +9,0 @@

2

package.json
{
"name": "buble",
"version": "0.8.5",
"version": "0.9.0",
"description": "The blazing fast, batteries-included ES2015 compiler",

@@ -5,0 +5,0 @@ "main": "dist/buble.umd.js",

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

import CompileError from '../utils/CompileError.js';
import destructure from '../utils/destructure.js';

@@ -89,17 +90,3 @@ export default class BlockStatement extends Node {

if ( /Function/.test( this.parent.type ) ) {
// object pattern
if ( transforms.parameterDestructuring ) {
this.transpileObjectPattern( code, introStatementGenerators );
this.transpileArrayPattern( code, introStatementGenerators );
}
// default parameters
if ( transforms.defaultParameter ) {
this.transpileDefaultParameters( code, introStatementGenerators );
}
// rest parameter
if ( transforms.spreadRest ) {
this.transpileRestElement( code, introStatementGenerators, indentation );
}
this.transpileParameters( code, transforms, indentation, introStatementGenerators );
}

@@ -141,2 +128,58 @@

transpileParameters ( code, transforms, indentation, introStatementGenerators ) {
const params = this.parent.params;
params.forEach( param => {
if ( param.type === 'AssignmentPattern' && param.left.type === 'Identifier' ) {
if ( transforms.defaultParameter ) {
introStatementGenerators.push( ( start, prefix, suffix ) => {
const lhs = `${prefix}if ( ${param.left.name} === void 0 ) ${param.left.name}`;
code
.insertRight( param.left.end, `${lhs}` )
.move( param.left.end, param.right.end, start )
.insertLeft( param.right.end, `;${suffix}` );
});
}
}
else if ( param.type === 'RestElement' ) {
if ( transforms.spreadRest ) {
introStatementGenerators.push( ( start, prefix, suffix ) => {
const penultimateParam = params[ params.length - 2 ];
if ( penultimateParam ) {
code.remove( penultimateParam ? penultimateParam.end : param.start, param.end );
} else {
let start = param.start, end = param.end; // TODO https://gitlab.com/Rich-Harris/buble/issues/8
while ( /\s/.test( code.original[ start - 1 ] ) ) start -= 1;
while ( /\s/.test( code.original[ end ] ) ) end += 1;
code.remove( start, end );
}
const name = param.argument.name;
const len = this.scope.createIdentifier( 'len' );
const count = params.length - 1;
if ( count ) {
code.insertLeft( start, `${prefix}var ${name} = [], ${len} = arguments.length - ${count};\n${indentation}while ( ${len}-- > 0 ) ${name}[ ${len} ] = arguments[ ${len} + ${count} ];${suffix}` );
} else {
code.insertLeft( start, `${prefix}var ${name} = [], ${len} = arguments.length;\n${indentation}while ( ${len}-- ) ${name}[ ${len} ] = arguments[ ${len} ];${suffix}` );
}
});
}
}
else if ( param.type !== 'Identifier' ) {
if ( transforms.parameterDestructuring ) {
const ref = this.scope.createIdentifier( 'ref' );
destructure( code, this.scope, param, ref, introStatementGenerators );
code.insertLeft( param.start, ref );
}
}
});
}
transpileBlockScopedIdentifiers ( code ) {

@@ -161,2 +204,3 @@ Object.keys( this.scope.blockScopedDeclarations ).forEach( name => {

declaration.name = outerAlias;
code.overwrite( declaration.node.start, declaration.node.end, outerAlias, true );

@@ -187,2 +231,3 @@ forStatement.aliases[ name ] = {

declaration.name = alias;
code.overwrite( declaration.node.start, declaration.node.end, alias, true );

@@ -198,142 +243,2 @@ for ( const identifier of declaration.instances ) {

}
transpileDefaultParameters ( code, introStatementGenerators ) {
this.parent.params.filter( param => param.type === 'AssignmentPattern' ).forEach( param => {
introStatementGenerators.push( ( start, prefix, suffix ) => {
const lhs = `${prefix}if ( ${param.left.name} === void 0 ) ${param.left.name}`;
code
.insertRight( param.left.end, `${lhs}` )
.move( param.left.end, param.right.end, start )
.insertLeft( param.right.end, `;${suffix}` );
});
});
}
transpileObjectPattern ( code, introStatementGenerators ) {
const params = this.parent.params;
const objectPatterns = params.filter( param => param.type === 'ObjectPattern' );
const assignmentPatterns = params.filter( param => param.type === 'AssignmentPattern' )
.map( exp => exp.left ).filter( param => param.type === 'ObjectPattern' );
[].concat(objectPatterns, assignmentPatterns).forEach( param => {
const ref = this.scope.createIdentifier( 'ref' );
param.name = ref;
code.insertRight( param.start, ref );
let c = param.start;
param.properties.forEach( prop => {
code.remove( c, prop.value.start );
const key = prop.key.name;
if ( prop.value.type === 'Identifier' ) {
code.remove( prop.value.start, prop.value.end );
const value = prop.value.name;
const declaration = this.scope.findDeclaration( value );
if ( declaration.instances.length === 1 ) {
const instance = declaration.instances[0];
code.overwrite( instance.start, instance.end, `${ref}.${key}` );
} else {
introStatementGenerators.push( ( start, prefix, suffix ) => {
code.insertLeft( start, `${prefix}var ${value} = ${ref}.${key};${suffix}` );
});
}
}
else if ( prop.value.type === 'AssignmentPattern' ) {
introStatementGenerators.push( ( start, prefix, suffix ) => {
code.remove( prop.value.start, prop.value.right.start );
const value = prop.value.left.name;
code
.insertRight( prop.value.right.start, `${prefix}var ${ref}_${key} = ${ref}.${key}, ${value} = ${ref}_${key} === void 0 ? ` )
.insertLeft( prop.value.right.end, ` : ${ref}_${key};${suffix}` )
.move( prop.value.right.start, prop.value.right.end, start );
});
}
else {
throw new CompileError( prop, `Compound destructuring is not supported` );
}
c = prop.value.end;
});
code.remove( c, param.end );
});
}
transpileArrayPattern ( code, introStatementGenerators ) {
// array pattern. TODO dry this out
this.parent.params.filter( param => param.type === 'ArrayPattern' ).forEach( param => {
const ref = this.scope.createIdentifier( 'ref' );
code.insertRight( param.start, ref );
let c = param.start;
param.elements.forEach( ( element, i ) => {
code.remove( c, element.start );
if ( element.type === 'Identifier' ) {
code.remove( element.start, element.end );
introStatementGenerators.push( ( start, prefix, suffix ) => {
code.insertLeft( start, `${prefix}var ${element.name} = ${ref}[${i}];${suffix}` );
});
} else if ( element.type === 'AssignmentPattern' ) {
introStatementGenerators.push( ( start, prefix, suffix ) => {
code.remove( element.start, element.right.start );
const name = element.left.name;
code
.insertRight( element.right.start, `${prefix}var ${ref}_${i} = ref[${i}], ${name} = ref_${i} === void 0 ? ` )
.insertLeft( element.right.end, ` : ref_${i};${suffix}` )
.move( element.right.start, element.right.end, start );
});
}
else {
throw new CompileError( element, `Compound destructuring is not supported` );
}
c = element.end;
});
code.remove( c, param.end );
});
}
transpileRestElement ( code, introStatementGenerators, indentation ) {
const params = this.parent.params;
const lastParam = params[ params.length - 1 ];
if ( lastParam && lastParam.type === 'RestElement' ) {
introStatementGenerators.push( ( start, prefix, suffix ) => {
const penultimateParam = params[ params.length - 2 ];
if ( penultimateParam ) {
code.remove( penultimateParam ? penultimateParam.end : lastParam.start, lastParam.end );
} else {
let start = lastParam.start, end = lastParam.end; // TODO https://gitlab.com/Rich-Harris/buble/issues/8
while ( /\s/.test( code.original[ start - 1 ] ) ) start -= 1;
while ( /\s/.test( code.original[ end ] ) ) end += 1;
code.remove( start, end );
}
const name = lastParam.argument.name;
const len = this.scope.createIdentifier( 'len' );
const count = params.length - 1;
if ( count ) {
code.insertLeft( start, `${prefix}var ${name} = [], ${len} = arguments.length - ${count};\n${indentation}while ( ${len}-- > 0 ) ${name}[ ${len} ] = arguments[ ${len} + ${count} ];${suffix}` );
} else {
code.insertLeft( start, `${prefix}var ${name} = [], ${len} = arguments.length;\n${indentation}while ( ${len}-- ) ${name}[ ${len} ] = arguments[ ${len} ];${suffix}` );
}
});
}
}
}

@@ -8,8 +8,8 @@ export default function extractNames ( node ) {

const extractors = {
Identifier ( names, param ) {
names.push( param.name );
Identifier ( names, node ) {
names.push( node );
},
ObjectPattern ( names, param ) {
for ( const prop of param.properties ) {
ObjectPattern ( names, node ) {
for ( const prop of node.properties ) {
extractors[ prop.value.type ]( names, prop.value );

@@ -19,4 +19,4 @@ }

ArrayPattern ( names, param ) {
for ( const element of param.elements ) {
ArrayPattern ( names, node ) {
for ( const element of node.elements ) {
if ( element ) extractors[ element.type ]( names, element );

@@ -26,9 +26,9 @@ }

RestElement ( names, param ) {
extractors[ param.argument.type ]( names, param.argument );
RestElement ( names, node ) {
extractors[ node.argument.type ]( names, node.argument );
},
AssignmentPattern ( names, param ) {
extractors[ param.left.type ]( names, param.left );
AssignmentPattern ( names, node ) {
extractors[ node.left.type ]( names, node.left );
}
};
import wrap from './wrap.js';
import keys from './keys.js';
// used for debugging, without the noise created by
// circular references
function toJSON ( node ) {
var obj = {};
Object.keys( node ).forEach( key => {
if ( key === 'parent' || key === 'program' || key === 'keys' || key === '__wrapped' ) return;
if ( Array.isArray( node[ key ] ) ) {
obj[ key ] = node[ key ].map( toJSON );
} else if ( node[ key ] && node[ key ].toJSON ) {
obj[ key ] = node[ key ].toJSON();
} else {
obj[ key ] = node[ key ];
}
});
return obj;
}
export default class Node {

@@ -86,4 +106,8 @@ constructor ( raw, parent ) {

toJSON () {
return toJSON( this );
}
toString () {
return this.program.magicString.slice( this.start, this.end );
return this.program.magicString.original.slice( this.start, this.end );
}

@@ -90,0 +114,0 @@

@@ -25,10 +25,11 @@ import extractNames from './extractNames.js';

addDeclaration ( node, kind ) {
for ( const name of extractNames( node ) ) {
for ( const identifier of extractNames( node ) ) {
const name = identifier.name;
const existingDeclaration = this.declarations[ name ];
if ( existingDeclaration && ( letConst.test( kind ) || letConst.test( existingDeclaration.kind ) ) ) {
// TODO warn about double var declarations?
throw new CompileError( node, `${name} is already declared` );
throw new CompileError( identifier, `${name} is already declared` );
}
const declaration = { name, node, kind, instances: [] };
const declaration = { name, node: identifier, kind, instances: [] };
this.declarations[ name ] = declaration;

@@ -35,0 +36,0 @@

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

const arrowFunction = this.findNearest( 'ArrowFunctionExpression' );
const loop = this.findNearest( /(?:For|While)Statement/ );
const loop = this.findNearest( /(?:For(?:In|Of)?|While)Statement/ );

@@ -29,3 +29,3 @@ if ( arrowFunction && arrowFunction.depth > lexicalBoundary.depth ) {

if ( loop && loop.depth > lexicalBoundary.depth ) {
if ( loop && loop.body.contains( this ) && loop.depth > lexicalBoundary.depth ) {
this.alias = lexicalBoundary.getArgumentsAlias();

@@ -32,0 +32,0 @@ }

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

const arrowFunction = this.findNearest( 'ArrowFunctionExpression' );
const loop = this.findNearest( /(?:For|While)Statement/ );
const loop = this.findNearest( /(?:For(?:In|Of)?|While)Statement/ );

@@ -15,3 +15,3 @@ if ( arrowFunction && arrowFunction.depth > lexicalBoundary.depth ) {

if ( loop && loop.depth > lexicalBoundary.depth ) {
if ( loop && loop.body.contains( this ) && loop.depth > lexicalBoundary.depth ) {
this.alias = lexicalBoundary.getThisAlias();

@@ -18,0 +18,0 @@ }

import Node from '../Node.js';
import destructure from '../../utils/destructure.js';

@@ -10,8 +11,77 @@ export default class VariableDeclaration extends Node {

transpile ( code, transforms ) {
if ( transforms.letConst && this.kind !== 'var' ) {
code.overwrite( this.start, this.start + this.kind.length, 'var', true );
const i0 = this.getIndentation();
let kind = this.kind;
if ( transforms.letConst && kind !== 'var' ) {
kind = 'var';
code.overwrite( this.start, this.start + this.kind.length, kind, true );
}
this.declarations.forEach( declarator => declarator.transpile( code, transforms ) );
if ( transforms.destructuring ) {
let c = this.start;
let lastDeclaratorIsPattern;
this.declarations.forEach( ( declarator, i ) => {
if ( declarator.id.type === 'Identifier' ) {
if ( i > 0 && this.declarations[ i - 1 ].id.type !== 'Identifier' ) {
code.overwrite( c, declarator.id.start, `var ` );
}
} else {
if ( i === 0 ) {
code.remove( c, declarator.id.start );
} else {
code.overwrite( c, declarator.id.start, `;\n${i0}` );
}
const simple = declarator.init.type === 'Identifier' && !declarator.init.rewritten;
const i0 = declarator.getIndentation();
const name = simple ? declarator.init.name : declarator.findScope( true ).createIdentifier( 'ref' );
let c = declarator.start;
let statementGenerators = [];
if ( simple ) {
code.remove( declarator.id.end, declarator.end );
} else {
statementGenerators.push( ( start, prefix, suffix ) => {
code.insertRight( declarator.id.end, `var ${name}` );
code.insertLeft( declarator.init.end, `;${suffix}` );
code.move( declarator.id.end, declarator.end, start );
});
}
destructure( code, declarator.findScope( true ), declarator.id, name, statementGenerators );
let suffix = `\n${i0}`;
statementGenerators.forEach( ( fn, j ) => {
if ( i === this.declarations.length - 1 && j === statementGenerators.length - 1 ) {
suffix = '';
}
fn( declarator.start, ``, suffix );
});
}
if ( declarator.init ) {
declarator.init.transpile( code, transforms );
}
c = declarator.end;
lastDeclaratorIsPattern = declarator.id.type !== 'Identifier';
});
if ( lastDeclaratorIsPattern ) {
code.remove( c, this.end );
}
}
else {
this.declarations.forEach( declarator => {
if ( declarator.init ) declarator.init.transpile( code, transforms );
});
}
}
}

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

initialise ( transforms ) {
this.isObjectPattern = this.id.type === 'ObjectPattern';
// disallow compound destructuring, for now at least
if ( /Pattern/.test( this.id.type ) ) {
this.id[ this.isObjectPattern ? 'properties' : 'elements' ].forEach( node => {
if ( node && /Pattern/.test( this.isObjectPattern ? node.value.type : node.type ) ) {
throw new CompileError( node.value, 'Compound destructuring is not supported' );
}
});
}
let kind = this.parent.kind;

@@ -26,45 +15,2 @@ if ( kind === 'let' && this.parent.parent.type === 'ForStatement' ) {

}
transpile ( code, transforms ) {
if ( transforms.destructuring && this.id.type !== 'Identifier' ) {
const simple = this.init.type === 'Identifier' && !this.init.rewritten;
const props = this.isObjectPattern ? this.id.properties : this.id.elements;
const i0 = this.getIndentation();
const name = simple ? this.init.name : this.findScope( true ).createIdentifier( 'ref' );
let c = this.start;
let first = simple;
if ( simple ) {
code.remove( this.id.end, this.end );
} else {
code.insertRight( this.id.end, `${name}` );
code.move( this.id.end, this.end, c );
}
props.forEach( ( property, i ) => {
if ( property ) {
const id = this.isObjectPattern ? property.value : property;
const rhs = this.isObjectPattern ? `${name}.${property.key.name}` : `${name}[${i}]`;
let start = first ? '' : 'var ';
if ( !first ) start = `;\n${i0}${start}`;
code.insertRight( id.start, start );
code.move( id.start, id.end, this.start );
code.insertLeft( id.end, ` = ${rhs}` );
code.remove( c, id.start );
c = property.end;
first = false;
}
});
code.remove( c, this.id.end );
}
super.transpile( code, transforms );
}
}

@@ -14,2 +14,4 @@ export default function isReference ( node, parent ) {

if ( parent.type === 'VariableDeclarator' ) return node === parent.init;
// TODO is this right?

@@ -20,4 +22,9 @@ if ( parent.type === 'MemberExpression' || parent.type === 'MethodDefinition' ) {

if ( parent.type === 'ArrayPattern' ) return false;
// disregard the `bar` in `{ bar: foo }`, but keep it in `{ [bar]: foo }`
if ( parent.type === 'Property' ) return parent.computed || node === parent.value;
if ( parent.type === 'Property' ) {
if ( parent.parent.type === 'ObjectPattern' ) return false;
return parent.computed || node === parent.value;
}

@@ -24,0 +31,0 @@ // disregard the `bar` in `class Foo { bar () {...} }`

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