question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Is there an option to not emit code for class fields that have no initializer

See original GitHub issue

We are suffering from a v8 performance issue. The following code(directly run on NodeJs, no babel) would get a very low performance:

class Vec3_104 {
	x = 0; y = 0; z = 0;
	constructor(x, y, z) { this.x = x; this.y = y; this.z = z; }
}

class Vec3_110 {
	x; y; z;
	constructor(x, y, z) { this.x = x; this.y = y; this.z = z; }
}

const Vec3 = Vec3_104;

const t1 = Date.now();
((dt) => {
    let _temp_vec3a = new Vec3(1, 2, 3);
    let _temp_vec3b = new Vec3(2, 3, 1);
    for (let i = 0; i < 1000000; i++) {
        _temp_vec3a.x = _temp_vec3a.x + _temp_vec3b.x * dt;
        _temp_vec3a.y = _temp_vec3a.y + _temp_vec3b.y * dt;
        _temp_vec3a.z = _temp_vec3a.z + _temp_vec3b.z * dt;
        _temp_vec3a.x = 1;
        _temp_vec3a.y = 1;
        _temp_vec3a.z = 1;
    }
})(Math.random());
const t2 = Date.now();
console.log(`Past: ${t2 - t1}ms`);

if I modify the code as const Vec3 = Vec3_110.

As in babel, use @babel/plugin-proposal-class-fields(loose: true) and @babel/preset-typescript. A class field with no initializer like:

class Vec3 { x;  constructor (x) { this.x = x; } }

will emit code like:

function Vec3 {
   /* ... */
   this.x = void 0; // According to spec, babel emit this,
   this.x = x;
};

It also suffers from the performance issue(Chrome, NodeJS).

So can babel have an option to solve this problem?

Issue Analytics

  • State:closed
  • Created 3 years ago
  • Comments:7 (4 by maintainers)

github_iconTop GitHub Comments

2reactions
nicolo-ribaudocommented, Mar 27, 2020

You are effectively aking for an option to ignore a language feature (i.e. class fields without an explicit initializer) because your style guide requires you to use that feature, but you don’t want to use that feature at runtime because of performance reasons.

It’s like if a style guide mandated the use of ===, but you need to use ==.

Anyway, I can propose a few alternatives:

  1. If you don’t want the class fields to be initialized to undefined, you can comment them out:

    class Vec3_110 {
      /* x; */
      /* y; */
      /* z; */
      constructor(x, y, z) { this.x = x; this.y = y; this.z = z; }
    }
    

    This will still make it clear for the maintainer which is the structure of the class, without making this “documentation” affect the runtime behavior.

  2. If you are using Flow or TypeScript, you can use the declare modifier. This is exactly the same as using a comment, but makes it possible to type-check the field:

    class Vec3_110 {
      declare x;
      declare y;
      declare z;
      constructor(x, y, z) { this.x = x; this.y = y; this.z = z; }
    }
    
  3. If you want to write “standard-like” class fields in your code, but you don’t want to make them affect the runtime behavior, you can write a custom plugin to remove them: https://astexplorer.net/#/gist/3c9364f6659100761c07ef36a9ee85c3/eea7156b032b6381d6f598c1477d212e608deb67

0reactions
nicolo-ribaudocommented, Mar 27, 2020

Why couldn’t the transpiler use a default value which is compatible to the type we declared instead of just undefined.

One of the reasons is that the spec defines them as initialised to undefined. This code should never throw:

new class A {
  x;
  constructor(x) {
    check(this);
    this.x = x;
  }
}

function check(obj) {
  if (obj.x !== undefined) throw new Error();
}

Also, a more “practical” reason is that from this code it’s impossible for us to know the type of x:

class A {
  x;
  constructor(x) { this.x = x; }
}
Read more comments on GitHub >

github_iconTop Results From Across the Web

Property '...' has no initializer and is not definitely assigned in ...
The simple way to fix this error in Angular applications is to disable --strictPropertyInitialization flag in typescript compiler options in ...
Read more >
Property 'xxx' has no initializer and is not definitely assigned in ...
When "strictPropertyInitialization" is not specified or set to true then rules with a label will generate code that produces an error with Typescript....
Read more >
Documentation - Classes - TypeScript
The strictPropertyInitialization setting controls whether class fields need to be initialized in the constructor. name : string; Property 'name' has no ...
Read more >
Class has no initializers | Apple Developer Forums
I have a simple class in a .swift file that will keep track of the user's info. ... me an error at line...
Read more >
@Data - Project Lombok
@Data is a convenient shortcut annotation that bundles the features of @ToString , @EqualsAndHashCode , @Getter / @Setter and @RequiredArgsConstructor together: ...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found