mike-lischke / antlr4ng

Next Generation TypeScript runtime for ANTLR4
Other
85 stars 15 forks source link

ReferenceError: Super constructor may only be called once #30

Closed DuShuYuan closed 8 months ago

DuShuYuan commented 8 months ago
"antlr4": "4.13.1",
"antlr4-c3": "3.3.5",
"antlr4ng": "2.0.10",

The location of the error: 1706758290883

I guess the corresponding code position should be: image

I see a similar code in antlr4-c3 as well.

It's mine tsconfig.json:

{
  "compileOnSave": false,
  "compilerOptions": {
    "baseUrl": "./",
    "outDir": "./dist/out-tsc",
    "incremental": true,
    "forceConsistentCasingInFileNames": true,
    "noFallthroughCasesInSwitch": true,
    "sourceMap": true,
    "declaration": false,
    "downlevelIteration": true,
    "experimentalDecorators": true,
    "moduleResolution": "node",
    "importHelpers": true,
    "esModuleInterop": true,
    "allowSyntheticDefaultImports": true,
    "target": "es2015",
    "module": "ESNext",
    "lib": [
      "DOM",
      "ESNext"
    ]
  },
  "angularCompilerOptions": {
    "enableI18nLegacyMessageIdFormat": false,
    "strictInjectionParameters": true,
    "strictInputAccessModifiers": true,
    "strictTemplates": true
  }
}

tsconfig.worker.json:

{
  "extends": "./tsconfig.json",
  "compilerOptions": {
    "outDir": "./out-tsc/worker",
    "lib": [
      "ES2021",
      "webworker"
    ],
    "types": ["node"]
  },
  "include": [
    "src/**/*.worker.ts"
  ]
}

I think it can be solved this way:

class Parent {
  constructor(arg = null) {
    // ...
  }
}

class Child extends Parent {
  constructor(e) {
    super(e || someDefaultValue); // e is used if it exists, otherwise the default value is used
  }
}
mike-lischke commented 8 months ago

This is a bogus error. The super constructor is in fact only called once. Sometimes you cannot easily define parameters to inherited methods using the nullish coalescing operator or similar constructs, particularly in method overload situations.

DuShuYuan commented 8 months ago

This is a bogus error. The super constructor is in fact only called once. Sometimes you cannot easily define parameters to inherited methods using the nullish coalescing operator or similar constructs, particularly in method overload situations.

Please how can I fix this error, my project is not running now

mike-lischke commented 8 months ago

I can try to debug that if you give me a complete example (as a repo or full code here), which reproduces the issue. As I wrote above, IMO it's not an error.

DuShuYuan commented 8 months ago

Thanks, I've solved it, I modified the constructor. But I don't understand why a different constructor is called depending on the argument, why not just call super(...).

image image

mike-lischke commented 8 months ago

Strange that this is accepted by your tsc. It should not! Keep in mind this is a method overloading situation. The two overloads either allow no parameters at all or exactly two. If you use invokingStateNumber directly you violate this requirement, because this parameter can be unassigned, leading to the situation that only one parameter is given.

Are you directly transpiling with tsc? Do you have an automatic syntax checker in your project (like VS Code has)?

DuShuYuan commented 8 months ago

Cause: Modify "target": "ES2021" in tsconfig.json

image

DuShuYuan commented 8 months ago

Strange that this is accepted by your tsc. It should not! Keep in mind this is a method overloading situation. The two overloads either allow no parameters at all or exactly two. If you use invokingStateNumber directly you violate this requirement, because this parameter can be unassigned, leading to the situation that only one parameter is given.

Are you directly transpiling with tsc? Do you have an automatic syntax checker in your project (like VS Code has)?

Thanks, I see. But my project has to support ES2021, or even ES2015, and it seems that this syntax is not available anymore

mike-lischke commented 8 months ago

You can always bundle your code to support older ES versions. The bundler will then generate wrappers or polyfills from unsupported code.

nashbridges commented 8 months ago

I think we see the same error. The weird thing, it happens only in a production build, where the code is transpiled by Webpack.

Here's the excerpt of the transpiled code (which it seems corresponds to InterpreterRuleContext:

function PV(e, t) {
  if (t.has(e)) throw new TypeError("Cannot initialize the same private elements twice on an object")
}

function IV(e, t, n) {
  PV(e, t), t.set(e, n)
}

function LV(e, t, n) {
  return function(e, t, n) {
    if (t.set) t.set.call(e, n);
    else {
      if (!t.writable) throw new TypeError("attempted to set read only private field");
      t.value = n
    }
  }

  Xre = (Iee = new WeakMap, class extends jte {
    constructor(e, t, n) {
      void 0 !== n ? (super(t, n), IV(this, Iee, {
        writable: !0,
        value: void 0
      })) : (super(), super(t, n), IV(this, Iee, {
        writable: !0,
        value: void 0
      })), LV(this, Iee, e)
    }
    get ruleIndex() {
      return kV(this, Iee)
    }
  })

Notice the super(), super(t, n)

We use the ESM version of the library, which is distributed as

var Pt = class extends q {
  #e;
  constructor(e, t, r) {
    r !== void 0 ? super(t, r) : super(), this.#e = e
  }
  get ruleIndex() {
    return this.#e
  }
}
mike-lischke commented 8 months ago

Oh, so it's a webpack problem actually? Thanks for the analysis @nashbridges. I guess I need to find a different way then to implement this.

nashbridges commented 8 months ago

Right. Sorry for being confusing. This is either webpack or, more likely, babel's plugin issue. I haven't yet checked if upgrading them would help. Another potential fix is to bump up browserlist, so that private properties would not have to be transpiled, but that's not an option for many.

nashbridges commented 8 months ago

Another potential fix is to bump up browserlist

I can confirm that setting "last 2 years" in the browserlist makes the issue disappear.

mike-lischke commented 8 months ago

@nashbridges I'd like to use the suggested values from the NPM docs. Would that also work?

nashbridges commented 8 months ago

Yes, setting "defaults and fully supports es6-module" also helps with the issue.