Integer literal larger than 2^53 is rounded when compiled to JavaScript
ID |
dart.portability.avoid_js_rounded_ints |
Severity |
low |
Remediation Complexity |
medium |
Remediation Risk |
medium |
Remediation Effort |
medium |
Resource |
Platform Portability |
Language |
Dart |
Description
Reports an integer literal, decimal or hexadecimal, whose magnitude exceeds 9007199254740992 (2^53) - the largest integer a JavaScript number represents exactly.
Rationale
Dart integers are 64-bit on the VM but become JavaScript numbers, IEEE-754 doubles, when compiled to the web. Above 2^53 a double cannot hold every integer, so the literal is rounded to the nearest representable value the moment it is compiled: the constant in the web build is silently a different number from the one in the source and from the one the VM build uses. Identifiers taken from other systems - snowflake ids, 64-bit masks, nanosecond timestamps - are exactly the values that exceed the limit, and rounding them corrupts comparisons and lookups rather than making them fail loudly.
The following code illustrates the pattern detected by this rule:
class Ids {
// FLAGGED: Integer literal larger than 2^53 is rounded when compiled to JavaScript
static const snowflake = 9007199254740993;
}
Remediation
Do not carry the value in an int if the code has to run on the web. Keep an identifier as a String and compare it as text, use BigInt for arithmetic that must stay exact, or Int64 from package:fixnum for 64-bit bit manipulation. Where the platform is known to be native only, state that in the code so the constraint is not lost.