@@ -3562,40 +3562,48 @@ class JSCodeGen()(using genCtx: Context) {
3562
3562
* )
3563
3563
* }}}
3564
3564
*
3565
- * and eventually reach the back-end as
3565
+ * When the original `structural` value is already of a subtype of
3566
+ * `scala.reflect.Selectable`, there is no conversion involved. There could
3567
+ * also be any other arbitrary conversion, such as the deprecated bridge for
3568
+ * Scala 2's `import scala.language.reflectiveCalls`. In general, the shape
3569
+ * is therefore the following, for some `selectable: reflect.Selectable`:
3566
3570
*
3567
3571
* {{{
3568
- * reflectiveSelectable(structural) .selectDynamic("foo") // same as above
3569
- * reflectiveSelectable(structural) .applyDynamic("bar",
3570
- * wrapRefArray([ classOf[Int], classOf[String] : jl.Class ]
3572
+ * selectable .selectDynamic("foo")
3573
+ * selectable .applyDynamic("bar",
3574
+ * classOf[Int], classOf[String]
3571
3575
* )(
3572
- * genericWrapArray([ Int.box(6) , "hello" : Object ])
3576
+ * 6 , "hello"
3573
3577
* )
3574
3578
* }}}
3575
3579
*
3576
- * If we use the deprecated `import scala.language.reflectiveCalls`, the
3577
- * wrapper for the receiver `structural` are the following instead:
3580
+ * and eventually reaches the back-end as
3578
3581
*
3579
3582
* {{{
3580
- * reflectiveSelectableFromLangReflectiveCalls(structural)(
3581
- * using scala.languageFeature.reflectiveCalls)
3583
+ * selectable.selectDynamic("foo") // same as above
3584
+ * selectable.applyDynamic("bar",
3585
+ * wrapRefArray([ classOf[Int], classOf[String] : jl.Class ]
3586
+ * )(
3587
+ * genericWrapArray([ Int.box(6), "hello" : Object ])
3588
+ * )
3582
3589
* }}}
3583
3590
*
3584
- * (in which case we don't care about the contextual argument).
3585
- *
3586
3591
* In SJSIR, they must be encoded as follows:
3587
3592
*
3588
3593
* {{{
3589
- * structural .foo;R()
3590
- * structural .bar;I;Ljava.lang.String;R(
3594
+ * selectable.selectedValue;O() .foo;R()
3595
+ * selectable.selectedValue;O() .bar;I;Ljava.lang.String;R(
3591
3596
* Int.box(6).asInstanceOf[int],
3592
3597
* "hello".asInstanceOf[java.lang.String]
3593
3598
* )
3594
3599
* }}}
3595
3600
*
3601
+ * where `selectedValue;O()` is declared in `scala.reflect.Selectable` and
3602
+ * holds the actual instance on which to perform the reflective operations.
3603
+ * For the typical use case from the first snippet, it returns `structural`.
3604
+ *
3596
3605
* This means that we must deconstruct the elaborated calls to recover:
3597
3606
*
3598
- * - the original receiver `structural`
3599
3607
* - the method name as a compile-time string `foo` or `bar`
3600
3608
* - the `tp: Type`s that have been wrapped in `classOf[tp]`, as a
3601
3609
* compile-time List[Type], from which we'll derive `jstpe.Type`s for the
@@ -3607,26 +3615,10 @@ class JSCodeGen()(using genCtx: Context) {
3607
3615
*/
3608
3616
private def genReflectiveCall (tree : Apply , isSelectDynamic : Boolean ): js.Tree = {
3609
3617
implicit val pos = tree.span
3610
- val Apply (fun @ Select (receiver0 , _), args) = tree
3618
+ val Apply (fun @ Select (receiver , _), args) = tree
3611
3619
3612
- /* Extract the real receiver, which is the first argument to one of the
3613
- * implicit conversions scala.reflect.Selectable.reflectiveSelectable or
3614
- * scala.Selectable.reflectiveSelectableFromLangReflectiveCalls.
3615
- */
3616
- val receiver = receiver0 match {
3617
- case Apply (fun1, receiver :: _)
3618
- if fun1.symbol == jsdefn.ReflectSelectable_reflectiveSelectable ||
3619
- fun1.symbol == jsdefn.Selectable_reflectiveSelectableFromLangReflectiveCalls =>
3620
- genExpr(receiver)
3621
-
3622
- case _ =>
3623
- report.error(
3624
- " The receiver of Selectable.selectDynamic or Selectable.applyDynamic " +
3625
- " must be a call to the (implicit) method scala.reflect.Selectable.reflectiveSelectable. " +
3626
- " Other uses are not supported in Scala.js." ,
3627
- tree.sourcePos)
3628
- js.Undefined ()
3629
- }
3620
+ val selectedValueTree = js.Apply (js.ApplyFlags .empty, genExpr(receiver),
3621
+ js.MethodIdent (selectedValueMethodName), Nil )(jstpe.AnyType )
3630
3622
3631
3623
// Extract the method name as a String
3632
3624
val methodNameStr = args.head match {
@@ -3682,7 +3674,7 @@ class JSCodeGen()(using genCtx: Context) {
3682
3674
3683
3675
val methodName = MethodName .reflectiveProxy(methodNameStr, formalParamTypeRefs)
3684
3676
3685
- js.Apply (js.ApplyFlags .empty, receiver , js.MethodIdent (methodName), actualArgs)(jstpe.AnyType )
3677
+ js.Apply (js.ApplyFlags .empty, selectedValueTree , js.MethodIdent (methodName), actualArgs)(jstpe.AnyType )
3686
3678
}
3687
3679
3688
3680
/** Gen actual actual arguments to Scala method call.
@@ -4296,10 +4288,13 @@ object JSCodeGen {
4296
4288
private val NullPointerExceptionClass = ClassName (" java.lang.NullPointerException" )
4297
4289
private val JSObjectClassName = ClassName (" scala.scalajs.js.Object" )
4298
4290
4291
+ private val ObjectClassRef = jstpe.ClassRef (ir.Names .ObjectClass )
4292
+
4299
4293
private val newSimpleMethodName = SimpleMethodName (" new" )
4300
4294
4301
- private val ObjectArgConstructorName =
4302
- MethodName .constructor(List (jstpe.ClassRef (ir.Names .ObjectClass )))
4295
+ private val selectedValueMethodName = MethodName (" selectedValue" , Nil , ObjectClassRef )
4296
+
4297
+ private val ObjectArgConstructorName = MethodName .constructor(List (ObjectClassRef ))
4303
4298
4304
4299
private val thisOriginalName = OriginalName (" this" )
4305
4300
0 commit comments