From 0ebf3a740b416de4525401ede840b874d33a7323 Mon Sep 17 00:00:00 2001 From: uzlopak Date: Wed, 30 Nov 2022 12:58:02 +0100 Subject: [PATCH 1/9] Use Set instead of Map --- index.js | 7 +++---- test/emit-interpolated-string.test.js | 2 +- test/emit-once-only.test.js | 2 +- test/jest.test.js | 2 +- 4 files changed, 6 insertions(+), 7 deletions(-) diff --git a/index.js b/index.js index d0f0b6b..34e35d7 100644 --- a/index.js +++ b/index.js @@ -4,7 +4,7 @@ const { format } = require('util') function build () { const codes = {} - const emitted = new Map() + const emitted = new Set() function create (name, code, message) { if (!name) throw new Error('Warning name must not be empty') @@ -37,7 +37,6 @@ function build () { } } - emitted.set(code, false) codes[code] = buildWarnOpts return codes[code] @@ -45,8 +44,8 @@ function build () { function emit (code, a, b, c) { if (codes[code] === undefined) throw new Error(`The code '${code}' does not exist`) - if (emitted.get(code) === true) return - emitted.set(code, true) + if (emitted.has(code)) return + emitted.add(code) const warning = codes[code](a, b, c) process.emitWarning(warning.message, warning.name, warning.code) diff --git a/test/emit-interpolated-string.test.js b/test/emit-interpolated-string.test.js index c282a3c..88956f7 100644 --- a/test/emit-interpolated-string.test.js +++ b/test/emit-interpolated-string.test.js @@ -12,7 +12,7 @@ test('emit with interpolated string', t => { t.equal(warning.name, 'FastifyDeprecation') t.equal(warning.code, 'CODE') t.equal(warning.message, 'Hello world') - t.ok(emitted.get('CODE')) + t.ok(emitted.has('CODE')) } create('FastifyDeprecation', 'CODE', 'Hello %s') diff --git a/test/emit-once-only.test.js b/test/emit-once-only.test.js index e1d8a30..ec74cd9 100644 --- a/test/emit-once-only.test.js +++ b/test/emit-once-only.test.js @@ -13,7 +13,7 @@ test('emit should emit a given code only once', t => { t.equal(warning.name, 'FastifyDeprecation') t.equal(warning.code, 'CODE') t.equal(warning.message, 'Hello world') - t.ok(emitted.get('CODE')) + t.ok(emitted.has('CODE')) } create('FastifyDeprecation', 'CODE', 'Hello world') diff --git a/test/jest.test.js b/test/jest.test.js index b02660d..135afea 100644 --- a/test/jest.test.js +++ b/test/jest.test.js @@ -14,7 +14,7 @@ test('works with jest', done => { // we can only test it was emitted indirectly // and test no exception is raised setImmediate(() => { - expect(emitted.get('CODE')).toBeTruthy() + expect(emitted.has('CODE')).toBeTruthy() done() }) }) From be64b6db9d72a2934e6ae673e4596d181892ea38 Mon Sep 17 00:00:00 2001 From: uzlopak Date: Wed, 30 Nov 2022 15:13:31 +0100 Subject: [PATCH 2/9] replace codes-Object with Map delete warning after emitting --- index.js | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/index.js b/index.js index 34e35d7..6b02c29 100644 --- a/index.js +++ b/index.js @@ -3,7 +3,7 @@ const { format } = require('util') function build () { - const codes = {} + const codes = new Map() const emitted = new Set() function create (name, code, message) { @@ -13,7 +13,7 @@ function build () { code = code.toUpperCase() - if (codes[code] !== undefined) { + if (codes.has(code) || emitted.has(code)) { throw new Error(`The code '${code}' already exist`) } @@ -37,18 +37,23 @@ function build () { } } - codes[code] = buildWarnOpts + codes.set(code, buildWarnOpts) - return codes[code] + return buildWarnOpts } function emit (code, a, b, c) { - if (codes[code] === undefined) throw new Error(`The code '${code}' does not exist`) - if (emitted.has(code)) return + if (emitted.has(code)) { + return + } + if (codes.has(code) === false) { + throw new Error(`The code '${code}' does not exist`) + } emitted.add(code) - const warning = codes[code](a, b, c) + const warning = codes.get(code)(a, b, c) process.emitWarning(warning.message, warning.name, warning.code) + codes.delete(code) } return { From 5c05266cfa9c7f75103336b4c42b354f421916a9 Mon Sep 17 00:00:00 2001 From: uzlopak Date: Wed, 30 Nov 2022 15:16:56 +0100 Subject: [PATCH 3/9] fix typings --- types/index.d.ts | 2 +- types/index.test-d.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/types/index.d.ts b/types/index.d.ts index c4eb9b0..791f730 100644 --- a/types/index.d.ts +++ b/types/index.d.ts @@ -11,7 +11,7 @@ export type BuildWarnOptsFn = (a?: any, b?: any, c?: any) => WarnOpts interface Warning { create(name: string, code: string, message: string): BuildWarnOptsFn, emit(cod: string, a?: any, b?: any, c?: any): void, - emitted: Map + emitted: Set } export default warning diff --git a/types/index.test-d.ts b/types/index.test-d.ts index a225b5c..64d298b 100644 --- a/types/index.test-d.ts +++ b/types/index.test-d.ts @@ -11,4 +11,4 @@ expectType(opts.message) expectType(opts.name) expectType(warning.emit('CODE')) -expectType>(warning.emitted) +expectType>(warning.emitted) From 3dcb605439fb0f17355ddce66a4af1dc4411be33 Mon Sep 17 00:00:00 2001 From: uzlopak Date: Wed, 30 Nov 2022 15:20:02 +0100 Subject: [PATCH 4/9] fix readme --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 3c7aade..40641a4 100644 --- a/README.md +++ b/README.md @@ -55,13 +55,13 @@ warning.create('FastifyWarning', 'FST_ERROR_CODE', 'Hello %s') warning.emit('FST_ERROR_CODE', 'world') ``` -The module also exports an `warning.emitted` [Map](https://developer.mozilla.org/it/docs/Web/JavaScript/Reference/Global_Objects/Map), which contains all the warnings already emitted. Useful for testing. +The module also exports an `warning.emitted` [Set](https://developer.mozilla.org/it/docs/Web/JavaScript/Reference/Global_Objects/Set), which contains all the warnings already emitted. Useful for testing. ```js const warning = require('process-warning')() warning.create('FastifyWarning', 'FST_ERROR_CODE', 'Hello %s') -console.log(warning.emitted.get('FST_ERROR_CODE')) // false +console.log(warning.emitted.has('FST_ERROR_CODE')) // false warning.emit('FST_ERROR_CODE', 'world') -console.log(warning.emitted.get('FST_ERROR_CODE')) // true +console.log(warning.emitted.has('FST_ERROR_CODE')) // true ``` ## License From b2854f1882956b090ed5a88c69f91f454cc746f2 Mon Sep 17 00:00:00 2001 From: uzlopak Date: Thu, 1 Dec 2022 20:15:40 +0100 Subject: [PATCH 5/9] use classic objects for faster property lookup --- README.md | 6 +++--- benchmark/benchmark.js | 16 ++++++++++++++++ index.js | 17 ++++++++--------- package.json | 2 ++ test/emit-interpolated-string.test.js | 2 +- test/emit-once-only.test.js | 2 +- test/jest.test.js | 2 +- types/index.d.ts | 2 +- types/index.test-d.ts | 2 +- 9 files changed, 34 insertions(+), 17 deletions(-) create mode 100644 benchmark/benchmark.js diff --git a/README.md b/README.md index 40641a4..d387714 100644 --- a/README.md +++ b/README.md @@ -55,13 +55,13 @@ warning.create('FastifyWarning', 'FST_ERROR_CODE', 'Hello %s') warning.emit('FST_ERROR_CODE', 'world') ``` -The module also exports an `warning.emitted` [Set](https://developer.mozilla.org/it/docs/Web/JavaScript/Reference/Global_Objects/Set), which contains all the warnings already emitted. Useful for testing. +The module also exports an `warning.emitted` Object, which contains all the warnings already emitted. Useful for testing. ```js const warning = require('process-warning')() warning.create('FastifyWarning', 'FST_ERROR_CODE', 'Hello %s') -console.log(warning.emitted.has('FST_ERROR_CODE')) // false +console.log(warning.emitted.FST_ERROR_CODE) // false warning.emit('FST_ERROR_CODE', 'world') -console.log(warning.emitted.has('FST_ERROR_CODE')) // true +console.log(warning.emitted.FST_ERROR_CODE) // true ``` ## License diff --git a/benchmark/benchmark.js b/benchmark/benchmark.js new file mode 100644 index 0000000..ba8d685 --- /dev/null +++ b/benchmark/benchmark.js @@ -0,0 +1,16 @@ +'use strict' + +const { Suite } = require('benchmark') +const warning = require('..')() + +warning.create('FastifyWarning', 'FST_ERROR_CODE', 'message') +new Suite() + .add('warn', function () { + warning.emit('FST_ERROR_CODE') + }) + // add listeners + .on('cycle', function (event) { + console.log(String(event.target)); + }) + // run async + .run(); \ No newline at end of file diff --git a/index.js b/index.js index 6b02c29..3bf7ab2 100644 --- a/index.js +++ b/index.js @@ -3,8 +3,8 @@ const { format } = require('util') function build () { - const codes = new Map() - const emitted = new Set() + const codes = {} + const emitted = {} function create (name, code, message) { if (!name) throw new Error('Warning name must not be empty') @@ -13,7 +13,7 @@ function build () { code = code.toUpperCase() - if (codes.has(code) || emitted.has(code)) { + if (codes[code] !== undefined) { throw new Error(`The code '${code}' already exist`) } @@ -37,23 +37,22 @@ function build () { } } - codes.set(code, buildWarnOpts) + codes[code] = buildWarnOpts return buildWarnOpts } function emit (code, a, b, c) { - if (emitted.has(code)) { + if (emitted[code] === true) { return } - if (codes.has(code) === false) { + if (codes[code] === undefined) { throw new Error(`The code '${code}' does not exist`) } - emitted.add(code) + emitted[code] = true - const warning = codes.get(code)(a, b, c) + const warning = codes[code](a, b, c) process.emitWarning(warning.message, warning.name, warning.code) - codes.delete(code) } return { diff --git a/package.json b/package.json index 0e922b4..76582dc 100644 --- a/package.json +++ b/package.json @@ -5,6 +5,7 @@ "main": "index.js", "types": "types/index.d.ts", "scripts": { + "benchmark": "node benchmark/benchmark.js", "lint": "standard", "test": "npm run test:unit && npm run test:jest && npm run test:typescript", "test:jest": "jest jest.test.js", @@ -31,6 +32,7 @@ }, "homepage": "https://github.com/fastify/fastify-warning#readme", "devDependencies": { + "benchmark": "^2.1.4", "jest": "^29.0.1", "standard": "^17.0.0", "tap": "^16.3.0", diff --git a/test/emit-interpolated-string.test.js b/test/emit-interpolated-string.test.js index 88956f7..7ef9c52 100644 --- a/test/emit-interpolated-string.test.js +++ b/test/emit-interpolated-string.test.js @@ -12,7 +12,7 @@ test('emit with interpolated string', t => { t.equal(warning.name, 'FastifyDeprecation') t.equal(warning.code, 'CODE') t.equal(warning.message, 'Hello world') - t.ok(emitted.has('CODE')) + t.ok(emitted.CODE) } create('FastifyDeprecation', 'CODE', 'Hello %s') diff --git a/test/emit-once-only.test.js b/test/emit-once-only.test.js index ec74cd9..5f0ca74 100644 --- a/test/emit-once-only.test.js +++ b/test/emit-once-only.test.js @@ -13,7 +13,7 @@ test('emit should emit a given code only once', t => { t.equal(warning.name, 'FastifyDeprecation') t.equal(warning.code, 'CODE') t.equal(warning.message, 'Hello world') - t.ok(emitted.has('CODE')) + t.ok(emitted.CODE) } create('FastifyDeprecation', 'CODE', 'Hello world') diff --git a/test/jest.test.js b/test/jest.test.js index 135afea..09ad800 100644 --- a/test/jest.test.js +++ b/test/jest.test.js @@ -14,7 +14,7 @@ test('works with jest', done => { // we can only test it was emitted indirectly // and test no exception is raised setImmediate(() => { - expect(emitted.has('CODE')).toBeTruthy() + expect(emitted.CODE).toBeTruthy() done() }) }) diff --git a/types/index.d.ts b/types/index.d.ts index 791f730..536bc09 100644 --- a/types/index.d.ts +++ b/types/index.d.ts @@ -11,7 +11,7 @@ export type BuildWarnOptsFn = (a?: any, b?: any, c?: any) => WarnOpts interface Warning { create(name: string, code: string, message: string): BuildWarnOptsFn, emit(cod: string, a?: any, b?: any, c?: any): void, - emitted: Set + emitted: { [key: string]: boolean } } export default warning diff --git a/types/index.test-d.ts b/types/index.test-d.ts index 64d298b..1bedbed 100644 --- a/types/index.test-d.ts +++ b/types/index.test-d.ts @@ -11,4 +11,4 @@ expectType(opts.message) expectType(opts.name) expectType(warning.emit('CODE')) -expectType>(warning.emitted) +expectType<{ [key: string]: boolean }>(warning.emitted) From 6f4d881c8afe83f7ee0653e779b0d8879ad5f518 Mon Sep 17 00:00:00 2001 From: uzlopak Date: Thu, 1 Dec 2022 20:16:53 +0100 Subject: [PATCH 6/9] fix lint --- benchmark/benchmark.js | 4 ++-- index.js | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/benchmark/benchmark.js b/benchmark/benchmark.js index ba8d685..63d5c0e 100644 --- a/benchmark/benchmark.js +++ b/benchmark/benchmark.js @@ -10,7 +10,7 @@ new Suite() }) // add listeners .on('cycle', function (event) { - console.log(String(event.target)); + console.log(String(event.target)) }) // run async - .run(); \ No newline at end of file + .run() diff --git a/index.js b/index.js index 3bf7ab2..0779f6a 100644 --- a/index.js +++ b/index.js @@ -46,7 +46,7 @@ function build () { if (emitted[code] === true) { return } - if (codes[code] === undefined) { + if (codes[code] === undefined) { throw new Error(`The code '${code}' does not exist`) } emitted[code] = true From a0a7ba38948cc92c0c8eff39149222b8f85b0f38 Mon Sep 17 00:00:00 2001 From: uzlopak Date: Thu, 1 Dec 2022 20:38:11 +0100 Subject: [PATCH 7/9] reduce delta --- index.js | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/index.js b/index.js index 0779f6a..c0cb844 100644 --- a/index.js +++ b/index.js @@ -39,16 +39,12 @@ function build () { codes[code] = buildWarnOpts - return buildWarnOpts + return codes[code] } function emit (code, a, b, c) { - if (emitted[code] === true) { - return - } - if (codes[code] === undefined) { - throw new Error(`The code '${code}' does not exist`) - } + if (emitted[code] === true) return + if (codes[code] === undefined) throw new Error(`The code '${code}' does not exist`) emitted[code] = true const warning = codes[code](a, b, c) From 8146da4ce66a6de64baa479a2d7ee9ffbbc5ab02 Mon Sep 17 00:00:00 2001 From: uzlopak Date: Thu, 1 Dec 2022 20:56:29 +0100 Subject: [PATCH 8/9] use in operator instead of checking the value better benchmark --- benchmark/benchmark.js | 7 +++++-- index.js | 3 +-- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/benchmark/benchmark.js b/benchmark/benchmark.js index 63d5c0e..34967b9 100644 --- a/benchmark/benchmark.js +++ b/benchmark/benchmark.js @@ -3,10 +3,13 @@ const { Suite } = require('benchmark') const warning = require('..')() -warning.create('FastifyWarning', 'FST_ERROR_CODE', 'message') +warning.create('FastifyWarning', 'FST_ERROR_CODE_1', 'message') +warning.create('FastifyWarning', 'FST_ERROR_CODE_2', 'message') +warning.create('FastifyWarning', 'FST_ERROR_CODE_3', 'message') new Suite() .add('warn', function () { - warning.emit('FST_ERROR_CODE') + warning.emit('FST_ERROR_CODE_1') + warning.emit('FST_ERROR_CODE_3') }) // add listeners .on('cycle', function (event) { diff --git a/index.js b/index.js index c0cb844..a4a9e44 100644 --- a/index.js +++ b/index.js @@ -38,12 +38,11 @@ function build () { } codes[code] = buildWarnOpts - return codes[code] } function emit (code, a, b, c) { - if (emitted[code] === true) return + if (code in emitted) return if (codes[code] === undefined) throw new Error(`The code '${code}' does not exist`) emitted[code] = true From 4689628a4b26bd95ab4c6b03aaa04efa2cdc4da2 Mon Sep 17 00:00:00 2001 From: uzlopak Date: Thu, 1 Dec 2022 21:01:25 +0100 Subject: [PATCH 9/9] better check for value, faster on node18 --- index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/index.js b/index.js index a4a9e44..97ca465 100644 --- a/index.js +++ b/index.js @@ -42,7 +42,7 @@ function build () { } function emit (code, a, b, c) { - if (code in emitted) return + if (emitted[code] === true) return if (codes[code] === undefined) throw new Error(`The code '${code}' does not exist`) emitted[code] = true