8000 Do not (ab)use blocks for top level trees · scala-js/scala-js@1982a6b · GitHub
[go: up one dir, main page]

Skip to content

Commit 1982a6b

Browse files
committed
Do not (ab)use blocks for top level trees
1 parent 2f1fc32 commit 1982a6b

File tree

6 files changed

+356
-395
lines changed

6 files changed

+356
-395
lines changed

linker/shared/src/main/scala/org/scalajs/linker/backend/emitter/ClassEmitter.scala

Lines changed: 54 additions & 68 deletions
Original file line numberDiff line numberDiff line change
@@ -45,23 +45,15 @@ private[emitter] final class ClassEmitter(sjsGen: SJSGen) {
4545

4646
def buildClass(className: ClassName, kind: ClassKind, jsClassCaptures: Option[List[ParamDef]],
4747
hasClassInitializer: Boolean,
48-
superClass: Option[ClassIdent], jsSuperClass: Option[Tree], useESClass: Boolean, ctor: js.Tree,
48+
superClass: Option[ClassIdent], jsSuperClass: Option[Tree], useESClass: Boolean, ctorDefs: List[js.Tree],
4949
memberDefs: List[js.MethodDef], exportedDefs: List[js.Tree])(
5050
implicit moduleContext: ModuleContext,
51-
globalKnowledge: GlobalKnowledge, pos: Position): WithGlobals[js.Tree] = {
51+
globalKnowledge: GlobalKnowledge, pos: Position): WithGlobals[List[js.Tree]] = {
5252

53-
def allES6Defs = {
54-
js.Block(ctor +: (memberDefs ++ exportedDefs)) match {
55-
case js.Block(allDefs) => allDefs
56-
case js.Skip() => Nil
57-
case oneDef => List(oneDef)
58-
}
59-
}
53+
def allES6Defs = ctorDefs ::: memberDefs ::: exportedDefs
6054

61-
def allES5Defs(classVar: js.Tree) = {
62-
WithGlobals(js.Block(
63-
ctor, assignES5ClassMembers(classVar, memberDefs), js.Block(exportedDefs: _*)))
64-
}
55+
def allES5Defs(classVar: js.Tree) =
56+
WithGlobals(ctorDefs ::: assignES5ClassMembers(classVar, memberDefs) ::: exportedDefs)
6557

6658
if (!kind.isJSClass) {
6759
assert(jsSuperClass.isEmpty, className)
@@ -95,7 +87,7 @@ private[emitter] final class ClassEmitter(sjsGen: SJSGen) {
9587

9688
val entireClassDefWithGlobals = if (useESClass) {
9789
genJSSuperCtor(superClass, jsSuperClass).map { jsSuperClass =>
98-
classValueVar := js.ClassDef(Some(classValueIdent), Some(jsSuperClass), allES6Defs)
90+
List(classValueVar := js.ClassDef(Some(classValueIdent), Some(jsSuperClass), allES6Defs))
9991
}
10092
} else {
10193
allES5Defs(classValueVar)
@@ -106,7 +98,7 @@ private[emitter] final class ClassEmitter(sjsGen: SJSGen) {
10698
entireClassDef <- entireClassDefWithGlobals
10799
createStaticFields <- genCreateStaticFieldsOfJSClass(className)
108100
} yield {
109-
optStoreJSSuperClass.toList ::: entireClassDef :: createStaticFields
101+
optStoreJSSuperClass.toList ::: entireClassDef ::: createStaticFields
110102
}
111103

112104
jsClassCaptures.fold {
@@ -125,7 +117,7 @@ private[emitter] final class ClassEmitter(sjsGen: SJSGen) {
125117
)
126118
createAccessor <- globalFunctionDef("a", className, Nil, None, body)
127119
} yield {
128-
js.Block(createClassValueVar, createAccessor)
120+
createClassValueVar :: createAccessor
129121
}
130122
} { jsClassCaptures =>
131123
val captureParamDefs = for (param <- jsClassCaptures) yield {
@@ -173,7 +165,7 @@ private[emitter] final class ClassEmitter(sjsGen: SJSGen) {
173165
def genScalaClassConstructor(className: ClassName, superClass: Option[ClassIdent],
174166
useESClass: Boolean, initToInline: Option[MethodDef])(
175167
implicit moduleContext: ModuleContext,
176-
globalKnowledge: GlobalKnowledge, pos: Position): WithGlobals[js.Tree] = {
168+
globalKnowledge: GlobalKnowledge, pos: Position): WithGlobals[List[js.Tree]] = {
177169

178170
assert(superClass.isDefined || className == ObjectClass,
179171
s"Class $className is missing a parent class")
@@ -192,9 +184,9 @@ private[emitter] final class ClassEmitter(sjsGen: SJSGen) {
192184
}
193185

194186
if (args.isEmpty && isTrivialCtorBody)
195-
js.Skip()
187+
Nil
196188
else
197-
js.MethodDef(static = false, js.Ident("constructor"), args, restParam, body)
189+
js.MethodDef(static = false, js.Ident("constructor"), args, restParam, body) :: Nil
198190
}
199191
} else {
200192
import TreeDSL._
@@ -203,13 +195,13 @@ private[emitter] final class ClassEmitter(sjsGen: SJSGen) {
203195

204196
val chainProtoWithGlobals = superClass match {
205197
case None =>
206-
WithGlobals(js.Skip())
198+
WithGlobals.nil
207199

208200
case Some(_) if shouldExtendJSError(className, superClass) =>
209201
untrackedGlobalRef("Error").map(chainPrototypeWithLocalCtor(className, ctorVar, _))
210202

211203
case Some(parentIdent) =>
212-
WithGlobals(ctorVar.prototype := js.New(globalVar("h", parentIdent.name), Nil))
204+
WithGlobals(List(ctorVar.prototype := js.New(globalVar("h", parentIdent.name), Nil)))
213205
}
214206

215207
for {
@@ -220,17 +212,17 @@ private[emitter] final class ClassEmitter(sjsGen: SJSGen) {
220212
globalFunctionDef("h", className, Nil, None, js.Skip())
221213
chainProto <- chainProtoWithGlobals
222214
} yield {
223-
js.Block(
224-
// Real constructor
225-
js.DocComment("@constructor"),
226-
realCtorDef,
227-
chainProto,
228-
genIdentBracketSelect(ctorVar.prototype, "constructor") := ctorVar,
229-
230-
// Inheritable constructor
231-
js.DocComment("@constructor"),
232-
inheritableCtorDef,
233-
globalVar("h", className).prototype := ctorVar.prototype
215+
(
216+
// Real constructor
217+
js.DocComment("@constructor") ::
218+
realCtorDef :::
219+
chainProto :::
220+
(genIdentBracketSelect(ctorVar.prototype, "constructor") := ctorVar) ::
221+
222+
// Inheritable constructor
223+
js.DocComment("@constructor") ::
224+
inheritableCtorDef :::
225+
(globalVar("h", className).prototype := ctorVar.prototype) :: Nil
234226
)
235227
}
236228
}
@@ -240,15 +232,15 @@ private[emitter] final class ClassEmitter(sjsGen: SJSGen) {
240232
def genJSConstructor(className: ClassName, superClass: Option[ClassIdent],
241233
jsSuperClass: Option[Tree], useESClass: Boolean, jsConstructorDef: JSConstructorDef)(
242234
implicit moduleContext: ModuleContext,
243-
globalKnowledge: GlobalKnowledge, pos: Position): WithGlobals[js.Tree] = {
235+
globalKnowledge: GlobalKnowledge, pos: Position): WithGlobals[List[js.Tree]] = {
244236

245237
val JSConstructorDef(_, params, restParam, body) = jsConstructorDef
246238
val ctorFunWithGlobals = desugarToFunction(className, params, restParam, body)
247239

248240
if (useESClass) {
249241
for (fun <- ctorFunWithGlobals) yield {
250242
js.MethodDef(static = false, js.Ident("constructor"),
251-
fun.args, fun.restParam, fun.body)
243+
fun.args, fun.restParam, fun.body) :: Nil
252244
}
253245
} else {
254246
for {
@@ -259,12 +251,10 @@ private[emitter] final class ClassEmitter(sjsGen: SJSGen) {
259251

260252
val ctorVar = fileLevelVar("b", genName(className))
261253

262-
js.Block(
263-
js.DocComment("@constructor"),
264-
ctorVar := ctorFun,
265-
chainPrototypeWithLocalCtor(className, ctorVar, superCtor),
266-
genIdentBracketSelect(ctorVar.prototype, "constructor") := ctorVar
267-
)
254+
js.DocComment("@constructor") ::
255+
(ctorVar := ctorFun) ::
256+
chainPrototypeWithLocalCtor(className, ctorVar, superCtor) :::
257+
(genIdentBracketSelect(ctorVar.prototype, "constructor") := ctorVar) :: Nil
268258
}
269259
}
270260
}
@@ -348,12 +338,12 @@ private[emitter] final class ClassEmitter(sjsGen: SJSGen) {
348338
}
349339

350340
private def chainPrototypeWithLocalCtor(className: ClassName, ctorVar: js.Tree,
351-
superCtor: js.Tree)(implicit pos: Position): js.Tree = {
341+
superCtor: js.Tree)(implicit pos: Position): List[js.Tree] = {
352342
import TreeDSL._
353343

354344
val dummyCtor = fileLevelVar("hh", genName(className))
355345

356-
js.Block(
346+
List(
357347
js.DocComment("@constructor"),
358348
genConst(dummyCtor.ident, js.Function(false, Nil, None, js.Skip())),
359349
dummyCtor.prototype := superCtor.prototype,
@@ -396,7 +386,7 @@ private[emitter] final class ClassEmitter(sjsGen: SJSGen) {
396386
globalVarDef("t", varScope, value, origName.orElse(name))
397387
}
398388

399-
WithGlobals.list(defs)
389+
WithGlobals.flatten(defs)
400390
}
401391

402392
/** Generates the creation of the private JS field defs for a JavaScript
@@ -424,7 +414,7 @@ private[emitter] final class ClassEmitter(sjsGen: SJSGen) {
424414
}
425415
}
426416

427-
WithGlobals.list(defs)
417+
WithGlobals.flatten(defs)
428418
}
429419

430420
/** Generates the creation of the static fields for a JavaScript class. */
@@ -497,7 +487,7 @@ private[emitter] final class ClassEmitter(sjsGen: SJSGen) {
497487

498488
def genStaticLikeMethod(className: ClassName, method: MethodDef)(
499489
implicit moduleContext: ModuleContext,
500-
globalKnowledge: GlobalKnowledge): WithGlobals[js.Tree] = {
490+
globalKnowledge: GlobalKnowledge): WithGlobals[List[js.Tree]] = {
501491
val methodBody = method.body.getOrElse(
502492
throw new AssertionError("Cannot generate an abstract method"))
503493

@@ -570,11 +560,11 @@ private[emitter] final class ClassEmitter(sjsGen: SJSGen) {
570560
private def genJSProperty(className: ClassName, kind: ClassKind, useESClass: Boolean,
571561
property: JSPropertyDef)(
572562
implicit moduleContext: ModuleContext,
573-
globalKnowledge: GlobalKnowledge): WithGlobals[js.Tree] = {
563+
globalKnowledge: GlobalKnowledge): WithGlobals[List[js.Tree]] = {
574564
if (useESClass)
575565
genJSPropertyES6(className, property)
576566
else
577-
genJSPropertyES5(className, kind, property)
567+
genJSPropertyES5(className, kind, property).map(_ :: Nil)
578568
}
579569

580570
private def genJSPropertyES5(className: ClassName, kind: ClassKind, property: JSPropertyDef)(
@@ -612,31 +602,27 @@ private[emitter] final class ClassEmitter(sjsGen: SJSGen) {
612602

613603
private def genJSPropertyES6(className: ClassName, property: JSPropertyDef)(
614604
implicit moduleContext: ModuleContext,
615-
globalKnowledge: GlobalKnowledge): WithGlobals[js.Tree] = {
605+
globalKnowledge: GlobalKnowledge): WithGlobals[List[js.Tree]] = {
616606
implicit val pos = property.pos
617607

618608
val static = property.flags.namespace.isStatic
619609

620610
genMemberNameTree(property.name).flatMap { propName =>
621-
val getterWithGlobals = property.getterBody.fold {
622-
WithGlobals[js.Tree](js.Skip())
623-
} { body =>
611+
val getterWithGlobals = property.getterBody.map { body =>
624612
for (fun <- desugarToFunction(className, Nil, body, resultType = AnyType))
625613
yield js.GetterDef(static, propName, fun.body)
626614
}
627615

628-
val setterWithGlobals = property.setterArgAndBody.fold {
629-
WithGlobals[js.Tree](js.Skip())
630-
} { case (arg, body) =>
616+
val setterWithGlobals = property.setterArgAndBody.map { case (arg, body) =>
631617
for (fun <- desugarToFunction(className, arg :: Nil, body, resultType = NoType))
632618
yield js.SetterDef(static, propName, fun.args.head, fun.body)
633619
}
634620

635621
for {
636-
getter <- getterWithGlobals
637-
setter <- setterWithGlobals
622+
getter <- WithGlobals.option(getterWithGlobals)
623+
setter <- WithGlobals.option(setterWithGlobals)
638624
} yield {
639-
js.Block(getter, setter)
625+
getter.toList ::: setter.toList
640626
}
641627
}
642628
}
@@ -756,11 +742,11 @@ private[emitter] final class ClassEmitter(sjsGen: SJSGen) {
756742
val createIsStatWithGlobals = if (needIsFunction) {
757743
globalFunctionDef("is", className, List(objParam), None, js.Return(isExpression))
758744
} else {
759-
WithGlobals(js.Skip())
745+
WithGlobals.nil
760746
}
761747

762748
val createAsStatWithGlobals = if (semantics.asInstanceOfs == Unchecked) {
763-
WithGlobals(js.Skip())
749+
WithGlobals.nil
764750
} else {
765751
globalFunctionDef("as", className, List(objParam), None, js.Return {
766752
val isCond =
@@ -780,10 +766,10 @@ private[emitter] final class ClassEmitter(sjsGen: SJSGen) {
780766
createIsStat <- createIsStatWithGlobals
781767
createAsStat <- createAsStatWithGlobals
782768
} yield {
783-
List(createIsStat, createAsStat)
769+
createIsStat ::: createAsStat
784770
}
785771
} else {
786-
WithGlobals(Nil)
772+
WithGlobals.nil
787773 }
788774
}
789775

@@ -816,7 +802,7 @@ private[emitter] final class ClassEmitter(sjsGen: SJSGen) {
816802
}
817803

818804
val createAsArrayOfStatWithGlobals = if (semantics.asInstanceOfs == Unchecked) {
819-
WithGlobals(js.Skip())
805+
WithGlobals.nil
820806
} else {
821807
globalFunctionDef("asArrayOf", className, List(objParam, depthParam), None, {
822808
js.Return {
@@ -835,7 +821,7 @@ private[emitter] final class ClassEmitter(sjsGen: SJSGen) {
835821
createIsArrayOfStat <- createIsArrayOfStatWithGlobals
836822
createAsArrayOfStat <- createAsArrayOfStatWithGlobals
837823
} yield {
838-
List(createIsArrayOfStat, createAsArrayOfStat)
824+
createIsArrayOfStat ::: createAsArrayOfStat
839825
}
840826
}
841827

@@ -855,7 +841,7 @@ private[emitter] final class ClassEmitter(sjsGen: SJSGen) {
855841
superClass: Option[ClassIdent], ancestors: List[ClassName],
856842
jsNativeLoadSpec: Option[JSNativeLoadSpec])(
857843
implicit moduleContext: ModuleContext,
858-
globalKnowledge: GlobalKnowledge, pos: Position): WithGlobals[js.Tree] = {
844+
globalKnowledge: GlobalKnowledge, pos: Position): WithGlobals[List[js.Tree]] = {
859845
import TreeDSL._
860846

861847
val isObjectClass =
@@ -959,7 +945,7 @@ private[emitter] final class ClassEmitter(sjsGen: SJSGen) {
959945

960946
def genModuleAccessor(className: ClassName, kind: ClassKind)(
961947
implicit moduleContext: ModuleContext,
962-
globalKnowledge: GlobalKnowledge, pos: Position): WithGlobals[js.Tree] = {
948+
globalKnowledge: GlobalKnowledge, pos: Position): WithGlobals[List[js.Tree]] = {
963949
import TreeDSL._
964950

965951
val tpe = ClassType(className)
@@ -1013,14 +999,14 @@ private[emitter] final class ClassEmitter(sjsGen: SJSGen) {
1013999
globalFunctionDef("m", className, Nil, None, body)
10141000
}
10151001

1016-
createAccessor.map(js.Block(createModuleInstanceField, _))
1002+
createAccessor.map(createModuleInstanceField :: _)
10171003
}
10181004

10191005
def genExportedMember(className: ClassName, kind: ClassKind, useESClass: Boolean, member: JSMethodPropDef)(
10201006
implicit moduleContext: ModuleContext,
1021-
globalKnowledge: GlobalKnowledge): WithGlobals[js.Tree] = {
1007+
globalKnowledge: GlobalKnowledge): WithGlobals[List[js.Tree]] = {
10221008
member match {
1023-
case m: JSMethodDef => genJSMethod(className, kind, useESClass, m)
1009+
case m: JSMethodDef => genJSMethod(className, kind, useESClass, m).map(_ :: Nil)
10241010
case p: JSPropertyDef => genJSProperty(className, kind, useESClass, p)
10251011
}
10261012
}

0 commit comments

Comments
 (0)
0