Comparing version 0.13.2 to 0.14.0
# buble changelog | ||
## 0.14.0 | ||
* Always wrap block-less bodies in curlies ([#110](https://gitlab.com/Rich-Harris/buble/issues/110), [#117](https://gitlab.com/Rich-Harris/buble/issues/117), [!80](https://gitlab.com/Rich-Harris/buble/merge_requests/80)) | ||
* Make sure block-scoped variables in loops have an initializer ([#124](https://gitlab.com/Rich-Harris/buble/issues/124)) | ||
* Destructuring assignments ([!82](https://gitlab.com/Rich-Harris/buble/merge_requests/82)) | ||
* Support string literals in object destructuring ([!81](https://gitlab.com/Rich-Harris/buble/merge_requests/81)) | ||
* Standalone arrow function expression statements ([!79](https://gitlab.com/Rich-Harris/buble/merge_requests/79)) | ||
## 0.13.2 | ||
@@ -4,0 +12,0 @@ |
{ | ||
"name": "buble", | ||
"version": "0.13.2", | ||
"version": "0.14.0", | ||
"description": "The blazing fast, batteries-included ES2015 compiler", | ||
@@ -23,3 +23,4 @@ "main": "dist/buble.umd.js", | ||
"pretest:node": "npm run build:umd", | ||
"prepublish": "npm test && npm run build:es" | ||
"prepublish": "npm test && npm run build:es", | ||
"lint": "eslint src" | ||
}, | ||
@@ -26,0 +27,0 @@ "bin": { |
@@ -1,5 +0,4 @@ | ||
import wrap from './wrap.js'; | ||
import './wrap.js'; // TODO necessary for ordering. sort it out | ||
import Node from './Node.js'; | ||
import Scope from './Scope.js'; | ||
import CompileError from '../utils/CompileError.js'; | ||
import destructure from '../utils/destructure.js'; | ||
@@ -93,3 +92,3 @@ | ||
while ( true ) { | ||
while ( true ) { // eslint-disable-line no-constant-condition | ||
c += 1; | ||
@@ -96,0 +95,0 @@ const char = source[c]; |
@@ -25,3 +25,9 @@ import Node from '../Node.js'; | ||
// add function | ||
code.insertRight( this.start, 'function ' ); | ||
if ( this.parent && this.parent.type === 'ExpressionStatement' ) { | ||
// standalone expression statement | ||
code.insertRight( this.start, '(function' ); | ||
code.insertRight( this.end, ')' ); | ||
} else { | ||
code.insertRight( this.start, 'function ' ); | ||
} | ||
} | ||
@@ -28,0 +34,0 @@ |
@@ -19,6 +19,2 @@ import Node from '../Node.js'; | ||
if ( /Pattern/.test( this.left.type ) ) { | ||
throw new CompileError( this.left, 'Destructuring assignments are not currently supported. Coming soon!' ); | ||
} | ||
super.initialise( transforms ); | ||
@@ -29,108 +25,226 @@ } | ||
if ( this.operator === '**=' && transforms.exponentiation ) { | ||
const scope = this.findScope( false ); | ||
const getAlias = name => { | ||
const declaration = scope.findDeclaration( name ); | ||
return declaration ? declaration.name : name; | ||
}; | ||
this.transpileExponentiation( code, transforms ); | ||
} | ||
// first, the easy part – `**=` -> `=` | ||
let charIndex = this.left.end; | ||
while ( code.original[ charIndex ] !== '*' ) charIndex += 1; | ||
code.remove( charIndex, charIndex + 2 ); | ||
else if ( /Pattern/.test( this.left.type ) && transforms.destructuring ) { | ||
this.transpileDestructuring( code, transforms ); | ||
} | ||
// how we do the next part depends on a number of factors – whether | ||
// this is a top-level statement, and whether we're updating a | ||
// simple or complex reference | ||
let base; | ||
super.transpile( code, transforms ); | ||
} | ||
let left = this.left; | ||
while ( left.type === 'ParenthesizedExpression' ) left = left.expression; | ||
transpileDestructuring ( code ) { | ||
const scope = this.findScope( true ); | ||
const value = scope.createIdentifier( 'assign' ); | ||
const temporaries = [value]; | ||
if ( left.type === 'Identifier' ) { | ||
base = getAlias( left.name ); | ||
} else if ( left.type === 'MemberExpression' ) { | ||
let object; | ||
let needsObjectVar = false; | ||
let property; | ||
let needsPropertyVar = false; | ||
const start = this.start; | ||
const statement = this.findNearest( /(?:Statement|Declaration)$/ ); | ||
const i0 = statement.getIndentation(); | ||
// We need to pick out some elements from the original code, | ||
// interleaved with generated code. These helpers are used to | ||
// easily do that while keeping the order of the output | ||
// predictable. | ||
let text = ''; | ||
function use ( node ) { | ||
code.insertRight( node.start, text ); | ||
code.move( node.start, node.end, start ); | ||
text = ''; | ||
} | ||
function write ( string ) { | ||
text += string; | ||
} | ||
if ( left.property.type === 'Identifier' ) { | ||
property = left.computed ? getAlias( left.property.name ) : left.property.name; | ||
} else { | ||
property = scope.createIdentifier( 'property' ); | ||
needsPropertyVar = true; | ||
write( `(${value} = ` ); | ||
use( this.right ); | ||
// Walk `pattern`, generating code that assigns the value in | ||
// `ref` to it. When `mayDuplicate` is false, the function | ||
// must take care to only output `ref` once. | ||
function destructure ( pattern, ref, mayDuplicate ) { | ||
if ( pattern.type === 'Identifier' || pattern.type === 'MemberExpression' ) { | ||
write( ', ' ); | ||
use( pattern ); | ||
write( ` = ${ref}` ); | ||
} | ||
else if ( pattern.type === 'AssignmentPattern' ) { | ||
if ( pattern.left.type === 'Identifier' ) { | ||
const target = pattern.left.name; | ||
let source = ref; | ||
if ( !mayDuplicate ) { | ||
write( `, ${target} = ${ref}` ); | ||
source = target; | ||
} | ||
write( `, ${target} = ${source} === void 0 ? ` ); | ||
use( pattern.right ); | ||
write( ` : ${source}` ); | ||
} | ||
else { | ||
const target = scope.createIdentifier( 'temp' ); | ||
let source = ref; | ||
temporaries.push( target ); | ||
if ( !mayDuplicate ) { | ||
write( `, ${target} = ${ref}` ); | ||
source = target; | ||
} | ||
write( `, ${target} = ${source} === void 0 ? ` ); | ||
use( pattern.right ); | ||
write( ` : ${source}` ); | ||
destructure( pattern.left, target, true ); | ||
} | ||
} | ||
if ( left.object.type === 'Identifier' ) { | ||
object = getAlias( left.object.name ); | ||
} else { | ||
object = scope.createIdentifier( 'object' ); | ||
needsObjectVar = true; | ||
else if ( pattern.type === 'ArrayPattern' ) { | ||
const elements = pattern.elements; | ||
if ( elements.length === 1 ) { | ||
destructure( elements[0], `${ref}[0]`, false ); | ||
} | ||
if ( left.start === statement.start ) { | ||
if ( needsObjectVar && needsPropertyVar ) { | ||
code.insertRight( statement.start, `var ${object} = ` ); | ||
code.overwrite( left.object.end, left.property.start, `;\n${i0}var ${property} = ` ); | ||
code.overwrite( left.property.end, left.end, `;\n${i0}${object}[${property}]` ); | ||
else { | ||
if ( !mayDuplicate ) { | ||
const temp = scope.createIdentifier( 'array' ); | ||
temporaries.push( temp ); | ||
write( `, ${temp} = ${ref}` ); | ||
ref = temp; | ||
} | ||
elements.forEach( ( element, i ) => { | ||
if ( element ) destructure( element, `${ref}[${i}]`, false ); | ||
} ); | ||
} | ||
} | ||
else if ( needsObjectVar ) { | ||
code.insertRight( statement.start, `var ${object} = ` ); | ||
code.insertLeft( left.object.end, `;\n${i0}` ); | ||
code.insertLeft( left.object.end, object ); | ||
else if ( pattern.type === 'ObjectPattern' ) { | ||
const props = pattern.properties; | ||
if ( props.length == 1 ) { | ||
destructure ( props[0].value, `${ref}.${props[0].key.name}`, false ); | ||
} | ||
else { | ||
if ( !mayDuplicate ) { | ||
const temp = scope.createIdentifier( 'obj' ); | ||
temporaries.push( temp ); | ||
write( `, ${temp} = ${ref}` ); | ||
ref = temp; | ||
} | ||
props.forEach( prop => { | ||
destructure( prop.value, `${ref}.${prop.key.name}`, false ); | ||
} ); | ||
} | ||
} | ||
else if ( needsPropertyVar ) { | ||
code.insertRight( left.property.start, `var ${property} = ` ); | ||
code.insertLeft( left.property.end, `;\n${i0}` ); | ||
code.move( left.property.start, left.property.end, this.start ); | ||
else { | ||
throw new Error( `Unexpected node type in destructuring assignment (${pattern.type})` ); | ||
} | ||
} | ||
destructure( this.left, value, true ); | ||
code.insertLeft( left.object.end, `[${property}]` ); | ||
code.remove( left.object.end, left.property.start ); | ||
code.remove( left.property.end, left.end ); | ||
} | ||
code.insertRight( start, text + ')' ); | ||
code.remove( start, this.right.start ); | ||
const statement = this.findNearest( /(?:Statement|Declaration)$/ ); | ||
code.insertLeft( statement.start, `var ${temporaries.join( ', ' )};\n${statement.getIndentation()}` ); | ||
} | ||
transpileExponentiation ( code ) { | ||
const scope = this.findScope( false ); | ||
const getAlias = name => { | ||
const declaration = scope.findDeclaration( name ); | ||
return declaration ? declaration.name : name; | ||
}; | ||
// first, the easy part – `**=` -> `=` | ||
let charIndex = this.left.end; | ||
while ( code.original[ charIndex ] !== '*' ) charIndex += 1; | ||
code.remove( charIndex, charIndex + 2 ); | ||
// how we do the next part depends on a number of factors – whether | ||
// this is a top-level statement, and whether we're updating a | ||
// simple or complex reference | ||
let base; | ||
let left = this.left; | ||
while ( left.type === 'ParenthesizedExpression' ) left = left.expression; | ||
if ( left.type === 'Identifier' ) { | ||
base = getAlias( left.name ); | ||
} else if ( left.type === 'MemberExpression' ) { | ||
let object; | ||
let needsObjectVar = false; | ||
let property; | ||
let needsPropertyVar = false; | ||
const statement = this.findNearest( /(?:Statement|Declaration)$/ ); | ||
const i0 = statement.getIndentation(); | ||
if ( left.property.type === 'Identifier' ) { | ||
property = left.computed ? getAlias( left.property.name ) : left.property.name; | ||
} else { | ||
property = scope.createIdentifier( 'property' ); | ||
needsPropertyVar = true; | ||
} | ||
if ( left.object.type === 'Identifier' ) { | ||
object = getAlias( left.object.name ); | ||
} else { | ||
object = scope.createIdentifier( 'object' ); | ||
needsObjectVar = true; | ||
} | ||
if ( left.start === statement.start ) { | ||
if ( needsObjectVar && needsPropertyVar ) { | ||
code.insertRight( statement.start, `var ${object} = ` ); | ||
code.overwrite( left.object.end, left.property.start, `;\n${i0}var ${property} = ` ); | ||
code.overwrite( left.property.end, left.end, `;\n${i0}${object}[${property}]` ); | ||
} | ||
else { | ||
let declarators = []; | ||
if ( needsObjectVar ) declarators.push( object ); | ||
if ( needsPropertyVar ) declarators.push( property ); | ||
code.insertRight( statement.start, `var ${declarators.join( ', ' )};\n${i0}` ); | ||
else if ( needsObjectVar ) { | ||
code.insertRight( statement.start, `var ${object} = ` ); | ||
code.insertLeft( left.object.end, `;\n${i0}` ); | ||
code.insertLeft( left.object.end, object ); | ||
} | ||
if ( needsObjectVar && needsPropertyVar ) { | ||
code.insertRight( left.start, `( ${object} = ` ); | ||
code.overwrite( left.object.end, left.property.start, `, ${property} = ` ); | ||
code.overwrite( left.property.end, left.end, `, ${object}[${property}]` ); | ||
} | ||
else if ( needsPropertyVar ) { | ||
code.insertRight( left.property.start, `var ${property} = ` ); | ||
code.insertLeft( left.property.end, `;\n${i0}` ); | ||
code.move( left.property.start, left.property.end, this.start ); | ||
else if ( needsObjectVar ) { | ||
code.insertRight( left.start, `( ${object} = ` ); | ||
code.insertLeft( left.object.end, `, ${object}` ); | ||
} | ||
code.insertLeft( left.object.end, `[${property}]` ); | ||
code.remove( left.object.end, left.property.start ); | ||
code.remove( left.property.end, left.end ); | ||
} | ||
} | ||
else if ( needsPropertyVar ) { | ||
code.insertRight( left.property.start, `( ${property} = ` ); | ||
code.insertLeft( left.property.end, `, ` ); | ||
code.move( left.property.start, left.property.end, left.start ); | ||
else { | ||
let declarators = []; | ||
if ( needsObjectVar ) declarators.push( object ); | ||
if ( needsPropertyVar ) declarators.push( property ); | ||
code.insertRight( statement.start, `var ${declarators.join( ', ' )};\n${i0}` ); | ||
code.overwrite( left.object.end, left.property.start, `[${property}]` ); | ||
code.remove( left.property.end, left.end ); | ||
} | ||
if ( needsObjectVar && needsPropertyVar ) { | ||
code.insertRight( left.start, `( ${object} = ` ); | ||
code.overwrite( left.object.end, left.property.start, `, ${property} = ` ); | ||
code.overwrite( left.property.end, left.end, `, ${object}[${property}]` ); | ||
} | ||
code.insertLeft( this.end, ` )` ); | ||
else if ( needsObjectVar ) { | ||
code.insertRight( left.start, `( ${object} = ` ); | ||
code.insertLeft( left.object.end, `, ${object}` ); | ||
} | ||
base = object + ( left.computed || needsPropertyVar ? `[${property}]` : `.${property}` ); | ||
else if ( needsPropertyVar ) { | ||
code.insertRight( left.property.start, `( ${property} = ` ); | ||
code.insertLeft( left.property.end, `, ` ); | ||
code.move( left.property.start, left.property.end, left.start ); | ||
code.overwrite( left.object.end, left.property.start, `[${property}]` ); | ||
code.remove( left.property.end, left.end ); | ||
} | ||
code.insertLeft( this.end, ` )` ); | ||
} | ||
code.insertRight( this.right.start, `Math.pow( ${base}, ` ); | ||
code.insertLeft( this.right.end, ` )` ); | ||
base = object + ( left.computed || needsPropertyVar ? `[${property}]` : `.${property}` ); | ||
} | ||
super.transpile( code, transforms ); | ||
code.insertRight( this.right.start, `Math.pow( ${base}, ` ); | ||
code.insertLeft( this.right.end, ` )` ); | ||
} | ||
} |
@@ -6,3 +6,3 @@ import Node from '../Node.js'; | ||
export default class BreakStatement extends Node { | ||
initialise ( transforms ) { | ||
initialise () { | ||
const loop = this.findNearest( loopStatement ); | ||
@@ -17,3 +17,3 @@ const switchCase = this.findNearest( 'SwitchCase' ); | ||
transpile ( code, transforms ) { | ||
transpile ( code ) { | ||
if ( this.loop && this.loop.shouldRewriteAsFunction ) { | ||
@@ -20,0 +20,0 @@ if ( this.label ) throw new CompileError( this, 'Labels are not currently supported in a loop with locally-scoped variables' ); |
@@ -6,3 +6,3 @@ import Node from '../Node.js'; | ||
export default class ContinueStatement extends Node { | ||
transpile ( code, transforms ) { | ||
transpile ( code ) { | ||
const loop = this.findNearest( loopStatement ); | ||
@@ -9,0 +9,0 @@ if ( loop.shouldRewriteAsFunction ) { |
@@ -38,3 +38,3 @@ import Node from '../Node.js'; | ||
transpile ( code, transforms ) { | ||
transpile ( code ) { | ||
if ( this.alias ) { | ||
@@ -41,0 +41,0 @@ code.overwrite( this.start, this.end, this.alias, true ); |
@@ -19,2 +19,3 @@ import ArrayExpression from './ArrayExpression.js'; | ||
import Identifier from './Identifier.js'; | ||
import IfStatement from './IfStatement.js'; | ||
import ImportDeclaration from './ImportDeclaration.js'; | ||
@@ -66,2 +67,3 @@ import ImportDefaultSpecifier from './ImportDefaultSpecifier.js'; | ||
Identifier, | ||
IfStatement, | ||
ImportDeclaration, | ||
@@ -68,0 +70,0 @@ ImportDefaultSpecifier, |
@@ -11,3 +11,3 @@ import Node from '../Node.js'; | ||
// tag without value | ||
code.overwrite( this.name.start, this.name.end, `${this.name.name}: true`) | ||
code.overwrite( this.name.start, this.name.end, `${this.name.name}: true` ); | ||
} | ||
@@ -14,0 +14,0 @@ |
@@ -8,3 +8,3 @@ import Node from '../Node.js'; | ||
export default class JSXClosingElement extends Node { | ||
transpile ( code, transforms ) { | ||
transpile ( code ) { | ||
let spaceBeforeParen = true; | ||
@@ -11,0 +11,0 @@ |
@@ -90,3 +90,10 @@ import Node from '../Node.js'; | ||
code.overwrite( moveStart, prop.start, isSimpleAssignment ? `;\n${i0}${name}` : `, ${name}` ); | ||
const propId = isSimpleAssignment ? `;\n${i0}${name}` : `, ${name}`; | ||
if (moveStart < prop.start) { | ||
code.overwrite( moveStart, prop.start, propId ); | ||
} else { | ||
code.insertRight( prop.start, propId ); | ||
} | ||
let c = prop.key.end; | ||
@@ -93,0 +100,0 @@ while ( code.original[c] !== ']' ) c += 1; |
import Node from '../../Node.js'; | ||
import extractNames from '../../extractNames.js'; | ||
@@ -46,2 +45,6 @@ export default class LoopStatement extends Node { | ||
transpile ( code, transforms ) { | ||
const needsBlock = this.type != 'ForOfStatement' && ( | ||
this.body.type !== 'BlockStatement' | ||
|| this.body.type === 'BlockStatement' && this.body.synthetic ); | ||
if ( this.shouldRewriteAsFunction ) { | ||
@@ -82,2 +85,5 @@ const i0 = this.getIndentation(); | ||
} | ||
} else if ( needsBlock ) { | ||
code.insertLeft( this.body.start, '{ ' ); | ||
code.insertRight( this.body.end, ' }' ); | ||
} | ||
@@ -84,0 +90,0 @@ |
import Node from '../Node.js'; | ||
import reserved from '../../utils/reserved.js'; | ||
@@ -4,0 +3,0 @@ export default class SpreadProperty extends Node { |
import Node from '../Node.js'; | ||
export default class TemplateElement extends Node { | ||
initialise ( transforms ) { | ||
initialise () { | ||
this.program.templateElements.push( this ); | ||
} | ||
} |
@@ -21,3 +21,3 @@ import Node from '../Node.js'; | ||
transpile ( code, transforms ) { | ||
transpile ( code ) { | ||
if ( this.alias ) { | ||
@@ -24,0 +24,0 @@ code.overwrite( this.start, this.end, this.alias, true ); |
@@ -69,5 +69,3 @@ import Node from '../Node.js'; | ||
if ( declarator.init ) { | ||
declarator.init.transpile( code, transforms ); | ||
} | ||
declarator.transpile( code, transforms ); | ||
@@ -85,7 +83,6 @@ c = declarator.end; | ||
this.declarations.forEach( declarator => { | ||
if ( declarator.init ) declarator.init.transpile( code, transforms ); | ||
declarator.transpile( code, transforms ); | ||
}); | ||
} | ||
} | ||
} |
import Node from '../Node.js'; | ||
import CompileError from '../../utils/CompileError.js'; | ||
@@ -14,2 +13,13 @@ export default class VariableDeclarator extends Node { | ||
} | ||
transpile ( code, transforms ) { | ||
if ( !this.init && transforms.letConst && this.parent.kind !== 'var' ) { | ||
let inLoop = this.findNearest( /Function|^ForStatement|^(?:Do)?WhileStatement/ ); | ||
if ( inLoop && ! /Function/.test( inLoop.type ) ) { | ||
code.insertLeft( this.id.end, ' = void 0' ); | ||
} | ||
} | ||
if ( this.init ) this.init.transpile( code, transforms ); | ||
} | ||
} |
@@ -56,3 +56,4 @@ import { findIndex } from './array.js'; | ||
node.properties.forEach( prop => { | ||
handleProperty( code, scope, c, prop.value, `${ref}.${prop.key.name}`, inline, statementGenerators ); | ||
let value = prop.key.type === 'Literal' ? `${ref}[${prop.key.raw}]` : `${ref}.${prop.key.name}`; | ||
handleProperty( code, scope, c, prop.value, value, inline, statementGenerators ); | ||
c = prop.end; | ||
@@ -59,0 +60,0 @@ }); |
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
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
81
25618
2482583