Compare commits

..

73 Commits

Author SHA1 Message Date
Sebastian McKenzie
8111ab28d7 v5.6.16 2015-07-09 16:13:06 +01:00
Sebastian McKenzie
ed25845152 remove accidental stackTraceLimit assignment 2015-07-09 16:12:06 +01:00
Sebastian McKenzie
457638e904 add type comments to t.valueToNode 2015-07-09 16:11:57 +01:00
Sebastian McKenzie
2e5255dbf5 peg recast version - fixes #1958 2015-07-09 16:11:46 +01:00
Sebastian McKenzie
205fab2ed8 split up badges 2015-07-08 14:58:31 +01:00
Sebastian McKenzie
d01b26951b channel -> community 2015-07-08 14:45:56 +01:00
Sebastian McKenzie
fc15c91b2a replace descriptor.writable assignment in createDecoraredObject helper - fixes #1949 2015-07-08 14:45:50 +01:00
Sebastian McKenzie
421b01865f add Generated/User/Directive virtual node types 2015-07-08 11:35:56 +01:00
Sebastian McKenzie
af7510adec fix some bugs in PathHoister - fixes babel-plugins/babel-plugin-react-constant-elements#1
- Don't hoist constant elements to the same function as their original paths function parent.
 - Push each violation paths ancestry to the breakOnScopePaths collection to avoid constant hoisting to nested paths.
2015-07-08 11:35:34 +01:00
Sebastian McKenzie
ec7c40fbf6 add quiet option to CLI - fixes #1931 2015-07-07 11:26:45 +01:00
Sebastian McKenzie
4a36a9fb31 check for functions in util.shouldIgnore - closes #1865, closes #1859 2015-07-07 11:23:31 +01:00
Sebastian McKenzie
4d25b0d96a Merge branch 'master' of github.com:babel/babel 2015-07-07 11:12:42 +01:00
Sebastian McKenzie
babc9c90b4 fix tail call recursion on functions with less arguments than parameters - fixes #1938 2015-07-07 11:11:58 +01:00
Sebastian McKenzie
288293ca11 Merge pull request #1936 from loganfsmyth/system-module-hoisting
Only special-case for..on declaration hoisting - fixes #1929
2015-07-07 10:54:26 +01:00
Sebastian McKenzie
a262e99abd strip flow directives in flow transformer - fixes #1934 2015-07-07 10:52:43 +01:00
Logan Smyth
b518394a3f Only special-case for..on/of declaration hoisting - fixes #1929 2015-07-06 21:06:11 -07:00
Sebastian McKenzie
337c51df5c fixes out of bounds check to default parameter template - #1845 - cc @RReverser 2015-07-06 21:25:33 +01:00
Sebastian McKenzie
0509fb148f add out of bounds check to default parameter template - addresses #1845 - cc @RReverser 2015-07-06 20:12:10 +01:00
Sebastian McKenzie
bb5f1120b7 Merge branch 'master' of github.com:babel/babel 2015-07-05 21:41:58 +01:00
Sebastian McKenzie
38d46012a7 Merge pull request #1926 from loganfsmyth/systemjs-modules-export
Optimize export-from in System.register - fixes #1722
2015-07-05 21:39:30 +01:00
Logan Smyth
cdb8e3aefa Optimize export-from in System.register - fixes #1722 2015-07-05 11:40:33 -07:00
Sebastian McKenzie
4a84cd785a Merge pull request #1915 from loganfsmyth/destructuring-default-hoisting
Ensure _blockHoist is set on function destructuring defaults
2015-07-05 19:24:01 +01:00
Logan Smyth
f47d17345c Ensure _blockHoist is set on function destructuring defaults - fixes #1908 2015-07-05 09:10:09 -07:00
Sebastian McKenzie
8746ca8d31 add Statement virtual type 2015-07-05 01:23:37 +02:00
Sebastian McKenzie
76e954bc36 add reference to issue #1920 2015-07-05 01:23:32 +02:00
Sebastian McKenzie
64903d0dcf Merge branch 'master' of github.com:babel/babel 2015-07-04 23:33:33 +02:00
Sebastian McKenzie
1fd0b1f741 delay this assignment when referencing this inside an arrow function pre-bare super in derived class constructors - fixes #1920 2015-07-04 23:32:11 +02:00
Sebastian McKenzie
cda2bfce38 enable do expression tests 2015-07-04 21:51:57 +02:00
Sebastian McKenzie
0e4bb5ee3f clean up verifyConstructor classes visitor and disallow super.* before super() in derived class constructors - fixes #1921 2015-07-04 21:38:22 +02:00
Sebastian McKenzie
e9793b1f16 Merge pull request #1916 from conradz/inline-single-child
Handle single child when using React inlining
2015-07-04 11:23:15 +02:00
Conrad Zimmerman
224db29c05 Handle single child when using React inlining
Changes optimisation.react.inlineElements to handle a single child as the
value of the `children` property instead of wrapping it with an array.
This matches the behavior of `React.createElement`.
2015-07-03 18:55:38 -04:00
Sebastian McKenzie
bd1bd38556 add undeclared type variable 2015-07-03 00:14:40 +02:00
Sebastian McKenzie
1f39114126 Merge branch 'master' into development 2015-07-03 00:07:53 +02:00
Sebastian McKenzie
4c0b8599f1 add optional context parameter to NodePath#get 2015-07-03 00:07:37 +02:00
Sebastian McKenzie
848909620c add more comments to path methods 2015-07-03 00:07:23 +02:00
Sebastian McKenzie
c40215497d Merge pull request #1900 from samccone/sjs/opt2
rework findCommonStringDelimiter
2015-07-02 23:54:52 +02:00
Sebastian McKenzie
6450f5263e Merge pull request #1901 from loganfsmyth/constructor-scope-fix
Properly regenerate scope for replaced nodes - fixes #1773
2015-07-02 23:54:28 +02:00
Sam Saccone
74c59c94ce 2015-07-02 16:57:12 -04:00
Logan Smyth
3f38a83600 Properly regenerate scope for replaced nodes - fixes #1773 2015-07-01 22:06:05 -07:00
Sam Saccone
1945f849c3 Move into for block
https://www.youtube.com/watch?v=FHDwRECFL8M
2015-07-01 20:36:24 -07:00
Sam Saccone
5b0b7ba226 🍴 Switch to ternary for return
https://www.youtube.com/watch?v=XAbY2cmEsS0
2015-07-01 20:36:17 -07:00
James Kyle
42de6bc716 Merge pull request #1894 from samccone/patch-4
🐳
2015-07-02 01:06:50 +01:00
James Kyle
fb66f347b9 Merge pull request #1895 from samccone/patch-5
remove 💀 comment lines
2015-07-02 01:05:51 +01:00
Brian Donovan
5e28bd4e68 Merge pull request #1893 from samccone/patch-1
🍕 Fix grammatical issue
2015-07-01 16:16:20 -07:00
Sam Saccone
9869566963 remove 💀 comment lines
Added in 
3561efdb86

if this is a style thing you want to keep around then my all means close away.
2015-07-01 15:59:05 -07:00
Sam Saccone
4a27b10e8a 👶 2015-07-01 15:56:11 -07:00
Sam Saccone
c3b5ed5b3d 💄 Fix grammatical issue 2015-07-01 15:51:56 -07:00
Sebastian McKenzie
afa4871a08 Merge pull request #1892 from samccone/patch-1
📝 better english
2015-07-02 00:48:57 +02:00
Sam Saccone
70c739250b 📝 better english 2015-07-01 15:48:00 -07:00
Sebastian McKenzie
722e706a8c Merge pull request #1891 from samccone/patch-1
️  this that this
2015-07-02 00:42:05 +02:00
Sam Saccone
f3973c8397 📝 clarify how it inherits this 2015-07-01 15:41:15 -07:00
Sebastian McKenzie
47c3792d34 Merge pull request #1890 from samccone/patch-1
️  Add link to ESTree
2015-07-02 00:39:23 +02:00
Sam Saccone
456accb4b3 📝 Add link to ESTree 2015-07-01 15:37:20 -07:00
Sebastian McKenzie
72771ed439 update escape regex test to use new lodash result 2015-06-30 23:56:47 +01:00
Sebastian McKenzie
7cb7ea4248 Merge pull request #1884 from arthurvr/resolve
Add `resolve` to `CONTRIBUTING.md`
2015-06-30 23:39:33 +01:00
Arthur Verschaeve
301df15921 Add resolve to CONTRIBUTING.md
Introduced in aaf4cbf06f
2015-06-30 23:56:30 +02:00
Sebastian McKenzie
15535406bd Merge pull request #1883 from arthurvr/patch-1
Remove `user-home` from `CONTRIBUTING.md`
2015-06-30 22:43:42 +01:00
Arthur Verschaeve
63f53e3773 Remove user-home from CONTRIBUTING.md
In favor of `user-or-tmp`

