@@ -68,6 +68,12 @@ class JSCodeGen()(implicit ctx: Context) {
68
68
private val thisLocalVarIdent = new ScopedVar [Option [js.Ident ]]
69
69
private val undefinedDefaultParams = new ScopedVar [mutable.Set [Symbol ]]
70
70
71
+ private def withNewLocalNameScope [A ](body : => A ): A = {
72
+ withScopedVars(localNames := new LocalNameGenerator ) {
73
+ body
74
+ }
75
+ }
76
+
71
77
/** Implicitly materializes the current local name generator. */
72
78
private implicit def implicitLocalNames : LocalNameGenerator = localNames.get
73
79
@@ -86,6 +92,10 @@ class JSCodeGen()(implicit ctx: Context) {
86
92
private def freshLocalIdent (base : String )(implicit pos : Position ): js.Ident =
87
93
localNames.get.freshLocalIdent(base)
88
94
95
+ /** Returns a new fresh local identifier. */
96
+ private def freshLocalIdent (base : TermName )(implicit pos : Position ): js.Ident =
97
+ localNames.get.freshLocalIdent(base)
98
+
89
99
// Compilation unit --------------------------------------------------------
90
100
91
101
def run (): Unit = {
@@ -287,9 +297,31 @@ class JSCodeGen()(implicit ctx: Context) {
287
297
Nil
288
298
}
289
299
300
+ // Static initializer
301
+ val optStaticInitializer = {
302
+ // Initialization of reflection data, if required
303
+ val reflectInit = {
304
+ val enableReflectiveInstantiation = {
305
+ sym.baseClasses.exists { ancestor =>
306
+ ancestor.hasAnnotation(jsdefn.EnableReflectiveInstantiationAnnot )
307
+ }
308
+ }
309
+ if (enableReflectiveInstantiation)
310
+ genRegisterReflectiveInstantiation(sym)
311
+ else
312
+ None
313
+ }
314
+
315
+ val staticInitializerStats = reflectInit.toList
316
+ if (staticInitializerStats.nonEmpty)
317
+ Some (genStaticInitializerWithStats(js.Block (staticInitializerStats)))
318
+ else
319
+ None
320
+ }
321
+
290
322
// Hashed definitions of the class
291
323
val hashedDefs =
292
- ir.Hashers .hashMemberDefs(generatedMembers ++ exports)
324
+ ir.Hashers .hashMemberDefs(generatedMembers ++ exports ++ optStaticInitializer )
293
325
294
326
// The complete class definition
295
327
val kind =
@@ -461,6 +493,93 @@ class JSCodeGen()(implicit ctx: Context) {
461
493
}).toList
462
494
}
463
495
496
+ // Static initializers -----------------------------------------------------
497
+
498
+ private def genStaticInitializerWithStats (stats : js.Tree )(
499
+ implicit pos : Position ): js.MethodDef = {
500
+ js.MethodDef (
501
+ js.MemberFlags .empty.withNamespace(js.MemberNamespace .StaticConstructor ),
502
+ js.Ident (ir.Definitions .StaticInitializerName ),
503
+ Nil ,
504
+ jstpe.NoType ,
505
+ Some (stats))(
506
+ OptimizerHints .empty, None )
507
+ }
508
+
509
+ private def genRegisterReflectiveInstantiation (sym : Symbol )(
510
+ implicit pos : Position ): Option [js.Tree ] = {
511
+ if (isStaticModule(sym))
512
+ genRegisterReflectiveInstantiationForModuleClass(sym)
513
+ else if (sym.is(ModuleClass ))
514
+ None // scala-js#3228
515
+ // TODO What is `originalOwner` in dotc?
516
+ // else if (sym.is(Lifted) && !sym.originalOwner.isClass)
517
+ // None // scala-js#3227
518
+ else
519
+ genRegisterReflectiveInstantiationForNormalClass(sym)
520
+ }
521
+
522
+ private def genRegisterReflectiveInstantiationForModuleClass (sym : Symbol )(
523
+ implicit pos : Position ): Option [js.Tree ] = {
524
+ val fqcnArg = js.StringLiteral (sym.fullName.toString)
525
+ val runtimeClassArg = js.ClassOf (toTypeRef(sym.info))
526
+ val loadModuleFunArg =
527
+ js.Closure (arrow = true , Nil , Nil , genLoadModule(sym), Nil )
528
+
529
+ val stat = genApplyMethod(
530
+ genLoadModule(jsdefn.ReflectModule ),
531
+ jsdefn.Reflect_registerLoadableModuleClass ,
532
+ List (fqcnArg, runtimeClassArg, loadModuleFunArg))
533
+
534
+ Some (stat)
535
+ }
536
+
537
+ private def genRegisterReflectiveInstantiationForNormalClass (sym : Symbol )(
538
+ implicit pos : Position ): Option [js.Tree ] = {
539
+ val ctors =
540
+ if (sym.is(Abstract )) Nil
541
+ else sym.info.member(nme.CONSTRUCTOR ).alternatives.map(_.symbol).filter(m => ! m.is(Private | Protected ))
542
+
543
+ if (ctors.isEmpty) {
544
+ None
545
+ } else {
546
+ val constructorsInfos = for {
547
+ ctor <- ctors
548
+ } yield {
549
+ withNewLocalNameScope {
550
+ val (parameterTypes, formalParams, actualParams) = (for {
551
+ (paramName, paramInfo) <- ctor.info.paramNamess.flatten.zip(ctor.info.paramInfoss.flatten)
552
+ } yield {
553
+ val paramType = js.ClassOf (toTypeRef(paramInfo))
554
+ val paramDef = js.ParamDef (freshLocalIdent(paramName), jstpe.AnyType ,
555
+ mutable = false , rest = false )
556
+ val actualParam = unbox(paramDef.ref, paramInfo)
557
+ (paramType, paramDef, actualParam)
558
+ }).unzip3
559
+
560
+ val paramTypesArray = js.JSArrayConstr (parameterTypes)
561
+
562
+ val newInstanceFun = js.Closure (arrow = true , Nil , formalParams, {
563
+ js.New (encodeClassRef(sym), encodeMethodSym(ctor), actualParams)
564
+ }, Nil )
565
+
566
+ js.JSArrayConstr (List (paramTypesArray, newInstanceFun))
567
+ }
568
+ }
569
+
570
+ val fqcnArg = js.StringLiteral (sym.fullName.toString)
571
+ val runtimeClassArg = js.ClassOf (toTypeRef(sym.info))
572
+ val ctorsInfosArg = js.JSArrayConstr (constructorsInfos)
573
+
574
+ val stat = genApplyMethod(
575
+ genLoadModule(jsdefn.ReflectModule ),
576
+ jsdefn.Reflect_registerInstantiatableClass ,
577
+ List (fqcnArg, runtimeClassArg, ctorsInfosArg))
578
+
579
+ Some (stat)
580
+ }
581
+ }
582
+
464
583
// Generate a method -------------------------------------------------------
465
584
466
585
private def genMethod (dd : DefDef ): Option [js.MethodDef ] = {
0 commit comments