From 9d066a818171cc51bab05972f58024b16a68581c Mon Sep 17 00:00:00 2001
From: Josh Wolfe <jwolfe@igalia.com>
Date: Thu, 18 Jan 2018 13:50:44 -0700
Subject: [PATCH] Order of evaluation tests for infix numeric operators

---
 .../addition/order-of-evaluation.js           | 140 ++++++++++++++++++
 .../bitwise-and/order-of-evaluation.js        | 138 +++++++++++++++++
 .../bitwise-or/order-of-evaluation.js         | 138 +++++++++++++++++
 .../bitwise-xor/order-of-evaluation.js        | 138 +++++++++++++++++
 .../division/order-of-evaluation.js           | 138 +++++++++++++++++
 .../exponentiation/order-of-evaluation.js     | 138 +++++++++++++++++
 .../left-shift/order-of-evaluation.js         | 138 +++++++++++++++++
 .../modulus/order-of-evaluation.js            | 138 +++++++++++++++++
 .../multiplication/order-of-evaluation.js     | 138 +++++++++++++++++
 .../right-shift/order-of-evaluation.js        | 138 +++++++++++++++++
 .../subtraction/order-of-evaluation.js        | 138 +++++++++++++++++
 .../order-of-evaluation.js                    | 138 +++++++++++++++++
 12 files changed, 1658 insertions(+)
 create mode 100644 test/language/expressions/addition/order-of-evaluation.js
 create mode 100644 test/language/expressions/bitwise-and/order-of-evaluation.js
 create mode 100644 test/language/expressions/bitwise-or/order-of-evaluation.js
 create mode 100644 test/language/expressions/bitwise-xor/order-of-evaluation.js
 create mode 100644 test/language/expressions/division/order-of-evaluation.js
 create mode 100644 test/language/expressions/exponentiation/order-of-evaluation.js
 create mode 100644 test/language/expressions/left-shift/order-of-evaluation.js
 create mode 100644 test/language/expressions/modulus/order-of-evaluation.js
 create mode 100644 test/language/expressions/multiplication/order-of-evaluation.js
 create mode 100644 test/language/expressions/right-shift/order-of-evaluation.js
 create mode 100644 test/language/expressions/subtraction/order-of-evaluation.js
 create mode 100644 test/language/expressions/unsigned-right-shift/order-of-evaluation.js

