Skip to content

Default parameters in constructors of nested JS classes cause invalid IR #4465

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
gzm0 opened this issue Apr 11, 2021 · 1 comment · Fixed by #4502
Closed

Default parameters in constructors of nested JS classes cause invalid IR #4465

gzm0 opened this issue Apr 11, 2021 · 1 comment · Fixed by #4502
Assignees
Labels
bug Confirmed bug. Needs to be fixed.
Milestone

Comments

@gzm0
Copy link
Contributor

gzm0 commented Apr 11, 2021

Repro:

package helloworld

import scala.scalajs.js
import js.annotation._

class B {
  class A(x: String = "") extends js.Object {  }
}

object HelloWorld {
  def main(args: Array[String]): Unit = {
    val b = new B
    new b.A()
  }
}

expected: links,
get:

Cannot access module for non-module helloworld.B$A$
[error]   exported to JavaScript with @JSExport

The problem is that the call-site and the definition site do not agree on whether the companion is a class or a module:

captures: superClass$: any, arg$outer: helloworld.B
js class helloworld.B$A extends scala.scalajs.js.Object (via superClass$) {
  val $outer: helloworld.B
  def "constructor"(...rest: any): any = {
    val prep0: java.lang.String = if ((rest[0] === (void 0))) {
      mod:helloworld.B$A$.$lessinit$greater$default$1;Ljava.lang.String()
    } else {
      rest[0].asInstanceOf[java.lang.String]
    };
    val outer: helloworld.B = arg$outer;
    val x: java.lang.String = prep0;
    super();
    if ((outer === null)) {
      throw mod:scala.scalajs.runtime.package$.unwrapJavaScriptException;Ljava.lang.Throwable;Ljava.lang.Object(null)
    } else {
      this.helloworld.B$A::$outer = outer
    };
    (void 0)
  }
  static def helloworld$B$A$$$outer;Lhelloworld.B$A;Lhelloworld.B{$outer}(this{this}: any): helloworld.B = {
    this.helloworld.B$A::$outer.asInstanceOf[helloworld.B]
  }
}
class helloworld.B$A$ extends java.lang.Object {
  def $lessinit$greater$default$1;Ljava.lang.String{<init>$default$1}(): java.lang.String = {
    ""
  }
  constructor def <init>;Lhelloworld.B;V(outer{$outer}: helloworld.B) {
    this.java.lang.Object::<init>;V()
  }
}
@gzm0 gzm0 added the bug Confirmed bug. Needs to be fixed. label Apr 11, 2021
@gzm0
Copy link
Contributor Author

gzm0 commented Apr 11, 2021

More specifically: The companion is of course a class (not a module) because it must be initialized with the outer pointer. It's simply the synthesized default getter that is wrong.

@gzm0 gzm0 self-assigned this Apr 11, 2021
@gzm0 gzm0 assigned gzm0 and unassigned gzm0 May 30, 2021
gzm0 added a commit to gzm0/scala-js that referenced this issue Jun 6, 2021
gzm0 added a commit to gzm0/scala-js that referenced this issue Jul 10, 2021
gzm0 added a commit to gzm0/scala-js that referenced this issue Jul 11, 2021
sjrd added a commit that referenced this issue Jul 11, 2021
Fix #4465: Properly call default param getters for nested JS ctors
@gzm0 gzm0 added this to the v1.7.0 milestone Jul 13, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Confirmed bug. Needs to be fixed.
Projects
None yet
Development

Successfully merging a pull request may close this issue.

1 participant