Ref 90b8826e73
2015-06-30 23:40:24 +02:00
Brian Donovan
03a979a6bd Merge pull request #1867 from arthurvr/deps
Add `path-exists` to `CONTRIBUTING.md`
2015-06-30 14:31:24 -07:00
Sebastian McKenzie
910622e66e fix linting errors 2015-06-30 15:17:26 +01:00
Sebastian McKenzie
c5a8702021 clean up derived classes, fixes super path referencing user constructor instead of our new function - #1877 2015-06-30 14:55:11 +01:00
Sebastian McKenzie
336c65fe2c restructure classes transformer, fix class name inference - #1877 2015-06-30 14:49:04 +01:00
Sebastian McKenzie
092d98fb27 add constructor to body in order that it was supplied in - fixes #1877 2015-06-30 10:10:52 +01:00
Sebastian McKenzie
e55ce575cd move up template literal simplification logic - fixes #1874 2015-06-29 23:36:06 +01:00
Sebastian McKenzie
d63ae5fce8 remove loose console.log 2015-06-29 22:59:23 +01:00
Sebastian McKenzie
541309c4bb fix collisions for getBindingIdentifiers 2015-06-29 22:04:17 +01:00
Sebastian McKenzie
2d289150d1 Merge pull request #1868 from benjamn/patch-2
Upgrade Regenerator to 0.8.32.
2015-06-29 20:47:05 +01:00
Ben Newman
b9f6169ed4 Upgrade Regenerator to 0.8.32.
This includes some major runtime performance improvements:
https://github.com/facebook/regenerator/pull/207
https://github.com/facebook/regenerator/pull/208

And also some bug fixes relating to async generator functions:
https://github.com/facebook/regenerator/commit/29d81b6929
https://github.com/facebook/regenerator/commit/7d2a052ddb
https://github.com/facebook/regenerator/commit/5b9dd1086d
2015-06-29 10:43:54 -04:00
Arthur Verschaeve
ce372281cd Add path-exists to CONTRIBUTING.md 2015-06-29 12:35:37 +02:00
Sebastian McKenzie
0044100e3d perform function name inference on functions in properties before they're properly visited - fixes #1860 2015-06-29 00:20:47 +01:00
Sebastian McKenzie
81edc4c6ab add make comment-issues skeleton 2015-06-28 00:59:24 +01:00
Sebastian McKenzie
3b1a9a0adb trim eval code in babel-node 2015-06-28 00:59:12 +01:00
Sebastian McKenzie
8ab90aacd3 add babel-core version to babel-cli version - closes #1861 2015-06-28 00:59:05 +01:00
108 changed files with 926 additions and 426 deletions

View File

@@ -30,4 +30,5 @@ deploy:
after_deploy:
- make publish-cli
- make publish-runtime
- make rebuild-website
- make build-website
- make comment-issues

View File

