Comparing version 5.0.0 to 5.1.0
# History | ||
## 5.1.0 | ||
* chore: remove extra trailing newlines (fa561e2) | ||
* feature: allow callers to pass in the Promise constructor (aa5a664) | ||
* refactor: better names for the option-mangling functions (5eb2e4e) | ||
## 5.0.0 | ||
@@ -4,0 +10,0 @@ |
{ | ||
"name": "bfj", | ||
"version": "5.0.0", | ||
"version": "5.1.0", | ||
"description": "Big-friendly JSON. Asynchronous streaming functions for large JSON data sets.", | ||
@@ -5,0 +5,0 @@ "homepage": "https://github.com/philbooth/bfj", |
@@ -24,3 +24,3 @@ # BFJ | ||
* [Options for serialisation functions](#options-for-serialisation-functions) | ||
* [Why does it return bluebird promises?](#why-does-it-return-bluebird-promises) | ||
* [Why does it default to bluebird promises?](#why-does-it-default-to-bluebird-promises) | ||
* [Can I specify a different promise implementation?](#can-i-specify-a-different-promise-implementation) | ||
@@ -564,2 +564,13 @@ * [Is there a change log?](#is-there-a-change-log) | ||
* `options.Promise`: | ||
Promise constructor that will be used | ||
for promises returned by all methods. | ||
If you set this option, | ||
please be aware that some promise implementations | ||
(including native promises) | ||
may cause your process to die | ||
with out-of-memory exceptions. | ||
Defaults to [bluebird's implementation][promise], | ||
which does not have that problem. | ||
### Options for serialisation functions | ||
@@ -646,21 +657,38 @@ | ||
## Why does it return bluebird promises? | ||
* `options.Promise`: | ||
Promise constructor that will be used | ||
for promises returned by all methods. | ||
If you set this option, | ||
please be aware that some promise implementations | ||
(including native promises) | ||
may cause your process to die | ||
with out-of-memory exceptions. | ||
Defaults to [bluebird's implementation][promise], | ||
which does not have that problem. | ||
Before version `5.0.0`, | ||
## Why does it default to bluebird promises? | ||
Until version `4.2.4`, | ||
native promises were used. | ||
But they were found to be an indirect cause | ||
of out-of-memory errors | ||
But they were found | ||
to cause out-of-memory errors | ||
when serialising large amounts of data to JSON, | ||
due to [well-documented problems | ||
with the native promise implementation](https://alexn.org/blog/2017/10/11/javascript-promise-leaks-memory.html). | ||
So alternative implementations were evaluated | ||
and bluebird won. | ||
So in version `5.0.0`, | ||
bluebird promises were used instead. | ||
In version `5.1.0`, | ||
an option was added | ||
that enables callers to specify | ||
the promise constructor to use. | ||
Use it at your own risk. | ||
## Can I specify a different promise implementation? | ||
I'm not against adding a `Promise` option | ||
that allows callers to specify | ||
the implementation that should be used, | ||
I just haven't got round to implementing it yet. | ||
I'll accept a PR if anyone wants to work on it. | ||
Yes. | ||
Just pass the `Promise` option | ||
to any method. | ||
If you get out-of-memory errors | ||
when using that option, | ||
consider changing your promise implementation. | ||
@@ -667,0 +695,0 @@ ## Is there a change log? |
@@ -23,2 +23,1 @@ 'use strict' | ||
} | ||
@@ -6,3 +6,3 @@ 'use strict' | ||
const events = require('./events') | ||
const Promise = require('bluebird') | ||
const promise = require('./promise') | ||
@@ -39,13 +39,17 @@ const invalidTypes = { | ||
* default is 16384. | ||
* | ||
* @option Promise: The promise constructor to use, defaults to bluebird. | ||
**/ | ||
function eventify (data, options) { | ||
let ignoreCircularReferences, ignoreItems | ||
const references = new Map() | ||
function eventify (data, options = {}) { | ||
const coercions = {} | ||
const emitter = new EventEmitter() | ||
const Promise = promise(options) | ||
const references = new Map() | ||
let count = 0 | ||
let disableCoercions = false | ||
let count = 0 | ||
let ignoreCircularReferences | ||
let ignoreItems | ||
let pause | ||
let yieldRate | ||
let pause | ||
@@ -61,3 +65,3 @@ emitter.pause = () => { | ||
} | ||
normaliseOptions() | ||
parseOptions() | ||
setImmediate(begin) | ||
@@ -67,10 +71,8 @@ | ||
function normaliseOptions () { | ||
options = options || {} | ||
function parseOptions () { | ||
parseCoercionOption('promises') | ||
parseCoercionOption('buffers') | ||
parseCoercionOption('maps') | ||
parseCoercionOption('iterables') | ||
normaliseOption('promises') | ||
normaliseOption('buffers') | ||
normaliseOption('maps') | ||
normaliseOption('iterables') | ||
if (Object.keys(coercions).length === 0) { | ||
@@ -88,3 +90,3 @@ disableCoercions = true | ||
function normaliseOption (key) { | ||
function parseCoercionOption (key) { | ||
if (options[key] !== 'ignore') { | ||
@@ -181,4 +183,4 @@ coercions[key] = true | ||
function coercePromise (promise) { | ||
return promise | ||
function coercePromise (p) { | ||
return p | ||
} | ||
@@ -300,2 +302,1 @@ | ||
} | ||
@@ -17,2 +17,1 @@ 'use strict' | ||
module.exports.endObject = module.exports.endPrefix + module.exports.object | ||
@@ -14,2 +14,1 @@ 'use strict' | ||
} | ||
@@ -24,2 +24,1 @@ 'use strict' | ||
} | ||
@@ -46,2 +46,1 @@ 'use strict' | ||
} | ||
@@ -5,3 +5,3 @@ 'use strict' | ||
const events = require('./events') | ||
const Promise = require('bluebird') | ||
const promise = require('./promise') | ||
const walk = require('./walk') | ||
@@ -24,11 +24,10 @@ | ||
* default is 16384. | ||
* | ||
* @option Promise: The promise constructor to use, defaults to bluebird. | ||
**/ | ||
function parse (stream, options) { | ||
let resolve, reject, scopeKey | ||
function parse (stream, options = {}) { | ||
const Promise = promise(options) | ||
options = options || {} | ||
const reviver = options.reviver | ||
try { | ||
check.assert.maybe.function(reviver, 'Invalid reviver option') | ||
check.assert.maybe.function(options.reviver, 'Invalid reviver option') | ||
} catch (err) { | ||
@@ -39,6 +38,8 @@ return Promise.reject(err) | ||
const emitter = walk(stream, options) | ||
const errors = [] | ||
const reviver = options.reviver | ||
const scopes = [] | ||
const errors = [] | ||
let resolve, reject, scopeKey | ||
emitter.on(events.array, array) | ||
@@ -151,2 +152,1 @@ emitter.on(events.object, object) | ||
} | ||
@@ -5,3 +5,3 @@ 'use strict' | ||
const parse = require('./parse') | ||
const Promise = require('bluebird') | ||
const promise = require('./promise') | ||
@@ -23,4 +23,8 @@ module.exports = read | ||
* default is 16384. | ||
* | ||
* @option Promise: The promise constructor to use, defaults to bluebird. | ||
**/ | ||
function read (path, options) { | ||
const Promise = promise(options) | ||
try { | ||
@@ -32,2 +36,1 @@ return parse(fs.createReadStream(path, options), options) | ||
} | ||
@@ -8,3 +8,3 @@ 'use strict' | ||
const Hoopy = require('hoopy') | ||
const Promise = require('bluebird') | ||
const promise = require('./promise') | ||
const tryer = require('tryer') | ||
@@ -41,18 +41,21 @@ | ||
* @option bufferLength: The length of the buffer, default is 1024. | ||
* | ||
* @option Promise: The promise constructor to use, defaults to bluebird. | ||
**/ | ||
function streamify (data, options = {}) { | ||
let isProperty, needsComma, isEnded | ||
const emitter = eventify(data, options) | ||
const json = new Hoopy(options.bufferLength || DEFAULT_BUFFER_LENGTH) | ||
const Promise = promise(options) | ||
const space = normaliseSpace(options) | ||
const stream = new JsonStream(read) | ||
const emitter = eventify(data, options) | ||
const json = new Hoopy(options.bufferLength || DEFAULT_BUFFER_LENGTH) | ||
let length = 0 | ||
let awaitPush = true | ||
let index = 0 | ||
let indentation = '' | ||
let awaitPush = true | ||
let isEnded | ||
let isPaused = false | ||
let isProperty | ||
let length = 0 | ||
let mutex = Promise.resolve() | ||
let needsComma | ||
@@ -270,2 +273,1 @@ emitter.on(events.array, noRacing(array)) | ||
} | ||
'use strict' | ||
const Promise = require('bluebird') | ||
const promise = require('./promise') | ||
const streamify = require('./streamify') | ||
@@ -33,9 +33,12 @@ | ||
* @option bufferLength: The length of the buffer, default is 1024. | ||
* | ||
* @option Promise: The promise constructor to use, defaults to bluebird. | ||
**/ | ||
function stringify (data, options) { | ||
const json = [] | ||
const Promise = promise(options) | ||
const stream = streamify(data, options) | ||
let resolve, reject | ||
const stream = streamify(data, options) | ||
const json = [] | ||
stream.on('data', read) | ||
@@ -62,2 +65,1 @@ stream.on('end', end) | ||
} | ||
@@ -38,2 +38,1 @@ 'use strict' | ||
} | ||
@@ -7,3 +7,3 @@ 'use strict' | ||
const events = require('./events') | ||
const Promise = require('bluebird') | ||
const promise = require('./promise') | ||
@@ -40,7 +40,23 @@ const terminators = { | ||
* default is 16384. | ||
* | ||
* @option Promise: The promise constructor to use, defaults to bluebird. | ||
**/ | ||
function initialise (stream, options) { | ||
function initialise (stream, options = {}) { | ||
check.assert.instanceStrict(stream, require('stream').Readable, 'Invalid stream argument') | ||
options = options || {} | ||
const currentPosition = { | ||
line: 1, | ||
column: 1 | ||
} | ||
const emitter = new EventEmitter() | ||
const handlers = { | ||
arr: value, | ||
obj: property | ||
} | ||
const json = [] | ||
const lengths = [] | ||
const previousPosition = {} | ||
const Promise = promise(options) | ||
const scopes = [] | ||
const yieldRate = options.yieldRate || 16384 | ||
@@ -56,17 +72,2 @@ let index = 0 | ||
const json = [] | ||
const lengths = [] | ||
const currentPosition = { | ||
line: 1, | ||
column: 1 | ||
} | ||
const previousPosition = {} | ||
const scopes = [] | ||
const handlers = { | ||
arr: value, | ||
obj: property | ||
} | ||
const emitter = new EventEmitter() | ||
const yieldRate = options.yieldRate || 16384 | ||
stream.setEncoding('utf8') | ||
@@ -648,2 +649,1 @@ stream.on('data', readStream) | ||
} | ||
'use strict' | ||
const fs = require('fs') | ||
const Promise = require('bluebird') | ||
const promise = require('./promise') | ||
const streamify = require('./streamify') | ||
@@ -37,4 +37,8 @@ | ||
* @option bufferLength: The length of the buffer, default is 1024. | ||
* | ||
* @option Promise: The promise constructor to use, defaults to bluebird. | ||
**/ | ||
function write (path, data, options) { | ||
const Promise = promise(options) | ||
return new Promise((resolve, reject) => { | ||
@@ -50,2 +54,1 @@ streamify(data, options) | ||
} | ||
@@ -49,3 +49,3 @@ 'use strict' | ||
test('walk expects one argument', () => { | ||
assert.lengthOf(bfj.walk, 2) | ||
assert.lengthOf(bfj.walk, 1) | ||
}) | ||
@@ -57,4 +57,4 @@ | ||
test('parse expects two arguments', () => { | ||
assert.lengthOf(bfj.parse, 2) | ||
test('parse expects one argument', () => { | ||
assert.lengthOf(bfj.parse, 1) | ||
}) | ||
@@ -74,4 +74,4 @@ | ||
test('eventify expects two arguments', () => { | ||
assert.lengthOf(bfj.eventify, 2) | ||
test('eventify expects one argument', () => { | ||
assert.lengthOf(bfj.eventify, 1) | ||
}) | ||
@@ -78,0 +78,0 @@ |
@@ -93,2 +93,1 @@ 'use strict' | ||
}) | ||
@@ -1896,2 +1896,1 @@ 'use strict' | ||
}) | ||
@@ -108,2 +108,1 @@ 'use strict' | ||
}) | ||
@@ -40,4 +40,4 @@ 'use strict' | ||
test('parse expects two arguments', () => { | ||
assert.lengthOf(parse, 2) | ||
test('parse expects one argument', () => { | ||
assert.lengthOf(parse, 1) | ||
}) | ||
@@ -67,2 +67,8 @@ | ||
test('parse returns a different type of promise if the option is set', () => { | ||
assert.isFunction(global.Promise) | ||
assert.notStrictEqual(Promise, global.Promise) | ||
assert.instanceOf(parse('', { Promise: global.Promise }), global.Promise) | ||
}) | ||
test('parse rejects immediately if reviver is an object', () => { | ||
@@ -808,2 +814,1 @@ return parse({}, { reviver: {} }) | ||
}) | ||
@@ -137,2 +137,1 @@ 'use strict' | ||
}) | ||
@@ -990,2 +990,1 @@ 'use strict' | ||
}) | ||
@@ -179,2 +179,1 @@ 'use strict' | ||
}) | ||
@@ -126,2 +126,1 @@ 'use strict' | ||
}) | ||
@@ -277,2 +277,1 @@ 'use strict' | ||
}) | ||
Sorry, the diff of this file is too big to display
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
281052
35
7420
766