Skip to content

Commit 11e35c1

Browse files
authored
Merge pull request scala-js#4625 from sjrd/fix-js-ops-side-effects
Fix scala-js#4621: Preserve the side effects of JS binary and unary ops.
2 parents c27013f + 58b0110 commit 11e35c1

File tree

2 files changed

+45
-2
lines changed

2 files changed

+45
-2
lines changed

linker/shared/src/main/scala/org/scalajs/linker/backend/emitter/FunctionEmitter.scala

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1256,8 +1256,6 @@ private[emitter] class FunctionEmitter(sjsGen: SJSGen) {
12561256
case If(cond, thenp, elsep) => test(cond) && test(thenp) && test(elsep)
12571257
case BinaryOp(_, lhs, rhs) => test(lhs) && test(rhs)
12581258
case UnaryOp(_, lhs) => test(lhs)
1259-
case JSBinaryOp(_, lhs, rhs) => test(lhs) && test(rhs)
1260-
case JSUnaryOp(_, lhs) => test(lhs)
12611259
case ArrayLength(array) => test(array)
12621260
case RecordSelect(record, _) => test(record)
12631261
case IsInstanceOf(expr, _) => test(expr)
@@ -1346,6 +1344,10 @@ private[emitter] class FunctionEmitter(sjsGen: SJSGen) {
13461344
allowSideEffects
13471345
case LoadJSModule(_) =>
13481346
allowSideEffects
1347+
case JSBinaryOp(_, lhs, rhs) =>
1348+
allowSideEffects && test(lhs) && test(rhs)
1349+
case JSUnaryOp(_, lhs) =>
1350+
allowSideEffects && test(lhs)
13491351
case JSGlobalRef(_) =>
13501352
allowSideEffects
13511353
case JSTypeOfGlobalRef(_) =>

test-suite/js/src/test/scala/org/scalajs/testsuite/compiler/RegressionJSTest.scala

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,10 @@ import scala.scalajs.js.annotation._
1717

1818
import org.junit.Test
1919
import org.junit.Assert._
20+
import org.junit.Assume._
21+
22+
import org.scalajs.testsuite.utils.AssertThrows.assertThrows
23+
import org.scalajs.testsuite.utils.Platform._
2024

2125
class RegressionJSTest {
2226
import RegressionJSTest._
@@ -96,6 +100,43 @@ class RegressionJSTest {
96100
assertEquals(6, obj2.bar)
97101
}
98102

103+
@Test def preserveSideEffectsOfJSOpsWithBigInts_Issue4621(): Unit = {
104+
assumeTrue("requires BigInts support", jsBigInts)
105+
106+
@noinline def bi(x: Int): js.BigInt = js.BigInt(x)
107+
108+
// These must be stored as `val`s first in order to trigger the original problem
109+
val bi5: Any = bi(5)
110+
val bi0: Any = bi(0)
111+
val bi1: Any = bi(1)
112+
113+
assertThrows(classOf[js.JavaScriptException], {
114+
bi5.asInstanceOf[js.Dynamic] / bi0.asInstanceOf[js.Dynamic]
115+
fail("unreachable") // required for the above line to be in statement position
116+
})
117+
assertThrows(classOf[js.JavaScriptException], {
118+
+bi5.asInstanceOf[js.Dynamic]
119+
fail("unreachable")
120+
})
121+
}
122+
123+
@Test def preserveSideEffectsOfJSOpsWithCustomValueOf_Issue4621(): Unit = {
124+
// This must be a `val` in order to trigger the original problem
125+
val obj: Any = new js.Object {
126+
override def valueOf(): Double =
127+
throw new UnsupportedOperationException()
128+
}
129+
130+
assertThrows(classOf[UnsupportedOperationException], {
131+
obj.asInstanceOf[js.Dynamic] + 5.asInstanceOf[js.Dynamic]
132+
fail("unreachable")
133+
})
134+
assertThrows(classOf[UnsupportedOperationException], {
135+
-obj.asInstanceOf[js.Dynamic]
136+
fail("unreachable")
137+
})
138+
}
139+
99140
}
100141

101142
object RegressionJSTest {

0 commit comments

Comments
 (0)