Compare commits

..

127 Commits

Author SHA1 Message Date
Sebastian McKenzie
215c2da7cb v1.12.10 2014-11-14 07:40:41 +11:00
Sebastian McKenzie
c7c41d6548 add changelog for 1.12.10 2014-11-14 07:39:06 +11:00
Sebastian McKenzie
695571b435 fix LetScoping::pushDeclar - fixes #156 2014-11-14 07:34:50 +11:00
Sebastian McKenzie
f845633cc1 v1.12.9 2014-11-14 02:24:08 +11:00
Sebastian McKenzie
72c9b1d6c9 remove redundant changelog message 2014-11-14 02:23:23 +11:00
Sebastian McKenzie
edd3363e48 fix unicode regex test escaping 2014-11-14 02:23:12 +11:00
Sebastian McKenzie
114b5ef9ec add changelog for 1.12.9 2014-11-14 02:20:15 +11:00
Sebastian McKenzie
2f4e0c3361 escape unicode characters - fixes #154 2014-11-14 02:17:06 +11:00
Sebastian McKenzie
3ee51dae1a fix semicolon 2014-11-14 00:59:18 +11:00
Sebastian McKenzie
20263c1151 fix newline in let-scoping/for-break-continue-return test 2014-11-14 00:55:39 +11:00
Sebastian McKenzie
eaac564f11 add toIdentifier, toBlock and toStatement tests 2014-11-14 00:55:22 +11:00
Sebastian McKenzie
63a47ef7bb optimise types.toStatement for when we're directly passed a statement 2014-11-14 00:55:14 +11:00
Sebastian McKenzie
6963cc1e40 fix WithStatement missing paranthesis 2014-11-14 00:54:58 +11:00
Sebastian McKenzie
5eb2462e29 fix up semicolons for module ExportDeclaration generator 2014-11-14 00:54:28 +11:00
Sebastian McKenzie
9e285cdc20 remove unneccesary Literal generator raw 2014-11-14 00:54:12 +11:00
Sebastian McKenzie
01ade47af9 add single spread test 2014-11-14 00:54:00 +11:00
Sebastian McKenzie
b1fe449b0d allow XJSElement and SequenceExpression to be user whitespacable 2014-11-14 00:53:45 +11:00
Sebastian McKenzie
2b458ec2d4 make it illegal to use destructuring outside of an ExpressionStatement 2014-11-14 00:53:10 +11:00
Sebastian McKenzie
d5f47f4f4d generator: correctly output XJSEmptyExpression 2014-11-14 00:52:49 +11:00
Sebastian McKenzie
d4deb18975 support async functions in generator and move MethodDefinition to class generator 2014-11-14 00:52:36 +11:00
Sebastian McKenzie
5a794db73b fix up let scoping transformer comments 2014-11-14 00:52:15 +11:00
Sebastian McKenzie
dc131f05a8 add comprehensive generation tests 2014-11-14 00:51:59 +11:00
Sebastian McKenzie
1d4f79790a add brief usage to doc/index.md - thanks @gabrielecirulli ❤️ 2014-11-13 23:31:51 +11:00
Sebastian McKenzie
6bcbaf6df1 better feature code examples 2014-11-13 19:00:08 +11:00
Sebastian McKenzie
bc199ef0c9 better api documentation 2014-11-13 18:59:59 +11:00
Sebastian McKenzie
f5fed99c81 better 6to5 tagline 2014-11-13 18:59:46 +11:00
Sebastian McKenzie
66a6d3cffe add CONTRIBUTING.md 2014-11-13 18:59:29 +11:00
Sebastian McKenzie
39227486a6 add async to caveats 2014-11-13 14:47:39 +11:00
Sebastian McKenzie
caafa31df1 chagne ES6 to ES6+ when talking about 6to5 support 2014-11-13 14:47:32 +11:00
Sebastian McKenzie
4c41c904f5 v1.12.8 2014-11-13 13:42:54 +11:00
Sebastian McKenzie
0917a6a5b1 better destructuring AssignmentExpression error message 2014-11-13 13:42:18 +11:00
Sebastian McKenzie
349eba33ce add async functions to traceur differences 2014-11-13 13:40:54 +11:00
Sebastian McKenzie
8ff21b407d temporarily forbid AssignmentExpression destructuring outside of ExpressionStatement 2014-11-13 13:40:41 +11:00
Sebastian McKenzie
751ea7a12c v1.12.7 2014-11-13 13:19:45 +11:00
Sebastian McKenzie
b30cd227cc update acorn-6to5 - fixes #153 2014-11-13 13:18:59 +11:00
Sebastian McKenzie
18dc7b8143 v1.12.6 2014-11-13 12:55:39 +11:00
Sebastian McKenzie
1c628bbec1 disable generation/comments/comment-only test 2014-11-13 12:53:38 +11:00
Sebastian McKenzie
d4c3dde02a update to latest acorn-6to5 2014-11-13 12:49:29 +11:00
Sebastian McKenzie
a587106a6b v1.12.5 2014-11-13 12:26:16 +11:00
Sebastian McKenzie
9c1b60e451 fix excessive whitespace trimming resulting in innaccurate sourcemap line - fixes #151 2014-11-13 12:25:11 +11:00
Sebastian McKenzie
0c7e0b65b9 add browser support, array comprehension, async functions and generator comprehension to differences table 2014-11-13 03:24:45 +11:00
Sebastian McKenzie
5c17091db4 replace documentation link 2014-11-13 01:17:14 +11:00
Sebastian McKenzie
7fa5ba88df v1.12.4 2014-11-13 01:16:45 +11:00
Sebastian McKenzie
2fae245cd5 add 1.12.4 changelog 2014-11-13 01:15:41 +11:00
Sebastian McKenzie
297f103ddb move docs to folder 2014-11-13 01:13:48 +11:00
Sebastian McKenzie
fd63650d6a add .hound.yml 2014-11-12 19:25:35 +11:00
Sebastian McKenzie
e13ed39567 v1.12.3 2014-11-12 18:43:39 +11:00
Sebastian McKenzie
bb00f641b7 remove unused variables in spread transformer 2014-11-12 18:42:24 +11:00
Sebastian McKenzie
25b466a627 remove unused variables 2014-11-12 18:39:50 +11:00
Sebastian McKenzie
ac231f2987 add 1.12.3 changelog 2014-11-12 18:38:39 +11:00
Sebastian McKenzie
458e3d48f6 use Array.from instead of Array.prototype.slice in spread transformer and support NewExpression spreads - fixes #148 2014-11-12 18:38:30 +11:00
Sebastian McKenzie
c235780611 move down 6to5-node util declaration 2014-11-12 18:37:32 +11:00
Sebastian McKenzie
56b858ccb1 add generator comprehension transformer 2014-11-12 18:29:41 +11:00
Sebastian McKenzie
d42351bb02 add default parameters existence change to well... the defaultParameters transformer 2014-11-12 18:29:27 +11:00
Sebastian McKenzie
ed7378cc2d add apply-constructor declaration and add support for not returning generated code in opts.code 2014-11-12 18:29:03 +11:00
Sebastian McKenzie
a47a7dc347 rename util.parseNoProperties to util.parseTemplate 2014-11-12 18:28:11 +11:00
Sebastian McKenzie
2c82b5a4b0 add generator option to FunctionExpression builder keys 2014-11-12 18:27:56 +11:00
Sebastian McKenzie
3578135b90 add spread caveat and add generator comprehension and react/jsx to features 2014-11-12 18:27:05 +11:00
Sebastian McKenzie
5f3408b2a2 upgrade regenerator-6to5 2014-11-12 18:26:29 +11:00
Sebastian McKenzie
9e3f9fda6b add support for generator comprehensions - fixes #149 2014-11-12 18:26:22 +11:00
Sebastian McKenzie
7f425d2c6e v1.12.2 2014-11-12 12:22:03 +11:00
Sebastian McKenzie
311a8e042b add missing semicolon 2014-11-12 12:19:25 +11:00
Sebastian McKenzie
27d30329fd add more react spread tests 2014-11-12 12:18:16 +11:00
Sebastian McKenzie
12c5a3e73b add 1.12.2 changelog 2014-11-12 12:17:59 +11:00
Sebastian McKenzie
2a166a6ed1 support jsx spread attributes that aren't the first - fixes #146 2014-11-12 12:17:45 +11:00
Sebastian McKenzie
896929378e add util.trimRight method - fixes #147 2014-11-12 12:17:26 +11:00
Sebastian McKenzie
ae439d27b9 update mocha and browserify 2014-11-12 12:08:33 +11:00
Sebastian McKenzie
e22798261a change useless self references to this 2014-11-12 02:03:46 +11:00
Sebastian McKenzie
d0af8b8d0a remove numeric literals transformer 2014-11-12 02:03:25 +11:00
Sebastian McKenzie
beaa2fa540 add async functions to features 2014-11-12 02:03:11 +11:00
Sebastian McKenzie
b8cac9787e produce new MemberExpression in a CallExpression super identifier instead of mutating the property 2014-11-12 01:51:57 +11:00
Sebastian McKenzie
64f6e4a0c5 clean up classes transformer and add comments 2014-11-12 01:48:55 +11:00
Sebastian McKenzie
c4a7ac5a8b turn classes transformer into a class like let scoping 2014-11-12 01:39:35 +11:00
Sebastian McKenzie
1ed682fa76 fix up jsdoc in let-scoping transformer 2014-11-12 01:39:02 +11:00
Sebastian McKenzie
9987e7fe0e add 1.12.1 changelog 2014-11-12 01:38:50 +11:00
Sebastian McKenzie
e74c7cb0b7 turn the let scoping transformer into a class because it's quite complicated and the logic needs to be WAY more organised 2014-11-12 01:20:51 +11:00
Sebastian McKenzie
2f01e5c3af v1.12.1 2014-11-12 00:47:53 +11:00
Sebastian McKenzie
6847211971 fix up aliasFunctions transformer 2014-11-12 00:46:36 +11:00
Sebastian McKenzie
965e246259 add back opts defaults 2014-11-12 00:46:20 +11:00
Sebastian McKenzie
af59eb7d6a fix linting errors 2014-11-12 00:33:39 +11:00
Sebastian McKenzie
def4319058 stop _alias-functions transformer when hitting a function that's not an arrow function - fixes #145 2014-11-12 00:32:30 +11:00
Sebastian McKenzie
d90383b1ba generator: add Buffer class that deals with the actual code output 2014-11-12 00:27:59 +11:00
Sebastian McKenzie
1ac40ee834 remove static whitespace properties in favor of pushing to the dynamic ones 2014-11-12 00:15:31 +11:00
Sebastian McKenzie
3d5d170eff move whitespace and parentheses generation logic into separate files 2014-11-12 00:11:34 +11:00
Sebastian McKenzie
b5bdba46f1 change test-appveyor to test-spec and add test-clean method to clean up after tests 2014-11-11 23:27:01 +11:00
Sebastian McKenzie
c4e162b8e5 add rails to plugins 2014-11-11 22:27:52 +11:00
Sebastian McKenzie
98bc750b05 add mocha to plugins 2014-11-11 22:25:27 +11:00
Sebastian McKenzie
84002ed1ce add jest to plugins 2014-11-11 22:12:26 +11:00
Sebastian McKenzie
aaab2db0ec add react/jsx to readme 2014-11-11 20:06:02 +11:00
Sebastian McKenzie
7f3959444c v1.12.0 2014-11-11 19:14:52 +11:00
Sebastian McKenzie
0ba9216d6f remove unused variables in react transformer 2014-11-11 19:14:00 +11:00
Sebastian McKenzie
6dfe66bce3 add v1.12.0 to changelog 2014-11-11 19:12:44 +11:00
Sebastian McKenzie
9e08a6f084 combine jsx and react transformer so we can make the jsx output correct - #143 2014-11-11 19:11:30 +11:00
Sebastian McKenzie
b9f3f1e2a9 add comment inheriting to types.inherits 2014-11-11 19:10:41 +11:00
Sebastian McKenzie
4f18ed406c v1.11.15 2014-11-11 17:17:08 +11:00
Sebastian McKenzie
4d8e5f728a 1.11.15 2014-11-11 17:16:11 +11:00
Sebastian McKenzie
54857ceac7 fix jsx literal generator - closes #143 2014-11-11 17:15:37 +11:00
Sebastian McKenzie
5b961ea3e7 v1.11.14 2014-11-11 15:35:18 +11:00
Sebastian McKenzie
35b28cf722 more reliable jsx literal whitespace 2014-11-11 15:34:29 +11:00
Sebastian McKenzie
c5bfbf37f0 add 1.11.14 changelog 2014-11-11 15:27:23 +11:00
Sebastian McKenzie
cfee68aa67 jsx: replace all newlines and excess whitespace with spaces - fixes #142 2014-11-11 15:26:25 +11:00
Sebastian McKenzie
7d0dae129c nicer let-scoping switch 2014-11-11 15:25:37 +11:00
Sebastian McKenzie
f9d14fa2ed add runtime, property-literals and shebang tests 2014-11-11 15:25:27 +11:00
Sebastian McKenzie
11d55e661e rename let-scoping tests to traceur-let-scoping and add additional let-scoping tests 2014-11-11 15:25:13 +11:00
Sebastian McKenzie
0544e98fb1 add switch case generated node whitespace 2014-11-11 15:24:40 +11:00
Sebastian McKenzie
59d918ea67 remove unused isArray traverse.hasType 2014-11-11 15:23:52 +11:00
Sebastian McKenzie
b4232699d2 add newline after shebang 2014-11-11 15:23:31 +11:00
Sebastian McKenzie
6bd67ca660 v1.11.13 2014-11-11 14:31:06 +11:00
Sebastian McKenzie
4722c0ce56 add support for escodegen-style format options 2014-11-11 14:30:06 +11:00
Sebastian McKenzie
25a5caa0fc update regenerator-6to5 2014-11-11 14:29:32 +11:00
Sebastian McKenzie
6f05466cf5 normalise windows path separators to unix 2014-11-11 13:36:59 +11:00
Sebastian McKenzie
1ad9edb57c tests/bin: normalise stdout path separators 2014-11-11 13:33:50 +11:00
Sebastian McKenzie
c6ae33c5a2 tests: change all windows line endings to unix ones 2014-11-11 13:30:19 +11:00
Sebastian McKenzie
e0d620b1d5 remove browser-polyfill.js instead of polyfill.js 2014-11-11 13:29:50 +11:00
Sebastian McKenzie
5588bf56eb add CHANGELOG 2014-11-11 13:29:37 +11:00
Sebastian McKenzie
a0e500de6c v1.11.12 2014-11-11 13:14:31 +11:00
Sebastian McKenzie
bf8d9801ce rename browserified polyfill to browser-polyfill - fixes #140 2014-11-11 13:13:10 +11:00
Sebastian McKenzie
68b99a7004 v1.11.11 2014-11-11 13:06:06 +11:00
Sebastian McKenzie
5ae4f8eec7 add AwaitExpression generator 2014-11-11 13:05:07 +11:00
Sebastian McKenzie
d9a3eadad7 move generators transformer to bottom 2014-11-11 13:03:06 +11:00
Sebastian McKenzie
b1cc5419a4 add AwaitExpression visitor keys - fixes #141 2014-11-11 13:02:55 +11:00
Sebastian McKenzie
c6a7a9c401 v1.11.10 2014-11-11 09:48:28 +11:00
Sebastian McKenzie
608df54b02 bump acorn-6to5 version to one that supports async/await - closes #134 2014-11-11 09:47:29 +11:00
Sebastian McKenzie
2ac83ec95b v1.11.9 2014-11-11 08:07:29 +11:00
Sebastian McKenzie
e4596f638d only check string literals in property-literals transformer 2014-11-11 08:06:31 +11:00
Sebastian McKenzie
1425af9b2a v1.11.8 2014-11-11 07:51:43 +11:00
Sebastian McKenzie
9351c6470f bump regenerator version 2014-11-11 07:50:07 +11:00
367 changed files with 3160 additions and 1784 deletions

2
.gitignore vendored
View File

@@ -6,7 +6,7 @@ test/tmp
/templates.json
/tests.json
/browser.js
/polyfill.js
/browser-polyfill.js
/runtime.js
coverage
dist

3
.hound.yml Normal file
View File

@@ -0,0 +1,3 @@
java_script:
enabled: true
config_file: .jshintrc

View File

