From a5330425038988091f6dbb8b7fa912e7cfb7276c Mon Sep 17 00:00:00 2001 From: Sebastian McKenzie Date: Mon, 25 May 2015 01:42:54 +0100 Subject: [PATCH] fix bad .gitignore paths resulting in some tests and path/lib files not being included... --- .gitignore | 14 +- src/babel/traversal/path/lib/hoister.js | 130 ++++++++++++++++++ src/babel/traversal/path/lib/removal-hooks.js | 71 ++++++++++ src/babel/traversal/path/lib/virtual-types.js | 34 +++++ .../babel/--ignore/out-files/lib/bar/index.js | 3 + .../babel/--only/out-files/lib/bar/index.js | 3 + .../out-files/lib/bar/bar.js | 8 ++ .../out-files/lib/foo.js | 6 + .../out-files/lib/bar/bar.js | 8 ++ .../out-files/lib/bar/bar.js.map | 1 + .../out-files/lib/foo.js | 6 + .../out-files/lib/foo.js.map | 1 + .../dir --out-dir/out-files/lib/bar/bar.js | 7 + .../babel/dir --out-dir/out-files/lib/foo.js | 5 + 14 files changed, 290 insertions(+), 7 deletions(-) create mode 100644 src/babel/traversal/path/lib/hoister.js create mode 100644 src/babel/traversal/path/lib/removal-hooks.js create mode 100644 src/babel/traversal/path/lib/virtual-types.js create mode 100644 test/core/fixtures/bin/babel/--ignore/out-files/lib/bar/index.js create mode 100644 test/core/fixtures/bin/babel/--only/out-files/lib/bar/index.js create mode 100644 test/core/fixtures/bin/babel/dir --out-dir --source-maps inline/out-files/lib/bar/bar.js create mode 100644 test/core/fixtures/bin/babel/dir --out-dir --source-maps inline/out-files/lib/foo.js create mode 100644 test/core/fixtures/bin/babel/dir --out-dir --source-maps/out-files/lib/bar/bar.js create mode 100644 test/core/fixtures/bin/babel/dir --out-dir --source-maps/out-files/lib/bar/bar.js.map create mode 100644 test/core/fixtures/bin/babel/dir --out-dir --source-maps/out-files/lib/foo.js create mode 100644 test/core/fixtures/bin/babel/dir --out-dir --source-maps/out-files/lib/foo.js.map create mode 100644 test/core/fixtures/bin/babel/dir --out-dir/out-files/lib/bar/bar.js create mode 100644 test/core/fixtures/bin/babel/dir --out-dir/out-files/lib/foo.js diff --git a/.gitignore b/.gitignore index 012bda1ffd..f1ac2c5c93 100644 --- a/.gitignore +++ b/.gitignore @@ -8,10 +8,10 @@ test/core/tmp /browser.js /browser-polyfill.js /runtime.js -coverage -dist -.package.json -packages/babel-runtime/core-js -packages/babel-runtime/helpers/*.js -packages/babel-runtime/regenerator/*.js -lib +/coverage +/dist +/.package.json +/packages/babel-runtime/core-js +/packages/babel-runtime/helpers/*.js +/packages/babel-runtime/regenerator/*.js +/lib diff --git a/src/babel/traversal/path/lib/hoister.js b/src/babel/traversal/path/lib/hoister.js new file mode 100644 index 0000000000..5964e6c088 --- /dev/null +++ b/src/babel/traversal/path/lib/hoister.js @@ -0,0 +1,130 @@ +import * as react from "../../../transformation/helpers/react"; +import * as t from "../../../types"; + +var referenceVisitor = { + ReferencedIdentifier(node, parent, scope, state) { + if (this.isJSXIdentifier() && react.isCompatTag(node.name)) { + return; + } + + // direct references that we need to track to hoist this to the highest scope we can + var bindingInfo = scope.getBinding(node.name); + if (!bindingInfo) return; + + // this binding isn't accessible from the parent scope so we can safely ignore it + // eg. it's in a closure etc + if (bindingInfo !== state.scope.getBinding(node.name)) return; + + if (bindingInfo.constant) { + state.bindings[node.name] = bindingInfo; + } else { + for (var violationPath of (bindingInfo.constantViolations: Array)) { + state.breakOnScopePaths.push(violationPath.scope.path); + } + } + } +}; + +export default class PathHoister { + constructor(path, scope) { + this.breakOnScopePaths = []; + this.bindings = {}; + this.scopes = []; + this.scope = scope; + this.path = path; + } + + isCompatibleScope(scope) { + for (var key in this.bindings) { + var binding = this.bindings[key]; + if (!scope.bindingIdentifierEquals(key, binding.identifier)) { + return false; + } + } + + return true; + } + + getCompatibleScopes() { + var scope = this.path.scope; + do { + if (this.isCompatibleScope(scope)) { + this.scopes.push(scope); + } else { + break; + } + + if (this.breakOnScopePaths.indexOf(scope.path) >= 0) { + break; + } + } while(scope = scope.parent); + } + + getAttachmentPath() { + var scopes = this.scopes; + + var scope = scopes.pop(); + if (!scope) return; + + if (scope.path.isFunction()) { + if (this.hasOwnParamBindings(scope)) { + // should ignore this scope since it's ourselves + if (this.scope.is(scope)) return; + + // needs to be attached to the body + return scope.path.get("body").get("body")[0]; + } else { + // doesn't need to be be attached to this scope + return this.getNextScopeStatementParent(); + } + } else if (scope.path.isProgram()) { + return this.getNextScopeStatementParent(); + } + } + + getNextScopeStatementParent() { + var scope = this.scopes.pop(); + if (scope) return scope.path.getStatementParent(); + } + + hasOwnParamBindings(scope) { + for (var name in this.bindings) { + if (!scope.hasOwnBinding(name)) continue; + + var binding = this.bindings[name]; + if (binding.kind === "param") return true; + } + return false; + } + + run() { + var node = this.path.node; + if (node._hoisted) return; + node._hoisted = true; + + this.path.traverse(referenceVisitor, this); + + this.getCompatibleScopes(); + + var path = this.getAttachmentPath(); + if (!path) return; + + var uid = path.scope.generateUidIdentifier("ref"); + + path.insertBefore([ + t.variableDeclaration("var", [ + t.variableDeclarator(uid, this.path.node) + ]) + ]); + + var parent = this.path.parentPath; + + if (parent.isJSXElement() && this.path.container === parent.node.children) { + // turning the `span` in `
` to an expression so we need to wrap it with + // an expression container + uid = t.jSXExpressionContainer(uid); + } + + this.path.replaceWith(uid); + } +} diff --git a/src/babel/traversal/path/lib/removal-hooks.js b/src/babel/traversal/path/lib/removal-hooks.js new file mode 100644 index 0000000000..fc6e60ae9b --- /dev/null +++ b/src/babel/traversal/path/lib/removal-hooks.js @@ -0,0 +1,71 @@ +// This file contains all the cases where we have to perform additional logic when performing +// specific operations in order to retain correct JavaScript semantics. + +import * as t from "../../../types"; + +// pre hooks should be used for either rejecting removal or delegating removal to a replacement +export var pre = [ + function (self, parent) { + if (self.key === "body" && self.isBlockStatement() && parent.isFunction()) { + // lol nah, you'll break stuff + return true; + } + }, + + function (self, parent) { + // attempting to remove body of an arrow function so we just replace it with undefined + if (self.key === "body" && parent.isArrowFunctionExpression()) { + self.replaceWith(t.identifier("undefined")); + return true; + } + } +]; + +// post hooks should be used for cleaning up parents +export var post = [ + function (self, parent) { + // just remove a declaration for an export so this is no longer valid + if (self.key === "declaration" && parent.isExportDeclaration()) { + parent.remove(); + return true; + } + }, + + function (self, parent) { + // we've just removed the last declarator of a variable declaration so there's no point in + // keeping it + if (parent.isVariableDeclaration() && parent.node.declarations.length === 0) { + parent.remove(); + return true; + } + }, + + function (self, parent) { + // we're the child of an expression statement so we should remove the parent + if (parent.isExpressionStatement()) { + parent.remove(); + return true; + } + }, + + function (self, parent) { + // we've just removed the second element of a sequence expression so let's turn that sequence + // expression into a regular expression + if (parent.isSequenceExpression() && parent.node.expressions.length === 1) { + parent.replaceWith(parent.node.expressions[0]); + return true; + } + }, + + function (self, parent) { + // we're in a binary expression, better remove it and replace it with the last expression + if (parent.isBinary()) { + if (self.key === "left") { + parent.replaceWith(parent.node.right); + } else { // key === "right" + parent.replaceWith(parent.node.left); + } + return true; + } + } +]; diff --git a/src/babel/traversal/path/lib/virtual-types.js b/src/babel/traversal/path/lib/virtual-types.js new file mode 100644 index 0000000000..7f6ba09015 --- /dev/null +++ b/src/babel/traversal/path/lib/virtual-types.js @@ -0,0 +1,34 @@ +import * as t from "../../../types"; + +export var ReferencedIdentifier = { + types: ["Identifier", "JSXIdentifier"], + checkPath(path, opts) { + return t.isReferencedIdentifier(path.node, path.parent, opts); + } +}; + +export var Scope = { + types: ["Scopable"], + checkPath(path) { + return t.isScope(path.node, path.parent); + } +}; + +export var Referenced = { + checkPath(path) { + return t.isReferenced(path.node, path.parent); + } +}; + +export var BlockScoped = { + checkPath(path) { + return t.isBlockScoped(path.node); + } +}; + +export var Var = { + types: ["VariableDeclaration"], + checkPath(path) { + return t.isVar(path.node); + } +}; diff --git a/test/core/fixtures/bin/babel/--ignore/out-files/lib/bar/index.js b/test/core/fixtures/bin/babel/--ignore/out-files/lib/bar/index.js new file mode 100644 index 0000000000..0ed075a193 --- /dev/null +++ b/test/core/fixtures/bin/babel/--ignore/out-files/lib/bar/index.js @@ -0,0 +1,3 @@ +"use strict"; + +bar; diff --git a/test/core/fixtures/bin/babel/--only/out-files/lib/bar/index.js b/test/core/fixtures/bin/babel/--only/out-files/lib/bar/index.js new file mode 100644 index 0000000000..0ed075a193 --- /dev/null +++ b/test/core/fixtures/bin/babel/--only/out-files/lib/bar/index.js @@ -0,0 +1,3 @@ +"use strict"; + +bar; diff --git a/test/core/fixtures/bin/babel/dir --out-dir --source-maps inline/out-files/lib/bar/bar.js b/test/core/fixtures/bin/babel/dir --out-dir --source-maps inline/out-files/lib/bar/bar.js new file mode 100644 index 0000000000..7c44c97342 --- /dev/null +++ b/test/core/fixtures/bin/babel/dir --out-dir --source-maps inline/out-files/lib/bar/bar.js @@ -0,0 +1,8 @@ +"use strict"; + +function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } + +var Test = function Test() { + _classCallCheck(this, Test); +}; +//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9iYXIvYmFyLmpzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7SUFBTSxJQUFJLFlBQUosSUFBSTt3QkFBSixJQUFJIiwiZmlsZSI6ImJhci5qcyIsInNvdXJjZXNDb250ZW50IjpbImNsYXNzIFRlc3Qge1xuXG59Il19 diff --git a/test/core/fixtures/bin/babel/dir --out-dir --source-maps inline/out-files/lib/foo.js b/test/core/fixtures/bin/babel/dir --out-dir --source-maps inline/out-files/lib/foo.js new file mode 100644 index 0000000000..3537587fad --- /dev/null +++ b/test/core/fixtures/bin/babel/dir --out-dir --source-maps inline/out-files/lib/foo.js @@ -0,0 +1,6 @@ +"use strict"; + +arr.map(function (x) { + return x * MULTIPLIER; +}); +//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uL3NyYy9mb28uanMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7QUFBQSxHQUFHLENBQUMsR0FBRyxDQUFDLFVBQUEsQ0FBQztTQUFJLENBQUMsR0FBRyxVQUFVO0NBQUEsQ0FBQyxDQUFDIiwiZmlsZSI6ImZvby5qcyIsInNvdXJjZXNDb250ZW50IjpbImFyci5tYXAoeCA9PiB4ICogTVVMVElQTElFUik7Il19 diff --git a/test/core/fixtures/bin/babel/dir --out-dir --source-maps/out-files/lib/bar/bar.js b/test/core/fixtures/bin/babel/dir --out-dir --source-maps/out-files/lib/bar/bar.js new file mode 100644 index 0000000000..85d52f9265 --- /dev/null +++ b/test/core/fixtures/bin/babel/dir --out-dir --source-maps/out-files/lib/bar/bar.js @@ -0,0 +1,8 @@ +"use strict"; + +function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } + +var Test = function Test() { + _classCallCheck(this, Test); +}; +//# sourceMappingURL=bar.js.map diff --git a/test/core/fixtures/bin/babel/dir --out-dir --source-maps/out-files/lib/bar/bar.js.map b/test/core/fixtures/bin/babel/dir --out-dir --source-maps/out-files/lib/bar/bar.js.map new file mode 100644 index 0000000000..d2f66bb31f --- /dev/null +++ b/test/core/fixtures/bin/babel/dir --out-dir --source-maps/out-files/lib/bar/bar.js.map @@ -0,0 +1 @@ +{"version":3,"sources":["../../src/bar/bar.js"],"names":[],"mappings":";;;;IAAM,IAAI,YAAJ,IAAI;wBAAJ,IAAI","file":"bar.js","sourcesContent":["class Test {\n\n}"]} diff --git a/test/core/fixtures/bin/babel/dir --out-dir --source-maps/out-files/lib/foo.js b/test/core/fixtures/bin/babel/dir --out-dir --source-maps/out-files/lib/foo.js new file mode 100644 index 0000000000..7a5ff48137 --- /dev/null +++ b/test/core/fixtures/bin/babel/dir --out-dir --source-maps/out-files/lib/foo.js @@ -0,0 +1,6 @@ +"use strict"; + +arr.map(function (x) { + return x * MULTIPLIER; +}); +//# sourceMappingURL=foo.js.map diff --git a/test/core/fixtures/bin/babel/dir --out-dir --source-maps/out-files/lib/foo.js.map b/test/core/fixtures/bin/babel/dir --out-dir --source-maps/out-files/lib/foo.js.map new file mode 100644 index 0000000000..77300ca29a --- /dev/null +++ b/test/core/fixtures/bin/babel/dir --out-dir --source-maps/out-files/lib/foo.js.map @@ -0,0 +1 @@ +{"version":3,"sources":["../src/foo.js"],"names":[],"mappings":";;AAAA,GAAG,CAAC,GAAG,CAAC,UAAA,CAAC;SAAI,CAAC,GAAG,UAAU;CAAA,CAAC,CAAC","file":"foo.js","sourcesContent":["arr.map(x => x * MULTIPLIER);"]} diff --git a/test/core/fixtures/bin/babel/dir --out-dir/out-files/lib/bar/bar.js b/test/core/fixtures/bin/babel/dir --out-dir/out-files/lib/bar/bar.js new file mode 100644 index 0000000000..7c09ea8b39 --- /dev/null +++ b/test/core/fixtures/bin/babel/dir --out-dir/out-files/lib/bar/bar.js @@ -0,0 +1,7 @@ +"use strict"; + +function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } + +var Test = function Test() { + _classCallCheck(this, Test); +}; diff --git a/test/core/fixtures/bin/babel/dir --out-dir/out-files/lib/foo.js b/test/core/fixtures/bin/babel/dir --out-dir/out-files/lib/foo.js new file mode 100644 index 0000000000..ae4557e57b --- /dev/null +++ b/test/core/fixtures/bin/babel/dir --out-dir/out-files/lib/foo.js @@ -0,0 +1,5 @@ +"use strict"; + +arr.map(function (x) { + return x * MULTIPLIER; +});