bfj 4.2.0 → 4.2.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/HISTORY.md +18 -0
- package/README.md +0 -8
- package/package.json +7 -7
- package/src/eventify.js +10 -11
- package/src/parse.js +0 -3
- package/src/read.js +0 -3
- package/src/streamify.js +2 -2
- package/src/stringify.js +3 -3
- package/src/walk.js +65 -26
- package/test/unit/read.js +1 -1
- package/test/unit/streamify.js +1 -1
- package/test/unit/write.js +1 -1
package/HISTORY.md
CHANGED
|
@@ -1,5 +1,23 @@
|
|
|
1
1
|
# History
|
|
2
2
|
|
|
3
|
+
## 4.2.4
|
|
4
|
+
|
|
5
|
+
* chore: update deps (c3eeeb4)
|
|
6
|
+
|
|
7
|
+
## 4.2.3
|
|
8
|
+
|
|
9
|
+
* fix: eliminate costly string concatenation (42998d7)
|
|
10
|
+
* fix: micro-optimise eventify::proceed::after (98a2519)
|
|
11
|
+
* fix: micro-optimise walk::character (8d1c4cf)
|
|
12
|
+
|
|
13
|
+
## 4.2.2
|
|
14
|
+
|
|
15
|
+
* fix: silence obnoxious unhandled rejection warnings (1d4a902)
|
|
16
|
+
|
|
17
|
+
## 4.2.1
|
|
18
|
+
|
|
19
|
+
* refactor: discard chunks more aggressively (970a964)
|
|
20
|
+
|
|
3
21
|
## 4.2.0
|
|
4
22
|
|
|
5
23
|
* chore: add a unit test for parallel object references (e8f3895)
|
package/README.md
CHANGED
|
@@ -548,14 +548,6 @@ of an object,
|
|
|
548
548
|
is analagous to the
|
|
549
549
|
[reviver parameter for JSON.parse][reviver].
|
|
550
550
|
|
|
551
|
-
* `options.discard`:
|
|
552
|
-
The number of characters
|
|
553
|
-
to process before
|
|
554
|
-
discarding them
|
|
555
|
-
to save memory.
|
|
556
|
-
The default value
|
|
557
|
-
is `1048576`.
|
|
558
|
-
|
|
559
551
|
* `options.yieldRate`:
|
|
560
552
|
The number of data items to process
|
|
561
553
|
before yielding to the event loop.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "bfj",
|
|
3
|
-
"version": "4.2.
|
|
3
|
+
"version": "4.2.4",
|
|
4
4
|
"description": "Big-friendly JSON. Asynchronous streaming functions for large JSON data sets.",
|
|
5
5
|
"homepage": "https://github.com/philbooth/bfj",
|
|
6
6
|
"bugs": "https://github.com/philbooth/bfj/issues",
|
|
@@ -30,14 +30,14 @@
|
|
|
30
30
|
},
|
|
31
31
|
"dependencies": {
|
|
32
32
|
"check-types": "^7.3.0",
|
|
33
|
-
"hoopy": "^0.1.
|
|
34
|
-
"
|
|
33
|
+
"hoopy": "^0.1.2",
|
|
34
|
+
"tryer": "^1.0.0"
|
|
35
35
|
},
|
|
36
36
|
"devDependencies": {
|
|
37
|
-
"eslint": "
|
|
38
|
-
"mocha": "3.
|
|
39
|
-
"chai": "
|
|
40
|
-
"mockery": "2.
|
|
37
|
+
"eslint": "4.6.x",
|
|
38
|
+
"mocha": "3.5.x",
|
|
39
|
+
"chai": "4.1.x",
|
|
40
|
+
"mockery": "2.1.x",
|
|
41
41
|
"spooks": "2.0.x",
|
|
42
42
|
"please-release-me": "1.0.x",
|
|
43
43
|
"request": "2.81.x"
|
package/src/eventify.js
CHANGED
|
@@ -114,21 +114,20 @@ function eventify (data, options) {
|
|
|
114
114
|
return literal(coerced)
|
|
115
115
|
}
|
|
116
116
|
|
|
117
|
-
const type = typeof coerced
|
|
118
|
-
|
|
119
|
-
if (type === 'number') {
|
|
120
|
-
return value(coerced, type)
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
if (type === 'string') {
|
|
124
|
-
return value(escapeString(coerced), type)
|
|
125
|
-
}
|
|
126
|
-
|
|
127
117
|
if (Array.isArray(coerced)) {
|
|
128
118
|
return array(coerced)
|
|
129
119
|
}
|
|
130
120
|
|
|
131
|
-
|
|
121
|
+
const type = typeof coerced
|
|
122
|
+
|
|
123
|
+
switch (type) {
|
|
124
|
+
case 'number':
|
|
125
|
+
return value(coerced, type)
|
|
126
|
+
case 'string':
|
|
127
|
+
return value(escapeString(coerced), type)
|
|
128
|
+
default:
|
|
129
|
+
return object(coerced)
|
|
130
|
+
}
|
|
132
131
|
}
|
|
133
132
|
}
|
|
134
133
|
|
package/src/parse.js
CHANGED
|
@@ -17,9 +17,6 @@ module.exports = parse
|
|
|
17
17
|
*
|
|
18
18
|
* @option reviver: Transformation function, invoked depth-first.
|
|
19
19
|
*
|
|
20
|
-
* @option discard: The number of characters to process before discarding
|
|
21
|
-
* them to save memory. The default value is `1048576`.
|
|
22
|
-
*
|
|
23
20
|
* @option yieldRate: The number of data items to process per timeslice,
|
|
24
21
|
* default is 16384.
|
|
25
22
|
**/
|
package/src/read.js
CHANGED
|
@@ -16,9 +16,6 @@ module.exports = read
|
|
|
16
16
|
*
|
|
17
17
|
* @option reviver: Transformation function, invoked depth-first.
|
|
18
18
|
*
|
|
19
|
-
* @option discard: The number of characters to process before discarding them
|
|
20
|
-
* to save memory. The default value is `1048576`.
|
|
21
|
-
*
|
|
22
19
|
* @option yieldRate: The number of data items to process per timeslice,
|
|
23
20
|
* default is 16384.
|
|
24
21
|
**/
|
package/src/streamify.js
CHANGED
|
@@ -5,7 +5,7 @@ const eventify = require('./eventify')
|
|
|
5
5
|
const events = require('./events')
|
|
6
6
|
const JsonStream = require('./jsonstream')
|
|
7
7
|
const Hoopy = require('hoopy')
|
|
8
|
-
const
|
|
8
|
+
const tryer = require('tryer')
|
|
9
9
|
|
|
10
10
|
const DEFAULT_BUFFER_LENGTH = 1048576
|
|
11
11
|
|
|
@@ -167,7 +167,7 @@ function streamify (data, options = {}) {
|
|
|
167
167
|
isPaused = true
|
|
168
168
|
return new Promise(resolve => {
|
|
169
169
|
const unpause = emitter.pause()
|
|
170
|
-
|
|
170
|
+
tryer({
|
|
171
171
|
interval: -10,
|
|
172
172
|
until () {
|
|
173
173
|
return length + 1 <= json.length
|
package/src/stringify.js
CHANGED
|
@@ -34,7 +34,7 @@ function stringify (data, options) {
|
|
|
34
34
|
let resolve, reject
|
|
35
35
|
|
|
36
36
|
const stream = streamify(data, options)
|
|
37
|
-
|
|
37
|
+
const json = []
|
|
38
38
|
|
|
39
39
|
stream.on('data', read)
|
|
40
40
|
stream.on('end', end)
|
|
@@ -46,11 +46,11 @@ function stringify (data, options) {
|
|
|
46
46
|
})
|
|
47
47
|
|
|
48
48
|
function read (chunk) {
|
|
49
|
-
json
|
|
49
|
+
json.push(chunk)
|
|
50
50
|
}
|
|
51
51
|
|
|
52
52
|
function end () {
|
|
53
|
-
resolve(json)
|
|
53
|
+
resolve(json.join(''))
|
|
54
54
|
}
|
|
55
55
|
|
|
56
56
|
function error (e) {
|
package/src/walk.js
CHANGED
|
@@ -33,9 +33,6 @@ module.exports = initialise
|
|
|
33
33
|
*
|
|
34
34
|
* @param stream: Readable instance representing the incoming JSON.
|
|
35
35
|
*
|
|
36
|
-
* @option discard: The number of characters to process before discarding
|
|
37
|
-
* them to save memory. The default value is `1048576`.
|
|
38
|
-
*
|
|
39
36
|
* @option yieldRate: The number of data items to process per timeslice,
|
|
40
37
|
* default is 16384.
|
|
41
38
|
**/
|
|
@@ -44,7 +41,6 @@ function initialise (stream, options) {
|
|
|
44
41
|
|
|
45
42
|
options = options || {}
|
|
46
43
|
|
|
47
|
-
let json = ''
|
|
48
44
|
let index = 0
|
|
49
45
|
let isStreamEnded = false
|
|
50
46
|
let isWalkBegun = false
|
|
@@ -52,7 +48,10 @@ function initialise (stream, options) {
|
|
|
52
48
|
let isWalkingString = false
|
|
53
49
|
let count = 0
|
|
54
50
|
let resumeFn
|
|
51
|
+
let cachedCharacter
|
|
55
52
|
|
|
53
|
+
const json = []
|
|
54
|
+
const lengths = []
|
|
56
55
|
const currentPosition = {
|
|
57
56
|
line: 1,
|
|
58
57
|
column: 1
|
|
@@ -64,7 +63,6 @@ function initialise (stream, options) {
|
|
|
64
63
|
obj: property
|
|
65
64
|
}
|
|
66
65
|
const emitter = new EventEmitter()
|
|
67
|
-
const discardThreshold = options.discard || 1048576
|
|
68
66
|
const yieldRate = options.yieldRate || 16384
|
|
69
67
|
|
|
70
68
|
stream.setEncoding('utf8')
|
|
@@ -74,7 +72,7 @@ function initialise (stream, options) {
|
|
|
74
72
|
return emitter
|
|
75
73
|
|
|
76
74
|
function readStream (chunk) {
|
|
77
|
-
|
|
75
|
+
addChunk(chunk)
|
|
78
76
|
|
|
79
77
|
if (!isWalkBegun) {
|
|
80
78
|
isWalkBegun = true
|
|
@@ -84,6 +82,26 @@ function initialise (stream, options) {
|
|
|
84
82
|
return resume()
|
|
85
83
|
}
|
|
86
84
|
|
|
85
|
+
function addChunk (chunk) {
|
|
86
|
+
json.push(chunk)
|
|
87
|
+
|
|
88
|
+
const chunkLength = chunk.length
|
|
89
|
+
lengths.push({
|
|
90
|
+
item: chunkLength,
|
|
91
|
+
aggregate: length() + chunkLength
|
|
92
|
+
})
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
function length () {
|
|
96
|
+
const chunkCount = lengths.length
|
|
97
|
+
|
|
98
|
+
if (chunkCount === 0) {
|
|
99
|
+
return 0
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
return lengths[chunkCount - 1].aggregate
|
|
103
|
+
}
|
|
104
|
+
|
|
87
105
|
function value () {
|
|
88
106
|
/* eslint-disable no-underscore-dangle */
|
|
89
107
|
if (++count % yieldRate !== 0) {
|
|
@@ -121,7 +139,7 @@ function initialise (stream, options) {
|
|
|
121
139
|
function awaitCharacter () {
|
|
122
140
|
let resolve, reject
|
|
123
141
|
|
|
124
|
-
if (index <
|
|
142
|
+
if (index < length()) {
|
|
125
143
|
return Promise.resolve()
|
|
126
144
|
}
|
|
127
145
|
|
|
@@ -138,7 +156,7 @@ function initialise (stream, options) {
|
|
|
138
156
|
})
|
|
139
157
|
|
|
140
158
|
function after () {
|
|
141
|
-
if (index <
|
|
159
|
+
if (index < length()) {
|
|
142
160
|
return resolve()
|
|
143
161
|
}
|
|
144
162
|
|
|
@@ -151,7 +169,21 @@ function initialise (stream, options) {
|
|
|
151
169
|
}
|
|
152
170
|
|
|
153
171
|
function character () {
|
|
154
|
-
|
|
172
|
+
if (cachedCharacter) {
|
|
173
|
+
return cachedCharacter
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
if (lengths[0].item > index) {
|
|
177
|
+
return cachedCharacter = json[0][index]
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
const len = lengths.length
|
|
181
|
+
for (let i = 1; i < len; ++i) {
|
|
182
|
+
const { aggregate, item } = lengths[i]
|
|
183
|
+
if (aggregate > index) {
|
|
184
|
+
return cachedCharacter = json[i][index + item - aggregate]
|
|
185
|
+
}
|
|
186
|
+
}
|
|
155
187
|
}
|
|
156
188
|
|
|
157
189
|
function next () {
|
|
@@ -160,6 +192,7 @@ function initialise (stream, options) {
|
|
|
160
192
|
function after () {
|
|
161
193
|
const result = character()
|
|
162
194
|
|
|
195
|
+
cachedCharacter = null
|
|
163
196
|
index += 1
|
|
164
197
|
previousPosition.line = currentPosition.line
|
|
165
198
|
previousPosition.column = currentPosition.column
|
|
@@ -171,9 +204,13 @@ function initialise (stream, options) {
|
|
|
171
204
|
currentPosition.column += 1
|
|
172
205
|
}
|
|
173
206
|
|
|
174
|
-
if (index
|
|
175
|
-
json
|
|
176
|
-
|
|
207
|
+
if (index > lengths[0].aggregate) {
|
|
208
|
+
json.shift()
|
|
209
|
+
|
|
210
|
+
const difference = lengths.shift().item
|
|
211
|
+
index -= difference
|
|
212
|
+
|
|
213
|
+
lengths.forEach(len => len.aggregate -= difference)
|
|
177
214
|
}
|
|
178
215
|
|
|
179
216
|
return result
|
|
@@ -320,7 +357,7 @@ function initialise (stream, options) {
|
|
|
320
357
|
|
|
321
358
|
function walkString (event) {
|
|
322
359
|
let isEscaping = false
|
|
323
|
-
|
|
360
|
+
const str = []
|
|
324
361
|
|
|
325
362
|
isWalkingString = true
|
|
326
363
|
|
|
@@ -331,7 +368,7 @@ function initialise (stream, options) {
|
|
|
331
368
|
isEscaping = false
|
|
332
369
|
|
|
333
370
|
return escape(char).then(escaped => {
|
|
334
|
-
str
|
|
371
|
+
str.push(escaped)
|
|
335
372
|
return next().then(step)
|
|
336
373
|
})
|
|
337
374
|
}
|
|
@@ -342,12 +379,12 @@ function initialise (stream, options) {
|
|
|
342
379
|
}
|
|
343
380
|
|
|
344
381
|
if (char !== '"') {
|
|
345
|
-
str
|
|
382
|
+
str.push(char)
|
|
346
383
|
return next().then(step)
|
|
347
384
|
}
|
|
348
385
|
|
|
349
386
|
isWalkingString = false
|
|
350
|
-
emitter.emit(event, str)
|
|
387
|
+
emitter.emit(event, str.join(''))
|
|
351
388
|
}
|
|
352
389
|
}
|
|
353
390
|
|
|
@@ -365,19 +402,21 @@ function initialise (stream, options) {
|
|
|
365
402
|
}
|
|
366
403
|
|
|
367
404
|
function escapeHex () {
|
|
368
|
-
let hexits =
|
|
405
|
+
let hexits = []
|
|
369
406
|
|
|
370
407
|
return next().then(step.bind(null, 0))
|
|
371
408
|
|
|
372
409
|
function step (idx, char) {
|
|
373
410
|
if (isHexit(char)) {
|
|
374
|
-
hexits
|
|
411
|
+
hexits.push(char)
|
|
375
412
|
}
|
|
376
413
|
|
|
377
414
|
if (idx < 3) {
|
|
378
415
|
return next().then(step.bind(null, idx + 1))
|
|
379
416
|
}
|
|
380
417
|
|
|
418
|
+
hexits = hexits.join('')
|
|
419
|
+
|
|
381
420
|
if (hexits.length === 4) {
|
|
382
421
|
return String.fromCharCode(parseInt(hexits, 16))
|
|
383
422
|
}
|
|
@@ -393,12 +432,12 @@ function initialise (stream, options) {
|
|
|
393
432
|
}
|
|
394
433
|
|
|
395
434
|
function number (firstCharacter) {
|
|
396
|
-
let digits = firstCharacter
|
|
435
|
+
let digits = [ firstCharacter ]
|
|
397
436
|
|
|
398
437
|
return walkDigits().then(addDigits.bind(null, checkDecimalPlace))
|
|
399
438
|
|
|
400
439
|
function addDigits (step, result) {
|
|
401
|
-
digits
|
|
440
|
+
digits = digits.concat(result.digits)
|
|
402
441
|
|
|
403
442
|
if (result.atEnd) {
|
|
404
443
|
return endNumber()
|
|
@@ -410,7 +449,7 @@ function initialise (stream, options) {
|
|
|
410
449
|
function checkDecimalPlace () {
|
|
411
450
|
if (character() === '.') {
|
|
412
451
|
return next().then(char => {
|
|
413
|
-
digits
|
|
452
|
+
digits.push(char)
|
|
414
453
|
walkDigits().then(addDigits.bind(null, checkExponent))
|
|
415
454
|
})
|
|
416
455
|
}
|
|
@@ -421,7 +460,7 @@ function initialise (stream, options) {
|
|
|
421
460
|
function checkExponent () {
|
|
422
461
|
if (character() === 'e' || character() === 'E') {
|
|
423
462
|
return next().then(char => {
|
|
424
|
-
digits
|
|
463
|
+
digits.push(char)
|
|
425
464
|
awaitCharacter()
|
|
426
465
|
.then(checkSign)
|
|
427
466
|
.catch(fail.bind(null, 'EOF', 'exponent', currentPosition))
|
|
@@ -434,7 +473,7 @@ function initialise (stream, options) {
|
|
|
434
473
|
function checkSign () {
|
|
435
474
|
if (character() === '+' || character() === '-') {
|
|
436
475
|
return next().then(char => {
|
|
437
|
-
digits
|
|
476
|
+
digits.push(char)
|
|
438
477
|
readExponent()
|
|
439
478
|
})
|
|
440
479
|
}
|
|
@@ -447,13 +486,13 @@ function initialise (stream, options) {
|
|
|
447
486
|
}
|
|
448
487
|
|
|
449
488
|
function endNumber () {
|
|
450
|
-
emitter.emit(events.number, parseFloat(digits))
|
|
489
|
+
emitter.emit(events.number, parseFloat(digits.join('')))
|
|
451
490
|
return endValue()
|
|
452
491
|
}
|
|
453
492
|
}
|
|
454
493
|
|
|
455
494
|
function walkDigits () {
|
|
456
|
-
|
|
495
|
+
const digits = []
|
|
457
496
|
|
|
458
497
|
return wait()
|
|
459
498
|
|
|
@@ -466,7 +505,7 @@ function initialise (stream, options) {
|
|
|
466
505
|
function step () {
|
|
467
506
|
if (isDigit(character())) {
|
|
468
507
|
return next().then(char => {
|
|
469
|
-
digits
|
|
508
|
+
digits.push(char)
|
|
470
509
|
return wait()
|
|
471
510
|
})
|
|
472
511
|
}
|
package/test/unit/read.js
CHANGED
package/test/unit/streamify.js
CHANGED
|
@@ -9,7 +9,7 @@ const modulePath = '../../src/streamify'
|
|
|
9
9
|
mockery.registerAllowable(modulePath)
|
|
10
10
|
mockery.registerAllowable('hoopy')
|
|
11
11
|
mockery.registerAllowable('check-types')
|
|
12
|
-
mockery.registerAllowable('
|
|
12
|
+
mockery.registerAllowable('tryer')
|
|
13
13
|
mockery.registerAllowable('./events')
|
|
14
14
|
|
|
15
15
|
suite('streamify:', () => {
|