@@ -8,4 +8,4 @@ Makefile
.*
dist
tests.json
!README.md
CHANGELOG.md

64
CHANGELOG.md Normal file
View File

@@ -0,0 +1,64 @@
# 1.12.10
* Fix let scoping var hoisting.
# 1.12.9
* Escape unicode characters when generating string `Literal`s.
* Fix semicolons being output for statements in `ExportDeclaration`.
* Fix `WithStatement` missing parenthesis.
# 1.12.8
* Temporarily forbid `AssignmentExpression` destructuring outside of `ExpressionStatement`.
# 1.12.7
* Update to latest `acorn-6to5`.
# 1.12.6
* Update to latest `acorn-6to5`.
# 1.12.5
* Fix excessive whitespace trimming resulting in innaccurate sourcemap line.
# 1.12.4
* Add `doc` folder for documentation.
# 1.12.3
* Support generator comprehensions.
* Use `Array.from` instead of `Array.prototype.slice` in spread transformer.
* Support spread in `NewExpression`s.
# 1.12.2
* Upgrade `matcha` to `0.6.0` and `browserify` to `6.3.2`.
* Add own `trimRight` helper instead of relying on the string instance method.
* Support JSX spreads that aren't the first.
# 1.12.1
* Fix `this` and `arguments` mapping in the `_aliasFunctions` transformer.
# 1.12.0
* Combine `jsx` and `react` transformers to `react`.
* Update `react` syntax output to React v0.12.
# 1.11.15
* Fix JSX literal whitespace generation.
# 1.11.14
* Avoid using a switch for let-scoping continue and break statements and use an if statement instead.
* Remove excess whitespace and newlines from JSX literals.
# 1.11.13
* Update regenerator-6to5
* Add support for most escodegen formatting options

31
CONTRIBUTING.md Normal file
View File

@@ -0,0 +1,31 @@
# Contributing
* **General**
* No ES6 syntax features or methods, exclusively ES5.
* Max of five arguments for functions
* Max depth of four nested blocks
* 2-spaced soft tabs
* **Naming**
* CamelCase all class names
* camelBack all variable names
* **Spacing**
* 80 character line max
* Spaces after all keywords
* Spaces before all left curly braces
* **Comments**
* Use JSDoc-style comments for methods
* Single-line comments for ambiguous code
* **Quotes**
* Always use double quotes
* Only use single quotes when the string contains a double quote
* **Declaration**
* No unused variables
* No pollution of global variables and prototypes
## Testing
$ make test
## Linting
$ make lint

View File

@@ -1,162 +0,0 @@
# Features
## Array comprehension
```javascript
[for (i of [1, 2, 3]) i * i]; // [1, 4, 9]
```
## Arrow functions
```javascript
arr.map(x => x * x);
```
## Let scoping
```javascript
for (let i in arr) {
let v = arr[i];
}
```
## Classes
```javascript
class Foo extends Bar {
constructor() { }
foo() { }
get bar() { }
set bar() { }
}
```
## Computed property names
```javascript
var foo = "foo";
var bar = "bar";
var obj = {
["foo" + bar]: "heh",
["bar" + foo]: "noo",
foo: "foo",
bar: "bar"
};
```
## Constants
```javascript
const MULTIPLIER = 5;
console.log(2 * MULTIPLIER);
MULTIPLIER = 6; // error
var MULTIPLIER; // error
```
## Default parameters
```javascript
function foo(bar = "foo") {
return bar + "bar";
}
```
## Destructuring
```javascript
var [a, [b], c, d] = ["hello", [", ", "junk"], ["world"]];
console.log(a + b + c); // hello, world
```
## For-of
```javascript
for (var i of [1, 2, 3]) {
console.log(i * i);
}
```
## Generators
```javascript
```
## Modules
```javascript
```
## Numeric literals
```javascript
0b111110111 === 503; // true
0o767 === 503; // true
```
## Property method assignment
```javascript
var obj = {
foo() {
return "foobar";
},
get bar() {
return this._bar;
},
set bar(val) {
this._bar = val;
}
};
```
## Property name shorthand
```javascript
function f(x, y) {
return { x, y };
}
```
## Rest parameters
```javascript
function printList(name, ...items) {
console.log("list %s has the following items", name);
items.forEach(function (item) {
console.log(item);
});
}
```
## Spread
```javascript
function add(x, y) {
return x + y;
}
var numbers = [5, 10];
add(...numbers); // 15
```
## Template literals
```javascript
var x = 5;
var y = 10;
console.log(`${x} + ${y} = ${x + y}`); // "5 + 10 = 15"
```
## Unicode regex
```javascript
var string = 'foo💩bar';
var match = string.match(/foo(.)bar/u);
console.log(match[1]);
```

View File

@@ -6,7 +6,7 @@ MOCHA_CMD = node_modules/mocha/bin/_mocha
export NODE_ENV = test
.PHONY: clean test test-cov tlint est-travis test-appveyor test-browser publish bench build
.PHONY: clean test test-cov test-clean lint test-travis test-spec test-browser publish bench build
clean:
rm -rf coverage templates.json test/tmp dist
@@ -18,19 +18,23 @@ bench:
lint:
$(JSHINT_CMD) lib bin benchmark/index.js
test-clean:
rm -rf test/tmp
test:
make lint
$(MOCHA_CMD)
make test-clean
test-cov:
rm -rf coverage
node $(ISTANBUL_CMD) $(MOCHA_CMD) --
test-appveyor:
test-spec:
node $(ISTANBUL_CMD) $(MOCHA_CMD) -- --reporter spec
test-travis:
make test-appveyor
make test-spec
if test -n "$$CODECLIMATE_REPO_TOKEN"; then codeclimate < coverage/lcov.info; fi
test-browser:
@@ -66,7 +70,7 @@ publish:
make build
cp dist/6to5.min.js browser.js
cp dist/polyfill.min.js polyfill.js
cp dist/polyfill.min.js browser-polyfill.js
cp dist/runtime.min.js runtime.js
node bin/cache-templates
@@ -78,4 +82,4 @@ publish:
git push --follow-tags
rm -rf templates.json browser.js runtime.js polyfill.js
rm -rf templates.json browser.js runtime.js browser-polyfill.js

477
README.md
View File