@@ -143,8 +143,11 @@ your [`$PATH`](http://unix.stackexchange.com/questions/26047/how-to-correctly-ad
+ [trim-right](http://ghub.io/trim-right) Trims the rightside whitespace.
+ [user-home](http://ghub.io/user-home) Gets the users home directory. This is used to resolve the babel-node/babel/register cache.
+ [path-exists](https://www.npmjs.com/package/path-exists) Checks if a path exists. (replaces the deprecated `fs.exists` methods)
+ [home-or-tmp](https://github.com/sindresorhus/home-or-tmp) Gets the user home directory with fallback to the system temporary directory. This is used to resolve the babel-node/babel/register cache.
+ [resolve](https://www.npmjs.com/package/resolve) Implements the [`require.resolve()` algorithm](http://nodejs.org/docs/v0.12.0/api/all.html#all_require_resolve) such that we can `require.resolve()` on behalf of a file asynchronously and synchronously.
#### Code Standards

View File

@@ -108,6 +108,9 @@ publish-cli:
build-website:
@./tools/build-website.sh
comment-issues:
@./tools/comment-issues.sh
bootstrap:
npm list --global --depth 1 babel >/dev/null 2>&1 && npm uninstall -g babel || true
npm install

View File

@@ -10,16 +10,19 @@
<p align="center">
<a href="https://travis-ci.org/babel/babel"><img alt="Build Status" src="https://img.shields.io/travis/babel/babel.svg?style=flat"></a>
<a href="http://issuestats.com/github/babel/babel"><img alt="Issue Stats" src="http://issuestats.com/github/babel/babel/badge/pr?style=flat"></a>
<a href="http://issuestats.com/github/babel/babel"><img alt="Issue Stats" src="http://issuestats.com/github/babel/babel/badge/issue?style=flat"></a>
<a href="http://badge.fury.io/js/babel-core"><img alt="npm version" src="https://badge.fury.io/js/babel-core.svg"></a>
<a href="https://npmjs.org/package/babel-core"><img alt="Downloads" src="http://img.shields.io/npm/dm/babel-core.svg"></a>
</p>
<p align="center">
<a href="http://issuestats.com/github/babel/babel"><img alt="Issue Stats" src="http://issuestats.com/github/babel/babel/badge/pr?style=flat"></a>
<a href="http://issuestats.com/github/babel/babel"><img alt="Issue Stats" src="http://issuestats.com/github/babel/babel/badge/issue?style=flat"></a>
</p>
----
<p align="center">
For questions and support please visit the <a href="https://babel-slack.herokuapp.com">slack channel</a> or <a href="http://stackoverflow.com/questions/tagged/babeljs">StackOverflow</a>. The Babel issue tracker is <strong>exclusively</strong> for bug reports and feature requests.
For questions and support please visit the <a href="https://babel-slack.herokuapp.com">Slack community</a> or <a href="http://stackoverflow.com/questions/tagged/babeljs">StackOverflow</a>. The Babel issue tracker is <strong>exclusively</strong> for bug reports and feature requests.
</p>
<p align="center">

View File

@@ -1,5 +1,5 @@
# Properties of nodes
These are properties babel stores in AST node objects for internal use, as opposed to properties that are part of the AST spec (ESTree at the time of this writing).
These are properties babel stores in AST node objects for internal use, as opposed to properties that are part of the AST spec ([ESTree](https://github.com/estree/estree) at the time of this writing).
## `_blockHoist`
`node._blockHoist != null` triggers the [block-hoist transformer](/src/babel/transformation/transformers/internal/block-hoist.js). Value should be `true` or an integer in the range `0..3`. `true` is equivalent to `2`. The value indicates whether the node should be hoisted and to what degree. See the source code for more detailed information.
@@ -8,4 +8,4 @@ These are properties babel stores in AST node objects for internal use, as oppos
Stores a representation of a node's position in the tree and relationship to other nodes.
## `shadow`
A truthy value on a function node triggers the [shadow-functions transformer](/src/babel/transformation/transformers/internal/shadow-functions.js), which transforms the node so that it references (or inherits) `arguments` and `this` from the parent scope. It is invoked for arrow functions, for example.
A truthy value on a function node triggers the [shadow-functions transformer](/src/babel/transformation/transformers/internal/shadow-functions.js), which transforms the node so that it references (or inherits) `arguments` and the `this` context from the parent scope. It is invoked for arrow functions, for example.

View File

@@ -1,7 +1,7 @@
{
"name": "babel-core",
"description": "A compiler for writing next generation JavaScript",
"version": "5.6.15",
"version": "5.6.16",
"author": "Sebastian McKenzie <sebmck@gmail.com>",
"homepage": "https://babeljs.io/",
"license": "MIT",
@@ -63,7 +63,8 @@
"path-exists": "^1.0.0",
"path-is-absolute": "^1.0.0",
"private": "^0.1.6",
"regenerator": "0.8.31",
"recast": "0.10.16",
"regenerator": "0.8.32",
"regexpu": "^1.1.2",
"repeating": "^1.1.2",
"resolve": "^1.1.6",

View File

@@ -41,6 +41,7 @@ babel.register({
//
var _eval = function (code, filename) {
code = code.trim();
if (!code) return undefined;
code = babel.transform(code, {

View File

@@ -28,7 +28,7 @@ module.exports = function (commander, filenames) {
outputFileSync(dest, data.code);
console.log(src + " -> " + dest);
util.log(src + " -> " + dest);
};
var handleFile = function (src, filename) {

View File

@@ -135,7 +135,7 @@ module.exports = function (commander, filenames, opts) {
ignoreInitial: true
}).on("all", function (type, filename) {
if (type === "add" || type === "change") {
console.log(type, filename);
util.log(type + " " + filename);
try {
walk();
} catch (err) {

View File

@@ -45,6 +45,7 @@ commander.option("-w, --watch", "Recompile files on changes");
commander.option("-o, --out-file [out]", "Compile all input files into a single file");
commander.option("-d, --out-dir [out]", "Compile an input directory of modules into an output directory");
commander.option("-D, --copy-files", "When compiling a directory copy over non-compilable files");
commander.option("-q, --quiet", "Don't log anything");
commander.on("--help", function () {
var outKeys = function (title, obj) {
@@ -67,7 +68,7 @@ commander.on("--help", function () {
});
var pkg = require("../../package.json");
commander.version(pkg.version);
commander.version(pkg.version + " (babel-core " + require("babel-core").version + ")");
commander.usage("[options] <files ...>");
commander.parse(process.argv);

View File

@@ -25,6 +25,10 @@ exports.addSourceMappingUrl = function (code, loc) {
return code + "\n//# sourceMappingURL=" + path.basename(loc);
};
exports.log = function (msg) {
if (!commander.quiet) console.log(msg);
};
exports.transform = function (filename, code, opts) {
opts = _.defaults(opts || {}, index.opts);
opts.filename = filename;

View File

@@ -73,7 +73,6 @@ each(File.helpers, function (helperName) {
writeFile("regenerator/index.js", readFile("regenerator/runtime-module", true));
writeFile("regenerator/runtime.js", selfContainify(readFile("regenerator/runtime")));
//
var coreDefinitions = require("babel-plugin-runtime/lib/definitions");
@@ -93,6 +92,5 @@ each(paths, function (path) {
writeFile("core-js/" + path + ".js", defaultify('require("core-js/library/fn/' + path + '")'));
});
//
updatePackage();

View File

@@ -1,4 +1,3 @@
Error.stackTraceLimit = Infinity;
var acorn = require("../src/index")
var pp = acorn.Parser.prototype

View File

@@ -57,34 +57,16 @@ class CodeGenerator {
return format;
}
static findCommonStringDelimiter(code, tokens) {
var occurences = {
single: 0,
double: 0
};
var checked = 0;
for (var i = 0; i < tokens.length; i++) {
var token = tokens[i];
if (token.type.label !== "string") continue;
var raw = code.slice(token.start, token.end);
if (raw[0] === "'") {
occurences.single++;
} else {
occurences.double++;
}
checked++;
if (checked >= 3) break;
static findCommonStringDelimiter(code, tokens, occurences = {"'": 0, "\"": 0}) {
if (tokens.length === 0 || occurences["'"] + occurences["\""] >= 3) {
return occurences["'"] > occurences["\""] ? "single" : "double";
}
if (occurences.single > occurences.double) {
return "single";
} else {
return "double";
if (tokens[0].type.label === "string") {
occurences[code[tokens[0].start]]++;
}
return this.findCommonStringDelimiter(code, tokens.slice(1), occurences);
}
static generators = {

View File

@@ -1,7 +1,7 @@
import * as util from "util";
export const MESSAGES = {
tailCallReassignmentDeopt: "Function reference has been reassigned so it's probably be dereferenced so we can't optimise this with confidence",
tailCallReassignmentDeopt: "Function reference has been reassigned, so it will probably be dereferenced, therefore we can't optimise this with confidence",
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",
@@ -17,7 +17,7 @@ export const MESSAGES = {
missingTemplatesDirectory: "no templates directory - this is most likely the result of a broken `npm publish`. Please report to https://github.com/babel/babel/issues",
unsupportedOutputType: "Unsupported output type $1",
illegalMethodName: "Illegal method name $1",
lostTrackNodePath: "We lost track of this nodes position, likely because the AST was directly manipulated",
lostTrackNodePath: "We lost track of this node's position, likely because the AST was directly manipulated",
modulesIllegalExportName: "Illegal export $1",
modulesDuplicateDeclarations: "Duplicate module declarations with the same source but in different scopes",
@@ -26,7 +26,7 @@ export const MESSAGES = {
undeclaredVariableType: "Referencing a type alias outside of a type annotation",
undeclaredVariableSuggestion: "Reference to undeclared variable $1 - did you mean $2?",
traverseNeedsParent: "Must pass a scope and parentPath unless traversing a Program/File got a $1 node",
traverseNeedsParent: "You must pass a scope and parentPath unless traversing a Program/File got a $1 node",
traverseVerifyRootFunction: "You passed `traverse()` a function when it expected a visitor object, are you sure you didn't mean `{ enter: Function }`?",
traverseVerifyVisitorProperty: "You passed `traverse()` a visitor object with the property $1 that has the invalid property $2",
traverseVerifyNodeType: "You gave us a visitor for the node type $1 but it's not a valid type",
@@ -37,7 +37,7 @@ export const MESSAGES = {
pluginNotTransformer: "The plugin $1 didn't export a Plugin instance",
pluginUnknown: "Unknown plugin $1",
pluginNotFile: "Plugin $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 than what is performing the transformation."
};
export function get(key: String, ...args) {

View File

@@ -33,8 +33,7 @@ var hoistVariablesVisitor = {
}
// for (var i in test)
// for (var i = 0;;)
if (t.isFor(parent) && (parent.left === node || parent.init === node)) {
if (t.isFor(parent) && parent.left === node) {
return node.declarations[0].id;
}
@@ -78,6 +77,7 @@ export default class SystemFormatter extends AMDFormatter {
constructor(file) {
super(file);
this._setters = null;
this.exportIdentifier = file.scope.generateUidIdentifier("export");
this.noInteropRequireExport = true;
this.noInteropRequireImport = true;
@@ -178,11 +178,14 @@ export default class SystemFormatter extends AMDFormatter {
var block = t.blockStatement(program.body);
var setterListNode = this._buildRunnerSetters(block, hoistDeclarators);
this._setters = setterListNode;
var runner = util.template("system", {
MODULE_DEPENDENCIES: t.arrayExpression(this.buildDependencyLiterals()),
EXPORT_IDENTIFIER: this.exportIdentifier,
MODULE_NAME: moduleNameLiteral,
SETTERS: this._buildRunnerSetters(block, hoistDeclarators),
SETTERS: setterListNode,
EXECUTE: t.functionExpression(null, [], block)
}, true);

View File

@@ -1 +1 @@
let VARIABLE_NAME = ARGUMENTS[ARGUMENT_KEY] === undefined ? DEFAULT_VALUE : ARGUMENTS[ARGUMENT_KEY];
let VARIABLE_NAME = ARGUMENTS.length <= ARGUMENT_KEY || ARGUMENTS[ARGUMENT_KEY] === undefined ? DEFAULT_VALUE : ARGUMENTS[ARGUMENT_KEY];

View File

@@ -13,7 +13,7 @@
descriptor.enumerable = true;
descriptor.configurable = true;
descriptor.writable = true;
if ("value" in descriptor || descriptor.initializer) descriptor.writable = true;
if (decorators) {
for (var f = 0; f < decorators.length; f++) {

View File

@@ -0,0 +1,23 @@
import LooseTransformer from "./loose";
import VanillaTransformer from "./vanilla";
import * as t from "../../../../types";
import { bare } from "../../../helpers/name-method";
export var visitor = {
ClassDeclaration(node) {
return t.variableDeclaration("let", [
t.variableDeclarator(node.id, t.toExpression(node))
]);
},
ClassExpression(node, parent, scope, file) {
var inferred = bare(node, parent, scope);
if (inferred) return inferred;
if (file.isLoose("es6.classes")) {
return new LooseTransformer(this, file).run();
} else {
return new VanillaTransformer(this, file).run();
}
}
};

View File

@@ -0,0 +1,24 @@
import VanillaTransformer from "./vanilla";
import * as t from "../../../../types";
export default class LooseClassTransformer extends VanillaTransformer {
constructor() {
super(...arguments);
this.isLoose = true;
}
_processMethod(node) {
if (!node.decorators) {
// use assignments instead of define properties for loose classes
var classRef = this.classRef;
if (!node.static) classRef = t.memberExpression(classRef, t.identifier("prototype"));
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);
this.body.push(expr);
return true;
}
}
}

View File

@@ -1,27 +1,15 @@
import type NodePath from "../../../traversal/path";
import type File from "../../file";
import memoiseDecorators from "../../helpers/memoise-decorators";
import ReplaceSupers from "../../helpers/replace-supers";
import * as nameMethod from "../../helpers/name-method";
import * as defineMap from "../../helpers/define-map";
import * as messages from "../../../messages";
import * as util from "../../../util";
import * as t from "../../../types";
import type NodePath from "../../../../traversal/path";
import type File from "../../../file";
import memoiseDecorators from "../../../helpers/memoise-decorators";
import ReplaceSupers from "../../../helpers/replace-supers";
import * as nameMethod from "../../../helpers/name-method";
import * as defineMap from "../../../helpers/define-map";
import * as messages from "../../../../messages";
import * as util from "../../../../util";
import * as t from "../../../../types";
const PROPERTY_COLLISION_METHOD_NAME = "__initializeProperties";
export var visitor = {
ClassDeclaration(node) {
return t.variableDeclaration("let", [
t.variableDeclarator(node.id, t.toExpression(node))
]);
},
ClassExpression(node, parent, scope, file) {
return new ClassTransformer(this, file).run();
}
};
var collectPropertyReferencesVisitor = {
Identifier: {
enter(node, parent, scope, state) {
@@ -37,16 +25,12 @@ var collectPropertyReferencesVisitor = {
};
var verifyConstructorVisitor = {
MethodDefinition: {
enter() {
this.skip();
}
MethodDefinition() {
this.skip();
},
Property: {
enter(node) {
if (node.method) this.skip();
}
Property(node) {
if (node.method) this.skip();
},
CallExpression: {
@@ -55,35 +39,45 @@ var verifyConstructorVisitor = {
state.hasBareSuper = true;
state.bareSuper = this;
if (!state.hasSuper) {
if (!state.isDerived) {
throw this.errorWithNode("super call is only allowed in derived constructor");
}
}
}
},
FunctionDeclaration: {
enter() {
this.skip();
}
"FunctionDeclaration|FunctionExpression"() {
this.skip();
},
FunctionExpression: {
enter() {
this.skip();
}
},
ThisExpression(node, parent, scope, state) {
if (state.isDerived && !state.hasBareSuper) {
if (this.inShadow()) {
// https://github.com/babel/babel/issues/1920
var thisAlias = state.constructorPath.getData("this");
ThisExpression: {
enter(node, parent, scope, state) {
if (state.hasSuper && !state.hasBareSuper) {
if (!thisAlias) {
thisAlias = state.constructorPath.setData(
"this",
state.constructorPath.scope.generateUidIdentifier("this")
);
}
return thisAlias;
} else {
throw this.errorWithNode("'this' is not allowed before super()");
}
}
},
Super(node, parent, scope, state) {
if (state.isDerived && !state.hasBareSuper && !this.parentPath.isCallExpression({ callee: node })) {
throw this.errorWithNode("'super.*' is not allowed before super()");
}
}
};
class ClassTransformer {
export default class ClassTransformer {
/**
* Description
@@ -96,26 +90,29 @@ class ClassTransformer {
this.path = path;
this.file = file;
this.hasInstanceDescriptors = false;
this.hasStaticDescriptors = false;
this.instanceMutatorMap = {};
this.staticMutatorMap = {};
this.clearDescriptors();
this.instancePropBody = [];
this.instancePropRefs = {};
this.staticPropBody = [];
this.body = [];
this.hasConstructor = false;
this.hasDecorators = false;
this.className = this.node.id;
this.classRef = this.node.id || this.scope.generateUidIdentifier("class");
this.pushedConstructor = false;
this.pushedInherits = false;
this.hasDecorators = false;
this.isLoose = false;
// class id
this.classId = this.node.id;
// this is the name of the binding that will **always** reference the class we've constructed
this.classRef = this.node.id || this.scope.generateUidIdentifier("class");
// this is a direct reference to the class we're building, class decorators can shadow the classRef
this.directRef = null;
this.superName = this.node.superClass || t.identifier("Function");
this.hasSuper = !!this.node.superClass;
this.isLoose = file.isLoose("es6.classes");
this.isDerived = !!this.node.superClass;
}
/**
@@ -126,7 +123,6 @@ class ClassTransformer {
run() {
var superName = this.superName;
var classRef = this.classRef;
var file = this.file;
//
@@ -136,16 +132,7 @@ class ClassTransformer {
//
var constructorBody = this.constructorBody = t.blockStatement([]);
var constructor;
if (this.className) {
constructor = t.functionDeclaration(this.className, [], constructorBody);
body.push(constructor);
} else {
constructor = t.functionExpression(null, [], constructorBody);
}
this.constructor = constructor;
this.constructor = this.buildConstructor();
//
@@ -153,26 +140,22 @@ class ClassTransformer {
var closureArgs = [];
//
if (this.hasSuper) {
if (this.isDerived) {
closureArgs.push(superName);
superName = this.scope.generateUidIdentifierBasedOnNode(superName);
closureParams.push(superName);
this.superName = superName;
body.push(t.expressionStatement(t.callExpression(file.addHelper("inherits"), [classRef, superName])));
}
//
var decorators = this.node.decorators;
if (decorators) {
// create a class reference to use later on
this.classRef = this.scope.generateUidIdentifier(classRef);
// this is so super calls and the decorators have access to the raw function
body.push(t.variableDeclaration("var", [
t.variableDeclarator(this.classRef, classRef)
]));
this.directRef = this.scope.generateUidIdentifier(this.classRef);
} else {
this.directRef = this.classRef;
}
//
@@ -181,46 +164,21 @@ class ClassTransformer {
// make sure this class isn't directly called
constructorBody.body.unshift(t.expressionStatement(t.callExpression(file.addHelper("class-call-check"), [
t.thisExpression(),
this.classRef
this.directRef
])));
//
if (decorators) {
// reverse the decorators so we execute them in the right order
decorators = decorators.reverse();
for (var i = 0; i < decorators.length; i++) {
var decorator = decorators[i];
var decoratorNode = util.template("class-decorator", {
DECORATOR: decorator.expression,
CLASS_REF: classRef
}, true);
decoratorNode.expression._ignoreModulesRemap = true;
body.push(decoratorNode);
}
}
this.pushDecorators();
body = body.concat(this.staticPropBody);
if (this.className) {
if (this.classId) {
// named class with only a constructor
if (body.length === 1) return t.toExpression(body[0]);
} else {
// infer class name if this is a nameless class expression
constructor = nameMethod.bare(constructor, this.parent, this.scope) || constructor;
body.unshift(t.variableDeclaration("var", [
t.variableDeclarator(classRef, constructor)
]));
t.inheritsComments(body[0], this.node);
}
//
body.push(t.returnStatement(classRef));
body.push(t.returnStatement(this.classRef));
return t.callExpression(
t.functionExpression(null, closureParams, t.blockStatement(body)),
@@ -228,6 +186,14 @@ class ClassTransformer {
);
}
/**
* Description
*/
buildConstructor() {
return t.functionDeclaration(this.classRef, [], this.constructorBody);
}
/**
* Description
*/
@@ -258,23 +224,26 @@ class ClassTransformer {
*/
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) return;
if (!hasConstructor) {
this.path.get("body").unshiftContainer("body", t.methodDefinition(
t.identifier("constructor"),
util.template("class-derived-default-constructor"),
"constructor"
));
var constructor;
if (this.isDerived) {
constructor = util.template("class-derived-default-constructor");
} else {
constructor = t.functionExpression(null, [], t.blockStatement([]));
}
this.path.get("body").unshiftContainer("body", t.methodDefinition(
t.identifier("constructor"),
constructor,
"constructor"
));
}
/**
@@ -283,10 +252,25 @@ class ClassTransformer {
buildBody() {
this.constructorMeMaybe();
this.pushBody();
this.placePropertyInitializers();
var constructorBody = this.constructorBody;
var classBodyPaths = this.path.get("body.body");
var body = this.body;
if (this.userConstructor) {
var constructorBody = this.constructorBody;
constructorBody.body = constructorBody.body.concat(this.userConstructor.body.body);
t.inherits(this.constructor, this.userConstructor);
t.inherits(constructorBody, this.userConstructor.body);
}
this.pushDescriptors();
}
/**
* Description
*/
pushBody() {
var classBodyPaths = this.path.get("body.body");
for (var path of (classBodyPaths: Array)) {
var node = path.node;
@@ -302,7 +286,7 @@ class ClassTransformer {
var replaceSupers = new ReplaceSupers({
methodPath: path,
methodNode: node,
objectRef: this.classRef,
objectRef: this.directRef,
superRef: this.superName,
isStatic: node.static,
isLoose: this.isLoose,
@@ -321,16 +305,28 @@ class ClassTransformer {
this.pushProperty(node, path);
}
}
}
//
this.placePropertyInitializers();
/**
* Description
*/
//
if (this.userConstructor) {
constructorBody.body = constructorBody.body.concat(this.userConstructor.body.body);
t.inherits(this.constructor, this.userConstructor);
t.inherits(this.constructorBody, this.userConstructor.body);
}
clearDescriptors() {
this.hasInstanceDescriptors = false;
this.hasStaticDescriptors = false;
this.instanceMutatorMap = {};
this.staticMutatorMap = {};
}
/**
* Description
*/
pushDescriptors() {
this.pushInherits();
var body = this.body;
var instanceProps;
var staticProps;
@@ -378,8 +374,14 @@ class ClassTransformer {
t.callExpression(this.file.addHelper(classHelper), args)
));
}
this.clearDescriptors();
}
/**
* Description
*/
buildObjectAssignment(id) {
return t.variableDeclaration("var", [
t.variableDeclarator(id, t.objectExpression([]))
@@ -405,18 +407,14 @@ class ClassTransformer {
t.functionExpression(null, [], t.blockStatement(body))
), null, true);
if (this.hasSuper) {
if (this.isDerived) {
this.bareSuper.insertAfter(call);
} else {
this.constructorBody.body.unshift(call);
}
} else {
if (this.hasSuper) {
if (this.hasConstructor) {
this.bareSuper.insertAfter(body);
} else {
this.constructorBody.body = this.constructorBody.body.concat(body);
}
if (this.isDerived) {
this.bareSuper.insertAfter(body);
} else {
this.constructorBody.body = body.concat(this.constructorBody.body);
}
@@ -437,7 +435,7 @@ class ClassTransformer {
}
return false;
}
}
/**
* Description
@@ -445,17 +443,25 @@ class ClassTransformer {
verifyConstructor(path: NodePath) {
var state = {
hasBareSuper: false,
bareSuper: null,
hasSuper: this.hasSuper,
file: this.file
constructorPath: path.get("value"),
hasBareSuper: false,
bareSuper: null,
isDerived: this.isDerived,
file: this.file,
};
path.get("value").traverse(verifyConstructorVisitor, state);
state.constructorPath.traverse(verifyConstructorVisitor, state);
var thisAlias = state.constructorPath.getData("this");
if (thisAlias && state.bareSuper) {
state.bareSuper.insertAfter(t.variableDeclaration("var", [
t.variableDeclarator(thisAlias, t.thisExpression())
]));
}
this.bareSuper = state.bareSuper;
if (!state.hasBareSuper && this.hasSuper) {
if (!state.hasBareSuper && this.isDerived) {
throw path.errorWithNode("Derived constructor must call super()");
}
}
@@ -471,24 +477,16 @@ class ClassTransformer {
if (node.kind === "method") {
nameMethod.property(node, this.file, path ? path.get("value").scope : this.scope);
if (this.isLoose && !node.decorators) {
// use assignments instead of define properties for loose classes
var classRef = this.classRef;
if (!node.static) classRef = t.memberExpression(classRef, t.identifier("prototype"));
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);
this.body.push(expr);
return;
}
if (this._processMethod(node)) return;
}
this.pushToMap(node);
}
_processMethod() {
return false;
}
/**
* Description
*/
@@ -568,5 +566,61 @@ class ClassTransformer {
construct.params = fn.params;
t.inherits(construct.body, fn.body);
// push constructor to body
this._pushConstructor();
}
_pushConstructor() {
if (this.pushedConstructor) return;
this.pushedConstructor = true;
// we haven't pushed any descriptors yet
if (this.hasInstanceDescriptors || this.hasStaticDescriptors) {
this.pushDescriptors();
}
this.body.push(this.constructor);
this.pushInherits();
}
/**
* Push inherits helper to body.
*/
pushInherits() {
if (!this.isDerived || this.pushedInherits) return;
this.pushedInherits = true;
this.body.push(t.expressionStatement(t.callExpression(
this.file.addHelper("inherits"),
[this.classRef, this.superName]
)));
}
/**
* Push decorators to body.
*/
pushDecorators() {
var decorators = this.node.decorators;
if (!decorators) return;
this.body.push(t.variableDeclaration("var", [
t.variableDeclarator(this.directRef, this.classRef)
]));
// reverse the decorators so we execute them in the right order
decorators = decorators.reverse();
for (var decorator of (decorators: Array)) {
var decoratorNode = util.template("class-decorator", {
DECORATOR: decorator.expression,
CLASS_REF: this.classRef
}, true);
decoratorNode.expression._ignoreModulesRemap = true;
this.body.push(decoratorNode);
}
}
}

View File

@@ -316,9 +316,12 @@ class DestructuringTransformer {
var left = pattern.left;
if (t.isPattern(left)) {
this.nodes.push(t.expressionStatement(
var tempValueDefault = t.expressionStatement(
t.assignmentExpression("=", tempValueRef, tempConditional)
));
);
tempValueDefault._blockHoist = this.blockHoist;
this.nodes.push(tempValueDefault);
this.push(left, tempValueRef);
} else {
this.nodes.push(this.buildVariableAssignment(left, tempConditional));

View File

@@ -337,10 +337,6 @@ class TailCallTransformer {
args = t.arrayExpression(node.arguments);
}
if (t.isArrayExpression(args) && args.elements.length > this.node.params.length) {
this.needsArguments = true;
}
var argumentsId = this.getArgumentsId();
var params = this.getParams();
@@ -354,17 +350,30 @@ class TailCallTransformer {
if (t.isArrayExpression(args)) {
var elems = args.elements;
for (let i = 0; i < elems.length && i < params.length; i++) {
// pad out the args so all the function args are reset - https://github.com/babel/babel/issues/1938
while (elems.length < params.length) {
elems.push(t.identifier("undefined"));
}
for (let i = 0; i < elems.length; i++) {
let param = params[i];
let elem = elems[i] || (elems[i] = t.identifier("undefined"));
if (!param._isDefaultPlaceholder) {
let elem = elems[i];
if (param && !param._isDefaultPlaceholder) {
elems[i] = t.assignmentExpression("=", param, elem);
} else {
// exceeds parameters but push it anyway to ensure correct execution
}
}
if (!this.needsArguments) {
for (let elem of (elems: Array)) {
body.push(t.expressionStatement(elem));
// only push expressions that we really need, this will skip pure arguments that exceed the
// parameter length of the current function
if (!this.scope.isPure(elem)) {
body.push(t.expressionStatement(elem));
}
}
}
} else {

View File

@@ -60,20 +60,16 @@ export var visitor = {
if (expr) nodes.push(expr);
}
// filter out empty string literals
nodes = nodes.filter(n => !t.isLiteral(n, { value: "" }));
// 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(""));
}
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)) {

View File

@@ -84,4 +84,5 @@ export default {
_blockHoist: require("./internal/block-hoist"),
jscript: require("babel-plugin-jscript"),
flow: require("./other/flow"),
"optimisation.modules.system": require("./optimisation/modules.system"),
};

View File

@@ -6,7 +6,8 @@ export var metadata = {
function remap(path, key, create) {
// ensure that we're shadowed
if (!path.inShadow()) return;
var shadowPath = path.inShadow();
if (!shadowPath || shadowPath.isArrowFunctionExpression()) return;
var shadowFunction = path.node._shadowedFunctionLiteral;
var currentFunction;

View File

@@ -0,0 +1,50 @@
import * as t from "../../../types";
export var metadata = {
optional: true,
group: "builtin-trailing"
};
export var visitor = {
Program(node, parent, scope, file){
if (file.moduleFormatter._setters){
scope.traverse(file.moduleFormatter._setters, optimizeSettersVisitor, {
exportFunctionIdentifier: file.moduleFormatter.exportIdentifier
});
}
}
};
/**
* Setters are optimized to avoid slow export behavior in modules that rely on deep hierarchies
* of export-from declarations.
* More info in https://github.com/babel/babel/pull/1722 and
* https://github.com/ModuleLoader/es6-module-loader/issues/386.
*
* TODO: Ideally this would be optimized during construction of the setters, but the current
* architecture of the module formatters make that difficult.
*/
var optimizeSettersVisitor = {
FunctionExpression: {
enter: (node, parent, scope, state) => {
state.hasExports = false;
state.exportObjectIdentifier = scope.generateUidIdentifier("exportObj");
},
exit: (node, parent, scope, state) => {
if (!state.hasExports) return;
node.body.body.unshift(t.variableDeclaration("var", [
t.variableDeclarator(t.cloneDeep(state.exportObjectIdentifier), t.objectExpression([]))
]));
node.body.body.push(t.expressionStatement(t.callExpression(
t.cloneDeep(state.exportFunctionIdentifier), [t.cloneDeep(state.exportObjectIdentifier)])));
}
},
CallExpression: (node, parent, scope, state) => {
if (!t.isIdentifier(node.callee, {name: state.exportFunctionIdentifier.name})) return;
state.hasExports = true;
var memberNode = t.memberExpression(t.cloneDeep(state.exportObjectIdentifier), node.arguments[0], true);
return t.assignmentExpression("=", memberNode, node.arguments[1]);
}
};

View File

@@ -49,7 +49,9 @@ export var visitor = {
pushElemProp("ref", t.literal(null));
if (node.children.length) {
pushProp(props.properties, t.identifier("children"), t.arrayExpression(react.buildChildren(node)));
var children = react.buildChildren(node);
children = children.length === 1 ? children[0] : t.arrayExpression(children);
pushProp(props.properties, t.identifier("children"), children);
}
// props

View File

@@ -5,6 +5,14 @@ export var metadata = {
};
export var visitor = {
Program(node, parent, scope, file) {
for (var comment of (file.ast.comments: Array)) {
if (comment.value.indexOf("@flow") >= 0) {
comment._displayed = true;
}
}
},
Flow() {
this.dangerouslyRemove();
},

View File

@@ -4,8 +4,24 @@ export var metadata = {
group: "builtin-basic"
};
// visit Property functions first - https://github.com/babel/babel/issues/1860
export var visitor = {
"ArrowFunctionExpression|FunctionExpression": {
exit: bare
exit() {
if (!this.parentPath.isProperty()) {
return bare.apply(this, arguments);
}
}
},
ObjectExpression() {
var props = this.get("properties");
for (var prop of (props: Array)) {
var value = prop.get("value");
if (value.isFunction()) {
var newNode = bare(value.node, prop.node, value.scope);
if (newNode) value.replaceWith(newNode);
}
}
}
};

View File

@@ -2,20 +2,28 @@ import * as t from "../../types";
import NodePath from "./index";
/**
* Description
* Call the provided `callback` with the `NodePath`s of all the parents.
* When the `callback` returns a truthy value, we return that node path.
*/
export function findParent(callback) {
var path = this;
while (path) {
while (path = path.parentPath) {
if (callback(path)) return path;
path = path.parentPath;
}
return null;
}
/**
* Description
* Get the parent function of the current path.
*/
export function getFunctionParent() {
return this.findParent((path) => path.isFunction() || path.isProgram());
}
/**
* Walk up the tree until we hit a parent node path in a list.
*/
export function getStatementParent() {
@@ -139,7 +147,9 @@ export function getDeepestCommonAncestorFrom(paths: Array<NodePath>, filter?: Fu
}
/**
* Description
* Build an array of node paths containing the entire ancestry of the current node path.
*
* NOTE: The current node path is included in this.
*/
export function getAncestry() {
@@ -168,14 +178,14 @@ export function inType() {
}
/**
* Description
* Check if we're inside a shadowed function.
*/
export function inShadow() {
var path = this;
while (path) {
if (path.isFunction()) {
if (path.node.shadow) {
if (path.node.shadow || path.isArrowFunctionExpression()) {
return path;
} else {
return null;

View File

@@ -1,3 +1,4 @@
import type TraversalContext from "../index";
import NodePath from "./index";
import * as t from "../../types";
@@ -39,7 +40,7 @@ export function getOpposite() {
* Description
*/
export function getCompletionRecords(): Array<NodePath> {
export function getCompletionRecords(): Array {
var paths = [];
var add = function (path) {
@@ -80,12 +81,13 @@ export function getSibling(key) {
* Description
*/
export function get(key: string): NodePath {
export function get(key: string, context?: boolean | TraversalContext): NodePath {
if (context === true) context = this.context;
var parts = key.split(".");
if (parts.length === 1) { // "foo"
return this._getKey(key);
return this._getKey(key, context);
} else { // "foo.bar"
return this._getPattern(parts);
return this._getPattern(parts, context);
}
}
@@ -93,7 +95,7 @@ export function get(key: string): NodePath {
* Description
*/
export function _getKey(key) {
export function _getKey(key, context?) {
var node = this.node;
var container = node[key];
@@ -106,7 +108,7 @@ export function _getKey(key) {
parent: node,
container: container,
key: i
}).setContext();
}).setContext(context);
});
} else {
return NodePath.get({
@@ -114,7 +116,7 @@ export function _getKey(key) {
parent: node,
container: node,
key: key
}).setContext();
}).setContext(context);
}
}
@@ -122,7 +124,7 @@ export function _getKey(key) {
* Description
*/
export function _getPattern(parts) {
export function _getPattern(parts, context) {
var path = this;
for (var part of (parts: Array)) {
if (part === ".") {
@@ -131,7 +133,7 @@ export function _getPattern(parts) {
if (Array.isArray(path)) {
path = path[part];
} else {
path = path.get(part);
path = path.get(part, context);
}
}
}
@@ -142,6 +144,6 @@ export function _getPattern(parts) {
* Description
*/
export function getBindingIdentifiers() {
return t.getBindingIdentifiers(this.node);
export function getBindingIdentifiers(duplicates?) {
return t.getBindingIdentifiers(this.node, duplicates);
}

View File

@@ -147,18 +147,6 @@ export function isCompletionRecord(allowInsideFunction?) {
return true;
}
/**
* Description
*/
export function isDirective() {
if (this.isExpressionStatement()) {
return this.get("expression").isLiteral();
} else {
return this.isLiteral() && this.parentPath.isExpressionStatement();
}
}
/**
* Check whether or not the current `key` allows either a single statement or block statement
* so we can explode it if necessary.
@@ -172,22 +160,6 @@ export function isStatementOrBlock() {
}
}
/**
* Check whether this node was a part of the original AST.
*/
export function isUser() {
return this.node && !!this.node.loc;
}
/**
* Check whether this node was generated by us and not a part of the original AST.
*/
export function isGenerated() {
return !this.isUser();
}
/**
* Check if the currently assigned path references the `importName` of `moduleSource`.
*/
@@ -226,7 +198,7 @@ export function referencesImport(moduleSource, importName) {
}
/**
* Description
* Get the source code associated with this node.
*/
export function getSource() {

View File

@@ -19,7 +19,7 @@ var referenceVisitor = {
state.bindings[node.name] = binding;
} else {
for (var violationPath of (binding.constantViolations: Array)) {
state.breakOnScopePaths.push(violationPath.scope.path);
state.breakOnScopePaths = state.breakOnScopePaths.concat(violationPath.getAncestry());
}
}
}
@@ -106,12 +106,15 @@ export default class PathHoister {
this.getCompatibleScopes();
var path = this.getAttachmentPath();
if (!path) return;
var attachTo = this.getAttachmentPath();
if (!attachTo) return;
var uid = path.scope.generateUidIdentifier("ref");
// don't bother hoisting to the same function as this will cause multiple branches to be evaluated more than once leading to a bad optimisation
if (attachTo.getFunctionParent() === this.path.getFunctionParent()) return;
path.insertBefore([
var uid = attachTo.scope.generateUidIdentifier("ref");
attachTo.insertBefore([
t.variableDeclaration("var", [
t.variableDeclarator(uid, this.path.node)
])

View File

@@ -25,6 +25,22 @@ export var BindingIdentifier = {
}
};
export var Statement = {
types: ["Statement"],
checkPath({ node, parent }) {
if (t.isStatement(node)) {
if (t.isVariableDeclaration(node)) {
if (t.isForXStatement(parent, { left: node })) return false;
if (t.isForStatement(parent, { init: node })) return false;
}
return true;
} else {
return false;
}
}
};
export var Expression = {
types: ["Expression"],
checkPath(path) {
@@ -61,3 +77,29 @@ export var Var = {
return t.isVar(path.node);
}
};
export var DirectiveLiteral = {
types: ["Literal"],
checkPath(path) {
return path.isLiteral() && path.parentPath.isExpressionStatement();
}
};
export var Directive = {
types: ["ExpressionStatement"],
checkPath(path) {
return path.get("expression").isLiteral();
}
};
export var User = {
checkPath(path) {
return path.node && !!path.node.loc;
}
};
export var Generated = {
checkPath(path) {
return !path.isUser();
}
};

View File

@@ -3,7 +3,7 @@ import NodePath from "./index";
import * as t from "../../types";
/**
* Description
* Insert the provided nodes before the current one.
*/
export function insertBefore(nodes) {
@@ -75,7 +75,8 @@ export function _maybePopFromStatements(nodes) {
}
/**
* Description
* Insert the provided nodes after the current one. When inserting nodes after an
* expression, ensure that the completion record is correct by pushing the current node.
*/
export function insertAfter(nodes) {
@@ -108,7 +109,7 @@ export function insertAfter(nodes) {
}
/**
* Description
* Update all sibling node paths after `fromIndex` by `incrementBy`.
*/
export function updateSiblingKeys(fromIndex, incrementBy) {
@@ -121,10 +122,6 @@ export function updateSiblingKeys(fromIndex, incrementBy) {
}
}
/**
* Description
*/
/**
* Description
*/
@@ -200,7 +197,8 @@ export function pushContainer(listKey, nodes) {
}
/**
* Description
* Hoist the current node to the highest scope possible and return a UID
* referencing it.
*/
export function hoist(scope = this.scope) {

View File

@@ -11,7 +11,8 @@ export function remove() {
}
/**
* Description
* Dangerously remove the current node. This may sometimes result in a tainted
* invalid AST so use with caution.
*/
export function dangerouslyRemove() {

View File

@@ -32,7 +32,11 @@ var hoistVariablesVisitor = {
};
/**
* Description
* Replace a node with an array of multiple. This method performs the following steps:
*
* - Inherit the comments of first provided node with that of the current node.
* - Insert the provided nodes after the current node.
* - Remove the current node.
*/
export function replaceWithMultiple(nodes: Array<Object>) {
@@ -46,7 +50,11 @@ export function replaceWithMultiple(nodes: Array<Object>) {
}
/**
* Description
* Parse a string as an expression and replace the current node with the result.
*
* NOTE: This is typically not a good idea to use. Building source strings when
* transforming ASTs is an antipattern and SHOULD NOT be encouraged. Even if it's
* easier to use, your transforms will be extremely brittle.
*/
export function replaceWithSourceString(replacement) {
@@ -70,7 +78,7 @@ export function replaceWithSourceString(replacement) {
}
/**
* Description
* Replace the current node with another.
*/
export function replaceWith(replacement, whateverAllowed) {
@@ -147,7 +155,9 @@ export function replaceWith(replacement, whateverAllowed) {
}
/**
* Description
* This method takes an array of statements nodes and then explodes it
* into expressions. This method retains completion records which is
* extremely important to retain original semantics.
*/
export function replaceExpressionWithStatements(nodes: Array) {

View File

@@ -146,7 +146,7 @@ export default class Scope {
}
var cached = path.getData("scope");
if (cached && cached.parent === parent) {
if (cached && cached.parent === parent && cached.block === path.node) {
return cached;
} else {
path.setData("scope", this);
@@ -491,32 +491,32 @@ export default class Scope {
}
var parent = this.getProgramParent();
var ids = path.getBindingIdentifiers();
var ids = path.getBindingIdentifiers(true);
for (var name in ids) {
var id = ids[name];
for (var id of (ids[name]: Array)) {
var local = this.getOwnBinding(name);
if (local) {
// don't ever let a type alias shadow a local binding
if (kind === "type") continue;
var local = this.getOwnBinding(name);
if (local) {
// don't ever let a type alias shadow a local binding
if (kind === "type") continue;
// same identifier so continue safely as we're likely trying to register it
// multiple times
if (local.identifier === id) continue;
// same identifier so continue safely as we're likely trying to register it
// multiple times
if (local.identifier === id) continue;
this.checkBlockScopedCollisions(local, kind, name, id);
}
this.checkBlockScopedCollisions(local, kind, name, id);
parent.references[name] = true;
this.bindings[name] = new Binding({
identifier: id,
existing: local,
scope: this,
path: path,
kind: kind
});
}
parent.references[name] = true;
this.bindings[name] = new Binding({
identifier: id,
existing: local,
scope: this,
path: path,
kind: kind
});
}
}

View File

@@ -261,18 +261,22 @@ export function toBlock(node: Object, parent: Object): Object {
*/
export function valueToNode(value: any): Object {
// undefined
if (value === undefined) {
return t.identifier("undefined");
}
// null, booleans, strings, numbers, regexs
if (value === true || value === false || value === null || isString(value) || isNumber(value) || isRegExp(value)) {
return t.literal(value);
}
// array
if (Array.isArray(value)) {
return t.arrayExpression(value.map(t.valueToNode));
}
// object
if (isPlainObject(value)) {
var props = [];
for (var key in value) {

View File

@@ -5,7 +5,7 @@ import * as t from "./index";
* Return a list of binding identifiers associated with the input `node`.
*/
export function getBindingIdentifiers(node: Object): Object {
export function getBindingIdentifiers(node: Object, duplicates?): Object {
var search = [].concat(node);
var ids = object();
@@ -16,7 +16,12 @@ export function getBindingIdentifiers(node: Object): Object {
var key = t.getBindingIdentifiers.keys[id.type];
if (t.isIdentifier(id)) {
ids[id.name] = id;
if (duplicates) {
var _ids = ids[id.name] = ids[id.name] || [];
_ids.push(id);
} else {
ids[id.name] = id;
}
} else if (t.isExportDeclaration(id)) {
if (t.isDeclaration(node.declaration)) {
search.push(node.declaration);

View File

@@ -56,7 +56,7 @@ export function resolveRelative(loc: string) {
}
}
export function list(val: string): Array<string> {
export function list(val: string): Array {
if (!val) {
return [];
} else if (Array.isArray(val)) {
@@ -114,18 +114,26 @@ export function shouldIgnore(filename, ignore, only) {
if (only) {
for (let pattern of (only: Array)) {
if (pattern.test(filename)) return false;
if (_shouldIgnore(pattern, filename)) return false;
}
return true;
} else if (ignore.length) {
for (let pattern of (ignore: Array)) {
if (pattern.test(filename)) return true;
if (_shouldIgnore(pattern, filename)) return true;
}
}
return false;
}
function _shouldIgnore(pattern, filename) {
if (typeof pattern === "function") {
return pattern(filename);
} else {
return pattern.test(filename);
}
}
var templateVisitor = {
noScope: true,

View File

@@ -1 +0,0 @@
assert.ok(false);

View File

@@ -1,3 +0,0 @@
assert.equal(do {
do { "foo" };
}, "foo");

View File

@@ -1 +0,0 @@
assert.ok(false);

View File

@@ -1,9 +1,9 @@
"use strict";
var some = function some() {
var count = arguments[0] === undefined ? "30" : arguments[0];
var count = arguments.length <= 0 || arguments[0] === undefined ? "30" : arguments[0];
console.log("count", count);
};
some();
some();

View File

@@ -0,0 +1,13 @@
class x {
f() {
1
2
3
}
constructor() {
4
5
6
}
}

View File

@@ -0,0 +1,18 @@
"use strict";
var x = (function () {
x.prototype.f = function f() {
1;
2;
3;
};
function x() {
4;
5;
6;
babelHelpers.classCallCheck(this, x);
}
return x;
})();

View File

@@ -10,3 +10,12 @@ class Foo extends Bar {
this.state = "test";
}
}
class ConstructorScoping {
constructor(){
let bar;
{
let bar;
}
}
}

View File

@@ -16,4 +16,13 @@ var Foo = (function (_Bar) {
babelHelpers.inherits(Foo, _Bar);
return Foo;
})(Bar);
})(Bar);
var ConstructorScoping = function ConstructorScoping() {
babelHelpers.classCallCheck(this, ConstructorScoping);
var bar = undefined;
{
var _bar = undefined;
}
};

View File

@@ -0,0 +1,7 @@
class Foo extends Bar {
constructor() {
super(() => {
this.test;
});
}
}

View File

@@ -0,0 +1,16 @@
"use strict";
var Foo = (function (_Bar) {
function Foo() {
babelHelpers.classCallCheck(this, Foo);
babelHelpers.get(Object.getPrototypeOf(Foo.prototype), "constructor", this).call(this, function () {
_this.test;
});
var _this = this;
}
babelHelpers.inherits(Foo, _Bar);
return Foo;
})(Bar);

View File

@@ -6,26 +6,22 @@ var BaseView = function BaseView() {
this.autoRender = true;
};
var BaseView = (function () {
var _class = function BaseView() {
babelHelpers.classCallCheck(this, _class);
var BaseView = function BaseView() {
babelHelpers.classCallCheck(this, BaseView);
this.autoRender = true;
};
return _class;
})();
this.autoRender = true;
};
var BaseView = (function () {
var _class2 = function BaseView() {
babelHelpers.classCallCheck(this, _class2);
};
function BaseView() {
babelHelpers.classCallCheck(this, BaseView);
}
babelHelpers.createClass(_class2, [{
babelHelpers.createClass(BaseView, [{
key: "foo",
value: function foo() {
this.autoRender = true;
}
}]);
return _class2;
return BaseView;
})();

View File

@@ -9,9 +9,9 @@ var TestEmpty = (function (_ref) {
babelHelpers.inherits(TestEmpty, _ref);
return TestEmpty;
})((function () {
var _class = function _class() {
function _class() {
babelHelpers.classCallCheck(this, _class);
};
}
return _class;
})());
@@ -25,9 +25,9 @@ var TestConstructorOnly = (function (_ref2) {
babelHelpers.inherits(TestConstructorOnly, _ref2);
return TestConstructorOnly;
})((function () {
var _class2 = function _class2() {
function _class2() {
babelHelpers.classCallCheck(this, _class2);
};
}
return _class2;
})());
@@ -41,9 +41,9 @@ var TestMethodOnly = (function (_ref3) {
babelHelpers.inherits(TestMethodOnly, _ref3);
return TestMethodOnly;
})((function () {
var _class3 = function _class3() {
function _class3() {
babelHelpers.classCallCheck(this, _class3);
};
}
babelHelpers.createClass(_class3, [{
key: "method",
@@ -61,9 +61,9 @@ var TestConstructorAndMethod = (function (_ref4) {
babelHelpers.inherits(TestConstructorAndMethod, _ref4);
return TestConstructorAndMethod;
})((function () {
var _class4 = function _class4() {
function _class4() {
babelHelpers.classCallCheck(this, _class4);
};
}
babelHelpers.createClass(_class4, [{
key: "method",
@@ -81,9 +81,9 @@ var TestMultipleMethods = (function (_ref5) {
babelHelpers.inherits(TestMultipleMethods, _ref5);
return TestMultipleMethods;
})((function () {
var _class5 = function _class5() {
function _class5() {
babelHelpers.classCallCheck(this, _class5);
};
}
babelHelpers.createClass(_class5, [{
key: "m1",

View File

@@ -0,0 +1,6 @@
class Foo extends Bar {
constructor() {
super.foo();
super();
}
}

View File

@@ -0,0 +1,3 @@
{
"throws": "'super.*' is not allowed before super()"
}

View File

@@ -1,4 +1,4 @@
function somethingAdvanced({topLeft: {x: x1, y: y1}, bottomRight: {x: x2, y: y2}}){
function somethingAdvanced({topLeft: {x: x1, y: y1} = {}, bottomRight: {x: x2, y: y2} = {}}, p2, p3){
}

View File

@@ -1,10 +1,12 @@
"use strict";
function somethingAdvanced(_ref) {
function somethingAdvanced(_ref, p2, p3) {
var _ref$topLeft = _ref.topLeft;
_ref$topLeft = _ref$topLeft === undefined ? {} : _ref$topLeft;
var x1 = _ref$topLeft.x;
var y1 = _ref$topLeft.y;
var _ref$bottomRight = _ref.bottomRight;
_ref$bottomRight = _ref$bottomRight === undefined ? {} : _ref$bottomRight;
var x2 = _ref$bottomRight.x;
var y2 = _ref$bottomRight.y;
}

View File

@@ -9,13 +9,9 @@ define(["exports", "module"], function (exports, module) {
module.exports = function () {};
var _default = (function () {
var _class = function _default() {
babelHelpers.classCallCheck(this, _class);
};
return _class;
})();
var _default = function _default() {
babelHelpers.classCallCheck(this, _default);
};
module.exports = _default;

View File

@@ -11,13 +11,9 @@ exports["default"] = foo;
exports["default"] = function () {};
var _default = (function () {
var _class = function _default() {
babelHelpers.classCallCheck(this, _class);
};
return _class;
})();
var _default = function _default() {
babelHelpers.classCallCheck(this, _default);
};
exports["default"] = _default;

View File

@@ -2,13 +2,9 @@
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
var _default = (function () {
var _class = function _default() {
_classCallCheck(this, _class);
};
return _class;
})();
var _default = function _default() {
_classCallCheck(this, _default);
};
function foo() {}

View File

@@ -22,13 +22,9 @@ System.register([], function (_export) {
_export("default", function () {});
_default = (function () {
var _class = function _default() {
_classCallCheck(this, _class);
};
return _class;
})();
_default = function _default() {
_classCallCheck(this, _default);
};
_export("default", _default);
@@ -43,4 +39,4 @@ System.register([], function (_export) {
})());
}
};
});
});

View File

@@ -8,6 +8,8 @@ export var p = 5;
for (var a in b) ;
for (var i = 0, j = 0;;) ;
export var isOdd = (function (isEven) {
return function (n) {
return !isEven(n);

View File

@@ -1,7 +1,7 @@
System.register(["./evens"], function (_export) {
"use strict";
var isEven, p, a, isOdd;
var isEven, p, a, i, j, isOdd;
_export("nextOdd", nextOdd);
@@ -20,6 +20,8 @@ System.register(["./evens"], function (_export) {
for (a in b);
for (i = 0, j = 0;;);
isOdd = (function (isEven) {
return function (n) {
return !isEven(n);

View File

@@ -21,13 +21,9 @@
module.exports = function () {};
var _default = (function () {
var _class = function _default() {
babelHelpers.classCallCheck(this, _class);
};
return _class;
})();
var _default = function _default() {
babelHelpers.classCallCheck(this, _default);
};
module.exports = _default;

View File

@@ -2,7 +2,7 @@
var x = "outside";
function outer() {
var a = arguments[0] === undefined ? function () {
var a = arguments.length <= 0 || arguments[0] === undefined ? function () {
return eval("x");
} : arguments[0];
return (function () {
@@ -10,4 +10,4 @@ function outer() {
return a();
})();
}
outer();
outer();

View File

@@ -1,14 +1,14 @@
"use strict";
var t = function t() {
var e = arguments[0] === undefined ? "foo" : arguments[0];
var f = arguments[1] === undefined ? 5 : arguments[1];
var e = arguments.length <= 0 || arguments[0] === undefined ? "foo" : arguments[0];
var f = arguments.length <= 1 || arguments[1] === undefined ? 5 : arguments[1];
return e + " bar " + f;
};
var a = function a(e) {
var f = arguments[1] === undefined ? 5 : arguments[1];
var f = arguments.length <= 1 || arguments[1] === undefined ? 5 : arguments[1];
return e + " bar " + f;
};
};

View File

@@ -1,7 +1,7 @@
"use strict";
var t = function t() {
var f = arguments[0] === undefined ? "foo" : arguments[0];
var f = arguments.length <= 0 || arguments[0] === undefined ? "foo" : arguments[0];
return f + " bar";
};
};

View File

@@ -6,9 +6,9 @@ function sum() {
_function: while (_again) {
a = b = undefined;
var a = _arguments[0] === undefined ? 1 : _arguments[0];
var a = _arguments.length <= 0 || _arguments[0] === undefined ? 1 : _arguments[0];
_again = false;
var b = _arguments[1] === undefined ? 2 : _arguments[1];
var b = _arguments.length <= 1 || _arguments[1] === undefined ? 2 : _arguments[1];
if (b > 0) {
_arguments = [a + 1, b - 1];
@@ -17,4 +17,4 @@ function sum() {
}
return a;
}
}
}

View File

@@ -8,7 +8,7 @@ function fact(_x2) {
var n = _x2;
acc = undefined;
_again = false;
var acc = _arguments[1] === undefined ? 1 : _arguments[1];
var acc = _arguments.length <= 1 || _arguments[1] === undefined ? 1 : _arguments[1];
if (n > 1) {
_arguments = [_x2 = n - 1, acc * n];
_again = true;
@@ -17,4 +17,4 @@ function fact(_x2) {
return acc;
}
}
}
}

View File

@@ -7,7 +7,7 @@ var count = function count() {
_function: while (_again) {
i = undefined;
_again = false;
var i = _arguments[0] === undefined ? 10 : _arguments[0];
var i = _arguments.length <= 0 || _arguments[0] === undefined ? 10 : _arguments[0];
if (!i) return;
_arguments = [i - 1];
@@ -23,11 +23,11 @@ function count2() {
_function2: while (_again2) {
i = undefined;
_again2 = false;
var i = _arguments2[0] === undefined ? 10 : _arguments2[0];
var i = _arguments2.length <= 0 || _arguments2[0] === undefined ? 10 : _arguments2[0];
if (!i) return;
_arguments2 = [i - 1];
_again2 = true;
continue _function2;
}
}
}

View File

@@ -0,0 +1,15 @@
function foo(a, b) {
if (b) {
return foo(b);
} else {
return a;
}
}
function foo(a, b) {
if (b) {
return foo("a", "b", "c");
} else {
return a;
}
}

View File

@@ -0,0 +1,9 @@
function foo(a, b) {
if (b) {
return foo(b);
} else {
return a;
}
}
assert.equal(foo("Michael", "Jackson"), "Jackson");

View File

@@ -0,0 +1,28 @@
"use strict";
function foo(a, b) {
if (b) {
return foo(b);
} else {
return a;
}
}
function foo(_x, _x2) {
var _again = true;
_function: while (_again) {
var a = _x,
b = _x2;
_again = false;
if (b) {
_x = "a";
_x2 = "b";
_again = true;
continue _function;
} else {
return a;
}
}
}

View File

@@ -11,7 +11,7 @@
var g = function g() {};
_again = false;
var m = _arguments[1] === undefined ? getDefaultValue() : _arguments[1];
var m = _arguments.length <= 1 || _arguments[1] === undefined ? getDefaultValue() : _arguments[1];
// `m` should be `getDefaultValue()` after first pass
if (n <= 0) {
@@ -27,4 +27,4 @@
_again = true;
continue _function;
}
})(1e6, true) === "foo";
})(1e6, true) === "foo";

View File

@@ -6,3 +6,4 @@ const example = `${"a"}`;
const example2 = `${1}`;
const example3 = 1 + `${foo}${bar}${baz}`;
const example4 = 1 + `${foo}bar${baz}`;
const example5 = `${""}`;

View File

@@ -8,3 +8,4 @@ var example = "a";
var example2 = "" + 1;
var example3 = 1 + ("" + foo + bar + baz);
var example4 = 1 + (foo + "bar" + baz);
var example5 = "";

View File

@@ -14,14 +14,14 @@ var Foo = (function (_Bar) {
})(Bar);
var Foo2 = (function (_Bar2) {
var _class = function Foo2() {
babelHelpers.classCallCheck(this, _class2);
function Foo2() {
babelHelpers.classCallCheck(this, _Foo2);
babelHelpers.get(Object.getPrototypeOf(_class2.prototype), "constructor", this).call(this);
};
babelHelpers.get(Object.getPrototypeOf(_Foo2.prototype), "constructor", this).call(this);
}
babelHelpers.inherits(_class, _Bar2);
var _class2 = _class;
_class = bar(_class) || _class;
return _class;
})(Bar);
babelHelpers.inherits(Foo2, _Bar2);
var _Foo2 = Foo2;
Foo2 = bar(Foo2) || Foo2;
return Foo2;
})(Bar);

View File

@@ -1,8 +1,6 @@
var obj = {
@foo
bar() {
},
bar() {},
@bar
foo: "lol",

View File

@@ -3,7 +3,7 @@
var obj = babelHelpers.createDecoratedObject([{
key: "bar",
decorators: [foo],
value: function value() {}
value: function bar() {}
}, {
key: "foo",
decorators: [bar],
@@ -15,4 +15,4 @@ var obj = babelHelpers.createDecoratedObject([{
initializer: function initializer() {
return "wow";
}
}]);
}]);

View File

@@ -0,0 +1,5 @@
assert.equal(do {
var i = 5;
do { i--; } while(i > 3);
i;
}, 3);

View File

@@ -2,4 +2,4 @@ assert.equal(do {
for (var i = 0; i < 5; i++) {
i;
}
}, 5);
}, 4);

View File

@@ -0,0 +1,5 @@
assert.equal(do {
var i = 5;
while (i > 3) i--;
i;
}, 3);

View File

@@ -0,0 +1,9 @@
/*@flow*/
/* @flow */
/**
* @flow
*/
foo();

View File

@@ -0,0 +1 @@
foo();

View File

@@ -1,7 +1,7 @@
"use strict";
function test() {
var x = arguments[0] === undefined ? "hi" : arguments[0];
var x = arguments.length <= 0 || arguments[0] === undefined ? "hi" : arguments[0];
return x;
}
}

View File

@@ -0,0 +1,4 @@
{
"modules": "system",
"optional": ["optimisation.modules.system"]
}

View File

@@ -0,0 +1,8 @@
export * from "foo";
export {foo} from "foo";
export {foo, bar} from "foo";
export {foo as bar} from "bar";
export {foo as default} from "bar";
export {foo as default, bar} from "bar";
export var foo, bar;

View File

@@ -0,0 +1,33 @@
System.register(["foo", "bar"], function (_export) {
"use strict";
var foo, bar;
return {
setters: [function (_foo) {
var _exportObj = {};
for (var _key in _foo) {
_exportObj[_key] = _foo[_key];
}
_exportObj["foo"] = _foo.foo;
_exportObj["foo"] = _foo.foo;
_exportObj["bar"] = _foo.bar;
_export(_exportObj);
}, function (_bar) {
var _exportObj2 = {};
_exportObj2["bar"] = _bar.foo;
_exportObj2["default"] = _bar.foo;
_exportObj2["default"] = _bar.foo;
_exportObj2["bar"] = _bar.bar;
_export(_exportObj2);
}],
execute: function () {
_export("foo", foo);
_export("bar", bar);
}
};
});

View File

@@ -0,0 +1,9 @@
function render() {
var children = <b></b>;
if (someCondition) {
children = <span></span>;
}
return <div>{children}</div>;
}

View File

@@ -0,0 +1,15 @@
"use strict";
var _ref = <b></b>;
var _ref2 = <span></span>;
function render() {
var children = _ref;
if (someCondition) {
children = _ref2;
}
return <div>{children}</div>;
}

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