Skip to content

Commit e092688

Browse files
committed
Scala.js: Add support for the JS operator **.
This is a forward port of the compiler changes in the Scala.js commit scala-js/scala-js@5bfa254 It is now possible to use `@JSOperator` on a method named `**` in a JS type. In that case, it will translate to the JavaScript `**` operator. This is only valid when emitting ES 2016 or later, as it is not valid ES 2015 code. Without an explicit `@JSOperator` annotation, such a method still defaults to being a method call, to preserve backward compatibility.
1 parent 8c9c051 commit e092688

File tree

2 files changed

+40
-30
lines changed

2 files changed

+40
-30
lines changed

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

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,8 @@ final class JSDefinitions()(using Context) {
8585
def JSGlobalScopeAnnot(using Context) = JSGlobalScopeAnnotType.symbol.asClass
8686
@threadUnsafe lazy val JSNameAnnotType: TypeRef = requiredClassRef("scala.scalajs.js.annotation.JSName")
8787
def JSNameAnnot(using Context) = JSNameAnnotType.symbol.asClass
88+
@threadUnsafe lazy val JSOperatorAnnotType: TypeRef = requiredClassRef("scala.scalajs.js.annotation.JSOperator")
89+
def JSOperatorAnnot(using Context) = JSOperatorAnnotType.symbol.asClass
8890
@threadUnsafe lazy val JSFullNameAnnotType: TypeRef = requiredClassRef("scala.scalajs.js.annotation.JSFullName")
8991
def JSFullNameAnnot(using Context) = JSFullNameAnnotType.symbol.asClass
9092
@threadUnsafe lazy val JSBracketAccessAnnotType: TypeRef = requiredClassRef("scala.scalajs.js.annotation.JSBracketAccess")

compiler/src/dotty/tools/dotc/transform/sjs/JSSymUtils.scala

Lines changed: 38 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -73,10 +73,16 @@ object JSSymUtils {
7373
lazy val pc = sym.info.paramNamess.map(_.size).sum
7474

7575
sym.name match {
76-
case nme.apply => Call
77-
case JSUnaryOpMethodName(code) if pc == 0 => UnaryOp(code)
78-
case JSBinaryOpMethodName(code) if pc == 1 => BinaryOp(code)
79-
case _ => default
76+
case nme.apply =>
77+
Call
78+
case JSUnaryOpMethodName(code, defaultsToOp)
79+
if (defaultsToOp || sym.hasAnnotation(jsdefn.JSOperatorAnnot)) && pc == 0 =>
80+
UnaryOp(code)
81+
case JSBinaryOpMethodName(code, defaultsToOp)
82+
if (defaultsToOp || sym.hasAnnotation(jsdefn.JSOperatorAnnot)) && pc == 1 =>
83+
BinaryOp(code)
84+
case _ =>
85+
default
8086
}
8187
} else {
8288
default
@@ -232,41 +238,43 @@ object JSSymUtils {
232238

233239
private object JSUnaryOpMethodName {
234240
private val map = Map(
235-
nme.UNARY_+ -> js.JSUnaryOp.+,
236-
nme.UNARY_- -> js.JSUnaryOp.-,
237-
nme.UNARY_~ -> js.JSUnaryOp.~,
238-
nme.UNARY_! -> js.JSUnaryOp.!
241+
nme.UNARY_+ -> (js.JSUnaryOp.+, true),
242+
nme.UNARY_- -> (js.JSUnaryOp.-, true),
243+
nme.UNARY_~ -> (js.JSUnaryOp.~, true),
244+
nme.UNARY_! -> (js.JSUnaryOp.!, true),
239245
)
240246

241-
def unapply(name: TermName): Option[js.JSUnaryOp.Code] =
247+
def unapply(name: TermName): Option[(js.JSUnaryOp.Code, Boolean)] =
242248
map.get(name)
243249
}
244250

245251
private object JSBinaryOpMethodName {
246252
private val map = Map(
247-
nme.ADD -> js.JSBinaryOp.+,
248-
nme.SUB -> js.JSBinaryOp.-,
249-
nme.MUL -> js.JSBinaryOp.*,
250-
nme.DIV -> js.JSBinaryOp./,
251-
nme.MOD -> js.JSBinaryOp.%,
252-
253-
nme.LSL -> js.JSBinaryOp.<<,
254-
nme.ASR -> js.JSBinaryOp.>>,
255-
nme.LSR -> js.JSBinaryOp.>>>,
256-
nme.OR -> js.JSBinaryOp.|,
257-
nme.AND -> js.JSBinaryOp.&,
258-
nme.XOR -> js.JSBinaryOp.^,
259-
260-
nme.LT -> js.JSBinaryOp.<,
261-
nme.LE -> js.JSBinaryOp.<=,
262-
nme.GT -> js.JSBinaryOp.>,
263-
nme.GE -> js.JSBinaryOp.>=,
264-
265-
nme.ZAND -> js.JSBinaryOp.&&,
266-
nme.ZOR -> js.JSBinaryOp.||
253+
nme.ADD -> (js.JSBinaryOp.+, true),
254+
nme.SUB -> (js.JSBinaryOp.-, true),
255+
nme.MUL -> (js.JSBinaryOp.*, true),
256+
nme.DIV -> (js.JSBinaryOp./, true),
257+
nme.MOD -> (js.JSBinaryOp.%, true),
258+
259+
nme.LSL -> (js.JSBinaryOp.<<, true),
260+
nme.ASR -> (js.JSBinaryOp.>>, true),
261+
nme.LSR -> (js.JSBinaryOp.>>>, true),
262+
nme.OR -> (js.JSBinaryOp.|, true),
263+
nme.AND -> (js.JSBinaryOp.&, true),
264+
nme.XOR -> (js.JSBinaryOp.^, true),
265+
266+
nme.LT -> (js.JSBinaryOp.<, true),
267+
nme.LE -> (js.JSBinaryOp.<=, true),
268+
nme.GT -> (js.JSBinaryOp.>, true),
269+
nme.GE -> (js.JSBinaryOp.>=, true),
270+
271+
nme.ZAND -> (js.JSBinaryOp.&&, true),
272+
nme.ZOR -> (js.JSBinaryOp.||, true),
273+
274+
termName("**") -> (js.JSBinaryOp.**, false),
267275
)
268276

269-
def unapply(name: TermName): Option[js.JSBinaryOp.Code] =
277+
def unapply(name: TermName): Option[(js.JSBinaryOp.Code, Boolean)] =
270278
map.get(name)
271279
}
272280
}

0 commit comments

Comments
 (0)