Thanks to visit codestin.com
Credit goes to github.com

Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
71 changes: 16 additions & 55 deletions compiler/src/main/scala/org/scalajs/nscplugin/GenJSCode.scala
Original file line number Diff line number Diff line change
Expand Up @@ -1417,13 +1417,8 @@ abstract class GenJSCode[G <: Global with Singleton](val global: G)
implicit pos: Position): Option[js.Tree] = {
val fqcnArg = js.StringLiteral(sym.fullName + "$")
val runtimeClassArg = js.ClassOf(toTypeRef(sym.info))

val loadModuleFunArg = js.NewLambda(
js.NewLambda.Descriptor(encodeClassName(AbstractFunctionClass(0)), Nil,
MethodName("apply", Nil, jswkn.ObjectRef),
Nil, jstpe.AnyType),
js.Closure(js.ClosureFlags.typed, Nil, Nil, None, jstpe.AnyType, genLoadModule(sym), Nil)
)(encodeClassType(FunctionClass(0)))
val loadModuleFunArg =
js.Closure(js.ClosureFlags.arrow, Nil, Nil, None, jstpe.AnyType, genLoadModule(sym), Nil)

val stat = genApplyMethod(
genLoadModule(ReflectModule),
Expand All @@ -1442,40 +1437,12 @@ abstract class GenJSCode[G <: Global with Singleton](val global: G)
if (ctors.isEmpty) {
None
} else {
val objectArrayRef = jstpe.ArrayTypeRef(jswkn.ObjectRef, 1)
val objectArrayType = jstpe.ArrayType(objectArrayRef, nullable = true)
val tuple2Class = encodeClassName(TupleClass(2))
val tuple2ArrayRef = jstpe.ArrayTypeRef(jstpe.ClassRef(tuple2Class), 1)
val classClassRef = jstpe.ClassRef(jswkn.ClassClass)
val classArrayRef = jstpe.ArrayTypeRef(classClassRef, 1)

val tuple2Ctor = MethodName.constructor(List(jswkn.ObjectRef, jswkn.ObjectRef))

val newInstanceFunDescriptor = {
js.NewLambda.Descriptor(encodeClassName(AbstractFunctionClass(1)), Nil,
MethodName("apply", List(jswkn.ObjectRef), jswkn.ObjectRef),
List(jstpe.AnyType), jstpe.AnyType)
}

val constructorsInfos = for {
ctor <- ctors
} yield {
val paramTypesArray = js.ArrayValue(classArrayRef,
ctor.tpe.params.map(p => js.ClassOf(toTypeRef(p.tpe))))

val newInstanceClosure = {
// param args: Object
val argsParamDef = js.ParamDef(js.LocalIdent(LocalName("args")),
NoOriginalName, jstpe.AnyType, mutable = false)

// val argsArray: Object[] = args.asInstanceOf[Object[]]
val argsArrayVarDef = js.VarDef(js.LocalIdent(LocalName("argsArray")),
NoOriginalName, objectArrayType, mutable = false,
js.AsInstanceOf(argsParamDef.ref, objectArrayType))

// argsArray[i].asInstanceOf[Ti] for every parameter of the constructor
val actualParams = for {
(param, index) <- ctor.tpe.params.zipWithIndex
withNewLocalNameScope {
val (parameterTypes, formalParams, actualParams) = (for {
param <- ctor.tpe.params
} yield {
/* Note that we do *not* use `param.tpe` entering posterasure
* (neither to compute `paramType` nor to give to `fromAny`).
Expand All @@ -1493,30 +1460,24 @@ abstract class GenJSCode[G <: Global with Singleton](val global: G)
* parameter types is `List(classOf[Int])`, and when invoked
* reflectively, it must be given an `Int` (or `Integer`).
*/
fromAny(
js.ArraySelect(argsArrayVarDef.ref, js.IntLiteral(index))(jstpe.AnyType),
param.tpe)
}
val paramType = js.ClassOf(toTypeRef(param.tpe))
val paramDef = genParamDef(param, jstpe.AnyType)
val actualParam = fromAny(paramDef.ref, param.tpe)
(paramType, paramDef, actualParam)
}).unzip3

/* typed-lambda<>(args: Object): any = {
* val argsArray: Object[] = args.asInstanceOf[Object[]]
* new MyClass(...argsArray[i].asInstanceOf[Ti])
* }
*/
js.Closure(js.ClosureFlags.typed, Nil, argsParamDef :: Nil, None, jstpe.AnyType, {
js.Block(argsArrayVarDef, genNew(sym, ctor, actualParams))
}, Nil)
}
val paramTypesArray = js.JSArrayConstr(parameterTypes)

val newInstanceFun = js.NewLambda(newInstanceFunDescriptor, newInstanceClosure)(
encodeClassType(FunctionClass(1)))
val newInstanceFun = js.Closure(js.ClosureFlags.arrow, Nil,
formalParams, None, jstpe.AnyType, genNew(sym, ctor, actualParams), Nil)

js.New(tuple2Class, js.MethodIdent(tuple2Ctor), List(paramTypesArray, newInstanceFun))
js.JSArrayConstr(List(paramTypesArray, newInstanceFun))
}
}

val fqcnArg = js.StringLiteral(sym.fullName)
val runtimeClassArg = js.ClassOf(toTypeRef(sym.info))
val ctorsInfosArg = js.ArrayValue(tuple2ArrayRef, constructorsInfos)
val ctorsInfosArg = js.JSArrayConstr(constructorsInfos)

val stat = genApplyMethod(
genLoadModule(ReflectModule),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -151,8 +151,8 @@ trait JSDefinitions {
def ScalaRunTime_isArray: Symbol = getMemberMethod(ScalaRunTimeModule, newTermName("isArray")).suchThat(_.tpe.params.size == 2)

lazy val ReflectModule = getRequiredModule("scala.scalajs.reflect.Reflect")
lazy val Reflect_registerLoadableModuleClass = getMemberMethod(ReflectModule, newTermName("registerLoadableModuleClassV2"))
lazy val Reflect_registerInstantiatableClass = getMemberMethod(ReflectModule, newTermName("registerInstantiatableClassV2"))
lazy val Reflect_registerLoadableModuleClass = getMemberMethod(ReflectModule, newTermName("registerLoadableModuleClass"))
lazy val Reflect_registerInstantiatableClass = getMemberMethod(ReflectModule, newTermName("registerInstantiatableClass"))

lazy val EnableReflectiveInstantiationAnnotation = getRequiredClass("scala.scalajs.reflect.annotation.EnableReflectiveInstantiation")

Expand Down
12 changes: 11 additions & 1 deletion library/src/main/scala/scala/scalajs/reflect/Reflect.scala
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,17 @@ object Reflect {
constructors: js.Array[js.Tuple2[js.Array[Class[_]], js.Function]]): Unit = {

registerInstantiatableClassV2(fqcn, runtimeClass, constructors.map { c =>
(c._1.toArray, (args: Array[Any]) => c._2.asInstanceOf[JSFunctionVarArgs].apply(args: _*))
val paramClassesArray = c._1.toArray
val newInstanceJSFun = c._2.asInstanceOf[JSFunctionVarArgs]

val newInstanceFun: Array[Any] => Any = { (args: Array[Any]) =>
// The shenanigans in this function are required to be compatible across all Scala patch versions
import scala.scalajs.runtime.toRefVarArgs // this is fine because we are inside scalajs-library
val argsAsRefArray = args.asInstanceOf[Array[AnyRef]] // no-op because Array[Any] also erases to jl.Object[]
newInstanceJSFun.apply(toRefVarArgs(argsAsRefArray): _*)
}

(paramClassesArray, newInstanceFun)
}.toArray)
}

Expand Down
Loading