Skip to content

class property initializer of extended class is duplicated in nested extended class constructor #7371

@kentor

Description

@kentor

This is a bug report

With the @babel/plugin-proposal-class-properties plugin, it appears that property initializers get duplicated in the nested class' constructor when both classes are extended classes that call super.

Input Code

Minimum repro:

class A extends C {
  B;
  constructor() {
    super();
    this.B = class B extends C {
      constructor() {
        super();
      }
    };
  }
}

Babel/Babylon Configuration (.babelrc, package.json, cli command)

module.exports = {
  plugins: [
    ['@babel/plugin-proposal-class-properties', { loose: true }],
  ],
  presets: [
    ['@babel/preset-env', { targets: { node: 'current' } }],
  ],
};

Expected Behavior

class A extends C {
  constructor() {
    super();
    this.B = void 0;
    this.B = class B extends C {
      constructor() {
        super();
      }
    };
  }
}

Current Behavior

class A extends C {
  constructor() {
    super();
    this.B = void 0;
    this.B = class B extends C {
      constructor() {
        super();
        this.B = void 0; // THIS LINE SHOULDN'T BE HERE!
      }
    };
  }
}

example (same deal, but with B = 1;): https://babeljs.io/repl/#?babili=false&browsers=&build=&builtIns=false&code_lz=MYGwhgzhAECC0FMAeAXBA7AJjAwtA3gFDTQBC0AvNAIwDcx0wA9uhCgE4CuwKT7AFAEoCDEhE4AHBAMH0SJFAAsAlhAB05KqEgxyyNFlwj585qw7deM4yfnipMubYC-o6M6evnQA&debug=false&forceAllTransforms=false&shippedProposals=false&circleciRepo=&evaluate=false&fileSize=false&lineWrap=false&presets=stage-2&prettier=false&targets=&version=6.26.0&envVersion=

There is an extra this.B = void 0; which is problematic because it will make this.B = undefined if the inner class is instantiated at any point, overwriting this.B = class ....

Possible Solution

There's probably some logic that just naively inserts the initializer based on the constructor pattern without accounting for context?

Context

I am implementing some React components, where a nested component is defined during the parent's constructor call because it will need to read props from the parent. The reason why there's a property initializer that's set to undefined in the first place is for flow types.

Your Environment

software version(s)
Babel 7.0.0-beta.39
Babylon
node 8.9.0
npm 5.5.1
Operating System macos

Metadata

Metadata

Assignees

No one assigned

    Labels

    Spec: Class FieldsoutdatedA closed issue/PR that is archived due to age. Recommended to make a new issue

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions