Skip to content

Commit 7146587

Browse files
authored
perf: improve performance of isValidSubprotocol (#2861)
1 parent 1978601 commit 7146587

File tree

3 files changed

+68
-22
lines changed

3 files changed

+68
-22
lines changed
+17
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
import { bench, group, run } from 'mitata'
2+
import { isValidSubprotocol } from '../lib/web/websocket/util.js'
3+
4+
const valid = 'valid'
5+
const invalid = 'invalid '
6+
7+
group('isValidSubprotocol', () => {
8+
bench(`valid: ${valid}`, () => {
9+
return isValidSubprotocol(valid)
10+
})
11+
12+
bench(`invalid: ${invalid}`, () => {
13+
return isValidSubprotocol(invalid)
14+
})
15+
})
16+
17+
await run()

lib/web/websocket/util.js

+20-22
Original file line numberDiff line numberDiff line change
@@ -119,31 +119,29 @@ function isValidSubprotocol (protocol) {
119119
return false
120120
}
121121

122-
for (const char of protocol) {
123-
const code = char.charCodeAt(0)
122+
for (let i = 0; i < protocol.length; ++i) {
123+
const code = protocol.charCodeAt(i)
124124

125125
if (
126-
code < 0x21 ||
126+
code < 0x21 || // CTL, contains SP (0x20) and HT (0x09)
127127
code > 0x7E ||
128-
char === '(' ||
129-
char === ')' ||
130-
char === '<' ||
131-
char === '>' ||
132-
char === '@' ||
133-
char === ',' ||
134-
char === ';' ||
135-
char === ':' ||
136-
char === '\\' ||
137-
char === '"' ||
138-
char === '/' ||
139-
char === '[' ||
140-
char === ']' ||
141-
char === '?' ||
142-
char === '=' ||
143-
char === '{' ||
144-
char === '}' ||
145-
code === 32 || // SP
146-
code === 9 // HT
128+
code === 0x22 || // "
129+
code === 0x28 || // (
130+
code === 0x29 || // )
131+
code === 0x2C || // ,
132+
code === 0x2F || // /
133+
code === 0x3A || // :
134+
code === 0x3B || // ;
135+
code === 0x3C || // <
136+
code === 0x3D || // =
137+
code === 0x3E || // >
138+
code === 0x3F || // ?
139+
code === 0x40 || // @
140+
code === 0x5B || // [
141+
code === 0x5C || // \
142+
code === 0x5D || // ]
143+
code === 0x7B || // {
144+
code === 0x7D // }
147145
) {
148146
return false
149147
}

test/websocket/util.js

+31
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
'use strict'
2+
3+
const { tspl } = require('@matteo.collina/tspl')
4+
const { describe, test } = require('node:test')
5+
const { isValidSubprotocol } = require('../../lib/web/websocket/util')
6+
7+
describe('isValidSubprotocol', () => {
8+
test('empty string returns false', t => {
9+
t = tspl(t, { plan: 1 })
10+
t.strictEqual(isValidSubprotocol(''), false)
11+
})
12+
13+
test('simple valid value returns false', t => {
14+
t = tspl(t, { plan: 1 })
15+
t.strictEqual(isValidSubprotocol('chat'), true)
16+
})
17+
18+
test('empty string returns false', t => {
19+
t = tspl(t, { plan: 1 })
20+
t.strictEqual(isValidSubprotocol(''), false)
21+
})
22+
23+
test('value with "(),/:;<=>?@[\\]{} returns false', t => {
24+
const chars = '"(),/:;<=>?@[\\]{}'
25+
t = tspl(t, { plan: 17 })
26+
27+
for (let i = 0; i < chars.length; ++i) {
28+
t.strictEqual(isValidSubprotocol('valid' + chars[i]), false)
29+
}
30+
})
31+
})

0 commit comments

Comments
 (0)