@blamejs/blamejs-shop 0.4.100 → 0.4.102
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +4 -0
- package/lib/asset-manifest.json +1 -1
- package/lib/cart-bulk-ops.js +7 -1
- package/lib/vendor/MANIFEST.json +55 -51
- package/lib/vendor/blamejs/.gitignore +5 -0
- package/lib/vendor/blamejs/CHANGELOG.md +4 -0
- package/lib/vendor/blamejs/api-snapshot.json +2 -2
- package/lib/vendor/blamejs/lib/sandbox.js +23 -5
- package/lib/vendor/blamejs/package.json +1 -1
- package/lib/vendor/blamejs/release-notes/v0.15.25.json +18 -0
- package/lib/vendor/blamejs/release-notes/v0.15.26.json +18 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/ai-adverse-decision.test.js +5 -2
- package/lib/vendor/blamejs/test/layer-0-primitives/atomic-file-open-nofollow.test.js +7 -2
- package/lib/vendor/blamejs/test/layer-0-primitives/azure-blob-bucket-ops.test.js +30 -10
- package/lib/vendor/blamejs/test/layer-0-primitives/azure-blob-key-encoding.test.js +21 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/bearer-auth.test.js +22 -17
- package/lib/vendor/blamejs/test/layer-0-primitives/body-parser-chunked-malformed.test.js +23 -18
- package/lib/vendor/blamejs/test/layer-0-primitives/breach-deadline.test.js +8 -3
- package/lib/vendor/blamejs/test/layer-0-primitives/ciba-authreqid-binding.test.js +22 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/codebase-patterns.test.js +50 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/compliance-sanctions.test.js +13 -5
- package/lib/vendor/blamejs/test/layer-0-primitives/cra-report.test.js +5 -2
- package/lib/vendor/blamejs/test/layer-0-primitives/daily-byte-quota.test.js +20 -9
- package/lib/vendor/blamejs/test/layer-0-primitives/dsr.test.js +8 -2
- package/lib/vendor/blamejs/test/layer-0-primitives/fido-mds3.test.js +34 -15
- package/lib/vendor/blamejs/test/layer-0-primitives/gcs-bucket-ops.test.js +30 -9
- package/lib/vendor/blamejs/test/layer-0-primitives/guard-csv.test.js +15 -3
- package/lib/vendor/blamejs/test/layer-0-primitives/http-client-cache.test.js +41 -18
- package/lib/vendor/blamejs/test/layer-0-primitives/http-client-stream.test.js +33 -14
- package/lib/vendor/blamejs/test/layer-0-primitives/http-client-throttle-transform.test.js +21 -2
- package/lib/vendor/blamejs/test/layer-0-primitives/incident-report.test.js +5 -2
- package/lib/vendor/blamejs/test/layer-0-primitives/log-stream-otlp.test.js +29 -8
- package/lib/vendor/blamejs/test/layer-0-primitives/mail-server-imap.test.js +42 -23
- package/lib/vendor/blamejs/test/layer-0-primitives/network-byte-quota.test.js +5 -2
- package/lib/vendor/blamejs/test/layer-0-primitives/network-dns.test.js +20 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/network-nts-handshake-byte-cap.test.js +20 -1
- package/lib/vendor/blamejs/test/layer-0-primitives/nis2-report.test.js +5 -2
- package/lib/vendor/blamejs/test/layer-0-primitives/oauth-callback.test.js +22 -1
- package/lib/vendor/blamejs/test/layer-0-primitives/observability-tracing.test.js +8 -2
- package/lib/vendor/blamejs/test/layer-0-primitives/parser-verify-hardening.test.js +21 -16
- package/lib/vendor/blamejs/test/layer-0-primitives/parsers-standalone.test.js +5 -2
- package/lib/vendor/blamejs/test/layer-0-primitives/queue-sqs.test.js +31 -11
- package/lib/vendor/blamejs/test/layer-0-primitives/request-id-async-context.test.js +21 -4
- package/lib/vendor/blamejs/test/layer-0-primitives/sandbox.test.js +35 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/sd-jwt-vc.test.js +5 -2
- package/lib/vendor/blamejs/test/layer-0-primitives/self-update-poll-asset-digest.test.js +21 -2
- package/lib/vendor/blamejs/test/layer-0-primitives/self-update.test.js +29 -10
- package/lib/vendor/blamejs/test/layer-0-primitives/sigv4-bucket-ops.test.js +51 -33
- package/lib/vendor/blamejs/test/layer-0-primitives/sigv4-multipart-sse.test.js +31 -13
- package/lib/vendor/blamejs/test/layer-0-primitives/static.test.js +41 -21
- package/lib/vendor/blamejs/test/layer-0-primitives/testing-request.test.js +25 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/tls-exporter.test.js +30 -6
- package/lib/vendor/blamejs/test/layer-0-primitives/webhook.test.js +22 -0
- package/lib/vendor/blamejs/test/layer-0-primitives/worker-pool-recycle-race.test.js +10 -6
- package/lib/vendor/blamejs/test/layer-0-primitives/ws-client.test.js +91 -20
- package/package.json +1 -1
|
@@ -103,11 +103,28 @@ async function testConcurrentRequestsIsolated() {
|
|
|
103
103
|
check("concurrent: every response header matches its request", hdrsMatch);
|
|
104
104
|
}
|
|
105
105
|
|
|
106
|
+
// Each fixture http.Server is .close()'d, but the listening handle finalizes on
|
|
107
|
+
// a later event-loop turn — past the forked worker's post-run grace window.
|
|
108
|
+
// Poll process.getActiveResourcesInfo until no TCP handle remains; polling
|
|
109
|
+
// drives the real event-loop turns that complete the close inside run().
|
|
110
|
+
async function _drainTcpHandles() {
|
|
111
|
+
if (typeof process.getActiveResourcesInfo !== "function") return;
|
|
112
|
+
await helpers.waitUntil(function () {
|
|
113
|
+
return process.getActiveResourcesInfo().filter(function (t) {
|
|
114
|
+
return t === "TCPSocketWrap" || t === "TCPServerWrap";
|
|
115
|
+
}).length === 0;
|
|
116
|
+
}, { timeoutMs: 5000, label: "request-id-async-context: TCP handle drain" });
|
|
117
|
+
}
|
|
118
|
+
|
|
106
119
|
async function run() {
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
120
|
+
try {
|
|
121
|
+
testSurface();
|
|
122
|
+
await testAsyncContextBindsAls();
|
|
123
|
+
await testDefaultModeDoesNotBindAls();
|
|
124
|
+
await testConcurrentRequestsIsolated();
|
|
125
|
+
} finally {
|
|
126
|
+
await _drainTcpHandles();
|
|
127
|
+
}
|
|
111
128
|
}
|
|
112
129
|
|
|
113
130
|
module.exports = { run: run };
|
|
@@ -240,9 +240,44 @@ async function testByteCapMultibyte() {
|
|
|
240
240
|
t2 && t2.code === "sandbox/oversized-result");
|
|
241
241
|
}
|
|
242
242
|
|
|
243
|
+
async function testWorkerHandleReleased() {
|
|
244
|
+
// b.sandbox.run spawns a worker thread and calls worker.terminate() — which
|
|
245
|
+
// is asynchronous — on the result/timeout paths. It must await that
|
|
246
|
+
// termination before settling the caller's promise, otherwise the worker's
|
|
247
|
+
// MessagePort stays alive past the resolve and a long-lived process running
|
|
248
|
+
// sandboxed code repeatedly accumulates leaked MessagePort handles. The
|
|
249
|
+
// timeout path is the widest leak window (the worker is spinning and
|
|
250
|
+
// forcibly terminated, so terminate() takes longest); drive it repeatedly
|
|
251
|
+
// and assert no MessagePort is left active. RED before the fix (the reject
|
|
252
|
+
// raced ahead of the async terminate, leaving the busy worker's port alive).
|
|
253
|
+
function _ports() {
|
|
254
|
+
return process.getActiveResourcesInfo().filter(function (r) { return r === "MessagePort"; }).length;
|
|
255
|
+
}
|
|
256
|
+
var before = _ports();
|
|
257
|
+
// Drive several spinning workers CONCURRENTLY so that, if terminate() is not
|
|
258
|
+
// awaited, all their MessagePorts are mid-close at the instant Promise.all
|
|
259
|
+
// settles — amplifying the leak from one racy handle into N simultaneously
|
|
260
|
+
// open ones, which the synchronous count below catches deterministically.
|
|
261
|
+
var N = 8;
|
|
262
|
+
var runs = [];
|
|
263
|
+
for (var i = 0; i < N; i += 1) {
|
|
264
|
+
runs.push(b.sandbox.run({ source: "while (true) {}", timeoutMs: 150 }).then(
|
|
265
|
+
function () { return "resolved"; },
|
|
266
|
+
function (e) { return e && e.code; }));
|
|
267
|
+
}
|
|
268
|
+
var outcomes = await Promise.all(runs);
|
|
269
|
+
check("all spinning sandbox.run calls time out",
|
|
270
|
+
outcomes.length === N && outcomes.every(function (o) { return o === "sandbox/timeout"; }));
|
|
271
|
+
// The fix awaits worker.terminate() before settling, so every port is closed
|
|
272
|
+
// by the time its promise resolves; with the bug, N ports linger here.
|
|
273
|
+
check("sandbox.run releases the worker MessagePort after timeout-terminate (no handle leak)",
|
|
274
|
+
_ports() <= before);
|
|
275
|
+
}
|
|
276
|
+
|
|
243
277
|
async function run() {
|
|
244
278
|
await testByteCapMultibyte();
|
|
245
279
|
testErrorClassExposed();
|
|
280
|
+
await testWorkerHandleReleased();
|
|
246
281
|
await testHappyPath();
|
|
247
282
|
await testAllowedBuiltins();
|
|
248
283
|
await testBadAllowedRejected();
|
|
@@ -813,7 +813,7 @@ function testExports() {
|
|
|
813
813
|
|
|
814
814
|
// ---- Run all ----
|
|
815
815
|
|
|
816
|
-
|
|
816
|
+
async function run() {
|
|
817
817
|
testDisclosureEncodeDecode();
|
|
818
818
|
testDisclosureValueComplexShape();
|
|
819
819
|
testDisclosureBadInput();
|
|
@@ -847,4 +847,7 @@ function testExports() {
|
|
|
847
847
|
await testHolderAlgFromKeyType();
|
|
848
848
|
await testKbAlgKtyCrossCheck();
|
|
849
849
|
testExports();
|
|
850
|
-
}
|
|
850
|
+
}
|
|
851
|
+
|
|
852
|
+
module.exports = { run: run };
|
|
853
|
+
if (require.main === module) run().catch(function (e) { console.error(e); process.exit(1); });
|
|
@@ -75,9 +75,28 @@ async function testPollDigestNullWhenAbsent() {
|
|
|
75
75
|
} finally { server.close(); }
|
|
76
76
|
}
|
|
77
77
|
|
|
78
|
+
// selfUpdate.poll dials the releases endpoint through the shared httpClient
|
|
79
|
+
// keep-alive transport pool; a cached client socket finalizes its destroy on a
|
|
80
|
+
// later event-loop turn, past the forked worker's grace window. Reset the pool,
|
|
81
|
+
// then poll until every TCP handle (client sockets + the fixture server's
|
|
82
|
+
// accept socket) has actually drained so none outlives run().
|
|
83
|
+
async function _drainTcpHandles() {
|
|
84
|
+
b.httpClient._resetForTest();
|
|
85
|
+
if (typeof process.getActiveResourcesInfo !== "function") return;
|
|
86
|
+
await helpers.waitUntil(function () {
|
|
87
|
+
return process.getActiveResourcesInfo().filter(function (t) {
|
|
88
|
+
return t === "TCPSocketWrap" || t === "TCPServerWrap";
|
|
89
|
+
}).length === 0;
|
|
90
|
+
}, { timeoutMs: 5000, label: "self-update-poll-asset-digest: TCP handle drain after _resetForTest" });
|
|
91
|
+
}
|
|
92
|
+
|
|
78
93
|
async function run() {
|
|
79
|
-
|
|
80
|
-
|
|
94
|
+
try {
|
|
95
|
+
await testPollExposesAssetDigest();
|
|
96
|
+
await testPollDigestNullWhenAbsent();
|
|
97
|
+
} finally {
|
|
98
|
+
await _drainTcpHandles();
|
|
99
|
+
}
|
|
81
100
|
}
|
|
82
101
|
|
|
83
102
|
module.exports = { run: run };
|
|
@@ -280,17 +280,36 @@ async function testRollbackMissingBackupRefused() {
|
|
|
280
280
|
try { fs.rmdirSync(dir); } catch (_e) { /* best-effort */ }
|
|
281
281
|
}
|
|
282
282
|
|
|
283
|
+
// selfUpdate.poll dials the releases endpoint through the shared httpClient
|
|
284
|
+
// keep-alive transport pool; a cached client socket finalizes its destroy on a
|
|
285
|
+
// later event-loop turn, past the forked worker's grace window. Reset the pool,
|
|
286
|
+
// then poll until every TCP handle (client sockets + any fixture-server accept
|
|
287
|
+
// socket) has actually drained so none outlives run().
|
|
288
|
+
async function _drainTcpHandles() {
|
|
289
|
+
b.httpClient._resetForTest();
|
|
290
|
+
if (typeof process.getActiveResourcesInfo !== "function") return;
|
|
291
|
+
await helpers.waitUntil(function () {
|
|
292
|
+
return process.getActiveResourcesInfo().filter(function (t) {
|
|
293
|
+
return t === "TCPSocketWrap" || t === "TCPServerWrap";
|
|
294
|
+
}).length === 0;
|
|
295
|
+
}, { timeoutMs: 5000, label: "self-update: TCP handle drain after _resetForTest" });
|
|
296
|
+
}
|
|
297
|
+
|
|
283
298
|
async function run() {
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
299
|
+
try {
|
|
300
|
+
testSurface();
|
|
301
|
+
testCompareTags();
|
|
302
|
+
await testPollRejectsBadOpts();
|
|
303
|
+
await testPollAvailableAndUpToDate();
|
|
304
|
+
await testPollArrayShape();
|
|
305
|
+
await testPollNon2xxRefused();
|
|
306
|
+
await testVerifyPassFail();
|
|
307
|
+
await testSwapAndRollback();
|
|
308
|
+
await testSwapMissingFromRefused();
|
|
309
|
+
await testRollbackMissingBackupRefused();
|
|
310
|
+
} finally {
|
|
311
|
+
await _drainTcpHandles();
|
|
312
|
+
}
|
|
294
313
|
}
|
|
295
314
|
|
|
296
315
|
module.exports = { run: run };
|
|
@@ -1017,40 +1017,58 @@ function testCanonicalPathSingleEncodeForS3() {
|
|
|
1017
1017
|
sigv4.awsUriEncode("photo-\u{1F600}.jpg", true) === "photo-%F0%9F%98%80.jpg");
|
|
1018
1018
|
}
|
|
1019
1019
|
|
|
1020
|
+
// bucketOps dispatches every request through the shared httpClient keep-alive
|
|
1021
|
+
// transport pool; a cached client socket finalizes its destroy on a later
|
|
1022
|
+
// event-loop turn, past the forked worker's grace window. Reset the pool, then
|
|
1023
|
+
// poll until every TCP handle has actually drained so none outlives run().
|
|
1024
|
+
async function _drainTcpHandles() {
|
|
1025
|
+
b.httpClient._resetForTest();
|
|
1026
|
+
if (typeof process.getActiveResourcesInfo !== "function") return;
|
|
1027
|
+
await helpers.waitUntil(function () {
|
|
1028
|
+
return process.getActiveResourcesInfo().filter(function (t) {
|
|
1029
|
+
return t === "TCPSocketWrap" || t === "TCPServerWrap";
|
|
1030
|
+
}).length === 0;
|
|
1031
|
+
}, { timeoutMs: 5000, label: "sigv4-bucket-ops: TCP handle drain after _resetForTest" });
|
|
1032
|
+
}
|
|
1033
|
+
|
|
1020
1034
|
async function run() {
|
|
1021
|
-
|
|
1022
|
-
|
|
1023
|
-
|
|
1024
|
-
|
|
1025
|
-
|
|
1026
|
-
|
|
1027
|
-
|
|
1028
|
-
|
|
1029
|
-
|
|
1030
|
-
|
|
1031
|
-
|
|
1032
|
-
|
|
1033
|
-
|
|
1034
|
-
|
|
1035
|
-
|
|
1036
|
-
|
|
1037
|
-
|
|
1038
|
-
|
|
1039
|
-
|
|
1040
|
-
|
|
1041
|
-
|
|
1042
|
-
|
|
1043
|
-
|
|
1044
|
-
|
|
1045
|
-
|
|
1046
|
-
|
|
1047
|
-
|
|
1048
|
-
|
|
1049
|
-
|
|
1050
|
-
|
|
1051
|
-
|
|
1052
|
-
|
|
1053
|
-
|
|
1035
|
+
try {
|
|
1036
|
+
testSurface();
|
|
1037
|
+
testCanonicalPathSingleEncodeForS3();
|
|
1038
|
+
testFactoryValidation();
|
|
1039
|
+
testBucketNameValidation();
|
|
1040
|
+
testLifecycleXml();
|
|
1041
|
+
testCorsXml();
|
|
1042
|
+
await testCreateBucketUsEast1NoBody();
|
|
1043
|
+
await testCreateBucketOtherRegionSendsLocationConstraint();
|
|
1044
|
+
await testCreateBucketAlreadyOwnedMaps();
|
|
1045
|
+
await testCreateBucketTakenMaps();
|
|
1046
|
+
await testDeleteBucketHappyAndMissing();
|
|
1047
|
+
await testDeleteBucketNotEmptyMaps();
|
|
1048
|
+
await testListBuckets();
|
|
1049
|
+
await testSetLifecycleSendsXml();
|
|
1050
|
+
await testSetCorsRulesSendsXml();
|
|
1051
|
+
// v0.6.47 — Object Lock
|
|
1052
|
+
await testCreateBucketObjectLockEnabled();
|
|
1053
|
+
await testSetObjectLockConfiguration();
|
|
1054
|
+
await testSetObjectLockConfigurationValidation();
|
|
1055
|
+
await testGetObjectLockConfiguration();
|
|
1056
|
+
await testSetObjectRetention();
|
|
1057
|
+
await testSetObjectRetentionBypassGovernance();
|
|
1058
|
+
await testSetObjectRetentionValidation();
|
|
1059
|
+
await testGetObjectRetention();
|
|
1060
|
+
await testLegalHold();
|
|
1061
|
+
// v0.6.51 — not-configured response paths return clean defaults
|
|
1062
|
+
await testGetObjectLockConfigurationNotConfigured();
|
|
1063
|
+
await testGetObjectRetentionNotConfigured();
|
|
1064
|
+
await testGetObjectLegalHoldNotConfigured();
|
|
1065
|
+
// v0.6.53 — audit + observability emissions
|
|
1066
|
+
await testAuditObservabilityWiring();
|
|
1067
|
+
await testAuditSuccessFalseDisablesSuccessAudit();
|
|
1068
|
+
await testPerCallActorOverrideHonored();
|
|
1069
|
+
} finally {
|
|
1070
|
+
await _drainTcpHandles();
|
|
1071
|
+
}
|
|
1054
1072
|
}
|
|
1055
1073
|
|
|
1056
1074
|
module.exports = { run: run };
|
|
@@ -24,7 +24,6 @@ var sigv4 = require("../../lib/object-store/sigv4");
|
|
|
24
24
|
var b = helpers.b;
|
|
25
25
|
var check = helpers.check;
|
|
26
26
|
var listenOnRandomPort = helpers.listenOnRandomPort;
|
|
27
|
-
void b;
|
|
28
27
|
|
|
29
28
|
function _baseConfig(port, overrides) {
|
|
30
29
|
var cfg = {
|
|
@@ -416,19 +415,38 @@ async function testMultipartFalseRejectsStreams() {
|
|
|
416
415
|
}
|
|
417
416
|
}
|
|
418
417
|
|
|
418
|
+
// The sigv4 store dispatches every part / initiate / complete request through
|
|
419
|
+
// the shared httpClient keep-alive transport pool; cached client sockets
|
|
420
|
+
// finalize their destroy on a later event-loop turn, past the forked worker's
|
|
421
|
+
// grace window. Reset the pool, then poll until every TCP handle has actually
|
|
422
|
+
// drained so none outlives run().
|
|
423
|
+
async function _drainTcpHandles() {
|
|
424
|
+
b.httpClient._resetForTest();
|
|
425
|
+
if (typeof process.getActiveResourcesInfo !== "function") return;
|
|
426
|
+
await helpers.waitUntil(function () {
|
|
427
|
+
return process.getActiveResourcesInfo().filter(function (t) {
|
|
428
|
+
return t === "TCPSocketWrap" || t === "TCPServerWrap";
|
|
429
|
+
}).length === 0;
|
|
430
|
+
}, { timeoutMs: 5000, label: "sigv4-multipart-sse: TCP handle drain after _resetForTest" });
|
|
431
|
+
}
|
|
432
|
+
|
|
419
433
|
async function run() {
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
434
|
+
try {
|
|
435
|
+
await testSinglePutRemainsBufferAtThreshold();
|
|
436
|
+
await testMultipartAutoDetectAboveThreshold();
|
|
437
|
+
await testMultipartFromReadableStream();
|
|
438
|
+
await testMultipartAbortsOnPartFailure();
|
|
439
|
+
await testMultipartCompleteErrorBodyFails();
|
|
440
|
+
await testSseAES256Forwarded();
|
|
441
|
+
await testSseKmsForwardedWithKeyId();
|
|
442
|
+
await testSseForwardedOnEveryMultipartRequest();
|
|
443
|
+
await testSseResponseVerificationFailsOnDroppedHeader();
|
|
444
|
+
await testSseValidationRejectsBadValues();
|
|
445
|
+
testConfigValidation();
|
|
446
|
+
await testMultipartFalseRejectsStreams();
|
|
447
|
+
} finally {
|
|
448
|
+
await _drainTcpHandles();
|
|
449
|
+
}
|
|
432
450
|
}
|
|
433
451
|
|
|
434
452
|
module.exports = { run: run };
|
|
@@ -524,28 +524,48 @@ async function testConditionalEntityTagPrecedence() {
|
|
|
524
524
|
}
|
|
525
525
|
}
|
|
526
526
|
|
|
527
|
+
// The _get helper drives each fixture server with a default-agent http.request
|
|
528
|
+
// (keep-alive), and srv.close() runs fire-and-forget. The kept-alive client
|
|
529
|
+
// sockets, the servers' accept sockets, and any in-flight static-file read
|
|
530
|
+
// (FSReqCallback) finalize their teardown on a later event-loop turn — past the
|
|
531
|
+
// forked worker's grace window. Destroy the global-agent socket pool, then poll
|
|
532
|
+
// until every TCP/fs handle has drained so none outlives run().
|
|
533
|
+
async function _drainTcpHandles() {
|
|
534
|
+
http.globalAgent.destroy();
|
|
535
|
+
if (typeof process.getActiveResourcesInfo !== "function") return;
|
|
536
|
+
await helpers.waitUntil(function () {
|
|
537
|
+
return process.getActiveResourcesInfo().filter(function (t) {
|
|
538
|
+
return t === "TCPSocketWrap" || t === "TCPServerWrap" || t === "FSReqCallback";
|
|
539
|
+
}).length === 0;
|
|
540
|
+
}, { timeoutMs: 5000, label: "static: TCP/fs handle drain after globalAgent.destroy" });
|
|
541
|
+
}
|
|
542
|
+
|
|
527
543
|
async function run() {
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
544
|
+
try {
|
|
545
|
+
await testConditionalEntityTagPrecedence();
|
|
546
|
+
await testForceAttachmentDefaultOff();
|
|
547
|
+
await testForceAttachmentOnHtml();
|
|
548
|
+
await testForceAttachmentOnJs();
|
|
549
|
+
await testForceAttachmentTextStillInline();
|
|
550
|
+
await testForceAttachmentRasterStillInline();
|
|
551
|
+
await testForceAttachmentSvgWithoutSanitizer();
|
|
552
|
+
await testForceAttachmentSvgWithSanitizerInlineAllowed();
|
|
553
|
+
await testForceAttachmentPdfDefaultDownload();
|
|
554
|
+
await testForceAttachmentPdfOptInInline();
|
|
555
|
+
await testMountTypeUserContentForcesDownloadByDefault();
|
|
556
|
+
await testMountTypeCuratedKeepsInline();
|
|
557
|
+
await testMountTypeExplicitOverrideWins();
|
|
558
|
+
testMountTypeBadValueThrows();
|
|
559
|
+
testRejectsUnknownOpts();
|
|
560
|
+
await testOnErrorFiresOnRefusal();
|
|
561
|
+
await testOnErrorThrowDoesNotCorruptResponse();
|
|
562
|
+
testOnErrorRejectsNonFunction();
|
|
563
|
+
await testPathTraversalRefused();
|
|
564
|
+
await testNestedFileServed();
|
|
565
|
+
await testDirectoryIndexServed();
|
|
566
|
+
} finally {
|
|
567
|
+
await _drainTcpHandles();
|
|
568
|
+
}
|
|
549
569
|
}
|
|
550
570
|
|
|
551
571
|
module.exports = { run: run };
|
|
@@ -3,11 +3,36 @@
|
|
|
3
3
|
* b.testing.request — supertest-style chainable HTTP test helper.
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
|
+
var http = require("node:http");
|
|
6
7
|
var helpers = require("../helpers");
|
|
7
8
|
var b = helpers.b;
|
|
8
9
|
var check = helpers.check;
|
|
9
10
|
|
|
11
|
+
// b.testing.request drives the harness server with a default-agent http.request
|
|
12
|
+
// (keep-alive) and closes the fixture server fire-and-forget. The kept-alive
|
|
13
|
+
// client socket and the server's accept socket finalize their destroy on a
|
|
14
|
+
// later event-loop turn, past the forked worker's grace window. Destroy the
|
|
15
|
+
// global-agent socket pool, then poll until every TCP handle has drained so
|
|
16
|
+
// none outlives run().
|
|
17
|
+
async function _drainTcpHandles() {
|
|
18
|
+
http.globalAgent.destroy();
|
|
19
|
+
if (typeof process.getActiveResourcesInfo !== "function") return;
|
|
20
|
+
await helpers.waitUntil(function () {
|
|
21
|
+
return process.getActiveResourcesInfo().filter(function (t) {
|
|
22
|
+
return t === "TCPSocketWrap" || t === "TCPServerWrap";
|
|
23
|
+
}).length === 0;
|
|
24
|
+
}, { timeoutMs: 5000, label: "testing-request: TCP handle drain after globalAgent.destroy" });
|
|
25
|
+
}
|
|
26
|
+
|
|
10
27
|
async function run() {
|
|
28
|
+
try {
|
|
29
|
+
await _runTests();
|
|
30
|
+
} finally {
|
|
31
|
+
await _drainTcpHandles();
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
async function _runTests() {
|
|
11
36
|
// ---- Surface ----
|
|
12
37
|
check("b.testing.request is fn", typeof b.testing.request === "function");
|
|
13
38
|
|
|
@@ -112,9 +112,11 @@ function testLiveHandshake() {
|
|
|
112
112
|
} catch (e) {
|
|
113
113
|
client.destroy(); server.close(); reject(e); return;
|
|
114
114
|
}
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
115
|
+
// Hand the live handles back so run()'s drain can destroy them and
|
|
116
|
+
// poll until their TCP handles release — a fire-and-forget end()/close()
|
|
117
|
+
// here leaves the client/server sockets finalizing past the worker's
|
|
118
|
+
// post-run grace window.
|
|
119
|
+
resolve({ server: server, client: client });
|
|
118
120
|
}
|
|
119
121
|
|
|
120
122
|
var server = nodeTls.createServer({
|
|
@@ -154,10 +156,32 @@ function testLiveHandshake() {
|
|
|
154
156
|
});
|
|
155
157
|
}
|
|
156
158
|
|
|
159
|
+
// Destroy the live TLS client + server handed back by the handshake, then poll
|
|
160
|
+
// until their TCP handles release. Polling drives the real event-loop turns
|
|
161
|
+
// that complete the async socket teardown inside run(), instead of leaving it
|
|
162
|
+
// to finalize in the worker's post-run grace window.
|
|
163
|
+
async function _drainTcpHandles(handles) {
|
|
164
|
+
if (handles) {
|
|
165
|
+
if (handles.client) { try { handles.client.destroy(); } catch (_e) { /* already torn down */ } }
|
|
166
|
+
if (handles.server) { try { handles.server.close(); } catch (_e) { /* already closed */ } }
|
|
167
|
+
}
|
|
168
|
+
if (typeof process.getActiveResourcesInfo !== "function") return;
|
|
169
|
+
await helpers.waitUntil(function () {
|
|
170
|
+
return process.getActiveResourcesInfo().filter(function (t) {
|
|
171
|
+
return t === "TCPSocketWrap" || t === "TCPServerWrap";
|
|
172
|
+
}).length === 0;
|
|
173
|
+
}, { timeoutMs: 5000, label: "tls-exporter: TCP handle drain after socket destroy" });
|
|
174
|
+
}
|
|
175
|
+
|
|
157
176
|
async function run() {
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
177
|
+
var handles = null;
|
|
178
|
+
try {
|
|
179
|
+
testSurface();
|
|
180
|
+
testValidationPaths();
|
|
181
|
+
handles = await testLiveHandshake();
|
|
182
|
+
} finally {
|
|
183
|
+
await _drainTcpHandles(handles);
|
|
184
|
+
}
|
|
161
185
|
}
|
|
162
186
|
|
|
163
187
|
module.exports = { run: run };
|
|
@@ -736,7 +736,29 @@ async function testStripeNonceStoreConcurrentAtomic() {
|
|
|
736
736
|
if (ns.close) await ns.close();
|
|
737
737
|
}
|
|
738
738
|
|
|
739
|
+
// signer.send dispatches through the shared httpClient keep-alive transport
|
|
740
|
+
// pool; a cached client socket finalizes its destroy on a later event-loop
|
|
741
|
+
// turn, past the forked worker's grace window. Reset the pool, then poll until
|
|
742
|
+
// every TCP handle has actually drained so none outlives run().
|
|
743
|
+
async function _drainTcpHandles() {
|
|
744
|
+
b.httpClient._resetForTest();
|
|
745
|
+
if (typeof process.getActiveResourcesInfo !== "function") return;
|
|
746
|
+
await helpers.waitUntil(function () {
|
|
747
|
+
return process.getActiveResourcesInfo().filter(function (t) {
|
|
748
|
+
return t === "TCPSocketWrap" || t === "TCPServerWrap";
|
|
749
|
+
}).length === 0;
|
|
750
|
+
}, { timeoutMs: 5000, label: "webhook: TCP handle drain after _resetForTest" });
|
|
751
|
+
}
|
|
752
|
+
|
|
739
753
|
async function run() {
|
|
754
|
+
try {
|
|
755
|
+
await _runTests();
|
|
756
|
+
} finally {
|
|
757
|
+
await _drainTcpHandles();
|
|
758
|
+
}
|
|
759
|
+
}
|
|
760
|
+
|
|
761
|
+
async function _runTests() {
|
|
740
762
|
testWebhookSurface();
|
|
741
763
|
await testHmacRoundtrip();
|
|
742
764
|
await testHmacBufferBody();
|
|
@@ -42,11 +42,12 @@ async function run() {
|
|
|
42
42
|
.catch(function (e) { bError = e; });
|
|
43
43
|
|
|
44
44
|
// Bound the wait so a hung B fails the test rather than hanging the suite.
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
45
|
+
// withTestTimeout clears its guard timer on settle (a raced waitUntil would
|
|
46
|
+
// keep polling — and leave its in-flight poll timer — once Promise.all won).
|
|
47
|
+
await helpers.withTestTimeout(
|
|
48
|
+
"#127: queued task settles after the slot recycles",
|
|
49
|
+
function () { return Promise.all([aPromise, bPromise]); },
|
|
50
|
+
{ timeoutMs: 8000 });
|
|
50
51
|
|
|
51
52
|
check("#127 the timing-out task A is reaped (timeout, as expected)",
|
|
52
53
|
aErr && aErr.code === "workerpool/timeout");
|
|
@@ -55,7 +56,10 @@ async function run() {
|
|
|
55
56
|
check("#127 the queued task runs on the replacement worker and returns its result",
|
|
56
57
|
bResult && bResult.v === 42);
|
|
57
58
|
} finally {
|
|
58
|
-
|
|
59
|
+
// Await termination so the worker threads fully exit before run()
|
|
60
|
+
// returns — an un-awaited terminate() leaves the worker's MessagePort
|
|
61
|
+
// and reap timer alive past the assertions.
|
|
62
|
+
await pool.terminate();
|
|
59
63
|
}
|
|
60
64
|
}
|
|
61
65
|
|