Compare commits

..

171 Commits

Author SHA1 Message Date
Sebastian McKenzie
3815913537 v1.12.18 2014-11-16 21:01:12 +11:00
Sebastian McKenzie
e5c18749f0 add changelog for 1.12.18 2014-11-16 21:00:00 +11:00
Sebastian McKenzie
b7458f949c Merge pull request #177 from josh/browser-global
Prefer module provided `global` rather than `window` reference
2014-11-16 20:58:12 +11:00
Sebastian McKenzie
69302b314f add sprockets-es6 to plugins 2014-11-16 20:55:56 +11:00
Joshua Peek
0c57a00fdb Check if attachEvent is defined 2014-11-16 01:41:56 -08:00
Joshua Peek
3bec8b0311 Prefer module global reference rather than window 2014-11-16 01:41:16 -08:00
Sebastian McKenzie
6a88e05362 v1.12.17 2014-11-16 19:29:25 +11:00
Sebastian McKenzie
e3bd2dff8d remove unused path variable 2014-11-16 19:27:49 +11:00
Sebastian McKenzie
ef82171254 update amd/umd modules documentation 2014-11-16 19:27:15 +11:00
Sebastian McKenzie
00d94fd810 update changelog with additional new options 2014-11-16 19:26:03 +11:00
Sebastian McKenzie
d929d3c5eb remove duplicate i variable from traverse 2014-11-16 19:24:58 +11:00
Sebastian McKenzie
5c1ee86b97 remove filenameRelative from bin/6to5* since it's unneccesary 2014-11-16 19:24:47 +11:00
Sebastian McKenzie
5409691a3a update umd and amd tests with new moduleName option 2014-11-16 19:22:37 +11:00
Sebastian McKenzie
24964ac454 add filenameRelative to bin/6to5* 2014-11-16 19:20:08 +11:00
Sebastian McKenzie
faa81ab85b add 1.12.17 changelog 2014-11-16 19:19:57 +11:00
Sebastian McKenzie
d4bc082bb9 add new filenameRelative, sourceRoot and moduleRoot option documentation 2014-11-16 19:19:46 +11:00
Sebastian McKenzie
3777af6bbd add filenameRelative default and make sourceFileName and sourceMapName inherit form it 2014-11-16 19:19:25 +11:00
Sebastian McKenzie
1f258e9e9c add sourceRoot to source map 2014-11-16 19:19:07 +11:00
Sebastian McKenzie
50333c879c add comments and change single quotes in amd formatter getModuleName 2014-11-16 19:18:56 +11:00
Sebastian McKenzie
105e6ac379 add filenameRelative to tests 2014-11-16 19:18:30 +11:00
Sebastian McKenzie
dadab64e39 Merge pull request #176 from darvelo/master
Generate moduleNames for AMD/UMD
2014-11-16 19:00:56 +11:00
Sebastian McKenzie
2b82f2bcc2 ignore unknown nodes in traversal 2014-11-16 18:52:54 +11:00
Sebastian McKenzie
f1183505b1 optimise traverse, improves traversal speed by 50% 2014-11-16 18:50:07 +11:00
Sebastian McKenzie
fa3b24e5b4 don't lazy set templates, can't even remember why i did this 2014-11-16 18:49:29 +11:00
Sebastian McKenzie
5789447068 add loc option to exec test 2014-11-16 18:48:32 +11:00
David Arvelo
f1f7321590 Generate moduleNames for AMD/UMD 2014-11-16 02:38:00 -05:00
Sebastian McKenzie
9ff4df6dae v1.12.16 2014-11-16 14:39:15 +11:00
Sebastian McKenzie
0dbb24c922 remove unused i variable in default parameters transformer 2014-11-16 14:37:26 +11:00
Sebastian McKenzie
a027d2b9cf add 1.12.16 changelog 2014-11-16 14:34:42 +11:00
Sebastian McKenzie
e290990371 scope: remove unused references instance property 2014-11-16 14:34:29 +11:00
Sebastian McKenzie
d0a2bd170e clean up constants transformer 2014-11-16 14:33:37 +11:00
Sebastian McKenzie
69db46f96b move down and clump constants and let scoping transformer positions 2014-11-16 14:33:29 +11:00
Sebastian McKenzie
27ba4b2bba scope: switch over declaration building to info so we can build multiple things 2014-11-16 14:33:16 +11:00
Sebastian McKenzie
b337c1ab06 test/transformation: use full location as filename 2014-11-16 14:32:40 +11:00
Sebastian McKenzie
a1895b4bb4 implement temporal dead zone for default parameters - fixes #169 2014-11-16 14:32:03 +11:00
Sebastian McKenzie
00483917f0 fix comments not being retained from MethodDefinition in classes 2014-11-16 11:30:05 +11:00
Sebastian McKenzie
d09bafaf8c Merge pull request #172 from thejameskyle/docs-whitespace
Add newline to keep marked from parsing incorrectly
2014-11-16 10:32:04 +11:00
James Kyle
a7ef02c781 Add newline to keep marked from parsing incorrectly 2014-11-15 15:31:16 -08:00
Sebastian McKenzie
94cd45c269 v1.12.15 2014-11-15 11:42:06 +11:00
Sebastian McKenzie
424bab97d0 update acorn-6to5 - fixes #165 2014-11-15 11:40:34 +11:00
Sebastian McKenzie
a1bdd804e2 v1.12.14 2014-11-15 11:30:37 +11:00
Sebastian McKenzie
10c051890b fix changelog version 2014-11-15 11:29:41 +11:00
Sebastian McKenzie
ac49d0a335 v1.12.4 2014-11-15 11:29:06 +11:00
Sebastian McKenzie
b56f1800e5 update regenerator-6to5 2014-11-15 11:27:29 +11:00
Sebastian McKenzie
49ef92c586 add changelog for v1.12.4 2014-11-15 11:23:42 +11:00
Sebastian McKenzie
542fe89123 fix up tests to work with new member expression keyword generator 2014-11-15 11:23:16 +11:00
Sebastian McKenzie
5b118c0c3f add _property-literals test 2014-11-15 11:13:10 +11:00
Sebastian McKenzie
8503916799 add _memberExpressionKeywords transformer that turns keyword identifiers to computed literals 2014-11-15 11:13:02 +11:00
Sebastian McKenzie
206c828a56 more react compliant whitespace - #165 2014-11-15 11:00:32 +11:00
Sebastian McKenzie
7a261a1db1 fix duplicate let scoping in functions - fixes #166 2014-11-15 09:47:48 +11:00
Sebastian McKenzie
c9d9a085f1 v1.12.13 2014-11-15 03:08:35 +11:00
Sebastian McKenzie
6d1953d9c3 fix constants transformer not accurately checking nodes 2014-11-15 03:07:33 +11:00
Sebastian McKenzie
92621d71c7 remove unused variable 2014-11-15 03:01:58 +11:00
Sebastian McKenzie
dc01731c25 add changelog for 1.12.13 2014-11-15 03:01:01 +11:00
Sebastian McKenzie
9fb8a80f60 support raw property on tagged template literals - closes #164 2014-11-15 03:00:53 +11:00
Sebastian McKenzie
85c2de57e4 fix for-head duplication testing and replacement - fixes #162 2014-11-15 02:50:05 +11:00
Sebastian McKenzie
58fac2e2be support duplicate constants within different block scopes - fixes #161 2014-11-15 02:49:49 +11:00
Sebastian McKenzie
682806f1ca instead of ignoring dot tests, add them as pending 2014-11-15 02:49:28 +11:00
Sebastian McKenzie
47c6f74251 v1.12.12 2014-11-14 23:15:14 +11:00
Sebastian McKenzie
37f360c72d make scope tracker more reliable to handle all edgecases 2014-11-14 23:13:58 +11:00
Sebastian McKenzie
e5a8c95b62 v1.12.11 2014-11-14 19:39:25 +11:00
Sebastian McKenzie
921d459f13 fix transformation let scoping hoisting test 2014-11-14 19:38:29 +11:00
Sebastian McKenzie
58898932e6 shift letScoping to before forOf transformer 2014-11-14 19:35:07 +11:00
Sebastian McKenzie
c7b45116c4 fix generation of integer Literals in MemberExpression 2014-11-14 19:34:54 +11:00
Sebastian McKenzie
32ddd638ba Revert "expose moduleName option - closes #158"
This reverts commit fdd1451d53.
2014-11-14 18:33:11 +11:00
Sebastian McKenzie
0eb3cda2d4 add 1.12.11 changelog 2014-11-14 17:20:05 +11:00
Sebastian McKenzie
2acb24d43d block scope classes 2014-11-14 17:19:46 +11:00
Sebastian McKenzie
fdd1451d53 expose moduleName option - closes #158 2014-11-14 17:19:39 +11:00
Sebastian McKenzie
43e2f121a6 remove nodes replacing in util.template 2014-11-14 09:28:23 +11:00
Sebastian McKenzie
297e55ba63 Revert "fix up types.toStatement and return an expressionStatement if all else fails"
This reverts commit 740193b1e2.
2014-11-14 09:28:04 +11:00
Sebastian McKenzie
38396dadd5 remove unused nodes.inherits in util.template 2014-11-14 09:15:29 +11:00
Sebastian McKenzie
f75f045026 turn custom runtime into a proper identifier 2014-11-14 09:15:00 +11:00
Sebastian McKenzie
740193b1e2 fix up types.toStatement and return an expressionStatement if all else fails 2014-11-14 09:14:49 +11:00
Sebastian McKenzie
b9fe1475c2 add basic api test 2014-11-14 09:13:00 +11:00
Sebastian McKenzie
6065220f9b add runtime test 2014-11-14 09:12:54 +11:00
Sebastian McKenzie
715884662e fix basic unicode-regex test 2014-11-14 09:12:49 +11:00
Sebastian McKenzie
11780c28ff add let scoping hoisting test 2014-11-14 09:12:38 +11:00
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
364 changed files with 3563 additions and 1981 deletions

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

