Skip to content

Commit 4e6d83e

Browse files
committed
Call the new javalibintf.Reflect API from the codegen.
1 parent 474fe14 commit 4e6d83e

File tree

2 files changed

+112
-28
lines changed

2 files changed

+112
-28
lines changed

compiler/src/main/scala/org/scalajs/nscplugin/GenJSCode.scala

Lines changed: 112 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1417,13 +1417,18 @@ abstract class GenJSCode[G <: Global with Singleton](val global: G)
14171417
implicit pos: Position): Option[js.Tree] = {
14181418
val fqcnArg = js.StringLiteral(sym.fullName + "$")
14191419
val runtimeClassArg = js.ClassOf(toTypeRef(sym.info))
1420-
val loadModuleFunArg =
1421-
js.Closure(js.ClosureFlags.arrow, Nil, Nil, None, jstpe.AnyType, genLoadModule(sym), Nil)
14221420

1423-
val stat = genApplyMethod(
1424-
genLoadModule(ReflectModule),
1425-
Reflect_registerLoadableModuleClass,
1426-
List(fqcnArg, runtimeClassArg, loadModuleFunArg))
1421+
val loadModuleFunArg = js.NewLambda(
1422+
JSupplierClassDescriptor,
1423+
js.Closure(js.ClosureFlags.typed, Nil, Nil, None, jstpe.AnyType, genLoadModule(sym), Nil)
1424+
)(jstpe.ClassType(JSupplierClassName, nullable = false))
1425+
1426+
val stat = js.ApplyStatic(
1427+
js.ApplyFlags.empty,
1428+
JavalibIntfReflectClassName,
1429+
js.MethodIdent(Reflect_registerLoadableModuleClassMethodName),
1430+
List(fqcnArg, runtimeClassArg, loadModuleFunArg)
1431+
)(jstpe.VoidType)
14271432

14281433
Some(stat)
14291434
}
@@ -1440,9 +1445,22 @@ abstract class GenJSCode[G <: Global with Singleton](val global: G)
14401445
val constructorsInfos = for {
14411446
ctor <- ctors
14421447
} yield {
1443-
withNewLocalNameScope {
1444-
val (parameterTypes, formalParams, actualParams) = (for {
1445-
param <- ctor.tpe.params
1448+
val paramTypesArray = js.ArrayValue(ClassArrayRef,
1449+
ctor.tpe.params.map(p => js.ClassOf(toTypeRef(p.tpe))))
1450+
1451+
val newInstanceClosure = {
1452+
// param args: Object
1453+
val argsParamDef = js.ParamDef(js.LocalIdent(LocalName("args")),
1454+
NoOriginalName, jstpe.AnyType, mutable = false)
1455+
1456+
// val argsArray: Object[] = args.asInstanceOf[Object[]]
1457+
val argsArrayVarDef = js.VarDef(js.LocalIdent(LocalName("argsArray")),
1458+
NoOriginalName, ObjectArrayType, mutable = false,
1459+
js.AsInstanceOf(argsParamDef.ref, ObjectArrayType))
1460+
1461+
// argsArray[i].asInstanceOf[Ti] for every parameter of the constructor
1462+
val actualParams = for {
1463+
(param, index) <- ctor.tpe.params.zipWithIndex
14461464
} yield {
14471465
/* Note that we do *not* use `param.tpe` entering posterasure
14481466
* (neither to compute `paramType` nor to give to `fromAny`).
@@ -1460,29 +1478,38 @@ abstract class GenJSCode[G <: Global with Singleton](val global: G)
14601478
* parameter types is `List(classOf[Int])`, and when invoked
14611479
* reflectively, it must be given an `Int` (or `Integer`).
14621480
*/
1463-
val paramType = js.ClassOf(toTypeRef(param.tpe))
1464-
val paramDef = genParamDef(param, jstpe.AnyType)
1465-
val actualParam = fromAny(paramDef.ref, param.tpe)
1466-
(paramType, paramDef, actualParam)
1467-
}).unzip3
1481+
fromAny(
1482+
js.ArraySelect(argsArrayVarDef.ref, js.IntLiteral(index))(jstpe.AnyType),
1483+
param.tpe)
1484+
}
14681485

1469-
val paramTypesArray = js.JSArrayConstr(parameterTypes)
1486+
/* typed-lambda<>(args: Object): any = {
1487+
* val argsArray: Object[] = args.asInstanceOf[Object[]]
1488+
* new MyClass(...argsArray[i].asInstanceOf[Ti])
1489+
* }
1490+
*/
1491+
js.Closure(js.ClosureFlags.typed, Nil, argsParamDef :: Nil, None, jstpe.AnyType, {
1492+
js.Block(argsArrayVarDef, genNew(sym, ctor, actualParams))
1493+
}, Nil)
1494+
}
14701495

1471-
val newInstanceFun = js.Closure(js.ClosureFlags.arrow, Nil,
1472-
formalParams, None, jstpe.AnyType, genNew(sym, ctor, actualParams), Nil)
1496+
val newInstanceFun = js.NewLambda(JFunctionClassDescriptor, newInstanceClosure)(
1497+
jstpe.ClassType(JFunctionClassName, nullable = false))
14731498

1474-
js.JSArrayConstr(List(paramTypesArray, newInstanceFun))
1475-
}
1499+
js.New(SimpleMapEntryClassName, js.MethodIdent(TwoObjectArgsConstructorName),
1500+
List(paramTypesArray, newInstanceFun))
14761501
}
14771502

