@@ -3192,7 +3192,7 @@ class JSCodeGen()(using genCtx: Context) {
31923192 case resType => resType
31933193 }
31943194
3195- var clauses : List [(List [js.Tree ], js.Tree )] = Nil
3195+ var clauses : List [(List [js.MatchableLiteral ], js.Tree )] = Nil
31963196 var optDefaultClause : Option [js.Tree ] = None
31973197
31983198 for (caze @ CaseDef (pat, guard, body) <- cases) {
@@ -3201,19 +3201,29 @@ class JSCodeGen()(using genCtx: Context) {
32013201
32023202 val genBody = genStatOrExpr(body, isStat)
32033203
3204+ def invalidCase (): Nothing =
3205+ abortMatch(" Invalid case" )
3206+
3207+ def genMatchableLiteral (tree : Literal ): js.MatchableLiteral = {
3208+ genExpr(tree) match {
3209+ case matchableLiteral : js.MatchableLiteral => matchableLiteral
3210+ case otherExpr => invalidCase()
3211+ }
3212+ }
3213+
32043214 pat match {
32053215 case lit : Literal =>
3206- clauses = (List (genExpr (lit)), genBody) :: clauses
3216+ clauses = (List (genMatchableLiteral (lit)), genBody) :: clauses
32073217 case Ident (nme.WILDCARD ) =>
32083218 optDefaultClause = Some (genBody)
32093219 case Alternative (alts) =>
32103220 val genAlts = alts.map {
3211- case lit : Literal => genExpr (lit)
3212- case _ => abortMatch( " Invalid case in alternative " )
3221+ case lit : Literal => genMatchableLiteral (lit)
3222+ case _ => invalidCase( )
32133223 }
32143224 clauses = (genAlts, genBody) :: clauses
32153225 case _ =>
3216- abortMatch( " Invalid case pattern " )
3226+ invalidCase( )
32173227 }
32183228 }
32193229
@@ -3228,10 +3238,6 @@ class JSCodeGen()(using genCtx: Context) {
32283238 * case is a typical product of `match`es that are full of
32293239 * `case n if ... =>`, which are used instead of `if` chains for
32303240 * convenience and/or readability.
3231- *
3232- * When no optimization applies, and any of the case values is not a
3233- * literal int, we emit a series of `if..else` instead of a `js.Match`.
3234- * This became necessary in 2.13.2 with strings and nulls.
32353241 */
32363242 def isInt (tree : js.Tree ): Boolean = tree.tpe == jstpe.IntType
32373243
@@ -3251,32 +3257,8 @@ class JSCodeGen()(using genCtx: Context) {
32513257 js.If (js.BinaryOp (op, genSelector, uniqueAlt), caseRhs, defaultClause)(resultType)
32523258
32533259 case _ =>
3254- if (isInt(genSelector) &&
3255- clauses.forall(_._1.forall(_.isInstanceOf [js.IntLiteral ]))) {
3256- // We have int literals only: use a js.Match
3257- val intClauses = clauses.asInstanceOf [List [(List [js.IntLiteral ], js.Tree )]]
3258- js.Match (genSelector, intClauses, defaultClause)(resultType)
3259- } else {
3260- // We have other stuff: generate an if..else chain
3261- val (tempSelectorDef, tempSelectorRef) = genSelector match {
3262- case varRef : js.VarRef =>
3263- (js.Skip (), varRef)
3264- case _ =>
3265- val varDef = js.VarDef (freshLocalIdent(), NoOriginalName ,
3266- genSelector.tpe, mutable = false , genSelector)
3267- (varDef, varDef.ref)
3268- }
3269- val ifElseChain = clauses.foldRight(defaultClause) { (caze, elsep) =>
3270- val conds = caze._1.map { caseValue =>
3271- js.BinaryOp (js.BinaryOp .=== , tempSelectorRef, caseValue)
3272- }
3273- val cond = conds.reduceRight[js.Tree ] { (left, right) =>
3274- js.If (left, js.BooleanLiteral (true ), right)(jstpe.BooleanType )
3275- }
3276- js.If (cond, caze._2, elsep)(resultType)
3277- }
3278- js.Block (tempSelectorDef, ifElseChain)
3279- }
3260+ // We have more than one case: use a js.Match
3261+ js.Match (genSelector, clauses, defaultClause)(resultType)
32803262 }
32813263 }
32823264
0 commit comments