[Pkg-javascript-commits] [node-buble] 01/04: New upstream version 0.19.3

Julien Puydt julien.puydt at laposte.net
Sat Feb 17 23:21:54 UTC 2018


This is an automated email from the git hooks/post-receive script.

jpuydt-guest pushed a commit to branch master
in repository node-buble.

commit d5d50904c2f02e60ebc73a43dfd1808fcf61358e
Author: Julien Puydt <julien.puydt at laposte.net>
Date:   Sun Feb 18 00:12:59 2018 +0100

    New upstream version 0.19.3
---
 CHANGELOG.md                                  |  49 +++
 bin/runBuble.js                               |   2 +-
 package-lock.json                             | 587 +++++++++++---------------
 package.json                                  |  37 +-
 rollup.config.js                              |  90 ++--
 src/index.js                                  |  12 +-
 src/program/BlockStatement.js                 |  26 +-
 src/program/Node.js                           |  18 -
 src/program/Program.js                        |  21 +
 src/program/Scope.js                          |  15 +-
 src/program/types/ArrayExpression.js          |   4 +-
 src/program/types/AssignmentExpression.js     | 217 ++--------
 src/program/types/CallExpression.js           |   9 +-
 src/program/types/ClassDeclaration.js         |   4 +-
 src/program/types/ForInStatement.js           |  44 +-
 src/program/types/ForOfStatement.js           |  25 +-
 src/program/types/Identifier.js               |   3 +-
 src/program/types/JSXClosingElement.js        |   2 +-
 src/program/types/JSXClosingFragment.js       |  22 +
 src/program/types/JSXElement.js               |  11 +-
 src/program/types/JSXFragment.js              |   4 +
 src/program/types/JSXOpeningFragment.js       |   7 +
 src/program/types/NewExpression.js            |   7 +-
 src/program/types/ObjectExpression.js         |  29 +-
 src/program/types/Super.js                    |   2 +-
 src/program/types/TaggedTemplateExpression.js |  16 +-
 src/program/types/TemplateLiteral.js          |   2 +-
 src/program/types/UpdateExpression.js         |  15 +-
 src/program/types/VariableDeclaration.js      |   8 +-
 src/program/types/index.js                    |   6 +
 src/program/wrap.js                           |  13 +-
 src/support.js                                |  90 ++--
 src/utils/checkConst.js                       |   8 +
 src/utils/destructure.js                      | 107 +++--
 src/utils/removeTrailingComma.js              |   5 +-
 test/samples/block-scoping.js                 | 100 ++++-
 test/samples/computed-properties.js           |  51 ++-
 test/samples/destructuring.js                 | 130 +++++-
 test/samples/dynamic-import.js                |   8 +
 test/samples/exponentiation-operator.js       |  19 +-
 test/samples/for-of.js                        |  46 ++
 test/samples/jsx.js                           |  20 +
 test/samples/loops.js                         |  88 +++-
 test/samples/object-properties.js             |  14 +-
 test/samples/object-rest-spread.js            |  51 ++-
 test/samples/spread-operator.js               |  82 +++-
 test/samples/template-strings.js              |  18 +-
 test/samples/trailing-function-commas.js      |  32 +-
 test/test.js                                  |   8 +-
 49 files changed, 1388 insertions(+), 796 deletions(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 2377c3e..3232aff 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,54 @@
 # buble changelog
 
+## 0.19.3 (2018-02-13)
+
+* Make sure browser builds are actually valid ES5 (except for the modules build)
+
+## 0.19.2 (2018-02-12)
+
+* Correctly specify browser field in package.json ([#107](https://github.com/Rich-Harris/buble/issues/107))
+* Fix a compile error about using `super` outside of class methods
+* Fix transpiling rest properties
+
+## 0.19.1 (2018-02-10)
+
+* Fix transpiling let and const if arrow functions are not transpiled (i. e. node: 4)
+
+## 0.19.0 (2018-02-10)
+
+### Enhancements
+
+* Add support information for new environments
+* Add (pass-thru) support for aync generators and for-async-of
+* Add support for dynamic import ([#102](https://github.com/Rich-Harris/buble/pull/102))
+* Add support for JSX fragments ([#62](https://github.com/Rich-Harris/buble/issues/62))
+* Add unpkg build and transpile browser build for older environments ([#93](https://github.com/Rich-Harris/buble/issues/93))
+* Reuse tagged template quasis ([#67](https://github.com/Rich-Harris/buble/pull/67))
+* Transpile trailing commas in new expressions ([#63](https://github.com/Rich-Harris/buble/issues/63))
+* Add support for destructuring in for-in and for-of loop heads
+* Add support for destructuring in catch clause params
+* Add support for rest properties in assignments
+
+### Fixes
+
+* Don't remove commas in comments after the last argument ([#89](https://github.com/Rich-Harris/buble/issues/89))
+* Support transformations involving aliasing of variables in block scopes ([#60](https://github.com/Rich-Harris/buble/issues/60))
+* Evaluate expression only once with inline default pattern elements
+* Fix nested object and array patterns, rest properties and default values in for loop heads
+* Only put own properties in rest properties
+* Improve declaration of helper variables
+* Allow modification of mutable variables that shadow a const before declaration ([#59](https://github.com/Rich-Harris/buble/issues/59))
+* Correctly detect modification of immutable variables through destructuring assignments
+* In object methods, support destructuring declarations initialized with a variable having the same name as the method ([#86](https://github.com/Rich-Harris/buble/issues/86))
+* Fix properties with string literal keys after computed properties ([#91](https://github.com/Rich-Harris/buble/pull/91))
+* Fix methods after computed properties ([#101](https://github.com/Rich-Harris/buble/issues/101))
+* Fix short-hand generator methods
+* Fix template literals in array after spread element ([#105](https://github.com/Rich-Harris/buble/issues/105))
+* Fix arrow functions in array after spread element ([#100](https://github.com/Rich-Harris/buble/issues/100))
+* Fix arrow functions in new expression after spread element ([#100](https://github.com/Rich-Harris/buble/issues/100))
+* Restore decoding HTML entities in JSX ([#104](https://github.com/Rich-Harris/buble/issues/104))
+* Correct various entries in support matrix
+
 ## 0.18.0
 
 * Allow anonymous functions and classes as default exports ([#37](https://github.com/Rich-Harris/buble/issues/37))
diff --git a/bin/runBuble.js b/bin/runBuble.js
index cb621e3..a93c0a9 100644
--- a/bin/runBuble.js
+++ b/bin/runBuble.js
@@ -1,6 +1,6 @@
 var fs = require('fs');
 var path = require('path');
-var buble = require('../dist/buble.deps.js');
+var buble = require('..');
 var handleError = require('./handleError.js');
 var EOL = require('os').EOL;
 
diff --git a/package-lock.json b/package-lock.json
index 43849da..dab468d 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -1,41 +1,34 @@
 {
   "name": "buble",
-  "version": "0.17.2",
+  "version": "0.19.3",
   "lockfileVersion": 1,
   "requires": true,
   "dependencies": {
     "acorn": {
-      "version": "5.2.1",
-      "resolved": "https://registry.npmjs.org/acorn/-/acorn-5.2.1.tgz",
-      "integrity": "sha512-jG0u7c4Ly+3QkkW18V+NRDN+4bWHdln30NL1ZL2AvFZZmQe/BfopYCtghCKKVBUSetZ4QKcyA0pY6/4Gw8Pv8w=="
+      "version": "5.4.1",
+      "resolved": "https://registry.npmjs.org/acorn/-/acorn-5.4.1.tgz",
+      "integrity": "sha1-/cWNnRf0pOmNEC3tgmqbl1kSUQI="
     },
-    "acorn-jsx": {
-      "version": "3.0.1",
-      "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-3.0.1.tgz",
-      "integrity": "sha1-r9+UiPsezvyDSPb7IvRk4ypYs2s=",
+    "acorn-dynamic-import": {
+      "version": "3.0.0",
+      "resolved": "https://registry.npmjs.org/acorn-dynamic-import/-/acorn-dynamic-import-3.0.0.tgz",
+      "integrity": "sha1-kBzu5Mf6rvfgetKkfokGddpQong=",
       "requires": {
-        "acorn": "3.3.0"
-      },
-      "dependencies": {
-        "acorn": {
-          "version": "3.3.0",
-          "resolved": "https://registry.npmjs.org/acorn/-/acorn-3.3.0.tgz",
-          "integrity": "sha1-ReN/s56No/JbruP/U2niu18iAXo="
-        }
+        "acorn": "5.4.1"
       }
     },
-    "acorn5-object-spread": {
-      "version": "4.0.0",
-      "resolved": "https://registry.npmjs.org/acorn5-object-spread/-/acorn5-object-spread-4.0.0.tgz",
-      "integrity": "sha1-1XWAge7ZcSGrC+R+Mcqu8qo5lpc=",
+    "acorn-jsx": {
+      "version": "4.1.1",
+      "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-4.1.1.tgz",
+      "integrity": "sha1-6OQeSOov4MiWdAYQq2pP/YrdIl4=",
       "requires": {
-        "acorn": "5.2.1"
+        "acorn": "5.4.1"
       }
     },
     "ajv": {
-      "version": "5.3.0",
-      "resolved": "https://registry.npmjs.org/ajv/-/ajv-5.3.0.tgz",
-      "integrity": "sha1-RBT/dKUIecII7l/cgm4ywwNUnto=",
+      "version": "5.5.2",
+      "resolved": "https://registry.npmjs.org/ajv/-/ajv-5.5.2.tgz",
+      "integrity": "sha1-c7Xuyj+rZT49P5Qis0GtQiBdyWU=",
       "dev": true,
       "requires": {
         "co": "4.6.0",
@@ -53,7 +46,7 @@
     "ansi-escapes": {
       "version": "3.0.0",
       "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-3.0.0.tgz",
-      "integrity": "sha512-O/klc27mWNUigtv0F8NJWbLF00OcegQalkqKURWdosW08YZKi4m6CnSUSvIZG1otNJbTWhN01Hhz389DW7mvDQ==",
+      "integrity": "sha1-7D6LTp+AZPwCw6ybZfHCdb2o75I=",
       "dev": true
     },
     "ansi-regex": {
@@ -91,7 +84,7 @@
     "arr-flatten": {
       "version": "1.1.0",
       "resolved": "https://registry.npmjs.org/arr-flatten/-/arr-flatten-1.1.0.tgz",
-      "integrity": "sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg==",
+      "integrity": "sha1-NgSLv/TntH4TZkQxbJlmnqWukfE=",
       "dev": true
     },
     "array-union": {
@@ -151,6 +144,15 @@
             "supports-color": "2.0.0"
           }
         },
+        "strip-ansi": {
+          "version": "3.0.1",
+          "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz",
+          "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=",
+          "dev": true,
+          "requires": {
+            "ansi-regex": "2.1.1"
+          }
+        },
         "supports-color": {
           "version": "2.0.0",
           "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz",
@@ -166,9 +168,9 @@
       "dev": true
     },
     "brace-expansion": {
-      "version": "1.1.8",
-      "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.8.tgz",
-      "integrity": "sha1-wHshHHyVLsH479Uad+8NHTmQopI=",
+      "version": "1.1.10",
+      "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.10.tgz",
+      "integrity": "sha512-u0KjSZq9NOEh36yRmKT/pIYOu0rpGAyUTeUmJgNd1K2tpAaUomh092TZ0fqbBGQc4hz85BVngAiB2mqekvQvIw==",
       "dev": true,
       "requires": {
         "balanced-match": "1.0.0",
@@ -186,23 +188,6 @@
         "repeat-element": "1.1.2"
       }
     },
-    "browser-resolve": {
-      "version": "1.11.2",
-      "resolved": "https://registry.npmjs.org/browser-resolve/-/browser-resolve-1.11.2.tgz",
-      "integrity": "sha1-j/CbCixCFxihBRwmCzLkj0QpOM4=",
-      "dev": true,
-      "requires": {
-        "resolve": "1.1.7"
-      },
-      "dependencies": {
-        "resolve": {
-          "version": "1.1.7",
-          "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.1.7.tgz",
-          "integrity": "sha1-IDEU2CrSxe2ejgQRs5ModeiJ6Xs=",
-          "dev": true
-        }
-      }
-    },
     "browser-stdout": {
       "version": "1.3.0",
       "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.0.tgz",
@@ -210,57 +195,19 @@
       "dev": true
     },
     "buble": {
-      "version": "0.8.2",
-      "resolved": "https://registry.npmjs.org/buble/-/buble-0.8.2.tgz",
-      "integrity": "sha1-qsqgCrya8VWSdMV40vCXeyv0oaY=",
+      "version": "0.19.1",
+      "resolved": "https://registry.npmjs.org/buble/-/buble-0.19.1.tgz",
+      "integrity": "sha512-coEp3YIDTC2sInoPkY9ztJDr7oZVX/l5MUZ8ioGerlEXtUkacYd3qB6ln7pCUIaPhlJJZ3OeeVMd1GxxwaFiSg==",
       "dev": true,
       "requires": {
-        "acorn": "3.3.0",
-        "chalk": "1.1.3",
-        "magic-string": "0.13.1",
-        "minimist": "1.2.0"
-      },
-      "dependencies": {
-        "acorn": {
-          "version": "3.3.0",
-          "resolved": "https://registry.npmjs.org/acorn/-/acorn-3.3.0.tgz",
-          "integrity": "sha1-ReN/s56No/JbruP/U2niu18iAXo=",
-          "dev": true
-        },
-        "ansi-styles": {
-          "version": "2.2.1",
-          "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz",
-          "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=",
-          "dev": true
-        },
-        "chalk": {
-          "version": "1.1.3",
-          "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz",
-          "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=",
-          "dev": true,
-          "requires": {
-            "ansi-styles": "2.2.1",
-            "escape-string-regexp": "1.0.5",
-            "has-ansi": "2.0.0",
-            "strip-ansi": "3.0.1",
-            "supports-color": "2.0.0"
-          }
-        },
-        "magic-string": {
-          "version": "0.13.1",
-          "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.13.1.tgz",
-          "integrity": "sha1-QEuYyVFhmndKLJJXDA07HmZ3nj4=",
-          "dev": true,
-          "requires": {
-            "vlq": "0.2.3"
-          }
-        },
-        "supports-color": {
-          "version": "2.0.0",
-          "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz",
-          "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=",
-          "dev": true
-        }
+        "acorn": "5.4.1",
+        "acorn-dynamic-import": "3.0.0",
+        "acorn-jsx": "4.1.1",
+        "chalk": "2.3.1",
+        "magic-string": "0.22.4",
+        "minimist": "1.2.0",
+        "os-homedir": "1.0.2",
+        "vlq": "1.0.0"
       }
     },
     "builtin-modules": {
@@ -285,19 +232,25 @@
       "dev": true
     },
     "chalk": {
-      "version": "2.3.0",
-      "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.3.0.tgz",
-      "integrity": "sha512-Az5zJR2CBujap2rqXGaJKaPHyJ0IrUimvYNX+ncCy8PJP4ltOGTrHUIo097ZaL2zMeKYpiCdqDvS6zdrTFok3Q==",
+      "version": "2.3.1",
+      "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.3.1.tgz",
+      "integrity": "sha512-QUU4ofkDoMIVO7hcx1iPTISs88wsO8jA92RQIm4JAwZvFGGAV2hSAA1NX7oVj2Ej2Q6NDTcRDjPTFrMCRZoJ6g==",
       "requires": {
         "ansi-styles": "3.2.0",
         "escape-string-regexp": "1.0.5",
-        "supports-color": "4.5.0"
+        "supports-color": "5.2.0"
       }
     },
+    "chardet": {
+      "version": "0.4.2",
+      "resolved": "https://registry.npmjs.org/chardet/-/chardet-0.4.2.tgz",
+      "integrity": "sha1-tUc7M9yXxCTl2Y3IfVXU2KKci/I=",
+      "dev": true
+    },
     "circular-json": {
       "version": "0.3.3",
       "resolved": "https://registry.npmjs.org/circular-json/-/circular-json-0.3.3.tgz",
-      "integrity": "sha512-UZK3NBx2Mca+b5LsG7bY183pHWt5Y1xts4P3Pz7ENTwGVnJOUWbRb3ocjvX7hx9tq/yTAdclXm9sZ38gNuem4A==",
+      "integrity": "sha1-gVyZ6oT2gJUp0vRXkb34JxE1LWY=",
       "dev": true
     },
     "cli-cursor": {
@@ -337,7 +290,7 @@
     "commander": {
       "version": "2.11.0",
       "resolved": "https://registry.npmjs.org/commander/-/commander-2.11.0.tgz",
-      "integrity": "sha512-b0553uYA5YAEGgyYIGYROzKQ7X5RAqedkfjiZxwi0kL1g3bOaBNNZfYkzt/CL0umgD5wc9Jec2FbB98CjkMRvQ==",
+      "integrity": "sha1-FXFS/R56bI2YpbcVzzdt+SgARWM=",
       "dev": true
     },
     "concat-map": {
@@ -353,7 +306,7 @@
       "dev": true,
       "requires": {
         "inherits": "2.0.3",
-        "readable-stream": "2.3.3",
+        "readable-stream": "2.3.4",
         "typedarray": "0.0.6"
       }
     },
@@ -383,7 +336,7 @@
     "debug": {
       "version": "3.1.0",
       "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz",
-      "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==",
+      "integrity": "sha1-W7WgZyYotkFJVmuhaBnmFRjGcmE=",
       "dev": true,
       "requires": {
         "ms": "2.0.0"
@@ -413,17 +366,16 @@
     "diff": {
       "version": "3.3.1",
       "resolved": "https://registry.npmjs.org/diff/-/diff-3.3.1.tgz",
-      "integrity": "sha512-MKPHZDMB0o6yHyDryUOScqZibp914ksXwAMYMTHj6KO8UeKsRYNJD3oNCKjTqZon+V488P7N/HzXF8t7ZR95ww==",
+      "integrity": "sha1-qoVnpu7QPFMfyJ0/cRzQ5SWd7HU=",
       "dev": true
     },
     "doctrine": {
-      "version": "2.0.0",
-      "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.0.0.tgz",
-      "integrity": "sha1-xz2NKQnSIpHhoAejlYBNqLZl/mM=",
+      "version": "2.1.0",
+      "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz",
+      "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==",
       "dev": true,
       "requires": {
-        "esutils": "2.0.2",
-        "isarray": "1.0.0"
+        "esutils": "2.0.2"
       }
     },
     "escape-string-regexp": {
@@ -432,35 +384,35 @@
       "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ="
     },
     "eslint": {
-      "version": "4.11.0",
-      "resolved": "https://registry.npmjs.org/eslint/-/eslint-4.11.0.tgz",
-      "integrity": "sha512-UWbhQpaKlm8h5x/VLwm0S1kheMrDj8jPwhnBMjr/Dlo3qqT7MvcN/UfKAR3E1N4lr4YNtOvS4m3hwsrVc/ky7g==",
+      "version": "4.17.0",
+      "resolved": "https://registry.npmjs.org/eslint/-/eslint-4.17.0.tgz",
+      "integrity": "sha512-AyxBUCANU/o/xC0ijGMKavo5Ls3oK6xykiOITlMdjFjrKOsqLrA7Nf5cnrDgcKrHzBirclAZt63XO7YZlVUPwA==",
       "dev": true,
       "requires": {
-        "ajv": "5.3.0",
+        "ajv": "5.5.2",
         "babel-code-frame": "6.26.0",
-        "chalk": "2.3.0",
+        "chalk": "2.3.1",
         "concat-stream": "1.6.0",
         "cross-spawn": "5.1.0",
         "debug": "3.1.0",
-        "doctrine": "2.0.0",
+        "doctrine": "2.1.0",
         "eslint-scope": "3.7.1",
-        "espree": "3.5.2",
+        "eslint-visitor-keys": "1.0.0",
+        "espree": "3.5.3",
         "esquery": "1.0.0",
-        "estraverse": "4.2.0",
         "esutils": "2.0.2",
         "file-entry-cache": "2.0.0",
         "functional-red-black-tree": "1.0.1",
         "glob": "7.1.2",
-        "globals": "9.18.0",
+        "globals": "11.3.0",
         "ignore": "3.3.7",
         "imurmurhash": "0.1.4",
         "inquirer": "3.3.0",
-        "is-resolvable": "1.0.0",
+        "is-resolvable": "1.1.0",
         "js-yaml": "3.10.0",
         "json-stable-stringify-without-jsonify": "1.0.1",
         "levn": "0.3.0",
-        "lodash": "4.17.4",
+        "lodash": "4.17.5",
         "minimatch": "3.0.4",
         "mkdirp": "0.5.1",
         "natural-compare": "1.4.0",
@@ -469,28 +421,11 @@
         "pluralize": "7.0.0",
         "progress": "2.0.0",
         "require-uncached": "1.0.3",
-        "semver": "5.4.1",
+        "semver": "5.5.0",
         "strip-ansi": "4.0.0",
         "strip-json-comments": "2.0.1",
         "table": "4.0.2",
         "text-table": "0.2.0"
-      },
-      "dependencies": {
-        "ansi-regex": {
-          "version": "3.0.0",
-          "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz",
-          "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=",
-          "dev": true
-        },
-        "strip-ansi": {
-          "version": "4.0.0",
-          "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz",
-          "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=",
-          "dev": true,
-          "requires": {
-            "ansi-regex": "3.0.0"
-          }
-        }
       }
     },
     "eslint-scope": {
@@ -503,20 +438,45 @@
         "estraverse": "4.2.0"
       }
     },
+    "eslint-visitor-keys": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.0.0.tgz",
+      "integrity": "sha512-qzm/XxIbxm/FHyH341ZrbnMUpe+5Bocte9xkmFMzPMjRaZMcXww+MpBptFvtU+79L362nqiLhekCxCxDPaUMBQ==",
+      "dev": true
+    },
     "espree": {
-      "version": "3.5.2",
-      "resolved": "https://registry.npmjs.org/espree/-/espree-3.5.2.tgz",
-      "integrity": "sha512-sadKeYwaR/aJ3stC2CdvgXu1T16TdYN+qwCpcWbMnGJ8s0zNWemzrvb2GbD4OhmJ/fwpJjudThAlLobGbWZbCQ==",
+      "version": "3.5.3",
+      "resolved": "https://registry.npmjs.org/espree/-/espree-3.5.3.tgz",
+      "integrity": "sha512-Zy3tAJDORxQZLl2baguiRU1syPERAIg0L+JB2MWorORgTu/CplzvxS9WWA7Xh4+Q+eOQihNs/1o1Xep8cvCxWQ==",
       "dev": true,
       "requires": {
-        "acorn": "5.2.1",
+        "acorn": "5.4.1",
         "acorn-jsx": "3.0.1"
+      },
+      "dependencies": {
+        "acorn-jsx": {
+          "version": "3.0.1",
+          "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-3.0.1.tgz",
+          "integrity": "sha1-r9+UiPsezvyDSPb7IvRk4ypYs2s=",
+          "dev": true,
+          "requires": {
+            "acorn": "3.3.0"
+          },
+          "dependencies": {
+            "acorn": {
+              "version": "3.3.0",
+              "resolved": "https://registry.npmjs.org/acorn/-/acorn-3.3.0.tgz",
+              "integrity": "sha1-ReN/s56No/JbruP/U2niu18iAXo=",
+              "dev": true
+            }
+          }
+        }
       }
     },
     "esprima": {
       "version": "4.0.0",
       "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.0.tgz",
-      "integrity": "sha512-oftTcaMu/EGrEIu904mWteKIv8vMuOgGYo7EhVJJN00R/EED9DCua/xxHRdYnKtcECzVg7xOWhflvJMnqcFZjw==",
+      "integrity": "sha1-RJnt3NERDgshi6zy+n9/WfVcqAQ=",
       "dev": true
     },
     "esquery": {
@@ -545,9 +505,9 @@
       "dev": true
     },
     "estree-walker": {
-      "version": "0.2.1",
-      "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-0.2.1.tgz",
-      "integrity": "sha1-va/oCVOD2EFNXcLs9MkXO225QS4=",
+      "version": "0.3.1",
+      "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-0.3.1.tgz",
+      "integrity": "sha1-5rGlHPcpJSTnI3wxLl/mZgwc4ao=",
       "dev": true
     },
     "esutils": {
@@ -575,13 +535,13 @@
       }
     },
     "external-editor": {
-      "version": "2.0.5",
-      "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-2.0.5.tgz",
-      "integrity": "sha512-Msjo64WT5W+NhOpQXh0nOHm+n0RfU1QUwDnKYvJ8dEJ8zlwLrqXNTv5mSUTJpepf41PDJGyhueTw2vNZW+Fr/w==",
+      "version": "2.1.0",
+      "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-2.1.0.tgz",
+      "integrity": "sha512-E44iT5QVOUJBKij4IIV3uvxuNlbKS38Tw1HiupxEIHPv9qtC2PrDYohbXV5U+1jnfIXttny8gUhj+oZvflFlzA==",
       "dev": true,
       "requires": {
+        "chardet": "0.4.2",
         "iconv-lite": "0.4.19",
-        "jschardet": "1.6.0",
         "tmp": "0.0.33"
       }
     },
@@ -692,7 +652,7 @@
     "glob": {
       "version": "7.1.2",
       "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz",
-      "integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==",
+      "integrity": "sha1-wZyd+aAocC1nhhI4SmVSQExjbRU=",
       "dev": true,
       "requires": {
         "fs.realpath": "1.0.0",
@@ -723,9 +683,9 @@
       }
     },
     "globals": {
-      "version": "9.18.0",
-      "resolved": "https://registry.npmjs.org/globals/-/globals-9.18.0.tgz",
-      "integrity": "sha512-S0nG3CLEQiY/ILxqtztTWH/3iRRdyBLw6KMDxnKMchrtbj2OFmehVh0WUCfW3DUrIgx/qFrJPICrq4Z4sTR9UQ==",
+      "version": "11.3.0",
+      "resolved": "https://registry.npmjs.org/globals/-/globals-11.3.0.tgz",
+      "integrity": "sha512-kkpcKNlmQan9Z5ZmgqKH/SMbSmjxQ7QjyNqfXVc8VJcoBV2UEg+sxQD15GQofGRh2hfpwUb70VC31DR7Rq5Hdw==",
       "dev": true
     },
     "globby": {
@@ -751,7 +711,7 @@
     "growl": {
       "version": "1.10.3",
       "resolved": "https://registry.npmjs.org/growl/-/growl-1.10.3.tgz",
-      "integrity": "sha512-hKlsbA5Vu3xsh1Cg3J7jSmX/WaW6A5oBeqzM88oNbCRQFz+zUaXm6yxS4RVytp1scBoJzSYl4YAEOQIt6O8V1Q==",
+      "integrity": "sha1-GSa6kM8+3+KttJJ/WIC8IsZseQ8=",
       "dev": true
     },
     "has-ansi": {
@@ -766,7 +726,8 @@
     "has-flag": {
       "version": "2.0.0",
       "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-2.0.0.tgz",
-      "integrity": "sha1-6CB68cx7MNRGzHC3NLXovhj4jVE="
+      "integrity": "sha1-6CB68cx7MNRGzHC3NLXovhj4jVE=",
+      "dev": true
     },
     "he": {
       "version": "1.1.1",
@@ -777,13 +738,13 @@
     "iconv-lite": {
       "version": "0.4.19",
       "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.19.tgz",
-      "integrity": "sha512-oTZqweIP51xaGPI4uPa56/Pri/480R+mo7SeU+YETByQNhDG55ycFyNLIgta9vXhILrxXDmF7ZGhqZIcuN0gJQ==",
+      "integrity": "sha1-90aPYBNfXl2tM5nAqBvpoWA6CCs=",
       "dev": true
     },
     "ignore": {
       "version": "3.3.7",
       "resolved": "https://registry.npmjs.org/ignore/-/ignore-3.3.7.tgz",
-      "integrity": "sha512-YGG3ejvBNHRqu0559EOxxNFihD0AjpvHlC/pdGKd3X3ofe+CoJkYazwNJYTNebqpPKN+VVQbh4ZFn1DivMNuHA==",
+      "integrity": "sha1-YSKJv7PCIOGGpYEYYY1b6MG6sCE=",
       "dev": true
     },
     "imurmurhash": {
@@ -811,16 +772,16 @@
     "inquirer": {
       "version": "3.3.0",
       "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-3.3.0.tgz",
-      "integrity": "sha512-h+xtnyk4EwKvFWHrUYsWErEVR+igKtLdchu+o0Z1RL7VU/jVMFbYir2bp6bAj8efFNxWqHX0dIss6fJQ+/+qeQ==",
+      "integrity": "sha1-ndLyrXZdyrH/BEO0kUQqILoifck=",
       "dev": true,
       "requires": {
         "ansi-escapes": "3.0.0",
-        "chalk": "2.3.0",
+        "chalk": "2.3.1",
         "cli-cursor": "2.1.0",
         "cli-width": "2.2.0",
-        "external-editor": "2.0.5",
+        "external-editor": "2.1.0",
         "figures": "2.0.0",
-        "lodash": "4.17.4",
+        "lodash": "4.17.5",
         "mute-stream": "0.0.7",
         "run-async": "2.3.0",
         "rx-lite": "4.0.8",
@@ -828,29 +789,12 @@
         "string-width": "2.1.1",
         "strip-ansi": "4.0.0",
         "through": "2.3.8"
-      },
-      "dependencies": {
-        "ansi-regex": {
-          "version": "3.0.0",
-          "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz",
-          "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=",
-          "dev": true
-        },
-        "strip-ansi": {
-          "version": "4.0.0",
-          "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz",
-          "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=",
-          "dev": true,
-          "requires": {
-            "ansi-regex": "3.0.0"
-          }
-        }
       }
     },
     "is-buffer": {
       "version": "1.1.6",
       "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz",
-      "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==",
+      "integrity": "sha1-76ouqdqg16suoTqXsritUf776L4=",
       "dev": true
     },
     "is-dotfile": {
@@ -922,13 +866,13 @@
       "integrity": "sha1-ZHdYK4IU1gI0YJRWcAO+ip6sBNw=",
       "dev": true,
       "requires": {
-        "is-path-inside": "1.0.0"
+        "is-path-inside": "1.0.1"
       }
     },
     "is-path-inside": {
-      "version": "1.0.0",
-      "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-1.0.0.tgz",
-      "integrity": "sha1-/AbloWg/vaE95mev9xe7wQpI838=",
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-1.0.1.tgz",
+      "integrity": "sha1-jvW33lBDej/cprToZe96pVy0gDY=",
       "dev": true,
       "requires": {
         "path-is-inside": "1.0.2"
@@ -953,13 +897,10 @@
       "dev": true
     },
     "is-resolvable": {
-      "version": "1.0.0",
-      "resolved": "https://registry.npmjs.org/is-resolvable/-/is-resolvable-1.0.0.tgz",
-      "integrity": "sha1-jfV8YeouPFAUCNEA+wE8+NbgzGI=",
-      "dev": true,
-      "requires": {
-        "tryit": "1.0.3"
-      }
+      "version": "1.1.0",
+      "resolved": "https://registry.npmjs.org/is-resolvable/-/is-resolvable-1.1.0.tgz",
+      "integrity": "sha512-qgDYXFSR5WvEfuS5dMj6oTMEbrrSaM0CrFk2Yiq/gXnBvD9pMa2jGXxyhGLfvhZpuMZe18CJpFxAt3CRs42NMg==",
+      "dev": true
     },
     "isarray": {
       "version": "1.0.0",
@@ -991,19 +932,13 @@
     "js-yaml": {
       "version": "3.10.0",
       "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.10.0.tgz",
-      "integrity": "sha512-O2v52ffjLa9VeM43J4XocZE//WT9N0IiwDa3KSHH7Tu8CtH+1qM8SIZvnsTh6v+4yFy5KUY3BHUVwjpfAWsjIA==",
+      "integrity": "sha1-LnhEFka9RoLpY/IrbpKCPDCcYtw=",
       "dev": true,
       "requires": {
         "argparse": "1.0.9",
         "esprima": "4.0.0"
       }
     },
-    "jschardet": {
-      "version": "1.6.0",
-      "resolved": "https://registry.npmjs.org/jschardet/-/jschardet-1.6.0.tgz",
-      "integrity": "sha512-xYuhvQ7I9PDJIGBWev9xm0+SMSed3ZDBAmvVjbFR1ZRLAF+vlXcQu6cRI9uAlj81rzikElRVteehwV7DuX2ZmQ==",
-      "dev": true
-    },
     "jsesc": {
       "version": "0.5.0",
       "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-0.5.0.tgz",
@@ -1042,15 +977,15 @@
       }
     },
     "lodash": {
-      "version": "4.17.4",
-      "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.4.tgz",
-      "integrity": "sha1-eCA6TRwyiuHYbcpkYONptX9AVa4=",
+      "version": "4.17.5",
+      "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.5.tgz",
+      "integrity": "sha512-svL3uiZf1RwhH+cWrfZn3A4+U58wbP0tGVTLQPbjplZxZ8ROD9VLuNgsRniTlLe7OlSqR79RUehXgpBW/s0IQw==",
       "dev": true
     },
     "lru-cache": {
       "version": "4.1.1",
       "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.1.tgz",
-      "integrity": "sha512-q4spe4KTfsAS1SUHLO0wz8Qiyf1+vMIAgpRYioFYDMNqKfHQbg+AVDH3i4fvpl71/P1L0dBl+fQi+P37UYf0ew==",
+      "integrity": "sha1-Yi4y6CSItJJ5EUpPns9F581rulU=",
       "dev": true,
       "requires": {
         "pseudomap": "1.0.2",
@@ -1060,9 +995,16 @@
     "magic-string": {
       "version": "0.22.4",
       "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.22.4.tgz",
-      "integrity": "sha512-kxBL06p6iO2qPBHsqGK2b3cRwiRGpnmSuVWNhwHcMX7qJOUr1HvricYP1LZOCdkQBUp0jiWg2d6WJwR3vYgByw==",
+      "integrity": "sha1-MQObTkA2Y5VhjB1s+Bk8U5F0df8=",
       "requires": {
         "vlq": "0.2.3"
+      },
+      "dependencies": {
+        "vlq": {
+          "version": "0.2.3",
+          "resolved": "https://registry.npmjs.org/vlq/-/vlq-0.2.3.tgz",
+          "integrity": "sha1-jz5DKM9jsVQMDWfhsneDhviXWyY="
+        }
       }
     },
     "micromatch": {
@@ -1087,18 +1029,18 @@
       }
     },
     "mimic-fn": {
-      "version": "1.1.0",
-      "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-1.1.0.tgz",
-      "integrity": "sha1-5md4PZLonb00KBi1IwudYqZyrRg=",
+      "version": "1.2.0",
+      "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-1.2.0.tgz",
+      "integrity": "sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ==",
       "dev": true
     },
     "minimatch": {
       "version": "3.0.4",
       "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz",
-      "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==",
+      "integrity": "sha1-UWbihkV/AzBgZL5Ul+jbsMPTIIM=",
       "dev": true,
       "requires": {
-        "brace-expansion": "1.1.8"
+        "brace-expansion": "1.1.10"
       }
     },
     "minimist": {
@@ -1124,9 +1066,9 @@
       }
     },
     "mocha": {
-      "version": "4.0.1",
-      "resolved": "https://registry.npmjs.org/mocha/-/mocha-4.0.1.tgz",
-      "integrity": "sha512-evDmhkoA+cBNiQQQdSKZa2b9+W2mpLoj50367lhy+Klnx9OV8XlCIhigUnn1gaTFLQCa0kdNhEGDr0hCXOQFDw==",
+      "version": "5.0.0",
+      "resolved": "https://registry.npmjs.org/mocha/-/mocha-5.0.0.tgz",
+      "integrity": "sha1-zMrJiLC8VHcRnLoOQ9569tatj04=",
       "dev": true,
       "requires": {
         "browser-stdout": "1.3.0",
@@ -1144,7 +1086,7 @@
         "supports-color": {
           "version": "4.4.0",
           "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-4.4.0.tgz",
-          "integrity": "sha512-rKC3+DyXWgK0ZLKwmRsrkyHVZAjNkfzeehuFWdGGcqGDTZFH73+RH6S/RDAAxl9GusSjZSUWYLmT9N5pzXFOXQ==",
+          "integrity": "sha1-iD992rwWUUKyphQn8zUt7RldGj4=",
           "dev": true,
           "requires": {
             "has-flag": "2.0.0"
@@ -1210,7 +1152,7 @@
       "integrity": "sha1-BnQoIw/WdEOyeUsiu6UotoZ5YtQ=",
       "dev": true,
       "requires": {
-        "mimic-fn": "1.1.0"
+        "mimic-fn": "1.2.0"
       }
     },
     "optionator": {
@@ -1292,7 +1234,7 @@
     "pluralize": {
       "version": "7.0.0",
       "resolved": "https://registry.npmjs.org/pluralize/-/pluralize-7.0.0.tgz",
-      "integrity": "sha512-ARhBOdzS3e41FbkW/XWrTEtukqqLoK5+Z/4UeDaLuSW+39JPeFgs4gCGqsrJHVZX0fUrx//4OF0K1CUGwlIFow==",
+      "integrity": "sha1-KYuJ34uTsCIdv0Ia0rGx6iP8Z3c=",
       "dev": true
     },
     "prelude-ls": {
@@ -1308,9 +1250,9 @@
       "dev": true
     },
     "process-nextick-args": {
-      "version": "1.0.7",
-      "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-1.0.7.tgz",
-      "integrity": "sha1-FQ4gt1ZZCtP5EJPyWk8q2L/zC6M=",
+      "version": "2.0.0",
+      "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.0.tgz",
+      "integrity": "sha512-MtEC1TqN0EU5nephaJ4rAtThHtC86dNN9qCuEhtshvpVBkAW5ZO7BASN9REnF9eoXGcRub+pFuKEpOHE+HbEMw==",
       "dev": true
     },
     "progress": {
@@ -1328,7 +1270,7 @@
     "randomatic": {
       "version": "1.1.7",
       "resolved": "https://registry.npmjs.org/randomatic/-/randomatic-1.1.7.tgz",
-      "integrity": "sha512-D5JUjPyJbaJDkuAazpVnSfVkLlpeO3wDlPROTMLGKG1zMFNFRgrciKo1ltz/AzNTkqE0HzDx655QOL51N06how==",
+      "integrity": "sha1-x6vpzIuHwLqodrGf3oP9RkeX44w=",
       "dev": true,
       "requires": {
         "is-number": "3.0.0",
@@ -1367,15 +1309,15 @@
       }
     },
     "readable-stream": {
-      "version": "2.3.3",
-      "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.3.tgz",
-      "integrity": "sha512-m+qzzcn7KUxEmd1gMbchF+Y2eIUbieUaxkWtptyHywrX0rE8QEYqPC07Vuy4Wm32/xE16NcdBctb8S0Xe/5IeQ==",
+      "version": "2.3.4",
+      "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.4.tgz",
+      "integrity": "sha512-vuYxeWYM+fde14+rajzqgeohAI7YoJcHE7kXDAc4Nk0EbuKnJfqtY9YtRkLo/tqkuF7MsBQRhPnPeyjYITp3ZQ==",
       "dev": true,
       "requires": {
         "core-util-is": "1.0.2",
         "inherits": "2.0.3",
         "isarray": "1.0.0",
-        "process-nextick-args": "1.0.7",
+        "process-nextick-args": "2.0.0",
         "safe-buffer": "5.1.1",
         "string_decoder": "1.0.3",
         "util-deprecate": "1.0.2"
@@ -1384,13 +1326,13 @@
     "regenerate": {
       "version": "1.3.3",
       "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.3.3.tgz",
-      "integrity": "sha512-jVpo1GadrDAK59t/0jRx5VxYWQEDkkEKi6+HjE3joFVLfDOh9Xrdh0dF1eSq+BI/SwvTQ44gSscJ8N5zYL61sg==",
+      "integrity": "sha1-DDNtOYBVPXVcObWGrjsgqknIK38=",
       "dev": true
     },
     "regenerate-unicode-properties": {
       "version": "5.1.3",
       "resolved": "https://registry.npmjs.org/regenerate-unicode-properties/-/regenerate-unicode-properties-5.1.3.tgz",
-      "integrity": "sha512-Yjy6t7jFQczDhYE+WVm7pg6gWYE258q4sUkk9qDErwXJIqx7jU9jGrMFHutJK/SRfcg7MEkXjGaYiVlOZyev/A==",
+      "integrity": "sha1-VPWJFUNGjzbyJ0tnxrxMAzwnswg=",
       "dev": true,
       "requires": {
         "regenerate": "1.3.3"
@@ -1399,7 +1341,7 @@
     "regex-cache": {
       "version": "0.4.4",
       "resolved": "https://registry.npmjs.org/regex-cache/-/regex-cache-0.4.4.tgz",
-      "integrity": "sha512-nVIZwtCjkC9YgvWkpM55B5rBhBYRZhAaJbgcFYXXsHnbZ9UZI9nnVWYZpBlCqv9ho2eZryPnWrZGsOdPwVWXWQ==",
+      "integrity": "sha1-db3FiioUls7EihKDW8VMjVYjNt0=",
       "dev": true,
       "requires": {
         "is-equal-shallow": "0.1.3"
@@ -1408,7 +1350,7 @@
     "regexpu-core": {
       "version": "4.1.3",
       "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-4.1.3.tgz",
-      "integrity": "sha512-mB+njEzO7oezA57IbQxxd6fVPOeWKDmnGvJ485CwmfNchjHe5jWwqKepapmzUEj41yxIAqOg+C4LbXuJlkiO8A==",
+      "integrity": "sha1-+4FhbbvCqRenQZsz+DeRRPUeuNA=",
       "dev": true,
       "requires": {
         "regenerate": "1.3.3",
@@ -1465,7 +1407,7 @@
     "resolve": {
       "version": "1.5.0",
       "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.5.0.tgz",
-      "integrity": "sha512-hgoSGrc3pjzAPHNBg+KnFcK2HwlHTs/YrAGUr6qgTVUZmXv1UEXXl0bZNBKMA9fud6lRYFdPGz0xXxycPzmmiw==",
+      "integrity": "sha1-HwmsznlsmnYlefMbLBzEw83fnzY=",
       "dev": true,
       "requires": {
         "path-parse": "1.0.5"
@@ -1490,114 +1432,77 @@
     "rimraf": {
       "version": "2.6.2",
       "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.2.tgz",
-      "integrity": "sha512-lreewLK/BlghmxtfH36YYVg1i8IAce4TI7oao75I1g245+6BctqTVQiBP3YUJ9C6DQOXJmkYR9X9fCLtCOJc5w==",
+      "integrity": "sha1-LtgVDSShbqhlHm1u8PR8QVjOejY=",
       "dev": true,
       "requires": {
         "glob": "7.1.2"
       }
     },
     "rollup": {
-      "version": "0.51.3",
-      "resolved": "https://registry.npmjs.org/rollup/-/rollup-0.51.3.tgz",
-      "integrity": "sha512-K9oygeFN+DhZTyWxAu0S/6cYMKSE9F2YXjXItwzBf8lRBRFRiQLurXkeUbqE+LCxvMtauiMFMApPb8YNyHT0Vw==",
+      "version": "0.55.5",
+      "resolved": "https://registry.npmjs.org/rollup/-/rollup-0.55.5.tgz",
+      "integrity": "sha512-2hke9NOy332kxvnmMQOgl7DHm94zihNyYJNd8ZLWo4U0EjFvjUkeWa0+ge+70bTg+mY0xJ7NUsf5kIhDtrGrtA==",
       "dev": true
     },
     "rollup-plugin-buble": {
-      "version": "0.8.0",
-      "resolved": "https://registry.npmjs.org/rollup-plugin-buble/-/rollup-plugin-buble-0.8.0.tgz",
-      "integrity": "sha1-TgLudzKWRnqGMaYa3w86to5ZITI=",
+      "version": "0.19.1",
+      "resolved": "https://registry.npmjs.org/rollup-plugin-buble/-/rollup-plugin-buble-0.19.1.tgz",
+      "integrity": "sha512-MhhyMysnHzuD0TMMC2M0Z/eHY37ZaCxB6iDqbDybBY3Ds/a8EJBiSJVUTIjOKZBkA6WucdfFPlWwRJIwrruxsA==",
       "dev": true,
       "requires": {
-        "buble": "0.8.2",
-        "rollup-pluginutils": "1.5.2"
+        "buble": "0.19.1",
+        "rollup-pluginutils": "2.0.1"
       }
     },
     "rollup-plugin-commonjs": {
-      "version": "8.2.6",
-      "resolved": "https://registry.npmjs.org/rollup-plugin-commonjs/-/rollup-plugin-commonjs-8.2.6.tgz",
-      "integrity": "sha512-qK0+uhktmnAgZkHkqFuajNmPw93fjrO7+CysDaxWE5jrUR9XSlSvuao5ZJP+XizxA8weakhgYYBtbVz9SGBpjA==",
+      "version": "8.3.0",
+      "resolved": "https://registry.npmjs.org/rollup-plugin-commonjs/-/rollup-plugin-commonjs-8.3.0.tgz",
+      "integrity": "sha512-PYs3OiYgENFYEmI3vOEm5nrp3eY90YZqd5vGmQqeXmhJsAWFIrFdROCvOasqJ1HgeTvqyYo9IGXnFDyoboNcgQ==",
       "dev": true,
       "requires": {
-        "acorn": "5.2.1",
-        "estree-walker": "0.5.0",
+        "acorn": "5.4.1",
+        "estree-walker": "0.5.1",
         "magic-string": "0.22.4",
         "resolve": "1.5.0",
         "rollup-pluginutils": "2.0.1"
       },
       "dependencies": {
         "estree-walker": {
-          "version": "0.5.0",
-          "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-0.5.0.tgz",
-          "integrity": "sha512-/bEAy+yKAZQrEWUhGmS3H9XpGqSDBtRzX0I2PgMw9kA2n1jN22uV5B5p7MFdZdvWdXCRJztXAfx6ZeRfgkEETg==",
+          "version": "0.5.1",
+          "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-0.5.1.tgz",
+          "integrity": "sha1-ZPw3UFOrxvV9c+m9LwBGRK08WFQ=",
           "dev": true
-        },
-        "rollup-pluginutils": {
-          "version": "2.0.1",
-          "resolved": "https://registry.npmjs.org/rollup-pluginutils/-/rollup-pluginutils-2.0.1.tgz",
-          "integrity": "sha1-fslbNXP2VDpGpkYb2afFRFJdD8A=",
-          "dev": true,
-          "requires": {
-            "estree-walker": "0.3.1",
-            "micromatch": "2.3.11"
-          },
-          "dependencies": {
-            "estree-walker": {
-              "version": "0.3.1",
-              "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-0.3.1.tgz",
-              "integrity": "sha1-5rGlHPcpJSTnI3wxLl/mZgwc4ao=",
-              "dev": true
-            }
-          }
         }
       }
     },
     "rollup-plugin-json": {
       "version": "2.3.0",
       "resolved": "https://registry.npmjs.org/rollup-plugin-json/-/rollup-plugin-json-2.3.0.tgz",
-      "integrity": "sha512-W45nZH7lmXgkSR/DkeyF4ks0YWFrMysdjUT049gTuAg+lwUEDBKI2+PztqW8UDSMlXCAeEONsLzpDDyBy9m+9A==",
+      "integrity": "sha1-PAekUsG1ORvigAb7//NkQFbOCt0=",
       "dev": true,
       "requires": {
         "rollup-pluginutils": "2.0.1"
-      },
-      "dependencies": {
-        "estree-walker": {
-          "version": "0.3.1",
-          "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-0.3.1.tgz",
-          "integrity": "sha1-5rGlHPcpJSTnI3wxLl/mZgwc4ao=",
-          "dev": true
-        },
-        "rollup-pluginutils": {
-          "version": "2.0.1",
-          "resolved": "https://registry.npmjs.org/rollup-pluginutils/-/rollup-pluginutils-2.0.1.tgz",
-          "integrity": "sha1-fslbNXP2VDpGpkYb2afFRFJdD8A=",
-          "dev": true,
-          "requires": {
-            "estree-walker": "0.3.1",
-            "micromatch": "2.3.11"
-          }
-        }
       }
     },
     "rollup-plugin-node-resolve": {
-      "version": "3.0.0",
-      "resolved": "https://registry.npmjs.org/rollup-plugin-node-resolve/-/rollup-plugin-node-resolve-3.0.0.tgz",
-      "integrity": "sha1-i4l8TDAw1QASd7BRSyXSygloPuA=",
+      "version": "3.0.2",
+      "resolved": "https://registry.npmjs.org/rollup-plugin-node-resolve/-/rollup-plugin-node-resolve-3.0.2.tgz",
+      "integrity": "sha1-OLq8Ev1ATMK6H/aGSP5D+j/+5rA=",
       "dev": true,
       "requires": {
-        "browser-resolve": "1.11.2",
         "builtin-modules": "1.1.1",
         "is-module": "1.0.0",
         "resolve": "1.5.0"
       }
     },
     "rollup-pluginutils": {
-      "version": "1.5.2",
-      "resolved": "https://registry.npmjs.org/rollup-pluginutils/-/rollup-pluginutils-1.5.2.tgz",
-      "integrity": "sha1-HhVud4+UtyVb+hs9AXi+j1xVJAg=",
+      "version": "2.0.1",
+      "resolved": "https://registry.npmjs.org/rollup-pluginutils/-/rollup-pluginutils-2.0.1.tgz",
+      "integrity": "sha1-fslbNXP2VDpGpkYb2afFRFJdD8A=",
       "dev": true,
       "requires": {
-        "estree-walker": "0.2.1",
-        "minimatch": "3.0.4"
+        "estree-walker": "0.3.1",
+        "micromatch": "2.3.11"
       }
     },
     "run-async": {
@@ -1627,13 +1532,13 @@
     "safe-buffer": {
       "version": "5.1.1",
       "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz",
-      "integrity": "sha512-kKvNJn6Mm93gAczWVJg7wH+wGYWNrDHdWvpUmHyEsgCtIwwo3bqPtV4tR5tuPaUhTOo/kvhVwd8XwwOllGYkbg==",
+      "integrity": "sha1-iTMSr2myEj3vcfV4iQAWce6yyFM=",
       "dev": true
     },
     "semver": {
-      "version": "5.4.1",
-      "resolved": "https://registry.npmjs.org/semver/-/semver-5.4.1.tgz",
-      "integrity": "sha512-WfG/X9+oATh81XtllIo/I8gOiY9EXRdv1cQdyykeXK17YcUW3EXUAi2To4pcH6nZtJPr7ZOpM5OMyWJZm+8Rsg==",
+      "version": "5.5.0",
+      "resolved": "https://registry.npmjs.org/semver/-/semver-5.5.0.tgz",
+      "integrity": "sha512-4SJ3dm0WAwWy/NVeioZh5AntkdJoWKxHxcmyP622fOkgHa4z3R0TdBJICINyaSDE6uNwVc8gZr+ZinwZAH4xIA==",
       "dev": true
     },
     "shebang-command": {
@@ -1660,7 +1565,7 @@
     "slice-ansi": {
       "version": "1.0.0",
       "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-1.0.0.tgz",
-      "integrity": "sha512-POqxBK6Lb3q6s047D/XsDVNPnF9Dl8JSaqe9h9lURl0OdNqy/ujDrOiIHtsqXMGbWWTIomRzAMaTyawAU//Reg==",
+      "integrity": "sha1-BE8aSdiEL/MHqta1Be0Xi9lQE00=",
       "dev": true,
       "requires": {
         "is-fullwidth-code-point": "2.0.0"
@@ -1669,13 +1574,13 @@
     "source-map": {
       "version": "0.6.1",
       "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
-      "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
+      "integrity": "sha1-dHIq8y6WFOnCh6jQu95IteLxomM=",
       "dev": true
     },
     "source-map-support": {
-      "version": "0.5.0",
-      "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.0.tgz",
-      "integrity": "sha512-vUoN3I7fHQe0R/SJLKRdKYuEdRGogsviXFkHHo17AWaTGv17VLnxw+CFXvqy+y4ORZ3doWLQcxRYfwKrsd/H7Q==",
+      "version": "0.5.3",
+      "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.3.tgz",
+      "integrity": "sha512-eKkTgWYeBOQqFGXRfKabMFdnWepo51vWqEdoeikaEPFiJC7MCU5j2h4+6Q8npkZTeLGbSyecZvRxiSoWl3rh+w==",
       "dev": true,
       "requires": {
         "source-map": "0.6.1"
@@ -1690,46 +1595,37 @@
     "string-width": {
       "version": "2.1.1",
       "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz",
-      "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==",
+      "integrity": "sha1-q5Pyeo3BPSjKyBXEYhQ6bZASrp4=",
       "dev": true,
       "requires": {
         "is-fullwidth-code-point": "2.0.0",
         "strip-ansi": "4.0.0"
-      },
-      "dependencies": {
-        "ansi-regex": {
-          "version": "3.0.0",
-          "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz",
-          "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=",
-          "dev": true
-        },
-        "strip-ansi": {
-          "version": "4.0.0",
-          "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz",
-          "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=",
-          "dev": true,
-          "requires": {
-            "ansi-regex": "3.0.0"
-          }
-        }
       }
     },
     "string_decoder": {
       "version": "1.0.3",
       "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz",
-      "integrity": "sha512-4AH6Z5fzNNBcH+6XDMfA/BTt87skxqJlO0lAh3Dker5zThcAxG6mKz+iGu308UKoPPQ8Dcqx/4JhujzltRa+hQ==",
+      "integrity": "sha1-D8Z9fBQYJd6UKC3VNr7GubzoYKs=",
       "dev": true,
       "requires": {
         "safe-buffer": "5.1.1"
       }
     },
     "strip-ansi": {
-      "version": "3.0.1",
-      "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz",
-      "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=",
+      "version": "4.0.0",
+      "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz",
+      "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=",
       "dev": true,
       "requires": {
-        "ansi-regex": "2.1.1"
+        "ansi-regex": "3.0.0"
+      },
+      "dependencies": {
+        "ansi-regex": {
+          "version": "3.0.0",
+          "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz",
+          "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=",
+          "dev": true
+        }
       }
     },
     "strip-json-comments": {
@@ -1739,23 +1635,30 @@
       "dev": true
     },
     "supports-color": {
-      "version": "4.5.0",
-      "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-4.5.0.tgz",
-      "integrity": "sha1-vnoN5ITexcXN34s9WRJQRJEvY1s=",
+      "version": "5.2.0",
+      "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.2.0.tgz",
+      "integrity": "sha512-F39vS48la4YvTZUPVeTqsjsFNrvcMwrV3RLZINsmHo+7djCvuUzSIeXOnZ5hmjef4bajL1dNccN+tg5XAliO5Q==",
       "requires": {
-        "has-flag": "2.0.0"
+        "has-flag": "3.0.0"
+      },
+      "dependencies": {
+        "has-flag": {
+          "version": "3.0.0",
+          "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz",
+          "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0="
+        }
       }
     },
     "table": {
       "version": "4.0.2",
       "resolved": "https://registry.npmjs.org/table/-/table-4.0.2.tgz",
-      "integrity": "sha512-UUkEAPdSGxtRpiV9ozJ5cMTtYiqz7Ni1OGqLXRCynrvzdtR1p+cfOWe2RJLwvUG8hNanaSRjecIqwOjqeatDsA==",
+      "integrity": "sha1-ozRHN1OR52atNNNIbm4q7chNLjY=",
       "dev": true,
       "requires": {
-        "ajv": "5.3.0",
+        "ajv": "5.5.2",
         "ajv-keywords": "2.1.1",
-        "chalk": "2.3.0",
-        "lodash": "4.17.4",
+        "chalk": "2.3.1",
+        "lodash": "4.17.5",
         "slice-ansi": "1.0.0",
         "string-width": "2.1.1"
       }
@@ -1775,18 +1678,12 @@
     "tmp": {
       "version": "0.0.33",
       "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz",
-      "integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==",
+      "integrity": "sha1-bTQzWIl2jSGyvNoKonfO07G/rfk=",
       "dev": true,
       "requires": {
         "os-tmpdir": "1.0.2"
       }
     },
-    "tryit": {
-      "version": "1.0.3",
-      "resolved": "https://registry.npmjs.org/tryit/-/tryit-1.0.3.tgz",
-      "integrity": "sha1-OTvnMKlEb9Hq1tpZoBQwjzbCics=",
-      "dev": true
-    },
     "type-check": {
       "version": "0.3.2",
       "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz",
@@ -1805,13 +1702,13 @@
     "unicode-canonical-property-names-ecmascript": {
       "version": "1.0.3",
       "resolved": "https://registry.npmjs.org/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-1.0.3.tgz",
-      "integrity": "sha512-iG/2t0F2LAU8aZYPkX5gi7ebukHnr3sWFESpb+zPQeeaQwOkfoO6ZW17YX7MdRPNG9pCy+tjzGill+Ah0Em0HA==",
+      "integrity": "sha1-9hGfQXRnWTwAhjV8hVRratWrxYM=",
       "dev": true
     },
     "unicode-match-property-ecmascript": {
       "version": "1.0.3",
       "resolved": "https://registry.npmjs.org/unicode-match-property-ecmascript/-/unicode-match-property-ecmascript-1.0.3.tgz",
-      "integrity": "sha512-nFcaBFcr08UQNF15ZgI5ISh3yUnQm7SJRRxwYrL5VYX46pS+6Q7TCTv4zbK+j6/l7rQt0mMiTL2zpmeygny6rA==",
+      "integrity": "sha1-25sctP/GfgxVg3gLG1k3Dky+l7k=",
       "dev": true,
       "requires": {
         "unicode-canonical-property-names-ecmascript": "1.0.3",
@@ -1821,13 +1718,13 @@
     "unicode-match-property-value-ecmascript": {
       "version": "1.0.1",
       "resolved": "https://registry.npmjs.org/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-1.0.1.tgz",
-      "integrity": "sha512-lM8B0FDZQh9yYGgiabRQcyWicB27VLOolSBRIxsO7FeQPtg+79Oe7sC8Mzr8BObDs+G9CeYmC/shHo6OggNEog==",
+      "integrity": "sha1-/qBZEgoBb0A6/Tv1hhYrTbA+BgQ=",
       "dev": true
     },
     "unicode-property-aliases-ecmascript": {
       "version": "1.0.3",
       "resolved": "https://registry.npmjs.org/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-1.0.3.tgz",
-      "integrity": "sha512-TdDmDOTxEf2ad1g3ZBpM6cqKIb2nJpVlz1Q++casDryKz18tpeMBhSng9hjC1CTQCkOV9Rw2knlSB6iRo7ad1w==",
+      "integrity": "sha1-rDUiWDueYwWA+RZjUzPgDF6taQ0=",
       "dev": true
     },
     "util-deprecate": {
@@ -1837,14 +1734,14 @@
       "dev": true
     },
     "vlq": {
-      "version": "0.2.3",
-      "resolved": "https://registry.npmjs.org/vlq/-/vlq-0.2.3.tgz",
-      "integrity": "sha512-DRibZL6DsNhIgYQ+wNdWDL2SL3bKPlVrRiBqV5yuMm++op8W4kGFtaQfCs4KEJn0wBZcHVHJ3eoywX8983k1ow=="
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/vlq/-/vlq-1.0.0.tgz",
+      "integrity": "sha1-gQG+kIQ0IpVMKxPrJ/LzEivcyAY="
     },
     "which": {
       "version": "1.3.0",
       "resolved": "https://registry.npmjs.org/which/-/which-1.3.0.tgz",
-      "integrity": "sha512-xcJpopdamTuY5duC/KnTTNBraPK54YwpenP4lzxU8H91GudWpFv38u0CKjclE1Wi2EH2EDz5LRcHcKbCIzqGyg==",
+      "integrity": "sha1-/wS9/AEO5UfXgL7DjhrBwnd9JTo=",
       "dev": true,
       "requires": {
         "isexe": "2.0.0"
diff --git a/package.json b/package.json
index bc6211b..1adf80c 100644
--- a/package.json
+++ b/package.json
@@ -1,10 +1,14 @@
 {
   "name": "buble",
-  "version": "0.18.0",
+  "version": "0.19.3",
   "description": "The blazing fast, batteries-included ES2015 compiler",
-  "main": "dist/buble.umd.js",
+  "main": "dist/buble.cjs.js",
   "module": "dist/buble.es.js",
-  "browser": "dist/buble.deps.js",
+  "browser": {
+    "dist/buble.cjs.js": "./dist/buble-browser.cjs.js",
+    "dist/buble.es.js": "./dist/buble-browser.es.js"
+  },
+  "unpkg": "dist/buble-browser-deps.umd.js",
   "files": [
     "bin",
     "src",
@@ -43,29 +47,28 @@
   },
   "homepage": "https://github.com/Rich-Harris/buble#README",
   "devDependencies": {
-    "buble": "0.8.2",
     "console-group": "^0.3.3",
-    "eslint": "^4.7.2",
+    "eslint": "^4.17.0",
     "glob": "^7.0.3",
-    "mocha": "^4.0.1",
+    "mocha": "^5.0.0",
     "regexpu-core": "^4.1.3",
     "rimraf": "^2.5.2",
-    "rollup": "^0.51.3",
-    "rollup-plugin-buble": "^0.8.0",
-    "rollup-plugin-commonjs": "^8.2.1",
-    "rollup-plugin-json": "^2.0.0",
-    "rollup-plugin-node-resolve": "^3.0.0",
+    "rollup": "^0.55.5",
+    "rollup-plugin-buble": "^0.19.1",
+    "rollup-plugin-commonjs": "^8.3.0",
+    "rollup-plugin-json": "^2.3.0",
+    "rollup-plugin-node-resolve": "^3.0.2",
     "source-map": "^0.6.1",
-    "source-map-support": "^0.5.0"
+    "source-map-support": "^0.5.3"
   },
   "dependencies": {
-    "acorn": "^5.1.2",
-    "acorn-jsx": "^3.0.1",
-    "acorn5-object-spread": "^4.0.0",
-    "chalk": "^2.1.0",
+    "acorn": "^5.4.1",
+    "acorn-dynamic-import": "^3.0.0",
+    "acorn-jsx": "^4.1.1",
+    "chalk": "^2.3.1",
     "magic-string": "^0.22.4",
     "minimist": "^1.2.0",
     "os-homedir": "^1.0.1",
-    "vlq": "^0.2.2"
+    "vlq": "^1.0.0"
   }
 }
diff --git a/rollup.config.js b/rollup.config.js
index 6528ebb..8a72d49 100644
--- a/rollup.config.js
+++ b/rollup.config.js
@@ -4,49 +4,63 @@ import resolve from 'rollup-plugin-node-resolve';
 import commonjs from 'rollup-plugin-commonjs';
 import pkg from './package.json';
 
-const config = {
-	input: 'src/index.js',
-	plugins: [
-		json(),
-		commonjs(),
-		buble({
-			target: {
-				node: 4
-			},
-			include: [
-				'src/**',
-				'node_modules/acorn-object-spread/**',
-				'node_modules/unicode-loose-match/**',
-				'node_modules/regexpu-core/**'
-			],
-			transforms: {
-				dangerousForOf: true
-			}
-		}),
-		resolve()
-	],
-	name: 'buble',
-	sourcemap: true
+const ensureArray = maybeArr => Array.isArray(maybeArr) ? maybeArr : [maybeArr];
+
+const createConfig = (opts) => {
+	opts = opts || {};
+	const browser = opts.browser || false;
+	const external = opts.external || ['acorn', 'magic-string'];
+	const output = ensureArray(opts.output);
+
+	return {
+		input: 'src/index.js',
+		output: output.map(format => Object.assign({}, format, {
+			name: 'buble',
+			sourcemap: true
+		})),
+		external: external,
+		plugins: [
+			json(),
+			commonjs(),
+			buble({
+				target: !browser ? { node: 4 } : null,
+				include: [
+					'src/**',
+					'node_modules/regexpu-core/**',
+					'node_modules/unicode-match-property-ecmascript/**',
+					'node_modules/unicode-match-property-value-ecmascript/**',
+				],
+				transforms: {
+					dangerousForOf: true
+				}
+			}),
+			resolve()
+		],
+	};
 };
 
-export default [
-	/* ESM/UMD builds */
-	Object.assign({}, config, {
-		external: ['acorn/dist/acorn.js', 'magic-string'],
+const configs = [
+	/* node ESM/CJS builds */
+	createConfig({
 		output: [
 			{ format: 'es', file: pkg.module },
-			{ format: 'umd', file: pkg.main }
+			{ format: 'cjs', file: pkg.main }
 		],
-		globals: {
-			'acorn/dist/acorn.js': 'acorn',
-			'magic-string': 'MagicString'
-		}
 	}),
-
-	/* UMD with bundled dependencies, for browsers */
-	Object.assign({}, config, {
+	/* browser ESM/CJS builds (for bundlers) */
+	createConfig({
+		browser: true,
 		output: [
-			{ format: 'umd', file: pkg.browser }
-		]
-	})
+			{ format: 'es', file: pkg.browser[pkg.module] },
+			{ format: 'cjs', file: pkg.browser[pkg.main] }
+		],
+	}),
+	/* UMD with bundled dependencies, ready for browsers */
+	createConfig({
+		browser: true,
+		external: [],
+		output: { format: 'umd', file: pkg.unpkg },
+	}),
 ];
+
+export default configs;
diff --git a/src/index.js b/src/index.js
index 3c707fc..244148a 100644
--- a/src/index.js
+++ b/src/index.js
@@ -1,11 +1,11 @@
 import * as acorn from 'acorn';
 import acornJsx from 'acorn-jsx/inject';
-import acornObjectSpread from 'acorn5-object-spread/inject';
+import acornDynamicImport from 'acorn-dynamic-import/lib/inject';
 import Program from './program/Program.js';
 import { features, matrix } from './support.js';
 import getSnippet from './utils/getSnippet.js';
 
-const { parse } = [acornObjectSpread, acornJsx].reduce(
+const { parse } = [acornJsx, acornDynamicImport].reduce(
 	(final, plugin) => plugin(final),
 	acorn
 );
@@ -15,8 +15,8 @@ const dangerousTransforms = ['dangerousTaggedTemplateString', 'dangerousForOf'];
 export function target(target) {
 	const targets = Object.keys(target);
 	let bitmask = targets.length
-		? 0b11111111111111111111111111111111
-		: 0b01000000000000000000000000000000;
+		? 0b11111111111111111111
+		: 0b01000000000000000000;
 
 	Object.keys(target).forEach(environment => {
 		const versions = matrix[environment];
@@ -57,7 +57,7 @@ export function transform(source, options = {}) {
 
 	try {
 		ast = parse(source, {
-			ecmaVersion: 8,
+			ecmaVersion: 9,
 			preserveParens: true,
 			sourceType: 'module',
 			onComment: (block, text) => {
@@ -68,7 +68,7 @@ export function transform(source, options = {}) {
 			},
 			plugins: {
 				jsx: true,
-				objectSpread: true
+				dynamicImport: true
 			}
 		});
 		options.jsx = jsx || options.jsx;
diff --git a/src/program/BlockStatement.js b/src/program/BlockStatement.js
index 0c887ce..f0cb894 100644
--- a/src/program/BlockStatement.js
+++ b/src/program/BlockStatement.js
@@ -1,4 +1,3 @@
-import './wrap.js'; // TODO necessary for ordering. sort it out
 import Node from './Node.js';
 import Scope from './Scope.js';
 import destructure from '../utils/destructure.js';
@@ -16,7 +15,8 @@ export default class BlockStatement extends Node {
 		this.isFunctionBlock = this.parentIsFunction || this.parent.type === 'Root';
 		this.scope = new Scope({
 			block: !this.isFunctionBlock,
-			parent: this.parent.findScope(false)
+			parent: this.parent.findScope(false),
+			declare: id => this.createdDeclarations.push(id)
 		});
 
 		if (this.parentIsFunction) {
@@ -154,6 +154,15 @@ export default class BlockStatement extends Node {
 
 		if (/Function/.test(this.parent.type)) {
 			this.transpileParameters(
+				this.parent.params,
+				code,
+				transforms,
+				indentation,
+				introStatementGenerators
+			);
+		} else if ('CatchClause' === this.parent.type) {
+			this.transpileParameters(
+				[this.parent.param],
 				code,
 				transforms,
 				indentation,
@@ -211,15 +220,7 @@ export default class BlockStatement extends Node {
 		});
 	}
 
-	declareIdentifier(name) {
-		const id = this.scope.createIdentifier(name);
-		this.createdDeclarations.push(id);
-		return id;
-	}
-
-	transpileParameters(code, transforms, indentation, introStatementGenerators) {
-		const params = this.parent.params;
-
+	transpileParameters(params, code, transforms, indentation, introStatementGenerators) {
 		params.forEach(param => {
 			if (
 				param.type === 'AssignmentPattern' &&
@@ -287,7 +288,8 @@ export default class BlockStatement extends Node {
 					const ref = this.scope.createIdentifier('ref');
 					destructure(
 						code,
-						this.scope,
+						id => this.scope.createIdentifier(id),
+						({ name }) => this.scope.resolveName(name),
 						param,
 						ref,
 						false,
diff --git a/src/program/Node.js b/src/program/Node.js
index 5a65fd1..3e0429c 100644
--- a/src/program/Node.js
+++ b/src/program/Node.js
@@ -1,6 +1,3 @@
-import wrap from './wrap.js';
-import keys from './keys.js';
-
 // used for debugging, without the noise created by
 // circular references
 function toJSON(node) {
@@ -28,21 +25,6 @@ function toJSON(node) {
 }
 
 export default class Node {
-	constructor(raw, parent) {
-		raw.parent = parent;
-		raw.program = parent.program || parent;
-		raw.depth = parent.depth + 1;
-		raw.keys = keys[raw.type];
-		raw.indentation = undefined;
-
-		for (const key of keys[raw.type]) {
-			wrap(raw[key], raw);
-		}
-
-		raw.program.magicString.addSourcemapLocation(raw.start);
-		raw.program.magicString.addSourcemapLocation(raw.end);
-	}
-
 	ancestor(level) {
 		let node = this;
 		while (level--) {
diff --git a/src/program/Program.js b/src/program/Program.js
index 5a6065d..ee66702 100644
--- a/src/program/Program.js
+++ b/src/program/Program.js
@@ -18,6 +18,15 @@ export default function Program(source, ast, transforms, options) {
 	wrap((this.body = ast), this);
 	this.body.__proto__ = BlockStatement.prototype;
 
+	this.templateLiteralQuasis = Object.create(null);
+	for (let i = 0; i < this.body.body.length; ++i) {
+		if (!this.body.body[i].directive) {
+			this.prependAt = this.body.body[i].start;
+			break;
+		}
+	}
+	this.objectWithoutPropertiesHelper = null;
+
 	this.indentExclusionElements = [];
 	this.body.initialise(transforms);
 
@@ -49,5 +58,17 @@ Program.prototype = {
 
 	findScope() {
 		return null;
+	},
+
+	getObjectWithoutPropertiesHelper(code) {
+		if (!this.objectWithoutPropertiesHelper) {
+			this.objectWithoutPropertiesHelper = this.body.scope.createIdentifier('objectWithoutProperties');
+			code.prependLeft(this.prependAt, `function ${this.objectWithoutPropertiesHelper} (obj, exclude) { ` +
+				`var target = {}; for (var k in obj) ` +
+				`if (Object.prototype.hasOwnProperty.call(obj, k) && exclude.indexOf(k) === -1) ` +
+				`target[k] = obj[k]; return target; }\n`
+			);
+		}
+		return this.objectWithoutPropertiesHelper;
 	}
 };
diff --git a/src/program/Scope.js b/src/program/Scope.js
index 18f1664..bb93d3e 100644
--- a/src/program/Scope.js
+++ b/src/program/Scope.js
@@ -6,6 +6,7 @@ export default function Scope(options) {
 
 	this.parent = options.parent;
 	this.isBlockScope = !!options.block;
+	this.createDeclarationCallback = options.declare;
 
 	let scope = this;
 	while (scope.isBlockScope) scope = scope.parent;
@@ -15,7 +16,7 @@ export default function Scope(options) {
 	this.declarations = Object.create(null);
 	this.references = Object.create(null);
 	this.blockScopedDeclarations = this.isBlockScope ? null : Object.create(null);
-	this.aliases = this.isBlockScope ? null : Object.create(null);
+	this.aliases = Object.create(null);
 }
 
 Scope.prototype = {
@@ -94,10 +95,22 @@ Scope.prototype = {
 		return name;
 	},
 
+	createDeclaration(base) {
+		const id = this.createIdentifier(base);
+		this.createDeclarationCallback(id);
+		return id;
+	},
+
 	findDeclaration(name) {
 		return (
 			this.declarations[name] ||
 			(this.parent && this.parent.findDeclaration(name))
 		);
+	},
+
+	// Sometimes, block scope declarations change name during transpilation
+	resolveName(name) {
+		const declaration = this.findDeclaration(name);
+		return declaration ? declaration.name : name;
 	}
 };
diff --git a/src/program/types/ArrayExpression.js b/src/program/types/ArrayExpression.js
index c8e6304..d815d6e 100644
--- a/src/program/types/ArrayExpression.js
+++ b/src/program/types/ArrayExpression.js
@@ -23,6 +23,8 @@ export default class ArrayExpression extends Node {
 	}
 
 	transpile(code, transforms) {
+		super.transpile(code, transforms);
+
 		if (transforms.spreadRest) {
 			// erase trailing comma after last array element if not an array hole
 			if (this.elements.length) {
@@ -64,7 +66,5 @@ export default class ArrayExpression extends Node {
 				}
 			}
 		}
-
-		super.transpile(code, transforms);
 	}
 }
diff --git a/src/program/types/AssignmentExpression.js b/src/program/types/AssignmentExpression.js
index a80dc60..a89bb53 100644
--- a/src/program/types/AssignmentExpression.js
+++ b/src/program/types/AssignmentExpression.js
@@ -1,14 +1,11 @@
 import Node from '../Node.js';
-import CompileError from '../../utils/CompileError.js';
+import checkConst from '../../utils/checkConst.js';
+import destructure from '../../utils/destructure.js';
 
 export default class AssignmentExpression extends Node {
 	initialise(transforms) {
 		if (this.left.type === 'Identifier') {
 			const declaration = this.findScope(false).findDeclaration(this.left.name);
-			if (declaration && declaration.kind === 'const') {
-				throw new CompileError(`${this.left.name} is read-only`, this.left);
-			}
-
 			// special case – https://gitlab.com/Rich-Harris/buble/issues/11
 			const statement = declaration && declaration.node.ancestor(3);
 			if (
@@ -24,6 +21,12 @@ export default class AssignmentExpression extends Node {
 	}
 
 	transpile(code, transforms) {
+		if (this.left.type === 'Identifier') {
+			// Do this check after everything has been initialized to find
+			// shadowing declarations after this expression
+			checkConst(this.left, this.findScope(false));
+		}
+
 		if (this.operator === '**=' && transforms.exponentiation) {
 			this.transpileExponentiation(code, transforms);
 		} else if (/Pattern/.test(this.left.type) && transforms.destructuring) {
@@ -34,166 +37,47 @@ export default class AssignmentExpression extends Node {
 	}
 
 	transpileDestructuring(code) {
-		const scope = this.findScope(true);
-		const assign = scope.createIdentifier('assign');
-		const temporaries = [assign];
-
-		const start = this.start;
-
-		// We need to pick out some elements from the original code,
-		// interleaved with generated code. These helpers are used to
-		// easily do that while keeping the order of the output
-		// predictable.
-		let text = '';
-		function use(node) {
-			code.prependRight(node.start, text);
-			code.move(node.start, node.end, start);
-			text = '';
-		}
-		function write(string) {
-			text += string;
-		}
-
-		write(`(${assign} = `);
-		use(this.right);
-
-		// Walk `pattern`, generating code that assigns the value in
-		// `ref` to it. When `mayDuplicate` is false, the function
-		// must take care to only output `ref` once.
-		function destructure(pattern, ref, mayDuplicate) {
-			if (
-				pattern.type === 'Identifier' ||
-				pattern.type === 'MemberExpression'
-			) {
-				write(', ');
-				use(pattern);
-				write(` = ${ref}`);
-			} else if (pattern.type === 'AssignmentPattern') {
-				if (pattern.left.type === 'Identifier') {
-					code.remove(pattern.start, pattern.right.start);
-
-					const target = pattern.left.name;
-					let source = ref;
-					if (!mayDuplicate) {
-						write(`, ${target} = ${ref}`);
-						source = target;
-					}
-					write(`, ${target} = ${source} === void 0 ? `);
-					use(pattern.right);
-					write(` : ${source}`);
-				} else {
-					code.remove(pattern.left.end, pattern.right.start);
-
-					const target = scope.createIdentifier('temp');
-					let source = ref;
-					temporaries.push(target);
-					if (!mayDuplicate) {
-						write(`, ${target} = ${ref}`);
-						source = target;
-					}
-					write(`, ${target} = ${source} === void 0 ? `);
-					use(pattern.right);
-					write(` : ${source}`);
-					destructure(pattern.left, target, true);
-				}
-			} else if (pattern.type === 'ArrayPattern') {
-				const elements = pattern.elements;
-				if (elements.length === 1) {
-					code.remove(pattern.start, elements[0].start);
-					destructure(elements[0], `${ref}[0]`, false);
-					code.remove(elements[0].end, pattern.end);
-				} else {
-					if (!mayDuplicate) {
-						const temp = scope.createIdentifier('array');
-						temporaries.push(temp);
-						write(`, ${temp} = ${ref}`);
-						ref = temp;
-					}
-
-					let c = pattern.start;
-					elements.forEach((element, i) => {
-						if (!element) return;
-
-						code.remove(c, element.start);
-						c = element.end;
-
-						if (element.type === 'RestElement') {
-							code.remove(element.start, element.argument.start);
-							destructure(element.argument, `${ref}.slice(${i})`, false);
-						} else {
-							destructure(element, `${ref}[${i}]`, false);
-						}
-					});
-
-					code.remove(c, pattern.end);
-				}
-			} else if (pattern.type === 'ObjectPattern') {
-				const props = pattern.properties;
-				if (props.length == 1) {
-					const prop = props[0];
-					const value =
-						prop.computed || prop.key.type !== 'Identifier'
-							? `${ref}[${code.slice(prop.key.start, prop.key.end)}]`
-							: `${ref}.${prop.key.name}`;
-
-					code.remove(pattern.start, prop.value.start);
-					destructure(prop.value, value, false);
-					code.remove(prop.end, pattern.end);
-				} else {
-					if (!mayDuplicate) {
-						const temp = scope.createIdentifier('obj');
-						temporaries.push(temp);
-						write(`, ${temp} = ${ref}`);
-						ref = temp;
-					}
-
-					let c = pattern.start;
-
-					props.forEach(prop => {
-						const value =
-							prop.computed || prop.key.type !== 'Identifier'
-								? `${ref}[${code.slice(prop.key.start, prop.key.end)}]`
-								: `${ref}.${prop.key.name}`;
-
-						code.remove(c, prop.value.start);
-						c = prop.end;
-
-						destructure(prop.value, value, false);
-					});
+		const writeScope = this.findScope(true);
+		const lookupScope = this.findScope(false);
+		const assign = writeScope.createDeclaration('assign');
+		code.appendRight(this.left.end, `(${assign}`);
+
+		code.appendLeft(this.right.end, ', ');
+		const statementGenerators = [];
+		destructure(
+			code,
+			id => writeScope.createDeclaration(id),
+			node => {
+				const name = lookupScope.resolveName(node.name);
+				checkConst(node, lookupScope);
+				return name;
+			},
+			this.left,
+			assign,
+			true,
+			statementGenerators
+		);
 
-					code.remove(c, pattern.end);
-				}
-			} else {
-				throw new Error(
-					`Unexpected node type in destructuring assignment (${pattern.type})`
-				);
+		let suffix = ', ';
+		statementGenerators.forEach((fn, j) => {
+			if (j === statementGenerators.length - 1) {
+				suffix = '';
 			}
-		}
 
-		destructure(this.left, assign, true);
-		code.remove(this.left.end, this.right.start);
+			fn(this.end, '', suffix);
+		});
 
 		if (this.unparenthesizedParent().type === 'ExpressionStatement') {
 			// no rvalue needed for expression statement
-			code.prependRight(start, `${text})`);
+			code.appendRight(this.end, `)`);
 		} else {
 			// destructuring is part of an expression - need an rvalue
-			code.prependRight(start, `${text}, ${assign})`);
+			code.appendRight(this.end, `, ${assign})`);
 		}
-
-		const statement = this.findNearest(/(?:Statement|Declaration)$/);
-		code.appendLeft(
-			statement.start,
-			`var ${temporaries.join(', ')};\n${statement.getIndentation()}`
-		);
 	}
 
 	transpileExponentiation(code) {
 		const scope = this.findScope(false);
-		const getAlias = name => {
-			const declaration = scope.findDeclaration(name);
-			return declaration ? declaration.name : name;
-		};
 
 		// first, the easy part – `**=` -> `=`
 		let charIndex = this.left.end;
@@ -208,7 +92,7 @@ export default class AssignmentExpression extends Node {
 		const left = this.left.unparenthesize();
 
 		if (left.type === 'Identifier') {
-			base = getAlias(left.name);
+			base = scope.resolveName(left.name);
 		} else if (left.type === 'MemberExpression') {
 			let object;
 			let needsObjectVar = false;
@@ -220,27 +104,27 @@ export default class AssignmentExpression extends Node {
 
 			if (left.property.type === 'Identifier') {
 				property = left.computed
-					? getAlias(left.property.name)
+					? scope.resolveName(left.property.name)
 					: left.property.name;
 			} else {
-				property = scope.createIdentifier('property');
+				property = scope.createDeclaration('property');
 				needsPropertyVar = true;
 			}
 
 			if (left.object.type === 'Identifier') {
-				object = getAlias(left.object.name);
+				object = scope.resolveName(left.object.name);
 			} else {
-				object = scope.createIdentifier('object');
+				object = scope.createDeclaration('object');
 				needsObjectVar = true;
 			}
 
 			if (left.start === statement.start) {
 				if (needsObjectVar && needsPropertyVar) {
-					code.prependRight(statement.start, `var ${object} = `);
+					code.prependRight(statement.start, `${object} = `);
 					code.overwrite(
 						left.object.end,
 						left.property.start,
-						`;\n${i0}var ${property} = `
+						`;\n${i0}${property} = `
 					);
 					code.overwrite(
 						left.property.end,
@@ -248,11 +132,11 @@ export default class AssignmentExpression extends Node {
 						`;\n${i0}${object}[${property}]`
 					);
 				} else if (needsObjectVar) {
-					code.prependRight(statement.start, `var ${object} = `);
+					code.prependRight(statement.start, `${object} = `);
 					code.appendLeft(left.object.end, `;\n${i0}`);
 					code.appendLeft(left.object.end, object);
 				} else if (needsPropertyVar) {
-					code.prependRight(left.property.start, `var ${property} = `);
+					code.prependRight(left.property.start, `${property} = `);
 					code.appendLeft(left.property.end, `;\n${i0}`);
 					code.move(left.property.start, left.property.end, this.start);
 
@@ -261,17 +145,6 @@ export default class AssignmentExpression extends Node {
 					code.remove(left.property.end, left.end);
 				}
 			} else {
-				let declarators = [];
-				if (needsObjectVar) declarators.push(object);
-				if (needsPropertyVar) declarators.push(property);
-
-				if (declarators.length) {
-					code.prependRight(
-						statement.start,
-						`var ${declarators.join(', ')};\n${i0}`
-					);
-				}
-
 				if (needsObjectVar && needsPropertyVar) {
 					code.prependRight(left.start, `( ${object} = `);
 					code.overwrite(
diff --git a/src/program/types/CallExpression.js b/src/program/types/CallExpression.js
index 3f6b2c3..3671f52 100644
--- a/src/program/types/CallExpression.js
+++ b/src/program/types/CallExpression.js
@@ -57,17 +57,10 @@ export default class CallExpression extends Node {
 					if (this.callee.object.type === 'Identifier') {
 						context = this.callee.object.name;
 					} else {
-						context = this.findScope(true).createIdentifier('ref');
+						context = this.findScope(true).createDeclaration('ref');
 						const callExpression = this.callee.object;
-						const enclosure = callExpression.findNearest(/Function/);
-						const block = enclosure
-							? enclosure.body.body
-							: callExpression.findNearest(/^Program$/).body;
-						const lastStatementInBlock = block[block.length - 1];
-						const i0 = lastStatementInBlock.getIndentation();
 						code.prependRight(callExpression.start, `(${context} = `);
 						code.appendLeft(callExpression.end, `)`);
-						code.appendLeft(lastStatementInBlock.end, `\n${i0}var ${context};`);
 					}
 				} else {
 					context = 'void 0';
diff --git a/src/program/types/ClassDeclaration.js b/src/program/types/ClassDeclaration.js
index ddca8e7..d3563b8 100644
--- a/src/program/types/ClassDeclaration.js
+++ b/src/program/types/ClassDeclaration.js
@@ -31,10 +31,10 @@ export default class ClassDeclaration extends Node {
 				code.remove(this.parent.start, this.start);
 			}
 
-			let c = this.start
+			let c = this.start;
 			if (this.id) {
 				code.overwrite(c, this.id.start, 'var ');
-				c = this.id.end
+				c = this.id.end;
 			} else {
 				code.prependLeft(c, `var ${this.name}`);
 			}
diff --git a/src/program/types/ForInStatement.js b/src/program/types/ForInStatement.js
index c58a348..6354c62 100644
--- a/src/program/types/ForInStatement.js
+++ b/src/program/types/ForInStatement.js
@@ -1,4 +1,5 @@
 import LoopStatement from './shared/LoopStatement.js';
+import destructure from '../../utils/destructure.js';
 import extractNames from '../extractNames.js';
 
 export default class ForInStatement extends LoopStatement {
@@ -9,10 +10,12 @@ export default class ForInStatement extends LoopStatement {
 	}
 
 	transpile(code, transforms) {
+		const hasDeclaration = this.left.type === 'VariableDeclaration';
+
 		if (this.shouldRewriteAsFunction) {
 			// which variables are declared in the init statement?
 			const names =
-				this.left.type === 'VariableDeclaration'
+				hasDeclaration
 					? [].concat.apply(
 							[],
 							this.left.declarations.map(declarator =>
@@ -30,5 +33,44 @@ export default class ForInStatement extends LoopStatement {
 		}
 
 		super.transpile(code, transforms);
+
+		const maybePattern = hasDeclaration ? this.left.declarations[0].id : this.left;
+		if (maybePattern.type !== 'Identifier') {
+			this.destructurePattern(code, maybePattern, hasDeclaration);
+		}
+	}
+
+	destructurePattern(code, pattern, isDeclaration) {
+		const scope = this.findScope(true);
+		const i0 = this.getIndentation();
+		const i1 = i0 + code.getIndentString();
+
+		const ref = scope.createIdentifier('ref');
+
+		const bodyStart = this.body.body.length ? this.body.body[0].start : this.body.start + 1;
+
+		code.move(pattern.start, pattern.end, bodyStart);
+
+		code.prependRight(pattern.end, isDeclaration ? ref : `var ${ref}`);
+
+		let statementGenerators = [];
+		destructure(
+			code,
+			id => scope.createIdentifier(id),
+			({ name }) => scope.resolveName(name),
+			pattern,
+			ref,
+			false,
+			statementGenerators
+		);
+
+		let suffix = `;\n${i1}`;
+		statementGenerators.forEach((fn, i) => {
+			if (i === statementGenerators.length - 1) {
+				suffix = `;\n\n${i1}`;
+			}
+
+			fn(bodyStart, '', suffix);
+		});
 	}
 }
diff --git a/src/program/types/ForOfStatement.js b/src/program/types/ForOfStatement.js
index c8229f9..2bf0e61 100644
--- a/src/program/types/ForOfStatement.js
+++ b/src/program/types/ForOfStatement.js
@@ -52,13 +52,20 @@ export default class ForOfStatement extends LoopStatement {
 		code.prependRight(this.right.start, `var ${key} = 0, ${list} = `);
 		code.appendLeft(this.right.end, `; ${key} < ${list}.length; ${key} += 1`);
 
-		// destructuring. TODO non declaration destructuring
-		const declarator =
-			this.left.type === 'VariableDeclaration' && this.left.declarations[0];
-		if (declarator && declarator.id.type !== 'Identifier') {
+		const isDeclaration = this.left.type === 'VariableDeclaration';
+		const maybeDestructuring = isDeclaration ? this.left.declarations[0].id : this.left;
+		if (maybeDestructuring.type !== 'Identifier') {
 			let statementGenerators = [];
 			const ref = scope.createIdentifier('ref');
-			destructure(code, scope, declarator.id, ref, false, statementGenerators);
+			destructure(
+				code,
+				id => scope.createIdentifier(id),
+				({ name }) => scope.resolveName(name),
+				maybeDestructuring,
+				ref,
+				!isDeclaration,
+				statementGenerators
+			);
 
 			let suffix = `;\n${i1}`;
 			statementGenerators.forEach((fn, i) => {
@@ -69,8 +76,12 @@ export default class ForOfStatement extends LoopStatement {
 				fn(bodyStart, '', suffix);
 			});
 
-			code.appendLeft(this.left.start + this.left.kind.length + 1, ref);
-			code.appendLeft(this.left.end, ` = ${list}[${key}];\n${i1}`);
+			if (isDeclaration) {
+				code.appendLeft(this.left.start + this.left.kind.length + 1, ref);
+				code.appendLeft(this.left.end, ` = ${list}[${key}];\n${i1}`);
+			} else {
+				code.appendLeft(this.left.end, `var ${ref} = ${list}[${key}];\n${i1}`);
+			}
 		} else {
 			code.appendLeft(this.left.end, ` = ${list}[${key}];\n\n${i1}`);
 		}
diff --git a/src/program/types/Identifier.js b/src/program/types/Identifier.js
index e71d778..5aa7878 100644
--- a/src/program/types/Identifier.js
+++ b/src/program/types/Identifier.js
@@ -16,8 +16,9 @@ export default class Identifier extends Node {
 	}
 
 	initialise(transforms) {
-		if (transforms.arrow && isReference(this, this.parent)) {
+		if (isReference(this, this.parent)) {
 			if (
+				transforms.arrow &&
 				this.name === 'arguments' &&
 				!this.findScope(false).contains(this.name)
 			) {
diff --git a/src/program/types/JSXClosingElement.js b/src/program/types/JSXClosingElement.js
index d2cb44a..3c7476b 100644
--- a/src/program/types/JSXClosingElement.js
+++ b/src/program/types/JSXClosingElement.js
@@ -2,7 +2,7 @@ import Node from '../Node.js';
 
 function containsNewLine(node) {
 	return (
-		node.type === 'Literal' && !/\S/.test(node.value) && /\n/.test(node.value)
+		node.type === 'JSXText' && !/\S/.test(node.value) && /\n/.test(node.value)
 	);
 }
 
diff --git a/src/program/types/JSXClosingFragment.js b/src/program/types/JSXClosingFragment.js
new file mode 100644
index 0000000..8d54477
--- /dev/null
+++ b/src/program/types/JSXClosingFragment.js
@@ -0,0 +1,22 @@
+import Node from '../Node.js';
+
+function containsNewLine(node) {
+	return (
+		node.type === 'JSXText' && !/\S/.test(node.value) && /\n/.test(node.value)
+	);
+}
+
+export default class JSXClosingFragment extends Node {
+	transpile(code) {
+		let spaceBeforeParen = true;
+
+		const lastChild = this.parent.children[this.parent.children.length - 1];
+
+		// omit space before closing paren if this is on a separate line
+		if (lastChild && containsNewLine(lastChild)) {
+			spaceBeforeParen = false;
+		}
+
+		code.overwrite(this.start, this.end, spaceBeforeParen ? ' )' : ')');
+	}
+}
diff --git a/src/program/types/JSXElement.js b/src/program/types/JSXElement.js
index 7fa7468..7ca888a 100644
--- a/src/program/types/JSXElement.js
+++ b/src/program/types/JSXElement.js
@@ -1,6 +1,9 @@
 import Node from '../Node.js';
 
 function normalise(str, removeTrailingWhitespace) {
+
+	str = str.replace(/\u00a0/g, ' ');
+
 	if (removeTrailingWhitespace && /\n/.test(str)) {
 		str = str.replace(/\s+$/, '');
 	}
@@ -18,7 +21,7 @@ export default class JSXElement extends Node {
 		super.transpile(code, transforms);
 
 		const children = this.children.filter(child => {
-			if (child.type !== 'Literal') return true;
+			if (child.type !== 'JSXText') return true;
 
 			// remove whitespace-only literals, unless on a single line
 			return /\S/.test(child.raw) || !/\n/.test(child.raw);
@@ -38,12 +41,12 @@ export default class JSXElement extends Node {
 					// empty block is a no op
 				} else {
 					const tail =
-						code.original[c] === '\n' && child.type !== 'Literal' ? '' : ' ';
+						code.original[c] === '\n' && child.type !== 'JSXText' ? '' : ' ';
 					code.appendLeft(c, `,${tail}`);
 				}
 
-				if (child.type === 'Literal') {
-					const str = normalise(child.raw, i === children.length - 1);
+				if (child.type === 'JSXText') {
+					const str = normalise(child.value, i === children.length - 1);
 					code.overwrite(child.start, child.end, str);
 				}
 
diff --git a/src/program/types/JSXFragment.js b/src/program/types/JSXFragment.js
new file mode 100644
index 0000000..bef4820
--- /dev/null
+++ b/src/program/types/JSXFragment.js
@@ -0,0 +1,4 @@
+import JSXElement from './JSXElement.js';
+
+export default class JSXFragment extends JSXElement {
+}
diff --git a/src/program/types/JSXOpeningFragment.js b/src/program/types/JSXOpeningFragment.js
new file mode 100644
index 0000000..ba3c6eb
--- /dev/null
+++ b/src/program/types/JSXOpeningFragment.js
@@ -0,0 +1,7 @@
+import Node from '../Node.js';
+
+export default class JSXOpeningFragment extends Node {
+	transpile(code, transforms) {
+		code.overwrite(this.start, this.end, `${this.program.jsx}( React.Fragment, null`);
+	}
+}
diff --git a/src/program/types/NewExpression.js b/src/program/types/NewExpression.js
index 8d33c06..a096cb4 100644
--- a/src/program/types/NewExpression.js
+++ b/src/program/types/NewExpression.js
@@ -1,5 +1,6 @@
 import Node from '../Node.js';
 import spread, { isArguments } from '../../utils/spread.js';
+import removeTrailingComma from '../../utils/removeTrailingComma.js';
 
 export default class NewExpression extends Node {
 	initialise(transforms) {
@@ -20,6 +21,8 @@ export default class NewExpression extends Node {
 	}
 
 	transpile(code, transforms) {
+		super.transpile(code, transforms);
+
 		if (transforms.spreadRest && this.arguments.length) {
 			const firstArgument = this.arguments[0];
 			const isNew = true;
@@ -45,6 +48,8 @@ export default class NewExpression extends Node {
 			}
 		}
 
-		super.transpile(code, transforms);
+		if (this.arguments.length) {
+			removeTrailingComma(code, this.arguments[this.arguments.length - 1].end);
+		}
 	}
 }
diff --git a/src/program/types/ObjectExpression.js b/src/program/types/ObjectExpression.js
index 9afff13..c0f887b 100644
--- a/src/program/types/ObjectExpression.js
+++ b/src/program/types/ObjectExpression.js
@@ -119,8 +119,7 @@ export default class ObjectExpression extends Node {
 			if (spreadPropertyCount) isSimpleAssignment = false;
 
 			// handle block scoping
-			const declaration = this.findScope(false).findDeclaration(name);
-			if (declaration) name = declaration.name;
+			name = this.findScope(false).resolveName(name);
 
 			const start = firstPropertyStart;
 			const end = this.end;
@@ -132,7 +131,7 @@ export default class ObjectExpression extends Node {
 					firstSpreadProperty === null ||
 					firstComputedProperty < firstSpreadProperty
 				) {
-					name = this.findLexicalBoundary().declareIdentifier('obj');
+					name = this.findScope(true).createDeclaration('obj');
 
 					code.prependRight(this.start, `( ${name} = `);
 				} else name = null; // We don't actually need this variable
@@ -155,14 +154,14 @@ export default class ObjectExpression extends Node {
 					lastComputedProp = prop;
 
 					if (!name) {
-						name = this.findLexicalBoundary().declareIdentifier('obj');
+						name = this.findScope(true).createDeclaration('obj');
 
 						const propId = name + (prop.computed ? '' : '.');
 						code.appendRight(prop.start, `( ${name} = {}, ${propId}`);
 					} else {
 						const propId =
 							(isSimpleAssignment ? `;\n${i0}${name}` : `, ${name}`) +
-							(prop.computed ? '' : '.');
+							(prop.key.type === 'Literal' || prop.computed ? '' : '.');
 
 						if (moveStart < prop.start) {
 							code.overwrite(moveStart, prop.start, propId);
@@ -176,19 +175,29 @@ export default class ObjectExpression extends Node {
 						while (code.original[c] !== ']') c += 1;
 						c += 1;
 					}
-					if (prop.shorthand) {
+					if (prop.key.type === 'Literal' && !prop.computed) {
 						code.overwrite(
 							prop.start,
+							prop.key.end + 1,
+							'[' + code.slice(prop.start, prop.key.end) + '] = '
+						);
+					} else if (prop.shorthand || (prop.method && !prop.computed && transforms.conciseMethodProperty)) {
+						// Replace : with = if Property::transpile inserted the :
+						code.overwrite(
+							prop.key.start,
 							prop.key.end,
-							code.slice(prop.start, prop.key.end).replace(/:/, ' =')
+							code.slice(prop.key.start, prop.key.end).replace(/:/, ' =')
 						);
 					} else {
 						if (prop.value.start > c) code.remove(c, prop.value.start);
-						code.appendLeft(c, ' = ');
+						code.prependLeft(c, ' = ');
 					}
 
-					if (prop.method && transforms.conciseMethodProperty) {
-						code.prependRight(prop.value.start, 'function ');
+					// This duplicates behavior from Property::transpile which is disabled
+					// for computed properties or if conciseMethodProperty is false
+					if (prop.method && (prop.computed || !transforms.conciseMethodProperty)) {
+						if (prop.value.generator) code.remove(prop.start, prop.key.start);
+						code.prependRight(prop.value.start, `function${prop.value.generator ? '*' : ''} `);
 					}
 				} else if (prop.type === 'SpreadElement') {
 					if (name && i > 0) {
diff --git a/src/program/types/Super.js b/src/program/types/Super.js
index d26e873..aaee2ee 100644
--- a/src/program/types/Super.js
+++ b/src/program/types/Super.js
@@ -7,7 +7,7 @@ export default class Super extends Node {
 		if (transforms.classes) {
 			this.method = this.findNearest('MethodDefinition');
 			if (!this.method)
-				throw new CompileError(this, 'use of super outside class method');
+				throw new CompileError('use of super outside class method', this);
 
 			const parentClass = this.findNearest('ClassBody').parent;
 			this.superClassName =
diff --git a/src/program/types/TaggedTemplateExpression.js b/src/program/types/TaggedTemplateExpression.js
index 987aabe..b3d607e 100644
--- a/src/program/types/TaggedTemplateExpression.js
+++ b/src/program/types/TaggedTemplateExpression.js
@@ -22,14 +22,26 @@ export default class TaggedTemplateExpression extends Node {
 				.concat(this.quasi.quasis)
 				.sort((a, b) => a.start - b.start);
 
+			const program = this.program;
+			const rootScope = program.body.scope;
+
 			// insert strings at start
 			const templateStrings = this.quasi.quasis.map(quasi =>
 				JSON.stringify(quasi.value.cooked)
-			);
+			).join(', ');
+
+			let templateObject = this.program.templateLiteralQuasis[templateStrings];
+			if (!templateObject) {
+				templateObject = rootScope.createIdentifier('templateObject');
+				code.prependRight(this.program.prependAt, `var ${templateObject} = Object.freeze([${templateStrings}]);\n`);
+
+				this.program.templateLiteralQuasis[templateStrings] = templateObject;
+			}
+
 			code.overwrite(
 				this.tag.end,
 				ordered[0].start,
-				`([${templateStrings.join(', ')}]`
+				`(${templateObject}`
 			);
 
 			let lastIndex = ordered[0].start;
diff --git a/src/program/types/TemplateLiteral.js b/src/program/types/TemplateLiteral.js
index b89961f..93ac4ff 100644
--- a/src/program/types/TemplateLiteral.js
+++ b/src/program/types/TemplateLiteral.js
@@ -74,7 +74,7 @@ export default class TemplateLiteral extends Node {
 			});
 
 			if (parenthesise) code.appendLeft(lastIndex, ')');
-			code.remove(lastIndex, this.end);
+			code.overwrite(lastIndex, this.end, "", { contentOnly: true } );
 		}
 	}
 }
diff --git a/src/program/types/UpdateExpression.js b/src/program/types/UpdateExpression.js
index a094db8..eb1765b 100644
--- a/src/program/types/UpdateExpression.js
+++ b/src/program/types/UpdateExpression.js
@@ -1,5 +1,5 @@
 import Node from '../Node.js';
-import CompileError from '../../utils/CompileError.js';
+import checkConst from '../../utils/checkConst.js';
 
 export default class UpdateExpression extends Node {
 	initialise(transforms) {
@@ -7,10 +7,6 @@ export default class UpdateExpression extends Node {
 			const declaration = this.findScope(false).findDeclaration(
 				this.argument.name
 			);
-			if (declaration && declaration.kind === 'const') {
-				throw new CompileError(`${this.argument.name} is read-only`, this);
-			}
-
 			// special case – https://gitlab.com/Rich-Harris/buble/issues/150
 			const statement = declaration && declaration.node.ancestor(3);
 			if (
@@ -24,4 +20,13 @@ export default class UpdateExpression extends Node {
 
 		super.initialise(transforms);
 	}
+
+	transpile(code, transforms) {
+		if (this.argument.type === 'Identifier') {
+			// Do this check after everything has been initialized to find
+			// shadowing declarations after this expression
+			checkConst(this.argument, this.findScope(false));
+		}
+		super.transpile(code, transforms);
+	}
 }
diff --git a/src/program/types/VariableDeclaration.js b/src/program/types/VariableDeclaration.js
index 42134ed..694e1e7 100644
--- a/src/program/types/VariableDeclaration.js
+++ b/src/program/types/VariableDeclaration.js
@@ -19,7 +19,7 @@ export default class VariableDeclaration extends Node {
 			});
 		}
 
-		if (transforms.destructuring && this.parent.type !== 'ForOfStatement') {
+		if (transforms.destructuring && this.parent.type !== 'ForOfStatement' && this.parent.type !== 'ForInStatement') {
 			let c = this.start;
 			let lastDeclaratorIsPattern;
 
@@ -43,7 +43,7 @@ export default class VariableDeclaration extends Node {
 						declarator.init.type === 'Identifier' && !declarator.init.rewritten;
 
 					const name = simple
-						? declarator.init.name
+						? (declarator.init.alias || declarator.init.name)
 						: declarator.findScope(true).createIdentifier('ref');
 
 					c = declarator.start;
@@ -60,9 +60,11 @@ export default class VariableDeclaration extends Node {
 						});
 					}
 
+					const scope = declarator.findScope(false);
 					destructure(
 						code,
-						declarator.findScope(false),
+						id => scope.createIdentifier(id),
+						({ name }) => scope.resolveName(name),
 						declarator.id,
 						name,
 						inline,
diff --git a/src/program/types/index.js b/src/program/types/index.js
index f0d4f65..0b747e5 100644
--- a/src/program/types/index.js
+++ b/src/program/types/index.js
@@ -22,9 +22,12 @@ import ImportDefaultSpecifier from './ImportDefaultSpecifier.js';
 import ImportSpecifier from './ImportSpecifier.js';
 import JSXAttribute from './JSXAttribute.js';
 import JSXClosingElement from './JSXClosingElement.js';
+import JSXClosingFragment from './JSXClosingFragment.js';
 import JSXElement from './JSXElement.js';
 import JSXExpressionContainer from './JSXExpressionContainer.js';
+import JSXFragment from './JSXFragment.js';
 import JSXOpeningElement from './JSXOpeningElement.js';
+import JSXOpeningFragment from './JSXOpeningFragment.js';
 import JSXSpreadAttribute from './JSXSpreadAttribute.js';
 import Literal from './Literal.js';
 import LoopStatement from './shared/LoopStatement.js';
@@ -69,9 +72,12 @@ export default {
 	ImportSpecifier,
 	JSXAttribute,
 	JSXClosingElement,
+	JSXClosingFragment,
 	JSXElement,
 	JSXExpressionContainer,
+	JSXFragment,
 	JSXOpeningElement,
+	JSXOpeningFragment,
 	JSXSpreadAttribute,
 	Literal,
 	MemberExpression,
diff --git a/src/program/wrap.js b/src/program/wrap.js
index c9ea787..5144753 100644
--- a/src/program/wrap.js
+++ b/src/program/wrap.js
@@ -49,7 +49,18 @@ export default function wrap(raw, parent) {
 		};
 	}
 
-	new Node(raw, parent);
+	raw.parent = parent;
+	raw.program = parent.program || parent;
+	raw.depth = parent.depth + 1;
+	raw.keys = keys[raw.type];
+	raw.indentation = undefined;
+
+	for (const key of keys[raw.type]) {
+		wrap(raw[key], raw);
+	}
+
+	raw.program.magicString.addSourcemapLocation(raw.start);
+	raw.program.magicString.addSourcemapLocation(raw.end);
 
 	const type =
 		(raw.type === 'BlockStatement' ? BlockStatement : types[raw.type]) || Node;
diff --git a/src/support.js b/src/support.js
index 7b48b92..bba5d05 100644
--- a/src/support.js
+++ b/src/support.js
@@ -1,71 +1,89 @@
 export const matrix = {
 	chrome: {
-		    48: 0b01001111011111100111110101111101,
-		    49: 0b01001111111111100111111111111111,
-		    50: 0b01011111111111100111111111111111,
-		    51: 0b01011111111111100111111111111111,
-		    52: 0b01111111111111100111111111111111
+		    48: 0b01001010100011001101,
+		    49: 0b01001111100111111111,
+		    50: 0b01011111100111111111,
+		    51: 0b01011111100111111111,
+		    52: 0b01111111100111111111,
+		    53: 0b01111111100111111111,
+		    54: 0b01111111100111111111,
+		    55: 0b01111111100111111111,
+		    56: 0b01111111100111111111,
+		    57: 0b01111111100111111111,
+		    58: 0b11111111100111111111,
+		    59: 0b11111111100111111111,
+		    60: 0b11111111100111111111,
+		    61: 0b11111111100111111111,
+		    62: 0b11111111100111111111,
+		    63: 0b11111111100111111111
 	},
 	firefox: {
-		    43: 0b01000111111101100000110111011101,
-		    44: 0b01000111111101100000110111011101,
-		    45: 0b01000111111101100000110111011101,
-		    46: 0b01010111111111100000110111011101,
-		    47: 0b01010111111111100111111111011111,
-		    48: 0b01010111111111100111111111011111
+		    43: 0b01001111100011011101,
+		    44: 0b01001111100111011101,
+		    45: 0b01001111100111011111,
+		    46: 0b01011111100111011111,
+		    47: 0b01011111100111111111,
+		    48: 0b01011111100111111111,
+		    49: 0b01011110100111111111,
+		    50: 0b01011110100111111111,
+		    51: 0b01011110100111111111,
+		    52: 0b11111111100111111111,
+		    53: 0b11111111100111111111,
+		    54: 0b11111111100111111111,
+		    55: 0b11111111100111111111,
+		    56: 0b11111111100111111111,
+		    57: 0b11111111100111111111,
+		    58: 0b11111111100111111111
 	},
 	safari: {
-		     8: 0b01000000000000000000000000000000,
-		     9: 0b01001111001101100000011101011110
+		     8: 0b01000000000000000100,
+		     9: 0b01001001100001101110,
+		    10: 0b11011111100111111111,
+		'10.1': 0b11111111100111111111,
+		    11: 0b11111111100111111111
 	},
 	ie: {
-		     8: 0b00000000000000000000000000000000,
-		     9: 0b01000000000000000000000000000000,
-		    10: 0b01000000000000000000000000000000,
-		    11: 0b01000000000000000111000001100000
+		     8: 0b00000000000000000000,
+		     9: 0b01000000000000000000,
+		    10: 0b01000000000000000000,
+		    11: 0b01000000000100000000
 	},
 	edge: {
-		    12: 0b01011110110111100011010001011101,
-		    13: 0b01011111110111100011110001011111
+		    12: 0b01001010100101001101,
+		    13: 0b01011110100111001111,
+		    14: 0b11111110100111111111,
+		    15: 0b11111110100111111111,
+		    16: 0b11111110100111111111
 	},
 	node: {
-		'0.10': 0b01000000000101000000000001000000,
-		'0.12': 0b01000001000101000000010001000100,
-		     4: 0b01001111000111100111111001111111,
-		     5: 0b01001111000111100111111001111111,
-		     6: 0b01011111111111100111111111111111
+		'0.10': 0b01000000000000000000,
+		'0.12': 0b01000000000001000000,
+		     4: 0b01001000100011001111,
+		     5: 0b01001000100011001111,
+		     6: 0b01011111100111111111,
+		     8: 0b11111111100111111111,
+		 '8.3': 0b11111111100111111111,
+		 '8.7': 0b11111111100111111111
 	}
 };
 
 export const features = [
 	'arrow',
 	'classes',
-	'collections',
 	'computedProperty',
 	'conciseMethodProperty',
-	'constLoop',
-	'constRedef',
 	'defaultParameter',
 	'destructuring',
-	'extendNatives',
 	'forOf',
 	'generator',
 	'letConst',
-	'letLoop',
-	'letLoopScope',
 	'moduleExport',
 	'moduleImport',
 	'numericLiteral',
-	'objectProto',
-	'objectSuper',
-	'oldOctalLiteral',
 	'parameterDestructuring',
 	'spreadRest',
 	'stickyRegExp',
-	'symbol',
 	'templateString',
-	'unicodeEscape',
-	'unicodeIdentifier',
 	'unicodeRegExp',
 
 	// ES2016
diff --git a/src/utils/checkConst.js b/src/utils/checkConst.js
new file mode 100644
index 0000000..c980b20
--- /dev/null
+++ b/src/utils/checkConst.js
@@ -0,0 +1,8 @@
+import CompileError from './CompileError.js';
+
+export default function checkConst(identifier, scope) {
+	const declaration = scope.findDeclaration(identifier.name);
+	if (declaration && declaration.kind === 'const') {
+		throw new CompileError(`${identifier.name} is read-only`, identifier);
+	}
+}
diff --git a/src/utils/destructure.js b/src/utils/destructure.js
index 0f620fd..1b840b0 100644
--- a/src/utils/destructure.js
+++ b/src/utils/destructure.js
@@ -10,18 +10,35 @@ const handlers = {
 
 export default function destructure(
 	code,
-	scope,
+	createIdentifier,
+	resolveName,
 	node,
 	ref,
 	inline,
 	statementGenerators
 ) {
-	handlers[node.type](code, scope, node, ref, inline, statementGenerators);
+	handlers[node.type](code, createIdentifier, resolveName, node, ref, inline, statementGenerators);
 }
 
 function destructureIdentifier(
 	code,
-	scope,
+	createIdentifier,
+	resolveName,
+	node,
+	ref,
+	inline,
+	statementGenerators
+) {
+	statementGenerators.push((start, prefix, suffix) => {
+		code.overwrite(node.start, node.end, (inline ? prefix : `${prefix}var `) + resolveName(node) + ` = ${ref}${suffix}`);
+		code.move(node.start, node.end, start);
+	});
+}
+
+function destructureMemberExpression(
+	code,
+	createIdentifier,
+	resolveName,
 	node,
 	ref,
 	inline,
@@ -36,7 +53,8 @@ function destructureIdentifier(
 
 function destructureAssignmentPattern(
 	code,
-	scope,
+	createIdentifier,
+	resolveName,
 	node,
 	ref,
 	inline,
@@ -57,13 +75,14 @@ function destructureAssignmentPattern(
 	}
 
 	if (!isIdentifier) {
-		destructure(code, scope, node.left, ref, inline, statementGenerators);
+		destructure(code, createIdentifier, resolveName, node.left, ref, inline, statementGenerators);
 	}
 }
 
 function destructureArrayPattern(
 	code,
-	scope,
+	createIdentifier,
+	resolveName,
 	node,
 	ref,
 	inline,
@@ -77,7 +96,8 @@ function destructureArrayPattern(
 		if (element.type === 'RestElement') {
 			handleProperty(
 				code,
-				scope,
+				createIdentifier,
+				resolveName,
 				c,
 				element.argument,
 				`${ref}.slice(${i})`,
@@ -87,7 +107,8 @@ function destructureArrayPattern(
 		} else {
 			handleProperty(
 				code,
-				scope,
+				createIdentifier,
+				resolveName,
 				c,
 				element,
 				`${ref}[${i}]`,
@@ -103,7 +124,8 @@ function destructureArrayPattern(
 
 function destructureObjectPattern(
 	code,
-	scope,
+	createIdentifier,
+	resolveName,
 	node,
 	ref,
 	inline,
@@ -125,15 +147,13 @@ function destructureObjectPattern(
 			nonRestKeys.push(isComputedKey ? key : '"' + key + '"');
 		} else if (prop.type === 'RestElement') {
 			content = prop.argument;
-			value = scope.createIdentifier('rest');
-			const n = scope.createIdentifier('n');
+			value = createIdentifier('rest');
 			statementGenerators.push((start, prefix, suffix) => {
+				const helper = prop.program.getObjectWithoutPropertiesHelper(code);
 				code.overwrite(
 					prop.start,
 					(c = prop.argument.start),
-					`${prefix}var ${value} = {}; for (var ${n} in ${ref}) if([${nonRestKeys.join(
-						', '
-					)}].indexOf(${n}) === -1) ${value}[${n}] = ${ref}[${n}]${suffix}`
+					(inline ? prefix : `${prefix}var `) + `${value} = ${helper}( ${ref}, [${nonRestKeys.join(', ')}] )${suffix}`
 				);
 				code.move(prop.start, c, start);
 			});
@@ -143,7 +163,7 @@ function destructureObjectPattern(
 				`Unexpected node of type ${prop.type} in object pattern`
 			);
 		}
-		handleProperty(code, scope, c, content, value, inline, statementGenerators);
+		handleProperty(code, createIdentifier, resolveName, c, content, value, inline, statementGenerators);
 		c = prop.end;
 	});
 
@@ -152,7 +172,8 @@ function destructureObjectPattern(
 
 function handleProperty(
 	code,
-	scope,
+	createIdentifier,
+	resolveName,
 	c,
 	node,
 	value,
@@ -164,7 +185,8 @@ function handleProperty(
 			code.remove(c, node.start);
 			destructureIdentifier(
 				code,
-				scope,
+				createIdentifier,
+				resolveName,
 				node,
 				value,
 				inline,
@@ -173,26 +195,37 @@ function handleProperty(
 			break;
 		}
 
+		case 'MemberExpression':
+			code.remove(c, node.start);
+			destructureMemberExpression(
+				code,
+				createIdentifier,
+				resolveName,
+				node,
+				value,
+				true,
+				statementGenerators
+			);
+			break;
+
 		case 'AssignmentPattern': {
 			let name;
 
 			const isIdentifier = node.left.type === 'Identifier';
 
 			if (isIdentifier) {
-				name = node.left.name;
-				const declaration = scope.findDeclaration(name);
-				if (declaration) name = declaration.name;
+				name = resolveName(node.left);
 			} else {
-				name = scope.createIdentifier(value);
+				name = createIdentifier(value);
 			}
 
 			statementGenerators.push((start, prefix, suffix) => {
 				if (inline) {
 					code.prependRight(
 						node.right.start,
-						`${name} = ${value} === undefined ? `
+						`${name} = ${value}, ${name} = ${name} === void 0 ? `
 					);
-					code.appendLeft(node.right.end, ` : ${value}`);
+					code.appendLeft(node.right.end, ` : ${name}${suffix}`);
 				} else {
 					code.prependRight(
 						node.right.start,
@@ -211,7 +244,8 @@ function handleProperty(
 				code.remove(node.left.end, node.right.start);
 				handleProperty(
 					code,
-					scope,
+					createIdentifier,
+					resolveName,
 					c,
 					node.left,
 					name,
@@ -228,19 +262,19 @@ function handleProperty(
 
 			let ref = value;
 			if (node.properties.length > 1) {
-				ref = scope.createIdentifier(value);
+				ref = createIdentifier(value);
 
 				statementGenerators.push((start, prefix, suffix) => {
 					// this feels a tiny bit hacky, but we can't do a
 					// straightforward appendLeft and keep correct order...
-					code.prependRight(node.start, `${prefix}var ${ref} = `);
+					code.prependRight(node.start, (inline ? '' : `${prefix}var `) + `${ref} = `);
 					code.overwrite(node.start, (c = node.start + 1), value);
 					code.appendLeft(c, suffix);
 
 					code.overwrite(
 						node.start,
 						(c = node.start + 1),
-						`${prefix}var ${ref} = ${value}${suffix}`
+						(inline ? '' : `${prefix}var `) + `${ref} = ${value}${suffix}`
 					);
 					code.move(node.start, c, start);
 				});
@@ -248,7 +282,8 @@ function handleProperty(
 
 			destructureObjectPattern(
 				code,
-				scope,
+				createIdentifier,
+				resolveName,
 				node,
 				ref,
 				inline,
@@ -262,10 +297,10 @@ function handleProperty(
 			code.remove(c, (c = node.start));
 
 			if (node.elements.filter(Boolean).length > 1) {
-				const ref = scope.createIdentifier(value);
+				const ref = createIdentifier(value);
 
 				statementGenerators.push((start, prefix, suffix) => {
-					code.prependRight(node.start, `${prefix}var ${ref} = `);
+					code.prependRight(node.start, (inline ? '' : `${prefix}var `) + `${ref} = `);
 					code.overwrite(node.start, (c = node.start + 1), value, {
 						contentOnly: true
 					});
@@ -280,7 +315,8 @@ function handleProperty(
 					if (element.type === 'RestElement') {
 						handleProperty(
 							code,
-							scope,
+							createIdentifier,
+							resolveName,
 							c,
 							element.argument,
 							`${ref}.slice(${i})`,
@@ -290,7 +326,8 @@ function handleProperty(
 					} else {
 						handleProperty(
 							code,
-							scope,
+							createIdentifier,
+							resolveName,
 							c,
 							element,
 							`${ref}[${i}]`,
@@ -306,7 +343,8 @@ function handleProperty(
 				if (element.type === 'RestElement') {
 					handleProperty(
 						code,
-						scope,
+						createIdentifier,
+						resolveName,
 						c,
 						element.argument,
 						`${value}.slice(${index})`,
@@ -316,7 +354,8 @@ function handleProperty(
 				} else {
 					handleProperty(
 						code,
-						scope,
+						createIdentifier,
+						resolveName,
 						c,
 						element,
 						`${value}[${index}]`,
diff --git a/src/utils/removeTrailingComma.js b/src/utils/removeTrailingComma.js
index 50b610c..8980f7a 100644
--- a/src/utils/removeTrailingComma.js
+++ b/src/utils/removeTrailingComma.js
@@ -5,6 +5,9 @@ export default function removeTrailingComma(code, c) {
 			return;
 		}
 
+		if (code.original[c] === '/') {
+			c = code.original.indexOf(code.original[c + 1] === '/' ? '\n' : '*/', c) + 1;
+		}
 		c += 1;
 	}
-}
\ No newline at end of file
+}
diff --git a/test/samples/block-scoping.js b/test/samples/block-scoping.js
index bb2f802..93d2a5a 100644
--- a/test/samples/block-scoping.js
+++ b/test/samples/block-scoping.js
@@ -86,6 +86,51 @@ module.exports = [
 	},
 
 	{
+		description: 'disallows destructured reassignment to constants, short-hand property',
+		input: `
+			const x = 1;
+			({ x } = {});
+		`,
+		error: /x is read-only/
+	},
+
+	{
+		description: 'disallows destructured reassignment to constants, rest property',
+		input: `
+			const x = 1;
+			({ ...x } = {});
+		`,
+		error: /x is read-only/
+	},
+
+	{
+		description: 'disallows destructured reassignment to constants, renamed property',
+		input: `
+			const x = 1;
+			({ y: x } = {});
+		`,
+		error: /x is read-only/
+	},
+
+	{
+		description: 'disallows destructured reassignment to constants, array',
+		input: `
+			const x = 1;
+			([ x ] = []);
+		`,
+		error: /x is read-only/
+	},
+
+	{
+		description: 'disallows destructured reassignment to constants, rest element',
+		input: `
+			const x = 1;
+			([ ...x ] = []);
+		`,
+		error: /x is read-only/
+	},
+
+	{
 		description: 'disallows updates to constants',
 		input: `
 			const x = 1;
@@ -375,7 +420,6 @@ module.exports = [
 	},
 
 	{
-		skip: true,
 		description: 'deconflicts rest element declarations',
 
 		input: `
@@ -390,7 +434,9 @@ module.exports = [
 			var x;
 
 			if ( true ) {
-				var first = y[0], second = y[1], x$1 = y.slice( 2 );
+				var first = y[0];
+				var second = y[1];
+				var x$1 = y.slice(2);
 				console.log( x$1 );
 			}`
 	},
@@ -440,5 +486,55 @@ module.exports = [
 				a();
 				b();
 			}`
+	},
+
+	{
+		description: 'correctly recognizes shadowing of const variables by mutable variables declared after mutation',
+
+		input: `
+			const bar = "FAIL";
+			(function() {
+					function foo() {
+							--bar;
+							bar = ["fail", "PASS", "Fail"][bar];
+					}
+					let bar = 2;
+					foo();
+					console.log(bar);
+			}());
+		`,
+
+		output: `
+			var bar = "FAIL";
+			(function() {
+					function foo() {
+							--bar;
+							bar = ["fail", "PASS", "Fail"][bar];
+					}
+					var bar = 2;
+					foo();
+					console.log(bar);
+			}());
+		`
+	},
+
+	{
+		description: 'correctly transpiles if arrow functions are not transpiled',
+
+		options: { transforms: { arrow: false } },
+
+		input: `
+			var c;
+			if (true) {
+				let c = prop.end;
+				console.log(c);
+			}`,
+
+		output: `
+			var c;
+			if (true) {
+				var c$1 = prop.end;
+				console.log(c$1);
+			}`,
 	}
 ];
diff --git a/test/samples/computed-properties.js b/test/samples/computed-properties.js
index d68001d..e0c55ed 100644
--- a/test/samples/computed-properties.js
+++ b/test/samples/computed-properties.js
@@ -41,6 +41,38 @@ module.exports = [
 	},
 
 	{
+		description: 'creates a computed property at start of literal with method afterwards',
+
+		input: `
+			var obj = {
+				[a]: 1,
+				b() {}
+			};`,
+
+		output: `
+			var obj = {};
+			obj[a] = 1;
+			obj.b = function b() {};`
+	},
+
+	{
+		description: 'creates a computed property at start of literal with generator method afterwards when transpiling methods is disabled',
+
+		options: { transforms: { conciseMethodProperty: false, generator: false } },
+
+		input: `
+			var obj = {
+				[a]: 1,
+				*b() {}
+			};`,
+
+		output: `
+			var obj = {};
+			obj[a] = 1;
+			obj.b = function* () {};`
+	},
+
+	{
 		description: 'creates a computed property at end of literal',
 
 		input: `
@@ -227,9 +259,11 @@ module.exports = [
 			foo => bar({[x - y]: obj});
 		`,
 		output: `
-			var obj$1;
+			!function(foo) {
+				var obj$1;
 
-			!function(foo) { return bar(( obj$1 = {}, obj$1[x - y] = obj, obj$1 )); };
+				return bar(( obj$1 = {}, obj$1[x - y] = obj, obj$1 ));
+			};
 		`
 	},
 
@@ -244,5 +278,18 @@ module.exports = [
 			var obj, obj$1;
  return ( obj$1 = {}, obj$1[key] = ( obj = {}, obj[key] = val, obj ), obj$1 ) })
 		`
+	},
+
+	{
+		description: 'Puts helper variables in correct scope',
+
+		input: `
+			((x) => {var obj = 2; console.log([{[x]: 1}, obj]);})(3);
+		`,
+		output: `
+			(function (x) {
+			var obj$1;
+var obj = 2; console.log([( obj$1 = {}, obj$1[x] = 1, obj$1 ), obj]);})(3);
+		`
 	}
 ];
diff --git a/test/samples/destructuring.js b/test/samples/destructuring.js
index 8ea25cb..5571b87 100644
--- a/test/samples/destructuring.js
+++ b/test/samples/destructuring.js
@@ -343,8 +343,9 @@ module.exports = [
 			({ [FirstProp]: one, [SecondProp]: two = 'Too', 3: three, Fore: four } = x);
 		`,
 		output: `
-			var one, two, three, four;
 			var assign;
+
+			var one, two, three, four;
 			((assign = x, one = assign[FirstProp], two = assign[SecondProp], two = two === void 0 ? 'Too' : two, three = assign[3], four = assign.Fore));
 		`
 	},
@@ -468,10 +469,11 @@ module.exports = [
 			console.log(a, b, c, d);
 		`,
 		output: `
+			var assign, assign_slice_1_, assign_slice_1_2, assign_slice_1_2_s;
+
 			var x = [1, 2, {r: 9}, {s: ["table"]} ];
 			var a, b, c, d;
-			var assign, array, obj, temp;
-			((assign = x, a = assign[0], array = assign.slice(1), b = array[1].r, obj = array[2], c = obj.r, c = c === void 0 ? "nothing" : c, temp = obj.s, temp = temp === void 0 ? "nope" : temp, d = temp[0]));
+			((assign = x, a = assign[0], assign_slice_1_ = assign.slice(1), b = assign_slice_1_[1].r, assign_slice_1_2 = assign_slice_1_[2], c = assign_slice_1_2.r, c = c === void 0 ? "nothing" : c, assign_slice_1_2_s = assign_slice_1_2.s, assign_slice_1_2_s = assign_slice_1_2_s === void 0 ? "nope" : assign_slice_1_2_s, d = assign_slice_1_2_s[0]));
 			console.log(a, b, c, d);
 		`
 	},
@@ -511,6 +513,7 @@ module.exports = [
 			[x, y] = [1, 2];`,
 		output: `
 			var assign;
+
 			(assign = [1, 2], x = assign[0], y = assign[1]);`
 	},
 
@@ -521,6 +524,7 @@ module.exports = [
 			[x = 4, y] = [1, 2];`,
 		output: `
 			var assign;
+
 			(assign = [1, 2], x = assign[0], x = x === void 0 ? 4 : x, y = assign[1]);`
 	},
 
@@ -530,6 +534,7 @@ module.exports = [
 			[[x], y] = [1, 2];`,
 		output: `
 			var assign;
+
 			(assign = [1, 2], x = assign[0][0], y = assign[1]);`
 	},
 
@@ -539,8 +544,9 @@ module.exports = [
 		input: `
 			[[x, z], y] = [1, 2];`,
 		output: `
-			var assign, array;
-			(assign = [1, 2], array = assign[0], x = array[0], z = array[1], y = assign[1]);`
+			var assign, assign_0;
+
+			(assign = [1, 2], assign_0 = assign[0], x = assign_0[0], z = assign_0[1], y = assign[1]);`
 	},
 
 	{
@@ -549,8 +555,9 @@ module.exports = [
 		input: `
 			[[x] = [], y] = [1, 2];`,
 		output: `
-			var assign, temp;
-			(assign = [1, 2], temp = assign[0], temp = temp === void 0 ? [] : temp, x = temp[0], y = assign[1]);`
+			var assign, assign_0;
+
+			(assign = [1, 2], assign_0 = assign[0], assign_0 = assign_0 === void 0 ? [] : assign_0, x = assign_0[0], y = assign[1]);`
 	},
 
 	{
@@ -559,6 +566,7 @@ module.exports = [
 			[x, y.z] = [1, 2];`,
 		output: `
 			var assign;
+
 			(assign = [1, 2], x = assign[0], y.z = assign[1]);`
 	},
 
@@ -567,8 +575,9 @@ module.exports = [
 		input: `
 			[x, y.z = 3] = [1, 2];`,
 		output: `
-			var assign, temp;
-			(assign = [1, 2], x = assign[0], temp = assign[1], temp = temp === void 0 ? 3 : temp, y.z = temp);`
+			var assign, assign_1;
+
+			(assign = [1, 2], x = assign[0], assign_1 = assign[1], assign_1 = assign_1 === void 0 ? 3 : assign_1, y.z = assign_1);`
 	},
 
 	{
@@ -577,6 +586,7 @@ module.exports = [
 			({x, y} = {x: 1});`,
 		output: `
 			var assign;
+
 			((assign = {x: 1}, x = assign.x, y = assign.y));`
 	},
 
@@ -587,6 +597,7 @@ module.exports = [
 			({x, y: z} = {x: 1});`,
 		output: `
 			var assign;
+
 			((assign = {x: 1}, x = assign.x, z = assign.y));`
 	},
 
@@ -596,6 +607,7 @@ module.exports = [
 			({x, y: {z}} = {x: 1});`,
 		output: `
 			var assign;
+
 			((assign = {x: 1}, x = assign.x, z = assign.y.z));`
 	},
 
@@ -606,6 +618,7 @@ module.exports = [
 			({x, y = 4} = {x: 1});`,
 		output: `
 			var assign;
+
 			((assign = {x: 1}, x = assign.x, y = assign.y, y = y === void 0 ? 4 : y));`
 	},
 
@@ -614,8 +627,9 @@ module.exports = [
 		input: `
 			({x, y: {z, q}} = {x: 1});`,
 		output: `
-			var assign, obj;
-			((assign = {x: 1}, x = assign.x, obj = assign.y, z = obj.z, q = obj.q));`
+			var assign, assign_y;
+
+			((assign = {x: 1}, x = assign.x, assign_y = assign.y, z = assign_y.z, q = assign_y.q));`
 	},
 
 	{
@@ -624,6 +638,7 @@ module.exports = [
 			({x, y: {z}} = {x: 1});`,
 		output: `
 			var assign;
+
 			((assign = {x: 1}, x = assign.x, z = assign.y.z));`
 	},
 
@@ -635,8 +650,9 @@ module.exports = [
 				baz();
 			}`,
 		output: `
-			foo();
 			var assign;
+
+			foo();
 			if ( bar((assign = [1, 2], x = assign[0], y = assign[1], assign)) ) {
 				baz();
 			}`
@@ -651,6 +667,7 @@ module.exports = [
 		output: `
 			function foo() {
 				var assign;
+
 				(assign = [1, 2], x = assign[0], y = assign[1]);
 			}`
 	},
@@ -728,15 +745,17 @@ module.exports = [
 			console.log( [ a, b ] = c );
 		`,
 		output: `
+			var assign;
+
 			var Point = function Point () {};
 
 			Point.prototype.set = function set ( array ) {
-				var assign;
-					return (assign = array, this.x = assign[0], this.y = assign[1], assign);
+					var assign;
+
+				return (assign = array, this.x = assign[0], this.y = assign[1], assign);
 			};
 
 			var a, b, c = [ 1, 2, 3 ];
-			var assign;
 			console.log( (assign = c, a = assign[0], b = assign[1], assign) );
 		`
 	},
@@ -755,15 +774,17 @@ module.exports = [
 			[ a, b ] = c;
 		`,
 		output: `
+			var assign;
+
 			var Point = function Point () {};
 
 			Point.prototype.set = function set ( array ) {
-				var assign;
-					(assign = array, this.x = assign[0], this.y = assign[1]);
+					var assign;
+
+				(assign = array, this.x = assign[0], this.y = assign[1]);
 			};
 
 			var a, b, c = [ 1, 2, 3 ];
-			var assign;
 			(assign = c, a = assign[0], b = assign[1]);
 		`
 	},
@@ -782,5 +803,78 @@ module.exports = [
 			var a = ref.a;
 			var b = ref.b;
 		`
+	},
+
+	{
+		description: 'destructures within block scope',
+
+		input: `
+			if (true) {
+				let [[a, b]] = [[1, 2]];
+			}
+		`,
+
+		output: `
+			if (true) {
+				var ref = [[1, 2]];
+				var ref_0 = ref[0];
+				var a = ref_0[0];
+				var b = ref_0[1];
+			}
+		`
+	},
+
+	{
+		description: 'destructures rewritten block scope variables',
+
+		input: `
+			let x;
+			if (maybe) {
+				let x;
+				({ x } = { x: 3 });
+				[ x ] = [ 3 ];
+			}`,
+
+		output: `
+			var assign, assign$1;
+
+			var x;
+			if (maybe) {
+				var x$1;
+				((assign = { x: 3 }, x$1 = assign.x));
+				(assign$1 = [ 3 ], x$1 = assign$1[0]);
+			}`
+	},
+
+	{
+		description: 'destructures try catch parameters',
+
+		input: `
+			try {} catch ({message}) {
+			}`,
+
+		output: `
+			try {} catch (ref) {
+				var message = ref.message;
+
+			}`
+	},
+
+	{
+		description: 'destructures parameters with same name as function',
+
+		input: `
+			const a = {
+				options (options) {
+					const { input } = options;
+				}
+			}`,
+
+		output: `
+			var a = {
+				options: function options (options$1) {
+					var input = options$1.input;
+				}
+			}`
 	}
 ];
diff --git a/test/samples/dynamic-import.js b/test/samples/dynamic-import.js
new file mode 100644
index 0000000..5d4ec8c
--- /dev/null
+++ b/test/samples/dynamic-import.js
@@ -0,0 +1,8 @@
+module.exports = [
+	{
+		description: 'support dynamic import',
+		input: `import('./module.js')`,
+		output: `import('./module.js')`
+	}
+
+];
diff --git a/test/samples/exponentiation-operator.js b/test/samples/exponentiation-operator.js
index 813ca0d..7e75853 100644
--- a/test/samples/exponentiation-operator.js
+++ b/test/samples/exponentiation-operator.js
@@ -59,7 +59,9 @@ module.exports = [
 			foo.bar.baz **= y;`,
 
 		output: `
-			var object = foo.bar;
+			var object;
+
+			object = foo.bar;
 			object.baz = Math.pow( object.baz, y );`
 	},
 
@@ -82,7 +84,9 @@ module.exports = [
 			foo[ bar() ] **= y;`,
 
 		output: `
-			var property = bar();
+			var property;
+
+			property = bar();
 			foo[property] = Math.pow( foo[property], y );`
 	},
 
@@ -94,8 +98,10 @@ module.exports = [
 			foo[ bar() ][ baz() ] **= y;`,
 
 		output: `
-			var object = foo[ bar() ];
-			var property = baz();
+			var property, object;
+
+			object = foo[ bar() ];
+			property = baz();
 			object[property] = Math.pow( object[property], y );`
 	},
 
@@ -107,7 +113,8 @@ module.exports = [
 			var baz = 1, lolwut = foo[ bar() ][ baz * 2 ] **= y;`,
 
 		output: `
-			var object, property;
+			var property, object;
+
 			var baz = 1, lolwut = ( object = foo[ bar() ], property = baz * 2, object[property] = Math.pow( object[property], y ) );`
 	},
 
@@ -120,6 +127,7 @@ module.exports = [
 
 		output: `
 			var property;
+
 			var baz = 1, lolwut = ( property = bar(), foo[property] = Math.pow( foo[property], y ) );`
 	},
 
@@ -171,6 +179,7 @@ module.exports = [
 		`,
 		output: `
 			var property;
+
 			x=( property = bar(), a[property]=Math.pow( a[property], 2 ) );
 		`
 	}
diff --git a/test/samples/for-of.js b/test/samples/for-of.js
index ec9b643..2f32cd2 100644
--- a/test/samples/for-of.js
+++ b/test/samples/for-of.js
@@ -223,5 +223,51 @@ module.exports = [
 
 				console.log(x, y);
 			}`
+	},
+
+	{
+		description: 'destructures assignment in forOf loop',
+		options: { transforms: { dangerousForOf: true } },
+
+		input: `
+			var x, y;
+			for ({x, y} of [{x: 1, y: 2}]) {
+				console.log(x, y);
+			}
+		`,
+
+		output: `
+			var x, y;
+			for (var i = 0, list = [{x: 1, y: 2}]; i < list.length; i += 1) {
+				var ref = list[i];
+				x = ref.x;
+				y = ref.y;
+
+				console.log(x, y);
+			}
+		`
+	},
+
+	{
+		description: 'destructures assignment in forOf loop with array pattern',
+		options: { transforms: { dangerousForOf: true } },
+
+		input: `
+			var x, y;
+			for ([x, y] of [[1, 2]]) {
+				console.log(x, y);
+			}
+		`,
+
+		output: `
+			var x, y;
+			for (var i = 0, list = [[1, 2]]; i < list.length; i += 1) {
+				var ref = list[i];
+				x = ref[0];
+				y = ref[1];
+
+				console.log(x, y);
+			}
+		`
 	}
 ];
diff --git a/test/samples/jsx.js b/test/samples/jsx.js
index da5b146..e23f91e 100644
--- a/test/samples/jsx.js
+++ b/test/samples/jsx.js
@@ -156,6 +156,12 @@ module.exports = [
 	},
 
 	{
+		description: 'transpiles JSX fragments',
+		input: `var divs = <><div contentEditable /><div /></>;`,
+		output: `var divs = React.createElement( React.Fragment, null, React.createElement( 'div', { contentEditable: true }), React.createElement( 'div', null ) );`
+	},
+
+	{
 		description: 'transpiles one JSX spread attributes',
 		input: `var element = <div {...props} />;`,
 		output: `var element = React.createElement( 'div', props);`
@@ -287,5 +293,19 @@ module.exports = [
 			React.createElement( 'div', null,
 				React.createElement( 'a', null, "1" ), "   ")
 		`
+	},
+
+	{
+		description: 'transpiles entities',
+
+		input: `
+			<div>
+				<a>1<</a> 
+			</div>
+		`,
+		output: `
+			React.createElement( 'div', null,
+				React.createElement( 'a', null, "1<" ), " ")
+		`
 	}
 ];
diff --git a/test/samples/loops.js b/test/samples/loops.js
index 7f96945..c93a939 100644
--- a/test/samples/loops.js
+++ b/test/samples/loops.js
@@ -543,7 +543,67 @@ module.exports = [
 				return { start: 10, end: 20 };
 			}
 
-			for ( var ref = range(), i = ref.start, end = ref.end === undefined ? 100 : ref.end; i < end; i += 1 ) {
+			for ( var ref = range(), i = ref.start, end = ref.end, end = end === void 0 ? 100 : end; i < end; i += 1 ) {
+				console.log( i );
+			}`
+	},
+
+	{
+		description:
+			'nested destructuring in variable declaration in for loop head',
+
+		input: `
+			for ( var { start: { a, b } } = range(); i < end; i += 1 ) {
+				console.log( i );
+			}`,
+
+		output: `
+			for ( var ref = range(), ref_start = ref.start, a = ref_start.a, b = ref_start.b; i < end; i += 1 ) {
+				console.log( i );
+			}`
+	},
+
+	{
+		description:
+			'nested array destructuring in variable declaration in for loop head',
+
+		input: `
+			for ( var [[x, z], y] = [1, 2]; i < end; i += 1 ) {
+				console.log( i );
+			}`,
+
+		output: `
+			for ( var ref = [1, 2], ref_0 = ref[0], x = ref_0[0], z = ref_0[1], y = ref[1]; i < end; i += 1 ) {
+				console.log( i );
+			}`
+	},
+
+	{
+		description:
+			'array destructuring with default value in variable declaration in for loop head',
+
+		input: `
+			for ( var [x, y = 4, z] = [1, 2, 3]; i < end; i += 1 ) {
+				console.log( i );
+			}`,
+
+		output: `
+			for ( var ref = [1, 2, 3], x = ref[0], y = ref[1], y = y === void 0 ? 4 : y, z = ref[2]; i < end; i += 1 ) {
+				console.log( i );
+			}`
+	},
+
+	{
+		description:
+			'object destructuring with default value in variable declaration in for loop head',
+
+		input: `
+			for ( var {x, y = 4, z} = {}; i < end; i += 1 ) {
+				console.log( i );
+			}`,
+
+		output: `
+			for ( var ref = {}, x = ref.x, y = ref.y, y = y === void 0 ? 4 : y, z = ref.z; i < end; i += 1 ) {
 				console.log( i );
 			}`
 	},
@@ -769,5 +829,31 @@ module.exports = [
 			};
 			new Foo().do();
 		`
+	},
+
+	{
+		description: 'transpiles destructuring in for-in loop heads',
+
+		input: `for (var [a, b] in []) {}`,
+
+		output: `for (var ref in []) {var a = ref[0];
+	var b = ref[1];
+
+	}`
+	},
+
+	{
+		description: 'transpiles destructuring in for-in loop heads',
+
+		input: `
+			for ([a, b = "_"] in [])
+				f(a, b)`,
+
+		output: `
+			for (var ref in [])
+				{ var a = ref[0];
+				var b = ref[1]; if ( b === void 0 ) b = "_";
+
+				f(a, b) }`
 	}
 ];
diff --git a/test/samples/object-properties.js b/test/samples/object-properties.js
index c43427f..a72a497 100644
--- a/test/samples/object-properties.js
+++ b/test/samples/object-properties.js
@@ -114,8 +114,20 @@ module.exports = [
 	},
 
 	{
-		description: 'avoids shadowing free variables with method names (#166)',
+		description: 'transpiles string-keyed properties after computed properties',
+
+		input: `
+			fn({['computed']:1, 'some-var':2, a: 3});
+		`,
+		output: `
+			var obj;
 
+			fn(( obj = {}, obj['computed'] = 1, obj['some-var'] = 2, obj.a = 3, obj ));
+		`
+	},
+
+	{
+		description: 'avoids shadowing free variables with method names (#166)',
 		input: `
 			let x = {
 				foo() { return foo },
diff --git a/test/samples/object-rest-spread.js b/test/samples/object-rest-spread.js
index 603a1f9..401cefe 100644
--- a/test/samples/object-rest-spread.js
+++ b/test/samples/object-rest-spread.js
@@ -160,28 +160,59 @@ module.exports = [
 	{
 		description: 'transpiles rest properties',
 		input: `var {a, ...b} = c`,
-		output: `var a = c.a;
-var rest = {}; for (var n in c) if(["a"].indexOf(n) === -1) rest[n] = c[n];
+		output: `function objectWithoutProperties (obj, exclude) { var target = {}; for (var k in obj) if (Object.prototype.hasOwnProperty.call(obj, k) && exclude.indexOf(k) === -1) target[k] = obj[k]; return target; }
+var a = c.a;
+var rest = objectWithoutProperties( c, ["a"] );
 var b = rest;`
 	},
 
 	{
+		description: 'transpiles rest properties in assignments',
+		input: `({a, ...b} = c);`,
+		output: `function objectWithoutProperties (obj, exclude) { var target = {}; for (var k in obj) if (Object.prototype.hasOwnProperty.call(obj, k) && exclude.indexOf(k) === -1) target[k] = obj[k]; return target; }
+
+var assign, rest;
+((assign = c, a = assign.a, rest = objectWithoutProperties( assign, ["a"] ), b = rest));`
+	},
+
+	{
 		description: 'transpiles rest properties in arguments',
-		input: `(function({x, ...y}) {})`,
-		output: `(function(ref) {
-	var x = ref.x;
-	var rest = {}; for (var n in ref) if(["x"].indexOf(n) === -1) rest[n] = ref[n];
-	var y = rest;
-})`
+		input: `
+			"use strict";
+			function objectWithoutProperties({x, ...y}) {}`,
+		output: `
+			"use strict";
+			function objectWithoutProperties$1 (obj, exclude) { var target = {}; for (var k in obj) if (Object.prototype.hasOwnProperty.call(obj, k) && exclude.indexOf(k) === -1) target[k] = obj[k]; return target; }
+function objectWithoutProperties(ref) {
+				var x = ref.x;
+				var rest = objectWithoutProperties$1( ref, ["x"] );
+				var y = rest;
+}`
 	},
 
 	{
 		description: 'transpiles rest properties in arrow function arguments',
 		input: `(({x, ...y}) => {})`,
-		output: `(function (ref) {
+		output: `function objectWithoutProperties (obj, exclude) { var target = {}; for (var k in obj) if (Object.prototype.hasOwnProperty.call(obj, k) && exclude.indexOf(k) === -1) target[k] = obj[k]; return target; }
+(function (ref) {
 	var x = ref.x;
-	var rest = {}; for (var n in ref) if(["x"].indexOf(n) === -1) rest[n] = ref[n];
+	var rest = objectWithoutProperties( ref, ["x"] );
 	var y = rest;
 })`
+	},
+
+	{
+	description: 'transpiles rest properties in for loop heads',
+	input: `for( var {a, ...b} = c;; ) {}`,
+	output: `function objectWithoutProperties (obj, exclude) { var target = {}; for (var k in obj) if (Object.prototype.hasOwnProperty.call(obj, k) && exclude.indexOf(k) === -1) target[k] = obj[k]; return target; }
+for( var a = c.a, rest = objectWithoutProperties( c, ["a"] ), b = rest;; ) {}`
+	},
+
+	{
+	description: 'transpiles trivial rest properties in for loop heads',
+	input: `for( var {...b} = c;; ) {}`,
+	output: `function objectWithoutProperties (obj, exclude) { var target = {}; for (var k in obj) if (Object.prototype.hasOwnProperty.call(obj, k) && exclude.indexOf(k) === -1) target[k] = obj[k]; return target; }
+for( var rest = objectWithoutProperties( c, [] ), b = rest;; ) {}`
 	}
+
 ];
diff --git a/test/samples/spread-operator.js b/test/samples/spread-operator.js
index d831eea..6cda801 100644
--- a/test/samples/spread-operator.js
+++ b/test/samples/spread-operator.js
@@ -38,8 +38,9 @@ module.exports = [
 			( foo || bar ).baz( ...values );`,
 
 		output: `
-			(ref = ( foo || bar )).baz.apply( ref, values );
-			var ref;`
+			var ref;
+
+			(ref = ( foo || bar )).baz.apply( ref, values );`
 	},
 
 	{
@@ -51,8 +52,9 @@ module.exports = [
 			}`,
 		output: `
 			function a( args ) {
-				return (ref = this).go.apply( ref, args );
 				var ref;
+
+				return (ref = this).go.apply( ref, args );
 			}`
 	},
 
@@ -84,16 +86,18 @@ module.exports = [
 				while ( len-- ) args[ len ] = arguments[ len ];
 
 				return Domain.run(function () {
-					return (ref = this$1).go.apply(ref, args);
 					var ref;
+
+					return (ref = this$1).go.apply(ref, args);
 				});
 			}
 			function bar(args) {
 				var this$1 = this;
 
 				return Domain.run(function () {
-					return (ref = this$1).go.apply(ref, args);
 					var ref;
+
+					return (ref = this$1).go.apply(ref, args);
 				});
 			}
 			function baz() {
@@ -101,8 +105,9 @@ module.exports = [
 				var this$1 = this;
 
 				return Domain.run(function () {
-					return (ref = this$1).go.apply(ref, arguments$1);
 					var ref;
+
+					return (ref = this$1).go.apply(ref, arguments$1);
 				});
 			}
 		`
@@ -153,7 +158,7 @@ module.exports = [
 				while ( i-- ) argsArray[i] = arguments[i];
 
 				return Domain.run(function () {
-					return new (Function.prototype.bind.apply( this$1.Test, [ null ].concat( arguments$1) ));
+					return new (Function.prototype.bind.apply( this$1.Test, [ null ].concat( argsArray) ));
 				});
 			}
 		`
@@ -170,11 +175,12 @@ module.exports = [
 			process( result );`,
 
 		output: `
+			var ref$1;
+
 			var result;
 			if ( ref )
 				{ result = (ref$1 = expr()).baz.apply( ref$1, values ); }
-			process( result );
-			var ref$1;`
+			process( result );`
 	},
 
 	{
@@ -190,12 +196,12 @@ module.exports = [
 			}`,
 		output: `
 			function foo() {
+				var ref$1, ref$2;
+
 				stuff();
 				if ( ref )
 					{ return (ref$1 = expr()).baz.apply( ref$1, values ); }
 				return (ref$2 = (up || down)).bar.apply( ref$2, values );
-				var ref$1;
-				var ref$2;
 			}`
 	},
 
@@ -211,12 +217,12 @@ module.exports = [
 			}`,
 		output: `
 			function ref() {
+				var ref, ref$2;
+
 				stuff();
 				if ( ref$1 )
 					{ return (ref = expr()).baz.apply( ref, [ a ].concat( values, [(ref$2 = (up || down)).bar.apply( ref$2, [ c ].concat( values, [d] ) )] ) ); }
 				return other();
-				var ref;
-				var ref$2;
 			}`
 	},
 
@@ -243,9 +249,9 @@ module.exports = [
 				prepare: function prepare() {
 					var i = arguments.length, argsArray = Array(i);
 					while ( i-- ) argsArray[i] = arguments[i];
+					var ref;
 
 					return (ref = this.add).bind.apply(ref, [ this ].concat( argsArray ))
-					var ref;
 				}
 			}`
 	},
@@ -526,8 +532,11 @@ module.exports = [
 		output: `
 			function foo (x) {
 				if ( x )
-					{ return function (ref) { return (ref$1 = (bar || baz)).Test.apply( ref$1, [ ref ].concat( x ) )
-						var ref$1;; }; }
+					{ return function (ref) {
+						var ref$1;
+
+						return (ref$1 = (bar || baz)).Test.apply( ref$1, [ ref ].concat( x ) );
+						}; }
 			}
 		`
 	},
@@ -548,7 +557,7 @@ module.exports = [
 				while ( i-- ) argsArray[i] = arguments[i];
 
 				if ( x )
-					{ return function (ref) { return new (Function.prototype.bind.apply( (bar || baz).Test, [ null ].concat( [ref], arguments$1 ) )); }; }
+					{ return function (ref) { return new (Function.prototype.bind.apply( (bar || baz).Test, [ null ].concat( [ref], argsArray ) )); }; }
 			}
 		`
 	},
@@ -569,9 +578,44 @@ module.exports = [
 				while ( i-- ) argsArray[i] = arguments[i];
 
 				if ( x )
-					{ return function (ref) { return (ref$1 = (bar || baz)).Test.apply( ref$1, [ ref ].concat( arguments$1 ) )
-						var ref$1;; }; }
+					{ return function (ref) {
+						var ref$1;
+
+						return (ref$1 = (bar || baz)).Test.apply( ref$1, [ ref ].concat( arguments$1 ) );
+						}; }
 			}
 		`
+	},
+
+	{
+		description: 'transpiles spread with template literal afterwards',
+
+		input: `
+			[...f(b), "n"];
+			[...f(b), 'n'];
+			[...f(b), \`n\`];
+		`,
+
+		output: `
+			f(b).concat( ["n"]);
+			f(b).concat( ['n']);
+			f(b).concat( ["n"]);
+		`
+	},
+
+	{
+		description: 'transpiles spread with arrow function afterwards',
+
+		input: `[...A, () => 'B']`,
+
+		output: `A.concat( [function () { return 'B'; }])`
+	},
+
+	{
+		description: 'transpiles spread in new with arrow function afterwards',
+
+		input: `new X(...A, () => 'B')`,
+
+		output: `new (Function.prototype.bind.apply( X, [ null ].concat( A, [function () { return 'B'; }]) ))`
 	}
 ];
diff --git a/test/samples/template-strings.js b/test/samples/template-strings.js
index 6b69b50..5a65ef6 100644
--- a/test/samples/template-strings.js
+++ b/test/samples/template-strings.js
@@ -41,7 +41,7 @@ module.exports = [
 			'transpiles tagged template literals with `transforms.dangerousTaggedTemplateString = true`',
 		options: { transforms: { dangerousTaggedTemplateString: true } },
 		input: 'var str = x`y${(() => 42)()}`;',
-		output: `var str = x(["y", ""], (function () { return 42; })());`
+		output: `var templateObject = Object.freeze(["y", ""]);\nvar str = x(templateObject, (function () { return 42; })());`
 	},
 
 	{
@@ -49,7 +49,21 @@ module.exports = [
 			'transpiles tagged template literals with `transforms.dangerousTaggedTemplateString = true`',
 		options: { transforms: { dangerousTaggedTemplateString: true } },
 		input: 'var str = x`${(() => 42)()}y`;',
-		output: `var str = x(["", "y"], (function () { return 42; })());`
+		output: `var templateObject = Object.freeze(["", "y"]);\nvar str = x(templateObject, (function () { return 42; })());`
+	},
+
+	{
+		description: 'reuses quasi array for identical tagged template strings',
+		options: { transforms: { dangerousTaggedTemplateString: true } },
+		input: 'x`a${a}b`, x`a${b}b`, x`b${c}a`',
+		output: `var templateObject$1 = Object.freeze(["b", "a"]);\nvar templateObject = Object.freeze(["a", "b"]);\nx(templateObject, a), x(templateObject, b), x(templateObject$1, c)`
+	},
+
+	{
+		description: 'reuses quasi array for identical tagged template strings in strict mode',
+		options: { transforms: { dangerousTaggedTemplateString: true } },
+		input: '"use strict";\nx`a${a}b`, x`a${b}b`, x`b${c}a`',
+		output: `"use strict";\nvar templateObject$1 = Object.freeze(["b", "a"]);\nvar templateObject = Object.freeze(["a", "b"]);\nx(templateObject, a), x(templateObject, b), x(templateObject$1, c)`
 	},
 
 	{
diff --git a/test/samples/trailing-function-commas.js b/test/samples/trailing-function-commas.js
index 67cc793..76731de 100644
--- a/test/samples/trailing-function-commas.js
+++ b/test/samples/trailing-function-commas.js
@@ -64,5 +64,35 @@ module.exports = [
 				var b = ref[0];
 				var c = ref$1.c;
 })`
-	}
+	},
+
+	{
+		description: 'strips trailing commas in new expression arguments',
+
+		input: `
+			new f(a,)`,
+
+		output: `
+			new f(a)`
+	},
+
+	{
+		description: 'keeps commas in trailing comments in normal function declaration arguments',
+
+		input: `
+			function f(a/*,*/) {}`,
+
+		output: `
+			function f(a/*,*/) {}`
+	},
+
+	{
+		description: 'strips trailing commas after comments in normal function declaration arguments',
+
+		input: `
+			function f(a/*a*/,) {}`,
+
+		output: `
+			function f(a/*a*/) {}`
+	},
 ];
diff --git a/test/test.js b/test/test.js
index 0c91a14..64f0af3 100644
--- a/test/test.js
+++ b/test/test.js
@@ -6,7 +6,7 @@ var assert = require('assert');
 var glob = require('glob');
 var SourceMapConsumer = require('source-map').SourceMapConsumer;
 var getLocation = require('./utils/getLocation.js');
-var buble = require('../dist/buble.umd.js');
+var buble = require('..');
 
 require('source-map-support').install();
 require('console-group').install();
@@ -157,11 +157,11 @@ describe('buble', () => {
 				assert.equal(err.message, 'x is read-only (1:13)');
 				assert.equal(
 					err.snippet,
-					`1 : const x = 1; x++;\n                 ^^^`
+					`1 : const x = 1; x++;\n                 ^`
 				);
 				assert.equal(
 					err.toString(),
-					`CompileError: x is read-only (1:13)\n1 : const x = 1; x++;\n                 ^^^`
+					`CompileError: x is read-only (1:13)\n1 : const x = 1; x++;\n                 ^`
 				);
 			}
 		});
@@ -193,7 +193,7 @@ describe('buble', () => {
 			assert.equal(
 				result,
 				`
-				const power = ( base, exponent ) => {
+				var power = ( base, exponent ) => {
 					if ( exponent === void 0 ) exponent = 2;
 
 					return Math.pow( base, exponent );

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-javascript/node-buble.git



More information about the Pkg-javascript-commits mailing list