From aaf48aa3b17a5c20c472a5f8e23dbfe6f0df4219 Mon Sep 17 00:00:00 2001 From: Tan Li Hau Date: Mon, 27 May 2019 01:55:34 +0800 Subject: [PATCH] fix unshiftContainer and insertBefore --- .../src/misc.js | 13 +++++-- .../nested-class/super-call-in-key/output.js | 5 +-- .../super-property-in-key/output.js | 5 +-- .../fixtures/public-loose/computed/output.js | 35 ++++++++++++------- .../public-loose/instance-computed/output.js | 4 ++- .../test/fixtures/public/computed/output.js | 35 ++++++++++++------- .../public/instance-computed/output.js | 4 ++- .../test/fixtures/regression/7371/output.js | 4 ++- .../test/fixtures/regression/8882/exec.js | 23 ++++++++++++ .../test/fixtures/regression/8882/input.js | 13 +++++++ .../fixtures/regression/8882/options.json | 3 ++ .../test/fixtures/regression/8882/output.js | 23 ++++++++++++ .../decorator-interop/output.js | 4 ++- .../static-property-tdz/edgest-case/output.js | 4 ++- .../static-property-tdz/general/output.js | 4 ++- .../static-property-tdz/loose/output.js | 4 ++- .../babel-traverse/src/path/modification.js | 7 ++-- packages/babel-traverse/test/modification.js | 13 +++++++ 18 files changed, 160 insertions(+), 43 deletions(-) create mode 100644 packages/babel-plugin-proposal-class-properties/test/fixtures/regression/8882/exec.js create mode 100644 packages/babel-plugin-proposal-class-properties/test/fixtures/regression/8882/input.js create mode 100644 packages/babel-plugin-proposal-class-properties/test/fixtures/regression/8882/options.json create mode 100644 packages/babel-plugin-proposal-class-properties/test/fixtures/regression/8882/output.js diff --git a/packages/babel-helper-create-class-features-plugin/src/misc.js b/packages/babel-helper-create-class-features-plugin/src/misc.js index 2468167fe940..9a831dace2d1 100644 --- a/packages/babel-helper-create-class-features-plugin/src/misc.js +++ b/packages/babel-helper-create-class-features-plugin/src/misc.js @@ -85,6 +85,9 @@ export function injectInitialization(path, constructor, nodes, renamer) { export function extractComputedKeys(ref, path, computedPaths, file) { const declarations = []; + const nearestBlock = path.find( + parentPath => parentPath.isBlockStatement() || parentPath.isProgram(), + ); for (const computedPath of computedPaths) { computedPath.traverse(classFieldDefinitionEvaluationTDZVisitor, { classBinding: path.node.id && path.scope.getBinding(path.node.id.name), @@ -98,10 +101,14 @@ export function extractComputedKeys(ref, path, computedPaths, file) { const ident = path.scope.generateUidIdentifierBasedOnNode( computedNode.key, ); + nearestBlock.unshiftContainer( + "body", + t.variableDeclaration("let", [t.variableDeclarator(ident, null)]), + ); declarations.push( - t.variableDeclaration("var", [ - t.variableDeclarator(ident, computedNode.key), - ]), + t.expressionStatement( + t.assignmentExpression("=", t.cloneNode(ident), computedNode.key), + ), ); computedNode.key = t.cloneNode(ident); } diff --git a/packages/babel-plugin-proposal-class-properties/test/fixtures/nested-class/super-call-in-key/output.js b/packages/babel-plugin-proposal-class-properties/test/fixtures/nested-class/super-call-in-key/output.js index 2ded153f1e81..e8711f41073e 100644 --- a/packages/babel-plugin-proposal-class-properties/test/fixtures/nested-class/super-call-in-key/output.js +++ b/packages/babel-plugin-proposal-class-properties/test/fixtures/nested-class/super-call-in-key/output.js @@ -18,9 +18,10 @@ function (_Hello) { function Outer() { var _this; - babelHelpers.classCallCheck(this, Outer); + let _this2; - var _this2 = _this = babelHelpers.possibleConstructorReturn(this, babelHelpers.getPrototypeOf(Outer).call(this)); + babelHelpers.classCallCheck(this, Outer); + _this2 = _this = babelHelpers.possibleConstructorReturn(this, babelHelpers.getPrototypeOf(Outer).call(this)); let Inner = function Inner() { babelHelpers.classCallCheck(this, Inner); diff --git a/packages/babel-plugin-proposal-class-properties/test/fixtures/nested-class/super-property-in-key/output.js b/packages/babel-plugin-proposal-class-properties/test/fixtures/nested-class/super-property-in-key/output.js index 6df7880cd395..25e23eb68008 100644 --- a/packages/babel-plugin-proposal-class-properties/test/fixtures/nested-class/super-property-in-key/output.js +++ b/packages/babel-plugin-proposal-class-properties/test/fixtures/nested-class/super-property-in-key/output.js @@ -24,10 +24,11 @@ function (_Hello) { function Outer() { var _this; + let _babelHelpers$get$cal; + babelHelpers.classCallCheck(this, Outer); _this = babelHelpers.possibleConstructorReturn(this, babelHelpers.getPrototypeOf(Outer).call(this)); - - var _babelHelpers$get$cal = babelHelpers.get(babelHelpers.getPrototypeOf(Outer.prototype), "toString", babelHelpers.assertThisInitialized(_this)).call(babelHelpers.assertThisInitialized(_this)); + _babelHelpers$get$cal = babelHelpers.get(babelHelpers.getPrototypeOf(Outer.prototype), "toString", babelHelpers.assertThisInitialized(_this)).call(babelHelpers.assertThisInitialized(_this)); let Inner = function Inner() { babelHelpers.classCallCheck(this, Inner); diff --git a/packages/babel-plugin-proposal-class-properties/test/fixtures/public-loose/computed/output.js b/packages/babel-plugin-proposal-class-properties/test/fixtures/public-loose/computed/output.js index 0cd7c14b4559..bacb965768ac 100644 --- a/packages/babel-plugin-proposal-class-properties/test/fixtures/public-loose/computed/output.js +++ b/packages/babel-plugin-proposal-class-properties/test/fixtures/public-loose/computed/output.js @@ -1,24 +1,35 @@ -var foo = "foo"; +var _ref4; -var bar = () => {}; +var _baz; -var four = 4; +var _ref3; + +var _ref2; -var _one = one(); +var _computed2; -var _ref = 2 * four + seven; +var _computed; -var _undefined = undefined; +var _undefined; -var _computed = computed(); +var _ref; -var _computed2 = computed(); +var _one; -var _ref2 = "test" + one; +var foo = "foo"; + +var bar = () => {}; -var _ref3 = /regex/; -var _baz = baz; -var _ref4 = `template${expression}`; +var four = 4; +_one = one(); +_ref = 2 * four + seven; +_undefined = undefined; +_computed = computed(); +_computed2 = computed(); +_ref2 = "test" + one; +_ref3 = /regex/; +_baz = baz; +_ref4 = `template${expression}`; var MyClass = /*#__PURE__*/ diff --git a/packages/babel-plugin-proposal-class-properties/test/fixtures/public-loose/instance-computed/output.js b/packages/babel-plugin-proposal-class-properties/test/fixtures/public-loose/instance-computed/output.js index 0e98b482c741..c7e13f2d1b6e 100644 --- a/packages/babel-plugin-proposal-class-properties/test/fixtures/public-loose/instance-computed/output.js +++ b/packages/babel-plugin-proposal-class-properties/test/fixtures/public-loose/instance-computed/output.js @@ -1,5 +1,7 @@ function test(x) { - var _x = x; + var _x; + + _x = x; var F = function F() { "use strict"; diff --git a/packages/babel-plugin-proposal-class-properties/test/fixtures/public/computed/output.js b/packages/babel-plugin-proposal-class-properties/test/fixtures/public/computed/output.js index bc9a90b21252..a5137b75cf13 100644 --- a/packages/babel-plugin-proposal-class-properties/test/fixtures/public/computed/output.js +++ b/packages/babel-plugin-proposal-class-properties/test/fixtures/public/computed/output.js @@ -1,24 +1,35 @@ -var foo = "foo"; +var _ref4; -var bar = () => {}; +var _baz; -var four = 4; +var _ref3; + +var _ref2; -var _one = one(); +var _computed2; -var _ref = 2 * four + seven; +var _computed; -var _undefined = undefined; +var _undefined; -var _computed = computed(); +var _ref; -var _computed2 = computed(); +var _one; -var _ref2 = "test" + one; +var foo = "foo"; + +var bar = () => {}; -var _ref3 = /regex/; -var _baz = baz; -var _ref4 = `template${expression}`; +var four = 4; +_one = one(); +_ref = 2 * four + seven; +_undefined = undefined; +_computed = computed(); +_computed2 = computed(); +_ref2 = "test" + one; +_ref3 = /regex/; +_baz = baz; +_ref4 = `template${expression}`; var MyClass = /*#__PURE__*/ diff --git a/packages/babel-plugin-proposal-class-properties/test/fixtures/public/instance-computed/output.js b/packages/babel-plugin-proposal-class-properties/test/fixtures/public/instance-computed/output.js index 79bfad744af4..5a311f2ad9d4 100644 --- a/packages/babel-plugin-proposal-class-properties/test/fixtures/public/instance-computed/output.js +++ b/packages/babel-plugin-proposal-class-properties/test/fixtures/public/instance-computed/output.js @@ -1,5 +1,7 @@ function test(x) { - var _x = x; + var _x; + + _x = x; var F = function F() { "use strict"; diff --git a/packages/babel-plugin-proposal-class-properties/test/fixtures/regression/7371/output.js b/packages/babel-plugin-proposal-class-properties/test/fixtures/regression/7371/output.js index 5c6ac57eeba1..352c791bdb72 100644 --- a/packages/babel-plugin-proposal-class-properties/test/fixtures/regression/7371/output.js +++ b/packages/babel-plugin-proposal-class-properties/test/fixtures/regression/7371/output.js @@ -77,7 +77,9 @@ class ComputedField extends Obj { constructor() { var _temp3; - var _ref = (_temp3 = super(), babelHelpers.defineProperty(this, "field", 1), _temp3); + let _ref; + + _ref = (_temp3 = super(), babelHelpers.defineProperty(this, "field", 1), _temp3); class B extends Obj { constructor() { diff --git a/packages/babel-plugin-proposal-class-properties/test/fixtures/regression/8882/exec.js b/packages/babel-plugin-proposal-class-properties/test/fixtures/regression/8882/exec.js new file mode 100644 index 000000000000..a16b8048dcaf --- /dev/null +++ b/packages/babel-plugin-proposal-class-properties/test/fixtures/regression/8882/exec.js @@ -0,0 +1,23 @@ +const classes = []; +for (let i = 0; i <= 10; ++i) { + classes.push( + class A { + [i] = `computed field ${i}`; + static foo = `static field ${i}`; + #bar = `private field ${i}`; + getBar() { + return this.#bar; + } + } + ); +} + +for(let i=0; i<= 10; ++i) { + const clazz = classes[i]; + expect(clazz.foo).toBe('static field ' + i); + + const instance = new clazz(); + expect(Object.getOwnPropertyNames(instance)).toEqual([String(i)]) + expect(instance[i]).toBe('computed field ' + i); + expect(instance.getBar()).toBe('private field ' + i); +} \ No newline at end of file diff --git a/packages/babel-plugin-proposal-class-properties/test/fixtures/regression/8882/input.js b/packages/babel-plugin-proposal-class-properties/test/fixtures/regression/8882/input.js new file mode 100644 index 000000000000..f7ca46cc407d --- /dev/null +++ b/packages/babel-plugin-proposal-class-properties/test/fixtures/regression/8882/input.js @@ -0,0 +1,13 @@ +const classes = []; +for (let i = 0; i <= 10; ++i) { + classes.push( + class A { + [i] = `computed field ${i}`; + static foo = `static field ${i}`; + #bar = `private field ${i}`; + getBar() { + return this.#bar; + } + } + ); +} \ No newline at end of file diff --git a/packages/babel-plugin-proposal-class-properties/test/fixtures/regression/8882/options.json b/packages/babel-plugin-proposal-class-properties/test/fixtures/regression/8882/options.json new file mode 100644 index 000000000000..9d30185b9bff --- /dev/null +++ b/packages/babel-plugin-proposal-class-properties/test/fixtures/regression/8882/options.json @@ -0,0 +1,3 @@ +{ + "plugins": ["external-helpers", "proposal-class-properties"] +} diff --git a/packages/babel-plugin-proposal-class-properties/test/fixtures/regression/8882/output.js b/packages/babel-plugin-proposal-class-properties/test/fixtures/regression/8882/output.js new file mode 100644 index 000000000000..deac2db7fd23 --- /dev/null +++ b/packages/babel-plugin-proposal-class-properties/test/fixtures/regression/8882/output.js @@ -0,0 +1,23 @@ +const classes = []; + +for (let i = 0; i <= 10; ++i) { + var _class, _temp, _bar; + + let _i; + + classes.push((_temp = (_i = i, _class = class A { + constructor() { + babelHelpers.defineProperty(this, _i, `computed field ${i}`); + + _bar.set(this, { + writable: true, + value: `private field ${i}` + }); + } + + getBar() { + return babelHelpers.classPrivateFieldGet(this, _bar); + } + + }), _bar = new WeakMap(), babelHelpers.defineProperty(_class, "foo", `static field ${i}`), _temp)); +} diff --git a/packages/babel-plugin-proposal-class-properties/test/fixtures/static-property-tdz/decorator-interop/output.js b/packages/babel-plugin-proposal-class-properties/test/fixtures/static-property-tdz/decorator-interop/output.js index 8f3aff871cf0..8c68fe7dc126 100644 --- a/packages/babel-plugin-proposal-class-properties/test/fixtures/static-property-tdz/decorator-interop/output.js +++ b/packages/babel-plugin-proposal-class-properties/test/fixtures/static-property-tdz/decorator-interop/output.js @@ -1,4 +1,4 @@ -var _class, _descriptor, _Symbol$search, _temp; +var _class, _descriptor, _temp; function _initializerDefineProperty(target, property, descriptor, context) { if (!descriptor) return; Object.defineProperty(target, property, { enumerable: descriptor.enumerable, configurable: descriptor.configurable, writable: descriptor.writable, value: descriptor.initializer ? descriptor.initializer.call(context) : void 0 }); } @@ -8,6 +8,8 @@ function _defineProperties(target, props) { for (var i = 0; i < props.length; i+ function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; } +let _Symbol$search; + function _applyDecoratedDescriptor(target, property, decorators, descriptor, context) { var desc = {}; Object.keys(descriptor).forEach(function (key) { desc[key] = descriptor[key]; }); desc.enumerable = !!desc.enumerable; desc.configurable = !!desc.configurable; if ('value' in desc || desc.initializer) { desc.writable = true; } desc = decorators.slice().reverse().reduce(function (desc, decorator) { return decorator(target, property, desc) || desc; }, desc); if (context && desc.initializer !== void 0) { desc.value = desc.initializer ? desc.initializer.call(context) : void 0; desc.initializer = undefined; } if (desc.initializer === void 0) { Object.defineProperty(target, property, desc); desc = null; } return desc; } function _initializerWarningHelper(descriptor, context) { throw new Error('Decorating class property failed. Please ensure that ' + 'proposal-class-properties is enabled and set to use loose mode. ' + 'To use proposal-class-properties in spec mode with decorators, wait for ' + 'the next major version of decorators in stage 2.'); } diff --git a/packages/babel-plugin-proposal-class-properties/test/fixtures/static-property-tdz/edgest-case/output.js b/packages/babel-plugin-proposal-class-properties/test/fixtures/static-property-tdz/edgest-case/output.js index c3fc9ecd57e0..081e7168eb4a 100644 --- a/packages/babel-plugin-proposal-class-properties/test/fixtures/static-property-tdz/edgest-case/output.js +++ b/packages/babel-plugin-proposal-class-properties/test/fixtures/static-property-tdz/edgest-case/output.js @@ -2,9 +2,11 @@ function _classCallCheck(instance, Constructor) { if (!(instance instanceof Cons function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } +let _x$x; + function _classNameTDZError(name) { throw new Error("Class \"" + name + "\" cannot be referenced in computed property keys."); } -var _x$x = { +_x$x = { x: (_classNameTDZError("A"), A) || 0 }.x; diff --git a/packages/babel-plugin-proposal-class-properties/test/fixtures/static-property-tdz/general/output.js b/packages/babel-plugin-proposal-class-properties/test/fixtures/static-property-tdz/general/output.js index 21c823a89aae..f4412c3079f5 100644 --- a/packages/babel-plugin-proposal-class-properties/test/fixtures/static-property-tdz/general/output.js +++ b/packages/babel-plugin-proposal-class-properties/test/fixtures/static-property-tdz/general/output.js @@ -2,9 +2,11 @@ function _classCallCheck(instance, Constructor) { if (!(instance instanceof Cons function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } +let _ref; + function _classNameTDZError(name) { throw new Error("Class \"" + name + "\" cannot be referenced in computed property keys."); } -var _ref = (_classNameTDZError("C"), C) + 3; +_ref = (_classNameTDZError("C"), C) + 3; let C = function C() { "use strict"; diff --git a/packages/babel-plugin-proposal-class-properties/test/fixtures/static-property-tdz/loose/output.js b/packages/babel-plugin-proposal-class-properties/test/fixtures/static-property-tdz/loose/output.js index a6acc92159f9..9ab3df7368f7 100644 --- a/packages/babel-plugin-proposal-class-properties/test/fixtures/static-property-tdz/loose/output.js +++ b/packages/babel-plugin-proposal-class-properties/test/fixtures/static-property-tdz/loose/output.js @@ -1,6 +1,8 @@ +let _ref; + function _classNameTDZError(name) { throw new Error("Class \"" + name + "\" cannot be referenced in computed property keys."); } -var _ref = (_classNameTDZError("C"), C) + 3; +_ref = (_classNameTDZError("C"), C) + 3; class C {} diff --git a/packages/babel-traverse/src/path/modification.js b/packages/babel-traverse/src/path/modification.js index abd1890e993e..6039a94c6090 100644 --- a/packages/babel-traverse/src/path/modification.js +++ b/packages/babel-traverse/src/path/modification.js @@ -24,10 +24,7 @@ export function insertBefore(nodes) { ) { return parentPath.insertBefore(nodes); } else if ( - (this.isNodeType("Expression") && - this.listKey !== "params" && - this.listKey !== "arguments" && - !this.isJSXElement()) || + (this.isNodeType("Expression") && !this.isJSXElement()) || (parentPath.isForStatement() && this.key === "init") ) { if (this.node) nodes.push(this.node); @@ -221,7 +218,7 @@ export function unshiftContainer(listKey, nodes) { key: 0, }); - return path.insertBefore(nodes); + return path._containerInsertBefore(nodes); } export function pushContainer(listKey, nodes) { diff --git a/packages/babel-traverse/test/modification.js b/packages/babel-traverse/test/modification.js index 027b71945723..a4ccc90823ab 100644 --- a/packages/babel-traverse/test/modification.js +++ b/packages/babel-traverse/test/modification.js @@ -36,6 +36,19 @@ describe("modification", function() { expect(generateCode(rootPath)).toBe("function test(a) {\n b;\n}"); }); + + it("properly handles more than one arguments", function() { + const code = "foo(a, b);"; + const ast = parse(code); + traverse(ast, { + CallExpression: function(path) { + path.pushContainer("arguments", t.identifier("d")); + expect(generateCode(path)).toBe("foo(a, b, d);"); + path.pushContainer("arguments", t.stringLiteral("s")); + expect(generateCode(path)).toBe(`foo(a, b, d, "s");`); + }, + }); + }); }); describe("unshiftContainer", function() { it("unshifts identifier into params", function() {