diff --git a/compiler/src/dotty/tools/backend/sjs/JSCodeGen.scala b/compiler/src/dotty/tools/backend/sjs/JSCodeGen.scala index 535da488a013..deaad2d51dbc 100644 --- a/compiler/src/dotty/tools/backend/sjs/JSCodeGen.scala +++ b/compiler/src/dotty/tools/backend/sjs/JSCodeGen.scala @@ -2569,6 +2569,8 @@ class JSCodeGen()(using genCtx: Context) { genCoercion(tree, receiver, code) else if (code == JSPrimitives.THROW) genThrow(tree, args) + else if (code == JSPrimitives.NEW_ARRAY) + genNewArray(tree, args) else if (JSPrimitives.isJSPrimitive(code)) genJSPrimitive(tree, args, code, isStat) else @@ -3038,6 +3040,24 @@ class JSCodeGen()(using genCtx: Context) { } } + /** Gen a call to the special `newArray` method. */ + private def genNewArray(tree: Apply, args: List[Tree]): js.Tree = { + implicit val pos: SourcePosition = tree.sourcePos + + val List(elemClazz, Literal(arrayClassConstant), dimsArray: JavaSeqLiteral) = args: @unchecked + + dimsArray.elems match { + case singleDim :: Nil => + // Use a js.NewArray + val arrayTypeRef = toTypeRef(arrayClassConstant.typeValue).asInstanceOf[jstpe.ArrayTypeRef] + js.NewArray(arrayTypeRef, genExpr(singleDim)) + case _ => + // Delegate to jlr.Array.newInstance + js.ApplyStatic(js.ApplyFlags.empty, JLRArrayClassName, js.MethodIdent(JLRArrayNewInstanceMethodName), + List(genExpr(elemClazz), genJavaSeqLiteral(dimsArray)))(jstpe.AnyType) + } + } + /** Gen a "normal" apply (to a true method). * * But even these are further refined into: @@ -4846,7 +4866,7 @@ class JSCodeGen()(using genCtx: Context) { object JSCodeGen { - private val NullPointerExceptionClass = ClassName("java.lang.NullPointerException") + private val JLRArrayClassName = ClassName("java.lang.reflect.Array") private val JSObjectClassName = ClassName("scala.scalajs.js.Object") private val JavaScriptExceptionClassName = ClassName("scala.scalajs.js.JavaScriptException") @@ -4856,6 +4876,9 @@ object JSCodeGen { private val selectedValueMethodName = MethodName("selectedValue", Nil, ObjectClassRef) + private val JLRArrayNewInstanceMethodName = + MethodName("newInstance", List(jstpe.ClassRef(jsNames.ClassClass), jstpe.ArrayTypeRef(jstpe.IntRef, 1)), ObjectClassRef) + private val ObjectArgConstructorName = MethodName.constructor(List(ObjectClassRef)) private val thisOriginalName = OriginalName("this") diff --git a/compiler/src/dotty/tools/backend/sjs/JSPrimitives.scala b/compiler/src/dotty/tools/backend/sjs/JSPrimitives.scala index 60c671b21c5b..41e62094b04f 100644 --- a/compiler/src/dotty/tools/backend/sjs/JSPrimitives.scala +++ b/compiler/src/dotty/tools/backend/sjs/JSPrimitives.scala @@ -47,9 +47,10 @@ object JSPrimitives { inline val UNWRAP_FROM_THROWABLE = WRAP_AS_THROWABLE + 1 // js.special.unwrapFromThrowable inline val DEBUGGER = UNWRAP_FROM_THROWABLE + 1 // js.special.debugger - inline val THROW = DEBUGGER + 1 + inline val THROW = DEBUGGER + 1 // .throw + inline val NEW_ARRAY = THROW + 1 // scala.runtime.Arrays.newArray - inline val UNION_FROM = THROW + 1 // js.|.from + inline val UNION_FROM = NEW_ARRAY + 1 // js.|.from inline val UNION_FROM_TYPE_CONSTRUCTOR = UNION_FROM + 1 // js.|.fromTypeConstructor inline val REFLECT_SELECTABLE_SELECTDYN = UNION_FROM_TYPE_CONSTRUCTOR + 1 // scala.reflect.Selectable.selectDynamic @@ -135,6 +136,7 @@ class JSPrimitives(ictx: Context) extends DottyPrimitives(ictx) { addPrimitive(jsdefn.Special_debugger, DEBUGGER) addPrimitive(defn.throwMethod, THROW) + addPrimitive(defn.newArrayMethod, NEW_ARRAY) addPrimitive(jsdefn.PseudoUnion_from, UNION_FROM) addPrimitive(jsdefn.PseudoUnion_fromTypeConstructor, UNION_FROM_TYPE_CONSTRUCTOR)