sdk icon indicating copy to clipboard operation
sdk copied to clipboard

Non-intuitive behavior of bitwise operations compiled into JavaScript

Open BlueRayi opened this issue 1 year ago • 3 comments

TL;DR Currently, Dart compiled into JavaScript considers the operands of bitwise operations as unsigned 32-bit integers.

I wrote and ran the following code

void main() {
  print(-1 & -1);
  print(-2 ^ 0);
  print(-3 | 0);
  print(~~-4);
  print(-5 << 0);
  print(-6 >> 0);
}

&-1, ^0, |0, ~~, <<0, >>0 These are all known to be identity functions for integers. So, of course, this is what happens when you perform this.

-1
-2
-3
-4
-5
-6

However, when we compile this into JavaScript code and look at the console, something strange is happening.

4294967295
4294967294
4294967293
4294967292
4294967291
4294967290

This is obviously happening because negative values (expressed in 2's complement) are interpreted as unsigned integers. It is my opinion that they should be considered signed 32-bit integers.

In particular, the reference for ~ reads as follows:

This maps any integer x to -x - 1.

Therefore, I consider this implementation inappropriate.

Postscript.

This is not directly related to the above, but the fact that >>>0 is a identity function even for negative values is different from JavaScript semantics and confuses me a bit.

BlueRayi avatar Jul 21 '22 13:07 BlueRayi

Hi @BlueRayi - thank you for reaching out and for providing great details!

This may not be the answer you are looking for, but this is in great part by design. This article https://dart.dev/guides/language/numbers has a deep discussion on the topic, and hopefully can shed some light into why we have these differences and how to reason about them. Note also the section discussing bitwise operations

I don't expect changes in the semantics going forward. That said, we should do better in communicating this in our documentation. As you said, the API docs are misleading today.

@lrhn - would you be open to include a reference to the numbers article from all of our libraries dartdocs? I'd be inclined to include it on every single API, not just at the class level (e.g. int.~, int.&, int.^, etc), to make sure it's very visible when developers are looking at a single API at a time.

sigmundch avatar Jul 21 '22 15:07 sigmundch

/cc @rakudrama in case there is anything else to add

sigmundch avatar Jul 21 '22 15:07 sigmundch

It's probably a good idea to have such links, so it's fine with me.

lrhn avatar Aug 09 '22 14:08 lrhn