Skip to content

Commit ad6b0c6

Browse files
authored
chore: remove zstd and markAsUncloneable feature probes (#4968)
1 parent a0291b9 commit ad6b0c6

8 files changed

Lines changed: 39 additions & 83 deletions

File tree

lib/interceptor/decompress.js

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@
33
const { createInflate, createGunzip, createBrotliDecompress, createZstdDecompress } = require('node:zlib')
44
const { pipeline } = require('node:stream')
55
const DecoratorHandler = require('../handler/decorator-handler')
6-
const { runtimeFeatures } = require('../util/runtime-features')
76

87
/** @typedef {import('node:stream').Transform} Transform */
98
/** @typedef {import('node:stream').Transform} Controller */
@@ -17,7 +16,7 @@ const supportedEncodings = {
1716
deflate: createInflate,
1817
compress: createInflate,
1918
'x-compress': createInflate,
20-
...(runtimeFeatures.has('zstd') ? { zstd: createZstdDecompress } : {})
19+
zstd: createZstdDecompress
2120
}
2221

2322
const defaultSkipStatusCodes = /** @type {const} */ ([204, 304])

lib/util/runtime-features.js

Lines changed: 3 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,7 @@
66
const lazyLoaders = {
77
__proto__: null,
88
'node:crypto': () => require('node:crypto'),
9-
'node:sqlite': () => require('node:sqlite'),
10-
'node:worker_threads': () => require('node:worker_threads'),
11-
'node:zlib': () => require('node:zlib')
9+
'node:sqlite': () => require('node:sqlite')
1210
}
1311

1412
/**
@@ -27,35 +25,9 @@ function detectRuntimeFeatureByNodeModule (moduleName) {
2725
}
2826
}
2927

30-
/**
31-
* @param {NodeModuleName} moduleName
32-
* @param {string} property
33-
* @returns {boolean}
34-
*/
35-
function detectRuntimeFeatureByExportedProperty (moduleName, property) {
36-
const module = lazyLoaders[moduleName]()
37-
return typeof module[property] !== 'undefined'
38-
}
39-
40-
const runtimeFeaturesByExportedProperty = /** @type {const} */ (['markAsUncloneable', 'zstd'])
41-
42-
/** @type {Record<RuntimeFeatureByExportedProperty, [NodeModuleName, string]>} */
43-
const exportedPropertyLookup = {
44-
markAsUncloneable: ['node:worker_threads', 'markAsUncloneable'],
45-
zstd: ['node:zlib', 'createZstdDecompress']
46-
}
47-
48-
/** @typedef {typeof runtimeFeaturesByExportedProperty[number]} RuntimeFeatureByExportedProperty */
49-
5028
const runtimeFeaturesAsNodeModule = /** @type {const} */ (['crypto', 'sqlite'])
5129
/** @typedef {typeof runtimeFeaturesAsNodeModule[number]} RuntimeFeatureByNodeModule */
52-
53-
const features = /** @type {const} */ ([
54-
...runtimeFeaturesAsNodeModule,
55-
...runtimeFeaturesByExportedProperty
56-
])
57-
58-
/** @typedef {typeof features[number]} Feature */
30+
/** @typedef {RuntimeFeatureByNodeModule} Feature */
5931

6032
/**
6133
* @param {Feature} feature
@@ -64,9 +36,6 @@ const features = /** @type {const} */ ([
6436
function detectRuntimeFeature (feature) {
6537
if (runtimeFeaturesAsNodeModule.includes(/** @type {RuntimeFeatureByNodeModule} */ (feature))) {
6638
return detectRuntimeFeatureByNodeModule(`node:${feature}`)
67-
} else if (runtimeFeaturesByExportedProperty.includes(/** @type {RuntimeFeatureByExportedProperty} */ (feature))) {
68-
const [moduleName, property] = exportedPropertyLookup[feature]
69-
return detectRuntimeFeatureByExportedProperty(moduleName, property)
7039
}
7140
throw new TypeError(`unknown feature: ${feature}`)
7241
}
@@ -101,7 +70,7 @@ class RuntimeFeatures {
10170
* @param {boolean} value
10271
*/
10372
set (feature, value) {
104-
if (features.includes(feature) === false) {
73+
if (runtimeFeaturesAsNodeModule.includes(feature) === false) {
10574
throw new TypeError(`unknown feature: ${feature}`)
10675
}
10776
this.#map.set(feature, value)

lib/web/fetch/index.js

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -65,10 +65,6 @@ const { webidl } = require('../webidl')
6565
const { STATUS_CODES } = require('node:http')
6666
const { bytesMatch } = require('../subresource-integrity/subresource-integrity')
6767
const { isomorphicEncode } = require('../infra')
68-
const { runtimeFeatures } = require('../../util/runtime-features')
69-
70-
// Node.js v23.8.0+ and v22.15.0+ supports Zstandard
71-
const hasZstd = runtimeFeatures.has('zstd')
7268

7369
const GET_OR_HEAD = ['GET', 'HEAD']
7470

@@ -2250,7 +2246,7 @@ async function httpNetworkFetch (
22502246
flush: zlib.constants.BROTLI_OPERATION_FLUSH,
22512247
finishFlush: zlib.constants.BROTLI_OPERATION_FLUSH
22522248
}))
2253-
} else if (coding === 'zstd' && hasZstd) {
2249+
} else if (coding === 'zstd') {
22542250
decoders.push(zlib.createZstdDecompress({
22552251
flush: zlib.constants.ZSTD_e_continue,
22562252
finishFlush: zlib.constants.ZSTD_e_end

lib/web/webidl/index.js

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

33
const assert = require('node:assert')
44
const { types, inspect } = require('node:util')
5-
const { runtimeFeatures } = require('../../util/runtime-features')
5+
const { markAsUncloneable } = require('node:worker_threads')
66

77
const UNDEFINED = 1
88
const BOOLEAN = 2
@@ -158,9 +158,7 @@ webidl.util.TypeValueToString = function (o) {
158158
}
159159
}
160160

161-
webidl.util.markAsUncloneable = runtimeFeatures.has('markAsUncloneable')
162-
? require('node:worker_threads').markAsUncloneable
163-
: () => {}
161+
webidl.util.markAsUncloneable = markAsUncloneable
164162

165163
// https://webidl.spec.whatwg.org/#abstract-opdef-converttoint
166164
webidl.util.ConvertToInt = function (V, bitLength, signedness, flags) {

test/fetch/encoding.js

Lines changed: 9 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -76,18 +76,16 @@ describe('content-encoding handling', () => {
7676
t.assert.strictEqual(await response.text(), 'Hello, World!')
7777
})
7878

79-
test('should decompress zstandard response',
80-
{ skip: typeof require('node:zlib').createZstdDecompress !== 'function' },
81-
async (t) => {
82-
const response = await fetch(`http://localhost:${server.address().port}`, {
83-
keepalive: false,
84-
headers: { 'accept-encoding': 'zstd' }
85-
})
86-
87-
t.assert.strictEqual(response.headers.get('content-encoding'), 'zstd')
88-
t.assert.strictEqual(response.headers.get('content-type'), 'text/plain')
89-
t.assert.strictEqual(await response.text(), 'Hello, World!')
79+
test('should decompress zstandard response', async (t) => {
80+
const response = await fetch(`http://localhost:${server.address().port}`, {
81+
keepalive: false,
82+
headers: { 'accept-encoding': 'zstd' }
9083
})
84+
85+
t.assert.strictEqual(response.headers.get('content-encoding'), 'zstd')
86+
t.assert.strictEqual(response.headers.get('content-type'), 'text/plain')
87+
t.assert.strictEqual(await response.text(), 'Hello, World!')
88+
})
9189
})
9290

9391
describe('content-encoding chain limit', () => {

test/interceptors/decompress.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -135,7 +135,7 @@ test('should decompress brotli response', async t => {
135135
await t.completed
136136
})
137137

138-
test('should decompress zstd response', { skip: typeof createZstdCompress !== 'function' }, async t => {
138+
test('should decompress zstd response', async t => {
139139
t = tspl(t, { plan: 3 })
140140

141141
const server = createServer({ joinDuplicateHeaders: true }, async (req, res) => {

test/node-platform-objects.js

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

33
const { tspl } = require('@matteo.collina/tspl')
44
const { test } = require('node:test')
5-
const { markAsUncloneable } = require('node:worker_threads')
65
const { Response, Request, FormData, Headers, ErrorEvent, MessageEvent, CloseEvent, EventSource, WebSocket } = require('..')
76
const { CacheStorage } = require('../lib/web/cache/cachestorage')
87
const { Cache } = require('../lib/web/cache/cache')
98
const { kConstruct } = require('../lib/core/symbols')
109

11-
test('unserializable web instances should be uncloneable if node exposes the api', (t) => {
12-
if (markAsUncloneable !== undefined) {
13-
t = tspl(t, { plan: 11 })
14-
const uncloneables = [
15-
{ Uncloneable: Response, brand: 'Response' },
16-
{ Uncloneable: Request, value: 'http://localhost', brand: 'Request' },
17-
{ Uncloneable: FormData, brand: 'FormData' },
18-
{ Uncloneable: MessageEvent, value: 'dummy event', brand: 'MessageEvent' },
19-
{ Uncloneable: CloseEvent, value: 'dummy event', brand: 'CloseEvent' },
20-
{ Uncloneable: ErrorEvent, value: 'dummy event', brand: 'ErrorEvent' },
21-
{ Uncloneable: EventSource, value: 'http://localhost', brand: 'EventSource', doneCb: (entity) => entity.close() },
22-
{ Uncloneable: Headers, brand: 'Headers' },
23-
{ Uncloneable: WebSocket, value: 'http://localhost', brand: 'WebSocket' },
24-
{ Uncloneable: Cache, value: kConstruct, brand: 'Cache' },
25-
{ Uncloneable: CacheStorage, value: kConstruct, brand: 'CacheStorage' }
26-
]
27-
uncloneables.forEach((platformEntity) => {
28-
const entity = new platformEntity.Uncloneable(platformEntity.value)
29-
t.throws(() => structuredClone(entity),
30-
DOMException,
31-
`Cloning ${platformEntity.brand} should throw DOMException`)
10+
test('unserializable web instances should be uncloneable', (t) => {
11+
t = tspl(t, { plan: 11 })
12+
const uncloneables = [
13+
{ Uncloneable: Response, brand: 'Response' },
14+
{ Uncloneable: Request, value: 'http://localhost', brand: 'Request' },
15+
{ Uncloneable: FormData, brand: 'FormData' },
16+
{ Uncloneable: MessageEvent, value: 'dummy event', brand: 'MessageEvent' },
17+
{ Uncloneable: CloseEvent, value: 'dummy event', brand: 'CloseEvent' },
18+
{ Uncloneable: ErrorEvent, value: 'dummy event', brand: 'ErrorEvent' },
19+
{ Uncloneable: EventSource, value: 'http://localhost', brand: 'EventSource', doneCb: (entity) => entity.close() },
20+
{ Uncloneable: Headers, brand: 'Headers' },
21+
{ Uncloneable: WebSocket, value: 'http://localhost', brand: 'WebSocket' },
22+
{ Uncloneable: Cache, value: kConstruct, brand: 'Cache' },
23+
{ Uncloneable: CacheStorage, value: kConstruct, brand: 'CacheStorage' }
24+
]
25+
uncloneables.forEach((platformEntity) => {
26+
const entity = new platformEntity.Uncloneable(platformEntity.value)
27+
t.throws(() => structuredClone(entity),
28+
DOMException,
29+
`Cloning ${platformEntity.brand} should throw DOMException`)
3230

33-
platformEntity.doneCb?.(entity)
34-
})
35-
}
31+
platformEntity.doneCb?.(entity)
32+
})
3633
})

types/webidl.d.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,6 @@ interface WebidlUtil {
8787

8888
/**
8989
* Mark a value as uncloneable for Node.js.
90-
* This is only effective in some newer Node.js versions.
9190
*/
9291
markAsUncloneable (V: any): void
9392

0 commit comments

Comments
 (0)