@@ -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,92 @@ 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
+ else if (sym.is(Lifted ) && ! sym.originalOwner.isClass)
516
+ None // scala-js#3227
517
+ else
518
+ genRegisterReflectiveInstantiationForNormalClass(sym)
519
+ }
520
+
521
+ private def genRegisterReflectiveInstantiationForModuleClass (sym : Symbol )(
522
+ implicit pos : Position ): Option [js.Tree ] = {
523
+ val fqcnArg = js.StringLiteral (sym.fullName.toString)
524
+ val runtimeClassArg = js.ClassOf (toTypeRef(sym.info))
525
+ val loadModuleFunArg =
526
+ js.Closure (arrow = true , Nil , Nil , genLoadModule(sym), Nil )
527
+
528
+ val stat = genApplyMethod(
529
+ genLoadModule(jsdefn.ReflectModule ),
530
+ jsdefn.Reflect_registerLoadableModuleClass ,
531
+ List (fqcnArg, runtimeClassArg, loadModuleFunArg))
532
+
533
+ Some (stat)
534
+ }
535
+
536
+ private def genRegisterReflectiveInstantiationForNormalClass (sym : Symbol )(
537
+ implicit pos : Position ): Option [js.Tree ] = {
538
+ val ctors =
539
+ if (sym.is(Abstract )) Nil
540
+ else sym.info.member(nme.CONSTRUCTOR ).alternatives.map(_.symbol).filter(m => ! m.is(Private | Protected ))
541
+
542
+ if (ctors.isEmpty) {
543
+ None
544
+ } else {
545
+ val constructorsInfos = for {
546
+ ctor <- ctors
547
+ } yield {
548
+ withNewLocalNameScope {
549
+ val (parameterTypes, formalParams, actualParams) = (for {
550
+ (paramName, paramInfo) <- ctor.info.paramNamess.flatten.zip(ctor.info.paramInfoss.flatten)
551
+ } yield {
552
+ val paramType = js.ClassOf (toTypeRef(paramInfo))
553
+ val paramDef = js.ParamDef (freshLocalIdent(paramName), jstpe.AnyType ,
554
+ mutable = false , rest = false )
555
+ val actualParam = unbox(paramDef.ref, paramInfo)
556
+ (paramType, paramDef, actualParam)
557
+ }).unzip3
558
+
559
+ val paramTypesArray = js.JSArrayConstr (parameterTypes)
560
+
561
+ val newInstanceFun = js.Closure (arrow = true , Nil , formalParams, {
562
+ js.New (encodeClassRef(sym), encodeMethodSym(ctor), actualParams)
563
+ }, Nil )
564
+
565
+ js.JSArrayConstr (List (paramTypesArray, newInstanceFun))
566
+ }
567
+ }
568
+
569
+ val fqcnArg = js.StringLiteral (sym.fullName.toString)
570
+ val runtimeClassArg = js.ClassOf (toTypeRef(sym.info))
571
+ val ctorsInfosArg = js.JSArrayConstr (constructorsInfos)
572
+
573
+ val stat = genApplyMethod(
574
+ genLoadModule(jsdefn.ReflectModule ),
575
+ jsdefn.Reflect_registerInstantiatableClass ,
576
+ List (fqcnArg, runtimeClassArg, ctorsInfosArg))
577
+
578
+ Some (stat)
579
+ }
580
+ }
581
+
464
582
// Generate a method -------------------------------------------------------
465
583
466
584
private def genMethod (dd : DefDef ): Option [js.MethodDef ] = {
0 commit comments