Skip to content

Commit 1c9bfbf

Browse files
authored
fix: cache duplicated symbols (fastify#4612)
* refactor: cleanup duplicated symbols * refactor: rename to kRequestCacheValidateFns * refactor: rename to kReplyCacheSerializeFns * test: extend test cases * test: add test case for context
1 parent 4bb798f commit 1c9bfbf

File tree

9 files changed

+76
-40
lines changed

9 files changed

+76
-40
lines changed

lib/context.js

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,8 @@ const {
1111
kLogLevel,
1212
kContentTypeParser,
1313
kRouteByFastify,
14-
kRequestValidateWeakMap,
15-
kReplySerializeWeakMap,
14+
kRequestCacheValidateFns,
15+
kReplyCacheSerializeFns,
1616
kPublicRouteContext
1717
} = require('./symbols.js')
1818

@@ -68,8 +68,8 @@ function Context ({
6868
defaultSchemaErrorFormatter
6969
this[kRouteByFastify] = isFastify
7070

71-
this[kRequestValidateWeakMap] = null
72-
this[kReplySerializeWeakMap] = null
71+
this[kRequestCacheValidateFns] = null
72+
this[kReplyCacheSerializeFns] = null
7373
this.validatorCompiler = validatorCompiler || null
7474
this.serializerCompiler = serializerCompiler || null
7575

lib/reply.js

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ const {
1818
kReplyNextErrorHandler,
1919
kDisableRequestLogging,
2020
kSchemaResponse,
21-
kReplySerializeWeakMap,
21+
kReplyCacheSerializeFns,
2222
kSchemaController,
2323
kOptions,
2424
kRouteContext
@@ -323,7 +323,7 @@ Reply.prototype.getSerializationFunction = function (schemaOrStatus, contentType
323323
serialize = this[kRouteContext][kSchemaResponse]?.[schemaOrStatus]
324324
}
325325
} else if (typeof schemaOrStatus === 'object') {
326-
serialize = this[kRouteContext][kReplySerializeWeakMap]?.get(schemaOrStatus)
326+
serialize = this[kRouteContext][kReplyCacheSerializeFns]?.get(schemaOrStatus)
327327
}
328328

329329
return serialize
@@ -334,8 +334,8 @@ Reply.prototype.compileSerializationSchema = function (schema, httpStatus = null
334334
const { method, url } = request
335335

336336
// Check if serialize function already compiled
337-
if (this[kRouteContext][kReplySerializeWeakMap]?.has(schema)) {
338-
return this[kRouteContext][kReplySerializeWeakMap].get(schema)
337+
if (this[kRouteContext][kReplyCacheSerializeFns]?.has(schema)) {
338+
return this[kRouteContext][kReplyCacheSerializeFns].get(schema)
339339
}
340340

341341
const serializerCompiler = this[kRouteContext].serializerCompiler ||
@@ -360,11 +360,11 @@ Reply.prototype.compileSerializationSchema = function (schema, httpStatus = null
360360
// if it is not used
361361
// TODO: Explore a central cache for all the schemas shared across
362362
// encapsulated contexts
363-
if (this[kRouteContext][kReplySerializeWeakMap] == null) {
364-
this[kRouteContext][kReplySerializeWeakMap] = new WeakMap()
363+
if (this[kRouteContext][kReplyCacheSerializeFns] == null) {
364+
this[kRouteContext][kReplyCacheSerializeFns] = new WeakMap()
365365
}
366366

367-
this[kRouteContext][kReplySerializeWeakMap].set(schema, serializeFn)
367+
this[kRouteContext][kReplyCacheSerializeFns].set(schema, serializeFn)
368368

369369
return serializeFn
370370
}
@@ -393,8 +393,8 @@ Reply.prototype.serializeInput = function (input, schema, httpStatus, contentTyp
393393
}
394394
} else {
395395
// Check if serialize function already compiled
396-
if (this[kRouteContext][kReplySerializeWeakMap]?.has(schema)) {
397-
serialize = this[kRouteContext][kReplySerializeWeakMap].get(schema)
396+
if (this[kRouteContext][kReplyCacheSerializeFns]?.has(schema)) {
397+
serialize = this[kRouteContext][kReplyCacheSerializeFns].get(schema)
398398
} else {
399399
serialize = this.compileSerializationSchema(schema, httpStatus, contentType)
400400
}

lib/request.js

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ const {
1111
kSchemaQuerystring,
1212
kSchemaController,
1313
kOptions,
14-
kRequestValidateWeakMap,
14+
kRequestCacheValidateFns,
1515
kRouteContext,
1616
kPublicRouteContext
1717
} = require('./symbols')
@@ -254,16 +254,16 @@ Object.defineProperties(Request.prototype, {
254254
const symbol = HTTP_PART_SYMBOL_MAP[httpPartOrSchema]
255255
return this[kRouteContext][symbol]
256256
} else if (typeof httpPartOrSchema === 'object') {
257-
return this[kRouteContext][kRequestValidateWeakMap]?.get(httpPartOrSchema)
257+
return this[kRouteContext][kRequestCacheValidateFns]?.get(httpPartOrSchema)
258258
}
259259
}
260260
},
261261
compileValidationSchema: {
262262
value: function (schema, httpPart = null) {
263263
const { method, url } = this
264264

265-
if (this[kRouteContext][kRequestValidateWeakMap]?.has(schema)) {
266-
return this[kRouteContext][kRequestValidateWeakMap].get(schema)
265+
if (this[kRouteContext][kRequestCacheValidateFns]?.has(schema)) {
266+
return this[kRouteContext][kRequestCacheValidateFns].get(schema)
267267
}
268268

269269
const validatorCompiler = this[kRouteContext].validatorCompiler ||
@@ -287,11 +287,11 @@ Object.defineProperties(Request.prototype, {
287287
// if it is not used
288288
// TODO: Explore a central cache for all the schemas shared across
289289
// encapsulated contexts
290-
if (this[kRouteContext][kRequestValidateWeakMap] == null) {
291-
this[kRouteContext][kRequestValidateWeakMap] = new WeakMap()
290+
if (this[kRouteContext][kRequestCacheValidateFns] == null) {
291+
this[kRouteContext][kRequestCacheValidateFns] = new WeakMap()
292292
}
293293

294-
this[kRouteContext][kRequestValidateWeakMap].set(schema, validateFn)
294+
this[kRouteContext][kRequestCacheValidateFns].set(schema, validateFn)
295295

296296
return validateFn
297297
}
@@ -317,8 +317,8 @@ Object.defineProperties(Request.prototype, {
317317
}
318318

319319
if (validate == null) {
320-
if (this[kRouteContext][kRequestValidateWeakMap]?.has(schema)) {
321-
validate = this[kRouteContext][kRequestValidateWeakMap].get(schema)
320+
if (this[kRouteContext][kRequestCacheValidateFns]?.has(schema)) {
321+
validate = this[kRouteContext][kRequestCacheValidateFns].get(schema)
322322
} else {
323323
// We proceed to compile if there's no validate function yet
324324
validate = this.compileValidationSchema(schema, httpPart)

lib/symbols.js

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -27,10 +27,9 @@ const keys = {
2727
kSchemaVisited: Symbol('fastify.schemas.visited'),
2828
// Request
2929
kRequest: Symbol('fastify.Request'),
30-
kRequestValidateFns: Symbol('fastify.request.cache.validateFns'),
3130
kRequestPayloadStream: Symbol('fastify.RequestPayloadStream'),
3231
kRequestAcceptVersion: Symbol('fastify.RequestAcceptVersion'),
33-
kRequestValidateWeakMap: Symbol('fastify.request.cache.validators'),
32+
kRequestCacheValidateFns: Symbol('fastify.request.cache.validateFns'),
3433
// 404
3534
kFourOhFour: Symbol('fastify.404'),
3635
kCanSetNotFoundHandler: Symbol('fastify.canSetNotFoundHandler'),
@@ -51,7 +50,7 @@ const keys = {
5150
kReplyErrorHandlerCalled: Symbol('fastify.reply.errorHandlerCalled'),
5251
kReplyIsRunningOnErrorHook: Symbol('fastify.reply.isRunningOnErrorHook'),
5352
kReplySerializerDefault: Symbol('fastify.replySerializerDefault'),
54-
kReplySerializeWeakMap: Symbol('fastify.reply.cache.serializeFns'),
53+
kReplyCacheSerializeFns: Symbol('fastify.reply.cache.serializeFns'),
5554
// This symbol is only meant to be used for fastify tests and should not be used for any other purpose
5655
kTestInternals: Symbol('fastify.testInternals'),
5756
kErrorHandler: Symbol('fastify.errorHandler'),

test/internals/context.test.js

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
'use strict'
2+
3+
const { test } = require('tap')
4+
5+
const { kRouteContext } = require('../../lib/symbols')
6+
const Context = require('../../lib/context')
7+
8+
const Fastify = require('../..')
9+
10+
test('context', context => {
11+
context.plan(1)
12+
13+
context.test('Should not contain undefined as key prop', async t => {
14+
const app = Fastify()
15+
16+
app.get('/', (req, reply) => {
17+
t.type(req[kRouteContext], Context)
18+
t.type(reply[kRouteContext], Context)
19+
t.notOk('undefined' in reply[kRouteContext])
20+
t.notOk('undefined' in req[kRouteContext])
21+
22+
reply.send('hello world!')
23+
})
24+
25+
try {
26+
await app.inject('/')
27+
} catch (e) {
28+
t.fail(e)
29+
}
30+
31+
t.plan(4)
32+
})
33+
})

test/internals/reply-serialize.test.js

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
'use strict'
22

33
const { test } = require('tap')
4-
const { kReplySerializeWeakMap, kRouteContext } = require('../../lib/symbols')
4+
const { kReplyCacheSerializeFns, kRouteContext } = require('../../lib/symbols')
55
const Fastify = require('../../fastify')
66

77
function getDefaultSchema () {
@@ -207,9 +207,9 @@ test('Reply#compileSerializationSchema', t => {
207207
fastify.get('/', (req, reply) => {
208208
const input = { hello: 'world' }
209209

210-
t.equal(reply[kRouteContext][kReplySerializeWeakMap], null)
210+
t.equal(reply[kRouteContext][kReplyCacheSerializeFns], null)
211211
t.equal(reply.compileSerializationSchema(getDefaultSchema())(input), JSON.stringify(input))
212-
t.type(reply[kRouteContext][kReplySerializeWeakMap], WeakMap)
212+
t.type(reply[kRouteContext][kReplyCacheSerializeFns], WeakMap)
213213
t.equal(reply.compileSerializationSchema(getDefaultSchema())(input), JSON.stringify(input))
214214

215215
reply.send({ hello: 'world' })
@@ -408,9 +408,9 @@ test('Reply#getSerializationFunction', t => {
408408

409409
fastify.get('/', (req, reply) => {
410410
t.notOk(reply.getSerializationFunction(getDefaultSchema()))
411-
t.equal(reply[kRouteContext][kReplySerializeWeakMap], null)
411+
t.equal(reply[kRouteContext][kReplyCacheSerializeFns], null)
412412
t.notOk(reply.getSerializationFunction('200'))
413-
t.equal(reply[kRouteContext][kReplySerializeWeakMap], null)
413+
t.equal(reply[kRouteContext][kReplyCacheSerializeFns], null)
414414

415415
reply.send({ hello: 'world' })
416416
})
@@ -684,9 +684,9 @@ test('Reply#serializeInput', t => {
684684

685685
fastify.get('/', (req, reply) => {
686686
const input = { hello: 'world' }
687-
t.equal(reply[kRouteContext][kReplySerializeWeakMap], null)
687+
t.equal(reply[kRouteContext][kReplyCacheSerializeFns], null)
688688
t.equal(reply.serializeInput(input, getDefaultSchema()), JSON.stringify(input))
689-
t.type(reply[kRouteContext][kReplySerializeWeakMap], WeakMap)
689+
t.type(reply[kRouteContext][kReplyCacheSerializeFns], WeakMap)
690690

691691
reply.send({ hello: 'world' })
692692
})

test/internals/reply.test.js

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ const doGet = function (url) {
3232
}
3333

3434
test('Once called, Reply should return an object with methods', t => {
35-
t.plan(13)
35+
t.plan(14)
3636
const response = { res: 'res' }
3737
const context = {}
3838
const request = { [kRouteContext]: context }
@@ -50,6 +50,8 @@ test('Once called, Reply should return an object with methods', t => {
5050
t.same(reply.raw, response)
5151
t.equal(reply[kRouteContext], context)
5252
t.equal(reply.request, request)
53+
// Aim to not bad property keys (including Symbols)
54+
t.notOk('undefined' in reply)
5355
})
5456

5557
test('reply.send will logStream error and destroy the stream', t => {

test/internals/request-validate.test.js

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
const { test } = require('tap')
44
const Ajv = require('ajv')
5-
const { kRequestValidateWeakMap, kRouteContext } = require('../../lib/symbols')
5+
const { kRequestCacheValidateFns, kRouteContext } = require('../../lib/symbols')
66
const Fastify = require('../../fastify')
77

88
const defaultSchema = {
@@ -231,11 +231,11 @@ test('#compileValidationSchema', subtest => {
231231
t.plan(5)
232232

233233
fastify.get('/', (req, reply) => {
234-
t.equal(req[kRouteContext][kRequestValidateWeakMap], null)
234+
t.equal(req[kRouteContext][kRequestCacheValidateFns], null)
235235
t.type(req.compileValidationSchema(defaultSchema), Function)
236-
t.type(req[kRouteContext][kRequestValidateWeakMap], WeakMap)
236+
t.type(req[kRouteContext][kRequestCacheValidateFns], WeakMap)
237237
t.type(req.compileValidationSchema(Object.assign({}, defaultSchema)), Function)
238-
t.type(req[kRouteContext][kRequestValidateWeakMap], WeakMap)
238+
t.type(req[kRouteContext][kRequestCacheValidateFns], WeakMap)
239239

240240
reply.send({ hello: 'world' })
241241
})
@@ -424,7 +424,7 @@ test('#getValidationFunction', subtest => {
424424
req.getValidationFunction(defaultSchema)
425425
req.getValidationFunction('body')
426426

427-
t.equal(req[kRouteContext][kRequestValidateWeakMap], null)
427+
t.equal(req[kRouteContext][kRequestCacheValidateFns], null)
428428
reply.send({ hello: 'world' })
429429
})
430430

@@ -724,9 +724,9 @@ test('#validate', subtest => {
724724
t.plan(3)
725725

726726
fastify.get('/', (req, reply) => {
727-
t.equal(req[kRouteContext][kRequestValidateWeakMap], null)
727+
t.equal(req[kRouteContext][kRequestCacheValidateFns], null)
728728
t.equal(req.validateInput({ hello: 'world' }, defaultSchema), true)
729-
t.type(req[kRouteContext][kRequestValidateWeakMap], WeakMap)
729+
t.type(req[kRouteContext][kRequestCacheValidateFns], WeakMap)
730730

731731
reply.send({ hello: 'world' })
732732
})

test/internals/request.test.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,8 @@ test('Regular request', t => {
6666
t.equal(request.routerMethod, context.config.method)
6767
t.equal(request.routeConfig, context[kPublicRouteContext].config)
6868
t.equal(request.routeSchema, context[kPublicRouteContext].schema)
69+
// Aim to not bad property keys (including Symbols)
70+
t.notOk('undefined' in request)
6971

7072
// This will be removed, it's deprecated
7173
t.equal(request.connection, req.connection)

0 commit comments

Comments
 (0)