-
Notifications
You must be signed in to change notification settings - Fork 1.4k
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
Use BigInt over Number for int64 #1557
Conversation
Hi @mjgp2, Thank you for this PR. We probably cannot include it in v7.0.0 (that is coming soon) but we'll think if we can drop (1) start accepting Also, dropping support for Node.js v4-6-8 is a big decision. Of course, Cc: @dcodeIO on this. I promise we'll get back to reviewing this PR when we're done with releasing v7.0.0 :) |
Thanks for your reply. Yes, I think that definitely you could support Number, BigInt, String and Long for int64 types. My thinking here was firstly to understand the codebase and to swap Long for BigInt being simpler than adding the extra branching logic, and then hopefully get some feedback. I would suggest that it is considered whether support for Number for int64 should be dropped - there are silent overflows today I think within the codebase that are really data corruption. |
Any progress on this PR? |
@ardatan - you can use the branch on my repo, it works, i.e. in your package.json
I understand it's going to be targeted for version 8. I'm happy to help when the time comes - it's still my thinking that Number support for int64 should be dropped in version 8 because it will corrupt data. |
Sorry for pinging a bunch of people but me and my colleagues are really looking forward to this PR being merged and published so we are looking for a status on this. Is it stuck on something other than having conflicts? Can we help out in any way? |
I'm happy to take it forward, but I think I was waiting for v7 to be released first. Not sure where that is right now? |
Well done @mjgp2 Is there some sort of a timeline with a release date for v7 and v8?, I'm really looking forward to dropping the ~40KB long.js from our codebase. |
} else | ||
object.uint64Val = options.longs === String ? "0" : 0; | ||
var long = new $util.LongBits(NaN, NaN, undefined); | ||
object.uint64Val = options.longs === String ? long.toBigInt().toString() : options.longs === BigInt ? long.toBigInt().toString() : long; |
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.
Potential bug fix to default value here if the user chooses to use { longs: BitInt }
object.uint64Val = options.longs === String ? long.toBigInt().toString() : options.longs === BigInt ? long.toBigInt().toString() : long; | |
object.uint64Val = options.longs === String ? long.toBigInt(true).toString() : options.longs === BigInt ? long.toBigInt(true): long; |
@alexander-fenster - wondering if there is an ETA for v7 so I can start to work out how to take this forward? |
* Zero hash. | ||
* @memberof util.LongBits | ||
* @type {string} | ||
* Constructs new long bits from the specified number. |
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.
* Constructs new long bits from the specified number. | |
* Constructs new long bits from the specified bigint. |
* @memberof util.LongBits | ||
* @type {string} | ||
* Constructs new long bits from the specified number. | ||
* @param {number} value Value |
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.
* @param {number} value Value | |
* @param {bigint} value Value |
*/ | ||
var zeroHash = LongBits.zeroHash = "\0\0\0\0\0\0\0\0"; | ||
LongBits.fromBigInt = function fromNumber(value) { |
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.
LongBits.fromBigInt = function fromNumber(value) { | |
LongBits.fromBigInt = function fromBigInt(value) { |
Any news? |
Well, v7 has been released (woo!), and so hopefully we can start to pick this up @dcodeIO ? |
Yes, we finally got v7 out - and also dropped support for older versions of Node.js (we start from 12 now). I should say I'm not sure how we properly release this if we make this change, this will be a huge breaking change for many users. I wonder if we could somehow use the configuration option to choose which type to use (and have this option for |
var hi = Number(value >> 32n) | 0; | ||
var lo = Number(value - ( BigInt(hi) << 32n ) ) | 0; |
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've been unable to correctly encode uint64 fields with the max field value of 18446744073709551615n
without this change:
var hi = Number(value >> 32n) | 0; | |
var lo = Number(value - ( BigInt(hi) << 32n ) ) | 0; | |
var hi = Number(value >> 32n); | |
var lo = Number(value - ( BigInt(hi) << 32n ) ); |
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 fixed it by juzibot#7
Ports just the parts of protobufjs we use to typescript and integrates the changes from protobufjs/protobuf.js#1557 to have native BigInt support.
I'm assuming bigint will perform significantly better since it's a native type. If we aren't going to merge this, would it make sense to fork this repo and have an npm package under a different name? Having an object wrapping two Numbers uses significantly more memory as well, so wouldn't it be advantageous to remove Long? We could add a Long shim around bigint for backwards compatibility. |
Any news? |
1 similar comment
Any news? |
I'm not a maintainer so speaking for myself here. Honestly I don't think this can be merged due to breaking compatibility. What needs to be done is: First: Add support for bigints as an option (so people can migrate to it). Then: Maybe in 5 years, drop support of Long (since no one would be using it by then, hopefully). It's a great patch and I wish it were merged already. I need bigints myself and don't want to start a new project with legacy junk from the start. However, I can imagine that there are millions of lines of code affected by this change and that's why it's been 2 years since the patch was written and it's still not merged. It breaks people's code. Yes, the maintainers can merge it and force people to migrate or stay behind. However, people will generally not like that. @dcodeIO @alexander-fenster @mjgp2 Is this kinda what the situation is? Would this be a reasonable approach to make progress? |
Why not just merge this and release a full version bump? That's what versions are for. Software that wants to keep using Long can stick with an older version. Putting two Numbers (which are float64) in an Object to handle integers over 52 bits is a very inefficient solution. |
i agree merge this. i vote we merge this 1 year after bigint has been released in stable JS versions. “millions of lines of code” = code generated by this library. |
Bigint is in all major browsers for over 2 years and since Node 10. I think it's waiting for the owner(s) to decide how to proceed - there is a decision to be made about if it is necessary to support both Long and BigInt. I do not generate code with this library, just use it dynamically, so do not have much context on how it affects that. |
@alexander-fenster ping from 2023 |
I wait for native bigint too |
("d%s=o.longs===String?n.toString():o.longs===Number?n.toNumber():n", prop) | ||
("}else") | ||
("d%s=o.longs===String?%j:%i", prop, field.typeDefault.toString(), field.typeDefault.toNumber()); | ||
("var n=new util.LongBits(%i,%i,%j)", field.typeDefault.low, field.typeDefault.high, field.typeDefault.unsigned) |
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.
This code will define n for every long field, which cause failure on es6 build(-w es6
).
You should check if n has declared in previous field.
Like this : seo-rii@1dac06f#diff-444e086c8038faf674140e30c0597966b9a9102859bf04422d247118adedd08c
I created a PR that's smaller in scope: #1908 which adds support for |
Ports just the parts of protobufjs we use to typescript and integrates the changes from protobufjs/protobuf.js#1557 to have native BigInt support.
2024, any progress? |
I don't have bandwidth to look at this any further - hopefully someone will be able to get some form of support for BigInt in. |
😢 |
😢 😢 😢 |
Lol. |
This PR removes the need for the
Long
package, and instead of Number uses BigInt as standard for all int64 types.I realise that this would be a breaking change, but it seems like it would be the right design decision for the next major version of this library?
All unit tests pass, and needed to switch to terser from uglify.
Node versions before 10 would not be supported. However, Node 10 LTS is EOL on 2021-04-30.