diff --git a/.eslintignore b/.eslintignore index 1954cc29ef41..5ea6066c6040 100644 --- a/.eslintignore +++ b/.eslintignore @@ -1,9 +1,11 @@ -packages/babel-core/src/transformation/templates +/lib scripts -lib +packages/babel-core/src/transformation/templates packages/babel-runtime packages/*/node_modules +packages/*/lib packages/*/dist +packages/*/test/fixtures vendor _babel.github.io Gulpfile.js diff --git a/.github/ISSUE_TEMPLATE.md b/.github/ISSUE_TEMPLATE.md index 3bdbe759bf7b..1ae98155f179 100644 --- a/.github/ISSUE_TEMPLATE.md +++ b/.github/ISSUE_TEMPLATE.md @@ -1,6 +1,8 @@ + ```js var your => (code) => here; diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index 4d7a1e8be339..798216b16336 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -1,18 +1,21 @@ - -| Q | A -| ----------------- | --- -| Bug fix? | yes/no -| Breaking change? | yes/no -| New feature? | yes/no -| Deprecations? | yes/no -| Spec compliancy? | yes/no -| Tests added/pass? | yes/no -| Fixed tickets | comma-separated list of tickets fixed by the PR, if any -| License | MIT -| Doc PR | reference to the documentation PR, if any +| Q | A +| ------------------------ | --- +| Patch: Bug Fix? | +| Major: Breaking Change? | +| Minor: New Feature? | +| Deprecations? | +| Spec Compliancy? | +| Tests Added/Pass? | +| Fixed Tickets | `Fixes #1, Fixes #2` +| License | MIT +| Doc PR | +| Dependency Changes | diff --git a/.gitignore b/.gitignore index fa0fb139841d..7e25e4ad0589 100644 --- a/.gitignore +++ b/.gitignore @@ -16,3 +16,4 @@ dist /packages/*/lib _babel.github.io /tests/.browser-build.js +.nyc_output diff --git a/.istanbul.yml b/.istanbul.yml deleted file mode 100644 index 6489c5aeff0e..000000000000 --- a/.istanbul.yml +++ /dev/null @@ -1,5 +0,0 @@ -instrumentation: - root: . - excludes: - - "**/node_modules/**" - - "scripts/*.js" diff --git a/CHANGELOG.md b/CHANGELOG.md index 66f2a812cc8c..4a6c18faa2d2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,6 +13,447 @@ _Note: Gaps between patch versions are faulty, broken or test releases._ See [CHANGELOG - 6to5](CHANGELOG-6to5.md) for the pre-4.0.0 version changelog. +## v6.20.3 (2016-12-08) + +#### :cry: Regression + +* `babel-plugin-transform-async-to-generator` + * [#4978](https://github.com/babel/babel/pull/4978) Calculate the correct arity for async functions with destructuring. (fixes [#4977](https://github.com/babel/babel/issues/4977)) ([@loganfsmyth](https://github.com/loganfsmyth)) + +## v6.20.2 (2016-12-08) + +#### :cry: Regression + +Issue: https://github.com/babel/babel/issues/4972 again. Fixed by reverting part of the original PR in [babel/babel#4883](https://github.com/babel/babel/pull/4883). + +## v6.20.1 (2016-12-08) + +#### :cry: Regression + +Issue: https://github.com/babel/babel/issues/4972 + +The way that [babel/babel#4883](https://github.com/babel/babel/pull/4883) changed visiting SpreadProperty (which didn't need to modified) caused an infinite loop. Added `path.stop` which ended up not fixing it correctly. + +## v6.20.0 (2016-12-08) + +> If you missed it, please check out our latest blog post: [The State of Babel](http://babeljs.io/blog/2016/12/07/the-state-of-babel). Talks about where we can possibly move forward as a project and how you can help! + +- Maybe fix that crazy babel-generator deopt message you've all probably seen! +- Change to `babel-code-frame` for [facebookincubator/create-react-app#1101](https://github.com/facebookincubator/create-react-app/issues/1101) +- Change to `babel-generator` for [webpack/webpack#3413](https://github.com/webpack/webpack/pull/3413) +- Move implementation of Regenerator back to the original repo. + +--- + +You've probably seen this more than a few times and had no idea what it meant... + +``` +[BABEL] Note: The code generator has deoptimised the styling of "app.js" as it exceeds the max of "100KB". +``` + +Generating code used to get really slow as file size increased. We've mostly fixed that, but we still automatically fall back to compact output on large files. We're going to bump the limit to 500KB and if there aren't issues just remove it. + +--- + +[Ben Newman, @benjamn](https://github.com/benjamn): wrote [Regenerator](https://github.com/facebook/regenerator) while at Facebook. It used a bunch of other libraries such as `ast-types` but has now been rewritten as a standalone **Babel plugin** (also thanks to [Sebastian's](https://github.com/kittens) previous work in [facebook/regenerator#222](https://github.com/facebook/regenerator/pull/222)). We're also moving the implementation of Regenerator back into the original repository since Ben is the creator/maintainer. + +#### :rocket: New Feature +* `babel-traverse` + * [#4876](https://github.com/babel/babel/pull/4876) Add `getBindingIdentifierPaths`/`getOuterBindingIdentifierPaths`. ([@boopathi](https://github.com/boopathi)) + +Returns `Array` rather than `Array`. + +- `path.getBindingIdentifierPaths()` +- `path.getOuterBindingIdentifierPaths()` + +```js +traverse(parse(` + var a = 1, {b} = c, [d] = e, function f() {}; +`), { + VariableDeclaration(path) { + let nodes = path.getBindingIdentifiers(); // a, d, b + let paths = path.getBindingIdentifierPaths(); + }, + FunctionDeclaration(path) { + let outerNodes = path.getOuterBindingIdentifiers(); // f + let outerPaths = path.getOuterBindingIdentifierPaths(); + } +}); +``` + +* `babel-code-frame` + * [#4913](https://github.com/babel/babel/pull/4913) Add `forceColor` option to `babel-code-frame`. ([@Timer](https://github.com/Timer)) + +> Forcibly syntax highlight the code as JavaScript (for non-terminals); overrides `highlightCode`. For [facebookincubator/create-react-app#1101](https://github.com/facebookincubator/create-react-app/issues/1101) + +Usage + +```js +const result = codeFrame(rawLines, lineNumber, colNumber, { + forceColor: true +}); +``` + +#### :bug: Bug Fix +* `babel-plugin-transform-es2015-block-scoping` + * [#4880](https://github.com/babel/babel/pull/4880) Add (and fix) failing test of function parameter bindings in a catch block. ([@benjamn](https://github.com/benjamn)) + +**In** + +```js +try { + foo(); +} catch (x) { + function harmless(x) { + return x; + } +} +``` + +**Correct Out** + +```js +try { + foo(); +} catch (x) { + var harmless = function (x) { + return x; + }; +} +``` + +* `babel-helper-remap-async-to-generator`, `babel-plugin-transform-async-generator-functions`, `babel-plugin-transform-async-to-generator` + * [#4901](https://github.com/babel/babel/pull/4901) Only base async fn arity on non-default/non-rest params - Closes [#4891](https://github.com/babel/babel/issues/4891). ([@loganfsmyth](https://github.com/loganfsmyth)) + +```js +// both length's should be 0 +const foo = (...args) => { } +console.log(foo.length) // 0 +const asyncFoo = async (...args) => { } +console.log(asyncFoo.length) // 0 +``` + +* `babel-generator`, `babel-types` + * [#4945](https://github.com/babel/babel/pull/4945) Add `babel-generator` support for `Import`. ([@TheLarkInn](https://github.com/TheLarkInn)) + +> Relevant for webpack 2 support of `Import`. Just allows Babel to print it correctly. + +```js +import("module.js"); +``` + +* `babel-plugin-transform-object-rest-spread` + * [#4883](https://github.com/babel/babel/pull/4883) Fix for object-rest with parameters destructuring nested rest. ([@christophehurpeau](https://github.com/christophehurpeau)) + +```js +function a5({a3, b2: { ba1, ...ba2 }, ...c3}) {} +``` + +* `babel-traverse` + * [#4875](https://github.com/babel/babel/pull/4875) Fix `path.evaluate` for references before declarations. ([@boopathi](https://github.com/boopathi)) + +```js +// should deopt if ids are referenced before the bindings +var a = b + 2; var b = 2 + 2; +``` + +* `babel-core`, `babel-generator`, `babel-helper-transform-fixture-test-runner`, `babel-plugin-transform-object-rest-spread` + * [#4858](https://github.com/babel/babel/pull/4858) Fix bug + Generate test fixtures if no expected.js. ([@hzoo](https://github.com/hzoo)) +* `babel-types` + * [#4853](https://github.com/babel/babel/pull/4853) Preserve null in `babel-types` `t.clone` and `t.deepClone` ([@NTillmann](https://github.com/NTillmann)) + +#### :nail_care: Polish +* `babel-generator` + * [#4862](https://github.com/babel/babel/pull/4862) Fix identation with empty leading `ObjectTypeProperty`. ([@existentialism](https://github.com/existentialism)) + +#### :memo: Documentation +* `Various Packages` + * [#4938](https://github.com/babel/babel/pull/4938) Update babel-core documentation. ([@xtuc](https://github.com/xtuc)) + * [#4939](https://github.com/babel/babel/pull/4939) Add example to transform-react-display-name docs. ([@existentialism](https://github.com/existentialism)) + * [#4931](https://github.com/babel/babel/pull/4931) Update plugins READMEs from babel.github.io [skip ci]. ([@raspo](https://github.com/raspo)) + * [#4926](https://github.com/babel/babel/pull/4926) Update transform-es2015 READMEs from babel.github.io [skip ci]. ([@existentialism](https://github.com/existentialism)) + * [#4930](https://github.com/babel/babel/pull/4930) Update transform-object-rest-spread's README from babel.github.io [skip ci]. ([@lukyth](https://github.com/lukyth)) + * [#4929](https://github.com/babel/babel/pull/4929) Update transform-object-assign's README from babel.github.io [skip ci]. ([@lukyth](https://github.com/lukyth)) + * [#4928](https://github.com/babel/babel/pull/4928) mention [skip ci] in PR template. ([@hzoo](https://github.com/hzoo)) + * [#4925](https://github.com/babel/babel/pull/4925) Tweak example in transform-jsx-source README [skip ci]. ([@existentialism](https://github.com/existentialism)) + * [#4919](https://github.com/babel/babel/pull/4919) Update async READMEs from babel.github.io [skip-ci]. ([@existentialism](https://github.com/existentialism)) + * [#4917](https://github.com/babel/babel/pull/4917) Fix some React transform README issues [skip-ci]. ([@existentialism](https://github.com/existentialism)) + * [#4903](https://github.com/babel/babel/pull/4903) Update React transform READMEs from babel.github.io [skip ci]. ([@existentialism](https://github.com/existentialism)) + * [#4884](https://github.com/babel/babel/pull/4884) Readme updates from babel.github.io [skip ci]. ([@hzoo](https://github.com/hzoo)) + +#### :house: Internal +* `babel-plugin-transform-regenerator` + * [#4881](https://github.com/babel/babel/pull/4881) Use `regenerator-transform` to implement `babel-plugin-transform-regenerator`. ([@benjamn](https://github.com/benjamn)) +* `babel-traverse` + * [#4934](https://github.com/babel/babel/pull/4934) Hoist `generateDeclaredUidIdentifier` helper function. ([@jridgewell](https://github.com/jridgewell)) +* `babel-polyfill` + * [#4966](https://github.com/babel/babel/pull/4966) update `regenerator-runtime` in `babel-polyfill`. ([@zloirock](https://github.com/zloirock)) +* `babel-runtime` + * [#4877](https://github.com/babel/babel/pull/4877) Upgrade `regenerator-runtime` to version 0.10.0. ([@benjamn](https://github.com/benjamn)) +* `babel-plugin-syntax-trailing-function-commas` + * [#4936](https://github.com/babel/babel/pull/4936) Add `test` to `babel-plugin-syntax-trailing-function-commas` `.npmignore` ([@wtgtybhertgeghgtwtg](https://github.com/wtgtybhertgeghgtwtg)) +* `babel-helper-fixtures` + * [#4907](https://github.com/babel/babel/pull/4907) Remove `shouldIgnore` check. ([@danez](https://github.com/danez)) +* `babel-core`, `babel-traverse` + * [#4897](https://github.com/babel/babel/pull/4897) Fix eslint. ([@danez](https://github.com/danez)) +* `babel-generator` + * [#4965](https://github.com/babel/babel/pull/4965) Raise limit on code size before compacting ([@existentialism](https://github.com/existentialism)) + +#### Committers: 17 +- Ben Newman ([benjamn](https://github.com/benjamn)) +- Benjamin E. Coe ([bcoe](https://github.com/bcoe)) +- Boopathi Rajaa ([boopathi](https://github.com/boopathi)) +- Brian Ng ([existentialism](https://github.com/existentialism)) +- Christophe Hurpeau ([christophehurpeau](https://github.com/christophehurpeau)) +- Daniel Tschinder ([danez](https://github.com/danez)) +- Denis Pushkarev ([zloirock](https://github.com/zloirock)) +- Henry Zhu ([hzoo](https://github.com/hzoo)) +- Joe Haddad ([Timer](https://github.com/Timer)) +- Justin Ridgewell ([jridgewell](https://github.com/jridgewell)) +- Kanitkorn Sujautra ([lukyth](https://github.com/lukyth)) +- Logan Smyth ([loganfsmyth](https://github.com/loganfsmyth)) +- Nikolai Tillmann ([NTillmann](https://github.com/NTillmann)) +- Sean Larkin ([TheLarkInn](https://github.com/TheLarkInn)) +- Sven SAULEAU ([xtuc](https://github.com/xtuc)) +- Tommaso ([raspo](https://github.com/raspo)) +- [wtgtybhertgeghgtwtg](https://github.com/wtgtybhertgeghgtwtg) + +## v6.19.0 (2016-11-16) + +#### :rocket: New Feature +* `babel-plugin-transform-object-rest-spread` + * [#4755](https://github.com/babel/babel/pull/4755) Make the plugin work standalone with parameters/destructuring plugins. ([@hzoo](https://github.com/hzoo)) + +This rewrite fixes a long standing issue where the object-rest-spread plugin was depending on 2 other plugins to compile `RestProperty`. This is important given the assumption that plugins should be independent and is vital for the use of [babel-preset-env](https://github.com/babel/babel-preset-env/) since new environments support destructuring natively. + +*RestProperty* + +- [x] Parameters +``` js +function a({ b, ...c }) {} +``` +- [x] VariableDeclaration +```js +const { a, ...b } = c; +``` +- [x] ExportNamedDeclaration +```js +export var { a, ...b } = c; +``` +- [x] CatchClause +```js +try {} catch ({a, ...b}) {} +``` +- [x] AssignmentExpression +```js +({a, ...b} = c); +``` +- [x] ForXStatement +```js +for ({a, ...b} of []) {} +``` + +*SpreadProperty* + +- [x] ObjectExpression +```js +var a = { ...b, ...c } +``` + +* `babel-plugin-transform-class-properties` + * [#4544](https://github.com/babel/babel/pull/4544) Greater spec compliance for class properties with the new `spec` option. ([@motiz88](https://github.com/motiz88)) + +Usage +```js +{ + "plugins": [ + ["transform-class-properties", { + "spec": true + }] + ] +} +``` + +- Class properties are compiled to use `Object.defineProperty` +- Static fields are now defined even if they are not initialized + +In +```js +class Foo { + static bar; +} +``` + +Out +```js +var Foo = function Foo() { + babelHelpers.classCallCheck(this, Foo); +}; + +Object.defineProperty(Foo, "bar", { + enumerable: true, + writable: true, + value: undefined +}); +``` +* `babel-traverse` + * [#4836](https://github.com/babel/babel/pull/4836) Add path utilities `isAncestor` and `isDescendant`. ([@boopathi](https://github.com/boopathi)) + +We've added 2 similar "ancestry" path methods to `path.findParent`: + +`path.isAncestor`/`path.isDescenant` + +Usage: +```js +let programPath, numberPath; +traverse(ast, { + Program(path) { programPath = path; }, + NumberPath(path) { numberPath = path; }, +}); + +programPath.isAncestor(numberPath); // true +numberPath.isDescendant(programPath); // true +``` + + * [#4835](https://github.com/babel/babel/pull/4835) Add `clearCache` and `clearPath` as separate APIs under traverse. ([@boopathi](https://github.com/boopathi)) + +Usage: +```js +traverse.clearCache(); // clears both path's and scope cache +traverse.clearCache.clearPath(); +traverse.clearCache.clearScope(); +``` + +* `babel-generator` + * [#4827](https://github.com/babel/babel/pull/4827) Add `jsonCompatibleStrings` option to generator. ([@kangax](https://github.com/kangax)) + +Usage: +```js +{ + "generatorOpts": { + "jsonCompatibleStrings": true // defaults to false + } +} +``` + +Set to true for the generator to use `jsesc` with `"json": true`. This will make it print `"\u00A9"` vs. `"©"`; + + * [#3547](https://github.com/babel/babel/pull/3547) Added `flowUsesCommas` option for object types. ([@sampepose](https://github.com/sampepose)) + +Usage: +```js +{ + "generatorOpts": { + "flowCommaSeparator": true // defaults to false + } +} +``` + +Currently there are 2 supported syntaxes (`,` and `;`) in Flow Object Types. The use of commas is in line with the more popular style and matches how objects are defined in Javascript, making it a bit more natural to write. + +```js +var a: { param1: number; param2: string } +var a: { param1: number, param2: string } +``` + +* `babel-types` + * [#3553](https://github.com/babel/babel/pull/3553) Start babel-types tests, add `isNodesEquivalent`. ([@hzoo](https://github.com/hzoo)) + +`t.isNodesEquivalent` + +Usage: + +```js +assert(t.isNodesEquivalent(parse("1 + 1"), parse("1+1")) === true); +``` + +* `babel-plugin-transform-es2015-modules-systemjs` + * [#4789](https://github.com/babel/babel/pull/4789) Support `import()` as contextual import in system module format. ([@guybedford](https://github.com/guybedford)) + +Support stage-2 `import()` in systemjs. + +It does not compile by default; you'll want to add the stage-2 preset or explicitly include `babel-plugin-syntax-dynamic-import`. + +```js +export function lazyLoadOperation () { + return import('./x') + .then(function (x) { + x.y(); + }); +} +``` + +#### :bug: Bug Fix +* `babel-generator` + * [#4830](https://github.com/babel/babel/pull/4830) Bug fix for printing minified literals. ([@shinew](https://github.com/shinew)) + +Will print the shorter of the `NumericLiteral`s if using the `minified` option. + +Input +```js +5e1; +5e4; +``` + +Output +```js +50; +5e4; +``` + +* `babel-plugin-transform-es2015-modules-systemjs` + * [#4832](https://github.com/babel/babel/pull/4832) Fix system transformer to ensure consistent modules iteration. ([@guybedford](https://github.com/guybedford)) + +Fixes inconsistent modules iteration for numeric imports + +```js +import "2"; // should be imported first +import "1"; // second +``` + +* `babel-plugin-transform-es2015-destructuring`, `babel-plugin-transform-react-constant-elements` + * [#4813](https://github.com/babel/babel/pull/4813) Fix binding kind of destructured variables.. ([@STRML](https://github.com/STRML)) + +Fixes an issue with destructuring parameters being hoisted incorrectly. + +Input +``` +function render({ text }) { + return () => (); +} +``` + +Output +``` +function render(_ref) { + let text = _ref.text; + var _ref2 = ; + return () => _ref2; +} +``` + +#### :memo: Documentation +* Other + * [#4802](https://github.com/babel/babel/pull/4802) Add toc [skip ci]. ([@hzoo](https://github.com/hzoo)) + +#### :house: Internal +* `babel-plugin-transform-async-to-generator` + * [#4837](https://github.com/babel/babel/pull/4837) Fix crlf to lf. ([@lion-man44](https://github.com/lion-man44)) +* Other + * [#4807](https://github.com/babel/babel/pull/4807) Chore: FLOW command in makefile and logic in .travis.yml(issue#4710).. ([@sstern6](https://github.com/sstern6)) + +#### Committers: 10 +- Boopathi Rajaa ([boopathi](https://github.com/boopathi)) +- Guy Bedford ([guybedford](https://github.com/guybedford)) +- Henry Zhu ([hzoo](https://github.com/hzoo)) +- Juriy Zaytsev ([kangax](https://github.com/kangax)) +- Moti Zilberman ([motiz88](https://github.com/motiz88)) +- Sam Pepose ([sampepose](https://github.com/sampepose)) +- Samuel Reed ([STRML](https://github.com/STRML)) +- Scott Stern ([sstern6](https://github.com/sstern6)) +- Shine Wang ([shinew](https://github.com/shinew)) +- lion ([lion-man44](https://github.com/lion-man44)) + ## v6.18.2 (2016-11-01) Weird publishing issue with v6.18.1, same release. @@ -75,7 +516,7 @@ class C2 { +p: T = e }; ```js // in -['a' + 'b']: 10 * 20, 'z': [1, 2, 3]} +{['a' + 'b']: 10 * 20, 'z': [1, 2, 3]} // out {ab: 200, z: [1, 2, 3]} ``` diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 4d38b69a5ee5..80c27d86d30b 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -5,7 +5,7 @@

Setup | - Running tests + Running linting/tests | Writing tests | @@ -195,3 +195,10 @@ For both `babel-plugin-x` and `babylon`, you can easily generate an `expected.js - actual.js - expected.json (will be generated if not created) ``` + +#### Internals +- AST spec ([babylon/ast/spec.md](https://github.com/babel/babylon/blob/master/ast/spec.md)) +- Versionning ([doc/design/versioning.md](./doc/design/versioning.md)) +- Monorepo ([doc/design/monorepo.md](./doc/design/monorepo.md)) +- Compiler environment support ([doc/design/compiler-environment-support.md](./doc/design/compiler-environment-support.md)) +- Compiler assumptions ([doc/design/compiler-assumptions.md](./doc/design/compiler-assumptions.md)) diff --git a/Gulpfile.js b/Gulpfile.js index 54f20cafb8ed..a1e8eff335e9 100644 --- a/Gulpfile.js +++ b/Gulpfile.js @@ -9,7 +9,6 @@ var gulp = require("gulp"); var path = require("path"); var scripts = "./packages/*/src/**/*.js"; -var dest = "packages"; var srcEx, libFragment; @@ -21,9 +20,36 @@ if (path.win32 === path) { libFragment = "$1/lib/"; } +var mapToDest = function (path) { return path.replace(srcEx, libFragment); }; +var dest = "packages"; + gulp.task("default", ["build"]); gulp.task("build", function () { + return gulp.src(scripts) + .pipe(plumber({ + errorHandler: function (err) { + gutil.log(err.stack); + } + })) + .pipe(newer({map: mapToDest})) + .pipe(through.obj(function (file, enc, callback) { + gutil.log("Compiling", "'" + chalk.cyan(file.path) + "'..."); + callback(null, file); + })) + .pipe(babel()) + .pipe(through.obj(function (file, enc, callback) { + file._path = file.path; + file.path = mapToDest(file.path); + callback(null, file); + })) + .pipe(gulp.dest(dest)); +}); + +// TODO: remove this section +// temporarily just copying the old code since watch isn't working +var dest = "packages"; +gulp.task("build-watch", function () { return gulp.src(scripts) .pipe(plumber({ errorHandler: function (err) { @@ -44,8 +70,8 @@ gulp.task("build", function () { .pipe(gulp.dest(dest)); }); -gulp.task("watch", ["build"], function (callback) { +gulp.task("watch", ["build-watch"], function (callback) { watch(scripts, {debounceDelay: 200}, function () { - gulp.start("build"); + gulp.start("build-watch"); }); }); diff --git a/Makefile b/Makefile index b196fb99d687..c7e27bf712c1 100644 --- a/Makefile +++ b/Makefile @@ -15,19 +15,19 @@ build-dist: build node scripts/generate-babel-types-docs.js watch: clean + rm -rf packages/*/lib ./node_modules/.bin/gulp watch lint: - ./node_modules/.bin/eslint packages/*/{src,test}/*.js --format=codeframe + ./node_modules/.bin/eslint packages/ --format=codeframe flow: ./node_modules/.bin/flow check fix: - ./node_modules/.bin/eslint packages/*/{src,test}/*.js --format=codeframe --fix + ./node_modules/.bin/eslint packages/ --format=codeframe --fix clean: test-clean - rm -rf packages/*/lib rm -rf packages/babel-polyfill/browser* rm -rf packages/babel-polyfill/dist rm -rf coverage @@ -52,13 +52,13 @@ test: lint test-only test-cov: clean # rebuild with test rm -rf packages/*/lib - BABEL_ENV=test; ./node_modules/.bin/gulp build + BABEL_ENV=test ./node_modules/.bin/gulp build ./scripts/test-cov.sh test-ci: NODE_ENV=test make bootstrap - ./scripts/test-cov.sh - cat ./coverage/coverage.json | ./node_modules/codecov.io/bin/codecov.io.js + make test-cov + ./node_modules/.bin/codecov -f coverage/coverage-final.json publish: git pull --rebase diff --git a/README.md b/README.md index 80d2c3ff4035..04057583fe3e 100644 --- a/README.md +++ b/README.md @@ -13,8 +13,43 @@ CircleCI Status Coverage Status Slack Status + NPM Downloads

+Babel is a community-driven tool that helps you write the latest version of JavaScript. + +When your supported environments don't support certain features natively, it will help you compile it down to a supported version. + +**In** + +```js +// ES2015 arrow function +[1,2,3].map(n => n + 1); +``` + +**Out** + +```js +[1,2,3].map(function(n) { + return n + 1; +}); +``` + +Try it out at our [REPL](https://babeljs.io/repl/#?babili=false&evaluate=true&lineWrap=false&presets=latest&code=%5B1%2C2%2C3%5D.map(n%20%3D%3E%20n%20%2B%201)%3B&experimental=true&loose=true&spec=false&playground=false&stage=0) and follow us at [@babeljs](https://twitter.com/babeljs). + +- [FAQ](#faq) +- [Packages](#packages) + - [Core Packages](#core-packages) + - [Other](#other) + - [Presets](#presets) + - [Plugins](#plugins) + - [Transform Plugins](#transform-plugins) + - [Syntax Plugins](#syntax-plugins) + - [Misc Packages](#misc-packages) +- [License](#license) + +# FAQ + ## Docs? Check out our website: [babeljs.io](http://babeljs.io/) @@ -198,7 +233,7 @@ These just enable the transform plugins to be able to parse certain features (th These are mostly for internal use in various plugins: `babel-helper-x`. -### Misc +### Misc Packages - [`babel`](/packages/babel) the deprecated `babel` package on npm that was used in Babel 5. - [`babel-messages`](/packages/babel-messages) a package to keep error messages, etc (not always used) diff --git a/doc/design/monorepo.md b/doc/design/monorepo.md index c479bca828e2..c8d062b44b36 100644 --- a/doc/design/monorepo.md +++ b/doc/design/monorepo.md @@ -21,6 +21,7 @@ This is quite taboo but let's look at the pros and cons: * Codebase looks more intimidating. * Repo is bigger in size. + * Lower ranking in [npms](https://npms.io/) results. At least until [npms-io/npms-analyzer#83](https://github.com/npms-io/npms-analyzer/issues/83) is fixed. * ??? ## This is dumb! Nobody in open source does this! diff --git a/lerna.json b/lerna.json index e18bde079ddf..3236999da4d4 100644 --- a/lerna.json +++ b/lerna.json @@ -1,6 +1,6 @@ { "lerna": "2.0.0-beta.23", - "version": "6.18.2", + "version": "6.20.3", "changelog": { "repo": "babel/babel", "labels": { diff --git a/package.json b/package.json index a725535bd961..e62332ff1989 100644 --- a/package.json +++ b/package.json @@ -11,6 +11,7 @@ "async": "^1.5.0", "babel-core": "^6.13.2", "babel-eslint": "^7.0.0", + "babel-plugin-istanbul": "^2.0.1", "babel-plugin-transform-class-properties": "^6.6.0", "babel-plugin-transform-flow-strip-types": "^6.3.13", "babel-plugin-transform-runtime": "^6.3.13", @@ -22,7 +23,7 @@ "bundle-collapser": "^1.2.1", "chai": "^3.5.0", "chalk": "1.1.1", - "codecov.io": "^0.1.6", + "codecov": "^1.0.1", "derequire": "^2.0.2", "eslint": "^3.9.0", "eslint-config-babel": "^2.0.1", @@ -35,11 +36,11 @@ "gulp-plumber": "^1.0.1", "gulp-util": "^3.0.7", "gulp-watch": "^4.3.5", - "istanbul": "^0.4.5", "lerna": "2.0.0-beta.23", "lerna-changelog": "^0.2.0", "lodash": "^4.2.0", "mocha": "^3.0.0", + "nyc": "^10.0.0", "output-file-sync": "^1.1.1", "rimraf": "^2.4.3", "semver": "^5.0.0", @@ -65,8 +66,20 @@ ], "env": { "test": { - "auxiliaryCommentBefore": "istanbul ignore next" + "auxiliaryCommentBefore": "istanbul ignore next", + "plugins": [ + "istanbul" + ] } } + }, + "nyc": { + "all": true, + "exclude": [ + "scripts/*.js", + "packages/*/test/**" + ], + "sourceMap": false, + "instrument": false } } diff --git a/packages/babel-cli/README.md b/packages/babel-cli/README.md index 6b2f7a06e68d..a32c3721b440 100644 --- a/packages/babel-cli/README.md +++ b/packages/babel-cli/README.md @@ -9,13 +9,13 @@ There are some shell-executable utility scripts, `babel-external-helpers.js` and ## Install ```sh -$ npm install babel-cli +npm install --save-dev babel-cli ``` ## Usage ```sh -$ babel script.js +babel script.js ``` For more in depth documentation see: http://babeljs.io/docs/usage/cli/ diff --git a/packages/babel-code-frame/README.md b/packages/babel-code-frame/README.md index 7e61e3ea5b97..0257a2da1fb8 100644 --- a/packages/babel-code-frame/README.md +++ b/packages/babel-code-frame/README.md @@ -5,7 +5,7 @@ ## Install ```sh -$ npm install babel-code-frame +npm install --save-dev babel-code-frame ``` ## Usage @@ -40,3 +40,4 @@ name | type | default | description highlightCode | boolean | `false` | Syntax highlight the code as JavaScript for terminals linesAbove | number | 2 | The number of lines to show above the error linesBelow | number | 3 | The number of lines to show below the error +forceColor | boolean | `false` | Forcibly syntax highlight the code as JavaScript (for non-terminals); overrides highlightCode diff --git a/packages/babel-code-frame/package.json b/packages/babel-code-frame/package.json index 113ac80fb0cc..f48072728355 100644 --- a/packages/babel-code-frame/package.json +++ b/packages/babel-code-frame/package.json @@ -1,6 +1,6 @@ { "name": "babel-code-frame", - "version": "6.16.0", + "version": "6.20.0", "description": "Generate errors that contain a code frame that point to source locations.", "author": "Sebastian McKenzie ", "homepage": "https://babeljs.io/", diff --git a/packages/babel-code-frame/src/index.js b/packages/babel-code-frame/src/index.js index 105061f60003..05637e9e40ba 100644 --- a/packages/babel-code-frame/src/index.js +++ b/packages/babel-code-frame/src/index.js @@ -1,25 +1,27 @@ import jsTokens from "js-tokens"; import esutils from "esutils"; -import chalk from "chalk"; +import Chalk from "chalk"; /** * Chalk styles for token types. */ -let defs = { - keyword: chalk.cyan, - capitalized: chalk.yellow, - jsx_tag: chalk.yellow, - punctuator: chalk.yellow, - // bracket: intentionally omitted. - number: chalk.magenta, - string: chalk.green, - regex: chalk.magenta, - comment: chalk.grey, - invalid: chalk.white.bgRed.bold, - gutter: chalk.grey, - marker: chalk.red.bold, -}; +function getDefs(chalk) { + return { + keyword: chalk.cyan, + capitalized: chalk.yellow, + jsx_tag: chalk.yellow, + punctuator: chalk.yellow, + // bracket: intentionally omitted. + number: chalk.magenta, + string: chalk.green, + regex: chalk.magenta, + comment: chalk.grey, + invalid: chalk.white.bgRed.bold, + gutter: chalk.grey, + marker: chalk.red.bold, + }; +} /** * RegExp to test for newlines in terminal. @@ -75,7 +77,7 @@ function getTokenType(match) { * Highlight `text`. */ -function highlight(text: string) { +function highlight(defs: Object, text: string) { return text.replace(jsTokens, function (...args) { let type = getTokenType(args); let colorize = defs[type]; @@ -99,11 +101,16 @@ export default function ( ): string { colNumber = Math.max(colNumber, 0); - let highlighted = opts.highlightCode && chalk.supportsColor; + let highlighted = (opts.highlightCode && Chalk.supportsColor) || opts.forceColor; + let chalk = Chalk; + if (opts.forceColor) { + chalk = new Chalk.constructor({ enabled: true }); + } let maybeHighlight = (chalkFn, string) => { return highlighted ? chalkFn(string) : string; }; - if (highlighted) rawLines = highlight(rawLines); + let defs = getDefs(chalk); + if (highlighted) rawLines = highlight(defs, rawLines); let linesAbove = opts.linesAbove || 2; let linesBelow = opts.linesBelow || 3; diff --git a/packages/babel-code-frame/test/index.js b/packages/babel-code-frame/test/index.js index 39813d7e1690..c85d59ddec60 100644 --- a/packages/babel-code-frame/test/index.js +++ b/packages/babel-code-frame/test/index.js @@ -186,4 +186,21 @@ describe("babel-code-frame", function () { " 8 | " ].join("\n")); }); + + it("opts.forceColor", function() { + let marker = chalk.red.bold; + let gutter = chalk.grey; + + let rawLines = [ + "", + "", + "", + "" + ].join("\n"); + assert.equal(codeFrame(rawLines, 3, null, { linesAbove: 1, linesBelow: 1, forceColor: true }), chalk.reset([ + " " + gutter(" 2 | "), + marker(">") + gutter(" 3 | "), + " " + gutter(" 4 | ") + ].join("\n"))); + }); }); diff --git a/packages/babel-core/README.md b/packages/babel-core/README.md index 8818c4f65701..3db09945ec2c 100644 --- a/packages/babel-core/README.md +++ b/packages/babel-core/README.md @@ -2,23 +2,116 @@ > Babel compiler core. -## Install +```javascript +var babel = require("babel-core"); +import { transform } from 'babel-core'; +import * as babel from 'babel-core'; ``` -$ npm install babel-core + +## babel.transform(code: string, [options?](/docs/usage/api/#options): Object) + +Transforms the passed in `code`. Returning an object with the generated code, +source map, and AST. + +```js +babel.transform(code, options) // => { code, map, ast } ``` -## Usage +**Example** ```js -import * as babel from 'babel-core'; +var result = babel.transform("code();", options); +result.code; +result.map; +result.ast; +``` + +## babel.transformFile(filename: string, [options?](/docs/usage/api/#options): Object, callback: Function) + +Asynchronously transforms the entire contents of a file. + +```js +babel.transformFile(filename, options, callback) +``` + +**Example** + +```js +babel.transformFile("filename.js", options, function (err, result) { + result; // => { code, map, ast } +}); +``` + +## babel.transformFileSync(filename: string, [options?](/docs/usage/api/#options): Object) + +Synchronous version of `babel.transformFile`. Returns the transformed contents of +the `filename`. + +```js +babel.transformFileSync(filename, options) // => { code, map, ast } +``` -const code = `class Example {}`; -const result = babel.transform(code, { /* options */ }); +**Example** -result.code; // Generated code -result.map; // Sourcemap -result.ast; // AST +```js +babel.transformFileSync("filename.js", options).code; ``` -For more in depth documentation see: http://babeljs.io/docs/usage/api/ +## babel.transformFromAst(ast: Object, code?: string, [options?](/docs/usage/api/#options): Object) + +Given, an [AST](https://astexplorer.net/), transform it. + +```js +const code = "if (true) return;"; +const ast = babylon.parse(code, { allowReturnOutsideFunction: true }); +const { code, map, ast } = babel.transformFromAst(ast, code, options); +``` + +## Options + +
+

Babel CLI

+

+ You can pass these options from the Babel CLI like so: +

+

+ babel --name=value +

+
+ +Following is a table of the options you can use: + +| Option | Default | Description | +| ------------------------ | -------------------- | ------------------------------- | +| `filename` | `"unknown"` | Filename for use in errors etc. | +| `filenameRelative` | `(filename)` | Filename relative to `sourceRoot`. | +| `presets` | `[]` | List of [presets](/docs/plugins/#presets) (a set of plugins) to load and use. | +| `plugins` | `[]` | List of [plugins](/docs/plugins/) to load and use. | +| `parserOpts` | `{}` | An object containing the options to be passed down to the babel parser, babylon | +| `generatorOpts` | `{}` | An object containing the options to be passed down to the babel code generator, babel-generator | +| `highlightCode` | `true` | ANSI highlight syntax error code frames | +| `only` | `null` | A [glob](https://github.com/isaacs/minimatch), regex, or mixed array of both, matching paths to **only** compile. Can also be an array of arrays containing paths to explicitly match. When attempting to compile a non-matching file it's returned verbatim. | +| `ignore` | `null` | Opposite to the `only` option. `ignore` is disregarded if `only` is specified. | +| `auxiliaryCommentBefore` | `null` | Attach a comment before all non-user injected code. | +| `auxiliaryCommentAfter` | `null` | Attach a comment after all non-user injected code. | +| `sourceMaps` | `false` | If truthy, adds a `map` property to returned output. If set to `"inline"`, a comment with a sourceMappingURL directive is added to the bottom of the returned code. If set to `"both"` then a `map` property is returned as well as a source map comment appended. **This does not emit sourcemap files by itself!** To have sourcemaps emitted using the CLI, you must pass it the `--source-maps` option. | +| `inputSourceMap` | `null` | A source map object that the output source map will be based on. | +| `sourceMapTarget` | `(filenameRelative)` | Set `file` on returned source map. | +| `sourceFileName` | `(filenameRelative)` | Set `sources[0]` on returned source map. | +| `sourceRoot` | `(moduleRoot)` | The root from which all sources are relative. | +| `moduleRoot` | `(sourceRoot)` | Optional prefix for the AMD module formatter that will be prepend to the filename on module definitions. | +| `moduleIds` | `false` | If truthy, insert an explicit id for modules. By default, all modules are anonymous. (Not available for `common` modules) | +| `moduleId` | `null` | Specify a custom name for module ids. | +| `getModuleId` | `null` | Specify a custom callback to generate a module id with. Called as `getModuleId(moduleName)`. If falsy value is returned then the generated module id is used. | +| `resolveModuleSource` | `null` | Resolve a module source ie. `import "SOURCE";` to a custom value. Called as `resolveModuleSource(source, filename)`. | +| `code` | `true` | Enable code generation | +| `no-babelrc` | [CLI flag](http://babeljs.io/docs/usage/cli/#ignoring-babelrc) | Specify whether or not to use .babelrc and .babelignore files. Only available when using the CLI. | +| `ast` | `true` | Include the AST in the returned object | +| `compact` | `"auto"` | Do not include superfluous whitespace characters and line terminators. When set to `"auto"` compact is set to `true` on input sizes of >500KB. | +| `minified` | `false` | Should the output be minified (not printing last semicolons in blocks, printing literal string values instead of escaped ones, stripping `()` from `new` when safe) | +| `comments` | `true` | Output comments in generated output. | +| `shouldPrintComment` | `null` | An optional callback that controls whether a comment should be output or not. Called as `shouldPrintComment(commentContents)`. **NOTE:** This overrides the `comment` option when used. | +| `env` | `{}` | This is an object of keys that represent different environments. For example, you may have: `{ env: { production: { /* specific options */ } } }` which will use those options when the enviroment variable `BABEL_ENV` is set to `"production"`. If `BABEL_ENV` isn't set then `NODE_ENV` will be used, if it's not set then it defaults to `"development"` | +| `retainLines` | `false` | Retain line numbers. This will lead to wacky code but is handy for scenarios where you can't use source maps. (**NOTE:** This will not retain the columns) | +| `extends` | `null` | A path to an `.babelrc` file to extend | diff --git a/packages/babel-core/package.json b/packages/babel-core/package.json index 0f921c72bd3a..02f3cd66a085 100644 --- a/packages/babel-core/package.json +++ b/packages/babel-core/package.json @@ -1,6 +1,6 @@ { "name": "babel-core", - "version": "6.18.2", + "version": "6.20.0", "description": "Babel compiler core.", "author": "Sebastian McKenzie ", "homepage": "https://babeljs.io/", @@ -24,15 +24,15 @@ "test": "make test" }, "dependencies": { - "babel-code-frame": "^6.16.0", - "babel-generator": "^6.18.0", + "babel-code-frame": "^6.20.0", + "babel-generator": "^6.20.0", "babel-helpers": "^6.16.0", "babel-messages": "^6.8.0", "babel-template": "^6.16.0", - "babel-runtime": "^6.9.1", + "babel-runtime": "^6.20.0", "babel-register": "^6.18.0", - "babel-traverse": "^6.18.0", - "babel-types": "^6.18.0", + "babel-traverse": "^6.20.0", + "babel-types": "^6.20.0", "babylon": "^6.11.0", "convert-source-map": "^1.1.0", "debug": "^2.1.1", @@ -45,8 +45,8 @@ "source-map": "^0.5.0" }, "devDependencies": { - "babel-helper-fixtures": "^6.18.2", - "babel-helper-transform-fixture-test-runner": "^6.18.2", - "babel-polyfill": "^6.16.0" + "babel-helper-fixtures": "^6.20.0", + "babel-helper-transform-fixture-test-runner": "^6.20.0", + "babel-polyfill": "^6.20.0" } } diff --git a/packages/babel-core/src/transformation/file/options/option-manager.js b/packages/babel-core/src/transformation/file/options/option-manager.js index d492eeda6638..1ab1a5badb8a 100644 --- a/packages/babel-core/src/transformation/file/options/option-manager.js +++ b/packages/babel-core/src/transformation/file/options/option-manager.js @@ -182,7 +182,7 @@ export default class OptionManager { this.log.error(`Using removed Babel 5 option: ${alias}.${key} - ${removed[key].message}`, ReferenceError); } else { let unknownOptErr = `Unknown option: ${alias}.${key}. Check out http://babeljs.io/docs/usage/options/ for more information about options.`; - let presetConfigErr = `A common cause of this error is the presence of a configuration options object without the corresponding preset name. Example:\n\nInvalid:\n \`{ presets: [{option: value}] }\`\nValid:\n \`{ presets: [['presetName', {option: value}]] }\`\n\nFor more detailed information on preset configuration, please see http://babeljs.io/docs/plugins/#pluginpresets-options.`; + let presetConfigErr = "A common cause of this error is the presence of a configuration options object without the corresponding preset name. Example:\n\nInvalid:\n `{ presets: [{option: value}] }`\nValid:\n `{ presets: [['presetName', {option: value}]] }`\n\nFor more detailed information on preset configuration, please see http://babeljs.io/docs/plugins/#pluginpresets-options."; this.log.error(`${unknownOptErr}\n\n${presetConfigErr}`, ReferenceError); } diff --git a/packages/babel-core/test/fixtures/transformation/misc/regression-4855/actual.js b/packages/babel-core/test/fixtures/transformation/misc/regression-4855/actual.js new file mode 100644 index 000000000000..1e124fb4e108 --- /dev/null +++ b/packages/babel-core/test/fixtures/transformation/misc/regression-4855/actual.js @@ -0,0 +1,2 @@ +({ [fieldName]: value, ...rest } = values); +let error; diff --git a/packages/babel-core/test/fixtures/transformation/misc/regression-4855/expected.js b/packages/babel-core/test/fixtures/transformation/misc/regression-4855/expected.js new file mode 100644 index 000000000000..c6e87b5bee4f --- /dev/null +++ b/packages/babel-core/test/fixtures/transformation/misc/regression-4855/expected.js @@ -0,0 +1,7 @@ +"use strict"; + +var _values = values; +value = _values[fieldName]; +rest = babelHelpers.objectWithoutProperties(_values, [fieldName]); + +var error = void 0; \ No newline at end of file diff --git a/packages/babel-core/test/fixtures/transformation/misc/regression-4855/options.json b/packages/babel-core/test/fixtures/transformation/misc/regression-4855/options.json new file mode 100644 index 000000000000..797622c3308e --- /dev/null +++ b/packages/babel-core/test/fixtures/transformation/misc/regression-4855/options.json @@ -0,0 +1,4 @@ +{ + "compact": false, + "presets": ["es2015","stage-2"] +} diff --git a/packages/babel-generator/README.md b/packages/babel-generator/README.md index 5de763278c05..46a4c051b305 100644 --- a/packages/babel-generator/README.md +++ b/packages/babel-generator/README.md @@ -5,7 +5,7 @@ ## Install ```sh -$ npm install babel-generator +npm install --save-dev babel-generator ``` ## Usage @@ -37,7 +37,8 @@ minified | boolean | `false` | Should the output be minif concise | boolean | `false` | Set to `true` to reduce whitespace (but not as much as `opts.compact`) quotes | `'single'` or `'double'` | autodetect based on `ast.tokens` | The type of quote to use in the output filename | string | | Used in warning messages - +flowCommaSeparator | boolean | `false` | Set to `true` to use commas instead of semicolons as Flow property separators +jsonCompatibleStrings | boolean | `false` | Set to true to run `jsesc` with "json": true to print "\u00A9" vs. "©"; Options for source maps: name | type | default | description diff --git a/packages/babel-generator/package.json b/packages/babel-generator/package.json index 9464e5fd4e2a..84fd0c04d282 100644 --- a/packages/babel-generator/package.json +++ b/packages/babel-generator/package.json @@ -1,6 +1,6 @@ { "name": "babel-generator", - "version": "6.18.0", + "version": "6.20.0", "description": "Turns an AST into code.", "author": "Sebastian McKenzie ", "homepage": "https://babeljs.io/", @@ -12,15 +12,15 @@ ], "dependencies": { "babel-messages": "^6.8.0", - "babel-runtime": "^6.9.0", - "babel-types": "^6.18.0", + "babel-runtime": "^6.20.0", + "babel-types": "^6.20.0", "detect-indent": "^4.0.0", "jsesc": "^1.3.0", "lodash": "^4.2.0", "source-map": "^0.5.0" }, "devDependencies": { - "babel-helper-fixtures": "^6.18.0", + "babel-helper-fixtures": "^6.20.0", "babylon": "^6.11.0" } } diff --git a/packages/babel-generator/src/generators/expressions.js b/packages/babel-generator/src/generators/expressions.js index a6cc4548d04c..26ab26a0f901 100644 --- a/packages/babel-generator/src/generators/expressions.js +++ b/packages/babel-generator/src/generators/expressions.js @@ -113,6 +113,10 @@ export function CallExpression(node: Object) { this.token(")"); } +export function Import() { + this.word("import"); +} + function buildYieldAwait(keyword: string) { return function (node: Object) { this.word(keyword); diff --git a/packages/babel-generator/src/generators/flow.js b/packages/babel-generator/src/generators/flow.js index b6c5a8b20d69..9ef56bdde494 100644 --- a/packages/babel-generator/src/generators/flow.js +++ b/packages/babel-generator/src/generators/flow.js @@ -270,11 +270,18 @@ export function ObjectTypeAnnotation(node: Object) { this.space(); this.printJoin(props, node, { + addNewlines(leading) { + if (leading && !props[0]) return 1; + }, indent: true, statement: true, iterator: () => { if (props.length !== 1) { - this.semicolon(); + if (this.format.flowCommaSeparator) { + this.token(","); + } else { + this.semicolon(); + } this.space(); } } diff --git a/packages/babel-generator/src/generators/types.js b/packages/babel-generator/src/generators/types.js index 6ef895ab9399..3f803c8e11eb 100644 --- a/packages/babel-generator/src/generators/types.js +++ b/packages/babel-generator/src/generators/types.js @@ -124,23 +124,33 @@ export function NullLiteral() { } export function NumericLiteral(node: Object) { - let raw = this.getPossibleRaw(node); - - this.number(raw == null ? node.value + "" : raw); + const raw = this.getPossibleRaw(node); + const value = node.value + ""; + if (raw == null) { + this.number(value); // normalize + } else if (this.format.minified) { + this.number(raw.length < value.length ? raw : value); + } else { + this.number(raw); + } } export function StringLiteral(node: Object, parent: Object) { let raw = this.getPossibleRaw(node); - if (raw != null) { + if (!this.format.minified && raw != null) { this.token(raw); return; } // ensure the output is ASCII-safe - let val = jsesc(node.value, { + const opts = { quotes: t.isJSX(parent) ? "double" : this.format.quotes, wrap: true - }); + }; + if (this.format.jsonCompatibleStrings) { + opts.json = true; + } + let val = jsesc(node.value, opts); return this.token(val); } diff --git a/packages/babel-generator/src/index.js b/packages/babel-generator/src/index.js index 714f21d748c9..c212cbdf7c05 100644 --- a/packages/babel-generator/src/index.js +++ b/packages/babel-generator/src/index.js @@ -38,7 +38,7 @@ class Generator extends Printer { * Normalize generator options, setting defaults. * * - Detects code indentation. - * - If `opts.compact = "auto"` and the code is over 100KB, `compact` will be set to `true`. + * - If `opts.compact = "auto"` and the code is over 500KB, `compact` will be set to `true`. */ function normalizeOptions(code, opts, tokens): Format { @@ -59,11 +59,13 @@ function normalizeOptions(code, opts, tokens): Format { minified: opts.minified, concise: opts.concise, quotes: opts.quotes || findCommonStringDelimiter(code, tokens), + jsonCompatibleStrings: opts.jsonCompatibleStrings, indent: { adjustMultilineComment: true, style: style, base: 0 - } + }, + flowCommaSeparator: opts.flowCommaSeparator, }; if (format.minified) { @@ -76,10 +78,10 @@ function normalizeOptions(code, opts, tokens): Format { } if (format.compact === "auto") { - format.compact = code.length > 100000; // 100KB + format.compact = code.length > 500000; // 500KB if (format.compact) { - console.error("[BABEL] " + messages.get("codeGeneratorDeopt", opts.filename, "100KB")); + console.error("[BABEL] " + messages.get("codeGeneratorDeopt", opts.filename, "500KB")); } } diff --git a/packages/babel-generator/src/printer.js b/packages/babel-generator/src/printer.js index 9ce317e52bf8..a9af0094297b 100644 --- a/packages/babel-generator/src/printer.js +++ b/packages/babel-generator/src/printer.js @@ -388,8 +388,6 @@ export default class Printer { } getPossibleRaw(node) { - if (this.format.minified) return; - let extra = node.extra; if (extra && extra.raw != null && extra.rawValue != null && node.value === extra.rawValue) { return extra.raw; diff --git a/packages/babel-generator/test/fixtures/compact/expression-statement/actual.js b/packages/babel-generator/test/fixtures/compact/expression-statement/actual.js new file mode 100644 index 000000000000..d0f213e6c892 --- /dev/null +++ b/packages/babel-generator/test/fixtures/compact/expression-statement/actual.js @@ -0,0 +1,2 @@ +({ [fieldName]: value, ...rest } = values) +let error; diff --git a/packages/babel-generator/test/fixtures/compact/expression-statement/expected.js b/packages/babel-generator/test/fixtures/compact/expression-statement/expected.js new file mode 100644 index 000000000000..c1dab6506a87 --- /dev/null +++ b/packages/babel-generator/test/fixtures/compact/expression-statement/expected.js @@ -0,0 +1 @@ +({[fieldName]:value,...rest}=values);let error; diff --git a/packages/babel-generator/test/fixtures/escapes/jsonEscape/actual.js b/packages/babel-generator/test/fixtures/escapes/jsonEscape/actual.js new file mode 100644 index 000000000000..2305ada28e08 --- /dev/null +++ b/packages/babel-generator/test/fixtures/escapes/jsonEscape/actual.js @@ -0,0 +1 @@ +"©"; diff --git a/packages/babel-generator/test/fixtures/escapes/jsonEscape/expected.js b/packages/babel-generator/test/fixtures/escapes/jsonEscape/expected.js new file mode 100644 index 000000000000..fd903a4b2df6 --- /dev/null +++ b/packages/babel-generator/test/fixtures/escapes/jsonEscape/expected.js @@ -0,0 +1 @@ +"\u00A9"; diff --git a/packages/babel-generator/test/fixtures/escapes/options.json b/packages/babel-generator/test/fixtures/escapes/options.json new file mode 100644 index 000000000000..96bc693445f1 --- /dev/null +++ b/packages/babel-generator/test/fixtures/escapes/options.json @@ -0,0 +1,4 @@ +{ + "minified": true, + "jsonCompatibleStrings": true +} diff --git a/packages/babel-generator/test/fixtures/flowUsesCommas/ObjectExpression/actual.js b/packages/babel-generator/test/fixtures/flowUsesCommas/ObjectExpression/actual.js new file mode 100644 index 000000000000..b25558906e18 --- /dev/null +++ b/packages/babel-generator/test/fixtures/flowUsesCommas/ObjectExpression/actual.js @@ -0,0 +1,10 @@ +var a: { numVal: number }; +var a: { numVal: number; }; +var a: { numVal: number; [indexer: string]: number }; +var a: ?{ numVal: number }; +var a: { numVal: number; strVal: string } +var a: { subObj: {strVal: string} } +var a: { subObj: ?{strVal: string} } +var a: { param1: number; param2: string } +var a: { param1: number; param2?: string } +var a: { [a: number]: string; [b: number]: string; }; diff --git a/packages/babel-generator/test/fixtures/flowUsesCommas/ObjectExpression/expected.js b/packages/babel-generator/test/fixtures/flowUsesCommas/ObjectExpression/expected.js new file mode 100644 index 000000000000..69dd9891bbb5 --- /dev/null +++ b/packages/babel-generator/test/fixtures/flowUsesCommas/ObjectExpression/expected.js @@ -0,0 +1,10 @@ +var a: { numVal: number }; +var a: { numVal: number }; +var a: { numVal: number, [indexer: string]: number, }; +var a: ?{ numVal: number }; +var a: { numVal: number, strVal: string, }; +var a: { subObj: { strVal: string } }; +var a: { subObj: ?{ strVal: string } }; +var a: { param1: number, param2: string, }; +var a: { param1: number, param2?: string, }; +var a: { [a: number]: string, [b: number]: string, }; diff --git a/packages/babel-generator/test/fixtures/flowUsesCommas/options.json b/packages/babel-generator/test/fixtures/flowUsesCommas/options.json new file mode 100644 index 000000000000..f50690ec1364 --- /dev/null +++ b/packages/babel-generator/test/fixtures/flowUsesCommas/options.json @@ -0,0 +1,3 @@ +{ + "flowCommaSeparator": true +} diff --git a/packages/babel-generator/test/fixtures/minified/literals/actual.js b/packages/babel-generator/test/fixtures/minified/literals/actual.js index c3cd0166ba19..42ffdc30a312 100644 --- a/packages/babel-generator/test/fixtures/minified/literals/actual.js +++ b/packages/babel-generator/test/fixtures/minified/literals/actual.js @@ -1,5 +1,7 @@ 5; 5.0; +5e1; +5e4; "foobar"; '\x20'; "\n\r"; diff --git a/packages/babel-generator/test/fixtures/minified/literals/expected.js b/packages/babel-generator/test/fixtures/minified/literals/expected.js index 7de3c221ce16..d5af8701de86 100644 --- a/packages/babel-generator/test/fixtures/minified/literals/expected.js +++ b/packages/babel-generator/test/fixtures/minified/literals/expected.js @@ -1 +1 @@ -5;5;"foobar";" ";"\n\r";"\uD83D\uDE02";`😂`;/foobar/g;null;true;false;5;2;56;31; +5;5;50;5e4;"foobar";" ";"\n\r";"\uD83D\uDE02";`😂`;/foobar/g;null;true;false;5;2;56;31; diff --git a/packages/babel-generator/test/fixtures/types/Import/actual.js b/packages/babel-generator/test/fixtures/types/Import/actual.js new file mode 100644 index 000000000000..66a063bcb484 --- /dev/null +++ b/packages/babel-generator/test/fixtures/types/Import/actual.js @@ -0,0 +1 @@ +import("module.js"); diff --git a/packages/babel-generator/test/fixtures/types/Import/expected.js b/packages/babel-generator/test/fixtures/types/Import/expected.js new file mode 100644 index 000000000000..66a063bcb484 --- /dev/null +++ b/packages/babel-generator/test/fixtures/types/Import/expected.js @@ -0,0 +1 @@ +import("module.js"); diff --git a/packages/babel-generator/test/index.js b/packages/babel-generator/test/index.js index 92b4c5b3d274..bbdb06eddbe6 100644 --- a/packages/babel-generator/test/index.js +++ b/packages/babel-generator/test/index.js @@ -6,6 +6,8 @@ let parse = require("babylon").parse; let chai = require("chai"); let t = require("babel-types"); let _ = require("lodash"); +let fs = require("fs"); +let path = require("path"); describe("generation", function () { it("completeness", function () { @@ -141,6 +143,27 @@ describe("programmatic generation", function() { "}", ].join("\n")); }); + + it("flow object indentation with empty leading ObjectTypeProperty", function() { + let objectStatement = t.objectTypeAnnotation( + [], + [ + t.objectTypeIndexer( + t.identifier("key"), + t.anyTypeAnnotation(), + t.identifier("Test"), + ), + ] + ); + + let output = generate.default(objectStatement).code; + + assert.equal(output, [ + "{", + " [key: any]: Test;", + "}", + ].join("\n")); + }); }); describe("whitespace", function () { @@ -158,25 +181,24 @@ suites.forEach(function (testSuite) { it(task.title, !task.disabled && function () { let expect = task.expect; let actual = task.actual; - - let actualAst = parse(actual.code, { - filename: actual.loc, - plugins: [ - "jsx", - "flow", - "decorators", - "asyncFunctions", - "exportExtensions", - "functionBind", - "classConstructorCall", - "classProperties", - ], - strictMode: false, - sourceType: "module", - }); - - let actualCode = generate.default(actualAst, task.options, actual.code).code; - chai.expect(actualCode).to.equal(expect.code, actual.loc + " !== " + expect.loc); + let actualCode = actual.code; + + if (actualCode) { + let actualAst = parse(actualCode, { + filename: actual.loc, + plugins: ["*"], + strictMode: false, + sourceType: "module", + }); + let result = generate.default(actualAst, task.options, actualCode); + + if (!expect.code && result.code && fs.statSync(path.dirname(expect.loc)).isDirectory() && !process.env.CI) { + console.log(`New test file created: ${expect.loc}`); + fs.writeFileSync(expect.loc, result.code); + } else { + chai.expect(result.code).to.be.equal(expect.code, actual.loc + " !== " + expect.loc); + } + } }); }); }); diff --git a/packages/babel-helper-fixtures/package.json b/packages/babel-helper-fixtures/package.json index ab7694f79012..974ea4321730 100644 --- a/packages/babel-helper-fixtures/package.json +++ b/packages/babel-helper-fixtures/package.json @@ -1,13 +1,13 @@ { "name": "babel-helper-fixtures", - "version": "6.18.2", + "version": "6.20.0", "description": "Helper function to support fixtures", "author": "Sebastian McKenzie ", "license": "MIT", "repository": "https://github.com/babel/babel/tree/master/packages/babel-helper-fixtures", "main": "lib/index.js", "dependencies": { - "babel-runtime": "^6.9.0", + "babel-runtime": "^6.20.0", "lodash": "^4.2.0", "try-resolve": "^1.0.0" } diff --git a/packages/babel-helper-fixtures/src/index.js b/packages/babel-helper-fixtures/src/index.js index 499745654c16..40faaf153037 100644 --- a/packages/babel-helper-fixtures/src/index.js +++ b/packages/babel-helper-fixtures/src/index.js @@ -71,7 +71,6 @@ export default function get(entryLoc): Array { if (suiteOptsLoc) suite.options = require(suiteOptsLoc); for (let taskName of fs.readdirSync(suite.filename)) { - if (shouldIgnore(taskName)) continue; push(taskName, suite.filename + "/" + taskName); } diff --git a/packages/babel-helper-remap-async-to-generator/package.json b/packages/babel-helper-remap-async-to-generator/package.json index 4d3876a19ea8..0e633745d612 100644 --- a/packages/babel-helper-remap-async-to-generator/package.json +++ b/packages/babel-helper-remap-async-to-generator/package.json @@ -1,15 +1,15 @@ { "name": "babel-helper-remap-async-to-generator", - "version": "6.18.0", + "version": "6.20.3", "description": "Helper function to remap async functions to generators", "repository": "https://github.com/babel/babel/tree/master/packages/babel-helper-remap-async-to-generator", "license": "MIT", "main": "lib/index.js", "dependencies": { - "babel-runtime": "^6.0.0", + "babel-runtime": "^6.20.0", "babel-template": "^6.16.0", - "babel-types": "^6.18.0", - "babel-traverse": "^6.18.0", + "babel-types": "^6.20.0", + "babel-traverse": "^6.20.0", "babel-helper-function-name": "^6.18.0" } } diff --git a/packages/babel-helper-remap-async-to-generator/src/index.js b/packages/babel-helper-remap-async-to-generator/src/index.js index 056606da3aab..840a195d8afd 100644 --- a/packages/babel-helper-remap-async-to-generator/src/index.js +++ b/packages/babel-helper-remap-async-to-generator/src/index.js @@ -122,7 +122,18 @@ function plainFunction(path: NodePath, callId: Object) { NAME: asyncFnId, REF: path.scope.generateUidIdentifier("ref"), FUNCTION: built, - PARAMS: node.params.map(() => path.scope.generateUidIdentifier("x")) + PARAMS: node.params.reduce((acc, param) => { + acc.done = acc.done || t.isAssignmentPattern(param) || t.isRestElement(param); + + if (!acc.done) { + acc.params.push(path.scope.generateUidIdentifier("x")); + } + + return acc; + }, { + params: [], + done: false, + }).params, }).expression; if (isDeclaration) { diff --git a/packages/babel-helper-transform-fixture-test-runner/package.json b/packages/babel-helper-transform-fixture-test-runner/package.json index 564226d7472c..4239b53e4772 100644 --- a/packages/babel-helper-transform-fixture-test-runner/package.json +++ b/packages/babel-helper-transform-fixture-test-runner/package.json @@ -1,6 +1,6 @@ { "name": "babel-helper-transform-fixture-test-runner", - "version": "6.18.2", + "version": "6.20.0", "description": "Transform test runner for babel-helper-fixtures module", "author": "Sebastian McKenzie ", "homepage": "https://babeljs.io/", @@ -8,12 +8,12 @@ "repository": "https://github.com/babel/babel/tree/master/packages/babel-helper-transform-fixture-test-runner", "main": "lib/index.js", "dependencies": { - "babel-runtime": "^6.9.0", - "babel-core": "^6.18.2", - "babel-polyfill": "^6.16.0", - "babel-helper-fixtures": "^6.18.2", + "babel-runtime": "^6.20.0", + "babel-core": "^6.20.0", + "babel-polyfill": "^6.20.0", + "babel-helper-fixtures": "^6.20.0", "source-map": "^0.5.0", - "babel-code-frame": "^6.16.0", + "babel-code-frame": "^6.20.0", "chai": "^3.0.0", "lodash": "^4.2.0" } diff --git a/packages/babel-helper-transform-fixture-test-runner/src/index.js b/packages/babel-helper-transform-fixture-test-runner/src/index.js index b930522cc945..12d94265c4ab 100644 --- a/packages/babel-helper-transform-fixture-test-runner/src/index.js +++ b/packages/babel-helper-transform-fixture-test-runner/src/index.js @@ -82,6 +82,7 @@ function run(task) { if (!execCode || actualCode) { result = babel.transform(actualCode, getOpts(actual)); if (!expect.code && result.code && !opts.throws && fs.statSync(path.dirname(expect.loc)).isDirectory() && !process.env.CI) { + console.log(`New test file created: ${expect.loc}`); fs.writeFileSync(expect.loc, result.code); } else { actualCode = result.code.trim(); diff --git a/packages/babel-helpers/README.md b/packages/babel-helpers/README.md index c4a927ffab0d..5a57c5d46a40 100644 --- a/packages/babel-helpers/README.md +++ b/packages/babel-helpers/README.md @@ -5,7 +5,7 @@ ## Install ```js -$ npm install babel-helpers +npm install --save-dev babel-helpers ``` ## Usage diff --git a/packages/babel-messages/README.md b/packages/babel-messages/README.md index 297cd0c83741..98ecf8b2c0a8 100644 --- a/packages/babel-messages/README.md +++ b/packages/babel-messages/README.md @@ -5,7 +5,7 @@ ## Install ```sh -$ npm install babel-messages +npm install --save-dev babel-messages ``` ## Usage diff --git a/packages/babel-plugin-check-es2015-constants/README.md b/packages/babel-plugin-check-es2015-constants/README.md index 0401a3f5c0c1..ee85b823e73e 100644 --- a/packages/babel-plugin-check-es2015-constants/README.md +++ b/packages/babel-plugin-check-es2015-constants/README.md @@ -1,11 +1,31 @@ # babel-plugin-check-es2015-constants -Validate ES2015 constants +Validate ES2015 constants (prevents reassignment of const variables). + +## Example + +**In** + +```js +const a = 1; +a = 2; +``` + +**Out** + +```bash +repl: "a" is read-only + 1 | const a = 1; +> 2 | a = 2; + | ^ +``` + +[Try in REPL](http://babeljs.io/repl/#?babili=false&evaluate=true&lineWrap=false&presets=es2015&experimental=false&loose=false&spec=false&code=const%20a%20%3D%201%3B%0Aa%20%3D%202%3B&playground=true) ## Installation ```sh -$ npm install babel-plugin-check-es2015-constants +npm install --save-dev babel-plugin-check-es2015-constants ``` ## Usage @@ -23,7 +43,7 @@ $ npm install babel-plugin-check-es2015-constants ### Via CLI ```sh -$ babel --plugins check-es2015-constants script.js +babel --plugins check-es2015-constants script.js ``` ### Via Node API diff --git a/packages/babel-plugin-external-helpers/README.md b/packages/babel-plugin-external-helpers/README.md index d7e0860bf8e6..4bb1e18beb73 100644 --- a/packages/babel-plugin-external-helpers/README.md +++ b/packages/babel-plugin-external-helpers/README.md @@ -3,7 +3,7 @@ ## Installation ```sh -$ npm install babel-plugin-external-helpers +npm install --save-dev babel-plugin-external-helpers ``` ## Usage @@ -21,7 +21,7 @@ $ npm install babel-plugin-external-helpers ### Via CLI ```sh -$ babel --plugins external-helpers script.js +babel --plugins external-helpers script.js ``` ### Via Node API diff --git a/packages/babel-plugin-syntax-async-functions/README.md b/packages/babel-plugin-syntax-async-functions/README.md index a2c13f519d31..469785a13f39 100644 --- a/packages/babel-plugin-syntax-async-functions/README.md +++ b/packages/babel-plugin-syntax-async-functions/README.md @@ -1,11 +1,22 @@ # babel-plugin-syntax-async-functions -Allow parsing of async functions. +This plugin allows Babel to parse async functions. + +## Example + +**Syntax** + +```javascript +(async function() { + await loadStory(); + console.log("Yey, story successfully loaded!"); +}()); +``` ## Installation ```sh -$ npm install babel-plugin-syntax-async-functions +npm install --save-dev babel-plugin-syntax-async-functions ``` ## Usage @@ -23,7 +34,7 @@ $ npm install babel-plugin-syntax-async-functions ### Via CLI ```sh -$ babel --plugins syntax-async-functions script.js +babel --plugins syntax-async-functions script.js ``` ### Via Node API @@ -33,3 +44,7 @@ require("babel-core").transform("code", { plugins: ["syntax-async-functions"] }); ``` + +## References + +* [Proposal: Async Functions for ECMAScript](https://github.com/tc39/ecmascript-asyncawait) diff --git a/packages/babel-plugin-syntax-async-generators/README.md b/packages/babel-plugin-syntax-async-generators/README.md index 330f8e2079e4..a3c8fc51a934 100644 --- a/packages/babel-plugin-syntax-async-generators/README.md +++ b/packages/babel-plugin-syntax-async-generators/README.md @@ -2,10 +2,28 @@ Allow parsing of async generator functions. +## Example + +**Syntax** + +```javascript +async function* agf() { + await 1; +} +``` + +```js +async function f() { + for await (let x of y) { + g(x); + } +} +``` + ## Installation ```sh -$ npm install babel-plugin-syntax-async-generators +npm install --save-dev babel-plugin-syntax-async-generators ``` ## Usage @@ -23,7 +41,7 @@ $ npm install babel-plugin-syntax-async-generators ### Via CLI ```sh -$ babel --plugins syntax-async-generators script.js +babel --plugins syntax-async-generators script.js ``` ### Via Node API @@ -33,3 +51,7 @@ require("babel-core").transform("code", { plugins: ["syntax-async-generators"] }); ``` + +## References + +* [Proposal: Asynchronous iteration for ECMAScript](https://github.com/tc39/proposal-async-iteration) diff --git a/packages/babel-plugin-syntax-class-constructor-call/README.md b/packages/babel-plugin-syntax-class-constructor-call/README.md index 174c8d555dc8..6b3a3e804e88 100644 --- a/packages/babel-plugin-syntax-class-constructor-call/README.md +++ b/packages/babel-plugin-syntax-class-constructor-call/README.md @@ -1,11 +1,13 @@ # babel-plugin-syntax-class-constructor-call (deprecated) -Allow parsing of do expressions. +> Proposal Withdrawn: can be solved with decorators. + +Allow parsing of call constructors. ## Installation ```sh -$ npm install babel-plugin-syntax-class-constructor-call +npm install --save-dev babel-plugin-syntax-class-constructor-call ``` ## Usage @@ -23,7 +25,7 @@ $ npm install babel-plugin-syntax-class-constructor-call ### Via CLI ```sh -$ babel --plugins syntax-class-constructor-call script.js +babel --plugins syntax-class-constructor-call script.js ``` ### Via Node API @@ -33,3 +35,9 @@ require("babel-core").transform("code", { plugins: ["syntax-class-constructor-call"] }); ``` + +## References + +* [Inactive Proposals](https://github.com/tc39/proposals/blob/master/inactive-proposals.md) +* [Proposal: Call Constructor](https://github.com/tc39/ecma262/blob/master/workingdocs/callconstructor.md) +* [Blog post: ECMAScript proposal: function-callable classes](http://www.2ality.com/2015/10/call-constructor-esprop.html) diff --git a/packages/babel-plugin-syntax-class-properties/README.md b/packages/babel-plugin-syntax-class-properties/README.md index 970049b47a41..7f0c6cff1aa0 100644 --- a/packages/babel-plugin-syntax-class-properties/README.md +++ b/packages/babel-plugin-syntax-class-properties/README.md @@ -5,7 +5,7 @@ Allow parsing of class properties. ## Installation ```sh -$ npm install babel-plugin-syntax-class-properties +npm install --save-dev babel-plugin-syntax-class-properties ``` ## Usage @@ -23,7 +23,7 @@ $ npm install babel-plugin-syntax-class-properties ### Via CLI ```sh -$ babel --plugins syntax-class-properties script.js +babel --plugins syntax-class-properties script.js ``` ### Via Node API diff --git a/packages/babel-plugin-syntax-decorators/README.md b/packages/babel-plugin-syntax-decorators/README.md index a7b27efc8866..40b6ad9e39f3 100644 --- a/packages/babel-plugin-syntax-decorators/README.md +++ b/packages/babel-plugin-syntax-decorators/README.md @@ -5,7 +5,7 @@ Allow parsing of decorators. ## Installation ```sh -$ npm install babel-plugin-syntax-decorators +npm install --save-dev babel-plugin-syntax-decorators ``` ## Usage @@ -23,7 +23,7 @@ $ npm install babel-plugin-syntax-decorators ### Via CLI ```sh -$ babel --plugins syntax-decorators script.js +babel --plugins syntax-decorators script.js ``` ### Via Node API diff --git a/packages/babel-plugin-syntax-do-expressions/README.md b/packages/babel-plugin-syntax-do-expressions/README.md index 9f7556a15d2e..2bca5e16d3e5 100644 --- a/packages/babel-plugin-syntax-do-expressions/README.md +++ b/packages/babel-plugin-syntax-do-expressions/README.md @@ -5,7 +5,7 @@ Allow parsing of do expressions. ## Installation ```sh -$ npm install babel-plugin-syntax-do-expressions +npm install --save-dev babel-plugin-syntax-do-expressions ``` ## Usage @@ -23,7 +23,7 @@ $ npm install babel-plugin-syntax-do-expressions ### Via CLI ```sh -$ babel --plugins syntax-do-expressions script.js +babel --plugins syntax-do-expressions script.js ``` ### Via Node API diff --git a/packages/babel-plugin-syntax-dynamic-import/README.md b/packages/babel-plugin-syntax-dynamic-import/README.md index 47279fcd36d3..153a1bfd349e 100644 --- a/packages/babel-plugin-syntax-dynamic-import/README.md +++ b/packages/babel-plugin-syntax-dynamic-import/README.md @@ -5,7 +5,7 @@ Allow parsing of `import()`. ## Installation ```sh -$ npm install babel-plugin-syntax-dynamic-import +npm install --save-dev babel-plugin-syntax-dynamic-import ``` ## Usage @@ -23,7 +23,7 @@ $ npm install babel-plugin-syntax-dynamic-import ### Via CLI ```sh -$ babel --plugins syntax-dynamic-import script.js +babel --plugins syntax-dynamic-import script.js ``` ### Via Node API diff --git a/packages/babel-plugin-syntax-exponentiation-operator/README.md b/packages/babel-plugin-syntax-exponentiation-operator/README.md index 42057eaf2346..384a07f87b38 100644 --- a/packages/babel-plugin-syntax-exponentiation-operator/README.md +++ b/packages/babel-plugin-syntax-exponentiation-operator/README.md @@ -5,7 +5,7 @@ Allow parsing of the exponentiation operator. ## Installation ```sh -$ npm install babel-plugin-syntax-exponentiation-operator +npm install --save-dev babel-plugin-syntax-exponentiation-operator ``` ## Usage @@ -23,7 +23,7 @@ $ npm install babel-plugin-syntax-exponentiation-operator ### Via CLI ```sh -$ babel --plugins syntax-exponentiation-operator script.js +babel --plugins syntax-exponentiation-operator script.js ``` ### Via Node API diff --git a/packages/babel-plugin-syntax-export-extensions/README.md b/packages/babel-plugin-syntax-export-extensions/README.md index 97e99ccd3b30..fc2dc569d6e5 100644 --- a/packages/babel-plugin-syntax-export-extensions/README.md +++ b/packages/babel-plugin-syntax-export-extensions/README.md @@ -5,7 +5,7 @@ Allow parsing of export extensions. ## Installation ```sh -$ npm install babel-plugin-syntax-export-extensions +npm install --save-dev babel-plugin-syntax-export-extensions ``` ## Usage @@ -23,7 +23,7 @@ $ npm install babel-plugin-syntax-export-extensions ### Via CLI ```sh -$ babel --plugins syntax-export-extensions script.js +babel --plugins syntax-export-extensions script.js ``` ### Via Node API diff --git a/packages/babel-plugin-syntax-flow/README.md b/packages/babel-plugin-syntax-flow/README.md index 0e4691f553e6..77bf2cc8413b 100644 --- a/packages/babel-plugin-syntax-flow/README.md +++ b/packages/babel-plugin-syntax-flow/README.md @@ -5,7 +5,7 @@ ## Installation ```sh -$ npm install babel-plugin-syntax-flow +npm install --save-dev babel-plugin-syntax-flow ``` ## Usage @@ -23,7 +23,7 @@ $ npm install babel-plugin-syntax-flow ### Via CLI ```sh -$ babel --plugins syntax-flow script.js +babel --plugins syntax-flow script.js ``` ### Via Node API diff --git a/packages/babel-plugin-syntax-function-bind/README.md b/packages/babel-plugin-syntax-function-bind/README.md index aa133ea9e45c..1a86b7fdfb51 100644 --- a/packages/babel-plugin-syntax-function-bind/README.md +++ b/packages/babel-plugin-syntax-function-bind/README.md @@ -5,7 +5,7 @@ Allow parsing of function bind. ## Installation ```sh -$ npm install babel-plugin-syntax-function-bind +npm install --save-dev babel-plugin-syntax-function-bind ``` ## Usage @@ -23,7 +23,7 @@ $ npm install babel-plugin-syntax-function-bind ### Via CLI ```sh -$ babel --plugins syntax-function-bind script.js +babel --plugins syntax-function-bind script.js ``` ### Via Node API diff --git a/packages/babel-plugin-syntax-function-sent/README.md b/packages/babel-plugin-syntax-function-sent/README.md index 4493d7ccda3f..e1ed3e3b72b8 100644 --- a/packages/babel-plugin-syntax-function-sent/README.md +++ b/packages/babel-plugin-syntax-function-sent/README.md @@ -5,7 +5,7 @@ Allow parsing of the `function.sent` meta property. ## Installation ```sh -$ npm install babel-plugin-syntax-function-sent +npm install --save-dev babel-plugin-syntax-function-sent ``` ## Usage @@ -23,7 +23,7 @@ $ npm install babel-plugin-syntax-function-sent ### Via CLI ```sh -$ babel --plugins syntax-function-sent script.js +babel --plugins syntax-function-sent script.js ``` ### Via Node API diff --git a/packages/babel-plugin-syntax-jsx/README.md b/packages/babel-plugin-syntax-jsx/README.md index e8c7e6b5fc9b..006107b523ff 100644 --- a/packages/babel-plugin-syntax-jsx/README.md +++ b/packages/babel-plugin-syntax-jsx/README.md @@ -5,7 +5,7 @@ ## Installation ```sh -$ npm install babel-plugin-syntax-jsx +npm install --save-dev babel-plugin-syntax-jsx ``` ## Usage @@ -23,7 +23,7 @@ $ npm install babel-plugin-syntax-jsx ### Via CLI ```sh -$ babel --plugins syntax-jsx script.js +babel --plugins syntax-jsx script.js ``` ### Via Node API diff --git a/packages/babel-plugin-syntax-object-rest-spread/README.md b/packages/babel-plugin-syntax-object-rest-spread/README.md index 59392f71a42b..9cec118a07f9 100644 --- a/packages/babel-plugin-syntax-object-rest-spread/README.md +++ b/packages/babel-plugin-syntax-object-rest-spread/README.md @@ -5,7 +5,7 @@ Allow parsing of object rest/spread. ## Installation ```sh -$ npm install babel-plugin-syntax-object-rest-spread +npm install --save-dev babel-plugin-syntax-object-rest-spread ``` ## Usage @@ -23,7 +23,7 @@ $ npm install babel-plugin-syntax-object-rest-spread ### Via CLI ```sh -$ babel --plugins syntax-object-rest-spread script.js +babel --plugins syntax-object-rest-spread script.js ``` ### Via Node API diff --git a/packages/babel-plugin-syntax-trailing-function-commas/.npmignore b/packages/babel-plugin-syntax-trailing-function-commas/.npmignore index cace0d6ddcdd..31852902b187 100644 --- a/packages/babel-plugin-syntax-trailing-function-commas/.npmignore +++ b/packages/babel-plugin-syntax-trailing-function-commas/.npmignore @@ -1,3 +1,4 @@ node_modules *.log src +test diff --git a/packages/babel-plugin-syntax-trailing-function-commas/README.md b/packages/babel-plugin-syntax-trailing-function-commas/README.md index 61e15051e0b6..fd7022b23fdf 100644 --- a/packages/babel-plugin-syntax-trailing-function-commas/README.md +++ b/packages/babel-plugin-syntax-trailing-function-commas/README.md @@ -2,10 +2,92 @@ Compile trailing function commas to ES5 + +```js +function clownPuppiesEverywhere( + param1, + param2, +) { /* ... */ } + +clownPuppiesEverywhere( + 'foo', + 'bar', +); +``` +[Try in REPL](http://babeljs.io/repl/#?evaluate=true&presets=es2015%2Cstage-0&code=function%20clownPuppiesEverywhere(%0A%20%20param1%2C%0A%20%20param2%2C%0A)%20%7B%20%2F*%20...%20*%2F%20%7D%0A%0AclownPuppiesEverywhere(%0A%20%20'foo'%2C%0A%20%20'bar'%2C%0A)%3B) + +## Example + +### Basic +This is an example from the [Proposal](https://github.com/jeffmo/es-trailing-function-commas). + +Let's say you have this function: + +```js +function clownPuppiesEverywhere( + param1, + param2 +) { /* ... */ } + +clownPuppiesEverywhere( + 'foo', + 'bar' +); +``` + +If you want to have a new parameter called `param3`, the diff output would be like that: + +```diff +function clownPuppiesEverywhere( + param1, +- param2 ++ param2, // Change this line to add a comma ++ param3 // Add param3 +) { /* ... */ } + +clownPuppiesEverywhere( + 'foo', +- 'bar' ++ 'bar', // Change this line to add a comma ++ 'baz' // Add param3 +); +``` +In total, you have to change 2 lines for the function declaration and 2 lines for each usage. + +If you had your function defined with trailing commas: + +```js +function clownPuppiesEverywhere( + param1, + param2, +) { /* ... */ } + +clownPuppiesEverywhere( + 'foo', + 'bar', +); +``` +Adding a new parameter would only change one line in the function declaration and one line for each usage: + +```diff +function clownPuppiesEverywhere( + param1, + param2, ++ param3, // Add param3 +) { /* ... */ } + +clownPuppiesEverywhere( + 'foo', + 'bar', ++ 'baz', // Add param3 +); +``` +In the end, your diff output will be cleaner and easier to read, it would be much quicker to add a new parameter to your functions, it also makes it easier to copy paste elements and move code around. + ## Installation ```sh -$ npm install babel-plugin-syntax-trailing-function-commas +npm install --save-dev babel-plugin-syntax-trailing-function-commas ``` ## Usage @@ -23,7 +105,7 @@ $ npm install babel-plugin-syntax-trailing-function-commas ### Via CLI ```sh -$ babel --plugins syntax-trailing-function-commas script.js +babel --plugins syntax-trailing-function-commas script.js ``` ### Via Node API @@ -33,3 +115,9 @@ require("babel-core").transform("code", { plugins: ["syntax-trailing-function-commas"] }); ``` + +## References + +* [Proposal](https://github.com/jeffmo/es-trailing-function-commas) +* [Spec](http://jeffmo.github.io/es-trailing-function-commas/) +* [Why you should enforce Dangling Commas for Multiline Statements](https://medium.com/@nikgraf/why-you-should-enforce-dangling-commas-for-multiline-statements-d034c98e36f8) diff --git a/packages/babel-plugin-syntax-trailing-function-commas/package.json b/packages/babel-plugin-syntax-trailing-function-commas/package.json index 076e23337e8a..74d448be81b3 100644 --- a/packages/babel-plugin-syntax-trailing-function-commas/package.json +++ b/packages/babel-plugin-syntax-trailing-function-commas/package.json @@ -1,6 +1,6 @@ { "name": "babel-plugin-syntax-trailing-function-commas", - "version": "6.13.0", + "version": "6.20.0", "description": "Compile trailing function commas to ES5", "repository": "https://github.com/babel/babel/tree/master/packages/babel-plugin-syntax-trailing-function-commas", "license": "MIT", diff --git a/packages/babel-plugin-transform-async-functions/README.md b/packages/babel-plugin-transform-async-functions/README.md index 204eabd515e9..3ee23321aec8 100644 --- a/packages/babel-plugin-transform-async-functions/README.md +++ b/packages/babel-plugin-transform-async-functions/README.md @@ -5,7 +5,7 @@ Compile async functions to ES5 ## Installation ```sh -$ npm install babel-plugin-transform-async-functions +npm install --save-dev babel-plugin-transform-async-functions ``` ## Usage @@ -23,7 +23,7 @@ $ npm install babel-plugin-transform-async-functions ### Via CLI ```sh -$ babel --plugins transform-async-functions script.js +babel --plugins transform-async-functions script.js ``` ### Via Node API diff --git a/packages/babel-plugin-transform-async-generator-functions/README.md b/packages/babel-plugin-transform-async-generator-functions/README.md index 33cbd52888b7..e8388bbb7cde 100644 --- a/packages/babel-plugin-transform-async-generator-functions/README.md +++ b/packages/babel-plugin-transform-async-generator-functions/README.md @@ -1,11 +1,79 @@ # babel-plugin-transform-async-generator-functions -Turn async generator functions and for-await statements to ES2015 generators +> Turn async generator functions and for-await statements to ES2015 generators + +## Example + +**In** + +```javascript +async function* agf() { + await 1; + yield 2; +} +``` + +**Out** + +```javascript +var _asyncGenerator = ... + +let agf = (() => { + var _ref = _asyncGenerator.wrap(function* () { + yield _asyncGenerator.await(1); + yield 2; + }); + + return function agf() { + return _ref.apply(this, arguments); + }; +})(); +``` + +For await example + +```js +async function f() { + for await (let x of y) { + g(x); + } +} +``` + +**Example Usage** + +```js +async function* genAnswers() { + var stream = [ Promise.resolve(4), Promise.resolve(9), Promise.resolve(12) ]; + var total = 0; + for await (let val of stream) { + total += await val; + yield total; + } +} + +function forEach(ai, fn) { + return ai.next().then(function (r) { + if (!r.done) { + fn(r); + return forEach(ai, fn); + } + }); +} + +var output = 0; +forEach(genAnswers(), function(val) { output += val.value }) +.then(function () { + console.log(output); // 42 +}); +``` + +[Try it Out in the REPL](https://babeljs.io/repl/#?babili=false&evaluate=true&lineWrap=false&presets=stage-3&code=async%20function*%20genAnswers()%20%7B%0A%20%20var%20stream%20%3D%20%5B%20Promise.resolve(4)%2C%20Promise.resolve(9)%2C%20Promise.resolve(12)%20%5D%3B%0A%20%20var%20total%20%3D%200%3B%0A%20%20for%20await%20(let%20val%20of%20stream)%20%7B%0A%20%20%20%20total%20%2B%3D%20await%20val%3B%0A%20%20%20%20yield%20total%3B%0A%20%20%7D%0A%7D%0A%0Afunction%20forEach(ai%2C%20fn)%20%7B%0A%20%20return%20ai.next().then(function%20(r)%20%7B%0A%20%20%20%20if%20(!r.done)%20%7B%0A%20%20%20%20%20%20fn(r)%3B%0A%20%20%20%20%20%20return%20forEach(ai%2C%20fn)%3B%0A%20%20%20%20%7D%0A%20%20%7D)%3B%0A%7D%0A%0Avar%20output%20%3D%200%3B%0AforEach(genAnswers()%2C%20function(val)%20%7B%20output%20%2B%3D%20val.value%20%7D)%0A.then(function%20()%20%7B%0A%20%20console.log(output)%3B%20%2F%2F%2042%0A%7D)%3B&experimental=true&loose=false&spec=false&playground=true&stage=0) ## Installation ```sh -$ npm install babel-plugin-transform-async-generator-functions +npm install --save-dev babel-plugin-transform-async-generator-functions ``` ## Usage @@ -23,7 +91,7 @@ $ npm install babel-plugin-transform-async-generator-functions ### Via CLI ```sh -$ babel --plugins transform-async-generator-functions script.js +babel --plugins transform-async-generator-functions script.js ``` ### Via Node API @@ -33,3 +101,7 @@ require("babel-core").transform("code", { plugins: ["transform-async-generator-functions"] }); ``` + +## References + +* [Proposal: Asynchronous iteration for ECMAScript](https://github.com/tc39/proposal-async-iteration) diff --git a/packages/babel-plugin-transform-async-generator-functions/test/fixtures/nested/async-in-params/expected.js b/packages/babel-plugin-transform-async-generator-functions/test/fixtures/nested/async-in-params/expected.js index 4ad05ddcfacf..bd04572e8aa0 100644 --- a/packages/babel-plugin-transform-async-generator-functions/test/fixtures/nested/async-in-params/expected.js +++ b/packages/babel-plugin-transform-async-generator-functions/test/fixtures/nested/async-in-params/expected.js @@ -6,7 +6,7 @@ let g = (() => { yield 3; }); - return function g(_x) { + return function g() { return _ref.apply(this, arguments); }; })(); diff --git a/packages/babel-plugin-transform-async-to-generator/README.md b/packages/babel-plugin-transform-async-to-generator/README.md index b9b6f1d1af73..8f50b7a818f4 100644 --- a/packages/babel-plugin-transform-async-to-generator/README.md +++ b/packages/babel-plugin-transform-async-to-generator/README.md @@ -1,11 +1,32 @@ # babel-plugin-transform-async-to-generator -Turn async functions into ES2015 generators +> Turn async functions into ES2015 generators + +## Example + +**In** + +```javascript +async function foo() { + await bar(); +} +``` + +**Out** + +```javascript +var _asyncToGenerator = function (fn) { + ... +}; +var foo = _asyncToGenerator(function* () { + yield bar(); +}); +``` ## Installation ```sh -$ npm install babel-plugin-transform-async-to-generator +npm install --save-dev babel-plugin-transform-async-to-generator ``` ## Usage @@ -23,7 +44,7 @@ $ npm install babel-plugin-transform-async-to-generator ### Via CLI ```sh -$ babel --plugins transform-async-to-generator script.js +babel --plugins transform-async-to-generator script.js ``` ### Via Node API @@ -33,3 +54,7 @@ require("babel-core").transform("code", { plugins: ["transform-async-to-generator"] }); ``` + +## References + +* [Proposal: Async Functions for ECMAScript](https://github.com/tc39/ecmascript-asyncawait) diff --git a/packages/babel-plugin-transform-async-to-generator/test/fixtures/async-to-generator/async-arrow-in-method/actual.js b/packages/babel-plugin-transform-async-to-generator/test/fixtures/async-to-generator/async-arrow-in-method/actual.js index 7855375f121a..382e756db698 100644 --- a/packages/babel-plugin-transform-async-to-generator/test/fixtures/async-to-generator/async-arrow-in-method/actual.js +++ b/packages/babel-plugin-transform-async-to-generator/test/fixtures/async-to-generator/async-arrow-in-method/actual.js @@ -1,10 +1,10 @@ -let TestClass = { - name: "John Doe", - - testMethodFailure() { - return new Promise(async (resolve) => { - console.log(this); - setTimeout(resolve, 1000); - }); - } -}; +let TestClass = { + name: "John Doe", + + testMethodFailure() { + return new Promise(async (resolve) => { + console.log(this); + setTimeout(resolve, 1000); + }); + } +}; diff --git a/packages/babel-plugin-transform-async-to-generator/test/fixtures/async-to-generator/function-arity/actual.js b/packages/babel-plugin-transform-async-to-generator/test/fixtures/async-to-generator/function-arity/actual.js new file mode 100644 index 000000000000..a08e67e7f33a --- /dev/null +++ b/packages/babel-plugin-transform-async-to-generator/test/fixtures/async-to-generator/function-arity/actual.js @@ -0,0 +1,6 @@ +async function one(a, b = 1) {} +async function two(a, b, ...c) {} +async function three(a, b = 1, c, d = 3) {} +async function four(a, b = 1, c, ...d) {} +async function five(a, {b}){} +async function six(a, {b} = {}){} diff --git a/packages/babel-plugin-transform-async-to-generator/test/fixtures/async-to-generator/function-arity/expected.js b/packages/babel-plugin-transform-async-to-generator/test/fixtures/async-to-generator/function-arity/expected.js new file mode 100644 index 000000000000..e74b618424d4 --- /dev/null +++ b/packages/babel-plugin-transform-async-to-generator/test/fixtures/async-to-generator/function-arity/expected.js @@ -0,0 +1,47 @@ +let one = (() => { + var _ref = babelHelpers.asyncToGenerator(function* (a, b = 1) {}); + + return function one(_x) { + return _ref.apply(this, arguments); + }; +})(); + +let two = (() => { + var _ref2 = babelHelpers.asyncToGenerator(function* (a, b, ...c) {}); + + return function two(_x2, _x3) { + return _ref2.apply(this, arguments); + }; +})(); + +let three = (() => { + var _ref3 = babelHelpers.asyncToGenerator(function* (a, b = 1, c, d = 3) {}); + + return function three(_x4) { + return _ref3.apply(this, arguments); + }; +})(); + +let four = (() => { + var _ref4 = babelHelpers.asyncToGenerator(function* (a, b = 1, c, ...d) {}); + + return function four(_x5) { + return _ref4.apply(this, arguments); + }; +})(); + +let five = (() => { + var _ref5 = babelHelpers.asyncToGenerator(function* (a, { b }) {}); + + return function five(_x6, _x7) { + return _ref5.apply(this, arguments); + }; +})(); + +let six = (() => { + var _ref6 = babelHelpers.asyncToGenerator(function* (a, { b } = {}) {}); + + return function six(_x8) { + return _ref6.apply(this, arguments); + }; +})(); \ No newline at end of file diff --git a/packages/babel-plugin-transform-async-to-generator/test/fixtures/async-to-generator/function-arity/options.json b/packages/babel-plugin-transform-async-to-generator/test/fixtures/async-to-generator/function-arity/options.json new file mode 100644 index 000000000000..2373e1598fb3 --- /dev/null +++ b/packages/babel-plugin-transform-async-to-generator/test/fixtures/async-to-generator/function-arity/options.json @@ -0,0 +1,6 @@ +{ + "plugins": [ + "transform-async-to-generator", + "external-helpers" + ] +} \ No newline at end of file diff --git a/packages/babel-plugin-transform-async-to-module-method/README.md b/packages/babel-plugin-transform-async-to-module-method/README.md index 4d206746324f..268271a16398 100644 --- a/packages/babel-plugin-transform-async-to-module-method/README.md +++ b/packages/babel-plugin-transform-async-to-module-method/README.md @@ -1,11 +1,31 @@ # babel-plugin-transform-async-to-module-method -Turn async functions into a Bluebird coroutine +> Turn async functions into a Bluebird coroutine + +## Example + +**In** + +```javascript +async function foo() { + await bar(); +} +``` + +**Out** + +```javascript +var Bluebird = require("bluebird"); + +var foo = Bluebird.coroutine(function* () { + yield bar(); +}); +``` ## Installation ```sh -$ npm install babel-plugin-transform-async-to-module-method +npm install --save-dev babel-plugin-transform-async-to-module-method ``` ## Usage @@ -34,7 +54,7 @@ $ npm install babel-plugin-transform-async-to-module-method ### Via CLI ```sh -$ babel --plugins transform-async-to-module-method script.js +babel --plugins transform-async-to-module-method script.js ``` ### Via Node API diff --git a/packages/babel-plugin-transform-class-constructor-call/README.md b/packages/babel-plugin-transform-class-constructor-call/README.md index b06dab710f73..badb23aef9b8 100644 --- a/packages/babel-plugin-transform-class-constructor-call/README.md +++ b/packages/babel-plugin-transform-class-constructor-call/README.md @@ -1,9 +1,71 @@ # babel-plugin-transform-class-constructor-call (deprecated) +> Proposal Withdrawn: can be solved with decorators. + +This plugin allows Babel to transform class constructors. + +It basically allows to use the [new.target](http://mdn.io/new.target) feature on ES2015 classes: + +```js +class Point { + + constructor(x, y) { + this.x = x; + this.y = y; + } + + call constructor(x, y) { + return new Point(x, y); + } + +} + +let p1 = new Point(1, 2); // OK +let p2 = Point(3, 4); // OK +``` +[Try in REPL](http://babeljs.io/repl/#?evaluate=true&presets=es2015%2Cstage-0&code=class%20Point%20%7B%0A%0A%20%20constructor(x%2C%20y)%20%7B%0A%20%20%20%20this.x%20%3D%20x%3B%0A%20%20%20%20this.y%20%3D%20y%3B%0A%20%20%7D%0A%0A%20%20call%20constructor(x%2C%20y)%20%7B%0A%20%20%20%20return%20new%20Point(x%2C%20y)%3B%0A%20%20%7D%0A%0A%7D%0A%0Alet%20p1%20%3D%20new%20Point(1%2C%202)%3B%20%2F%2F%20OK%0Alet%20p2%20%3D%20Point(3%2C%204)%3B%20%2F%2F%20OK) + +## Example + +### Date example +The javascript [Date](http://mdn.io/date) works this way: + +```js +// You can get a Date instance using the new keyword +let now = new Date(); +console.log(now.getMonth()); // Prints '3' +console.log(now.toString()); // Prints 'Mon Apr 11 2016 13:26:07 GMT+0100 (BST)' + +// You can get a string of the current date using Date as a function: +let nowStr = Date(); +console.log(nowStr); // Prints 'Mon Apr 11 2016 13:26:07 GMT+0100 (BST)' +``` + +It is currently possible to implement something like that using [new.target](http://mdn.io/new.target) (see [example in proposal](https://github.com/tc39/ecma262/blob/master/workingdocs/callconstructor.md#motivating-example)) and this new feature makes it available for ES2015 classes. + +A date implementation could be: + +```js +class Date { + constructor() { + // ... + } + + call constructor() { + let date = new Date(); + return date.toString(); + } +} + +let now = new Date(); // Get a Date instance +let nowStr = Date(); // Use the 'call constructor()' part to get a string value of the current date +``` +[Try in REPL](http://babeljs.io/repl/#?evaluate=true&presets=es2015%2Cstage-0&code=class%20Date%20%7B%0A%20%20constructor()%20%7B%0A%20%20%20%20%2F%2F%20...%0A%20%20%7D%0A%0A%20%20call%20constructor()%20%7B%0A%20%20%20%20let%20date%20%3D%20new%20Date()%3B%0A%20%20%20%20return%20date.toString()%3B%0A%20%20%7D%0A%7D%0A%0Alet%20now%20%3D%20new%20Date()%3B%20%2F%2F%20Get%20a%20Date%20instance%0Alet%20nowStr%20%3D%20Date()%3B%20%2F%2F%20Use%20the%20'call%20constructor()'%20part%20to%20get%20a%20string%20value%20of%20the%20current%20date) + ## Installation ```sh -$ npm install babel-plugin-transform-class-constructor-call +npm install --save-dev babel-plugin-transform-class-constructor-call ``` ## Usage @@ -21,7 +83,7 @@ $ npm install babel-plugin-transform-class-constructor-call ### Via CLI ```sh -$ babel --plugins transform-class-constructor-call script.js +babel --plugins transform-class-constructor-call script.js ``` ### Via Node API @@ -31,3 +93,9 @@ require("babel-core").transform("code", { plugins: ["transform-class-constructor-call"] }); ``` + +## References + +* [Inactive Proposals](https://github.com/tc39/proposals/blob/master/inactive-proposals.md) +* [Proposal: Call Constructor](https://github.com/tc39/ecma262/blob/master/workingdocs/callconstructor.md) +* [Blog post: ECMAScript proposal: function-callable classes](http://www.2ality.com/2015/10/call-constructor-esprop.html) diff --git a/packages/babel-plugin-transform-class-properties/README.md b/packages/babel-plugin-transform-class-properties/README.md index 6b66fcc4f8c7..a4c7ea02c03c 100644 --- a/packages/babel-plugin-transform-class-properties/README.md +++ b/packages/babel-plugin-transform-class-properties/README.md @@ -1,9 +1,44 @@ # babel-plugin-transform-class-properties +> This plugin transforms es2015 static class properties as well as properties declared with the es2016 property initializer syntax. + +## Example + +Below is a class with four class properties which will be transformed. + +```js + class Bork { + //Property initializer syntax + instanceProperty = "bork"; + boundFunction = () => { + return this.instanceProperty; + } + + //Static class properties + static staticProperty = "babeliscool"; + static staticFunction = function() { + return Bork.staticProperty; + } + } + + let myBork = new Bork; + + //Property initializers are not on the prototype. + console.log(myBork.prototype.boundFunction); // > undefined + + //Bound functions are bound to the class instance. + console.log(myBork.boundFunction.call(undefined)); // > "bork" + + //Static function exists on the class. + console.log(Bork.staticFunction()); // > "babelIsCool" +``` + +[Try in REPL](http://babeljs.io/repl/#?babili=false&evaluate=false&lineWrap=false&presets=es2016%2Clatest%2Cstage-2&code=%20%20class%20Bork%20%7B%0A%20%20%20%20%2F%2FProperty%20initilizer%20syntax%0A%20%20%20%20instanceProperty%20%3D%20%22bork%22%3B%0A%20%20%20%20boundFunction%20%3D%20()%20%3D%3E%20%7B%0A%20%20%20%20%20%20return%20this.instanceProperty%3B%0A%20%20%20%20%7D%0A%20%20%20%20%0A%20%20%20%20%2F%2FStatic%20class%20properties%0A%20%20%20%20static%20staticProperty%20%3D%20%22babeliscool%22%3B%0A%20%20%20%20static%20staticFunction%20%3D%20function()%20%7B%0A%20%20%20%20%20%20return%20Bork.staticProperty%3B%0A%20%20%20%20%7D%0A%20%20%7D%0A%0A%20%20let%20myBork%20%3D%20new%20Bork%3B%0A%0A%20%20%2F%2FProperty%20initializers%20are%20not%20on%20the%20prototype.%0A%20%20console.log(Bork.prototype.boundFunction)%3B%20%2F%2F%20%3E%20undefined%0A%0A%20%20%2F%2FBound%20functions%20are%20bound%20to%20the%20class%20instance.%0A%20%20console.log(myBork.boundFunction.call(undefined))%3B%20%2F%2F%20%3E%20%22bork%22%0A%0A%20%20%2F%2FStatic%20function%20exists%20on%20the%20class.%0A%20%20console.log(Bork.staticFunction())%3B%20%2F%2F%20%3E%20%22babelIsCool%22) + ## Installation ```sh -$ npm install babel-plugin-transform-class-properties +npm install --save-dev babel-plugin-transform-class-properties ``` ## Usage @@ -13,15 +48,23 @@ $ npm install babel-plugin-transform-class-properties **.babelrc** ```json +// without options { "plugins": ["transform-class-properties"] } + +// with options +{ + "plugins": [ + ["transform-class-properties", { "spec": true }] + ] +} ``` ### Via CLI ```sh -$ babel --plugins transform-class-properties script.js +babel --plugins transform-class-properties script.js ``` ### Via Node API @@ -31,3 +74,11 @@ require("babel-core").transform("code", { plugins: ["transform-class-properties"] }); ``` + +## Options + +* `spec` - Class properties are compiled to use `Object.defineProperty. Static fields are now defined even if they are not initialized + +## References + +* [Proposal: ES Class Fields & Static Properties](https://github.com/jeffmo/es-class-static-properties-and-fields) diff --git a/packages/babel-plugin-transform-class-properties/package.json b/packages/babel-plugin-transform-class-properties/package.json index 5ece9ddc2080..63288d330af6 100644 --- a/packages/babel-plugin-transform-class-properties/package.json +++ b/packages/babel-plugin-transform-class-properties/package.json @@ -1,6 +1,6 @@ { "name": "babel-plugin-transform-class-properties", - "version": "6.18.0", + "version": "6.19.0", "description": "This plugin transforms static class properties as well as properties declared with the property initializer syntax", "repository": "https://github.com/babel/babel/tree/master/packages/babel-plugin-transform-class-properties", "license": "MIT", @@ -11,7 +11,8 @@ "dependencies": { "babel-helper-function-name": "^6.18.0", "babel-plugin-syntax-class-properties": "^6.8.0", - "babel-runtime": "^6.9.1" + "babel-runtime": "^6.9.1", + "babel-template": "^6.15.0" }, "devDependencies": { "babel-helper-plugin-test-runner": "^6.18.0" diff --git a/packages/babel-plugin-transform-class-properties/src/index.js b/packages/babel-plugin-transform-class-properties/src/index.js index 5744b14afc90..10451b377988 100644 --- a/packages/babel-plugin-transform-class-properties/src/index.js +++ b/packages/babel-plugin-transform-class-properties/src/index.js @@ -1,6 +1,6 @@ /* eslint max-len: 0 */ -// todo: define instead of assign import nameFunction from "babel-helper-function-name"; +import template from "babel-template"; export default function ({ types: t }) { let findBareSupers = { @@ -20,11 +20,31 @@ export default function ({ types: t }) { } }; + const buildObjectDefineProperty = template(` + Object.defineProperty(REF, KEY, { + // configurable is false by default + enumerable: true, + writable: true, + value: VALUE + }); + `); + + const buildClassPropertySpec = (ref, {key, value, computed}) => buildObjectDefineProperty({ + REF: ref, + KEY: (t.isIdentifier(key) && !computed) ? t.stringLiteral(key.name) : key, + VALUE: value ? value : t.identifier("undefined") + }); + + const buildClassPropertyNonSpec = (ref, {key, value, computed}) => t.expressionStatement( + t.assignmentExpression("=", t.memberExpression(ref, key, computed || t.isLiteral(key)), value) + ); + return { inherits: require("babel-plugin-syntax-class-properties"), visitor: { - Class(path) { + Class(path, state) { + const buildClassProperty = state.opts.spec ? buildClassPropertySpec : buildClassPropertyNonSpec; let isDerived = !!path.node.superClass; let constructor; let props = []; @@ -55,19 +75,18 @@ export default function ({ types: t }) { for (let prop of props) { let propNode = prop.node; if (propNode.decorators && propNode.decorators.length > 0) continue; - if (!propNode.value) continue; + + // In non-spec mode, all properties without values are ignored. + // In spec mode, *static* properties without values are still defined (see below). + if (!state.opts.spec && !propNode.value) continue; let isStatic = propNode.static; - let isComputed = propNode.computed || t.isLiteral(prop.key); if (isStatic) { - nodes.push(t.expressionStatement( - t.assignmentExpression("=", t.memberExpression(ref, propNode.key, isComputed), propNode.value) - )); + nodes.push(buildClassProperty(ref, propNode)); } else { - instanceBody.push(t.expressionStatement( - t.assignmentExpression("=", t.memberExpression(t.thisExpression(), propNode.key, isComputed), propNode.value) - )); + if (!propNode.value) continue; // Ignore instance property with no value in spec mode + instanceBody.push(buildClassProperty(t.thisExpression(), propNode)); } } diff --git a/packages/babel-plugin-transform-class-properties/test/fixtures/spec/constructor-collision/actual.js b/packages/babel-plugin-transform-class-properties/test/fixtures/spec/constructor-collision/actual.js new file mode 100644 index 000000000000..3bf6c834720f --- /dev/null +++ b/packages/babel-plugin-transform-class-properties/test/fixtures/spec/constructor-collision/actual.js @@ -0,0 +1,9 @@ +var foo = "bar"; + +class Foo { + bar = foo; + + constructor() { + var foo = "foo"; + } +} diff --git a/packages/babel-plugin-transform-class-properties/test/fixtures/spec/constructor-collision/expected.js b/packages/babel-plugin-transform-class-properties/test/fixtures/spec/constructor-collision/expected.js new file mode 100644 index 000000000000..0b239c656791 --- /dev/null +++ b/packages/babel-plugin-transform-class-properties/test/fixtures/spec/constructor-collision/expected.js @@ -0,0 +1,17 @@ +var foo = "bar"; + +var Foo = function Foo() { + babelHelpers.classCallCheck(this, Foo); + + _initialiseProps.call(this); + + var foo = "foo"; +}; + +var _initialiseProps = function () { + Object.defineProperty(this, "bar", { + enumerable: true, + writable: true, + value: foo + }); +}; diff --git a/packages/babel-plugin-transform-class-properties/test/fixtures/spec/derived/actual.js b/packages/babel-plugin-transform-class-properties/test/fixtures/spec/derived/actual.js new file mode 100644 index 000000000000..cd8e3fdd8031 --- /dev/null +++ b/packages/babel-plugin-transform-class-properties/test/fixtures/spec/derived/actual.js @@ -0,0 +1,3 @@ +class Foo extends Bar { + bar = "foo"; +} diff --git a/packages/babel-plugin-transform-class-properties/test/fixtures/spec/derived/expected.js b/packages/babel-plugin-transform-class-properties/test/fixtures/spec/derived/expected.js new file mode 100644 index 000000000000..f2cd75235023 --- /dev/null +++ b/packages/babel-plugin-transform-class-properties/test/fixtures/spec/derived/expected.js @@ -0,0 +1,16 @@ +var Foo = function (_Bar) { + babelHelpers.inherits(Foo, _Bar); + + function Foo(...args) { + var _temp, _this, _ret; + + babelHelpers.classCallCheck(this, Foo); + return _ret = (_temp = (_this = babelHelpers.possibleConstructorReturn(this, (Foo.__proto__ || Object.getPrototypeOf(Foo)).call(this, ...args)), _this), Object.defineProperty(_this, "bar", { + enumerable: true, + writable: true, + value: "foo" + }), _temp), babelHelpers.possibleConstructorReturn(_this, _ret); + } + + return Foo; +}(Bar); diff --git a/packages/babel-plugin-transform-class-properties/test/fixtures/spec/foobar/actual.js b/packages/babel-plugin-transform-class-properties/test/fixtures/spec/foobar/actual.js new file mode 100644 index 000000000000..60a1c5e823cd --- /dev/null +++ b/packages/babel-plugin-transform-class-properties/test/fixtures/spec/foobar/actual.js @@ -0,0 +1,9 @@ +class Child extends Parent { + constructor() { + super(); + } + + scopedFunctionWithThis = () => { + this.name = {}; + } +} diff --git a/packages/babel-plugin-transform-class-properties/test/fixtures/spec/foobar/expected.js b/packages/babel-plugin-transform-class-properties/test/fixtures/spec/foobar/expected.js new file mode 100644 index 000000000000..f03f62503423 --- /dev/null +++ b/packages/babel-plugin-transform-class-properties/test/fixtures/spec/foobar/expected.js @@ -0,0 +1,22 @@ +"use strict"; + +var Child = function (_Parent) { + babelHelpers.inherits(Child, _Parent); + + function Child() { + babelHelpers.classCallCheck(this, Child); + + var _this = babelHelpers.possibleConstructorReturn(this, (Child.__proto__ || Object.getPrototypeOf(Child)).call(this)); + + Object.defineProperty(_this, "scopedFunctionWithThis", { + enumerable: true, + writable: true, + value: function value() { + _this.name = {}; + } + }); + return _this; + } + + return Child; +}(Parent); diff --git a/packages/babel-plugin-transform-class-properties/test/fixtures/spec/foobar/options.json b/packages/babel-plugin-transform-class-properties/test/fixtures/spec/foobar/options.json new file mode 100644 index 000000000000..a9cbc232a33b --- /dev/null +++ b/packages/babel-plugin-transform-class-properties/test/fixtures/spec/foobar/options.json @@ -0,0 +1,4 @@ +{ + "plugins": ["external-helpers", ["transform-class-properties", { "spec": true }]], + "presets": ["stage-0", "es2015"] +} diff --git a/packages/babel-plugin-transform-class-properties/test/fixtures/spec/instance-undefined/actual.js b/packages/babel-plugin-transform-class-properties/test/fixtures/spec/instance-undefined/actual.js new file mode 100644 index 000000000000..a36cdd975c82 --- /dev/null +++ b/packages/babel-plugin-transform-class-properties/test/fixtures/spec/instance-undefined/actual.js @@ -0,0 +1,3 @@ +class Foo { + bar; +} diff --git a/packages/babel-plugin-transform-class-properties/test/fixtures/spec/instance-undefined/expected.js b/packages/babel-plugin-transform-class-properties/test/fixtures/spec/instance-undefined/expected.js new file mode 100644 index 000000000000..4f46d4a64230 --- /dev/null +++ b/packages/babel-plugin-transform-class-properties/test/fixtures/spec/instance-undefined/expected.js @@ -0,0 +1,3 @@ +var Foo = function Foo() { + babelHelpers.classCallCheck(this, Foo); +}; diff --git a/packages/babel-plugin-transform-class-properties/test/fixtures/spec/instance/actual.js b/packages/babel-plugin-transform-class-properties/test/fixtures/spec/instance/actual.js new file mode 100644 index 000000000000..9cecfe8a3013 --- /dev/null +++ b/packages/babel-plugin-transform-class-properties/test/fixtures/spec/instance/actual.js @@ -0,0 +1,3 @@ +class Foo { + bar = "foo"; +} diff --git a/packages/babel-plugin-transform-class-properties/test/fixtures/spec/instance/expected.js b/packages/babel-plugin-transform-class-properties/test/fixtures/spec/instance/expected.js new file mode 100644 index 000000000000..912039e90064 --- /dev/null +++ b/packages/babel-plugin-transform-class-properties/test/fixtures/spec/instance/expected.js @@ -0,0 +1,8 @@ +var Foo = function Foo() { + babelHelpers.classCallCheck(this, Foo); + Object.defineProperty(this, "bar", { + enumerable: true, + writable: true, + value: "foo" + }); +}; diff --git a/packages/babel-plugin-transform-class-properties/test/fixtures/spec/non-block-arrow-func/actual.js b/packages/babel-plugin-transform-class-properties/test/fixtures/spec/non-block-arrow-func/actual.js new file mode 100644 index 000000000000..4b67e0e158f6 --- /dev/null +++ b/packages/babel-plugin-transform-class-properties/test/fixtures/spec/non-block-arrow-func/actual.js @@ -0,0 +1,11 @@ +export default param => + class App { + static props = { + prop1: 'prop1', + prop2: 'prop2' + } + + getParam() { + return param; + } + } diff --git a/packages/babel-plugin-transform-class-properties/test/fixtures/spec/non-block-arrow-func/expected.js b/packages/babel-plugin-transform-class-properties/test/fixtures/spec/non-block-arrow-func/expected.js new file mode 100644 index 000000000000..977b45abfb1c --- /dev/null +++ b/packages/babel-plugin-transform-class-properties/test/fixtures/spec/non-block-arrow-func/expected.js @@ -0,0 +1,24 @@ +export default (param => { + var _class, _temp; + + return _temp = _class = function () { + function App() { + babelHelpers.classCallCheck(this, App); + } + + babelHelpers.createClass(App, [{ + key: 'getParam', + value: function getParam() { + return param; + } + }]); + return App; + }(), Object.defineProperty(_class, 'props', { + enumerable: true, + writable: true, + value: { + prop1: 'prop1', + prop2: 'prop2' + } + }), _temp; +}); diff --git a/packages/babel-plugin-transform-class-properties/test/fixtures/spec/options.json b/packages/babel-plugin-transform-class-properties/test/fixtures/spec/options.json new file mode 100644 index 000000000000..31ab836c1e9d --- /dev/null +++ b/packages/babel-plugin-transform-class-properties/test/fixtures/spec/options.json @@ -0,0 +1,3 @@ +{ + "plugins": ["external-helpers", ["transform-class-properties", { "spec": true }], "transform-es2015-classes", "transform-es2015-block-scoping", "syntax-class-properties"] +} diff --git a/packages/babel-plugin-transform-class-properties/test/fixtures/spec/regression-T2983/actual.js b/packages/babel-plugin-transform-class-properties/test/fixtures/spec/regression-T2983/actual.js new file mode 100644 index 000000000000..2961c9a40366 --- /dev/null +++ b/packages/babel-plugin-transform-class-properties/test/fixtures/spec/regression-T2983/actual.js @@ -0,0 +1,7 @@ +call(class { + static test = true +}); + +export default class { + static test = true +}; diff --git a/packages/babel-plugin-transform-class-properties/test/fixtures/spec/regression-T2983/expected.js b/packages/babel-plugin-transform-class-properties/test/fixtures/spec/regression-T2983/expected.js new file mode 100644 index 000000000000..e146566f95b8 --- /dev/null +++ b/packages/babel-plugin-transform-class-properties/test/fixtures/spec/regression-T2983/expected.js @@ -0,0 +1,21 @@ +var _class, _temp; + +call((_temp = _class = function _class() { + babelHelpers.classCallCheck(this, _class); +}, Object.defineProperty(_class, "test", { + enumerable: true, + writable: true, + value: true +}), _temp)); + +var _class2 = function _class2() { + babelHelpers.classCallCheck(this, _class2); +}; + +Object.defineProperty(_class2, "test", { + enumerable: true, + writable: true, + value: true +}); +export default _class2; +; diff --git a/packages/babel-plugin-transform-class-properties/test/fixtures/spec/regression-T6719/actual.js b/packages/babel-plugin-transform-class-properties/test/fixtures/spec/regression-T6719/actual.js new file mode 100644 index 000000000000..38b9e80baecc --- /dev/null +++ b/packages/babel-plugin-transform-class-properties/test/fixtures/spec/regression-T6719/actual.js @@ -0,0 +1,14 @@ +function withContext(ComposedComponent) { + return class WithContext extends Component { + + static propTypes = { + context: PropTypes.shape( + { + addCss: PropTypes.func, + setTitle: PropTypes.func, + setMeta: PropTypes.func, + } + ), + }; + }; +} diff --git a/packages/babel-plugin-transform-class-properties/test/fixtures/spec/regression-T6719/expected.js b/packages/babel-plugin-transform-class-properties/test/fixtures/spec/regression-T6719/expected.js new file mode 100644 index 000000000000..4ecdd4777431 --- /dev/null +++ b/packages/babel-plugin-transform-class-properties/test/fixtures/spec/regression-T6719/expected.js @@ -0,0 +1,24 @@ +function withContext(ComposedComponent) { + var _class, _temp; + + return _temp = _class = function (_Component) { + babelHelpers.inherits(WithContext, _Component); + + function WithContext() { + babelHelpers.classCallCheck(this, WithContext); + return babelHelpers.possibleConstructorReturn(this, (WithContext.__proto__ || Object.getPrototypeOf(WithContext)).apply(this, arguments)); + } + + return WithContext; + }(Component), Object.defineProperty(_class, "propTypes", { + enumerable: true, + writable: true, + value: { + context: PropTypes.shape({ + addCss: PropTypes.func, + setTitle: PropTypes.func, + setMeta: PropTypes.func + }) + } + }), _temp; +} diff --git a/packages/babel-plugin-transform-class-properties/test/fixtures/spec/regression-T7364/actual.js b/packages/babel-plugin-transform-class-properties/test/fixtures/spec/regression-T7364/actual.js new file mode 100644 index 000000000000..1ddb4a1e7887 --- /dev/null +++ b/packages/babel-plugin-transform-class-properties/test/fixtures/spec/regression-T7364/actual.js @@ -0,0 +1,17 @@ +class MyClass { + myAsyncMethod = async () => { + console.log(this); + } +} + +(class MyClass2 { + myAsyncMethod = async () => { + console.log(this); + } +}) + +export default class MyClass3 { + myAsyncMethod = async () => { + console.log(this); + } +} diff --git a/packages/babel-plugin-transform-class-properties/test/fixtures/spec/regression-T7364/expected.js b/packages/babel-plugin-transform-class-properties/test/fixtures/spec/regression-T7364/expected.js new file mode 100644 index 000000000000..74a4cbc036f1 --- /dev/null +++ b/packages/babel-plugin-transform-class-properties/test/fixtures/spec/regression-T7364/expected.js @@ -0,0 +1,62 @@ +class MyClass { + constructor() { + var _this = this; + + Object.defineProperty(this, "myAsyncMethod", { + enumerable: true, + writable: true, + value: (() => { + var _ref = babelHelpers.asyncToGenerator(function* () { + console.log(_this); + }); + + return function value() { + return _ref.apply(this, arguments); + }; + })() + }); + } + +} + +(class MyClass2 { + constructor() { + var _this2 = this; + + Object.defineProperty(this, "myAsyncMethod", { + enumerable: true, + writable: true, + value: (() => { + var _ref2 = babelHelpers.asyncToGenerator(function* () { + console.log(_this2); + }); + + return function value() { + return _ref2.apply(this, arguments); + }; + })() + }); + } + +}); + +export default class MyClass3 { + constructor() { + var _this3 = this; + + Object.defineProperty(this, "myAsyncMethod", { + enumerable: true, + writable: true, + value: (() => { + var _ref3 = babelHelpers.asyncToGenerator(function* () { + console.log(_this3); + }); + + return function value() { + return _ref3.apply(this, arguments); + }; + })() + }); + } + +} diff --git a/packages/babel-plugin-transform-class-properties/test/fixtures/spec/regression-T7364/options.json b/packages/babel-plugin-transform-class-properties/test/fixtures/spec/regression-T7364/options.json new file mode 100644 index 000000000000..3d827b26c954 --- /dev/null +++ b/packages/babel-plugin-transform-class-properties/test/fixtures/spec/regression-T7364/options.json @@ -0,0 +1,7 @@ +{ + "plugins": [ + "external-helpers", + "transform-async-to-generator", + ["transform-class-properties", { "spec": true }] + ] +} diff --git a/packages/babel-plugin-transform-class-properties/test/fixtures/spec/static-export/actual.js b/packages/babel-plugin-transform-class-properties/test/fixtures/spec/static-export/actual.js new file mode 100644 index 000000000000..729475cc52ff --- /dev/null +++ b/packages/babel-plugin-transform-class-properties/test/fixtures/spec/static-export/actual.js @@ -0,0 +1,7 @@ +export class MyClass { + static property = value; +} + +export default class MyClass2 { + static property = value; +} diff --git a/packages/babel-plugin-transform-class-properties/test/fixtures/spec/static-export/expected.js b/packages/babel-plugin-transform-class-properties/test/fixtures/spec/static-export/expected.js new file mode 100644 index 000000000000..3363e3b4cecf --- /dev/null +++ b/packages/babel-plugin-transform-class-properties/test/fixtures/spec/static-export/expected.js @@ -0,0 +1,20 @@ +export var MyClass = function MyClass() { + babelHelpers.classCallCheck(this, MyClass); +}; + +Object.defineProperty(MyClass, "property", { + enumerable: true, + writable: true, + value: value +}); + +var MyClass2 = function MyClass2() { + babelHelpers.classCallCheck(this, MyClass2); +}; + +Object.defineProperty(MyClass2, "property", { + enumerable: true, + writable: true, + value: value +}); +export default MyClass2; diff --git a/packages/babel-plugin-transform-class-properties/test/fixtures/spec/static-infer-name/actual.js b/packages/babel-plugin-transform-class-properties/test/fixtures/spec/static-infer-name/actual.js new file mode 100644 index 000000000000..96f03df576a0 --- /dev/null +++ b/packages/babel-plugin-transform-class-properties/test/fixtures/spec/static-infer-name/actual.js @@ -0,0 +1,3 @@ +var Foo = class { + static num = 0; +} diff --git a/packages/babel-plugin-transform-class-properties/test/fixtures/spec/static-infer-name/exec.js b/packages/babel-plugin-transform-class-properties/test/fixtures/spec/static-infer-name/exec.js new file mode 100644 index 000000000000..b7ecf2f9cb5b --- /dev/null +++ b/packages/babel-plugin-transform-class-properties/test/fixtures/spec/static-infer-name/exec.js @@ -0,0 +1,7 @@ +var Foo = class { + static num = 0; +} + +assert.equal(Foo.num, 0); +assert.equal(Foo.num = 1, 1); +assert.equal(Foo.name, "Foo"); diff --git a/packages/babel-plugin-transform-class-properties/test/fixtures/spec/static-infer-name/expected.js b/packages/babel-plugin-transform-class-properties/test/fixtures/spec/static-infer-name/expected.js new file mode 100644 index 000000000000..78cc38220674 --- /dev/null +++ b/packages/babel-plugin-transform-class-properties/test/fixtures/spec/static-infer-name/expected.js @@ -0,0 +1,9 @@ +var _class, _temp; + +var Foo = (_temp = _class = function Foo() { + babelHelpers.classCallCheck(this, Foo); +}, Object.defineProperty(_class, "num", { + enumerable: true, + writable: true, + value: 0 +}), _temp); diff --git a/packages/babel-plugin-transform-class-properties/test/fixtures/spec/static-undefined/actual.js b/packages/babel-plugin-transform-class-properties/test/fixtures/spec/static-undefined/actual.js new file mode 100644 index 000000000000..4ee31b9c3541 --- /dev/null +++ b/packages/babel-plugin-transform-class-properties/test/fixtures/spec/static-undefined/actual.js @@ -0,0 +1,3 @@ +class Foo { + static bar; +} diff --git a/packages/babel-plugin-transform-class-properties/test/fixtures/spec/static-undefined/exec.js b/packages/babel-plugin-transform-class-properties/test/fixtures/spec/static-undefined/exec.js new file mode 100644 index 000000000000..0771105a6137 --- /dev/null +++ b/packages/babel-plugin-transform-class-properties/test/fixtures/spec/static-undefined/exec.js @@ -0,0 +1,6 @@ +class Foo { + static num; +} + +assert.equal("num" in Foo, true); +assert.equal(Foo.num, undefined); diff --git a/packages/babel-plugin-transform-class-properties/test/fixtures/spec/static-undefined/expected.js b/packages/babel-plugin-transform-class-properties/test/fixtures/spec/static-undefined/expected.js new file mode 100644 index 000000000000..cbdc0a11b6d6 --- /dev/null +++ b/packages/babel-plugin-transform-class-properties/test/fixtures/spec/static-undefined/expected.js @@ -0,0 +1,9 @@ +var Foo = function Foo() { + babelHelpers.classCallCheck(this, Foo); +}; + +Object.defineProperty(Foo, "bar", { + enumerable: true, + writable: true, + value: undefined +}); diff --git a/packages/babel-plugin-transform-class-properties/test/fixtures/spec/static/actual.js b/packages/babel-plugin-transform-class-properties/test/fixtures/spec/static/actual.js new file mode 100644 index 000000000000..ddc637ec2391 --- /dev/null +++ b/packages/babel-plugin-transform-class-properties/test/fixtures/spec/static/actual.js @@ -0,0 +1,3 @@ +class Foo { + static bar = "foo"; +} diff --git a/packages/babel-plugin-transform-class-properties/test/fixtures/spec/static/exec.js b/packages/babel-plugin-transform-class-properties/test/fixtures/spec/static/exec.js new file mode 100644 index 000000000000..299aa7949d6b --- /dev/null +++ b/packages/babel-plugin-transform-class-properties/test/fixtures/spec/static/exec.js @@ -0,0 +1,9 @@ +class Foo { + static num = 0; + static str = "foo"; +} + +assert.equal(Foo.num, 0); +assert.equal(Foo.num = 1, 1); +assert.equal(Foo.str, "foo"); +assert.equal(Foo.str = "bar", "bar"); diff --git a/packages/babel-plugin-transform-class-properties/test/fixtures/spec/static/expected.js b/packages/babel-plugin-transform-class-properties/test/fixtures/spec/static/expected.js new file mode 100644 index 000000000000..78f546364a44 --- /dev/null +++ b/packages/babel-plugin-transform-class-properties/test/fixtures/spec/static/expected.js @@ -0,0 +1,9 @@ +var Foo = function Foo() { + babelHelpers.classCallCheck(this, Foo); +}; + +Object.defineProperty(Foo, "bar", { + enumerable: true, + writable: true, + value: "foo" +}); diff --git a/packages/babel-plugin-transform-class-properties/test/fixtures/spec/super-expression/actual.js b/packages/babel-plugin-transform-class-properties/test/fixtures/spec/super-expression/actual.js new file mode 100644 index 000000000000..222dec81a60c --- /dev/null +++ b/packages/babel-plugin-transform-class-properties/test/fixtures/spec/super-expression/actual.js @@ -0,0 +1,7 @@ +class Foo extends Bar { + bar = "foo"; + + constructor() { + foo(super()); + } +} diff --git a/packages/babel-plugin-transform-class-properties/test/fixtures/spec/super-expression/expected.js b/packages/babel-plugin-transform-class-properties/test/fixtures/spec/super-expression/expected.js new file mode 100644 index 000000000000..78def7939a3f --- /dev/null +++ b/packages/babel-plugin-transform-class-properties/test/fixtures/spec/super-expression/expected.js @@ -0,0 +1,18 @@ +var Foo = function (_Bar) { + babelHelpers.inherits(Foo, _Bar); + + function Foo() { + var _temp, _this; + + babelHelpers.classCallCheck(this, Foo); + + foo((_temp = (_this = babelHelpers.possibleConstructorReturn(this, (Foo.__proto__ || Object.getPrototypeOf(Foo)).call(this)), _this), Object.defineProperty(_this, "bar", { + enumerable: true, + writable: true, + value: "foo" + }), _temp)); + return _this; + } + + return Foo; +}(Bar); diff --git a/packages/babel-plugin-transform-class-properties/test/fixtures/spec/super-statement/actual.js b/packages/babel-plugin-transform-class-properties/test/fixtures/spec/super-statement/actual.js new file mode 100644 index 000000000000..0af8843375d4 --- /dev/null +++ b/packages/babel-plugin-transform-class-properties/test/fixtures/spec/super-statement/actual.js @@ -0,0 +1,7 @@ +class Foo extends Bar { + bar = "foo"; + + constructor() { + super(); + } +} diff --git a/packages/babel-plugin-transform-class-properties/test/fixtures/spec/super-statement/expected.js b/packages/babel-plugin-transform-class-properties/test/fixtures/spec/super-statement/expected.js new file mode 100644 index 000000000000..5050e95e6a8d --- /dev/null +++ b/packages/babel-plugin-transform-class-properties/test/fixtures/spec/super-statement/expected.js @@ -0,0 +1,18 @@ +var Foo = function (_Bar) { + babelHelpers.inherits(Foo, _Bar); + + function Foo() { + babelHelpers.classCallCheck(this, Foo); + + var _this = babelHelpers.possibleConstructorReturn(this, (Foo.__proto__ || Object.getPrototypeOf(Foo)).call(this)); + + Object.defineProperty(_this, "bar", { + enumerable: true, + writable: true, + value: "foo" + }); + return _this; + } + + return Foo; +}(Bar); diff --git a/packages/babel-plugin-transform-decorators/README.md b/packages/babel-plugin-transform-decorators/README.md index 7a0d76196d49..71fee789b477 100644 --- a/packages/babel-plugin-transform-decorators/README.md +++ b/packages/babel-plugin-transform-decorators/README.md @@ -1,11 +1,55 @@ # babel-plugin-transform-decorators -Compile class and object decorators to ES5 +> Compile class and object decorators to ES5 + +## Example + +(examples are from proposal) + +### Simple class decorator + +```js +@annotation +class MyClass { } + +function annotation(target) { + target.annotated = true; +} +``` + +### Class decorator + +```js +@isTestable(true) +class MyClass { } + +function isTestable(value) { + return function decorator(target) { + target.isTestable = value; + } +} +``` + +### Class function decorator + +```js +class C { + @enumerable(false) + method() { } +} + +function enumerable(value) { + return function (target, key, descriptor) { + descriptor.enumerable = value; + return descriptor; + } +} +``` ## Installation ```sh -$ npm install babel-plugin-transform-decorators +npm install --save-dev babel-plugin-transform-decorators ``` ## Usage @@ -23,7 +67,7 @@ $ npm install babel-plugin-transform-decorators ### Via CLI ```sh -$ babel --plugins transform-decorators script.js +babel --plugins transform-decorators script.js ``` ### Via Node API @@ -33,3 +77,7 @@ require("babel-core").transform("code", { plugins: ["transform-decorators"] }); ``` + +## References + +* [Proposal: Javascript Decorators](https://github.com/wycats/javascript-decorators/blob/master/README.md) diff --git a/packages/babel-plugin-transform-do-expressions/README.md b/packages/babel-plugin-transform-do-expressions/README.md index bdf303c85d42..44e252e17da3 100644 --- a/packages/babel-plugin-transform-do-expressions/README.md +++ b/packages/babel-plugin-transform-do-expressions/README.md @@ -1,11 +1,93 @@ # babel-plugin-transform-do-expressions -Compile do expressions to ES5 +> Compile `do` expressions to ES5 + +## Detail + +> The `do { .. }` expression executes a block (with one or many statements in it), and the final statement completion value inside the block becomes the completion value of the do expression. + +from [You Don't Know JS](https://github.com/getify/You-Dont-Know-JS/blob/master/types%20%26%20grammar/ch5.md#statement-completion-values) + +It can be seen as a complex version of the [ternary operator](http://mdn.io/ternary): + +```js +let a = do { + if(x > 10) { + 'big'; + } else { + 'small'; + } +}; +// is equivalent to: +let a = x > 10 ? 'big' : 'small'; +``` + +[Try in REPL](http://babeljs.io/repl/#?evaluate=true&presets=es2015%2Cstage-0&code=%0Alet%20x%20%3D%20100%3B%0A%0Alet%20a%20%3D%20do%20%7B%0A%20%20if(x%20%3E%2010)%20%7B%0A%20%20%20%20'big'%3B%0A%20%20%7D%20else%20%7B%0A%20%20%20%20'small'%3B%0A%20%20%7D%0A%7D%3B%0A%0Aconsole.log(a)%3B) + +This example is not the best usage because it is too simple and using a ternary operator is a better option but you can have a much more complex condition in the `do { ... }` expression with several `if ... else` chains: + +```js +let x = 100; +let y = 20; + +let a = do { + if(x > 10) { + if(y > 20) { + 'big x, big y'; + } else { + 'big x, small y'; + } + } else { + if(y > 10) { + 'small x, big y'; + } else { + 'small x, small y'; + } + } +}; +``` + +[Try in REPL](http://babeljs.io/repl/#?evaluate=true&presets=es2015%2Cstage-0&code=let%20x%20%3D%20100%3B%0Alet%20y%20%3D%2020%3B%0A%0Alet%20a%20%3D%20do%20%7B%0A%20%20if(x%20%3E%2010)%20%7B%0A%20%20%20%20if(y%20%3E%2020)%20%7B%0A%20%20%20%20%20%20'big%20x%2C%20big%20y'%3B%0A%20%20%20%20%7D%20else%20%7B%0A%20%20%20%20%20%20'big%20x%2C%20small%20y'%3B%0A%20%20%20%20%7D%0A%20%20%7D%20else%20%7B%0A%20%20%20%20if(y%20%3E%2010)%20%7B%0A%20%20%20%20%20%20'small%20x%2C%20big%20y'%3B%0A%20%20%20%20%7D%20else%20%7B%0A%20%20%20%20%20%20'small%20x%2C%20small%20y'%3B%0A%20%20%20%20%7D%0A%20%20%7D%0A%7D%3B%0A%0Aconsole.log(a)%3B) + +## Example + +### In JSX +One of the most useful usage of the `do` expression is inside JSX. If we want to conditionally display a component we usually have to call another function which would implement the condition and return the correct value, for example: + +```js +const getColoredComponent = color => { + if(color === 'blue') { return ; } + if(color === 'red') { return ; } + if(color === 'green') { return ; } +} + +const Component = props => +
+ {getColoredComponent()} +
+; +``` + +Using a do expression you can add logic inside JSX: + +```js +const Component = props => +
+ {do { + if(color === 'blue') { ; } + if(color === 'red') { ; } + if(color === 'green') { ; } + }} +
+; +``` + +[Try in REPL](http://babeljs.io/repl/#?evaluate=true&presets=es2015%2Creact%2Cstage-0&code=const%20Component%20%3D%20props%20%3D%3E%0A%20%20%3Cdiv%20className%3D'myComponent'%3E%0A%20%20%20%20%7Bdo%20%7B%0A%20%20%20%20%20%20if(color%20%3D%3D%3D%20'blue')%20%7B%20%3CBlueComponent%2F%3E%3B%20%7D%0A%20%20%20%20%20%20if(color%20%3D%3D%3D%20'red')%20%7B%20%3CRedComponent%2F%3E%3B%20%7D%0A%20%20%20%20%20%20if(color%20%3D%3D%3D%20'green')%20%7B%20%3CGreenComponent%2F%3E%3B%20%7D%0A%20%20%20%20%7D%7D%0A%20%20%3C%2Fdiv%3E%0A%3B) ## Installation ```sh -$ npm install babel-plugin-transform-do-expressions +npm install --save-dev babel-plugin-transform-do-expressions ``` ## Usage @@ -23,7 +105,7 @@ $ npm install babel-plugin-transform-do-expressions ### Via CLI ```sh -$ babel --plugins transform-do-expressions script.js +babel --plugins transform-do-expressions script.js ``` ### Via Node API @@ -33,3 +115,8 @@ require("babel-core").transform("code", { plugins: ["transform-do-expressions"] }); ``` + +## References +- [Proposal](http://wiki.ecmascript.org/doku.php?id=strawman:do_expressions) +- [You Don't Know JS](https://github.com/getify/You-Dont-Know-JS/blob/master/types%20%26%20grammar/ch5.md#statement-completion-values) +- Very handy for conditions inside JSX: [reactjs/react-future#35](https://github.com/reactjs/react-future/issues/35#issuecomment-120009203) diff --git a/packages/babel-plugin-transform-es2015-arrow-functions/README.md b/packages/babel-plugin-transform-es2015-arrow-functions/README.md index 80a12d3d780d..6e1b8f353e78 100644 --- a/packages/babel-plugin-transform-es2015-arrow-functions/README.md +++ b/packages/babel-plugin-transform-es2015-arrow-functions/README.md @@ -1,11 +1,62 @@ # babel-plugin-transform-es2015-arrow-functions -Compile ES2015 arrow functions to ES5 +> Compile ES2015 arrow functions to ES5 + +## Example + +**In** + +```javascript +var a = () => {}; +var a = (b) => b; + +const double = [1,2,3].map((num) => num * 2); +console.log(double); // [2,4,6] + +var bob = { + _name: "Bob", + _friends: ["Sally", "Tom"], + printFriends() { + this._friends.forEach(f => + console.log(this._name + " knows " + f)); + } +}; +console.log(bob.printFriends()); +``` + +**Out** + +```javascript +var a = function a() {}; +var a = function a(b) { + return b; +}; + +var double = [1, 2, 3].map(function (num) { + return num * 2; +}); +console.log(double); // [2,4,6] + +var bob = { + _name: "Bob", + _friends: ["Sally", "Tom"], + printFriends: function printFriends() { + var _this = this; + + this._friends.forEach(function (f) { + return console.log(_this._name + " knows " + f); + }); + } +}; +console.log(bob.printFriends()); +``` + +[Try in REPL](http://babeljs.io/repl/#?evaluate=true&lineWrap=true&presets=es2015%2Ces2015-loose&experimental=false&loose=false&spec=false&code=var%20a%20%3D%20()%20%3D%3E%20%7B%7D%3B%0Avar%20a%20%3D%20(b)%20%3D%3E%20b%3B%0A%0Aconst%20double%20%3D%20%5B1%2C2%2C3%5D.map((num)%20%3D%3E%20num%20*%202)%3B%0Aconsole.log(double)%3B%20%2F%2F%20%5B2%2C4%2C6%5D%0A%0Avar%20bob%20%3D%20%7B%0A%20%20_name%3A%20%22Bob%22%2C%0A%20%20_friends%3A%20%5B%22Sally%22%2C%20%22Tom%22%5D%2C%0A%20%20printFriends()%20%7B%0A%20%20%20%20this._friends.forEach(f%20%3D%3E%0A%20%20%20%20%20%20console.log(this._name%20%2B%20%22%20knows%20%22%20%2B%20f))%3B%0A%20%20%7D%0A%7D%3B%0Aconsole.log(bob.printFriends())%3B&playground=true) ## Installation ```sh -$ npm install babel-plugin-transform-es2015-arrow-functions +npm install --save-dev babel-plugin-transform-es2015-arrow-functions ``` ## Usage @@ -31,7 +82,7 @@ $ npm install babel-plugin-transform-es2015-arrow-functions ### Via CLI ```sh -$ babel --plugins transform-es2015-arrow-functions script.js +babel --plugins transform-es2015-arrow-functions script.js ``` ### Via Node API @@ -41,3 +92,7 @@ require("babel-core").transform("code", { plugins: ["transform-es2015-arrow-functions"] }); ``` + +## Options + +* `spec` - This option wraps the generated function in `.bind(this)` and keeps uses of `this` inside the function as-is, instead of using a renamed `this`. It also adds a runtime check to ensure the functions are not instantiated. diff --git a/packages/babel-plugin-transform-es2015-block-scoped-functions/README.md b/packages/babel-plugin-transform-es2015-block-scoped-functions/README.md index fa4eb2de1f6e..4119eb97583c 100644 --- a/packages/babel-plugin-transform-es2015-block-scoped-functions/README.md +++ b/packages/babel-plugin-transform-es2015-block-scoped-functions/README.md @@ -1,11 +1,11 @@ # babel-plugin-transform-es2015-block-scoped-functions -Babel plugin to ensure function declarations at the block level are block scoped. +> Babel plugin to ensure function declarations at the block level are block scoped. ## Installation ```sh -$ npm install babel-plugin-transform-es2015-block-scoped-functions +npm install --save-dev babel-plugin-transform-es2015-block-scoped-functions ``` ## Usage @@ -23,7 +23,7 @@ $ npm install babel-plugin-transform-es2015-block-scoped-functions ### Via CLI ```sh -$ babel --plugins transform-es2015-block-scoped-functions script.js +babel --plugins transform-es2015-block-scoped-functions script.js ``` ### Via Node API diff --git a/packages/babel-plugin-transform-es2015-block-scoping/README.md b/packages/babel-plugin-transform-es2015-block-scoping/README.md index 06884df4f9ae..ee1d426600b9 100644 --- a/packages/babel-plugin-transform-es2015-block-scoping/README.md +++ b/packages/babel-plugin-transform-es2015-block-scoping/README.md @@ -1,11 +1,11 @@ # babel-plugin-transform-es2015-block-scoping -Compile ES2015 block scoping (const and let) to ES5 +> Compile ES2015 block scoping (const and let) to ES5 ## Installation ```sh -$ npm install babel-plugin-transform-es2015-block-scoping +npm install --save-dev babel-plugin-transform-es2015-block-scoping ``` ## Usage @@ -23,7 +23,7 @@ $ npm install babel-plugin-transform-es2015-block-scoping ### Via CLI ```sh -$ babel --plugins transform-es2015-block-scoping script.js +babel --plugins transform-es2015-block-scoping script.js ``` ### Via Node API diff --git a/packages/babel-plugin-transform-es2015-block-scoping/package.json b/packages/babel-plugin-transform-es2015-block-scoping/package.json index 49f8144055cd..4df1c289cee3 100644 --- a/packages/babel-plugin-transform-es2015-block-scoping/package.json +++ b/packages/babel-plugin-transform-es2015-block-scoping/package.json @@ -1,16 +1,16 @@ { "name": "babel-plugin-transform-es2015-block-scoping", - "version": "6.18.0", + "version": "6.20.0", "description": "Compile ES2015 block scoping (const and let) to ES5", "repository": "https://github.com/babel/babel/tree/master/packages/babel-plugin-transform-es2015-block-scoping", "license": "MIT", "main": "lib/index.js", "dependencies": { - "babel-traverse": "^6.18.0", - "babel-types": "^6.18.0", + "babel-traverse": "^6.20.0", + "babel-types": "^6.20.0", "babel-template": "^6.15.0", "lodash": "^4.2.0", - "babel-runtime": "^6.9.0" + "babel-runtime": "^6.20.0" }, "keywords": [ "babel-plugin" diff --git a/packages/babel-plugin-transform-es2015-block-scoping/src/index.js b/packages/babel-plugin-transform-es2015-block-scoping/src/index.js index 6f212351963d..eb27618ae376 100644 --- a/packages/babel-plugin-transform-es2015-block-scoping/src/index.js +++ b/packages/babel-plugin-transform-es2015-block-scoping/src/index.js @@ -524,7 +524,11 @@ class BlockScoping { // for (let i = 0; i < declarators.length; i++) { let declar = declarators[i]; - let keys = t.getBindingIdentifiers(declar); + // Passing true as the third argument causes t.getBindingIdentifiers + // to return only the *outer* binding identifiers of this + // declaration, rather than (for example) mistakenly including the + // parameters of a function declaration. Fixes #4880. + let keys = t.getBindingIdentifiers(declar, false, true); extend(this.letReferences, keys); this.hasLetReferences = true; } diff --git a/packages/babel-plugin-transform-es2015-block-scoping/test/fixtures/general/function-in-catch/actual.js b/packages/babel-plugin-transform-es2015-block-scoping/test/fixtures/general/function-in-catch/actual.js new file mode 100644 index 000000000000..c38a4caa3a45 --- /dev/null +++ b/packages/babel-plugin-transform-es2015-block-scoping/test/fixtures/general/function-in-catch/actual.js @@ -0,0 +1,7 @@ +try { + foo(); +} catch (x) { + function harmless(x) { + return x; + } +} diff --git a/packages/babel-plugin-transform-es2015-block-scoping/test/fixtures/general/function-in-catch/expected.js b/packages/babel-plugin-transform-es2015-block-scoping/test/fixtures/general/function-in-catch/expected.js new file mode 100644 index 000000000000..940393047618 --- /dev/null +++ b/packages/babel-plugin-transform-es2015-block-scoping/test/fixtures/general/function-in-catch/expected.js @@ -0,0 +1,7 @@ +try { + foo(); +} catch (x) { + var harmless = function (x) { + return x; + }; +} diff --git a/packages/babel-plugin-transform-es2015-classes/README.md b/packages/babel-plugin-transform-es2015-classes/README.md index ab9f4ce9d341..aa68fde1ca6b 100644 --- a/packages/babel-plugin-transform-es2015-classes/README.md +++ b/packages/babel-plugin-transform-es2015-classes/README.md @@ -1,11 +1,17 @@ # babel-plugin-transform-es2015-classes -Compile ES2015 classes to ES5 +> Compile ES2015 classes to ES5 + +## Caveats + +Built-in classes such as `Date`, `Array`, `DOM` etc cannot be properly subclassed +due to limitations in ES5 (for the [es2015-classes](http://babeljs.io/docs/plugins/transform-es2015-classes) plugin). +You can try to use [babel-plugin-transform-builtin-extend](https://github.com/loganfsmyth/babel-plugin-transform-builtin-extend) based on `Object.setPrototypeOf` and `Reflect.construct`, but it also has some limitations. ## Installation ```sh -$ npm install babel-plugin-transform-es2015-classes +npm install --save-dev babel-plugin-transform-es2015-classes ``` ## Usage @@ -33,7 +39,7 @@ $ npm install babel-plugin-transform-es2015-classes ### Via CLI ```sh -$ babel --plugins transform-es2015-classes script.js +babel --plugins transform-es2015-classes script.js ``` ### Via Node API @@ -43,3 +49,55 @@ require("babel-core").transform("code", { plugins: ["transform-es2015-classes"] }); ``` + +## Options `loose` + +#### Method enumerability + +Please note that in loose mode class methods **are** enumerable. This is not in line +with the spec and you may run into issues. + +#### Method assignment + +Under loose mode, methods are defined on the class prototype with simple assignments +instead of being defined. This can result in the following not working: + +```javascript +class Foo { + set bar() { + throw new Error("foo!"); + } +} + +class Bar extends Foo { + bar() { + // will throw an error when this method is defined + } +} +``` + +When `Bar.prototype.foo` is defined it triggers the setter on `Foo`. This is a +case that is very unlikely to appear in production code however it's something +to keep in mind. + +## Usage + +### Via `.babelrc` (Recommended) + +**.babelrc** + +```js +// without options +{ + "plugins": ["transform-es2015-classes"] +} + +// with options +{ + "plugins": [ + ["transform-es2015-classes", { + "loose": true + }] + ] +} +``` diff --git a/packages/babel-plugin-transform-es2015-computed-properties/README.md b/packages/babel-plugin-transform-es2015-computed-properties/README.md index 1501ec5b9976..db0e270a3899 100644 --- a/packages/babel-plugin-transform-es2015-computed-properties/README.md +++ b/packages/babel-plugin-transform-es2015-computed-properties/README.md @@ -1,11 +1,11 @@ # babel-plugin-transform-es2015-computed-properties -Compile ES2015 computed properties to ES5 +> Compile ES2015 computed properties to ES5 ## Installation ```sh -$ npm install babel-plugin-transform-es2015-computed-properties +npm install --save-dev babel-plugin-transform-es2015-computed-properties ``` ## Usage @@ -33,7 +33,7 @@ $ npm install babel-plugin-transform-es2015-computed-properties ### Via CLI ```sh -$ babel --plugins transform-es2015-computed-properties script.js +babel --plugins transform-es2015-computed-properties script.js ``` ### Via Node API @@ -43,3 +43,9 @@ require("babel-core").transform("code", { plugins: ["transform-es2015-computed-properties"] }); ``` + +## Options + +* `loose` - Just like method assignment in classes, in loose mode, computed property names +use simple assignments instead of being defined. This is unlikely to be an issue +in production code. diff --git a/packages/babel-plugin-transform-es2015-destructuring/README.md b/packages/babel-plugin-transform-es2015-destructuring/README.md index 77e3e48f16d6..b20732c4b0a3 100644 --- a/packages/babel-plugin-transform-es2015-destructuring/README.md +++ b/packages/babel-plugin-transform-es2015-destructuring/README.md @@ -1,11 +1,11 @@ # babel-plugin-transform-es2015-destructuring -Compile ES2015 destructuring to ES5 +> Compile ES2015 destructuring to ES5 ## Installation ```sh -$ npm install babel-plugin-transform-es2015-destructuring +npm install --save-dev babel-plugin-transform-es2015-destructuring ``` ## Usage @@ -23,7 +23,7 @@ $ npm install babel-plugin-transform-es2015-destructuring ### Via CLI ```sh -$ babel --plugins transform-es2015-destructuring script.js +babel --plugins transform-es2015-destructuring script.js ``` ### Via Node API diff --git a/packages/babel-plugin-transform-es2015-destructuring/package.json b/packages/babel-plugin-transform-es2015-destructuring/package.json index 25ea307dadaa..2d8f9fc233aa 100644 --- a/packages/babel-plugin-transform-es2015-destructuring/package.json +++ b/packages/babel-plugin-transform-es2015-destructuring/package.json @@ -1,6 +1,6 @@ { "name": "babel-plugin-transform-es2015-destructuring", - "version": "6.18.0", + "version": "6.19.0", "description": "Compile ES2015 destructuring to ES5", "repository": "https://github.com/babel/babel/tree/master/packages/babel-plugin-transform-es2015-destructuring", "license": "MIT", diff --git a/packages/babel-plugin-transform-es2015-duplicate-keys/README.md b/packages/babel-plugin-transform-es2015-duplicate-keys/README.md index 0e5c9e896279..bfcb7c4257ca 100644 --- a/packages/babel-plugin-transform-es2015-duplicate-keys/README.md +++ b/packages/babel-plugin-transform-es2015-duplicate-keys/README.md @@ -1,16 +1,35 @@ # babel-plugin-transform-es2015-duplicate-keys -Compile objects with duplicate keys to valid strict ES5. +> Compile objects with duplicate keys to valid strict ES5. This plugin actually converts duplicate keys in objects to be computed properties, which then must be handled by the [transform-es2015-computed-properties](http://babeljs.io/docs/plugins/transform-es2015-computed-properties) plugin. The final result won't contain any object literals with duplicate keys. -This plugin actually converts duplicate keys in objects to be computed -properties, which then must be handled by the -transform-es2015-computed-properties plugin. The final result won't contain any -object literals with duplicate keys. +## Example + +**In** + +```javascript +var x = { a: 5, a: 6 }; +var y = { + get a() {}, + set a(x) {}, + a: 3 +}; +``` + +**Out** + +```javascript +var x = { a: 5, ["a"]: 6 }; +var y = { + get a() {}, + set a(x) {}, + ["a"]: 3 +}; +``` ## Installation ```sh -$ npm install babel-plugin-transform-es2015-duplicate-keys +npm install --save-dev babel-plugin-transform-es2015-duplicate-keys ``` ## Usage @@ -28,7 +47,7 @@ $ npm install babel-plugin-transform-es2015-duplicate-keys ### Via CLI ```sh -$ babel --plugins transform-es2015-duplicate-keys script.js +babel --plugins transform-es2015-duplicate-keys script.js ``` ### Via Node API diff --git a/packages/babel-plugin-transform-es2015-for-of/README.md b/packages/babel-plugin-transform-es2015-for-of/README.md index ec5840ffd8aa..22aae1b1a059 100644 --- a/packages/babel-plugin-transform-es2015-for-of/README.md +++ b/packages/babel-plugin-transform-es2015-for-of/README.md @@ -1,11 +1,11 @@ # babel-plugin-transform-es2015-for-of -Compile ES2015 for...of to ES5 +> Compile ES2015 for...of to ES5 ## Installation ```sh -$ npm install babel-plugin-transform-es2015-for-of +npm install --save-dev babel-plugin-transform-es2015-for-of ``` ## Usage @@ -33,7 +33,7 @@ $ npm install babel-plugin-transform-es2015-for-of ### Via CLI ```sh -$ babel --plugins transform-es2015-for-of script.js +babel --plugins transform-es2015-for-of script.js ``` ### Via Node API @@ -43,3 +43,69 @@ require("babel-core").transform("code", { plugins: ["transform-es2015-for-of"] }); ``` + +## Options `loose` + +#### Abrupt completions + +In loose mode an iterators `return` method will not be called on abrupt completions caused by thrown errors. + +Please see [google/traceur-compiler#1773](https://github.com/google/traceur-compiler/issues/1773) and +[babel/babel#838](https://github.com/babel/babel/issues/838) for more information. + +#### Arrays + +Under loose mode the `forOf` transformer will output more verbose iteration code. + +For example the following: + +```javascript +for (var i of foo) {} +``` + +is normally output as: + +```javascript +for (var _iterator = foo[Symbol.iterator](), _step; !(_step = _iterator.next()).done;) { + var i = _step.value; +} +``` + +Under loose mode however it's output as: + +```javascript +for (var _iterator = foo, _isArray = Array.isArray(_iterator), _i = 0, _iterator = _isArray ? _iterator : _iterator[Symbol.iterator]();;) { + var i; + if (_isArray) { + if (_i >= _iterator.length) break; + i = _iterator[_i++]; + } else { + _i = _iterator.next(); + if (_i.done) break; + i = _i.value; + } +} +``` + +The result is that arrays are put in a fast path, heavily increasing performance. +All other iterables will continue to work fine but array iteration will be +significantly faster. + +### Optimization + +If a basic array is used, Babel will compile the for-of loop down to a regular for loop. + +**In** + +```js +for (let a of [1,2,3]) {} +``` + +**Out** + +```js +var _arr = [1, 2, 3]; +for (var _i = 0; _i < _arr.length; _i++) { + var a = _arr[_i]; +} +``` diff --git a/packages/babel-plugin-transform-es2015-function-name/README.md b/packages/babel-plugin-transform-es2015-function-name/README.md index 57b690f9284b..815acc5be340 100644 --- a/packages/babel-plugin-transform-es2015-function-name/README.md +++ b/packages/babel-plugin-transform-es2015-function-name/README.md @@ -1,11 +1,11 @@ # babel-plugin-transform-es2015-function-name -Apply ES2015 function.name semantics to all functions +> Apply ES2015 function.name semantics to all functions ## Installation ```sh -$ npm install babel-plugin-transform-es2015-function-name +npm install --save-dev babel-plugin-transform-es2015-function-name ``` ## Usage @@ -23,7 +23,7 @@ $ npm install babel-plugin-transform-es2015-function-name ### Via CLI ```sh -$ babel --plugins transform-es2015-function-name script.js +babel --plugins transform-es2015-function-name script.js ``` ### Via Node API diff --git a/packages/babel-plugin-transform-es2015-instanceof/README.md b/packages/babel-plugin-transform-es2015-instanceof/README.md index f5d4766b8775..a26a86fc9c43 100644 --- a/packages/babel-plugin-transform-es2015-instanceof/README.md +++ b/packages/babel-plugin-transform-es2015-instanceof/README.md @@ -3,7 +3,7 @@ ## Installation ```sh -$ npm install babel-plugin-transform-es2015-instanceof +npm install --save-dev babel-plugin-transform-es2015-instanceof ``` ## Usage @@ -21,7 +21,7 @@ $ npm install babel-plugin-transform-es2015-instanceof ### Via CLI ```sh -$ babel --plugins transform-es2015-instanceof script.js +babel --plugins transform-es2015-instanceof script.js ``` ### Via Node API diff --git a/packages/babel-plugin-transform-es2015-literals/README.md b/packages/babel-plugin-transform-es2015-literals/README.md index ec81710e37a7..102248228d6f 100644 --- a/packages/babel-plugin-transform-es2015-literals/README.md +++ b/packages/babel-plugin-transform-es2015-literals/README.md @@ -1,11 +1,29 @@ # babel-plugin-transform-es2015-literals -Compile ES2015 unicode string and number literals to ES5 +> Compile ES2015 unicode string and number literals to ES5 + +## Example + +**In** + +```js +var b = 0b11; // binary integer literal +var o = 0o7; // octal integer literal +const u = 'Hello\u{000A}\u{0009}!'; // unicode string literals, newline and tab +``` + +**Out** + +```js +var b = 3; // binary integer literal +var o = 7; // octal integer literal +const u = 'Hello\n\t!'; // unicode string literals, newline and tab +``` ## Installation ```sh -$ npm install babel-plugin-transform-es2015-literals +npm install --save-dev babel-plugin-transform-es2015-literals ``` ## Usage @@ -23,7 +41,7 @@ $ npm install babel-plugin-transform-es2015-literals ### Via CLI ```sh -$ babel --plugins transform-es2015-literals script.js +babel --plugins transform-es2015-literals script.js ``` ### Via Node API diff --git a/packages/babel-plugin-transform-es2015-modules-amd/README.md b/packages/babel-plugin-transform-es2015-modules-amd/README.md index beb7cfc104d0..04455655accf 100644 --- a/packages/babel-plugin-transform-es2015-modules-amd/README.md +++ b/packages/babel-plugin-transform-es2015-modules-amd/README.md @@ -1,9 +1,33 @@ # babel-plugin-transform-es2015-modules-amd +> This plugin transforms ES2015 modules to [Asynchronous Module Definition (AMD)](https://github.com/amdjs/amdjs-api). + +## Example + +**In** + +```javascript +export default 42; +``` + +**Out** + +```javascript +define(["exports"], function (exports) { + "use strict"; + + Object.defineProperty(exports, "__esModule", { + value: true + }); + + exports.default = 42; +}); +``` + ## Installation ```sh -$ npm install babel-plugin-transform-es2015-modules-amd +npm install --save-dev babel-plugin-transform-es2015-modules-amd ``` ## Usage @@ -21,7 +45,7 @@ $ npm install babel-plugin-transform-es2015-modules-amd ### Via CLI ```sh -$ babel --plugins transform-es2015-modules-amd script.js +babel --plugins transform-es2015-modules-amd script.js ``` ### Via Node API diff --git a/packages/babel-plugin-transform-es2015-modules-commonjs/README.md b/packages/babel-plugin-transform-es2015-modules-commonjs/README.md index 95ea03c20fab..0693b91f07d6 100644 --- a/packages/babel-plugin-transform-es2015-modules-commonjs/README.md +++ b/packages/babel-plugin-transform-es2015-modules-commonjs/README.md @@ -1,9 +1,29 @@ # babel-plugin-transform-es2015-modules-commonjs +> This plugin transforms ES2015 modules to [CommonJS](http://wiki.commonjs.org/wiki/Modules/1.1). + +## Example + +**In** + +```javascript +export default 42; +``` + +**Out** + +```javascript +Object.defineProperty(exports, "__esModule", { + value: true +}); + +exports.default = 42; +``` + ## Installation ```sh -$ npm install babel-plugin-transform-es2015-modules-commonjs +npm install --save-dev babel-plugin-transform-es2015-modules-commonjs ``` ## Usage @@ -31,7 +51,7 @@ $ npm install babel-plugin-transform-es2015-modules-commonjs ### Via CLI ```sh -$ babel --plugins transform-es2015-modules-commonjs script.js +babel --plugins transform-es2015-modules-commonjs script.js ``` ### Via Node API @@ -41,3 +61,27 @@ require("babel-core").transform("code", { plugins: ["transform-es2015-modules-commonjs"] }); ``` + +## Options `loose` + +As per the spec, `import` and `export` are only allowed to be used at the top +level. When in loose mode these are allowed to be used anywhere. + +And by default, when using exports with babel a non-enumerable `__esModule` property +is exported. + +```javascript +var foo = exports.foo = 5; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +``` + +In environments that don't support this you can enable loose mode on `es6.modules` +and instead of using `Object.defineProperty` an assignment will be used instead. + +```javascript +var foo = exports.foo = 5; +exports.__esModule = true; +``` diff --git a/packages/babel-plugin-transform-es2015-modules-systemjs/README.md b/packages/babel-plugin-transform-es2015-modules-systemjs/README.md index 553b315d42d2..ca205005d9be 100644 --- a/packages/babel-plugin-transform-es2015-modules-systemjs/README.md +++ b/packages/babel-plugin-transform-es2015-modules-systemjs/README.md @@ -1,9 +1,32 @@ # babel-plugin-transform-es2015-modules-systemjs +> This plugin transforms ES2015 modules to [SystemJS](https://github.com/systemjs/systemjs). + +## Example + +**In** + +```javascript +export default 42; +``` + +**Out** + +```javascript +System.register([], function (_export, _context) { + return { + setters: [], + execute: function () { + _export("default", 42); + } + }; +}); +``` + ## Installation ```sh -$ npm install babel-plugin-transform-es2015-modules-systemjs +npm install --save-dev babel-plugin-transform-es2015-modules-systemjs ``` ## Usage @@ -32,7 +55,7 @@ $ npm install babel-plugin-transform-es2015-modules-systemjs ### Via CLI ```sh -$ babel --plugins transform-es2015-modules-systemjs script.js +babel --plugins transform-es2015-modules-systemjs script.js ``` ### Via Node API diff --git a/packages/babel-plugin-transform-es2015-modules-systemjs/package.json b/packages/babel-plugin-transform-es2015-modules-systemjs/package.json index 586893e7a35b..7a9e82b1593a 100644 --- a/packages/babel-plugin-transform-es2015-modules-systemjs/package.json +++ b/packages/babel-plugin-transform-es2015-modules-systemjs/package.json @@ -1,6 +1,6 @@ { "name": "babel-plugin-transform-es2015-modules-systemjs", - "version": "6.18.0", + "version": "6.19.0", "description": "This plugin transforms ES2015 modules to SystemJS", "repository": "https://github.com/babel/babel/tree/master/packages/babel-plugin-transform-es2015-modules-systemjs", "license": "MIT", @@ -14,6 +14,7 @@ "babel-plugin" ], "devDependencies": { - "babel-helper-plugin-test-runner": "^6.18.0" + "babel-helper-plugin-test-runner": "^6.18.0", + "babel-plugin-syntax-dynamic-import": "^6.18.0" } } diff --git a/packages/babel-plugin-transform-es2015-modules-systemjs/src/index.js b/packages/babel-plugin-transform-es2015-modules-systemjs/src/index.js index ac8a8e2889d6..93091bac29de 100644 --- a/packages/babel-plugin-transform-es2015-modules-systemjs/src/index.js +++ b/packages/babel-plugin-transform-es2015-modules-systemjs/src/index.js @@ -22,6 +22,9 @@ let buildExportAll = template(` } `); + +const TYPE_IMPORT = "Import"; + export default function ({ types: t }) { let IGNORE_REASSIGNMENT_SYMBOL = Symbol(); @@ -69,6 +72,14 @@ export default function ({ types: t }) { return { visitor: { + + CallExpression(path, state) { + if (path.node.callee.type === TYPE_IMPORT) { + let contextIdent = state.contextIdent; + path.replaceWith(t.callExpression(t.memberExpression(contextIdent, t.identifier("import")), path.node.arguments)); + } + }, + ReferencedIdentifier(path, state) { if (path.node.name == "__moduleName" && !path.scope.hasBinding("__moduleName")) { path.replaceWith(t.memberExpression(state.contextIdent, t.identifier("id"))); @@ -84,7 +95,7 @@ export default function ({ types: t }) { let contextIdent = state.contextIdent; let exportNames = Object.create(null); - let modules = Object.create(null); + let modules = []; let beforeBody = []; let setters = []; @@ -98,8 +109,16 @@ export default function ({ types: t }) { } function pushModule(source, key, specifiers) { - let _modules = modules[source] = modules[source] || { imports: [], exports: [] }; - _modules[key] = _modules[key].concat(specifiers); + let module; + modules.forEach(function (m) { + if (m.key === source) { + module = m; + } + }); + if (!module) { + modules.push(module = { key: source, imports: [], exports: [] }); + } + module[key] = module[key].concat(specifiers); } function buildExportCall(name, val) { @@ -205,11 +224,9 @@ export default function ({ types: t }) { } } - for (let source in modules) { - let specifiers = modules[source]; - + modules.forEach(function (specifiers) { let setterBody = []; - let target = path.scope.generateUidIdentifier(source); + let target = path.scope.generateUidIdentifier(specifiers.key); for (let specifier of specifiers.imports) { if (t.isImportNamespaceSpecifier(specifier)) { @@ -249,9 +266,9 @@ export default function ({ types: t }) { setterBody.push(t.expressionStatement(t.callExpression(exportIdent, [exportObjRef]))); } - sources.push(t.stringLiteral(source)); + sources.push(t.stringLiteral(specifiers.key)); setters.push(t.functionExpression(null, [target], t.blockStatement(setterBody))); - } + }); let moduleName = this.getModuleName(); diff --git a/packages/babel-plugin-transform-es2015-modules-systemjs/test/fixtures/dynamic-import/dynamic-import/actual.js b/packages/babel-plugin-transform-es2015-modules-systemjs/test/fixtures/dynamic-import/dynamic-import/actual.js new file mode 100644 index 000000000000..6e6ea639620c --- /dev/null +++ b/packages/babel-plugin-transform-es2015-modules-systemjs/test/fixtures/dynamic-import/dynamic-import/actual.js @@ -0,0 +1,6 @@ +export function lazyLoadOperation () { + return import('./x') + .then(function (x) { + x.y(); + }); +} diff --git a/packages/babel-plugin-transform-es2015-modules-systemjs/test/fixtures/dynamic-import/dynamic-import/expected.js b/packages/babel-plugin-transform-es2015-modules-systemjs/test/fixtures/dynamic-import/dynamic-import/expected.js new file mode 100644 index 000000000000..de2b2da61985 --- /dev/null +++ b/packages/babel-plugin-transform-es2015-modules-systemjs/test/fixtures/dynamic-import/dynamic-import/expected.js @@ -0,0 +1,16 @@ +System.register([], function (_export, _context) { + "use strict"; + + function lazyLoadOperation() { + return _context.import('./x').then(function (x) { + x.y(); + }); + } + + _export('lazyLoadOperation', lazyLoadOperation); + + return { + setters: [], + execute: function () {} + }; +}); diff --git a/packages/babel-plugin-transform-es2015-modules-systemjs/test/fixtures/dynamic-import/options.json b/packages/babel-plugin-transform-es2015-modules-systemjs/test/fixtures/dynamic-import/options.json new file mode 100644 index 000000000000..20631e3163ac --- /dev/null +++ b/packages/babel-plugin-transform-es2015-modules-systemjs/test/fixtures/dynamic-import/options.json @@ -0,0 +1,3 @@ +{ + "plugins": ["external-helpers", "syntax-dynamic-import", "transform-es2015-modules-systemjs"] +} diff --git a/packages/babel-plugin-transform-es2015-modules-systemjs/test/fixtures/systemjs/imports-numbered/actual.js b/packages/babel-plugin-transform-es2015-modules-systemjs/test/fixtures/systemjs/imports-numbered/actual.js new file mode 100644 index 000000000000..fa6a368c4511 --- /dev/null +++ b/packages/babel-plugin-transform-es2015-modules-systemjs/test/fixtures/systemjs/imports-numbered/actual.js @@ -0,0 +1,2 @@ +import "2"; +import "1"; diff --git a/packages/babel-plugin-transform-es2015-modules-systemjs/test/fixtures/systemjs/imports-numbered/expected.js b/packages/babel-plugin-transform-es2015-modules-systemjs/test/fixtures/systemjs/imports-numbered/expected.js new file mode 100644 index 000000000000..c622c621b6ac --- /dev/null +++ b/packages/babel-plugin-transform-es2015-modules-systemjs/test/fixtures/systemjs/imports-numbered/expected.js @@ -0,0 +1,8 @@ +System.register(["2", "1"], function (_export, _context) { + "use strict"; + + return { + setters: [function (_) {}, function (_2) {}], + execute: function () {} + }; +}); diff --git a/packages/babel-plugin-transform-es2015-modules-umd/README.md b/packages/babel-plugin-transform-es2015-modules-umd/README.md index 9af5b210c004..31fc41548017 100644 --- a/packages/babel-plugin-transform-es2015-modules-umd/README.md +++ b/packages/babel-plugin-transform-es2015-modules-umd/README.md @@ -1,9 +1,45 @@ # babel-plugin-transform-es2015-modules-umd +> This plugin transforms ES2015 modules to [Universal Module Definition (UMD)](https://github.com/umdjs/umd). + +## Example + +**In** + +```javascript +export default 42; +``` + +**Out** + +```javascript +(function (global, factory) { + if (typeof define === "function" && define.amd) { + define(["exports"], factory); + } else if (typeof exports !== "undefined") { + factory(exports); + } else { + var mod = { + exports: {} + }; + factory(mod.exports); + global.actual = mod.exports; + } +})(this, function (exports) { + "use strict"; + + Object.defineProperty(exports, "__esModule", { + value: true + }); + + exports.default = 42; +}); +``` + ## Installation ```sh -$ npm install babel-plugin-transform-es2015-modules-umd +npm install --save-dev babel-plugin-transform-es2015-modules-umd ``` ## Usage @@ -166,7 +202,7 @@ global.My.Custom.Module.Name = mod.exports; ### Via CLI ```sh -$ babel --plugins transform-es2015-modules-umd script.js +babel --plugins transform-es2015-modules-umd script.js ``` ### Via Node API diff --git a/packages/babel-plugin-transform-es2015-object-super/README.md b/packages/babel-plugin-transform-es2015-object-super/README.md index ea5bf50c7fee..be0d505fce39 100644 --- a/packages/babel-plugin-transform-es2015-object-super/README.md +++ b/packages/babel-plugin-transform-es2015-object-super/README.md @@ -1,11 +1,11 @@ # babel-plugin-transform-es2015-object-super -Compile ES2015 object super to ES5 +> Compile ES2015 object super to ES5 ## Installation ```sh -$ npm install babel-plugin-transform-es2015-object-super +npm install --save-dev babel-plugin-transform-es2015-object-super ``` ## Usage @@ -23,7 +23,7 @@ $ npm install babel-plugin-transform-es2015-object-super ### Via CLI ```sh -$ babel --plugins transform-es2015-object-super script.js +babel --plugins transform-es2015-object-super script.js ``` ### Via Node API diff --git a/packages/babel-plugin-transform-es2015-parameters/README.md b/packages/babel-plugin-transform-es2015-parameters/README.md index e443bbba37bf..bd55bbc350ad 100644 --- a/packages/babel-plugin-transform-es2015-parameters/README.md +++ b/packages/babel-plugin-transform-es2015-parameters/README.md @@ -1,13 +1,19 @@ # babel-plugin-transform-es2015-parameters -Compile ES2015 default and rest parameters to ES5 +> Compile ES2015 default and rest parameters to ES5 ## Installation ```sh -$ npm install babel-plugin-transform-es2015-parameters +npm install --save-dev babel-plugin-transform-es2015-parameters ``` +## Caveats + +Default parameters desugar into `let` declarations to retain proper semantics. If this is +not supported in your environment then you'll need the +[transform-block-scoping](http://babeljs.io/docs/plugins/transform-es2015-block-scoping) plugin. + ## Usage ### Via `.babelrc` (Recommended) @@ -23,7 +29,7 @@ $ npm install babel-plugin-transform-es2015-parameters ### Via CLI ```sh -$ babel --plugins transform-es2015-parameters script.js +babel --plugins transform-es2015-parameters script.js ``` ### Via Node API diff --git a/packages/babel-plugin-transform-es2015-shorthand-properties/README.md b/packages/babel-plugin-transform-es2015-shorthand-properties/README.md index 8fc11b00b27c..171aa1ead7c9 100644 --- a/packages/babel-plugin-transform-es2015-shorthand-properties/README.md +++ b/packages/babel-plugin-transform-es2015-shorthand-properties/README.md @@ -1,11 +1,45 @@ # babel-plugin-transform-es2015-shorthand-properties -Compile ES2015 shorthand properties to ES5 +> Compile ES2015 shorthand properties to ES5 + +## Example + +**In** + +```js +var o = { a, b, c }; +``` + +**Out** + +```js +var o = { a: a, b: b, c:c }; +``` + +**In** + +```js +var cat = { + getName() { + return name; + } +}; +``` + +**Out** + +```js +var cat = { + getName: function () { + return name; + } +}; +``` ## Installation ```sh -$ npm install babel-plugin-transform-es2015-shorthand-properties +npm install --save-dev babel-plugin-transform-es2015-shorthand-properties ``` ## Usage @@ -23,7 +57,7 @@ $ npm install babel-plugin-transform-es2015-shorthand-properties ### Via CLI ```sh -$ babel --plugins transform-es2015-shorthand-properties script.js +babel --plugins transform-es2015-shorthand-properties script.js ``` ### Via Node API diff --git a/packages/babel-plugin-transform-es2015-spread/README.md b/packages/babel-plugin-transform-es2015-spread/README.md index 62e9b385bf70..9d0e16629d1b 100644 --- a/packages/babel-plugin-transform-es2015-spread/README.md +++ b/packages/babel-plugin-transform-es2015-spread/README.md @@ -1,11 +1,11 @@ # babel-plugin-transform-es2015-spread -Compile ES2015 spread to ES5 +> Compile ES2015 spread to ES5 ## Installation ```sh -$ npm install babel-plugin-transform-es2015-spread +npm install --save-dev babel-plugin-transform-es2015-spread ``` ## Usage @@ -33,7 +33,7 @@ $ npm install babel-plugin-transform-es2015-spread ### Via CLI ```sh -$ babel --plugins transform-es2015-spread script.js +babel --plugins transform-es2015-spread script.js ``` ### Via Node API @@ -43,3 +43,7 @@ require("babel-core").transform("code", { plugins: ["transform-es2015-spread"] }); ``` + +## Options + +* `loose` - All iterables are assumed to be arrays. diff --git a/packages/babel-plugin-transform-es2015-sticky-regex/README.md b/packages/babel-plugin-transform-es2015-sticky-regex/README.md index 61d17b58b53d..aefaaf9749b8 100644 --- a/packages/babel-plugin-transform-es2015-sticky-regex/README.md +++ b/packages/babel-plugin-transform-es2015-sticky-regex/README.md @@ -1,11 +1,11 @@ # babel-plugin-transform-es2015-sticky-regex -Compile ES2015 sticky regex to an ES5 RegExp constructor +> Compile ES2015 sticky regex to an ES5 RegExp constructor ## Installation ```sh -$ npm install babel-plugin-transform-es2015-sticky-regex +npm install --save-dev babel-plugin-transform-es2015-sticky-regex ``` ## Usage @@ -23,7 +23,7 @@ $ npm install babel-plugin-transform-es2015-sticky-regex ### Via CLI ```sh -$ babel --plugins transform-es2015-sticky-regex script.js +babel --plugins transform-es2015-sticky-regex script.js ``` ### Via Node API diff --git a/packages/babel-plugin-transform-es2015-template-literals/README.md b/packages/babel-plugin-transform-es2015-template-literals/README.md index ef61c1b2a742..854bc74be624 100644 --- a/packages/babel-plugin-transform-es2015-template-literals/README.md +++ b/packages/babel-plugin-transform-es2015-template-literals/README.md @@ -1,11 +1,25 @@ # babel-plugin-transform-es2015-template-literals -Compile ES2015 template literals to ES5 +> Compile ES2015 template literals to ES5 + +## Example + +**In** + +```javascript +`foo${bar}`; +``` + +**Out** + +```javascript +"foo" + bar; +``` ## Installation ```sh -$ npm install babel-plugin-transform-es2015-template-literals +npm install --save-dev babel-plugin-transform-es2015-template-literals ``` ## Usage @@ -34,7 +48,7 @@ $ npm install babel-plugin-transform-es2015-template-literals ### Via CLI ```sh -$ babel --plugins transform-es2015-template-literals script.js +babel --plugins transform-es2015-template-literals script.js ``` ### Via Node API @@ -44,3 +58,24 @@ require("babel-core").transform("code", { plugins: ["transform-es2015-template-literals"] }); ``` + +## Options + +### `loose` +In loose mode, tagged template literal objects aren't frozen. + + +### `spec` +This option wraps all template literal expressions with `String`. See [babel/babel#1065](https://github.com/babel/babel/issues/1065) for more info. + +**In** + +```javascript +`foo${bar}`; +``` + +**Out** + +```javascript +"foo" + String(bar); +``` diff --git a/packages/babel-plugin-transform-es2015-typeof-symbol/README.md b/packages/babel-plugin-transform-es2015-typeof-symbol/README.md index 63fe8215e268..53b9236ab328 100644 --- a/packages/babel-plugin-transform-es2015-typeof-symbol/README.md +++ b/packages/babel-plugin-transform-es2015-typeof-symbol/README.md @@ -1,9 +1,29 @@ # babel-plugin-transform-es2015-typeof-symbol +> ES6 introduces a new native type called [symbols](http://babeljs.io/docs/learn-es6#symbols). This transformer wraps all `typeof` expressions with a method that replicates native behaviour. (ie. returning "symbol" for symbols) + +## Example + +**In** + +```javascript +typeof Symbol() === "symbol"; +``` + +**Out** + +```javascript +var _typeof = function (obj) { + return obj && obj.constructor === Symbol ? "symbol" : typeof obj; +}; + +_typeof(Symbol()) === "symbol"; +``` + ## Installation ```sh -$ npm install babel-plugin-transform-es2015-typeof-symbol +npm install --save-dev babel-plugin-transform-es2015-typeof-symbol ``` ## Usage @@ -21,7 +41,7 @@ $ npm install babel-plugin-transform-es2015-typeof-symbol ### Via CLI ```sh -$ babel --plugins transform-es2015-typeof-symbol script.js +babel --plugins transform-es2015-typeof-symbol script.js ``` ### Via Node API diff --git a/packages/babel-plugin-transform-es2015-unicode-regex/README.md b/packages/babel-plugin-transform-es2015-unicode-regex/README.md index 99a694cfa5b3..56b2035f6ce1 100644 --- a/packages/babel-plugin-transform-es2015-unicode-regex/README.md +++ b/packages/babel-plugin-transform-es2015-unicode-regex/README.md @@ -1,11 +1,27 @@ # babel-plugin-transform-es2015-unicode-regex -Compile ES2015 unicode regex to ES5 +> Compile ES2015 unicode regex to ES5 + +## Example + +**In** + +```js +var string = "foo💩bar"; +var match = string.match(/foo(.)bar/u); +``` + +**Out** + +```js +var string = "foo💩bar"; +var match = string.match(/foo((?:[\0-\t\x0B\f\x0E-\u2027\u202A-\uD7FF\uE000-\uFFFF]|[\uD800-\uDBFF][\uDC00-\uDFFF]|[\uD800-\uDBFF](?![\uDC00-\uDFFF])|(?:[^\uD800-\uDBFF]|^)[\uDC00-\uDFFF]))bar/); +``` ## Installation ```sh -$ npm install babel-plugin-transform-es2015-unicode-regex +npm install --save-dev babel-plugin-transform-es2015-unicode-regex ``` ## Usage @@ -23,7 +39,7 @@ $ npm install babel-plugin-transform-es2015-unicode-regex ### Via CLI ```sh -$ babel --plugins transform-es2015-unicode-regex script.js +babel --plugins transform-es2015-unicode-regex script.js ``` ### Via Node API diff --git a/packages/babel-plugin-transform-es3-member-expression-literals/README.md b/packages/babel-plugin-transform-es3-member-expression-literals/README.md index 9a1ec5842e53..030f48290267 100644 --- a/packages/babel-plugin-transform-es3-member-expression-literals/README.md +++ b/packages/babel-plugin-transform-es3-member-expression-literals/README.md @@ -1,11 +1,25 @@ # babel-plugin-transform-es3-member-expression-literals -Ensure that reserved words are quoted in property accesses +> Ensure that reserved words are quoted in property accesses + +## Example + +**In** + +```javascript +foo.catch; +``` + +**Out** + +```javascript +foo["catch"]; +``` ## Installation ```sh -$ npm install babel-plugin-transform-es3-member-expression-literals +npm install --save-dev babel-plugin-transform-es3-member-expression-literals ``` ## Usage @@ -23,7 +37,7 @@ $ npm install babel-plugin-transform-es3-member-expression-literals ### Via CLI ```sh -$ babel --plugins transform-es3-member-expression-literals script.js +babel --plugins transform-es3-member-expression-literals script.js ``` ### Via Node API diff --git a/packages/babel-plugin-transform-es3-property-literals/README.md b/packages/babel-plugin-transform-es3-property-literals/README.md index 308825865d47..9cf9976a8be5 100644 --- a/packages/babel-plugin-transform-es3-property-literals/README.md +++ b/packages/babel-plugin-transform-es3-property-literals/README.md @@ -1,11 +1,29 @@ # babel-plugin-transform-es3-property-literals -Ensure that reserved words are quoted in object property keys +> Ensure that reserved words are quoted in object property keys + +## Example + +**In** + +```javascript +var foo = { + catch: function () {} +}; +``` + +**Out** + +```javascript +var foo = { + "catch": function () {} +}; +``` ## Installation ```sh -$ npm install babel-plugin-transform-es3-property-literals +npm install --save-dev babel-plugin-transform-es3-property-literals ``` ## Usage @@ -23,7 +41,7 @@ $ npm install babel-plugin-transform-es3-property-literals ### Via CLI ```sh -$ babel --plugins transform-es3-property-literals script.js +babel --plugins transform-es3-property-literals script.js ``` ### Via Node API diff --git a/packages/babel-plugin-transform-es5-property-mutators/README.md b/packages/babel-plugin-transform-es5-property-mutators/README.md index 4b40bbfeae22..a9bb7c252dc2 100644 --- a/packages/babel-plugin-transform-es5-property-mutators/README.md +++ b/packages/babel-plugin-transform-es5-property-mutators/README.md @@ -1,11 +1,37 @@ # babel-plugin-transform-es5-property-mutators -Compile ES5 property mutator shorthand syntax to Object.defineProperty +> This plugin allows Babel to transform [object initializer mutators](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Object_initializer#Method_definitions) into `Object.defineProperties`. + +## Example + +**In** + +```javascript +var foo = { + get bar() { + return "bar"; + } +}; +``` + +**Out** + +```javascript +var foo = Object.defineProperties({}, { + bar: { + get: function () { + return "bar"; + }, + enumerable: true, + configurable: true + } +}); +``` ## Installation ```sh -$ npm install babel-plugin-transform-es5-property-mutators +npm install --save-dev babel-plugin-transform-es5-property-mutators ``` ## Usage @@ -23,7 +49,7 @@ $ npm install babel-plugin-transform-es5-property-mutators ### Via CLI ```sh -$ babel --plugins transform-es5-property-mutators script.js +babel --plugins transform-es5-property-mutators script.js ``` ### Via Node API diff --git a/packages/babel-plugin-transform-eval/README.md b/packages/babel-plugin-transform-eval/README.md index 3c57bb51476f..8a67afe8ce66 100644 --- a/packages/babel-plugin-transform-eval/README.md +++ b/packages/babel-plugin-transform-eval/README.md @@ -1,6 +1,6 @@ # babel-plugin-transform-eval -Compile eval calls with string literals +> This plugin allows Babel to compile eval calls with string literals. ## Example @@ -19,7 +19,7 @@ eval("(function () { return 'foo'; })"); ## Installation ```sh -$ npm install babel-plugin-transform-eval +npm install --save-dev babel-plugin-transform-eval ``` ## Usage @@ -37,7 +37,7 @@ $ npm install babel-plugin-transform-eval ### Via CLI ```sh -$ babel --plugins transform-eval script.js +babel --plugins transform-eval script.js ``` ### Via Node API diff --git a/packages/babel-plugin-transform-exponentiation-operator/README.md b/packages/babel-plugin-transform-exponentiation-operator/README.md index 0851d321f12c..82769d80a36a 100644 --- a/packages/babel-plugin-transform-exponentiation-operator/README.md +++ b/packages/babel-plugin-transform-exponentiation-operator/README.md @@ -1,11 +1,35 @@ # babel-plugin-transform-exponentiation-operator -Compile exponentiation operator to ES5 +> Compile exponentiation operator to ES5 + +## Example + +```js +// x ** y + +let squared = 2 ** 2; +// same as: 2 * 2 + +let cubed = 2 ** 3; +// same as: 2 * 2 * 2 + + +// x **= y + +let a = 2; +a **= 2; +// same as: a = a * a; + +let b = 3; +b **= 3; +// same as: b = b * b * b; +``` +[Try in REPL](http://babeljs.io/repl/#?evaluate=true&presets=es2015%2Cstage-0&code=%2F%2F%20x%20**%20y%0A%0Alet%20squared%20%3D%202%20**%202%3B%0A%2F%2F%20same%20as%3A%202%20*%202%0A%0Alet%20cubed%20%3D%202%20**%203%3B%0A%2F%2F%20same%20as%3A%202%20*%202%20*%202%0A%0A%0A%2F%2F%20x%20**%3D%20y%0A%0Alet%20a%20%3D%202%3B%0Aa%20**%3D%202%3B%0A%2F%2F%20same%20as%3A%20a%20%3D%20a%20*%20a%3B%0A%0Alet%20b%20%3D%203%3B%0Ab%20**%3D%203%3B%0A%2F%2F%20same%20as%3A%20b%20%3D%20b%20*%20b%20*%20b%3B) ## Installation ```sh -$ npm install babel-plugin-transform-exponentiation-operator +npm install --save-dev babel-plugin-transform-exponentiation-operator ``` ## Usage @@ -23,7 +47,7 @@ $ npm install babel-plugin-transform-exponentiation-operator ### Via CLI ```sh -$ babel --plugins transform-exponentiation-operator script.js +babel --plugins transform-exponentiation-operator script.js ``` ### Via Node API @@ -33,3 +57,8 @@ require("babel-core").transform("code", { plugins: ["transform-exponentiation-operator"] }); ``` + +## References + +* [Proposal: Exponentiation Operator](https://github.com/rwaldron/exponentiation-operator) +* [Spec: Exponential Operator](https://rwaldron.github.io/exponentiation-operator/) diff --git a/packages/babel-plugin-transform-export-extensions/README.md b/packages/babel-plugin-transform-export-extensions/README.md index 13a8489fb8d3..26f7d5127824 100644 --- a/packages/babel-plugin-transform-export-extensions/README.md +++ b/packages/babel-plugin-transform-export-extensions/README.md @@ -1,11 +1,19 @@ # babel-plugin-transform-export-extensions -Compile export extensions to ES2015 +> Compile additional export-from statements to ES2015 + +## Example + +```js +export * as ns from 'mod'; +export v from 'mod'; +``` +[Try in REPL](http://babeljs.io/repl/#?evaluate=true&presets=es2015%2Cstage-0&code=export%20*%20as%20ns%20from%20'mod'%3B%0Aexport%20v%20from%20'mod'%3B) ## Installation ```sh -$ npm install babel-plugin-transform-export-extensions +npm install --save-dev babel-plugin-transform-export-extensions ``` ## Usage @@ -23,7 +31,7 @@ $ npm install babel-plugin-transform-export-extensions ### Via CLI ```sh -$ babel --plugins transform-export-extensions script.js +babel --plugins transform-export-extensions script.js ``` ### Via Node API @@ -33,3 +41,8 @@ require("babel-core").transform("code", { plugins: ["transform-export-extensions"] }); ``` +## References + +* ~~[Proposal: Additional export-from statements in ES7](https://github.com/leebyron/ecmascript-more-export-from)~~ (Withdrawn) +* [ECMAScript Proposal: export ns from](https://github.com/leebyron/ecmascript-export-ns-from) +* [ECMAScript Proposal: export default from](https://github.com/leebyron/ecmascript-export-default-from) diff --git a/packages/babel-plugin-transform-flow-comments/README.md b/packages/babel-plugin-transform-flow-comments/README.md index 4a5afd27b801..46beb7a301e9 100644 --- a/packages/babel-plugin-transform-flow-comments/README.md +++ b/packages/babel-plugin-transform-flow-comments/README.md @@ -1,10 +1,10 @@ # babel-plugin-transform-flow-comments -Turn flow type annotations into comments. +> Turn flow type annotations into comments. You should be able to use this plugin instead of `babel-plugin-flow-strip-types` to preserve the `/* @flow */` directive and still use flow. -http://flowtype.org/blog/2015/02/20/Flow-Comments.html +[Flow Comments Blog Post](http://flowtype.org/blog/2015/02/20/Flow-Comments.html) ## Example @@ -41,7 +41,7 @@ function foo(x /*: number*/) /*: string*/ {} ## Installation ```sh -$ npm install babel-plugin-transform-flow-comments +npm install --save-dev babel-plugin-transform-flow-comments ``` ## Usage @@ -59,7 +59,7 @@ $ npm install babel-plugin-transform-flow-comments ### Via CLI ```sh -$ babel --plugins transform-flow-comments script.js +babel --plugins transform-flow-comments script.js ``` ### Via Node API diff --git a/packages/babel-plugin-transform-flow-strip-types/README.md b/packages/babel-plugin-transform-flow-strip-types/README.md index f846bd24d7ee..afde54949b27 100644 --- a/packages/babel-plugin-transform-flow-strip-types/README.md +++ b/packages/babel-plugin-transform-flow-strip-types/README.md @@ -1,11 +1,28 @@ # babel-plugin-transform-flow-strip-types -Strip flow type annotations from your output code. +> Strip all [flow](http://flowtype.org) type annotations and declarations from your output code. + +## Example + +**In** + +```javascript +function foo(one: any, two: number, three?): string {} +``` + +**Out** + +```javascript +function foo(one, two, three) {} +``` + +[Try in REPL](http://babeljs.io/repl/#?babili=false&evaluate=true&lineWrap=false&presets=react&code=function%20foo(one%3A%20any%2C%20two%3A%20number%2C%20three%3F)%3A%20string%20%7B%7D&experimental=false&loose=false&spec=false&playground=false&stage=0 +) ## Installation ```sh -$ npm install babel-plugin-transform-flow-strip-types +npm install --save-dev babel-plugin-transform-flow-strip-types ``` ## Usage @@ -23,7 +40,7 @@ $ npm install babel-plugin-transform-flow-strip-types ### Via CLI ```sh -$ babel --plugins transform-flow-strip-types script.js +babel --plugins transform-flow-strip-types script.js ``` ### Via Node API diff --git a/packages/babel-plugin-transform-function-bind/README.md b/packages/babel-plugin-transform-function-bind/README.md index 8f496c5fd9f1..8e11aeae8698 100644 --- a/packages/babel-plugin-transform-function-bind/README.md +++ b/packages/babel-plugin-transform-function-bind/README.md @@ -1,11 +1,91 @@ # babel-plugin-transform-function-bind -Compile function bind operator to ES5 +> Compile the new function bind operator `::` to ES5. + +## Detail + +```js +obj::func +// is equivalent to: +func.bind(obj) + +obj::func(val) +// is equivalent to: +func.call(obj, val) + +::obj.func(val) +// is equivalent to: +func.call(obj, val) +``` + +[Try in REPL](http://babeljs.io/repl/#?evaluate=true&presets=es2015%2Cstage-0&code=obj%3A%3Afunc%3B%0A%0Aobj%3A%3Afunc(val)%3B%0A%0A%3A%3Aobj.func(val)%3B) + +## Example + +### Basic + +```js +const box = { + weight: 2, + getWeight() { return this.weight; }, +}; + +const { getWeight } = box; + +console.log(box.getWeight()); // prints '2' + +const bigBox = { weight: 10 }; +console.log(bigBox::getWeight()); // prints '10' + +// Can be chained: +function add(val) { return this + val; } + +console.log(bigBox::getWeight()::add(5)); // prints '15' +``` + +[Try in REPL](http://babeljs.io/repl/#?evaluate=true&presets=es2015%2Cstage-0&code=const%20box%20%3D%20%7B%0A%20%20weight%3A%202%2C%0A%20%20getWeight()%20%7B%20return%20this.weight%3B%20%7D%2C%0A%7D%3B%0A%0Aconst%20%7B%20getWeight%20%7D%20%3D%20box%3B%0A%0Aconsole.log(box.getWeight())%3B%20%2F%2F%20prints%20'2'%0A%0Aconst%20bigBox%20%3D%20%7B%20weight%3A%2010%20%7D%3B%0Aconsole.log(bigBox%3A%3AgetWeight())%3B%20%2F%2F%20prints%20'10'%0A%2F%2F%20bigBox%3A%3AgetWeight()%20is%20equivalent%20to%20getWeight.call(bigBox)%0A%0A%2F%2F%20Can%20be%20chained%3A%0Afunction%20add(val)%20%7B%20return%20this%20%2B%20val%3B%20%7D%0A%0Aconsole.log(bigBox%3A%3AgetWeight()%3A%3Aadd(5))%3B%20%2F%2F%20prints%20'15') + +### Using with `document.querySelectorAll` + +It can be very handy when used with `document.querySelectorAll`: + +```js +const { map, filter } = Array.prototype; + +let sslUrls = document.querySelectorAll('a') + ::map(node => node.href) + ::filter(href => href.substring(0, 5) === 'https'); + +console.log(sslUrls); +``` + +[Try in REPL](http://babeljs.io/repl/#?evaluate=true&presets=es2015%2Cstage-0&code=%0Aconst%20%7B%20map%2C%20filter%20%7D%20%3D%20Array.prototype%3B%0A%0Alet%20sslUrls%20%3D%20document.querySelectorAll('a')%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%3A%3Amap(node%20%3D%3E%20node.href)%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%3A%3Afilter(href%20%3D%3E%20href.substring(0%2C%205)%20%3D%3D%3D%20'https')%3B%0A%0Aconsole.log(sslUrls)%3B%0A) + +`document.querySelectorAll` returns a `NodeList` element which is not a plain array, so you normally can't use the `map` function on it, and have to use it this way: `Array.prototype.map.call(document.querySelectorAll(...), node => { ... })`. The above code using the `::` will work because it is equivalent to: + +```js +const { map, filter } = Array.prototype; + +let sslUrls = document.querySelectorAll('a'); +sslUrls = map.call(sslUrls, node => node.href); +sslUrls = filter.call(sslUrls, href => href.substring(0, 5) === 'https'); + +console.log(sslUrls); +``` + +### Auto self binding +When nothing is specified before the `::` operator, the function is bound to its object: + +```js +$('.some-link').on('click', ::view.reset); +// is equivalent to: +$('.some-link').on('click', view.reset.bind(view)); +``` ## Installation ```sh -$ npm install babel-plugin-transform-function-bind +npm install --save-dev babel-plugin-transform-function-bind ``` ## Usage @@ -23,7 +103,7 @@ $ npm install babel-plugin-transform-function-bind ### Via CLI ```sh -$ babel --plugins transform-function-bind script.js +babel --plugins transform-function-bind script.js ``` ### Via Node API @@ -33,3 +113,8 @@ require("babel-core").transform("code", { plugins: ["transform-function-bind"] }); ``` + +## References + +* [Proposal](https://github.com/zenparsing/es-function-bind) +* [Babel Blog: Function Bind Syntax](/blog/2015/05/14/function-bind) \ No newline at end of file diff --git a/packages/babel-plugin-transform-jscript/README.md b/packages/babel-plugin-transform-jscript/README.md index 948344bac522..5595b21b55ad 100644 --- a/packages/babel-plugin-transform-jscript/README.md +++ b/packages/babel-plugin-transform-jscript/README.md @@ -1,11 +1,33 @@ # babel-plugin-transform-jscript -Babel plugin to fix buggy JScript named function expressions +> This plugin allows Babel to transform named function expressions into function declarations to get around some [particularly nasty JScript bugs](https://kangax.github.io/nfe/#jscript-bugs) related to name function expressions. + +## Example + +**In** + +```javascript +var foo = function bar() { + +}; +``` + +**Out** + +```javascript +"use strict"; + +var foo = (function () { + function bar() {} + + return bar; +})(); +``` ## Installation ```sh -$ npm install babel-plugin-transform-jscript +npm install --save-dev babel-plugin-transform-jscript ``` ## Usage @@ -23,7 +45,7 @@ $ npm install babel-plugin-transform-jscript ### Via CLI ```sh -$ babel --plugins transform-jscript script.js +babel --plugins transform-jscript script.js ``` ### Via Node API diff --git a/packages/babel-plugin-transform-object-assign/README.md b/packages/babel-plugin-transform-object-assign/README.md index 027b096217cd..100fe5fbb895 100644 --- a/packages/babel-plugin-transform-object-assign/README.md +++ b/packages/babel-plugin-transform-object-assign/README.md @@ -1,6 +1,6 @@ # babel-plugin-transform-object-assign -Replace `Object.assign` with an inline helper. +> Replace `Object.assign` with an inline helper. If you are authoring an application, rather than a library, it is recommended that you use the `Object.assign` polyfill instead. ## Example @@ -18,10 +18,19 @@ var _extends = ...; _extends(a, b); ``` +## Caveats + +- Will only work with code of the form `Object.assign` or `Object['assign']`. The following patterns are not supported: + + ```javascript + var { assign } = Object; + var assign = Object.assign; + ``` + ## Installation ```sh -$ npm install babel-plugin-transform-object-assign +npm install --save-dev babel-plugin-transform-object-assign ``` ## Usage @@ -39,7 +48,7 @@ $ npm install babel-plugin-transform-object-assign ### Via CLI ```sh -$ babel --plugins transform-object-assign script.js +babel --plugins transform-object-assign script.js ``` ### Via Node API diff --git a/packages/babel-plugin-transform-object-rest-spread/README.md b/packages/babel-plugin-transform-object-rest-spread/README.md index 622cfa208bff..7fd2afe5305d 100644 --- a/packages/babel-plugin-transform-object-rest-spread/README.md +++ b/packages/babel-plugin-transform-object-rest-spread/README.md @@ -1,20 +1,27 @@ # babel-plugin-transform-object-rest-spread -Compile object rest and spread to ES5 +> This plugin allows Babel to transform rest properties for object destructuring assignment and spread properties for object literals. -```js -// source -z = { x, ...y }; +## Example -// compiled -_extends = Object.assign || function(target) { ... } -z = _extends({ x }, y); +```js +// Rest properties +let { x, y, ...z } = { x: 1, y: 2, a: 3, b: 4 }; +console.log(x); // 1 +console.log(y); // 2 +console.log(z); // { a: 3, b: 4 } + +// Spread properties +let n = { x, y, ...z }; +console.log(n); // { x: 1, y: 2, a: 3, b: 4 } ``` +[Try in REPL](https://babeljs.io/repl/#?evaluate=true&presets=es2015%2Cstage-0&code=%2F%2F%20Rest%20properties%0Alet%20%7B%20x%2C%20y%2C%20...z%20%7D%20%3D%20%7B%20x%3A%201%2C%20y%3A%202%2C%20a%3A%203%2C%20b%3A%204%20%7D%3B%0Aconsole.log(x)%3B%20%2F%2F%201%0Aconsole.log(y)%3B%20%2F%2F%202%0Aconsole.log(z)%3B%20%2F%2F%20%7B%20a%3A%203%2C%20b%3A%204%20%7D%0A%0A%2F%2F%20Spread%20properties%0Alet%20n%20%3D%20%7B%20x%2C%20y%2C%20...z%20%7D%3B%0Aconsole.log(n)%3B%20%2F%2F%20%7B%20x%3A%201%2C%20y%3A%202%2C%20a%3A%203%2C%20b%3A%204%20%7D) + ## Installation ```sh -$ npm install babel-plugin-transform-object-rest-spread +npm install --save-dev babel-plugin-transform-object-rest-spread ``` ## Usage @@ -51,7 +58,7 @@ z = Object.assign({ x }, y); ### Via CLI ```sh -$ babel --plugins transform-object-rest-spread script.js +babel --plugins transform-object-rest-spread script.js ``` ### Via Node API @@ -61,3 +68,8 @@ require("babel-core").transform("code", { plugins: ["transform-object-rest-spread"] }); ``` + +## References + +* [Proposal: Object Rest/Spread Properties for ECMAScript](https://github.com/sebmarkbage/ecmascript-rest-spread) +* [Spec](http://sebmarkbage.github.io/ecmascript-rest-spread) diff --git a/packages/babel-plugin-transform-object-rest-spread/package.json b/packages/babel-plugin-transform-object-rest-spread/package.json index 18017a87f761..572fc9c51676 100644 --- a/packages/babel-plugin-transform-object-rest-spread/package.json +++ b/packages/babel-plugin-transform-object-rest-spread/package.json @@ -1,6 +1,6 @@ { "name": "babel-plugin-transform-object-rest-spread", - "version": "6.16.0", + "version": "6.20.2", "description": "Compile object rest and spread to ES5", "repository": "https://github.com/babel/babel/tree/master/packages/babel-plugin-transform-object-rest-spread", "license": "MIT", @@ -10,7 +10,7 @@ ], "dependencies": { "babel-plugin-syntax-object-rest-spread": "^6.8.0", - "babel-runtime": "^6.0.0" + "babel-runtime": "^6.20.0" }, "devDependencies": { "babel-helper-plugin-test-runner": "^6.8.0" diff --git a/packages/babel-plugin-transform-object-rest-spread/src/index.js b/packages/babel-plugin-transform-object-rest-spread/src/index.js index ec78fd61a8fd..dbc357be07d9 100644 --- a/packages/babel-plugin-transform-object-rest-spread/src/index.js +++ b/packages/babel-plugin-transform-object-rest-spread/src/index.js @@ -1,6 +1,17 @@ export default function ({ types: t }) { + function hasRestProperty(path) { + let foundRestProperty = false; + path.traverse({ + RestProperty() { + foundRestProperty = true; + path.stop(); + } + }); + return foundRestProperty; + } + function hasSpread(node) { - for (let prop of (node.properties: Array)) { + for (let prop of (node.properties)) { if (t.isSpreadProperty(prop)) { return true; } @@ -8,10 +19,209 @@ export default function ({ types: t }) { return false; } + function createObjectSpread(file, props, objRef) { + const restProperty = props.pop(); + + let keys = []; + for (let prop of props) { + let key = prop.key; + if (t.isIdentifier(key) && !prop.computed) { + key = t.stringLiteral(prop.key.name); + } + keys.push(key); + } + + return [ + restProperty.argument, + t.callExpression( + file.addHelper("objectWithoutProperties"), [ + objRef, + t.arrayExpression(keys) + ] + ) + ]; + } + + function replaceRestProperty(paramsPath, i, numParams) { + if (paramsPath.isObjectPattern() && hasRestProperty(paramsPath)) { + let parentPath = paramsPath.parentPath; + let uid = parentPath.scope.generateUidIdentifier("ref"); + + let declar = t.variableDeclaration("let", [ + t.variableDeclarator(paramsPath.node, uid) + ]); + declar._blockHoist = i ? numParams - i : 1; + + parentPath.ensureBlock(); + parentPath.get("body").unshiftContainer("body", declar); + paramsPath.replaceWith(uid); + } + } + return { inherits: require("babel-plugin-syntax-object-rest-spread"), visitor: { + // taken from transform-es2015-parameters/src/destructuring.js + // function a({ b, ...c }) {} + Function(path) { + let params = path.get("params"); + for (let i = 0; i < params.length; i++) { + replaceRestProperty(params[i], i, params.length); + } + }, + // adapted from transform-es2015-destructuring/src/index.js#pushObjectRest + // const { a, ...b } = c; + VariableDeclarator(path, file) { + if (!path.get("id").isObjectPattern()) { return; } + const kind = path.parentPath.node.kind; + let nodes = []; + + path.traverse({ + RestProperty(path) { + let ref = this.originalPath.node.init; + + path.findParent((path) => { + if (path.isObjectProperty()) { + ref = t.memberExpression(ref, t.identifier(path.node.key.name)); + } else if (path.isVariableDeclarator()) { + return true; + } + }); + + let [ argument, callExpression ] = createObjectSpread( + file, + path.parentPath.node.properties, + ref + ); + + nodes.push( + t.variableDeclarator( + argument, + callExpression + ) + ); + + if (path.parentPath.node.properties.length === 0) { + path.findParent( + (path) => path.isObjectProperty() || path.isVariableDeclaration() + ).remove(); + } + } + },{ + originalPath: path + }); + + if (nodes.length > 0) { + path.parentPath.getSibling(path.parentPath.key + 1) + .insertBefore( + t.variableDeclaration(kind, nodes) + ); + } + }, + // taken from transform-es2015-destructuring/src/index.js#visitor + // export var { a, ...b } = c; + ExportNamedDeclaration(path) { + let declaration = path.get("declaration"); + if (!declaration.isVariableDeclaration()) return; + if (!hasRestProperty(declaration)) return; + + let specifiers = []; + + for (let name in path.getOuterBindingIdentifiers(path)) { + let id = t.identifier(name); + specifiers.push(t.exportSpecifier(id, id)); + } + + // Split the declaration and export list into two declarations so that the variable + // declaration can be split up later without needing to worry about not being a + // top-level statement. + path.replaceWith(declaration.node); + path.insertAfter(t.exportNamedDeclaration(null, specifiers)); + }, + // try {} catch ({a, ...b}) {} + CatchClause(path) { + replaceRestProperty(path.get("param")); + }, + // ({a, ...b} = c); + AssignmentExpression(path, file) { + let leftPath = path.get("left"); + if (leftPath.isObjectPattern() && hasRestProperty(leftPath)) { + let nodes = []; + + let ref; + if (path.isCompletionRecord() || path.parentPath.isExpressionStatement()) { + ref = path.scope.generateUidIdentifierBasedOnNode(path.node.right, "ref"); + + nodes.push(t.variableDeclaration("var", [ + t.variableDeclarator(ref, path.node.right) + ])); + } + + let [ argument, callExpression ] = createObjectSpread( + file, + path.node.left.properties, + ref + ); + + let nodeWithoutSpread = t.clone(path.node); + nodeWithoutSpread.right = ref; + nodes.push(t.expressionStatement(nodeWithoutSpread)); + nodes.push(t.toStatement(t.assignmentExpression( + "=", + argument, + callExpression + ))); + + if (ref) { + nodes.push(t.expressionStatement(ref)); + } + + path.replaceWithMultiple(nodes); + } + }, + // taken from transform-es2015-destructuring/src/index.js#visitor + ForXStatement(path) { + let { node, scope } = path; + let leftPath = path.get("left"); + let left = node.left; + + // for ({a, ...b} of []) {} + if (t.isObjectPattern(left) && hasRestProperty(leftPath)) { + let temp = scope.generateUidIdentifier("ref"); + + node.left = t.variableDeclaration("var", [ + t.variableDeclarator(temp) + ]); + + path.ensureBlock(); + + node.body.body.unshift(t.variableDeclaration("var", [ + t.variableDeclarator(left, temp) + ])); + + return; + } + + if (!t.isVariableDeclaration(left)) return; + + let pattern = left.declarations[0].id; + if (!t.isObjectPattern(pattern)) return; + + let key = scope.generateUidIdentifier("ref"); + node.left = t.variableDeclaration(left.kind, [ + t.variableDeclarator(key, null) + ]); + + path.ensureBlock(); + + node.body.body.unshift( + t.variableDeclaration(node.left.kind, [ + t.variableDeclarator(pattern, key) + ]) + ); + }, + // var a = { ...b, ...c } ObjectExpression(path, file) { if (!hasSpread(path.node)) return; diff --git a/packages/babel-plugin-transform-object-rest-spread/test/fixtures/object-rest-spread/assignment/actual.js b/packages/babel-plugin-transform-object-rest-spread/test/fixtures/object-rest-spread/assignment/actual.js deleted file mode 100644 index 8d610842d85f..000000000000 --- a/packages/babel-plugin-transform-object-rest-spread/test/fixtures/object-rest-spread/assignment/actual.js +++ /dev/null @@ -1 +0,0 @@ -z = { x, ...y }; diff --git a/packages/babel-plugin-transform-object-rest-spread/test/fixtures/object-rest/assignment-expression/actual.js b/packages/babel-plugin-transform-object-rest-spread/test/fixtures/object-rest/assignment-expression/actual.js new file mode 100644 index 000000000000..99416a6a7fd2 --- /dev/null +++ b/packages/babel-plugin-transform-object-rest-spread/test/fixtures/object-rest/assignment-expression/actual.js @@ -0,0 +1,4 @@ +({ a1 } = c1); +({ a2, ...b2 } = c2); + +console.log({ a3, ...b3 } = c3); diff --git a/packages/babel-plugin-transform-object-rest-spread/test/fixtures/object-rest/assignment-expression/expected.js b/packages/babel-plugin-transform-object-rest-spread/test/fixtures/object-rest/assignment-expression/expected.js new file mode 100644 index 000000000000..5ecfdb6a350f --- /dev/null +++ b/packages/babel-plugin-transform-object-rest-spread/test/fixtures/object-rest/assignment-expression/expected.js @@ -0,0 +1,9 @@ +var _c2; + +({ a1 } = c1); +var _c = c2; +({ a2 } = _c); +b2 = babelHelpers.objectWithoutProperties(_c, ["a2"]); + + +console.log((_c2 = c3, ({ a3 } = _c2), b3 = babelHelpers.objectWithoutProperties(_c2, ["a3"]), _c2)); \ No newline at end of file diff --git a/packages/babel-plugin-transform-object-rest-spread/test/fixtures/object-rest/catch-clause/actual.js b/packages/babel-plugin-transform-object-rest-spread/test/fixtures/object-rest/catch-clause/actual.js new file mode 100644 index 000000000000..26b209f90483 --- /dev/null +++ b/packages/babel-plugin-transform-object-rest-spread/test/fixtures/object-rest/catch-clause/actual.js @@ -0,0 +1,8 @@ +try {} catch({ ...a34 }) {} +try {} catch({a1, ...b1}) {} +try {} catch({a2, b2, ...c2}) {} +try {} catch({a2, b2, c2: { c3, ...c4 }}) {} + +// Unchanged +try {} catch(a) {} +try {} catch({ b }) {} diff --git a/packages/babel-plugin-transform-object-rest-spread/test/fixtures/object-rest/catch-clause/expected.js b/packages/babel-plugin-transform-object-rest-spread/test/fixtures/object-rest/catch-clause/expected.js new file mode 100644 index 000000000000..c1695cf2ed16 --- /dev/null +++ b/packages/babel-plugin-transform-object-rest-spread/test/fixtures/object-rest/catch-clause/expected.js @@ -0,0 +1,19 @@ +try {} catch (_ref) { + let a34 = babelHelpers.objectWithoutProperties(_ref, []); +} +try {} catch (_ref2) { + let { a1 } = _ref2; + let b1 = babelHelpers.objectWithoutProperties(_ref2, ["a1"]); +} +try {} catch (_ref3) { + let { a2, b2 } = _ref3; + let c2 = babelHelpers.objectWithoutProperties(_ref3, ["a2", "b2"]); +} +try {} catch (_ref4) { + let { a2, b2, c2: { c3 } } = _ref4; + let c4 = babelHelpers.objectWithoutProperties(_ref4.c2, ["c3"]); +} + +// Unchanged +try {} catch (a) {} +try {} catch ({ b }) {} diff --git a/packages/babel-plugin-transform-object-rest-spread/test/fixtures/object-rest/export/actual.js b/packages/babel-plugin-transform-object-rest-spread/test/fixtures/object-rest/export/actual.js new file mode 100644 index 000000000000..5f0d8f60672d --- /dev/null +++ b/packages/babel-plugin-transform-object-rest-spread/test/fixtures/object-rest/export/actual.js @@ -0,0 +1,5 @@ +// ExportNamedDeclaration +export var { b, ...c } = asdf2; +// Skip +export var { bb, cc } = ads; +export var [ dd, ee ] = ads; diff --git a/packages/babel-plugin-transform-object-rest-spread/test/fixtures/object-rest/export/expected.js b/packages/babel-plugin-transform-object-rest-spread/test/fixtures/object-rest/export/expected.js new file mode 100644 index 000000000000..d3d2967d6e53 --- /dev/null +++ b/packages/babel-plugin-transform-object-rest-spread/test/fixtures/object-rest/export/expected.js @@ -0,0 +1,7 @@ +// ExportNamedDeclaration +var { b } = asdf2; +// Skip +var c = babelHelpers.objectWithoutProperties(asdf2, ["b"]); +export { b, c }; +export var { bb, cc } = ads; +export var [dd, ee] = ads; \ No newline at end of file diff --git a/packages/babel-plugin-transform-object-rest-spread/test/fixtures/object-rest/for-x/actual.js b/packages/babel-plugin-transform-object-rest-spread/test/fixtures/object-rest/for-x/actual.js new file mode 100644 index 000000000000..dd954fa0d235 --- /dev/null +++ b/packages/babel-plugin-transform-object-rest-spread/test/fixtures/object-rest/for-x/actual.js @@ -0,0 +1,19 @@ +// ForXStatement +for (var {a, ...b} of []) {} +for ({a, ...b} of []) {} +async function a() { + for await ({a, ...b} of []) {} +} + +// skip +for ({a} in {}) {} +for ({a} of []) {} +async function a() { + for await ({a} of []) {} +} + +for (a in {}) {} +for (a of []) {} +async function a() { + for await (a of []) {} +} diff --git a/packages/babel-plugin-transform-object-rest-spread/test/fixtures/object-rest/for-x/expected.js b/packages/babel-plugin-transform-object-rest-spread/test/fixtures/object-rest/for-x/expected.js new file mode 100644 index 000000000000..59b38ec57f9c --- /dev/null +++ b/packages/babel-plugin-transform-object-rest-spread/test/fixtures/object-rest/for-x/expected.js @@ -0,0 +1,28 @@ +// ForXStatement +for (var _ref of []) { + var { a } = _ref; + var b = babelHelpers.objectWithoutProperties(_ref, ["a"]); +} +for (var _ref2 of []) { + var { a } = _ref2; + var b = babelHelpers.objectWithoutProperties(_ref2, ["a"]); +} +async function a() { + for await (var _ref3 of []) { + var { a } = _ref3; + var b = babelHelpers.objectWithoutProperties(_ref3, ["a"]); + } +} + +// skip +for ({ a } in {}) {} +for ({ a } of []) {} +async function a() { + for ({ a } of []) {} +} + +for (a in {}) {} +for (a of []) {} +async function a() { + for (a of []) {} +} \ No newline at end of file diff --git a/packages/babel-plugin-transform-object-rest-spread/test/fixtures/object-rest/options.json b/packages/babel-plugin-transform-object-rest-spread/test/fixtures/object-rest/options.json new file mode 100644 index 000000000000..cd791fa2bca5 --- /dev/null +++ b/packages/babel-plugin-transform-object-rest-spread/test/fixtures/object-rest/options.json @@ -0,0 +1,7 @@ +{ + "plugins": [ + "syntax-async-generators", + "transform-object-rest-spread", + "external-helpers" + ] +} diff --git a/packages/babel-plugin-transform-object-rest-spread/test/fixtures/object-rest/parameters/actual.js b/packages/babel-plugin-transform-object-rest-spread/test/fixtures/object-rest/parameters/actual.js new file mode 100644 index 000000000000..a3beccb8a4f5 --- /dev/null +++ b/packages/babel-plugin-transform-object-rest-spread/test/fixtures/object-rest/parameters/actual.js @@ -0,0 +1,10 @@ +function a({ ...a34 }) {} +function a2({a1, ...b1}) {} +function a3({a2, b2, ...c2}) {} +function a4({a3, ...c3}, {a5, ...c5}) {} +function a5({a3, b2: { ba1, ...ba2 }, ...c3}) {} +function a6({a3, b2: { ba1, ...ba2 } }) {} +// Unchanged +function b(a) {} +function b2(a, ...b) {} +function b3({ b }) {} diff --git a/packages/babel-plugin-transform-object-rest-spread/test/fixtures/object-rest/parameters/expected.js b/packages/babel-plugin-transform-object-rest-spread/test/fixtures/object-rest/parameters/expected.js new file mode 100644 index 000000000000..a3ec9786f754 --- /dev/null +++ b/packages/babel-plugin-transform-object-rest-spread/test/fixtures/object-rest/parameters/expected.js @@ -0,0 +1,30 @@ +function a(_ref) { + let a34 = babelHelpers.objectWithoutProperties(_ref, []); +} +function a2(_ref2) { + let { a1 } = _ref2; + let b1 = babelHelpers.objectWithoutProperties(_ref2, ["a1"]); +} +function a3(_ref3) { + let { a2, b2 } = _ref3; + let c2 = babelHelpers.objectWithoutProperties(_ref3, ["a2", "b2"]); +} +function a4(_ref4, _ref5) { + let { a5 } = _ref5; + let c5 = babelHelpers.objectWithoutProperties(_ref5, ["a5"]); + let { a3 } = _ref4; + let c3 = babelHelpers.objectWithoutProperties(_ref4, ["a3"]); +} +function a5(_ref6) { + let { a3, b2: { ba1 } } = _ref6; + let ba2 = babelHelpers.objectWithoutProperties(_ref6.b2, ["ba1"]), + c3 = babelHelpers.objectWithoutProperties(_ref6, ["a3", "b2"]); +} +function a6(_ref7) { + let { a3, b2: { ba1 } } = _ref7; + let ba2 = babelHelpers.objectWithoutProperties(_ref7.b2, ["ba1"]); +} +// Unchanged +function b(a) {} +function b2(a, ...b) {} +function b3({ b }) {} diff --git a/packages/babel-plugin-transform-object-rest-spread/test/fixtures/object-rest/variable-destructuring/actual.js b/packages/babel-plugin-transform-object-rest-spread/test/fixtures/object-rest/variable-destructuring/actual.js new file mode 100644 index 000000000000..6eed55d73979 --- /dev/null +++ b/packages/babel-plugin-transform-object-rest-spread/test/fixtures/object-rest/variable-destructuring/actual.js @@ -0,0 +1,19 @@ +var z = {}; +var { ...x } = z; +var { ...a } = { a: 1 }; +var { ...x } = a.b; +var { ...x } = a(); +var {x1, ...y1} = z; +x1++; +var { [a]: b, ...c } = z; +var {x1, ...y1} = z; +let {x2, y2, ...z2} = z; +const {w3, x3, y3, ...z4} = z; + +let { + x: { a: xa, [d]: f, ...asdf }, + y: { ...d }, + ...g +} = complex; + +let { x4: { ...y4 } } = z; diff --git a/packages/babel-plugin-transform-object-rest-spread/test/fixtures/object-rest/variable-destructuring/expected.js b/packages/babel-plugin-transform-object-rest-spread/test/fixtures/object-rest/variable-destructuring/expected.js new file mode 100644 index 000000000000..c7d81cdf9998 --- /dev/null +++ b/packages/babel-plugin-transform-object-rest-spread/test/fixtures/object-rest/variable-destructuring/expected.js @@ -0,0 +1,27 @@ +var z = {}; +var x = babelHelpers.objectWithoutProperties(z, []); +var a = babelHelpers.objectWithoutProperties({ a: 1 }, []); +var x = babelHelpers.objectWithoutProperties(a.b, []); +var x = babelHelpers.objectWithoutProperties(a(), []); + +var { x1 } = z; +var y1 = babelHelpers.objectWithoutProperties(z, ["x1"]); +x1++; +var { [a]: b } = z; +var c = babelHelpers.objectWithoutProperties(z, [a]); +var { x1 } = z; +var y1 = babelHelpers.objectWithoutProperties(z, ["x1"]); +let { x2, y2 } = z; +let z2 = babelHelpers.objectWithoutProperties(z, ["x2", "y2"]); +const { w3, x3, y3 } = z; + +const z4 = babelHelpers.objectWithoutProperties(z, ["w3", "x3", "y3"]); +let { + x: { a: xa, [d]: f } +} = complex; + +let asdf = babelHelpers.objectWithoutProperties(complex.x, ["a", d]), + d = babelHelpers.objectWithoutProperties(complex.y, []), + g = babelHelpers.objectWithoutProperties(complex, ["x"]); +let {} = z; +let y4 = babelHelpers.objectWithoutProperties(z.x4, []); diff --git a/packages/babel-plugin-transform-object-rest-spread/test/fixtures/object-rest/variable-exec/exec.js b/packages/babel-plugin-transform-object-rest-spread/test/fixtures/object-rest/variable-exec/exec.js new file mode 100644 index 000000000000..7f58d8f45444 --- /dev/null +++ b/packages/babel-plugin-transform-object-rest-spread/test/fixtures/object-rest/variable-exec/exec.js @@ -0,0 +1,22 @@ +// var { x, y, ...z } = { x: 1, y: 2, a: 3, b: 4 }; + +// assert.equal(x, 1); +// assert.equal(y, 2); +// assert.deepEqual(z, { a: 3, b: 4 }); + +// var complex = { +// x: { a: 1, b: 2, c: 3 }, +// }; + +// var { +// x: { a: xa, ...xbc } +// } = complex; + +// assert.equal(xa, 1); +// assert.deepEqual(xbc, { b: 2, c: 3}); + +// // own properties +// function ownX({ ...properties }) { +// return properties.x; +// } +// assert.equal(ownX(Object.create({ x: 1 })), undefined); diff --git a/packages/babel-plugin-transform-object-rest-spread/test/fixtures/object-rest-spread/options.json b/packages/babel-plugin-transform-object-rest-spread/test/fixtures/object-rest/variable-exec/options.json similarity index 100% rename from packages/babel-plugin-transform-object-rest-spread/test/fixtures/object-rest-spread/options.json rename to packages/babel-plugin-transform-object-rest-spread/test/fixtures/object-rest/variable-exec/options.json diff --git a/packages/babel-plugin-transform-object-rest-spread/test/fixtures/object-spread/assignment/actual.js b/packages/babel-plugin-transform-object-rest-spread/test/fixtures/object-spread/assignment/actual.js new file mode 100644 index 000000000000..6f0367fb7c70 --- /dev/null +++ b/packages/babel-plugin-transform-object-rest-spread/test/fixtures/object-spread/assignment/actual.js @@ -0,0 +1,3 @@ +z = { x, ...y }; + +z = { x, w: { ...y } }; diff --git a/packages/babel-plugin-transform-object-rest-spread/test/fixtures/object-rest-spread/assignment/expected.js b/packages/babel-plugin-transform-object-rest-spread/test/fixtures/object-spread/assignment/expected.js similarity index 89% rename from packages/babel-plugin-transform-object-rest-spread/test/fixtures/object-rest-spread/assignment/expected.js rename to packages/babel-plugin-transform-object-rest-spread/test/fixtures/object-spread/assignment/expected.js index 5e42763fcec7..1b1a3defbabd 100644 --- a/packages/babel-plugin-transform-object-rest-spread/test/fixtures/object-rest-spread/assignment/expected.js +++ b/packages/babel-plugin-transform-object-rest-spread/test/fixtures/object-spread/assignment/expected.js @@ -1,3 +1,5 @@ var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; z = _extends({ x }, y); + +z = { x, w: _extends({}, y) }; diff --git a/packages/babel-plugin-transform-object-rest-spread/test/fixtures/object-rest-spread/expression/actual.js b/packages/babel-plugin-transform-object-rest-spread/test/fixtures/object-spread/expression/actual.js similarity index 100% rename from packages/babel-plugin-transform-object-rest-spread/test/fixtures/object-rest-spread/expression/actual.js rename to packages/babel-plugin-transform-object-rest-spread/test/fixtures/object-spread/expression/actual.js diff --git a/packages/babel-plugin-transform-object-rest-spread/test/fixtures/object-rest-spread/expression/expected.js b/packages/babel-plugin-transform-object-rest-spread/test/fixtures/object-spread/expression/expected.js similarity index 100% rename from packages/babel-plugin-transform-object-rest-spread/test/fixtures/object-rest-spread/expression/expected.js rename to packages/babel-plugin-transform-object-rest-spread/test/fixtures/object-spread/expression/expected.js diff --git a/packages/babel-plugin-transform-object-rest-spread/test/fixtures/object-spread/options.json b/packages/babel-plugin-transform-object-rest-spread/test/fixtures/object-spread/options.json new file mode 100644 index 000000000000..85af630bdd1b --- /dev/null +++ b/packages/babel-plugin-transform-object-rest-spread/test/fixtures/object-spread/options.json @@ -0,0 +1,3 @@ +{ + "plugins": ["transform-object-rest-spread"] +} diff --git a/packages/babel-plugin-transform-object-rest-spread/test/fixtures/object-rest-spread/variable-declaration/actual.js b/packages/babel-plugin-transform-object-rest-spread/test/fixtures/object-spread/variable-declaration/actual.js similarity index 100% rename from packages/babel-plugin-transform-object-rest-spread/test/fixtures/object-rest-spread/variable-declaration/actual.js rename to packages/babel-plugin-transform-object-rest-spread/test/fixtures/object-spread/variable-declaration/actual.js diff --git a/packages/babel-plugin-transform-object-rest-spread/test/fixtures/object-rest-spread/variable-declaration/expected.js b/packages/babel-plugin-transform-object-rest-spread/test/fixtures/object-spread/variable-declaration/expected.js similarity index 100% rename from packages/babel-plugin-transform-object-rest-spread/test/fixtures/object-rest-spread/variable-declaration/expected.js rename to packages/babel-plugin-transform-object-rest-spread/test/fixtures/object-spread/variable-declaration/expected.js diff --git a/packages/babel-plugin-transform-object-set-prototype-of-to-assign/README.md b/packages/babel-plugin-transform-object-set-prototype-of-to-assign/README.md index f22270bdf1bf..e11da1d99ddc 100644 --- a/packages/babel-plugin-transform-object-set-prototype-of-to-assign/README.md +++ b/packages/babel-plugin-transform-object-set-prototype-of-to-assign/README.md @@ -1,7 +1,6 @@ # babel-plugin-transform-object-set-prototype-of-to-assign - -The `object-set-prototype-of-to-assign` plugin will transform all `Object.setPrototypeOf` calls to a method that will do a shallow defaults of all properties. +> This plugin will transform all `Object.setPrototypeOf` calls to a method that will do a shallow defaults of all properties. **NOTE:** There are some caveats when using this plugin, see the [`babel-plugin-transform-proto-to-assign` README](https://github.com/babel/babel/tree/master/packages/babel-plugin-transform-proto-to-assign) for more information.. @@ -24,7 +23,7 @@ _defaults(bar, foo); ## Installation ```sh -$ npm install babel-plugin-transform-object-set-prototype-of-to-assign +npm install --save-dev babel-plugin-transform-object-set-prototype-of-to-assign ``` ## Usage @@ -42,7 +41,7 @@ $ npm install babel-plugin-transform-object-set-prototype-of-to-assign ### Via CLI ```sh -$ babel --plugins transform-object-set-prototype-of-to-assign script.js +babel --plugins transform-object-set-prototype-of-to-assign script.js ``` ### Via Node API diff --git a/packages/babel-plugin-transform-proto-to-assign/README.md b/packages/babel-plugin-transform-proto-to-assign/README.md index 1af2deab1b02..9e6997265b07 100644 --- a/packages/babel-plugin-transform-proto-to-assign/README.md +++ b/packages/babel-plugin-transform-proto-to-assign/README.md @@ -1,7 +1,8 @@ # babel-plugin-transform-proto-to-assign -The `proto-to-assign`plugin will transform all `__proto__` assignments to a method that will do a shallow copy of -all properties. +> This plugin allows Babel to transform all `__proto__` assignments to a method that will do a shallow copy of all properties. + +## Detail This means that the following **will** work: @@ -45,7 +46,7 @@ _defaults(bar, foo); ## Installation ```sh -$ npm install babel-plugin-transform-proto-to-assign +npm install --save-dev babel-plugin-transform-proto-to-assign ``` ## Usage @@ -63,7 +64,7 @@ $ npm install babel-plugin-transform-proto-to-assign ### Via CLI ```sh -$ babel --plugins transform-proto-to-assign script.js +babel --plugins transform-proto-to-assign script.js ``` ### Via Node API diff --git a/packages/babel-plugin-transform-react-constant-elements/README.md b/packages/babel-plugin-transform-react-constant-elements/README.md index e2c7e2cb99ca..6a75ab7a4a4c 100644 --- a/packages/babel-plugin-transform-react-constant-elements/README.md +++ b/packages/babel-plugin-transform-react-constant-elements/README.md @@ -1,11 +1,52 @@ # babel-plugin-transform-react-constant-elements -Treat React JSX elements as value types and hoist them to the highest scope +> Treat React JSX elements as value types and hoist them to the highest scope + +## Example + +**In** + +```js +const Hr = () => { + return
; +}; +``` + +**Out** + +```js +const _ref =
; + +const Hr = () => { + return _ref; +}; +``` + +**Deopts** + +- **Spread Operator** + + ```js +
+ ``` + +- **Refs** + + ```js +
+
this.node = node} /> + ``` + +- **Composite Components** + + ```js + const ComponentA = () =>
; + ``` ## Installation ```sh -$ npm install babel-plugin-transform-react-constant-elements +npm install --save-dev babel-plugin-transform-react-constant-elements ``` ## Usage @@ -23,7 +64,7 @@ $ npm install babel-plugin-transform-react-constant-elements ### Via CLI ```sh -$ babel --plugins transform-react-constant-elements script.js +babel --plugins transform-react-constant-elements script.js ``` ### Via Node API @@ -33,3 +74,7 @@ require("babel-core").transform("code", { plugins: ["transform-react-constant-elements"] }); ``` + +## References + +* [[facebook/react#3226] Optimizing Compiler: Reuse Constant Value Types like ReactElement](https://github.com/facebook/react/issues/3226) diff --git a/packages/babel-plugin-transform-react-display-name/README.md b/packages/babel-plugin-transform-react-display-name/README.md index 1eeb49cda258..da5fddf0bcc1 100644 --- a/packages/babel-plugin-transform-react-display-name/README.md +++ b/packages/babel-plugin-transform-react-display-name/README.md @@ -1,11 +1,27 @@ # babel-plugin-transform-react-display-name -Add displayName to React.createClass calls +> Add displayName to React.createClass calls + +## Example + +**In** + +```js +var foo = React.createClass({}); +``` + +**Out** + +```js +var foo = React.createClass({ + displayName: "foo" +}); +``` ## Installation ```sh -$ npm install babel-plugin-transform-react-display-name +npm install --save-dev babel-plugin-transform-react-display-name ``` ## Usage @@ -23,7 +39,7 @@ $ npm install babel-plugin-transform-react-display-name ### Via CLI ```sh -$ babel --plugins transform-react-display-name script.js +babel --plugins transform-react-display-name script.js ``` ### Via Node API diff --git a/packages/babel-plugin-transform-react-inline-elements/README.md b/packages/babel-plugin-transform-react-inline-elements/README.md index 8d3834c3d494..8893106af4da 100644 --- a/packages/babel-plugin-transform-react-inline-elements/README.md +++ b/packages/babel-plugin-transform-react-inline-elements/README.md @@ -1,11 +1,44 @@ # babel-plugin-transform-react-inline-elements -Turn JSX elements into exploded React objects +> Replaces the `React.createElement` function with one that is more optimized for production: `babelHelpers.jsx`. + +## Example + +**In** + +```javascript +; +``` + +**Out** + +```javascript +babelHelpers.jsx(Baz, { + foo: "bar" +}, "1"); + +/** + * Instead of + * + * React.createElement(Baz, { + * foo: "bar", + * key: "1", + * }); + */ +``` + +**Deopt** + +```js +// The plugin will still use React.createElement when `ref` or `object rest spread` is used + + +``` ## Installation ```sh -$ npm install babel-plugin-transform-react-inline-elements +npm install --save-dev babel-plugin-transform-react-inline-elements ``` ## Usage @@ -23,7 +56,7 @@ $ npm install babel-plugin-transform-react-inline-elements ### Via CLI ```sh -$ babel --plugins transform-react-inline-elements script.js +babel --plugins transform-react-inline-elements script.js ``` ### Via Node API @@ -33,3 +66,7 @@ require("babel-core").transform("code", { plugins: ["transform-react-inline-elements"] }); ``` + +## References + +* [[facebook/react#3228] Optimizing Compiler: Inline React Elements](https://github.com/facebook/react/issues/3228) diff --git a/packages/babel-plugin-transform-react-jsx-compat/README.md b/packages/babel-plugin-transform-react-jsx-compat/README.md index dee9fd8fdbd8..73006a47167b 100644 --- a/packages/babel-plugin-transform-react-jsx-compat/README.md +++ b/packages/babel-plugin-transform-react-jsx-compat/README.md @@ -1,11 +1,31 @@ # babel-plugin-transform-react-jsx-compat -Turn JSX into React Pre-0.12 function calls +> Turn JSX into React Pre-0.12 function calls + +## Example + +**In** + +```javascript +var profile =
+ +

{[user.firstName, user.lastName].join(' ')}

+
; +``` + +**Out** + +```javascript +var profile = React.DOM.div(null, + React.DOM.img({ src: "avatar.png", "class": "profile" }), + React.DOM.h3(null, [user.firstName, user.lastName].join(" ")) +); +``` ## Installation ```sh -$ npm install babel-plugin-transform-react-jsx-compat +npm install --save-dev babel-plugin-transform-react-jsx-compat ``` ## Usage @@ -23,7 +43,7 @@ $ npm install babel-plugin-transform-react-jsx-compat ### Via CLI ```sh -$ babel --plugins transform-react-jsx-compat script.js +babel --plugins transform-react-jsx-compat script.js ``` ### Via Node API diff --git a/packages/babel-plugin-transform-react-jsx-self/README.md b/packages/babel-plugin-transform-react-jsx-self/README.md index 2a60a3b5013c..69395fe45469 100644 --- a/packages/babel-plugin-transform-react-jsx-self/README.md +++ b/packages/babel-plugin-transform-react-jsx-self/README.md @@ -1,16 +1,16 @@ # babel-plugin-transform-react-jsx-self -Adds `__self` prop to JSX elements, which React will use to generate some runtime warnings. All React users -should enable this transform in dev mode. +> Adds `__self` prop to JSX elements, which React will use to generate some runtime warnings. All React users should enable this transform in dev mode. ## Example -###In +**In** ``` ``` -###Out + +**Out** ``` @@ -19,7 +19,7 @@ should enable this transform in dev mode. ## Installation ```sh -$ npm install babel-plugin-transform-react-jsx-self +npm install --save-dev babel-plugin-transform-react-jsx-self ``` ## Usage @@ -37,7 +37,7 @@ $ npm install babel-plugin-transform-react-jsx-self ### Via CLI ```sh -$ babel --plugins transform-react-jsx-self script.js +babel --plugins transform-react-jsx-self script.js ``` ### Via Node API diff --git a/packages/babel-plugin-transform-react-jsx-source/README.md b/packages/babel-plugin-transform-react-jsx-source/README.md index 002c1adbd966..da6e5a4bed88 100644 --- a/packages/babel-plugin-transform-react-jsx-source/README.md +++ b/packages/babel-plugin-transform-react-jsx-source/README.md @@ -1,24 +1,25 @@ # babel-plugin-transform-react-jsx-source -Adds source file and line number to JSX elements. +> Adds source file and line number to JSX elements. ## Example -###In +**In** ``` ``` -###Out + +**Out** ``` - + ``` ## Installation ```sh -$ npm install babel-plugin-transform-react-jsx-source +npm install --save-dev babel-plugin-transform-react-jsx-source ``` ## Usage @@ -36,7 +37,7 @@ $ npm install babel-plugin-transform-react-jsx-source ### Via CLI ```sh -$ babel --plugins transform-react-jsx-source script.js +babel --plugins transform-react-jsx-source script.js ``` ### Via Node API diff --git a/packages/babel-plugin-transform-react-jsx/README.md b/packages/babel-plugin-transform-react-jsx/README.md index 7534e19486d3..4a7c3ae0fb66 100644 --- a/packages/babel-plugin-transform-react-jsx/README.md +++ b/packages/babel-plugin-transform-react-jsx/README.md @@ -1,11 +1,61 @@ # babel-plugin-transform-react-jsx -Turn JSX into React function calls +> Turn JSX into React function calls + +## Example + +### React + +**In** + +```javascript +var profile =
+ +

{[user.firstName, user.lastName].join(' ')}

+
; +``` + +**Out** + +```javascript +var profile = React.createElement("div", null, + React.createElement("img", { src: "avatar.png", className: "profile" }), + React.createElement("h3", null, [user.firstName, user.lastName].join(" ")) +); +``` + +### Custom + +**In** + +```javascript +/** @jsx dom */ + +var { dom } = require("deku"); + +var profile =
+ +

{[user.firstName, user.lastName].join(' ')}

+
; +``` + +**Out** + +```javascript +/** @jsx dom */ + +var dom = require("deku").dom; + +var profile = dom( "div", null, + dom("img", { src: "avatar.png", className: "profile" }), + dom("h3", null, [user.firstName, user.lastName].join(" ")) +); +``` ## Installation ```sh -$ npm install babel-plugin-transform-react-jsx +npm install --save-dev babel-plugin-transform-react-jsx ``` ## Usage @@ -32,7 +82,7 @@ $ npm install babel-plugin-transform-react-jsx ### Via CLI ```sh -$ babel --plugins transform-react-jsx script.js +babel --plugins transform-react-jsx script.js ``` ### Via Node API @@ -42,3 +92,9 @@ require("babel-core").transform("code", { plugins: ["transform-react-jsx"] }); ``` + +## Options + +* `pragma` - Replace the function used when compiling JSX expressions (Defaults to `React.createElement`). + - Note that the `@jsx React.DOM` pragma has been deprecated as of React v0.12 +* `useBuiltIns` - When spreading props, use Object.assign instead of Babel's extend helper (Disabled by default). diff --git a/packages/babel-plugin-transform-regenerator/.npmignore b/packages/babel-plugin-transform-regenerator/.npmignore index e216ae5e1314..31852902b187 100644 --- a/packages/babel-plugin-transform-regenerator/.npmignore +++ b/packages/babel-plugin-transform-regenerator/.npmignore @@ -1,2 +1,4 @@ -/node_modules -/test +node_modules +*.log +src +test diff --git a/packages/babel-plugin-transform-regenerator/.test/async.es6.js b/packages/babel-plugin-transform-regenerator/.test/async.es6.js deleted file mode 100644 index 587e9b5f0054..000000000000 --- a/packages/babel-plugin-transform-regenerator/.test/async.es6.js +++ /dev/null @@ -1,493 +0,0 @@ -/** - * Copyright (c) 2014, Facebook, Inc. - * All rights reserved. - * - * This source code is licensed under the BSD-style license found in the - * https://raw.github.com/facebook/regenerator/master/LICENSE file. An - * additional grant of patent rights can be found in the PATENTS file in - * the same directory. - */ - -var assert = require("assert"); - -describe("async functions and await expressions", function() { - Promise = require("promise"); - - describe("regeneratorRuntime", function() { - it("should be defined globally", function() { - var global = Function("return this")(); - assert.ok("regeneratorRuntime" in global); - assert.strictEqual(global.regeneratorRuntime, regeneratorRuntime); - }); - - it("should have a .wrap method", function() { - assert.strictEqual(typeof regeneratorRuntime.wrap, "function"); - }); - }); - - describe("Promise", function() { - it("should be defined globally", function() { - var global = Function("return this")(); - assert.ok("Promise" in global); - assert.strictEqual(global.Promise, Promise); - }); - - it("should be a function", function() { - assert.strictEqual(typeof Promise, "function"); - }); - }); - - describe("no-await async function", function() { - it("should return a Promise", function(done) { - var called = false; - - async function noAwait(value) { - called = true; - return value; - } - - var promise = noAwait("asdf"); - assert.strictEqual(called, true); - - promise.then(function(value) { - assert.strictEqual(called, true); - assert.strictEqual(value, "asdf"); - done(); - }).catch(done); - }); - }); - - describe("one-await async function", function() { - it("should finish asynchronously", function(done) { - var flag1 = false; - var flag2 = false; - - async function oneAwait(value) { - flag1 = true; - var result = await value; - flag2 = true; - return result; - } - - var promise = oneAwait("asdf"); - assert.strictEqual(flag1, true); - assert.strictEqual(flag2, false); - - promise.then(function(value) { - assert.strictEqual(flag2, true); - assert.strictEqual(value, "asdf"); - done(); - }).catch(done); - }); - }); - - describe("nested async function calls", function() { - it("should evaluate in the right order", function(done) { - var markers = []; - - async function innerMost(marker) { - markers.push(marker); - return await marker; - } - - async function inner(marker) { - markers.push(marker); - - assert.strictEqual( - await innerMost(marker + 1), - marker + 1 - ); - - markers.push(marker + 2); - - assert.strictEqual( - await innerMost(marker + 3), - marker + 3 - ); - - markers.push(marker + 4); - } - - async function outer() { - markers.push(0); - await inner(1); - markers.push(6); - await inner(7); - markers.push(12); - } - - outer().then(function() { - var expected = []; - for (var i = 0; i <= 12; ++i) - expected.push(i); - assert.deepEqual(markers, expected); - done(); - }).catch(done); - }); - }); - - describe("dependent promises", function() { - it("should be awaitable out of order", function(done) { - async function outer(value) { - var resolved = false; - var p1 = new Promise(function(resolve) { - setTimeout(function() { - resolve(value + 1); - resolved = true; - }, 0); - }); - - assert.strictEqual(resolved, false); - - var v2 = await p1.then(function(value) { - return value + 1; - }); - - assert.strictEqual(resolved, true); - - var v1 = await p1; - - return [v1, v2]; - } - - outer(1).then(function(pair) { - assert.deepEqual(pair, [2, 3]); - done(); - }).catch(done); - }); - }); - - describe("rejected promises", function() { - it("should cause await expressions to throw", function(done) { - var error = new Error("rejected"); - - async function f(arg) { - try { - return await arg; - } catch (e) { - assert.strictEqual(e, error); - return "did throw"; - } - } - - Promise.all([ - f(Promise.reject(error)), - f(Promise.resolve("did not throw")) - ]).then(function(results) { - assert.deepEqual(results, [ - "did throw", - "did not throw" - ]); - done(); - }).catch(done); - }); - - it("should be returned by exceptional async functions", function(done) { - var error = new Error("rejected"); - - async function e(arg) { - if (arg) { - throw arg; - } - return "did not throw"; - } - - async function f(arg) { - return await e(arg); - } - - async function g(arg) { - return await f(arg); - } - - async function h(arg) { - return await Promise.all([ - g(arg), - Promise.resolve("dummy") - ]); - } - - Promise.all([ - h(error).then(function() { - done(new Error("should not have resolved")); - }, function(e) { - assert.strictEqual(e, error); - return "ok1"; - }), - h(null).then(function(result) { - assert.deepEqual(result, [ - "did not throw", - "dummy" - ]); - return "ok2"; - }) - ]).then(function(results) { - assert.deepEqual(results, ["ok1", "ok2"]); - done(); - }).catch(done); - }); - - it("should propagate failure when returned", function() { - var rejection = new Error("rejection"); - - async function f() { - return new Promise(function(resolve, reject) { - reject(rejection); - }); - } - - return f().then(function(result) { - assert.ok(false, "should have been rejected"); - }, function(error) { - assert.strictEqual(error, rejection); - }); - }); - }); - - describe("async function expressions", function() { - it("should be allowed", function(done) { - (async function(arg) { - return await arg; - })(Promise.resolve(1234)).then(function(value) { - assert.strictEqual(value, 1234); - done(); - }).catch(done); - }); - }); -}); - -describe("async generator functions", function() { - it("should return a working AsyncIterator", function() { - var markers = []; - - async function *gen(arg) { - markers.push(0); - var sent = yield arg; - markers.push(1); - var result = await sent; - markers.push(2); - assert.strictEqual(await (yield "second"), "sent after second"); - markers.push(3); - return result; - } - - var iter = gen("initial argument"); - assert.deepEqual(markers, []); - - var firstPromise = iter.next(); - assert.deepEqual(markers, [0]); - - return firstPromise.then(function(firstResult) { - assert.deepEqual(firstResult, { - value: "initial argument", - done: false - }); - - assert.deepEqual(markers, [0]); - - return iter.next(new Promise(function(resolve) { - setTimeout(resolve, 100); - }).then(function() { - assert.deepEqual(markers, [0, 1]); - return "will become final result"; - })); - - }).then(function(secondResult) { - assert.deepEqual(secondResult, { - value: "second", - done: false - }); - - assert.deepEqual(markers, [0, 1, 2]); - - return iter.next("sent after second"); - - }).then(function(finalResult) { - assert.deepEqual(markers, [0, 1, 2, 3]); - assert.deepEqual(finalResult, { - value: "will become final result", - done: true - }); - }); - }); - - it("should keep results in order", function() { - async function *range(limit) { - var before = []; - var after = []; - for (var i = 0; i < limit; ++i) { - before.push(i); - yield i; - after.push(i); - } - assert.deepEqual(before, after); - return before; - } - - var limit = 10; - var iter = range(limit); - var promises = []; - var results = []; - - for (var i = 0; i < limit; ++i) { - var promise = iter.next(); - promises.push(promise); - - promise.then(function(result) { - assert.strictEqual(result.done, false); - results.push(result); - }); - } - - assert.deepEqual(results, []); - - return Promise.all(promises).then(function(promiseResults) { - assert.deepEqual(results, promiseResults); - - return iter.next(); - - }).then(function(finalResult) { - assert.deepEqual(results.map(function(result) { - return result.value; - }), finalResult.value); - - assert.strictEqual(finalResult.done, true); - }); - }); - - it("should be able to handle many awaits", function() { - var awaitCount = 0; - - function countAwait(i) { - return Promise.resolve(i).then(function() { - ++awaitCount; - }); - } - - async function *gen(limit) { - await countAwait(0); - yield 1; - await countAwait(2); - await countAwait(3); - yield 4; - await countAwait(5); - await countAwait(6); - await countAwait(7); - yield 8; - for (var i = 0; i < limit; ++i) { - await countAwait(i); - } - return "done"; - } - - var iter = gen(100); - - return iter.next().then(function(result) { - assert.strictEqual(awaitCount, 1); - - assert.deepEqual(result, { - value: 1, - done: false - }); - - return iter.next(); - - }).then(function(result) { - assert.strictEqual(awaitCount, 3); - - assert.deepEqual(result, { - value: 4, - done: false - }); - - return iter.next(); - - }).then(function(result) { - assert.strictEqual(awaitCount, 6); - - assert.deepEqual(result, { - value: 8, - done: false - }); - - return iter.next(); - - }).then(function(result) { - assert.strictEqual(awaitCount, 6 + 100); - - assert.deepEqual(result, { - value: "done", - done: true - }); - - return iter.next(); - - }).then(function(result) { - assert.deepEqual(result, { - value: void 0, - done: true - }); - }); - }); - - it("should not propagate exceptions between iterations", function() { - async function *gen() { - yield 1; - yield 2; - } - - var iter = gen(); - - return iter.next().then(function(result) { - assert.deepEqual(result, { - value: 1, - done: false - }); - - return iter.throw(new Error("thrown from first yield")); - - }).then(function() { - throw new Error("should have thrown"); - - }, function(error) { - assert.strictEqual(error.message, "thrown from first yield"); - return iter.next(); - - }).then(function(result) { - assert.deepEqual(result, { - value: void 0, - done: true - }); - }); - }); - - it("should allow yielding a rejected Promise", function() { - var yielded = new Error("yielded rejection"); - var returned = new Error("returned rejection"); - - async function *gen() { - assert.strictEqual(yield Promise.reject(yielded), "first sent"); - assert.strictEqual(yield "middle", "second sent"); - return Promise.reject(returned); - } - - var iter = gen(); - - return iter.next().then(function(result) { - assert.ok(false, "should have yielded a rejected Promise"); - }, function(error) { - assert.strictEqual(error, yielded); - return iter.next("first sent"); - }).then(function(result) { - assert.deepEqual(result, { - value: "middle", - done: false - }); - return iter.next("second sent"); - }).then(function(result) { - assert.ok(false, "should have returned a rejected Promise"); - }, function(error) { - assert.strictEqual(error, returned); - }); - }); -}); diff --git a/packages/babel-plugin-transform-regenerator/.test/tests.es6.js b/packages/babel-plugin-transform-regenerator/.test/tests.es6.js deleted file mode 100644 index 3df59e76e9ab..000000000000 --- a/packages/babel-plugin-transform-regenerator/.test/tests.es6.js +++ /dev/null @@ -1,2560 +0,0 @@ -/** - * Copyright (c) 2014, Facebook, Inc. - * All rights reserved. - * - * This source code is licensed under the BSD-style license found in the - * https://raw.github.com/facebook/regenerator/master/LICENSE file. An - * additional grant of patent rights can be found in the PATENTS file in - * the same directory. - */ - -var assert = require("assert"); -var runningInTranslation = /\.wrap\(/.test(function*(){}); -var iteratorSymbol = typeof Symbol === "function" - && Symbol.iterator - || "@@iterator"; - -function check(g, yields, returnValue) { - for (var i = 0; i < yields.length; ++i) { - var info = g.next(i); - assert.deepEqual(info.value, yields[i]); - assert.strictEqual(info.done, false); - } - - assert.deepEqual( - i > 0 ? g.next(i) : g.next(), - { value: returnValue, done: true } - ); -} - -// A version of `throw` whose behavior can't be statically analyzed. -// Useful for testing dynamic exception dispatching. -function raise(argument) { - throw argument; -} - -function assertAlreadyFinished(generator) { - assert.deepEqual(generator.next(), { - value: void 0, - done: true - }); -} - -describe("regeneratorRuntime", function() { - it("should be defined globally", function() { - var global = Function("return this")(); - assert.ok("regeneratorRuntime" in global); - assert.strictEqual(global.regeneratorRuntime, regeneratorRuntime); - }); - - it("should have a .wrap method", function() { - assert.strictEqual(typeof regeneratorRuntime.wrap, "function"); - }); - - it("should have a .mark method", function() { - assert.strictEqual(typeof regeneratorRuntime.mark, "function"); - }); - - it("should be the object name returned by util.runtimeProperty", function() { - assert.strictEqual( - require("../lib/util").runtimeProperty("foo").object.name, - "regeneratorRuntime" - ); - }); -}); - -(runningInTranslation ? describe : xdescribe)("@@iterator", function() { - it("is defined on Generator.prototype and returns this", function() { - function *gen(){} - var iterator = gen(); - assert.ok(!iterator.hasOwnProperty(iteratorSymbol)); - assert.ok(!Object.getPrototypeOf(iterator).hasOwnProperty(iteratorSymbol)); - assert.ok(Object.getPrototypeOf( - Object.getPrototypeOf(iterator) - ).hasOwnProperty(iteratorSymbol)); - assert.strictEqual(iterator[iteratorSymbol](), iterator); - }); -}); - -describe("simple argument yielder", function() { - it("should yield only its first argument", function() { - function *gen(x) { - yield x; - } - - check(gen("oyez"), ["oyez"]); - check(gen("foo", "bar"), ["foo"]); - }); - - it("should support multiple yields in expression", function() { - function *gen() { return (yield 0) + (yield 0); } - var itr = gen(); - itr.next(); - itr.next(1); - assert.equal(itr.next(2).value, 3); - }); -}); - -function *range(n) { - for (var i = 0; i < n; ++i) { - yield i; - } -} - -describe("range generator", function() { - it("should yield the empty range", function() { - check(range(0), []); - }) - - it("should yield the range 0..n-1", function() { - check(range(5), [0, 1, 2, 3, 4]); - }); -}); - -describe("collatz generator", function() { - function *gen(n) { - var count = 0; - - yield n; - - while (n !== 1) { - count += 1; - - if (n % 2) { - yield n = n * 3 + 1; - } else { - yield n >>= 1; - } - } - - return count; - } - - function collatz(n) { - var result = [n]; - - while (n !== 1) { - if (n % 2) { - n *= 3; - n += 1; - } else { - n >>= 1; - } - - result.push(n); - } - - return result; - } - - var seven = collatz(7); - var fiftyTwo = seven.slice(seven.indexOf(52)); - var eightyTwo = collatz(82); - - it("seven", function() { - check(gen(7), seven, 16); - }); - - it("fifty two", function() { - check(gen(52), fiftyTwo, 11); - }); - - it("eighty two", function() { - check(gen(82), eightyTwo, 110); - }); -}); - -describe("throw", function() { - (runningInTranslation ? it : xit)("should complete generator", function() { - function *gen(x) { - throw 1; - } - - var u = gen(); - - try { - u.next(); - } catch (err) { - assert.strictEqual(err, 1); - } - - assertAlreadyFinished(u); - }); -}); - -describe("try-catch generator", function() { - function *usingThrow(x) { - yield 0; - try { - yield 1; - if (x % 2 === 0) - throw 2; - yield x; - } catch (x) { - yield x; - } - yield 3; - } - - function *usingRaise(x) { - yield 0; - try { - yield 1; - if (x % 2 === 0) - raise(2); - yield x; - } catch (x) { - yield x; - } - yield 3; - } - - it("should catch static exceptions properly", function() { - check(usingThrow(4), [0, 1, 2, 3]); - check(usingThrow(5), [0, 1, 5, 3]); - }); - - it("should catch dynamic exceptions properly", function() { - check(usingRaise(4), [0, 1, 2, 3]); - check(usingRaise(5), [0, 1, 5, 3]); - }); -}); - -describe("nested generators in try-catch", function() { - function *gen() { - try { - nonExistent; - } catch (e) { - yield function* () { - yield e; - } - } - } - - it('should get a reference to the caught error', function () { - var genFun2 = gen().next().value; - assert.ok(regeneratorRuntime.isGeneratorFunction(genFun2)); - var gen2 = genFun2(); - var res = gen2.next(); - assert.ok(res.value instanceof ReferenceError); - // Note that we don't do strict equality over the message because it varies - // across browsers (if we ever want to run tests in browsers). - assert.ok(res.value.message.match(/nonExistent/)); - }); - -}); - -describe("try-finally generator", function() { - function *usingThrow(condition) { - yield 0; - try { - yield 1; - throw 2; - yield 3; - } finally { - if (condition) { - yield 4; - return 5; - } - yield 6; - return 7; - } - } - - function *usingRaise(condition) { - yield 0; - try { - yield 1; - raise(2); - yield 3; - } finally { - if (condition) { - yield 4; - return 5; - } - yield 6; - return 7; - } - } - - function *usingAbrupt(abruptType, finallyAbruptType) { - yield 0; - for (;;) { - try { - yield 1; - if (abruptType === "return") { - return 2; - } else if (abruptType === "break") { - break; - } else if (abruptType === "continue") { - abruptType = "return"; - continue; - } - } - finally { - yield 3; - if (finallyAbruptType === "return") { - return 4; - } else if (finallyAbruptType === "break") { - break; - } else if (finallyAbruptType === "continue") { - finallyAbruptType = null; - continue; - } - } - } - return 5; - } - - it("should honor return", function() { - check(usingAbrupt("return", null), [0, 1, 3], 2); - }); - - it("should honor break", function() { - check(usingAbrupt("break", null), [0, 1, 3], 5); - }); - - it("should honor continue", function() { - check(usingAbrupt("continue", null), [0, 1, 3, 1, 3], 2); - }); - - it("should override abrupt with return", function() { - check(usingAbrupt("return", "return"), [0, 1, 3], 4); - check(usingAbrupt("break", "return"), [0, 1, 3], 4); - check(usingAbrupt("continue", "return"), [0, 1, 3], 4); - }); - - it("should override abrupt with break", function() { - check(usingAbrupt("return", "break"), [0, 1, 3], 5); - check(usingAbrupt("break", "break"), [0, 1, 3], 5); - check(usingAbrupt("continue", "break"), [0, 1, 3], 5); - }); - - it("should override abrupt with continue", function() { - check(usingAbrupt("return", "continue"), [0, 1, 3, 1, 3], 2); - check(usingAbrupt("break", "continue"), [0, 1, 3, 1, 3], 5); - check(usingAbrupt("continue", "continue"), [0, 1, 3, 1, 3], 2); - }); - - it("should execute finally blocks statically", function() { - check(usingThrow(true), [0, 1, 4], 5); - check(usingThrow(false), [0, 1, 6], 7); - }); - - it("should execute finally blocks dynamically", function() { - check(usingRaise(true), [0, 1, 4], 5); - check(usingRaise(false), [0, 1, 6], 7); - }); - - it("should execute finally blocks before throwing", function() { - var uncaughtError = new Error("uncaught"); - - function *uncaught(condition) { - try { - yield 0; - if (condition) { - yield 1; - raise(uncaughtError); - } - yield 2; - } finally { - yield 3; - } - yield 4; - } - - check(uncaught(false), [0, 2, 3, 4]); - - var u = uncaught(true); - - assert.deepEqual(u.next(), { value: 0, done: false }); - assert.deepEqual(u.next(), { value: 1, done: false }); - assert.deepEqual(u.next(), { value: 3, done: false }); - - try { - u.next(); - assert.ok(false, "should have thrown an exception"); - } catch (err) { - assert.strictEqual(err, uncaughtError); - } - }); - - it("should throw correct error when finally contains catch", function() { - var right = new Error("right"); - var wrong = new Error("wrong"); - - function *gen() { - try { - yield 0; - raise(right); - } finally { - yield 1; - try { - raise(wrong); - } catch (err) { - assert.strictEqual(err, wrong); - yield 2; - } - } - } - - var g = gen(); - - assert.deepEqual(g.next(), { - value: 0, - done: false - }); - - assert.deepEqual(g.next(), { - value: 1, - done: false - }); - - assert.deepEqual(g.next(), { - value: 2, - done: false - }); - - try { - g.next(); - assert.ok(false, "should have thrown an exception"); - } catch (err) { - assert.strictEqual(err, right); - } - }); - - it("should run finally after break within try", function() { - function *gen() { - try { - yield 0; - while (true) { - yield 1; - break; - } - } finally { - yield 2; - } - yield 3; - } - - check(gen(), [0, 1, 2, 3]); - }); -}); - -describe("try-catch-finally generator", function() { - function *usingThrow() { - yield 0; - try { - try { - yield 1; - throw 2; - yield 3; - } catch (x) { - throw yield x; - } finally { - yield 5; - } - } catch (thrown) { - yield thrown; - } - yield 6; - } - - function *usingRaise() { - yield 0; - try { - try { - yield 1; - raise(2); - yield 3; - } catch (x) { - throw yield x; - } finally { - yield 5; - } - } catch (thrown) { - yield thrown; - } - yield 6; - } - - it("should statically catch and then finalize", function() { - check(usingThrow(), [0, 1, 2, 5, 3, 6]); - }); - - it("should dynamically catch and then finalize", function() { - check(usingRaise(), [0, 1, 2, 5, 3, 6]); - }); - - it("should execute catch and finally blocks at most once", function() { - var error = new Error(); - - function *gen() { - try { - switch (1) { - case 1: - yield "a"; - break; - default: - break; - } - throw error; - } catch (e) { - assert.strictEqual(e, error); - yield "b"; - do { - do { - yield "c"; - break; - } while (false); - yield "d"; - break; - } while (false); - yield "e"; - } finally { - yield "f"; - } - } - - check(gen(), ["a", "b", "c", "d", "e", "f"]); - }); - - it("should handle backwards jumps in labeled loops", function() { - function *gen() { - var firstTime = true; - outer: - while (true) { - yield 0; - try { - while (true) { - yield 1; - if (firstTime) { - firstTime = false; - yield 2; - continue outer; - } else { - yield 3; - break; - } - } - yield 4; - break; - } finally { - yield 5; - } - yield 6; - } - yield 7; - } - - check(gen(), [0, 1, 2, 5, 0, 1, 3, 4, 5, 7]); - }); - - it("should handle loop continue statements properly", function() { - var error = new Error("thrown"); - var markers = []; - - function *gen() { - var c = 2; - while (c > 0) { - try { - markers.push("try"); - yield c; - } catch (e) { - assert.strictEqual(e, error); - markers.push("catch"); - continue; - } finally { - markers.push("finally"); - } - markers.push("decrement"); - --c; - } - } - - var g = gen(); - - assert.deepEqual(g.next(), { value: 2, done: false }); - assert.deepEqual(g.throw(error), { value: 2, done: false }); - assert.deepEqual(g.next(), { value: 1, done: false }); - assert.deepEqual(g.next(), { value: void 0, done: true }); - - assert.deepEqual(markers, [ - "try", - "catch", - "finally", - "try", - "finally", - "decrement", - "try", - "finally", - "decrement" - ]); - }); -}); - -describe("dynamic exception", function() { - function *gen(x, fname) { - try { - return fns[fname](x); - } catch (thrown) { - yield thrown; - } - } - - var fns = { - f: function(x) { - throw x; - }, - - g: function(x) { - return x; - } - }; - - it("should be dispatched correctly", function() { - check(gen("asdf", "f"), ["asdf"]); - check(gen("asdf", "g"), [], "asdf"); - }); -}); - -describe("nested finally blocks", function() { - function *usingThrow() { - try { - try { - try { - throw "thrown"; - } finally { - yield 1; - } - } catch (thrown) { - yield thrown; - } finally { - yield 2; - } - } finally { - yield 3; - } - } - - function *usingRaise() { - try { - try { - try { - raise("thrown"); - } finally { - yield 1; - } - } catch (thrown) { - yield thrown; - } finally { - yield 2; - } - } finally { - yield 3; - } - } - - it("should statically execute in order", function() { - check(usingThrow(), [1, "thrown", 2, 3]); - }); - - it("should dynamically execute in order", function() { - check(usingRaise(), [1, "thrown", 2, 3]); - }); -}); - -describe("for-in loop generator", function() { - it("should handle the simple case", function() { - function *gen() { - var count = 0; - var obj = {foo: 1, bar: 2}; - for (var key in obj) { - assert(obj.hasOwnProperty(key), key + " must be own property"); - yield [key, obj[key]]; - count += 1; - } - return count; - } - - check(gen(), [["foo", 1], ["bar", 2]], 2); - }); - - it("should handle break in loop", function() { - function *gen(obj) { - var count = 0; - for (var key in (yield "why not", obj)) { - if (obj.hasOwnProperty(key)) { - if (key === "skip") { - break; - } - count += 1; - yield [key, obj[key]]; - } - } - return count; - } - - check( - gen({ a: 1, b: 2, skip: 3, c: 4 }), - ["why not", ["a", 1], ["b", 2]], - 2 - ); - }); - - it("should handle property deletion in loop", function() { - function *gen() { - var count = 0; - var obj = {foo: 1, bar: 2}; - for (var key in obj) { - assert(obj.hasOwnProperty(key), key + " must be own property"); - yield [key, obj[key]]; - delete obj.bar; - count += 1; - } - return count; - } - - check(gen(), [["foo", 1]], 1); - }); - - it("should loop over inherited properties", function() { - function *gen() { - var count = 0; - function Foo() { - this.baz = 1 - } - Foo.prototype.bar = 2; - - var foo = new Foo(); - for (var key in foo) { - yield [key, foo[key]]; - count += 1; - } - return count; - } - - check(gen(), [["baz", 1], ["bar", 2]], 2); - }); - - it("should handle risky object expressions", function() { - function a(sent) { - assert.strictEqual(sent, 1); - a.called = true; - } - - function b(sent) { - assert.strictEqual(sent, 2); - b.called = true; - return { callee: b }; - } - - function *gen() { - assert.ok(!a.called); - assert.ok(!b.called); - for (var key in a(yield 0), b(yield 1)) { - assert.ok(a.called); - assert.ok(b.called); - assert.strictEqual(yield key, 3); - } - - for (var key in a(1), { foo: "foo", bar: "bar" }) { - yield key; - } - } - - check(gen(), [0, 1, "callee", "foo", "bar"]); - }); - - it("should allow non-Identifier left-hand expressions", function() { - var obj = {}; - var baz = { a: 1, b: 2, c: 3 }; - var markers = []; - - function foo() { - markers.push("called foo"); - return obj; - } - - function *gen() { - for (foo().bar in baz) { - markers.push(obj.bar); - yield obj.bar; - } - } - - check(gen(), ["a", "b", "c"]); - - assert.deepEqual(markers, [ - "called foo", - "a", - "called foo", - "b", - "called foo", - "c" - ]); - }); -}); - -describe("yield chain", function() { - function *gen(n) { - return yield yield yield yield n; - } - - it("should have correct associativity", function() { - check(gen(5), [5, 1, 2, 3], 4); - check(gen("asdf"), ["asdf", 1, 2, 3], 4); - }); -}); - -describe("object literal generator", function() { - function *gen(a, b) { - yield { - a: a - (yield a), - b: yield b - }; - } - - it("should yield the correct object", function() { - check(gen(1, 2), [1, 2, { a: 0, b: 2 }]); - check(gen(4, 2), [4, 2, { a: 3, b: 2 }]); - }); -}); - -describe("switch statement generator", function() { - function *gen(a) { - switch (yield a) { - case (yield "x") - a: - return "first case"; - case (yield "y") - a: - return "second case"; - } - } - - it("should jump to the correct cases", function() { - check(gen(1), [1, "x"], "first case"); - check(gen(2), [2, "x", "y"], "second case"); - }); -}); - -describe("infinite sequence generator", function() { - function *gen(start, step) { - step = step || 1; - while (true) { - yield start; - start += step; - } - } - - function *limit(g, stop) { - while (true) { - var info = g.next(); - if (info.done) { - return; - } else if (info.value < stop) { - yield info.value; - } else { - return; - } - } - } - - it("should generate a lot of plausible values", function() { - var g = gen(10, 2); - - assert.deepEqual(g.next(), { value: 10, done: false }); - assert.deepEqual(g.next(), { value: 12, done: false }); - assert.deepEqual(g.next(), { value: 14, done: false }); - assert.deepEqual(g.next(), { value: 16, done: false }); - - var sum = 10 + 12 + 14 + 16; - - for (var n = 0; n < 1000; ++n) { - var info = g.next(); - sum += info.value; - assert.strictEqual(info.done, false); - } - - assert.strictEqual(sum, 1017052); - }); - - it("should allow limiting", function() { - check(limit(gen(10, 3), 20), [10, 13, 16, 19]); - }); -}); - -describe("generator function expression", function() { - it("should behave just like a declared generator", function() { - check(function *(x, y) { - yield x; - yield y; - yield x + y; - return x * y; - }(3, 7), [3, 7, 10], 21); - }) -}); - -describe("generator reentry attempt", function() { - function *gen(x) { - try { - (yield x).next(x); - } catch (err) { - yield err; - } - return x + 1; - } - - it("should complain with a TypeError", function() { - var g = gen(3); - assert.deepEqual(g.next(), { value: 3, done: false }); - var complaint = g.next(g); // Sending the generator to itself. - assert.ok(complaint.value instanceof Error); - assert.strictEqual( - complaint.value.message, - "Generator is already running" - ); - assert.deepEqual(g.next(), { value: 4, done: true }); - }); -}); - -describe("completed generator", function() { - function *gen() { - return "ALL DONE"; - } - - (runningInTranslation ? it : xit) - ("should refuse to resume", function() { - var g = gen(); - - assert.deepEqual(g.next(), { - value: "ALL DONE", done: true - }); - - assertAlreadyFinished(g); - }); -}); - -describe("delegated yield", function() { - it("should delegate correctly", function() { - function *gen(condition) { - yield 0; - if (condition) { - yield 1; - yield* gen(false); - yield 2; - } - yield 3; - } - - check(gen(true), [0, 1, 0, 3, 2, 3]); - check(gen(false), [0, 3]); - }); - - it("should cope with empty delegatees", function() { - function *gen(condition) { - if (condition) { - yield 0; - yield* gen(false); - yield 1; - } - } - - check(gen(true), [0, 1]); - check(gen(false), []); - }); - - it("should support deeper nesting", function() { - function *outer(n) { - yield n; - yield* middle(n - 1, inner(n + 10)); - yield n + 1; - } - - function *middle(n, plusTen) { - yield n; - yield* inner(n - 1); - yield n + 1; - yield* plusTen; - } - - function *inner(n) { - yield n; - } - - check(outer(5), [5, 4, 3, 5, 15, 6]); - }); - - it("should pass sent values through", function() { - function *outer(n) { - yield* inner(n << 1); - yield "zxcv"; - } - - function *inner(n) { - return yield yield yield n; - } - - var g = outer(3); - assert.deepEqual(g.next(), { value: 6, done: false }); - assert.deepEqual(g.next(1), { value: 1, done: false }); - assert.deepEqual(g.next(2), { value: 2, done: false }); - assert.deepEqual(g.next(4), { value: "zxcv", done: false }); - assert.deepEqual(g.next(5), { value: void 0, done: true }); - }); - - it("should be governed by enclosing try statements", function() { - var error = new Error("thrown"); - - function *outer(n) { - try { - yield 0; - yield* inner(n); - yield 1; - } catch (err) { - yield err.message; - } - yield 4; - } - - function *inner(n) { - while (n --> 0) { - try { - if (n === 3) { - raise(error); - } - } finally { - yield n; - } - } - } - - check(outer(3), [0, 2, 1, 0, 1, 4]); - check(outer(5), [0, 4, 3, "thrown", 4]); - }); - - it("should dispatch .thrown exceptions correctly", function() { - var count = 0; - - function *gen() { - yield* inner(); - try { - yield* inner(); - } catch (err) { - // pass - } - return yield* inner(); - } - - function *inner() { - return yield count++; - } - - var g = gen(); - - assert.deepEqual(g.next(), { - value: 0, - done: false - }); - - assert.deepEqual(g.next(), { - value: 1, - done: false - }); - - assert.deepEqual(g.throw(new Error("lol")), { - value: 2, - done: false, - }); - - assert.deepEqual(g.next("sent"), { - value: "sent", - done: true - }); - }); - - it("should call .return methods of delegate iterators", function() { - var throwee = new Error("argument to gen.throw"); - var thrownFromThrow = new Error("thrown from throw method"); - var thrownFromReturn = new Error("thrown from return method"); - - function *gen(delegate) { - try { - return yield* delegate; - } catch (err) { - return err; - } - } - - function check(throwMethod, returnMethod) { - var throwCalled = false; - var returnCalled = false; - var count = 0; - var iterator = { - next: function() { - return { value: count++, done: false }; - } - }; - - iterator[iteratorSymbol] = function() { - return this; - }; - - if (throwMethod) { - iterator["throw"] = function() { - throwCalled = true; - return throwMethod.apply(this, arguments); - }; - } - - if (returnMethod) { - iterator["return"] = function() { - returnCalled = true; - return returnMethod.apply(this, arguments); - }; - } - - var g = gen(iterator); - - assert.deepEqual(g.next(), { value: 0, done: false }); - assert.deepEqual(g.next(), { value: 1, done: false }); - assert.deepEqual(g.next(), { value: 2, done: false }); - assert.deepEqual(g.next(), { value: 3, done: false }); - - assert.strictEqual(throwCalled, false); - assert.strictEqual(returnCalled, false); - - var result = {}; - - result.throwResult = g.throw(throwee); - result.throwCalled = throwCalled; - result.returnCalled = returnCalled; - - return result; - } - - var checkResult = check(undefined, function() { - throw thrownFromReturn; - }); - if (runningInTranslation) { - // BUG: Node v0.11 and v0.12 neglect to call .return here. - assert.strictEqual(checkResult.throwResult.value, thrownFromReturn); - } else { - // This is the TypeError that results from trying to call the - // undefined .throw method of the iterator. - assert.ok(checkResult.throwResult.value instanceof TypeError); - } - assert.strictEqual(checkResult.throwResult.done, true); - assert.strictEqual(checkResult.throwCalled, false); - // BUG: Node v0.11 and v0.12 neglect to call .return here. - assert.strictEqual(checkResult.returnCalled, runningInTranslation); - - checkResult = check(undefined, function() { - return { value: "from return", done: true }; - }); - assert.notStrictEqual(checkResult.throwResult.value, throwee); - // This is the TypeError that results from trying to call the - // undefined .throw method of the iterator. - assert.ok(checkResult.throwResult.value instanceof TypeError); - assert.strictEqual(checkResult.throwResult.done, true); - assert.strictEqual(checkResult.throwCalled, false); - // BUG: Node v0.11 and v0.12 neglect to call .return here. - assert.strictEqual(checkResult.returnCalled, runningInTranslation); - - var checkResult = check(function(thrown) { - return { value: "from throw", done: true }; - }, function() { - throw thrownFromReturn; - }); - assert.strictEqual(checkResult.throwResult.value, "from throw"); - assert.strictEqual(checkResult.throwResult.done, true); - assert.strictEqual(checkResult.throwCalled, true); - assert.strictEqual(checkResult.returnCalled, false); - - var checkResult = check(function(thrown) { - throw thrownFromThrow; - }, function() { - throw thrownFromReturn; - }); - assert.strictEqual(checkResult.throwResult.value, thrownFromThrow); - assert.strictEqual(checkResult.throwResult.done, true); - assert.strictEqual(checkResult.throwCalled, true); - assert.strictEqual(checkResult.returnCalled, false); - - var checkResult = check(undefined, undefined); - assert.notStrictEqual(checkResult.throwResult.value, throwee); - // This is the TypeError that results from trying to call the - // undefined .throw method of the iterator. - assert.ok(checkResult.throwResult.value instanceof TypeError); - assert.strictEqual(checkResult.throwResult.done, true); - assert.strictEqual(checkResult.throwCalled, false); - assert.strictEqual(checkResult.returnCalled, false); - }); - - it("should not be required to have a .return method", function() { - function *gen(delegate) { - return yield* delegate; - } - - var inner = range(5); - var iterator = { next: inner.next.bind(inner) }; - iterator[iteratorSymbol] = function() { - return this; - }; - - var g = gen(iterator); - assert.deepEqual(g.next(), { value: 0, done: false }); - assert.deepEqual(g.next(), { value: 1, done: false }); - assert.deepEqual(g.next(), { value: 2, done: false }); - - if (typeof g.return === "function") { - assert.deepEqual(g.return(-1), { value: -1, done: true }); - assert.deepEqual(g.next(), { value: void 0, done: true }); - } - }); - - (runningInTranslation ? it : xit) - ("should support any iterable argument", function() { - function *gen() { - yield 0; - yield* [ - yield "one", - yield "two", - yield "three" - ]; - yield 5; - } - - check(gen(), [0, "one", "two", "three", 2, 3, 4, 5]); - - function *string() { - return yield* "asdf"; - } - - check(string(), ["a", "s", "d", "f"]); - }); - - it("should evaluate to the return value of the delegate", function() { - function *inner() { - yield 1; - return 2; - } - - function *outer(delegate) { - return yield* delegate; - } - - check(outer(inner()), [1], 2); - - var arrayDelegate = [3, 4]; - if (!runningInTranslation) { - // Node v0.11 doesn't know how to turn arrays into iterators over - // their elements without a little help. - arrayDelegate = regeneratorRuntime.values(arrayDelegate); - } - check(outer(arrayDelegate), [3, 4], void 0); // See issue #143. - - if (!runningInTranslation) { - return; - } - - check(outer({ - next: function() { - return { value: "oyez", done: true }; - } - }), [], "oyez"); - }); - - it("should work as a subexpression", function() { - function *inner(arg) { - return arg; - } - - function *gen(delegate) { - // Unfortunately these parentheses appear to be necessary. - return 1 + (yield* delegate); - } - - check(gen(inner(2)), [], 3); - check(gen(inner(3)), [], 4); - - if (!runningInTranslation) { - return; - } - - check(gen({ - next: function() { - return { value: "foo", done: true }; - } - }), [], "1foo"); - }); -}); - -describe("function declaration hoisting", function() { - it("should work even if the declarations are out of order", function() { - function *gen(n) { - yield increment(n); - - function increment(x) { - return x + 1; - } - - if (n % 2) { - yield halve(decrement(n)); - - function halve(x) { - return x >> 1; - } - - function decrement(x) { - return x - 1; - } - } else { - // The behavior of function declarations nested inside conditional - // blocks is notoriously underspecified, and in V8 it appears the - // halve function is still defined when we take this branch, so - // "undefine" it for consistency with regenerator semantics. - halve = void 0; - } - - yield typeof halve; - - yield increment(increment(n)); - } - - check(gen(3), [4, 1, "function", 5]); - check(gen(4), [5, "undefined", 6]); - }); - - it("should work for nested generator function declarations", function() { - function *outer(n) { - yield 0; - assert.ok(regeneratorRuntime.isGeneratorFunction(inner)); - return yield* inner(n); - - // Note that this function declaration comes after everything else - // in the outer function, but needs to be fully available above. - function *inner(n) { - yield n - 1; - yield n; - return yield n + 1; - } - } - - check(outer(2), [0, 1, 2, 3], 4); - }); - - it("should not interfere with function rebinding", function() { - function rebindTo(value) { - var oldValue = toBeRebound; - toBeRebound = value; - return oldValue; - } - - function *toBeRebound() { - var originalValue = toBeRebound; - yield toBeRebound; - assert.strictEqual(rebindTo(42), originalValue); - yield toBeRebound; - assert.strictEqual(rebindTo("asdf"), 42); - yield toBeRebound; - } - - var original = toBeRebound; - check(toBeRebound(), [original, 42, "asdf"]); - - function attemptToRebind(value) { - var oldValue = safe; - safe = value; - return oldValue; - } - - var safe = function *safe() { - var originalValue = safe; - yield safe; - assert.strictEqual(attemptToRebind(42), originalValue); - yield safe; - assert.strictEqual(attemptToRebind("asdf"), 42); - yield safe; - } - - original = safe; - check(safe(), [safe, safe, safe]); - }); -}); - -describe("the arguments object", function() { - it("should work in simple variadic functions", function() { - function *sum() { - var result = 0; - - for (var i = 0; i < arguments.length; ++i) { - yield result += arguments[i]; - } - - return result; - } - - check(sum(1, 2, 3), [1, 3, 6], 6); - check(sum(9, -5, 3, 0, 2), [9, 4, 7, 7, 9], 9); - }); - - it("should alias function parameters", function() { - function *gen(x, y) { - yield x; - ++arguments[0]; - yield x; - - yield y; - --arguments[1]; - yield y; - - var temp = y; - y = x; - x = temp; - - yield x; - yield y; - } - - check(gen(3, 7), [3, 4, 7, 6, 6, 4]); - check(gen(10, -5), [10, 11, -5, -6, -6, 11]); - }); - - it("should be shadowable by explicit declarations", function() { - function *asParameter(x, arguments) { - arguments = arguments + 1; - yield x + arguments; - } - - check(asParameter(4, 5), [10]); - check(asParameter("asdf", "zxcv"), ["asdfzxcv1"]); - - function *asVariable(x) { - // TODO References to arguments before the variable declaration - // seem to see the object instead of the undefined value. - var arguments = x + 1; - yield arguments; - } - - check(asVariable(4), [5]); - check(asVariable("asdf"), ["asdf1"]); - }); - - it("should not get confused by properties", function() { - function *gen(args) { - var obj = { arguments: args }; - yield obj.arguments; - obj.arguments = "oyez"; - yield obj; - } - - check(gen(42), [42, { arguments: "oyez" }]); - }); - - it("supports .callee", function() { - function *gen(doYield) { - yield 1; - if (doYield) { - yield 2; - } else { - yield 3 - yield* arguments.callee(true); - yield 4 - } - yield 5; - } - - check(gen(false), [1, 3, 1, 2, 5, 4, 5]); - }); -}); - -describe("catch parameter shadowing", function() { - it("should leave outer variables unmodified", function() { - function *gen(x) { - var y = x + 1; - try { - throw x + 2; - } catch (x) { - yield x; - x += 1; - yield x; - } - yield x; - try { - throw x + 3; - } catch (y) { - yield y; - y *= 2; - yield y; - } - yield y; - } - - check(gen(1), [3, 4, 1, 4, 8, 2]); - check(gen(2), [4, 5, 2, 5, 10, 3]); - }); - - it("should not replace variables defined in inner scopes", function() { - function *gen(x) { - try { - throw x; - } catch (x) { - yield x; - - yield (function(x) { - return x += 1; - }(x + 1)); - - yield (function() { - var x = arguments[0]; - return x * 2; - }(x + 2)); - - yield (function() { - function notCalled(x) { - throw x; - } - - x >>= 1; - return x; - }()); - - yield x -= 1; - } - - yield x; - } - - check(gen(10), [10, 12, 24, 5, 4, 10]); - check(gen(11), [11, 13, 26, 5, 4, 11]); - }); - - it("should allow nested catch parameters of the same name", function() { - function *gen() { - try { - raise("e1"); - } catch (e) { - yield e; - try { - raise("e2"); - } catch (e) { - yield e; - } - yield e; - } - } - - check(gen(), ["e1", "e2", "e1"]); - }); - - it("should not interfere with non-referential identifiers", function() { - function *gen() { - try { - yield 1; - raise(new Error("oyez")); - yield 2; - } catch (e) { - yield 3; - e.e = "e.e"; - e[e.message] = "e.oyez"; - return { - e: e, - identity: function(x) { - var e = x; - return e; - } - }; - } - yield 4; - } - - var g = gen(); - assert.deepEqual(g.next(), { value: 1, done: false }); - assert.deepEqual(g.next(), { value: 3, done: false }); - - var info = g.next(); - assert.strictEqual(info.done, true); - assert.strictEqual(info.value.e.message, "oyez"); - assert.strictEqual(info.value.e.e, "e.e"); - assert.strictEqual(info.value.e.oyez, "e.oyez"); - assert.strictEqual(info.value.identity("same"), "same"); - }); -}); - -describe("empty while loops", function() { - it("should be preserved in generated code", function() { - function *gen(x) { - while (x) { - // empty while loop - } - - do { - // empty do-while loop - } while (x); - - return gen.toString(); - } - - var info = gen(false).next(); - assert.strictEqual(info.done, true); - assert.ok(/empty while loop/.test(info.value)); - assert.ok(/empty do-while loop/.test(info.value)); - }); -}); - -describe("object literals with multiple yields", function() { - it("should receive different sent values", function() { - function *gen(fn) { - return { - a: yield "a", - b: yield "b", - c: fn(yield "c", yield "d"), - d: [yield "e", yield "f"] - }; - } - - check(gen(function sum(x, y) { - return x + y; - }), ["a", "b", "c", "d", "e", "f"], { - a: 1, - b: 2, - c: 3 + 4, - d: [5, 6] - }); - }); -}); - -describe("generator .throw method", function() { - (runningInTranslation ? it : xit)("should complete generator", function() { - function *gen(x) { - yield 2; - throw 1; - } - - var u = gen(); - - u.next(); - - try { - u.throw(2); - } catch (err) { - assert.strictEqual(err, 2); - } - - assertAlreadyFinished(u); - }); - - it("should work after the final call to .next", function() { - function *gen() { - yield 1; - } - - var g = gen(); - assert.deepEqual(g.next(), { value: 1, done: false }); - - var exception = new Error("unhandled exception"); - try { - g.throw(exception); - assert.ok(false, "should have thrown an exception"); - } catch (err) { - assert.strictEqual(err, exception); - } - }); - - it("should immediately complete a new-born generator", function() { - var began = false; - - function *gen() { - began = true; - yield 1; - } - - var g = gen(); - var exception = new Error("unhandled exception"); - try { - g.throw(exception); - assert.ok(false, "should have thrown an exception"); - } catch (err) { - assert.strictEqual(err, exception); - assert.strictEqual(began, false); - } - }); - - it("should not propagate errors handled inside a delegate", function() { - function *outer() { - try { - yield* inner(); - } catch (err) { - return -1; - } - return 1; - } - - function *inner() { - try { - yield void 0; - } catch (e) { - return; - } - } - - var g = outer(); - g.next(); - assert.equal(g.throw(new Error('foo')).value, 1); - }); - - it("should propagate errors unhandled inside a delegate", function() { - function *outer() { - try { - yield* inner(); - } catch (err) { - return -1; - } - return 1; - } - - function *inner() { - yield void 0; - } - - var g = outer(); - g.next(); - assert.equal(g.throw(new Error('foo')).value, -1); - }); -}); - -describe("unqualified function calls", function() { - it("should have a global `this` object", function() { - function getThis() { - return this; - } - - // This is almost certainly the global object, but there's a chance it - // might be null or undefined (in strict mode). - var unqualifiedThis = getThis(); - - function *invoke() { - // It seems like a bug in the ES6 spec that we have to yield an - // argument instead of just calling (yield)(). - return (yield "dummy")(); - } - - var g = invoke(); - var info = g.next(); - - assert.deepEqual(info, { value: "dummy", done: false }); - - info = g.next(getThis); - - // Avoid using assert.strictEqual when the arguments might equal the - // global object, since JSON.stringify chokes on circular structures. - assert.ok(info.value === unqualifiedThis); - - assert.strictEqual(info.done, true); - }); -}); - -describe("yield* expression results", function () { - it("have correct values", function () { - function* foo() { - yield 0; - return yield* bar(); - } - - function* bar() { - yield 1; - return 2; - } - - check(foo(), [0, 1], 2); - }); - - it("can be used in complex expressions", function () { - function pumpNumber(gen) { - var n = 0; - - while (true) { - var res = n > 0 ? gen.next(n) : gen.next(); - n = res.value; - if (res.done) { - return n; - } - } - } - - function* foo() { - return (yield* bar()) + (yield* bar()); - } - - function* bar() { - return (yield 2) + (yield 3); - } - - assert.strictEqual(pumpNumber(bar()), 5); - assert.strictEqual(pumpNumber(foo()), 10); - }); -}); - -describe("isGeneratorFunction", function() { - it("should work for function declarations", function() { - // Do the assertions up here to make sure the generator function is - // marked at the beginning of the block the function is declared in. - assert.strictEqual( - regeneratorRuntime.isGeneratorFunction(genFun), - true - ); - - assert.strictEqual( - regeneratorRuntime.isGeneratorFunction(normalFun), - false - ); - - function normalFun() { - return 0; - } - - function *genFun() { - yield 0; - } - }); - - it("should work for function expressions", function() { - assert.strictEqual( - regeneratorRuntime.isGeneratorFunction(function *genFun() { - yield 0; - }), - true - ); - - assert.strictEqual( - regeneratorRuntime.isGeneratorFunction(function normalFun() { - return 0; - }), - false - ); - }); -}); - -describe("new expressions", function() { - it("should be able to contain yield sub-expressions", function() { - function A(first, second) { - this.first = first; - this.second = second; - } - - function *gen() { - return yield new (yield 0)(yield 1, yield 2); - } - - var g = gen(); - - assert.deepEqual(g.next(), { value: 0, done: false }); - assert.deepEqual(g.next(A), { value: 1, done: false }); - assert.deepEqual(g.next("asdf"), { value: 2, done: false }); - - var info = g.next("zxcv"); - assert.strictEqual(info.done, false); - assert.ok(info.value instanceof A); - assert.strictEqual(info.value.first, "asdf"); - assert.strictEqual(info.value.second, "zxcv"); - - assert.deepEqual(g.next("qwer"), { value: "qwer", done: true }); - }); -}); - -describe("block binding", function() { - it("should translate block binding correctly", function() { - "use strict"; - - function *gen() { - var a$0 = 0, a$1 = 1; - - let a = 3; - - { - let a = 1; - yield a + a$0; - } - - { - let a = 2; - yield a - 1 + a$1; - } - - yield a; - } - - var g = gen(); - - assert.deepEqual(g.next(), { value: 1, done: false }); - assert.deepEqual(g.next(), { value: 2, done: false }); - assert.deepEqual(g.next(), { value: 3, done: false }); - assert.deepEqual(g.next(), { value: void 0, done: true }); - }); - - it("should translate block binding with iife correctly", function() { - "use strict"; - - function *gen() { - let arr = []; - - for (let x = 0; x < 3; x++) { - let y = x; - arr.push(function() { return y; }); - } - - { - let x; - while( x = arr.pop() ) { - yield x; - } - } - } - - var g = gen(); - - assert.equal(g.next().value(), 2); - assert.equal(g.next().value(), 1); - assert.equal(g.next().value(), 0); - assert.deepEqual(g.next(), { value: void 0, done: true }); - }); -}); - -describe("newborn generators", function() { - it("should be able to yield* non-newborn generators", function() { - function *inner() { - return [yield 1, yield 2]; - } - - function *outer(delegate) { - return yield* delegate; - } - - var n = inner(); - - assert.deepEqual(n.next(), { - value: 1, - done: false - }); - - var g = outer(n); - - // I would really like to be able to pass 3 to g.next here, but V8 - // ignores values sent to newborn generators, and SpiderMonkey throws - // a TypeError. - assert.deepEqual(g.next(), { - value: 2, - done: false - }); - - assert.deepEqual(g.next(4), { - value: [void 0, 4], - done: true - }); - }); - - it("should support the ignore-initial-yield wrapper idiom", function() { - var markers = []; - - function *inner() { - markers.push(0); - var sent1 = yield 1; - markers.push(2); - var sent2 = yield 2; - markers.push(3); - return [sent1, sent2]; - } - - function wrapper(delegate) { - var gen = (function*() { - // This yield is the "initial yield" whose argument we ignore. - var sent = yield "ignored", info; - - markers.push(1); - - while (!(info = delegate.next(sent)).done) { - sent = yield info.value; - } - - markers.push(4); - - return info.value; - })(); - - // Ensure that gen is not newborn and that the next invocation of - // gen.next(value) can send value to the initial yield expression. - gen.next(); - - return gen; - } - - var n = inner(); - - assert.deepEqual(n.next(), { - value: 1, - done: false - }); - - var g = wrapper(n); - - // Unlike in the previous spec, it's fine to pass 3 to g.next here, - // because g is not newborn, because g.next was already called once - // before g was returned from the wrapper function. - assert.deepEqual(g.next(3), { - value: 2, - done: false - }); - - assert.deepEqual(g.next(4), { - value: [3, 4], - done: true - }); - - // Ensure we encountered the marker points in the expected order. - assert.deepEqual(markers, [0, 1, 2, 3, 4]); - }); - - it("should allow chaining newborn and non-newborn generators", function() { - function *range(n) { - for (var i = 0; i < n; ++i) { - yield i; - } - } - - function *chain(a, b) { - yield* a; - yield* b; - } - - check(chain(range(3), range(5)), [0, 1, 2, 0, 1, 2, 3, 4]); - - function *y3(x) { - return yield yield yield x; - } - - function *y5(x) { - return yield yield yield yield yield x; - } - - check( - chain(y3("foo"), y5("bar")), - ["foo", 1, 2, "bar", 4, 5, 6, 7] - ); - - var g3 = y3("three"); - assert.deepEqual(g3.next(), { - value: "three", - done: false - }); - - var g5 = y5("five"); - assert.deepEqual(g5.next(), { - value: "five", - done: false - }); - - var undef; // A little easier to read than void 0. - check(chain(g3, g5), [undef, 1, undef, 3, 4, 5]); - }); -}); - -describe("labeled break and continue statements", function() { - it("should be able to exit multiple try statements", function() { - var e1 = "first"; - var e2 = "second"; - var e3 = "third"; - var e4 = "fourth"; - - function *gen(n, which) { - try { - yield 0; - raise(e1); - - } finally { - yield 1; - - loop: - for (var i = 0; i < n; ++i) { - yield i; - - try { - raise(e2); - } finally { - yield 2; - - try { - raise(e3); - } finally { - yield 3; - - try { - raise(e4); - } finally { - yield 4; - - if (which === "break") { - yield "breaking"; - break loop; - } - - if (which === "continue") { - yield "continuing"; - continue loop; - } - - yield 5; - } - } - } - } - - yield 6; - } - } - - try { - check(gen(1, "break"), [ - 0, 1, 0, 2, 3, 4, "breaking", 6 - ]); - assert.ok(false, "should have thrown an exception"); - } catch (err) { - assert.strictEqual(err, e1); - } - - try { - check(gen(3, "continue"), [ - 0, 1, 0, 2, 3, 4, "continuing", - 1, 2, 3, 4, "continuing", - 2, 2, 3, 4, "continuing", - 6 // Loop finished naturally. - ]); - assert.ok(false, "should have thrown an exception"); - } catch (err) { - assert.strictEqual(err, e1); - } - - try { - check(gen(3, "neither"), [ - 0, 1, 0, 2, 3, 4, 5 - ]); - assert.ok(false, "should have thrown an exception"); - } catch (err) { - assert.strictEqual(err, e4); - } - }); - - it("should allow breaking from any labeled statement", function() { - function* gen(limit) { - yield 0; - - for (var i = 0; i < limit; ++i) { - yield 1; - - label1: { - yield 2; - break label1; - yield 3; - } - - label2: - if (limit === 3) label3: { - yield 4; - if (i === 0) break label2; - yield 5; - if (i === 1) break label3; - label4: yield 6; - // This should break from the for-loop. - if (i === 2) xxx: break; - yield 7; - } - - // This should be a no-op. - xxx: break xxx; - - yield 8 - } - - yield 9; - } - - check(gen(0), [0, 9]); - check(gen(1), [0, 1, 2, 8, 9]); - check(gen(2), [0, 1, 2, 8, 1, 2, 8, 9]); - check(gen(3), [0, 1, 2, 4, 8, 1, 2, 4, 5, 8, 1, 2, 4, 5, 6, 9]); - }); -}); - -describe("for loop with var decl and no update expression", function() { - // https://github.com/facebook/regenerator/issues/103 - function *range() { - for (var i = 0; false; ) { - } - } - - it("should compile and run", function() { - check(range(), []); - }); -}); - -describe("generator function prototype", function() { - function getProto(obj) { - return Object.getPrototypeOf - ? Object.getPrototypeOf(obj) - : obj.__proto__; - } - - it("should follow the expected object model", function() { - var GeneratorFunctionPrototype = getProto(f); - var GeneratorFunction = GeneratorFunctionPrototype.constructor; - - assert.strictEqual(GeneratorFunction.name, 'GeneratorFunction'); - assert.strictEqual(GeneratorFunction.prototype, - GeneratorFunctionPrototype); - assert.strictEqual(GeneratorFunctionPrototype.prototype.constructor, - GeneratorFunctionPrototype); - assert.strictEqual(GeneratorFunctionPrototype.prototype, - getProto(f.prototype)); - assert.strictEqual(getProto(GeneratorFunctionPrototype), - Function.prototype); - - if (typeof process === "undefined" || - process.version.slice(1, 3) === "0.") { - // Node version strings start with 0. - assert.strictEqual(GeneratorFunctionPrototype.name, - "GeneratorFunctionPrototype"); - } else if (process.version.slice(1, 3) === "1.") { - // iojs version strings start with 1., and iojs gets this .name - // property wrong. TODO report this? - assert.strictEqual(GeneratorFunctionPrototype.name, ""); - } - - assert.strictEqual(typeof f2, "function"); - assert.strictEqual(f2.constructor, GeneratorFunction); - assert.ok(f2 instanceof GeneratorFunction); - assert.strictEqual(f2.name, "f2"); - - var g = f(); - assert.ok(g instanceof f); - assert.strictEqual(getProto(g), f.prototype); - - assert.deepEqual([], Object.getOwnPropertyNames(f.prototype)); - // assert.deepEqual([], Object.getOwnPropertyNames(g)); - - f.prototype.x = 42; - - var g2 = f(); - assert.strictEqual(g2.x, 42); - - var g3 = new f(); - assert.strictEqual(g3.x, 42); - - function* f2() { - yield 1; - } - - assert.strictEqual(getProto(f), getProto(f2)); - assert.strictEqual(f.hasOwnProperty('constructor'), false); - assert.strictEqual(getProto(f).constructor.name, 'GeneratorFunction'); - - // Intentionally at the end to test hoisting. - function* f() { - yield this; - } - - function* f() { - yield 1; - } - - var f2 = f; - f = 42; - var g = f2(); - - assert.deepEqual(g.next(), { value: 1, done: false }); - assert.deepEqual(g.next(), { value: void 0, done: true }); - assert.ok(g instanceof f2); - }); -}); - -describe("for-of loops", function() { - (runningInTranslation ? it : xit) - ("should work for Arrays", function() { - var sum = 0; - for (var x of [1, 2].concat(3)) { - sum += x; - } - assert.strictEqual(sum, 6); - }); - - it("should work for generators", function() { - var value, values = []; - for (value of range(3)) - values.push(value); - assert.deepEqual(values, [0, 1, 2]); - }); - - it("should work inside of generators", function() { - function *yieldPermutations(list) { - if (list.length < 2) { - yield list; - return 1; - } - - var count = 0; - var first = list.slice(0, 1); - var genRest = yieldPermutations(list.slice(1)); - - for (var perm of genRest) { - for (var i = 0; i < list.length; ++i) { - var prefix = perm.slice(0, i); - var suffix = perm.slice(i); - yield prefix.concat(first, suffix); - } - - count += i; - } - - return count; - } - - var count = 0; - for (var perm of yieldPermutations([])) { - assert.deepEqual(perm, []); - ++count; - } - assert.strictEqual(count, 1); - - check(yieldPermutations([1]), [[1]], 1); - - check(yieldPermutations([2, 1]), [ - [2, 1], - [1, 2] - ], 2); - - check(yieldPermutations([1,3,2]), [ - [1, 3, 2], - [3, 1, 2], - [3, 2, 1], - [1, 2, 3], - [2, 1, 3], - [2, 3, 1] - ], 6); - }); -}); - -describe("generator return method", function() { - if (!runningInTranslation) { - // The return method has not been specified or implemented natively, - // yet, so these tests need only pass in translation. - return; - } - - it("should work with newborn generators", function() { - function *gen() { - yield 0; - } - - var g = gen(); - - assert.deepEqual(g.return("argument"), { - value: "argument", - done: true - }); - - assertAlreadyFinished(g); - }); - - it("should behave as if generator actually returned", function() { - var executedFinally = false; - - function *gen() { - try { - yield 0; - } catch (err) { - assert.ok(false, "should not have executed the catch handler"); - } finally { - executedFinally = true; - } - } - - var g = gen(); - assert.deepEqual(g.next(), { value: 0, done: false }); - - assert.deepEqual(g.return("argument"), { - value: "argument", - done: true - }); - - assert.strictEqual(executedFinally, true); - assertAlreadyFinished(g); - }); - - it("should return both delegate and delegator", function() { - var checkpoints = []; - - function* callee(errorToThrow) { - try { - yield 1; - yield 2; - } finally { - checkpoints.push("callee finally"); - if (errorToThrow) { - throw errorToThrow; - } - } - } - - function* caller(errorToThrow) { - try { - yield 0; - yield* callee(errorToThrow); - yield 3; - } finally { - checkpoints.push("caller finally"); - } - } - - var g1 = caller(); - - assert.deepEqual(g1.next(), { value: 0, done: false }); - assert.deepEqual(g1.next(), { value: 1, done: false }); - assert.deepEqual(g1.return(-1), { value: -1, done: true }); - assert.deepEqual(checkpoints, [ - "callee finally", - "caller finally" - ]); - - var error = new Error("thrown from callee"); - var g2 = caller(error); - - assert.deepEqual(g2.next(), { value: 0, done: false }); - assert.deepEqual(g2.next(), { value: 1, done: false }); - - try { - g2.return(-1); - assert.ok(false, "should have thrown an exception"); - } catch (thrown) { - assert.strictEqual(thrown, error); - } - - assert.deepEqual(checkpoints, [ - "callee finally", - "caller finally", - "callee finally", - "caller finally" - ]); - }); -}); - -describe("expressions containing yield subexpressions", function() { - it("should evaluate all subexpressions before yielding", function() { - function *gen(x) { - return x * (yield (function(y) { x = y })); - } - - var g = gen(2); - var result = g.next(); - assert.strictEqual(result.done, false); - - result.value(5); - - assert.deepEqual(g.next(5), { - value: 10, - done: true - }); - }); - - it("should work even with getter member expressions", function() { - function *gen() { - return a.b + (yield "asdf"); - } - - var a = {}; - var b = 0; - - Object.defineProperty(a, "b", { - get: function() { - return ++b; - } - }); - - var g = gen(); - - assert.strictEqual(a.b, 1); - - assert.deepEqual(g.next(), { - value: "asdf", - done: false - }); - - assert.strictEqual(a.b, 3); - - assert.deepEqual(g.next(2), { - value: 4, - done: true - }); - }); - - it("should evaluate all array elements before yielding", function() { - function *gen() { - return [a, yield "asdf", a]; - } - - var a = 1; - var g = gen(); - - assert.deepEqual(g.next(), { - value: "asdf", - done: false - }); - - a = 3; - - assert.deepEqual(g.next(2), { - value: [1, 2, 3], - done: true - }); - }); - - it("should handle callee member expressions correctly", function() { - function *gen() { - a = a.slice(0).concat(yield "asdf"); - return a; - } - - var a = []; - var g = gen(); - - assert.deepEqual(g.next(), { - value: "asdf", - done: false - }); - - a.push(1); - - assert.deepEqual(g.next(2), { - value: [2], - done: true - }); - }); - - it("should handle implicit stringification correctly", function() { - function *gen() { - return a + (yield "asdf"); - } - - var a = [1, 2]; - var g = gen(); - - assert.deepEqual(g.next(), { - value: "asdf", - done: false - }); - - a = [4,5]; - - assert.deepEqual(g.next(",3"), { - value: "1,2,3", - done: true - }); - }); -}); diff --git a/packages/babel-plugin-transform-regenerator/LICENSE b/packages/babel-plugin-transform-regenerator/LICENSE deleted file mode 100644 index 187bfe283df6..000000000000 --- a/packages/babel-plugin-transform-regenerator/LICENSE +++ /dev/null @@ -1,14 +0,0 @@ -BSD License - -For "regenerator" software - -Copyright (c) 2014, Facebook, Inc. -All rights reserved. - -Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - - * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. - - * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/packages/babel-plugin-transform-regenerator/PATENTS b/packages/babel-plugin-transform-regenerator/PATENTS deleted file mode 100644 index a2bd67d0dbe2..000000000000 --- a/packages/babel-plugin-transform-regenerator/PATENTS +++ /dev/null @@ -1,33 +0,0 @@ -Additional Grant of Patent Rights Version 2 - -"Software" means the Regenerator software distributed by Facebook, Inc. - -Facebook, Inc. ("Facebook") hereby grants to each recipient of the Software -("you") a perpetual, worldwide, royalty-free, non-exclusive, irrevocable -(subject to the termination provision below) license under any Necessary -Claims, to make, have made, use, sell, offer to sell, import, and otherwise -transfer the Software. For avoidance of doubt, no license is granted under -Facebook's rights in any patent claims that are infringed by (i) modifications -to the Software made by you or any third party or (ii) the Software in -combination with any software or other technology. - -The license granted hereunder will terminate, automatically and without notice, -if you (or any of your subsidiaries, corporate affiliates or agents) initiate -directly or indirectly, or take a direct financial interest in, any Patent -Assertion: (i) against Facebook or any of its subsidiaries or corporate -affiliates, (ii) against any party if such Patent Assertion arises in whole or -in part from any software, technology, product or service of Facebook or any of -its subsidiaries or corporate affiliates, or (iii) against any party relating -to the Software. Notwithstanding the foregoing, if Facebook or any of its -subsidiaries or corporate affiliates files a lawsuit alleging patent -infringement against you in the first instance, and you respond by filing a -patent infringement counterclaim in that lawsuit against that party that is -unrelated to the Software, the license granted hereunder will not terminate -under section (i) of this paragraph due to such counterclaim. - -A "Necessary Claim" is a claim of a patent owned by Facebook that is -necessarily infringed by the Software standing alone. - -A "Patent Assertion" is any lawsuit or other action alleging direct, indirect, -or contributory infringement or inducement to infringe any patent, including a -cross-claim or counterclaim. diff --git a/packages/babel-plugin-transform-regenerator/README.md b/packages/babel-plugin-transform-regenerator/README.md index 0ee17fcf9f1e..18adfa4bca43 100644 --- a/packages/babel-plugin-transform-regenerator/README.md +++ b/packages/babel-plugin-transform-regenerator/README.md @@ -1,11 +1,45 @@ # babel-plugin-transform-regenerator -Transform async/generator functions with [regenerator](https://github.com/facebook/regenerator) +> Transform async/generator functions with [regenerator](https://github.com/facebook/regenerator) + +## Example + +**In** + +```javascript +function* a() { + yield 1; +} +``` + +**Out** + +```javascript +var _marked = [a].map(regeneratorRuntime.mark); + +function a() { + return regeneratorRuntime.wrap(function a$(_context) { + while (1) { + switch (_context.prev = _context.next) { + case 0: + _context.next = 2; + return 1; + + case 2: + case "end": + return _context.stop(); + } + } + }, _marked[0], this); +} +``` + +[Try in REPL](http://babeljs.io/repl/#?evaluate=true&lineWrap=true&presets=es2015%2Ces2015-loose%2Creact&experimental=false&loose=false&spec=false&code=function%20*range(max%2C%20step)%20%7B%0A%20%20var%20count%20%3D%200%3B%0A%20%20step%20%3D%20step%20%7C%7C%201%3B%0A%20%0A%20%20for%20(var%20i%20%3D%200%3B%20i%20%3C%20max%3B%20i%20%2B%3D%20step)%20%7B%0A%20%20%20%20count%2B%2B%3B%0A%20%20%20%20yield%20i%3B%0A%20%20%7D%0A%20%0A%20%20return%20count%3B%0A%7D%0A%20%0Avar%20gen%20%3D%20range(20%2C%203)%2C%20info%3B%0A%20%0Awhile%20(!(info%20%3D%20gen.next()).done)%20%7B%0A%20%20console.log(info.value)%3B%0A%7D%0A%20%0Aconsole.log(%22steps%20taken%3A%20%22%20%2B%20info.value)%3B&playground=true) ## Installation ```sh -$ npm install babel-plugin-transform-regenerator +npm install --save-dev babel-plugin-transform-regenerator ``` ## Usage @@ -23,9 +57,9 @@ $ npm install babel-plugin-transform-regenerator { "plugins": [ ["transform-regenerator", { - asyncGenerators: false, // true by default - generators: false, // true by default - async: false // true by default + asyncGenerators: false, // true by default + generators: false, // true by default + async: false // true by default }] ] } @@ -34,7 +68,7 @@ $ npm install babel-plugin-transform-regenerator ### Via CLI ```sh -$ babel --plugins transform-regenerator script.js +babel --plugins transform-regenerator script.js ``` ### Via Node API diff --git a/packages/babel-plugin-transform-regenerator/package.json b/packages/babel-plugin-transform-regenerator/package.json index 491b227a0fd6..bb57a9a2dadc 100644 --- a/packages/babel-plugin-transform-regenerator/package.json +++ b/packages/babel-plugin-transform-regenerator/package.json @@ -2,16 +2,14 @@ "name": "babel-plugin-transform-regenerator", "author": "Ben Newman ", "description": "Explode async and generator functions into a state machine.", - "version": "6.16.1", + "version": "6.20.0", "homepage": "https://github.com/babel/babel/tree/master/packages/babel-plugin-transform-regenerator", "repository": "https://github.com/babel/babel/tree/master/packages/babel-plugin-transform-regenerator", "main": "lib/index.js", "dependencies": { - "babel-types": "^6.16.0", - "babel-runtime": "^6.9.0", - "private": "~0.1.5" + "regenerator-transform": "0.9.8" }, - "license": "BSD", + "license": "MIT", "devDependencies": { "babel-helper-plugin-test-runner": "^6.8.0" } diff --git a/packages/babel-plugin-transform-regenerator/src/emit.js b/packages/babel-plugin-transform-regenerator/src/emit.js deleted file mode 100644 index b3378867b3b4..000000000000 --- a/packages/babel-plugin-transform-regenerator/src/emit.js +++ /dev/null @@ -1,1184 +0,0 @@ -/** - * Copyright (c) 2014, Facebook, Inc. - * All rights reserved. - * - * This source code is licensed under the BSD-style license found in the - * https://raw.github.com/facebook/regenerator/master/LICENSE file. An - * additional grant of patent rights can be found in the PATENTS file in - * the same directory. - */ - -import assert from "assert"; -import * as t from "babel-types"; -import * as leap from "./leap"; -import * as meta from "./meta"; -import * as util from "./util"; - -let hasOwn = Object.prototype.hasOwnProperty; - -function Emitter(contextId) { - assert.ok(this instanceof Emitter); - t.assertIdentifier(contextId); - - // Used to generate unique temporary names. - this.nextTempId = 0; - - // In order to make sure the context object does not collide with - // anything in the local scope, we might have to rename it, so we - // refer to it symbolically instead of just assuming that it will be - // called "context". - this.contextId = contextId; - - // An append-only list of Statements that grows each time this.emit is - // called. - this.listing = []; - - // A sparse array whose keys correspond to locations in this.listing - // that have been marked as branch/jump targets. - this.marked = [true]; - - // The last location will be marked when this.getDispatchLoop is - // called. - this.finalLoc = loc(); - - // A list of all leap.TryEntry statements emitted. - this.tryEntries = []; - - // Each time we evaluate the body of a loop, we tell this.leapManager - // to enter a nested loop context that determines the meaning of break - // and continue statements therein. - this.leapManager = new leap.LeapManager(this); -} - -let Ep = Emitter.prototype; -exports.Emitter = Emitter; - -// Offsets into this.listing that could be used as targets for branches or -// jumps are represented as numeric Literal nodes. This representation has -// the amazingly convenient benefit of allowing the exact value of the -// location to be determined at any time, even after generating code that -// refers to the location. -function loc() { - return t.numericLiteral(-1); -} - -// Sets the exact value of the given location to the offset of the next -// Statement emitted. -Ep.mark = function(loc) { - t.assertLiteral(loc); - let index = this.listing.length; - if (loc.value === -1) { - loc.value = index; - } else { - // Locations can be marked redundantly, but their values cannot change - // once set the first time. - assert.strictEqual(loc.value, index); - } - this.marked[index] = true; - return loc; -}; - -Ep.emit = function(node) { - if (t.isExpression(node)) { - node = t.expressionStatement(node); - } - - t.assertStatement(node); - this.listing.push(node); -}; - -// Shorthand for emitting assignment statements. This will come in handy -// for assignments to temporary variables. -Ep.emitAssign = function(lhs, rhs) { - this.emit(this.assign(lhs, rhs)); - return lhs; -}; - -// Shorthand for an assignment statement. -Ep.assign = function(lhs, rhs) { - return t.expressionStatement( - t.assignmentExpression("=", lhs, rhs)); -}; - -// Convenience function for generating expressions like context.next, -// context.sent, and context.rval. -Ep.contextProperty = function(name, computed) { - return t.memberExpression( - this.contextId, - computed ? t.stringLiteral(name) : t.identifier(name), - !!computed - ); -}; - -// Shorthand for setting context.rval and jumping to `context.stop()`. -Ep.stop = function(rval) { - if (rval) { - this.setReturnValue(rval); - } - - this.jump(this.finalLoc); -}; - -Ep.setReturnValue = function(valuePath) { - t.assertExpression(valuePath.value); - - this.emitAssign( - this.contextProperty("rval"), - this.explodeExpression(valuePath) - ); -}; - -Ep.clearPendingException = function(tryLoc, assignee) { - t.assertLiteral(tryLoc); - - let catchCall = t.callExpression( - this.contextProperty("catch", true), - [tryLoc] - ); - - if (assignee) { - this.emitAssign(assignee, catchCall); - } else { - this.emit(catchCall); - } -}; - -// Emits code for an unconditional jump to the given location, even if the -// exact value of the location is not yet known. -Ep.jump = function(toLoc) { - this.emitAssign(this.contextProperty("next"), toLoc); - this.emit(t.breakStatement()); -}; - -// Conditional jump. -Ep.jumpIf = function(test, toLoc) { - t.assertExpression(test); - t.assertLiteral(toLoc); - - this.emit(t.ifStatement( - test, - t.blockStatement([ - this.assign(this.contextProperty("next"), toLoc), - t.breakStatement() - ]) - )); -}; - -// Conditional jump, with the condition negated. -Ep.jumpIfNot = function(test, toLoc) { - t.assertExpression(test); - t.assertLiteral(toLoc); - - let negatedTest; - if (t.isUnaryExpression(test) && - test.operator === "!") { - // Avoid double negation. - negatedTest = test.argument; - } else { - negatedTest = t.unaryExpression("!", test); - } - - this.emit(t.ifStatement( - negatedTest, - t.blockStatement([ - this.assign(this.contextProperty("next"), toLoc), - t.breakStatement() - ]) - )); -}; - -// Returns a unique MemberExpression that can be used to store and -// retrieve temporary values. Since the object of the member expression is -// the context object, which is presumed to coexist peacefully with all -// other local variables, and since we just increment `nextTempId` -// monotonically, uniqueness is assured. -Ep.makeTempVar = function() { - return this.contextProperty("t" + this.nextTempId++); -}; - -Ep.getContextFunction = function(id) { - return t.functionExpression( - id || null/*Anonymous*/, - [this.contextId], - t.blockStatement([this.getDispatchLoop()]), - false, // Not a generator anymore! - false // Nor an expression. - ); -}; - -// Turns this.listing into a loop of the form -// -// while (1) switch (context.next) { -// case 0: -// ... -// case n: -// return context.stop(); -// } -// -// Each marked location in this.listing will correspond to one generated -// case statement. -Ep.getDispatchLoop = function() { - let self = this; - let cases = []; - let current; - - // If we encounter a break, continue, or return statement in a switch - // case, we can skip the rest of the statements until the next case. - let alreadyEnded = false; - - self.listing.forEach(function(stmt, i) { - if (self.marked.hasOwnProperty(i)) { - cases.push(t.switchCase( - t.numericLiteral(i), - current = [])); - alreadyEnded = false; - } - - if (!alreadyEnded) { - current.push(stmt); - if (t.isCompletionStatement(stmt)) - alreadyEnded = true; - } - }); - - // Now that we know how many statements there will be in this.listing, - // we can finally resolve this.finalLoc.value. - this.finalLoc.value = this.listing.length; - - cases.push( - t.switchCase(this.finalLoc, [ - // Intentionally fall through to the "end" case... - ]), - - // So that the runtime can jump to the final location without having - // to know its offset, we provide the "end" case as a synonym. - t.switchCase(t.stringLiteral("end"), [ - // This will check/clear both context.thrown and context.rval. - t.returnStatement( - t.callExpression(this.contextProperty("stop"), []) - ) - ]) - ); - - return t.whileStatement( - t.numericLiteral(1), - t.switchStatement( - t.assignmentExpression( - "=", - this.contextProperty("prev"), - this.contextProperty("next") - ), - cases - ) - ); -}; - -Ep.getTryLocsList = function() { - if (this.tryEntries.length === 0) { - // To avoid adding a needless [] to the majority of runtime.wrap - // argument lists, force the caller to handle this case specially. - return null; - } - - let lastLocValue = 0; - - return t.arrayExpression( - this.tryEntries.map(function(tryEntry) { - let thisLocValue = tryEntry.firstLoc.value; - assert.ok(thisLocValue >= lastLocValue, "try entries out of order"); - lastLocValue = thisLocValue; - - let ce = tryEntry.catchEntry; - let fe = tryEntry.finallyEntry; - - let locs = [ - tryEntry.firstLoc, - // The null here makes a hole in the array. - ce ? ce.firstLoc : null - ]; - - if (fe) { - locs[2] = fe.firstLoc; - locs[3] = fe.afterLoc; - } - - return t.arrayExpression(locs); - }) - ); -}; - -// All side effects must be realized in order. - -// If any subexpression harbors a leap, all subexpressions must be -// neutered of side effects. - -// No destructive modification of AST nodes. - -Ep.explode = function(path, ignoreResult) { - let node = path.node; - let self = this; - - t.assertNode(node); - - if (t.isDeclaration(node)) - throw getDeclError(node); - - if (t.isStatement(node)) - return self.explodeStatement(path); - - if (t.isExpression(node)) - return self.explodeExpression(path, ignoreResult); - - switch (node.type) { - case "Program": - return path.get("body").map( - self.explodeStatement, - self - ); - - case "VariableDeclarator": - throw getDeclError(node); - - // These node types should be handled by their parent nodes - // (ObjectExpression, SwitchStatement, and TryStatement, respectively). - case "Property": - case "SwitchCase": - case "CatchClause": - throw new Error( - node.type + " nodes should be handled by their parents"); - - default: - throw new Error( - "unknown Node of type " + - JSON.stringify(node.type)); - } -}; - -function getDeclError(node) { - return new Error( - "all declarations should have been transformed into " + - "assignments before the Exploder began its work: " + - JSON.stringify(node)); -} - -Ep.explodeStatement = function(path, labelId) { - let stmt = path.node; - let self = this; - let before, after, head; - - t.assertStatement(stmt); - - if (labelId) { - t.assertIdentifier(labelId); - } else { - labelId = null; - } - - // Explode BlockStatement nodes even if they do not contain a yield, - // because we don't want or need the curly braces. - if (t.isBlockStatement(stmt)) { - path.get("body").forEach(function (path) { - self.explodeStatement(path); - }); - return; - } - - if (!meta.containsLeap(stmt)) { - // Technically we should be able to avoid emitting the statement - // altogether if !meta.hasSideEffects(stmt), but that leads to - // confusing generated code (for instance, `while (true) {}` just - // disappears) and is probably a more appropriate job for a dedicated - // dead code elimination pass. - self.emit(stmt); - return; - } - - switch (stmt.type) { - case "ExpressionStatement": - self.explodeExpression(path.get("expression"), true); - break; - - case "LabeledStatement": - after = loc(); - - // Did you know you can break from any labeled block statement or - // control structure? Well, you can! Note: when a labeled loop is - // encountered, the leap.LabeledEntry created here will immediately - // enclose a leap.LoopEntry on the leap manager's stack, and both - // entries will have the same label. Though this works just fine, it - // may seem a bit redundant. In theory, we could check here to - // determine if stmt knows how to handle its own label; for example, - // stmt happens to be a WhileStatement and so we know it's going to - // establish its own LoopEntry when we explode it (below). Then this - // LabeledEntry would be unnecessary. Alternatively, we might be - // tempted not to pass stmt.label down into self.explodeStatement, - // because we've handled the label here, but that's a mistake because - // labeled loops may contain labeled continue statements, which is not - // something we can handle in this generic case. All in all, I think a - // little redundancy greatly simplifies the logic of this case, since - // it's clear that we handle all possible LabeledStatements correctly - // here, regardless of whether they interact with the leap manager - // themselves. Also remember that labels and break/continue-to-label - // statements are rare, and all of this logic happens at transform - // time, so it has no additional runtime cost. - self.leapManager.withEntry( - new leap.LabeledEntry(after, stmt.label), - function() { - self.explodeStatement(path.get("body"), stmt.label); - } - ); - - self.mark(after); - - break; - - case "WhileStatement": - before = loc(); - after = loc(); - - self.mark(before); - self.jumpIfNot(self.explodeExpression(path.get("test")), after); - self.leapManager.withEntry( - new leap.LoopEntry(after, before, labelId), - function() { self.explodeStatement(path.get("body")); } - ); - self.jump(before); - self.mark(after); - - break; - - case "DoWhileStatement": - let first = loc(); - let test = loc(); - after = loc(); - - self.mark(first); - self.leapManager.withEntry( - new leap.LoopEntry(after, test, labelId), - function() { self.explode(path.get("body")); } - ); - self.mark(test); - self.jumpIf(self.explodeExpression(path.get("test")), first); - self.mark(after); - - break; - - case "ForStatement": - head = loc(); - let update = loc(); - after = loc(); - - if (stmt.init) { - // We pass true here to indicate that if stmt.init is an expression - // then we do not care about its result. - self.explode(path.get("init"), true); - } - - self.mark(head); - - if (stmt.test) { - self.jumpIfNot(self.explodeExpression(path.get("test")), after); - } else { - // No test means continue unconditionally. - } - - self.leapManager.withEntry( - new leap.LoopEntry(after, update, labelId), - function() { self.explodeStatement(path.get("body")); } - ); - - self.mark(update); - - if (stmt.update) { - // We pass true here to indicate that if stmt.update is an - // expression then we do not care about its result. - self.explode(path.get("update"), true); - } - - self.jump(head); - - self.mark(after); - - break; - - case "TypeCastExpression": - return self.explodeExpression(path.get("expression")); - - case "ForInStatement": - head = loc(); - after = loc(); - - let keyIterNextFn = self.makeTempVar(); - self.emitAssign( - keyIterNextFn, - t.callExpression( - util.runtimeProperty("keys"), - [self.explodeExpression(path.get("right"))] - ) - ); - - self.mark(head); - - let keyInfoTmpVar = self.makeTempVar(); - self.jumpIf( - t.memberExpression( - t.assignmentExpression( - "=", - keyInfoTmpVar, - t.callExpression(keyIterNextFn, []) - ), - t.identifier("done"), - false - ), - after - ); - - self.emitAssign( - stmt.left, - t.memberExpression( - keyInfoTmpVar, - t.identifier("value"), - false - ) - ); - - self.leapManager.withEntry( - new leap.LoopEntry(after, head, labelId), - function() { self.explodeStatement(path.get("body")); } - ); - - self.jump(head); - - self.mark(after); - - break; - - case "BreakStatement": - self.emitAbruptCompletion({ - type: "break", - target: self.leapManager.getBreakLoc(stmt.label) - }); - - break; - - case "ContinueStatement": - self.emitAbruptCompletion({ - type: "continue", - target: self.leapManager.getContinueLoc(stmt.label) - }); - - break; - - case "SwitchStatement": - // Always save the discriminant into a temporary variable in case the - // test expressions overwrite values like context.sent. - let disc = self.emitAssign( - self.makeTempVar(), - self.explodeExpression(path.get("discriminant")) - ); - - after = loc(); - let defaultLoc = loc(); - let condition = defaultLoc; - let caseLocs = []; - - // If there are no cases, .cases might be undefined. - let cases = stmt.cases || []; - - for (let i = cases.length - 1; i >= 0; --i) { - let c = cases[i]; - t.assertSwitchCase(c); - - if (c.test) { - condition = t.conditionalExpression( - t.binaryExpression("===", disc, c.test), - caseLocs[i] = loc(), - condition - ); - } else { - caseLocs[i] = defaultLoc; - } - } - - let discriminant = path.get("discriminant"); - discriminant.replaceWith(condition); - self.jump(self.explodeExpression(discriminant)); - - self.leapManager.withEntry( - new leap.SwitchEntry(after), - function() { - path.get("cases").forEach(function(casePath) { - let i = casePath.key; - self.mark(caseLocs[i]); - - casePath.get("consequent").forEach(function (path) { - self.explodeStatement(path); - }); - }); - } - ); - - self.mark(after); - if (defaultLoc.value === -1) { - self.mark(defaultLoc); - assert.strictEqual(after.value, defaultLoc.value); - } - - break; - - case "IfStatement": - let elseLoc = stmt.alternate && loc(); - after = loc(); - - self.jumpIfNot( - self.explodeExpression(path.get("test")), - elseLoc || after - ); - - self.explodeStatement(path.get("consequent")); - - if (elseLoc) { - self.jump(after); - self.mark(elseLoc); - self.explodeStatement(path.get("alternate")); - } - - self.mark(after); - - break; - - case "ReturnStatement": - self.emitAbruptCompletion({ - type: "return", - value: self.explodeExpression(path.get("argument")) - }); - - break; - - case "WithStatement": - throw new Error("WithStatement not supported in generator functions."); - - case "TryStatement": - after = loc(); - - let handler = stmt.handler; - - let catchLoc = handler && loc(); - let catchEntry = catchLoc && new leap.CatchEntry( - catchLoc, - handler.param - ); - - let finallyLoc = stmt.finalizer && loc(); - let finallyEntry = finallyLoc && - new leap.FinallyEntry(finallyLoc, after); - - let tryEntry = new leap.TryEntry( - self.getUnmarkedCurrentLoc(), - catchEntry, - finallyEntry - ); - - self.tryEntries.push(tryEntry); - self.updateContextPrevLoc(tryEntry.firstLoc); - - self.leapManager.withEntry(tryEntry, function() { - self.explodeStatement(path.get("block")); - - if (catchLoc) { - if (finallyLoc) { - // If we have both a catch block and a finally block, then - // because we emit the catch block first, we need to jump over - // it to the finally block. - self.jump(finallyLoc); - - } else { - // If there is no finally block, then we need to jump over the - // catch block to the fall-through location. - self.jump(after); - } - - self.updateContextPrevLoc(self.mark(catchLoc)); - - let bodyPath = path.get("handler.body"); - let safeParam = self.makeTempVar(); - self.clearPendingException(tryEntry.firstLoc, safeParam); - - bodyPath.traverse(catchParamVisitor, { - safeParam: safeParam, - catchParamName: handler.param.name - }); - - self.leapManager.withEntry(catchEntry, function() { - self.explodeStatement(bodyPath); - }); - } - - if (finallyLoc) { - self.updateContextPrevLoc(self.mark(finallyLoc)); - - self.leapManager.withEntry(finallyEntry, function() { - self.explodeStatement(path.get("finalizer")); - }); - - self.emit(t.returnStatement(t.callExpression( - self.contextProperty("finish"), - [finallyEntry.firstLoc] - ))); - } - }); - - self.mark(after); - - break; - - case "ThrowStatement": - self.emit(t.throwStatement( - self.explodeExpression(path.get("argument")) - )); - - break; - - default: - throw new Error( - "unknown Statement of type " + - JSON.stringify(stmt.type)); - } -}; - -let catchParamVisitor = { - Identifier: function(path, state) { - if (path.node.name === state.catchParamName && util.isReference(path)) { - path.replaceWith(state.safeParam); - } - }, - - Scope: function(path, state) { - if (path.scope.hasOwnBinding(state.catchParamName)) { - // Don't descend into nested scopes that shadow the catch - // parameter with their own declarations. - path.skip(); - } - } -}; - -Ep.emitAbruptCompletion = function(record) { - if (!isValidCompletion(record)) { - assert.ok( - false, - "invalid completion record: " + - JSON.stringify(record) - ); - } - - assert.notStrictEqual( - record.type, "normal", - "normal completions are not abrupt" - ); - - let abruptArgs = [t.stringLiteral(record.type)]; - - if (record.type === "break" || - record.type === "continue") { - t.assertLiteral(record.target); - abruptArgs[1] = record.target; - } else if (record.type === "return" || - record.type === "throw") { - if (record.value) { - t.assertExpression(record.value); - abruptArgs[1] = record.value; - } - } - - this.emit( - t.returnStatement( - t.callExpression( - this.contextProperty("abrupt"), - abruptArgs - ) - ) - ); -}; - -function isValidCompletion(record) { - let type = record.type; - - if (type === "normal") { - return !hasOwn.call(record, "target"); - } - - if (type === "break" || - type === "continue") { - return !hasOwn.call(record, "value") - && t.isLiteral(record.target); - } - - if (type === "return" || - type === "throw") { - return hasOwn.call(record, "value") - && !hasOwn.call(record, "target"); - } - - return false; -} - - -// Not all offsets into emitter.listing are potential jump targets. For -// example, execution typically falls into the beginning of a try block -// without jumping directly there. This method returns the current offset -// without marking it, so that a switch case will not necessarily be -// generated for this offset (I say "not necessarily" because the same -// location might end up being marked in the process of emitting other -// statements). There's no logical harm in marking such locations as jump -// targets, but minimizing the number of switch cases keeps the generated -// code shorter. -Ep.getUnmarkedCurrentLoc = function() { - return t.numericLiteral(this.listing.length); -}; - -// The context.prev property takes the value of context.next whenever we -// evaluate the switch statement discriminant, which is generally good -// enough for tracking the last location we jumped to, but sometimes -// context.prev needs to be more precise, such as when we fall -// successfully out of a try block and into a finally block without -// jumping. This method exists to update context.prev to the freshest -// available location. If we were implementing a full interpreter, we -// would know the location of the current instruction with complete -// precision at all times, but we don't have that luxury here, as it would -// be costly and verbose to set context.prev before every statement. -Ep.updateContextPrevLoc = function(loc) { - if (loc) { - t.assertLiteral(loc); - - if (loc.value === -1) { - // If an uninitialized location literal was passed in, set its value - // to the current this.listing.length. - loc.value = this.listing.length; - } else { - // Otherwise assert that the location matches the current offset. - assert.strictEqual(loc.value, this.listing.length); - } - - } else { - loc = this.getUnmarkedCurrentLoc(); - } - - // Make sure context.prev is up to date in case we fell into this try - // statement without jumping to it. TODO Consider avoiding this - // assignment when we know control must have jumped here. - this.emitAssign(this.contextProperty("prev"), loc); -}; - -Ep.explodeExpression = function(path, ignoreResult) { - let expr = path.node; - if (expr) { - t.assertExpression(expr); - } else { - return expr; - } - - let self = this; - let result; // Used optionally by several cases below. - let after; - - function finish(expr) { - t.assertExpression(expr); - if (ignoreResult) { - self.emit(expr); - } else { - return expr; - } - } - - // If the expression does not contain a leap, then we either emit the - // expression as a standalone statement or return it whole. - if (!meta.containsLeap(expr)) { - return finish(expr); - } - - // If any child contains a leap (such as a yield or labeled continue or - // break statement), then any sibling subexpressions will almost - // certainly have to be exploded in order to maintain the order of their - // side effects relative to the leaping child(ren). - let hasLeapingChildren = meta.containsLeap.onlyChildren(expr); - - // In order to save the rest of explodeExpression from a combinatorial - // trainwreck of special cases, explodeViaTempVar is responsible for - // deciding when a subexpression needs to be "exploded," which is my - // very technical term for emitting the subexpression as an assignment - // to a temporary variable and the substituting the temporary variable - // for the original subexpression. Think of exploded view diagrams, not - // Michael Bay movies. The point of exploding subexpressions is to - // control the precise order in which the generated code realizes the - // side effects of those subexpressions. - function explodeViaTempVar(tempVar, childPath, ignoreChildResult) { - assert.ok( - !ignoreChildResult || !tempVar, - "Ignoring the result of a child expression but forcing it to " + - "be assigned to a temporary variable?" - ); - - let result = self.explodeExpression(childPath, ignoreChildResult); - - if (ignoreChildResult) { - // Side effects already emitted above. - - } else if (tempVar || (hasLeapingChildren && - !t.isLiteral(result))) { - // If tempVar was provided, then the result will always be assigned - // to it, even if the result does not otherwise need to be assigned - // to a temporary variable. When no tempVar is provided, we have - // the flexibility to decide whether a temporary variable is really - // necessary. Unfortunately, in general, a temporary variable is - // required whenever any child contains a yield expression, since it - // is difficult to prove (at all, let alone efficiently) whether - // this result would evaluate to the same value before and after the - // yield (see #206). One narrow case where we can prove it doesn't - // matter (and thus we do not need a temporary variable) is when the - // result in question is a Literal value. - result = self.emitAssign( - tempVar || self.makeTempVar(), - result - ); - } - return result; - } - - // If ignoreResult is true, then we must take full responsibility for - // emitting the expression with all its side effects, and we should not - // return a result. - - switch (expr.type) { - case "MemberExpression": - return finish(t.memberExpression( - self.explodeExpression(path.get("object")), - expr.computed - ? explodeViaTempVar(null, path.get("property")) - : expr.property, - expr.computed - )); - - case "CallExpression": - let calleePath = path.get("callee"); - let argsPath = path.get("arguments"); - - let newCallee; - let newArgs = []; - - let hasLeapingArgs = false; - argsPath.forEach(function(argPath) { - hasLeapingArgs = hasLeapingArgs || - meta.containsLeap(argPath.node); - }); - - if (t.isMemberExpression(calleePath.node)) { - if (hasLeapingArgs) { - // If the arguments of the CallExpression contained any yield - // expressions, then we need to be sure to evaluate the callee - // before evaluating the arguments, but if the callee was a member - // expression, then we must be careful that the object of the - // member expression still gets bound to `this` for the call. - - let newObject = explodeViaTempVar( - // Assign the exploded callee.object expression to a temporary - // variable so that we can use it twice without reevaluating it. - self.makeTempVar(), - calleePath.get("object") - ); - - let newProperty = calleePath.node.computed - ? explodeViaTempVar(null, calleePath.get("property")) - : calleePath.node.property; - - newArgs.unshift(newObject); - - newCallee = t.memberExpression( - t.memberExpression( - newObject, - newProperty, - calleePath.node.computed - ), - t.identifier("call"), - false - ); - - } else { - newCallee = self.explodeExpression(calleePath); - } - - } else { - newCallee = self.explodeExpression(calleePath); - - if (t.isMemberExpression(newCallee)) { - // If the callee was not previously a MemberExpression, then the - // CallExpression was "unqualified," meaning its `this` object - // should be the global object. If the exploded expression has - // become a MemberExpression (e.g. a context property, probably a - // temporary variable), then we need to force it to be unqualified - // by using the (0, object.property)(...) trick; otherwise, it - // will receive the object of the MemberExpression as its `this` - // object. - newCallee = t.sequenceExpression([ - t.numericLiteral(0), - newCallee - ]); - } - } - - argsPath.forEach(function(argPath) { - newArgs.push(explodeViaTempVar(null, argPath)); - }); - - return finish(t.callExpression( - newCallee, - newArgs - )); - - case "NewExpression": - return finish(t.newExpression( - explodeViaTempVar(null, path.get("callee")), - path.get("arguments").map(function(argPath) { - return explodeViaTempVar(null, argPath); - }) - )); - - case "ObjectExpression": - return finish(t.objectExpression( - path.get("properties").map(function(propPath) { - if (propPath.isObjectProperty()) { - return t.objectProperty( - propPath.node.key, - explodeViaTempVar(null, propPath.get("value")), - propPath.node.computed - ); - } else { - return propPath.node; - } - }) - )); - - case "ArrayExpression": - return finish(t.arrayExpression( - path.get("elements").map(function(elemPath) { - return explodeViaTempVar(null, elemPath); - }) - )); - - case "SequenceExpression": - let lastIndex = expr.expressions.length - 1; - - path.get("expressions").forEach(function(exprPath) { - if (exprPath.key === lastIndex) { - result = self.explodeExpression(exprPath, ignoreResult); - } else { - self.explodeExpression(exprPath, true); - } - }); - - return result; - - case "LogicalExpression": - after = loc(); - - if (!ignoreResult) { - result = self.makeTempVar(); - } - - let left = explodeViaTempVar(result, path.get("left")); - - if (expr.operator === "&&") { - self.jumpIfNot(left, after); - } else { - assert.strictEqual(expr.operator, "||"); - self.jumpIf(left, after); - } - - explodeViaTempVar(result, path.get("right"), ignoreResult); - - self.mark(after); - - return result; - - case "ConditionalExpression": - let elseLoc = loc(); - after = loc(); - let test = self.explodeExpression(path.get("test")); - - self.jumpIfNot(test, elseLoc); - - if (!ignoreResult) { - result = self.makeTempVar(); - } - - explodeViaTempVar(result, path.get("consequent"), ignoreResult); - self.jump(after); - - self.mark(elseLoc); - explodeViaTempVar(result, path.get("alternate"), ignoreResult); - - self.mark(after); - - return result; - - case "UnaryExpression": - return finish(t.unaryExpression( - expr.operator, - // Can't (and don't need to) break up the syntax of the argument. - // Think about delete a[b]. - self.explodeExpression(path.get("argument")), - !!expr.prefix - )); - - case "BinaryExpression": - return finish(t.binaryExpression( - expr.operator, - explodeViaTempVar(null, path.get("left")), - explodeViaTempVar(null, path.get("right")) - )); - - case "AssignmentExpression": - return finish(t.assignmentExpression( - expr.operator, - self.explodeExpression(path.get("left")), - self.explodeExpression(path.get("right")) - )); - - case "UpdateExpression": - return finish(t.updateExpression( - expr.operator, - self.explodeExpression(path.get("argument")), - expr.prefix - )); - - case "YieldExpression": - after = loc(); - let arg = expr.argument && self.explodeExpression(path.get("argument")); - - if (arg && expr.delegate) { - let result = self.makeTempVar(); - - self.emit(t.returnStatement(t.callExpression( - self.contextProperty("delegateYield"), [ - arg, - t.stringLiteral(result.property.name), - after - ] - ))); - - self.mark(after); - - return result; - } - - self.emitAssign(self.contextProperty("next"), after); - self.emit(t.returnStatement(arg || null)); - self.mark(after); - - return self.contextProperty("sent"); - - default: - throw new Error( - "unknown Expression of type " + - JSON.stringify(expr.type)); - } -}; diff --git a/packages/babel-plugin-transform-regenerator/src/hoist.js b/packages/babel-plugin-transform-regenerator/src/hoist.js deleted file mode 100644 index cac505fdfe12..000000000000 --- a/packages/babel-plugin-transform-regenerator/src/hoist.js +++ /dev/null @@ -1,150 +0,0 @@ -/** - * Copyright (c) 2014, Facebook, Inc. - * All rights reserved. - * - * This source code is licensed under the BSD-style license found in the - * https://raw.github.com/facebook/regenerator/master/LICENSE file. An - * additional grant of patent rights can be found in the PATENTS file in - * the same directory. - */ - -import * as t from "babel-types"; -let hasOwn = Object.prototype.hasOwnProperty; - -// The hoist function takes a FunctionExpression or FunctionDeclaration -// and replaces any Declaration nodes in its body with assignments, then -// returns a VariableDeclaration containing just the names of the removed -// declarations. -exports.hoist = function(funPath) { - t.assertFunction(funPath.node); - - let vars = {}; - - function varDeclToExpr(vdec, includeIdentifiers) { - t.assertVariableDeclaration(vdec); - // TODO assert.equal(vdec.kind, "var"); - let exprs = []; - - vdec.declarations.forEach(function(dec) { - // Note: We duplicate 'dec.id' here to ensure that the variable declaration IDs don't - // have the same 'loc' value, since that can make sourcemaps and retainLines behave poorly. - vars[dec.id.name] = t.identifier(dec.id.name); - - if (dec.init) { - exprs.push(t.assignmentExpression( - "=", dec.id, dec.init - )); - } else if (includeIdentifiers) { - exprs.push(dec.id); - } - }); - - if (exprs.length === 0) - return null; - - if (exprs.length === 1) - return exprs[0]; - - return t.sequenceExpression(exprs); - } - - funPath.get("body").traverse({ - VariableDeclaration: { - exit: function(path) { - let expr = varDeclToExpr(path.node, false); - if (expr === null) { - path.remove(); - } else { - // We don't need to traverse this expression any further because - // there can't be any new declarations inside an expression. - path.replaceWith(t.expressionStatement(expr)); - } - - // Since the original node has been either removed or replaced, - // avoid traversing it any further. - path.skip(); - } - }, - - ForStatement: function(path) { - let init = path.node.init; - if (t.isVariableDeclaration(init)) { - path.get("init").replaceWith(varDeclToExpr(init, false)); - } - }, - - ForXStatement: function(path) { - let left = path.get("left"); - if (left.isVariableDeclaration()) { - left.replaceWith(varDeclToExpr(left.node, true)); - } - }, - - FunctionDeclaration: function(path) { - let node = path.node; - vars[node.id.name] = node.id; - - let assignment = t.expressionStatement( - t.assignmentExpression( - "=", - node.id, - t.functionExpression( - node.id, - node.params, - node.body, - node.generator, - node.expression - ) - ) - ); - - if (path.parentPath.isBlockStatement()) { - // Insert the assignment form before the first statement in the - // enclosing block. - path.parentPath.unshiftContainer("body", assignment); - - // Remove the function declaration now that we've inserted the - // equivalent assignment form at the beginning of the block. - path.remove(); - } else { - // If the parent node is not a block statement, then we can just - // replace the declaration with the equivalent assignment form - // without worrying about hoisting it. - path.replaceWith(assignment); - } - - // Don't hoist variables out of inner functions. - path.skip(); - }, - - FunctionExpression: function(path) { - // Don't descend into nested function expressions. - path.skip(); - } - }); - - let paramNames = {}; - funPath.get("params").forEach(function(paramPath) { - let param = paramPath.node; - if (t.isIdentifier(param)) { - paramNames[param.name] = param; - } else { - // Variables declared by destructuring parameter patterns will be - // harmlessly re-declared. - } - }); - - let declarations = []; - - Object.keys(vars).forEach(function(name) { - if (!hasOwn.call(paramNames, name)) { - declarations.push(t.variableDeclarator(vars[name], null)); - } - }); - - if (declarations.length === 0) { - return null; // Be sure to handle this case! - } - - return t.variableDeclaration("var", declarations); -}; diff --git a/packages/babel-plugin-transform-regenerator/src/index.js b/packages/babel-plugin-transform-regenerator/src/index.js index 34fea7a15a98..ba3acbf5b92f 100644 --- a/packages/babel-plugin-transform-regenerator/src/index.js +++ b/packages/babel-plugin-transform-regenerator/src/index.js @@ -8,6 +8,4 @@ * the same directory. */ -export default function () { - return require("./visit"); -} +export default require("regenerator-transform"); diff --git a/packages/babel-plugin-transform-regenerator/src/leap.js b/packages/babel-plugin-transform-regenerator/src/leap.js deleted file mode 100644 index 047a2bf263a4..000000000000 --- a/packages/babel-plugin-transform-regenerator/src/leap.js +++ /dev/null @@ -1,174 +0,0 @@ -/** - * Copyright (c) 2014, Facebook, Inc. - * All rights reserved. - * - * This source code is licensed under the BSD-style license found in the - * https://raw.github.com/facebook/regenerator/master/LICENSE file. An - * additional grant of patent rights can be found in the PATENTS file in - * the same directory. - */ - -import assert from "assert"; -import * as t from "babel-types"; -import { inherits } from "util"; - -function Entry() { - assert.ok(this instanceof Entry); -} - -function FunctionEntry(returnLoc) { - Entry.call(this); - t.assertLiteral(returnLoc); - this.returnLoc = returnLoc; -} - -inherits(FunctionEntry, Entry); -exports.FunctionEntry = FunctionEntry; - -function LoopEntry(breakLoc, continueLoc, label) { - Entry.call(this); - - t.assertLiteral(breakLoc); - t.assertLiteral(continueLoc); - - if (label) { - t.assertIdentifier(label); - } else { - label = null; - } - - this.breakLoc = breakLoc; - this.continueLoc = continueLoc; - this.label = label; -} - -inherits(LoopEntry, Entry); -exports.LoopEntry = LoopEntry; - -function SwitchEntry(breakLoc) { - Entry.call(this); - t.assertLiteral(breakLoc); - this.breakLoc = breakLoc; -} - -inherits(SwitchEntry, Entry); -exports.SwitchEntry = SwitchEntry; - -function TryEntry(firstLoc, catchEntry, finallyEntry) { - Entry.call(this); - - t.assertLiteral(firstLoc); - - if (catchEntry) { - assert.ok(catchEntry instanceof CatchEntry); - } else { - catchEntry = null; - } - - if (finallyEntry) { - assert.ok(finallyEntry instanceof FinallyEntry); - } else { - finallyEntry = null; - } - - // Have to have one or the other (or both). - assert.ok(catchEntry || finallyEntry); - - this.firstLoc = firstLoc; - this.catchEntry = catchEntry; - this.finallyEntry = finallyEntry; -} - -inherits(TryEntry, Entry); -exports.TryEntry = TryEntry; - -function CatchEntry(firstLoc, paramId) { - Entry.call(this); - - t.assertLiteral(firstLoc); - t.assertIdentifier(paramId); - - this.firstLoc = firstLoc; - this.paramId = paramId; -} - -inherits(CatchEntry, Entry); -exports.CatchEntry = CatchEntry; - -function FinallyEntry(firstLoc, afterLoc) { - Entry.call(this); - t.assertLiteral(firstLoc); - t.assertLiteral(afterLoc); - this.firstLoc = firstLoc; - this.afterLoc = afterLoc; -} - -inherits(FinallyEntry, Entry); -exports.FinallyEntry = FinallyEntry; - -function LabeledEntry(breakLoc, label) { - Entry.call(this); - - t.assertLiteral(breakLoc); - t.assertIdentifier(label); - - this.breakLoc = breakLoc; - this.label = label; -} - -inherits(LabeledEntry, Entry); -exports.LabeledEntry = LabeledEntry; - -function LeapManager(emitter) { - assert.ok(this instanceof LeapManager); - - let Emitter = require("./emit").Emitter; - assert.ok(emitter instanceof Emitter); - - this.emitter = emitter; - this.entryStack = [new FunctionEntry(emitter.finalLoc)]; -} - -let LMp = LeapManager.prototype; -exports.LeapManager = LeapManager; - -LMp.withEntry = function(entry, callback) { - assert.ok(entry instanceof Entry); - this.entryStack.push(entry); - try { - callback.call(this.emitter); - } finally { - let popped = this.entryStack.pop(); - assert.strictEqual(popped, entry); - } -}; - -LMp._findLeapLocation = function(property, label) { - for (let i = this.entryStack.length - 1; i >= 0; --i) { - let entry = this.entryStack[i]; - let loc = entry[property]; - if (loc) { - if (label) { - if (entry.label && - entry.label.name === label.name) { - return loc; - } - } else if (entry instanceof LabeledEntry) { - // Ignore LabeledEntry entries unless we are actually breaking to - // a label. - } else { - return loc; - } - } - } - - return null; -}; - -LMp.getBreakLoc = function(label) { - return this._findLeapLocation("breakLoc", label); -}; - -LMp.getContinueLoc = function(label) { - return this._findLeapLocation("continueLoc", label); -}; diff --git a/packages/babel-plugin-transform-regenerator/src/meta.js b/packages/babel-plugin-transform-regenerator/src/meta.js deleted file mode 100644 index dc7ffcdd45a1..000000000000 --- a/packages/babel-plugin-transform-regenerator/src/meta.js +++ /dev/null @@ -1,103 +0,0 @@ -/** - * Copyright (c) 2014, Facebook, Inc. - * All rights reserved. - * - * This source code is licensed under the BSD-style license found in the - * https://raw.github.com/facebook/regenerator/master/LICENSE file. An - * additional grant of patent rights can be found in the PATENTS file in - * the same directory. - */ - -import assert from "assert"; -let m = require("private").makeAccessor(); -import * as t from "babel-types"; -let hasOwn = Object.prototype.hasOwnProperty; - -function makePredicate(propertyName, knownTypes) { - function onlyChildren(node) { - t.assertNode(node); - - // Assume no side effects until we find out otherwise. - let result = false; - - function check(child) { - if (result) { - // Do nothing. - } else if (Array.isArray(child)) { - child.some(check); - } else if (t.isNode(child)) { - assert.strictEqual(result, false); - result = predicate(child); - } - return result; - } - - let keys = t.VISITOR_KEYS[node.type]; - if (keys) { - for (let i = 0; i < keys.length; i++) { - let key = keys[i]; - let child = node[key]; - check(child); - } - } - - return result; - } - - function predicate(node) { - t.assertNode(node); - - let meta = m(node); - if (hasOwn.call(meta, propertyName)) - return meta[propertyName]; - - // Certain types are "opaque," which means they have no side - // effects or leaps and we don't care about their subexpressions. - if (hasOwn.call(opaqueTypes, node.type)) - return meta[propertyName] = false; - - if (hasOwn.call(knownTypes, node.type)) - return meta[propertyName] = true; - - return meta[propertyName] = onlyChildren(node); - } - - predicate.onlyChildren = onlyChildren; - - return predicate; -} - -let opaqueTypes = { - FunctionExpression: true -}; - -// These types potentially have side effects regardless of what side -// effects their subexpressions have. -let sideEffectTypes = { - CallExpression: true, // Anything could happen! - ForInStatement: true, // Modifies the key variable. - UnaryExpression: true, // Think delete. - BinaryExpression: true, // Might invoke .toString() or .valueOf(). - AssignmentExpression: true, // Side-effecting by definition. - UpdateExpression: true, // Updates are essentially assignments. - NewExpression: true // Similar to CallExpression. -}; - -// These types are the direct cause of all leaps in control flow. -let leapTypes = { - YieldExpression: true, - BreakStatement: true, - ContinueStatement: true, - ReturnStatement: true, - ThrowStatement: true -}; - -// All leap types are also side effect types. -for (let type in leapTypes) { - if (hasOwn.call(leapTypes, type)) { - sideEffectTypes[type] = leapTypes[type]; - } -} - -exports.hasSideEffects = makePredicate("hasSideEffects", sideEffectTypes); -exports.containsLeap = makePredicate("containsLeap", leapTypes); diff --git a/packages/babel-plugin-transform-regenerator/src/util.js b/packages/babel-plugin-transform-regenerator/src/util.js deleted file mode 100644 index 78bfa0f28b10..000000000000 --- a/packages/babel-plugin-transform-regenerator/src/util.js +++ /dev/null @@ -1,23 +0,0 @@ -/** - * Copyright (c) 2014, Facebook, Inc. - * All rights reserved. - * - * This source code is licensed under the BSD-style license found in the - * https://raw.github.com/facebook/regenerator/master/LICENSE file. An - * additional grant of patent rights can be found in the PATENTS file in - * the same directory. - */ - -import * as t from "babel-types"; - -export function runtimeProperty(name) { - return t.memberExpression( - t.identifier("regeneratorRuntime"), - t.identifier(name), - false - ); -} - -export function isReference(path) { - return path.isReferenced() || path.parentPath.isAssignmentExpression({ left: path.node }); -} diff --git a/packages/babel-plugin-transform-regenerator/src/visit.js b/packages/babel-plugin-transform-regenerator/src/visit.js deleted file mode 100644 index 8d96f2b40495..000000000000 --- a/packages/babel-plugin-transform-regenerator/src/visit.js +++ /dev/null @@ -1,269 +0,0 @@ -/** - * Copyright (c) 2014, Facebook, Inc. - * All rights reserved. - * - * This source code is licensed under the BSD-style license found in the - * https://raw.github.com/facebook/regenerator/master/LICENSE file. An - * additional grant of patent rights can be found in the PATENTS file in - * the same directory. - */ - -import assert from "assert"; -import * as t from "babel-types"; -import { hoist } from "./hoist"; -import { Emitter } from "./emit"; -import * as util from "./util"; - -let getMarkInfo = require("private").makeAccessor(); - -exports.visitor = { - Function: { - exit: function(path, state) { - let node = path.node; - - if (node.generator) { - if (node.async) { - // Async generator - if (state.opts.asyncGenerators === false) return; - } else { - // Plain generator - if (state.opts.generators === false) return; - } - } else if (node.async) { - // Async function - if (state.opts.async === false) return; - } else { - // Not a generator or async function. - return; - } - - let contextId = path.scope.generateUidIdentifier("context"); - let argsId = path.scope.generateUidIdentifier("args"); - - path.ensureBlock(); - let bodyBlockPath = path.get("body"); - - if (node.async) { - bodyBlockPath.traverse(awaitVisitor); - } - - bodyBlockPath.traverse(functionSentVisitor, { - context: contextId - }); - - let outerBody = []; - let innerBody = []; - - bodyBlockPath.get("body").forEach(function(childPath) { - let node = childPath.node; - if (node && node._blockHoist != null) { - outerBody.push(node); - } else { - innerBody.push(node); - } - }); - - if (outerBody.length > 0) { - // Only replace the inner body if we actually hoisted any statements - // to the outer body. - bodyBlockPath.node.body = innerBody; - } - - let outerFnExpr = getOuterFnExpr(path); - // Note that getOuterFnExpr has the side-effect of ensuring that the - // function has a name (so node.id will always be an Identifier), even - // if a temporary name has to be synthesized. - t.assertIdentifier(node.id); - let innerFnId = t.identifier(node.id.name + "$"); - - // Turn all declarations into vars, and replace the original - // declarations with equivalent assignment expressions. - let vars = hoist(path); - - let didRenameArguments = renameArguments(path, argsId); - if (didRenameArguments) { - vars = vars || t.variableDeclaration("var", []); - vars.declarations.push(t.variableDeclarator( - argsId, t.identifier("arguments") - )); - } - - let emitter = new Emitter(contextId); - emitter.explode(path.get("body")); - - if (vars && vars.declarations.length > 0) { - outerBody.push(vars); - } - - let wrapArgs = [ - emitter.getContextFunction(innerFnId), - // Async functions that are not generators don't care about the - // outer function because they don't need it to be marked and don't - // inherit from its .prototype. - node.generator ? outerFnExpr : t.nullLiteral(), - t.thisExpression() - ]; - - let tryLocsList = emitter.getTryLocsList(); - if (tryLocsList) { - wrapArgs.push(tryLocsList); - } - - let wrapCall = t.callExpression( - util.runtimeProperty(node.async ? "async" : "wrap"), - wrapArgs - ); - - outerBody.push(t.returnStatement(wrapCall)); - node.body = t.blockStatement(outerBody); - - let wasGeneratorFunction = node.generator; - if (wasGeneratorFunction) { - node.generator = false; - } - - if (node.async) { - node.async = false; - } - - if (wasGeneratorFunction && t.isExpression(node)) { - path.replaceWith(t.callExpression(util.runtimeProperty("mark"), [node])); - } - - // Generators are processed in 'exit' handlers so that regenerator only has to run on - // an ES5 AST, but that means traversal will not pick up newly inserted references - // to things like 'regeneratorRuntime'. To avoid this, we explicitly requeue. - path.requeue(); - } - } -}; - -// Given a NodePath for a Function, return an Expression node that can be -// used to refer reliably to the function object from inside the function. -// This expression is essentially a replacement for arguments.callee, with -// the key advantage that it works in strict mode. -function getOuterFnExpr(funPath) { - let node = funPath.node; - t.assertFunction(node); - - if (!node.id) { - // Default-exported function declarations, and function expressions may not - // have a name to reference, so we explicitly add one. - node.id = funPath.scope.parent.generateUidIdentifier("callee"); - } - - if (node.generator && // Non-generator functions don't need to be marked. - t.isFunctionDeclaration(node)) { - let pp = funPath.findParent(function (path) { - return path.isProgram() || path.isBlockStatement(); - }); - - if (!pp) { - return node.id; - } - - let markDecl = getRuntimeMarkDecl(pp); - let markedArray = markDecl.declarations[0].id; - let funDeclIdArray = markDecl.declarations[0].init.callee.object; - t.assertArrayExpression(funDeclIdArray); - - let index = funDeclIdArray.elements.length; - funDeclIdArray.elements.push(node.id); - - return t.memberExpression( - markedArray, - t.numericLiteral(index), - true - ); - } - - return node.id; -} - -function getRuntimeMarkDecl(blockPath) { - let block = blockPath.node; - assert.ok(Array.isArray(block.body)); - - let info = getMarkInfo(block); - if (info.decl) { - return info.decl; - } - - info.decl = t.variableDeclaration("var", [ - t.variableDeclarator( - blockPath.scope.generateUidIdentifier("marked"), - t.callExpression( - t.memberExpression( - t.arrayExpression([]), - t.identifier("map"), - false - ), - [util.runtimeProperty("mark")] - ) - ) - ]); - - blockPath.unshiftContainer("body", info.decl); - - return info.decl; -} - -function renameArguments(funcPath, argsId) { - let state = { - didRenameArguments: false, - argsId: argsId - }; - - funcPath.traverse(argumentsVisitor, state); - - // If the traversal replaced any arguments references, then we need to - // alias the outer function's arguments binding (be it the implicit - // arguments object or some other parameter or variable) to the variable - // named by argsId. - return state.didRenameArguments; -} - -let argumentsVisitor = { - "FunctionExpression|FunctionDeclaration": function(path) { - path.skip(); - }, - - Identifier: function(path, state) { - if (path.node.name === "arguments" && util.isReference(path)) { - path.replaceWith(state.argsId); - state.didRenameArguments = true; - } - } -}; - -let functionSentVisitor = { - MetaProperty(path) { - let { node } = path; - - if (node.meta.name === "function" && node.property.name === "sent") { - path.replaceWith(t.memberExpression(this.context, t.identifier("_sent"))); - } - } -}; - -let awaitVisitor = { - Function: function(path) { - path.skip(); // Don't descend into nested function scopes. - }, - - AwaitExpression: function(path) { - // Convert await expressions to yield expressions. - let argument = path.node.argument; - - // Transforming `await x` to `yield regeneratorRuntime.awrap(x)` - // causes the argument to be wrapped in such a way that the runtime - // can distinguish between awaited and merely yielded values. - path.replaceWith(t.yieldExpression( - t.callExpression( - util.runtimeProperty("awrap"), - [argument] - ), - false - )); - } -}; diff --git a/packages/babel-plugin-transform-runtime/README.md b/packages/babel-plugin-transform-runtime/README.md index 0839da1b0cab..ff42d7e9af98 100644 --- a/packages/babel-plugin-transform-runtime/README.md +++ b/packages/babel-plugin-transform-runtime/README.md @@ -1,28 +1,38 @@ # babel-plugin-transform-runtime -Externalise references to helpers and builtins, automatically polyfilling your code without polluting globals. +> Externalise references to helpers and builtins, automatically polyfilling your code without polluting globals. (This plugin is recommended in a library/tool) + +NOTE: Instance methods such as `"foobar".includes("foo")` will not work since that would require modification of existing builtins (Use [`babel-polyfill`](http://babeljs.io/docs/usage/polyfill) for that). ## Why? Babel uses very small helpers for common functions such as `_extend`. By default this will be added to every file that requires it. This duplication is sometimes unnecessary, especially when your application is spread out over multiple files. -This is where the runtime transformer plugin comes in: all of the helpers will reference the module babel-runtime to avoid duplication across your compiled output. The runtime will be compiled into your build. +This is where the `transform-runtime` plugin comes in: all of the helpers will reference the module `babel-runtime` to avoid duplication across your compiled output. The runtime will be compiled into your build. -Another purpose of this transformer is to create a sandboxed environment for your code. If you use [babel-polyfill](https://babeljs.io/docs/usage/polyfill/) and the built-ins it provides such as `Promise`, `Set` and `Map`, those will pollute the global scope. While this might be ok for an app or a command line tool, it becomes a problem if your code is a library which you intend to publish for others to use or if you can't exactly control the environment in which your code will run. +Another purpose of this transformer is to create a sandboxed environment for your code. If you use [babel-polyfill](http://babeljs.io/docs/usage/polyfill/) and the built-ins it provides such as `Promise`, `Set` and `Map`, those will pollute the global scope. While this might be ok for an app or a command line tool, it becomes a problem if your code is a library which you intend to publish for others to use or if you can't exactly control the environment in which your code will run. The transformer will alias these built-ins to `core-js` so you can use them seamlessly without having to require the polyfill. -See the technical details section for more information on how this works and the types of transformations that occur. +See the [technical details](#technical-details) section for more information on how this works and the types of transformations that occur. ## Installation +**NOTE - Production vs. development dependencies** + +In most cases, you should install `babel-plugin-transform-runtime` as a development dependency (with `--save-dev`). + +```sh +npm install --save-dev babel-plugin-transform-runtime +``` + +and `babel-runtime` as a production dependency (with `--save`). + ```sh -$ npm install babel-plugin-transform-runtime +npm install --save babel-runtime ``` -It is also recommended you install the `babel-runtime` package as a -runtime dependency, if you haven't already, as the transformed code will -require that package. See the examples below for more details. +The transformation plugin is typically used only in development, but the runtime itself will be depended on by your deployed/published code. See the examples below for more details. ## Usage @@ -52,7 +62,7 @@ Add the following line to your `.babelrc` file: ### Via CLI ```sh -$ babel --plugins transform-runtime script.js +babel --plugins transform-runtime script.js ``` ### Via Node API diff --git a/packages/babel-plugin-transform-strict-mode/README.md b/packages/babel-plugin-transform-strict-mode/README.md index 638d1f83a53b..d6c258d3008a 100644 --- a/packages/babel-plugin-transform-strict-mode/README.md +++ b/packages/babel-plugin-transform-strict-mode/README.md @@ -1,16 +1,31 @@ # babel-plugin-transform-strict-mode -Add the `"use strict";` directive to the top of your files if it is not there -already. +> This plugin places a `"use strict";` directive at the top of all files to enable [strict mode](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Strict_mode). -> This plugin may be enabled via `babel-plugin-transform-es2015-modules-commonjs`. -> If you wish to disable it you can either turn `strict` off or pass -> `strictMode: false` as an option to the commonjs transform. +This plugin may be enabled via `babel-plugin-transform-es2015-modules-commonjs`. +If you wish to disable it you can either turn `strict` off or pass +`strictMode: false` as an option to the commonjs transform. + +## Example + +**In** + +```javascript +foo(); +``` + +**Out** + +```javascript +"use strict"; + +foo(); +``` ## Installation ```sh -$ npm install babel-plugin-transform-strict-mode +npm install --save-dev babel-plugin-transform-strict-mode ``` ## Usage @@ -38,7 +53,7 @@ $ npm install babel-plugin-transform-strict-mode ### Via CLI ```sh -$ babel --plugins transform-strict-mode script.js +babel --plugins transform-strict-mode script.js ``` ### Via Node API diff --git a/packages/babel-plugin-undeclared-variables-check/README.md b/packages/babel-plugin-undeclared-variables-check/README.md index 8051e67a124e..5bdf1b783aff 100644 --- a/packages/babel-plugin-undeclared-variables-check/README.md +++ b/packages/babel-plugin-undeclared-variables-check/README.md @@ -1,11 +1,32 @@ # babel-plugin-undeclared-variables-check -Throw a compile-time error on references to undeclared variables +> This plugin throws a compile-time error on references to undeclared variables. + +## Example + +**In** + +```javascript +function foo() {} +foo(); +bar(); +``` + +**Out** + +``` +ReferenceError: stdin: Line 3: Reference to undeclared variable "bar" - did you mean "foo"? + 1 | function foo() {} + 2 | foo(); +> 3 | bar(); + | ^ + 4 | +``` ## Installation ```sh -$ npm install babel-plugin-undeclared-variables-check +npm install --save-dev babel-plugin-undeclared-variables-check ``` ## Usage @@ -23,7 +44,7 @@ $ npm install babel-plugin-undeclared-variables-check ### Via CLI ```sh -$ babel --plugins undeclared-variables-check script.js +babel --plugins undeclared-variables-check script.js ``` ### Via Node API diff --git a/packages/babel-polyfill/package.json b/packages/babel-polyfill/package.json index c674fb21c6a2..15cd6f4379de 100644 --- a/packages/babel-polyfill/package.json +++ b/packages/babel-polyfill/package.json @@ -1,6 +1,6 @@ { "name": "babel-polyfill", - "version": "6.16.0", + "version": "6.20.0", "description": "Provides polyfills necessary for a full ES2015+ environment", "author": "Sebastian McKenzie ", "homepage": "https://babeljs.io/", @@ -9,7 +9,7 @@ "main": "lib/index.js", "dependencies": { "core-js": "^2.4.0", - "babel-runtime": "^6.9.1", - "regenerator-runtime": "^0.9.5" + "babel-runtime": "^6.20.0", + "regenerator-runtime": "^0.10.0" } } diff --git a/packages/babel-preset-es2015/README.md b/packages/babel-preset-es2015/README.md index 588606a944c5..dacd924c737c 100644 --- a/packages/babel-preset-es2015/README.md +++ b/packages/babel-preset-es2015/README.md @@ -5,7 +5,7 @@ ## Install ```sh -$ npm install --save-dev babel-preset-es2015 +npm install --save-dev babel-preset-es2015 ``` ## Usage @@ -23,7 +23,7 @@ $ npm install --save-dev babel-preset-es2015 ### Via CLI ```sh -$ babel script.js --presets es2015 +babel script.js --presets es2015 ``` ### Via Node API @@ -37,18 +37,29 @@ require("babel-core").transform("code", { ## Options * `loose` - Enable "loose" transformations for any plugins in this preset that allow them (Disabled by default). -* `modules` - Enable transformation of ES6 module syntax to another module type (Enabled by default to "commonjs"). +* `modules` - Enable transformation of ES6 module syntax to another module type (Enabled by default to `"commonjs"`). * Can be `false` to not transform modules, or one of `["amd", "umd", "systemjs", "commonjs"]` +* `spec` - Enable "spec" transformations for any plugins in this preset that allow them (Disabled by default) -``` +```js +{ + presets: [ + ["es2015", { "loose": true }] + ] +} +{ + presets: [ + ["es2015", { "modules": false }] + ] +} { presets: [ - ["es2015", {"loose": true, "modules": "amd"}] + ["es2015", { "loose": true, "modules": false }] ] } { presets: [ - ["es2015", {"loose": true, "modules": false}] + ["es2015", { "spec": true }] ] } ``` diff --git a/packages/babel-preset-es2016/README.md b/packages/babel-preset-es2016/README.md index ea9086b5bbbf..ef42f7b0bd3b 100644 --- a/packages/babel-preset-es2016/README.md +++ b/packages/babel-preset-es2016/README.md @@ -5,7 +5,7 @@ ## Install ```sh -$ npm install --save-dev babel-preset-es2016 +npm install --save-dev babel-preset-es2016 ``` ## Usage @@ -23,7 +23,7 @@ $ npm install --save-dev babel-preset-es2016 ### Via CLI ```sh -$ babel script.js --presets es2016 +babel script.js --presets es2016 ``` ### Via Node API diff --git a/packages/babel-preset-es2017/README.md b/packages/babel-preset-es2017/README.md index a8498dc5f998..450c214ea204 100644 --- a/packages/babel-preset-es2017/README.md +++ b/packages/babel-preset-es2017/README.md @@ -5,7 +5,7 @@ ## Install ```sh -$ npm install --save-dev babel-preset-es2017 +npm install --save-dev babel-preset-es2017 ``` ## Usage @@ -23,7 +23,7 @@ $ npm install --save-dev babel-preset-es2017 ### Via CLI ```sh -$ babel script.js --presets es2017 +babel script.js --presets es2017 ``` ### Via Node API diff --git a/packages/babel-preset-latest/README.md b/packages/babel-preset-latest/README.md index d01635f7c6db..f46761d1aa60 100644 --- a/packages/babel-preset-latest/README.md +++ b/packages/babel-preset-latest/README.md @@ -5,7 +5,7 @@ ## Install ```sh -$ npm install --save-dev babel-preset-latest +npm install --save-dev babel-preset-latest ``` ## Usage @@ -23,7 +23,7 @@ $ npm install --save-dev babel-preset-latest ### Via CLI ```sh -$ babel script.js --presets latest +babel script.js --presets latest ``` ### Via Node API @@ -33,3 +33,33 @@ require("babel-core").transform("code", { presets: ["latest"] }); ``` + +### Options + +- `es2015`: Optionally not run any plugins from this preset (defaults to true) +- `es2016`: Optionally not run any plugins from this preset (defaults to true) +- `es2017`: Optionally not run any plugins from this preset (defaults to true) + +```js +{ + "presets": [ + ["latest", { + "es2015": false // defaults to true + }] + ] +} +``` + +You can also pass options down to the `es2015` preset. + +```js +{ + "presets": [ + ["latest", { + "es2015": { + "modules": false + } + }] + ] +} +``` diff --git a/packages/babel-preset-react/README.md b/packages/babel-preset-react/README.md index f09fc56642de..827160b2469d 100644 --- a/packages/babel-preset-react/README.md +++ b/packages/babel-preset-react/README.md @@ -5,7 +5,7 @@ ## Install ```sh -$ npm install --save-dev babel-preset-react +npm install --save-dev babel-preset-react ``` ## Usage @@ -23,7 +23,7 @@ $ npm install --save-dev babel-preset-react ### Via CLI ```sh -$ babel script.js --presets react +babel script.js --presets react ``` ### Via Node API diff --git a/packages/babel-preset-stage-0/README.md b/packages/babel-preset-stage-0/README.md index 001e55e3b04a..5b0236d8ceeb 100644 --- a/packages/babel-preset-stage-0/README.md +++ b/packages/babel-preset-stage-0/README.md @@ -5,7 +5,7 @@ ## Install ```sh -$ npm install --save-dev babel-preset-stage-0 +npm install --save-dev babel-preset-stage-0 ``` ## Usage @@ -23,7 +23,7 @@ $ npm install --save-dev babel-preset-stage-0 ### Via CLI ```sh -$ babel script.js --presets stage-0 +babel script.js --presets stage-0 ``` ### Via Node API diff --git a/packages/babel-preset-stage-1/README.md b/packages/babel-preset-stage-1/README.md index 9b50a4be24d8..d0af0ffd584e 100644 --- a/packages/babel-preset-stage-1/README.md +++ b/packages/babel-preset-stage-1/README.md @@ -5,7 +5,7 @@ ## Install ```sh -$ npm install --save-dev babel-preset-stage-1 +npm install --save-dev babel-preset-stage-1 ``` ## Usage @@ -23,7 +23,7 @@ $ npm install --save-dev babel-preset-stage-1 ### Via CLI ```sh -$ babel script.js --presets stage-1 +babel script.js --presets stage-1 ``` ### Via Node API diff --git a/packages/babel-preset-stage-2/README.md b/packages/babel-preset-stage-2/README.md index aeadc27b7021..1c6a5f900e5b 100644 --- a/packages/babel-preset-stage-2/README.md +++ b/packages/babel-preset-stage-2/README.md @@ -5,7 +5,7 @@ ## Install ```sh -$ npm install --save-dev babel-preset-stage-2 +npm install --save-dev babel-preset-stage-2 ``` ## Usage @@ -23,7 +23,7 @@ $ npm install --save-dev babel-preset-stage-2 ### Via CLI ```sh -$ babel script.js --presets stage-2 +babel script.js --presets stage-2 ``` ### Via Node API diff --git a/packages/babel-preset-stage-3/README.md b/packages/babel-preset-stage-3/README.md index a3807019a840..fd29e4670ec1 100644 --- a/packages/babel-preset-stage-3/README.md +++ b/packages/babel-preset-stage-3/README.md @@ -5,7 +5,7 @@ ## Install ```sh -$ npm install --save-dev babel-preset-stage-3 +npm install --save-dev babel-preset-stage-3 ``` ## Usage @@ -23,7 +23,7 @@ $ npm install --save-dev babel-preset-stage-3 ### Via CLI ```sh -$ babel script.js --presets stage-3 +babel script.js --presets stage-3 ``` ### Via Node API diff --git a/packages/babel-register/README.md b/packages/babel-register/README.md index 13f79b2d97ba..0abbe9b81fb4 100644 --- a/packages/babel-register/README.md +++ b/packages/babel-register/README.md @@ -1,11 +1,16 @@ # babel-register -The require hook will bind itself to node's require and automatically compile files on the fly. +> The require hook will bind itself to node's require and automatically compile files on the fly. + +One of the ways you can use Babel is through the require hook. The require hook +will bind itself to node's `require` and automatically compile files on the +fly. This is equivalent to CoffeeScript's +[coffee-script/register](http://coffeescript.org/documentation/docs/register.html). ## Install -``` -$ npm install babel-register +```sh +npm install babel-register --save-dev ``` ## Usage @@ -14,6 +19,79 @@ $ npm install babel-register require("babel-register"); ``` -All subsequent files required by node with the extensions `.es6`, `.es`, `.jsx` and `.js` will be transformed by Babel. +All subsequent files required by node with the extensions `.es6`, `.es`, `.jsx` +and `.js` will be transformed by Babel. + +
+

Polyfill not included

+

+ You must include the polyfill separately when using features that require it, like generators. +

+
+ +### Ignores `node_modules` by default -See [documentation](http://babeljs.io/docs/usage/require/) for details. +**NOTE:** By default all requires to `node_modules` will be ignored. You can +override this by passing an ignore regex via: + +```js +require("babel-register")({ + // This will override `node_modules` ignoring - you can alternatively pass + // an array of strings to be explicitly matched or a regex / glob + ignore: false +}); +``` + +## Specifying options + +```javascript +require("babel-register")({ + // Optional ignore regex - if any filenames **do** match this regex then they + // aren't compiled. + ignore: /regex/, + + // Ignore can also be specified as a function. + ignore: function(filename) { + if (filename === '/path/to/es6-file.js') { + return false; + } else { + return true; + } + }, + + // Optional only regex - if any filenames **don't** match this regex then they + // aren't compiled + only: /my_es6_folder/, + + // Setting this will remove the currently hooked extensions of .es6, `.es`, `.jsx` + // and .js so you'll have to add them back if you want them to be used again. + extensions: [".es6", ".es", ".jsx", ".js"] +}); +``` + +You can pass in all other [options](/docs/usage/options/#options) as well, including `plugins` and `presets`. But note that the closest [`.babelrc`](/docs/usage/babelrc/) to each file still applies, and takes precedence over any options you pass in here. + +## Environment variables + +By default `babel-node` and `babel-register` will save to a json cache in your +temporary directory. + +This will heavily improve with the startup and compilation of your files. There +are however scenarios where you want to change this behaviour and there are +environment variables exposed to allow you to do this. + +### BABEL_CACHE_PATH + +Specify a different cache location. + +```sh +BABEL_CACHE_PATH=/foo/my-cache.json babel-node script.js +``` + +### BABEL_DISABLE_CACHE + +Disable the cache. + +```sh +BABEL_DISABLE_CACHE=1 babel-node script.js +``` diff --git a/packages/babel-runtime/package.json b/packages/babel-runtime/package.json index 05c419af1793..73eb96ec151a 100644 --- a/packages/babel-runtime/package.json +++ b/packages/babel-runtime/package.json @@ -1,13 +1,13 @@ { "name": "babel-runtime", - "version": "6.18.0", + "version": "6.20.0", "description": "babel selfContained runtime", "license": "MIT", "repository": "https://github.com/babel/babel/tree/master/packages/babel-runtime", "author": "Sebastian McKenzie ", "dependencies": { "core-js": "^2.4.0", - "regenerator-runtime": "^0.9.5" + "regenerator-runtime": "^0.10.0" }, "devDependencies": { "babel-helpers": "^6.6.0", diff --git a/packages/babel-template/README.md b/packages/babel-template/README.md index 77f73a8c2d7a..9eeb0adf3f62 100644 --- a/packages/babel-template/README.md +++ b/packages/babel-template/README.md @@ -7,7 +7,7 @@ In computer science, this is known as an implementation of quasiquotes. ## Install ```sh -$ npm install babel-template +npm install --save-dev babel-template ``` ## Usage diff --git a/packages/babel-traverse/package.json b/packages/babel-traverse/package.json index 3aea616765f9..01bfc59f3975 100644 --- a/packages/babel-traverse/package.json +++ b/packages/babel-traverse/package.json @@ -1,6 +1,6 @@ { "name": "babel-traverse", - "version": "6.18.0", + "version": "6.20.0", "description": "The Babel Traverse module maintains the overall tree state, and is responsible for replacing, removing, and adding nodes", "author": "Sebastian McKenzie ", "homepage": "https://babeljs.io/", @@ -8,10 +8,10 @@ "repository": "https://github.com/babel/babel/tree/master/packages/babel-traverse", "main": "lib/index.js", "dependencies": { - "babel-code-frame": "^6.16.0", + "babel-code-frame": "^6.20.0", "babel-messages": "^6.8.0", - "babel-runtime": "^6.9.0", - "babel-types": "^6.18.0", + "babel-runtime": "^6.20.0", + "babel-types": "^6.20.0", "babylon": "^6.11.0", "debug": "^2.2.0", "globals": "^9.0.0", diff --git a/packages/babel-traverse/src/cache.js b/packages/babel-traverse/src/cache.js index 08a771a5fc3f..d1a3c265d4f9 100644 --- a/packages/babel-traverse/src/cache.js +++ b/packages/babel-traverse/src/cache.js @@ -2,6 +2,14 @@ export let path = new WeakMap(); export let scope = new WeakMap(); export function clear() { - path = new WeakMap(); - scope = new WeakMap(); + clearPath(); + clearScope(); +} + +export function clearPath() { + path = new WeakMap; +} + +export function clearScope() { + scope = new WeakMap; } diff --git a/packages/babel-traverse/src/index.js b/packages/babel-traverse/src/index.js index 6c1ac706503e..6a3d4660a4b7 100644 --- a/packages/babel-traverse/src/index.js +++ b/packages/babel-traverse/src/index.js @@ -98,6 +98,9 @@ traverse.clearCache = function() { cache.clear(); }; +traverse.clearCache.clearPath = cache.clearPath; +traverse.clearCache.clearScope = cache.clearScope; + traverse.copyCache = function(source, destination) { if (cache.path.has(source)) { cache.path.set(destination, cache.path.get(source)); diff --git a/packages/babel-traverse/src/path/ancestry.js b/packages/babel-traverse/src/path/ancestry.js index e7c321709305..35fb7b34359c 100644 --- a/packages/babel-traverse/src/path/ancestry.js +++ b/packages/babel-traverse/src/path/ancestry.js @@ -175,6 +175,20 @@ export function getAncestry() { return paths; } +/** + * A helper to find if `this` path is an ancestor of @param maybeDescendant + */ +export function isAncestor(maybeDescendant) { + return maybeDescendant.isDescendant(this); +} + +/** + * A helper to find if `this` path is a descendant of @param maybeAncestor + */ +export function isDescendant(maybeAncestor) { + return !!this.findParent((parent) => parent === maybeAncestor); +} + export function inType() { let path = this; while (path) { diff --git a/packages/babel-traverse/src/path/evaluation.js b/packages/babel-traverse/src/path/evaluation.js index ef478103b1fb..3b41b188c6ce 100644 --- a/packages/babel-traverse/src/path/evaluation.js +++ b/packages/babel-traverse/src/path/evaluation.js @@ -173,6 +173,10 @@ export function evaluate(): { confident: boolean; value: any } { return deopt(binding.path); } + if (binding && path.node.start < binding.path.node.end) { + return deopt(binding.path); + } + if (binding && binding.hasValue) { return binding.value; } else { diff --git a/packages/babel-traverse/src/path/family.js b/packages/babel-traverse/src/path/family.js index b27538edafb9..f7a630d0a79c 100644 --- a/packages/babel-traverse/src/path/family.js +++ b/packages/babel-traverse/src/path/family.js @@ -125,3 +125,64 @@ export function getBindingIdentifiers(duplicates?) { export function getOuterBindingIdentifiers(duplicates?) { return t.getOuterBindingIdentifiers(this.node, duplicates); } + +// original source - https://github.com/babel/babel/blob/master/packages/babel-types/src/retrievers.js +// path.getBindingIdentifiers returns nodes where the following re-implementation +// returns paths +export function getBindingIdentifierPaths(duplicates = false, outerOnly = false) { + let path = this; + let search = [].concat(path); + let ids = Object.create(null); + + while (search.length) { + let id = search.shift(); + if (!id) continue; + if (!id.node) continue; + + let keys = t.getBindingIdentifiers.keys[id.node.type]; + + if (id.isIdentifier()) { + if (duplicates) { + let _ids = ids[id.node.name] = ids[id.node.name] || []; + _ids.push(id); + } else { + ids[id.node.name] = id; + } + continue; + } + + if (id.isExportDeclaration()) { + const declaration = id.get("declaration"); + if (declaration.isDeclaration()) { + search.push(declaration); + } + continue; + } + + if (outerOnly) { + if (id.isFunctionDeclaration()) { + search.push(id.get("id")); + continue; + } + if (id.isFunctionExpression()) { + continue; + } + } + + if (keys) { + for (let i = 0; i < keys.length; i++) { + let key = keys[i]; + let child = id.get(key); + if (Array.isArray(child) || child.node) { + search = search.concat(child); + } + } + } + } + + return ids; +} + +export function getOuterBindingIdentifierPaths(duplicates?) { + return this.getBindingIdentifierPaths(duplicates, true); +} diff --git a/packages/babel-traverse/src/path/lib/removal-hooks.js b/packages/babel-traverse/src/path/lib/removal-hooks.js index fc232871e5f4..e016c712f325 100644 --- a/packages/babel-traverse/src/path/lib/removal-hooks.js +++ b/packages/babel-traverse/src/path/lib/removal-hooks.js @@ -68,11 +68,11 @@ export let hooks = [ function (self, parent) { if ( - (parent.isIfStatement() && (self.key === 'consequent' || self.key === 'alternate')) || - (parent.isLoop() && self.key === 'body') + (parent.isIfStatement() && (self.key === "consequent" || self.key === "alternate")) || + (parent.isLoop() && self.key === "body") ) { self.replaceWith({ - type: 'BlockStatement', + type: "BlockStatement", body: [] }); return true; diff --git a/packages/babel-traverse/src/scope/index.js b/packages/babel-traverse/src/scope/index.js index 5c5395877291..83e80df926a8 100644 --- a/packages/babel-traverse/src/scope/index.js +++ b/packages/babel-traverse/src/scope/index.js @@ -37,6 +37,36 @@ function getCache(path, parentScope, self) { } } +// Recursively gathers the identifying names of a node. +function gatherNodeParts(node: Object, parts: Array) { + if (t.isModuleDeclaration(node)) { + if (node.source) { + gatherNodeParts(node.source, parts); + } else if (node.specifiers && node.specifiers.length) { + for (let specifier of (node.specifiers: Array)) { + gatherNodeParts(specifier, parts); + } + } else if (node.declaration) { + gatherNodeParts(node.declaration, parts); + } + } else if (t.isModuleSpecifier(node)) { + gatherNodeParts(node.local, parts); + } else if (t.isMemberExpression(node)) { + gatherNodeParts(node.object, parts); + gatherNodeParts(node.property, parts); + } else if (t.isIdentifier(node)) { + parts.push(node.name); + } else if (t.isLiteral(node)) { + parts.push(node.value); + } else if (t.isCallExpression(node)) { + gatherNodeParts(node.callee, parts); + } else if (t.isObjectExpression(node) || t.isObjectPattern(node)) { + for (let prop of (node.properties: Array)) { + gatherNodeParts(prop.key || prop.argument, parts); + } + } +} + // let collectorVisitor = { @@ -254,38 +284,8 @@ export default class Scope { node = node.key; } - let parts = []; - - let add = function (node) { - if (t.isModuleDeclaration(node)) { - if (node.source) { - add(node.source); - } else if (node.specifiers && node.specifiers.length) { - for (let specifier of (node.specifiers: Array)) { - add(specifier); - } - } else if (node.declaration) { - add(node.declaration); - } - } else if (t.isModuleSpecifier(node)) { - add(node.local); - } else if (t.isMemberExpression(node)) { - add(node.object); - add(node.property); - } else if (t.isIdentifier(node)) { - parts.push(node.name); - } else if (t.isLiteral(node)) { - parts.push(node.value); - } else if (t.isCallExpression(node)) { - add(node.callee); - } else if (t.isObjectExpression(node) || t.isObjectPattern(node)) { - for (let prop of (node.properties: Array)) { - add(prop.key || prop.argument); - } - } - }; - - add(node); + const parts = []; + gatherNodeParts(node, parts); let id = parts.join("$"); id = id.replace(/^_/, "") || defaultName || "ref"; diff --git a/packages/babel-traverse/src/scope/lib/renamer.js b/packages/babel-traverse/src/scope/lib/renamer.js index 50da4ea40d6d..b8c1fb3b9c3f 100644 --- a/packages/babel-traverse/src/scope/lib/renamer.js +++ b/packages/babel-traverse/src/scope/lib/renamer.js @@ -42,7 +42,7 @@ export default class Renamer { let isDefault = exportDeclar.isExportDefaultDeclaration(); if (isDefault && (parentDeclar.isFunctionDeclaration() || - parentDeclar.isClassDeclaration())&& !parentDeclar.node.id) { + parentDeclar.isClassDeclaration()) && !parentDeclar.node.id) { // Ensure that default class and function exports have a name so they have a identifier to // reference from the export specifier list. parentDeclar.node.id = parentDeclar.scope.generateUidIdentifier("default"); diff --git a/packages/babel-traverse/test/ancestry.js b/packages/babel-traverse/test/ancestry.js new file mode 100644 index 000000000000..43e09859ef66 --- /dev/null +++ b/packages/babel-traverse/test/ancestry.js @@ -0,0 +1,65 @@ +let traverse = require("../lib").default; +let assert = require("assert"); +let parse = require("babylon").parse; + +describe("path/ancestry", function () { + describe("isAncestor", function () { + let ast = parse("var a = 1; 'a';"); + + it("returns true if ancestor", function() { + let paths = []; + traverse(ast, { + "Program|NumericLiteral"(path) { + paths.push(path); + }, + }); + + let [ programPath, numberPath ] = paths; + + assert(programPath.isAncestor(numberPath)); + }); + + it("returns false if not ancestor", function() { + let paths = []; + traverse(ast, { + "Program|NumericLiteral|StringLiteral"(path) { + paths.push(path); + } + }); + + let [ , numberPath, stringPath ] = paths; + + assert(!stringPath.isAncestor(numberPath)); + }); + }); + + describe("isDescendant", function () { + let ast = parse("var a = 1; 'a';"); + + it("returns true if descendant", function() { + let paths = []; + traverse(ast, { + "Program|NumericLiteral"(path) { + paths.push(path); + }, + }); + + let [ programPath, numberPath ] = paths; + + assert(numberPath.isDescendant(programPath)); + }); + + it("returns false if not descendant", function() { + let paths = []; + traverse(ast, { + "Program|NumericLiteral|StringLiteral"(path) { + paths.push(path); + } + }); + + let [ , numberPath, stringPath ] = paths; + + assert(!numberPath.isDescendant(stringPath)); + }); + }); +}); diff --git a/packages/babel-traverse/test/evaluation.js b/packages/babel-traverse/test/evaluation.js index 97dc0c3df9dd..956d656eb3d3 100644 --- a/packages/babel-traverse/test/evaluation.js +++ b/packages/babel-traverse/test/evaluation.js @@ -86,4 +86,16 @@ describe("evaluation", function () { false ); }); + + it("should deopt ids that are referenced before the bindings", function () { + assert.strictEqual( + getPath("let x = y + 5; let y = 5;").get("body.0.declarations.0.init").evaluate().confident, + false + ); + assert.strictEqual( + getPath("if (typeof x === 'undefined') var x = {}") + .get("body.0.test").evaluate().confident, + false + ); + }); }); diff --git a/packages/babel-traverse/test/family.js b/packages/babel-traverse/test/family.js new file mode 100644 index 000000000000..c6fc297f86a6 --- /dev/null +++ b/packages/babel-traverse/test/family.js @@ -0,0 +1,60 @@ +let traverse = require("../lib").default; +let assert = require("assert"); +let parse = require("babylon").parse; + +describe("path/family", function () { + describe("getBindingIdentifiers", function () { + let ast = parse("var a = 1, {b} = c, [d] = e; function f() {}"); + let nodes = {}, paths = {}, outerNodes = {}, outerPaths = {}; + traverse(ast, { + VariableDeclaration(path) { + nodes = path.getBindingIdentifiers(); + paths = path.getBindingIdentifierPaths(); + }, + FunctionDeclaration(path) { + outerNodes = path.getOuterBindingIdentifiers(); + outerPaths = path.getOuterBindingIdentifierPaths(); + } + }); + + it("should contain keys of nodes in paths", function () { + Object.keys(nodes).forEach((id) => { + assert.strictEqual(hop(paths, id), true, "Node's keys exists in paths"); + }); + }); + + it("should contain outer bindings", function () { + Object.keys(outerNodes).forEach((id) => { + assert.strictEqual(hop(outerPaths, id), true, "Has same outer keys"); + }); + }); + + it("should return paths", function () { + Object.keys(paths).forEach((id) => { + assert.strictEqual(!!paths[id].node, true, "Has a property node that's not falsy"); + assert.strictEqual(paths[id].type, paths[id].node.type, "type matches"); + }); + + Object.keys(outerPaths).forEach((id) => { + assert.strictEqual(!!outerPaths[id].node, true, "has property node"); + assert.strictEqual(outerPaths[id].type, outerPaths[id].node.type, "type matches"); + }); + }); + + it("should match paths and nodes returned for the same ast", function () { + Object.keys(nodes).forEach((id) => { + assert.strictEqual(nodes[id], paths[id].node, "Nodes match"); + }); + }); + + it("should match paths and nodes returned for outer Bindings", function () { + Object.keys(outerNodes).forEach((id) => { + assert.strictEqual(outerNodes[id], outerPaths[id].node, "nodes match"); + }); + }); + }); +}); + +function hop(o, key) { + return Object.hasOwnProperty.call(o, key); +} diff --git a/packages/babel-traverse/test/traverse.js b/packages/babel-traverse/test/traverse.js index f8446a11aeb4..cee715715059 100644 --- a/packages/babel-traverse/test/traverse.js +++ b/packages/babel-traverse/test/traverse.js @@ -1,63 +1,23 @@ let traverse = require("../lib").default; let assert = require("assert"); let _ = require("lodash"); +let parse = require("babylon").parse; describe("traverse", function () { - let ast = { - type: "Program", - body: [ - { - "type": "VariableDeclaration", - "declarations": [ - { - "type": "VariableDeclarator", - "id": { - "type": "Identifier", - "name": "foo", - }, - "init": { - "type": "StringLiteral", - "value": "bar", - "raw": "\'bar\'" - } - } - ], - "kind": "var" - }, - { - "type": "ExpressionStatement", - "expression": { - "type": "AssignmentExpression", - "operator": "=", - "left": { - "type": "MemberExpression", - "computed": false, - "object": { - "type": "ThisExpression" - }, - "property": { - "type": "Identifier", - "name": "test" - } - }, - "right": { - "type": "StringLiteral", - "value": "wow", - "raw": "\'wow\'" - } - } - } - ] - }; - - let body = ast.body; + let code = ` + var foo = "bar"; + this.test = "wow"; + `; + let ast = parse(code); + let program = ast.program; + let body = program.body; it("traverse replace", function () { let replacement = { type: "StringLiteral", value: "foo" }; - let ast2 = _.cloneDeep(ast); + let ast2 = _.cloneDeep(program); traverse(ast2, { enter: function (path) { @@ -76,7 +36,7 @@ describe("traverse", function () { let actual = []; - traverse(ast, { + traverse(program, { enter: function (path) { actual.push(path.node); } @@ -101,7 +61,7 @@ describe("traverse", function () { let actual = []; - traverse(ast, { + traverse(program, { blacklist: ["MemberExpression"], enter: function (path) { actual.push(path.node); @@ -126,17 +86,46 @@ describe("traverse", function () { it("clearCache", function () { let paths = []; + let scopes = []; traverse(ast, { - enter: function (path) { + enter(path) { + scopes.push(path.scope); paths.push(path); + path.stop(); } }); traverse.clearCache(); let paths2 = []; + let scopes2 = []; traverse(ast, { - enter: function (path) { + enter(path) { + scopes2.push(path.scope); + paths2.push(path); + path.stop(); + } + }); + + scopes2.forEach(function (_, i) { + assert.notStrictEqual(scopes[i], scopes2[i]); + assert.notStrictEqual(paths[i], paths2[i]); + }); + }); + + it("clearPath", function () { + let paths = []; + traverse(ast, { + enter(path) { + paths.push(path); + } + }); + + traverse.clearCache.clearPath(); + + let paths2 = []; + traverse(ast, { + enter(path) { paths2.push(path); } }); @@ -145,4 +134,28 @@ describe("traverse", function () { assert.notStrictEqual(p, paths[i]); }); }); + + it("clearScope", function () { + let scopes = []; + traverse(ast, { + enter(path) { + scopes.push(path.scope); + path.stop(); + } + }); + + traverse.clearCache.clearScope(); + + let scopes2 = []; + traverse(ast, { + enter(path) { + scopes2.push(path.scope); + path.stop(); + } + }); + + scopes2.forEach(function (p, i) { + assert.notStrictEqual(p, scopes[i]); + }); + }); }); diff --git a/packages/babel-types/README.md b/packages/babel-types/README.md index 4c0162febcf0..855bc4cef530 100644 --- a/packages/babel-types/README.md +++ b/packages/babel-types/README.md @@ -1,19 +1,33 @@ # babel-types -This module contains methods for building ASTs manually and for checking the types of AST nodes. +> This module contains methods for building ASTs manually and for checking the types of AST nodes. + +## Install + +```sh +npm install --save-dev babel-types +``` ## API -### t.anyTypeAnnotation() +### anyTypeAnnotation +```javascript +t.anyTypeAnnotation() +``` See also `t.isAnyTypeAnnotation(node, opts)` and `t.assertAnyTypeAnnotation(node, opts)`. Aliases: `Flow`, `FlowBaseAnnotation` -### t.arrayExpression(elements) +--- + +### arrayExpression +```javascript +t.arrayExpression(elements) +``` See also `t.isArrayExpression(node, opts)` and `t.assertArrayExpression(node, opts)`. @@ -21,7 +35,12 @@ Aliases: `Expression` - `elements`: `Array` (default: `[]`) -### t.arrayPattern(elements, typeAnnotation) +--- + +### arrayPattern +```javascript +t.arrayPattern(elements, typeAnnotation) +``` See also `t.isArrayPattern(node, opts)` and `t.assertArrayPattern(node, opts)`. @@ -31,7 +50,12 @@ Aliases: `Pattern`, `LVal` - `typeAnnotation` (required) - `decorators`: `Array` (default: `null`) -### t.arrayTypeAnnotation(elementType) +--- + +### arrayTypeAnnotation +```javascript +t.arrayTypeAnnotation(elementType) +``` See also `t.isArrayTypeAnnotation(node, opts)` and `t.assertArrayTypeAnnotation(node, opts)`. @@ -39,7 +63,12 @@ Aliases: `Flow` - `elementType` (required) -### t.arrowFunctionExpression(params, body, async) +--- + +### arrowFunctionExpression +```javascript +t.arrowFunctionExpression(params, body, async) +``` See also `t.isArrowFunctionExpression(node, opts)` and `t.assertArrowFunctionExpression(node, opts)`. @@ -51,7 +80,12 @@ Aliases: `Scopable`, `Function`, `BlockParent`, `FunctionParent`, `Expression`, - `returnType` (default: `null`) - `typeParameters` (default: `null`) -### t.assignmentExpression(operator, left, right) +--- + +### assignmentExpression +```javascript +t.assignmentExpression(operator, left, right) +``` See also `t.isAssignmentExpression(node, opts)` and `t.assertAssignmentExpression(node, opts)`. @@ -61,7 +95,12 @@ Aliases: `Expression` - `left`: `LVal` (required) - `right`: `Expression` (required) -### t.assignmentPattern(left, right) +--- + +### assignmentPattern +```javascript +t.assignmentPattern(left, right) +``` See also `t.isAssignmentPattern(node, opts)` and `t.assertAssignmentPattern(node, opts)`. @@ -71,7 +110,12 @@ Aliases: `Pattern`, `LVal` - `right`: `Expression` (required) - `decorators`: `Array` (default: `null`) -### t.awaitExpression(argument) +--- + +### awaitExpression +```javascript +t.awaitExpression(argument) +``` See also `t.isAwaitExpression(node, opts)` and `t.assertAwaitExpression(node, opts)`. @@ -79,7 +123,12 @@ Aliases: `Expression`, `Terminatorless` - `argument`: `Expression` (required) -### t.binaryExpression(operator, left, right) +--- + +### binaryExpression +```javascript +t.binaryExpression(operator, left, right) +``` See also `t.isBinaryExpression(node, opts)` and `t.assertBinaryExpression(node, opts)`. @@ -89,7 +138,12 @@ Aliases: `Binary`, `Expression` - `left`: `Expression` (required) - `right`: `Expression` (required) -### t.bindExpression(object, callee) +--- + +### bindExpression +```javascript +t.bindExpression(object, callee) +``` See also `t.isBindExpression(node, opts)` and `t.assertBindExpression(node, opts)`. @@ -98,7 +152,12 @@ Aliases: `Expression` - `object` (required) - `callee` (required) -### t.blockStatement(body, directives) +--- + +### blockStatement +```javascript +t.blockStatement(body, directives) +``` See also `t.isBlockStatement(node, opts)` and `t.assertBlockStatement(node, opts)`. @@ -107,7 +166,12 @@ Aliases: `Scopable`, `BlockParent`, `Block`, `Statement` - `body`: `Array` (required) - `directives`: `Array` (default: `[]`) -### t.booleanLiteral(value) +--- + +### booleanLiteral +```javascript +t.booleanLiteral(value) +``` See also `t.isBooleanLiteral(node, opts)` and `t.assertBooleanLiteral(node, opts)`. @@ -115,21 +179,36 @@ Aliases: `Expression`, `Pureish`, `Literal`, `Immutable` - `value`: `boolean` (required) -### t.booleanLiteralTypeAnnotation() +--- + +### booleanLiteralTypeAnnotation +```javascript +t.booleanLiteralTypeAnnotation() +``` See also `t.isBooleanLiteralTypeAnnotation(node, opts)` and `t.assertBooleanLiteralTypeAnnotation(node, opts)`. Aliases: `Flow` -### t.booleanTypeAnnotation() +--- + +### booleanTypeAnnotation +```javascript +t.booleanTypeAnnotation() +``` See also `t.isBooleanTypeAnnotation(node, opts)` and `t.assertBooleanTypeAnnotation(node, opts)`. Aliases: `Flow`, `FlowBaseAnnotation` -### t.breakStatement(label) +--- + +### breakStatement +```javascript +t.breakStatement(label) +``` See also `t.isBreakStatement(node, opts)` and `t.assertBreakStatement(node, opts)`. @@ -137,7 +216,12 @@ Aliases: `Statement`, `Terminatorless`, `CompletionStatement` - `label`: `Identifier` (default: `null`) -### t.callExpression(callee, arguments) +--- + +### callExpression +```javascript +t.callExpression(callee, arguments) +``` See also `t.isCallExpression(node, opts)` and `t.assertCallExpression(node, opts)`. @@ -146,7 +230,12 @@ Aliases: `Expression` - `callee`: `Expression` (required) - `arguments`: `Array` (required) -### t.catchClause(param, body) +--- + +### catchClause +```javascript +t.catchClause(param, body) +``` See also `t.isCatchClause(node, opts)` and `t.assertCatchClause(node, opts)`. @@ -155,13 +244,23 @@ Aliases: `Scopable` - `param`: `Identifier` (required) - `body`: `BlockStatement` (required) -### t.classBody(body) +--- + +### classBody +```javascript +t.classBody(body) +``` See also `t.isClassBody(node, opts)` and `t.assertClassBody(node, opts)`. - `body`: `Array` (required) -### t.classDeclaration(id, superClass, body, decorators) +--- + +### classDeclaration +```javascript +t.classDeclaration(id, superClass, body, decorators) +``` See also `t.isClassDeclaration(node, opts)` and `t.assertClassDeclaration(node, opts)`. @@ -176,7 +275,12 @@ Aliases: `Scopable`, `Class`, `Statement`, `Declaration`, `Pureish` - `superTypeParameters` (default: `null`) - `typeParameters` (default: `null`) -### t.classExpression(id, superClass, body, decorators) +--- + +### classExpression +```javascript +t.classExpression(id, superClass, body, decorators) +``` See also `t.isClassExpression(node, opts)` and `t.assertClassExpression(node, opts)`. @@ -191,7 +295,12 @@ Aliases: `Scopable`, `Class`, `Expression`, `Pureish` - `superTypeParameters` (default: `null`) - `typeParameters` (default: `null`) -### t.classImplements(id, typeParameters) +--- + +### classImplements +```javascript +t.classImplements(id, typeParameters) +``` See also `t.isClassImplements(node, opts)` and `t.assertClassImplements(node, opts)`. @@ -200,7 +309,12 @@ Aliases: `Flow` - `id` (required) - `typeParameters` (required) -### t.classMethod(kind, key, params, body, computed, static) +--- + +### classMethod +```javascript +t.classMethod(kind, key, params, body, computed, static) +``` See also `t.isClassMethod(node, opts)` and `t.assertClassMethod(node, opts)`. @@ -218,7 +332,12 @@ Aliases: `Function`, `Scopable`, `BlockParent`, `FunctionParent`, `Method` - `returnType` (default: `null`) - `typeParameters` (default: `null`) -### t.classProperty(key, value, typeAnnotation, decorators, computed) +--- + +### classProperty +```javascript +t.classProperty(key, value, typeAnnotation, decorators, computed) +``` See also `t.isClassProperty(node, opts)` and `t.assertClassProperty(node, opts)`. @@ -230,7 +349,12 @@ Aliases: `Property` - `decorators` (required) - `computed`: `boolean` (default: `false`) -### t.conditionalExpression(test, consequent, alternate) +--- + +### conditionalExpression +```javascript +t.conditionalExpression(test, consequent, alternate) +``` See also `t.isConditionalExpression(node, opts)` and `t.assertConditionalExpression(node, opts)`. @@ -240,7 +364,12 @@ Aliases: `Expression`, `Conditional` - `consequent`: `Expression` (required) - `alternate`: `Expression` (required) -### t.continueStatement(label) +--- + +### continueStatement +```javascript +t.continueStatement(label) +``` See also `t.isContinueStatement(node, opts)` and `t.assertContinueStatement(node, opts)`. @@ -248,14 +377,24 @@ Aliases: `Statement`, `Terminatorless`, `CompletionStatement` - `label`: `Identifier` (default: `null`) -### t.debuggerStatement() +--- + +### debuggerStatement +```javascript +t.debuggerStatement() +``` See also `t.isDebuggerStatement(node, opts)` and `t.assertDebuggerStatement(node, opts)`. Aliases: `Statement` -### t.declareClass(id, typeParameters, extends, body) +--- + +### declareClass +```javascript +t.declareClass(id, typeParameters, extends, body) +``` See also `t.isDeclareClass(node, opts)` and `t.assertDeclareClass(node, opts)`. @@ -266,7 +405,12 @@ Aliases: `Flow`, `FlowDeclaration`, `Statement`, `Declaration` - `extends` (required) - `body` (required) -### t.declareFunction(id) +--- + +### declareFunction +```javascript +t.declareFunction(id) +``` See also `t.isDeclareFunction(node, opts)` and `t.assertDeclareFunction(node, opts)`. @@ -274,7 +418,12 @@ Aliases: `Flow`, `FlowDeclaration`, `Statement`, `Declaration` - `id` (required) -### t.declareInterface(id, typeParameters, extends, body) +--- + +### declareInterface +```javascript +t.declareInterface(id, typeParameters, extends, body) +``` See also `t.isDeclareInterface(node, opts)` and `t.assertDeclareInterface(node, opts)`. @@ -285,7 +434,12 @@ Aliases: `Flow`, `FlowDeclaration`, `Statement`, `Declaration` - `extends` (required) - `body` (required) -### t.declareModule(id, body) +--- + +### declareModule +```javascript +t.declareModule(id, body) +``` See also `t.isDeclareModule(node, opts)` and `t.assertDeclareModule(node, opts)`. @@ -294,7 +448,12 @@ Aliases: `Flow`, `FlowDeclaration`, `Statement`, `Declaration` - `id` (required) - `body` (required) -### t.declareModuleExports(typeAnnotation) +--- + +### declareModuleExports +```javascript +t.declareModuleExports(typeAnnotation) +``` See also `t.isDeclareModuleExports(node, opts)` and `t.assertDeclareModuleExports(node, opts)`. @@ -302,7 +461,12 @@ Aliases: `Flow`, `FlowDeclaration`, `Statement`, `Declaration` - `typeAnnotation` (required) -### t.declareTypeAlias(id, typeParameters, right) +--- + +### declareTypeAlias +```javascript +t.declareTypeAlias(id, typeParameters, right) +``` See also `t.isDeclareTypeAlias(node, opts)` and `t.assertDeclareTypeAlias(node, opts)`. @@ -312,7 +476,12 @@ Aliases: `Flow`, `FlowDeclaration`, `Statement`, `Declaration` - `typeParameters` (required) - `right` (required) -### t.declareVariable(id) +--- + +### declareVariable +```javascript +t.declareVariable(id) +``` See also `t.isDeclareVariable(node, opts)` and `t.assertDeclareVariable(node, opts)`. @@ -320,25 +489,45 @@ Aliases: `Flow`, `FlowDeclaration`, `Statement`, `Declaration` - `id` (required) -### t.decorator(expression) +--- + +### decorator +```javascript +t.decorator(expression) +``` See also `t.isDecorator(node, opts)` and `t.assertDecorator(node, opts)`. - `expression`: `Expression` (required) -### t.directive(value) +--- + +### directive +```javascript +t.directive(value) +``` See also `t.isDirective(node, opts)` and `t.assertDirective(node, opts)`. - `value`: `DirectiveLiteral` (required) -### t.directiveLiteral(value) +--- + +### directiveLiteral +```javascript +t.directiveLiteral(value) +``` See also `t.isDirectiveLiteral(node, opts)` and `t.assertDirectiveLiteral(node, opts)`. - `value`: `string` (required) -### t.doExpression(body) +--- + +### doExpression +```javascript +t.doExpression(body) +``` See also `t.isDoExpression(node, opts)` and `t.assertDoExpression(node, opts)`. @@ -346,7 +535,12 @@ Aliases: `Expression` - `body`: `BlockStatement` (required) -### t.doWhileStatement(test, body) +--- + +### doWhileStatement +```javascript +t.doWhileStatement(test, body) +``` See also `t.isDoWhileStatement(node, opts)` and `t.assertDoWhileStatement(node, opts)`. @@ -355,28 +549,48 @@ Aliases: `Statement`, `BlockParent`, `Loop`, `While`, `Scopable` - `test`: `Expression` (required) - `body`: `Statement` (required) -### t.emptyStatement() +--- + +### emptyStatement +```javascript +t.emptyStatement() +``` See also `t.isEmptyStatement(node, opts)` and `t.assertEmptyStatement(node, opts)`. Aliases: `Statement` -### t.emptyTypeAnnotation() +--- + +### emptyTypeAnnotation +```javascript +t.emptyTypeAnnotation() +``` See also `t.isEmptyTypeAnnotation(node, opts)` and `t.assertEmptyTypeAnnotation(node, opts)`. Aliases: `Flow`, `FlowBaseAnnotation` -### t.existentialTypeParam() +--- + +### existentialTypeParam +```javascript +t.existentialTypeParam() +``` See also `t.isExistentialTypeParam(node, opts)` and `t.assertExistentialTypeParam(node, opts)`. Aliases: `Flow` -### t.exportAllDeclaration(source) +--- + +### exportAllDeclaration +```javascript +t.exportAllDeclaration(source) +``` See also `t.isExportAllDeclaration(node, opts)` and `t.assertExportAllDeclaration(node, opts)`. @@ -384,7 +598,12 @@ Aliases: `Statement`, `Declaration`, `ModuleDeclaration`, `ExportDeclaration` - `source`: `StringLiteral` (required) -### t.exportDefaultDeclaration(declaration) +--- + +### exportDefaultDeclaration +```javascript +t.exportDefaultDeclaration(declaration) +``` See also `t.isExportDefaultDeclaration(node, opts)` and `t.assertExportDefaultDeclaration(node, opts)`. @@ -392,7 +611,12 @@ Aliases: `Statement`, `Declaration`, `ModuleDeclaration`, `ExportDeclaration` - `declaration`: `FunctionDeclaration | ClassDeclaration | Expression` (required) -### t.exportDefaultSpecifier(exported) +--- + +### exportDefaultSpecifier +```javascript +t.exportDefaultSpecifier(exported) +``` See also `t.isExportDefaultSpecifier(node, opts)` and `t.assertExportDefaultSpecifier(node, opts)`. @@ -400,7 +624,12 @@ Aliases: `ModuleSpecifier` - `exported`: `Identifier` (required) -### t.exportNamedDeclaration(declaration, specifiers, source) +--- + +### exportNamedDeclaration +```javascript +t.exportNamedDeclaration(declaration, specifiers, source) +``` See also `t.isExportNamedDeclaration(node, opts)` and `t.assertExportNamedDeclaration(node, opts)`. @@ -410,7 +639,12 @@ Aliases: `Statement`, `Declaration`, `ModuleDeclaration`, `ExportDeclaration` - `specifiers`: `Array` (required) - `source`: `StringLiteral` (default: `null`) -### t.exportNamespaceSpecifier(exported) +--- + +### exportNamespaceSpecifier +```javascript +t.exportNamespaceSpecifier(exported) +``` See also `t.isExportNamespaceSpecifier(node, opts)` and `t.assertExportNamespaceSpecifier(node, opts)`. @@ -418,7 +652,12 @@ Aliases: `ModuleSpecifier` - `exported`: `Identifier` (required) -### t.exportSpecifier(local, exported) +--- + +### exportSpecifier +```javascript +t.exportSpecifier(local, exported) +``` See also `t.isExportSpecifier(node, opts)` and `t.assertExportSpecifier(node, opts)`. @@ -427,7 +666,12 @@ Aliases: `ModuleSpecifier` - `local`: `Identifier` (required) - `exported`: `Identifier` (required) -### t.expressionStatement(expression) +--- + +### expressionStatement +```javascript +t.expressionStatement(expression) +``` See also `t.isExpressionStatement(node, opts)` and `t.assertExpressionStatement(node, opts)`. @@ -435,7 +679,12 @@ Aliases: `Statement`, `ExpressionWrapper` - `expression`: `Expression` (required) -### t.file(program, comments, tokens) +--- + +### file +```javascript +t.file(program, comments, tokens) +``` See also `t.isFile(node, opts)` and `t.assertFile(node, opts)`. @@ -443,7 +692,12 @@ See also `t.isFile(node, opts)` and `t.assertFile(node, opts)`. - `comments` (required) - `tokens` (required) -### t.forAwaitStatement(left, right, body) +--- + +### forAwaitStatement +```javascript +t.forAwaitStatement(left, right, body) +``` See also `t.isForAwaitStatement(node, opts)` and `t.assertForAwaitStatement(node, opts)`. @@ -453,7 +707,12 @@ Aliases: `Scopable`, `Statement`, `For`, `BlockParent`, `Loop`, `ForXStatement` - `right`: `Expression` (required) - `body`: `Statement` (required) -### t.forInStatement(left, right, body) +--- + +### forInStatement +```javascript +t.forInStatement(left, right, body) +``` See also `t.isForInStatement(node, opts)` and `t.assertForInStatement(node, opts)`. @@ -463,7 +722,12 @@ Aliases: `Scopable`, `Statement`, `For`, `BlockParent`, `Loop`, `ForXStatement` - `right`: `Expression` (required) - `body`: `Statement` (required) -### t.forOfStatement(left, right, body) +--- + +### forOfStatement +```javascript +t.forOfStatement(left, right, body) +``` See also `t.isForOfStatement(node, opts)` and `t.assertForOfStatement(node, opts)`. @@ -473,7 +737,12 @@ Aliases: `Scopable`, `Statement`, `For`, `BlockParent`, `Loop`, `ForXStatement` - `right`: `Expression` (required) - `body`: `Statement` (required) -### t.forStatement(init, test, update, body) +--- + +### forStatement +```javascript +t.forStatement(init, test, update, body) +``` See also `t.isForStatement(node, opts)` and `t.assertForStatement(node, opts)`. @@ -484,7 +753,12 @@ Aliases: `Scopable`, `Statement`, `For`, `BlockParent`, `Loop` - `update`: `Expression` (default: `null`) - `body`: `Statement` (required) -### t.functionDeclaration(id, params, body, generator, async) +--- + +### functionDeclaration +```javascript +t.functionDeclaration(id, params, body, generator, async) +``` See also `t.isFunctionDeclaration(node, opts)` and `t.assertFunctionDeclaration(node, opts)`. @@ -498,7 +772,12 @@ Aliases: `Scopable`, `Function`, `BlockParent`, `FunctionParent`, `Statement`, ` - `returnType` (default: `null`) - `typeParameters` (default: `null`) -### t.functionExpression(id, params, body, generator, async) +--- + +### functionExpression +```javascript +t.functionExpression(id, params, body, generator, async) +``` See also `t.isFunctionExpression(node, opts)` and `t.assertFunctionExpression(node, opts)`. @@ -512,7 +791,12 @@ Aliases: `Scopable`, `Function`, `BlockParent`, `FunctionParent`, `Expression`, - `returnType` (default: `null`) - `typeParameters` (default: `null`) -### t.functionTypeAnnotation(typeParameters, params, rest, returnType) +--- + +### functionTypeAnnotation +```javascript +t.functionTypeAnnotation(typeParameters, params, rest, returnType) +``` See also `t.isFunctionTypeAnnotation(node, opts)` and `t.assertFunctionTypeAnnotation(node, opts)`. @@ -523,7 +807,12 @@ Aliases: `Flow` - `rest` (required) - `returnType` (required) -### t.functionTypeParam(name, typeAnnotation) +--- + +### functionTypeParam +```javascript +t.functionTypeParam(name, typeAnnotation) +``` See also `t.isFunctionTypeParam(node, opts)` and `t.assertFunctionTypeParam(node, opts)`. @@ -532,7 +821,12 @@ Aliases: `Flow` - `name` (required) - `typeAnnotation` (required) -### t.genericTypeAnnotation(id, typeParameters) +--- + +### genericTypeAnnotation +```javascript +t.genericTypeAnnotation(id, typeParameters) +``` See also `t.isGenericTypeAnnotation(node, opts)` and `t.assertGenericTypeAnnotation(node, opts)`. @@ -541,7 +835,12 @@ Aliases: `Flow` - `id` (required) - `typeParameters` (required) -### t.identifier(name) +--- + +### identifier +```javascript +t.identifier(name) +``` See also `t.isIdentifier(node, opts)` and `t.assertIdentifier(node, opts)`. @@ -551,7 +850,12 @@ Aliases: `Expression`, `LVal` - `decorators`: `Array` (default: `null`) - `typeAnnotation` (default: `null`) -### t.ifStatement(test, consequent, alternate) +--- + +### ifStatement +```javascript +t.ifStatement(test, consequent, alternate) +``` See also `t.isIfStatement(node, opts)` and `t.assertIfStatement(node, opts)`. @@ -561,7 +865,24 @@ Aliases: `Statement`, `Conditional` - `consequent`: `Statement` (required) - `alternate`: `Statement` (default: `null`) -### t.importDeclaration(specifiers, source) +--- + +### import +```javascript +t.import() +``` + +See also `t.isImport(node, opts)` and `t.assertImport(node, opts)`. + +Aliases: `Expression` + + +--- + +### importDeclaration +```javascript +t.importDeclaration(specifiers, source) +``` See also `t.isImportDeclaration(node, opts)` and `t.assertImportDeclaration(node, opts)`. @@ -570,7 +891,12 @@ Aliases: `Statement`, `Declaration`, `ModuleDeclaration` - `specifiers`: `Array` (required) - `source`: `StringLiteral` (required) -### t.importDefaultSpecifier(local) +--- + +### importDefaultSpecifier +```javascript +t.importDefaultSpecifier(local) +``` See also `t.isImportDefaultSpecifier(node, opts)` and `t.assertImportDefaultSpecifier(node, opts)`. @@ -578,7 +904,12 @@ Aliases: `ModuleSpecifier` - `local`: `Identifier` (required) -### t.importNamespaceSpecifier(local) +--- + +### importNamespaceSpecifier +```javascript +t.importNamespaceSpecifier(local) +``` See also `t.isImportNamespaceSpecifier(node, opts)` and `t.assertImportNamespaceSpecifier(node, opts)`. @@ -586,7 +917,12 @@ Aliases: `ModuleSpecifier` - `local`: `Identifier` (required) -### t.importSpecifier(local, imported) +--- + +### importSpecifier +```javascript +t.importSpecifier(local, imported) +``` See also `t.isImportSpecifier(node, opts)` and `t.assertImportSpecifier(node, opts)`. @@ -595,7 +931,12 @@ Aliases: `ModuleSpecifier` - `local`: `Identifier` (required) - `imported`: `Identifier` (required) -### t.interfaceDeclaration(id, typeParameters, extends, body) +--- + +### interfaceDeclaration +```javascript +t.interfaceDeclaration(id, typeParameters, extends, body) +``` See also `t.isInterfaceDeclaration(node, opts)` and `t.assertInterfaceDeclaration(node, opts)`. @@ -606,7 +947,12 @@ Aliases: `Flow`, `FlowDeclaration`, `Statement`, `Declaration` - `extends` (required) - `body` (required) -### t.interfaceExtends(id, typeParameters) +--- + +### interfaceExtends +```javascript +t.interfaceExtends(id, typeParameters) +``` See also `t.isInterfaceExtends(node, opts)` and `t.assertInterfaceExtends(node, opts)`. @@ -615,7 +961,12 @@ Aliases: `Flow` - `id` (required) - `typeParameters` (required) -### t.intersectionTypeAnnotation(types) +--- + +### intersectionTypeAnnotation +```javascript +t.intersectionTypeAnnotation(types) +``` See also `t.isIntersectionTypeAnnotation(node, opts)` and `t.assertIntersectionTypeAnnotation(node, opts)`. @@ -623,7 +974,12 @@ Aliases: `Flow` - `types` (required) -### t.jSXAttribute(name, value) +--- + +### jSXAttribute +```javascript +t.jSXAttribute(name, value) +``` See also `t.isJSXAttribute(node, opts)` and `t.assertJSXAttribute(node, opts)`. @@ -632,7 +988,12 @@ Aliases: `JSX`, `Immutable` - `name`: `JSXIdentifier | JSXNamespacedName` (required) - `value`: `JSXElement | StringLiteral | JSXExpressionContainer` (default: `null`) -### t.jSXClosingElement(name) +--- + +### jSXClosingElement +```javascript +t.jSXClosingElement(name) +``` See also `t.isJSXClosingElement(node, opts)` and `t.assertJSXClosingElement(node, opts)`. @@ -640,7 +1001,12 @@ Aliases: `JSX`, `Immutable` - `name`: `JSXIdentifier | JSXMemberExpression` (required) -### t.jSXElement(openingElement, closingElement, children, selfClosing) +--- + +### jSXElement +```javascript +t.jSXElement(openingElement, closingElement, children, selfClosing) +``` See also `t.isJSXElement(node, opts)` and `t.assertJSXElement(node, opts)`. @@ -651,14 +1017,24 @@ Aliases: `JSX`, `Immutable`, `Expression` - `children`: `Array` (required) - `selfClosing` (required) -### t.jSXEmptyExpression() +--- + +### jSXEmptyExpression +```javascript +t.jSXEmptyExpression() +``` See also `t.isJSXEmptyExpression(node, opts)` and `t.assertJSXEmptyExpression(node, opts)`. Aliases: `JSX`, `Expression` -### t.jSXExpressionContainer(expression) +--- + +### jSXExpressionContainer +```javascript +t.jSXExpressionContainer(expression) +``` See also `t.isJSXExpressionContainer(node, opts)` and `t.assertJSXExpressionContainer(node, opts)`. @@ -666,7 +1042,12 @@ Aliases: `JSX`, `Immutable` - `expression`: `Expression` (required) -### t.jSXIdentifier(name) +--- + +### jSXIdentifier +```javascript +t.jSXIdentifier(name) +``` See also `t.isJSXIdentifier(node, opts)` and `t.assertJSXIdentifier(node, opts)`. @@ -674,7 +1055,12 @@ Aliases: `JSX`, `Expression` - `name`: `string` (required) -### t.jSXMemberExpression(object, property) +--- + +### jSXMemberExpression +```javascript +t.jSXMemberExpression(object, property) +``` See also `t.isJSXMemberExpression(node, opts)` and `t.assertJSXMemberExpression(node, opts)`. @@ -683,7 +1069,12 @@ Aliases: `JSX`, `Expression` - `object`: `JSXMemberExpression | JSXIdentifier` (required) - `property`: `JSXIdentifier` (required) -### t.jSXNamespacedName(namespace, name) +--- + +### jSXNamespacedName +```javascript +t.jSXNamespacedName(namespace, name) +``` See also `t.isJSXNamespacedName(node, opts)` and `t.assertJSXNamespacedName(node, opts)`. @@ -692,7 +1083,12 @@ Aliases: `JSX` - `namespace`: `JSXIdentifier` (required) - `name`: `JSXIdentifier` (required) -### t.jSXOpeningElement(name, attributes, selfClosing) +--- + +### jSXOpeningElement +```javascript +t.jSXOpeningElement(name, attributes, selfClosing) +``` See also `t.isJSXOpeningElement(node, opts)` and `t.assertJSXOpeningElement(node, opts)`. @@ -702,7 +1098,12 @@ Aliases: `JSX`, `Immutable` - `attributes`: `Array` (required) - `selfClosing`: `boolean` (default: `false`) -### t.jSXSpreadAttribute(argument) +--- + +### jSXSpreadAttribute +```javascript +t.jSXSpreadAttribute(argument) +``` See also `t.isJSXSpreadAttribute(node, opts)` and `t.assertJSXSpreadAttribute(node, opts)`. @@ -710,7 +1111,12 @@ Aliases: `JSX` - `argument`: `Expression` (required) -### t.jSXText(value) +--- + +### jSXText +```javascript +t.jSXText(value) +``` See also `t.isJSXText(node, opts)` and `t.assertJSXText(node, opts)`. @@ -718,7 +1124,12 @@ Aliases: `JSX`, `Immutable` - `value`: `string` (required) -### t.labeledStatement(label, body) +--- + +### labeledStatement +```javascript +t.labeledStatement(label, body) +``` See also `t.isLabeledStatement(node, opts)` and `t.assertLabeledStatement(node, opts)`. @@ -727,7 +1138,12 @@ Aliases: `Statement` - `label`: `Identifier` (required) - `body`: `Statement` (required) -### t.logicalExpression(operator, left, right) +--- + +### logicalExpression +```javascript +t.logicalExpression(operator, left, right) +``` See also `t.isLogicalExpression(node, opts)` and `t.assertLogicalExpression(node, opts)`. @@ -737,7 +1153,12 @@ Aliases: `Binary`, `Expression` - `left`: `Expression` (required) - `right`: `Expression` (required) -### t.memberExpression(object, property, computed) +--- + +### memberExpression +```javascript +t.memberExpression(object, property, computed) +``` See also `t.isMemberExpression(node, opts)` and `t.assertMemberExpression(node, opts)`. @@ -747,7 +1168,12 @@ Aliases: `Expression`, `LVal` - `property`if computed then `Expression` else `Identifier` (required) - `computed`: `boolean` (default: `false`) -### t.metaProperty(meta, property) +--- + +### metaProperty +```javascript +t.metaProperty(meta, property) +``` See also `t.isMetaProperty(node, opts)` and `t.assertMetaProperty(node, opts)`. @@ -756,14 +1182,24 @@ Aliases: `Expression` - `meta`: `string` (required) - `property`: `string` (required) -### t.mixedTypeAnnotation() +--- + +### mixedTypeAnnotation +```javascript +t.mixedTypeAnnotation() +``` See also `t.isMixedTypeAnnotation(node, opts)` and `t.assertMixedTypeAnnotation(node, opts)`. Aliases: `Flow`, `FlowBaseAnnotation` -### t.newExpression(callee, arguments) +--- + +### newExpression +```javascript +t.newExpression(callee, arguments) +``` See also `t.isNewExpression(node, opts)` and `t.assertNewExpression(node, opts)`. @@ -772,26 +1208,46 @@ Aliases: `Expression` - `callee`: `Expression` (required) - `arguments`: `Array` (required) -### t.noop() +--- + +### noop +```javascript +t.noop() +``` See also `t.isNoop(node, opts)` and `t.assertNoop(node, opts)`. -### t.nullLiteral() +--- + +### nullLiteral +```javascript +t.nullLiteral() +``` See also `t.isNullLiteral(node, opts)` and `t.assertNullLiteral(node, opts)`. Aliases: `Expression`, `Pureish`, `Literal`, `Immutable` -### t.nullLiteralTypeAnnotation() +--- + +### nullLiteralTypeAnnotation +```javascript +t.nullLiteralTypeAnnotation() +``` See also `t.isNullLiteralTypeAnnotation(node, opts)` and `t.assertNullLiteralTypeAnnotation(node, opts)`. Aliases: `Flow`, `FlowBaseAnnotation` -### t.nullableTypeAnnotation(typeAnnotation) +--- + +### nullableTypeAnnotation +```javascript +t.nullableTypeAnnotation(typeAnnotation) +``` See also `t.isNullableTypeAnnotation(node, opts)` and `t.assertNullableTypeAnnotation(node, opts)`. @@ -799,14 +1255,24 @@ Aliases: `Flow` - `typeAnnotation` (required) -### t.numberTypeAnnotation() +--- + +### numberTypeAnnotation +```javascript +t.numberTypeAnnotation() +``` See also `t.isNumberTypeAnnotation(node, opts)` and `t.assertNumberTypeAnnotation(node, opts)`. Aliases: `Flow`, `FlowBaseAnnotation` -### t.numericLiteral(value) +--- + +### numericLiteral +```javascript +t.numericLiteral(value) +``` See also `t.isNumericLiteral(node, opts)` and `t.assertNumericLiteral(node, opts)`. @@ -814,14 +1280,24 @@ Aliases: `Expression`, `Pureish`, `Literal`, `Immutable` - `value`: `number` (required) -### t.numericLiteralTypeAnnotation() +--- + +### numericLiteralTypeAnnotation +```javascript +t.numericLiteralTypeAnnotation() +``` See also `t.isNumericLiteralTypeAnnotation(node, opts)` and `t.assertNumericLiteralTypeAnnotation(node, opts)`. Aliases: `Flow` -### t.objectExpression(properties) +--- + +### objectExpression +```javascript +t.objectExpression(properties) +``` See also `t.isObjectExpression(node, opts)` and `t.assertObjectExpression(node, opts)`. @@ -829,7 +1305,12 @@ Aliases: `Expression` - `properties`: `Array` (required) -### t.objectMethod(kind, key, params, body, computed) +--- + +### objectMethod +```javascript +t.objectMethod(kind, key, params, body, computed) +``` See also `t.isObjectMethod(node, opts)` and `t.assertObjectMethod(node, opts)`. @@ -846,7 +1327,12 @@ Aliases: `UserWhitespacable`, `Function`, `Scopable`, `BlockParent`, `FunctionPa - `returnType` (default: `null`) - `typeParameters` (default: `null`) -### t.objectPattern(properties, typeAnnotation) +--- + +### objectPattern +```javascript +t.objectPattern(properties, typeAnnotation) +``` See also `t.isObjectPattern(node, opts)` and `t.assertObjectPattern(node, opts)`. @@ -856,7 +1342,12 @@ Aliases: `Pattern`, `LVal` - `typeAnnotation` (required) - `decorators`: `Array` (default: `null`) -### t.objectProperty(key, value, computed, shorthand, decorators) +--- + +### objectProperty +```javascript +t.objectProperty(key, value, computed, shorthand, decorators) +``` See also `t.isObjectProperty(node, opts)` and `t.assertObjectProperty(node, opts)`. @@ -868,7 +1359,12 @@ Aliases: `UserWhitespacable`, `Property`, `ObjectMember` - `shorthand`: `boolean` (default: `false`) - `decorators`: `Array` (default: `null`) -### t.objectTypeAnnotation(properties, indexers, callProperties) +--- + +### objectTypeAnnotation +```javascript +t.objectTypeAnnotation(properties, indexers, callProperties) +``` See also `t.isObjectTypeAnnotation(node, opts)` and `t.assertObjectTypeAnnotation(node, opts)`. @@ -878,7 +1374,12 @@ Aliases: `Flow` - `indexers` (required) - `callProperties` (required) -### t.objectTypeCallProperty(value) +--- + +### objectTypeCallProperty +```javascript +t.objectTypeCallProperty(value) +``` See also `t.isObjectTypeCallProperty(node, opts)` and `t.assertObjectTypeCallProperty(node, opts)`. @@ -886,7 +1387,12 @@ Aliases: `Flow`, `UserWhitespacable` - `value` (required) -### t.objectTypeIndexer(id, key, value) +--- + +### objectTypeIndexer +```javascript +t.objectTypeIndexer(id, key, value) +``` See also `t.isObjectTypeIndexer(node, opts)` and `t.assertObjectTypeIndexer(node, opts)`. @@ -896,7 +1402,12 @@ Aliases: `Flow`, `UserWhitespacable` - `key` (required) - `value` (required) -### t.objectTypeProperty(key, value) +--- + +### objectTypeProperty +```javascript +t.objectTypeProperty(key, value) +``` See also `t.isObjectTypeProperty(node, opts)` and `t.assertObjectTypeProperty(node, opts)`. @@ -905,7 +1416,12 @@ Aliases: `Flow`, `UserWhitespacable` - `key` (required) - `value` (required) -### t.parenthesizedExpression(expression) +--- + +### parenthesizedExpression +```javascript +t.parenthesizedExpression(expression) +``` See also `t.isParenthesizedExpression(node, opts)` and `t.assertParenthesizedExpression(node, opts)`. @@ -913,7 +1429,12 @@ Aliases: `Expression`, `ExpressionWrapper` - `expression`: `Expression` (required) -### t.program(body, directives) +--- + +### program +```javascript +t.program(body, directives) +``` See also `t.isProgram(node, opts)` and `t.assertProgram(node, opts)`. @@ -922,7 +1443,12 @@ Aliases: `Scopable`, `BlockParent`, `Block`, `FunctionParent` - `body`: `Array` (required) - `directives`: `Array` (default: `[]`) -### t.qualifiedTypeIdentifier(id, qualification) +--- + +### qualifiedTypeIdentifier +```javascript +t.qualifiedTypeIdentifier(id, qualification) +``` See also `t.isQualifiedTypeIdentifier(node, opts)` and `t.assertQualifiedTypeIdentifier(node, opts)`. @@ -931,7 +1457,12 @@ Aliases: `Flow` - `id` (required) - `qualification` (required) -### t.regExpLiteral(pattern, flags) +--- + +### regExpLiteral +```javascript +t.regExpLiteral(pattern, flags) +``` See also `t.isRegExpLiteral(node, opts)` and `t.assertRegExpLiteral(node, opts)`. @@ -940,7 +1471,12 @@ Aliases: `Expression`, `Literal` - `pattern`: `string` (required) - `flags`: `string` (default: `''`) -### t.restElement(argument, typeAnnotation) +--- + +### restElement +```javascript +t.restElement(argument, typeAnnotation) +``` See also `t.isRestElement(node, opts)` and `t.assertRestElement(node, opts)`. @@ -950,7 +1486,12 @@ Aliases: `LVal` - `typeAnnotation` (required) - `decorators`: `Array` (default: `null`) -### t.restProperty(argument) +--- + +### restProperty +```javascript +t.restProperty(argument) +``` See also `t.isRestProperty(node, opts)` and `t.assertRestProperty(node, opts)`. @@ -958,7 +1499,12 @@ Aliases: `UnaryLike` - `argument`: `LVal` (required) -### t.returnStatement(argument) +--- + +### returnStatement +```javascript +t.returnStatement(argument) +``` See also `t.isReturnStatement(node, opts)` and `t.assertReturnStatement(node, opts)`. @@ -966,7 +1512,12 @@ Aliases: `Statement`, `Terminatorless`, `CompletionStatement` - `argument`: `Expression` (default: `null`) -### t.sequenceExpression(expressions) +--- + +### sequenceExpression +```javascript +t.sequenceExpression(expressions) +``` See also `t.isSequenceExpression(node, opts)` and `t.assertSequenceExpression(node, opts)`. @@ -974,7 +1525,12 @@ Aliases: `Expression` - `expressions`: `Array` (required) -### t.spreadElement(argument) +--- + +### spreadElement +```javascript +t.spreadElement(argument) +``` See also `t.isSpreadElement(node, opts)` and `t.assertSpreadElement(node, opts)`. @@ -982,7 +1538,12 @@ Aliases: `UnaryLike` - `argument`: `Expression` (required) -### t.spreadProperty(argument) +--- + +### spreadProperty +```javascript +t.spreadProperty(argument) +``` See also `t.isSpreadProperty(node, opts)` and `t.assertSpreadProperty(node, opts)`. @@ -990,7 +1551,12 @@ Aliases: `UnaryLike` - `argument`: `Expression` (required) -### t.stringLiteral(value) +--- + +### stringLiteral +```javascript +t.stringLiteral(value) +``` See also `t.isStringLiteral(node, opts)` and `t.assertStringLiteral(node, opts)`. @@ -998,35 +1564,60 @@ Aliases: `Expression`, `Pureish`, `Literal`, `Immutable` - `value`: `string` (required) -### t.stringLiteralTypeAnnotation() +--- + +### stringLiteralTypeAnnotation +```javascript +t.stringLiteralTypeAnnotation() +``` See also `t.isStringLiteralTypeAnnotation(node, opts)` and `t.assertStringLiteralTypeAnnotation(node, opts)`. Aliases: `Flow` -### t.stringTypeAnnotation() +--- + +### stringTypeAnnotation +```javascript +t.stringTypeAnnotation() +``` See also `t.isStringTypeAnnotation(node, opts)` and `t.assertStringTypeAnnotation(node, opts)`. Aliases: `Flow`, `FlowBaseAnnotation` -### t.super() +--- + +### super +```javascript +t.super() +``` See also `t.isSuper(node, opts)` and `t.assertSuper(node, opts)`. Aliases: `Expression` -### t.switchCase(test, consequent) +--- + +### switchCase +```javascript +t.switchCase(test, consequent) +``` See also `t.isSwitchCase(node, opts)` and `t.assertSwitchCase(node, opts)`. - `test`: `Expression` (default: `null`) - `consequent`: `Array` (required) -### t.switchStatement(discriminant, cases) +--- + +### switchStatement +```javascript +t.switchStatement(discriminant, cases) +``` See also `t.isSwitchStatement(node, opts)` and `t.assertSwitchStatement(node, opts)`. @@ -1035,7 +1626,12 @@ Aliases: `Statement`, `BlockParent`, `Scopable` - `discriminant`: `Expression` (required) - `cases`: `Array` (required) -### t.taggedTemplateExpression(tag, quasi) +--- + +### taggedTemplateExpression +```javascript +t.taggedTemplateExpression(tag, quasi) +``` See also `t.isTaggedTemplateExpression(node, opts)` and `t.assertTaggedTemplateExpression(node, opts)`. @@ -1044,14 +1640,24 @@ Aliases: `Expression` - `tag`: `Expression` (required) - `quasi`: `TemplateLiteral` (required) -### t.templateElement(value, tail) +--- + +### templateElement +```javascript +t.templateElement(value, tail) +``` See also `t.isTemplateElement(node, opts)` and `t.assertTemplateElement(node, opts)`. - `value` (required) - `tail`: `boolean` (default: `false`) -### t.templateLiteral(quasis, expressions) +--- + +### templateLiteral +```javascript +t.templateLiteral(quasis, expressions) +``` See also `t.isTemplateLiteral(node, opts)` and `t.assertTemplateLiteral(node, opts)`. @@ -1060,21 +1666,36 @@ Aliases: `Expression`, `Literal` - `quasis`: `Array` (required) - `expressions`: `Array` (required) -### t.thisExpression() +--- + +### thisExpression +```javascript +t.thisExpression() +``` See also `t.isThisExpression(node, opts)` and `t.assertThisExpression(node, opts)`. Aliases: `Expression` -### t.thisTypeAnnotation() +--- + +### thisTypeAnnotation +```javascript +t.thisTypeAnnotation() +``` See also `t.isThisTypeAnnotation(node, opts)` and `t.assertThisTypeAnnotation(node, opts)`. Aliases: `Flow`, `FlowBaseAnnotation` -### t.throwStatement(argument) +--- + +### throwStatement +```javascript +t.throwStatement(argument) +``` See also `t.isThrowStatement(node, opts)` and `t.assertThrowStatement(node, opts)`. @@ -1082,7 +1703,12 @@ Aliases: `Statement`, `Terminatorless`, `CompletionStatement` - `argument`: `Expression` (required) -### t.tryStatement(block, handler, finalizer) +--- + +### tryStatement +```javascript +t.tryStatement(block, handler, finalizer) +``` See also `t.isTryStatement(node, opts)` and `t.assertTryStatement(node, opts)`. @@ -1093,7 +1719,12 @@ Aliases: `Statement` - `finalizer`: `BlockStatement` (default: `null`) - `body`: `BlockStatement` (default: `null`) -### t.tupleTypeAnnotation(types) +--- + +### tupleTypeAnnotation +```javascript +t.tupleTypeAnnotation(types) +``` See also `t.isTupleTypeAnnotation(node, opts)` and `t.assertTupleTypeAnnotation(node, opts)`. @@ -1101,7 +1732,12 @@ Aliases: `Flow` - `types` (required) -### t.typeAlias(id, typeParameters, right) +--- + +### typeAlias +```javascript +t.typeAlias(id, typeParameters, right) +``` See also `t.isTypeAlias(node, opts)` and `t.assertTypeAlias(node, opts)`. @@ -1111,7 +1747,12 @@ Aliases: `Flow`, `FlowDeclaration`, `Statement`, `Declaration` - `typeParameters` (required) - `right` (required) -### t.typeAnnotation(typeAnnotation) +--- + +### typeAnnotation +```javascript +t.typeAnnotation(typeAnnotation) +``` See also `t.isTypeAnnotation(node, opts)` and `t.assertTypeAnnotation(node, opts)`. @@ -1119,7 +1760,12 @@ Aliases: `Flow` - `typeAnnotation` (required) -### t.typeCastExpression(expression, typeAnnotation) +--- + +### typeCastExpression +```javascript +t.typeCastExpression(expression, typeAnnotation) +``` See also `t.isTypeCastExpression(node, opts)` and `t.assertTypeCastExpression(node, opts)`. @@ -1128,7 +1774,12 @@ Aliases: `Flow`, `ExpressionWrapper`, `Expression` - `expression` (required) - `typeAnnotation` (required) -### t.typeParameter(bound) +--- + +### typeParameter +```javascript +t.typeParameter(bound) +``` See also `t.isTypeParameter(node, opts)` and `t.assertTypeParameter(node, opts)`. @@ -1136,7 +1787,12 @@ Aliases: `Flow` - `bound` (required) -### t.typeParameterDeclaration(params) +--- + +### typeParameterDeclaration +```javascript +t.typeParameterDeclaration(params) +``` See also `t.isTypeParameterDeclaration(node, opts)` and `t.assertTypeParameterDeclaration(node, opts)`. @@ -1144,7 +1800,12 @@ Aliases: `Flow` - `params` (required) -### t.typeParameterInstantiation(params) +--- + +### typeParameterInstantiation +```javascript +t.typeParameterInstantiation(params) +``` See also `t.isTypeParameterInstantiation(node, opts)` and `t.assertTypeParameterInstantiation(node, opts)`. @@ -1152,7 +1813,12 @@ Aliases: `Flow` - `params` (required) -### t.typeofTypeAnnotation(argument) +--- + +### typeofTypeAnnotation +```javascript +t.typeofTypeAnnotation(argument) +``` See also `t.isTypeofTypeAnnotation(node, opts)` and `t.assertTypeofTypeAnnotation(node, opts)`. @@ -1160,7 +1826,12 @@ Aliases: `Flow` - `argument` (required) -### t.unaryExpression(operator, argument, prefix) +--- + +### unaryExpression +```javascript +t.unaryExpression(operator, argument, prefix) +``` See also `t.isUnaryExpression(node, opts)` and `t.assertUnaryExpression(node, opts)`. @@ -1170,7 +1841,12 @@ Aliases: `UnaryLike`, `Expression` - `argument`: `Expression` (required) - `prefix`: `boolean` (default: `true`) -### t.unionTypeAnnotation(types) +--- + +### unionTypeAnnotation +```javascript +t.unionTypeAnnotation(types) +``` See also `t.isUnionTypeAnnotation(node, opts)` and `t.assertUnionTypeAnnotation(node, opts)`. @@ -1178,7 +1854,12 @@ Aliases: `Flow` - `types` (required) -### t.updateExpression(operator, argument, prefix) +--- + +### updateExpression +```javascript +t.updateExpression(operator, argument, prefix) +``` See also `t.isUpdateExpression(node, opts)` and `t.assertUpdateExpression(node, opts)`. @@ -1188,7 +1869,12 @@ Aliases: `Expression` - `argument`: `Expression` (required) - `prefix`: `boolean` (default: `false`) -### t.variableDeclaration(kind, declarations) +--- + +### variableDeclaration +```javascript +t.variableDeclaration(kind, declarations) +``` See also `t.isVariableDeclaration(node, opts)` and `t.assertVariableDeclaration(node, opts)`. @@ -1197,21 +1883,36 @@ Aliases: `Statement`, `Declaration` - `kind`: `"var" | "let" | "const"` (required) - `declarations`: `Array` (required) -### t.variableDeclarator(id, init) +--- + +### variableDeclarator +```javascript +t.variableDeclarator(id, init) +``` See also `t.isVariableDeclarator(node, opts)` and `t.assertVariableDeclarator(node, opts)`. - `id`: `LVal` (required) - `init`: `Expression` (default: `null`) -### t.voidTypeAnnotation() +--- + +### voidTypeAnnotation +```javascript +t.voidTypeAnnotation() +``` See also `t.isVoidTypeAnnotation(node, opts)` and `t.assertVoidTypeAnnotation(node, opts)`. Aliases: `Flow`, `FlowBaseAnnotation` -### t.whileStatement(test, body) +--- + +### whileStatement +```javascript +t.whileStatement(test, body) +``` See also `t.isWhileStatement(node, opts)` and `t.assertWhileStatement(node, opts)`. @@ -1220,7 +1921,12 @@ Aliases: `Statement`, `BlockParent`, `Loop`, `While`, `Scopable` - `test`: `Expression` (required) - `body`: `BlockStatement | Statement` (required) -### t.withStatement(object, body) +--- + +### withStatement +```javascript +t.withStatement(object, body) +``` See also `t.isWithStatement(node, opts)` and `t.assertWithStatement(node, opts)`. @@ -1229,7 +1935,12 @@ Aliases: `Statement` - `object` (required) - `body`: `BlockStatement | Statement` (required) -### t.yieldExpression(argument, delegate) +--- + +### yieldExpression +```javascript +t.yieldExpression(argument, delegate) +``` See also `t.isYieldExpression(node, opts)` and `t.assertYieldExpression(node, opts)`. @@ -1238,6 +1949,8 @@ Aliases: `Expression`, `Terminatorless` - `argument`: `Expression` (default: `null`) - `delegate`: `boolean` (default: `false`) +--- + diff --git a/packages/babel-types/package.json b/packages/babel-types/package.json index d95ef6227381..96a12cce7140 100644 --- a/packages/babel-types/package.json +++ b/packages/babel-types/package.json @@ -1,6 +1,6 @@ { "name": "babel-types", - "version": "6.18.0", + "version": "6.20.0", "description": "Babel Types is a Lodash-esque utility library for AST nodes", "author": "Sebastian McKenzie ", "homepage": "https://babeljs.io/", @@ -8,9 +8,12 @@ "repository": "https://github.com/babel/babel/tree/master/packages/babel-types", "main": "lib/index.js", "dependencies": { - "babel-runtime": "^6.9.1", + "babel-runtime": "^6.20.0", "esutils": "^2.0.2", "lodash": "^4.2.0", "to-fast-properties": "^1.0.1" + }, + "devDependencies": { + "babylon": "^6.8.2" } } diff --git a/packages/babel-types/src/definitions/experimental.js b/packages/babel-types/src/definitions/experimental.js index afe11aa07c45..17949eaa4c66 100644 --- a/packages/babel-types/src/definitions/experimental.js +++ b/packages/babel-types/src/definitions/experimental.js @@ -35,6 +35,10 @@ defineType("BindExpression", { } }); +defineType("Import", { + aliases: ["Expression"] +}); + defineType("Decorator", { visitor: ["expression"], fields: { diff --git a/packages/babel-types/src/index.js b/packages/babel-types/src/index.js index e87118b29b5e..a5ae2c93257e 100644 --- a/packages/babel-types/src/index.js +++ b/packages/babel-types/src/index.js @@ -259,6 +259,7 @@ export function ensureBlock(node: Object, key: string = "body"): Object { */ export function clone(node: Object): Object { + if (!node) return node; let newNode = {}; for (let key in node) { if (key[0] === "_") continue; @@ -283,6 +284,7 @@ export function cloneWithoutLoc(node: Object): Object { */ export function cloneDeep(node: Object): Object { + if (!node) return node; let newNode = {}; for (let key in node) { @@ -529,7 +531,8 @@ export { isVar, isSpecifierDefault, isScope, - isImmutable + isImmutable, + isNodesEquivalent } from "./validators"; export { diff --git a/packages/babel-types/src/validators.js b/packages/babel-types/src/validators.js index 46b2c81fba8a..78ea84cb40f8 100644 --- a/packages/babel-types/src/validators.js +++ b/packages/babel-types/src/validators.js @@ -238,3 +238,47 @@ export function isImmutable(node: Object): boolean { return false; } + +/** + * Check if two nodes are equivalent + */ + +export function isNodesEquivalent(a, b) { + if (typeof a !== "object" || typeof a !== "object" || a == null || b == null) { + return a === b; + } + + if (a.type !== b.type) { + return false; + } + + const fields = Object.keys(t.NODE_FIELDS[a.type] || a.type); + + for (let field of fields) { + if (typeof a[field] !== typeof b[field]) { + return false; + } + + if (Array.isArray(a[field])) { + if (!Array.isArray(b[field])) { + return false; + } + if (a[field].length !== b[field].length) { + return false; + } + + for (let i = 0; i < a[field].length; i++) { + if (!isNodesEquivalent(a[field][i], b[field][i])) { + return false; + } + } + continue; + } + + if (!isNodesEquivalent(a[field], b[field])) { + return false; + } + } + + return true; +} diff --git a/packages/babel-types/test/cloning.js b/packages/babel-types/test/cloning.js new file mode 100644 index 000000000000..817a4e1ec467 --- /dev/null +++ b/packages/babel-types/test/cloning.js @@ -0,0 +1,69 @@ +let t = require("../lib"); +let assert = require("assert"); +let parse = require("babylon").parse; + +suite("cloning", function () { + suite("clone", function () { + it("should handle undefined", function () { + let node = undefined; + let cloned = t.clone(node); + assert(cloned === undefined); + }); + + it("should handle null", function () { + let node = null; + let cloned = t.clone(node); + assert(cloned === null); + }); + + it("should handle simple cases", function () { + let node = t.arrayExpression([null, t.identifier("a")]); + let cloned = t.clone(node); + assert(node !== cloned); + assert(t.isNodesEquivalent(node, cloned) === true); + }); + }); + + suite("cloneDeep", function () { + it("should handle undefined", function () { + let node = undefined; + let cloned = t.cloneDeep(node); + assert(cloned === undefined); + }); + + it("should handle null", function () { + let node = null; + let cloned = t.cloneDeep(node); + assert(cloned === null); + }); + + it("should handle simple cases", function () { + let node = t.arrayExpression([null, t.identifier("a")]); + let cloned = t.cloneDeep(node); + assert(node !== cloned); + assert(t.isNodesEquivalent(node, cloned) === true); + }); + + it("should handle full programs", function () { + let node = parse("1 + 1"); + let cloned = t.cloneDeep(node); + assert(node !== cloned); + assert(t.isNodesEquivalent(node, cloned) === true); + }); + + it("should handle complex programs", function () { + let program = "'use strict'; function lol() { wow();return 1; }"; + let node = parse(program); + let cloned = t.cloneDeep(node); + assert(node !== cloned); + assert(t.isNodesEquivalent(node, cloned) === true); + }); + + it("should handle missing array element", function () { + let node = parse("[,0]"); + let cloned = t.cloneDeep(node); + assert(node !== cloned); + assert(t.isNodesEquivalent(node, cloned) === true); + }); + }); +}); diff --git a/packages/babel-types/test/validators.js b/packages/babel-types/test/validators.js new file mode 100644 index 000000000000..c269614f48bc --- /dev/null +++ b/packages/babel-types/test/validators.js @@ -0,0 +1,30 @@ +let t = require("../lib"); +let assert = require("assert"); +let parse = require("babylon").parse; + +suite("validators", function () { + suite("isNodesEquivalent", function () { + it("should handle simple cases", function () { + let mem = t.memberExpression(t.identifier("a"), t.identifier("b")); + assert(t.isNodesEquivalent(mem, mem) === true); + + let mem2 = t.memberExpression(t.identifier("a"), t.identifier("c")); + assert(t.isNodesEquivalent(mem, mem2) === false); + }); + + it("should handle full programs", function () { + assert(t.isNodesEquivalent(parse("1 + 1"), parse("1+1")) === true); + assert(t.isNodesEquivalent(parse("1 + 1"), parse("1+2")) === false); + }); + + it("should handle complex programs", function () { + let program = "'use strict'; function lol() { wow();return 1; }"; + + assert(t.isNodesEquivalent(parse(program), parse(program)) === true); + + let program2 = "'use strict'; function lol() { wow();return -1; }"; + + assert(t.isNodesEquivalent(parse(program), parse(program2)) === false); + }); + }); +}); diff --git a/scripts/generate-babel-types-docs.js b/scripts/generate-babel-types-docs.js index 2a486d55cf64..c0336b161802 100644 --- a/scripts/generate-babel-types-docs.js +++ b/scripts/generate-babel-types-docs.js @@ -65,7 +65,10 @@ function getType(validator) { throw err; } Object.keys(types.BUILDER_KEYS).sort().forEach(function (key) { - readme.push('### t.' + key[0].toLowerCase() + key.substr(1) + '(' + types.BUILDER_KEYS[key].join(', ') + ')'); + readme.push('### ' + key[0].toLowerCase() + key.substr(1)); + readme.push('```javascript'); + readme.push('t.' + key[0].toLowerCase() + key.substr(1) + '(' + types.BUILDER_KEYS[key].join(', ') + ')'); + readme.push('```'); readme.push(''); readme.push('See also `t.is' + key + '(node, opts)` and `t.assert' + key + '(node, opts)`.'); readme.push(''); @@ -108,6 +111,9 @@ Object.keys(types.BUILDER_KEYS).sort().forEach(function (key) { } readme.push(' - ' + fieldDescription.join('')); }); + + readme.push(''); + readme.push('---'); readme.push(''); }); diff --git a/scripts/test-cov.sh b/scripts/test-cov.sh index 033f40dbc745..9be6c933c437 100755 --- a/scripts/test-cov.sh +++ b/scripts/test-cov.sh @@ -1,4 +1,5 @@ #!/bin/sh set -e -node node_modules/istanbul/lib/cli.js cover node_modules/mocha/bin/_mocha -- `scripts/_get-test-directories.sh` --opts test/mocha.opts +node_modules/.bin/nyc node_modules/mocha/bin/_mocha --opts test/mocha.opts `scripts/_get-test-directories.sh` +node_modules/.bin/nyc report --reporter=json