Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

BigInt arithmetic type errors #1282

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
42 changes: 42 additions & 0 deletions harness/typeCoercion.js
Original file line number Diff line number Diff line change
Expand Up @@ -407,3 +407,45 @@ function testNotCoercibleToBigInt(test) {
testStringValue("0xg");
testStringValue("1n");
}

function testNotCoercibleToBigIntAdditionOperand(test) {
function testPrimitiveValue(error, value) {
test(error, value);
testPrimitiveWrappers(value, "number", function (value) {
test(error, value);
});
}

// Undefined, Null, Number, Symbol -> TypeError
testPrimitiveValue(TypeError, undefined);
testPrimitiveValue(TypeError, null);
testPrimitiveValue(TypeError, 0);
testPrimitiveValue(TypeError, NaN);
testPrimitiveValue(TypeError, Infinity);
testPrimitiveValue(TypeError, Symbol("1"));
}

function testNotCoercibleToBigIntOperand(test) {
function testPrimitiveValue(error, value) {
test(error, value);
testPrimitiveWrappers(value, "number", function (value) {
test(error, value);
});
}

// Non-BigInt primitive -> TypeError
testPrimitiveValue(TypeError, undefined);
testPrimitiveValue(TypeError, null);
testPrimitiveValue(TypeError, 0);
testPrimitiveValue(TypeError, NaN);
testPrimitiveValue(TypeError, Infinity);
testPrimitiveValue(TypeError, "");
testPrimitiveValue(TypeError, "1");
testPrimitiveValue(TypeError, Symbol("1"));
}

function testCoercibleToBigIntOperand(value, test) {
test(value);
// ToPrimitive
testPrimitiveWrappers(value, "number", test);
}
29 changes: 29 additions & 0 deletions test/language/expressions/addition/bigint-err.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
// Copyright (C) 2017 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: BigInt addition type errors
info: >
The Addition Operator ( + )

Runtime Semantics: Evaluation

...
5. Let lprim be ? ToPrimitive(lval).
6. Let rprim be ? ToPrimitive(rval).
...
8. Let lnum be ? ToNumeric(lprim).
9. Let rnum be ? ToNumeric(rprim).
10. If Type(lnum) does not equal Type(rnum), throw a TypeError
exception.
includes: [typeCoercion.js]
features: [BigInt, Symbol, Symbol.toPrimitive, arrow-function]
---*/

