@@ -2702,7 +2702,7 @@ class JSCodeGen()(using genCtx: Context) {
27022702
27032703 case JSCallingConvention .Call =>
27042704 requireNotSuper()
2705- if (jsdefn.isJSThisFunctionClass( sym.owner))
2705+ if (sym.owner.isSubClass(jsdefn. JSThisFunctionClass ))
27062706 js.JSMethodApply (ruleOutGlobalScope(receiver), js.StringLiteral (" call" ), args)
27072707 else
27082708 js.JSFunctionApply (ruleOutGlobalScope(receiver), args)
@@ -3052,17 +3052,35 @@ class JSCodeGen()(using genCtx: Context) {
30523052 }
30533053 val (formalCaptures, actualCaptures) = formalAndActualCaptures.unzip
30543054
3055+ val funInterfaceSym = functionalInterface.tpe.typeSymbol
3056+ val hasRepeatedParam = {
3057+ funInterfaceSym.exists && {
3058+ val Seq (samMethodDenot) = funInterfaceSym.info.possibleSamMethods
3059+ val samMethod = samMethodDenot.symbol
3060+ atPhase(elimRepeatedPhase)(samMethod.info.paramInfoss.flatten.exists(_.isRepeatedParam))
3061+ }
3062+ }
3063+
30553064 val formalParamNames = sym.info.paramNamess.flatten.drop(envSize)
30563065 val formalParamTypes = sym.info.paramInfoss.flatten.drop(envSize)
3057- val formalParamNamesAndTypes = formalParamNames.zip(formalParamTypes)
3058- val formalAndActualParams = formalParamNamesAndTypes.map {
3059- case (name, tpe) =>
3066+ val formalParamRepeateds =
3067+ if (hasRepeatedParam) (0 until (formalParamTypes.size - 1 )).map(_ => false ) :+ true
3068+ else (0 until formalParamTypes.size).map(_ => false )
3069+
3070+ val formalAndActualParams = formalParamNames.lazyZip(formalParamTypes).lazyZip(formalParamRepeateds).map {
3071+ (name, tpe, repeated) =>
30603072 val formalParam = js.ParamDef (freshLocalIdent(name.toString),
30613073 OriginalName (name.toString), jstpe.AnyType , mutable = false )
3062- val actualParam = unbox(formalParam.ref, tpe)
3074+ val actualParam =
3075+ if (repeated) genJSArrayToVarArgs(formalParam.ref)(tree.sourcePos)
3076+ else unbox(formalParam.ref, tpe)
30633077 (formalParam, actualParam)
30643078 }
3065- val (formalParams, actualParams) = formalAndActualParams.unzip
3079+ val (formalAndRestParams, actualParams) = formalAndActualParams.unzip
3080+
3081+ val (formalParams, restParam) =
3082+ if (hasRepeatedParam) (formalAndRestParams.init, Some (formalAndRestParams.last))
3083+ else (formalAndRestParams, None )
30663084
30673085 val genBody = {
30683086 val call = if (isStaticCall) {
@@ -3077,34 +3095,41 @@ class JSCodeGen()(using genCtx: Context) {
30773095 box(call, sym.info.finalResultType)
30783096 }
30793097
3080- val funInterfaceSym = functionalInterface.tpe.typeSymbol
3098+ val isThisFunction = funInterfaceSym.isSubClass(jsdefn.JSThisFunctionClass ) && {
3099+ val ok = formalParams.nonEmpty
3100+ if (! ok)
3101+ report.error(" The SAM or apply method for a js.ThisFunction must have a leading non-varargs parameter" , tree)
3102+ ok
3103+ }
30813104
3082- if (jsdefn.isJSThisFunctionClass(funInterfaceSym) ) {
3105+ if (isThisFunction ) {
30833106 val thisParam :: otherParams = formalParams
30843107 js.Closure (
30853108 arrow = false ,
30863109 formalCaptures,
30873110 otherParams,
3088- None ,
3111+ restParam ,
30893112 js.Block (
30903113 js.VarDef (thisParam.name, thisParam.originalName,
30913114 thisParam.ptpe, mutable = false ,
30923115 js.This ()(thisParam.ptpe)(thisParam.pos))(thisParam.pos),
30933116 genBody),
30943117 actualCaptures)
30953118 } else {
3096- val closure = js.Closure (arrow = true , formalCaptures, formalParams, None , genBody, actualCaptures)
3119+ val closure = js.Closure (arrow = true , formalCaptures, formalParams, restParam , genBody, actualCaptures)
30973120
3098- if (jsdefn.isJSFunctionClass(funInterfaceSym)) {
3099- closure
3100- } else {
3121+ if (! funInterfaceSym.exists || defn.isFunctionClass(funInterfaceSym)) {
31013122 assert(! funInterfaceSym.exists || defn.isFunctionClass(funInterfaceSym),
31023123 s " Invalid functional interface $funInterfaceSym reached the back-end " )
31033124 val formalCount = formalParams.size
31043125 val cls = ClassName (" scala.scalajs.runtime.AnonFunction" + formalCount)
31053126 val ctorName = MethodName .constructor(
31063127 jstpe.ClassRef (ClassName (" scala.scalajs.js.Function" + formalCount)) :: Nil )
31073128 js.New (cls, js.MethodIdent (ctorName), List (closure))
3129+ } else {
3130+ assert(funInterfaceSym.isJSType,
3131+ s " Invalid functional interface $funInterfaceSym reached the back-end " )
3132+ closure
31083133 }
31093134 }
31103135 }
0 commit comments