Skip to content

Fix ObjectId.fromHexString(…) on web#5

Open
JonasWanke wants to merge 1 commit intogonuit:masterfrom
JonasWanke:fix-fromhexstring-on-web
Open

Fix ObjectId.fromHexString(…) on web#5
JonasWanke wants to merge 1 commit intogonuit:masterfrom
JonasWanke:fix-fromhexstring-on-web

Conversation

@JonasWanke
Copy link
Copy Markdown

Take the following code:

final id = ObjectId();
final idFromHexString = ObjectId.fromHexString(id.hexString);

print(id.hexString);
print(idFromHexString.hexString);
print('');
print(id.bytes);
print(idFromHexString.bytes);

When running it on the web, it prints something like the following:

699846cfc5a2616c8b8d30bb
699846cfc5a2616c8b8d30bb

[105, 152, 70, 207, 197, 162, 97, 108, 139, 141, 48, 187]
[105, 152, 70, 207, 0, 162, 97, 108, 139, 141, 48, 187]

https://dartpad.dev?id=00c4616e433c9e1d06910c01d450d10e&run=true

The hexStrings are equal, but the bytes differ. This caused quite some confusion in a Flutter web app we developed. The cause for this is how numbers work in Dart on the web:

Bitwise operations

For performance reasons on the web, bitwise (&, |, ^, ~) and shift (<<,>>, >>>) operators on int use the native JavaScript equivalents. In JavaScript, the operands are truncated to 32-bit integers that are treated as unsigned. This treatment can lead to surprising results on larger numbers. In particular, if operands are negative or don't fit into 32 bits, they're likely to produce different results between native and web.

https://dart.dev/resources/language/number-representation#bitwise-operations

Specifically, ObjectId.fromHexString(…) parses the five byte long process-unique part of the ObjectId into a number, and then extracts the individual bytes using shift operations – which works for the four lower bytes, but not the fifth one. (The hexString was still equal because it was cached from the input argument.)

To fix this, I split parsing the process unique part into two int.parse(…) calls.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant