Comparing version 0.4.11 to 0.4.12
# buble changelog | ||
## 0.4.12 | ||
* More complete and robust transpilation of loops that need to be rewritten as functions to simulate block scoping ([#11](https://gitlab.com/Rich-Harris/buble/issues/11), [#12](https://gitlab.com/Rich-Harris/buble/issues/12), [#13](https://gitlab.com/Rich-Harris/buble/issues/13)) | ||
## 0.4.11 | ||
@@ -4,0 +8,0 @@ |
{ | ||
"name": "buble", | ||
"version": "0.4.11", | ||
"version": "0.4.12", | ||
"description": "The blazing fast, batteries-included ES2015 compiler", | ||
@@ -5,0 +5,0 @@ "main": "dist/buble.umd.js", |
# Bublé | ||
The blazing fast, batteries-included ES2015 compiler | ||
The blazing fast, batteries-included ES2015 compiler. [Try it out at buble.surge.sh](http://buble.surge.sh) | ||
@@ -17,3 +17,5 @@ ![derp](bublé.gif) | ||
Unlike Babel, 100% spec compliance isn't an over-riding goal – for example it won't add runtime checks to ensure that you're not instantiating classes without `new`. (Complete spec compliance is impossible anyway, as some ES2015 features can't be transpiled.) You'll also need to bring your own polyfill (e.g. [es6-shim](https://github.com/es-shims/es6-shim)). You have been warned! | ||
## How do I use it? | ||
@@ -61,3 +63,3 @@ | ||
* Regex unicode flag | ||
* Modules (pssst... use [Rollup](rollupjs.org)!) | ||
* Modules (pssst... use [Rollup](http://rollupjs.org)!) | ||
* `Map`, `Set`, `WeakMap`, `WeakSet`, `Proxy`, `Symbol` | ||
@@ -64,0 +66,0 @@ * Tail call optimisation |
@@ -225,9 +225,40 @@ import wrap from './wrap.js'; | ||
const declaration = declarations[i]; | ||
const alias = this.scope.createIdentifier( name ); | ||
let cont = false; // TODO implement proper continue... | ||
if ( name !== alias ) { | ||
declaration.instances.forEach( identifier => { | ||
code.overwrite( identifier.start, identifier.end, alias, true ); | ||
}); | ||
if ( declaration.kind === 'for.let' ) { | ||
// special case | ||
const forStatement = declaration.node.findNearest( 'ForStatement' ); | ||
if ( forStatement.reassigned[ name ] ) { | ||
const outerAlias = this.scope.createIdentifier( name ); | ||
const innerAlias = this.scope.createIdentifier( name ); | ||
forStatement.aliases[ name ] = { | ||
outer: outerAlias, | ||
inner: innerAlias | ||
}; | ||
declaration.instances.forEach( identifier => { | ||
const alias = forStatement.body.contains( identifier ) ? | ||
innerAlias : | ||
outerAlias; | ||
if ( name !== alias ) { | ||
code.overwrite( identifier.start, identifier.end, alias, true ); | ||
} | ||
}); | ||
cont = true; | ||
} | ||
} | ||
if ( !cont ) { | ||
const alias = this.scope.createIdentifier( name ); | ||
if ( name !== alias ) { | ||
declaration.instances.forEach( identifier => { | ||
code.overwrite( identifier.start, identifier.end, alias, true ); | ||
}); | ||
} | ||
} | ||
} | ||
@@ -234,0 +265,0 @@ }); |
@@ -44,2 +44,21 @@ import { walk } from 'estree-walker'; | ||
ancestor ( level ) { | ||
let node = this; | ||
while ( level-- ) { | ||
node = node.parent; | ||
if ( !node ) return null; | ||
} | ||
return node; | ||
} | ||
contains ( node ) { | ||
while ( node ) { | ||
if ( node === this ) return true; | ||
node = node.parent; | ||
} | ||
return false; | ||
} | ||
findLexicalBoundary () { | ||
@@ -46,0 +65,0 @@ return this.parent.findLexicalBoundary(); |
@@ -11,2 +11,8 @@ import Node from '../Node.js'; | ||
} | ||
// special case – https://gitlab.com/Rich-Harris/buble/issues/11 | ||
const statement = declaration && declaration.node.ancestor( 3 ); | ||
if ( statement && statement.type === 'ForStatement' && statement.body.contains( this ) ) { | ||
statement.reassigned[ this.left.name ] = true; | ||
} | ||
} | ||
@@ -13,0 +19,0 @@ |
@@ -1,5 +0,5 @@ | ||
import Node from '../Node.js'; | ||
import LoopStatement from './shared/LoopStatement.js'; | ||
import extractNames from '../extractNames.js'; | ||
export default class ForStatement extends Node { | ||
export default class ForStatement extends LoopStatement { | ||
findScope ( functionScope ) { | ||
@@ -9,37 +9,6 @@ return functionScope || !this.createdScope ? this.parent.findScope( functionScope ) : this.body.scope; | ||
initialise () { | ||
this.body.createScope(); | ||
this.createdScope = true; | ||
super.initialise(); | ||
} | ||
transpile ( code ) { | ||
// see if any block-scoped declarations are referenced | ||
// inside function expressions | ||
const names = Object.keys( this.body.scope.declarations ); | ||
let shouldRewriteAsFunction = false; | ||
const i1 = this.getIndentation() + code.getIndentString(); | ||
let i = names.length; | ||
while ( i-- ) { | ||
const name = names[i]; | ||
const declaration = this.body.scope.declarations[ name ]; | ||
let j = declaration.instances.length; | ||
while ( j-- ) { | ||
const instance = declaration.instances[j]; | ||
const nearestFunctionExpression = instance.findNearest( /Function/ ); | ||
if ( nearestFunctionExpression && nearestFunctionExpression.depth > this.depth ) { | ||
shouldRewriteAsFunction = true; | ||
break; | ||
} | ||
} | ||
if ( shouldRewriteAsFunction ) break; | ||
} | ||
if ( shouldRewriteAsFunction ) { | ||
const indentation = this.getIndentation(); | ||
if ( this.shouldRewriteAsFunction ) { | ||
// which variables are declared in the init statement? | ||
@@ -50,10 +19,18 @@ const names = this.init.type === 'VariableDeclaration' ? | ||
const before = `var forLoop = function ( ${names.join( ', ' )} ) ` + ( this.body.synthetic ? `{\n${indentation}${code.getIndentString()}` : '' ); | ||
const after = ( this.body.synthetic ? `\n${indentation}}` : '' ) + `;\n\n${indentation}`; | ||
const aliases = this.aliases; | ||
code.insert( this.start, before ); | ||
code.move( this.body.start, this.body.end, this.start ); | ||
code.insert( this.start, after ); | ||
this.args = names.map( name => name in this.aliases ? this.aliases[ name ].outer : name ); | ||
this.params = names.map( name => name in this.aliases ? this.aliases[ name ].inner : name ); | ||
code.insert( this.end, `forLoop( ${names.join( ', ' )} );` ); | ||
const updates = Object.keys( this.reassigned ) | ||
.map( name => `${aliases[ name ].outer} = ${aliases[ name ].inner};` ); | ||
if ( updates.length ) { | ||
if ( this.body.synthetic ) { | ||
code.insert( this.body.body[0].end, `; ${updates.join(` `)}` ); | ||
} else { | ||
const lastStatement = this.body.body[ this.body.body.length - 1 ]; | ||
code.insert( lastStatement.end, `\n\n${i1}${updates.join(`\n${i1}`)}` ); | ||
} | ||
} | ||
} | ||
@@ -60,0 +37,0 @@ |
@@ -22,7 +22,11 @@ import Node from '../Node.js'; | ||
const arrowFunction = this.findNearest( 'ArrowFunctionExpression' ); | ||
const loop = this.findNearest( /(?:For|While)Statement/ ); | ||
if ( arrowFunction && arrowFunction.depth > lexicalBoundary.depth ) { | ||
const argumentsAlias = lexicalBoundary.getArgumentsAlias(); | ||
if ( argumentsAlias ) this.alias = argumentsAlias; | ||
this.alias = lexicalBoundary.getArgumentsAlias(); | ||
} | ||
if ( loop && loop.depth > lexicalBoundary.depth ) { | ||
this.alias = lexicalBoundary.getArgumentsAlias(); | ||
} | ||
} | ||
@@ -29,0 +33,0 @@ |
import ArrayExpression from './ArrayExpression.js'; | ||
import ArrowFunctionExpression from './ArrowFunctionExpression.js'; | ||
import AssignmentExpression from './AssignmentExpression.js'; | ||
import BreakStatement from './BreakStatement.js'; | ||
import CallExpression from './CallExpression.js'; | ||
@@ -8,2 +9,3 @@ import ClassBody from './ClassBody.js'; | ||
import ClassExpression from './ClassExpression.js'; | ||
import ContinueStatement from './ContinueStatement.js'; | ||
import ExportDefaultDeclaration from './ExportDefaultDeclaration.js'; | ||
@@ -17,4 +19,6 @@ import ForStatement from './ForStatement.js'; | ||
import Literal from './Literal.js'; | ||
import LoopStatement from './shared/LoopStatement.js'; | ||
import Identifier from './Identifier.js'; | ||
import Property from './Property.js'; | ||
import ReturnStatement from './ReturnStatement.js'; | ||
import Super from './Super.js'; | ||
@@ -33,2 +37,3 @@ import TaggedTemplateExpression from './TaggedTemplateExpression.js'; | ||
AssignmentExpression, | ||
BreakStatement, | ||
CallExpression, | ||
@@ -38,2 +43,4 @@ ClassBody, | ||
ClassExpression, | ||
ContinueStatement, | ||
DoWhileStatement: LoopStatement, | ||
ExportDefaultDeclaration, | ||
@@ -49,2 +56,3 @@ ForStatement, | ||
Property, | ||
ReturnStatement, | ||
Super, | ||
@@ -57,3 +65,4 @@ TaggedTemplateExpression, | ||
VariableDeclaration, | ||
VariableDeclarator | ||
VariableDeclarator, | ||
WhileStatement: LoopStatement | ||
}; |
@@ -7,7 +7,11 @@ import Node from '../Node.js'; | ||
const arrowFunction = this.findNearest( 'ArrowFunctionExpression' ); | ||
const loop = this.findNearest( /(?:For|While)Statement/ ); | ||
if ( arrowFunction && arrowFunction.depth > lexicalBoundary.depth ) { | ||
const thisAlias = lexicalBoundary.getThisAlias(); | ||
if ( thisAlias ) this.alias = thisAlias; | ||
this.alias = lexicalBoundary.getThisAlias(); | ||
} | ||
if ( loop && loop.depth > lexicalBoundary.depth ) { | ||
this.alias = lexicalBoundary.getThisAlias(); | ||
} | ||
} | ||
@@ -14,0 +18,0 @@ |
@@ -17,3 +17,8 @@ import Node from '../Node.js'; | ||
this.parent.scope.addDeclaration( this.id, this.parent.kind ); | ||
let kind = this.parent.kind; | ||
if ( kind === 'let' && this.parent.parent.type === 'ForStatement' ) { | ||
kind = 'for.let'; // special case... | ||
} | ||
this.parent.scope.addDeclaration( this.id, kind ); | ||
super.initialise(); | ||
@@ -20,0 +25,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
1837614
52
15635
95