View File

@@ -1,3 +1,94 @@
# 1.12.18
* Use `global` reference instead of `window`.
# 1.12.17
* Add `moduleName`, `sourceRoot` and `filenameRelative` options - thanks @darvelo!
* Traversal optimisations.
# 1.12.16
* Fix comments not being retained from `MethodDefinition` in classes.
* Add temporal dead zone in default parameters.
# 1.12.15
* Update `acorn-6to5`.
# 1.12.14
* Fix duplicate let scoping in functions.
* Make JSX whitespace more React-compliant.
* Add `_memberExpressionKeywords` transformer that turns keyword identifiers to computed literals.
* Upgrade `regenerator-6to5`.
# 1.12.13
* Support duplicate constants within different block scopes.
* Fix for-head duplication testing and replacement.
* Support `raw` property on tagged template literals.
# 1.12.12
* Make scope tracker more reliable to handle all edgecases.
# 1.12.11
* Block scope classes.
* Fix generation of integer `Literal`s in `MemberExpression`.
# 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.

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:

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 `browser-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.

226
doc/features.md Normal file
View File

@@ -0,0 +1,226 @@
# 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)

View File

@@ -66,7 +66,7 @@ export function bar() {
**Out**
```javascript
define(["exports", "foo"], function (exports, _foo) {
define("filename", ["exports", "foo"], function (exports, _foo) {
exports.bar = bar;
var foo = _foo.default;
@@ -94,7 +94,7 @@ export function bar() {
```javascript
(function (factory) {
if (typeof define === "function" && define.amd) {
define(["exports", "foo"], factory);
define("filename", ["exports", "foo"], factory);
} else if (typeof exports !== "undefined") {
factory(exports, require("foo"));
}
@@ -111,7 +111,6 @@ export function bar() {
### Ignore
**In**
```javascript

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/josh/sprockets-es6) or via [browserify-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

172
doc/usage.md Normal file
View File

@@ -0,0 +1,172 @@
# 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",
// Filename relative to `sourceRoot`
// Default: `filename` option.
filenameRelative: "",
// 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: `filenameRelative` option.
sourceMapName: "filename",
// Set `sources[0]` on returned source map.
// Default: `filenameRelative` option.
sourceFileName: "filename",
// The root from which all sources are relative
sourceRoot: "assets/scripts",
// Optional prefix for the AMD module formatter that will be prepend to the
// filename on module definitions
moduleRoot: "my-app",
// 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";
@@ -19,7 +12,7 @@ transform.load = function (url, callback, opts, hold) {
opts = opts || {};
opts.filename = opts.filename || url;
var xhr = window.ActiveXObject ? new window.ActiveXObject("Microsoft.XMLHTTP") : new window.XMLHttpRequest();
var xhr = global.ActiveXObject ? new global.ActiveXObject("Microsoft.XMLHTTP") : new global.XMLHttpRequest();
xhr.open("GET", url, true);
if ("overrideMimeType" in xhr) xhr.overrideMimeType("text/plain");
@@ -67,7 +60,7 @@ var runScripts = function () {
}
};
var _scripts = window.document.getElementsByTagName("script");
var _scripts = global.document.getElementsByTagName("script");
for (var i in _scripts) {
var _script = _scripts[i];
if (types.indexOf(_script.type) >= 0) scripts.push(_script);
@@ -80,8 +73,8 @@ var runScripts = function () {
exec();
};
if (window.addEventListener) {
window.addEventListener("DOMContentLoaded", runScripts, false);
} else {
window.attachEvent("onload", runScripts);
if (global.addEventListener) {
global.addEventListener("DOMContentLoaded", runScripts, false);
} else if (global.attachEvent) {
global.attachEvent("onload", runScripts);
}

View File

@@ -18,7 +18,8 @@ function File(opts) {
this.ast = {};
}
File.declarations = ["extends", "class-props", "slice"];
File.declarations = ["extends", "class-props", "slice", "apply-constructor",
"tagged-template-literal"];
File.normaliseOptions = function (opts) {
opts = _.cloneDeep(opts || {});
@@ -30,15 +31,20 @@ 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
filenameRelative: opts.filename
});
_.defaults(opts, {
sourceFileName: opts.filenameRelative,
sourceMapName: opts.filenameRelative
});
if (opts.runtime === true) {
@@ -142,6 +148,14 @@ 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) {
@@ -153,6 +167,8 @@ File.prototype.generate = function () {
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");
@@ -18,18 +19,21 @@ function CodeGenerator(ast, opts, code) {
this.comments = ast.comments || [];
this.tokens = ast.tokens || [];
this.opts = opts;
this.format = CodeGenerator.normaliseOptions(opts);
this.ast = ast;
this.buf = "";
this.format = CodeGenerator.normaliseOptions(opts);
this._indent = this.format.indent.base;
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 || {};
@@ -49,141 +53,30 @@ CodeGenerator.normaliseOptions = function (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.format.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.format.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.format.compact) {
return "";
} else {
return util.repeat(this._indent, this.format.indent.style);
}
};
CodeGenerator.prototype.indentSize = function () {
return this.getIndent().length;
};
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()
};
};
@@ -222,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;
}
@@ -246,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]) {

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

@@ -1,4 +1,5 @@
var t = require("../../types");
var util = require("../../util");
var t = require("../../types");
exports.UnaryExpression = function (node, print) {
var hasSpace = /[a-z]$/.test(node.operator);
@@ -105,6 +106,11 @@ exports.MemberExpression = function (node, print) {
print(node.property);
this.push("]");
} else {
// 5..toFixed(2);
if (t.isLiteral(node.object) && util.isInteger(node.object.value)) {
this.push(".");
}
this.push(".");
print(node.property);
}

View File

@@ -74,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,294 +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 (t.isSwitchCase(node) && parent.cases[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

@@ -9,7 +9,8 @@ function SourceMap(position, opts, code) {
if (opts.sourceMap) {
this.map = new sourceMap.SourceMapGenerator({
file: opts.sourceMapName
file: opts.sourceMapName,
sourceRoot: opts.sourceRoot
});
this.map.setSourceContent(opts.sourceFileName, code);

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

@@ -5,7 +5,7 @@ var t = require("./types");
var _ = require("lodash");
module.exports = function (namespace) {
namespace = t.identifier(namespace || "to5Runtime");
namespace = t.identifier(t.toIdentifier(namespace || "to5Runtime"));
var body = [];
var container = t.functionExpression(null, [], t.blockStatement(body));

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

@@ -0,0 +1,4 @@
(function (strings, raw) {
return Object.defineProperties(strings, { raw: { value: raw } });
});

View File

@@ -29,12 +29,41 @@ AMDFormatter.prototype.transform = function (ast) {
var params = _.values(this.ids);
params.unshift(t.identifier("exports"));
var moduleName = this.getModuleName();
var container = t.functionExpression(null, params, t.blockStatement(body));
var call = t.callExpression(t.identifier("define"), [names, container]);
var call = t.callExpression(t.identifier("define"), [t.literal(moduleName), names, container]);
program.body = [t.expressionStatement(call)];
};
AMDFormatter.prototype.getModuleName = function () {
var opts = this.file.opts;
var filenameRelative = opts.filenameRelative;
var moduleName = "";
if (opts.moduleRoot) {
moduleName = opts.moduleRoot + "/";
}
if (!opts.filenameRelative) {
return moduleName + opts.filename.replace(/^\//, "");
}
if (opts.sourceRoot) {
// remove sourceRoot from filename
var sourceRootRegEx = new RegExp("^" + opts.sourceRoot + "\/?");
filenameRelative = filenameRelative.replace(sourceRootRegEx, "");
}
// remove extension
filenameRelative = filenameRelative.replace(/\.(.*?)$/, "");
moduleName += filenameRelative;
return moduleName;
};
AMDFormatter.prototype._push = function (node) {
var id = node.source.value;
var ids = this.ids;

View File

@@ -32,8 +32,10 @@ UMDFormatter.prototype.transform = function (ast) {
// runner
var moduleName = this.getModuleName();
var runner = util.template("umd-runner-body", {
AMD_ARGUMENTS: t.arrayExpression([t.literal("exports")].concat(names)),
AMD_ARGUMENTS: [t.literal(moduleName), t.arrayExpression([t.literal("exports")].concat(names))],
COMMON_ARGUMENTS: names.map(function (name) {
return t.callExpression(t.identifier("require"), [name]);

View File

@@ -27,38 +27,39 @@ transform.moduleFormatters = {
};
_.each({
modules: require("./transformers/modules"),
propertyNameShorthand: require("./transformers/property-name-shorthand"),
constants: require("./transformers/constants"),
arrayComprehension: require("./transformers/array-comprehension"),
arrowFunctions: require("./transformers/arrow-functions"),
classes: require("./transformers/classes"),
modules: require("./transformers/modules"),
propertyNameShorthand: require("./transformers/property-name-shorthand"),
arrayComprehension: require("./transformers/array-comprehension"),
generatorComprehension: require("./transformers/generator-comprehension"),
arrowFunctions: require("./transformers/arrow-functions"),
classes: require("./transformers/classes"),
_propertyLiterals: require("./transformers/_property-literals"),
computedPropertyNames: require("./transformers/computed-property-names"),
_propertyLiterals: require("./transformers/_property-literals"),
computedPropertyNames: require("./transformers/computed-property-names"),
spread: require("./transformers/spread"),
templateLiterals: require("./transformers/template-literals"),
propertyMethodAssignment: require("./transformers/property-method-assignment"),
defaultParameters: require("./transformers/default-parameters"),
restParameters: require("./transformers/rest-parameters"),
destructuring: require("./transformers/destructuring"),
letScoping: require("./transformers/let-scoping"),
forOf: require("./transformers/for-of"),
unicodeRegex: require("./transformers/unicode-regex"),
numericLiterals: require("./transformers/numeric-literals"),
spread: require("./transformers/spread"),
templateLiterals: require("./transformers/template-literals"),
propertyMethodAssignment: require("./transformers/property-method-assignment"),
defaultParameters: require("./transformers/default-parameters"),
restParameters: require("./transformers/rest-parameters"),
destructuring: require("./transformers/destructuring"),
forOf: require("./transformers/for-of"),
unicodeRegex: require("./transformers/unicode-regex"),
react: require("./transformers/react"),
jsx: require("./transformers/jsx"),
constants: require("./transformers/constants"),
letScoping: require("./transformers/let-scoping"),
_aliasFunctions: require("./transformers/_alias-functions"),
_blockHoist: require("./transformers/_block-hoist"),
_declarations: require("./transformers/_declarations"),
react: require("./transformers/react"),
generators: require("./transformers/generators"),
useStrict: require("./transformers/use-strict"),
_aliasFunctions: require("./transformers/_alias-functions"),
_blockHoist: require("./transformers/_block-hoist"),
_declarations: require("./transformers/_declarations"),
_moduleFormatter: require("./transformers/_module-formatter")
generators: require("./transformers/generators"),
useStrict: require("./transformers/use-strict"),
_memberExpressionKeywords: require("./transformers/_member-expression-keywords"),
_moduleFormatter: require("./transformers/_module-formatter")
}, function (transformer, key) {
transform.transformers[key] = new Transformer(key, transformer);
});

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

@@ -0,0 +1,10 @@
var esutils = require("esutils");
var t = require("../../types");
exports.MemberExpression = function (node) {
var prop = node.property;
if (t.isIdentifier(prop) && esutils.keyword.isKeywordES6(prop.name, true)) {
node.property = t.literal(prop.name);
node.computed = true;
}
};

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

@@ -4,13 +4,13 @@ var t = require("../../types");
var _ = require("lodash");
exports.ClassDeclaration = function (node, parent, file, scope) {
return t.variableDeclaration("var", [
t.variableDeclarator(node.id, buildClass(node, file, scope))
return t.variableDeclaration("let", [
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,51 @@ 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);
t.inheritsComments(construct, method);
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

@@ -7,26 +7,30 @@ exports.BlockStatement =
exports.ForInStatement =
exports.ForOfStatement =
exports.ForStatement = function (node, parent, file) {
var constants = [];
var constants = {};
var check = function (node, names) {
_.each(names, function (name) {
if (constants.indexOf(name) >= 0) {
throw file.errorWithNode(node, name + " is read-only");
}
var check = function (parent, names) {
_.each(names, function (nameNode, name) {
if (!_.has(constants, name)) return;
if (parent && t.isBlockStatement(parent) && parent !== constants[name]) return;
throw file.errorWithNode(nameNode, name + " is read-only");
});
};
var getIds = function (node) {
return t.getIds(node, false, ["MemberExpression"]);
return t.getIds(node, true, ["MemberExpression"]);
};
_.each(node.body, function (child) {
_.each(node.body, function (child, parent) {
if (child && t.isVariableDeclaration(child, { kind: "const" })) {
_.each(child.declarations, function (declar) {
_.each(getIds(declar), function (name) {
check(declar, [name]);
constants.push(name);
_.each(getIds(declar), function (nameNode, name) {
var names = {};
names[name] = nameNode;
check(parent, names);
constants[name] = parent;
});
declar._ignoreConstant = true;
@@ -37,13 +41,14 @@ exports.ForStatement = function (node, parent, file) {
}
});
if (!constants.length) return;
if (_.isEmpty(constants)) return;
traverse(node, function (child) {
traverse(node, function (child, parent) {
if (child._ignoreConstant) return;
if (t.isVariableDeclaration(child)) return;
if (t.isVariableDeclarator(child) || t.isDeclaration(child) || t.isAssignmentExpression(child)) {
check(child, getIds(child));
check(parent, getIds(child));
}
});
};

View File

@@ -1,21 +1,70 @@
var util = require("../../util");
var t = require("../../types");
var _ = require("lodash");
var traverse = require("../../traverse");
var util = require("../../util");
var t = require("../../types");
var _ = require("lodash");
exports.Function = function (node) {
if (!node.defaults.length) return;
exports.Function = function (node, parent, file, scope) {
if (!node.defaults || !node.defaults.length) return;
t.ensureBlock(node);
var ids = node.params.map(function (param) {
return t.getIds(param);
});
var closure = false;
_.each(node.defaults, function (def, i) {
if (!def) return;
var param = node.params[i];
node.body.body.unshift(util.template("if-undefined-set-to", {
VARIABLE: param,
DEFAULT: def
// temporal dead zone check - here we prevent accessing of params that
// are to the right - ie. uninitialized parameters
_.each(ids.slice(i), function (ids) {
var check = function (node, parent) {
if (!t.isIdentifier(node) || !t.isReferenced(node, parent)) return;
if (_.contains(ids, node.name)) {
throw file.errorWithNode(node, "Temporal dead zone - accessing a variable before it's initialized");
}
if (scope.has(node.name)) {
closure = true;
}
};
check(def, node);
traverse(def, check);
});
// we're accessing a variable that's already defined within this function
var has = scope.get(param.name);
if (has && !_.contains(node.params, has)) {
closure = true;
}
});
var body = [];
_.each(node.defaults, function (def, i) {
if (!def) return;
body.push(util.template("if-undefined-set-to", {
VARIABLE: node.params[i],
DEFAULT: def
}, true));
});
if (closure) {
var container = t.functionExpression(null, [], node.body, node.generator);
container._aliasFunction = true;
body.push(t.returnStatement(t.callExpression(container, [])));
node.body = t.blockStatement(body);
} else {
node.body.body = body.concat(node.body.body);
}
node.defaults = [];
};

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,101 +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, i) {
var val = child.value;
if (t.isLiteral(child) && _.isString(val)) {
val = val.replace(/\n(\s+)/g, " ");
i = +i;
if (i === 0) val = val.trimLeft();
if (i === children.length - 1) val = val.trimRight();
if (!val) return;
child.value = val;
}
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,29 +50,134 @@ 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 = [];
}
/**
* Start the ball rolling.
*/
LetScoping.prototype.run = function () {
var block = this.block;
if (block._letDone) return;
block._letDone = true;
this.info = this.getInfo();
// this is a block within a `Function` so we can safely leave it be
if (t.isFunction(this.parent)) return this.noClosure();
// 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;
traverse(block, function (node, parent) {
var replace = function (node, parent) {
if (!t.isIdentifier(node)) return;
if (!t.isReferenced(node, parent)) return;
node.name = replacements[node.name] || node.name;
});
};
var traverseReplace = function (node, parent) {
replace(node, parent);
traverse(node, replace);
};
var forParent = this.forParent;
if (forParent) {
traverseReplace(forParent.right, forParent);
traverseReplace(forParent.test, forParent);
traverseReplace(forParent.update, forParent);
}
traverse(block, replace);
};
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
@@ -84,10 +196,23 @@ var getInfo = function (block, file, scope) {
keys: []
};
var duplicates = function (id, key) {
var has = scope.parentGet(key);
if (has && has !== id) {
// there's a variable with this exact name in an upper scope so we need
// to generate a new name
opts.duplicates[key] = id.name = file.generateUid(key, scope);
}
};
_.each(opts.declarators, function (declar) {
opts.declarators.push(declar);
var keys = t.getIds(declar);
var keys = t.getIds(declar, true);
_.each(keys, duplicates);
keys = _.keys(keys);
opts.outsideKeys = opts.outsideKeys.concat(keys);
opts.keys = opts.keys.concat(keys);
});
@@ -96,14 +221,7 @@ var getInfo = function (block, file, scope) {
if (!isLet(declar)) return;
_.each(t.getIds(declar, true), function (id, key) {
var has = scope.parentGet(key);
if (has && has !== id) {
// there's a variable with this exact name in an upper scope so we need
// to generate a new name
opts.duplicates[key] = id.name = file.generateUid(key, scope);
}
duplicates(id, key);
opts.keys.push(key);
});
});
@@ -111,15 +229,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)) {
@@ -144,38 +271,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 +339,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,125 +354,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)
]));
var retCheck;
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(file.generateUid("loop", scope));
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 (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 {
if (has.hasReturn) body.push(retCheck);
}
this.buildHas(ret, call);
} else {
body.push(t.expressionStatement(call));
this.body.push(t.expressionStatement(call));
}
};
/**
* Description
*
* @param {Node} ret Identifier
* @param {Node} call CallExpression
*/
LetScoping.prototype.buildHas = function (ret, call) {
var body = this.body;
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.hasContinue) {
cases.push(t.switchCase(t.literal("continue"), [t.continueStatement(label)]));
}
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 {
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,148 @@
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;
_.each(node.children, function (child) {
if (t.isLiteral(child)) {
var lines = child.value.split(/\r\n|\n|\r/);
_.each(lines, function (line, i) {
var isFirstLine = i === 0;
var isLastLine = i === lines.length - 1;
// replace rendered whitespace tabs with spaces
var trimmedLine = line.replace(/\t/g, ' ');
// trim whitespace touching a newline
if (!isFirstLine) {
trimmedLine = trimmedLine.replace(/^[ ]+/, '');
}
// trim whitespace touching an endline
if (!isLastLine) {
trimmedLine = trimmedLine.replace(/[ ]+$/, '');
}
if (trimmedLine) {
callExpr.arguments.push(t.literal(trimmedLine));
}
});
return;
}
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

@@ -5,14 +5,22 @@ var buildBinaryExpression = function (left, right) {
return t.binaryExpression("+", left, right);
};
exports.TaggedTemplateExpression = function (node) {
exports.TaggedTemplateExpression = function (node, parent, file) {
var args = [];
var quasi = node.quasi;
var strings = quasi.quasis.map(function (elem) {
return t.literal(elem.value.raw);
var strings = [];
var raw = [];
_.each(quasi.quasis, function (elem) {
strings.push(t.literal(elem.value.cooked));
raw.push(t.literal(elem.value.raw));
});
args.push(t.arrayExpression(strings));
args.push(t.callExpression(file.addDeclaration("tagged-template-literal"), [
t.arrayExpression(strings),
t.arrayExpression(raw)
]));
_.each(quasi.expressions, function (expr) {
args.push(expr);

View File

@@ -29,25 +29,32 @@ function traverse(parent, callbacks, opts) {
// normalise callbacks
if (_.isFunction(callbacks)) callbacks = { enter: callbacks };
_.each(keys, function (key) {
for (var i in keys) {
var key = keys[i];
var nodes = parent[key];
if (!nodes) return;
if (!nodes) continue;
var updated = false;
var handle = function (obj, key) {
var node = obj[key];
if (!node) return;
// type is blacklisted
if (_.contains(blacklistTypes, node.type)) return;
if (blacklistTypes.indexOf(node.type) > -1) return;
// replace node
var maybeReplace = function (result) {
if (result === false) return;
if (result != null) node = obj[key] = result;
if (result != null) {
updated = true;
node = obj[key] = result;
}
};
//
var opts2 = _.clone(opts);
var opts2 = { scope: opts.scope, blacklist: opts.blacklist };
if (t.isScope(node)) opts2.scope = new Scope(opts.scope, node);
// enter
@@ -69,15 +76,15 @@ function traverse(parent, callbacks, opts) {
};
if (_.isArray(nodes)) {
_.each(nodes, function (node, i) {
for (i in nodes) {
handle(nodes, i);
});
}
parent[key] = _.flatten(parent[key]);
if (updated) parent[key] = _.flatten(parent[key]);
} else {
handle(parent, key);
}
});
}
}
traverse.removeProperties = function (tree) {

View File

@@ -4,54 +4,93 @@ var traverse = require("./index");
var t = require("../types");
var _ = require("lodash");
var FOR_KEYS = ["left", "init"];
function Scope(parent, block) {
this.parent = parent;
this.block = block;
this.ids = this.getIds();
this.getIds();
this.info = this.getInfo();
this.declarations = this.info.declarations;
}
Scope.prototype.getIds = function () {
Scope.prototype.getInfo = function () {
var block = this.block;
if (block._scopeIds) return block._scopeIds;
if (block._scope) return block._scope;
var self = this;
var ids = block._scopeIds = {};
var info = block._scope = {
declarations: {}
};
if (t.isBlockStatement(block)) {
_.each(block.body, function (node) {
if (t.isVariableDeclaration(node) && node.kind !== "var") {
self.add(node, ids);
}
});
} else if (t.isProgram(block) || t.isFunction(block)) {
traverse(block, function (node, parent) {
if (parent !== block && t.isVariableDeclaration(node) && node.kind !== "var") {
return;
}
var add = function (node) {
self.addDeclaration(node, info.declarations);
};
if (t.isDeclaration(node)) {
self.add(node, ids);
} else if (t.isFunction(node)) {
return false;
}
// ForStatement - left, init
if (t.isFor(block)) {
_.each(FOR_KEYS, function (key) {
var node = block[key];
if (t.isLet(node)) add(node);
});
} else if (t.isCatchClause(block)) {
self.add(block.param, ids);
block = block.body;
}
// Program, BlockStatement - let variables
if (t.isBlockStatement(block) || t.isProgram(block)) {
_.each(block.body, function (node) {
// check for non-var `VariableDeclaration`s
if (t.isLet(node)) add(node);
});
}
// CatchClause - param
if (t.isCatchClause(block)) {
add(block.param);
}
// Program, Function - var variables
if (t.isProgram(block) || t.isFunction(block)) {
traverse(block, function (node) {
if (t.isFor(node)) {
_.each(FOR_KEYS, function (key) {
var declar = node[key];
if (t.isVar(declar)) add(declar);
});
}
// this block is a function so we'll stop since none of the variables
// declared within are accessible
if (t.isFunction(node)) return false;
// we've ran into a declaration!
// we'll let the BlockStatement scope deal with `let` declarations
if (t.isDeclaration(node) && !t.isLet(node)) {
add(node);
}
});
}
// Function - params, rest
if (t.isFunction(block)) {
add(block.rest);
_.each(block.params, function (param) {
self.add(param, ids);
add(param);
});
}
return ids;
return info;
};
Scope.prototype.add = function (node, ids) {
_.merge(ids || this.ids, t.getIds(node, true));
Scope.prototype.addDeclaration = function (node, declarations) {
if (!node) return;
_.merge(declarations || this.declarations, t.getIds(node, true));
};
Scope.prototype.get = function (id) {
@@ -59,7 +98,7 @@ Scope.prototype.get = function (id) {
};
Scope.prototype.getOwn = function (id) {
return _.has(this.ids, id) && this.ids[id];
return _.has(this.declarations, id) && this.declarations[id];
};
Scope.prototype.parentGet = function (id) {

View File

@@ -35,12 +35,13 @@
"ClassDeclaration": ["Statement", "Declaration", "Class"],
"ClassExpression": ["Class"],
"ForOfStatement": ["Statement", "For"],
"ForInStatement": ["Statement", "For"],
"ForStatement": ["Statement", "For"],
"ForOfStatement": ["Statement", "For", "Scope"],
"ForInStatement": ["Statement", "For", "Scope"],
"ForStatement": ["Statement", "For", "Scope"],
"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

@@ -70,6 +70,9 @@ t.isReferenced = function (node, parent) {
// we're a property key so we aren't referenced
if (t.isProperty(parent) && parent.key === node) return false;
// we're a variable declarator id so we aren't referenced
if (t.isVariableDeclarator(parent) && parent.id === node) return false;
var isMemberExpression = t.isMemberExpression(parent);
// we're in a member expression and we're the computed property so we're referenced
@@ -106,6 +109,10 @@ t.ensureBlock = function (node) {
};
t.toStatement = function (node, ignore) {
if (t.isStatement(node)) {
return node;
}
var mustHaveId = false;
var newType;
@@ -115,8 +122,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) {
@@ -159,7 +164,7 @@ t.toBlock = function (node, parent) {
t.getIds = function (node, map, ignoreTypes) {
ignoreTypes = ignoreTypes || [];
var search = [node];
var search = [].concat(node);
var ids = {};
while (search.length) {
@@ -204,11 +209,32 @@ t.getIds.arrays = {
ObjectPattern: "properties"
};
t.isLet = function (node) {
return t.isVariableDeclaration(node) && (node.kind !== "var" || node._let);
};
t.isVar = function (node) {
return t.isVariableDeclaration(node, { kind: "var" }) && !node._let;
};
t.removeComments = function (child) {
delete child.leadingComments;
delete child.trailingComments;
return child;
};
t.inheritsComments = function (child, parent) {
child.leadingComments = _.compact([].concat(child.leadingComments, parent.leadingComments));
child.trailingComments = _.compact([].concat(child.trailingComments, parent.trailingComments));
return child;
};
t.inherits = function (child, parent) {
child.loc = parent.loc;
child.end = parent.end;
child.range = parent.range;
child.start = parent.start;
t.inheritsComments(child, parent);
return child;
};

View File

@@ -71,6 +71,6 @@
"XJSMemberExpression": ["object", "property"],
"XJSNamespacedName": ["namespace", "name"],
"XJSOpeningElement": ["name", "attributes"],
"XJSSpreadAttribute": [],
"XJSSpreadAttribute": ["argument"],
"YieldExpression": ["argument"]
}

View File

@@ -17,6 +17,10 @@ exports.canCompile = function (filename, altExts) {
return _.contains(exts, ext);
};
exports.isInteger = function (i) {
return _.isNumber(i) && i % 1 === 0;
};
exports.resolve = function (loc) {
try {
return require.resolve(loc);
@@ -25,6 +29,10 @@ exports.resolve = function (loc) {
}
};
exports.trimRight = function (str) {
return str.replace(/[\n\s]+$/g, "");
};
exports.list = function (val) {
return val ? val.split(",") : [];
};
@@ -98,8 +106,13 @@ exports.buildDefineProperties = function (mutatorMap) {
if (key[0] === "_") return;
node = _.clone(node);
var inheritNode = node;
if (t.isMethodDefinition(node)) node = node.value;
mapNode.properties.push(t.property("init", t.identifier(key), node));
var prop = t.property("init", t.identifier(key), node);
t.inheritsComments(prop, inheritNode);
t.removeComments(inheritNode);
mapNode.properties.push(prop);
});
objExpr.properties.push(propNode);
@@ -119,23 +132,17 @@ exports.template = function (name, nodes, keepExpression) {
template = _.cloneDeep(template);
var inherits = false;
if (nodes) {
inherits = nodes.inherits;
delete nodes.inherits;
if (!_.isEmpty(nodes)) {
traverse(template, function (node) {
if (t.isIdentifier(node) && _.has(nodes, node.name)) {
var newNode = nodes[node.name];
if (_.isString(newNode)) {
node.name = newNode;
} else {
return newNode;
}
if (!_.isEmpty(nodes)) {
traverse(template, function (node) {
if (t.isIdentifier(node) && _.has(nodes, node.name)) {
var newNode = nodes[node.name];
if (_.isString(newNode)) {
node.name = newNode;
} else {
return newNode;
}
});
}
}
});
}
var node = template.body[0];
@@ -146,10 +153,6 @@ exports.template = function (name, nodes, keepExpression) {
if (t.isParenthesizedExpression(node)) node = node.expression;
}
if (inherits) {
node = t.inherits(node, inherits);
}
return node;
};
@@ -240,7 +243,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 +265,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;
@@ -273,9 +276,5 @@ try {
} catch (err) {
if (err.code !== "MODULE_NOT_FOUND") throw err;
Object.defineProperty(exports, "templates", {
get: function () {
return exports.templates = loadTemplates();
}
});
exports.templates = loadTemplates();
}

View File

@@ -1,7 +1,7 @@
{
"name": "6to5",
"description": "Turn ES6 code into readable vanilla ES5 with source maps",
"version": "1.11.15",
"version": "1.12.18",
"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/62d1bfcb331dcf0bbcdbbee8043da0c6408f09cf.tar.gz",
"regenerator-6to5": "https://github.com/6to5/regenerator-6to5/archive/a9c53518af063ffef410f826225f8ee250131932.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/0384a0d51f630f66ed591769c1765581a17d2124.tar.gz",
"acorn-6to5": "https://github.com/6to5/acorn-6to5/archive/74d8e9bed20ba302d3504f53d0b1c649968959e1.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"

View File

@@ -36,8 +36,6 @@ exports.get = function (entryName) {
if (fs.existsSync(suiteOptsLoc)) suite.options = require(suiteOptsLoc);
_.each(fs.readdirSync(suite.filename), function (taskName) {
if (taskName[0] === ".") return;
var taskDir = suite.filename + "/" + taskName;
if (fs.statSync(taskDir).isFile()) return;
@@ -50,8 +48,9 @@ exports.get = function (entryName) {
var execLoc = taskDir + "/exec.js";
var taskOpts = _.merge({
filename: actualLocAlias,
sourceMapName: expectLocAlias
filenameRelative: expectLocAlias,
sourceFileName: actualLocAlias,
sourceMapName: expectLocAlias
}, _.cloneDeep(suite.options));
var taskOptsLoc = taskDir + "/options.json";
@@ -59,8 +58,10 @@ exports.get = function (entryName) {
var test = {
title: humanise(taskName),
disabled: taskName[0] === ".",
options: taskOpts,
exec: {
loc: execLoc,
code: readFile(execLoc),
filename: execLocAlias,
},

17
test/api.js Normal file
View File

@@ -0,0 +1,17 @@
var transform = require("../lib/6to5/transformation/transform");
var assert = require("assert");
var File = require("../lib/6to5/file");
suite("api", function () {
test("{ code: false }", function () {
var result = transform("foo('bar');", { code: false });
assert.ok(!result.code);
});
test("addDeclaration unknown", function () {
var file = new File;
assert.throws(function () {
file.addDeclaration("foob");
}, /unknown declaration foob/);
});
});

View File

@@ -149,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;

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