From 960151c8766c42e12c2e45d3f9c032aea665b954 Mon Sep 17 00:00:00 2001 From: Oliver Don Date: Sun, 27 Aug 2017 02:15:45 +0100 Subject: [PATCH] Fix #4840: Alias class prototype for methods in loose mode (#5560) * Fix #4840: Alias class prototype for methods in loose mode * Cleanup --- .../src/loose.js | 19 ++++++++++++++++++- .../with-constructor/expected.js | 4 +++- .../loose/constructor-order/expected.js | 4 +++- .../fixtures/loose/literal-key/expected.js | 6 ++++-- .../method-return-type-annotation/expected.js | 6 ++++-- .../loose/method-reuse-prototype/actual.js | 5 +++++ .../loose/method-reuse-prototype/expected.js | 13 +++++++++++++ .../fixtures/regression/T6755/expected.js | 6 ++++-- .../expected.js | 6 ++++-- .../expected.js | 6 ++++-- 10 files changed, 62 insertions(+), 13 deletions(-) create mode 100644 packages/babel-plugin-transform-es2015-classes/test/fixtures/loose/method-reuse-prototype/actual.js create mode 100644 packages/babel-plugin-transform-es2015-classes/test/fixtures/loose/method-reuse-prototype/expected.js diff --git a/packages/babel-plugin-transform-es2015-classes/src/loose.js b/packages/babel-plugin-transform-es2015-classes/src/loose.js index 953a8a2322..ea6fd114b8 100644 --- a/packages/babel-plugin-transform-es2015-classes/src/loose.js +++ b/packages/babel-plugin-transform-es2015-classes/src/loose.js @@ -5,16 +5,33 @@ import * as t from "babel-types"; export default class LooseClassTransformer extends VanillaTransformer { constructor() { super(...arguments); + this._protoAlias = null; this.isLoose = true; } + _insertProtoAliasOnce() { + if (!this._protoAlias) { + this._protoAlias = this.scope.generateUidIdentifier("proto"); + const classProto = t.memberExpression( + this.classRef, + t.identifier("prototype"), + ); + const protoDeclaration = t.variableDeclaration("var", [ + t.variableDeclarator(this._protoAlias, classProto), + ]); + + this.body.push(protoDeclaration); + } + } + _processMethod(node, scope) { if (!node.decorators) { // use assignments instead of define properties for loose classes let classRef = this.classRef; if (!node.static) { - classRef = t.memberExpression(classRef, t.identifier("prototype")); + this._insertProtoAliasOnce(); + classRef = this._protoAlias; } const methodName = t.memberExpression( classRef, diff --git a/packages/babel-plugin-transform-es2015-classes/test/fixtures/loose-classCallCheck/with-constructor/expected.js b/packages/babel-plugin-transform-es2015-classes/test/fixtures/loose-classCallCheck/with-constructor/expected.js index db67764aee..a69cda83f5 100644 --- a/packages/babel-plugin-transform-es2015-classes/test/fixtures/loose-classCallCheck/with-constructor/expected.js +++ b/packages/babel-plugin-transform-es2015-classes/test/fixtures/loose-classCallCheck/with-constructor/expected.js @@ -5,7 +5,9 @@ let A = function A() { let B = function () { function B() {} - B.prototype.b = function b() { + var _proto = B.prototype; + + _proto.b = function b() { console.log('b'); }; diff --git a/packages/babel-plugin-transform-es2015-classes/test/fixtures/loose/constructor-order/expected.js b/packages/babel-plugin-transform-es2015-classes/test/fixtures/loose/constructor-order/expected.js index be7df63f56..cab5ecca60 100644 --- a/packages/babel-plugin-transform-es2015-classes/test/fixtures/loose/constructor-order/expected.js +++ b/packages/babel-plugin-transform-es2015-classes/test/fixtures/loose/constructor-order/expected.js @@ -1,5 +1,7 @@ var x = function () { - x.prototype.f = function f() { + var _proto = x.prototype; + + _proto.f = function f() { 1; 2; 3; diff --git a/packages/babel-plugin-transform-es2015-classes/test/fixtures/loose/literal-key/expected.js b/packages/babel-plugin-transform-es2015-classes/test/fixtures/loose/literal-key/expected.js index 126cb3ecde..1bb06b9c28 100644 --- a/packages/babel-plugin-transform-es2015-classes/test/fixtures/loose/literal-key/expected.js +++ b/packages/babel-plugin-transform-es2015-classes/test/fixtures/loose/literal-key/expected.js @@ -1,7 +1,9 @@ var Foo = function () { function Foo() {} - Foo.prototype["bar"] = function bar() {}; + var _proto = Foo.prototype; + + _proto["bar"] = function bar() {}; return Foo; -}(); +}(); \ No newline at end of file diff --git a/packages/babel-plugin-transform-es2015-classes/test/fixtures/loose/method-return-type-annotation/expected.js b/packages/babel-plugin-transform-es2015-classes/test/fixtures/loose/method-return-type-annotation/expected.js index 513dccbcdf..9502739999 100644 --- a/packages/babel-plugin-transform-es2015-classes/test/fixtures/loose/method-return-type-annotation/expected.js +++ b/packages/babel-plugin-transform-es2015-classes/test/fixtures/loose/method-return-type-annotation/expected.js @@ -2,9 +2,11 @@ var C = function () { function C() {} - C.prototype.m = function m(x: number): string { + var _proto = C.prototype; + + _proto.m = function m(x: number): string { return 'a'; }; return C; -}(); +}(); \ No newline at end of file diff --git a/packages/babel-plugin-transform-es2015-classes/test/fixtures/loose/method-reuse-prototype/actual.js b/packages/babel-plugin-transform-es2015-classes/test/fixtures/loose/method-reuse-prototype/actual.js new file mode 100644 index 0000000000..1c08a36449 --- /dev/null +++ b/packages/babel-plugin-transform-es2015-classes/test/fixtures/loose/method-reuse-prototype/actual.js @@ -0,0 +1,5 @@ +class Test { + a() {} + static b() {} + c() {} +} diff --git a/packages/babel-plugin-transform-es2015-classes/test/fixtures/loose/method-reuse-prototype/expected.js b/packages/babel-plugin-transform-es2015-classes/test/fixtures/loose/method-reuse-prototype/expected.js new file mode 100644 index 0000000000..859c173d15 --- /dev/null +++ b/packages/babel-plugin-transform-es2015-classes/test/fixtures/loose/method-reuse-prototype/expected.js @@ -0,0 +1,13 @@ +var Test = function () { + function Test() {} + + var _proto = Test.prototype; + + _proto.a = function a() {}; + + Test.b = function b() {}; + + _proto.c = function c() {}; + + return Test; +}(); \ No newline at end of file diff --git a/packages/babel-plugin-transform-es2015-classes/test/fixtures/regression/T6755/expected.js b/packages/babel-plugin-transform-es2015-classes/test/fixtures/regression/T6755/expected.js index af82cae559..6cc0c39120 100644 --- a/packages/babel-plugin-transform-es2015-classes/test/fixtures/regression/T6755/expected.js +++ b/packages/babel-plugin-transform-es2015-classes/test/fixtures/regression/T6755/expected.js @@ -3,11 +3,13 @@ var Example = function () { function Example() {} - Example.prototype.test1 = async function test1() { + var _proto = Example.prototype; + + _proto.test1 = async function test1() { await Promise.resolve(2); }; - Example.prototype.test2 = + _proto.test2 = /*#__PURE__*/ regeneratorRuntime.mark(function test2() { return regeneratorRuntime.wrap(function test2$(_context) { diff --git a/packages/babel-plugin-transform-flow-comments/test/fixtures/flow-comments/transformed-class-method-loose-return-type-annotation/expected.js b/packages/babel-plugin-transform-flow-comments/test/fixtures/flow-comments/transformed-class-method-loose-return-type-annotation/expected.js index af26da01bc..0c3f51c0a9 100644 --- a/packages/babel-plugin-transform-flow-comments/test/fixtures/flow-comments/transformed-class-method-loose-return-type-annotation/expected.js +++ b/packages/babel-plugin-transform-flow-comments/test/fixtures/flow-comments/transformed-class-method-loose-return-type-annotation/expected.js @@ -4,7 +4,9 @@ var C = function () { function C() {} - C.prototype.m = function m(x + var _proto = C.prototype; + + _proto.m = function m(x /*: number*/ ) /*: string*/ @@ -13,4 +15,4 @@ var C = function () { }; return C; -}(); +}(); \ No newline at end of file diff --git a/packages/babel-plugin-transform-flow-strip-types/test/fixtures/regression/transformed-class-method-loose-return-type-annotation/expected.js b/packages/babel-plugin-transform-flow-strip-types/test/fixtures/regression/transformed-class-method-loose-return-type-annotation/expected.js index d3f42768b7..abf414bec3 100644 --- a/packages/babel-plugin-transform-flow-strip-types/test/fixtures/regression/transformed-class-method-loose-return-type-annotation/expected.js +++ b/packages/babel-plugin-transform-flow-strip-types/test/fixtures/regression/transformed-class-method-loose-return-type-annotation/expected.js @@ -3,9 +3,11 @@ var C = function () { function C() {} - C.prototype.m = function m(x) { + var _proto = C.prototype; + + _proto.m = function m(x) { return 'a'; }; return C; -}(); +}(); \ No newline at end of file