Compare commits

...

96 Commits

Author SHA1 Message Date
Sebastian McKenzie
ce3c6289a2 v5.6.2 2015-06-22 00:08:52 +01:00
Sebastian McKenzie
0364519869 remove unused import 2015-06-22 00:06:43 +01:00
Sebastian McKenzie
58cda35831 log spread element rest parameter as a candidate instead of replacing it in place - fixes #1796 2015-06-22 00:06:03 +01:00
Sebastian McKenzie
ebaa06f4a2 add ensureBlock path method 2015-06-21 23:59:14 +01:00
Sebastian McKenzie
4b0f624fb3 turn method literal keys into assignments in loose mode - fixes #1797 2015-06-21 23:59:06 +01:00
Sebastian McKenzie
aa0f3ac5d0 5.6.1 2015-06-21 00:07:07 +01:00
Sebastian McKenzie
725906a7dc v5.6.1 2015-06-21 00:05:13 +01:00
Sebastian McKenzie
13d5c94b8b update transformation tests 2015-06-21 00:03:29 +01:00
Sebastian McKenzie
85308a1e8c fix super spread in loose mode 2015-06-21 00:01:19 +01:00
Sebastian McKenzie
83bcaba1a5 downgrade to babel 5.5.7 2015-06-21 00:01:11 +01:00
Sebastian McKenzie
185648cb2c 5.6.0 2015-06-20 23:44:46 +01:00
Sebastian McKenzie
be355fc1c6 fix build-runtime script 2015-06-20 23:37:46 +01:00
Sebastian McKenzie
7795e11d58 v5.6.0 2015-06-20 23:35:51 +01:00
Sebastian McKenzie
8f74e8068c fix generation tests to reflect acorn update 2015-06-20 23:35:02 +01:00
Sebastian McKenzie
4f08a77230 resync with upstream acorn 2015-06-20 23:28:49 +01:00
Sebastian McKenzie
4ac33d62af move spec.functionName transformer to builtin-basic - fixes #1743 2015-06-20 22:51:20 +01:00
Sebastian McKenzie
2710a914e8 add noop transform method to IgnoreFormatter 2015-06-20 22:48:45 +01:00
Sebastian McKenzie
8934e7f9da Merge branch 'master' of github.com:babel/babel 2015-06-20 22:48:00 +01:00
Sebastian McKenzie
b4f18e05fa Merge pull request #1776 from zertosh/matches-pattern-this
matchPattern fixes and "this" handling
2015-06-20 22:47:52 +01:00
Sebastian McKenzie
c07540a2c4 extend module IgnoreFormatter from DefaultFormatter - fixes #1763, closes #1771 2015-06-20 22:47:32 +01:00
Sebastian McKenzie
c409f63bbe Merge pull request #1772 from arthurvr/booleanify-tests
Add tests for util.booleanify
2015-06-20 22:22:08 +01:00
Sebastian McKenzie
d3c30b669f update babel-plugin-runtime 2015-06-20 22:21:44 +01:00
Sebastian McKenzie
d10856d16c don't terminate CLI when watching files fail compilation on init - fixes #1678 2015-06-20 22:14:21 +01:00
Sebastian McKenzie
fb08a519c8 register labels as bindings - fixes #1747 2015-06-20 22:10:29 +01:00
Sebastian McKenzie
6a8ecf2507 add uniq to filenames in babel-cli - fixes #1731 2015-06-20 22:04:33 +01:00
Sebastian McKenzie
100317e0c8 split react displayName addition into a plugin - fixes #1761 2015-06-20 22:01:40 +01:00
Sebastian McKenzie
a32f744341 disable module import receiver when in loose mode - fixes #1788 2015-06-20 21:49:31 +01:00
Sebastian McKenzie
c4feff3cb7 add more whitespace 2015-06-20 21:49:01 +01:00
Sebastian McKenzie
498297ce6b check for invalid binding identifiers when generating inferred method names - fixes #1794 2015-06-20 21:48:42 +01:00
Sebastian McKenzie
2412c1d502 remove bluebird 2015-06-20 21:48:18 +01:00
Sebastian McKenzie
d92e1a4fb8 Merge pull request #1793 from lydell/patch-1
Update to js-tokens@1.0.1
2015-06-20 13:28:27 +01:00
Simon Lydell
1d0d050413 Update to js-tokens@1.0.1 2015-06-20 09:03:26 +02:00
Sebastian McKenzie
a607ac0077 Merge pull request #1786 from callumacrae/update-regenerator
Update regenerator
2015-06-18 17:57:43 +01:00
Callum Macrae
41f5e7c077 removed ^ from regenerator 2015-06-18 17:57:04 +01:00
Callum Macrae
99604362ed update regenerator 2015-06-18 17:52:16 +01:00
Sebastian McKenzie
2c8e374eaf add back non-es5 number guard in literal code gen 2015-06-17 22:56:08 +01:00
Sebastian McKenzie
238c68f829 fix member expression generation on object integers 2015-06-17 22:54:45 +01:00
Ingvar Stepanyan
09b334ad21 Add guard against non-ES5 integer literals. 2015-06-17 21:11:20 +03:00
Sebastian McKenzie
d647ede94b fix up raw number literal 2015-06-17 17:58:03 +01:00
Sebastian McKenzie
6386b60b9a add comments to types generator 2015-06-17 16:53:23 +01:00
Sebastian McKenzie
25749a9933 clear properties to undefined in traverse.removeProperties 2015-06-17 16:53:08 +01:00
Ingvar Stepanyan
fd4c0dae95 Generate original number representation when value was not changed. 2015-06-17 18:20:35 +03:00
Andres Suarez
80d362c534 fix matchesPattern with deep member expressions 2015-06-16 23:37:32 -04:00
Andres Suarez
59820b9a84 matchesPattern recognizes "this" 2015-06-16 22:48:50 -04:00
Sebastian McKenzie
f6ff366edf add getEarliestCommonAncestorFrom jsdoc description 2015-06-17 02:40:15 +01:00
Sebastian McKenzie
c7cac7aaba add deply nested smart insertion of rest parameter allocation 2015-06-17 02:34:42 +01:00
Sebastian McKenzie
0647d374a3 add more comments 2015-06-17 02:09:38 +01:00
Sebastian McKenzie
25c2816a85 fix ancestry index loopup in Path#getEarliestCommonAncestorFrom 2015-06-17 02:07:35 +01:00
Sebastian McKenzie
b57a80ecae optimise rest parameters in spread element position and allocate rest array at the earliest common ancestor of all references - fixes #1768 2015-06-17 01:57:14 +01:00
Sebastian McKenzie
574d47a571 finish removal of esquery 2015-06-17 01:56:01 +01:00
Sebastian McKenzie
7c5d2b19b7 remove esquery 2015-06-17 01:38:49 +01:00
Arthur Verschaeve
c7669f44c1 Add tests for util.booleanify 2015-06-16 20:18:33 +02:00
Sebastian McKenzie
0ed5c5f480 add check for JSXMemberExpression to t.isReferenced 2015-06-16 02:29:59 +01:00
Sebastian McKenzie
94c34e0132 throw error when attemping to replace a Program root node with another node not of type Program - closes #1762 2015-06-16 01:53:53 +01:00
Sebastian McKenzie
92c4bbd003 remove unused import 2015-06-16 00:43:41 +01:00
Sebastian McKenzie
ec8e840841 upgrade babel-plugin-undeclared-variables-check 2015-06-16 00:42:30 +01:00
Sebastian McKenzie
1c3c64c12c add modulesDuplicateDeclarations message 2015-06-16 00:42:21 +01:00
Sebastian McKenzie
cae80d6e9b add scope to addImport importSpecifier call 2015-06-16 00:42:13 +01:00
Sebastian McKenzie
aaf29ddd82 move validation.undeclaredVariableCheck up 2015-06-16 00:42:03 +01:00
Sebastian McKenzie
fb485567b9 support module live bindings in arbitary positions not in Program statement position - fixes #1760 2015-06-16 00:41:53 +01:00
Sebastian McKenzie
050bcec617 add messages property to plugin context and add --copy-files flag to babel-plugin build 2015-06-15 18:55:03 +01:00
Sebastian McKenzie
6231015557 fix spelling mistake in CONTRIBUTING 2015-06-15 18:54:23 +01:00
Sebastian McKenzie
822eb47ee7 move more transformers into plugins 2015-06-15 18:54:14 +01:00
Sebastian McKenzie
91161ae9a1 Merge pull request #1758 from pygy/master
Add tests for IIFEs as default exports.
2015-06-15 18:36:27 +01:00
Pierre-Yves Gerardy
4c1b4b6490 Add tests for IIFEs as default exports. 2015-06-15 19:28:17 +02:00
Sebastian McKenzie
e792256087 add parse and traverse to plugin babel context 2015-06-15 16:36:56 +01:00
Sebastian McKenzie
19ad22f6e8 update tests to reflect new plugin api 2015-06-15 16:36:45 +01:00
Sebastian McKenzie
01818a50fa fix up babel-plugin CLI 2015-06-15 16:36:34 +01:00
Sebastian McKenzie
3247851019 yank out more transformers and put them into plugins 2015-06-15 16:35:41 +01:00
Sebastian McKenzie
939c00d33c Merge branch 'master' of github.com:babel/babel 2015-06-15 15:18:35 +01:00
Sebastian McKenzie
8b096ac705 start movement of core into plugins 2015-06-15 15:17:04 +01:00
Sebastian McKenzie
30c4a0cf06 Merge pull request #1726 from tikotzky/fix-require-hook-under-istanbul
Fix require hook under istanbul
2015-06-15 11:09:41 +01:00
Sebastian McKenzie
e08d400b36 Merge pull request #1733 from hzoo/i-1732
remove empty strings from beginning of template - fixes #1732
2015-06-15 10:46:28 +01:00
Sebastian McKenzie
7e080aa9d2 Merge pull request #1753 from loganfsmyth/optimize-call
Optimize NodePath#call a bit
2015-06-15 10:46:10 +01:00
Sebastian McKenzie
c0e5059634 Merge pull request #1752 from loganfsmyth/hidden-class-change
Initialize properties to avoid hidden class thrashing.
2015-06-15 10:45:30 +01:00
Logan Smyth
f8f5684faa Avoid concatenating callbacks and ensure that callback lists are arrays ahead of time. 2015-06-14 23:00:38 -07:00
Logan Smyth
2c3e9fbc07 Initialize properties to avoid hidden class thrashing. 2015-06-14 22:26:44 -07:00
Sebastian McKenzie
b9d066d953 add special case for null in get helper 2015-06-15 00:15:22 +01:00
Sebastian McKenzie
94e15b0750 remove unused variable 2015-06-14 23:52:09 +01:00
Sebastian McKenzie
3256c1d120 Merge branch 'master' of github.com:babel/babel 2015-06-14 23:44:30 +01:00
Sebastian McKenzie
eba9f0ffbd clean up default constructor in derived classes - fixes #1748 2015-06-14 23:44:21 +01:00
Sebastian McKenzie
52c3c143f9 add BindingIdentifier virtual type 2015-06-14 20:21:02 +01:00
Brian Donovan
b0f797205b Merge pull request #1744 from silfverstrom/bugg/typo-in-messages
Fixed very minor typo in messages.js.
2015-06-14 07:57:25 -07:00
Niklas Silfverström
dd52c6a687 Fixed very minor typo in messages.js. 2015-06-14 08:06:55 +02:00
Mordy Tikotzky
3cf773b528 fix register hook when not registering for .js extension. 2015-06-14 00:31:14 -04:00
Henry Zhu
98424f80af template-literals: remove unnecessary strings, only add "" to beginning if second node isn't a string - fixes #1732 2015-06-13 14:34:33 -04:00
Sebastian McKenzie
708879ff1b fix auxiliary comment option in makefile 2015-06-13 19:01:50 +01:00
Sebastian McKenzie
70042bb0a8 update internal babel version to latest 2015-06-13 18:57:22 +01:00
Sebastian McKenzie
0f7711a202 5.5.8 2015-06-13 18:54:52 +01:00
Sebastian McKenzie
27f039488e v5.5.8 2015-06-13 18:53:41 +01:00
Sebastian McKenzie
e3ce82e12f remove console.log 2015-06-13 18:50:51 +01:00
Sebastian McKenzie
4934ea56a0 change NodePath#inType to use arguments instead of types 2015-06-13 18:50:19 +01:00
Sebastian McKenzie
ce03457b19 add getOpposite path method 2015-06-13 18:50:05 +01:00
Sebastian McKenzie
1298c67949 rename getOwnBindingInfo to getOwnBinding 2015-06-13 18:49:59 +01:00
Sebastian McKenzie
668274edcb remove resolve-rc file 2015-06-13 18:49:37 +01:00
Sebastian McKenzie
0694a7dd06 5.5.7 2015-06-13 02:23:28 +01:00
223 changed files with 3031 additions and 2802 deletions

View File