@@ -24,479 +24,6 @@
</a>
</p>
**6to5** turns ES6 code into vanilla ES5, so you can use ES6 features **today.**
**6to5** turns ES6+ code into vanilla ES5, so you can use next generation features **today.**
- **Readable** - formatting is retained if possible so your generated code is as similar as possible.
- **Extensible** - with a large range of [plugins](#plugins) and **browser support**.
- **Lossless** - **source map support** so you can debug your compiled code with ease.
- **Compact** - maps directly to the equivalent ES5 with **no runtime**[\*](#generators).
## Installation
It's as easy as:
$ npm install -g 6to5
## Table of Contents
- [Features](#features)
- [Usage](#usage)
- [Plugins](#plugins)
- [CLI](#cli)
- [Node](#node-1)
- [Browser](#browser)
- [Modules](#modules)
- [Caveats](#caveats)
- [Polyfill](#polyfill)
- [Optional runtime](#optional-runtime)
- [Differences](#differences)
## [Features](FEATURES.md)
- [Array comprehension](FEATURES.md#array-comprehension)
- [Arrow functions](FEATURES.md#arrow-functions)
- [Classes](FEATURES.md#classes)
- [Computed property names](FEATURES.md#computed-property-names)
- [Constants](FEATURES.md#constants)
- [Default parameters](FEATURES.md#default-parameters)
- [Destructuring](FEATURES.md#destructuring)
- [For-of](FEATURES.md#for-of)
- [Generators](FEATURES.md#generators) via [regenerator](https://github.com/facebook/regenerator)
- [Let scoping](FEATURES.md#let-scoping)
- [Modules](FEATURES.md#modules)
- [Numeric literals](FEATURES.md#numeric-literals)
- [Property method assignment](FEATURES.md#property-method-assignment)
- [Property name shorthand](FEATURES.md#property-name-shorthand)
- [Rest parameters](FEATURES.md#rest-parameters)
- [Spread](FEATURES.md#spread)
- [Template literals](FEATURES.md#template-literals)
- [Unicode regex](FEATURES.md#unicode-regex)
## Usage
### Plugins
- [Broccoli](https://github.com/very-geek/broccoli-6to5-transpiler)
- [Browserify](https://github.com/6to5/6to5-browserify)
- [Brunch](https://github.com/es128/6to5-brunch)
- [Duo](https://github.com/bdo-labs/duo6to5)
- [Connect](https://github.com/6to5/6to5-connect)
- [Gulp](https://github.com/sindresorhus/gulp-6to5)
- [Grunt](https://github.com/sindresorhus/grunt-6to5)
- [Jade](https://github.com/Apoxx/jade-6to5)
- [Karma](https://github.com/shuhei/karma-6to5-preprocessor)
- [webpack](https://github.com/Couto/6to5-loader)
### CLI
Compile the file `script.js` and output it to stdout.
$ 6to5 script.js
Compile the file `script.js` and output it to `script-compiled.js`.
$ 6to5 script.js --out-file script-compiled.js
Compile the file `script.js` and output it to `script-compiled.js` and save a
source map to `script-compiled.js.map`.
$ 6to5 script.js --source-maps --out-file script-compiled.js
Compile the file `script.js` and output it to `script-compiled.js` with a source
map embedded in a comment at the bottom.
$ 6to5 script.js --source-maps-inline --out-file script-compiled.js
Compile the entire `src` directory and output it to the `lib` directory.
$ 6to5 src --out-dir lib
Compile the entire `src` directory and output it to the one concatenated file.
$ 6to5 src --out-file script-compiled.js
Pipe a file in via stdin and output it to `script-compiled.js`
$ 6to5 --out-file script-compiled.js < script.js
#### Node
Launch a repl.
$ 6to5-node
Evaluate code.
$ 6to5-node -e "class Test { }"
Compile and run `test.js`.
$ 6to5-node test
### Node
```javascript
var to5 = require("6to5");
var result = to5.transform("code();", options);
result.code;
result.map;
result.ast;
to5.transformFileSync("filename.js", options).code;
to5.transformFile("filename.js", options, function (err, result) {
});
```
##### Options
```javascript
{
// Filename for use in errors etc.
// Default: "unknown"
filename: "filename",
// List of transformers to EXCLUDE.
// Run `6to5 --help` to see a full list of transformers.
blacklist: [],
// List of transformers to ONLY use.
// Run `6to5 --help` to see a full list of transformers.
whitelist: [],
// Module formatter to use
// Run `6to5 --help` to see a full list of module formatters.
// Default: "common"
modules: "common",
// If truthy, adds a `map` property to returned output.
// If set to "inline", a comment with a sourceMappingURL directive is added to
// the bottom of the returned code.
// Default: false
sourceMap: true,
// Set `file` on returned source map.
// Default: `filename` option.
sourceMapName: "filename",
// Set `sources[0]` on returned source map.
// Default: `filename` option.
sourceFileName: "filename",
// Optionally replace all 6to5 helper declarations with a referenece to this
// variable. If set to `true` then the default namespace is used "to5Runtime".
// Default: false
runtime: true
}
```
#### Require hook
All subsequent files required by node with the extensions `.es6` and `.js` will
be transformed by 6to5. The polyfill specified in [Polyfill](#polyfill) is also
required.
```javascript
require("6to5/register");
```
**NOTE:** By default all requires to `node_modules` will be ignored. You can
override this by passing an ignore regex via:
```javascript
require("6to5/register")({
// This will override `node_modules` ignoring - you can alternatively pass
// a regex
ignore: false
});
```
##### Options
```javascript
require("6to5/register")({
// Optional ignore regex - if any filenames **do** match this regex then they
// aren't compiled
ignore: /regex/,
// Optional only regex - if any filenames **don't** match this regex then they
// aren't compiled
only: /my_es6_folder/,
// See options above for usage
whitelist: [],
blacklist: [],
// This will remove the currently hooked extensions of .es6 and .js so you'll
// have to add them back if you want them to be used again.
extensions: [".js", ".es6"]
});
```
### Browser
A browser version of 6to5 is available from `browser.js` inside the 6to5
directory in an npm release.
#### Scripts
While it's not recommended for serious use, when the browser version is included
all scripts with the type `text/ecmascript-6` and `text/6to5` are automatically
compiled and ran.
For example:
```html
<script src="node_modules/6to5/browser.js"></script>
<script type="text/6to5">
class Test {
test() {
return "test";
}
}
var test = new Test;
test.test();
</script>
```
#### Build
You can build a browser version of the compiler by running the following in the
6to5 directory:
$ make build
This will output the files `dist/6to5.js` and `dist/6to5.min.js`.
#### API
```javascript
to5.transform("class Test {}").code;
```
#### Test
To test 6to5 in your browser run:
$ make test-browser
And open `test/browser.html` in your browser if it doesn't open automatically.
## [Modules](MODULES.md)
See [Modules - Common](MODULES.md#common-default) for documentation on the
default module formatting.
Alternatively see [Modules](MODULES.md) for all other supported module formatting types.
## Caveats
### For-of
A polyfill is required for for-of functionality that implements `Symbol` and
adds `prototype[Symbol.iterator]` behaviour to built-ins. Using the polyfills
specified in [polyfill](#polyfill) suffices.
### Classes
Built-in classes such as `Date`, `Array` and `DOM` cannot be subclassed due to
limitations in ES5 implementations.
If you're inheriting from a class then static properties are inherited from it
via [\_\_proto\_\_](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/proto),
this is widely supported but you may run into problems with much older browsers.
**NOTE:** `__proto__` is not supported on IE <= 9 so static properties
**will not** be inherited. A possible workaround is to use `super();`:
```javascript
class Foo {
static foo() {
}
}
class Bar extends Foo {
static foo() {
super();
}
}
```
### Generators
The [regenerator runtime](https://github.com/facebook/regenerator/blob/master/runtime.js)
and an [ES6 polyfill](#polyfill) are required in order for generators to work.
## Polyfill
6to5 includes a polyfill that includes the
[regenerator runtime](https://github.com/facebook/regenerator/blob/master/runtime.js) and the
[es6-shim](https://github.com/paulmillr/es6-shim) and
[es6-symbol](https://github.com/medikoo/es6-symbol) polyfills.
### Node
```javascript
require("6to5/polyfill");
```
### Browser
Available from the `polyfill.js` file within the 6to5 directory of an npm
release.
## Optional runtime
6to5 has a few helper functions that'll be placed at the top of the generated
code if needed so it's not inlined multiple times throughout that file. This may
become an issue if you have multiple files, especially when you're sending them
to the browser. gzip alleviates most of this concern but it's still not ideal.
You can tell 6to5 to not place any declarations at the top of your files and
instead just point them to a reference contained within the runtime.
Simply use the following option if you're using the [Node API](#node-1):
```javascript
{
runtime: true
}
```
or the following flag if you're using the [CLI](#cli):
$ 6to5 --runtime
Then just include the runtime before your generated code.
### Getting the runtime
You can get the runtime via either:
$ 6to5-runtime
or
```javascript
require("6to5").runtime();
```
or from an npm release in `runtime.js` from the 6to5 directory.
### Customising namespace
You can also customise the runtime namespace by passing an optional namespace
argument:
```javascript
require("6to5").runtime("myCustomNamespace");
```
$ 6to5-runtime myCustomNamespace
See [Options - runtime](#options) for documentation on changing the reference in
generated code.
## Differences
### Philosophy
The fundamental concept behind 6to5 is that the generated code must be close as
possible to the original, retaining all the same formatting and readability.
Many other transpilers are just concerned with making the code work while 6to5
is concerned with making sure it works **and** is readable at the same time.
For example, given the following array comprehension:
```javascript
var seattlers = [for (c of customers) if (c.city == "Seattle") { name: c.name, age: c.age }];
```
is generated to the following with 6to5:
```javascript
var seattlers = customers.filter(function (c) {
return c.city == "Seattle";
}).map(function (c) {
return {
name: c.name,
age: c.age
};
});
```
The following is what Traceur generates:
```javascript
var seattlers = (function() {
var c;
var $__20 = 0,
$__21 = [];
for (var $__22 = customers[$traceurRuntime.toProperty(Symbol.iterator)](),
$__23; !($__23 = $__22.next()).done; ) {
c = $__23.value;
if (c.city == "Seattle")
$traceurRuntime.setProperty($__21, $__20++, {
name: c.name,
age: c.age
});
}
return $__21;
}());
```
As you can tell, it's not very pretty, unreadable even. Instead of mapping
directly to a runtime, like other transpilers, 6to5 maps directly to the
equivalent ES5.
I'm not saying 6to5 is for everyone or even suited for everything. Traceur is
better suited if you'd like a full ES6 environment with polyfills and all.
### Comparison to other transpilers
| | 6to5 | Traceur | esnext | es6now | es6-transpiler | jstransform |
| ---------------------------- | ---- | ------- | ------ | ------ | -------------- | ----------- |
| No runtime | ✓ | | | | ✓ | ✓ |
| Source maps | ✓ | ✓ | ✓ | | ✓ | ✓ |
| No compiler global pollution | ✓ | | ✓ | | ✓ | ✓ |
| Arrow functions | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
| Classes | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
| Computed property names | ✓ | ✓ | ✓ | ✓ | ✓ | |
| Constants | ✓ | ✓ | | | ✓ | |
| Default parameters | ✓ | ✓ | ✓ | ✓ | ✓ | |
| Destructuring | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
| For-of | ✓ | ✓ | ✓ | ✓ | ✓ | |
| Generators | ✓ | ✓ | ✓ | | | |
| Let scoping | ✓ | ✓ | | | ✓ | |
| Modules | ✓ | ✓ | | ✓ | | |
| Property method assignment | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
| Property name shorthand | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
| Rest parameters | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
| Spread | ✓ | ✓ | ✓ | ✓ | ✓ | |
| Template literals | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
| Unicode regex | ✓ | ✓ | | | ✓ | |
#### [Traceur](https://github.com/google/traceur-compiler)
Traceur requires quite a bulky runtime (~75KB) and produces quite verbose code.
While this can be trimmed down by selectively building the runtime, it's an
unneccesary step when a runtime can be eliminated entirely.
#### [es6now](https://github.com/zenparsing/es6now)
es6now doesn't output sourcemaps. This is cited as a positive as line-to-line
mapping is the goal. This however obviously doesn't retain column mapping
resulting in the output code not being very pleasant.
#### [es6-transpiler](https://github.com/termi/es6-transpiler)
The es6-transpiler compiler requires shims to operate which pollutes the global
scope resulting in possible collisions.
es6-transpiler maps line-by-line, just like es6now, this results in the same
issues such as lack of column information and unpleasant code output.
For more information view the [documentation](https://6to5.github.io).

View File

@@ -10,7 +10,7 @@ install:
test_script:
- "node --version"
- "npm --version"
- "make test-appveyor"
- "make test-spec"
build: "off"

View File

@@ -1,10 +1,10 @@
#!/usr/bin/env node
var commander = require("commander");
var util = require("../lib/6to5/util");
var path = require("path");
var repl = require("repl");
var to5 = require("../lib/6to5");
var util = require("../lib/6to5/util");
var vm = require("vm");
var _ = require("lodash");

61
doc/browser.md Normal file
View File

@@ -0,0 +1,61 @@
# Browser
A browser version of 6to5 is available from `browser.js` inside the 6to5
directory in an npm release.
## Scripts
While it's not recommended for serious use, when the browser version is included
all scripts with the type `text/ecmascript-6` and `text/6to5` are automatically
compiled and ran.
For example:
```html
<script src="node_modules/6to5/browser.js"></script>
<script type="text/6to5">
class Test {
test() {
return "test";
}
}
var test = new Test;
test.test();
</script>
```
## Build
You can build a browser version of the compiler by running the following in the
6to5 directory:
$ make build
This will output the files `dist/6to5.js` and `dist/6to5.min.js`.
## Test
To test 6to5 in your browser run:
$ make test-browser
And open `test/browser.html` in your browser if it doesn't open automatically.
## API
### to5.transform(code, [opts])
See [options](usage.md#options) for additional documentation.
```javascript
to5.transform("class Test {}").code;
```
### to5.run(code, [opts])
See [options](usage.md#options) for additional documentation.
```javascript
to5.run("class Test {}");
```

43
doc/caveats.md Normal file
View File

@@ -0,0 +1,43 @@
# Caveats
## Async/Generators
The [regenerator runtime](https://github.com/facebook/regenerator/blob/master/runtime.js)
and an [ES6 polyfill](polyfill.md) are required in order for generators to work.
## Classes
Built-in classes such as `Date`, `Array` and `DOM` cannot be subclassed due to
limitations in ES5 implementations.
If you're inheriting from a class then static properties are inherited from it
via [\_\_proto\_\_](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/proto),
this is widely supported but you may run into problems with much older browsers.
**NOTE:** `__proto__` is not supported on IE <= 9 so static properties
**will not** be inherited. A possible workaround is to use `super();`:
```javascript
class Foo {
static foo() {
}
}
class Bar extends Foo {
static foo() {
super();
}
}
```
## For-of
A polyfill is required for for-of functionality that implements `Symbol` and
adds `prototype[Symbol.iterator]` behaviour to built-ins. Using the polyfills
specified in [polyfill](polyfill.md) suffices.
## Spread
An [ES6 polyfill](polyfill.md) is required in order for spread to work. More
specifically a polyfill for `Array.from`.

103
doc/differences.md Normal file
View File

@@ -0,0 +1,103 @@
# Differences
## Philosophy
The fundamental concept behind 6to5 is that the generated code must be close as
possible to the original, retaining all the same formatting and readability.
Many other transpilers are just concerned with making the code work while 6to5
is concerned with making sure it works **and** is readable at the same time.
For example, given the following array comprehension:
```javascript
var seattlers = [for (c of customers) if (c.city == "Seattle") { name: c.name, age: c.age }];
```
is generated to the following with 6to5:
```javascript
var seattlers = customers.filter(function (c) {
return c.city == "Seattle";
}).map(function (c) {
return {
name: c.name,
age: c.age
};
});
```
The following is what Traceur generates:
```javascript
var seattlers = (function() {
var c;
var $__20 = 0,
$__21 = [];
for (var $__22 = customers[$traceurRuntime.toProperty(Symbol.iterator)](),
$__23; !($__23 = $__22.next()).done; ) {
c = $__23.value;
if (c.city == "Seattle")
$traceurRuntime.setProperty($__21, $__20++, {
name: c.name,
age: c.age
});
}
return $__21;
}());
```
As you can tell, it's not very pretty, unreadable even. Instead of mapping
directly to a runtime, like other transpilers, 6to5 maps directly to the
equivalent ES5.
I'm not saying 6to5 is for everyone or even suited for everything. Traceur is
better suited if you'd like a full ES6 environment with polyfills and all.
## Comparison to other transpilers
| | 6to5 | Traceur | esnext | es6now | es6-transpiler | jstransform |
| ---------------------------- | ---- | ------- | ------ | ------ | -------------- | ----------- |
| No runtime | ✓ | | | | ✓ | ✓ |
| Source maps | ✓ | ✓ | ✓ | | ✓ | ✓ |
| No compiler global pollution | ✓ | | ✓ | | ✓ | ✓ |
| Browser support | ✓ | ✓ | ✓ | | | |
| Array comprehension | ✓ | ✓ | | | ✓ | |
| Arrow functions | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
| Async functions | ✓ | ✓ | ✓ | | | |
| Classes | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
| Computed property names | ✓ | ✓ | ✓ | ✓ | ✓ | |
| Constants | ✓ | ✓ | | | ✓ | |
| Default parameters | ✓ | ✓ | ✓ | ✓ | ✓ | |
| Destructuring | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
| For-of | ✓ | ✓ | ✓ | ✓ | ✓ | |
| Generators | ✓ | ✓ | ✓ | | | |
| Generator comprehension | ✓ | ✓ | | | | |
| Let scoping | ✓ | ✓ | | | ✓ | |
| Modules | ✓ | ✓ | | ✓ | | |
| Property method assignment | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
| Property name shorthand | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
| Rest parameters | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
| Spread | ✓ | ✓ | ✓ | ✓ | ✓ | |
| Template literals | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
| Unicode regex | ✓ | ✓ | | | ✓ | |
### [Traceur](https://github.com/google/traceur-compiler)
Traceur requires quite a bulky runtime (~75KB) and produces quite verbose code.
While this can be trimmed down by selectively building the runtime, it's an
unneccesary step when a runtime can be eliminated entirely.
### [es6now](https://github.com/zenparsing/es6now)
es6now doesn't output sourcemaps. This is cited as a positive as line-to-line
mapping is the goal. This however obviously doesn't retain column mapping
resulting in the output code not being very pleasant.
### [es6-transpiler](https://github.com/termi/es6-transpiler)
The es6-transpiler compiler requires shims to operate which pollutes the global
scope resulting in possible collisions.
es6-transpiler maps line-by-line, just like es6now, this results in the same
issues such as lack of column information and unpleasant code output.

223
doc/features.md Normal file
View File

@@ -0,0 +1,223 @@
# Features
## Array comprehension
```javascript
var results = [for (c of customers) if (c.city == "Seattle") { name: c.name, age: c.age }]
```
## Arrow functions
```javascript
// Expression bodies
var odds = evens.map(v => v + 1);
var nums = evens.map((v, i) => v + i);
// Statement bodies
nums.forEach(v => {
if (v % 5 === 0)
fives.push(v);
});
// Lexical this
var bob = {
_name: "Bob",
_friends: [],
printFriends() {
this._friends.forEach(f => {
console.log(this._name + " knows " + f);
});
}
};
```
## Async functions
```javascript
async function chainAnimationsAsync(elem, animations) {
for (var anim of animations) {
await anim(elem);
}
}
```
## Classes
```javascript
class SkinnedMesh extends THREE.Mesh {
constructor(geometry, materials) {
super(geometry, materials);
this.idMatrix = SkinnedMesh.defaultMatrix();
this.bones = [];
this.boneMatrices = [];
//...
}
update(camera) {
//...
super.update();
}
static defaultMatrix() {
return new THREE.Matrix4();
}
}
```
## Computed property names
```javascript
var foo = "foo";
var bar = "bar";
var obj = {
["foo" + bar]: "heh",
["bar" + foo]: "noo",
foo: "foo",
bar: "bar"
};
```
## Constants
```javascript
const MULTIPLIER = 5;
console.log(2 * MULTIPLIER);
MULTIPLIER = 6; // error
var MULTIPLIER; // error
```
## Default parameters
```javascript
function f(x, y = 12) {
// y is 12 if not passed (or passed as undefined)
return x + y;
}
f(3) == 15
```
## Destructuring
```javascript
// list matching
var [a, , b] = [1,2,3];
// object matching
var { op: a, lhs: { op: b }, rhs: c } = getASTNode();
// object matching shorthand
// binds `op`, `lhs` and `rhs` in scope
var { op, lhs, rhs } = getASTNode();
// Can be used in parameter position
function g({ name: x }) {
console.log(x);
}
g({ name: 5 });
// Fail-soft destructuring
var [a] = [];
a === undefined;
```
## For-of
```javascript
for (var i of [1, 2, 3]) {
console.log(i * i);
}
```
## Generators
```javascript
```
## Generator comprehension
```javascript
```
## Let scoping
```javascript
for (let i in arr) {
let v = arr[i];
}
```
## Modules
```javascript
```
## Numeric literals
```javascript
0b111110111 === 503; // true
0o767 === 503; // true
```
## Property method assignment
```javascript
var obj = {
foo() {
return "foobar";
},
get bar() {
return this._bar;
},
set bar(val) {
this._bar = val;
}
};
```
## Property name shorthand
```javascript
function f(x, y) {
return { x, y };
}
```
## Rest parameters
```javascript
function f(x, ...y) {
// y is an Array
return x * y.length;
}
f(3, "hello", true) == 6
```
## Spread
```javascript
function f(x, y, z) {
return x + y + z;
}
// Pass each elem of array as argument
f(...[1,2,3]) == 6
```
## Template literals
```javascript
var x = 5;
var y = 10;
console.log(`${x} + ${y} = ${x + y}`); // "5 + 10 = 15"
```
## Unicode regex
```javascript
var string = 'foo💩bar';
var match = string.match(/foo(.)bar/u);
console.log(match[1]);
```

54
doc/index.md Normal file
View File

@@ -0,0 +1,54 @@
**6to5** turns ES6+ code into vanilla ES5, so you can use next generation features **today.**
- **Readable** - formatting is retained if possible so your generated code is as similar as possible.
- **Extensible** - with a large range of [plugins](plugins.md) and **browser support**.
- **Lossless** - **source map support** so you can debug your compiled code with ease.
- **Compact** - maps directly to the equivalent ES5 with **no runtime**[\*](caveats.md#generators).
## Installation
It's as easy as:
$ npm install -g 6to5
## Usage
Once you've installed 6to5, there are multiple paths you can take depending on
how you want to use it.
6to5 will simply compile your ES6+ script to ES5 if you pass it as an argument
to the command-line tool `6to5`:
$ 6to5 script.js
If you have a file written using ES6+ and you just want to run it, `6to5-node`
has you covered:
$ 6to5-node script.js
And it doesn't end here! To see all the ways you can use 6to5, check out the
[Usage](http://6to5.github.io/usage.html) page.
## [Features](features.md)
- [Array comprehension](features.md#array-comprehension)
- [Async functions](features.md#async-functions) via [regenerator](https://github.com/facebook/regenerator)
- [Arrow functions](features.md#arrow-functions)
- [Classes](features.md#classes)
- [Computed property names](features.md#computed-property-names)
- [Constants](features.md#constants)
- [Default parameters](features.md#default-parameters)
- [Destructuring](features.md#destructuring)
- [For-of](features.md#for-of)
- [Generators](features.md#generators) via [regenerator](https://github.com/facebook/regenerator)
- [Generator comprehension](features.md#generator-comprehension)
- [Let scoping](features.md#let-scoping)
- [Modules](features.md#modules)
- [Numeric literals](features.md#numeric-literals)
- [Property method assignment](features.md#property-method-assignment)
- [Property name shorthand](features.md#property-name-shorthand)
- [React/JSX](react.md)
- [Rest parameters](features.md#rest-parameters)
- [Spread](features.md#spread)
- [Template literals](features.md#template-literals)
- [Unicode regex](features.md#unicode-regex)

51
doc/optional-runtime.md Normal file
View File

@@ -0,0 +1,51 @@
# Optional runtime
6to5 has a few helper functions that'll be placed at the top of the generated
code if needed so it's not inlined multiple times throughout that file. This may
become an issue if you have multiple files, especially when you're sending them
to the browser. gzip alleviates most of this concern but it's still not ideal.
You can tell 6to5 to not place any declarations at the top of your files and
instead just point them to a reference contained within the runtime.
Simply use the following option if you're using the [Node API](usage.md#node):
```javascript
{
runtime: true
}
```
or the following flag if you're using the [CLI](usage.md#cli):
$ 6to5 --runtime
Then just include the runtime before your generated code.
## Getting the runtime
You can get the runtime via either:
$ 6to5-runtime
or
```javascript
require("6to5").runtime();
```
or from an npm release in `runtime.js` from the 6to5 directory.
## Customising namespace
You can also customise the runtime namespace by passing an optional namespace
argument:
```javascript
require("6to5").runtime("myCustomNamespace");
```
$ 6to5-runtime myCustomNamespace
See [Options - runtime](usage.md#options) for documentation on changing the
reference in generated code.

15
doc/plugins.md Normal file
View File

@@ -0,0 +1,15 @@
# Plugins
- [Broccoli](https://github.com/very-geek/broccoli-6to5-transpiler)
- [Browserify](https://github.com/6to5/6to5-browserify)
- [Brunch](https://github.com/es128/6to5-brunch)
- [Duo](https://github.com/bdo-labs/duo6to5)
- [Connect](https://github.com/6to5/6to5-connect)
- [Gulp](https://github.com/sindresorhus/gulp-6to5)
- [Grunt](https://github.com/sindresorhus/grunt-6to5)
- [Jade](https://github.com/Apoxx/jade-6to5)
- [Jest](https://github.com/6to5/6to5-jest)
- [Karma](https://github.com/shuhei/karma-6to5-preprocessor)
- [Mocha](https://github.com/6to5/6to5-mocha)
- [Rails](https://github.com/6to5/6to5-rails)
- [webpack](https://github.com/Couto/6to5-loader)

17
doc/polyfill.md Normal file
View File

@@ -0,0 +1,17 @@
# Polyfill
6to5 includes a polyfill that includes the
[regenerator runtime](https://github.com/facebook/regenerator/blob/master/runtime.js) and the
[es6-shim](https://github.com/paulmillr/es6-shim) and
[es6-symbol](https://github.com/medikoo/es6-symbol) polyfills.
## Node
```javascript
require("6to5/polyfill");
```
## Browser
Available from the `browser-polyfill.js` file within the 6to5 directory of an
npm release.

16
doc/react.md Normal file
View File

@@ -0,0 +1,16 @@
# React/JSX
6to5 has built-in support for React v0.12. Tags are automatically transformed to
their equivalent `React.createElement(...)` and `displayName` is automatically
inferred and added to all `React.createClass` calls.
## Blacklist
To disable this behaviour add `react` to your blacklist:
```javascript
to5.transform("code", { blacklist: ["react"] });
```
$ 6to5 --blacklist react

161
doc/usage.md Normal file
View File

@@ -0,0 +1,161 @@
# Usage
## CLI
Compile the file `script.js` and output it to stdout.
$ 6to5 script.js
Compile the file `script.js` and output it to `script-compiled.js`.
$ 6to5 script.js --out-file script-compiled.js
Compile the file `script.js` and output it to `script-compiled.js` and save a
source map to `script-compiled.js.map`.
$ 6to5 script.js --source-maps --out-file script-compiled.js
Compile the file `script.js` and output it to `script-compiled.js` with a source
map embedded in a comment at the bottom.
$ 6to5 script.js --source-maps-inline --out-file script-compiled.js
Compile the entire `src` directory and output it to the `lib` directory.
$ 6to5 src --out-dir lib
Compile the entire `src` directory and output it to the one concatenated file.
$ 6to5 src --out-file script-compiled.js
Pipe a file in via stdin and output it to `script-compiled.js`
$ 6to5 --out-file script-compiled.js < script.js
### Node
Launch a repl.
$ 6to5-node
Evaluate code.
$ 6to5-node -e "class Test { }"
Compile and run `test.js`.
$ 6to5-node test
## Node
```javascript
var to5 = require("6to5");
```
### to5.transform(code, [opts]);
```javascript
var result = to5.transform("code();", options);
result.code;
result.map;
result.ast;
```
### to5.transformFileSync(filename, [opts])
```javascript
to5.transformFileSync("filename.js", options).code;
```
### to5.transformFile(filename, [opts], callback)
```javascript
to5.transformFile("filename.js", options, function (err, result) {
result.code;
});
```
#### Options
```javascript
{
// Filename for use in errors etc.
// Default: "unknown"
filename: "filename",
// List of transformers to EXCLUDE.
// Run `6to5 --help` to see a full list of transformers.
blacklist: [],
// List of transformers to ONLY use.
// Run `6to5 --help` to see a full list of transformers.
whitelist: [],
// Module formatter to use
// Run `6to5 --help` to see a full list of module formatters.
// Default: "common"
modules: "common",
// If truthy, adds a `map` property to returned output.
// If set to "inline", a comment with a sourceMappingURL directive is added to
// the bottom of the returned code.
// Default: false
sourceMap: true,
// Set `file` on returned source map.
// Default: `filename` option.
sourceMapName: "filename",
// Set `sources[0]` on returned source map.
// Default: `filename` option.
sourceFileName: "filename",
// Optionally replace all 6to5 helper declarations with a referenece to this
// variable. If set to `true` then the default namespace is used "to5Runtime".
// Default: false
runtime: true
}
```
### Require hook
All subsequent files required by node with the extensions `.es6` and `.js` will
be transformed by 6to5. The polyfill specified in [Polyfill](polyfill.md) is
also required.
```javascript
require("6to5/register");
```
**NOTE:** By default all requires to `node_modules` will be ignored. You can
override this by passing an ignore regex via:
```javascript
require("6to5/register")({
// This will override `node_modules` ignoring - you can alternatively pass
// a regex
ignore: false
});
```
#### Options
```javascript
require("6to5/register")({
// Optional ignore regex - if any filenames **do** match this regex then they
// aren't compiled
ignore: /regex/,
// Optional only regex - if any filenames **don't** match this regex then they
// aren't compiled
only: /my_es6_folder/,
// See options above for usage
whitelist: [],
blacklist: [],
// This will remove the currently hooked extensions of .es6 and .js so you'll
// have to add them back if you want them to be used again.
extensions: [".js", ".es6"]
});
```

View File

@@ -2,13 +2,6 @@ var transform = module.exports = require("./transformation/transform");
transform.transform = transform;
transform.eval = function (code, opts) {
opts = opts || {};
opts.filename = opts.filename || "eval";
opts.sourceMap = "inline";
return eval(transform(code, opts).code);
};
transform.run = function (code, opts) {
opts = opts || {};
opts.sourceMap = "inline";

View File

@@ -18,7 +18,7 @@ function File(opts) {
this.ast = {};
}
File.declarations = ["extends", "class-props", "slice"];
File.declarations = ["extends", "class-props", "slice", "apply-constructor"];
File.normaliseOptions = function (opts) {
opts = _.cloneDeep(opts || {});
@@ -30,9 +30,13 @@ File.normaliseOptions = function (opts) {
sourceMap: false,
filename: "unknown",
modules: "common",
runtime: false
runtime: false,
code: true
});
// normalise windows path separators to unix
opts.filename = opts.filename.replace(/\\/g, "/");
_.defaults(opts, {
sourceFileName: opts.filename,
sourceMapName: opts.filename
@@ -139,17 +143,27 @@ File.prototype.generate = function () {
var opts = this.opts;
var ast = this.ast;
if (!opts.code) {
return {
code: "",
map: null,
ast: ast
};
}
var result = generate(ast, opts, this.code);
if (this.shebang) {
// add back shebang
result.code = this.shebang + result.code;
result.code = this.shebang + "\n" + result.code;
}
if (opts.sourceMap === "inline") {
result.code += "\n" + util.sourceMapToComment(result.map);
}
result.ast = result;
return result;
};

View File

@@ -0,0 +1,125 @@
module.exports = Buffer;
var util = require("../util");
var _ = require("lodash");
function Buffer(position, format) {
this.position = position;
this._indent = format.indent.base;
this.format = format;
this.buf = "";
}
Buffer.prototype.get = function () {
return util.trimRight(this.buf);
};
Buffer.prototype.getIndent = function () {
if (this.format.compact) {
return "";
} else {
return util.repeat(this._indent, this.format.indent.style);
}
};
Buffer.prototype.indentSize = function () {
return this.getIndent().length;
};
Buffer.prototype.indent = function () {
this._indent++;
};
Buffer.prototype.dedent = function () {
this._indent--;
};
Buffer.prototype.semicolon = function () {
if (this.format.semicolons) this.push(";");
};
Buffer.prototype.ensureSemicolon = function () {
if (!this.isLast(";")) this.semicolon();
};
Buffer.prototype.rightBrace = function () {
this.newline(true);
this.push("}");
};
Buffer.prototype.keyword = function (name) {
this.push(name);
this.push(" ");
};
Buffer.prototype.space = function () {
if (this.buf && !this.isLast([" ", "\n"])) {
this.push(" ");
}
};
Buffer.prototype.removeLast = function (cha) {
if (!this.isLast(cha)) return;
this.buf = this.buf.slice(0, -1);
this.position.unshift(cha);
};
Buffer.prototype.newline = function (i, removeLast) {
if (!this.buf) return;
if (this.format.compact) return;
if (this.endsWith("{\n")) return;
if (_.isBoolean(i)) {
removeLast = i;
i = null;
}
if (_.isNumber(i)) {
if (this.endsWith(util.repeat(i, "\n"))) return;
var self = this;
_.times(i, function () {
self.newline(null, removeLast);
});
return;
}
if (removeLast && this.isLast("\n")) this.removeLast("\n");
this.removeLast(" ");
this.buf = this.buf.replace(/\n +$/, "\n");
this._push("\n");
};
Buffer.prototype.push = function (str, noIndent) {
if (this._indent && !noIndent && str !== "\n") {
// we have an indent level and we aren't pushing a newline
var indent = this.getIndent();
// replace all newlines with newlines with the indentation
str = str.replace(/\n/g, "\n" + indent);
// we've got a newline before us so prepend on the indentation
if (this.isLast("\n")) str = indent + str;
}
this._push(str);
};
Buffer.prototype._push = function (str) {
this.position.push(str);
this.buf += str;
};
Buffer.prototype.endsWith = function (str) {
return this.buf.slice(-str.length) === str;
};
Buffer.prototype.isLast = function (cha, trimRight) {
var buf = this.buf;
if (trimRight) buf = util.trimRight(buf);
var chars = [].concat(cha);
return _.contains(chars, _.last(buf));
};

View File

@@ -8,6 +8,7 @@ module.exports.CodeGenerator = CodeGenerator;
var Whitespace = require("./whitespace");
var SourceMap = require("./source-map");
var Position = require("./position");
var Buffer = require("./buffer");
var util = require("../util");
var n = require("./node");
var t = require("../types");
@@ -16,165 +17,66 @@ var _ = require("lodash");
function CodeGenerator(ast, opts, code) {
opts = opts || {};
this.style = {
semicolons: true,
comments: true,
compact: false,
indent: {
char: " ",
width: 2
}
};
this.comments = ast.comments || [];
this.tokens = ast.tokens || [];
this.opts = opts;
this.format = CodeGenerator.normaliseOptions(opts);
this.ast = ast;
this.buf = "";
this._indent = 0;
this.whitespace = new Whitespace(this.tokens, this.comments);
this.position = new Position;
this.map = new SourceMap(this.position, opts, code);
this.buffer = new Buffer(this.position, this.format);
}
_.each(Buffer.prototype, function (fn, key) {
CodeGenerator.prototype[key] = function () {
return fn.apply(this.buffer, arguments);
};
});
CodeGenerator.normaliseOptions = function (opts) {
opts = opts.format || {};
opts = _.merge({
parentheses: true,
semicolons: true,
comments: true,
compact: false,
indent: {
adjustMultilineComment: true,
style: " ",
base: 0
}
}, opts);
return opts;
};
CodeGenerator.generators = {
arrayComprehensions: require("./generators/array-comprehensions"),
templateLiterals: require("./generators/template-literals"),
expressions: require("./generators/expressions"),
statements: require("./generators/statements"),
classes: require("./generators/classes"),
methods: require("./generators/methods"),
modules: require("./generators/modules"),
types: require("./generators/types"),
base: require("./generators/base"),
jsx: require("./generators/jsx")
templateLiterals: require("./generators/template-literals"),
comprehensions: require("./generators/comprehensions"),
expressions: require("./generators/expressions"),
statements: require("./generators/statements"),
classes: require("./generators/classes"),
methods: require("./generators/methods"),
modules: require("./generators/modules"),
types: require("./generators/types"),
base: require("./generators/base"),
jsx: require("./generators/jsx")
};
_.each(CodeGenerator.generators, function (generator) {
_.extend(CodeGenerator.prototype, generator);
});
CodeGenerator.prototype.newline = function (i, removeLast) {
if (!this.buf) return;
if (this.style.compact) return;
if (this.endsWith("{\n")) return;
if (_.isBoolean(i)) {
removeLast = i;
i = null;
}
if (_.isNumber(i)) {
var self = this;
_.times(i, function () {
self.newline(null, removeLast);
});
return;
}
if (removeLast && this.isLast("\n")) this.removeLast("\n");
this.removeLast(" ");
this.buf = this.buf.replace(/\n(\s+)$/, "\n");
this._push("\n");
};
CodeGenerator.prototype.removeLast = function (cha) {
if (!this.isLast(cha)) return;
this.buf = this.buf.slice(0, -1);
this.position.unshift(cha);
};
CodeGenerator.prototype.semicolon = function () {
if (this.style.semicolons) this.push(";");
};
CodeGenerator.prototype.ensureSemicolon = function () {
if (!this.isLast(";")) this.semicolon();
};
CodeGenerator.prototype.rightBrace = function () {
this.newline(true);
this.push("}");
};
CodeGenerator.prototype.keyword = function (name) {
this.push(name);
this.push(" ");
};
CodeGenerator.prototype.space = function () {
if (this.buf && !this.isLast([" ", "\n"])) {
this.push(" ");
}
};
CodeGenerator.prototype.push = function (str, noIndent) {
if (this._indent && !noIndent && str !== "\n") {
// we have an indent level and we aren't pushing a newline
var indent = this.getIndent();
// replace all newlines with newlines with the indentation
str = str.replace(/\n/g, "\n" + indent);
// we've got a newline before us so prepend on the indentation
if (this.isLast("\n")) str = indent + str;
}
this._push(str);
};
CodeGenerator.prototype._push = function (str) {
this.position.push(str);
this.buf += str;
};
CodeGenerator.prototype.endsWith = function (str) {
return this.buf.slice(-str.length) === str;
};
CodeGenerator.prototype.isLast = function (cha, trimRight) {
var buf = this.buf;
if (trimRight) buf = buf.trimRight();
var chars = [].concat(cha);
return _.contains(chars, _.last(buf));
};
CodeGenerator.prototype.getIndent = function () {
if (this.style.compact) {
return "";
} else {
return util.repeat(this.indentSize(), this.style.indent.char);
}
};
CodeGenerator.prototype.indentSize = function () {
return this._indent * this.style.indent.width;
};
CodeGenerator.prototype.indent = function () {
this._indent++;
};
CodeGenerator.prototype.dedent = function () {
this._indent--;
};
CodeGenerator.prototype.generate = function () {
var ast = this.ast;
this.print(ast);
this.buf = this.buf.trimRight();
return {
map: this.map.get(),
ast: ast,
code: this.buf
code: this.buffer.get()
};
};
@@ -213,8 +115,6 @@ CodeGenerator.prototype.print = function (node, parent, opts) {
opts = opts || {};
var newline = function (leading) {
var ignoreDuplicates = false;
if (!opts.statement && !n.isUserWhitespacable(node, parent)) {
return;
}
@@ -237,7 +137,7 @@ CodeGenerator.prototype.print = function (node, parent, opts) {
lines += needs(node, parent);
}
self.newline(lines, ignoreDuplicates);
self.newline(lines);
};
if (this[node.type]) {
@@ -353,8 +253,8 @@ CodeGenerator.prototype._getComments = function (key, node) {
};
CodeGenerator.prototype._printComments = function (comments) {
if (this.style.compact) return;
if (!this.style.comments) return;
if (this.format.compact) return;
if (!this.format.comments) return;
if (!comments || !comments.length) return;
var self = this;
@@ -373,14 +273,16 @@ CodeGenerator.prototype._printComments = function (comments) {
//
var offset = comment.loc.start.column;
if (offset) {
var newlineRegex = new RegExp("\\n\\s{1," + offset + "}", "g");
val = val.replace(newlineRegex, "\n");
}
if (comment.type === "Block" && self.format.indent.adjustMultilineComment) {
var offset = comment.loc.start.column;
if (offset) {
var newlineRegex = new RegExp("\\n\\s{1," + offset + "}", "g");
val = val.replace(newlineRegex, "\n");
}
var indent = Math.max(self.indentSize(), column);
val = val.replace(/\n/g, "\n" + util.repeat(indent));
var indent = Math.max(self.indentSize(), column);
val = val.replace(/\n/g, "\n" + util.repeat(indent));
}
if (column === 0) {
val = self.getIndent() + val;

View File

@@ -30,3 +30,11 @@ exports.ClassBody = function (node, print) {
this.rightBrace();
}
};
exports.MethodDefinition = function (node, print) {
if (node.static) {
this.push("static ");
}
this._method(node, print);
};

View File

@@ -8,7 +8,8 @@ exports.ComprehensionBlock = function (node, print) {
};
exports.ComprehensionExpression = function (node, print) {
this.push("[");
this.push(node.generator ? "(" : "[");
print.join(node.blocks, { separator: " " });
this.space();
@@ -21,5 +22,6 @@ exports.ComprehensionExpression = function (node, print) {
}
print(node.body);
this.push("]");
this.push(node.generator ? ")" : "]");
};

View File

@@ -44,9 +44,11 @@ exports.ConditionalExpression = function (node, print) {
exports.NewExpression = function (node, print) {
this.push("new ");
print(node.callee);
this.push("(");
print.join(node.arguments, { separator: ", " });
this.push(")");
if (node.arguments.length || this.format.parentheses) {
this.push("(");
print.join(node.arguments, { separator: ", " });
this.push(")");
}
};
exports.SequenceExpression = function (node, print) {
@@ -64,15 +66,20 @@ exports.CallExpression = function (node, print) {
this.push(")");
};
exports.YieldExpression = function (node, print) {
this.push("yield");
if (node.delegate) this.push("*");
if (node.argument) {
this.space();
print(node.argument);
}
var buildYieldAwait = function (keyword) {
return function (node, print) {
this.push(keyword);
if (node.delegate) this.push("*");
if (node.argument) {
this.space();
print(node.argument);
}
};
};
exports.YieldExpression = buildYieldAwait("yield");
exports.AwaitExpression = buildYieldAwait("await");
exports.EmptyStatement = function () {
this.semicolon();
};

View File

@@ -46,15 +46,11 @@ exports.XJSElement = function (node, print) {
this.indent();
_.each(node.children, function (child) {
if (t.isLiteral(child) && typeof child.value === "string") {
if (/\S/.test(child.value)) {
return self.push(child.value.replace(/^\s+|\s+$/g, ""));
} else if (/\n/.test(child.value)) {
return self.newline();
}
if (t.isLiteral(child)) {
self.push(child.value);
} else {
print(child);
}
print(child);
});
this.dedent();
@@ -78,5 +74,5 @@ exports.XJSClosingElement = function (node, print) {
};
exports.XJSEmptyExpression = function () {
this.push("null");
};

View File

@@ -41,6 +41,8 @@ exports._method = function (node, print) {
this.push(kind + " ");
}
if (value.async) this.push("async ");
if (node.computed) {
this.push("[");
print(key);
@@ -54,16 +56,9 @@ exports._method = function (node, print) {
print(value.body);
};
exports.MethodDefinition = function (node, print) {
if (node.static) {
this.push("static ");
}
this._method(node, print);
};
exports.FunctionDeclaration =
exports.FunctionExpression = function (node, print) {
if (node.async) this.push("async ");
this.push("function");
if (node.generator) this.push("*");
this.space();
@@ -74,6 +69,8 @@ exports.FunctionExpression = function (node, print) {
};
exports.ArrowFunctionExpression = function (node, print) {
if (node.async) this.push("async ");
if (node.params.length === 1 && !node.defaults.length && !node.rest && t.isIdentifier(node.params[0])) {
print(node.params[0]);
} else {

View File

@@ -25,9 +25,10 @@ exports.ExportDeclaration = function (node, print) {
if (node.declaration) {
print(node.declaration);
if (t.isStatement(node.declaration)) return;
} else {
if (specifiers.length === 1 && t.isExportBatchSpecifier(specifiers[0])) {
this.push("*");
print(specifiers[0]);
} else {
this.push("{");
if (specifiers.length) {

View File

@@ -4,6 +4,7 @@ exports.WithStatement = function (node, print) {
this.keyword("with");
this.push("(");
print(node.object);
this.push(")");
print.block(node.body);
};
@@ -134,15 +135,6 @@ exports.SwitchStatement = function (node, print) {
this.push(") {");
print.sequence(node.cases, { indent: true });
this.push("}");
//if (node.cases.length) {
// this.newline();
// print.sequence(node.cases, { indent: true });
// this.newline();
// this.rightBrace();
//} else {
// this.push("}");
//}
};
exports.SwitchCase = function (node, print) {
@@ -154,13 +146,8 @@ exports.SwitchCase = function (node, print) {
this.push("default:");
}
if (node.consequent.length === 1) {
this.space();
print(node.consequent[0]);
} else if (node.consequent.length > 1) {
this.newline();
print.sequence(node.consequent, { indent: true });
}
this.space();
print.sequence(node.consequent, { indent: true });
};
exports.DebuggerStatement = function () {

View File

@@ -74,13 +74,20 @@ exports.Literal = function (node) {
var val = node.value;
var type = typeof val;
if (type === "boolean" || type === "number" || type === "string") {
if (type === "string") {
val = JSON.stringify(val);
// escape unicode characters
val = val.replace(/[\u007f-\uffff]/g, function(c) {
return "\\u" + ("0000" + c.charCodeAt(0).toString(16)).slice(-4);
});
this.push(val);
} else if (type === "boolean" || type === "number") {
this.push(JSON.stringify(val));
} else if (node.regex) {
this.push("/" + node.regex.pattern + "/" + node.regex.flags);
} else if (val === null) {
this.push("null");
} else if (node.raw) {
this.push(node.raw);
}
};

View File

@@ -1,290 +0,0 @@
module.exports = Node;
var t = require("../types");
var _ = require("lodash");
function Node(node, parent) {
this.parent = parent;
this.node = node;
}
//
Node.whitespace = {
FunctionExpression: 1,
FunctionStatement: 1,
ClassExpression: 1,
ClassStatement: 1,
ForOfStatement: 1,
ForInStatement: 1,
ForStatement: 1,
SwitchStatement: 1,
IfStatement: { before: 1 },
//Property: { before: 1 },
Literal: { after: 1 }
};
_.each(Node.whitespace, function (amounts, type) {
if (_.isNumber(amounts)) amounts = { after: amounts, before: amounts };
Node.whitespace[type] = amounts;
});
//
Node.PRECEDENCE = {};
_.each([
["||"],
["&&"],
["|"],
["^"],
["&"],
["==", "===", "!=", "!=="],
["<", ">", "<=", ">=", "in", "instanceof"],
[">>", "<<", ">>>"],
["+", "-"],
["*", "/", "%"]
], function (tier, i) {
_.each(tier, function (op) {
Node.PRECEDENCE[op] = i;
});
});
//
Node.prototype.isUserWhitespacable = function () {
//var parent = this.parent;
var node = this.node;
if (t.isUserWhitespacable(node)) {
return true;
}
//if (t.isArrayExpression(parent)) {
// return true;
//}
return false;
};
Node.prototype.needsWhitespace = function (type) {
var parent = this.parent;
var node = this.node;
if (!node) return 0;
if (t.isExpressionStatement(node)) {
node = node.expression;
}
if (type === "before") {
if (t.isProperty(node) && parent.properties[0] === node) {
return 1;
}
}
if (type === "after") {
if (t.isCallExpression(node)) {
return 1;
}
var exprs = [];
if (t.isVariableDeclaration(node)) {
exprs = _.map(node.declarations, "init");
}
if (t.isArrayExpression(node)) {
exprs = node.elements;
}
if (t.isObjectExpression(node)) {
exprs = node.properties;
}
var lines = 0;
_.each(exprs, function (expr) {
lines = Node.needsWhitespace(expr, node, type);
if (lines) return false;
});
if (lines) return lines;
}
if (t.isCallExpression(node) && t.isFunction(node.callee)) {
return 1;
}
var opts = Node.whitespace[node.type];
return (opts && opts[type]) || 0;
};
Node.prototype.needsWhitespaceBefore = function () {
return this.needsWhitespace("before");
};
Node.prototype.needsWhitespaceAfter = function () {
return this.needsWhitespace("after");
};
Node.prototype.needsParens = function () {
var parent = this.parent;
var node = this.node;
if (!parent) return false;
//
if (t.isUnaryLike(node)) {
return t.isMemberExpression(parent) && parent.object === node;
}
if (t.isBinary(node)) {
//
if (t.isCallExpression(parent) && parent.callee === node) {
return true;
}
//
if (t.isUnaryLike(parent)) {
return true;
}
//
if (t.isMemberExpression(parent) && parent.object === node) {
return true;
}
if (t.isBinary(parent)) {
var parentOp = parent.operator;
var parentPos = Node.PRECEDENCE[parentOp];
var nodeOp = node.operator;
var nodePos = Node.PRECEDENCE[nodeOp];
if (parentPos > nodePos) {
return true;
}
if (parentPos === nodePos && parent.right === node) {
return true;
}
}
}
if (t.isBinaryExpression(node) && node.operator === "in") {
// var i = (1 in []);
if (t.isVariableDeclarator(parent)) {
return true;
}
// for ((1 in []);;);
if (t.isFor(parent)) {
return true;
}
}
// (class {});
if (t.isClassExpression(node) && t.isExpressionStatement(parent)) {
return true;
}
if (t.isSequenceExpression(node)) {
if (t.isForStatement(parent)) {
// Although parentheses wouldn't hurt around sequence
// expressions in the head of for loops, traditional style
// dictates that e.g. i++, j++ should not be wrapped with
// parentheses.
return false;
}
if (t.isExpressionStatement(parent) && parent.expression === node) {
return false;
}
// Otherwise err on the side of overparenthesization, adding
// explicit exceptions above if this proves overzealous.
return true;
}
//
if (t.isYieldExpression(node)) {
return t.isBinary(parent) ||
t.isUnaryLike(parent) ||
t.isCallExpression(parent) ||
t.isMemberExpression(parent) ||
t.isNewExpression(parent) ||
t.isConditionalExpression(parent) ||
t.isYieldExpression(parent);
}
if (t.isNewExpression(parent) && parent.callee === node) {
return t.isCallExpression(node) || _.some(node, function (val) {
return t.isCallExpression(val);
});
}
// (1).valueOf()
if (t.isLiteral(node) && _.isNumber(node.value) && t.isMemberExpression(parent) && parent.object === node) {
return true;
}
if (t.isAssignmentExpression(node) || t.isConditionalExpression(node)) {
//
if (t.isUnaryLike(parent)) {
return true;
}
//
if (t.isBinary(parent)) {
return true;
}
//
if (t.isCallExpression(parent) && parent.callee === node) {
return true;
}
//
if (t.isConditionalExpression(parent) && parent.test === node) {
return true;
}
//
if (t.isMemberExpression(parent) && parent.object === node) {
return true;
}
}
if (t.isFunctionExpression(node)) {
// function () {};
if (t.isExpressionStatement(parent)) {
return true;
}
// (function test() {}).name;
if (t.isMemberExpression(parent) && parent.object === node) {
return true;
}
// (function () {})();
if (t.isCallExpression(parent) && parent.callee === node) {
return true;
}
}
// ({ x, y }) = { x: 5, y: 6 };
if (t.isObjectPattern(node) && t.isAssignmentExpression(parent) && parent.left == node) {
return true;
}
return false;
};
_.each(Node.prototype, function (fn, key) {
Node[key] = function (node, parent) {
var n = new Node(node, parent);
var args = _.toArray(arguments).slice(2);
return n[key].apply(n, args);
};
});

View File

@@ -0,0 +1,87 @@
module.exports = Node;
var whitespace = require("./whitespace");
var parens = require("./parentheses");
var t = require("../../types");
var _ = require("lodash");
var find = function (obj, node, parent) {
var result;
_.each(obj, function (fn, type) {
if (t["is" + type](node)) {
result = fn(node, parent);
if (result != null) return false;
}
});
return result;
};
function Node(node, parent) {
this.parent = parent;
this.node = node;
}
Node.prototype.isUserWhitespacable = function () {
var parent = this.parent;
var node = this.node;
if (t.isUserWhitespacable(node) ||
t.isSequenceExpression(parent)) {
return true;
}
return false;
};
Node.prototype.needsWhitespace = function (type) {
var parent = this.parent;
var node = this.node;
if (!node) return 0;
if (t.isExpressionStatement(node)) {
node = node.expression;
}
var lines = find(whitespace[type].nodes, node, parent);
if (lines) return lines;
_.each(find(whitespace[type].list, node, parent), function (expr) {
lines = Node.needsWhitespace(expr, node, type);
if (lines) return false;
});
return lines || 0;
};
Node.prototype.needsWhitespaceBefore = function () {
return this.needsWhitespace("before");
};
Node.prototype.needsWhitespaceAfter = function () {
return this.needsWhitespace("after");
};
Node.prototype.needsParens = function () {
var parent = this.parent;
var node = this.node;
if (!parent) return false;
if (t.isNewExpression(parent) && parent.callee === node) {
return t.isCallExpression(node) || _.some(node, function (val) {
return t.isCallExpression(val);
});
}
return find(parens, node, parent);
};
_.each(Node.prototype, function (fn, key) {
Node[key] = function (node, parent) {
var n = new Node(node, parent);
var args = _.toArray(arguments).slice(2);
return n[key].apply(n, args);
};
});

View File

@@ -0,0 +1,150 @@
var t = require("../../types");
var _ = require("lodash");
var PRECEDENCE = {};
_.each([
["||"],
["&&"],
["|"],
["^"],
["&"],
["==", "===", "!=", "!=="],
["<", ">", "<=", ">=", "in", "instanceof"],
[">>", "<<", ">>>"],
["+", "-"],
["*", "/", "%"]
], function (tier, i) {
_.each(tier, function (op) {
PRECEDENCE[op] = i;
});
});
exports.Binary = function (node, parent) {
if (t.isCallExpression(parent) && parent.callee === node) {
return true;
}
if (t.isUnaryLike(parent)) {
return true;
}
if (t.isMemberExpression(parent) && parent.object === node) {
return true;
}
if (t.isBinary(parent)) {
var parentOp = parent.operator;
var parentPos = PRECEDENCE[parentOp];
var nodeOp = node.operator;
var nodePos = PRECEDENCE[nodeOp];
if (parentPos > nodePos) {
return true;
}
if (parentPos === nodePos && parent.right === node) {
return true;
}
}
};
exports.BinaryExpression = function (node, parent) {
if (node.operator === "in") {
// var i = (1 in []);
if (t.isVariableDeclarator(parent)) {
return true;
}
// for ((1 in []);;);
if (t.isFor(parent)) {
return true;
}
}
};
exports.SequenceExpression = function (node, parent) {
if (t.isForStatement(parent)) {
// Although parentheses wouldn't hurt around sequence
// expressions in the head of for loops, traditional style
// dictates that e.g. i++, j++ should not be wrapped with
// parentheses.
return false;
}
if (t.isExpressionStatement(parent) && parent.expression === node) {
return false;
}
// Otherwise err on the side of overparenthesization, adding
// explicit exceptions above if this proves overzealous.
return true;
};
exports.YieldExpression = function (node, parent) {
return t.isBinary(parent) ||
t.isUnaryLike(parent) ||
t.isCallExpression(parent) ||
t.isMemberExpression(parent) ||
t.isNewExpression(parent) ||
t.isConditionalExpression(parent) ||
t.isYieldExpression(parent);
};
exports.Literal = function (node, parent) {
// (1).valueOf()
if (_.isNumber(node.value) && t.isMemberExpression(parent) && parent.object === node) {
return true;
}
};
exports.ClassExpression = function (node, parent) {
return t.isExpressionStatement(parent);
};
exports.UnaryLike = function (node, parent) {
return t.isMemberExpression(parent) && parent.object === node;
};
exports.FunctionExpression = function (node, parent) {
// function () {};
if (t.isExpressionStatement(parent)) {
return true;
}
// (function test() {}).name;
if (t.isMemberExpression(parent) && parent.object === node) {
return true;
}
// (function () {})();
if (t.isCallExpression(parent) && parent.callee === node) {
return true;
}
};
exports.AssignmentExpression =
exports.ConditionalExpression = function (node, parent) {
if (t.isUnaryLike(parent)) {
return true;
}
if (t.isBinary(parent)) {
return true;
}
if (t.isCallExpression(parent) && parent.callee === node) {
return true;
}
if (t.isConditionalExpression(parent) && parent.test === node) {
return true;
}
if (t.isMemberExpression(parent) && parent.object === node) {
return true;
}
return false;
};

View File

@@ -0,0 +1,60 @@
var _ = require("lodash");
var t = require("../../types");
exports.before = {
nodes: {
Property: function (node, parent) {
if (parent.properties[0] === node) {
return 1;
}
},
SwitchCase: function (node, parent) {
if (parent.cases[0] === node) {
return 1;
}
},
CallExpression: function (node) {
if (t.isFunction(node.callee)) {
return 1;
}
}
}
};
exports.after = {
nodes: {},
list: {
VariableDeclaration: function (node) {
return _.map(node.declarations, "init");
},
ArrayExpression: function (node) {
return node.elements;
},
ObjectExpression: function (node) {
return node.properties;
}
}
};
_.each({
Function: 1,
Class: 1,
For: 1,
SwitchStatement: 1,
IfStatement: { before: 1 },
CallExpression: { after: 1 },
Literal: { after: 1 }
}, function (amounts, type) {
if (_.isNumber(amounts)) amounts = { after: amounts, before: amounts };
_.each(amounts, function (amount, key) {
exports[key].nodes[type] = function () {
return amount;
};
});
});

View File

@@ -36,6 +36,7 @@ var blacklistTest = function (transformer, code) {
};
blacklistTest("arrayComprehension", "var foo = [for (foo of bar) foo * foo];");
//blacklistTest("generatorComprehension", "");
blacklistTest("arrowFunctions", "var foo = x => x * x;");
blacklistTest("classes", "class Foo {}");
blacklistTest("computedPropertyNames", "var foo = { [foo]: bar };");

View File

@@ -0,0 +1,5 @@
(function (Constructor, args) {
var bindArgs = [null].concat(args);
var Factory = Constructor.bind.apply(Constructor, bindArgs);
return new Factory;
});

View File

@@ -31,6 +31,7 @@ _.each({
propertyNameShorthand: require("./transformers/property-name-shorthand"),
constants: require("./transformers/constants"),
arrayComprehension: require("./transformers/array-comprehension"),
generatorComprehension: require("./transformers/generator-comprehension"),
arrowFunctions: require("./transformers/arrow-functions"),
classes: require("./transformers/classes"),
@@ -46,16 +47,14 @@ _.each({
letScoping: require("./transformers/let-scoping"),
forOf: require("./transformers/for-of"),
unicodeRegex: require("./transformers/unicode-regex"),
generators: require("./transformers/generators"),
numericLiterals: require("./transformers/numeric-literals"),
react: require("./transformers/react"),
jsx: require("./transformers/jsx"),
_aliasFunctions: require("./transformers/_alias-functions"),
_blockHoist: require("./transformers/_block-hoist"),
_declarations: require("./transformers/_declarations"),
generators: require("./transformers/generators"),
useStrict: require("./transformers/use-strict"),
_moduleFormatter: require("./transformers/_module-formatter")

View File

@@ -15,6 +15,7 @@ Transformer.normalise = function (transformer) {
}
_.each(transformer, function (fns, type) {
if (type[0] === "_") return;
if (_.isFunction(fns)) fns = { enter: fns };
transformer[type] = fns;
});

View File

@@ -14,10 +14,9 @@ var go = function (getBody, node, file, scope) {
};
// traverse the function and find all alias functions so we can alias
// arguments and this if necessary
// `arguments` and `this` if necessary
traverse(node, function (node) {
var _aliasFunction = node._aliasFunction;
if (!_aliasFunction) {
if (!node._aliasFunction) {
if (t.isFunction(node)) {
// stop traversal of this node as it'll be hit again by this transformer
return false;
@@ -26,12 +25,10 @@ var go = function (getBody, node, file, scope) {
}
}
// traverse all child nodes of this function and find arguments and this
// traverse all child nodes of this function and find `arguments` and `this`
traverse(node, function (node, parent) {
if (_aliasFunction === "arrows") {
if (t.isFunction(node) && node._aliasFunction !== "arrows") {
return false;
}
if (t.isFunction(node) && !node._aliasFunction) {
return false;
}
if (node._ignoreAliasFunctions) return;

View File

@@ -1,10 +1,11 @@
var esutils = require("esutils");
var t = require("../../types");
var _ = require("lodash");
exports.Property = function (node) {
// ignore key literals that are valid identifiers
var key = node.key;
if (t.isLiteral(key) && esutils.keyword.isIdentifierName(key.value)) {
if (t.isLiteral(key) && _.isString(key.value) && esutils.keyword.isIdentifierName(key.value)) {
key.type = "Identifier";
key.name = key.value;
delete key.value;

View File

@@ -1,5 +1,6 @@
var util = require("../../util");
var t = require("../../types");
var _ = require("lodash");
var singleArrayExpression = function (node) {
var block = node.blocks[0];
@@ -13,7 +14,13 @@ var singleArrayExpression = function (node) {
ARRAY: block.right,
KEY: block.left
});
result._aliasFunction = true;
_.each([result.callee.object, result], function (call) {
if (t.isCallExpression(call)) {
call.arguments[0]._aliasFunction = true;
}
});
return result;
};
@@ -23,46 +30,49 @@ var multiple = function (node, file) {
var container = util.template("array-comprehension-container", {
KEY: uid
});
container._aliasFunction = true;
container.callee.expression._aliasFunction = true;
var block = container.callee.expression.body;
var body = block.body;
var returnStatement = body.pop();
var build = function () {
var self = node.blocks.shift();
if (!self) return;
var child = build();
if (!child) {
// last item
child = util.template("array-push", {
STATEMENT: node.body,
KEY: uid
}, true);
// add a filter as this is our final stop
if (node.filter) {
child = t.ifStatement(node.filter, t.blockStatement([child]));
}
}
return t.forOfStatement(
t.variableDeclaration("var", [t.variableDeclarator(self.left)]),
self.right,
t.blockStatement([child])
);
};
body.push(build());
body.push(exports._build(node, function () {
return util.template("array-push", {
STATEMENT: node.body,
KEY: uid
}, true);
}));
body.push(returnStatement);
return container;
};
exports._build = function (node, buildBody) {
var self = node.blocks.shift();
if (!self) return;
var child = exports._build(node, buildBody);
if (!child) {
// last item
child = buildBody();
// add a filter as this is our final stop
if (node.filter) {
child = t.ifStatement(node.filter, t.blockStatement([child]));
}
}
return t.forOfStatement(
t.variableDeclaration("var", [t.variableDeclarator(self.left)]),
self.right,
t.blockStatement([child])
);
};
exports.ComprehensionExpression = function (node, parent, file) {
if (node.generator) return;
if (node.blocks.length === 1 && t.isArrayExpression(node.blocks[0].right)) {
return singleArrayExpression(node);
} else {

View File

@@ -3,7 +3,7 @@ var t = require("../../types");
exports.ArrowFunctionExpression = function (node) {
t.ensureBlock(node);
node._aliasFunction = "arrows";
node._aliasFunction = true;
node.expression = false;
node.type = "FunctionExpression";

View File

@@ -5,12 +5,12 @@ var _ = require("lodash");
exports.ClassDeclaration = function (node, parent, file, scope) {
return t.variableDeclaration("var", [
t.variableDeclarator(node.id, buildClass(node, file, scope))
t.variableDeclarator(node.id, new Class(node, file, scope).run())
]);
};
exports.ClassExpression = function (node, parent, file, scope) {
return buildClass(node, file, scope);
return new Class(node, file, scope).run();
};
var getMemberExpressionObject = function (node) {
@@ -20,31 +20,59 @@ var getMemberExpressionObject = function (node) {
return node;
};
var buildClass = function (node, file, scope) {
var superName = node.superClass;
var className = node.id || t.identifier(file.generateUid("class", scope));
/**
* Description
*
* @param {Node} node
* @param {File} file
* @param {Scope} scope
*/
var superClassArgument = node.superClass;
var superClassCallee = node.superClass;
function Class(node, file, scope) {
this.scope = scope;
this.node = node;
this.file = file;
this.instanceMutatorMap = {};
this.staticMutatorMap = {};
this.hasConstructor = false;
this.className = node.id || t.identifier(file.generateUid("class", scope));
this.superName = node.superClass;
}
/**
* Description
*
* @returns {Array}
*/
Class.prototype.run = function () {
var superClassArgument = this.superName;
var superClassCallee = this.superName;
var superName = this.superName;
var className = this.className;
var file = this.file;
if (superName) {
if (t.isMemberExpression(superName)) {
superClassArgument = superClassCallee = getMemberExpressionObject(superName);
} else if (!t.isIdentifier(superName)) {
superClassArgument = superName;
superClassCallee = superName = t.identifier(file.generateUid("ref", scope));
superClassCallee = superName = t.identifier(file.generateUid("ref", this.scope));
}
}
this.superName = superName;
var container = util.template("class", {
CLASS_NAME: className
});
var block = container.callee.expression.body;
var body = block.body;
var constructor = body[0].declarations[0].init;
var body = this.body = block.body;
var constructor = this.constructor = body[0].declarations[0].init;
if (node.id) constructor.id = className;
if (this.node.id) constructor.id = className;
var returnStatement = body.pop();
@@ -55,14 +83,7 @@ var buildClass = function (node, file, scope) {
container.callee.expression.params.push(superClassCallee);
}
buildClassBody({
file: file,
body: body,
node: node,
className: className,
superName: superName,
constructor: constructor,
});
this.buildBody();
if (body.length === 1) {
// only a constructor so no need for a closure container
@@ -73,49 +94,29 @@ var buildClass = function (node, file, scope) {
}
};
var buildClassBody = function (opts) {
var file = opts.file;
var body = opts.body;
var node = opts.node;
var constructor = opts.constructor;
var className = opts.className;
var superName = opts.superName;
/**
* Description
*/
var instanceMutatorMap = {};
var staticMutatorMap = {};
var hasConstructor = false;
var classBody = node.body.body;
Class.prototype.buildBody = function () {
var constructor = this.constructor;
var className = this.className;
var superName = this.superName;
var classBody = this.node.body.body;
var body = this.body;
var self = this;
_.each(classBody, function (node) {
var methodName = node.key;
var method = node.value;
replaceInstanceSuperReferences(superName, node);
self.replaceInstanceSuperReferences(node);
if (node.key.name === "constructor") {
if (node.kind === "") {
hasConstructor = true;
addConstructor(constructor, method);
} else {
throw file.errorWithNode(node, "illegal kind for constructor method");
}
self.pushConstructor(node);
} else {
var mutatorMap = instanceMutatorMap;
if (node.static) mutatorMap = staticMutatorMap;
var kind = node.kind;
if (kind === "") {
kind = "value";
util.pushMutatorMap(mutatorMap, methodName, "writable", t.identifier("true"));
}
util.pushMutatorMap(mutatorMap, methodName, kind, node);
self.pushMethod(node);
}
});
if (!hasConstructor && superName) {
if (!this.hasConstructor && superName) {
constructor.body.body.push(util.template("class-super-constructor-call", {
SUPER_NAME: superName
}, true));
@@ -124,16 +125,16 @@ var buildClassBody = function (opts) {
var instanceProps;
var staticProps;
if (!_.isEmpty(instanceMutatorMap)) {
if (!_.isEmpty(this.instanceMutatorMap)) {
var protoId = util.template("prototype-identifier", {
CLASS_NAME: className
});
instanceProps = util.buildDefineProperties(instanceMutatorMap, protoId);
instanceProps = util.buildDefineProperties(this.instanceMutatorMap, protoId);
}
if (!_.isEmpty(staticMutatorMap)) {
staticProps = util.buildDefineProperties(staticMutatorMap, className);
if (!_.isEmpty(this.staticMutatorMap)) {
staticProps = util.buildDefineProperties(this.staticMutatorMap, className);
}
if (instanceProps || staticProps) {
@@ -143,17 +144,50 @@ var buildClassBody = function (opts) {
if (instanceProps) args.push(instanceProps);
body.push(t.expressionStatement(
t.callExpression(file.addDeclaration("class-props"), args)
t.callExpression(this.file.addDeclaration("class-props"), args)
));
}
};
var superIdentifier = function (superName, methodNode, node, parent) {
var methodName = methodNode.key;
/**
* Push a method to it's respective mutatorMap.
*
* @param {Node} node MethodDefinition
*/
if (parent.property === node) {
Class.prototype.pushMethod = function (node) {
var methodName = node.key;
var mutatorMap = this.instanceMutatorMap;
if (node.static) mutatorMap = this.staticMutatorMap;
var kind = node.kind;
if (kind === "") {
kind = "value";
util.pushMutatorMap(mutatorMap, methodName, "writable", t.identifier("true"));
}
util.pushMutatorMap(mutatorMap, methodName, kind, node);
};
/**
* Given a `methodNode`, produce a `MemberExpression` super class reference.
*
* @param {Node} methodNode MethodDefinition
* @param {Node} node Identifier
* @param {Node} parent
*
* @returns {Node}
*/
Class.prototype.superIdentifier = function (methodNode, id, parent) {
var methodName = methodNode.key;
var superName = this.superName || t.identifier("Function");
if (parent.property === id) {
return;
} else if (t.isCallExpression(parent, { callee: node })) {
} else if (t.isCallExpression(parent, { callee: id })) {
// super(); -> ClassName.prototype.MethodName.call(this);
parent.arguments.unshift(t.thisExpression());
@@ -161,15 +195,15 @@ var superIdentifier = function (superName, methodNode, node, parent) {
// constructor() { super(); }
return t.memberExpression(superName, t.identifier("call"));
} else {
node = superName;
id = superName;
// foo() { super(); }
if (!methodNode.static) {
node = t.memberExpression(node, t.identifier("prototype"));
id = t.memberExpression(id, t.identifier("prototype"));
}
node = t.memberExpression(node, methodName, methodNode.computed);
return t.memberExpression(node, t.identifier("call"));
id = t.memberExpression(id, methodName, methodNode.computed);
return t.memberExpression(id, t.identifier("call"));
}
} else if (t.isMemberExpression(parent) && !methodNode.static) {
// super.test -> ClassName.prototype.test
@@ -179,31 +213,50 @@ var superIdentifier = function (superName, methodNode, node, parent) {
}
};
var replaceInstanceSuperReferences = function (superName, methodNode) {
var method = methodNode.value;
/**
* Replace all `super` references with a reference to our `superClass`.
*
* @param {Node} methodNode MethodDefinition
*/
superName = superName || t.identifier("Function");
Class.prototype.replaceInstanceSuperReferences = function (methodNode) {
var method = methodNode.value;
var self = this;
traverse(method, function (node, parent) {
if (t.isIdentifier(node, { name: "super" })) {
return superIdentifier(superName, methodNode, node, parent);
return self.superIdentifier(methodNode, node, parent);
} else if (t.isCallExpression(node)) {
var callee = node.callee;
if (!t.isMemberExpression(callee)) return;
if (callee.object.name !== "super") return;
// super.test(); -> ClassName.prototype.MethodName.call(this);
callee.property.name = callee.property.name + ".call";
// super.test(); -> ClassName.prototype.MethodName.call(this);
callee.property = t.memberExpression(callee.property, t.identifier("call"));
node.arguments.unshift(t.thisExpression());
}
});
};
var addConstructor = function (construct, method) {
construct.defaults = method.defaults;
construct.params = method.params;
construct.body = method.body;
construct.rest = method.rest;
/**
* Replace the constructor body of our class.
*
* @param {Node} method MethodDefinition
*/
t.inherits(construct, method);
Class.prototype.pushConstructor = function (method) {
if (method.kind !== "") {
throw this.file.errorWithNode(method, "illegal kind for constructor method");
}
var construct = this.constructor;
var fn = method.value;
this.hasConstructor = true;
t.inherits(construct, fn);
construct.defaults = fn.defaults;
construct.params = fn.params;
construct.body = fn.body;
construct.rest = fn.rest;
};

View File

@@ -29,7 +29,7 @@ exports.ObjectExpression = function (node, parent, file) {
var containerCallee = container.callee.expression;
var containerBody = containerCallee.body.body;
containerCallee._aliasFunction = "arrows";
containerCallee._aliasFunction = true;
_.each(computed, function (prop) {
containerBody.unshift(

View File

@@ -3,7 +3,7 @@ var t = require("../../types");
var _ = require("lodash");
exports.Function = function (node) {
if (!node.defaults.length) return;
if (!node.defaults || !node.defaults.length) return;
t.ensureBlock(node);
_.each(node.defaults, function (def, i) {

View File

@@ -146,6 +146,12 @@ exports.ExpressionStatement = function (node, parent, file, scope) {
return nodes;
};
exports.AssignmentExpression = function (node, parent, file) {
if (parent.type === "ExpressionStatement") return;
if (!t.isPattern(node.left)) return;
throw file.errorWithNode(node, "AssignmentExpression destructuring outside of a ExpressionStatement is forbidden due to current 6to5 limitations");
};
exports.VariableDeclaration = function (node, parent, file, scope) {
if (t.isForInStatement(parent) || t.isForOfStatement(parent)) return;

View File

@@ -5,17 +5,17 @@ exports.ForOfStatement = function (node, parent, file, scope) {
var left = node.left;
var declar;
var stepKey = t.identifier(file.generateUid("step", scope));
var stepValueId = t.memberExpression(stepKey, t.identifier("value"));
var stepKey = t.identifier(file.generateUid("step", scope));
var stepValue = t.memberExpression(stepKey, t.identifier("value"));
if (t.isIdentifier(left)) {
declar = t.expressionStatement(t.assignmentExpression("=", left, stepValueId));
declar = t.expressionStatement(t.assignmentExpression("=", left, stepValue));
} else if (t.isVariableDeclaration(left)) {
declar = t.variableDeclaration(left.kind, [
t.variableDeclarator(left.declarations[0].id, stepValueId)
t.variableDeclarator(left.declarations[0].id, stepValue)
]);
} else {
return;
throw file.errorWithNode(left, "Unknown node type " + left.type + " in ForOfStatement");
}
var node2 = util.template("for-of", {

View File

@@ -0,0 +1,15 @@
var arrayComprehension = require("./array-comprehension");
var t = require("../../types");
exports.ComprehensionExpression = function (node) {
if (!node.generator) return;
var body = [];
var container = t.functionExpression(null, [], t.blockStatement(body), true);
body.push(arrayComprehension._build(node, function () {
return t.expressionStatement(t.yieldExpression(node.body));
}));
return t.callExpression(container, []);
};

View File

@@ -1,89 +0,0 @@
// Based upon the excellent jsx-transpiler by Ingvar Stepanyan (RReverser)
// https://github.com/RReverser/jsx-transpiler
var esutils = require("esutils");
var t = require("../../types");
var _ = require("lodash");
var JSX_ANNOTATION_REGEX = /^\*\s*@jsx\s+([^\s]+)/;
exports.Program = function (node, parent, file) {
var jsx = "React.DOM";
// looking for namespace annotation
_.each(node.leadingComments, function (comment) {
var matches = JSX_ANNOTATION_REGEX.exec(comment.value);
if (matches) jsx = matches[1];
});
// prebuilding AST node
file.jsx = jsx.split(".").map(t.identifier).reduce(function (object, property) {
return t.memberExpression(object, property);
});
};
exports.XJSIdentifier = function (node) {
if (esutils.keyword.isIdentifierName(node.name)) {
node.type = "Identifier";
} else {
return t.literal(node.name);
}
};
exports.XJSNamespacedName = function () {
throw new Error("Namespace tags are not supported. ReactJSX is not XML.");
};
exports.XJSMemberExpression = {
exit: function (node) {
node.computed = t.isLiteral(node.property);
node.type = "MemberExpression";
}
};
exports.XJSExpressionContainer = function (node) {
return node.expression;
};
exports.XJSAttribute = {
exit: function (node) {
var value = node.value || t.literal(true);
return t.property("init", node.name, value);
}
};
exports.XJSOpeningElement = {
exit: function (node, parent, file) {
var tagExpr = node.name;
if (t.isIdentifier(tagExpr)) {
var tagName = tagExpr.name;
if (/[a-z]/.exec(tagName[0]) || _.contains(tagName, "-")) {
tagExpr = t.memberExpression(file.jsx, tagExpr);
}
}
var props = node.attributes;
if (props.length) {
props = t.objectExpression(props);
} else {
props = t.literal(null);
}
return t.callExpression(tagExpr, [props]);
}
};
exports.XJSElement = {
exit: function (node) {
var callExpr = node.openingElement;
var children = node.children;
_.each(children, function (child) {
callExpr.arguments.push(child);
});
return t.inherits(callExpr, node);
}
};

View File

@@ -17,6 +17,12 @@ var isVar = function (node) {
return t.isVariableDeclaration(node, { kind: "var" }) && !isLet(node);
};
var standardiseLets = function (declars) {
_.each(declars, function (declar) {
delete declar._let;
});
};
exports.VariableDeclaration = function (node) {
isLet(node);
};
@@ -33,7 +39,8 @@ exports.For = function (node, parent, file, scope) {
node.label = parent.label;
}
run(node, node.body, parent, file, scope);
var letScoping = new LetScoping(node, node.body, parent, file, scope);
letScoping.run();
if (node.label && !t.isLabeledStatement(parent)) {
// we've been given a label so let's wrap ourselves
@@ -43,12 +50,98 @@ exports.For = function (node, parent, file, scope) {
exports.BlockStatement = function (block, parent, file, scope) {
if (!t.isFor(parent)) {
run(false, block, parent, file, scope);
var letScoping = new LetScoping(false, block, parent, file, scope);
letScoping.run();
}
};
var noClosure = function (letDeclars, block, replacements) {
standardiseLets(letDeclars);
/**
* Description
*
* @param {Boolean|Node} forParent
* @param {Node} block
* @param {Node} parent
* @param {File} file
* @param {Scope} scope
*/
function LetScoping(forParent, block, parent, file, scope) {
this.forParent = forParent;
this.parent = parent;
this.scope = scope;
this.block = block;
this.file = file;
this.letReferences = {};
this.body = [];
this.info = this.getInfo();
}
/**
* Start the ball rolling.
*/
LetScoping.prototype.run = function () {
var block = this.block;
if (block._letDone) return;
block._letDone = true;
// this is a block within a `Function` so we can safely leave it be
if (t.isFunction(this.parent)) return;
// this block has no let references so let's clean up
if (!this.info.keys.length) return this.noClosure();
// returns whether or not there are any outside let references within any
// functions
var referencesInClosure = this.getLetReferences();
// no need for a closure so let's clean up
if (!referencesInClosure) return this.noClosure();
// if we're inside of a for loop then we search to see if there are any
// `break`s, `continue`s, `return`s etc
this.has = this.checkFor();
// hoist var references to retain scope
this.hoistVarDeclarations();
// set let references to plain var references
standardiseLets(this.info.declarators);
// turn letReferences into an array
var letReferences = _.values(this.letReferences);
// build the closure that we're going to wrap the block with
var fn = t.functionExpression(null, letReferences, t.blockStatement(block.body));
fn._aliasFunction = true;
// replace the current block body with the one we're going to build
block.body = this.body;
// change upper scope references with their uid if they have one
var params = this.getParams(letReferences);
// build a call and a unique id that we can assign the return value to
var call = t.callExpression(fn, params);
var ret = t.identifier(this.file.generateUid("ret", this.scope));
this.build(ret, call);
};
/**
* There are no let references accessed within a closure so we can just traverse
* through this block and replace all references that exist in a higher scope to
* their uids.
*/
LetScoping.prototype.noClosure = function () {
var replacements = this.info.duplicates;
var declarators = this.info.declarators;
var block = this.block;
standardiseLets(declarators);
if (_.isEmpty(replacements)) return;
@@ -59,13 +152,17 @@ var noClosure = function (letDeclars, block, replacements) {
});
};
var standardiseLets = function (declars) {
_.each(declars, function (declar) {
delete declar._let;
});
};
/**
* Description
*
* @returns {Object}
*/
LetScoping.prototype.getInfo = function () {
var block = this.block;
var scope = this.scope;
var file = this.file;
var getInfo = function (block, file, scope) {
var opts = {
// array of `Identifier` names of let variables that appear lexically out of
// this scope but should be accessible - eg. `ForOfStatement`.left
@@ -111,15 +208,24 @@ var getInfo = function (block, file, scope) {
return opts;
};
var checkFor = function (forParent, block) {
/**
* If we're inside of a `For*Statement` then traverse it and check if it has one
* of the following node types `ReturnStatement`, `BreakStatement`,
* `ContinueStatement` and replace it with a return value that we can track
* later on.
*
* @returns {Object}
*/
LetScoping.prototype.checkFor = function () {
var has = {
hasContinue: false,
hasReturn: false,
hasBreak: false,
};
if (forParent) {
traverse(block, function (node) {
if (this.forParent) {
traverse(this.block, function (node) {
var replace;
if (t.isFunction(node) || t.isFor(node)) {
@@ -133,7 +239,7 @@ var checkFor = function (forParent, block) {
} else if (t.isReturnStatement(node)) {
has.hasReturn = true;
replace = t.returnStatement(t.objectExpression([
t.property("init", t.identifier("v"), node.argument)
t.property("init", t.identifier("v"), node.argument || t.identifier("undefined"))
]));
}
@@ -144,38 +250,59 @@ var checkFor = function (forParent, block) {
return has;
};
var hoistVarDeclarations = function (block, pushDeclar) {
traverse(block, function (node) {
/**
* Hoist all var declarations in this block to before it so they retain scope
* once we wrap everything in a closure.
*/
LetScoping.prototype.hoistVarDeclarations = function () {
var self = this;
traverse(this.block, function (node) {
if (t.isForStatement(node)) {
if (isVar(node.init)) {
node.init = t.sequenceExpression(pushDeclar(node.init));
node.init = t.sequenceExpression(self.pushDeclar(node.init));
}
} else if (t.isFor(node)) {
if (isVar(node.left)) {
node.left = node.left.declarations[0].id;
}
} else if (isVar(node)) {
return pushDeclar(node).map(t.expressionStatement);
return self.pushDeclar(node).map(t.expressionStatement);
} else if (t.isFunction(node)) {
return false;
}
});
};
var getParams = function (info, letReferences) {
var params = _.cloneDeep(letReferences);
/**
* Build up a parameter list that we'll call our closure wrapper with, replacing
* all duplicate ids with their uid.
*
* @param {Array} params
* @returns {Array}
*/
LetScoping.prototype.getParams = function (params) {
var info = this.info;
params = _.cloneDeep(params);
_.each(params, function (param) {
param.name = info.duplicates[param.name] || param.name;
});
return params;
};
var getLetReferences = function (block, info, letReferences) {
/**
* Get all let references within this block. Stopping whenever we reach another
* block.
*/
LetScoping.prototype.getLetReferences = function () {
var closurify = false;
var self = this;
// traverse through this block, stopping on functions and checking if they
// contain any outside let references
traverse(block, function (node, parent, scope) {
traverse(this.block, function (node, parent, scope) {
if (t.isFunction(node)) {
traverse(node, function (node, parent) {
// not an identifier so we have no use
@@ -191,10 +318,10 @@ var getLetReferences = function (block, info, letReferences) {
closurify = true;
// this key doesn't appear just outside our scope
if (!_.contains(info.outsideKeys, node.name)) return;
if (!_.contains(self.info.outsideKeys, node.name)) return;
// push this badboy
letReferences[node.name] = node;
self.letReferences[node.name] = node;
});
return false;
@@ -206,120 +333,100 @@ var getLetReferences = function (block, info, letReferences) {
return closurify;
};
var buildPushDeclar = function (body) {
return function (node) {
body.push(t.variableDeclaration(node.kind, node.declarations.map(function (declar) {
return t.variableDeclarator(declar.id);
})));
/**
* Turn a `VariableDeclaration` into an array of `AssignmentExpressions` with
* their declarations hoisted to before the closure wrapper.
*
* @param {Node} node VariableDeclaration
* @returns {Array}
*/
var replace = [];
LetScoping.prototype.pushDeclar = function (node) {
this.body.push(t.variableDeclaration(node.kind, node.declarations.map(function (declar) {
return t.variableDeclarator(declar.id);
})));
_.each(node.declarations, function (declar) {
if (!declar.init) return;
var replace = [];
var expr = t.assignmentExpression("=", declar.id, declar.init);
replace.push(t.inherits(expr, declar));
});
_.each(node.declarations, function (declar) {
if (!declar.init) return;
return replace;
};
var expr = t.assignmentExpression("=", declar.id, declar.init);
replace.push(t.inherits(expr, declar));
});
return replace;
};
var run = function (forParent, block, parent, file, scope) {
if (block._letDone) return;
block._letDone = true;
var info = getInfo(block, file, scope);
var declarators = info.declarators;
var letKeys = info.keys;
// this is a block within a `Function` so we can safely leave it be
if (t.isFunction(parent)) return;
// this block has no let references so let's clean up
if (!letKeys.length) return noClosure(declarators, block, info.duplicates);
// outside let references that we need to wrap
var letReferences = {};
// returns whether or not there are any outside let references within any
// functions
var closurify = getLetReferences(block, info, letReferences);
letReferences = _.values(letReferences);
// no need for a closure so let's clean up
if (!closurify) return noClosure(declarators, block, info.duplicates);
// if we're inside of a for loop then we search to see if there are any
// `break`s, `continue`s, `return`s etc
var has = checkFor(forParent, block);
var body = [];
// hoist a `VariableDeclaration` and add `AssignmentExpression`s in it's place
var pushDeclar = buildPushDeclar(body);
// hoist var references to retain scope
hoistVarDeclarations(block, pushDeclar);
// set let references to plain var references
standardiseLets(declarators);
// build the closure that we're going to wrap the block with
var fn = t.functionExpression(null, letReferences, t.blockStatement(block.body));
fn._aliasFunction = true;
// replace the current block body with the one we've built
block.body = body;
// change duplicate let references to their uid if they have one
var params = getParams(info, letReferences);
var call = t.callExpression(fn, params);
var ret = t.identifier(file.generateUid("ret", scope));
/**
* Push the closure to the body.
*
* @param {Node} ret Identifier
* @param {Node} call CallExpression
*/
LetScoping.prototype.build = function (ret, call) {
var has = this.has;
if (has.hasReturn || has.hasBreak || has.hasContinue) {
body.push(t.variableDeclaration("var", [
t.variableDeclarator(ret, call)
]));
this.buildHas(ret, call);
} else {
this.body.push(t.expressionStatement(call));
}
};
var retCheck;
/**
* Description
*
* @param {Node} ret Identifier
* @param {Node} call CallExpression
*/
if (has.hasReturn) {
// typeof ret === "object"
retCheck = util.template("let-scoping-return", {
RETURN: ret,
});
LetScoping.prototype.buildHas = function (ret, call) {
var body = this.body;
// there's no `break` or `continue` so we can just push in the `if`
if (!has.hasBreak && !has.hasContinue) {
body.push(retCheck);
}
body.push(t.variableDeclaration("var", [
t.variableDeclarator(ret, call)
]));
var forParent = this.forParent;
var retCheck;
var has = this.has;
var cases = [];
if (has.hasReturn) {
// typeof ret === "object"
retCheck = util.template("let-scoping-return", {
RETURN: ret
});
}
if (has.hasBreak || has.hasContinue) {
// ensure that the parent has a label as we're building a switch and we
// need to be able to access it
var label = forParent.label = forParent.label || t.identifier(this.file.generateUid("loop", this.scope));
if (has.hasBreak) {
cases.push(t.switchCase(t.literal("break"), [t.breakStatement(label)]));
}
if (has.hasBreak || has.hasContinue) {
// ensure that the parent has a label as we're building a switch and we
// need to be able to access it
var label = forParent.label = forParent.label || t.identifier(file.generateUid("loop", scope));
if (has.hasContinue) {
cases.push(t.switchCase(t.literal("continue"), [t.continueStatement(label)]));
}
var cases = [];
if (has.hasBreak) {
cases.push(t.switchCase(t.literal("break"), [t.breakStatement(label)]));
}
if (has.hasContinue) {
cases.push(t.switchCase(t.literal("continue"), [t.continueStatement(label)]));
}
if (has.hasReturn) {
cases.push(t.switchCase(null, [retCheck]));
}
if (has.hasReturn) {
cases.push(t.switchCase(null, [retCheck]));
}
if (cases.length === 1) {
var single = cases[0];
body.push(t.ifStatement(
t.binaryExpression("===", ret, single.test),
single.consequent[0]
));
} else {
body.push(t.switchStatement(ret, cases));
}
} else {
body.push(t.expressionStatement(call));
if (has.hasReturn) body.push(retCheck);
}
};

View File

@@ -1,6 +0,0 @@
var _ = require("lodash");
exports.Literal = function (node) {
// TODO: remove this when the new code generator is released
if (_.isNumber(node.value)) delete node.raw;
};

View File

@@ -1,5 +1,124 @@
var t = require("../../types");
var _ = require("lodash");
// Based upon the excellent jsx-transpiler by Ingvar Stepanyan (RReverser)
// https://github.com/RReverser/jsx-transpiler
// jsx
var esutils = require("esutils");
var t = require("../../types");
var _ = require("lodash");
exports.XJSIdentifier = function (node) {
if (esutils.keyword.isIdentifierName(node.name)) {
node.type = "Identifier";
} else {
return t.literal(node.name);
}
};
exports.XJSNamespacedName = function (node, parent, file) {
throw file.errorWithNode(node, "Namespace tags are not supported. ReactJSX is not XML.");
};
exports.XJSMemberExpression = {
exit: function (node) {
node.computed = t.isLiteral(node.property);
node.type = "MemberExpression";
}
};
exports.XJSExpressionContainer = function (node) {
return node.expression;
};
exports.XJSAttribute = {
exit: function (node) {
var value = node.value || t.literal(true);
return t.property("init", node.name, value);
}
};
exports.XJSOpeningElement = {
exit: function (node) {
var tagExpr = node.name;
var args = [];
var tagName;
if (t.isIdentifier(tagExpr)) {
tagName = tagExpr.name;
} else if (t.isLiteral(tagExpr)) {
tagName = tagExpr.value;
}
if (tagName && (/[a-z]/.exec(tagName[0]) || _.contains(tagName, "-"))) {
args.push(t.literal(tagName));
} else {
args.push(tagExpr);
}
var props = node.attributes;
if (props.length) {
var _props = [];
var objs = [];
var pushProps = function () {
if (!_props.length) return;
objs.push(t.objectExpression(_props));
_props = [];
};
while (props.length) {
var prop = props.shift();
if (t.isXJSSpreadAttribute(prop)) {
pushProps();
objs.push(prop.argument);
} else {
_props.push(prop);
}
}
pushProps();
if (objs.length === 1) {
props = objs[0];
} else {
if (!t.isObjectExpression(objs[0])) {
objs.unshift(t.objectExpression([]));
}
props = t.callExpression(
t.memberExpression(t.identifier("React"), t.identifier("__spread")),
objs
);
}
} else {
props = t.literal(null);
}
args.push(props);
tagExpr = t.memberExpression(t.identifier("React"), t.identifier("createElement"));
return t.callExpression(tagExpr, args);
}
};
exports.XJSElement = {
exit: function (node) {
var callExpr = node.openingElement;
var childrenToRender = node.children.filter(function(child) {
return !(t.isLiteral(child) && _.isString(child.value) && child.value.match(/^[ \t]*[\r\n][ \t\r\n]*$/));
});
_.each(childrenToRender, function (child) {
callExpr.arguments.push(child);
});
return t.inherits(callExpr, node);
}
};
// display names
var addDisplayName = function (id, call) {
if (!call || !t.isCallExpression(call)) return;

View File

@@ -1,14 +1,13 @@
var util = require("../../util");
var t = require("../../types");
var _ = require("lodash");
var t = require("../../types");
var _ = require("lodash");
var getSpreadLiteral = function (spread, file) {
var getSpreadLiteral = function (spread) {
var literal = spread.argument;
if (!t.isArrayExpression(literal)) {
literal = util.template("call", {
OBJECT: file.addDeclaration("slice"),
CONTEXT: literal
});
literal = t.callExpression(
t.memberExpression(t.identifier("Array"), t.identifier("from")),
[literal]
);
}
return literal;
};
@@ -24,7 +23,7 @@ var hasSpread = function (nodes) {
return has;
};
var build = function (props, file) {
var build = function (props) {
var nodes = [];
var _props = [];
@@ -38,7 +37,7 @@ var build = function (props, file) {
_.each(props, function (prop) {
if (t.isSpreadElement(prop)) {
push();
nodes.push(getSpreadLiteral(prop, file));
nodes.push(getSpreadLiteral(prop));
} else {
_props.push(prop);
}
@@ -49,11 +48,11 @@ var build = function (props, file) {
return nodes;
};
exports.ArrayExpression = function (node, parent, file) {
exports.ArrayExpression = function (node) {
var elements = node.elements;
if (!hasSpread(elements)) return;
var nodes = build(elements, file);
var nodes = build(elements);
var first = nodes.shift();
if (!nodes.length) return first;
@@ -61,7 +60,7 @@ exports.ArrayExpression = function (node, parent, file) {
return t.callExpression(t.memberExpression(first, t.identifier("concat")), nodes);
};
exports.CallExpression = function (node, parent, file) {
exports.CallExpression = function (node) {
var args = node.arguments;
if (!hasSpread(args)) return;
@@ -69,7 +68,7 @@ exports.CallExpression = function (node, parent, file) {
node.arguments = [];
var nodes = build(args, file);
var nodes = build(args);
var first = nodes.shift();
if (nodes.length) {
@@ -96,3 +95,19 @@ exports.CallExpression = function (node, parent, file) {
node.arguments.unshift(contextLiteral);
};
exports.NewExpression = function (node, parent, file) {
var args = node.arguments;
if (!hasSpread(args)) return;
var nodes = build(args);
var first = nodes.shift();
if (nodes.length) {
args = t.callExpression(t.memberExpression(first, t.identifier("concat")), nodes);
} else {
args = first;
}
return t.callExpression(file.addDeclaration("apply-constructor"), [node.callee, args]);
};

View File

@@ -40,8 +40,6 @@ function traverse(parent, callbacks, opts) {
// type is blacklisted
if (_.contains(blacklistTypes, node.type)) return;
var result;
// replace node
var maybeReplace = function (result) {
if (result === false) return;
@@ -54,12 +52,11 @@ function traverse(parent, callbacks, opts) {
// enter
if (callbacks.enter) {
result = callbacks.enter(node, parent, opts2.scope);
var result = callbacks.enter(node, parent, opts2.scope);
maybeReplace(result);
// stop iteration
if (result === false) return;
maybeReplace(result);
}
// traverse node
@@ -114,25 +111,18 @@ traverse.hasType = function (tree, type, blacklistTypes) {
var has = false;
if (_.isArray(tree)) {
// array of nodes, find the first
return tree.some(function (node) {
return traverse.hasType(node, type, blacklistTypes);
});
} else {
// the node we're searching in is blacklisted
if (_.contains(blacklistTypes, tree.type)) return false;
// the node we're searching in is blacklisted
if (_.contains(blacklistTypes, tree.type)) return false;
// the type we're looking for is the same as the passed node
if (tree.type === type) return true;
// the type we're looking for is the same as the passed node
if (tree.type === type) return true;
traverse(tree, function (node) {
if (node.type === type) {
has = true;
return false;
}
}, { blacklist: blacklistTypes });
}
traverse(tree, function (node) {
if (node.type === type) {
has = true;
return false;
}
}, { blacklist: blacklistTypes });
return has;
};

View File

@@ -42,5 +42,6 @@
"ObjectPattern": ["Pattern"],
"ArrayPattern": ["Pattern"],
"Property": ["UserWhitespacable"]
"Property": ["UserWhitespacable"],
"XJSElement": ["UserWhitespacable"]
}

View File

@@ -7,11 +7,12 @@
"ConditionalExpression": ["test", "consequent", "alternate"],
"ExpressionStatement": ["expression"],
"File": ["program", "comments", "tokens"],
"FunctionExpression": ["id", "params", "body"],
"FunctionExpression": ["id", "params", "body", "generator"],
"Identifier": ["name"],
"IfStatement": ["test", "consequent", "alternate"],
"Literal": ["value"],
"MemberExpression": ["object", "property", "computed"],
"NewExpression": ["callee", "arguments"],
"ObjectExpression": ["properties"],
"ParenthesizedExpression": ["expression"],
"Program": ["body"],

View File

@@ -106,6 +106,10 @@ t.ensureBlock = function (node) {
};
t.toStatement = function (node, ignore) {
if (t.isStatement(node)) {
return node;
}
var mustHaveId = false;
var newType;
@@ -115,8 +119,6 @@ t.toStatement = function (node, ignore) {
} else if (t.isFunction(node)) {
mustHaveId = true;
newType = "FunctionDeclaration";
} else if (t.isStatement(node)) {
newType = node.type;
}
if (mustHaveId && !node.id) {
@@ -205,10 +207,12 @@ t.getIds.arrays = {
};
t.inherits = function (child, parent) {
child.loc = parent.loc;
child.end = parent.end;
child.range = parent.range;
child.start = parent.start;
child.loc = parent.loc;
child.end = parent.end;
child.range = parent.range;
child.start = parent.start;
child.leadingComments = parent.leadingComments;
child.trailingComments = parent.trailingComments;
return child;
};

View File

@@ -3,6 +3,7 @@
"ArrayPattern": ["elements"],
"ArrowFunctionExpression": ["params", "defaults", "rest", "body"],
"AssignmentExpression": ["left", "right"],
"AwaitExpression": ["argument"],
"BinaryExpression": ["left", "right"],
"BlockStatement": ["body"],
"BreakStatement": ["label"],
@@ -70,6 +71,6 @@
"XJSMemberExpression": ["object", "property"],
"XJSNamespacedName": ["namespace", "name"],
"XJSOpeningElement": ["name", "attributes"],
"XJSSpreadAttribute": [],
"XJSSpreadAttribute": ["argument"],
"YieldExpression": ["argument"]
}

View File

@@ -25,6 +25,10 @@ exports.resolve = function (loc) {
}
};
exports.trimRight = function (str) {
return str.replace(/[\n\s]+$/g, "");
};
exports.list = function (val) {
return val ? val.split(",") : [];
};
@@ -240,7 +244,7 @@ exports.parse = function (opts, code, callback) {
}
};
exports.parseNoProperties = function (loc, code) {
exports.parseTemplate = function (loc, code) {
var ast = exports.parse({ filename: loc }, code).program;
return traverse.removeProperties(ast);
};
@@ -262,7 +266,7 @@ var loadTemplates = function () {
var loc = templatesLoc + "/" + name;
var code = fs.readFileSync(loc, "utf8");
templates[key] = exports.parseNoProperties(loc, code);
templates[key] = exports.parseTemplate(loc, code);
});
return templates;

View File

@@ -1,7 +1,7 @@
{
"name": "6to5",
"description": "Turn ES6 code into readable vanilla ES5 with source maps",
"version": "1.11.7",
"version": "1.12.10",
"author": "Sebastian McKenzie <sebmck@gmail.com>",
"homepage": "https://github.com/6to5/6to5",
"repository": {
@@ -44,19 +44,19 @@
"es6-symbol": "0.1.1",
"regexpu": "0.3.0",
"source-map": "0.1.40",
"regenerator-6to5": "https://github.com/6to5/regenerator-6to5/archive/b7bc53e1a655879974aad53a8ceb93a70efaa08d.tar.gz",
"regenerator-6to5": "https://github.com/6to5/regenerator-6to5/archive/75925940a7bb67d1ee8afec36b6d6eec072fb47c.tar.gz",
"chokidar": "0.10.5",
"source-map-support": "0.2.8",
"esutils": "1.1.4",
"acorn-6to5": "https://github.com/6to5/acorn-6to5/archive/49e421660af161af0e75c2fa066ea356d6650e69.tar.gz",
"acorn-6to5": "https://github.com/6to5/acorn-6to5/archive/a6c34ba73e215bd16ee585f6794f6a6587820c58.tar.gz",
"estraverse": "^1.7.0"
},
"devDependencies": {
"istanbul": "0.3.2",
"matcha": "0.5.0",
"matcha": "0.6.0",
"mocha": "2.0.1",
"uglify-js": "2.4.15",
"browserify": "6.2.0",
"browserify": "6.3.2",
"rimraf": "2.2.8",
"jshint": "2.5.10",
"chai": "^1.9.2"

1
polyfill.js Normal file
View File

@@ -0,0 +1 @@
module.exports = require("./lib/6to5/polyfill");

View File

@@ -5,9 +5,11 @@ var humanise = function (val) {
return val.replace(/-/g, " ");
};
var readFile = function (filename) {
var readFile = exports.readFile = function (filename) {
if (fs.existsSync(filename)) {
return fs.readFileSync(filename, "utf8").trim();
var file = fs.readFileSync(filename, "utf8").trim();
file = file.replace(/\r\n/g, "\n");
return file;
} else {
return "";
}

View File

@@ -1,4 +1,5 @@
var readdir = require("fs-readdir-recursive");
var helper = require("./_helper");
var assert = require("assert");
var rimraf = require("rimraf");
var mkdirp = require("mkdirp");
@@ -11,15 +12,11 @@ var _ = require("lodash");
var fixtureLoc = __dirname + "/fixtures/bin";
var tmpLoc = __dirname + "/tmp";
var readFile = function (filename) {
return fs.readFileSync(filename, "utf8").trim();
};
var readDir = function (loc) {
var files = {};
if (fs.existsSync(loc)) {
_.each(readdir(loc), function (filename) {
var contents = readFile(loc + "/" + filename);
var contents = helper.readFile(loc + "/" + filename);
files[filename] = contents;
});
}
@@ -51,6 +48,7 @@ var assertTest = function (stdout, stderr, opts) {
var expectStdout = opts.stdout.trim();
stdout = stdout.trim();
stdout = stdout.replace(/\\/g, "/");
if (opts.stdout) {
if (opts.stdoutContains) {
@@ -63,7 +61,7 @@ var assertTest = function (stdout, stderr, opts) {
}
_.each(opts.outFiles, function (expect, filename) {
var actual = readFile(filename);
var actual = helper.readFile(filename);
chai.expect(actual).to.equal(expect, "out-file " + filename);
});
};
@@ -138,7 +136,7 @@ _.each(fs.readdirSync(fixtureLoc), function (binName) {
_.each(["stdout", "stdin", "stderr"], function (key) {
var loc = testLoc + "/" + key + ".txt";
if (fs.existsSync(loc)) {
opts[key] = readFile(loc);
opts[key] = helper.readFile(loc);
} else {
opts[key] = opts[key] || "";
}
@@ -151,7 +149,3 @@ _.each(fs.readdirSync(fixtureLoc), function (binName) {
});
});
});
after(function () {
rimraf.sync(tmpLoc);
});

View File

@@ -1,3 +0,0 @@
var multiples = [for (num of nums) num * num];
var multiples = [for (num of nums) for (num2 of nums) num * num];
var multiples = [for (num of nums) if (num > 5) num * num];

View File

@@ -1,3 +0,0 @@
var multiples = [for (num of nums) num * num];
var multiples = [for (num of nums) for (num2 of nums) num * num];
var multiples = [for (num of nums) if (num > 5) num * num];

View File

@@ -1 +0,0 @@
var foo = [1, 2, 3];

View File

@@ -1 +0,0 @@
var foo = [1, 2, 3];

View File

@@ -1,17 +0,0 @@
var foo = `i
am a multiline string`;
var foo = `i am also
a multiline string
foobar`;
var foo = `im a single line string`;
var foo = tagit`i
am a multiline string`;
var foo = tagit`i am also
a multiline string
foobar`;
var foo = tagit`im a single line string`;

View File

@@ -1,17 +0,0 @@
var foo = `i
am a multiline string`;
var foo = `i am also
a multiline string
foobar`;
var foo = `im a single line string`;
var foo = tagit`i
am a multiline string`;
var foo = tagit`i am also
a multiline string
foobar`;
var foo = tagit`im a single line string`;

View File

@@ -20,8 +20,11 @@
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
// THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
function test() {}
// Copyright (C) 2012 Yusuke Suzuki <utatane.tea@gmail.com>
//
// Redistribution and use in source and binary forms, with or without

View File

@@ -4,6 +4,6 @@ export { a as b, c as d } from "hello";
export { a as b, c as d };
export {};
export default i = 20;
export function test() {};
export function test() {}
export var i = 20;
export let i = 42;

View File

@@ -0,0 +1,5 @@
[a, b, c];
[[], [b, c], []];
[a,, b,];
[a,,,, b];
[a, b,, c];

View File

@@ -0,0 +1,5 @@
[a, b, c];
[[], [b, c], []];
[a,, b];
[a,,,, b];
[a, b,, c];

View File

@@ -0,0 +1,4 @@
var foo = x => x * x;
var foo = (a, b) => a * b;
var foo = async x => x * x;
var foo = async (a, b) => a * b;

View File

@@ -0,0 +1,4 @@
var foo = x => x * x;
var foo = (a, b) => a * b;
var foo = async x => x * x;
var foo = async (a, b) => a * b;

View File

@@ -0,0 +1,3 @@
foo === bar;
foo + bar;
foo = bar;

View File

@@ -0,0 +1,3 @@
foo === bar;
foo + bar;
foo = bar;

View File

@@ -0,0 +1,7 @@
async function foo() {
await bar();
}
async function bar() {
await* foo();
}

View File

@@ -0,0 +1,7 @@
async function foo() {
await bar();
}
async function bar() {
await* foo();
}

View File

@@ -0,0 +1,5 @@
{}
{
foo();
}

View File

@@ -0,0 +1,5 @@
{}
{
foo();
}

View File

@@ -0,0 +1,7 @@
for (var i in foo) {
break;
}
foo: for (var i in foo) {
break foo;
}

View File

@@ -0,0 +1,7 @@
for (var i in foo) {
break;
}
foo: for (var i in foo) {
break foo;
}

Some files were not shown because too many files have changed in this diff Show More