@@ -791,9 +791,9 @@ class JSCodeGen()(using genCtx: Context) {
791791            toIRType(param.info), mutable =  false , rest =  false )
792792      }
793793
794-       /* if (primitives.isPrimitive(sym)) {
794+       if  (primitives.isPrimitive(sym)) {
795795        None 
796-       } else*/   if  (sym.is(Deferred )) {
796+       } else  if  (sym.is(Deferred )) {
797797        Some (js.MethodDef (js.MemberFlags .empty, methodName, originalName,
798798            jsParams, toIRType(patchedResultType(sym)), None )(
799799            OptimizerHints .empty, None ))
@@ -2815,9 +2815,181 @@ class JSCodeGen()(using genCtx: Context) {
28152815            js.ForIn (objVarDef.ref, keyVarIdent, NoOriginalName , {
28162816              js.JSFunctionApply (fVarDef.ref, List (keyVarRef))
28172817            }))
2818+ 
2819+       case  REFLECT_SELECTABLE_SELECTDYN  => 
2820+         //  scala.reflect.Selectable.selectDynamic
2821+         genReflectiveCall(tree, isSelectDynamic =  true )
2822+       case  REFLECT_SELECTABLE_APPLYDYN  => 
2823+         //  scala.reflect.Selectable.applyDynamic
2824+         genReflectiveCall(tree, isSelectDynamic =  false )
28182825    }
28192826  }
28202827
2828+   /**  Gen the SJSIR for a reflective call. 
2829+    * 
2830+    *  Reflective calls are calls to a structural type field or method that 
2831+    *  involve a reflective Selectable. They look like the following in source 
2832+    *  code: 
2833+    *  {{{ 
2834+    *  import scala.reflect.Selectable.reflectiveSelectable 
2835+    * 
2836+    *  type Structural = { 
2837+    *    val foo: Int 
2838+    *    def bar(x: Int, y: String): String 
2839+    *  } 
2840+    * 
2841+    *  val structural: Structural = new { 
2842+    *    val foo: Int = 5 
2843+    *    def bar(x: Int, y: String): String = x.toString + y 
2844+    *  } 
2845+    * 
2846+    *  structural.foo 
2847+    *  structural.bar(6, "hello") 
2848+    *  }}} 
2849+    * 
2850+    *  After expansion by the Scala 3 rules for structural member selections and 
2851+    *  calls, they look like 
2852+    * 
2853+    *  {{{ 
2854+    *  reflectiveSelectable(structural).selectDynamic("foo") 
2855+    *  reflectiveSelectable(structural).applyDynamic("bar", 
2856+    *    ClassTag(classOf[Int]), ClassTag(classOf[String]) 
2857+    *  )( 
2858+    *    6, "hello" 
2859+    *  ) 
2860+    *  }}} 
2861+    * 
2862+    *  and eventually reach the back-end as 
2863+    * 
2864+    *  {{{ 
2865+    *  reflectiveSelectable(structural).selectDynamic("foo") // same as above 
2866+    *  reflectiveSelectable(structural).applyDynamic("bar", 
2867+    *    wrapRefArray([ ClassTag(classOf[Int]), ClassTag(classOf[String]) : ClassTag ] 
2868+    *  )( 
2869+    *    genericWrapArray([ Int.box(6), "hello" : Object ]) 
2870+    *  ) 
2871+    *  }}} 
2872+    * 
2873+    *  If we use the deprecated `import scala.language.reflectiveCalls`, the 
2874+    *  wrapper for the receiver `structural` are the following instead: 
2875+    * 
2876+    *  {{{ 
2877+    *  reflectiveSelectableFromLangReflectiveCalls(structural)( 
2878+    *    using scala.languageFeature.reflectiveCalls) 
2879+    *  }}} 
2880+    * 
2881+    *  (in which case we don't care about the contextual argument). 
2882+    * 
2883+    *  In SJSIR, they must be encoded as follows: 
2884+    * 
2885+    *  {{{ 
2886+    *  structural.foo;R() 
2887+    *  structural.bar;I;Ljava.lang.String;R( 
2888+    *    Int.box(6).asInstanceOf[int], 
2889+    *    "hello".asInstanceOf[java.lang.String] 
2890+    *  ) 
2891+    *  }}} 
2892+    * 
2893+    *  This means that we must deconstruct the elaborated calls to recover: 
2894+    * 
2895+    *  - the original receiver `structural` 
2896+    *  - the method name as a compile-time string `foo` or `bar` 
2897+    *  - the `tp: Type`s that have been wrapped in `ClassTag(classOf[tp])`, as a 
2898+    *    compile-time List[Type], from which we'll derive `jstpe.Type`s for the 
2899+    *    `asInstanceOf`s and `jstpe.TypeRef`s for the `MethodName.reflectiveProxy` 
2900+    *  - the actual arguments as a compile-time `List[Tree]` 
2901+    * 
2902+    *  Virtually all of the code in `genReflectiveCall` deals with recovering 
2903+    *  those elements. Constructing the IR Tree is the easy part after that. 
2904+    */  
2905+   private  def  genReflectiveCall (tree : Apply , isSelectDynamic : Boolean ):  js.Tree  =  {
2906+     implicit  val  pos  =  tree.span
2907+     val  Apply (fun @  Select (receiver0, _), args) =  tree
2908+ 
2909+     /*  Extract the real receiver, which is the first argument to one of the
2910+      * implicit conversions scala.reflect.Selectable.reflectiveSelectable or 
2911+      * scala.Selectable.reflectiveSelectableFromLangReflectiveCalls. 
2912+      */  
2913+     val  receiver  =  receiver0 match  {
2914+       case  Apply (fun1, receiver ::  _)
2915+           if  fun1.symbol ==  jsdefn.ReflectSelectable_reflectiveSelectable  || 
2916+               fun1.symbol ==  jsdefn.Selectable_reflectiveSelectableFromLangReflectiveCalls  => 
2917+         genExpr(receiver)
2918+ 
2919+       case  _ => 
2920+         report.error(
2921+             " The receiver of Selectable.selectDynamic or Selectable.applyDynamic " + 
2922+             " must be a call to the (implicit) method scala.reflect.Selectable.reflectiveSelectable. " + 
2923+             " Other uses are not supported in Scala.js." 
2924+             tree.sourcePos)
2925+         js.Undefined ()
2926+     }
2927+ 
2928+     //  Extract the method name as a String
2929+     val  methodNameStr  =  args.head match  {
2930+       case  Literal (Constants .Constant (name : String )) => 
2931+         name
2932+       case  _ => 
2933+         report.error(
2934+             " The method name given to Selectable.selectDynamic or Selectable.applyDynamic " + 
2935+             " must be a literal string. " + 
2936+             " Other uses are not supported in Scala.js." 
2937+             args.head.sourcePos)
2938+         " erroneous" 
2939+     }
2940+ 
2941+     val  (formalParamTypeRefs, actualArgs) =  if  (isSelectDynamic) {
2942+       (Nil , Nil )
2943+     } else  {
2944+       //  Extract the param type refs and actual args from the 2nd and 3rd argument to applyDynamic
2945+       args.tail match  {
2946+         case  WrapArray (classTagsArray : JavaSeqLiteral ) ::  WrapArray (actualArgsAnyArray : JavaSeqLiteral ) ::  Nil  => 
2947+           //  Extract jstpe.Type's and jstpe.TypeRef's from the ClassTag.apply(_) trees
2948+           val  formalParamTypesAndTypeRefs  =  classTagsArray.elems.map {
2949+             //  ClassTag.apply(classOf[tp]) -> tp
2950+             case  Apply (fun, Literal (const) ::  Nil )
2951+                 if  fun.symbol ==  defn.ClassTagModule_apply  &&  const.tag ==  Constants .ClazzTag  => 
2952+               toIRTypeAndTypeRef(const.typeValue)
2953+             //  ClassTag.SpecialType -> erasure(SepecialType.typeRef) (e.g., ClassTag.Any -> Object)
2954+             case  Apply (Select (classTagModule, name), Nil )
2955+                 if  classTagModule.symbol ==  defn.ClassTagModule  && 
2956+                     defn.SpecialClassTagClasses .exists(_.name ==  name.toTypeName) => 
2957+               toIRTypeAndTypeRef(TypeErasure .erasure(
2958+                   defn.SpecialClassTagClasses .find(_.name ==  name.toTypeName).get.typeRef))
2959+             //  Anything else is invalid
2960+             case  classTag => 
2961+               report.error(
2962+                   " The ClassTags passed to Selectable.applyDynamic must be " + 
2963+                   " literal ClassTag(classOf[T]) expressions " + 
2964+                   " (typically compiler-generated). " + 
2965+                   " Other uses are not supported in Scala.js." 
2966+                   classTag.sourcePos)
2967+               (jstpe.AnyType , jstpe.ClassRef (jsNames.ObjectClass ))
2968+           }
2969+ 
2970+           //  Gen the actual args, downcasting them to the formal param types
2971+           val  actualArgs  =  actualArgsAnyArray.elems.zip(formalParamTypesAndTypeRefs).map {
2972+             (actualArgAny, formalParamTypeAndTypeRef) => 
2973+               val  genActualArgAny  =  genExpr(actualArgAny)
2974+               js.AsInstanceOf (genActualArgAny, formalParamTypeAndTypeRef._1)(genActualArgAny.pos)
2975+           }
2976+ 
2977+           (formalParamTypesAndTypeRefs.map(_._2), actualArgs)
2978+ 
2979+         case  _ => 
2980+           report.error(
2981+               " Passing the varargs of Selectable.applyDynamic with `: _*` " + 
2982+               " is not supported in Scala.js." 
2983+               tree.sourcePos)
2984+           (Nil , Nil )
2985+       }
2986+     }
2987+ 
2988+     val  methodName  =  MethodName .reflectiveProxy(methodNameStr, formalParamTypeRefs)
2989+ 
2990+     js.Apply (js.ApplyFlags .empty, receiver, js.MethodIdent (methodName), actualArgs)(jstpe.AnyType )
2991+   }
2992+ 
28212993  /**  Gen actual actual arguments to Scala method call. 
28222994   *  Returns a list of the transformed arguments. 
28232995   * 
@@ -2992,8 +3164,9 @@ class JSCodeGen()(using genCtx: Context) {
29923164    lazy  val  isWrapArray :  Set [Symbol ] =  {
29933165      val  names0  =  defn.ScalaValueClasses ().map(sym =>  nme.wrapXArray(sym.name))
29943166      val  names1  =  names0 ++  Set (nme.wrapRefArray, nme.genericWrapArray)
2995-       val  names2  =  names1.map(defn.ScalaPredefModule .requiredMethod(_))
2996-       names2.toSet
3167+       val  symsInPredef  =  names1.map(defn.ScalaPredefModule .requiredMethod(_))
3168+       val  symsInScalaRunTime  =  names1.map(defn.ScalaRuntimeModule .requiredMethod(_))
3169+       (symsInPredef ++  symsInScalaRunTime).toSet
29973170    }
29983171
29993172    def  unapply (tree : Apply ):  Option [Tree ] =  tree match  {
0 commit comments