diff --git a/src/compiler/transformers/classFields.ts b/src/compiler/transformers/classFields.ts index 01e3d7c7896a8..69fa41b207187 100644 --- a/src/compiler/transformers/classFields.ts +++ b/src/compiler/transformers/classFields.ts @@ -579,7 +579,7 @@ namespace ts { } function isPropertyDeclarationThatRequiresConstructorStatement(member: ClassElement): member is PropertyDeclaration { - if (!isPropertyDeclaration(member) || hasStaticModifier(member)) { + if (!isPropertyDeclaration(member) || hasStaticModifier(member) || hasSyntacticModifier(getOriginalNode(member), ModifierFlags.Abstract)) { return false; } if (context.getCompilerOptions().useDefineForClassFields) { @@ -779,6 +779,9 @@ namespace ts { } const propertyOriginalNode = getOriginalNode(property); + if (hasSyntacticModifier(propertyOriginalNode, ModifierFlags.Abstract)) { + return undefined; + } const initializer = property.initializer || emitAssignment ? visitNode(property.initializer, visitor, isExpression) ?? factory.createVoidZero() : isParameterPropertyDeclaration(propertyOriginalNode, propertyOriginalNode.parent) && isIdentifier(propertyName) ? propertyName : factory.createVoidZero(); diff --git a/src/compiler/transformers/ts.ts b/src/compiler/transformers/ts.ts index 3e2e789259915..98fff3625ab06 100644 --- a/src/compiler/transformers/ts.ts +++ b/src/compiler/transformers/ts.ts @@ -1900,7 +1900,7 @@ namespace ts { } function visitPropertyDeclaration(node: PropertyDeclaration) { - if (node.flags & NodeFlags.Ambient) { + if (node.flags & NodeFlags.Ambient || hasSyntacticModifier(node, ModifierFlags.Abstract)) { return undefined; } const updated = factory.updatePropertyDeclaration( diff --git a/tests/baselines/reference/abstractProperty(target=es2015).js b/tests/baselines/reference/abstractProperty(target=es2015).js new file mode 100644 index 0000000000000..37eb53fd7cb0c --- /dev/null +++ b/tests/baselines/reference/abstractProperty(target=es2015).js @@ -0,0 +1,38 @@ +//// [abstractProperty.ts] +abstract class A { + protected abstract x: string; + public foo() { + console.log(this.x); + } +} + +class B extends A { + protected x = 'B.x'; +} + +class C extends A { + protected get x() { return 'C.x' }; +} + + +//// [abstractProperty.js] +class A { + foo() { + console.log(this.x); + } +} +class B extends A { + constructor() { + super(...arguments); + Object.defineProperty(this, "x", { + enumerable: true, + configurable: true, + writable: true, + value: 'B.x' + }); + } +} +class C extends A { + get x() { return 'C.x'; } + ; +} diff --git a/tests/baselines/reference/abstractProperty(target=es2015).symbols b/tests/baselines/reference/abstractProperty(target=es2015).symbols new file mode 100644 index 0000000000000..1f2f0b97570ac --- /dev/null +++ b/tests/baselines/reference/abstractProperty(target=es2015).symbols @@ -0,0 +1,36 @@ +=== tests/cases/conformance/classes/propertyMemberDeclarations/abstractProperty.ts === +abstract class A { +>A : Symbol(A, Decl(abstractProperty.ts, 0, 0)) + + protected abstract x: string; +>x : Symbol(A.x, Decl(abstractProperty.ts, 0, 18)) + + public foo() { +>foo : Symbol(A.foo, Decl(abstractProperty.ts, 1, 33)) + + console.log(this.x); +>console.log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --)) +>console : Symbol(console, Decl(lib.dom.d.ts, --, --)) +>log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --)) +>this.x : Symbol(A.x, Decl(abstractProperty.ts, 0, 18)) +>this : Symbol(A, Decl(abstractProperty.ts, 0, 0)) +>x : Symbol(A.x, Decl(abstractProperty.ts, 0, 18)) + } +} + +class B extends A { +>B : Symbol(B, Decl(abstractProperty.ts, 5, 1)) +>A : Symbol(A, Decl(abstractProperty.ts, 0, 0)) + + protected x = 'B.x'; +>x : Symbol(B.x, Decl(abstractProperty.ts, 7, 19)) +} + +class C extends A { +>C : Symbol(C, Decl(abstractProperty.ts, 9, 1)) +>A : Symbol(A, Decl(abstractProperty.ts, 0, 0)) + + protected get x() { return 'C.x' }; +>x : Symbol(C.x, Decl(abstractProperty.ts, 11, 19)) +} + diff --git a/tests/baselines/reference/abstractProperty(target=es2015).types b/tests/baselines/reference/abstractProperty(target=es2015).types new file mode 100644 index 0000000000000..557c5833185dc --- /dev/null +++ b/tests/baselines/reference/abstractProperty(target=es2015).types @@ -0,0 +1,39 @@ +=== tests/cases/conformance/classes/propertyMemberDeclarations/abstractProperty.ts === +abstract class A { +>A : A + + protected abstract x: string; +>x : string + + public foo() { +>foo : () => void + + console.log(this.x); +>console.log(this.x) : void +>console.log : (...data: any[]) => void +>console : Console +>log : (...data: any[]) => void +>this.x : string +>this : this +>x : string + } +} + +class B extends A { +>B : B +>A : A + + protected x = 'B.x'; +>x : string +>'B.x' : "B.x" +} + +class C extends A { +>C : C +>A : A + + protected get x() { return 'C.x' }; +>x : string +>'C.x' : "C.x" +} + diff --git a/tests/baselines/reference/abstractProperty(target=esnext).js b/tests/baselines/reference/abstractProperty(target=esnext).js new file mode 100644 index 0000000000000..dd2f6822080d9 --- /dev/null +++ b/tests/baselines/reference/abstractProperty(target=esnext).js @@ -0,0 +1,30 @@ +//// [abstractProperty.ts] +abstract class A { + protected abstract x: string; + public foo() { + console.log(this.x); + } +} + +class B extends A { + protected x = 'B.x'; +} + +class C extends A { + protected get x() { return 'C.x' }; +} + + +//// [abstractProperty.js] +class A { + foo() { + console.log(this.x); + } +} +class B extends A { + x = 'B.x'; +} +class C extends A { + get x() { return 'C.x'; } + ; +} diff --git a/tests/baselines/reference/abstractProperty(target=esnext).symbols b/tests/baselines/reference/abstractProperty(target=esnext).symbols new file mode 100644 index 0000000000000..1f2f0b97570ac --- /dev/null +++ b/tests/baselines/reference/abstractProperty(target=esnext).symbols @@ -0,0 +1,36 @@ +=== tests/cases/conformance/classes/propertyMemberDeclarations/abstractProperty.ts === +abstract class A { +>A : Symbol(A, Decl(abstractProperty.ts, 0, 0)) + + protected abstract x: string; +>x : Symbol(A.x, Decl(abstractProperty.ts, 0, 18)) + + public foo() { +>foo : Symbol(A.foo, Decl(abstractProperty.ts, 1, 33)) + + console.log(this.x); +>console.log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --)) +>console : Symbol(console, Decl(lib.dom.d.ts, --, --)) +>log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --)) +>this.x : Symbol(A.x, Decl(abstractProperty.ts, 0, 18)) +>this : Symbol(A, Decl(abstractProperty.ts, 0, 0)) +>x : Symbol(A.x, Decl(abstractProperty.ts, 0, 18)) + } +} + +class B extends A { +>B : Symbol(B, Decl(abstractProperty.ts, 5, 1)) +>A : Symbol(A, Decl(abstractProperty.ts, 0, 0)) + + protected x = 'B.x'; +>x : Symbol(B.x, Decl(abstractProperty.ts, 7, 19)) +} + +class C extends A { +>C : Symbol(C, Decl(abstractProperty.ts, 9, 1)) +>A : Symbol(A, Decl(abstractProperty.ts, 0, 0)) + + protected get x() { return 'C.x' }; +>x : Symbol(C.x, Decl(abstractProperty.ts, 11, 19)) +} + diff --git a/tests/baselines/reference/abstractProperty(target=esnext).types b/tests/baselines/reference/abstractProperty(target=esnext).types new file mode 100644 index 0000000000000..557c5833185dc --- /dev/null +++ b/tests/baselines/reference/abstractProperty(target=esnext).types @@ -0,0 +1,39 @@ +=== tests/cases/conformance/classes/propertyMemberDeclarations/abstractProperty.ts === +abstract class A { +>A : A + + protected abstract x: string; +>x : string + + public foo() { +>foo : () => void + + console.log(this.x); +>console.log(this.x) : void +>console.log : (...data: any[]) => void +>console : Console +>log : (...data: any[]) => void +>this.x : string +>this : this +>x : string + } +} + +class B extends A { +>B : B +>A : A + + protected x = 'B.x'; +>x : string +>'B.x' : "B.x" +} + +class C extends A { +>C : C +>A : A + + protected get x() { return 'C.x' }; +>x : string +>'C.x' : "C.x" +} + diff --git a/tests/baselines/reference/accessorsOverrideProperty7.js b/tests/baselines/reference/accessorsOverrideProperty7.js index 206f8611b7fa1..7264bf45e5fc8 100644 --- a/tests/baselines/reference/accessorsOverrideProperty7.js +++ b/tests/baselines/reference/accessorsOverrideProperty7.js @@ -23,12 +23,6 @@ var __extends = (this && this.__extends) || (function () { })(); var A = /** @class */ (function () { function A() { - Object.defineProperty(this, "p", { - enumerable: true, - configurable: true, - writable: true, - value: 'yep' - }); } return A; }()); diff --git a/tests/baselines/reference/privateNamesIncompatibleModifiers.js b/tests/baselines/reference/privateNamesIncompatibleModifiers.js index 48695a4604fbc..f6e731d371d88 100644 --- a/tests/baselines/reference/privateNamesIncompatibleModifiers.js +++ b/tests/baselines/reference/privateNamesIncompatibleModifiers.js @@ -14,7 +14,7 @@ abstract class B { //// [privateNamesIncompatibleModifiers.js] "use strict"; -var _foo, _bar, _baz, _qux, _quux; +var _foo, _bar, _baz, _qux; class A { constructor() { _foo.set(this, 3); // Error @@ -25,8 +25,4 @@ class A { } _foo = new WeakMap(), _bar = new WeakMap(), _baz = new WeakMap(), _qux = new WeakMap(); class B { - constructor() { - _quux.set(this, 3); // Error - } } -_quux = new WeakMap(); diff --git a/tests/cases/conformance/classes/propertyMemberDeclarations/abstractProperty.ts b/tests/cases/conformance/classes/propertyMemberDeclarations/abstractProperty.ts new file mode 100644 index 0000000000000..5f7266c0ea70d --- /dev/null +++ b/tests/cases/conformance/classes/propertyMemberDeclarations/abstractProperty.ts @@ -0,0 +1,16 @@ +// @target: es2015,esnext +// @useDefineForClassFields: true +abstract class A { + protected abstract x: string; + public foo() { + console.log(this.x); + } +} + +class B extends A { + protected x = 'B.x'; +} + +class C extends A { + protected get x() { return 'C.x' }; +}