diff --git a/test/language/expressions/addition/order-of-evaluation.js b/test/language/expressions/addition/order-of-evaluation.js
new file mode 100644
index 0000000000..103f82d5dc
--- /dev/null
+++ b/test/language/expressions/addition/order-of-evaluation.js
@@ -0,0 +1,140 @@
+// Copyright (C) 2018 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-addition-operator-plus-runtime-semantics-evaluation
+description: Type coercion order of operations for addition operator
+features: [Symbol]
+info: |
+  Evaluate lhs
+  Evaluate rhs
+  ToPrimitive(lhs)
+  ToPrimitive(rhs)
+  ToNumeric(lhs)
+  ToNumeric(rhs)
+---*/
+
+function MyError() {}
+var trace;
+
+// ?GetValue(lhs) throws.
+trace = "";
+assert.throws(MyError, function() {
+  (function() {
+    trace += "1";
+    throw new MyError();
+  })() + (function() {
+    trace += "2";
+    throw new Test262Error("should not be evaluated");
+  })();
+}, "?GetValue(lhs) throws.");
+assert.sameValue(trace, "1", "?GetValue(lhs) throws.");
+
+// ?GetValue(rhs) throws.
+trace = "";
+assert.throws(MyError, function() {
+  (function() {
+    trace += "1";
+    return {
+      valueOf() {
+        trace += "3";
+        throw new Test262Error("should not be evaluated");
+      }
+    };
+  })() + (function() {
+    trace += "2";
+    throw new MyError();
+  })();
+}, "?GetValue(rhs) throws.");
+assert.sameValue(trace, "12", "?GetValue(rhs) throws.");
+
+// ?ToPrimive(lhs) throws.
+trace = "";
+assert.throws(MyError, function() {
+  (function() {
+    trace += "1";
+    return {
+      valueOf() {
+        trace += "3";
+        throw new MyError();
+      }
+    };
+  })() + (function() {
+    trace += "2";
+    return {
+      valueOf() {
+        trace += "4";
+        throw new Test262Error("should not be evaluated");
+      }
+    };
+  })();
+}, "?ToPrimive(lhs) throws.");
+assert.sameValue(trace, "123", "?ToPrimive(lhs) throws.");
+
+// ?ToPrimive(rhs) throws.
+trace = "";
+assert.throws(MyError, function() {
+  (function() {
+    trace += "1";
+    return {
+      valueOf() {
+        trace += "3";
+        return 1;
+      }
+    };
+  })() + (function() {
+    trace += "2";
+    return {
+      valueOf() {
+        trace += "4";
+        throw new MyError();
+      }
+    };
+  })();
+}, "?ToPrimive(rhs) throws.");
+assert.sameValue(trace, "1234", "?ToPrimive(rhs) throws.");
+
+// ?ToPrimive(rhs) is called before ?ToNumeric(lhs).
+trace = "";
+assert.throws(MyError, function() {
+  (function() {
+    trace += "1";
+    return {
+      valueOf() {
+        trace += "3";
+        return Symbol("1");
+      }
+    };
+  })() + (function() {
+    trace += "2";
+    return {
+      valueOf() {
+        trace += "4";
+        throw new MyError();
+      }
+    };
+  })();
+}, "?ToPrimive(rhs) is called before ?ToNumeric(lhs).");
+assert.sameValue(trace, "1234", "?ToPrimive(rhs) is called before ?ToNumeric(lhs).");
+
+// GetValue(lhs) throws.
+trace = "";
+assert.throws(TypeError, function() {
+  (function() {
+    trace += "1";
+    return {
+      valueOf() {
+        trace += "3";
+        return 1;
+      }
+    };
+  })() + (function() {
+    trace += "2";
+    return {
+      valueOf() {
+        trace += "4";
+        return Symbol("1");
+      }
+    };
+  })();
+}, "GetValue(lhs) throws.");
+assert.sameValue(trace, "1234", "GetValue(lhs) throws.");
diff --git a/test/language/expressions/bitwise-and/order-of-evaluation.js b/test/language/expressions/bitwise-and/order-of-evaluation.js
new file mode 100644
index 0000000000..8aab592f6d
--- /dev/null
+++ b/test/language/expressions/bitwise-and/order-of-evaluation.js
@@ -0,0 +1,138 @@
+// Copyright (C) 2018 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-binary-bitwise-operators-runtime-semantics-evaluation
+description: Type coercion order of operations for bitwise-and operator
+features: [Symbol]
+info: |
+  Evaluate lhs
+  Evaluate rhs
+  ToNumeric(lhs)
+  ToNumeric(rhs)
+---*/
+
+function MyError() {}
+var trace;
+
+// ?GetValue(lhs) throws.
+trace = "";
+assert.throws(MyError, function() {
+  (function() {
+    trace += "1";
+    throw new MyError();
+  })() & (function() {
+    trace += "2";
+    throw new Test262Error("should not be evaluated");
+  })();
+}, "?GetValue(lhs) throws.");
+assert.sameValue(trace, "1", "?GetValue(lhs) throws.");
+
+// ?GetValue(rhs) throws.
+trace = "";
+assert.throws(MyError, function() {
+  (function() {
+    trace += "1";
+    return {
+      valueOf() {
+        trace += "3";
+        throw new Test262Error("should not be evaluated");
+      }
+    };
+  })() & (function() {
+    trace += "2";
+    throw new MyError();
+  })();
+}, "?GetValue(rhs) throws.");
+assert.sameValue(trace, "12", "?GetValue(rhs) throws.");
+
+// ?ToPrimive(lhs) throws.
+trace = "";
+assert.throws(MyError, function() {
+  (function() {
+    trace += "1";
+    return {
+      valueOf() {
+        trace += "3";
+        throw new MyError();
+      }
+    };
+  })() & (function() {
+    trace += "2";
+    return {
+      valueOf() {
+        trace += "4";
+        throw new Test262Error("should not be evaluated");
+      }
+    };
+  })();
+}, "?ToPrimive(lhs) throws.");
+assert.sameValue(trace, "123", "?ToPrimive(lhs) throws.");
+
+// ?ToPrimive(rhs) throws.
+trace = "";
+assert.throws(MyError, function() {
+  (function() {
+    trace += "1";
+    return {
+      valueOf() {
+        trace += "3";
+        return 1;
+      }
+    };
+  })() & (function() {
+    trace += "2";
+    return {
+      valueOf() {
+        trace += "4";
+        throw new MyError();
+      }
+    };
+  })();
+}, "?ToPrimive(rhs) throws.");
+assert.sameValue(trace, "1234", "?ToPrimive(rhs) throws.");
+
+// ?ToNumeric(lhs) throws.
+trace = "";
+assert.throws(TypeError, function() {
+  (function() {
+    trace += "1";
+    return {
+      valueOf() {
+        trace += "3";
+        return Symbol("1");
+      }
+    };
+  })() & (function() {
+    trace += "2";
+    return {
+      valueOf() {
+        trace += "4";
+        throw new Test262Error("should not be evaluated");
+      }
+    };
+  })();
+}, "?ToNumeric(lhs) throws.");
+assert.sameValue(trace, "123", "?ToNumeric(lhs) throws.");
+
+// GetValue(lhs) throws.
+trace = "";
+assert.throws(TypeError, function() {
+  (function() {
+    trace += "1";
+    return {
+      valueOf() {
+        trace += "3";
+        return 1;
+      }
+    };
+  })() & (function() {
+    trace += "2";
+    return {
+      valueOf() {
+        trace += "4";
+        return Symbol("1");
+      }
+    };
+  })();
+}, "GetValue(lhs) throws.");
+assert.sameValue(trace, "1234", "GetValue(lhs) throws.");
diff --git a/test/language/expressions/bitwise-or/order-of-evaluation.js b/test/language/expressions/bitwise-or/order-of-evaluation.js
new file mode 100644
index 0000000000..c1bd291d44
--- /dev/null
+++ b/test/language/expressions/bitwise-or/order-of-evaluation.js
@@ -0,0 +1,138 @@
+// Copyright (C) 2018 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-binary-bitwise-operators-runtime-semantics-evaluation
+description: Type coercion order of operations for bitwise-or operator
+features: [Symbol]
+info: |
+  Evaluate lhs
+  Evaluate rhs
+  ToNumeric(lhs)
+  ToNumeric(rhs)
+---*/
+
+function MyError() {}
+var trace;
+
+// ?GetValue(lhs) throws.
+trace = "";
+assert.throws(MyError, function() {
+  (function() {
+    trace += "1";
+    throw new MyError();
+  })() | (function() {
+    trace += "2";
+    throw new Test262Error("should not be evaluated");
+  })();
+}, "?GetValue(lhs) throws.");
+assert.sameValue(trace, "1", "?GetValue(lhs) throws.");
+
+// ?GetValue(rhs) throws.
+trace = "";
+assert.throws(MyError, function() {
+  (function() {
+    trace += "1";
+    return {
+      valueOf() {
+        trace += "3";
+        throw new Test262Error("should not be evaluated");
+      }
+    };
+  })() | (function() {
+    trace += "2";
+    throw new MyError();
+  })();
+}, "?GetValue(rhs) throws.");
+assert.sameValue(trace, "12", "?GetValue(rhs) throws.");
+
+// ?ToPrimive(lhs) throws.
+trace = "";
+assert.throws(MyError, function() {
+  (function() {
+    trace += "1";
+    return {
+      valueOf() {
+        trace += "3";
+        throw new MyError();
+      }
+    };
+  })() | (function() {
+    trace += "2";
+    return {
+      valueOf() {
+        trace += "4";
+        throw new Test262Error("should not be evaluated");
+      }
+    };
+  })();
+}, "?ToPrimive(lhs) throws.");
+assert.sameValue(trace, "123", "?ToPrimive(lhs) throws.");
+
+// ?ToPrimive(rhs) throws.
+trace = "";
+assert.throws(MyError, function() {
+  (function() {
+    trace += "1";
+    return {
+      valueOf() {
+        trace += "3";
+        return 1;
+      }
+    };
+  })() | (function() {
+    trace += "2";
+    return {
+      valueOf() {
+        trace += "4";
+        throw new MyError();
+      }
+    };
+  })();
+}, "?ToPrimive(rhs) throws.");
+assert.sameValue(trace, "1234", "?ToPrimive(rhs) throws.");
+
+// ?ToNumeric(lhs) throws.
+trace = "";
+assert.throws(TypeError, function() {
+  (function() {
+    trace += "1";
+    return {
+      valueOf() {
+        trace += "3";
+        return Symbol("1");
+      }
+    };
+  })() | (function() {
+    trace += "2";
+    return {
+      valueOf() {
+        trace += "4";
+        throw new Test262Error("should not be evaluated");
+      }
+    };
+  })();
+}, "?ToNumeric(lhs) throws.");
+assert.sameValue(trace, "123", "?ToNumeric(lhs) throws.");
+
+// GetValue(lhs) throws.
+trace = "";
+assert.throws(TypeError, function() {
+  (function() {
+    trace += "1";
+    return {
+      valueOf() {
+        trace += "3";
+        return 1;
+      }
+    };
+  })() | (function() {
+    trace += "2";
+    return {
+      valueOf() {
+        trace += "4";
+        return Symbol("1");
+      }
+    };
+  })();
+}, "GetValue(lhs) throws.");
+assert.sameValue(trace, "1234", "GetValue(lhs) throws.");
diff --git a/test/language/expressions/bitwise-xor/order-of-evaluation.js b/test/language/expressions/bitwise-xor/order-of-evaluation.js
new file mode 100644
index 0000000000..e790ef35b8
--- /dev/null
+++ b/test/language/expressions/bitwise-xor/order-of-evaluation.js
@@ -0,0 +1,138 @@
+// Copyright (C) 2018 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-binary-bitwise-operators-runtime-semantics-evaluation
+description: Type coercion order of operations for bitwise-xor operator
+features: [Symbol]
+info: |
+  Evaluate lhs
+  Evaluate rhs
+  ToNumeric(lhs)
+  ToNumeric(rhs)
+---*/
+
+function MyError() {}
+var trace;
+
+// ?GetValue(lhs) throws.
+trace = "";
+assert.throws(MyError, function() {
+  (function() {
+    trace += "1";
+    throw new MyError();
+  })() ^ (function() {
+    trace += "2";
+    throw new Test262Error("should not be evaluated");
+  })();
+}, "?GetValue(lhs) throws.");
+assert.sameValue(trace, "1", "?GetValue(lhs) throws.");
+
+// ?GetValue(rhs) throws.
+trace = "";
+assert.throws(MyError, function() {
+  (function() {
+    trace += "1";
+    return {
+      valueOf() {
+        trace += "3";
+        throw new Test262Error("should not be evaluated");
+      }
+    };
+  })() ^ (function() {
+    trace += "2";
+    throw new MyError();
+  })();
+}, "?GetValue(rhs) throws.");
+assert.sameValue(trace, "12", "?GetValue(rhs) throws.");
+
+// ?ToPrimive(lhs) throws.
+trace = "";
+assert.throws(MyError, function() {
+  (function() {
+    trace += "1";
+    return {
+      valueOf() {
+        trace += "3";
+        throw new MyError();
+      }
+    };
+  })() ^ (function() {
+    trace += "2";
+    return {
+      valueOf() {
+        trace += "4";
+        throw new Test262Error("should not be evaluated");
+      }
+    };
+  })();
+}, "?ToPrimive(lhs) throws.");
+assert.sameValue(trace, "123", "?ToPrimive(lhs) throws.");
+
+// ?ToPrimive(rhs) throws.
+trace = "";
+assert.throws(MyError, function() {
+  (function() {
+    trace += "1";
+    return {
+      valueOf() {
+        trace += "3";
+        return 1;
+      }
+    };
+  })() ^ (function() {
+    trace += "2";
+    return {
+      valueOf() {
+        trace += "4";
+        throw new MyError();
+      }
+    };
+  })();
+}, "?ToPrimive(rhs) throws.");
+assert.sameValue(trace, "1234", "?ToPrimive(rhs) throws.");
+
+// ?ToNumeric(lhs) throws.
+trace = "";
+assert.throws(TypeError, function() {
+  (function() {
+    trace += "1";
+    return {
+      valueOf() {
+        trace += "3";
+        return Symbol("1");
+      }
+    };
+  })() ^ (function() {
+    trace += "2";
+    return {
+      valueOf() {
+        trace += "4";
+        throw new Test262Error("should not be evaluated");
+      }
+    };
+  })();
+}, "?ToNumeric(lhs) throws.");
+assert.sameValue(trace, "123", "?ToNumeric(lhs) throws.");
+
+// GetValue(lhs) throws.
+trace = "";
+assert.throws(TypeError, function() {
+  (function() {
+    trace += "1";
+    return {
+      valueOf() {
+        trace += "3";
+        return 1;
+      }
+    };
+  })() ^ (function() {
+    trace += "2";
+    return {
+      valueOf() {
+        trace += "4";
+        return Symbol("1");
+      }
+    };
+  })();
+}, "GetValue(lhs) throws.");
+assert.sameValue(trace, "1234", "GetValue(lhs) throws.");
diff --git a/test/language/expressions/division/order-of-evaluation.js b/test/language/expressions/division/order-of-evaluation.js
new file mode 100644
index 0000000000..80097fe34d
--- /dev/null
+++ b/test/language/expressions/division/order-of-evaluation.js
@@ -0,0 +1,138 @@
+// Copyright (C) 2018 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-multiplicative-operators-runtime-semantics-evaluation
+description: Type coercion order of operations for division operator
+features: [Symbol]
+info: |
+  Evaluate lhs
+  Evaluate rhs
+  ToNumeric(lhs)
+  ToNumeric(rhs)
+---*/
+
+function MyError() {}
+var trace;
+
+// ?GetValue(lhs) throws.
+trace = "";
+assert.throws(MyError, function() {
+  (function() {
+    trace += "1";
+    throw new MyError();
+  })() / (function() {
+    trace += "2";
+    throw new Test262Error("should not be evaluated");
+  })();
+}, "?GetValue(lhs) throws.");
+assert.sameValue(trace, "1", "?GetValue(lhs) throws.");
+
+// ?GetValue(rhs) throws.
+trace = "";
+assert.throws(MyError, function() {
+  (function() {
+    trace += "1";
+    return {
+      valueOf() {
+        trace += "3";
+        throw new Test262Error("should not be evaluated");
+      }
+    };
+  })() / (function() {
+    trace += "2";
+    throw new MyError();
+  })();
+}, "?GetValue(rhs) throws.");
+assert.sameValue(trace, "12", "?GetValue(rhs) throws.");
+
+// ?ToPrimive(lhs) throws.
+trace = "";
+assert.throws(MyError, function() {
+  (function() {
+    trace += "1";
+    return {
+      valueOf() {
+        trace += "3";
+        throw new MyError();
+      }
+    };
+  })() / (function() {
+    trace += "2";
+    return {
+      valueOf() {
+        trace += "4";
+        throw new Test262Error("should not be evaluated");
+      }
+    };
+  })();
+}, "?ToPrimive(lhs) throws.");
+assert.sameValue(trace, "123", "?ToPrimive(lhs) throws.");
+
+// ?ToPrimive(rhs) throws.
+trace = "";
+assert.throws(MyError, function() {
+  (function() {
+    trace += "1";
+    return {
+      valueOf() {
+        trace += "3";
+        return 1;
+      }
+    };
+  })() / (function() {
+    trace += "2";
+    return {
+      valueOf() {
+        trace += "4";
+        throw new MyError();
+      }
+    };
+  })();
+}, "?ToPrimive(rhs) throws.");
+assert.sameValue(trace, "1234", "?ToPrimive(rhs) throws.");
+
+// ?ToNumeric(lhs) throws.
+trace = "";
+assert.throws(TypeError, function() {
+  (function() {
+    trace += "1";
+    return {
+      valueOf() {
+        trace += "3";
+        return Symbol("1");
+      }
+    };
+  })() / (function() {
+    trace += "2";
+    return {
+      valueOf() {
+        trace += "4";
+        throw new Test262Error("should not be evaluated");
+      }
+    };
+  })();
+}, "?ToNumeric(lhs) throws.");
+assert.sameValue(trace, "123", "?ToNumeric(lhs) throws.");
+
+// GetValue(lhs) throws.
+trace = "";
+assert.throws(TypeError, function() {
+  (function() {
+    trace += "1";
+    return {
+      valueOf() {
+        trace += "3";
+        return 1;
+      }
+    };
+  })() / (function() {
+    trace += "2";
+    return {
+      valueOf() {
+        trace += "4";
+        return Symbol("1");
+      }
+    };
+  })();
+}, "GetValue(lhs) throws.");
+assert.sameValue(trace, "1234", "GetValue(lhs) throws.");
diff --git a/test/language/expressions/exponentiation/order-of-evaluation.js b/test/language/expressions/exponentiation/order-of-evaluation.js
new file mode 100644
index 0000000000..93da0d99e9
--- /dev/null
+++ b/test/language/expressions/exponentiation/order-of-evaluation.js
@@ -0,0 +1,138 @@
+// Copyright (C) 2018 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-exp-operator-runtime-semantics-evaluation
+description: Type coercion order of operations for exponentiation operator
+features: [Symbol]
+info: |
+  Evaluate lhs
+  Evaluate rhs
+  ToNumeric(lhs)
+  ToNumeric(rhs)
+---*/
+
+function MyError() {}
+var trace;
+
+// ?GetValue(lhs) throws.
+trace = "";
+assert.throws(MyError, function() {
+  (function() {
+    trace += "1";
+    throw new MyError();
+  })() ** (function() {
+    trace += "2";
+    throw new Test262Error("should not be evaluated");
+  })();
+}, "?GetValue(lhs) throws.");
+assert.sameValue(trace, "1", "?GetValue(lhs) throws.");
+
+// ?GetValue(rhs) throws.
+trace = "";
+assert.throws(MyError, function() {
+  (function() {
+    trace += "1";
+    return {
+      valueOf() {
+        trace += "3";
+        throw new Test262Error("should not be evaluated");
+      }
+    };
+  })() ** (function() {
+    trace += "2";
+    throw new MyError();
+  })();
+}, "?GetValue(rhs) throws.");
+assert.sameValue(trace, "12", "?GetValue(rhs) throws.");
+
+// ?ToPrimive(lhs) throws.
+trace = "";
+assert.throws(MyError, function() {
+  (function() {
+    trace += "1";
+    return {
+      valueOf() {
+        trace += "3";
+        throw new MyError();
+      }
+    };
+  })() ** (function() {
+    trace += "2";
+    return {
+      valueOf() {
+        trace += "4";
+        throw new Test262Error("should not be evaluated");
+      }
+    };
+  })();
+}, "?ToPrimive(lhs) throws.");
+assert.sameValue(trace, "123", "?ToPrimive(lhs) throws.");
+
+// ?ToPrimive(rhs) throws.
+trace = "";
+assert.throws(MyError, function() {
+  (function() {
+    trace += "1";
+    return {
+      valueOf() {
+        trace += "3";
+        return 1;
+      }
+    };
+  })() ** (function() {
+    trace += "2";
+    return {
+      valueOf() {
+        trace += "4";
+        throw new MyError();
+      }
+    };
+  })();
+}, "?ToPrimive(rhs) throws.");
+assert.sameValue(trace, "1234", "?ToPrimive(rhs) throws.");
+
+// ?ToNumeric(lhs) throws.
+trace = "";
+assert.throws(TypeError, function() {
+  (function() {
+    trace += "1";
+    return {
+      valueOf() {
+        trace += "3";
+        return Symbol("1");
+      }
+    };
+  })() ** (function() {
+    trace += "2";
+    return {
+      valueOf() {
+        trace += "4";
+        throw new Test262Error("should not be evaluated");
+      }
+    };
+  })();
+}, "?ToNumeric(lhs) throws.");
+assert.sameValue(trace, "123", "?ToNumeric(lhs) throws.");
+
+// GetValue(lhs) throws.
+trace = "";
+assert.throws(TypeError, function() {
+  (function() {
+    trace += "1";
+    return {
+      valueOf() {
+        trace += "3";
+        return 1;
+      }
+    };
+  })() ** (function() {
+    trace += "2";
+    return {
+      valueOf() {
+        trace += "4";
+        return Symbol("1");
+      }
+    };
+  })();
+}, "GetValue(lhs) throws.");
+assert.sameValue(trace, "1234", "GetValue(lhs) throws.");
diff --git a/test/language/expressions/left-shift/order-of-evaluation.js b/test/language/expressions/left-shift/order-of-evaluation.js
new file mode 100644
index 0000000000..e682dad729
--- /dev/null
+++ b/test/language/expressions/left-shift/order-of-evaluation.js
@@ -0,0 +1,138 @@
+// Copyright (C) 2018 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-left-shift-operator-runtime-semantics-evaluation
+description: Type coercion order of operations for left-shift operator
+features: [Symbol]
+info: |
+  Evaluate lhs
+  Evaluate rhs
+  ToNumeric(lhs)
+  ToNumeric(rhs)
+---*/
+
+function MyError() {}
+var trace;
+
+// ?GetValue(lhs) throws.
+trace = "";
+assert.throws(MyError, function() {
+  (function() {
+    trace += "1";
+    throw new MyError();
+  })() << (function() {
+    trace += "2";
+    throw new Test262Error("should not be evaluated");
+  })();
+}, "?GetValue(lhs) throws.");
+assert.sameValue(trace, "1", "?GetValue(lhs) throws.");
+
+// ?GetValue(rhs) throws.
+trace = "";
+assert.throws(MyError, function() {
+  (function() {
+    trace += "1";
+    return {
+      valueOf() {
+        trace += "3";
+        throw new Test262Error("should not be evaluated");
+      }
+    };
+  })() << (function() {
+    trace += "2";
+    throw new MyError();
+  })();
+}, "?GetValue(rhs) throws.");
+assert.sameValue(trace, "12", "?GetValue(rhs) throws.");
+
+// ?ToPrimive(lhs) throws.
+trace = "";
+assert.throws(MyError, function() {
+  (function() {
+    trace += "1";
+    return {
+      valueOf() {
+        trace += "3";
+        throw new MyError();
+      }
+    };
+  })() << (function() {
+    trace += "2";
+    return {
+      valueOf() {
+        trace += "4";
+        throw new Test262Error("should not be evaluated");
+      }
+    };
+  })();
+}, "?ToPrimive(lhs) throws.");
+assert.sameValue(trace, "123", "?ToPrimive(lhs) throws.");
+
+// ?ToPrimive(rhs) throws.
+trace = "";
+assert.throws(MyError, function() {
+  (function() {
+    trace += "1";
+    return {
+      valueOf() {
+        trace += "3";
+        return 1;
+      }
+    };
+  })() << (function() {
+    trace += "2";
+    return {
+      valueOf() {
+        trace += "4";
+        throw new MyError();
+      }
+    };
+  })();
+}, "?ToPrimive(rhs) throws.");
+assert.sameValue(trace, "1234", "?ToPrimive(rhs) throws.");
+
+// ?ToNumeric(lhs) throws.
+trace = "";
+assert.throws(TypeError, function() {
+  (function() {
+    trace += "1";
+    return {
+      valueOf() {
+        trace += "3";
+        return Symbol("1");
+      }
+    };
+  })() << (function() {
+    trace += "2";
+    return {
+      valueOf() {
+        trace += "4";
+        throw new Test262Error("should not be evaluated");
+      }
+    };
+  })();
+}, "?ToNumeric(lhs) throws.");
+assert.sameValue(trace, "123", "?ToNumeric(lhs) throws.");
+
+// GetValue(lhs) throws.
+trace = "";
+assert.throws(TypeError, function() {
+  (function() {
+    trace += "1";
+    return {
+      valueOf() {
+        trace += "3";
+        return 1;
+      }
+    };
+  })() << (function() {
+    trace += "2";
+    return {
+      valueOf() {
+        trace += "4";
+        return Symbol("1");
+      }
+    };
+  })();
+}, "GetValue(lhs) throws.");
+assert.sameValue(trace, "1234", "GetValue(lhs) throws.");
diff --git a/test/language/expressions/modulus/order-of-evaluation.js b/test/language/expressions/modulus/order-of-evaluation.js
new file mode 100644
index 0000000000..ac91c49d27
--- /dev/null
+++ b/test/language/expressions/modulus/order-of-evaluation.js
@@ -0,0 +1,138 @@
+// Copyright (C) 2018 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-multiplicative-operators-runtime-semantics-evaluation
+description: Type coercion order of operations for modulus operator
+features: [Symbol]
+info: |
+  Evaluate lhs
+  Evaluate rhs
+  ToNumeric(lhs)
+  ToNumeric(rhs)
+---*/
+
+function MyError() {}
+var trace;
+
+// ?GetValue(lhs) throws.
+trace = "";
+assert.throws(MyError, function() {
+  (function() {
+    trace += "1";
+    throw new MyError();
+  })() % (function() {
+    trace += "2";
+    throw new Test262Error("should not be evaluated");
+  })();
+}, "?GetValue(lhs) throws.");
+assert.sameValue(trace, "1", "?GetValue(lhs) throws.");
+
+// ?GetValue(rhs) throws.
+trace = "";
+assert.throws(MyError, function() {
+  (function() {
+    trace += "1";
+    return {
+      valueOf() {
+        trace += "3";
+        throw new Test262Error("should not be evaluated");
+      }
+    };
+  })() % (function() {
+    trace += "2";
+    throw new MyError();
+  })();
+}, "?GetValue(rhs) throws.");
+assert.sameValue(trace, "12", "?GetValue(rhs) throws.");
+
+// ?ToPrimive(lhs) throws.
+trace = "";
+assert.throws(MyError, function() {
+  (function() {
+    trace += "1";
+    return {
+      valueOf() {
+        trace += "3";
+        throw new MyError();
+      }
+    };
+  })() % (function() {
+    trace += "2";
+    return {
+      valueOf() {
+        trace += "4";
+        throw new Test262Error("should not be evaluated");
+      }
+    };
+  })();
+}, "?ToPrimive(lhs) throws.");
+assert.sameValue(trace, "123", "?ToPrimive(lhs) throws.");
+
+// ?ToPrimive(rhs) throws.
+trace = "";
+assert.throws(MyError, function() {
+  (function() {
+    trace += "1";
+    return {
+      valueOf() {
+        trace += "3";
+        return 1;
+      }
+    };
+  })() % (function() {
+    trace += "2";
+    return {
+      valueOf() {
+        trace += "4";
+        throw new MyError();
+      }
+    };
+  })();
+}, "?ToPrimive(rhs) throws.");
+assert.sameValue(trace, "1234", "?ToPrimive(rhs) throws.");
+
+// ?ToNumeric(lhs) throws.
+trace = "";
+assert.throws(TypeError, function() {
+  (function() {
+    trace += "1";
+    return {
+      valueOf() {
+        trace += "3";
+        return Symbol("1");
+      }
+    };
+  })() % (function() {
+    trace += "2";
+    return {
+      valueOf() {
+        trace += "4";
+        throw new Test262Error("should not be evaluated");
+      }
+    };
+  })();
+}, "?ToNumeric(lhs) throws.");
+assert.sameValue(trace, "123", "?ToNumeric(lhs) throws.");
+
+// GetValue(lhs) throws.
+trace = "";
+assert.throws(TypeError, function() {
+  (function() {
+    trace += "1";
+    return {
+      valueOf() {
+        trace += "3";
+        return 1;
+      }
+    };
+  })() % (function() {
+    trace += "2";
+    return {
+      valueOf() {
+        trace += "4";
+        return Symbol("1");
+      }
+    };
+  })();
+}, "GetValue(lhs) throws.");
+assert.sameValue(trace, "1234", "GetValue(lhs) throws.");
diff --git a/test/language/expressions/multiplication/order-of-evaluation.js b/test/language/expressions/multiplication/order-of-evaluation.js
new file mode 100644
index 0000000000..af612685aa
--- /dev/null
+++ b/test/language/expressions/multiplication/order-of-evaluation.js
@@ -0,0 +1,138 @@
+// Copyright (C) 2018 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-multiplicative-operators-runtime-semantics-evaluation
+description: Type coercion order of operations for multiplication operator
+features: [Symbol]
+info: |
+  Evaluate lhs
+  Evaluate rhs
+  ToNumeric(lhs)
+  ToNumeric(rhs)
+---*/
+
+function MyError() {}
+var trace;
+
+// ?GetValue(lhs) throws.
+trace = "";
+assert.throws(MyError, function() {
+  (function() {
+    trace += "1";
+    throw new MyError();
+  })() * (function() {
+    trace += "2";
+    throw new Test262Error("should not be evaluated");
+  })();
+}, "?GetValue(lhs) throws.");
+assert.sameValue(trace, "1", "?GetValue(lhs) throws.");
+
+// ?GetValue(rhs) throws.
+trace = "";
+assert.throws(MyError, function() {
+  (function() {
+    trace += "1";
+    return {
+      valueOf() {
+        trace += "3";
+        throw new Test262Error("should not be evaluated");
+      }
+    };
+  })() * (function() {
+    trace += "2";
+    throw new MyError();
+  })();
+}, "?GetValue(rhs) throws.");
+assert.sameValue(trace, "12", "?GetValue(rhs) throws.");
+
+// ?ToPrimive(lhs) throws.
+trace = "";
+assert.throws(MyError, function() {
+  (function() {
+    trace += "1";
+    return {
+      valueOf() {
+        trace += "3";
+        throw new MyError();
+      }
+    };
+  })() * (function() {
+    trace += "2";
+    return {
+      valueOf() {
+        trace += "4";
+        throw new Test262Error("should not be evaluated");
+      }
+    };
+  })();
+}, "?ToPrimive(lhs) throws.");
+assert.sameValue(trace, "123", "?ToPrimive(lhs) throws.");
+
+// ?ToPrimive(rhs) throws.
+trace = "";
+assert.throws(MyError, function() {
+  (function() {
+    trace += "1";
+    return {
+      valueOf() {
+        trace += "3";
+        return 1;
+      }
+    };
+  })() * (function() {
+    trace += "2";
+    return {
+      valueOf() {
+        trace += "4";
+        throw new MyError();
+      }
+    };
+  })();
+}, "?ToPrimive(rhs) throws.");
+assert.sameValue(trace, "1234", "?ToPrimive(rhs) throws.");
+
+// ?ToNumeric(lhs) throws.
+trace = "";
+assert.throws(TypeError, function() {
+  (function() {
+    trace += "1";
+    return {
+      valueOf() {
+        trace += "3";
+        return Symbol("1");
+      }
+    };
+  })() * (function() {
+    trace += "2";
+    return {
+      valueOf() {
+        trace += "4";
+        throw new Test262Error("should not be evaluated");
+      }
+    };
+  })();
+}, "?ToNumeric(lhs) throws.");
+assert.sameValue(trace, "123", "?ToNumeric(lhs) throws.");
+
+// GetValue(lhs) throws.
+trace = "";
+assert.throws(TypeError, function() {
+  (function() {
+    trace += "1";
+    return {
+      valueOf() {
+        trace += "3";
+        return 1;
+      }
+    };
+  })() * (function() {
+    trace += "2";
+    return {
+      valueOf() {
+        trace += "4";
+        return Symbol("1");
+      }
+    };
+  })();
+}, "GetValue(lhs) throws.");
+assert.sameValue(trace, "1234", "GetValue(lhs) throws.");
diff --git a/test/language/expressions/right-shift/order-of-evaluation.js b/test/language/expressions/right-shift/order-of-evaluation.js
new file mode 100644
index 0000000000..4630d98886
--- /dev/null
+++ b/test/language/expressions/right-shift/order-of-evaluation.js
@@ -0,0 +1,138 @@
+// Copyright (C) 2018 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-signed-right-shift-operator-runtime-semantics-evaluation
+description: Type coercion order of operations for right-shift operator
+features: [Symbol]
+info: |
+  Evaluate lhs
+  Evaluate rhs
+  ToNumeric(lhs)
+  ToNumeric(rhs)
+---*/
+
+function MyError() {}
+var trace;
+
+// ?GetValue(lhs) throws.
+trace = "";
+assert.throws(MyError, function() {
+  (function() {
+    trace += "1";
+    throw new MyError();
+  })() >> (function() {
+    trace += "2";
+    throw new Test262Error("should not be evaluated");
+  })();
+}, "?GetValue(lhs) throws.");
+assert.sameValue(trace, "1", "?GetValue(lhs) throws.");
+
+// ?GetValue(rhs) throws.
+trace = "";
+assert.throws(MyError, function() {
+  (function() {
+    trace += "1";
+    return {
+      valueOf() {
+        trace += "3";
+        throw new Test262Error("should not be evaluated");
+      }
+    };
+  })() >> (function() {
+    trace += "2";
+    throw new MyError();
+  })();
+}, "?GetValue(rhs) throws.");
+assert.sameValue(trace, "12", "?GetValue(rhs) throws.");
+
+// ?ToPrimive(lhs) throws.
+trace = "";
+assert.throws(MyError, function() {
+  (function() {
+    trace += "1";
+    return {
+      valueOf() {
+        trace += "3";
+        throw new MyError();
+      }
+    };
+  })() >> (function() {
+    trace += "2";
+    return {
+      valueOf() {
+        trace += "4";
+        throw new Test262Error("should not be evaluated");
+      }
+    };
+  })();
+}, "?ToPrimive(lhs) throws.");
+assert.sameValue(trace, "123", "?ToPrimive(lhs) throws.");
+
+// ?ToPrimive(rhs) throws.
+trace = "";
+assert.throws(MyError, function() {
+  (function() {
+    trace += "1";
+    return {
+      valueOf() {
+        trace += "3";
+        return 1;
+      }
+    };
+  })() >> (function() {
+    trace += "2";
+    return {
+      valueOf() {
+        trace += "4";
+        throw new MyError();
+      }
+    };
+  })();
+}, "?ToPrimive(rhs) throws.");
+assert.sameValue(trace, "1234", "?ToPrimive(rhs) throws.");
+
+// ?ToNumeric(lhs) throws.
+trace = "";
+assert.throws(TypeError, function() {
+  (function() {
+    trace += "1";
+    return {
+      valueOf() {
+        trace += "3";
+        return Symbol("1");
+      }
+    };
+  })() >> (function() {
+    trace += "2";
+    return {
+      valueOf() {
+        trace += "4";
+        throw new Test262Error("should not be evaluated");
+      }
+    };
+  })();
+}, "?ToNumeric(lhs) throws.");
+assert.sameValue(trace, "123", "?ToNumeric(lhs) throws.");
+
+// GetValue(lhs) throws.
+trace = "";
+assert.throws(TypeError, function() {
+  (function() {
+    trace += "1";
+    return {
+      valueOf() {
+        trace += "3";
+        return 1;
+      }
+    };
+  })() >> (function() {
+    trace += "2";
+    return {
+      valueOf() {
+        trace += "4";
+        return Symbol("1");
+      }
+    };
+  })();
+}, "GetValue(lhs) throws.");
+assert.sameValue(trace, "1234", "GetValue(lhs) throws.");
diff --git a/test/language/expressions/subtraction/order-of-evaluation.js b/test/language/expressions/subtraction/order-of-evaluation.js
new file mode 100644
index 0000000000..62134d0017
--- /dev/null
+++ b/test/language/expressions/subtraction/order-of-evaluation.js
@@ -0,0 +1,138 @@
+// Copyright (C) 2018 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-subtraction-operator-minus-runtime-semantics-evaluation
+description: Type coercion order of operations for subtraction operator
+features: [Symbol]
+info: |
+  Evaluate lhs
+  Evaluate rhs
+  ToNumeric(lhs)
+  ToNumeric(rhs)
+---*/
+
+function MyError() {}
+var trace;
+
+// ?GetValue(lhs) throws.
+trace = "";
+assert.throws(MyError, function() {
+  (function() {
+    trace += "1";
+    throw new MyError();
+  })() - (function() {
+    trace += "2";
+    throw new Test262Error("should not be evaluated");
+  })();
+}, "?GetValue(lhs) throws.");
+assert.sameValue(trace, "1", "?GetValue(lhs) throws.");
+
+// ?GetValue(rhs) throws.
+trace = "";
+assert.throws(MyError, function() {
+  (function() {
+    trace += "1";
+    return {
+      valueOf() {
+        trace += "3";
+        throw new Test262Error("should not be evaluated");
+      }
+    };
+  })() - (function() {
+    trace += "2";
+    throw new MyError();
+  })();
+}, "?GetValue(rhs) throws.");
+assert.sameValue(trace, "12", "?GetValue(rhs) throws.");
+
+// ?ToPrimive(lhs) throws.
+trace = "";
+assert.throws(MyError, function() {
+  (function() {
+    trace += "1";
+    return {
+      valueOf() {
+        trace += "3";
+        throw new MyError();
+      }
+    };
+  })() - (function() {
+    trace += "2";
+    return {
+      valueOf() {
+        trace += "4";
+        throw new Test262Error("should not be evaluated");
+      }
+    };
+  })();
+}, "?ToPrimive(lhs) throws.");
+assert.sameValue(trace, "123", "?ToPrimive(lhs) throws.");
+
+// ?ToPrimive(rhs) throws.
+trace = "";
+assert.throws(MyError, function() {
+  (function() {
+    trace += "1";
+    return {
+      valueOf() {
+        trace += "3";
+        return 1;
+      }
+    };
+  })() - (function() {
+    trace += "2";
+    return {
+      valueOf() {
+        trace += "4";
+        throw new MyError();
+      }
+    };
+  })();
+}, "?ToPrimive(rhs) throws.");
+assert.sameValue(trace, "1234", "?ToPrimive(rhs) throws.");
+
+// ?ToNumeric(lhs) throws.
+trace = "";
+assert.throws(TypeError, function() {
+  (function() {
+    trace += "1";
+    return {
+      valueOf() {
+        trace += "3";
+        return Symbol("1");
+      }
+    };
+  })() - (function() {
+    trace += "2";
+    return {
+      valueOf() {
+        trace += "4";
+        throw new Test262Error("should not be evaluated");
+      }
+    };
+  })();
+}, "?ToNumeric(lhs) throws.");
+assert.sameValue(trace, "123", "?ToNumeric(lhs) throws.");
+
+// GetValue(lhs) throws.
+trace = "";
+assert.throws(TypeError, function() {
+  (function() {
+    trace += "1";
+    return {
+      valueOf() {
+        trace += "3";
+        return 1;
+      }
+    };
+  })() - (function() {
+    trace += "2";
+    return {
+      valueOf() {
+        trace += "4";
+        return Symbol("1");
+      }
+    };
+  })();
+}, "GetValue(lhs) throws.");
+assert.sameValue(trace, "1234", "GetValue(lhs) throws.");
diff --git a/test/language/expressions/unsigned-right-shift/order-of-evaluation.js b/test/language/expressions/unsigned-right-shift/order-of-evaluation.js
new file mode 100644
index 0000000000..f8eb9442e4
--- /dev/null
+++ b/test/language/expressions/unsigned-right-shift/order-of-evaluation.js
@@ -0,0 +1,138 @@
+// Copyright (C) 2018 Igalia, S.L. All rights reserved.
+// This code is governed by the BSD license found in the LICENSE file.
+/*---
+esid: sec-unsigned-right-shift-operator-runtime-semantics-evaluation
+description: Type coercion order of operations for unsigned-right-shift operator
+features: [Symbol]
+info: |
+  Evaluate lhs
+  Evaluate rhs
+  ToNumeric(lhs)
+  ToNumeric(rhs)
+---*/
+
+function MyError() {}
+var trace;
+
+// ?GetValue(lhs) throws.
+trace = "";
+assert.throws(MyError, function() {
+  (function() {
+    trace += "1";
+    throw new MyError();
+  })() >>> (function() {
+    trace += "2";
+    throw new Test262Error("should not be evaluated");
+  })();
+}, "?GetValue(lhs) throws.");
+assert.sameValue(trace, "1", "?GetValue(lhs) throws.");
+
+// ?GetValue(rhs) throws.
+trace = "";
+assert.throws(MyError, function() {
+  (function() {
+    trace += "1";
+    return {
+      valueOf() {
+        trace += "3";
+        throw new Test262Error("should not be evaluated");
+      }
+    };
+  })() >>> (function() {
+    trace += "2";
+    throw new MyError();
+  })();
+}, "?GetValue(rhs) throws.");
+assert.sameValue(trace, "12", "?GetValue(rhs) throws.");
+
+// ?ToPrimive(lhs) throws.
+trace = "";
+assert.throws(MyError, function() {
+  (function() {
+    trace += "1";
+    return {
+      valueOf() {
+        trace += "3";
+        throw new MyError();
+      }
+    };
+  })() >>> (function() {
+    trace += "2";
+    return {
+      valueOf() {
+        trace += "4";
+        throw new Test262Error("should not be evaluated");
+      }
+    };
+  })();
+}, "?ToPrimive(lhs) throws.");
+assert.sameValue(trace, "123", "?ToPrimive(lhs) throws.");
+
+// ?ToPrimive(rhs) throws.
+trace = "";
+assert.throws(MyError, function() {
+  (function() {
+    trace += "1";
+    return {
+      valueOf() {
+        trace += "3";
+        return 1;
+      }
+    };
+  })() >>> (function() {
+    trace += "2";
+    return {
+      valueOf() {
+        trace += "4";
+        throw new MyError();
+      }
+    };
+  })();
+}, "?ToPrimive(rhs) throws.");
+assert.sameValue(trace, "1234", "?ToPrimive(rhs) throws.");
+
+// ?ToNumeric(lhs) throws.
+trace = "";
+assert.throws(TypeError, function() {
+  (function() {
+    trace += "1";
+    return {
+      valueOf() {
+        trace += "3";
+        return Symbol("1");
+      }
+    };
+  })() >>> (function() {
+    trace += "2";
+    return {
+      valueOf() {
+        trace += "4";
+        throw new Test262Error("should not be evaluated");
+      }
+    };
+  })();
+}, "?ToNumeric(lhs) throws.");
+assert.sameValue(trace, "123", "?ToNumeric(lhs) throws.");
+
+// GetValue(lhs) throws.
+trace = "";
+assert.throws(TypeError, function() {
+  (function() {
+    trace += "1";
+    return {
+      valueOf() {
+        trace += "3";
+        return 1;
+      }
+    };
+  })() >>> (function() {
+    trace += "2";
+    return {
+      valueOf() {
+        trace += "4";
+        return Symbol("1");
+      }
+    };
+  })();
+}, "GetValue(lhs) throws.");
+assert.sameValue(trace, "1234", "GetValue(lhs) throws.");
-- 
GitLab