Skip to content

Commit

Permalink
Scala.js: Upgrade to Scala.js 1.18.1.
Browse files Browse the repository at this point in the history
And port the changes that were made to the compiler backend.
Most notably, the changes from the following upstream PRs:

* Introduce non-nullable reference types in the IR.
  scala-js/scala-js#5018
* Opt: Remove useless *Ident indirections in the IR model.
  scala-js/scala-js#5092
* Merge the IR node This into VarRef, with a magic LocalName.
  scala-js/scala-js#5090
* Merge several IR nodes into UnaryOp.
  scala-js/scala-js#5088
* Restrict usages of StoreModule even further.
  scala-js/scala-js#5059
* Allow Return arg to be a void if the target Labeled is a void.
  scala-js/scala-js#5074
* Rename NoType to VoidType and print it as "void".
  scala-js/scala-js#5061
  • Loading branch information
sjrd committed Jan 17, 2025
1 parent 203bf23 commit 1b30bdc
Show file tree
Hide file tree
Showing 8 changed files with 112 additions and 119 deletions.
166 changes: 81 additions & 85 deletions compiler/src/dotty/tools/backend/sjs/JSCodeGen.scala

Large diffs are not rendered by default.

2 changes: 0 additions & 2 deletions compiler/src/dotty/tools/backend/sjs/JSDefinitions.scala
Original file line number Diff line number Diff line change
Expand Up @@ -179,8 +179,6 @@ final class JSDefinitions()(using Context) {
def Runtime_createLocalJSClass(using Context) = Runtime_createLocalJSClassR.symbol
@threadUnsafe lazy val Runtime_withContextualJSClassValueR = RuntimePackageClass.requiredMethodRef("withContextualJSClassValue")
def Runtime_withContextualJSClassValue(using Context) = Runtime_withContextualJSClassValueR.symbol
@threadUnsafe lazy val Runtime_linkingInfoR = RuntimePackageClass.requiredMethodRef("linkingInfo")
def Runtime_linkingInfo(using Context) = Runtime_linkingInfoR.symbol
@threadUnsafe lazy val Runtime_dynamicImportR = RuntimePackageClass.requiredMethodRef("dynamicImport")
def Runtime_dynamicImport(using Context) = Runtime_dynamicImportR.symbol

Expand Down
28 changes: 13 additions & 15 deletions compiler/src/dotty/tools/backend/sjs/JSEncoding.scala
Original file line number Diff line number Diff line change
Expand Up @@ -135,16 +135,13 @@ object JSEncoding {
def freshLabelName(base: String): LabelName =
freshLabelName(LabelName(base))

def freshLabelIdent(base: String)(implicit pos: ir.Position): js.LabelIdent =
js.LabelIdent(freshLabelName(base))

def labelSymbolName(sym: Symbol)(using Context): LabelName =
labelSymbolNames.getOrElseUpdate(sym, freshLabelName(sym.javaSimpleName))

def getEnclosingReturnLabel()(implicit pos: ir.Position): js.LabelIdent = {
def getEnclosingReturnLabel(): LabelName = {
if (returnLabelName.isEmpty)
returnLabelName = Some(freshLabelName("_return"))
js.LabelIdent(returnLabelName.get)
returnLabelName.get
}

/* If this `LocalNameGenerator` has a `returnLabelName` (often added in the
Expand All @@ -155,7 +152,7 @@ object JSEncoding {
case None =>
body
case Some(labelName) =>
js.Labeled(js.LabelIdent(labelName), tpe, body)
js.Labeled(labelName, tpe, body)
}
}
}
Expand All @@ -166,10 +163,9 @@ object JSEncoding {

// Encoding methods ----------------------------------------------------------

def encodeLabelSym(sym: Symbol)(
implicit ctx: Context, pos: ir.Position, localNames: LocalNameGenerator): js.LabelIdent = {
def encodeLabelSym(sym: Symbol)(implicit ctx: Context, localNames: LocalNameGenerator): LabelName = {
require(sym.is(Flags.Label), "encodeLabelSym called with non-label symbol: " + sym)
js.LabelIdent(localNames.labelSymbolName(sym))
localNames.labelSymbolName(sym)
}

def encodeFieldSym(sym: Symbol)(implicit ctx: Context, pos: ir.Position): js.FieldIdent =
Expand Down Expand Up @@ -248,11 +244,13 @@ object JSEncoding {
private def paramOrResultTypeRef(tpe: Type)(using Context): jstpe.TypeRef =
toParamOrResultTypeRef(toTypeRef(tpe))

def encodeLocalSym(sym: Symbol)(
implicit ctx: Context, pos: ir.Position, localNames: LocalNameGenerator): js.LocalIdent = {
def encodeLocalSym(sym: Symbol)(using Context, ir.Position, LocalNameGenerator): js.LocalIdent =
js.LocalIdent(encodeLocalSymName(sym))

def encodeLocalSymName(sym: Symbol)(using ctx: Context, localNames: LocalNameGenerator): LocalName = {
require(!sym.owner.isClass && sym.isTerm && !sym.is(Flags.Method) && !sym.is(Flags.Module),
"encodeLocalSym called with non-local symbol: " + sym)
js.LocalIdent(localNames.localSymbolName(sym))
localNames.localSymbolName(sym)
}

def encodeClassType(sym: Symbol)(using Context): jstpe.Type = {
Expand All @@ -261,7 +259,7 @@ object JSEncoding {
else {
assert(sym != defn.ArrayClass,
"encodeClassType() cannot be called with ArrayClass")
jstpe.ClassType(encodeClassName(sym))
jstpe.ClassType(encodeClassName(sym), nullable = true)
}
}

Expand Down Expand Up @@ -324,10 +322,10 @@ object JSEncoding {
else if (sym == defn.NullClass)
jstpe.NullType
else
jstpe.ClassType(typeRef.className)
jstpe.ClassType(typeRef.className, nullable = true)

case typeRef: jstpe.ArrayTypeRef =>
jstpe.ArrayType(typeRef)
jstpe.ArrayType(typeRef, nullable = true)
}
}

Expand Down
26 changes: 13 additions & 13 deletions compiler/src/dotty/tools/backend/sjs/JSExportsGen.scala
Original file line number Diff line number Diff line change
Expand Up @@ -652,7 +652,7 @@ final class JSExportsGen(jsCodeGen: JSCodeGen)(using Context) {
val superClass = {
val superClassSym = currentClassSym.asClass.superClass
if (superClassSym.isNestedJSClass)
js.VarRef(js.LocalIdent(JSSuperClassParamName))(jstpe.AnyType)
js.VarRef(JSSuperClassParamName)(jstpe.AnyType)
else
js.LoadJSConstructor(encodeClassName(superClassSym))
}
Expand Down Expand Up @@ -793,7 +793,7 @@ final class JSExportsGen(jsCodeGen: JSCodeGen)(using Context) {
}

// #15419 If the getter returns void, we must "box" it by returning undefined
if (callGetter.tpe == jstpe.NoType)
if (callGetter.tpe == jstpe.VoidType)
js.Block(callGetter, js.Undefined())
else
callGetter
Expand Down Expand Up @@ -837,7 +837,7 @@ final class JSExportsGen(jsCodeGen: JSCodeGen)(using Context) {
}

private def genThrowTypeError(msg: String = "No matching overload")(implicit pos: Position): js.Tree =
js.Throw(js.JSNew(js.JSGlobalRef("TypeError"), js.StringLiteral(msg) :: Nil))
js.UnaryOp(js.UnaryOp.Throw, js.JSNew(js.JSGlobalRef("TypeError"), js.StringLiteral(msg) :: Nil))

abstract class Exported(
val sym: Symbol,
Expand Down Expand Up @@ -935,9 +935,9 @@ final class JSExportsGen(jsCodeGen: JSCodeGen)(using Context) {
import dotty.tools.sjs.ir.Names

(toIRType(tpe): @unchecked) match {
case jstpe.AnyType => NoTypeTest
case jstpe.AnyType | jstpe.AnyNotNullType => NoTypeTest

case jstpe.NoType => PrimitiveTypeTest(jstpe.UndefType, 0)
case jstpe.VoidType => PrimitiveTypeTest(jstpe.UndefType, 0)
case jstpe.BooleanType => PrimitiveTypeTest(jstpe.BooleanType, 1)
case jstpe.CharType => PrimitiveTypeTest(jstpe.CharType, 2)
case jstpe.ByteType => PrimitiveTypeTest(jstpe.ByteType, 3)
Expand All @@ -947,11 +947,11 @@ final class JSExportsGen(jsCodeGen: JSCodeGen)(using Context) {
case jstpe.FloatType => PrimitiveTypeTest(jstpe.FloatType, 7)
case jstpe.DoubleType => PrimitiveTypeTest(jstpe.DoubleType, 8)

case jstpe.ClassType(Names.BoxedUnitClass) => PrimitiveTypeTest(jstpe.UndefType, 0)
case jstpe.ClassType(Names.BoxedStringClass) => PrimitiveTypeTest(jstpe.StringType, 9)
case jstpe.ClassType(_) => InstanceOfTypeTest(tpe)
case jstpe.ClassType(Names.BoxedUnitClass, _) => PrimitiveTypeTest(jstpe.UndefType, 0)
case jstpe.ClassType(Names.BoxedStringClass, _) => PrimitiveTypeTest(jstpe.StringType, 9)
case jstpe.ClassType(_, _) => InstanceOfTypeTest(tpe)

case jstpe.ArrayType(_) => InstanceOfTypeTest(tpe)
case jstpe.ArrayType(_, _) => InstanceOfTypeTest(tpe)
}
}
}
Expand Down Expand Up @@ -998,7 +998,7 @@ final class JSExportsGen(jsCodeGen: JSCodeGen)(using Context) {

def genArgRef(index: Int)(implicit pos: Position): js.Tree = {
if (index < minArgc)
js.VarRef(js.LocalIdent(fixedParamNames(index)))(jstpe.AnyType)
js.VarRef(fixedParamNames(index))(jstpe.AnyType)
else
js.JSSelect(genRestArgRef(), js.IntLiteral(index - minArgc))
}
Expand All @@ -1014,16 +1014,16 @@ final class JSExportsGen(jsCodeGen: JSCodeGen)(using Context) {

def genRestArgRef()(implicit pos: Position): js.Tree = {
assert(needsRestParam, s"trying to generate a reference to non-existent rest param at $pos")
js.VarRef(js.LocalIdent(restParamName))(jstpe.AnyType)
js.VarRef(restParamName)(jstpe.AnyType)
}

def genAllArgsRefsForForwarder()(implicit pos: Position): List[js.TreeOrJSSpread] = {
val fixedArgRefs = fixedParamNames.toList.map { paramName =>
js.VarRef(js.LocalIdent(paramName))(jstpe.AnyType)
js.VarRef(paramName)(jstpe.AnyType)
}

if (needsRestParam) {
val restArgRef = js.VarRef(js.LocalIdent(restParamName))(jstpe.AnyType)
val restArgRef = js.VarRef(restParamName)(jstpe.AnyType)
fixedArgRefs :+ js.JSSpread(restArgRef)
} else {
fixedArgRefs
Expand Down
4 changes: 1 addition & 3 deletions compiler/src/dotty/tools/backend/sjs/JSPrimitives.scala
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,7 @@ object JSPrimitives {
inline val CREATE_INNER_JS_CLASS = CONSTRUCTOROF + 1 // runtime.createInnerJSClass
inline val CREATE_LOCAL_JS_CLASS = CREATE_INNER_JS_CLASS + 1 // runtime.createLocalJSClass
inline val WITH_CONTEXTUAL_JS_CLASS_VALUE = CREATE_LOCAL_JS_CLASS + 1 // runtime.withContextualJSClassValue
inline val LINKING_INFO = WITH_CONTEXTUAL_JS_CLASS_VALUE + 1 // runtime.linkingInfo
inline val DYNAMIC_IMPORT = LINKING_INFO + 1 // runtime.dynamicImport
inline val DYNAMIC_IMPORT = WITH_CONTEXTUAL_JS_CLASS_VALUE + 1 // runtime.dynamicImport

inline val STRICT_EQ = DYNAMIC_IMPORT + 1 // js.special.strictEquals
inline val IN = STRICT_EQ + 1 // js.special.in
Expand Down Expand Up @@ -122,7 +121,6 @@ class JSPrimitives(ictx: Context) extends DottyPrimitives(ictx) {
addPrimitive(jsdefn.Runtime_createInnerJSClass, CREATE_INNER_JS_CLASS)
addPrimitive(jsdefn.Runtime_createLocalJSClass, CREATE_LOCAL_JS_CLASS)
addPrimitive(jsdefn.Runtime_withContextualJSClassValue, WITH_CONTEXTUAL_JS_CLASS_VALUE)
addPrimitive(jsdefn.Runtime_linkingInfo, LINKING_INFO)
addPrimitive(jsdefn.Runtime_dynamicImport, DYNAMIC_IMPORT)

addPrimitive(jsdefn.Special_strictEquals, STRICT_EQ)
Expand Down
1 change: 1 addition & 0 deletions project/Build.scala
Original file line number Diff line number Diff line change
Expand Up @@ -1669,6 +1669,7 @@ object Build {
"productionMode" -> sems.productionMode,
"esVersion" -> linkerConfig.esFeatures.esVersion.edition,
"useECMAScript2015Semantics" -> linkerConfig.esFeatures.useECMAScript2015Semantics,
"isWebAssembly" -> linkerConfig.experimentalUseWebAssembly,
)
}.taskValue,

Expand Down
2 changes: 1 addition & 1 deletion project/plugins.sbt
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
libraryDependencySchemes +=
"org.scala-lang.modules" %% "scala-xml" % VersionScheme.Always

addSbtPlugin("org.scala-js" % "sbt-scalajs" % "1.16.0")
addSbtPlugin("org.scala-js" % "sbt-scalajs" % "1.18.1")

addSbtPlugin("org.xerial.sbt" % "sbt-sonatype" % "3.9.21")

Expand Down
2 changes: 2 additions & 0 deletions tests/run/t8601d.scala
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
// scalajs: --compliant-semantics

object Test {
def monitor(x: AnyRef): Unit = {x.synchronized(()); ()}
def check(x: => Any) = try { x; sys.error("failed to throw NPE") } catch { case _: NullPointerException => }
Expand Down

0 comments on commit 1b30bdc

Please sign in to comment.