diff --git a/index.js b/index.js index e692d5e9..15ac92d4 100644 --- a/index.js +++ b/index.js @@ -10,9 +10,6 @@ const Location = require('./lib/location') const validate = require('./lib/schema-validator') const mergeSchemas = require('./lib/merge-schemas') -let largeArraySize = 2e4 -let largeArrayMechanism = 'default' - const NAMED_FRAGMENT_REF = /^#[a-z_][-\w._]*$/i const serializerFns = ` @@ -157,6 +154,8 @@ function build (schema, options) { functionsCounter: 0, functionsNamesBySchema: new Map(), options, + largeArraySize: 2e4, + largeArrayMechanism: 'default', refResolver: new RefResolver(), rootSchemaId: schema.$id || `__fjs_root_${schemaIdCounter++}`, validatorSchemasIds: new Set(), @@ -192,7 +191,7 @@ function build (schema, options) { if (options.largeArrayMechanism) { if (validLargeArrayMechanisms.has(options.largeArrayMechanism)) { - largeArrayMechanism = options.largeArrayMechanism + context.largeArrayMechanism = options.largeArrayMechanism } else { throw new Error(`Unsupported large array mechanism ${options.largeArrayMechanism}`) } @@ -203,11 +202,11 @@ function build (schema, options) { let parsedNumber if (largeArraySizeType === 'string' && Number.isFinite((parsedNumber = Number.parseInt(options.largeArraySize, 10)))) { - largeArraySize = parsedNumber + context.largeArraySize = parsedNumber } else if (largeArraySizeType === 'number' && Number.isInteger(options.largeArraySize)) { - largeArraySize = options.largeArraySize + context.largeArraySize = options.largeArraySize } else if (largeArraySizeType === 'bigint') { - largeArraySize = Number(options.largeArraySize) + context.largeArraySize = Number(options.largeArraySize) } else { throw new Error(`Unsupported large array size. Expected integer-like, got ${typeof options.largeArraySize} with value ${options.largeArraySize}`) } @@ -700,8 +699,8 @@ function buildArray (context, location, input) { ` } - if (largeArrayMechanism === 'json-stringify') { - functionCode += `if (arrayLength >= ${largeArraySize}) return JSON.stringify(obj)\n` + if (context.largeArrayMechanism === 'json-stringify') { + functionCode += `if (arrayLength >= ${context.largeArraySize}) return JSON.stringify(obj)\n` } functionCode += ` @@ -785,8 +784,8 @@ function buildArray (context, location, input) { ` } - if (largeArrayMechanism === 'json-stringify') { - inlinedCode += `if (arrayLength_${objVar} >= ${largeArraySize}) json += JSON.stringify(${objVar})\n else {` + if (context.largeArrayMechanism === 'json-stringify') { + inlinedCode += `if (arrayLength_${objVar} >= ${context.largeArraySize}) json += JSON.stringify(${objVar})\n else {` } inlinedCode += ` @@ -843,7 +842,7 @@ function buildArray (context, location, input) { json += JSON_STR_END_ARRAY ` - if (largeArrayMechanism === 'json-stringify') { + if (context.largeArrayMechanism === 'json-stringify') { inlinedCode += '}' } diff --git a/test/array.test.js b/test/array.test.js index 3dbeeb55..efc8fef8 100644 --- a/test/array.test.js +++ b/test/array.test.js @@ -686,3 +686,26 @@ buildTest({ largeArraySize: '10000', largeArrayMechanism: 'default' }) + +test('large-array options do not leak between serializers', (t) => { + t.plan(3) + + const schema = { + type: 'array', + items: { type: 'integer' } + } + + const jsonStringify = build(schema, { + largeArrayMechanism: 'json-stringify', + largeArraySize: 1 + }) + t.assert.throws(() => jsonStringify([1n]), /Do not know how to serialize a BigInt/) + + const jsonStringifyWithDefaultSize = build(schema, { + largeArrayMechanism: 'json-stringify' + }) + t.assert.equal(jsonStringifyWithDefaultSize([1n]), '[1]') + + const defaultStringify = build(schema) + t.assert.equal(defaultStringify([1n]), '[1]') +})