Skip to content

Commit 2c1da8f

Browse files
authored
Add support for BigInt (#696)
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
1 parent 4aad3bf commit 2c1da8f

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

47 files changed

+1054
-320
lines changed

bolt-connection/jest.config.js

+4-4
Original file line numberDiff line numberDiff line change
@@ -137,7 +137,7 @@ module.exports = {
137137
// snapshotSerializers: [],
138138

139139
// The test environment that will be used for testing
140-
testEnvironment: 'node'
140+
testEnvironment: 'node',
141141

142142
// Options that will be passed to the testEnvironment
143143
// testEnvironmentOptions: {},
@@ -172,9 +172,9 @@ module.exports = {
172172
// timers: "real",
173173

174174
// A map from regular expressions to paths to transformers
175-
// transform: {
176-
// "^.+\\.(ts|tsx)$": "ts-jest"
177-
// }
175+
transform: {
176+
'^.+\\.(ts|tsx|js)$': 'ts-jest'
177+
}
178178
// An array of regexp pattern strings that are matched against all source file paths, matched files will skip transformation
179179
// transformIgnorePatterns: [
180180
// "/node_modules/",

bolt-connection/package-lock.json

+1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

bolt-connection/src/bolt/bolt-protocol-v1.js

+7-5
Original file line numberDiff line numberDiff line change
@@ -52,23 +52,25 @@ export default class BoltProtocol {
5252
* @constructor
5353
* @param {Object} server the server informatio.
5454
* @param {Chunker} chunker the chunker.
55-
* @param {boolean} disableLosslessIntegers if this connection should convert all received integers to native JS numbers.
55+
* @param {Object} packstreamConfig Packstream configuration
56+
* @param {boolean} packstreamConfig.disableLosslessIntegers if this connection should convert all received integers to native JS numbers.
57+
* @param {boolean} packstreamConfig.useBigInt if this connection should convert all received integers to native BigInt numbers.
5658
* @param {CreateResponseHandler} createResponseHandler Function which creates the response handler
5759
* @param {Logger} log the logger
5860
* @param {OnProtocolError} onProtocolError handles protocol errors
5961
*/
6062
constructor (
6163
server,
6264
chunker,
63-
disableLosslessIntegers,
65+
{ disableLosslessIntegers, useBigInt } = {},
6466
createResponseHandler = () => null,
6567
log,
6668
onProtocolError
6769
) {
6870
this._server = server || {}
6971
this._chunker = chunker
7072
this._packer = this._createPacker(chunker)
71-
this._unpacker = this._createUnpacker(disableLosslessIntegers)
73+
this._unpacker = this._createUnpacker(disableLosslessIntegers, useBigInt)
7274
this._responseHandler = createResponseHandler(this)
7375
this._log = log
7476
this._onProtocolError = onProtocolError
@@ -317,8 +319,8 @@ export default class BoltProtocol {
317319
return new v1.Packer(chunker)
318320
}
319321

320-
_createUnpacker (disableLosslessIntegers) {
321-
return new v1.Unpacker(disableLosslessIntegers)
322+
_createUnpacker (disableLosslessIntegers, useBigInt) {
323+
return new v1.Unpacker(disableLosslessIntegers, useBigInt)
322324
}
323325

324326
/**

bolt-connection/src/bolt/bolt-protocol-v2.js

+2-2
Original file line numberDiff line numberDiff line change
@@ -29,8 +29,8 @@ export default class BoltProtocol extends BoltProtocolV1 {
2929
return new v2.Packer(chunker)
3030
}
3131

32-
_createUnpacker (disableLosslessIntegers) {
33-
return new v2.Unpacker(disableLosslessIntegers)
32+
_createUnpacker (disableLosslessIntegers, useBigInt) {
33+
return new v2.Unpacker(disableLosslessIntegers, useBigInt)
3434
}
3535

3636
get version () {

bolt-connection/src/bolt/bolt-protocol-v4x1.js

+5-3
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,9 @@ export default class BoltProtocol extends BoltProtocolV4 {
3030
* @constructor
3131
* @param {Object} server the server informatio.
3232
* @param {Chunker} chunker the chunker.
33-
* @param {boolean} disableLosslessIntegers if this connection should convert all received integers to native JS numbers.
33+
* @param {Object} packstreamConfig Packstream configuration
34+
* @param {boolean} packstreamConfig.disableLosslessIntegers if this connection should convert all received integers to native JS numbers.
35+
* @param {boolean} packstreamConfig.useBigInt if this connection should convert all received integers to native BigInt numbers.
3436
* @param {CreateResponseHandler} createResponseHandler Function which creates the response handler
3537
* @param {Logger} log the logger
3638
* @param {Object} serversideRouting
@@ -39,7 +41,7 @@ export default class BoltProtocol extends BoltProtocolV4 {
3941
constructor (
4042
server,
4143
chunker,
42-
disableLosslessIntegers,
44+
packstreamConfig,
4345
createResponseHandler = () => null,
4446
log,
4547
onProtocolError,
@@ -48,7 +50,7 @@ export default class BoltProtocol extends BoltProtocolV4 {
4850
super(
4951
server,
5052
chunker,
51-
disableLosslessIntegers,
53+
packstreamConfig,
5254
createResponseHandler,
5355
log,
5456
onProtocolError

bolt-connection/src/bolt/create.js

+11-9
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ import ResponseHandler from './response-handler'
3939
* @param {Logger} config.log The logger
4040
* @param {ResponseHandler~Observer} config.observer Observer
4141
* @param {boolean} config.disableLosslessIntegers Disable the lossless integers
42+
* @param {boolean} packstreamConfig.useBigInt if this connection should convert all received integers to native BigInt numbers.
4243
* @param {boolean} config.serversideRouting It's using server side routing
4344
*/
4445
export default function create ({
@@ -47,6 +48,7 @@ export default function create ({
4748
dechunker,
4849
channel,
4950
disableLosslessIntegers,
51+
useBigInt,
5052
serversideRouting,
5153
server, // server info
5254
log,
@@ -77,7 +79,7 @@ export default function create ({
7779
version,
7880
server,
7981
chunker,
80-
disableLosslessIntegers,
82+
{ disableLosslessIntegers, useBigInt },
8183
serversideRouting,
8284
createResponseHandler,
8385
observer.onProtocolError.bind(observer),
@@ -89,7 +91,7 @@ function createProtocol (
8991
version,
9092
server,
9193
chunker,
92-
disableLosslessIntegers,
94+
packingConfig,
9395
serversideRouting,
9496
createResponseHandler,
9597
onProtocolError,
@@ -100,7 +102,7 @@ function createProtocol (
100102
return new BoltProtocolV1(
101103
server,
102104
chunker,
103-
disableLosslessIntegers,
105+
packingConfig,
104106
createResponseHandler,
105107
log,
106108
onProtocolError
@@ -109,7 +111,7 @@ function createProtocol (
109111
return new BoltProtocolV2(
110112
server,
111113
chunker,
112-
disableLosslessIntegers,
114+
packingConfig,
113115
createResponseHandler,
114116
log,
115117
onProtocolError
@@ -118,7 +120,7 @@ function createProtocol (
118120
return new BoltProtocolV3(
119121
server,
120122
chunker,
121-
disableLosslessIntegers,
123+
packingConfig,
122124
createResponseHandler,
123125
log,
124126
onProtocolError
@@ -127,7 +129,7 @@ function createProtocol (
127129
return new BoltProtocolV4x0(
128130
server,
129131
chunker,
130-
disableLosslessIntegers,
132+
packingConfig,
131133
createResponseHandler,
132134
log,
133135
onProtocolError
@@ -136,7 +138,7 @@ function createProtocol (
136138
return new BoltProtocolV4x1(
137139
server,
138140
chunker,
139-
disableLosslessIntegers,
141+
packingConfig,
140142
createResponseHandler,
141143
log,
142144
onProtocolError,
@@ -146,7 +148,7 @@ function createProtocol (
146148
return new BoltProtocolV4x2(
147149
server,
148150
chunker,
149-
disableLosslessIntegers,
151+
packingConfig,
150152
createResponseHandler,
151153
log,
152154
onProtocolError,
@@ -156,7 +158,7 @@ function createProtocol (
156158
return new BoltProtocolV4x3(
157159
server,
158160
chunker,
159-
disableLosslessIntegers,
161+
packingConfig,
160162
createResponseHandler,
161163
log,
162164
onProtocolError,

bolt-connection/src/bolt/request-message.js

+9-9
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
* limitations under the License.
1818
*/
1919

20-
import { int, internal } from 'neo4j-driver-core'
20+
import { int, internal, json } from 'neo4j-driver-core'
2121

2222
const {
2323
constants: { ACCESS_MODE_READ, FETCH_ALL },
@@ -79,7 +79,7 @@ export default class RequestMessage {
7979
return new RequestMessage(
8080
RUN,
8181
[query, parameters],
82-
() => `RUN ${query} ${JSON.stringify(parameters)}`
82+
() => `RUN ${query} ${json.stringify(parameters)}`
8383
)
8484
}
8585

@@ -131,7 +131,7 @@ export default class RequestMessage {
131131
return new RequestMessage(
132132
BEGIN,
133133
[metadata],
134-
() => `BEGIN ${JSON.stringify(metadata)}`
134+
() => `BEGIN ${json.stringify(metadata)}`
135135
)
136136
}
137137

@@ -171,7 +171,7 @@ export default class RequestMessage {
171171
RUN,
172172
[query, parameters, metadata],
173173
() =>
174-
`RUN ${query} ${JSON.stringify(parameters)} ${JSON.stringify(metadata)}`
174+
`RUN ${query} ${json.stringify(parameters)} ${json.stringify(metadata)}`
175175
)
176176
}
177177

@@ -191,13 +191,13 @@ export default class RequestMessage {
191191
*/
192192
static pull ({ stmtId = NO_STATEMENT_ID, n = FETCH_ALL } = {}) {
193193
const metadata = buildStreamMetadata(
194-
stmtId || NO_STATEMENT_ID,
194+
stmtId === null || stmtId === undefined ? NO_STATEMENT_ID : stmtId,
195195
n || FETCH_ALL
196196
)
197197
return new RequestMessage(
198198
PULL,
199199
[metadata],
200-
() => `PULL ${JSON.stringify(metadata)}`
200+
() => `PULL ${json.stringify(metadata)}`
201201
)
202202
}
203203

@@ -209,13 +209,13 @@ export default class RequestMessage {
209209
*/
210210
static discard ({ stmtId = NO_STATEMENT_ID, n = FETCH_ALL } = {}) {
211211
const metadata = buildStreamMetadata(
212-
stmtId || NO_STATEMENT_ID,
212+
stmtId === null || stmtId === undefined ? NO_STATEMENT_ID : stmtId,
213213
n || FETCH_ALL
214214
)
215215
return new RequestMessage(
216216
DISCARD,
217217
[metadata],
218-
() => `DISCARD ${JSON.stringify(metadata)}`
218+
() => `DISCARD ${json.stringify(metadata)}`
219219
)
220220
}
221221

@@ -230,7 +230,7 @@ export default class RequestMessage {
230230
return new RequestMessage(
231231
ROUTE,
232232
[routingContext, databaseName],
233-
() => `ROUTE ${JSON.stringify(routingContext)} ${databaseName}`
233+
() => `ROUTE ${json.stringify(routingContext)} ${databaseName}`
234234
)
235235
}
236236
}

bolt-connection/src/bolt/response-handler.js

+5-5
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616
* See the License for the specific language governing permissions and
1717
* limitations under the License.
1818
*/
19-
import { newError } from 'neo4j-driver-core'
19+
import { newError, json } from 'neo4j-driver-core'
2020

2121
// Signature bytes for each response message type
2222
const SUCCESS = 0x70 // 0111 0000 // SUCCESS <metadata>
@@ -92,13 +92,13 @@ export default class ResponseHandler {
9292
switch (msg.signature) {
9393
case RECORD:
9494
if (this._log.isDebugEnabled()) {
95-
this._log.debug(`${this} S: RECORD ${JSON.stringify(msg)}`)
95+
this._log.debug(`${this} S: RECORD ${json.stringify(msg)}`)
9696
}
9797
this._currentObserver.onNext(payload)
9898
break
9999
case SUCCESS:
100100
if (this._log.isDebugEnabled()) {
101-
this._log.debug(`${this} S: SUCCESS ${JSON.stringify(msg)}`)
101+
this._log.debug(`${this} S: SUCCESS ${json.stringify(msg)}`)
102102
}
103103
try {
104104
const metadata = this._transformMetadata(payload)
@@ -109,7 +109,7 @@ export default class ResponseHandler {
109109
break
110110
case FAILURE:
111111
if (this._log.isDebugEnabled()) {
112-
this._log.debug(`${this} S: FAILURE ${JSON.stringify(msg)}`)
112+
this._log.debug(`${this} S: FAILURE ${json.stringify(msg)}`)
113113
}
114114
try {
115115
const error = newError(payload.message, payload.code)
@@ -125,7 +125,7 @@ export default class ResponseHandler {
125125
break
126126
case IGNORED:
127127
if (this._log.isDebugEnabled()) {
128-
this._log.debug(`${this} S: IGNORED ${JSON.stringify(msg)}`)
128+
this._log.debug(`${this} S: IGNORED ${json.stringify(msg)}`)
129129
}
130130
try {
131131
if (this._currentFailure && this._currentObserver.onError) {

bolt-connection/src/bolt/stream-observers.js

+6-6
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616
* See the License for the specific language governing permissions and
1717
* limitations under the License.
1818
*/
19-
import { newError, error, Integer, Record } from 'neo4j-driver-core'
19+
import { newError, error, Integer, Record, json } from 'neo4j-driver-core'
2020
import { ALL } from './request-message'
2121
import RawRoutingTable from './routing-table-raw'
2222

@@ -268,7 +268,7 @@ class ResultStreamObserver extends StreamObserver {
268268

269269
// Extract server generated query id for use in requestMore and discard
270270
// functions
271-
if (meta.qid) {
271+
if (meta.qid !== null && meta.qid !== undefined) {
272272
this._queryId = meta.qid
273273

274274
// remove qid from metadata object
@@ -392,7 +392,7 @@ class LoginObserver extends StreamObserver {
392392

393393
onNext (record) {
394394
this.onError(
395-
newError('Received RECORD when initializing ' + JSON.stringify(record))
395+
newError('Received RECORD when initializing ' + json.stringify(record))
396396
)
397397
}
398398

@@ -429,7 +429,7 @@ class ResetObserver extends StreamObserver {
429429
this.onError(
430430
newError(
431431
'Received RECORD when resetting: received record is: ' +
432-
JSON.stringify(record),
432+
json.stringify(record),
433433
PROTOCOL_ERROR
434434
)
435435
)
@@ -500,7 +500,7 @@ class ProcedureRouteObserver extends StreamObserver {
500500
'Illegal response from router. Received ' +
501501
this._records.length +
502502
' records but expected only one.\n' +
503-
JSON.stringify(this._records),
503+
json.stringify(this._records),
504504
PROTOCOL_ERROR
505505
)
506506
)
@@ -533,7 +533,7 @@ class RouteObserver extends StreamObserver {
533533
this.onError(
534534
newError(
535535
'Received RECORD when resetting: received record is: ' +
536-
JSON.stringify(record),
536+
json.stringify(record),
537537
PROTOCOL_ERROR
538538
)
539539
)

0 commit comments

Comments
 (0)