14781503
val fqcnArg = js.StringLiteral(sym.fullName)
14791504
val runtimeClassArg = js.ClassOf(toTypeRef(sym.info))
1480-
val ctorsInfosArg = js.JSArrayConstr(constructorsInfos)
1505+
val ctorsInfosArg = js.ArrayValue(MapEntryArrayRef, constructorsInfos)
14811506

1482-
val stat = genApplyMethod(
1483-
genLoadModule(ReflectModule),
1484-
Reflect_registerInstantiatableClass,
1485-
List(fqcnArg, runtimeClassArg, ctorsInfosArg))
1507+
val stat = js.ApplyStatic(
1508+
js.ApplyFlags.empty,
1509+
JavalibIntfReflectClassName,
1510+
js.MethodIdent(Reflect_registerInstantiatableClassMethodName),
1511+
List(fqcnArg, runtimeClassArg, ctorsInfosArg)
1512+
)(jstpe.VoidType)
14861513

14871514
Some(stat)
14881515
}
@@ -7387,10 +7414,71 @@ private object GenJSCode {
73877414
private val JSObjectClassName = ClassName("scala.scalajs.js.Object")
73887415
private val JavaScriptExceptionClassName = ClassName("scala.scalajs.js.JavaScriptException")
73897416

7417+
private val JavalibIntfReflectClassName = ClassName("org.scalajs.javalibintf.Reflect")
7418+
7419+
private val JFunctionClassName = ClassName("java.util.function.Function")
7420+
private val JSupplierClassName = ClassName("java.util.function.Supplier")
7421+
private val MapEntryClassName = ClassName("java.util.Map$Entry")
7422+
private val SimpleMapEntryClassName = ClassName("java.util.AbstractMap$SimpleImmutableEntry")
7423+
7424+
private val ObjectArrayType =
7425+
jstpe.ArrayType(jstpe.ArrayTypeRef(jswkn.ObjectRef, 1), nullable = true)
7426+
private val ClassArrayRef =
7427+
jstpe.ArrayTypeRef(jstpe.ClassRef(jswkn.ClassClass), 1)
7428+
7429+
private val MapEntryArrayRef =
7430+
jstpe.ArrayTypeRef(jstpe.ClassRef(MapEntryClassName), 1)
7431+
73907432
private val newSimpleMethodName = SimpleMethodName("new")
73917433

7434+
private val Reflect_registerLoadableModuleClassMethodName = {
7435+
MethodName(
7436+
"registerLoadableModuleClass",
7437+
List(
7438+
jstpe.ClassRef(jswkn.BoxedStringClass),
7439+
jstpe.ClassRef(jswkn.ClassClass),
7440+
jstpe.ClassRef(JSupplierClassName)
7441+
),
7442+
jstpe.VoidRef
7443+
)
7444+
}
7445+
7446+
private val Reflect_registerInstantiatableClassMethodName = {
7447+
MethodName(
7448+
"registerInstantiatableClass",
7449+
List(
7450+
jstpe.ClassRef(jswkn.BoxedStringClass),
7451+
jstpe.ClassRef(jswkn.ClassClass),
7452+
MapEntryArrayRef
7453+
),
7454+
jstpe.VoidRef
7455+
)
7456+
}
7457+
73927458
private val ObjectArgConstructorName =
73937459
MethodName.constructor(List(jswkn.ObjectRef))
7460+
private val TwoObjectArgsConstructorName =
7461+
MethodName.constructor(List(jswkn.ObjectRef, jswkn.ObjectRef))
7462+
7463+
private val JSupplierClassDescriptor = {
7464+
js.NewLambda.Descriptor(
7465+
jswkn.ObjectClass,
7466+
List(JSupplierClassName),
7467+
MethodName("get", Nil, jswkn.ObjectRef),
7468+
Nil,
7469+
jstpe.AnyType
7470+
)
7471+
}
7472+
7473+
private val JFunctionClassDescriptor = {
7474+
js.NewLambda.Descriptor(
7475+
jswkn.ObjectClass,
7476+
List(JFunctionClassName),
7477+
MethodName("apply", List(jswkn.ObjectRef), jswkn.ObjectRef),
7478+
List(jstpe.AnyType),
7479+
jstpe.AnyType
7480+
)
7481+
}
73947482

73957483
private val thisOriginalName = OriginalName("this")
73967484

compiler/src/main/scala/org/scalajs/nscplugin/JSDefinitions.scala

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -150,10 +150,6 @@ trait JSDefinitions {
150150
// (rather than definitions) and we weren't sure if it is safe to make this a lazy val
151151
def ScalaRunTime_isArray: Symbol = getMemberMethod(ScalaRunTimeModule, newTermName("isArray")).suchThat(_.tpe.params.size == 2)
152152

153-
lazy val ReflectModule = getRequiredModule("scala.scalajs.reflect.Reflect")
154-
lazy val Reflect_registerLoadableModuleClass = getMemberMethod(ReflectModule, newTermName("registerLoadableModuleClass"))
155-
lazy val Reflect_registerInstantiatableClass = getMemberMethod(ReflectModule, newTermName("registerInstantiatableClass"))
156-
157153
lazy val EnableReflectiveInstantiationAnnotation = getRequiredClass("scala.scalajs.reflect.annotation.EnableReflectiveInstantiation")
158154

159155
lazy val ExecutionContextModule = getRequiredModule("scala.concurrent.ExecutionContext")

0 commit comments

Comments
 (0)