Skip to content

Commit c715a47

Browse files
Upgrade to Scala.js 1.11.0 then 1.12.0. (#16411)
2 parents b76824c + 7c2be61 commit c715a47

File tree

9 files changed

+176
-83
lines changed

9 files changed

+176
-83
lines changed

compiler/src/dotty/tools/backend/sjs/JSCodeGen.scala

Lines changed: 133 additions & 68 deletions
Original file line numberDiff line numberDiff line change
@@ -125,7 +125,14 @@ class JSCodeGen()(using genCtx: Context) {
125125
/** Implicitly materializes the current local name generator. */
126126
implicit def implicitLocalNames: LocalNameGenerator = localNames.get
127127

128-
private def currentClassType = encodeClassType(currentClassSym)
128+
def currentThisType: jstpe.Type = {
129+
encodeClassType(currentClassSym) match {
130+
case tpe @ jstpe.ClassType(cls) =>
131+
jstpe.BoxedClassToPrimType.getOrElse(cls, tpe)
132+
case tpe =>
133+
tpe
134+
}
135+
}
129136

130137
/** Returns a new fresh local identifier. */
131138
private def freshLocalIdent()(implicit pos: Position): js.LocalIdent =
@@ -1023,7 +1030,7 @@ class JSCodeGen()(using genCtx: Context) {
10231030
// Constructor of a non-native JS class ------------------------------------
10241031

10251032
def genJSClassCapturesAndConstructor(constructorTrees: List[DefDef])(
1026-
implicit pos: SourcePosition): (List[js.ParamDef], js.JSMethodDef) = {
1033+
implicit pos: SourcePosition): (List[js.ParamDef], js.JSConstructorDef) = {
10271034
/* We need to merge all Scala constructors into a single one because the
10281035
* IR, like JavaScript, only allows a single one.
10291036
*
@@ -1095,20 +1102,21 @@ class JSCodeGen()(using genCtx: Context) {
10951102
(exports.result(), jsClassCaptures.result())
10961103
}
10971104

1105+
// The name 'constructor' is used for error reporting here
10981106
val (formalArgs, restParam, overloadDispatchBody) =
10991107
jsExportsGen.genOverloadDispatch(JSName.Literal("constructor"), exports, jstpe.IntType)
11001108

11011109
val overloadVar = js.VarDef(freshLocalIdent("overload"), NoOriginalName,
11021110
jstpe.IntType, mutable = false, overloadDispatchBody)
11031111

1104-
val ctorStats = genJSClassCtorStats(overloadVar.ref, ctorTree)
1105-
1106-
val constructorBody = js.Block(
1107-
paramVarDefs ::: List(overloadVar, ctorStats, js.Undefined()))
1112+
val constructorBody = wrapJSCtorBody(
1113+
paramVarDefs :+ overloadVar,
1114+
genJSClassCtorBody(overloadVar.ref, ctorTree),
1115+
js.Undefined() :: Nil
1116+
)
11081117

1109-
val constructorDef = js.JSMethodDef(
1110-
js.MemberFlags.empty,
1111-
js.StringLiteral("constructor"),
1118+
val constructorDef = js.JSConstructorDef(
1119+
js.MemberFlags.empty.withNamespace(js.MemberNamespace.Constructor),
11121120
formalArgs, restParam, constructorBody)(OptimizerHints.empty, None)
11131121

11141122
(jsClassCaptures, constructorDef)
@@ -1150,7 +1158,8 @@ class JSCodeGen()(using genCtx: Context) {
11501158
assert(jsSuperCall.isDefined,
11511159
s"Did not find Super call in primary JS construtor at ${dd.sourcePos}")
11521160

1153-
new PrimaryJSCtor(sym, genParamsAndInfo(sym, dd.paramss), jsSuperCall.get :: jsStats.result())
1161+
new PrimaryJSCtor(sym, genParamsAndInfo(sym, dd.paramss),
1162+
js.JSConstructorBody(Nil, jsSuperCall.get, jsStats.result())(dd.span))
11541163
}
11551164

11561165
private def genSecondaryJSClassCtor(dd: DefDef): SplitSecondaryJSCtor = {
@@ -1251,9 +1260,9 @@ class JSCodeGen()(using genCtx: Context) {
12511260
(jsExport, jsClassCaptures)
12521261
}
12531262

1254-
/** generates a sequence of JS constructor statements based on a constructor tree. */
1255-
private def genJSClassCtorStats(overloadVar: js.VarRef,
1256-
ctorTree: ConstructorTree[PrimaryJSCtor])(implicit pos: Position): js.Tree = {
1263+
/** Generates a JS constructor body based on a constructor tree. */
1264+
private def genJSClassCtorBody(overloadVar: js.VarRef,
1265+
ctorTree: ConstructorTree[PrimaryJSCtor])(implicit pos: Position): js.JSConstructorBody = {
12571266

12581267
/* generates a statement that conditionally executes body iff the chosen
12591268
* overload is any of the descendants of `tree` (including itself).
@@ -1348,21 +1357,27 @@ class JSCodeGen()(using genCtx: Context) {
13481357
val primaryCtor = ctorTree.ctor
13491358
val secondaryCtorTrees = ctorTree.subCtors
13501359

1351-
js.Block(
1352-
secondaryCtorTrees.map(preStats(_, primaryCtor.paramsAndInfo)) ++
1353-
primaryCtor.body ++
1360+
wrapJSCtorBody(
1361+
secondaryCtorTrees.map(preStats(_, primaryCtor.paramsAndInfo)),
1362+
primaryCtor.body,
13541363
secondaryCtorTrees.map(postStats(_))
13551364
)
13561365
}
13571366

1367+
private def wrapJSCtorBody(before: List[js.Tree], body: js.JSConstructorBody,
1368+
after: List[js.Tree]): js.JSConstructorBody = {
1369+
js.JSConstructorBody(before ::: body.beforeSuper, body.superCall,
1370+
body.afterSuper ::: after)(body.pos)
1371+
}
1372+
13581373
private sealed trait JSCtor {
13591374
val sym: Symbol
13601375
val paramsAndInfo: List[(Symbol, JSParamInfo)]
13611376
}
13621377

13631378
private class PrimaryJSCtor(val sym: Symbol,
13641379
val paramsAndInfo: List[(Symbol, JSParamInfo)],
1365-
val body: List[js.Tree]) extends JSCtor
1380+
val body: js.JSConstructorBody) extends JSCtor
13661381

13671382
private class SplitSecondaryJSCtor(val sym: Symbol,
13681383
val paramsAndInfo: List[(Symbol, JSParamInfo)],
@@ -1945,9 +1960,9 @@ class JSCodeGen()(using genCtx: Context) {
19451960
}*/
19461961

19471962
thisLocalVarIdent.fold[js.Tree] {
1948-
js.This()(currentClassType)
1963+
js.This()(currentThisType)
19491964
} { thisLocalIdent =>
1950-
js.VarRef(thisLocalIdent)(currentClassType)
1965+
js.VarRef(thisLocalIdent)(currentThisType)
19511966
}
19521967
}
19531968

@@ -2014,9 +2029,7 @@ class JSCodeGen()(using genCtx: Context) {
20142029

20152030
val (exceptValDef, exceptVar) = if (mightCatchJavaScriptException) {
20162031
val valDef = js.VarDef(freshLocalIdent("e"), NoOriginalName,
2017-
encodeClassType(defn.ThrowableClass), mutable = false, {
2018-
genModuleApplyMethod(jsdefn.Runtime_wrapJavaScriptException, origExceptVar :: Nil)
2019-
})
2032+
encodeClassType(defn.ThrowableClass), mutable = false, js.WrapAsThrowable(origExceptVar))
20202033
(valDef, valDef.ref)
20212034
} else {
20222035
(js.Skip(), origExceptVar)
@@ -2307,7 +2320,7 @@ class JSCodeGen()(using genCtx: Context) {
23072320
val privateFieldDefs = mutable.ListBuffer.empty[js.FieldDef]
23082321
val classDefMembers = mutable.ListBuffer.empty[js.MemberDef]
23092322
val instanceMembers = mutable.ListBuffer.empty[js.MemberDef]
2310-
var constructor: Option[js.JSMethodDef] = None
2323+
var constructor: Option[js.JSConstructorDef] = None
23112324

23122325
originalClassDef.memberDefs.foreach {
23132326
case fdef: js.FieldDef =>
@@ -2321,17 +2334,13 @@ class JSCodeGen()(using genCtx: Context) {
23212334
"Non-static, unexported method in non-native JS class")
23222335
classDefMembers += mdef
23232336

2324-
case mdef: js.JSMethodDef =>
2325-
mdef.name match {
2326-
case js.StringLiteral("constructor") =>
2327-
assert(!mdef.flags.namespace.isStatic, "Exported static method")
2328-
assert(constructor.isEmpty, "two ctors in class")
2329-
constructor = Some(mdef)
2337+
case cdef: js.JSConstructorDef =>
2338+
assert(constructor.isEmpty, "two ctors in class")
2339+
constructor = Some(cdef)
23302340

2331-
case _ =>
2332-
assert(!mdef.flags.namespace.isStatic, "Exported static method")
2333-
instanceMembers += mdef
2334-
}
2341+
case mdef: js.JSMethodDef =>
2342+
assert(!mdef.flags.namespace.isStatic, "Exported static method")
2343+
instanceMembers += mdef
23352344

23362345
case property: js.JSPropertyDef =>
23372346
instanceMembers += property
@@ -2361,7 +2370,7 @@ class JSCodeGen()(using genCtx: Context) {
23612370
val jsClassCaptures = originalClassDef.jsClassCaptures.getOrElse {
23622371
throw new AssertionError(s"no class captures for anonymous JS class at $pos")
23632372
}
2364-
val js.JSMethodDef(_, _, ctorParams, ctorRestParam, ctorBody) = constructor.getOrElse {
2373+
val js.JSConstructorDef(_, ctorParams, ctorRestParam, ctorBody) = constructor.getOrElse {
23652374
throw new AssertionError("No ctor found")
23662375
}
23672376
assert(ctorParams.isEmpty && ctorRestParam.isEmpty,
@@ -2396,6 +2405,9 @@ class JSCodeGen()(using genCtx: Context) {
23962405
case mdef: js.MethodDef =>
23972406
throw new AssertionError("unexpected MethodDef")
23982407

2408+
case cdef: js.JSConstructorDef =>
2409+
throw new AssertionError("unexpected JSConstructorDef")
2410+
23992411
case mdef: js.JSMethodDef =>
24002412
implicit val pos = mdef.pos
24012413
val impl = memberLambda(mdef.args, mdef.restParam, mdef.body)
@@ -2468,36 +2480,43 @@ class JSCodeGen()(using genCtx: Context) {
24682480
}
24692481

24702482
// Transform the constructor body.
2471-
val inlinedCtorStats = new ir.Transformers.Transformer {
2472-
override def transform(tree: js.Tree, isStat: Boolean): js.Tree = tree match {
2473-
// The super constructor call. Transform this into a simple new call.
2474-
case js.JSSuperConstructorCall(args) =>
2475-
implicit val pos = tree.pos
2476-
2477-
val newTree = {
2478-
val ident = originalClassDef.superClass.getOrElse(throw new FatalError("No superclass"))
2479-
if (args.isEmpty && ident.name == JSObjectClassName)
2480-
js.JSObjectConstr(Nil)
2481-
else
2482-
js.JSNew(jsSuperClassRef, args)
2483-
}
2484-
2485-
js.Block(
2486-
js.VarDef(selfName, thisOriginalName, jstpe.AnyType, mutable = false, newTree) ::
2487-
memberDefinitions)
2483+
val inlinedCtorStats: List[js.Tree] = {
2484+
val beforeSuper = ctorBody.beforeSuper
24882485

2489-
case js.This() =>
2490-
selfRef(tree.pos)
2486+
val superCall = {
2487+
implicit val pos = ctorBody.superCall.pos
2488+
val js.JSSuperConstructorCall(args) = ctorBody.superCall
24912489

2492-
// Don't traverse closure boundaries
2493-
case closure: js.Closure =>
2494-
val newCaptureValues = closure.captureValues.map(transformExpr)
2495-
closure.copy(captureValues = newCaptureValues)(closure.pos)
2490+
val newTree = {
2491+
val ident = originalClassDef.superClass.getOrElse(throw new FatalError("No superclass"))
2492+
if (args.isEmpty && ident.name == JSObjectClassName)
2493+
js.JSObjectConstr(Nil)
2494+
else
2495+
js.JSNew(jsSuperClassRef, args)
2496+
}
24962497

2497-
case tree =>
2498-
super.transform(tree, isStat)
2498+
val selfVarDef = js.VarDef(selfName, thisOriginalName, jstpe.AnyType, mutable = false, newTree)
2499+
selfVarDef :: memberDefinitions
24992500
}
2500-
}.transform(ctorBody, isStat = true)
2501+
2502+
// After the super call, substitute `selfRef` for `This()`
2503+
val afterSuper = new ir.Transformers.Transformer {
2504+
override def transform(tree: js.Tree, isStat: Boolean): js.Tree = tree match {
2505+
case js.This() =>
2506+
selfRef(tree.pos)
2507+
2508+
// Don't traverse closure boundaries
2509+
case closure: js.Closure =>
2510+
val newCaptureValues = closure.captureValues.map(transformExpr)
2511+
closure.copy(captureValues = newCaptureValues)(closure.pos)
2512+
2513+
case tree =>
2514+
super.transform(tree, isStat)
2515+
}
2516+
}.transformStats(ctorBody.afterSuper)
2517+
2518+
beforeSuper ::: superCall ::: afterSuper
2519+
}
25012520

25022521
val closure = js.Closure(arrow = true, jsClassCaptures, Nil, None,
25032522
js.Block(inlinedCtorStats, selfRef), jsSuperClassValue :: args)
@@ -2989,14 +3008,12 @@ class JSCodeGen()(using genCtx: Context) {
29893008
implicit val pos: SourcePosition = tree.sourcePos
29903009
val exception = args.head
29913010
val genException = genExpr(exception)
2992-
js.Throw {
2993-
if (exception.tpe.typeSymbol.derivesFrom(jsdefn.JavaScriptExceptionClass)) {
2994-
genModuleApplyMethod(
2995-
jsdefn.Runtime_unwrapJavaScriptException,
2996-
List(genException))
2997-
} else {
2998-
genException
2999-
}
3011+
genException match {
3012+
case js.New(cls, _, _) if cls != JavaScriptExceptionClassName =>
3013+
// Common case where ex is neither null nor a js.JavaScriptException
3014+
js.Throw(genException)
3015+
case _ =>
3016+
js.Throw(js.UnwrapFromThrowable(genException))
30003017
}
30013018
}
30023019

@@ -3982,6 +3999,53 @@ class JSCodeGen()(using genCtx: Context) {
39823999
js.JSFunctionApply(fVarDef.ref, List(keyVarRef))
39834000
}))
39844001

4002+
case JS_THROW =>
4003+
// js.special.throw(arg)
4004+
js.Throw(genArgs1)
4005+
4006+
case JS_TRY_CATCH =>
4007+
/* js.special.tryCatch(arg1, arg2)
4008+
*
4009+
* We must generate:
4010+
*
4011+
* val body = arg1
4012+
* val handler = arg2
4013+
* try {
4014+
* body()
4015+
* } catch (e) {
4016+
* handler(e)
4017+
* }
4018+
*
4019+
* with temporary vals, because `arg2` must be evaluated before
4020+
* `body` executes. Moreover, exceptions thrown while evaluating
4021+
* the function values `arg1` and `arg2` must not be caught.
4022+
*/
4023+
val (arg1, arg2) = genArgs2
4024+
val bodyVarDef = js.VarDef(freshLocalIdent("body"), NoOriginalName,
4025+
jstpe.AnyType, mutable = false, arg1)
4026+
val handlerVarDef = js.VarDef(freshLocalIdent("handler"), NoOriginalName,
4027+
jstpe.AnyType, mutable = false, arg2)
4028+
val exceptionVarIdent = freshLocalIdent("e")
4029+
val exceptionVarRef = js.VarRef(exceptionVarIdent)(jstpe.AnyType)
4030+
js.Block(
4031+
bodyVarDef,
4032+
handlerVarDef,
4033+
js.TryCatch(
4034+
js.JSFunctionApply(bodyVarDef.ref, Nil),
4035+
exceptionVarIdent,
4036+
NoOriginalName,
4037+
js.JSFunctionApply(handlerVarDef.ref, List(exceptionVarRef))
4038+
)(jstpe.AnyType)
4039+
)
4040+
4041+
case WRAP_AS_THROWABLE =>
4042+
// js.special.wrapAsThrowable(arg)
4043+
js.WrapAsThrowable(genArgs1)
4044+
4045+
case UNWRAP_FROM_THROWABLE =>
4046+
// js.special.unwrapFromThrowable(arg)
4047+
js.UnwrapFromThrowable(genArgs1)
4048+
39854049
case UNION_FROM | UNION_FROM_TYPE_CONSTRUCTOR =>
39864050
/* js.|.from and js.|.fromTypeConstructor
39874051
* We should not have to deal with those. They have a perfectly valid
@@ -4764,6 +4828,7 @@ object JSCodeGen {
47644828

47654829
private val NullPointerExceptionClass = ClassName("java.lang.NullPointerException")
47664830
private val JSObjectClassName = ClassName("scala.scalajs.js.Object")
4831+
private val JavaScriptExceptionClassName = ClassName("scala.scalajs.js.JavaScriptException")
47674832

47684833
private val ObjectClassRef = jstpe.ClassRef(ir.Names.ObjectClass)
47694834

compiler/src/dotty/tools/backend/sjs/JSDefinitions.scala

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -162,10 +162,6 @@ final class JSDefinitions()(using Context) {
162162

163163
@threadUnsafe lazy val RuntimePackageVal = requiredPackage("scala.scalajs.runtime")
164164
@threadUnsafe lazy val RuntimePackageClass = RuntimePackageVal.moduleClass.asClass
165-
@threadUnsafe lazy val RuntimePackage_wrapJavaScriptExceptionR = RuntimePackageClass.requiredMethodRef("wrapJavaScriptException")
166-
def Runtime_wrapJavaScriptException(using Context) = RuntimePackage_wrapJavaScriptExceptionR.symbol
167-
@threadUnsafe lazy val Runtime_unwrapJavaScriptExceptionR = RuntimePackageClass.requiredMethodRef("unwrapJavaScriptException")
168-
def Runtime_unwrapJavaScriptException(using Context) = Runtime_unwrapJavaScriptExceptionR.symbol
169165
@threadUnsafe lazy val Runtime_toScalaVarArgsR = RuntimePackageClass.requiredMethodRef("toScalaVarArgs")
170166
def Runtime_toScalaVarArgs(using Context) = Runtime_toScalaVarArgsR.symbol
171167
@threadUnsafe lazy val Runtime_toJSVarArgsR = RuntimePackageClass.requiredMethodRef("toJSVarArgs")
@@ -206,6 +202,14 @@ final class JSDefinitions()(using Context) {
206202
def Special_instanceof(using Context) = Special_instanceofR.symbol
207203
@threadUnsafe lazy val Special_strictEqualsR = SpecialPackageClass.requiredMethodRef("strictEquals")
208204
def Special_strictEquals(using Context) = Special_strictEqualsR.symbol
205+
@threadUnsafe lazy val Special_throwR = SpecialPackageClass.requiredMethodRef("throw")
206+
def Special_throw(using Context) = Special_throwR.symbol
207+
@threadUnsafe lazy val Special_tryCatchR = SpecialPackageClass.requiredMethodRef("tryCatch")
208+
def Special_tryCatch(using Context) = Special_tryCatchR.symbol
209+
@threadUnsafe lazy val Special_wrapAsThrowableR = SpecialPackageClass.requiredMethodRef("wrapAsThrowable")
210+
def Special_wrapAsThrowable(using Context) = Special_wrapAsThrowableR.symbol
211+
@threadUnsafe lazy val Special_unwrapFromThrowableR = SpecialPackageClass.requiredMethodRef("unwrapFromThrowable")
212+
def Special_unwrapFromThrowable(using Context) = Special_unwrapFromThrowableR.symbol
209213

210214
@threadUnsafe lazy val WrappedArrayType: TypeRef = requiredClassRef("scala.scalajs.js.WrappedArray")
211215
def WrappedArrayClass(using Context) = WrappedArrayType.symbol.asClass

compiler/src/dotty/tools/backend/sjs/JSExportsGen.scala

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -649,7 +649,7 @@ final class JSExportsGen(jsCodeGen: JSCodeGen)(using Context) {
649649
js.LoadJSConstructor(encodeClassName(superClassSym))
650650
}
651651

652-
val receiver = js.This()(jstpe.AnyType)
652+
val receiver = js.This()(currentThisType)
653653
val nameTree = genExpr(sym.jsName)
654654

655655
if (sym.isJSGetter) {
@@ -753,7 +753,7 @@ final class JSExportsGen(jsCodeGen: JSCodeGen)(using Context) {
753753
genApplyMethodMaybeStatically(receiver, modAccessor, Nil)
754754
}
755755
} else {
756-
js.This()(encodeClassType(targetSym))
756+
js.This()(currentThisType)
757757
}
758758
}
759759

@@ -810,7 +810,7 @@ final class JSExportsGen(jsCodeGen: JSCodeGen)(using Context) {
810810

811811
def receiver =
812812
if (static) genLoadModule(sym.owner)
813-
else js.This()(encodeClassType(currentClass))
813+
else js.This()(currentThisType)
814814

815815
def boxIfNeeded(call: js.Tree): js.Tree =
816816
box(call, atPhase(elimErasedValueTypePhase)(sym.info.resultType))

0 commit comments

Comments
 (0)