@@ -17,7 +17,8 @@
"no-fallthrough": 0,
"new-cap": 0,
"no-loop-func": 0,
"no-unreachable": 0
"no-unreachable": 0,
"no-labels": 0
},
"env": {
"node": true

View File

@@ -13,6 +13,51 @@ _Note: Gaps between patch versions are faulty/broken releases._
See [CHANGELOG - 6to5](CHANGELOG-6to5.md) for the pre-4.0.0 version changelog.
## 5.6.0
* **Bug Fix**
* Fix istanbul interop for register hook when registering for non-existence extension.
* Fix super class constructor call differing for no constructor in derived classes.
* Disable module import receiver when in loose mode.
* Fix duplicate filenames when using `babel` CLI when passing multiple matching patterns.
* Register labels as bindings to fix undeclared variable checks.
* **Polish**
* Remove unnecessary string binary expressions when transforming template literals.
* Support module live bindings in arbitary positions not in Program statement position.
* Throw error when attemping to replace a `Program` root node with another node not of type `Program`.
* Optimise rest parameters in spread element position and allocate rest array at the earliest common ancestor of all references.
* Generate original number representation when value was not changed.
* Check for invalid binding identifiers when generating inferred method names.
* Don't terminate CLI when watching files fail compilation on init.
* **New Feature**
* Add new plugin API.
* **Internal**
* Split react displayName addition into a plugin.
* Add check for `JSXMemberExpression` to `t.isReferenced`.
* Move `validation.undeclaredVariableCheck` transformer up.
* Start great core-to-plugin exodus.
* Add `BindingIdentifier` virtual type.
* Hidden class optimisations.
* Array allocation optimisations.
* Update `regenerator`.
* Update `js-tokens`.
* Sync with upstream Acorn.
## 5.5.8
* **Internal**
* Remove extremely unprofessional and harsh error message for those hotlinking to `resolve-rc`.
## 5.5.7
* **Bug Fix**
* Push newline after decorators when doing code gen.
* Rewriting error handling to normalise options before merging them.
* Remove duplicate keys in `alias-keys.json` causing errors in strict mode.
* Fix `$ babel --help` not showing optional transformers as such.
* **New Feature**
* Add `auxiliaryCommentBefore` and `auxiliaryCommentAfter` options.
## 5.5.6
* **Bug Fix**

View File

@@ -24,11 +24,10 @@ Contributions are always welcome, no matter how large or small. Before
contributing, please read the
[code of conduct](https://github.com/babel/babel/blob/master/CODE_OF_CONDUCT.md).
## Developing
>Note: Babel moves fast. Only the latest release is guaranteed to build correctly.
>Older releases are not officially supported. If you attempt to build them, do that at your own risk.
> Note: Babel moves fast. Only the latest release is guaranteed to build correctly.
> Older releases are not officially supported. If you attempt to build them, do that at your own risk.
#### Setup

View File

@@ -15,7 +15,7 @@ build-core: clean-core
node $(BABEL_CMD) src --out-dir lib --copy-files
build-core-test: clean-core
node $(BABEL_CMD) src --out-dir lib --copy-files --auxiliary-comment "istanbul ignore next"
node $(BABEL_CMD) src --out-dir lib --copy-files --auxiliary-comment-before "istanbul ignore next"
watch-core: clean-core
node $(BABEL_CMD) src --out-dir lib --watch --copy-files

View File

@@ -1,7 +1,7 @@
{
"name": "babel-core",
"description": "A compiler for writing next generation JavaScript",
"version": "5.5.7",
"version": "5.6.2",
"author": "Sebastian McKenzie <sebmck@gmail.com>",
"homepage": "https://babeljs.io/",
"license": "MIT",
@@ -30,20 +30,33 @@
"dependencies": {
"acorn-jsx": "^1.0.0",
"ast-types": "~0.7.0",
"bluebird": "^2.9.25",
"babel-plugin-constant-folding": "^1.0.1",
"babel-plugin-dead-code-elimination": "^1.0.1",
"babel-plugin-eval": "^1.0.1",
"babel-plugin-inline-environment-variables": "^1.0.1",
"babel-plugin-jscript": "^1.0.1",
"babel-plugin-member-expression-literals": "^1.0.1",
"babel-plugin-property-literals": "^1.0.1",
"babel-plugin-proto-to-assign": "^1.0.3",
"babel-plugin-react-constant-elements": "^1.0.3",
"babel-plugin-react-display-name": "^1.0.3",
"babel-plugin-remove-console": "^1.0.1",
"babel-plugin-remove-debugger": "^1.0.1",
"babel-plugin-runtime": "^1.0.7",
"babel-plugin-undeclared-variables-check": "^1.0.2",
"babel-plugin-undefined-to-void": "^1.1.6",
"chalk": "^1.0.0",
"convert-source-map": "^1.1.0",
"core-js": "^0.9.0",
"debug": "^2.1.1",
"detect-indent": "^3.0.0",
"esquery": "^0.4.0",
"estraverse": "^4.0.0",
"esutils": "^2.0.0",
"fs-readdir-recursive": "^0.1.0",
"globals": "^6.4.0",
"home-or-tmp": "^1.0.0",
"is-integer": "^1.0.4",
"js-tokens": "1.0.0",
"js-tokens": "1.0.1",
"leven": "^1.0.1",
"line-numbers": "0.2.0",
"lodash": "^3.6.0",
@@ -51,7 +64,7 @@
"output-file-sync": "^1.1.0",
"path-is-absolute": "^1.0.0",
"private": "^0.1.6",
"regenerator": "0.8.28",
"regenerator": "0.8.30",
"regexpu": "^1.1.2",
"repeating": "^1.1.2",
"resolve": "^1.1.6",
@@ -64,7 +77,7 @@
"trim-right": "^1.0.0"
},
"devDependencies": {
"babel": "5.3.1",
"babel": "5.5.7",
"browserify": "^9.0.8",
"chai": "^2.2.0",
"eslint": "^0.21.2",

View File

@@ -0,0 +1,140 @@
#!/usr/bin/env node
var readline = require("readline");
var child = require("child_process");
var path = require("path");
var fs = require("fs");
function spawn(cmd, args, callback) {
console.log(">", cmd, args);
var spawn = child.spawn(cmd, args, { stdio: "inherit" });
spawn.on("exit", function (code) {
if (code === 0) {
if (callback) callback();
} else {
console.log("Killing...");
process.exit(1);
}
});
}
function spawnMultiple(cmds) {
function next() {
var cmd = cmds.shift();
if (cmd) {
spawn(cmd.command, cmd.args, next);
} else {
process.exit();
}
}
next();
}
function template(name, data) {
var source = fs.readFileSync(__dirname + "/templates/" + name, "utf8");
source = source.replace(/[A-Z_]+/g, function (key) {
return data[key] === undefined ? key : data[key];
});
return source;
}
function write(filename, content) {
console.log(filename);
fs.writeFileSync(filename, content);
}
var rl = readline.createInterface({
input: process.stdin,
output: process.stdout
});
var BABEL_PLUGIN_PREFIX = "babel-plugin-";
var cmds = {
init: function () {
var name = path.basename(process.cwd());
if (name.indexOf(BABEL_PLUGIN_PREFIX) === 0) {
name = name.slice(BABEL_PLUGIN_PREFIX.length);
}
rl.question("Description (optional): ", function (description) {
rl.question("GitHub Repository (eg. sebmck/babel-plugin-foobar) (optional): ", function (repo) {
rl.close();
var templateData = {
DESCRIPTION: description,
FULL_NAME: BABEL_PLUGIN_PREFIX + name,
NAME: name
};
write("package.json", JSON.stringify({
name: templateData.FULL_NAME,
version: "1.0.0",
description: templateData.DESCRIPTION,
repository: repo || undefined,
license: "MIT",
main: "lib/index.js",
devDependencies: {
babel: "^5.6.0"
},
scripts: {
build: "babel-plugin build",
push: "babel-plugin publish",
test: "babel-plugin test"
},
keywords: ["babel-plugin"]
}, null, " ") + "\n");
write(".npmignore", "node_modules\n*.log\nsrc\n");
write(".gitignore", "node_modules\n*.log\nlib\n");
write("README.md", template("README.md", templateData));
if (!fs.existsSync("src")) {
fs.mkdirSync("src");
write("src/index.js", template("index.js", templateData));
}
});
});
},
build: function () {
spawn("babel", ["src", "--out-dir", "lib", "--copy-files"]);
},
publish: function () {
var pkg = require(process.cwd() + "/package.json");
console.log("Current verison:", pkg.version);
rl.question("New version (enter nothing for patch): ", function (newVersion) {
rl.close();
newVersion = newVersion || "patch";
spawnMultiple([
{ command: "git", args: ["pull"] },
{ command: "git", args: ["push"] },
{ command: "babel-plugin", args: ["build"] },
{ command: "npm", args: ["version", newVersion] },
{ command: "npm", args: ["publish"] },
{ command: "git", args: ["push", "--follow-tags"] }
]);
});
}
};
var cmd = cmds[process.argv[2]];
if (cmd) {
cmd();
} else {
console.error("Unknown command:", cmd);
process.exit(1);
}

View File

@@ -0,0 +1,35 @@
# FULL_NAME
DESCRIPTION
## Installation
```sh
$ npm install FULL_NAME
```
## Usage
### Via `.babelrc` (Recommended)
**.babelrc**
```json
{
"plugins": ["NAME"]
}
```
### Via CLI
```sh
$ babel --plugins NAME script.js
```
### Via Node API
```javascript
require("babel-core").transform("code", {
plugins: ["NAME"]
});
```

View File

@@ -0,0 +1,7 @@
export default function ({ Plugin, types: t }) {
return new Plugin("NAME", {
visitor: {
// your visitor methods go here
}
});
}

View File

@@ -6,6 +6,7 @@ var transform = require("babel-core").transform;
var kebabCase = require("lodash/string/kebabCase");
var options = require("babel-core").options;
var util = require("babel-core").util;
var uniq = require("lodash/array/uniq");
var each = require("lodash/collection/each");
var keys = require("lodash/object/keys");
var fs = require("fs");
@@ -84,6 +85,8 @@ var filenames = commander.args.reduce(function (globbed, input) {
return globbed.concat(files);
}, []);
filenames = uniq(filenames);
each(filenames, function (filename) {
if (!fs.existsSync(filename)) {
errors.push(filename + " doesn't exist");

View File

@@ -1,10 +1,11 @@
var readdir = require("fs-readdir-recursive");
var index = require("./index");
var babel = require("babel-core");
var util = require("babel-core").util;
var path = require("path");
var fs = require("fs");
var _ = require("lodash");
var commander = require("commander");
var readdir = require("fs-readdir-recursive");
var index = require("./index");
var babel = require("babel-core");
var util = require("babel-core").util;
var path = require("path");
var fs = require("fs");
var _ = require("lodash");
exports.readdirFilter = function (filename) {
return readdir(filename).filter(function (filename) {
@@ -37,6 +38,15 @@ exports.transform = function (filename, code, opts) {
};
exports.compile = function (filename, opts) {
var code = fs.readFileSync(filename, "utf8");
return exports.transform(filename, code, opts);
try {
var code = fs.readFileSync(filename, "utf8");
return exports.transform(filename, code, opts);
} catch (err) {
if (commander.watch) {
console.error(err.stack);
return { ignored: true };
} else {
throw err;
}
}
};

View File

@@ -1,14 +1,14 @@
{
"name": "babel",
"description": "Turn ES6 code into readable vanilla ES5 with source maps",
"version": "5.5.6",
"version": "5.6.1",
"author": "Sebastian McKenzie <sebmck@gmail.com>",
"homepage": "https://babeljs.io/",
"license": "MIT",
"repository": "babel/babel",
"preferGlobal": true,
"dependencies": {
"babel-core": "^5.5.6",
"babel-core": "^5.6.1",
"chokidar": "^1.0.0",
"commander": "^2.6.0",
"convert-source-map": "^1.1.0",
@@ -23,6 +23,7 @@
"bin": {
"babel": "./bin/babel/index.js",
"babel-node": "./bin/babel-node",
"babel-external-helpers": "./bin/babel-external-helpers"
"babel-external-helpers": "./bin/babel-external-helpers",
"babel-plugin": "./bin/babel-plugin/index.js"
}
}

View File

@@ -1,7 +1,7 @@
{
"name": "babel-runtime",
"description": "babel selfContained runtime",
"version": "5.5.6",
"version": "5.6.1",
"license": "MIT",
"repository": "babel/babel",
"author": "Sebastian McKenzie <sebmck@gmail.com>",

View File

@@ -75,7 +75,7 @@ writeFile("regenerator/runtime.js", selfContainify(readFile("regenerator/runtime
//
var coreDefinitions = require("../lib/babel/transformation/transformers/other/runtime/definitions");
var coreDefinitions = require("babel-plugin-runtime/lib/definitions");
var paths = ["is-iterable", "get-iterator"];

View File

@@ -29,14 +29,23 @@ const pp = Parser.prototype
// strict mode, init properties are also not allowed to be repeated.
pp.checkPropClash = function(prop, propHash) {
if (this.options.ecmaVersion >= 6) return
if (this.options.ecmaVersion >= 6 && (prop.computed || prop.method || prop.shorthand))
return
let key = prop.key, name
switch (key.type) {
case "Identifier": name = key.name; break
case "Literal": name = String(key.value); break
default: return
}
let kind = prop.kind || "init", other
let kind = prop.kind
if (this.options.ecmaVersion >= 6) {
if (name === "__proto__" && kind === "init") {
if (propHash.proto) this.raise(key.start, "Redefinition of __proto__ property");
propHash.proto = true
}
return
}
let other
if (has(propHash, name)) {
other = propHash[name]
let isGetSet = kind !== "init"
@@ -260,8 +269,10 @@ pp.parseNoCallExpr = function() {
pp.parseExprAtom = function(refShorthandDefaultPos) {
let node, canBeArrow = this.potentialArrowAt == this.start
switch (this.type) {
case tt._this:
case tt._super:
if (!this.inFunction)
this.raise(this.start, "'super' outside of function or class")
case tt._this:
let type = this.type === tt._this ? "ThisExpression" : "Super"
node = this.startNode()
this.next()
@@ -609,6 +620,14 @@ pp.parseObjPropValue = function (prop, start, isGenerator, isAsync, isPattern, r
prop.kind = prop.key.name
this.parsePropertyName(prop)
prop.value = this.parseMethod(false)
let paramCount = prop.kind === "get" ? 0 : 1
if (prop.value.params.length !== paramCount) {
let start = prop.value.start
if (prop.kind === "get")
this.raise(start, "getter should have no params");
else
this.raise(start, "setter should have exactly one param")
}
} else if (this.options.ecmaVersion >= 6 && !prop.computed && prop.key.type === "Identifier") {
prop.kind = "init"
if (isPattern) {
@@ -634,12 +653,12 @@ pp.parsePropertyName = function(prop) {
prop.computed = true
prop.key = this.parseMaybeAssign()
this.expect(tt.bracketR)
return
return prop.key
} else {
prop.computed = false
}
}
prop.key = (this.type === tt.num || this.type === tt.string) ? this.parseExprAtom() : this.parseIdent(true)
return prop.key = (this.type === tt.num || this.type === tt.string) ? this.parseExprAtom() : this.parseIdent(true)
}
// Initialize empty function node.

View File

@@ -35,6 +35,7 @@ pp.toAssignable = function(node, isBinding) {
case "AssignmentExpression":
if (node.operator === "=") {
node.type = "AssignmentPattern"
delete node.operator
} else {
this.raise(node.left.end, "Only '=' operator can be used for specifying default value.")
}
@@ -171,7 +172,7 @@ pp.checkLVal = function(expr, isBinding, checkClashes) {
break
case "ObjectPattern":
for (let i = 0; i < expr.properties.length; i++) {
for (let i = 0; i < expr.properties.length; i++) {
var prop = expr.properties[i];
if (prop.type === "Property") prop = prop.value;
this.checkLVal(prop, isBinding, checkClashes)
@@ -194,6 +195,10 @@ pp.checkLVal = function(expr, isBinding, checkClashes) {
this.checkLVal(expr.argument, isBinding, checkClashes)
break
case "ParenthesizedExpression":
this.checkLVal(expr.expression, isBinding, checkClashes)
break
default:
this.raise(expr.start, (isBinding ? "Binding" : "Assigning to") + " rvalue")
}

View File

@@ -1,5 +1,6 @@
import {reservedWords, keywords} from "./identifier"
import {types as tt, lineBreak} from "./tokentype"
import {types as tt} from "./tokentype"
import {lineBreak} from "./whitespace"
export function Parser(options, input, startPos) {
this.options = options

View File

@@ -347,7 +347,14 @@ pp.parseLabeledStatement = function(node, maybeName, expr) {
for (let i = 0; i < this.labels.length; ++i)
if (this.labels[i].name === maybeName) this.raise(expr.start, "Label '" + maybeName + "' is already declared")
let kind = this.type.isLoop ? "loop" : this.type === tt._switch ? "switch" : null
this.labels.push({name: maybeName, kind: kind})
for (let i = this.labels.length - 1; i >= 0; i--) {
let label = this.labels[i]
if (label.statementStart == node.start) {
label.statementStart = this.start;
label.kind = kind;
} else break;
}
this.labels.push({name: maybeName, kind: kind, statementStart: this.start})
node.body = this.parseStatement(true)
this.labels.pop()
node.label = expr
@@ -466,6 +473,7 @@ pp.parseClass = function(node, isStatement) {
this.parseClassId(node, isStatement)
this.parseClassSuper(node)
var classBody = this.startNode()
let hadConstructor = false
classBody.body = []
this.expect(tt.braceL)
let decorators = []
@@ -480,16 +488,14 @@ pp.parseClass = function(node, isStatement) {
method.decorators = decorators
decorators = []
}
let isMaybeStatic = this.type === tt.name && this.value === "static"
var isGenerator = this.eat(tt.star), isAsync = false
this.parsePropertyName(method)
if (this.type !== tt.parenL && !method.computed && method.key.type === "Identifier" &&
method.key.name === "static") {
method.static = isMaybeStatic && this.type !== tt.parenL
if (method.static) {
if (isGenerator) this.unexpected()
method['static'] = true
isGenerator = this.eat(tt.star)
this.parsePropertyName(method)
} else {
method['static'] = false
}
if (!isGenerator && method.key.type === "Identifier" && !method.computed && this.isClassProperty()) {
classBody.body.push(this.parseClassProperty(method))
@@ -500,23 +506,39 @@ pp.parseClass = function(node, isStatement) {
isAsync = true
this.parsePropertyName(method)
}
let isGetSet = false
method.kind = "method"
if (!method.computed && !isGenerator && !isAsync) {
if (method.key.type === "Identifier") {
if (this.type !== tt.parenL && (method.key.name === "get" || method.key.name === "set")) {
method.kind = method.key.name
this.parsePropertyName(method)
} else if (!method['static'] && method.key.name === "constructor") {
method.kind = "constructor"
}
} else if (!method['static'] && method.key.type === "Literal" && method.key.value === "constructor") {
if (!method.computed) {
let {key} = method
if (!isAsync && !isGenerator && key.type === "Identifier" && this.type !== tt.parenL && (key.name === "get" || key.name === "set")) {
isGetSet = true
method.kind = key.name
key = this.parsePropertyName(method)
}
if (!method.static && (key.type === "Identifier" && key.name === "constructor" ||
key.type === "Literal" && key.value === "constructor")) {
if (hadConstructor) this.raise(key.start, "Duplicate constructor in the same class")
if (isGetSet) this.raise(key.start, "Constructor can't have get/set modifier")
if (isGenerator) this.raise(key.start, "Constructor can't be a generator")
if (isAsync) this.raise(key.start, "Constructor can't be an async function")
method.kind = "constructor"
hadConstructor = true
}
}
if (method.kind === "constructor" && method.decorators) {
this.raise(method.start, "You can't attach decorators to a class constructor")
}
this.parseClassMethod(classBody, method, isGenerator, isAsync)
if (isGetSet) {
let paramCount = method.kind === "get" ? 0 : 1
if (method.value.params.length !== paramCount) {
let start = method.value.start
if (method.kind === "get")
this.raise(start, "getter should have no params");
else
this.raise(start, "setter should have exactly one param")
}
}
}
if (decorators.length) {
this.raise(this.start, "You have trailing decorators with no method");

View File

@@ -25,6 +25,9 @@ export class Token {
const pp = Parser.prototype
// Are we running under Rhino?
const isRhino = typeof Packages == "object" && Object.prototype.toString.call(Packages) == "[object JavaPackage]"
// Move to the next token
pp.next = function() {
@@ -430,23 +433,30 @@ pp.readRegexp = function() {
// negatives in unlikely scenarios. For example, `[\u{61}-b]` is a
// perfectly valid pattern that is equivalent to `[a-b]`, but it would
// be replaced by `[x-b]` which throws an error.
tmp = tmp.replace(/\\u([a-fA-F0-9]{4})|\\u\{([0-9a-fA-F]+)\}|[\uD800-\uDBFF][\uDC00-\uDFFF]/g, "x")
tmp = tmp.replace(/\\u\{([0-9a-fA-F]+)\}/g, (match, code, offset) => {
code = Number("0x" + code)
if (code > 0x10FFFF) this.raise(start + offset + 3, "Code point out of bounds")
return "x"
});
tmp = tmp.replace(/\\u([a-fA-F0-9]{4})|[\uD800-\uDBFF][\uDC00-\uDFFF]/g, "x")
}
}
// Detect invalid regular expressions.
try {
new RegExp(tmp)
} catch (e) {
if (e instanceof SyntaxError) this.raise(start, "Error parsing regular expression: " + e.message)
this.raise(e)
}
// Get a regular expression object for this pattern-flag pair, or `null` in
// case the current environment doesn't support the flags it uses.
let value
try {
value = new RegExp(content, mods)
} catch (err) {
value = null
let value = null
// Rhino's regular expression parser is flaky and throws uncatchable exceptions,
// so don't do detection if we are running under Rhino
if (!isRhino) {
try {
new RegExp(tmp)
} catch (e) {
if (e instanceof SyntaxError) this.raise(start, "Error parsing regular expression: " + e.message)
this.raise(e)
}
// Get a regular expression object for this pattern-flag pair, or `null` in
// case the current environment doesn't support the flags it uses.
try {
value = new RegExp(content, mods)
} catch (err) {}
}
return this.finishToken(tt.regexp, {pattern: content, flags: mods, value: value})
}
@@ -514,10 +524,10 @@ pp.readCodePoint = function() {
if (ch === 123) {
if (this.options.ecmaVersion < 6) this.unexpected()
++this.pos
let codePos = ++this.pos
code = this.readHexChar(this.input.indexOf('}', this.pos) - this.pos)
++this.pos
if (code > 0x10FFFF) this.unexpected()
if (code > 0x10FFFF) this.raise(codePos, "Code point out of bounds")
} else {
code = this.readHexChar(4)
}
@@ -539,7 +549,7 @@ pp.readString = function(quote) {
if (ch === quote) break
if (ch === 92) { // '\'
out += this.input.slice(chunkStart, this.pos)
out += this.readEscapedChar()
out += this.readEscapedChar(false)
chunkStart = this.pos
} else {
if (isNewLine(ch)) this.raise(this.start, "Unterminated string constant")
@@ -572,7 +582,7 @@ pp.readTmplToken = function() {
}
if (ch === 92) { // '\'
out += this.input.slice(chunkStart, this.pos)
out += this.readEscapedChar()
out += this.readEscapedChar(true)
chunkStart = this.pos
} else if (isNewLine(ch)) {
out += this.input.slice(chunkStart, this.pos)
@@ -600,42 +610,46 @@ pp.readTmplToken = function() {
// Used to read escaped characters
pp.readEscapedChar = function() {
pp.readEscapedChar = function(inTemplate) {
let ch = this.input.charCodeAt(++this.pos)
let octal = /^[0-7]+/.exec(this.input.slice(this.pos, this.pos + 3))
if (octal) octal = octal[0]
while (octal && parseInt(octal, 8) > 255) octal = octal.slice(0, -1)
if (octal === "0") octal = null
++this.pos
if (octal) {
if (this.strict) this.raise(this.pos - 2, "Octal literal in strict mode")
this.pos += octal.length - 1
return String.fromCharCode(parseInt(octal, 8))
} else {
switch (ch) {
case 110: return "\n"; // 'n' -> '\n'
case 114: return "\r"; // 'r' -> '\r'
case 120: return String.fromCharCode(this.readHexChar(2)); // 'x'
case 117: return codePointToString(this.readCodePoint()); // 'u'
case 116: return "\t"; // 't' -> '\t'
case 98: return "\b"; // 'b' -> '\b'
case 118: return "\u000b"; // 'v' -> '\u000b'
case 102: return "\f"; // 'f' -> '\f'
case 48: return "\0"; // 0 -> '\0'
case 13: if (this.input.charCodeAt(this.pos) === 10) ++this.pos; // '\r\n'
case 10: // ' \n'
if (this.options.locations) { this.lineStart = this.pos; ++this.curLine }
return ""
default: return String.fromCharCode(ch)
switch (ch) {
case 110: return "\n"; // 'n' -> '\n'
case 114: return "\r"; // 'r' -> '\r'
case 120: return String.fromCharCode(this.readHexChar(2)); // 'x'
case 117: return codePointToString(this.readCodePoint()); // 'u'
case 116: return "\t"; // 't' -> '\t'
case 98: return "\b"; // 'b' -> '\b'
case 118: return "\u000b"; // 'v' -> '\u000b'
case 102: return "\f"; // 'f' -> '\f'
case 13: if (this.input.charCodeAt(this.pos) === 10) ++this.pos; // '\r\n'
case 10: // ' \n'
if (this.options.locations) { this.lineStart = this.pos; ++this.curLine }
return ""
default:
if (ch >= 48 && ch <= 55) {
let octalStr = this.input.substr(this.pos - 1, 3).match(/^[0-7]+/)[0]
let octal = parseInt(octalStr, 8)
if (octal > 255) {
octalStr = octalStr.slice(0, -1)
octal = parseInt(octalStr, 8)
}
if (octal > 0 && (this.strict || inTemplate)) {
this.raise(this.pos - 2, "Octal literal in strict mode")
}
this.pos += octalStr.length - 1
return String.fromCharCode(octal)
}
return String.fromCharCode(ch)
}
}
// Used to read character escape sequences ('\x', '\u', '\U').
pp.readHexChar = function(len) {
let codePos = this.pos
let n = this.readInt(16, len)
if (n === null) this.raise(this.start, "Bad character escape sequence")
if (n === null) this.raise(codePos, "Bad character escape sequence")
return n
}

View File

@@ -9,8 +9,9 @@ export { pipeline } from "../transformation";
export { canCompile } from "../util";
export { default as options } from "../transformation/file/options/config";
export { default as Plugin } from "../transformation/plugin";
export { default as Transformer } from "../transformation/transformer";
export { default as TransformerPipeline } from "../transformation/transformer-pipeline";
export { default as Pipeline } from "../transformation/pipeline";
export { default as traverse } from "../traversal";
export { default as buildExternalHelpers } from "../tools/build-external-helpers";
export { version } from "../../../package";

View File

@@ -105,7 +105,7 @@ if (process.env.running_under_istanbul) {
if (istanbulMonkey[filename]) {
delete istanbulMonkey[filename];
var code = compile(filename, {
auxiliaryComment: "istanbul ignore next"
auxiliaryCommentBefore: "istanbul ignore next"
});
istanbulMonkey[filename] = true;
return code;
@@ -125,7 +125,7 @@ var normalLoader = function (m, filename) {
};
var registerExtension = function (ext) {
var old = oldHandlers[ext] || oldHandlers[".js"];
var old = oldHandlers[ext] || oldHandlers[".js"] || require.extensions[".js"];
var loader = normalLoader;
if (process.env.running_under_istanbul) loader = istanbulLoader;

View File

@@ -1,4 +1,3 @@
import isInteger from "is-integer";
import isNumber from "lodash/lang/isNumber";
import * as t from "../../types";
@@ -127,6 +126,12 @@ export function ExpressionStatement(node, print) {
this.semicolon();
}
export function AssignmentPattern(node, print) {
print.plain(node.left);
this.push(" = ");
print.plain(node.right);
}
export function AssignmentExpression(node, print) {
// todo: add cases where the spaces can be dropped when in compact mode
print.plain(node.left);
@@ -144,12 +149,9 @@ export function BindExpression(node, print) {
export {
AssignmentExpression as BinaryExpression,
AssignmentExpression as LogicalExpression,
AssignmentExpression as AssignmentPattern
AssignmentExpression as LogicalExpression
};
var SCIENTIFIC_NOTATION = /e/i;
export function MemberExpression(node, print) {
var obj = node.object;
print.plain(obj);
@@ -168,11 +170,6 @@ export function MemberExpression(node, print) {
print.plain(node.property);
this.push("]");
} else {
// 5..toFixed(2);
if (t.isLiteral(obj) && isInteger(obj.value) && !SCIENTIFIC_NOTATION.test(obj.value.toString())) {
this.push(".");
}
this.push(".");
print.plain(node.property);
}

View File

@@ -1,5 +1,6 @@
/* eslint quotes: 0 */
import isInteger from "is-integer";
import * as t from "../../types";
export function Identifier(node) {
@@ -90,14 +91,29 @@ export function ArrayExpression(node, print) {
export { ArrayExpression as ArrayPattern };
export function Literal(node) {
const SCIENTIFIC_NOTATION = /e/i;
export function Literal(node, print, parent) {
var val = node.value;
var type = typeof val;
if (type === "string") {
this._stringLiteral(val);
} else if (type === "number") {
this.push(val + "");
// check to see if this is the same number as the raw one in the original source as asm.js uses
// numbers in the form 5.0 for type hinting
var raw = node.raw;
if (val === +raw && raw[raw.length - 1] !== "." && !/^0[bo]/i.test(raw)) {
val = raw;
}
val = val + "";
if (isInteger(+val) && t.isMemberExpression(parent, { object: node }) && !SCIENTIFIC_NOTATION.test(val)) {
val += ".";
}
this.push(val);
} else if (type === "boolean") {
this.push(val ? "true" : "false");
} else if (node.regex) {
@@ -116,9 +132,16 @@ export function _stringLiteral(val) {
});
if (this.format.quotes === "single") {
// remove double quotes
val = val.slice(1, -1);
// unescape double quotes
val = val.replace(/\\"/g, '"');
// escape single quotes
val = val.replace(/'/g, "\\'");
// add single quotes
val = `'${val}'`;
}

View File

@@ -79,9 +79,11 @@ export default function (lines: number, lineNumber: number, colNumber: number, o
if (params.number !== lineNumber) {
return;
}
if (colNumber) {
params.line += `\n${params.before}${repeating(" ", params.width)}${params.after}${repeating(" ", colNumber - 1)}^`;
}
params.before = params.before.replace(/^./, ">");
}
}).join("\n");

View File

@@ -5,15 +5,12 @@ export const MESSAGES = {
JSXNamespacedTags: "Namespace tags are not supported. ReactJSX is not XML.",
classesIllegalBareSuper: "Illegal use of bare super",
classesIllegalSuperCall: "Direct super call is illegal in non-constructor, use super.$1() instead",
classesIllegalConstructorKind: "Illegal kind for constructor method",
scopeDuplicateDeclaration: "Duplicate declaration $1",
settersInvalidParamLength: "Setters must have exactly one parameter",
settersNoRest: "Setters aren't allowed to have a rest",
noAssignmentsInForHead: "No assignments allowed in for-in/of head",
expectedMemberExpressionOrIdentifier: "Expected type MemeberExpression or Identifier",
expectedMemberExpressionOrIdentifier: "Expected type MemberExpression or Identifier",
invalidParentForThisNode: "We don't know how to handle this node within the current parent - please open an issue",
readOnly: "$1 is read-only",
modulesIllegalExportName: "Illegal export $1",
unknownForHead: "Unknown node type $1 in ForStatement",
didYouMean: "Did you mean $1?",
codeGeneratorDeopt: "Note: The code generator has deoptimised the styling of $1 as it exceeds the max of $2.",
@@ -22,6 +19,9 @@ export const MESSAGES = {
illegalMethodName: "Illegal method name $1",
lostTrackNodePath: "We lost track of this nodes position, likely because the AST was directly manipulated",
modulesIllegalExportName: "Illegal export $1",
modulesDuplicateDeclarations: "Duplicate module declarations with the same source but in different scopes",
undeclaredVariable: "Reference to undeclared variable $1",
undeclaredVariableType: "Referencing a type alias outside of a type annotation",
undeclaredVariableSuggestion: "Reference to undeclared variable $1 - did you mean $2?",
@@ -34,10 +34,10 @@ export const MESSAGES = {
pluginIllegalKind: "Illegal kind $1 for plugin $2",
pluginIllegalPosition: "Illegal position $1 for plugin $2",
pluginKeyCollision: "The plugin $1 collides with another of the same name",
pluginNotTransformer: "The plugin $1 didn't export a Transformer instance",
pluginNotTransformer: "The plugin $1 didn't export a Plugin instance",
pluginUnknown: "Unknown plugin $1",
transformerNotFile: "Transformer $1 is resolving to a different Babel version to what is doing the actual transformation..."
pluginNotFile: "Plugin $1 is resolving to a different Babel version to what is doing the actual transformation..."
};
export function get(key: String, ...args) {

View File

@@ -1,5 +0,0 @@
console.trace("I know someone out there is hotlinking straight to this file. This is a " +
"PRIVATE API. I hate you, but I wont break your code just because you're a " +
"programmer who practices bad habits.");
export { default } from "../transformation/file/options/resolve-rc";

View File

@@ -4,7 +4,6 @@ import moduleFormatters from "../modules";
import PluginManager from "./plugin-manager";
import shebangRegex from "shebang-regex";
import NodePath from "../../traversal/path";
import Transformer from "../transformer";
import isFunction from "lodash/lang/isFunction";
import isAbsolute from "path-is-absolute";
import resolveRc from "./options/resolve-rc";
@@ -14,13 +13,14 @@ import codeFrame from "../../helpers/code-frame";
import defaults from "lodash/object/defaults";
import includes from "lodash/collection/includes";
import traverse from "../../traversal";
import Hub from "../../traversal/hub";
import assign from "lodash/object/assign";
import Logger from "./logger";
import Plugin from "../plugin";
import parse from "../../helpers/parse";
import merge from "../../helpers/merge";
import slash from "slash";
import clone from "lodash/lang/clone";
import Hub from "../../traversal/hub";
import * as util from "../../util";
import path from "path";
import * as t from "../../types";
@@ -246,7 +246,7 @@ export default class File {
// build dependency graph
for (let pass of (stack: Array)) {
for (var dep of (pass.transformer.dependencies: Array)) {
for (var dep of (pass.plugin.dependencies: Array)) {
this.transformerDependencies[dep] = pass.key;
}
}
@@ -263,7 +263,7 @@ export default class File {
// been merged
if (ignore.indexOf(pass) >= 0) continue;
var group = pass.transformer.metadata.group;
var group = pass.plugin.metadata.group;
// can't merge
if (!pass.canTransform() || !group) {
@@ -273,7 +273,7 @@ export default class File {
var mergeStack = [];
for (let pass of (_stack: Array)) {
if (pass.transformer.metadata.group === group) {
if (pass.plugin.metadata.group === group) {
mergeStack.push(pass);
ignore.push(pass);
}
@@ -281,11 +281,11 @@ export default class File {
var visitors = [];
for (let pass of (mergeStack: Array)) {
visitors.push(pass.handlers);
visitors.push(pass.plugin.visitor);
}
var visitor = traverse.visitors.merge(visitors);
var mergeTransformer = new Transformer(group, visitor);
stack.push(mergeTransformer.buildPass(this));
var mergePlugin = new Plugin(group, { visitor });
stack.push(mergePlugin.buildPass(this));
}
return stack;
@@ -335,7 +335,7 @@ export default class File {
}
if (this.transformers["es6.modules"].canTransform()) {
this.moduleFormatter.importSpecifier(specifiers[0], declar, this.dynamicImports);
this.moduleFormatter.importSpecifier(specifiers[0], declar, this.dynamicImports, this.scope);
this.moduleFormatter.hasLocalImports = true;
} else {
this.dynamicImports.push(declar);
@@ -586,7 +586,7 @@ export default class File {
call(key: string) {
for (var pass of (this.uncollapsedTransformerStack: Array)) {
var fn = pass.transformer[key];
var fn = pass.plugin[key];
if (fn) fn(this);
}
}

View File

@@ -1,5 +1,19 @@
import * as node from "../../api/node";
import Transformer from "../transformer";
import Plugin from "../plugin";
import * as types from "../../types";
import * as messages from "../../messages";
import traverse from "../../types";
import parse from "../../helpers/parse";
var context = {
messages,
Transformer,
Plugin,
types,
parse,
traverse
};
import * as util from "../../util";
export default class PluginManager {
@@ -11,7 +25,7 @@ export default class PluginManager {
if (plugin.container === fn) return plugin.transformer;
}
var transformer = fn(node);
var transformer = fn(context);
PluginManager.memoisedPlugins.push({
container: fn,
transformer: transformer
@@ -55,7 +69,7 @@ export default class PluginManager {
}
// validate Transformer instance
if (!plugin.buildPass || plugin.constructor.name !== "Transformer") {
if (!plugin.buildPass || plugin.constructor.name !== "Plugin") {
throw new TypeError(messages.get("pluginNotTransformer", name));
}

View File

@@ -9,8 +9,10 @@ import esutils from "esutils";
import * as react from "./react";
import * as t from "../../types";
export default function (exports, opts) {
exports.JSXIdentifier = function (node) {
export default function (opts) {
var visitor = {};
visitor.JSXIdentifier = function (node) {
if (node.name === "this" && this.isReferenced()) {
return t.thisExpression();
} else if (esutils.keyword.isIdentifierNameES6(node.name)) {
@@ -20,22 +22,22 @@ export default function (exports, opts) {
}
};
exports.JSXNamespacedName = function () {
visitor.JSXNamespacedName = function () {
throw this.errorWithNode(messages.get("JSXNamespacedTags"));
};
exports.JSXMemberExpression = {
visitor.JSXMemberExpression = {
exit(node) {
node.computed = t.isLiteral(node.property);
node.type = "MemberExpression";
}
};
exports.JSXExpressionContainer = function (node) {
visitor.JSXExpressionContainer = function (node) {
return node.expression;
};
exports.JSXAttribute = {
visitor.JSXAttribute = {
enter(node) {
var value = node.value;
if (t.isLiteral(value) && isString(value.value)) {
@@ -49,7 +51,7 @@ export default function (exports, opts) {
}
};
exports.JSXOpeningElement = {
visitor.JSXOpeningElement = {
exit(node, parent, scope, file) {
parent.children = react.buildChildren(parent);
@@ -139,7 +141,7 @@ export default function (exports, opts) {
return attribs;
};
exports.JSXElement = {
visitor.JSXElement = {
exit(node) {
var callExpr = node.openingElement;
@@ -153,54 +155,5 @@ export default function (exports, opts) {
}
};
// display names
var addDisplayName = function (id, call) {
var props = call.arguments[0].properties;
var safe = true;
for (var i = 0; i < props.length; i++) {
var prop = props[i];
var key = t.toComputedKey(prop);
if (t.isLiteral(key, { value: "displayName" })) {
safe = false;
break;
}
}
if (safe) {
props.unshift(t.property("init", t.identifier("displayName"), t.literal(id)));
}
};
exports.ExportDefaultDeclaration = function (node, parent, scope, file) {
if (react.isCreateClass(node.declaration)) {
addDisplayName(file.opts.basename, node.declaration);
}
};
exports.AssignmentExpression =
exports.Property =
exports.VariableDeclarator = function (node) {
var left, right;
if (t.isAssignmentExpression(node)) {
left = node.left;
right = node.right;
} else if (t.isProperty(node)) {
left = node.key;
right = node.value;
} else if (t.isVariableDeclarator(node)) {
left = node.id;
right = node.init;
}
if (t.isMemberExpression(left)) {
left = left.property;
}
if (t.isIdentifier(left) && react.isCreateClass(right)) {
addDisplayName(left.name, right);
}
};
return visitor;
}

View File

@@ -20,11 +20,8 @@ var visitor = {
visitIdentifier(this, node, scope, state);
},
AssignmentExpression(node, parent, scope, state) {
var ids = this.getBindingIdentifiers();
for (var name in ids) {
visitIdentifier(this, ids[name], scope, state);
}
BindingIdentifier(node, parent, scope, state) {
visitIdentifier(this, node, scope, state);
}
};
@@ -71,10 +68,10 @@ var visit = function (node, name, scope) {
// check to see if we have a local binding of the id we're setting inside of
// the function, this is important as there are caveats associated
var bindingInfo = scope.getOwnBindingInfo(name);
var binding = scope.getOwnBinding(name);
if (bindingInfo) {
if (bindingInfo.kind === "param") {
if (binding) {
if (binding.kind === "param") {
// safari will blow up in strict mode with code like:
//
// var t = function t(t) {};
@@ -114,8 +111,7 @@ export function property(node, file, scope) {
var key = t.toComputedKey(node, node.key);
if (!t.isLiteral(key)) return; // we can't set a function id with this
var name = t.toIdentifier(key.value);
if (name === "eval" || name === "arguments") name = "_" + name;
var name = t.toBindingIdentifierName(key.value);
var id = t.identifier(name);
var method = node.value;
@@ -136,8 +132,8 @@ export function bare(node, parent, scope) {
id = parent.id;
if (t.isIdentifier(id)) {
var bindingInfo = scope.parent.getBinding(id.name);
if (bindingInfo && bindingInfo.constant && scope.getBinding(id.name) === bindingInfo) {
var binding = scope.parent.getBinding(id.name);
if (binding && binding.constant && scope.getBinding(id.name) === binding) {
// always going to reference this method
node.id = id;
return;
@@ -156,7 +152,7 @@ export function bare(node, parent, scope) {
return;
}
name = t.toIdentifier(name);
name = t.toBindingIdentifierName(name);
id = t.identifier(name);
var state = visit(node, name, scope);

View File

@@ -1,24 +1,5 @@
import * as t from "../../types";
var isCreateClassCallExpression = t.buildMatchMemberExpression("React.createClass");
export function isCreateClass(node) {
if (!node || !t.isCallExpression(node)) return false;
// not React.createClass call member object
if (!isCreateClassCallExpression(node.callee)) return false;
// no call arguments
var args = node.arguments;
if (args.length !== 1) return false;
// first node arg is not an object
var first = args[0];
if (!t.isObjectExpression(first)) return false;
return true;
}
export var isReactComponent = t.buildMatchMemberExpression("React.Component");
export function isCompatTag(tagName) {

View File

@@ -169,7 +169,13 @@ export default class ReplaceSupers {
if (methodName.name === "constructor") {
// constructor() { super(); }
return t.memberExpression(superRef, t.identifier("call"));
if (parent.arguments.length === 2 && t.isSpreadElement(parent.arguments[1]) && t.isIdentifier(parent.arguments[1].argument, { name: "arguments" })) {
// special case single arguments spread
parent.arguments[1] = parent.arguments[1].argument;
return t.memberExpression(superRef, t.identifier("apply"));
} else {
return t.memberExpression(superRef, t.identifier("call"));
}
} else {
id = superRef;

View File

@@ -1,4 +1,4 @@
import Pipeline from "./transformer-pipeline";
import Pipeline from "./pipeline";
var pipeline = new Pipeline;
@@ -8,8 +8,11 @@ import transformers from "./transformers";
for (var key in transformers) {
var transformer = transformers[key];
var metadata = transformer.metadata = transformer.metadata || {};
metadata.group = metadata.group || "builtin-basic";
if (typeof transformer === "object") {
var metadata = transformer.metadata = transformer.metadata || {};
metadata.group = metadata.group || "builtin-basic";
}
}
pipeline.addTransformers(transformers);

View File

@@ -1,78 +1,16 @@
import * as messages from "../../messages";
import Remaps from "./lib/remaps";
import extend from "lodash/object/extend";
import object from "../../helpers/object";
import * as util from "../../util";
import * as t from "../../types";
var remapVisitor = {
enter(node) {
if (node._skipModulesRemap) {
return this.skip();
}
},
ReferencedIdentifier(node, parent, scope, formatter) {
var remap = formatter.internalRemap[node.name];
if (remap && node !== remap) {
if (!scope.hasBinding(node.name) || scope.bindingIdentifierEquals(node.name, formatter.localImports[node.name])) {
if (this.key === "callee" && this.parentPath.isCallExpression()) {
return t.sequenceExpression([t.literal(0), remap]);
} else {
return remap;
}
}
}
},
AssignmentExpression: {
exit(node, parent, scope, formatter) {
if (!node._ignoreModulesRemap) {
var exported = formatter.getExport(node.left, scope);
if (exported) {
return formatter.remapExportAssignment(node, exported);
}
}
}
},
UpdateExpression(node, parent, scope, formatter) {
var exported = formatter.getExport(node.argument, scope);
if (!exported) return;
this.skip();
// expand to long file assignment expression
var assign = t.assignmentExpression(node.operator[0] + "=", node.argument, t.literal(1));
// remap this assignment expression
var remapped = formatter.remapExportAssignment(assign, exported);
// we don't need to change the result
if (t.isExpressionStatement(parent) || node.prefix) {
return remapped;
}
var nodes = [];
nodes.push(remapped);
var operator;
if (node.operator === "--") {
operator = "+";
} else { // "++"
operator = "-";
}
nodes.push(t.binaryExpression(operator, node.argument, t.literal(1)));
return t.sequenceExpression(nodes);
}
};
var metadataVisitor = {
ModuleDeclaration: {
enter(node, parent, scope, formatter) {
if (node.source) {
node.source.value = formatter.file.resolveModuleSource(node.source.value);
formatter.addScope(this);
}
}
},
@@ -218,18 +156,27 @@ var metadataVisitor = {
}
},
Scope() {
this.skip();
Scope(node, parent, scope, formatter) {
if (!formatter.isLoose()) {
this.skip();
}
}
};
export default class DefaultFormatter {
constructor(file) {
this.internalRemap = object();
this.defaultIds = object();
this.scope = file.scope;
this.file = file;
this.ids = object();
// object containg all module sources with the scope that they're contained in
this.sourceScopes = object();
// ids for use in module ids
this.defaultIds = object();
this.ids = object();
// contains reference aliases for live bindings
this.remaps = new Remaps(file, this);
this.scope = file.scope;
this.file = file;
this.hasNonDefaultExports = false;
@@ -243,6 +190,18 @@ export default class DefaultFormatter {
this.getMetadata();
}
addScope(path) {
var source = path.node.source && path.node.source.value;
if (!source) return;
var existingScope = this.sourceScopes[source];
if (existingScope && existingScope !== path.scope) {
throw path.errorWithNode(messages.get("modulesDuplicateDeclarations"));
}
this.sourceScopes[source] = path.scope;
}
isModuleType(node, type) {
var modules = this.file.dynamicImportTypes[type];
return modules && modules.indexOf(node) >= 0;
@@ -264,12 +223,14 @@ export default class DefaultFormatter {
break;
}
}
if (has) this.file.path.traverse(metadataVisitor, this);
if (has || this.isLoose()) {
this.file.path.traverse(metadataVisitor, this);
}
}
remapAssignments() {
if (this.hasLocalExports || this.hasLocalImports) {
this.file.path.traverse(remapVisitor, this);
this.remaps.run();
}
}

View File

@@ -72,7 +72,7 @@ export default class AMDFormatter extends DefaultFormatter {
this.getExternalReference(node);
}
importSpecifier(specifier, node, nodes) {
importSpecifier(specifier, node, nodes, scope) {
var key = node.source.value;
var ref = this.getExternalReference(node);
@@ -90,7 +90,7 @@ export default class AMDFormatter extends DefaultFormatter {
// import * as bar from "foo";
} else if (!includes(this.file.dynamicImported, node) && t.isSpecifierDefault(specifier) && !this.noInteropRequireImport) {
// import foo from "foo";
var uid = this.scope.generateUidIdentifier(specifier.local.name);
var uid = scope.generateUidIdentifier(specifier.local.name);
nodes.push(t.variableDeclaration("var", [
t.variableDeclarator(uid, t.callExpression(this.file.addHelper("interop-require-default"), [ref]))
]));
@@ -102,7 +102,7 @@ export default class AMDFormatter extends DefaultFormatter {
ref = t.memberExpression(ref, imported);
}
this.internalRemap[specifier.local.name] = ref;
this.remaps.add(scope, specifier.local.name, ref);
}
exportSpecifier(specifier, node, nodes) {

View File

@@ -37,7 +37,7 @@ export default class CommonJSFormatter extends DefaultFormatter {
}
}
importSpecifier(specifier, node, nodes) {
importSpecifier(specifier, node, nodes, scope) {
var variableName = specifier.local;
var ref = this.getExternalReference(node, nodes);
@@ -47,9 +47,9 @@ export default class CommonJSFormatter extends DefaultFormatter {
if (this.isModuleType(node, "absolute")) {
// absolute module reference
} else if (this.isModuleType(node, "absoluteDefault")) {
this.internalRemap[variableName.name] = ref;
this.remaps.add(scope, variableName.name, ref);
} else if (this.noInteropRequireImport) {
this.internalRemap[variableName.name] = t.memberExpression(ref, t.identifier("default"));
this.remaps.add(scope, variableName.name, t.memberExpression(ref, t.identifier("default")));
} else {
var uid = this.scope.generateUidIdentifierBasedOnNode(node, "import");
@@ -57,7 +57,7 @@ export default class CommonJSFormatter extends DefaultFormatter {
t.variableDeclarator(uid, t.callExpression(this.file.addHelper("interop-require-default"), [ref]))
]));
this.internalRemap[variableName.name] = t.memberExpression(uid, t.identifier("default"));
this.remaps.add(scope, variableName.name, t.memberExpression(uid, t.identifier("default")));
}
} else {
if (t.isImportNamespaceSpecifier(specifier)) {
@@ -71,7 +71,7 @@ export default class CommonJSFormatter extends DefaultFormatter {
]));
} else {
// import { foo } from "foo";
this.internalRemap[variableName.name] = t.memberExpression(ref, specifier.imported);
this.remaps.add(scope, variableName.name, t.memberExpression(ref, specifier.imported));
}
}
}

View File

@@ -1,6 +1,7 @@
import DefaultFormatter from "./_default";
import * as t from "../../types";
export default class IgnoreFormatter {
export default class IgnoreFormatter extends DefaultFormatter {
exportDeclaration(node, nodes) {
var declar = t.toStatement(node.declaration, true);
if (declar) nodes.push(t.inherits(declar, node));
@@ -10,4 +11,5 @@ export default class IgnoreFormatter {
importDeclaration() {}
importSpecifier() {}
exportSpecifier() {}
transform() {}
}

View File

@@ -0,0 +1,121 @@
import * as t from "../../../types";
var remapVisitor = {
enter(node) {
if (node._skipModulesRemap) {
return this.skip();
}
},
ReferencedIdentifier(node, parent, scope, remaps) {
var { formatter } = remaps;
var remap = remaps.get(scope, node.name);
if (!remap || node === remap) return;
if (!scope.hasBinding(node.name) ||
scope.bindingIdentifierEquals(node.name, formatter.localImports[node.name])) {
if (!formatter.isLoose() && this.key === "callee" && this.parentPath.isCallExpression()) {
return t.sequenceExpression([t.literal(0), remap]);
} else {
return remap;
}
}
},
AssignmentExpression: {
exit(node, parent, scope, { formatter }) {
if (!node._ignoreModulesRemap) {
var exported = formatter.getExport(node.left, scope);
if (exported) {
return formatter.remapExportAssignment(node, exported);
}
}
}
},
UpdateExpression(node, parent, scope, { formatter }) {
var exported = formatter.getExport(node.argument, scope);
if (!exported) return;
this.skip();
// expand to long file assignment expression
var assign = t.assignmentExpression(node.operator[0] + "=", node.argument, t.literal(1));
// remap this assignment expression
var remapped = formatter.remapExportAssignment(assign, exported);
// we don't need to change the result
if (t.isExpressionStatement(parent) || node.prefix) {
return remapped;
}
var nodes = [];
nodes.push(remapped);
var operator;
if (node.operator === "--") {
operator = "+";
} else { // "++"
operator = "-";
}
nodes.push(t.binaryExpression(operator, node.argument, t.literal(1)));
return t.sequenceExpression(nodes);
}
};
export default class Remaps {
constructor(file, formatter) {
this.formatter = formatter;
this.file = file;
}
run() {
this.file.path.traverse(remapVisitor, this);
}
_getKey(name) {
return `${name}:moduleRemap`;
}
get(scope, name) {
return scope.getData(this._getKey(name));
}
add(scope, name, val) {
if (this.all) {
this.all.push({
name,
scope,
node: val
});
}
return scope.setData(this._getKey(name), val);
}
remove(scope, name) {
return scope.removeData(this._getKey(name));
}
/**
* These methods are used by the system module formatter who needs access to all the remaps
* so it can process them into it's specific setter method. We don't do this by default since
* no other module formatters need access to this.
*/
getAll() {
return this.all;
}
clearAll() {
if (this.all) {
for (var remap of (this.all: Array)) {
remap.scope.removeData(this._getKey(remap.name));
}
}
this.all = [];
}
}

View File

@@ -1,6 +1,5 @@
import DefaultFormatter from "./_default";
import AMDFormatter from "./amd";
import object from "../../helpers/object";
import * as util from "../../util";
import last from "lodash/array/last";
import map from "lodash/collection/map";
@@ -82,6 +81,8 @@ export default class SystemFormatter extends AMDFormatter {
this.exportIdentifier = file.scope.generateUidIdentifier("export");
this.noInteropRequireExport = true;
this.noInteropRequireImport = true;
this.remaps.clearAll();
}
_addImportSource(node, exportNode) {
@@ -137,13 +138,13 @@ export default class SystemFormatter extends AMDFormatter {
importSpecifier(specifier, node, nodes) {
AMDFormatter.prototype.importSpecifier.apply(this, arguments);
for (var name in this.internalRemap) {
for (var remap of (this.remaps.getAll(): Array)) {
nodes.push(t.variableDeclaration("var", [
t.variableDeclarator(t.identifier(name), this.internalRemap[name])
t.variableDeclarator(t.identifier(remap.name), remap.node)
]));
}
this.internalRemap = object();
this.remaps.clearAll();
this._addImportSource(last(nodes), node);
}

View File

@@ -1,10 +1,11 @@
import Transformer from "./transformer";
import PluginManager from "./file/plugin-manager";
import normalizeAst from "../helpers/normalize-ast";
import Plugin from "./plugin";
import assign from "lodash/object/assign";
import object from "../helpers/object";
import File from "./file";
export default class TransformerPipeline {
export default class Pipeline {
constructor() {
this.transformers = object();
this.namespaces = object();
@@ -20,7 +21,7 @@ export default class TransformerPipeline {
return this;
}
addTransformer(key, transformer) {
addTransformer(key, plugin) {
if (this.transformers[key]) throw new Error(); // todo: error
var namespace = key.split(".")[0];
@@ -28,7 +29,19 @@ export default class TransformerPipeline {
this.namespaces[namespace].push(key);
this.namespaces[key] = namespace;
this.transformers[key] = new Transformer(key, transformer);
if (typeof plugin === "function") {
plugin = PluginManager.memoisePluginContainer(plugin);
plugin.key = key;
plugin.metadata.optional = true;
if (key === "react.displayName") {
plugin.metadata.optional = false;
}
} else {
plugin = new Plugin(key, plugin);
}
this.transformers[key] = plugin;
}
addAliases(names) {
@@ -46,17 +59,24 @@ export default class TransformerPipeline {
return this;
}
canTransform(transformer, fileOpts) {
if (transformer.metadata.plugin) return true;
canTransform(plugin, fileOpts) {
if (plugin.metadata.plugin) {
return true;
}
for (var filter of (this.filters: Array)) {
var result = filter(transformer, fileOpts);
var result = filter(plugin, fileOpts);
if (result != null) return result;
}
return true;
}
analyze(code: string, opts?: Object = {}) {
opts.code = false;
return this.transform(code, opts);
}
pretransform(code: string, opts?: Object) {
var file = new File(opts, this);
return file.wrap(code, function () {

View File

@@ -7,14 +7,13 @@ import type File from "./file";
* AST and running it's parent transformers handlers over it.
*/
export default class TransformerPass {
constructor(file: File, transformer: Transformer) {
this.transformer = transformer;
this.handlers = transformer.handlers;
this.file = file;
this.key = transformer.key;
export default class PluginPass {
constructor(file: File, plugin: Transformer) {
this.plugin = plugin;
this.file = file;
this.key = plugin.key;
if (this.canTransform() && transformer.metadata.experimental && !file.opts.experimental) {
if (this.canTransform() && plugin.metadata.experimental && !file.opts.experimental) {
file.log.warn(`THE TRANSFORMER ${this.key} HAS BEEN MARKED AS EXPERIMENTAL AND IS WIP. USE AT YOUR OWN RISK. ` +
"THIS WILL HIGHLY LIKELY BREAK YOUR CODE SO USE WITH **EXTREME** CAUTION. ENABLE THE " +
"`experimental` OPTION TO IGNORE THIS WARNING.");
@@ -23,13 +22,13 @@ export default class TransformerPass {
canTransform(): boolean {
return this.file.transformerDependencies[this.key] ||
this.file.pipeline.canTransform(this.transformer, this.file.opts);
this.file.pipeline.canTransform(this.plugin, this.file.opts);
}
transform() {
var file = this.file;
file.log.debug(`Start transformer ${this.key}`);
traverse(file.ast, this.handlers, file.scope, file);
traverse(file.ast, this.plugin.visitor, file.scope, file);
file.log.debug(`Finish transformer ${this.key}`);
}
}

View File

@@ -0,0 +1,55 @@
import PluginPass from "./plugin-pass";
import * as messages from "../messages";
import isFunction from "lodash/lang/isFunction";
import traverse from "../traversal";
import assign from "lodash/object/assign";
import clone from "lodash/lang/clone";
import File from "./file";
export default class Plugin {
constructor(key: string, plugin: Object) {
plugin = assign({}, plugin);
var take = function (key) {
var val = plugin[key];
delete plugin[key];
return val;
};
this.manipulateOptions = take("manipulateOptions");
this.metadata = take("metadata") || {};
this.dependencies = this.metadata.dependencies || [];
this.post = take("post");
this.pre = take("pre");
//
if (this.metadata.stage != null) {
this.metadata.optional = true;
}
//
this.visitor = this.normalize(clone(take("visitor")) || {});
this.key = key;
}
normalize(visitor: Object): Object {
if (isFunction(visitor)) {
visitor = { ast: visitor };
}
traverse.explode(visitor);
return visitor;
}
buildPass(file: File): PluginPass {
// validate Transformer instance
if (!(file instanceof File)) {
throw new TypeError(messages.get("pluginNotFile", this.key));
}
return new PluginPass(file, this);
}
}

View File

@@ -0,0 +1,3 @@
(function () {
super(...arguments);
})

View File

@@ -1,3 +0,0 @@
if (SUPER_NAME != null) {
SUPER_NAME.apply(this, arguments);
}

View File

@@ -1,3 +0,0 @@
if (SUPER_NAME != null) {
SUPER_NAME.apply(this, arguments);
}

View File

@@ -1,5 +0,0 @@
if (SUPER_NAME != null) {
var NATIVE_REF = new SUPER_NAME(...arguments);
NATIVE_REF.__proto__ = CLASS_NAME.prototype;
return NATIVE_REF;
}

View File

@@ -1,4 +1,6 @@
(function get(object, property, receiver) {
if (object === null) object = Function.prototype;
var desc = Object.getOwnPropertyDescriptor(object, property);
if (desc === undefined) {

View File

@@ -1,82 +1,14 @@
import TransformerPass from "./transformer-pass";
import * as messages from "../messages";
import isFunction from "lodash/lang/isFunction";
import traverse from "../traversal";
import isObject from "lodash/lang/isObject";
import assign from "lodash/object/assign";
import File from "./file";
import each from "lodash/collection/each";
/**
* This is the class responsible for normalising a transformers handlers
* as well as constructing a `TransformerPass` that is responsible for
* actually running the transformer over the provided `File`.
*/
import Plugin from "./plugin";
export default class Transformer {
constructor(transformerKey: string, transformer: Object) {
transformer = assign({}, transformer);
constructor(key, obj) {
var plugin = {};
var take = function (key) {
var val = transformer[key];
delete transformer[key];
return val;
};
plugin.metadata = obj.metadata;
delete obj.metadata;
this.manipulateOptions = take("manipulateOptions");
this.metadata = take("metadata") || {};
this.dependencies = this.metadata.dependencies || [];
this.parser = take("parser");
this.post = take("post");
this.pre = take("pre");
plugin.visitor = obj;
//
if (this.metadata.stage != null) {
this.metadata.optional = true;
}
//
this.handlers = this.normalize(transformer);
this.key = transformerKey;
}
normalize(transformer: Object): Object {
if (isFunction(transformer)) {
transformer = { ast: transformer };
}
traverse.explode(transformer);
each(transformer, (fns, type) => {
// hidden property
if (type[0] === "_") {
this[type] = fns;
return;
}
if (type === "enter" || type === "exit") return;
if (isFunction(fns)) fns = { enter: fns };
if (!isObject(fns)) return;
if (!fns.enter) fns.enter = function () { };
if (!fns.exit) fns.exit = function () { };
transformer[type] = fns;
});
return transformer;
}
buildPass(file: File): TransformerPass {
// validate Transformer instance
if (!(file instanceof File)) {
throw new TypeError(messages.get("transformerNotFile", this.key));
}
return new TransformerPass(file, this);
return new Plugin(key, plugin);
}
}

View File

@@ -4,13 +4,15 @@ export var metadata = {
group: "builtin-trailing"
};
export var MemberExpression = {
exit(node) {
var prop = node.property;
if (!node.computed && t.isIdentifier(prop) && !t.isValidIdentifier(prop.name)) {
// foo.default -> foo["default"]
node.property = t.literal(prop.name);
node.computed = true;
export var visitor = {
MemberExpression: {
exit(node) {
var prop = node.property;
if (!node.computed && t.isIdentifier(prop) && !t.isValidIdentifier(prop.name)) {
// foo.default -> foo["default"]
node.property = t.literal(prop.name);
node.computed = true;
}
}
}
};

View File

@@ -4,12 +4,14 @@ export var metadata = {
group: "builtin-trailing"
};
export var Property = {
exit(node) {
var key = node.key;
if (!node.computed && t.isIdentifier(key) && !t.isValidIdentifier(key.name)) {
// default: "bar" -> "default": "bar"
node.key = t.literal(key.name);
export var visitor = {
Property: {
exit(node) {
var key = node.key;
if (!node.computed && t.isIdentifier(key) && !t.isValidIdentifier(key.name)) {
// default: "bar" -> "default": "bar"
node.key = t.literal(key.name);
}
}
}
};

View File

@@ -1,29 +1,31 @@
import * as defineMap from "../../helpers/define-map";
import * as t from "../../../types";
export function ObjectExpression(node, parent, scope, file) {
var hasAny = false;
for (var prop of (node.properties: Array)) {
if (prop.kind === "get" || prop.kind === "set") {
hasAny = true;
break;
export var visitor = {
ObjectExpression(node, parent, scope, file) {
var hasAny = false;
for (var prop of (node.properties: Array)) {
if (prop.kind === "get" || prop.kind === "set") {
hasAny = true;
break;
}
}
if (!hasAny) return;
var mutatorMap = {};
node.properties = node.properties.filter(function (prop) {
if (prop.kind === "get" || prop.kind === "set") {
defineMap.push(mutatorMap, prop, prop.kind, file);
return false;
} else {
return true;
}
});
return t.callExpression(
t.memberExpression(t.identifier("Object"), t.identifier("defineProperties")),
[node, defineMap.toDefineObject(mutatorMap)]
);
}
if (!hasAny) return;
var mutatorMap = {};
node.properties = node.properties.filter(function (prop) {
if (prop.kind === "get" || prop.kind === "set") {
defineMap.push(mutatorMap, prop, prop.kind, file);
return false;
} else {
return true;
}
});
return t.callExpression(
t.memberExpression(t.identifier("Object"), t.identifier("defineProperties")),
[node, defineMap.toDefineObject(mutatorMap)]
);
}
};

View File

@@ -1,9 +1,8 @@
import * as t from "../../../types";
export function ArrowFunctionExpression(node) {
t.ensureBlock(node);
node.expression = false;
node.type = "FunctionExpression";
node.shadow = true;
}
export var visitor = {
ArrowFunctionExpression(node) {
this.ensureBlock();
node.expression = false;
node.type = "FunctionExpression";
node.shadow = true;
}
};

View File

@@ -44,47 +44,47 @@ export var metadata = {
group: "builtin-advanced"
};
export function VariableDeclaration(node, parent, scope, file) {
if (!isLet(node, parent)) return;
export var visitor = {
VariableDeclaration(node, parent, scope, file) {
if (!isLet(node, parent)) return;
if (isLetInitable(node) && file.transformers["es6.spec.blockScoping"].canTransform()) {
var nodes = [node];
if (isLetInitable(node) && file.transformers["es6.spec.blockScoping"].canTransform()) {
var nodes = [node];
for (var i = 0; i < node.declarations.length; i++) {
var decl = node.declarations[i];
if (decl.init) {
var assign = t.assignmentExpression("=", decl.id, decl.init);
assign._ignoreBlockScopingTDZ = true;
nodes.push(t.expressionStatement(assign));
for (var i = 0; i < node.declarations.length; i++) {
var decl = node.declarations[i];
if (decl.init) {
var assign = t.assignmentExpression("=", decl.id, decl.init);
assign._ignoreBlockScopingTDZ = true;
nodes.push(t.expressionStatement(assign));
}
decl.init = file.addHelper("temporal-undefined");
}
decl.init = file.addHelper("temporal-undefined");
node._blockHoist = 2;
return nodes;
}
},
Loop(node, parent, scope, file) {
var init = node.left || node.init;
if (isLet(init, node)) {
t.ensureBlock(node);
node.body._letDeclarators = [init];
}
node._blockHoist = 2;
var blockScoping = new BlockScoping(this, this.get("body"), parent, scope, file);
return blockScoping.run();
},
return nodes;
"BlockStatement|Program"(block, parent, scope, file) {
if (!t.isLoop(parent)) {
var blockScoping = new BlockScoping(null, this, parent, scope, file);
blockScoping.run();
}
}
}
export function Loop(node, parent, scope, file) {
var init = node.left || node.init;
if (isLet(init, node)) {
t.ensureBlock(node);
node.body._letDeclarators = [init];
}
var blockScoping = new BlockScoping(this, this.get("body"), parent, scope, file);
return blockScoping.run();
}
export function BlockStatement(block, parent, scope, file) {
if (!t.isLoop(parent)) {
var blockScoping = new BlockScoping(null, this, parent, scope, file);
blockScoping.run();
}
}
export { BlockStatement as Program };
};
function replace(node, parent, scope, remaps) {
var remap = remaps[node.name];

View File

@@ -10,15 +10,17 @@ import * as t from "../../../types";
const PROPERTY_COLLISION_METHOD_NAME = "__initializeProperties";
export function ClassDeclaration(node, parent, scope, file) {
return t.variableDeclaration("let", [
t.variableDeclarator(node.id, t.toExpression(node))
]);
}
export var visitor = {
ClassDeclaration(node) {
return t.variableDeclaration("let", [
t.variableDeclarator(node.id, t.toExpression(node))
]);
},
export function ClassExpression(node, parent, scope, file) {
return new ClassTransformer(this, file).run();
}
ClassExpression(node, parent, scope, file) {
return new ClassTransformer(this, file).run();
}
};
var collectPropertyReferencesVisitor = {
Identifier: {
@@ -251,20 +253,43 @@ class ClassTransformer {
}
}
/**
* https://www.youtube.com/watch?v=fWNaR-rxAic
*/
constructorMeMaybe() {
if (!this.hasSuper) return;
var hasConstructor = false;
var paths = this.path.get("body.body");
for (var path of (paths: Array)) {
hasConstructor = path.equals("kind", "constructor");
if (hasConstructor) break;
}
if (!hasConstructor) {
this.path.get("body").unshiftContainer("body", t.methodDefinition(
t.identifier("constructor"),
util.template("class-derived-default-constructor"),
"constructor"
));
}
}
/**
* Description
*/
buildBody() {
this.constructorMeMaybe();
var constructorBody = this.constructorBody;
var classBody = this.node.body.body;
var classBodyPaths = this.path.get("body.body");
var body = this.body;
var classBodyPaths = this.path.get("body").get("body");
for (var i = 0; i < classBody.length; i++) {
var node = classBody[i];
var path = classBodyPaths[i];
for (var path of (classBodyPaths: Array)) {
var node = path.node;
if (node.decorators) {
memoiseDecorators(node.decorators, this.scope);
@@ -297,16 +322,6 @@ class ClassTransformer {
}
}
// we have no constructor, but we're a derived class
if (!this.hasConstructor && this.hasSuper) {
var helperName = "class-super-constructor-call";
if (this.isLoose) helperName += "-loose";
constructorBody.body.push(util.template(helperName, {
CLASS_NAME: this.classRef,
SUPER_NAME: this.superName
}, true));
}
//
this.placePropertyInitializers();
@@ -462,7 +477,7 @@ class ClassTransformer {
var classRef = this.classRef;
if (!node.static) classRef = t.memberExpression(classRef, t.identifier("prototype"));
var methodName = t.memberExpression(classRef, node.key, node.computed);
var methodName = t.memberExpression(classRef, node.key, node.computed || t.isLiteral(node.key));
var expr = t.expressionStatement(t.assignmentExpression("=", methodName, node.value));
t.inheritsComments(expr, node);

View File

@@ -1,18 +1,20 @@
import * as messages from "../../../messages";
export function Scope(node, parent, scope) {
for (var name in scope.bindings) {
var binding = scope.bindings[name];
export var visitor = {
Scope(node, parent, scope) {
for (var name in scope.bindings) {
var binding = scope.bindings[name];
// not a constant
if (binding.kind !== "const" && binding.kind !== "module") continue;
// not a constant
if (binding.kind !== "const" && binding.kind !== "module") continue;
for (var violation of (binding.constantViolations: Array)) {
throw violation.errorWithNode(messages.get("readOnly", name));
for (var violation of (binding.constantViolations: Array)) {
throw violation.errorWithNode(messages.get("readOnly", name));
}
}
}
}
},
export function VariableDeclaration(node) {
if (node.kind === "const") node.kind = "let";
}
VariableDeclaration(node) {
if (node.kind === "const") node.kind = "let";
}
};

View File

@@ -5,145 +5,201 @@ export var metadata = {
group: "builtin-advanced"
};
export function ForOfStatement(node, parent, scope, file) {
var left = node.left;
export var visitor = {
ForXStatement(node, parent, scope, file) {
var left = node.left;
if (t.isPattern(left)) {
// for ({ length: k } in { abc: 3 });
if (t.isPattern(left)) {
// for ({ length: k } in { abc: 3 });
var temp = scope.generateUidIdentifier("ref");
var temp = scope.generateUidIdentifier("ref");
node.left = t.variableDeclaration("var", [
t.variableDeclarator(temp)
node.left = t.variableDeclaration("var", [
t.variableDeclarator(temp)
]);
this.ensureBlock();
node.body.body.unshift(t.variableDeclaration("var", [
t.variableDeclarator(left, temp)
]));
return;
}
if (!t.isVariableDeclaration(left)) return;
var pattern = left.declarations[0].id;
if (!t.isPattern(pattern)) return;
var key = scope.generateUidIdentifier("ref");
node.left = t.variableDeclaration(left.kind, [
t.variableDeclarator(key, null)
]);
t.ensureBlock(node);
node.body.body.unshift(t.variableDeclaration("var", [
t.variableDeclarator(left, temp)
]));
return;
}
if (!t.isVariableDeclaration(left)) return;
var pattern = left.declarations[0].id;
if (!t.isPattern(pattern)) return;
var key = scope.generateUidIdentifier("ref");
node.left = t.variableDeclaration(left.kind, [
t.variableDeclarator(key, null)
]);
var nodes = [];
var destructuring = new DestructuringTransformer({
kind: left.kind,
file: file,
scope: scope,
nodes: nodes
});
destructuring.init(pattern, key);
t.ensureBlock(node);
var block = node.body;
block.body = nodes.concat(block.body);
}
export { ForOfStatement as ForInStatement };
export function Func/*tion*/(node, parent, scope, file) {
var hasDestructuring = false;
for (let pattern of (node.params: Array)) {
if (t.isPattern(pattern)) {
hasDestructuring = true;
break;
}
}
if (!hasDestructuring) return;
var nodes = [];
for (var i = 0; i < node.params.length; i++) {
let pattern = node.params[i];
if (!t.isPattern(pattern)) continue;
var ref = node.params[i] = scope.generateUidIdentifier("ref");
t.inherits(ref, pattern);
var nodes = [];
var destructuring = new DestructuringTransformer({
blockHoist: node.params.length - i,
nodes: nodes,
scope: scope,
file: file,
kind: "let"
kind: left.kind,
file: file,
scope: scope,
nodes: nodes
});
destructuring.init(pattern, ref);
}
destructuring.init(pattern, key);
t.ensureBlock(node);
this.ensureBlock();
var block = node.body;
block.body = nodes.concat(block.body);
}
var block = node.body;
block.body = nodes.concat(block.body);
},
export function CatchClause(node, parent, scope, file) {
var pattern = node.param;
if (!t.isPattern(pattern)) return;
var ref = scope.generateUidIdentifier("ref");
node.param = ref;
var nodes = [];
var destructuring = new DestructuringTransformer({
kind: "let",
file: file,
scope: scope,
nodes: nodes
});
destructuring.init(pattern, ref);
node.body.body = nodes.concat(node.body.body);
}
export function AssignmentExpression(node, parent, scope, file) {
if (!t.isPattern(node.left)) return;
var nodes = [];
var destructuring = new DestructuringTransformer({
operator: node.operator,
file: file,
scope: scope,
nodes: nodes
});
var ref;
if (this.isCompletionRecord() || !this.parentPath.isExpressionStatement()) {
ref = scope.generateUidIdentifierBasedOnNode(node.right, "ref");
nodes.push(t.variableDeclaration("var", [
t.variableDeclarator(ref, node.right)
]));
if (t.isArrayExpression(node.right)) {
destructuring.arrays[ref.name] = true;
Function(node, parent, scope, file) {
var hasDestructuring = false;
for (let pattern of (node.params: Array)) {
if (t.isPattern(pattern)) {
hasDestructuring = true;
break;
}
}
if (!hasDestructuring) return;
var nodes = [];
for (var i = 0; i < node.params.length; i++) {
let pattern = node.params[i];
if (!t.isPattern(pattern)) continue;
var ref = node.params[i] = scope.generateUidIdentifier("ref");
t.inherits(ref, pattern);
var destructuring = new DestructuringTransformer({
blockHoist: node.params.length - i,
nodes: nodes,
scope: scope,
file: file,
kind: "let"
});
destructuring.init(pattern, ref);
}
this.ensureBlock();
var block = node.body;
block.body = nodes.concat(block.body);
},
CatchClause(node, parent, scope, file) {
var pattern = node.param;
if (!t.isPattern(pattern)) return;
var ref = scope.generateUidIdentifier("ref");
node.param = ref;
var nodes = [];
var destructuring = new DestructuringTransformer({
kind: "let",
file: file,
scope: scope,
nodes: nodes
});
destructuring.init(pattern, ref);
node.body.body = nodes.concat(node.body.body);
},
AssignmentExpression(node, parent, scope, file) {
if (!t.isPattern(node.left)) return;
var nodes = [];
var destructuring = new DestructuringTransformer({
operator: node.operator,
file: file,
scope: scope,
nodes: nodes
});
var ref;
if (this.isCompletionRecord() || !this.parentPath.isExpressionStatement()) {
ref = scope.generateUidIdentifierBasedOnNode(node.right, "ref");
nodes.push(t.variableDeclaration("var", [
t.variableDeclarator(ref, node.right)
]));
if (t.isArrayExpression(node.right)) {
destructuring.arrays[ref.name] = true;
}
}
destructuring.init(node.left, ref || node.right);
if (ref) {
nodes.push(t.expressionStatement(ref));
}
return nodes;
},
VariableDeclaration(node, parent, scope, file) {
if (t.isForXStatement(parent)) return;
if (!variableDeclarationHasPattern(node)) return;
var nodes = [];
var declar;
for (var i = 0; i < node.declarations.length; i++) {
declar = node.declarations[i];
var patternId = declar.init;
var pattern = declar.id;
var destructuring = new DestructuringTransformer({
nodes: nodes,
scope: scope,
kind: node.kind,
file: file
});
if (t.isPattern(pattern)) {
destructuring.init(pattern, patternId);
if (+i !== node.declarations.length - 1) {
// we aren't the last declarator so let's just make the
// last transformed node inherit from us
t.inherits(nodes[nodes.length - 1], declar);
}
} else {
nodes.push(t.inherits(destructuring.buildVariableAssignment(declar.id, declar.init), declar));
}
}
if (!t.isProgram(parent) && !t.isBlockStatement(parent)) {
// https://github.com/babel/babel/issues/113
// for (let [x] = [0]; false;) {}
declar = null;
for (i = 0; i < nodes.length; i++) {
node = nodes[i];
declar = declar || t.variableDeclaration(node.kind, []);
if (!t.isVariableDeclaration(node) && declar.kind !== node.kind) {
throw file.errorWithNode(node, messages.get("invalidParentForThisNode"));
}
declar.declarations = declar.declarations.concat(node.declarations);
}
return declar;
}
return nodes;
}
destructuring.init(node.left, ref || node.right);
if (ref) {
nodes.push(t.expressionStatement(ref));
}
return nodes;
}
};
function variableDeclarationHasPattern(node) {
for (var i = 0; i < node.declarations.length; i++) {
@@ -154,62 +210,6 @@ function variableDeclarationHasPattern(node) {
return false;
}
export function VariableDeclaration(node, parent, scope, file) {
if (t.isForXStatement(parent)) return;
if (!variableDeclarationHasPattern(node)) return;
var nodes = [];
var declar;
for (var i = 0; i < node.declarations.length; i++) {
declar = node.declarations[i];
var patternId = declar.init;
var pattern = declar.id;
var destructuring = new DestructuringTransformer({
nodes: nodes,
scope: scope,
kind: node.kind,
file: file
});
if (t.isPattern(pattern)) {
destructuring.init(pattern, patternId);
if (+i !== node.declarations.length - 1) {
// we aren't the last declarator so let's just make the
// last transformed node inherit from us
t.inherits(nodes[nodes.length - 1], declar);
}
} else {
nodes.push(t.inherits(destructuring.buildVariableAssignment(declar.id, declar.init), declar));
}
}
if (!t.isProgram(parent) && !t.isBlockStatement(parent)) {
// https://github.com/babel/babel/issues/113
// for (let [x] = [0]; false;) {}
declar = null;
for (i = 0; i < nodes.length; i++) {
node = nodes[i];
declar = declar || t.variableDeclaration(node.kind, []);
if (!t.isVariableDeclaration(node) && declar.kind !== node.kind) {
throw file.errorWithNode(node, messages.get("invalidParentForThisNode"));
}
declar.declarations = declar.declarations.concat(node.declarations);
}
return declar;
}
return nodes;
}
function hasRest(pattern) {
for (var i = 0; i < pattern.elements.length; i++) {
if (t.isRestElement(pattern.elements[i])) {

View File

@@ -2,40 +2,42 @@ import * as messages from "../../../messages";
import * as util from "../../../util";
import * as t from "../../../types";
export function ForOfStatement(node, parent, scope, file) {
if (this.get("right").isArrayExpression()) {
return _ForOfStatementArray.call(this, node, scope, file);
export var visitor = {
ForOfStatement(node, parent, scope, file) {
if (this.get("right").isArrayExpression()) {
return _ForOfStatementArray.call(this, node, scope, file);
}
var callback = spec;
if (file.isLoose("es6.forOf")) callback = loose;
var build = callback(node, parent, scope, file);
var declar = build.declar;
var loop = build.loop;
var block = loop.body;
// ensure that it's a block so we can take all its statements
this.ensureBlock();
// add the value declaration to the new loop body
if (declar) {
block.body.push(declar);
}
// push the rest of the original loop body onto our new body
block.body = block.body.concat(node.body.body);
t.inherits(loop, node);
t.inherits(loop.body, node.body);
if (build.replaceParent) {
this.parentPath.replaceWithMultiple(build.node);
this.dangerouslyRemove();
} else {
return build.node;
}
}
var callback = spec;
if (file.isLoose("es6.forOf")) callback = loose;
var build = callback(node, parent, scope, file);
var declar = build.declar;
var loop = build.loop;
var block = loop.body;
// ensure that it's a block so we can take all its statements
t.ensureBlock(node);
// add the value declaration to the new loop body
if (declar) {
block.body.push(declar);
}
// push the rest of the original loop body onto our new body
block.body = block.body.concat(node.body.body);
t.inherits(loop, node);
t.inherits(loop.body, node.body);
if (build.replaceParent) {
this.parentPath.replaceWithMultiple(build.node);
this.dangerouslyRemove();
} else {
return build.node;
}
}
};
export function _ForOfStatementArray(node, scope, file) {
var nodes = [];

View File

@@ -12,64 +12,66 @@ export var metadata = {
group: "builtin-modules"
};
export function ImportDeclaration(node, parent, scope, file) {
// flow type
if (node.isType) return;
export var visitor = {
ImportDeclaration(node, parent, scope, file) {
// flow type
if (node.isType) return;
var nodes = [];
var nodes = [];
if (node.specifiers.length) {
for (var specifier of (node.specifiers: Array)) {
file.moduleFormatter.importSpecifier(specifier, node, nodes, parent);
}
} else {
file.moduleFormatter.importDeclaration(node, nodes, parent);
}
if (nodes.length === 1) {
// inherit `_blockHoist` - this is for `_blockHoist` in File.prototype.addImport
nodes[0]._blockHoist = node._blockHoist;
}
return nodes;
}
export function ExportAllDeclaration(node, parent, scope, file) {
var nodes = [];
file.moduleFormatter.exportAllDeclaration(node, nodes, parent);
keepBlockHoist(node, nodes);
return nodes;
}
export function ExportDefaultDeclaration(node, parent, scope, file) {
var nodes = [];
file.moduleFormatter.exportDeclaration(node, nodes, parent);
keepBlockHoist(node, nodes);
return nodes;
}
export function ExportNamedDeclaration(node, parent, scope, file) {
// flow type
if (this.get("declaration").isTypeAlias()) return;
var nodes = [];
if (node.declaration) {
// make sure variable exports have an initializer
// this is done here to avoid duplicating it in the module formatters
if (t.isVariableDeclaration(node.declaration)) {
var declar = node.declaration.declarations[0];
declar.init = declar.init || t.identifier("undefined");
if (node.specifiers.length) {
for (var specifier of (node.specifiers: Array)) {
file.moduleFormatter.importSpecifier(specifier, node, nodes, scope);
}
} else {
file.moduleFormatter.importDeclaration(node, nodes, scope);
}
file.moduleFormatter.exportDeclaration(node, nodes, parent);
} else if (node.specifiers) {
for (let i = 0; i < node.specifiers.length; i++) {
file.moduleFormatter.exportSpecifier(node.specifiers[i], node, nodes, parent);
if (nodes.length === 1) {
// inherit `_blockHoist` - this is for `_blockHoist` in File.prototype.addImport
nodes[0]._blockHoist = node._blockHoist;
}
return nodes;
},
ExportAllDeclaration(node, parent, scope, file) {
var nodes = [];
file.moduleFormatter.exportAllDeclaration(node, nodes, scope);
keepBlockHoist(node, nodes);
return nodes;
},
ExportDefaultDeclaration(node, parent, scope, file) {
var nodes = [];
file.moduleFormatter.exportDeclaration(node, nodes, scope);
keepBlockHoist(node, nodes);
return nodes;
},
ExportNamedDeclaration(node, parent, scope, file) {
// flow type
if (this.get("declaration").isTypeAlias()) return;
var nodes = [];
if (node.declaration) {
// make sure variable exports have an initializer
// this is done here to avoid duplicating it in the module formatters
if (t.isVariableDeclaration(node.declaration)) {
var declar = node.declaration.declarations[0];
declar.init = declar.init || t.identifier("undefined");
}
file.moduleFormatter.exportDeclaration(node, nodes, scope);
} else if (node.specifiers) {
for (let i = 0; i < node.specifiers.length; i++) {
file.moduleFormatter.exportSpecifier(node.specifiers[i], node, nodes, scope);
}
}
keepBlockHoist(node, nodes);
return nodes;
}
keepBlockHoist(node, nodes);
return nodes;
}
};

View File

@@ -17,17 +17,19 @@ function Property(path, node, scope, getObjectRef, file) {
replaceSupers.replace();
}
export function ObjectExpression(node, parent, scope, file) {
var objectRef;
var getObjectRef = () => objectRef = objectRef || scope.generateUidIdentifier("obj");
export var visitor = {
ObjectExpression(node, parent, scope, file) {
var objectRef;
var getObjectRef = () => objectRef = objectRef || scope.generateUidIdentifier("obj");
var propPaths = this.get("properties");
for (var i = 0; i < node.properties.length; i++) {
Property(propPaths[i], node.properties[i], scope, getObjectRef, file);
}
var propPaths = this.get("properties");
for (var i = 0; i < node.properties.length; i++) {
Property(propPaths[i], node.properties[i], scope, getObjectRef, file);
}
if (objectRef) {
scope.push({ id: objectRef });
return t.assignmentExpression("=", objectRef, node);
if (objectRef) {
scope.push({ id: objectRef });
return t.assignmentExpression("=", objectRef, node);
}
}
}
};

View File

@@ -22,97 +22,99 @@ var iifeVisitor = {
}
};
export function Func/*tion*/(node, parent, scope, file) {
if (!hasDefaults(node)) return;
export var visitor = {
Function(node, parent, scope, file) {
if (!hasDefaults(node)) return;
// ensure it's a block, useful for arrow functions
t.ensureBlock(node);
// ensure it's a block, useful for arrow functions
this.ensureBlock();
var state = {
iife: false,
scope: scope
};
var state = {
iife: false,
scope: scope
};
var body = [];
var body = [];
//
var argsIdentifier = t.identifier("arguments");
argsIdentifier._shadowedFunctionLiteral = true;
//
var argsIdentifier = t.identifier("arguments");
argsIdentifier._shadowedFunctionLiteral = true;
// push a default parameter definition
function pushDefNode(left, right, i) {
var defNode;
if (exceedsLastNonDefault(i) || t.isPattern(left) || file.transformers["es6.spec.blockScoping"].canTransform()) {
defNode = util.template("default-parameter", {
VARIABLE_NAME: left,
DEFAULT_VALUE: right,
ARGUMENT_KEY: t.literal(i),
ARGUMENTS: argsIdentifier
}, true);
} else {
defNode = util.template("default-parameter-assign", {
VARIABLE_NAME: left,
DEFAULT_VALUE: right
}, true);
}
defNode._blockHoist = node.params.length - i;
body.push(defNode);
}
// check if an index exceeds the functions arity
function exceedsLastNonDefault(i) {
return i + 1 > lastNonDefaultParam;
}
//
var lastNonDefaultParam = getFunctionArity(node);
//
var params = this.get("params");
for (var i = 0; i < params.length; i++) {
var param = params[i];
if (!param.isAssignmentPattern()) {
if (!param.isIdentifier()) {
param.traverse(iifeVisitor, state);
}
if (file.transformers["es6.spec.blockScoping"].canTransform() && param.isIdentifier()) {
pushDefNode(param.node, t.identifier("undefined"), i);
}
continue;
}
var left = param.get("left");
var right = param.get("right");
if (exceedsLastNonDefault(i) || left.isPattern()) {
var placeholder = scope.generateUidIdentifier("x");
placeholder._isDefaultPlaceholder = true;
node.params[i] = placeholder;
} else {
node.params[i] = left.node;
}
if (!state.iife) {
if (right.isIdentifier() && scope.hasOwnBinding(right.node.name)) {
state.iife = true;
// push a default parameter definition
function pushDefNode(left, right, i) {
var defNode;
if (exceedsLastNonDefault(i) || t.isPattern(left) || file.transformers["es6.spec.blockScoping"].canTransform()) {
defNode = util.template("default-parameter", {
VARIABLE_NAME: left,
DEFAULT_VALUE: right,
ARGUMENT_KEY: t.literal(i),
ARGUMENTS: argsIdentifier
}, true);
} else {
right.traverse(iifeVisitor, state);
defNode = util.template("default-parameter-assign", {
VARIABLE_NAME: left,
DEFAULT_VALUE: right
}, true);
}
defNode._blockHoist = node.params.length - i;
body.push(defNode);
}
pushDefNode(left.node, right.node, i);
}
// check if an index exceeds the functions arity
function exceedsLastNonDefault(i) {
return i + 1 > lastNonDefaultParam;
}
// we need to cut off all trailing default parameters
node.params = node.params.slice(0, lastNonDefaultParam);
//
var lastNonDefaultParam = getFunctionArity(node);
if (state.iife) {
body.push(callDelegate(node, scope));
node.body = t.blockStatement(body);
} else {
node.body.body = body.concat(node.body.body);
//
var params = this.get("params");
for (var i = 0; i < params.length; i++) {
var param = params[i];
if (!param.isAssignmentPattern()) {
if (!param.isIdentifier()) {
param.traverse(iifeVisitor, state);
}
if (file.transformers["es6.spec.blockScoping"].canTransform() && param.isIdentifier()) {
pushDefNode(param.node, t.identifier("undefined"), i);
}
continue;
}
var left = param.get("left");
var right = param.get("right");
if (exceedsLastNonDefault(i) || left.isPattern()) {
var placeholder = scope.generateUidIdentifier("x");
placeholder._isDefaultPlaceholder = true;
node.params[i] = placeholder;
} else {
node.params[i] = left.node;
}
if (!state.iife) {
if (right.isIdentifier() && scope.hasOwnBinding(right.node.name)) {
state.iife = true;
} else {
right.traverse(iifeVisitor, state);
}
}
pushDefNode(left.node, right.node, i);
}
// we need to cut off all trailing default parameters
node.params = node.params.slice(0, lastNonDefaultParam);
if (state.iife) {
body.push(callDelegate(node, scope));
node.body = t.blockStatement(body);
} else {
node.body.body = body.concat(node.body.body);
}
}
}
};

View File

@@ -9,41 +9,54 @@ var memberExpressionOptimisationVisitor = {
}
},
enter(node, parent, scope, state) {
var stop = () => {
state.canOptimise = false;
this.stop();
};
if (this.isArrowFunctionExpression()) return stop();
Function(node, parent, scope, state) {
// skip over functions as whatever `arguments` we reference inside will refer
// to the wrong function
if (this.isFunctionDeclaration() || this.isFunctionExpression()) {
state.noOptimise = true;
this.traverse(memberExpressionOptimisationVisitor, state);
state.noOptimise = false;
return this.skip();
state.noOptimise = true;
this.traverse(memberExpressionOptimisationVisitor, state);
state.noOptimise = false;
this.skip();
},
ReferencedIdentifier(node, parent, scope, state) {
// we can't guarantee the purity of arguments
if (node.name === "arguments") {
state.deopted = true;
}
// is this a referenced identifier and is it referencing the rest parameter?
if (!this.isReferencedIdentifier({ name: state.name })) return;
if (node.name !== state.name) return;
if (!state.noOptimise && t.isMemberExpression(parent) && parent.computed) {
// if we know that this member expression is referencing a number then we can safely
// optimise it
var prop = this.parentPath.get("property");
if (prop.isBaseType("number")) {
state.candidates.push(this);
return;
if (!state.noOptimise) {
if (this.parentPath.isMemberExpression({ computed: true, object: node })) {
// if we know that this member expression is referencing a number then we can safely
// optimise it
var prop = this.parentPath.get("property");
if (prop.isBaseType("number")) {
state.candidates.push(this);
return;
}
}
// optimise single spread args in calls
if (this.parentPath.isSpreadElement() && state.offset === 0) {
var call = this.parentPath.parentPath;
if (call.isCallExpression() && call.node.arguments.length === 1) {
state.candidates.push(this);
return;
}
}
}
stop();
if (state.noOptimise) {
state.deopted = true;
} else {
state.references.push(this);
}
}
};
function optimizeMemberExpression(parent, offset) {
function optimiseMemberExpression(parent, offset) {
if (offset === 0) return;
var newExpr;
@@ -58,91 +71,115 @@ function optimizeMemberExpression(parent, offset) {
}
}
var hasRest = function (node) {
function hasRest(node) {
return t.isRestElement(node.params[node.params.length - 1]);
};
export function Func/*tion*/(node, parent, scope, file) {
if (!hasRest(node)) return;
var restParam = node.params.pop();
var rest = restParam.argument;
var argsId = t.identifier("arguments");
// otherwise `arguments` will be remapped in arrow functions
argsId._shadowedFunctionLiteral = true;
// support patterns
if (t.isPattern(rest)) {
var pattern = rest;
rest = scope.generateUidIdentifier("ref");
var declar = t.variableDeclaration("let", pattern.elements.map(function (elem, index) {
var accessExpr = t.memberExpression(rest, t.literal(index), true);
return t.variableDeclarator(elem, accessExpr);
}));
node.body.body.unshift(declar);
}
// check if rest is used in member expressions and optimise for those cases
var state = {
outerBinding: scope.getBindingIdentifier(rest.name),
canOptimise: true,
candidates: [],
method: node,
name: rest.name
};
this.traverse(memberExpressionOptimisationVisitor, state);
// we only have shorthands and there's no other references
if (state.canOptimise && state.candidates.length) {
for (var candidate of (state.candidates: Array)) {
candidate.replaceWith(argsId);
optimizeMemberExpression(candidate.parent, node.params.length);
}
return;
}
//
var start = t.literal(node.params.length);
var key = scope.generateUidIdentifier("key");
var len = scope.generateUidIdentifier("len");
var arrKey = key;
var arrLen = len;
if (node.params.length) {
// this method has additional params, so we need to subtract
// the index of the current argument position from the
// position in the array that we want to populate
arrKey = t.binaryExpression("-", key, start);
// we need to work out the size of the array that we're
// going to store all the rest parameters
//
// we need to add a check to avoid constructing the array
// with <0 if there are less arguments than params as it'll
// cause an error
arrLen = t.conditionalExpression(
t.binaryExpression(">", len, start),
t.binaryExpression("-", len, start),
t.literal(0)
);
}
var loop = util.template("rest", {
ARRAY_TYPE: restParam.typeAnnotation,
ARGUMENTS: argsId,
ARRAY_KEY: arrKey,
ARRAY_LEN: arrLen,
START: start,
ARRAY: rest,
KEY: key,
LEN: len
});
loop._blockHoist = node.params.length + 1;
node.body.body.unshift(loop);
}
export var visitor = {
Function(node, parent, scope) {
if (!hasRest(node)) return;
var restParam = node.params.pop();
var rest = restParam.argument;
var argsId = t.identifier("arguments");
// otherwise `arguments` will be remapped in arrow functions
argsId._shadowedFunctionLiteral = true;
// support patterns
if (t.isPattern(rest)) {
var pattern = rest;
rest = scope.generateUidIdentifier("ref");
var declar = t.variableDeclaration("let", pattern.elements.map(function (elem, index) {
var accessExpr = t.memberExpression(rest, t.literal(index), true);
return t.variableDeclarator(elem, accessExpr);
}));
node.body.body.unshift(declar);
}
// check and optimise for extremely common cases
var state = {
references: [],
offset: node.params.length,
argumentsNode: argsId,
outerBinding: scope.getBindingIdentifier(rest.name),
// candidate member expressions we could optimise if there are no other references
candidates: [],
// local rest binding name
name: rest.name,
// whether any references to the rest parameter were made in a function
deopted: false
};
this.traverse(memberExpressionOptimisationVisitor, state);
if (!state.deopted && !state.references.length) {
// we only have shorthands and there are no other references
if (state.candidates.length) {
for (var candidate of (state.candidates: Array)) {
candidate.replaceWith(argsId);
if (candidate.parentPath.isMemberExpression()) {
optimiseMemberExpression(candidate.parent, state.offset);
}
}
}
return;
} else {
state.references = state.references.concat(state.candidates);
}
//
var start = t.literal(node.params.length);
var key = scope.generateUidIdentifier("key");
var len = scope.generateUidIdentifier("len");
var arrKey = key;
var arrLen = len;
if (node.params.length) {
// this method has additional params, so we need to subtract
// the index of the current argument position from the
// position in the array that we want to populate
arrKey = t.binaryExpression("-", key, start);
// we need to work out the size of the array that we're
// going to store all the rest parameters
//
// we need to add a check to avoid constructing the array
// with <0 if there are less arguments than params as it'll
// cause an error
arrLen = t.conditionalExpression(
t.binaryExpression(">", len, start),
t.binaryExpression("-", len, start),
t.literal(0)
);
}
var loop = util.template("rest", {
ARRAY_TYPE: restParam.typeAnnotation,
ARGUMENTS: argsId,
ARRAY_KEY: arrKey,
ARRAY_LEN: arrLen,
START: start,
ARRAY: rest,
KEY: key,
LEN: len
});
if (!state.deopted) {
// perform allocation at the lowest common denominator of all references
this.getEarliestCommonAncestorFrom(state.references).getStatementParent().insertBefore(loop);
return;
}
loop._blockHoist = node.params.length + 1;
node.body.body.unshift(loop);
}
};

View File

@@ -63,40 +63,42 @@ function spec(node, body, objId, initProps, file) {
}
}
export var ObjectExpression = {
exit(node, parent, scope, file) {
var hasComputed = false;
export var visitor = {
ObjectExpression: {
exit(node, parent, scope, file) {
var hasComputed = false;
for (var prop of (node.properties: Array)) {
hasComputed = t.isProperty(prop, { computed: true, kind: "init" });
if (hasComputed) break;
for (var prop of (node.properties: Array)) {
hasComputed = t.isProperty(prop, { computed: true, kind: "init" });
if (hasComputed) break;
}
if (!hasComputed) return;
var initProps = [];
var objId = scope.generateUidIdentifierBasedOnNode(parent);
//
var body = [];
//
var callback = spec;
if (file.isLoose("es6.properties.computed")) callback = loose;
var result = callback(node, body, objId, initProps, file);
if (result) return result;
//
body.unshift(t.variableDeclaration("var", [
t.variableDeclarator(objId, t.objectExpression(initProps))
]));
body.push(t.expressionStatement(objId));
return body;
}
if (!hasComputed) return;
var initProps = [];
var objId = scope.generateUidIdentifierBasedOnNode(parent);
//
var body = [];
//
var callback = spec;
if (file.isLoose("es6.properties.computed")) callback = loose;
var result = callback(node, body, objId, initProps, file);
if (result) return result;
//
body.unshift(t.variableDeclaration("var", [
t.variableDeclarator(objId, t.objectExpression(initProps))
]));
body.push(t.expressionStatement(objId));
return body;
}
};

View File

@@ -1,9 +1,11 @@
export function Property(node) {
if (node.method) {
node.method = false;
}
export var visitor = {
Property(node) {
if (node.method) {
node.method = false;
}
if (node.shorthand) {
node.shorthand = false;
if (node.shorthand) {
node.shorthand = false;
}
}
}
};

View File

@@ -1,10 +1,12 @@
import * as regex from "../../helpers/regex";
import * as t from "../../../types";
export function Literal(node) {
if (!regex.is(node, "y")) return;
return t.newExpression(t.identifier("RegExp"), [
t.literal(node.regex.pattern),
t.literal(node.regex.flags)
]);
}
export var visitor = {
Literal(node) {
if (!regex.is(node, "y")) return;
return t.newExpression(t.identifier("RegExp"), [
t.literal(node.regex.pattern),
t.literal(node.regex.flags)
]);
}
};

View File

@@ -1,8 +1,10 @@
import rewritePattern from "regexpu/rewrite-pattern";
import * as regex from "../../helpers/regex";
export function Literal(node) {
if (!regex.is(node, "u")) return;
node.regex.pattern = rewritePattern(node.regex.pattern, node.regex.flags);
regex.pullFlag(node, "u");
}
export var visitor = {
Literal(node) {
if (!regex.is(node, "u")) return;
node.regex.pattern = rewritePattern(node.regex.pattern, node.regex.flags);
regex.pullFlag(node, "u");
}
};

View File

@@ -15,7 +15,7 @@ function references(node, scope, state) {
return scope.getBindingIdentifier(node.name) === declared;
}
var visitor = {
var refVisitor = {
ReferencedIdentifier(node, parent, scope, state) {
if (t.isFor(parent) && parent.left === node) return;
@@ -62,16 +62,16 @@ export var metadata = {
group: "builtin-advanced"
};
export var BlockStatement = {
exit(node, parent, scope, file) {
var letRefs = node._letReferences;
if (!letRefs) return;
export var visitor = {
"Program|Loop|BlockStatement": {
exit(node, parent, scope, file) {
var letRefs = node._letReferences;
if (!letRefs) return;
this.traverse(visitor, {
letRefs: letRefs,
file: file
});
this.traverse(refVisitor, {
letRefs: letRefs,
file: file
});
}
}
};
export { BlockStatement as Program, BlockStatement as Loop };

View File

@@ -4,34 +4,34 @@ export var metadata = {
optional: true
};
export function UnaryExpression(node, parent, scope, file) {
if (node._ignoreSpecSymbols) return;
export var visitor = {
UnaryExpression(node, parent, scope, file) {
if (node._ignoreSpecSymbols) return;
if (node.operator === "typeof") {
var call = t.callExpression(file.addHelper("typeof"), [node.argument]);
if (this.get("argument").isIdentifier()) {
var undefLiteral = t.literal("undefined");
var unary = t.unaryExpression("typeof", node.argument);
unary._ignoreSpecSymbols = true;
return t.conditionalExpression(
t.binaryExpression("===", unary, undefLiteral),
undefLiteral,
call
);
} else {
return call;
if (node.operator === "typeof") {
var call = t.callExpression(file.addHelper("typeof"), [node.argument]);
if (this.get("argument").isIdentifier()) {
var undefLiteral = t.literal("undefined");
var unary = t.unaryExpression("typeof", node.argument);
unary._ignoreSpecSymbols = true;
return t.conditionalExpression(
t.binaryExpression("===", unary, undefLiteral),
undefLiteral,
call
);
} else {
return call;
}
}
},
BinaryExpression(node, parent, scope, file) {
if (node.operator === "instanceof") {
return t.callExpression(file.addHelper("instanceof"), [node.left, node.right]);
}
},
"VariableDeclaration|FunctionDeclaration"(node) {
if (node._generated) this.skip();
}
}
export function BinaryExpression(node, parent, scope, file) {
if (node.operator === "instanceof") {
return t.callExpression(file.addHelper("instanceof"), [node.left, node.right]);
}
}
export function VariableDeclaration(node) {
if (node._generated) this.skip();
}
export { VariableDeclaration as FunctionDeclaration };
};

View File

@@ -5,10 +5,12 @@ export var metadata = {
group: "builtin-pre"
};
export function TemplateLiteral(node, parent, scope, file) {
if (t.isTaggedTemplateExpression(parent)) return;
export var visitor = {
TemplateLiteral(node, parent) {
if (t.isTaggedTemplateExpression(parent)) return;
for (var i = 0; i < node.expressions.length; i++) {
node.expressions[i] = t.callExpression(t.identifier("String"), [node.expressions[i]]);
for (var i = 0; i < node.expressions.length; i++) {
node.expressions[i] = t.callExpression(t.identifier("String"), [node.expressions[i]]);
}
}
}
};

View File

@@ -1,7 +1,7 @@
import * as t from "../../../types";
function getSpreadLiteral(spread, scope) {
if (scope.hub.file.isLoose("es6.spread")) {
if (scope.hub.file.isLoose("es6.spread") && !t.isIdentifier(spread.argument, { name: "arguments" })) {
return spread.argument;
} else {
return scope.toArray(spread.argument, true);
@@ -43,76 +43,78 @@ function build(props, scope) {
return nodes;
}
export function ArrayExpression(node, parent, scope) {
var elements = node.elements;
if (!hasSpread(elements)) return;
export var visitor = {
ArrayExpression(node, parent, scope) {
var elements = node.elements;
if (!hasSpread(elements)) return;
var nodes = build(elements, scope);
var first = nodes.shift();
var nodes = build(elements, scope);
var first = nodes.shift();
if (!t.isArrayExpression(first)) {
nodes.unshift(first);
first = t.arrayExpression([]);
}
return t.callExpression(t.memberExpression(first, t.identifier("concat")), nodes);
}
export function CallExpression(node, parent, scope) {
var args = node.arguments;
if (!hasSpread(args)) return;
var contextLiteral = t.identifier("undefined");
node.arguments = [];
var nodes;
if (args.length === 1 && args[0].argument.name === "arguments") {
nodes = [args[0].argument];
} else {
nodes = build(args, scope);
}
var first = nodes.shift();
if (nodes.length) {
node.arguments.push(t.callExpression(t.memberExpression(first, t.identifier("concat")), nodes));
} else {
node.arguments.push(first);
}
var callee = node.callee;
if (this.get("callee").isMemberExpression()) {
var temp = scope.maybeGenerateMemoised(callee.object);
if (temp) {
callee.object = t.assignmentExpression("=", temp, callee.object);
contextLiteral = temp;
} else {
contextLiteral = callee.object;
if (!t.isArrayExpression(first)) {
nodes.unshift(first);
first = t.arrayExpression([]);
}
t.appendToMemberExpression(callee, t.identifier("apply"));
} else {
node.callee = t.memberExpression(node.callee, t.identifier("apply"));
return t.callExpression(t.memberExpression(first, t.identifier("concat")), nodes);
},
CallExpression(node, parent, scope) {
var args = node.arguments;
if (!hasSpread(args)) return;
var contextLiteral = t.identifier("undefined");
node.arguments = [];
var nodes;
if (args.length === 1 && args[0].argument.name === "arguments") {
nodes = [args[0].argument];
} else {
nodes = build(args, scope);
}
var first = nodes.shift();
if (nodes.length) {
node.arguments.push(t.callExpression(t.memberExpression(first, t.identifier("concat")), nodes));
} else {
node.arguments.push(first);
}
var callee = node.callee;
if (this.get("callee").isMemberExpression()) {
var temp = scope.maybeGenerateMemoised(callee.object);
if (temp) {
callee.object = t.assignmentExpression("=", temp, callee.object);
contextLiteral = temp;
} else {
contextLiteral = callee.object;
}
t.appendToMemberExpression(callee, t.identifier("apply"));
} else {
node.callee = t.memberExpression(node.callee, t.identifier("apply"));
}
node.arguments.unshift(contextLiteral);
},
NewExpression(node, parent, scope, file) {
var args = node.arguments;
if (!hasSpread(args)) return;
var nodes = build(args, scope);
var context = t.arrayExpression([t.literal(null)]);
args = t.callExpression(t.memberExpression(context, t.identifier("concat")), nodes);
return t.newExpression(
t.callExpression(
t.memberExpression(file.addHelper("bind"), t.identifier("apply")),
[node.callee, args]
),
[]
);
}
node.arguments.unshift(contextLiteral);
}
export function NewExpression(node, parent, scope, file) {
var args = node.arguments;
if (!hasSpread(args)) return;
var nodes = build(args, scope);
var context = t.arrayExpression([t.literal(null)]);
args = t.callExpression(t.memberExpression(context, t.identifier("concat")), nodes);
return t.newExpression(
t.callExpression(
t.memberExpression(file.addHelper("bind"), t.identifier("apply")),
[node.callee, args]
),
[]
);
}
};

View File

@@ -9,11 +9,13 @@ export var metadata = {
group: "builtin-trailing"
};
export function Func/*tion*/(node, parent, scope, file) {
if (node.generator || node.async) return;
var tailCall = new TailCallTransformer(this, scope, file);
tailCall.run();
}
export var visitor = {
Function(node, parent, scope, file) {
if (node.generator || node.async) return;
var tailCall = new TailCallTransformer(this, scope, file);
tailCall.run();
}
};
function returnBlock(expr) {
return t.blockStatement([t.returnStatement(expr)]);
@@ -148,7 +150,7 @@ class TailCallTransformer {
//
var body = t.ensureBlock(node).body;
var body = this.path.ensureBlock().body;
for (var i = 0; i < body.length; i++) {
var bodyNode = body[i];

View File

@@ -6,6 +6,10 @@ export var metadata = {
group: "builtin-pre"
};
function isString(node) {
return t.isLiteral(node) && typeof node.value === "string";
}
function buildBinaryExpression(left, right) {
var node = t.binaryExpression("+", left, right);
node._templateLiteralProduced = true;
@@ -21,54 +25,65 @@ function crawl(path) {
}
}
export function TaggedTemplateExpression(node, parent, scope, file) {
var quasi = node.quasi;
var args = [];
export var visitor = {
TaggedTemplateExpression(node, parent, scope, file) {
var quasi = node.quasi;
var args = [];
var strings = [];
var raw = [];
var strings = [];
var raw = [];
for (var elem of (quasi.quasis: Array)) {
strings.push(t.literal(elem.value.cooked));
raw.push(t.literal(elem.value.raw));
}
strings = t.arrayExpression(strings);
raw = t.arrayExpression(raw);
var templateName = "tagged-template-literal";
if (file.isLoose("es6.templateLiterals")) templateName += "-loose";
args.push(t.callExpression(file.addHelper(templateName), [strings, raw]));
args = args.concat(quasi.expressions);
return t.callExpression(node.tag, args);
}
export function TemplateLiteral(node, parent, scope, file) {
var nodes = [];
for (let elem of (node.quasis: Array)) {
nodes.push(t.literal(elem.value.cooked));
var expr = node.expressions.shift();
if (expr) nodes.push(expr);
}
if (nodes.length > 1) {
// remove redundant '' at the end of the expression
var last = nodes[nodes.length - 1];
if (t.isLiteral(last, { value: "" })) nodes.pop();
var root = buildBinaryExpression(nodes.shift(), nodes.shift());
for (let node of (nodes: Array)) {
root = buildBinaryExpression(root, node);
for (var elem of (quasi.quasis: Array)) {
strings.push(t.literal(elem.value.cooked));
raw.push(t.literal(elem.value.raw));
}
this.replaceWith(root);
//crawl(this);
} else {
return nodes[0];
strings = t.arrayExpression(strings);
raw = t.arrayExpression(raw);
var templateName = "tagged-template-literal";
if (file.isLoose("es6.templateLiterals")) templateName += "-loose";
args.push(t.callExpression(file.addHelper(templateName), [strings, raw]));
args = args.concat(quasi.expressions);
return t.callExpression(node.tag, args);
},
TemplateLiteral(node, parent, scope, file) {
var nodes = [];
for (let elem of (node.quasis: Array)) {
nodes.push(t.literal(elem.value.cooked));
var expr = node.expressions.shift();
if (expr) nodes.push(expr);
}
if (nodes.length > 1) {
// filter out empty string literals
nodes = nodes.filter(n => !t.isLiteral(n, { value: "" }));
if (nodes.length === 1 && isString(nodes[0])) {
return nodes[0];
}
// since `+` is left-to-right associative
// ensure the first node is a string if first/second isn't
if (!isString(nodes[0]) && !isString(nodes[1])) {
nodes.unshift(t.literal(""));
}
var root = buildBinaryExpression(nodes.shift(), nodes.shift());
for (let node of (nodes: Array)) {
root = buildBinaryExpression(root, node);
}
this.replaceWith(root);
//crawl(this);
} else {
return nodes[0];
}
}
}
};

View File

@@ -7,11 +7,13 @@ export var metadata = {
stage: 0
};
export function ComprehensionExpression(node, parent, scope, file) {
var callback = array;
if (node.generator) callback = generator;
return callback(node, parent, scope);
}
export var visitor = {
ComprehensionExpression(node, parent, scope) {
var callback = array;
if (node.generator) callback = generator;
return callback(node, parent, scope);
}
};
function generator(node) {
var body = [];

View File

@@ -8,35 +8,37 @@ export var metadata = {
stage: 1
};
export function ObjectExpression(node, parent, scope, file) {
var hasDecorators = false;
for (let i = 0; i < node.properties.length; i++) {
let prop = node.properties[i];
if (prop.decorators) {
hasDecorators = true;
break;
export var visitor = {
ObjectExpression(node, parent, scope, file) {
var hasDecorators = false;
for (let i = 0; i < node.properties.length; i++) {
let prop = node.properties[i];
if (prop.decorators) {
hasDecorators = true;
break;
}
}
}
if (!hasDecorators) return;
if (!hasDecorators) return;
var mutatorMap = {};
var mutatorMap = {};
for (let i = 0; i < node.properties.length; i++) {
let prop = node.properties[i];
if (prop.decorators) memoiseDecorators(prop.decorators, scope);
for (let i = 0; i < node.properties.length; i++) {
let prop = node.properties[i];
if (prop.decorators) memoiseDecorators(prop.decorators, scope);
if (prop.kind === "init" && !prop.method) {
prop.kind = "";
prop.value = t.functionExpression(null, [], t.blockStatement([
t.returnStatement(prop.value)
]));
if (prop.kind === "init" && !prop.method) {
prop.kind = "";
prop.value = t.functionExpression(null, [], t.blockStatement([
t.returnStatement(prop.value)
]));
}
defineMap.push(mutatorMap, prop, "initializer", file);
}
defineMap.push(mutatorMap, prop, "initializer", file);
var obj = defineMap.toClassObject(mutatorMap);
obj = defineMap.toComputedObjectFromClass(obj);
return t.callExpression(file.addHelper("create-decorated-object"), [obj]);
}
var obj = defineMap.toClassObject(mutatorMap);
obj = defineMap.toComputedObjectFromClass(obj);
return t.callExpression(file.addHelper("create-decorated-object"), [obj]);
}
};

View File

@@ -5,11 +5,13 @@ export var metadata = {
stage: 0
};
export function DoExpression(node) {
var body = node.body.body;
if (body.length) {
return body;
} else {
return t.identifier("undefined");
export var visitor = {
DoExpression(node) {
var body = node.body.body;
if (body.length) {
return body;
} else {
return t.identifier("undefined");
}
}
}
};

View File

@@ -9,20 +9,10 @@ export var metadata = {
var MATH_POW = t.memberExpression(t.identifier("Math"), t.identifier("pow"));
var {
ExpressionStatement,
AssignmentExpression,
BinaryExpression
} = build({
export var visitor = build({
operator: "**",
build(left, right) {
return t.callExpression(MATH_POW, [left, right]);
}
});
export {
ExpressionStatement,
AssignmentExpression,
BinaryExpression
};

View File

@@ -26,14 +26,16 @@ function build(node, nodes, scope) {
build(node, nodes, scope);
}
export function ExportNamedDeclaration(node, parent, scope) {
var nodes = [];
build(node, nodes, scope);
if (!nodes.length) return;
export var visitor = {
ExportNamedDeclaration(node, parent, scope) {
var nodes = [];
build(node, nodes, scope);
if (!nodes.length) return;
if (node.specifiers.length >= 1) {
nodes.push(node);
if (node.specifiers.length >= 1) {
nodes.push(node);
}
return nodes;
}
return nodes;
}
};

View File

@@ -36,16 +36,18 @@ function inferBindContext(bind, scope) {
return tempId;
}
export function CallExpression(node, parent, scope, file) {
var bind = node.callee;
if (!t.isBindExpression(bind)) return;
export var visitor = {
CallExpression(node, parent, scope) {
var bind = node.callee;
if (!t.isBindExpression(bind)) return;
var context = inferBindContext(bind, scope);
node.callee = t.memberExpression(bind.callee, t.identifier("call"));
node.arguments.unshift(context);
}
var context = inferBindContext(bind, scope);
node.callee = t.memberExpression(bind.callee, t.identifier("call"));
node.arguments.unshift(context);
},
export function BindExpression(node, parent, scope, file) {
var context = inferBindContext(node, scope);
return t.callExpression(t.memberExpression(node.callee, t.identifier("bind")), [context]);
}
BindExpression(node, parent, scope) {
var context = inferBindContext(node, scope);
return t.callExpression(t.memberExpression(node.callee, t.identifier("bind")), [context]);
}
};

View File

@@ -16,33 +16,35 @@ var hasSpread = function (node) {
return false;
};
export function ObjectExpression(node, parent, scope, file) {
if (!hasSpread(node)) return;
export var visitor = {
ObjectExpression(node, parent, scope, file) {
if (!hasSpread(node)) return;
var args = [];
var props = [];
var args = [];
var props = [];
var push = function () {
if (!props.length) return;
args.push(t.objectExpression(props));
props = [];
};
var push = function () {
if (!props.length) return;
args.push(t.objectExpression(props));
props = [];
};
for (var i = 0; i < node.properties.length; i++) {
var prop = node.properties[i];
if (t.isSpreadProperty(prop)) {
push();
args.push(prop.argument);
} else {
props.push(prop);
for (var i = 0; i < node.properties.length; i++) {
var prop = node.properties[i];
if (t.isSpreadProperty(prop)) {
push();
args.push(prop.argument);
} else {
props.push(prop);
}
}
push();
if (!t.isObjectExpression(args[0])) {
args.unshift(t.objectExpression([]));
}
return t.callExpression(file.addHelper("extends"), args);
}
push();
if (!t.isObjectExpression(args[0])) {
args.unshift(t.objectExpression([]));
}
return t.callExpression(file.addHelper("extends"), args);
}
};

View File

@@ -1,34 +1,35 @@
export default {
//- builtin-prepass
"minification.constantFolding": require("./minification/constant-folding"),
"minification.constantFolding": require("babel-plugin-constant-folding"),
//- builtin-pre
strict: require("./other/strict"),
eval: require("./other/eval"),
eval: require("babel-plugin-eval"),
_explode: require("./internal/explode"),
_validation: require("./internal/validation"),
_hoistDirectives: require("./internal/hoist-directives"),
"minification.removeDebugger": require("./minification/remove-debugger"),
"minification.removeConsole": require("./minification/remove-console"),
"utility.inlineEnvironmentVariables": require("./utility/inline-environment-variables"),
"minification.deadCodeElimination": require("./minification/dead-code-elimination"),
"minification.removeDebugger": require("babel-plugin-remove-debugger"),
"minification.removeConsole": require("babel-plugin-remove-console"),
"utility.inlineEnvironmentVariables": require("babel-plugin-inline-environment-variables"),
"minification.deadCodeElimination": require("babel-plugin-dead-code-elimination"),
_modules: require("./internal/modules"),
"spec.functionName": require("./spec/function-name"),
"react.displayName": require("babel-plugin-react-display-name"),
"es6.spec.templateLiterals": require("./es6/spec.template-literals"),
"es6.templateLiterals": require("./es6/template-literals"),
"validation.undeclaredVariableCheck": require("babel-plugin-undeclared-variables-check"),
//- builtin-basic
// this is where the bulk of the ES6 transformations take place, none of them require traversal state
// so they can all be concatenated together for performance
"spec.functionName": require("./spec/function-name"),
"es7.classProperties": require("./es7/class-properties"),
"es7.trailingFunctionCommas": require("./es7/trailing-function-commas"),
"es7.asyncFunctions": require("./es7/async-functions"),
"es7.decorators": require("./es7/decorators"),
"validation.undeclaredVariableCheck": require("./validation/undeclared-variable-check"),
"validation.react": require("./validation/react"),
"es6.arrowFunctions": require("./es6/arrow-functions"),
"spec.blockScopedFunctions": require("./spec/block-scoped-functions"),
"optimisation.react.constantElements": require("./optimisation/react.constant-elements"),
"optimisation.react.constantElements": require("babel-plugin-react-constant-elements"),
"optimisation.react.inlineElements": require("./optimisation/react.inline-elements"),
"es7.comprehensions": require("./es7/comprehensions"),
"es6.classes": require("./es6/classes"),
@@ -49,11 +50,11 @@ export default {
"es6.spread": require("./es6/spread"),
"es6.parameters.default": require("./es6/parameters.default"),
"es7.exportExtensions": require("./es7/export-extensions"),
"spec.protoToAssign": require("./spec/proto-to-assign"),
"spec.protoToAssign": require("babel-plugin-proto-to-assign"),
"es7.doExpressions": require("./es7/do-expressions"),
"es6.spec.symbols": require("./es6/spec.symbols"),
"es7.functionBind": require("./es7/function-bind"),
"spec.undefinedToVoid": require("./spec/undefined-to-void"),
"spec.undefinedToVoid": require("babel-plugin-undefined-to-void"),
//- builtin-advanced
"es6.destructuring": require("./es6/destructuring"),
@@ -67,7 +68,7 @@ export default {
// hissy fit
//- builtin-modules
runtime: require("./other/runtime"),
runtime: require("babel-plugin-runtime"),
"es6.modules": require("./es6/modules"),
_moduleFormatter: require("./internal/module-formatter"),
@@ -79,9 +80,9 @@ export default {
_shadowFunctions: require("./internal/shadow-functions"),
"es3.propertyLiterals": require("./es3/property-literals"),
"es3.memberExpressionLiterals": require("./es3/member-expression-literals"),
"minification.memberExpressionLiterals": require("./minification/member-expression-literals"),
"minification.propertyLiterals": require("./minification/property-literals"),
"minification.memberExpressionLiterals": require("babel-plugin-member-expression-literals"),
"minification.propertyLiterals": require("babel-plugin-property-literals"),
_blockHoist: require("./internal/block-hoist"),
jscript: require("./other/jscript"),
jscript: require("babel-plugin-jscript"),
flow: require("./other/flow"),
};

View File

@@ -11,24 +11,24 @@ export var metadata = {
// - 2 Priority over normal nodes
// - 3 We want this to be at the **very** top
export var BlockStatement = {
exit(node) {
var hasChange = false;
for (var i = 0; i < node.body.length; i++) {
var bodyNode = node.body[i];
if (bodyNode && bodyNode._blockHoist != null) hasChange = true;
export var visitor = {
Block: {
exit(node) {
var hasChange = false;
for (var i = 0; i < node.body.length; i++) {
var bodyNode = node.body[i];
if (bodyNode && bodyNode._blockHoist != null) hasChange = true;
}
if (!hasChange) return;
node.body = sortBy(node.body, function(bodyNode){
var priority = bodyNode && bodyNode._blockHoist;
if (priority == null) priority = 1;
if (priority === true) priority = 2;
// Higher priorities should move toward the top.
return -1 * priority;
});
}
if (!hasChange) return;
node.body = sortBy(node.body, function(bodyNode){
var priority = bodyNode && bodyNode._blockHoist;
if (priority == null) priority = 1;
if (priority === true) priority = 2;
// Higher priorities should move toward the top.
return -1 * priority;
});
}
};
export { BlockStatement as Program };

View File

@@ -25,9 +25,10 @@ function buildListClone(listKey, bindingKey, refKey) {
};
}
export var Property = buildClone("value", "key", function (node) {
return t.isAssignmentPattern(node.value) && node.value.left === node.key;
});
export var ExportDeclaration = buildListClone("specifiers", "local", "exported");
export var ImportDeclaration = buildListClone("specifiers", "local", "imported");
export var visitor = {
Property: buildClone("value", "key", function (node) {
return t.isAssignmentPattern(node.value) && node.value.left === node.key;
}),
ExportDeclaration: buildListClone("specifiers", "local", "exported"),
ImportDeclaration: buildListClone("specifiers", "local", "imported")
};

View File

@@ -4,17 +4,17 @@ export var metadata = {
group: "builtin-pre"
};
export var BlockStatement = {
exit(node) {
for (var i = 0; i < node.body.length; i++) {
var bodyNode = node.body[i];
if (t.isExpressionStatement(bodyNode) && t.isLiteral(bodyNode.expression)) {
bodyNode._blockHoist = Infinity;
} else {
return;
export var visitor = {
Block: {
exit(node) {
for (var i = 0; i < node.body.length; i++) {
var bodyNode = node.body[i];
if (t.isExpressionStatement(bodyNode) && t.isLiteral(bodyNode.expression)) {
bodyNode._blockHoist = Infinity;
} else {
return;
}
}
}
}
};
export { BlockStatement as Program };

View File

@@ -2,19 +2,21 @@ export var metadata = {
group: "builtin-modules"
};
export var Program = {
exit(program, parent, scope, file) {
// ensure that these are at the top, just like normal imports
for (var node of (file.dynamicImports: Array)) {
node._blockHoist = 3;
}
export var visitor = {
Program: {
exit(program, parent, scope, file) {
// ensure that these are at the top, just like normal imports
for (var node of (file.dynamicImports: Array)) {
node._blockHoist = 3;
}
program.body = file.dynamicImports.concat(program.body);
program.body = file.dynamicImports.concat(program.body);
if (!file.transformers["es6.modules"].canTransform()) return;
if (!file.transformers["es6.modules"].canTransform()) return;
if (file.moduleFormatter.transform) {
file.moduleFormatter.transform(program);
if (file.moduleFormatter.transform) {
file.moduleFormatter.transform(program);
}
}
}
};

View File

@@ -15,93 +15,95 @@ function getDeclar(node) {
return declar;
}
export var metadata = {
group: "builtin-pre"
};
export function ExportDefaultDeclaration(node, parent, scope) {
var declar = node.declaration;
if (t.isClassDeclaration(declar)) {
// export default class Foo {};
let nodes = [getDeclar(node), node];
node.declaration = declar.id;
return nodes;
} else if (t.isClassExpression(declar)) {
// export default class {};
var temp = scope.generateUidIdentifier("default");
node.declaration = t.variableDeclaration("var", [
t.variableDeclarator(temp, declar)
]);
let nodes = [getDeclar(node), node];
node.declaration = temp;
return nodes;
} else if (t.isFunctionDeclaration(declar)) {
// export default function Foo() {}
node._blockHoist = 2;
let nodes = [getDeclar(node), node];
node.declaration = declar.id;
return nodes;
}
}
function buildExportSpecifier(id) {
return t.exportSpecifier(clone(id), clone(id));
}
export function ExportNamedDeclaration(node, parent, scope) {
var declar = node.declaration;
export var metadata = {
group: "builtin-pre"
};
if (t.isClassDeclaration(declar)) {
// export class Foo {}
node.specifiers = [buildExportSpecifier(declar.id)];
export var visitor = {
ExportDefaultDeclaration(node, parent, scope) {
var declar = node.declaration;
let nodes = [getDeclar(node), node];
node.declaration = null;
return nodes;
} else if (t.isFunctionDeclaration(declar)) {
// export function Foo() {}
node.specifiers = [buildExportSpecifier(declar.id)];
node._blockHoist = 2;
if (t.isClassDeclaration(declar)) {
// export default class Foo {};
let nodes = [getDeclar(node), node];
node.declaration = declar.id;
return nodes;
} else if (t.isClassExpression(declar)) {
// export default class {};
var temp = scope.generateUidIdentifier("default");
node.declaration = t.variableDeclaration("var", [
t.variableDeclarator(temp, declar)
]);
let nodes = [getDeclar(node), node];
node.declaration = null;
return nodes;
} else if (t.isVariableDeclaration(declar)) {
// export var foo = "bar";
var specifiers = [];
var bindings = this.get("declaration").getBindingIdentifiers();
for (var key in bindings) {
specifiers.push(buildExportSpecifier(bindings[key]));
let nodes = [getDeclar(node), node];
node.declaration = temp;
return nodes;
} else if (t.isFunctionDeclaration(declar)) {
// export default function Foo() {}
node._blockHoist = 2;
let nodes = [getDeclar(node), node];
node.declaration = declar.id;
return nodes;
}
return [declar, t.exportNamedDeclaration(null, specifiers)];
}
}
export var Program = {
enter(node) {
var imports = [];
var rest = [];
for (var i = 0; i < node.body.length; i++) {
var bodyNode = node.body[i];
if (t.isImportDeclaration(bodyNode)) {
imports.push(bodyNode);
} else {
rest.push(bodyNode);
}
}
node.body = imports.concat(rest);
},
exit(node, parent, scope, file) {
if (!file.transformers["es6.modules"].canTransform()) return;
ExportNamedDeclaration(node) {
var declar = node.declaration;
if (file.moduleFormatter.setup) {
file.moduleFormatter.setup();
if (t.isClassDeclaration(declar)) {
// export class Foo {}
node.specifiers = [buildExportSpecifier(declar.id)];
let nodes = [getDeclar(node), node];
node.declaration = null;
return nodes;
} else if (t.isFunctionDeclaration(declar)) {
// export function Foo() {}
node.specifiers = [buildExportSpecifier(declar.id)];
node._blockHoist = 2;
let nodes = [getDeclar(node), node];
node.declaration = null;
return nodes;
} else if (t.isVariableDeclaration(declar)) {
// export var foo = "bar";
var specifiers = [];
var bindings = this.get("declaration").getBindingIdentifiers();
for (var key in bindings) {
specifiers.push(buildExportSpecifier(bindings[key]));
}
return [declar, t.exportNamedDeclaration(null, specifiers)];
}
},
Program: {
enter(node) {
var imports = [];
var rest = [];
for (var i = 0; i < node.body.length; i++) {
var bodyNode = node.body[i];
if (t.isImportDeclaration(bodyNode)) {
imports.push(bodyNode);
} else {
rest.push(bodyNode);
}
}
node.body = imports.concat(rest);
},
exit(node, parent, scope, file) {
if (!file.transformers["es6.modules"].canTransform()) return;
if (file.moduleFormatter.setup) {
file.moduleFormatter.setup();
}
}
}
};

View File

@@ -22,12 +22,14 @@ function remap(path, key, create) {
return id;
}
export function ThisExpression() {
return remap(this, "this", () => t.thisExpression());
}
export var visitor = {
ThisExpression() {
return remap(this, "this", () => t.thisExpression());
},
export function ReferencedIdentifier(node) {
if (node.name === "arguments" && !node._shadowedFunctionLiteral) {
return remap(this, "arguments", () => t.identifier("arguments"));
ReferencedIdentifier(node) {
if (node.name === "arguments" && !node._shadowedFunctionLiteral) {
return remap(this, "arguments", () => t.identifier("arguments"));
}
}
}
};

View File

@@ -5,41 +5,21 @@ export var metadata = {
group: "builtin-pre"
};
export function ForOfStatement(node, parent, scope, file) {
var left = node.left;
if (t.isVariableDeclaration(left)) {
var declar = left.declarations[0];
if (declar.init) throw file.errorWithNode(declar, messages.get("noAssignmentsInForHead"));
}
}
export var visitor = {
ForXStatement(node, parent, scope, file) {
var left = node.left;
if (t.isVariableDeclaration(left)) {
var declar = left.declarations[0];
if (declar.init) throw file.errorWithNode(declar, messages.get("noAssignmentsInForHead"));
}
},
export { ForOfStatement as ForInStatement };
export function MethodDefinition(node) {
if (node.kind !== "constructor") {
// get constructor() {}
var isConstructor = !node.computed && t.isIdentifier(node.key, { name: "constructor" });
// get ["constructor"]() {}
isConstructor = isConstructor || t.isLiteral(node.key, { value: "constructor" });
if (isConstructor) {
throw this.errorWithNode(messages.get("classesIllegalConstructorKind"));
Property(node, parent, scope, file) {
if (node.kind === "set") {
var first = node.value.params[0];
if (t.isRestElement(first)) {
throw file.errorWithNode(first, messages.get("settersNoRest"));
}
}
}
Property.apply(this, arguments);
}
export function Property(node, parent, scope, file) {
if (node.kind === "set") {
if (node.value.params.length !== 1) {
throw file.errorWithNode(node.value, messages.get("settersInvalidParamLength"));
}
var first = node.value.params[0];
if (t.isRestElement(first)) {
throw file.errorWithNode(first, messages.get("settersNoRest"));
}
}
}
};

View File

@@ -1,71 +0,0 @@
import * as t from "../../../types";
export var metadata = {
optional: true,
group: "builtin-prepass",
experimental: true
};
export function AssignmentExpression() {
var left = this.get("left");
if (!left.isIdentifier()) return;
var binding = this.scope.getBinding(left.node.name);
if (!binding || binding.hasDeoptValue) return;
var evaluated = this.get("right").evaluate();
if (evaluated.confident) {
binding.setValue(evaluated.value);
} else {
binding.deoptValue();
}
}
export function IfStatement() {
var evaluated = this.get("test").evaluate();
if (!evaluated.confident) {
// todo: deopt binding values for constant violations inside
return this.skip();
}
if (evaluated.value) {
this.skipKey("alternate");
} else {
this.skipKey("consequent");
}
}
export var Scopable = {
enter() {
var funcScope = this.scope.getFunctionParent();
for (var name in this.scope.bindings) {
var binding = this.scope.bindings[name];
var deopt = false;
for (var path of (binding.constantViolations: Array)) {
var funcViolationScope = path.scope.getFunctionParent();
if (funcViolationScope !== funcScope) {
deopt = true;
break;
}
}
if (deopt) binding.deoptValue();
}
},
exit() {
for (var name in this.scope.bindings) {
var binding = this.scope.bindings[name];
binding.clearValue();
}
}
};
export var Expression = {
exit() {
var res = this.evaluate();
if (res.confident) return t.valueToNode(res.value);
}
};

View File

@@ -1,154 +0,0 @@
import * as t from "../../../types";
function toStatements(node) {
if (t.isBlockStatement(node)) {
var hasBlockScoped = false;
for (var i = 0; i < node.body.length; i++) {
var bodyNode = node.body[i];
if (t.isBlockScoped(bodyNode)) hasBlockScoped = true;
}
if (!hasBlockScoped) {
return node.body;
}
}
return node;
}
export var metadata = {
optional: true,
group: "builtin-pre",
experimental: true
};
export function ReferencedIdentifier(node, parent, scope) {
var binding = scope.getBinding(node.name);
if (!binding || binding.references > 1 || !binding.constant) return;
if (binding.kind === "param" || binding.kind === "module") return;
var replacement = binding.path.node;
if (t.isVariableDeclarator(replacement)) {
replacement = replacement.init;
}
if (!replacement) return;
// ensure it's a "pure" type
if (!scope.isPure(replacement, true)) return;
if (t.isClass(replacement) || t.isFunction(replacement)) {
// don't change this if it's in a different scope, this can be bad
// for performance since it may be inside a loop or deeply nested in
// hot code
if (binding.path.scope.parent !== scope) return;
}
if (this.findParent((path) => path.node === replacement)) {
return;
}
t.toExpression(replacement);
scope.removeBinding(node.name);
binding.path.dangerouslyRemove();
return replacement;
}
export function FunctionDeclaration(node, parent, scope) {
var bindingInfo = scope.getBinding(node.id.name);
if (bindingInfo && !bindingInfo.referenced) {
this.dangerouslyRemove();
}
}
export { FunctionDeclaration as ClassDeclaration };
export function VariableDeclarator(node, parent, scope) {
if (!t.isIdentifier(node.id) || !scope.isPure(node.init, true)) return;
FunctionDeclaration.apply(this, arguments);
}
export function ConditionalExpression(node, parent, scope) {
var evaluateTest = this.get("test").evaluateTruthy();
if (evaluateTest === true) {
return node.consequent;
} else if (evaluateTest === false) {
return node.alternate;
}
}
export function BlockStatement(node) {
var paths = this.get("body");
var purge = false;
for (var i = 0; i < paths.length; i++) {
let path = paths[i];
if (!purge && path.isCompletionStatement()) {
purge = true;
continue;
}
if (purge && !path.isFunctionDeclaration()) {
path.dangerouslyRemove();
}
}
}
export var IfStatement = {
exit(node) {
var consequent = node.consequent;
var alternate = node.alternate;
var test = node.test;
var evaluateTest = this.get("test").evaluateTruthy();
// we can check if a test will be truthy 100% and if so then we can inline
// the consequent and completely ignore the alternate
//
// if (true) { foo; } -> { foo; }
// if ("foo") { foo; } -> { foo; }
//
if (evaluateTest === true) {
return toStatements(consequent);
}
// we can check if a test will be falsy 100% and if so we can inline the
// alternate if there is one and completely remove the consequent
//
// if ("") { bar; } else { foo; } -> { foo; }
// if ("") { bar; } ->
//
if (evaluateTest === false) {
if (alternate) {
return toStatements(alternate);
} else {
return this.dangerouslyRemove();
}
}
// remove alternate blocks that are empty
//
// if (foo) { foo; } else {} -> if (foo) { foo; }
//
if (t.isBlockStatement(alternate) && !alternate.body.length) {
alternate = node.alternate = null;
}
// if the consequent block is empty turn alternate blocks into a consequent
// and flip the test
//
// if (foo) {} else { bar; } -> if (!foo) { bar; }
//
if (t.isBlockStatement(consequent) && !consequent.body.length && t.isBlockStatement(alternate) && alternate.body.length) {
node.consequent = node.alternate;
node.alternate = null;
node.test = t.unaryExpression("!", test, true);
}
}
};

View File

@@ -1,17 +0,0 @@
import * as t from "../../../types";
export var metadata = {
optional: true,
group: "builtin-trailing"
};
export var MemberExpression = {
exit(node) {
var prop = node.property;
if (node.computed && t.isLiteral(prop) && t.isValidIdentifier(prop.value)) {
// foo["bar"] => foo.bar
node.property = t.identifier(prop.value);
node.computed = false;
}
}
};

View File

@@ -1,17 +0,0 @@
import * as t from "../../../types";
export var metadata = {
optional: true,
group: "builtin-trailing"
};
export var Property = {
exit(node) {
var key = node.key;
if (t.isLiteral(key) && t.isValidIdentifier(key.value)) {
// "foo": "bar" -> foo: "bar"
node.key = t.identifier(key.value);
node.computed = false;
}
}
};

View File

@@ -1,10 +0,0 @@
export var metadata = {
optional: true,
group: "builtin-pre"
};
export function CallExpression(node, parent) {
if (this.get("callee").matchesPattern("console", true)) {
this.dangerouslyRemove();
}
}

View File

@@ -1,8 +0,0 @@
export var metadata = {
optional: true,
group: "builtin-pre"
};
export function DebuggerStatement(node) {
this.dangerouslyRemove();
}

View File

@@ -4,8 +4,10 @@ export var metadata = {
optional: true
};
export function ForOfStatement(node, parent, scope, file) {
if (this.get("right").isGenericType("Array")) {
return _ForOfStatementArray.call(this, node, scope, file);
export var visitor = {
ForOfStatement(node, parent, scope, file) {
if (this.get("right").isGenericType("Array")) {
return _ForOfStatementArray.call(this, node, scope, file);
}
}
}
};

View File

@@ -1,40 +0,0 @@
export var metadata = {
optional: true
};
var immutabilityVisitor = {
enter(node, parent, scope, state) {
var stop = () => {
state.isImmutable = false;
this.stop();
};
if (this.isJSXClosingElement()) {
this.skip();
return;
}
if (this.isJSXIdentifier({ name: "ref" }) && this.parentPath.isJSXAttribute({ name: node })) {
return stop();
}
if (this.isJSXIdentifier() || this.isIdentifier() || this.isJSXMemberExpression()) {
return;
}
if (!this.isImmutable()) stop();
}
};
export function JSXElement(node, parent, scope, file) {
if (node._hoisted) return;
var state = { isImmutable: true };
this.traverse(immutabilityVisitor, state);
if (state.isImmutable) {
this.hoist();
} else {
node._hoisted = true;
}
}

View File

@@ -18,57 +18,59 @@ function isJSXAttributeOfName(attr, name) {
return t.isJSXAttribute(attr) && t.isJSXIdentifier(attr.name, { name: name });
}
export function JSXElement(node, parent, scope, file) {
// filter
var open = node.openingElement;
if (hasRefOrSpread(open.attributes)) return;
export var visitor = {
JSXElement(node, parent, scope, file) {
// filter
var open = node.openingElement;
if (hasRefOrSpread(open.attributes)) return;
// init
var isComponent = true;
var props = t.objectExpression([]);
var obj = t.objectExpression([]);
var key = t.literal(null);
var type = open.name;
// init
var isComponent = true;
var props = t.objectExpression([]);
var obj = t.objectExpression([]);
var key = t.literal(null);
var type = open.name;
if (t.isJSXIdentifier(type) && react.isCompatTag(type.name)) {
type = t.literal(type.name);
isComponent = false;
}
function pushElemProp(key, value) {
pushProp(obj.properties, t.identifier(key), value);
}
function pushProp(objProps, key, value) {
objProps.push(t.property("init", key, value));
}
// metadata
pushElemProp("type", type);
pushElemProp("ref", t.literal(null));
if (node.children.length) {
pushProp(props.properties, t.identifier("children"), t.arrayExpression(react.buildChildren(node)));
}
// props
for (var i = 0; i < open.attributes.length; i++) {
var attr = open.attributes[i];
if (isJSXAttributeOfName(attr, "key")) {
key = attr.value;
} else {
pushProp(props.properties, attr.name, attr.value || t.identifier("true"));
if (t.isJSXIdentifier(type) && react.isCompatTag(type.name)) {
type = t.literal(type.name);
isComponent = false;
}
function pushElemProp(key, value) {
pushProp(obj.properties, t.identifier(key), value);
}
function pushProp(objProps, key, value) {
objProps.push(t.property("init", key, value));
}
// metadata
pushElemProp("type", type);
pushElemProp("ref", t.literal(null));
if (node.children.length) {
pushProp(props.properties, t.identifier("children"), t.arrayExpression(react.buildChildren(node)));
}
// props
for (var i = 0; i < open.attributes.length; i++) {
var attr = open.attributes[i];
if (isJSXAttributeOfName(attr, "key")) {
key = attr.value;
} else {
pushProp(props.properties, attr.name, attr.value || t.identifier("true"));
}
}
if (isComponent) {
props = t.callExpression(file.addHelper("default-props"), [t.memberExpression(type, t.identifier("defaultProps")), props]);
}
pushElemProp("props", props);
// key
pushElemProp("key", key);
return obj;
}
if (isComponent) {
props = t.callExpression(file.addHelper("default-props"), [t.memberExpression(type, t.identifier("defaultProps")), props]);
}
pushElemProp("props", props);
// key
pushElemProp("key", key);
return obj;
}
};

View File

@@ -7,8 +7,10 @@ export var metadata = {
dependencies: ["es7.asyncFunctions", "es6.classes"]
};
export function Func/*tion*/(node, parent, scope, file) {
if (!node.async || node.generator) return;
export var visitor = {
Function(node, parent, scope, file) {
if (!node.async || node.generator) return;
return remapAsyncToGenerator(this, file.addHelper("async-to-generator"));
}
return remapAsyncToGenerator(this, file.addHelper("async-to-generator"));
}
};

View File

@@ -10,11 +10,13 @@ export var metadata = {
dependencies: ["es7.asyncFunctions", "es6.classes"]
};
export function Func/*tion*/(node, parent, scope, file) {
if (!node.async || node.generator) return;
export var visitor = {
Function(node, parent, scope, file) {
if (!node.async || node.generator) return;
return remapAsyncToGenerator(
this,
t.memberExpression(file.addImport("bluebird", null, "absolute"), t.identifier("coroutine"))
);
}
return remapAsyncToGenerator(
this,
t.memberExpression(file.addImport("bluebird", null, "absolute"), t.identifier("coroutine"))
);
}
};

View File

@@ -1,21 +0,0 @@
import traverse from "../../../traversal";
import parse from "../../../helpers/parse";
export var metadata = {
group: "builtin-pre",
optional: true
};
export function CallExpression(node) {
if (this.get("callee").isIdentifier({ name: "eval" }) && node.arguments.length === 1) {
var evaluate = this.get("arguments")[0].evaluate();
if (!evaluate.confident) return;
var code = evaluate.value;
if (typeof code !== "string") return;
var ast = parse(code);
traverse.removeProperties(ast);
return ast.program;
}
}

View File

@@ -4,37 +4,39 @@ export var metadata = {
group: "builtin-trailing"
};
export function Flow(node) {
this.dangerouslyRemove();
}
export var visitor = {
Flow() {
this.dangerouslyRemove();
},
export function ClassProperty(node) {
node.typeAnnotation = null;
if (!node.value) this.dangerouslyRemove();
}
ClassProperty(node) {
node.typeAnnotation = null;
if (!node.value) this.dangerouslyRemove();
},
export function Class(node) {
node.implements = null;
}
Class(node) {
node.implements = null;
},
export function Func/*tion*/(node) {
for (var i = 0; i < node.params.length; i++) {
var param = node.params[i];
param.optional = false;
Function(node) {
for (var i = 0; i < node.params.length; i++) {
var param = node.params[i];
param.optional = false;
}
},
TypeCastExpression(node) {
do {
node = node.expression;
} while(t.isTypeCastExpression(node));
return node;
},
ImportDeclaration(node) {
if (node.isType) this.dangerouslyRemove();
},
ExportDeclaration() {
if (this.get("declaration").isTypeAlias()) this.dangerouslyRemove();
}
}
export function TypeCastExpression(node) {
do {
node = node.expression;
} while(t.isTypeCastExpression(node));
return node;
}
export function ImportDeclaration(node) {
if (node.isType) this.dangerouslyRemove();
}
export function ExportDeclaration(node) {
if (this.get("declaration").isTypeAlias()) this.dangerouslyRemove();
}
};

View File

@@ -1,21 +0,0 @@
import * as t from "../../../types";
export var metadata = {
group: "builtin-trailing",
optional: true
};
export var FunctionExpression = {
exit(node) {
if (!node.id) return;
node._ignoreUserWhitespace = true;
return t.callExpression(
t.functionExpression(null, [], t.blockStatement([
t.toStatement(node),
t.returnStatement(node.id)
])),
[]
);
}
};

View File

@@ -10,7 +10,7 @@ export var metadata = {
group: "builtin-advanced"
};
require("../../helpers/build-react-transformer")(exports, {
export var visitor = require("../../helpers/build-react-transformer")({
pre(state) {
state.callee = state.tagExpr;
},

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