testNotCoercibleToBigIntAdditionOperand(function (error, value1) {
testCoercibleToBigIntOperand(0n, function (value2) {
assert.throws(error, () => value1 + value2);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can we have a sample of what calls we should expect here in this current case? It's being hard for me to traverse this code through all the abstraction.

a list just saying the expected values of value1 and value2 would be really helpful to tell if I am not wrong traversing this code.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When I ran these locally, I encountered a confusing failure:

FAIL test/language/expressions/addition/bigint-err.js
  Expected a MyError but got a TypeError

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The addition in this patch seems pretty analogous to lots of other things in typeCoercion.js, like testNotCoercibleToBigInt. Are those too confusing too? The nested calls are sort of like nested for loops, just done as calls so that we're sure to have the assert in this file.

I'm not sure how you ran the test locally, but when I ran this locally with V8, I saw it succeed. I'd guess that such an error could come from an implementation which doesn't do ToPrimitive properly, e.g., throwing on + between a BigInt and some kinds of objects that should be convertable to BigInt, rather than doing the conversion. An issue is that an unadorned MyError is thrown from a few different paths, so it's hard to figure out which one is failing.

Coercion is especially tricky with BigInt arithmetic operators, especially addition, so I'm glad this test gets at different cases in a comprehensive way. However, I'm not sure if we get much abstraction value by factoring out testNotCoercibleToBigIntAdditionOperand ; I imagine that's only useful in this particular test.

Another strategy, if the abstraction is too confusing, would be to generate many tests. I believe @thejoshwolfe has done this for certain other tests. I don't have a strong opinion one way or the other on which is better. I think if we allow some things in typeCoercion.js, we should allow nested calls like this for things which take multiple arguments; otherwise, where is the line exactly? Maybe there are disadvantages to typeCoercion.js overall in terms of debugging, though. I'm not really sure, since I haven't had the experience of working through a failure yet.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

rwaldron in ~/clonez/test262 on cxielarko-bigint-expr-err*
$ test262-harness --hostType d8 --hostPath `which d8` --hostArgs="--harmony_bigint" test/language/expressions/addition/bigint-err.js
FAIL test/language/expressions/addition/bigint-err.js
  Expected a MyError but got a TypeError

FAIL test/language/expressions/addition/bigint-err.js
  Expected a MyError but got a TypeError

Ran 2 tests
0 passed
2 failed

My d8 is built from 2d60b72890

Copy link
Member

@littledan littledan Oct 16, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Heh, I'm just one patch ahead of you and it seems like that exact bug was just fixed: https://chromium-review.googlesource.com/c/v8/v8/+/716863 , where in particular objects which had to get coerced to BigInts weren't being coerced properly for certain operators, and a valueOf method that returned a BigInt would lead to a TypeError. Good thing this test exists!

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok, I did a manual check for the assertions, registering each assertion call. The list is still incomplete, but enough to observe what is being tested.

here it goes:


testNotCoercibleToBigIntAdditionOperand(test)
  testNotCoercibleToPrimitive(hint: "number", test)
    test(error: TypeError, value1: {[@@toPrimitive]: 1});
      testCoercibleToBigIntOperand(value: 0n, test)
        test(value2: 0n);
          assert.throws(error: TypeError, ()  => {[@@toPrimitive]: 1} + 0n) ************ assertion **********
          assert.throws(error: TypeError, ()  => 0n + {[@@toPrimitive]: 1}) ************ assertion **********
        testPrimitiveWrappers(primitiveValue: 0n , hint: "number", test)
          if (primitiveValue != null) {
            test(value2: Object(primitiveValue: 0n))
              assert.throws(error: TypeError, ()  => {[@@toPrimitive]: 1} + Object(0n)) ************ assertion **********
              assert.throws(error: TypeError, ()  => Object(0n) + {[@@toPrimitive]: 1}) ************ assertion **********
            testCoercibleToPrimitiveWithMethod(hint: "number", method: () => primitiveValue: 0n, test: test);
              if (hint === "number") {
                methodNames = ["valueOf", "toString"];
              }
              
              test(value2: {
                [Symbol.toPrimitive]: (method: () => primitiveValue: 0n),
                [methodNames[0]]: function() { throw new Test262Error(); },
                [methodNames[1]]: function() { throw new Test262Error(); },
              });
                assert.throws(TypeError, ()  => {@@toPrimitive: 1} + {}) ************ assertion **********
                assert.throws(TypeError, ()  => {} + {@@toPrimitive: 1}) ************ assertion **********
              test(value2: {
                [methodNames[0]]: method,
                [methodNames[1]]: function() { throw new Test262Error(); },
              });
                assert.throws(TypeError, ()  => {[@@toPrimitive]: 1} + {} ) ************ assertion **********
                assert.throws(TypeError, ()  => {} + {[@@toPrimitive]: 1} ) ************ assertion **********
              
            
              if (hint === "number") {
                test({
                  [methodNames[1]]: method,
                });
                  assert.throws(TypeError, ()  => {[@@toPrimitive]: 1} + {} ) ************ assertion **********
                  assert.throws(TypeError, ()  => {} + {[@@toPrimitive]: 1} ) ************ assertion **********
              }
              
              test({
                [Symbol.toPrimitive]: undefined,
                [methodNames[0]]: method,
                [methodNames[1]]: method,
              });
                assert.throws(TypeError, ()  => {[@@toPrimitive]: 1} + {}) ************ assertion **********
                assert.throws(TypeError, ()  => {} + {[@@toPrimitive]: 1} ) ************ assertion **********
              test({
                [Symbol.toPrimitive]: null,
                [methodNames[0]]: method,
                [methodNames[1]]: method,
              });
                assert.throws(TypeError, ()  => {[@@toPrimitive]: 1} + {}) ************ assertion **********
                assert.throws(TypeError, ()  => {} + {[@@toPrimitive]: 1} ) ************ assertion **********

              test({
                [methodNames[0]]: null,
                [methodNames[1]]: method,
              });
                assert.throws(TypeError, ()  => {[@@toPrimitive]: 1} + {}) ************ assertion **********
                assert.throws(TypeError, ()  => {} + {[@@toPrimitive]: 1} ) ************ assertion **********
              
              test({
                [methodNames[0]]: 1,
                [methodNames[1]]: method,
              });
                assert.throws(TypeError, ()  => {[@@toPrimitive]: 1} + {}) ************ assertion **********
                assert.throws(TypeError, ()  => {} + {[@@toPrimitive]: 1} ) ************ assertion **********
              test({
                [methodNames[0]]: {},
                [methodNames[1]]: method,
              });
                assert.throws(TypeError, ()  => {[@@toPrimitive]: 1} + {}) ************ assertion **********
                assert.throws(TypeError, ()  => {} + {[@@toPrimitive]: 1} ) ************ assertion **********

              test({
                [methodNames[0]]: function() { return {}; },
                [methodNames[1]]: method,
              });
                assert.throws(TypeError, ()  => {[@@toPrimitive]: 1} + {}) ************ assertion **********
                assert.throws(TypeError, ()  => {} + {[@@toPrimitive]: 1} ) ************ assertion **********
              test({
                [methodNames[0]]: function() { return Object(1); },
                [methodNames[1]]: method,
              });
                assert.throws(TypeError, ()  => {[@@toPrimitive]: 1} + {}) ************ assertion **********
                assert.throws(TypeError, ()  => {} + {[@@toPrimitive]: 1} ) ************ assertion **********
  
    test(error: TypeError, value1: {[@@toPrimitive]: {}});
      ...
      assert.throws(TypeError, ()  => {@@toPrimitive: {}} + 0n) ************ assertion **********
      assert.throws(TypeError, ()  => 0n + {@@toPrimitive: {}}) ************ assertion **********
      
      assert.throws(TypeError, ()  => {@@toPrimitive: {}} + Object(0n)) ************ assertion **********
      assert.throws(TypeError, ()  => Object(0n) + {@@toPrimitive: {}}) ************ assertion **********
      assert.throws(TypeError, ()  => {@@toPrimitive: {}} + {}) ************ assertion **********
      assert.throws(TypeError, ()  => {} + {@@toPrimitive: {}}) ************ assertion **********
      assert.throws(TypeError, ()  => {@@toPrimitive: {}} + {}) ************ assertion **********
      assert.throws(TypeError, ()  => {} + {@@toPrimitive: {}}) ************ assertion **********
      assert.throws(TypeError, ()  => {@@toPrimitive: {}} + {}) ************ assertion **********
      assert.throws(TypeError, ()  => {} + {@@toPrimitive: {}}) ************ assertion **********
      assert.throws(TypeError, ()  => {@@toPrimitive: {}} + {}) ************ assertion **********
      assert.throws(TypeError, ()  => {} + {@@toPrimitive: {}}) ************ assertion **********
      assert.throws(TypeError, ()  => {@@toPrimitive: {}} + {}) ************ assertion **********
      assert.throws(TypeError, ()  => {} + {@@toPrimitive: {}}) ************ assertion **********
      assert.throws(TypeError, ()  => {@@toPrimitive: {}} + {}) ************ assertion **********
      assert.throws(TypeError, ()  => {} + {@@toPrimitive: {}}) ************ assertion **********
      assert.throws(TypeError, ()  => {@@toPrimitive: {}} + {}) ************ assertion **********
      assert.throws(TypeError, ()  => {} + {@@toPrimitive: {}}) ************ assertion **********
      assert.throws(TypeError, ()  => {@@toPrimitive: {}} + {}) ************ assertion **********
      assert.throws(TypeError, ()  => {} + {@@toPrimitive: {}}) ************ assertion **********
      assert.throws(TypeError, ()  => {@@toPrimitive: {}} + {}) ************ assertion **********
      assert.throws(TypeError, ()  => {} + {@@toPrimitive: {}}) ************ assertion **********
      

    test(TypeError, {[Symbol.toPrimitive]: function() { return Object(1); }});
      ...
      assert.throws(TypeError, ()  => {@@toPrimitive: () => Object(1)} + 0n) ************ assertion **********
      assert.throws(TypeError, ()  => 0n + {@@toPrimitive: () => Object(1)}) ************ assertion **********
      
      assert.throws(TypeError, ()  => {@@toPrimitive: () => Object(1)} + Object(0n)) ************ assertion **********
      assert.throws(TypeError, ()  => Object(0n) + {@@toPrimitive: () => Object(1)}) ************ assertion **********
      assert.throws(TypeError, ()  => {@@toPrimitive: () => Object(1)} + {}) ************ assertion **********
      assert.throws(TypeError, ()  => {} + {@@toPrimitive: () => Object(1)}) ************ assertion **********
      assert.throws(TypeError, ()  => {@@toPrimitive: () => Object(1)} + {}) ************ assertion **********
      assert.throws(TypeError, ()  => {} + {@@toPrimitive: () => Object(1)}) ************ assertion **********
      assert.throws(TypeError, ()  => {@@toPrimitive: () => Object(1)} + {}) ************ assertion **********
      assert.throws(TypeError, ()  => {} + {@@toPrimitive: () => Object(1)}) ************ assertion **********
      assert.throws(TypeError, ()  => {@@toPrimitive: () => Object(1)} + {}) ************ assertion **********
      assert.throws(TypeError, ()  => {} + {@@toPrimitive: () => Object(1)}) ************ assertion **********
      assert.throws(TypeError, ()  => {@@toPrimitive: () => Object(1)} + {}) ************ assertion **********
      assert.throws(TypeError, ()  => {} + {@@toPrimitive: () => Object(1)}) ************ assertion **********
      assert.throws(TypeError, ()  => {@@toPrimitive: () => Object(1)} + {}) ************ assertion **********
      assert.throws(TypeError, ()  => {} + {@@toPrimitive: () => Object(1)}) ************ assertion **********
      assert.throws(TypeError, ()  => {@@toPrimitive: () => Object(1)} + {}) ************ assertion **********
      assert.throws(TypeError, ()  => {} + {@@toPrimitive: () => Object(1)}) ************ assertion **********
      assert.throws(TypeError, ()  => {@@toPrimitive: () => Object(1)} + {}) ************ assertion **********
      assert.throws(TypeError, ()  => {} + {@@toPrimitive: () => Object(1)}) ************ assertion **********
      assert.throws(TypeError, ()  => {@@toPrimitive: () => Object(1)} + {}) ************ assertion **********
      assert.throws(TypeError, ()  => {} + {@@toPrimitive: () => Object(1)}) ************ assertion **********
      

    test(TypeError, {[Symbol.toPrimitive]: function() { return {}; }});
      ...
      assert.throws(TypeError, () => {@@toPrimitive: () => {}} + 0n) ************ assertion **********
      assert.throws(TypeError, ()  => 0n + {@@toPrimitive: () => {}}) ************ assertion **********
      
      assert.throws(TypeError, ()  => {@@toPrimitive: () => {}} + Object(0n)) ************ assertion **********
      assert.throws(TypeError, ()  => Object(0n) + {@@toPrimitive: () => {}}) ************ assertion **********
      assert.throws(TypeError, ()  => {@@toPrimitive: () => {}} + {}) ************ assertion **********
      assert.throws(TypeError, ()  => {} + {@@toPrimitive: () => {}}) ************ assertion **********
      assert.throws(TypeError, ()  => {@@toPrimitive: () => {}} + {}) ************ assertion **********
      assert.throws(TypeError, ()  => {} + {@@toPrimitive: () => {}}) ************ assertion **********
      assert.throws(TypeError, ()  => {@@toPrimitive: () => {}} + {}) ************ assertion **********
      assert.throws(TypeError, ()  => {} + {@@toPrimitive: () => {}}) ************ assertion **********
      assert.throws(TypeError, ()  => {@@toPrimitive: () => {}} + {}) ************ assertion **********
      assert.throws(TypeError, ()  => {} + {@@toPrimitive: () => {}}) ************ assertion **********
      assert.throws(TypeError, ()  => {@@toPrimitive: () => {}} + {}) ************ assertion **********
      assert.throws(TypeError, ()  => {} + {@@toPrimitive: () => {}}) ************ assertion **********
      assert.throws(TypeError, ()  => {@@toPrimitive: () => {}} + {}) ************ assertion **********
      assert.throws(TypeError, ()  => {} + {@@toPrimitive: () => {}}) ************ assertion **********
      assert.throws(TypeError, ()  => {@@toPrimitive: () => {}} + {}) ************ assertion **********
      assert.throws(TypeError, ()  => {} + {@@toPrimitive: () => {}}) ************ assertion **********
      assert.throws(TypeError, ()  => {@@toPrimitive: () => {}} + {}) ************ assertion **********
      assert.throws(TypeError, ()  => {} + {@@toPrimitive: () => {}}) ************ assertion **********
      assert.throws(TypeError, ()  => {@@toPrimitive: () => {}} + {}) ************ assertion **********
      assert.throws(TypeError, ()  => {} + {@@toPrimitive: () => {}}) ************ assertion **********
      
    test(MyError, {[Symbol.toPrimitive]: function() { throw new MyError(); }});
      ...
      obj = {@@toPrimitive: () => { throw new MyError() }}
      assert.throws(MyError, () => obj + 0n) ************ assertion **********
      assert.throws(MyError, () => 0n + obj) ************ assertion **********
      assert.throws(MyError, () => obj + Object(0n)) ************ assertion **********
      assert.throws(MyError, () => Object(0n) + obj) ************ assertion **********
      assert.throws(MyError, ()  => obj + {}) ************ assertion **********
      assert.throws(MyError, ()  => {} + obj) ************ assertion **********
      assert.throws(MyError, ()  => obj + {}) ************ assertion **********
      assert.throws(MyError, ()  => {} + obj) ************ assertion **********
      assert.throws(MyError, ()  => obj + {}) ************ assertion **********
      assert.throws(MyError, ()  => {} + obj) ************ assertion **********
      assert.throws(MyError, ()  => obj + {}) ************ assertion **********
      assert.throws(MyError, ()  => {} + obj) ************ assertion **********
      assert.throws(MyError, ()  => obj + {}) ************ assertion **********
      assert.throws(MyError, ()  => {} + obj) ************ assertion **********
      assert.throws(MyError, ()  => obj + {}) ************ assertion **********
      assert.throws(MyError, ()  => {} + obj) ************ assertion **********
      assert.throws(MyError, ()  => obj + {}) ************ assertion **********
      assert.throws(MyError, ()  => {} + obj) ************ assertion **********
      assert.throws(MyError, ()  => obj + {}) ************ assertion **********
      assert.throws(MyError, ()  => {} + obj) ************ assertion **********
      assert.throws(MyError, ()  => obj + {}) ************ assertion **********
      assert.throws(MyError, ()  => {} + obj) ************ assertion **********
     
    testCoercibleToPrimitiveWithMethod
      ...
      ???
    
    testUnsuitableMethod
      test(TypeError, {valueOf:null, toString:null});
    testUnsuitableMethod
      test(TypeError, {valueOf:1, toString:1});
    testUnsuitableMethod
      test(TypeError, {valueOf:{}, toString:{}});
    testUnsuitableMethod
      test(TypeError, {valueOf:function() { return Object(1); }, toString:function() { return Object(1); }});
    testUnsuitableMethod
      test(TypeError, {valueOf:function() { return {}; }, toString:function() { return {}; }});


   ....

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

so, reading from this list, I have to ask what is the purpose of having too many assertions. The target being tested are just the same. The cases where you coerce a valid operand should be fine if everything else you're testing is just checking for the error caused by the other operand.

This is just like:

assert.throws(Error, function() { poisoned + okcoercion });
assert.throws(Error, function() { okcoercion + poisoned });

and then you expand every possibility of valid coercions for the operand that is not poisoned. They are redundant and unhelpful if any assertion fails. Stressing the poisoned value should be the goal here, right?


There are even cases where both operands are poisoned and you can't even observe what part is failing:

testUnsuitableMethod
      test(TypeError, {valueOf:1, toString:1});

Leads you to assert poisoned1 + poisoned2 will cause a TypeError, from one operand or another. So the assertion might even produce a false positive if only one of them coerces to an invalid value type.


Being able to read and understand just the tests for this single file to finally write this here took me a very long time. I wonder if it's really worth making readability obscure using a weak abstraction. If this test ever needs maintenance, it will be really hard to change anything, specially not being able to tell if the abstractions won't affect anything else.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

for clarification, I've been working on this for a long time and after some editions I removed something relevant to explain my output blob:

              if (hint === "number") {
                methodNames = ["valueOf", "toString"];
              }
              
              test(value2: {
                [Symbol.toPrimitive]: (method: () => primitiveValue: 0n),
                [methodNames[0]]: function() { throw new Test262Error(); },
                [methodNames[1]]: function() { throw new Test262Error(); },
              });
                assert.throws(TypeError, ()  => {@@toPrimitive: 1} + {}`) ************ assertion **********
                assert.throws(TypeError, ()  => {} + {@@toPrimitive: 1}) ************ assertion **********

the simple {} is a short for the valid object being coerced. so when you read: {@@toPrimitive: 1} + {} it's a short and vague notation for:

{@@toPrimitive: 1} + {@@toPrimitive() { return primitiveValue }, valueOf: function() { throw new Test262Error(); }, function() { throw new Test262Error(); }}

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would it be better to statically generate the code for these tests, to make it clearer what assertions are actually being made?

I don't really understand why the "poisoned+non_poisoned" tests are problematic (since they're not incorrect or completely equivalent), but it's easy enough to simplify them. I'll remove the "poisoned+poisoned" assertions; there are already better tests for that.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would it be better to statically generate the code for these tests, to make it clearer what assertions are actually being made?

This gets my +1

assert.throws(error, () => value2 + value1);
});
});
27 changes: 27 additions & 0 deletions test/language/expressions/bitwise-and/bigint-err.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
// Copyright (C) 2017 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: BigInt bitwise and type errors
info: >
Binary Bitwise Operators

Runtime Semantics: Evaluation

...
5. Let lnum be ? ToNumeric(leftValue).
6. Let rnum be ? ToNumeric(rightValue).
7. If Type(lnum) does not equal Type(rnum), throw a TypeError
exception.
...
includes: [typeCoercion.js]
features: [BigInt, Symbol, Symbol.toPrimitive, arrow-function]
---*/

testNotCoercibleToBigIntOperand(function (error, value1) {
testCoercibleToBigIntOperand(0n, function (value2) {
assert.throws(error, () => value1 & value2);
assert.throws(error, () => value2 & value1);
});
});
27 changes: 27 additions & 0 deletions test/language/expressions/bitwise-or/bigint-err.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
// Copyright (C) 2017 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: BigInt bitwise or type errors
info: >
Binary Bitwise Operators

Runtime Semantics: Evaluation

...
5. Let lnum be ? ToNumeric(leftValue).
6. Let rnum be ? ToNumeric(rightValue).
7. If Type(lnum) does not equal Type(rnum), throw a TypeError
exception.
...
includes: [typeCoercion.js]
features: [BigInt, Symbol, Symbol.toPrimitive, arrow-function]
---*/

testNotCoercibleToBigIntOperand(function (error, value1) {
testCoercibleToBigIntOperand(0n, function (value2) {
assert.throws(error, () => value1 | value2);
assert.throws(error, () => value2 | value1);
});
});
27 changes: 27 additions & 0 deletions test/language/expressions/bitwise-xor/bigint-err.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
// Copyright (C) 2017 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: BigInt bitwise xor type errors
info: >
Binary Bitwise Operators

Runtime Semantics: Evaluation

...
5. Let lnum be ? ToNumeric(leftValue).
6. Let rnum be ? ToNumeric(rightValue).
7. If Type(lnum) does not equal Type(rnum), throw a TypeError
exception.
...
includes: [typeCoercion.js]
features: [BigInt, Symbol, Symbol.toPrimitive, arrow-function]
---*/

testNotCoercibleToBigIntOperand(function (error, value1) {
testCoercibleToBigIntOperand(0n, function (value2) {
assert.throws(error, () => value1 ^ value2);
assert.throws(error, () => value2 ^ value1);
});
});
27 changes: 27 additions & 0 deletions test/language/expressions/division/bigint-err.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
// Copyright (C) 2017 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: BigInt division type errors
info: >
Multiplicative Operators

Runtime Semantics: Evaluation

...
5. Let lnum be ? ToNumeric(leftValue).
6. Let rnum be ? ToNumeric(rightValue).
7. If Type(lnum) does not equal Type(rnum), throw a TypeError
exception.
...
includes: [typeCoercion.js]
features: [BigInt, Symbol, Symbol.toPrimitive, arrow-function]
---*/

testNotCoercibleToBigIntOperand(function (error, value1) {
testCoercibleToBigIntOperand(1n, function (value2) {
assert.throws(error, () => value1 / value2);
assert.throws(error, () => value2 / value1);
});
});
27 changes: 27 additions & 0 deletions test/language/expressions/exponentiation/bigint-err.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
// Copyright (C) 2017 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: BigInt exponentiation type errors
info: >
Exponentiation Operator

Runtime Semantics: Evaluation

...
5. Let base be ? ToNumeric(leftValue).
6. Let exponent be ? ToNumeric(rightValue).
7. If Type(lnum) does not equal Type(rnum), throw a TypeError
exception.
...
includes: [typeCoercion.js]
features: [BigInt, Symbol, Symbol.toPrimitive, arrow-function]
---*/

testNotCoercibleToBigIntOperand(function (error, value1) {
testCoercibleToBigIntOperand(1n, function (value2) {
assert.throws(error, () => value1 ** value2);
assert.throws(error, () => value2 ** value1);
});
});
27 changes: 27 additions & 0 deletions test/language/expressions/left-shift/bigint-err.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
// Copyright (C) 2017 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: BigInt left shift type errors
info: >
The Left Shift Operator ( << )

Runtime Semantics: Evaluation

...
5. Let lnum be ? ToNumeric(leftValue).
6. Let rnum be ? ToNumeric(rightValue).
7. If Type(lnum) does not equal Type(rnum), throw a TypeError
exception.
...
includes: [typeCoercion.js]
features: [BigInt, Symbol, Symbol.toPrimitive, arrow-function]
---*/

testNotCoercibleToBigIntOperand(function (error, value1) {
testCoercibleToBigIntOperand(0n, function (value2) {
assert.throws(error, () => value1 << value2);
assert.throws(error, () => value2 << value1);
});
});
27 changes: 27 additions & 0 deletions test/language/expressions/modulus/bigint-err.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
// Copyright (C) 2017 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: BigInt remainder type errors
info: >
Multiplicative Operators

Runtime Semantics: Evaluation

...
5. Let lnum be ? ToNumeric(leftValue).
6. Let rnum be ? ToNumeric(rightValue).
7. If Type(lnum) does not equal Type(rnum), throw a TypeError
exception.
...
includes: [typeCoercion.js]
features: [BigInt, Symbol, Symbol.toPrimitive, arrow-function]
---*/

testNotCoercibleToBigIntOperand(function (error, value1) {
testCoercibleToBigIntOperand(1n, function (value2) {
assert.throws(error, () => value1 % value2);
assert.throws(error, () => value2 % value1);
});
});
27 changes: 27 additions & 0 deletions test/language/expressions/multiplication/bigint-err.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
// Copyright (C) 2017 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: BigInt multiplication type errors
info: >
Multiplicative Operators

Runtime Semantics: Evaluation

...
5. Let lnum be ? ToNumeric(leftValue).
6. Let rnum be ? ToNumeric(rightValue).
7. If Type(lnum) does not equal Type(rnum), throw a TypeError
exception.
...
includes: [typeCoercion.js]
features: [BigInt, Symbol, Symbol.toPrimitive, arrow-function]
---*/

testNotCoercibleToBigIntOperand(function (error, value1) {
testCoercibleToBigIntOperand(0n, function (value2) {
assert.throws(error, () => value1 * value2);
assert.throws(error, () => value2 * value1);
});
});
27 changes: 27 additions & 0 deletions test/language/expressions/right-shift/bigint-err.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
// Copyright (C) 2017 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: BigInt right shift type errors
info: >
The Signed Right Shift Operator ( >> )

Runtime Semantics: Evaluation

...
5. Let lnum be ? ToNumeric(leftValue).
6. Let rnum be ? ToNumeric(rightValue).
7. If Type(lnum) does not equal Type(rnum), throw a TypeError
exception.
...
includes: [typeCoercion.js]
features: [BigInt, Symbol, Symbol.toPrimitive, arrow-function]
---*/

testNotCoercibleToBigIntOperand(function (error, value1) {
testCoercibleToBigIntOperand(0n, function (value2) {
assert.throws(error, () => value1 >> value2);
assert.throws(error, () => value2 >> value1);
});
});
27 changes: 27 additions & 0 deletions test/language/expressions/subtraction/bigint-err.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
// Copyright (C) 2017 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: BigInt subtraction type errors
info: >
The Subtraction Operator ( - )

Runtime Semantics: Evaluation

...
5. Let lnum be ? ToNumeric(lval).
6. Let rnum be ? ToNumeric(rval).
7. If Type(lnum) does not equal Type(rnum), throw a TypeError
exception.
...
includes: [typeCoercion.js]
features: [BigInt, Symbol, Symbol.toPrimitive, arrow-function]
---*/

testNotCoercibleToBigIntOperand(function (error, value1) {
testCoercibleToBigIntOperand(0n, function (value2) {
assert.throws(error, () => value1 - value2);
assert.throws(error, () => value2 - value1);
});
});
27 changes: 27 additions & 0 deletions test/language/expressions/unsigned-right-shift/bigint-err.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
// Copyright (C) 2017 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: BigInt unsigned right shift type errors
info: >
The Unsigned Right Shift Operator ( >>> )

Runtime Semantics: Evaluation

...
5. Let lnum be ? ToNumeric(leftValue).
6. Let rnum be ? ToNumeric(rightValue).
7. If Type(lnum) does not equal Type(rnum), throw a TypeError
exception.
...
includes: [typeCoercion.js]
features: [BigInt, Symbol, Symbol.toPrimitive, arrow-function]
---*/

testNotCoercibleToBigIntOperand(function (error, value1) {
testCoercibleToBigIntOperand(0n, function (value2) {
assert.throws(error, () => value1 >>> value2);
assert.throws(error, () => value2 >>> value1);
});
});