@@ -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
@@ -182,6 +188,7 @@ object JSSymUtils {
182188 sym.info.paramNamess.flatten.zip(sym.info.paramInfoss.flatten)
183189
184190 val paramInfosAtElimRepeated = atPhase(elimRepeatedPhase) {
191+ // See also JSCodeGen.genActualArgs
185192 val list =
186193 for ((name, info) <- paramNamesAndTypes) yield {
187194 val v =
@@ -230,43 +237,70 @@ object JSSymUtils {
230237 end sjsNeedsField
231238 }
232239
240+ /** Extractor for a `TermName` that *may* be a JS unary operator.
241+ *
242+ * If it may be a JS unary operator, then a method with that name may have
243+ * the `@JSOperator` annotation, and it will be treated as such.
244+ *
245+ * If a method has neither `@JSName` nor `@JSOperator`, then a default is
246+ * chosen. If the `Boolean` value is `true`, the default is to treat the
247+ * method as if it had `@JSOperator`. If it is `false`, the default is *not*
248+ * to treat it as an operator.
249+ *
250+ * Currently, all JS unary operators default to `@JSOperator`.
251+ */
233252 private object JSUnaryOpMethodName {
234253 private val map = Map (
235- nme.UNARY_+ -> js.JSUnaryOp .+ ,
236- nme.UNARY_- -> js.JSUnaryOp .- ,
237- nme.UNARY_~ -> js.JSUnaryOp .~ ,
238- nme.UNARY_! -> js.JSUnaryOp .!
254+ nme.UNARY_+ -> ( js.JSUnaryOp .+ , true ) ,
255+ nme.UNARY_- -> ( js.JSUnaryOp .- , true ) ,
256+ nme.UNARY_~ -> ( js.JSUnaryOp .~ , true ) ,
257+ nme.UNARY_! -> ( js.JSUnaryOp .! , true ),
239258 )
240259
241- def unapply (name : TermName ): Option [js.JSUnaryOp .Code ] =
260+ def unapply (name : TermName ): Option [( js.JSUnaryOp .Code , Boolean ) ] =
242261 map.get(name)
243262 }
244263
264+ /** Extractor for a `TermName` that *may* be a JS binary operator.
265+ *
266+ * If it may be a JS binary operator, then a method with that name may have
267+ * the `@JSOperator` annotation, and it will be treated as such.
268+ *
269+ * If a method has neither `@JSName` nor `@JSOperator`, then a default is
270+ * chosen. If the `Boolean` value is `true`, the default is to treat the
271+ * method as if it had `@JSOperator`. If it is `false`, the default is *not*
272+ * to treat it as an operator.
273+ *
274+ * Most JS binary operators default to `@JSOperator`. Currently, the only
275+ * exception is `**`, for backward compatibility reasons.
276+ */
245277 private object JSBinaryOpMethodName {
246278 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 .||
279+ nme.ADD -> (js.JSBinaryOp .+ , true ),
280+ nme.SUB -> (js.JSBinaryOp .- , true ),
281+ nme.MUL -> (js.JSBinaryOp .* , true ),
282+ nme.DIV -> (js.JSBinaryOp ./ , true ),
283+ nme.MOD -> (js.JSBinaryOp .% , true ),
284+
285+ nme.LSL -> (js.JSBinaryOp .<< , true ),
286+ nme.ASR -> (js.JSBinaryOp .>> , true ),
287+ nme.LSR -> (js.JSBinaryOp .>>> , true ),
288+ nme.OR -> (js.JSBinaryOp .| , true ),
289+ nme.AND -> (js.JSBinaryOp .& , true ),
290+ nme.XOR -> (js.JSBinaryOp .^ , true ),
291+
292+ nme.LT -> (js.JSBinaryOp .< , true ),
293+ nme.LE -> (js.JSBinaryOp .<= , true ),
294+ nme.GT -> (js.JSBinaryOp .> , true ),
295+ nme.GE -> (js.JSBinaryOp .>= , true ),
296+
297+ nme.ZAND -> (js.JSBinaryOp .&& , true ),
298+ nme.ZOR -> (js.JSBinaryOp .|| , true ),
299+
300+ termName(" **" ) -> (js.JSBinaryOp .** , false ),
267301 )
268302
269- def unapply (name : TermName ): Option [js.JSBinaryOp .Code ] =
303+ def unapply (name : TermName ): Option [( js.JSBinaryOp .Code , Boolean ) ] =
270304 map.get(name)
271305 }
272306}
0 commit comments