-
Notifications
You must be signed in to change notification settings - Fork 164
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
Add bigint type #525
Add bigint type #525
Conversation
It's a little weird that this setup would allow passing I assume bigint should not in fact be a "JSON type" because it can't be represented in JSON? Looks to me like ToJSON throws on BigInts in the BigInt proposal. |
In particular this situation is interesting: interface X {
void foo(bigint x);
void bar(unsigned long long y);
} What does calling |
The way the PR is written right now, it would call the
Good question. ;) Here's a worse case:
Here Also, we need corresponding changes to https://heycam.github.io/webidl/#es-to-union; those aren't in the PR afaict. |
Added union support. I also added union support for Symbol (since I didn't see it added yet, and there are some funny cases where it could intersect). |
Please don't do anything with Symbol here. It's not in the algorithm there on purpose, because you can never have a union accepting a Symbol anyway. The only way to pass Symbols in is via |
@bzbarsky Reverted |
I'd say, call the numeric overload over the bigint one. Doesn't this situation already exist in cases like the following, which would also call the numeric overload over the boolean one given a string argument?
|
Why? The bigint conversion is the less lossy one in this case, I would think.
It would, yes. Arguably conversion to numeric is less lossy than conversion to boolean. More generally, it seems we're going out of our way to provide seamless conversions from strings (but not other primitives!) to bigints. This is in contrast to numeric and boolean types, which can be converted from all primitives. So in some sense, there is some sort of privileged relationship between bigint and strings that is not shared by other primitive values in JS or other primitive-like idl types... |
Oh, and unlike a lot of overload scenarios, the "overload numeric and bigint" is not completely insane, because if you want to have an API that takes "numbers of arbitrary size" your options are:
Option 1 is slightly harder to use as an API, and the reasoning behind Option 2 involves an overload of bigint and numeric, and dataloss if you pass a long-enough string and it gets converted to the numeric. |
@bzbarsky I see; maybe we should then prohibit that particular overload and force an explicit string overload as well? There could still be some more obscure data loss cases, though. |
There really isn't a mechanism so far for prohibiting an overload but allowing it of more types are added. We could make bigint and numeric not distinguishable, forcing option 1. Or we could add some sort of mechanism along these lines. Or we could make es-to-idl conversion for bigint more like https://tc39.github.io/proposal-bigint/#sec-bigint-constructor-number-value than like https://tc39.github.io/proposal-bigint/#sec-to-bigint I suppose.... |
I'm not sure if that's in line with the goals of the BigInt proposal, to have new APIs which take both out of the box by design. I think most APIs fall into the category of "logically making sense for arbitrary-size integers" or "logically making sense for floating point values"; there's definitely stuff in the intersection ("logically making sense for only small integers"), and for that, Number works well. I was imagining overloading would mostly make sense when trying to upgrade an API from a Number version to a BigInt version, when we initially thought that it made sense only on small integers, but it turned out it was also important on large integers.
The hypothesis of the BigInt proposal design is that programmers will keep track of whether something is a BigInt operation or a Number operation, and the types of scalar values, and not do things generically. All the JS programmers I've heard from seem basically on board with this design. Part of this here is, even for small numeric constants, you put an
If we did that, and privileged the bigint path, we'd get surprising exceptions for things like I don't see a great answer here which makes everything beautiful, intuitive and not throw errors. Maybe we should start by making |
Ah, if there are simple bigint literals that helps a lot.
Yes, please. |
Yes, BigInt literals in both JavaScript and WebIDL look like
How does this patch look? |
Preface: this is all excellent discussion and @littledan's proactive approach to getting bigint integrated into the platform is awesome.
On that note: are there concrete examples of API that plan to consume/produce bigints, either via WebIDL or ES? (Indexed DB is unfortunately not a good example, since it requires custom integration) I'm slightly nervous that since it's too early to have good examples of bigint usage we may be missing something. @littledan describes "the hypothesis of the BigInt proposal design" which makes sense to me wanting to keep mentally separate from the rest of the platform.... but what will eventual idiomatic use of bigints look like? |
WebIDL has a number of cases where it switches among all of the JS primitive types. If BigInt is a type in JavaScript, maybe we should have some description or other of what the behavior is when a BigInt ends up floating into certain operations, such as converting an ES value to any, even if we want to wait until we have more information to decide how to define what it means to overload with a One place BigInt will come up is the WebAssembly-JS API. If the proposed BigInt/i64 integration is combined with the proposed WebAssembly.Global interface, then I think we'd want to say that the type of the WebAssembly.Global.prototype.valueOf method is Besides that, I don't have a particular other web platform feature that where I want to propose BigInt usage. All the examples I can think of (constant time 64-bit arithmetic operations, a date format representing time in nanoseconds since forever ago, etc) might make more sense in the JavaScript standard itself than as WebIDL-based APIs. Like the IndexedDB integration, I'm fine waiting until we have more motivation for this change. As much as it's appropriate to wait for more applications to get input for the design of the BigInt WebIDL binding, I wanted to document a suggestion for best practices here, at least from the perspective of the way BigInt was designed in JavaScript, in particular, avoiding implicit conversions that lose information, and continuing to use Number exclusively everywhere it is currently used in WebIDL. |
This may not be true. I am checking with Domenic.
|
Another way to handle both the union and overloading semantics could be to do something similar to what the JS spec does: Call ToNumeric in the ambiguous cases, and make the judgment based on whether a Number or BigInt falls out. This is what we do for most overloaded operators such as |
Any thoughts on whether we should support overloading between BigInt and Number or not? Note that one specification proposal where this arises is the integration of BigInt and Intl.NumberFormat (not implemented anywhere AFAIK): tc39/ecma402#236 . That PR follows the ToNumeric algorithm as in #525 (comment) . |
Only use BigInt where it is really needed! Number is good for existing use cases, and existing APIs shouldn't "upgrade" to BigInt unless there is a very strong reason. Probably not ready to merge yet, as we will need more practical use cases to emerge in the web platform to see how this comes up. For the same reason, WebIDL support is not yet landed, and some open questions remain about how flexible overloading/unions should be, see whatwg/webidl#525 (comment)
I think it actually makes sense to not allow overloading/union BigInt with any other IDL numeric type as that allows for (maybe even encourages) the kind of APIs TC39 doesn't want. Where the API silently does BigInt(arg) if you pass it a non-BigInt after crossing the IDL boundary. I'm also not sure why we'd support coercing string to BigInt, I think it makes sense to throw there as well. |
I think I addressed the remaining comments. @bzbarsky, would you mind reviewing? |
I will try to get to this, but there's a lot to page in and I am pretty swamped with other things at the moment. I can't promise any timeline other than "not in the next two days"... |
So IDB doesn't depend on this as far as I can tell and it's not clear that's moving forward anyway. Are there other places that might use this through IDL? I'd rather not add it until we have a concrete consumer I think. |
Well, WebAssembly intends to use |
I guess the way WebAssembly uses |
Ah, so that would be a problem for |
Right, if we don't want to permit bigint as an actual IDL type, we should make certain changes to WebIDL to let it "pass through". I've been hoping that this patch would land, so I didn't formulate another one for that subset. (I think WebIDL is just sort of incoherent right now, with BigInt existing as a type in JS.) I've heard from a few people in the TAG that they are interested in this patch landing. Comments here about why would be appreciated. @cynthia @kenchris If we conclude that this patch won't land, then let's formulate that more minimal patch and land that instead. |
It would make the API for a WebAudio noise generator a bit nicer if BigInt were supported. We currently using an array of two 32-bit unsigned ints to specify the 64-bit seed we need. |
That seems reasonable. And it doesn't seem to want to use overloading so we don't have to address that for now. |
Just to follow up, see https://github.com/WebAudio/web-audio-api-v2/issues/8#issuecomment-721439274 and https://github.com/WebAudio/web-audio-api-v2/issues/8#issuecomment-721803254. Using BigInt makes the API a bit nicer, but an array of 2 32-bit unsigned integers works fine too. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I just did a re-review and this looks good to me. @TimothyGu, would you be able to give it a double-check and/or merge?
CI seems to be failing due to infrastructural reasons. |
Added to Web IDL in whatwg/webidl#525 but now used (with wrong case) in w3c/webrtc-encoded-transform#77.
This patch adds a bigint type to WebIDL with the following properties:
used to refer to types which have a JavaScript representation of Number.
possible to overload a function for BigInt and numeric arguments.
Although it may be on the early side for such a change, the lack of
BigInt WebIDL integration is already coming up in some designs for integrating
BigInt with the Web Platform, such as w3c/IndexedDB#231
Preview | Diff