From 963e3aebda031ab4918db49c4d19463ba3326008 Mon Sep 17 00:00:00 2001 From: Prakhar Pathak Date: Mon, 26 Oct 2026 21:06:40 +0530 Subject: [PATCH 1/3] perf: reuse compiled serializers --- standalone.js | 17 ++++++++- test/duplicate-schema.test.js | 72 +++++++++++++++++++++++++++++------ 2 files changed, 77 insertions(+), 12 deletions(-) diff --git a/standalone.js b/standalone.js index 7f0d40a..da2b64d 100644 --- a/standalone.js +++ b/standalone.js @@ -5,7 +5,22 @@ const fastJsonStringify = require('fast-json-stringify') function SerializerSelector () { return function buildSerializerFactory (externalSchemas, serializerOpts) { const fjsOpts = Object.assign({}, serializerOpts, { schema: externalSchemas }) - return responseSchemaCompiler.bind(null, fjsOpts) + const cache = new WeakMap() + + return function responseSchemaCompilerWithCache (opts) { + const { schema } = opts + + let serializer = cache.get(schema) + + if (serializer !== undefined) { + return serializer + } + + serializer = responseSchemaCompiler(fjsOpts, opts) + cache.set(schema, serializer) + + return serializer + } } } diff --git a/test/duplicate-schema.test.js b/test/duplicate-schema.test.js index 2acaa24..402ccc6 100644 --- a/test/duplicate-schema.test.js +++ b/test/duplicate-schema.test.js @@ -3,24 +3,74 @@ const { test } = require('node:test') const FjsCompiler = require('../index') -test('Use input schema duplicate in the externalSchemas', async t => { - t.plan(1) +test('reuse compiled serializer for the same schema object', t => { + const schema = { + type: 'object', + properties: { + value: { type: 'string' } + } + } + + const factory = FjsCompiler() + const compiler = factory({}) + + const first = compiler({ schema }) + const second = compiler({ schema }) + + t.assert.strictEqual(first, second) +}) + +test('compile different schema objects independently', t => { + const factory = FjsCompiler() + const compiler = factory({}) + + const first = compiler({ schema: { type: 'string' } }) + const second = compiler({ schema: { type: 'number' } }) + + t.assert.notStrictEqual(first, second) +}) + +test('isolate caches between selector instances', t => { + const schema = { type: 'string' } + + const firstCompiler = FjsCompiler()({}) + const secondCompiler = FjsCompiler()({}) + + const first = firstCompiler({ schema }) + const second = secondCompiler({ schema }) + + t.assert.notStrictEqual(first, second) +}) + +test('handle schema duplicated in externalSchemas', t => { + const schema = { + $id: 'schema1', + type: 'number' + } + const externalSchemas = { - schema1: { - $id: 'schema1', - type: 'number' - }, + schema1: schema, schema2: { $id: 'schema2', type: 'string' } } - const factory = FjsCompiler() - const compiler = factory(externalSchemas) + const compiler = FjsCompiler()(externalSchemas) + const serializer = compiler({ schema }) + + t.assert.strictEqual(serializer(42), '42') +}) + +test('isolate caches between factory instances', t => { + const schema = { type: 'string' } + const selector = FjsCompiler() + + const firstCompiler = selector({}) + const secondCompiler = selector({}) - compiler({ schema: externalSchemas.schema1 }) - compiler({ schema: externalSchemas.schema2 }) + const first = firstCompiler({ schema }) + const second = secondCompiler({ schema }) - t.assert.ok(true) + t.assert.notStrictEqual(first, second) }) From 687d8fe3bbb377b336af828bf17bea042e296884 Mon Sep 17 00:00:00 2001 From: Prakhar Pathak Date: Mon, 2 Nov 2026 11:19:13 +0530 Subject: [PATCH 2/3] fix: handle boolean schemas in serializer cache --- standalone.js | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/standalone.js b/standalone.js index da2b64d..f4b6066 100644 --- a/standalone.js +++ b/standalone.js @@ -9,15 +9,21 @@ function SerializerSelector () { return function responseSchemaCompilerWithCache (opts) { const { schema } = opts + const isObject = typeof schema === 'object' && schema !== null - let serializer = cache.get(schema) + if (isObject) { + const serializer = cache.get(schema) - if (serializer !== undefined) { - return serializer + if (serializer !== undefined) { + return serializer + } } - serializer = responseSchemaCompiler(fjsOpts, opts) - cache.set(schema, serializer) + const serializer = responseSchemaCompiler(fjsOpts, opts) + + if (isObject) { + cache.set(schema, serializer) + } return serializer } From bf7f75742bfbb3ac5147929ff3278db2ab0f534c Mon Sep 17 00:00:00 2001 From: Prakhar Pathak Date: Mon, 2 Nov 2026 11:19:22 +0530 Subject: [PATCH 3/3] test: cover boolean schema serializer caching --- test/duplicate-schema.test.js | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/test/duplicate-schema.test.js b/test/duplicate-schema.test.js index 402ccc6..ebb1dea 100644 --- a/test/duplicate-schema.test.js +++ b/test/duplicate-schema.test.js @@ -74,3 +74,11 @@ test('isolate caches between factory instances', t => { t.assert.notStrictEqual(first, second) }) + +test('handle boolean schemas', t => { + const compiler = FjsCompiler()({}) + + const serializer = compiler({ schema: false }) + + t.assert.strictEqual(typeof serializer, 'function') +})