
BigInt Shipping in Firefox - ingve
https://wingolog.org/archives/2019/05/23/bigint-shipping-in-firefox
======
vngzs
Here is the proposal[0].

There are important real use cases for this. I authored an implementation of
the FNV64 hash function[1] at my last job. I needed to use the
BigInteger.js[2] library. It truly surprised me that Javascript in 2018 did
not support something so simple as 64-bit integers.

[0]: [https://tc39.github.io/proposal-
bigint/](https://tc39.github.io/proposal-bigint/)

[1]:
[https://golang.org/src/hash/fnv/fnv.go](https://golang.org/src/hash/fnv/fnv.go)

[2]:
[https://github.com/peterolson/BigInteger.js](https://github.com/peterolson/BigInteger.js)

~~~
ClassyJacket
Yeah - plus Javascript doesn't even support _32 bit_ integers.

~~~
GordonS
Eh? What exactly _is_ JavaScript's numeric type then? I always presumed it was
a 32-bit, signed integer..

~~~
vbezhenar
JavaScript uses double. Though its precision is more than enough to support 32
bits. Actually it supports 53 bits for integers, then it gets imprecise.

~~~
ska
lua does the same thing. It's not crazy.

~~~
rayiner
Failing to distinguish between integer and floating point types is crazy. Not
as crazy as TCL’s everything being a strong, but not the work of a mentally
well person.

~~~
nine_k
It's a work of RAM-constrained and time-constrained people in early 1990s,
following approaches developed on 1970s for Lisp.

Packing as much as possible into a single cons cell, or a JS value, was (and
is) important, so bit masking to distinguish between integers, floats,
strings, functions, objects, was an inevitable approach.

~~~
rayiner
Lisp has distinct integer and floating point types with the correct behavior
for those types. At runtime they might get passed around as tagged data, but
that’s not visible in the language semantics. In JavaScript, by contrast, the
language exposes only a double float rule and you have to use floats where
you’d otherwise use integers.

~~~
nine_k
I agree. A Lisp may not make available all bits of a machine word to an
integer, but they won't mix up an integer and a float.

JavaScript tried to make things artificially "simpler" by implicit
conversions. As usual, the lack of consistency only lead to more eventual
complexity than a sound solution would have in the first place.

------
dlbucci
Kind of bummed this is a new primitive type. Every instance of `typeof a ===
'number'` just became `typeof a === `number` || typeof a === 'bigint'`...

EDIT: The more I think about it (and the more comments I get), the more I
think this might actually be a good thing. I think bigint will probably not be
used in places where integer numbers are currently used, and it might be
unreasonable to expect code to work with numbers or bigints. In that case,
it's actually probably good that you can easily tell the difference using
typeof, without requiring some hacky fix like `Array.isArray`.

It does mean that "don't mix numbers and bigints" is going to become very
popular JS advice soon.

~~~
jchw
To be fair, it really shouldn’t be conflated with ‘number’ - it isn’t the same
thing, the behavior differs. And you can (and probably should) use small
helper functions for these kinds of checks, pretty much for this kind of
flexibility. Kind of curious what other libs (like lodash) will do.

~~~
wvenable
If you're really going to do it right, that small function should also be
published as npm package (isnumeric) that takes at least 2 other packages
(isnumber and isbigint) as dependencies.

~~~
jchw
I’m super strongly against this concept actually, which you might gather from
mention of lodash.

~~~
coolreader18
I think they were making a joke.

~~~
jchw
Obviously it was some degree of tongue-in-cheek, but I’m not really that
amused, to be honest. It needs a leftpad reference or something.

~~~
fgonzag
Anybody who thinks that's actually good (or even real) advice is going to
write horrible code regardless, IMHO.

~~~
wvenable
[https://www.npmjs.com/browse/depended/is-
number](https://www.npmjs.com/browse/depended/is-number)

~~~
fgonzag
That's horrifying, I thought the whole isNumber thing was a joke.

Do these guys assemble their application as hundreds (or thousands) of NPM
packages containing single functions and then import them together? Because
now I actually believe they are capable of it.

~~~
wvenable
You might enjoy this as well:
[https://www.theregister.co.uk/2016/03/23/npm_left_pad_chaos/](https://www.theregister.co.uk/2016/03/23/npm_left_pad_chaos/)

And this: [https://dev.to/leoat12/the-nodemodules-
problem-29dc](https://dev.to/leoat12/the-nodemodules-problem-29dc)

------
warpech
Anyone knows how does bigint serialization and deserialization to JSON look
like in practice in Chrome and Firefox?

~~~
callahad
You can define a toJSON property on the BigInt prototype that gets used for
serialization:

    
    
        Object.defineProperty(BigInt.prototype, "toJSON", {
            get() {
                "use strict";
                return () => String(this);
            }
        });
    

Of course you could also serialize to a Number, but that risks losing
precision. For example, the Twitter API often returns IDs as both a Number
("id") and a String ("id_str") to safely handle cases where the value might
fall outside of a normal double-precision float:
[https://developer.twitter.com/en/docs/tweets/data-
dictionary...](https://developer.twitter.com/en/docs/tweets/data-
dictionary/overview/intro-to-tweet-json.html)

~~~
zamadatix
Only in JS do people seem okay with constantly mucking with built-ins.

~~~
mikepurvis
Ruby has a culture around it too:
[https://www.justinweiss.com/articles/3-ways-to-monkey-
patch-...](https://www.justinweiss.com/articles/3-ways-to-monkey-patch-
without-making-a-mess/)

And you can get some of the patching effect in any language with uniform
function/method calls, though typically with a little more scoping and thus
less ability to inflict unexpected side effects:
[https://en.wikipedia.org/wiki/Uniform_Function_Call_Syntax](https://en.wikipedia.org/wiki/Uniform_Function_Call_Syntax)

~~~
badosu
For pretty much the past decade (specially the last few years) I feel the
culture has shifted to consider core monkey patches as a pretty bad practice.

~~~
hombre_fatal
Sure, but it's also a bad practice in Javascript.

------
cpeterso
BitInt's "n" suffix appears to stand for "numeric", but that seems confusing
when _typeof 1 === "number"_ and _typeof 1n === "bigint"_. Why not an "i"
suffix for "integer"? I understand that a "b" suffix is probably reserved in
case JavaScript adds support for binary literals.

[https://tc39.github.io/proposal-bigint/#prod-
BigIntLiteralSu...](https://tc39.github.io/proposal-bigint/#prod-
BigIntLiteralSuffix)

~~~
loeg
1i is a bit more difficult to read than 1n in many fonts. I don't think any
numeral is plausibly confused with n, so 'iNt' makes some sense as a suffix
IMO.

~~~
GordonS
As an aside, c# uses "L" to denote literals as 64-bit integers. "l" works too,
but "L" is encouraged for the same reason you give ("l" could be confused as
"1")

------
crazygringo
For context, more general browser compatibility:

[https://developer.mozilla.org/en-
US/docs/Web/JavaScript/Refe...](https://developer.mozilla.org/en-
US/docs/Web/JavaScript/Reference/Global_Objects/BigInt#Browser_compatibility)

In Chrome, but not Safari or Edge.

~~~
CharlesW
For those who care about JavaScript in embedded environments, Moddable
released BigInt support in their open-source XS engine a few months ago:
[http://blog.moddable.com/blog/bigint/](http://blog.moddable.com/blog/bigint/)

------
jshowa3
What's with the comment at the end of the blog entry? lol.

~~~
azinman2
I know right? Big accusation (that’s wrong), with nothing to back it up?

~~~
alxmdev
Maybe it's the algorithmic evolution of those gibberish comments WordPress
blogs used to get all the time...

------
1f60c
This is _big_ news! Shouldn’t the title be amended to include that it’s in
Firefox Beta for now?

------
mourner
That's awesome! Works great on my Pi digits calculation demo :)
[https://observablehq.com/@mourner/calculating-pi-
digits](https://observablehq.com/@mourner/calculating-pi-digits)

------
krispbyte
Once I was working with a database with large integer ids loading them through
json and showing them in the browser. There was a bug where ids didn't match
when updating a record. The issue was that the json decoder for Javascript
didn't handle large numbers, so an id like 12345678901234567 would show up as
12345678901234568. That was fun to debug.

I wonder if the interpreters will convert between BigInts and small ints
automatically now? The backend side was PHP and it did so we never noticed the
problem there.

~~~
tynorf
This is one reason why people use strings for IDs in JSON, even if they are
actually integers.

------
stcredzero
Now I can have 2^128 grid squares in my procedurally generated browser MMO,
instead of 2^106. That sounds like a joke, but it's actually a fact.

------
andreigheorghe
I'm curious why this wasn't shipped as a replacement of the existing Number
type implementation, instead of this new type and syntax.

~~~
Illniyar
Because Numbers in javascripts are floats, and not allowing floats in numbers
would be a serious backward compatibility issue.

Also, I'm assuming there are performance issues with using bigints.

~~~
52-6F-62
Sounds like you're correct according to MDN:

[https://developer.mozilla.org/en-
US/docs/Web/JavaScript/Refe...](https://developer.mozilla.org/en-
US/docs/Web/JavaScript/Reference/Global_Objects/BigInt#Cryptography)

------
snek
I'm so glad we have two shipping implementations now

------
Lowkeyloki
I can't wait to kick the tires on this feature. I wonder how it compares to
the integer implementation in WebAssembly.

~~~
recursive
WebAssembly has not arbitrary precision integers, so presumably is able to
execute arithmetic as direct hardware instructions. bigint, on the other hand,
is arbitrary precision, so it obviously can't do that.

------
qwerty456127
Now let's wait another decade before they add BigDecimal...

~~~
Gibbon1
I think a friend of mine said he was in a meeting back when Javascript was
being standardized. Mike Cowlishaw proposed that Javascript use REXX's Decimal
type instead of IEEE 754.

Everyone thought that was a really bad stupid idea.

~~~
qwerty456127
It probably is when it's about "instead". IEEE 754 floating point computations
are much much faster (given hardware support) while the precision is
sufficient for most of the applications that don't have to deal with money.

~~~
Gibbon1
I talked to my friend, he said Mike Cowlishaw tried very patiently explaining
multiple times the need for a decimal type and basically ran into your
argument.

IE. If we provide a decimal type as a default. Then everyone will use it and
it'll be 'slow'. Thus this is a bad idea. So we should not make that even an
option. Because IEEE 754 is fast and fast is 'good'

Frankly that decision was the worst language decision ever made bar none.

------
ggm
can it represent and manipulate ipv6 addresses (128 bit quantities)
efficiently? not having to split into two 64 bits or deal with them as bit-
strings may be an improvement for some things

~~~
dfox
Internally it is implemented by spliting the number into an array of
conveniently sized chunks (traditionally called limbs). That might mean either
the machine word size for optimized assembly implementation on many common
platforms or one bit less than native word size for portable C implementation
(and architectures without carry flag) or some fixed number like 15 bits (IIRC
mbedTLS has or at least used to have hardcoded limb size of 15bits in its
bignum implementation).

------
philbarr
I feel sorry for whoever has to write the polyfill for this...

~~~
derefr
Bignums themselves are actually pretty easy to implement as a plain library,
_provided_ your language has a uint8-array type (not just a String type, which
might require the content be utf-8 valid, or might only have facilities to
operate on codepoints, or might cut the data off at the first NUL.)

JS already has a Uint8Array, so bignum libraries are easy. (Let me tell you
though, there were JS bignum libraries _before_ Uint8Array, and they were,
ahem, “interesting.” I think a popular one built a byte-array abstraction on
top of hex-encoded strings, and then built bignums on that.)

Actually supporting the literal syntax or the operators via a plain library is
impossible; but you can just do it the other way around: encourage developers
to use a bignum library (for now), and have said library just “bake down” to
native BigInts when they’re available.

Since everybody until now who was using bignums in JS was using them through a
library, this won’t be a hard change to make.

(And it’s already been done! [https://www.npmjs.com/package/big-
integer](https://www.npmjs.com/package/big-integer) now bakes down to native
BigInts when it can.)

As for the brazen developers who start writing code to directly use the native
BigInt... I suppose they’ll have to have two versions of their compiled code
units in their minified blob, with a loader shim that evals out the version of
the class/module that does/doesn’t use bigints. Maybe we’ll see an JS-pipeline
pass to generate this. (I’m not a JS dev, so I’m not sure if there’s already
support for this kind of thing.)

~~~
anoncake
> Actually supporting the literal syntax or the operators via a plain library
> is impossible; but you can just do it the other way around: encourage
> developers to use a bignum library (for now), and have said library just
> “bake down” to native BigInts when they’re available.

Can't you rewrite the syntax into something usable at runtime? Not that it
were a good idea.

~~~
derefr
This ... _might_ be possible, but the performance would indeed suck; you’d
need to essentially ship half a compiler toolchain in your polyfill, and
ensure that it gets run separately, non-async, so that the browser finishes
installing it before attempting to interpret any more <script> tags. (And,
presumably, all of your app’s source would be in the next script tag, so that
your app can take advantage of native bigints; so your app wouldn’t load at
all until the toolchain had finished bootstrapping.)

I’m guessing this _has_ been done, to let the browser run—without backend
compilation—<script type=“foo”> where foo is CoffeeScript or TypeScript or
ClojureScript or what-have-you; but this one would be especially bad, because
the thing it’d be targeting would still be _Javascript_ , and so you’d have to
rewrite all Javascript sources you encounter, with most of them likely never
using native bigints but suffering the double-parsing overhead anyway.

Oh, and you’d have to override the ES6 module loader with one that also
rewrites what it loads. Ugly.

------
deathanatos
> _This contrasts with JavaScript number values, which have the well-known
> property of only being able to precisely represent integers between -2⁵³ and
> 2⁵³._

JS's Number can represent way more integers than just those between -2⁵³ and
2⁵³. There's a great StackOverflow answer[1] that answers a similar question,
("What is the biggest "no-floating" integer that can be stored in an IEEE 754
double type without losing precision?") which also applies here (A JS Number
is an IEEE double):

> _The biggest /largest integer that can be stored in a double without losing
> precision is the same as the largest possible value of a double. That is,
> DBL_MAX or approximately 1.8 × 10³⁰⁸ (if your double is an IEEE 754 64-bit
> double). It's an integer. It's represented exactly. What more do you want?_

> _Go on, ask me what the largest integer is, such that it and all smaller
> integers can be stored in IEEE 64-bit doubles without losing precision. An
> IEEE 64-bit double has 52 bits of mantissa, so I think it 's 2⁵³:_

More seriously, this is great news, and I think it'll be nice to have such a
numeric type in JS.

[1]:
[https://stackoverflow.com/a/1848762](https://stackoverflow.com/a/1848762)

~~~
taeric
You seem to be doing an uncharitable reading of what you quoted. They can
precisely represent numbers outside that range, true. They cannot represent
all numbers outside that range.

