Skip to content

Add support for BigInt #696

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

Merged
merged 5 commits into from
Apr 1, 2021
Merged

Add support for BigInt #696

merged 5 commits into from
Apr 1, 2021

Conversation

bigmontz
Copy link
Contributor

@bigmontz bigmontz commented Mar 29, 2021

Recent V8 release adds a new type - BigInt. It is thus available in latest NodeJS (v10+) and Chrome (v67+).

Driver could use this type instead of the custom Integer to represent lossy integer numbers. This is configurable because BigInt and Number are not fully compatible, so driver can't always return BitInts. For example BigInt(1) / Number(1) results in a TypeError, as well as JSON.stringify({v: BigInt(1)}).

The configuration property is useBigInt and it's false by default, in manner to break drivers user on update.

This configuration take precedence over disableLosslessIntegers

Compatibility matriz: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/BigInt

@bigmontz bigmontz force-pushed the 4.3-support-bigint branch 2 times, most recently from 3b5787c to c9a1bbc Compare March 29, 2021 15:11
@bigmontz bigmontz marked this pull request as ready for review March 29, 2021 15:11
@bigmontz bigmontz force-pushed the 4.3-support-bigint branch from c9a1bbc to 956501e Compare March 29, 2021 15:30
@fbiville
Copy link
Contributor

Are we OK with not supporting IE if big int usage is enabled?

@bigmontz bigmontz force-pushed the 4.3-support-bigint branch from 956501e to b1a11dc Compare March 29, 2021 15:55
@bigmontz
Copy link
Contributor Author

Are we OK with not supporting IE if big int usage is enabled?

I will check what's happen when it is not available and the flag is disabled. It should not fail.

Recent V8 release adds a new type - BigInt. It is thus available in latest NodeJS (v10+) and Chrome (v67+).

Driver could use this type instead of the custom Integer to represent lossy integer numbers. This is configurable because BigInt and Number are not fully compatible, so driver can't always return BitInts. For example `BigInt(1) / Number(1)` results in a TypeError, as well as `JSON.stringify({v: BigInt(1)})`.

The configuration property is `useBigInt` and it's `false` by default, in manner to break drivers user on update.

This configuration take precedence over `disableLosslessIntegers`
@bigmontz bigmontz force-pushed the 4.3-support-bigint branch 2 times, most recently from 6af3d93 to 863c946 Compare March 29, 2021 16:45
@bigmontz bigmontz force-pushed the 4.3-support-bigint branch from b0e42d8 to 9682974 Compare March 30, 2021 15:56
@bigmontz bigmontz force-pushed the 4.3-support-bigint branch from 9682974 to e61eef0 Compare March 30, 2021 16:49
@bigmontz
Copy link
Contributor Author

@fbiville, I've check in environment which doesn't support bigint, and if the useBigInt is not enabled, the BigInt constructor is not called and nothing undesired happen. If you enable, it will explode.

Copy link
Member

@oskarhane oskarhane left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just one comment where I think we're missing a useBigInt check.

In general, I like the move towards this over the customer integer type we currently have.

Just a side note:
In most of the applications we build we use web workers to get the result and transfer the data via postMessage with the result serialized as JSON.

Surprisingly BigInt's can be serialized at the moment so this kinds of usages of the driver need to add a custom .toJSON() to the big int results. See https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/BigInt#use_within_json

@@ -26,6 +26,7 @@ import {
} from '../bolt-connection/lib/pool/pool-config'
import { ServerVersion, VERSION_4_0_0 } from '../src/internal/server-version'
import testUtils from './internal/test-utils'
import { json as JSON } from 'neo4j-driver-core'
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's a detail, any specific reason some imports shadow JSON here and change all uses to json instead?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry, It's a leftover.

* @private
* @param val The value to be serialized as JSON
* @returns the json
*/
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Perhaps this doc comment could be updated to something like:

Custom version on JSON.stringify that can handle values that normally don't support serialization, such as BigInt.

@param val — A JavaScript value, usually an object or array, to be converted.
@returns A JSON string representing the given value.

core/src/json.ts Outdated
*/
export function stringify (val: any) {
return JSON.stringify(val, (_, value) =>
typeof value !== 'bigint' ? value : `${value}n`
Copy link
Contributor

@OskarDamkjaer OskarDamkjaer Mar 31, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Personally I find it clearer to read ternaries as typeof value === 'bigint' ? `${value}n` : value

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It makes sense, It was my C/C++ accent.

@@ -575,3 +580,12 @@ function formatNumber (
}
return isNegative ? '-' + numString : numString
}

function add (x: NumberOrInteger, y: number): NumberOrInteger {
if (x instanceof Integer) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

any reason functions have a space before listing arguments in this file?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is in the repository codestyle and it's done automatically. But it's a bit useful when you're searching for methods use or declarations.

import { internal } from 'neo4j-driver-core'

const WRITE = 'WRITE'
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Don't see why this variable is needed


import { internal } from 'neo4j-driver-core'

const WRITE = 'WRITE'
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure why this variable is needed, the string seems to be inlined in other changes

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually I prefer this const solution, it's cleaner and easy to change if the value change.

@OskarDamkjaer
Copy link
Contributor

I don't have a full view of how the driver/BigInt works, but looking through the code I didn't find anything that seemed off. I left some small code comments, feel free to disregard if you don't find them useful

@bigmontz bigmontz merged commit 2c1da8f into neo4j:4.3 Apr 1, 2021
@bigmontz bigmontz deleted the 4.3-support-bigint branch April 1, 2021 08:14
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.

4 participants