@blamejs/blamejs-shop 0.5.12 → 0.5.13

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.
Files changed (521) hide show
  1. package/CHANGELOG.md +2 -0
  2. package/lib/asset-manifest.json +1 -1
  3. package/lib/vendor/MANIFEST.json +632 -416
  4. package/lib/vendor/blamejs/.clusterfuzzlite/Dockerfile +21 -10
  5. package/lib/vendor/blamejs/.clusterfuzzlite/build.sh +30 -9
  6. package/lib/vendor/blamejs/.github/dependabot.yml +8 -0
  7. package/lib/vendor/blamejs/.github/workflows/actions-lint.yml +3 -3
  8. package/lib/vendor/blamejs/.github/workflows/cflite_batch.yml +7 -2
  9. package/lib/vendor/blamejs/.github/workflows/cflite_pr.yml +7 -2
  10. package/lib/vendor/blamejs/.github/workflows/ci.yml +21 -21
  11. package/lib/vendor/blamejs/.github/workflows/codeql.yml +3 -3
  12. package/lib/vendor/blamejs/.github/workflows/npm-publish.yml +4 -4
  13. package/lib/vendor/blamejs/.github/workflows/release-container.yml +7 -7
  14. package/lib/vendor/blamejs/.github/workflows/scorecard.yml +3 -3
  15. package/lib/vendor/blamejs/.github/workflows/sha-to-tag-verify.yml +1 -1
  16. package/lib/vendor/blamejs/.gitignore +2 -0
  17. package/lib/vendor/blamejs/CHANGELOG.md +122 -0
  18. package/lib/vendor/blamejs/NOTICE +26 -1
  19. package/lib/vendor/blamejs/SECURITY.md +1 -1
  20. package/lib/vendor/blamejs/api-snapshot.json +207 -5
  21. package/lib/vendor/blamejs/docker/keycloak/realm-blamejs-test.json +29 -0
  22. package/lib/vendor/blamejs/examples/wiki/DEPLOY.md +1 -0
  23. package/lib/vendor/blamejs/examples/wiki/lib/build-app.js +31 -0
  24. package/lib/vendor/blamejs/examples/wiki/lib/source-comment-block-validator.js +109 -0
  25. package/lib/vendor/blamejs/examples/wiki/nginx.conf +106 -0
  26. package/lib/vendor/blamejs/examples/wiki/package-lock.json +1 -1
  27. package/lib/vendor/blamejs/examples/wiki/test/e2e.js +92 -0
  28. package/lib/vendor/blamejs/fuzz/asn1-der.fuzz.js +28 -0
  29. package/lib/vendor/blamejs/fuzz/cms-codec.fuzz.js +17 -0
  30. package/lib/vendor/blamejs/fuzz/link-header.fuzz.js +18 -0
  31. package/lib/vendor/blamejs/index.js +6 -0
  32. package/lib/vendor/blamejs/lib/a2a.js +4 -4
  33. package/lib/vendor/blamejs/lib/agent-idempotency.js +18 -2
  34. package/lib/vendor/blamejs/lib/agent-saga.js +36 -8
  35. package/lib/vendor/blamejs/lib/agent-snapshot.js +63 -6
  36. package/lib/vendor/blamejs/lib/app-shutdown.js +23 -20
  37. package/lib/vendor/blamejs/lib/archive-read.js +8 -0
  38. package/lib/vendor/blamejs/lib/archive-tar.js +12 -2
  39. package/lib/vendor/blamejs/lib/arg-parser.js +49 -5
  40. package/lib/vendor/blamejs/lib/asn1-der.js +12 -0
  41. package/lib/vendor/blamejs/lib/audit-sign.js +47 -1
  42. package/lib/vendor/blamejs/lib/audit.js +71 -8
  43. package/lib/vendor/blamejs/lib/auth/ciba.js +14 -2
  44. package/lib/vendor/blamejs/lib/auth/fido-mds3.js +58 -47
  45. package/lib/vendor/blamejs/lib/auth/jwt.js +34 -0
  46. package/lib/vendor/blamejs/lib/auth/oauth.js +90 -13
  47. package/lib/vendor/blamejs/lib/auth/oid4vci.js +20 -17
  48. package/lib/vendor/blamejs/lib/auth/openid-federation.js +214 -23
  49. package/lib/vendor/blamejs/lib/auth/saml.js +38 -20
  50. package/lib/vendor/blamejs/lib/auth/sd-jwt-vc.js +10 -4
  51. package/lib/vendor/blamejs/lib/backup/bundle.js +13 -3
  52. package/lib/vendor/blamejs/lib/backup/index.js +16 -5
  53. package/lib/vendor/blamejs/lib/backup/manifest.js +18 -5
  54. package/lib/vendor/blamejs/lib/base32.js +21 -0
  55. package/lib/vendor/blamejs/lib/break-glass.js +19 -10
  56. package/lib/vendor/blamejs/lib/bundler.js +5 -1
  57. package/lib/vendor/blamejs/lib/cache-status.js +3 -7
  58. package/lib/vendor/blamejs/lib/calendar.js +21 -1
  59. package/lib/vendor/blamejs/lib/cbor.js +12 -1
  60. package/lib/vendor/blamejs/lib/cert.js +29 -11
  61. package/lib/vendor/blamejs/lib/cli.js +94 -24
  62. package/lib/vendor/blamejs/lib/cloud-events.js +2 -2
  63. package/lib/vendor/blamejs/lib/cluster-provider-db.js +13 -3
  64. package/lib/vendor/blamejs/lib/codepoint-class.js +85 -0
  65. package/lib/vendor/blamejs/lib/compliance-ai-act-prohibited.js +8 -4
  66. package/lib/vendor/blamejs/lib/compliance-ai-act-transparency.js +19 -4
  67. package/lib/vendor/blamejs/lib/compliance-ai-act.js +6 -8
  68. package/lib/vendor/blamejs/lib/content-credentials.js +1 -1
  69. package/lib/vendor/blamejs/lib/content-digest.js +2 -1
  70. package/lib/vendor/blamejs/lib/cookies.js +13 -3
  71. package/lib/vendor/blamejs/lib/cose.js +31 -16
  72. package/lib/vendor/blamejs/lib/crypto-field.js +32 -0
  73. package/lib/vendor/blamejs/lib/crypto-oprf.js +11 -2
  74. package/lib/vendor/blamejs/lib/crypto-xwing.js +22 -4
  75. package/lib/vendor/blamejs/lib/crypto.js +314 -19
  76. package/lib/vendor/blamejs/lib/csp.js +11 -3
  77. package/lib/vendor/blamejs/lib/daemon.js +270 -24
  78. package/lib/vendor/blamejs/lib/dark-patterns.js +5 -2
  79. package/lib/vendor/blamejs/lib/db-declare-view.js +2 -2
  80. package/lib/vendor/blamejs/lib/db-query.js +34 -7
  81. package/lib/vendor/blamejs/lib/db.js +18 -6
  82. package/lib/vendor/blamejs/lib/dbsc.js +17 -0
  83. package/lib/vendor/blamejs/lib/dev.js +21 -2
  84. package/lib/vendor/blamejs/lib/dsr.js +157 -102
  85. package/lib/vendor/blamejs/lib/external-db.js +41 -2
  86. package/lib/vendor/blamejs/lib/file-upload.js +25 -7
  87. package/lib/vendor/blamejs/lib/flag-providers.js +27 -15
  88. package/lib/vendor/blamejs/lib/forms.js +113 -27
  89. package/lib/vendor/blamejs/lib/gate-contract.js +23 -10
  90. package/lib/vendor/blamejs/lib/gdpr-ropa.js +8 -1
  91. package/lib/vendor/blamejs/lib/guard-agent-registry.js +1 -1
  92. package/lib/vendor/blamejs/lib/guard-archive.js +2 -2
  93. package/lib/vendor/blamejs/lib/guard-cidr.js +27 -1
  94. package/lib/vendor/blamejs/lib/guard-graphql.js +30 -11
  95. package/lib/vendor/blamejs/lib/guard-html.js +26 -53
  96. package/lib/vendor/blamejs/lib/guard-image.js +24 -5
  97. package/lib/vendor/blamejs/lib/guard-imap-command.js +10 -2
  98. package/lib/vendor/blamejs/lib/guard-jmap.js +19 -3
  99. package/lib/vendor/blamejs/lib/guard-jwt.js +18 -2
  100. package/lib/vendor/blamejs/lib/guard-list-unsubscribe.js +2 -2
  101. package/lib/vendor/blamejs/lib/guard-managesieve-command.js +10 -2
  102. package/lib/vendor/blamejs/lib/guard-markdown.js +11 -24
  103. package/lib/vendor/blamejs/lib/guard-pdf.js +18 -2
  104. package/lib/vendor/blamejs/lib/guard-pop3-command.js +10 -2
  105. package/lib/vendor/blamejs/lib/guard-regex.js +8 -5
  106. package/lib/vendor/blamejs/lib/guard-svg.js +31 -32
  107. package/lib/vendor/blamejs/lib/guard-time.js +1 -1
  108. package/lib/vendor/blamejs/lib/guard-uuid.js +2 -2
  109. package/lib/vendor/blamejs/lib/html-balance.js +3 -3
  110. package/lib/vendor/blamejs/lib/http-client-cache.js +82 -4
  111. package/lib/vendor/blamejs/lib/http-client-cookie-jar.js +16 -1
  112. package/lib/vendor/blamejs/lib/http-client.js +39 -7
  113. package/lib/vendor/blamejs/lib/http-message-signature.js +35 -1
  114. package/lib/vendor/blamejs/lib/i18n-messageformat.js +31 -6
  115. package/lib/vendor/blamejs/lib/i18n.js +35 -21
  116. package/lib/vendor/blamejs/lib/incident-report.js +8 -1
  117. package/lib/vendor/blamejs/lib/ip-utils.js +11 -1
  118. package/lib/vendor/blamejs/lib/json-path.js +23 -1
  119. package/lib/vendor/blamejs/lib/jwk.js +20 -3
  120. package/lib/vendor/blamejs/lib/link-header.js +2 -1
  121. package/lib/vendor/blamejs/lib/log-stream-otlp-grpc.js +5 -1
  122. package/lib/vendor/blamejs/lib/log-stream-otlp.js +5 -1
  123. package/lib/vendor/blamejs/lib/log-stream.js +8 -3
  124. package/lib/vendor/blamejs/lib/mail-auth.js +123 -22
  125. package/lib/vendor/blamejs/lib/mail-bimi.js +1 -1
  126. package/lib/vendor/blamejs/lib/mail-bounce.js +8 -0
  127. package/lib/vendor/blamejs/lib/mail-crypto-pgp.js +46 -10
  128. package/lib/vendor/blamejs/lib/mail-dav.js +22 -3
  129. package/lib/vendor/blamejs/lib/mail-dkim.js +96 -30
  130. package/lib/vendor/blamejs/lib/mail-helo.js +6 -1
  131. package/lib/vendor/blamejs/lib/mail-scan.js +23 -16
  132. package/lib/vendor/blamejs/lib/mail-send-deliver.js +34 -8
  133. package/lib/vendor/blamejs/lib/mail-server-imap.js +3 -4
  134. package/lib/vendor/blamejs/lib/mail-server-managesieve.js +7 -11
  135. package/lib/vendor/blamejs/lib/mail-server-mx.js +93 -7
  136. package/lib/vendor/blamejs/lib/mail-server-registry.js +8 -2
  137. package/lib/vendor/blamejs/lib/mail.js +15 -5
  138. package/lib/vendor/blamejs/lib/metrics.js +268 -63
  139. package/lib/vendor/blamejs/lib/middleware/age-gate.js +7 -1
  140. package/lib/vendor/blamejs/lib/middleware/asyncapi-serve.js +1 -1
  141. package/lib/vendor/blamejs/lib/middleware/body-parser.js +19 -4
  142. package/lib/vendor/blamejs/lib/middleware/bot-guard.js +5 -9
  143. package/lib/vendor/blamejs/lib/middleware/csp-report.js +40 -8
  144. package/lib/vendor/blamejs/lib/middleware/csrf-protect.js +24 -10
  145. package/lib/vendor/blamejs/lib/middleware/dpop.js +10 -5
  146. package/lib/vendor/blamejs/lib/middleware/index.js +6 -1
  147. package/lib/vendor/blamejs/lib/middleware/nel.js +1 -1
  148. package/lib/vendor/blamejs/lib/middleware/openapi-serve.js +1 -1
  149. package/lib/vendor/blamejs/lib/middleware/rate-limit.js +12 -1
  150. package/lib/vendor/blamejs/lib/middleware/require-bound-key.js +1 -1
  151. package/lib/vendor/blamejs/lib/middleware/scim-server.js +1 -1
  152. package/lib/vendor/blamejs/lib/middleware/tus-upload.js +6 -2
  153. package/lib/vendor/blamejs/lib/mtls-ca.js +18 -2
  154. package/lib/vendor/blamejs/lib/network-dns-resolver.js +11 -1
  155. package/lib/vendor/blamejs/lib/network-dns.js +21 -2
  156. package/lib/vendor/blamejs/lib/network-tls.js +69 -7
  157. package/lib/vendor/blamejs/lib/nonce-store.js +9 -1
  158. package/lib/vendor/blamejs/lib/object-store/gcs.js +7 -0
  159. package/lib/vendor/blamejs/lib/object-store/sigv4.js +31 -0
  160. package/lib/vendor/blamejs/lib/observability-otlp-exporter.js +1 -1
  161. package/lib/vendor/blamejs/lib/outbox.js +1 -1
  162. package/lib/vendor/blamejs/lib/parsers/safe-ini.js +9 -1
  163. package/lib/vendor/blamejs/lib/parsers/safe-toml.js +10 -1
  164. package/lib/vendor/blamejs/lib/permissions.js +6 -3
  165. package/lib/vendor/blamejs/lib/pid-probe.js +55 -0
  166. package/lib/vendor/blamejs/lib/pqc-agent.js +8 -1
  167. package/lib/vendor/blamejs/lib/pqc-software.js +3 -3
  168. package/lib/vendor/blamejs/lib/pubsub.js +20 -9
  169. package/lib/vendor/blamejs/lib/queue-local.js +8 -1
  170. package/lib/vendor/blamejs/lib/queue-redis.js +5 -0
  171. package/lib/vendor/blamejs/lib/redact.js +54 -0
  172. package/lib/vendor/blamejs/lib/restore-bundle.js +10 -2
  173. package/lib/vendor/blamejs/lib/restore.js +19 -0
  174. package/lib/vendor/blamejs/lib/retention.js +12 -4
  175. package/lib/vendor/blamejs/lib/router.js +60 -6
  176. package/lib/vendor/blamejs/lib/safe-buffer.js +69 -0
  177. package/lib/vendor/blamejs/lib/safe-decompress.js +8 -2
  178. package/lib/vendor/blamejs/lib/safe-dns.js +25 -20
  179. package/lib/vendor/blamejs/lib/safe-ical.js +7 -3
  180. package/lib/vendor/blamejs/lib/safe-mime.js +12 -1
  181. package/lib/vendor/blamejs/lib/safe-object.js +80 -0
  182. package/lib/vendor/blamejs/lib/safe-path.js +52 -4
  183. package/lib/vendor/blamejs/lib/safe-redirect.js +10 -2
  184. package/lib/vendor/blamejs/lib/safe-schema.js +4 -1
  185. package/lib/vendor/blamejs/lib/safe-sieve.js +33 -1
  186. package/lib/vendor/blamejs/lib/safe-sql.js +88 -0
  187. package/lib/vendor/blamejs/lib/safe-vcard.js +7 -3
  188. package/lib/vendor/blamejs/lib/scheduler.js +8 -1
  189. package/lib/vendor/blamejs/lib/security-assert.js +6 -6
  190. package/lib/vendor/blamejs/lib/self-update-standalone-verifier.js +74 -27
  191. package/lib/vendor/blamejs/lib/self-update.js +517 -87
  192. package/lib/vendor/blamejs/lib/server-timing.js +2 -4
  193. package/lib/vendor/blamejs/lib/session.js +34 -12
  194. package/lib/vendor/blamejs/lib/sql.js +15 -1
  195. package/lib/vendor/blamejs/lib/ssrf-guard.js +52 -0
  196. package/lib/vendor/blamejs/lib/static.js +55 -13
  197. package/lib/vendor/blamejs/lib/storage.js +8 -2
  198. package/lib/vendor/blamejs/lib/subject.js +6 -1
  199. package/lib/vendor/blamejs/lib/tenant-quota.js +52 -13
  200. package/lib/vendor/blamejs/lib/tls-exporter.js +3 -3
  201. package/lib/vendor/blamejs/lib/tsa.js +34 -13
  202. package/lib/vendor/blamejs/lib/uri-template.js +8 -1
  203. package/lib/vendor/blamejs/lib/vault/index.js +13 -0
  204. package/lib/vendor/blamejs/lib/vc.js +44 -5
  205. package/lib/vendor/blamejs/lib/vendor/MANIFEST.json +26 -26
  206. package/lib/vendor/blamejs/lib/vendor/noble-ciphers.cjs +792 -1
  207. package/lib/vendor/blamejs/lib/vendor/noble-curves.cjs +3443 -1
  208. package/lib/vendor/blamejs/lib/vendor/noble-post-quantum.cjs +2737 -1
  209. package/lib/vendor/blamejs/lib/vendor/pki.cjs +39550 -13
  210. package/lib/vendor/blamejs/lib/vendor/public-suffix-list.dat +55 -53
  211. package/lib/vendor/blamejs/lib/vendor/public-suffix-list.data.js +5551 -5554
  212. package/lib/vendor/blamejs/lib/vendor/simplewebauthn-server.cjs +22459 -32
  213. package/lib/vendor/blamejs/lib/watcher.js +89 -17
  214. package/lib/vendor/blamejs/lib/webhook-dispatcher.js +25 -3
  215. package/lib/vendor/blamejs/lib/webhook.js +12 -2
  216. package/lib/vendor/blamejs/lib/ws-client.js +32 -1
  217. package/lib/vendor/blamejs/lib/xml-c14n.js +29 -1
  218. package/lib/vendor/blamejs/oss-fuzz/projects/blamejs/Dockerfile +1 -1
  219. package/lib/vendor/blamejs/package-lock.json +2 -2
  220. package/lib/vendor/blamejs/package.json +1 -1
  221. package/lib/vendor/blamejs/release-notes/v0.16.x.json +1462 -0
  222. package/lib/vendor/blamejs/release-notes/v0.17.0.json +31 -0
  223. package/lib/vendor/blamejs/release-notes/v0.17.1.json +31 -0
  224. package/lib/vendor/blamejs/release-notes/v0.17.10.json +30 -0
  225. package/lib/vendor/blamejs/release-notes/v0.17.11.json +22 -0
  226. package/lib/vendor/blamejs/release-notes/v0.17.12.json +18 -0
  227. package/lib/vendor/blamejs/release-notes/v0.17.13.json +77 -0
  228. package/lib/vendor/blamejs/release-notes/v0.17.14.json +40 -0
  229. package/lib/vendor/blamejs/release-notes/v0.17.15.json +18 -0
  230. package/lib/vendor/blamejs/release-notes/v0.17.16.json +27 -0
  231. package/lib/vendor/blamejs/release-notes/v0.17.17.json +31 -0
  232. package/lib/vendor/blamejs/release-notes/v0.17.18.json +18 -0
  233. package/lib/vendor/blamejs/release-notes/v0.17.19.json +18 -0
  234. package/lib/vendor/blamejs/release-notes/v0.17.2.json +26 -0
  235. package/lib/vendor/blamejs/release-notes/v0.17.20.json +43 -0
  236. package/lib/vendor/blamejs/release-notes/v0.17.21.json +26 -0
  237. package/lib/vendor/blamejs/release-notes/v0.17.22.json +18 -0
  238. package/lib/vendor/blamejs/release-notes/v0.17.3.json +43 -0
  239. package/lib/vendor/blamejs/release-notes/v0.17.4.json +35 -0
  240. package/lib/vendor/blamejs/release-notes/v0.17.5.json +26 -0
  241. package/lib/vendor/blamejs/release-notes/v0.17.6.json +26 -0
  242. package/lib/vendor/blamejs/release-notes/v0.17.7.json +35 -0
  243. package/lib/vendor/blamejs/release-notes/v0.17.8.json +22 -0
  244. package/lib/vendor/blamejs/release-notes/v0.17.9.json +26 -0
  245. package/lib/vendor/blamejs/scripts/validate-source-comment-blocks.js +4 -0
  246. package/lib/vendor/blamejs/scripts/vendor-update.sh +293 -9
  247. package/lib/vendor/blamejs/socket.yml +94 -0
  248. package/lib/vendor/blamejs/test/00-primitives.js +605 -0
  249. package/lib/vendor/blamejs/test/helpers/drivers.js +12 -9
  250. package/lib/vendor/blamejs/test/integration/audit-stack-mysql.test.js +90 -1
  251. package/lib/vendor/blamejs/test/integration/audit-stack-postgres.test.js +122 -1
  252. package/lib/vendor/blamejs/test/integration/data-layer-mysql.test.js +30 -0
  253. package/lib/vendor/blamejs/test/integration/data-layer-pg.test.js +29 -0
  254. package/lib/vendor/blamejs/test/integration/dsr-cluster-mysql.test.js +479 -0
  255. package/lib/vendor/blamejs/test/integration/dsr-cluster-pg.test.js +487 -0
  256. package/lib/vendor/blamejs/test/integration/federation-auth.test.js +313 -5
  257. package/lib/vendor/blamejs/test/integration/mail-dkim.test.js +80 -0
  258. package/lib/vendor/blamejs/test/integration/openid-federation-chain.test.js +275 -0
  259. package/lib/vendor/blamejs/test/integration/webhook-dispatcher-pg.test.js +96 -0
  260. package/lib/vendor/blamejs/test/layer-0-primitives/a2a-tasks.test.js +401 -0
  261. package/lib/vendor/blamejs/test/layer-0-primitives/acme.test.js +1649 -2
  262. package/lib/vendor/blamejs/test/layer-0-primitives/age-gate.test.js +33 -0
  263. package/lib/vendor/blamejs/test/layer-0-primitives/agent-idempotency.test.js +0 -0
  264. package/lib/vendor/blamejs/test/layer-0-primitives/agent-saga.test.js +60 -0
  265. package/lib/vendor/blamejs/test/layer-0-primitives/agent-snapshot.test.js +524 -0
  266. package/lib/vendor/blamejs/test/layer-0-primitives/api-encrypt.test.js +891 -0
  267. package/lib/vendor/blamejs/test/layer-0-primitives/app-shutdown.test.js +128 -1
  268. package/lib/vendor/blamejs/test/layer-0-primitives/archive-adapters.test.js +271 -0
  269. package/lib/vendor/blamejs/test/layer-0-primitives/archive-read.test.js +628 -1
  270. package/lib/vendor/blamejs/test/layer-0-primitives/archive-tar-read.test.js +0 -0
  271. package/lib/vendor/blamejs/test/layer-0-primitives/archive-wrap.test.js +227 -0
  272. package/lib/vendor/blamejs/test/layer-0-primitives/arg-parser.test.js +15 -0
  273. package/lib/vendor/blamejs/test/layer-0-primitives/asn1-der.test.js +73 -0
  274. package/lib/vendor/blamejs/test/layer-0-primitives/atomic-file.test.js +114 -0
  275. package/lib/vendor/blamejs/test/layer-0-primitives/audit-sign-anchor.test.js +141 -0
  276. package/lib/vendor/blamejs/test/layer-0-primitives/audit-tools.test.js +624 -0
  277. package/lib/vendor/blamejs/test/layer-0-primitives/audit.test.js +769 -0
  278. package/lib/vendor/blamejs/test/layer-0-primitives/auth-jwt-defenses.test.js +436 -0
  279. package/lib/vendor/blamejs/test/layer-0-primitives/auth-oauth.test.js +1697 -0
  280. package/lib/vendor/blamejs/test/layer-0-primitives/auth-oid4vp.test.js +495 -0
  281. package/lib/vendor/blamejs/test/layer-0-primitives/auth-password.test.js +500 -0
  282. package/lib/vendor/blamejs/test/layer-0-primitives/auth-saml.test.js +1809 -0
  283. package/lib/vendor/blamejs/test/layer-0-primitives/auth-status-list.test.js +243 -1
  284. package/lib/vendor/blamejs/test/layer-0-primitives/backup-index.test.js +2226 -0
  285. package/lib/vendor/blamejs/test/layer-0-primitives/backup-manifest-signature.test.js +183 -0
  286. package/lib/vendor/blamejs/test/layer-0-primitives/base32.test.js +105 -0
  287. package/lib/vendor/blamejs/test/layer-0-primitives/break-glass.test.js +693 -0
  288. package/lib/vendor/blamejs/test/layer-0-primitives/cache.test.js +603 -0
  289. package/lib/vendor/blamejs/test/layer-0-primitives/calendar.test.js +557 -0
  290. package/lib/vendor/blamejs/test/layer-0-primitives/case-insensitive-security-token-guard.test.js +214 -0
  291. package/lib/vendor/blamejs/test/layer-0-primitives/cbor.test.js +25 -0
  292. package/lib/vendor/blamejs/test/layer-0-primitives/cert.test.js +843 -6
  293. package/lib/vendor/blamejs/test/layer-0-primitives/ciba-authreqid-binding.test.js +77 -2
  294. package/lib/vendor/blamejs/test/layer-0-primitives/ciba.test.js +866 -0
  295. package/lib/vendor/blamejs/test/layer-0-primitives/clear-site-data.test.js +18 -0
  296. package/lib/vendor/blamejs/test/layer-0-primitives/cli-erase.test.js +19 -0
  297. package/lib/vendor/blamejs/test/layer-0-primitives/cli.test.js +2790 -0
  298. package/lib/vendor/blamejs/test/layer-0-primitives/cluster-lease-renewal-ttl.test.js +114 -0
  299. package/lib/vendor/blamejs/test/layer-0-primitives/cluster.test.js +1032 -0
  300. package/lib/vendor/blamejs/test/layer-0-primitives/cms-codec.test.js +575 -0
  301. package/lib/vendor/blamejs/test/layer-0-primitives/codebase-patterns.test.js +739 -1
  302. package/lib/vendor/blamejs/test/layer-0-primitives/codepoint-class.test.js +8 -0
  303. package/lib/vendor/blamejs/test/layer-0-primitives/compliance-ai-act.test.js +194 -0
  304. package/lib/vendor/blamejs/test/layer-0-primitives/compliance-lifecycle-proto-key.test.js +104 -0
  305. package/lib/vendor/blamejs/test/layer-0-primitives/compliance-sanctions.test.js +254 -0
  306. package/lib/vendor/blamejs/test/layer-0-primitives/content-credentials.test.js +613 -3
  307. package/lib/vendor/blamejs/test/layer-0-primitives/cookies.test.js +140 -0
  308. package/lib/vendor/blamejs/test/layer-0-primitives/cose.test.js +407 -0
  309. package/lib/vendor/blamejs/test/layer-0-primitives/crypto-adversarial.test.js +352 -0
  310. package/lib/vendor/blamejs/test/layer-0-primitives/crypto-field-derived-hash.test.js +32 -0
  311. package/lib/vendor/blamejs/test/layer-0-primitives/crypto-field.test.js +575 -0
  312. package/lib/vendor/blamejs/test/layer-0-primitives/crypto-hash-files-parallel.test.js +10 -0
  313. package/lib/vendor/blamejs/test/layer-0-primitives/crypto-hash-stream.test.js +24 -0
  314. package/lib/vendor/blamejs/test/layer-0-primitives/crypto-oprf.test.js +17 -0
  315. package/lib/vendor/blamejs/test/layer-0-primitives/crypto-spki-pin.test.js +183 -0
  316. package/lib/vendor/blamejs/test/layer-0-primitives/crypto-xwing.test.js +48 -0
  317. package/lib/vendor/blamejs/test/layer-0-primitives/crypto.test.js +345 -0
  318. package/lib/vendor/blamejs/test/layer-0-primitives/csp-report.test.js +58 -0
  319. package/lib/vendor/blamejs/test/layer-0-primitives/csv.test.js +48 -0
  320. package/lib/vendor/blamejs/test/layer-0-primitives/daemon.test.js +459 -1
  321. package/lib/vendor/blamejs/test/layer-0-primitives/dark-patterns.test.js +19 -0
  322. package/lib/vendor/blamejs/test/layer-0-primitives/db-query.test.js +1019 -0
  323. package/lib/vendor/blamejs/test/layer-0-primitives/db-raw-residency-gate.test.js +77 -0
  324. package/lib/vendor/blamejs/test/layer-0-primitives/db.test.js +1621 -0
  325. package/lib/vendor/blamejs/test/layer-0-primitives/ddl-change-control.test.js +462 -3
  326. package/lib/vendor/blamejs/test/layer-0-primitives/dnssec.test.js +323 -0
  327. package/lib/vendor/blamejs/test/layer-0-primitives/dpop-middleware-verify.test.js +562 -0
  328. package/lib/vendor/blamejs/test/layer-0-primitives/dsr.test.js +901 -1
  329. package/lib/vendor/blamejs/test/layer-0-primitives/dual-control.test.js +249 -0
  330. package/lib/vendor/blamejs/test/layer-0-primitives/external-db-migrate.test.js +561 -0
  331. package/lib/vendor/blamejs/test/layer-0-primitives/external-db.test.js +1214 -0
  332. package/lib/vendor/blamejs/test/layer-0-primitives/fal.test.js +21 -0
  333. package/lib/vendor/blamejs/test/layer-0-primitives/fedcm-dbsc.test.js +46 -20
  334. package/lib/vendor/blamejs/test/layer-0-primitives/federation-vc-suite.test.js +147 -3
  335. package/lib/vendor/blamejs/test/layer-0-primitives/fido-mds3.test.js +907 -38
  336. package/lib/vendor/blamejs/test/layer-0-primitives/file-upload-content-safety-skip-audit.test.js +29 -0
  337. package/lib/vendor/blamejs/test/layer-0-primitives/file-upload.test.js +1135 -0
  338. package/lib/vendor/blamejs/test/layer-0-primitives/flag.test.js +30 -0
  339. package/lib/vendor/blamejs/test/layer-0-primitives/forms.test.js +747 -0
  340. package/lib/vendor/blamejs/test/layer-0-primitives/gate-contract.test.js +1855 -0
  341. package/lib/vendor/blamejs/test/layer-0-primitives/gdpr-ropa.test.js +30 -0
  342. package/lib/vendor/blamejs/test/layer-0-primitives/guard-archive.test.js +86 -0
  343. package/lib/vendor/blamejs/test/layer-0-primitives/guard-auth.test.js +117 -0
  344. package/lib/vendor/blamejs/test/layer-0-primitives/guard-cidr.test.js +151 -0
  345. package/lib/vendor/blamejs/test/layer-0-primitives/guard-domain.test.js +422 -0
  346. package/lib/vendor/blamejs/test/layer-0-primitives/guard-filename.test.js +424 -0
  347. package/lib/vendor/blamejs/test/layer-0-primitives/{guard-gate-disposition-coverage.test.js → guard-gate-disposition.test.js} +1 -1
  348. package/lib/vendor/blamejs/test/layer-0-primitives/guard-graphql.test.js +340 -0
  349. package/lib/vendor/blamejs/test/layer-0-primitives/guard-html.test.js +29 -0
  350. package/lib/vendor/blamejs/test/layer-0-primitives/guard-idempotency-key.test.js +28 -0
  351. package/lib/vendor/blamejs/test/layer-0-primitives/guard-image.test.js +519 -45
  352. package/lib/vendor/blamejs/test/layer-0-primitives/guard-imap-command.test.js +0 -0
  353. package/lib/vendor/blamejs/test/layer-0-primitives/guard-jmap.test.js +51 -0
  354. package/lib/vendor/blamejs/test/layer-0-primitives/guard-jsonpath.test.js +66 -0
  355. package/lib/vendor/blamejs/test/layer-0-primitives/guard-jwt.test.js +436 -0
  356. package/lib/vendor/blamejs/test/layer-0-primitives/guard-managesieve-command.test.js +25 -0
  357. package/lib/vendor/blamejs/test/layer-0-primitives/guard-markdown.test.js +16 -0
  358. package/lib/vendor/blamejs/test/layer-0-primitives/guard-mime.test.js +86 -0
  359. package/lib/vendor/blamejs/test/layer-0-primitives/guard-oauth.test.js +140 -0
  360. package/lib/vendor/blamejs/test/layer-0-primitives/guard-pdf.test.js +80 -0
  361. package/lib/vendor/blamejs/test/layer-0-primitives/guard-pop3-command.test.js +27 -0
  362. package/lib/vendor/blamejs/test/layer-0-primitives/guard-regex.test.js +99 -0
  363. package/lib/vendor/blamejs/test/layer-0-primitives/guard-shell.test.js +76 -0
  364. package/lib/vendor/blamejs/test/layer-0-primitives/{guard-sql-coverage.test.js → guard-sql.test.js} +3 -3
  365. package/lib/vendor/blamejs/test/layer-0-primitives/guard-svg.test.js +524 -0
  366. package/lib/vendor/blamejs/test/layer-0-primitives/guard-template.test.js +71 -0
  367. package/lib/vendor/blamejs/test/layer-0-primitives/guard-time.test.js +92 -0
  368. package/lib/vendor/blamejs/test/layer-0-primitives/guard-uuid.test.js +86 -0
  369. package/lib/vendor/blamejs/test/layer-0-primitives/html-balance.test.js +38 -0
  370. package/lib/vendor/blamejs/test/layer-0-primitives/http-client-cache-authorization.test.js +347 -0
  371. package/lib/vendor/blamejs/test/layer-0-primitives/http-client-cache.test.js +908 -0
  372. package/lib/vendor/blamejs/test/layer-0-primitives/http-client.test.js +2874 -0
  373. package/lib/vendor/blamejs/test/layer-0-primitives/http-message-signature.test.js +643 -0
  374. package/lib/vendor/blamejs/test/layer-0-primitives/i18n-messageformat.test.js +38 -0
  375. package/lib/vendor/blamejs/test/layer-0-primitives/i18n.test.js +1153 -1
  376. package/lib/vendor/blamejs/test/layer-0-primitives/idempotency-key.test.js +494 -0
  377. package/lib/vendor/blamejs/test/layer-0-primitives/ip-utils.test.js +30 -0
  378. package/lib/vendor/blamejs/test/layer-0-primitives/jsdoc-example-execution.test.js +177 -0
  379. package/lib/vendor/blamejs/test/layer-0-primitives/json-path.test.js +103 -0
  380. package/lib/vendor/blamejs/test/layer-0-primitives/json-schema.test.js +214 -0
  381. package/lib/vendor/blamejs/test/layer-0-primitives/jwk.test.js +41 -0
  382. package/lib/vendor/blamejs/test/layer-0-primitives/jwt-external.test.js +276 -0
  383. package/lib/vendor/blamejs/test/layer-0-primitives/keychain.test.js +0 -0
  384. package/lib/vendor/blamejs/test/layer-0-primitives/log-stream.test.js +241 -0
  385. package/lib/vendor/blamejs/test/layer-0-primitives/log.test.js +106 -0
  386. package/lib/vendor/blamejs/test/layer-0-primitives/mail-agent.test.js +441 -0
  387. package/lib/vendor/blamejs/test/layer-0-primitives/mail-auth.test.js +2136 -4
  388. package/lib/vendor/blamejs/test/layer-0-primitives/mail-bimi.test.js +759 -12
  389. package/lib/vendor/blamejs/test/layer-0-primitives/mail-bounce.test.js +811 -1
  390. package/lib/vendor/blamejs/test/layer-0-primitives/mail-crypto-pgp-experimental.test.js +401 -3
  391. package/lib/vendor/blamejs/test/layer-0-primitives/mail-crypto-pgp.test.js +751 -8
  392. package/lib/vendor/blamejs/test/layer-0-primitives/mail-crypto-smime.test.js +864 -0
  393. package/lib/vendor/blamejs/test/layer-0-primitives/mail-crypto.test.js +110 -0
  394. package/lib/vendor/blamejs/test/layer-0-primitives/mail-dav.test.js +830 -1
  395. package/lib/vendor/blamejs/test/layer-0-primitives/mail-deploy.test.js +635 -86
  396. package/lib/vendor/blamejs/test/layer-0-primitives/mail-dkim.test.js +818 -0
  397. package/lib/vendor/blamejs/test/layer-0-primitives/mail-helo.test.js +27 -0
  398. package/lib/vendor/blamejs/test/layer-0-primitives/mail-scan.test.js +199 -0
  399. package/lib/vendor/blamejs/test/layer-0-primitives/mail-send-deliver.test.js +686 -2
  400. package/lib/vendor/blamejs/test/layer-0-primitives/mail-server-imap.test.js +778 -0
  401. package/lib/vendor/blamejs/test/layer-0-primitives/mail-server-jmap.test.js +1438 -0
  402. package/lib/vendor/blamejs/test/layer-0-primitives/mail-server-managesieve.test.js +449 -6
  403. package/lib/vendor/blamejs/test/layer-0-primitives/mail-server-mx.test.js +773 -2
  404. package/lib/vendor/blamejs/test/layer-0-primitives/mail-server-pop3.test.js +623 -3
  405. package/lib/vendor/blamejs/test/layer-0-primitives/mail-server-rate-limit.test.js +55 -0
  406. package/lib/vendor/blamejs/test/layer-0-primitives/mail-server-registry.test.js +13 -0
  407. package/lib/vendor/blamejs/test/layer-0-primitives/mail-server-submission.test.js +877 -1
  408. package/lib/vendor/blamejs/test/layer-0-primitives/mail-sieve.test.js +326 -0
  409. package/lib/vendor/blamejs/test/layer-0-primitives/mail-store-fts.test.js +55 -0
  410. package/lib/vendor/blamejs/test/layer-0-primitives/mail-store.test.js +242 -0
  411. package/lib/vendor/blamejs/test/layer-0-primitives/mail.test.js +1596 -2
  412. package/lib/vendor/blamejs/test/layer-0-primitives/mcp.test.js +440 -4
  413. package/lib/vendor/blamejs/test/layer-0-primitives/metrics-snapshot.test.js +89 -0
  414. package/lib/vendor/blamejs/test/layer-0-primitives/metrics.test.js +1230 -0
  415. package/lib/vendor/blamejs/test/layer-0-primitives/middleware-assetlinks.test.js +113 -0
  416. package/lib/vendor/blamejs/test/layer-0-primitives/middleware-body-parser.test.js +1169 -0
  417. package/lib/vendor/blamejs/test/layer-0-primitives/middleware-bot-disclose.test.js +123 -0
  418. package/lib/vendor/blamejs/test/layer-0-primitives/middleware-cookies.test.js +108 -0
  419. package/lib/vendor/blamejs/test/layer-0-primitives/middleware-gpc.test.js +121 -0
  420. package/lib/vendor/blamejs/test/layer-0-primitives/middleware-headers.test.js +163 -0
  421. package/lib/vendor/blamejs/test/layer-0-primitives/middleware-host-allowlist.test.js +154 -0
  422. package/lib/vendor/blamejs/test/layer-0-primitives/middleware-require-content-type.test.js +127 -0
  423. package/lib/vendor/blamejs/test/layer-0-primitives/{middleware-tus-upload-coverage.test.js → middleware-tus-upload.test.js} +45 -0
  424. package/lib/vendor/blamejs/test/layer-0-primitives/middleware-web-app-manifest.test.js +132 -0
  425. package/lib/vendor/blamejs/test/layer-0-primitives/mtls-ca-crl-fingerprint-only.test.js +92 -0
  426. package/lib/vendor/blamejs/test/layer-0-primitives/network-dns-resolver.test.js +65 -0
  427. package/lib/vendor/blamejs/test/layer-0-primitives/network-dns.test.js +1727 -1
  428. package/lib/vendor/blamejs/test/layer-0-primitives/network-nts.test.js +699 -0
  429. package/lib/vendor/blamejs/test/layer-0-primitives/network-smtp-policy.test.js +1181 -0
  430. package/lib/vendor/blamejs/test/layer-0-primitives/network-tls.test.js +1876 -3
  431. package/lib/vendor/blamejs/test/layer-0-primitives/network.test.js +32 -0
  432. package/lib/vendor/blamejs/test/layer-0-primitives/nonce-store-enforce-replay-nonboolean.test.js +81 -0
  433. package/lib/vendor/blamejs/test/layer-0-primitives/ntp-check.test.js +122 -0
  434. package/lib/vendor/blamejs/test/layer-0-primitives/observability-tracing.test.js +378 -0
  435. package/lib/vendor/blamejs/test/layer-0-primitives/observability.test.js +77 -0
  436. package/lib/vendor/blamejs/test/layer-0-primitives/oid4vci.test.js +1016 -0
  437. package/lib/vendor/blamejs/test/layer-0-primitives/openid-federation.test.js +946 -0
  438. package/lib/vendor/blamejs/test/layer-0-primitives/outbox.test.js +818 -0
  439. package/lib/vendor/blamejs/test/layer-0-primitives/own-property-membership-guards.test.js +109 -0
  440. package/lib/vendor/blamejs/test/layer-0-primitives/parsers-safe-toml.test.js +543 -0
  441. package/lib/vendor/blamejs/test/layer-0-primitives/{parsers-safe-yaml-coverage.test.js → parsers-safe-yaml.test.js} +2 -2
  442. package/lib/vendor/blamejs/test/layer-0-primitives/parsers-standalone.test.js +73 -0
  443. package/lib/vendor/blamejs/test/layer-0-primitives/passkey.test.js +649 -0
  444. package/lib/vendor/blamejs/test/layer-0-primitives/permissions.test.js +524 -0
  445. package/lib/vendor/blamejs/test/layer-0-primitives/pqc-agent-curve.test.js +22 -0
  446. package/lib/vendor/blamejs/test/layer-0-primitives/pubsub.test.js +295 -0
  447. package/lib/vendor/blamejs/test/layer-0-primitives/queue-flow-repeat.test.js +36 -0
  448. package/lib/vendor/blamejs/test/layer-0-primitives/queue.test.js +83 -0
  449. package/lib/vendor/blamejs/test/layer-0-primitives/rate-limit-xff-spoofing.test.js +34 -0
  450. package/lib/vendor/blamejs/test/layer-0-primitives/redact.test.js +1031 -0
  451. package/lib/vendor/blamejs/test/layer-0-primitives/request-helpers.test.js +94 -0
  452. package/lib/vendor/blamejs/test/layer-0-primitives/require-bound-key.test.js +401 -0
  453. package/lib/vendor/blamejs/test/layer-0-primitives/restore-empty-manifest-wipe.test.js +154 -0
  454. package/lib/vendor/blamejs/test/layer-0-primitives/retention.test.js +600 -0
  455. package/lib/vendor/blamejs/test/layer-0-primitives/router-host-path-injection.test.js +231 -0
  456. package/lib/vendor/blamejs/test/layer-0-primitives/router-tls0rtt.test.js +21 -0
  457. package/lib/vendor/blamejs/test/layer-0-primitives/router.test.js +1277 -0
  458. package/lib/vendor/blamejs/test/layer-0-primitives/safe-async.test.js +133 -0
  459. package/lib/vendor/blamejs/test/layer-0-primitives/safe-buffer-linear-scans.test.js +14 -0
  460. package/lib/vendor/blamejs/test/layer-0-primitives/safe-buffer.test.js +80 -0
  461. package/lib/vendor/blamejs/test/layer-0-primitives/safe-decompress.test.js +28 -0
  462. package/lib/vendor/blamejs/test/layer-0-primitives/safe-dns.test.js +245 -0
  463. package/lib/vendor/blamejs/test/layer-0-primitives/safe-ical.test.js +32 -0
  464. package/lib/vendor/blamejs/test/layer-0-primitives/safe-ini.test.js +376 -0
  465. package/lib/vendor/blamejs/test/layer-0-primitives/safe-json.test.js +175 -0
  466. package/lib/vendor/blamejs/test/layer-0-primitives/safe-mime.test.js +518 -0
  467. package/lib/vendor/blamejs/test/layer-0-primitives/safe-object.test.js +62 -0
  468. package/lib/vendor/blamejs/test/layer-0-primitives/safe-path.test.js +30 -0
  469. package/lib/vendor/blamejs/test/layer-0-primitives/safe-schema.test.js +104 -0
  470. package/lib/vendor/blamejs/test/layer-0-primitives/safe-sql.test.js +142 -0
  471. package/lib/vendor/blamejs/test/layer-0-primitives/safe-url.test.js +112 -0
  472. package/lib/vendor/blamejs/test/layer-0-primitives/safe-vcard.test.js +26 -0
  473. package/lib/vendor/blamejs/test/layer-0-primitives/scheduler.test.js +157 -0
  474. package/lib/vendor/blamejs/test/layer-0-primitives/scim-server.test.js +396 -0
  475. package/lib/vendor/blamejs/test/layer-0-primitives/sd-jwt-vc.test.js +930 -0
  476. package/lib/vendor/blamejs/test/layer-0-primitives/security-assert.test.js +755 -82
  477. package/lib/vendor/blamejs/test/layer-0-primitives/self-update.test.js +1053 -0
  478. package/lib/vendor/blamejs/test/layer-0-primitives/session-device-binding.test.js +200 -0
  479. package/lib/vendor/blamejs/test/layer-0-primitives/session-strict-binding-missing-failclosed.test.js +110 -0
  480. package/lib/vendor/blamejs/test/layer-0-primitives/sigv4-bucket-ops.test.js +636 -0
  481. package/lib/vendor/blamejs/test/layer-0-primitives/sql-offset-without-limit.test.js +94 -0
  482. package/lib/vendor/blamejs/test/layer-0-primitives/sql.test.js +1190 -0
  483. package/lib/vendor/blamejs/test/layer-0-primitives/ssrf-guard.test.js +21 -0
  484. package/lib/vendor/blamejs/test/layer-0-primitives/static.test.js +850 -0
  485. package/lib/vendor/blamejs/test/layer-0-primitives/storage-presigned-url.test.js +146 -0
  486. package/lib/vendor/blamejs/test/layer-0-primitives/storage.test.js +621 -0
  487. package/lib/vendor/blamejs/test/layer-0-primitives/subject.test.js +47 -0
  488. package/lib/vendor/blamejs/test/layer-0-primitives/template.test.js +582 -0
  489. package/lib/vendor/blamejs/test/layer-0-primitives/tenant-quota.test.js +587 -25
  490. package/lib/vendor/blamejs/test/layer-0-primitives/time.test.js +11 -0
  491. package/lib/vendor/blamejs/test/layer-0-primitives/tsa.test.js +524 -63
  492. package/lib/vendor/blamejs/test/layer-0-primitives/uri-template.test.js +27 -0
  493. package/lib/vendor/blamejs/test/layer-0-primitives/vault-rotate.test.js +866 -0
  494. package/lib/vendor/blamejs/test/layer-0-primitives/vault.test.js +74 -0
  495. package/lib/vendor/blamejs/test/layer-0-primitives/vc.test.js +215 -0
  496. package/lib/vendor/blamejs/test/layer-0-primitives/watcher.test.js +550 -0
  497. package/lib/vendor/blamejs/test/layer-0-primitives/webhook-dispatcher.test.js +388 -0
  498. package/lib/vendor/blamejs/test/layer-0-primitives/webhook.test.js +262 -0
  499. package/lib/vendor/blamejs/test/layer-0-primitives/websocket.test.js +1294 -0
  500. package/lib/vendor/blamejs/test/layer-0-primitives/ws-client.test.js +629 -0
  501. package/lib/vendor/blamejs/test/layer-0-primitives/xml-c14n-attr-normalization.test.js +164 -0
  502. package/lib/vendor/blamejs/test/smoke.js +2 -0
  503. package/package.json +1 -1
  504. package/lib/vendor/blamejs/release-notes/v0.16.0.json +0 -44
  505. package/lib/vendor/blamejs/release-notes/v0.16.1.json +0 -36
  506. package/lib/vendor/blamejs/release-notes/v0.16.2.json +0 -71
  507. package/lib/vendor/blamejs/release-notes/v0.16.3.json +0 -71
  508. package/lib/vendor/blamejs/test/layer-0-primitives/acme-coverage.test.js +0 -441
  509. package/lib/vendor/blamejs/test/layer-0-primitives/auth-oauth-coverage.test.js +0 -482
  510. package/lib/vendor/blamejs/test/layer-0-primitives/auth-saml-coverage.test.js +0 -671
  511. package/lib/vendor/blamejs/test/layer-0-primitives/backup-index-coverage.test.js +0 -690
  512. package/lib/vendor/blamejs/test/layer-0-primitives/cli-coverage.test.js +0 -238
  513. package/lib/vendor/blamejs/test/layer-0-primitives/content-credentials-coverage.test.js +0 -319
  514. package/lib/vendor/blamejs/test/layer-0-primitives/keychain-coverage.test.js +0 -0
  515. package/lib/vendor/blamejs/test/layer-0-primitives/mail-auth-coverage.test.js +0 -437
  516. package/lib/vendor/blamejs/test/layer-0-primitives/mcp-coverage.test.js +0 -443
  517. package/lib/vendor/blamejs/test/layer-0-primitives/metrics-coverage.test.js +0 -395
  518. package/lib/vendor/blamejs/test/layer-0-primitives/network-smtp-policy-coverage.test.js +0 -565
  519. package/lib/vendor/blamejs/test/layer-0-primitives/router-coverage.test.js +0 -592
  520. package/lib/vendor/blamejs/test/layer-0-primitives/sql-coverage.test.js +0 -422
  521. package/lib/vendor/blamejs/test/layer-0-primitives/test-coverage.test.js +0 -573
@@ -0,0 +1,1294 @@
1
+ // SPDX-License-Identifier: Apache-2.0
2
+ // Copyright (c) blamejs contributors
3
+ "use strict";
4
+ /**
5
+ * websocket — RFC 6455 server + RFC 8441 h2 Extended CONNECT.
6
+ *
7
+ * Covers the handshake helpers (b.websocket.WebSocketError,
8
+ * buildUpgradeResponse, computeAcceptKey, validateUpgradeRequest,
9
+ * negotiateSubprotocol, isOriginAllowed), the frame layer (FrameParser
10
+ * + serializeFrame against adversarial frames — oversized, over-length,
11
+ * masked/unmasked, extended lengths), the WebSocketConnection state
12
+ * machine (send/ping/close, fragmentation, control-frame caps, close-
13
+ * code allowlist, UTF-8 validation, permessage-deflate, heartbeat), and
14
+ * the server-side entry points (handleUpgrade + handleExtendedConnect
15
+ * refusal + success paths) driven through injected socket / h2-stream
16
+ * stubs — never the real network.
17
+ *
18
+ * Run standalone: `node test/layer-0-primitives/websocket.test.js`
19
+ * Or via smoke: `node test/smoke.js`
20
+ */
21
+
22
+ var EventEmitter = require("node:events").EventEmitter;
23
+ var zlib = require("node:zlib");
24
+
25
+ var helpers = require("../helpers");
26
+ var b = helpers.b;
27
+ var check = helpers.check;
28
+
29
+ var ws = b.websocket;
30
+
31
+ // RFC 6455 §1.3 canonical example.
32
+ var RFC_KEY = "dGhlIHNhbXBsZSBub25jZQ==";
33
+ var RFC_ACCEPT = "s3pPLMBiTxaQ9kYGzzhZRbK+xOo=";
34
+
35
+ // ---- injected stubs (no network) ----
36
+
37
+ // A Duplex-shaped socket stub. WebSocketConnection registers
38
+ // data/error/close/end listeners and calls write/end/destroy — this
39
+ // captures every server-side write as a raw chunk and lets the test
40
+ // drive inbound bytes via socket.emit("data", frame).
41
+ function makeSocket(opts) {
42
+ opts = opts || {};
43
+ var s = new EventEmitter();
44
+ s.written = [];
45
+ s.destroyed = false;
46
+ s.writable = true;
47
+ s.ended = false;
48
+ s.write = function (chunk) {
49
+ if (opts.writeThrows) throw new Error("write EPIPE");
50
+ s.written.push(chunk); // raw — strings (101 response) stay strings
51
+ return true;
52
+ };
53
+ s.end = function () { s.ended = true; s.writable = false; };
54
+ s.destroy = function () { s.destroyed = true; s.writable = false; };
55
+ return s;
56
+ }
57
+
58
+ // An h2 stream stub for handleExtendedConnect. Adds respond()/close()
59
+ // on top of the socket surface WebSocketConnection consumes.
60
+ function makeH2Stream(opts) {
61
+ opts = opts || {};
62
+ var s = new EventEmitter();
63
+ s.written = [];
64
+ s.responded = null;
65
+ s.ended = false;
66
+ s.closed = false;
67
+ s.destroyed = false;
68
+ s.writable = true;
69
+ s.respond = function (headers) {
70
+ if (opts.respondThrows) throw new Error("h2 respond failed");
71
+ s.responded = headers;
72
+ };
73
+ s.end = function (data) { s.ended = true; if (data !== undefined) s.endData = data; s.writable = false; };
74
+ s.close = function () { s.closed = true; s.writable = false; };
75
+ s.write = function (chunk) { s.written.push(chunk); return true; };
76
+ s.destroy = function () { s.destroyed = true; s.writable = false; };
77
+ return s;
78
+ }
79
+
80
+ // Parse every Buffer chunk the server wrote back into frames.
81
+ function serverFrames(socket) {
82
+ var bufs = socket.written.filter(function (w) { return Buffer.isBuffer(w); });
83
+ if (bufs.length === 0) return [];
84
+ var fp = new ws.FrameParser();
85
+ return fp.push(Buffer.concat(bufs));
86
+ }
87
+
88
+ // Build a masked client→server frame (RFC 6455 §5.3: client frames MUST
89
+ // be masked). serializeFrame with mask:true is exactly the client shape.
90
+ function clientFrame(opcode, payload, extra) {
91
+ var o = Object.assign({ mask: true }, extra || {});
92
+ return ws.serializeFrame(opcode, payload, o);
93
+ }
94
+
95
+ // serializeFrame only wires RSV1; set RSV2/RSV3 (or any header-byte-0
96
+ // bit) by mutating the flags byte of an already-built masked frame.
97
+ function withByte0Bit(frame, bit) {
98
+ frame[0] = frame[0] | bit;
99
+ return frame;
100
+ }
101
+
102
+ function closePayload(code, reason) {
103
+ var r = reason ? (Buffer.isBuffer(reason) ? reason : Buffer.from(reason, "utf8")) : Buffer.alloc(0);
104
+ var buf = Buffer.alloc(2 + r.length);
105
+ buf.writeUInt16BE(code, 0);
106
+ if (r.length) r.copy(buf, 2);
107
+ return buf;
108
+ }
109
+
110
+ function upgradeReq(extraHeaders, url) {
111
+ var h = Object.assign({
112
+ upgrade: "websocket",
113
+ connection: "Upgrade",
114
+ "sec-websocket-key": RFC_KEY,
115
+ "sec-websocket-version": "13",
116
+ host: "app.example.com",
117
+ origin: "https://app.example.com",
118
+ }, extraHeaders || {});
119
+ return { method: "GET", url: url || "/ws", headers: h };
120
+ }
121
+
122
+ // Ensure a connection's ping timer is stopped (unref'd, but transition
123
+ // releases it cleanly). Idempotent.
124
+ function teardown(conn, socket) {
125
+ if (conn && conn.readyState !== "closed") socket.emit("close");
126
+ }
127
+
128
+ // ============================================================
129
+ // Existing handshake-helper coverage
130
+ // ============================================================
131
+
132
+ function testWebSocketError() {
133
+ var err = new ws.WebSocketError("ws/closed", "send() on a closed connection", 1002);
134
+ check("WebSocketError is an Error subclass", err instanceof Error);
135
+ check("WebSocketError carries the framework code", err.code === "ws/closed");
136
+ check("WebSocketError carries the message", err.message === "send() on a closed connection");
137
+ check("WebSocketError carries the RFC closeCode", err.closeCode === 1002);
138
+ check("WebSocketError flags isWebSocketError", err.isWebSocketError === true);
139
+ check("WebSocketError name is WebSocketError", err.name === "WebSocketError");
140
+
141
+ // Omitted closeCode defaults to 1002 (protocol error).
142
+ var dflt = new ws.WebSocketError("ws/proto", "bad frame");
143
+ check("WebSocketError defaults closeCode to CLOSE_PROTOCOL_ERROR (1002)",
144
+ dflt.closeCode === ws.CLOSE_PROTOCOL_ERROR && dflt.closeCode === 1002);
145
+ }
146
+
147
+ function testBuildUpgradeResponse() {
148
+ var resp = ws.buildUpgradeResponse(RFC_KEY, null, null);
149
+ check("buildUpgradeResponse starts with 101 Switching Protocols",
150
+ resp.indexOf("HTTP/1.1 101 Switching Protocols\r\n") === 0);
151
+ check("buildUpgradeResponse emits Upgrade: websocket",
152
+ /\r\nUpgrade: websocket\r\n/.test(resp));
153
+ check("buildUpgradeResponse emits Connection: Upgrade",
154
+ /\r\nConnection: Upgrade\r\n/.test(resp));
155
+ check("buildUpgradeResponse computes the RFC 6455 Sec-WebSocket-Accept",
156
+ resp.indexOf("Sec-WebSocket-Accept: " + RFC_ACCEPT + "\r\n") !== -1);
157
+ check("buildUpgradeResponse terminates with a blank line",
158
+ resp.slice(-4) === "\r\n\r\n");
159
+ check("buildUpgradeResponse omits Sec-WebSocket-Protocol when subprotocol is null",
160
+ resp.indexOf("Sec-WebSocket-Protocol") === -1);
161
+ check("buildUpgradeResponse omits Sec-WebSocket-Extensions when null",
162
+ resp.indexOf("Sec-WebSocket-Extensions") === -1);
163
+
164
+ check("buildUpgradeResponse Accept agrees with computeAcceptKey",
165
+ resp.indexOf("Sec-WebSocket-Accept: " + ws.computeAcceptKey(RFC_KEY) + "\r\n") !== -1);
166
+
167
+ var resp2 = ws.buildUpgradeResponse(RFC_KEY, "chat.v1", "permessage-deflate; server_no_context_takeover");
168
+ check("buildUpgradeResponse includes Sec-WebSocket-Protocol when subprotocol given",
169
+ /\r\nSec-WebSocket-Protocol: chat\.v1\r\n/.test(resp2));
170
+ check("buildUpgradeResponse includes Sec-WebSocket-Extensions when given",
171
+ resp2.indexOf("Sec-WebSocket-Extensions: permessage-deflate; server_no_context_takeover\r\n") !== -1);
172
+ check("buildUpgradeResponse with options still terminates with a blank line",
173
+ resp2.slice(-4) === "\r\n\r\n");
174
+ }
175
+
176
+ function testComputeAcceptKeyCustomGuid() {
177
+ var guid = "12345678-1234-1234-1234-1234567890AB";
178
+ var custom = ws.computeAcceptKey(RFC_KEY, guid);
179
+ check("computeAcceptKey with a custom GUID differs from the RFC default",
180
+ custom !== ws.computeAcceptKey(RFC_KEY));
181
+ check("computeAcceptKey with a custom GUID is deterministic",
182
+ custom === ws.computeAcceptKey(RFC_KEY, guid));
183
+ }
184
+
185
+ // ============================================================
186
+ // validateUpgradeRequest — every refusal branch
187
+ // ============================================================
188
+
189
+ function testValidateUpgradeRequest() {
190
+ check("validate: valid handshake ok",
191
+ ws.validateUpgradeRequest(upgradeReq(), {}).ok === true);
192
+
193
+ var m = ws.validateUpgradeRequest({ method: "POST", headers: upgradeReq().headers }, {});
194
+ check("validate: non-GET refused 405",
195
+ m.ok === false && m.status === 405 && /GET/.test(m.reason));
196
+
197
+ var u = ws.validateUpgradeRequest(upgradeReq({ upgrade: "h2c" }), {});
198
+ check("validate: missing Upgrade: websocket refused 400",
199
+ u.ok === false && u.status === 400 && /Upgrade/.test(u.reason));
200
+
201
+ var c = ws.validateUpgradeRequest(upgradeReq({ connection: "keep-alive" }), {});
202
+ check("validate: missing Connection: upgrade refused 400",
203
+ c.ok === false && /Connection/.test(c.reason));
204
+
205
+ // Multi-token Connection header ("keep-alive, Upgrade") still matches.
206
+ check("validate: multi-token Connection: keep-alive, Upgrade accepted",
207
+ ws.validateUpgradeRequest(upgradeReq({ connection: "keep-alive, Upgrade" }), {}).ok === true);
208
+
209
+ var noKey = upgradeReq();
210
+ delete noKey.headers["sec-websocket-key"];
211
+ var k = ws.validateUpgradeRequest(noKey, {});
212
+ check("validate: missing Sec-WebSocket-Key refused 400",
213
+ k.ok === false && /Sec-WebSocket-Key/.test(k.reason));
214
+
215
+ var badKey = ws.validateUpgradeRequest(upgradeReq({ "sec-websocket-key": "not-base64" }), {});
216
+ check("validate: malformed Sec-WebSocket-Key refused 400",
217
+ badKey.ok === false && /base64/.test(badKey.reason));
218
+
219
+ var ver = ws.validateUpgradeRequest(upgradeReq({ "sec-websocket-version": "8" }), {});
220
+ check("validate: wrong Sec-WebSocket-Version refused 400",
221
+ ver.ok === false && /Version/.test(ver.reason));
222
+
223
+ check("validate: missing headers object refused (no Upgrade)",
224
+ ws.validateUpgradeRequest({ method: "GET" }, {}).ok === false);
225
+ }
226
+
227
+ function testValidateCredentialQueryRefusal() {
228
+ var leak = ws.validateUpgradeRequest(upgradeReq({}, "/ws?access_token=abc"), {});
229
+ check("validate: credential query param refused 400",
230
+ leak.ok === false && /access_token/.test(leak.reason));
231
+
232
+ // URL-encoded param name still decodes + matches.
233
+ var enc = ws.validateUpgradeRequest(upgradeReq({}, "/ws?%61pi_key=abc"), {});
234
+ check("validate: URL-encoded credential param name still refused",
235
+ enc.ok === false && /api_key/.test(enc.reason));
236
+
237
+ // Malformed percent-encoding in an earlier param hits the decode
238
+ // catch, then a later credential param still matches.
239
+ var mal = ws.validateUpgradeRequest(upgradeReq({}, "/ws?%=1&apikey=x"), {});
240
+ check("validate: decode-error param falls through, later credential refused",
241
+ mal.ok === false && /apikey/.test(mal.reason));
242
+
243
+ // Fragment after the query is stripped before scanning.
244
+ check("validate: non-credential query with fragment accepted",
245
+ ws.validateUpgradeRequest(upgradeReq({}, "/ws?room=5#frag"), {}).ok === true);
246
+
247
+ // Param without '=' and empty pairs are skipped, not matched.
248
+ check("validate: bare + empty query pairs accepted",
249
+ ws.validateUpgradeRequest(upgradeReq({}, "/ws?flag&&room=1"), {}).ok === true);
250
+
251
+ // No query string at all.
252
+ check("validate: no query string accepted",
253
+ ws.validateUpgradeRequest(upgradeReq({}, "/ws"), {}).ok === true);
254
+
255
+ // Opt-out lets the credential-shaped param through.
256
+ check("validate: allowQueryAuthParams bypasses the refusal",
257
+ ws.validateUpgradeRequest(upgradeReq({}, "/ws?access_token=abc"),
258
+ { allowQueryAuthParams: true }).ok === true);
259
+ }
260
+
261
+ // ============================================================
262
+ // negotiateSubprotocol + isOriginAllowed — pure branches
263
+ // ============================================================
264
+
265
+ function testNegotiateSubprotocol() {
266
+ var req = { headers: { "sec-websocket-protocol": "chat.v2, chat.v1" } };
267
+ check("negotiate: no supported list returns null",
268
+ ws.negotiateSubprotocol(req, null) === null);
269
+ check("negotiate: empty supported list returns null",
270
+ ws.negotiateSubprotocol(req, []) === null);
271
+ check("negotiate: picks first client-offered that is supported",
272
+ ws.negotiateSubprotocol(req, ["chat.v1"]) === "chat.v1");
273
+ check("negotiate: honours client preference order",
274
+ ws.negotiateSubprotocol(req, ["chat.v1", "chat.v2"]) === "chat.v2");
275
+ check("negotiate: no intersection returns null",
276
+ ws.negotiateSubprotocol(req, ["chat.v9"]) === null);
277
+ check("negotiate: absent header with supported list returns null",
278
+ ws.negotiateSubprotocol({ headers: {} }, ["chat.v1"]) === null);
279
+ }
280
+
281
+ function testIsOriginAllowed() {
282
+ var same = { headers: { origin: "https://app.example.com", host: "app.example.com" } };
283
+ check("origin: '*' accept-all returns true",
284
+ ws.isOriginAllowed(same, "*") === true);
285
+ check("origin: default same-origin match returns true",
286
+ ws.isOriginAllowed(same, undefined) === true);
287
+
288
+ var cross = { headers: { origin: "https://evil.example.com", host: "app.example.com" } };
289
+ check("origin: default same-origin mismatch returns false",
290
+ ws.isOriginAllowed(cross, undefined) === false);
291
+
292
+ check("origin: array allowlist match returns true",
293
+ ws.isOriginAllowed(same, ["https://app.example.com"]) === true);
294
+ check("origin: array allowlist miss returns false",
295
+ ws.isOriginAllowed(same, ["https://other.example"]) === false);
296
+
297
+ check("origin: no Origin header (non-browser) bypasses to true",
298
+ ws.isOriginAllowed({ headers: { host: "app.example.com" } }, undefined) === true);
299
+
300
+ check("origin: default with Origin but no Host returns false",
301
+ ws.isOriginAllowed({ headers: { origin: "https://app.example.com" } }, undefined) === false);
302
+
303
+ check("origin: malformed Origin URL returns false (parse catch)",
304
+ ws.isOriginAllowed({ headers: { origin: "::::not a url", host: "app.example.com" } }, undefined) === false);
305
+
306
+ // origins present but not "*", not array, not falsy (e.g. a bogus
307
+ // string) falls through to the final `return false`.
308
+ check("origin: unrecognized origins shape returns false",
309
+ ws.isOriginAllowed(same, "https://app.example.com") === false);
310
+ }
311
+
312
+ // ============================================================
313
+ // FrameParser — adversarial + extended-length frames
314
+ // ============================================================
315
+
316
+ function testFrameParserRoundTrip() {
317
+ var fp = new ws.FrameParser();
318
+ var frames = fp.push(clientFrame(ws.OPCODE_TEXT, "hello"));
319
+ check("parser: one complete masked text frame",
320
+ frames.length === 1 && frames[0].opcode === ws.OPCODE_TEXT);
321
+ check("parser: unmasks the payload",
322
+ frames[0].payload.toString("utf8") === "hello" && frames[0].masked === true);
323
+ check("parser: fin bit decoded",
324
+ frames[0].fin === true);
325
+
326
+ // Unmasked (server-shape) frame — the copy-out branch.
327
+ var fp2 = new ws.FrameParser();
328
+ var f2 = fp2.push(ws.serializeFrame(ws.OPCODE_BINARY, Buffer.from([1, 2, 3])));
329
+ check("parser: unmasked frame copied out",
330
+ f2.length === 1 && f2[0].masked === false && f2[0].payload.length === 3);
331
+ }
332
+
333
+ function testFrameParserExtendedLengths() {
334
+ // 126 => 16-bit extended length.
335
+ var p16 = Buffer.alloc(200, 0x61);
336
+ var fp16 = new ws.FrameParser();
337
+ var f16 = fp16.push(clientFrame(ws.OPCODE_BINARY, p16));
338
+ check("parser: 16-bit extended length frame",
339
+ f16.length === 1 && f16[0].payload.length === 200);
340
+
341
+ // 127 => 64-bit extended length.
342
+ var p64 = Buffer.alloc(70000, 0x62);
343
+ var fp64 = new ws.FrameParser();
344
+ var f64 = fp64.push(clientFrame(ws.OPCODE_BINARY, p64));
345
+ check("parser: 64-bit extended length frame",
346
+ f64.length === 1 && f64[0].payload.length === 70000);
347
+ }
348
+
349
+ function testFrameParserIncremental() {
350
+ // Masked "chunked": headerLen = 2 + 4 mask = 6, payload = 7, total 13.
351
+ var full = clientFrame(ws.OPCODE_TEXT, "chunked");
352
+ var fp = new ws.FrameParser();
353
+ check("parser: single byte is incomplete (< 2 header bytes)",
354
+ fp.push(full.subarray(0, 1)).length === 0);
355
+ // 4 bytes: past the 2-byte minimum but short of the 6-byte masked
356
+ // header (exercises the header-pending return).
357
+ check("parser: partial header (2..5 bytes) is incomplete",
358
+ fp.push(full.subarray(1, 4)).length === 0);
359
+ // 8 bytes: full 6-byte header + 2 payload bytes — header complete but
360
+ // the payload is not (the payload-pending return, distinct from above).
361
+ check("parser: full header but partial payload is incomplete",
362
+ fp.push(full.subarray(4, 8)).length === 0);
363
+ var done = fp.push(full.subarray(8));
364
+ check("parser: completes once all bytes arrive",
365
+ done.length === 1 && done[0].payload.toString("utf8") === "chunked");
366
+ }
367
+
368
+ function testFrameParserFrameTooLarge() {
369
+ var fp = new ws.FrameParser({ maxFrameBytes: 4 });
370
+ var big = clientFrame(ws.OPCODE_BINARY, Buffer.alloc(100));
371
+ var threw = null;
372
+ try { fp.push(big); } catch (e) { threw = e; }
373
+ check("parser: over-maxFrameBytes throws WebSocketError",
374
+ threw && threw.isWebSocketError === true);
375
+ check("parser: frame-too-large carries closeCode 1009",
376
+ threw && threw.closeCode === ws.CLOSE_MESSAGE_TOO_BIG && threw.closeCode === 1009);
377
+ }
378
+
379
+ function testFrameParser64BitOverflow() {
380
+ // Hand-craft a 127-length frame whose high 32 bits exceed 0x1FFFFF
381
+ // (would overflow Number.MAX_SAFE_INTEGER). Masked so headerLen has
382
+ // the 4 mask bytes present.
383
+ var header = Buffer.alloc(2 + 8 + 4);
384
+ header[0] = 0x82; // fin + BINARY
385
+ header[1] = 0x80 | 127; // masked + 64-bit length indicator
386
+ header.writeUInt32BE(0x00200000, 2); // hi = 0x200000 > 0x1FFFFF
387
+ header.writeUInt32BE(0x00000000, 6); // lo
388
+ // 4 mask bytes already zero-filled.
389
+ var fp = new ws.FrameParser({ maxFrameBytes: 1000000 });
390
+ var threw = null;
391
+ try { fp.push(header); } catch (e) { threw = e; }
392
+ check("parser: 64-bit length past MAX_SAFE_INTEGER throws",
393
+ threw && threw.isWebSocketError === true && /MAX_SAFE_INTEGER/.test(threw.message));
394
+ }
395
+
396
+ // ============================================================
397
+ // serializeFrame — masking, extended lengths, invalid payload
398
+ // ============================================================
399
+
400
+ function testSerializeFrame() {
401
+ var basic = ws.serializeFrame(ws.OPCODE_TEXT, "hi");
402
+ check("serialize: basic unmasked text frame header",
403
+ basic[0] === 0x81 && (basic[1] & 0x80) === 0 && basic[1] === 2);
404
+
405
+ // Round-trip a masked frame — mask bit set, payload recovered.
406
+ var masked = ws.serializeFrame(ws.OPCODE_BINARY, Buffer.from([9, 8, 7]), { mask: true });
407
+ check("serialize: mask bit set on masked frame",
408
+ (masked[1] & 0x80) !== 0);
409
+ var rt = new ws.FrameParser().push(masked);
410
+ check("serialize: masked frame round-trips through the parser",
411
+ rt.length === 1 && rt[0].payload.length === 3 && rt[0].payload[0] === 9);
412
+
413
+ // fin:false + rsv1 header bits.
414
+ var frag = ws.serializeFrame(ws.OPCODE_TEXT, "x", { fin: false, rsv1: true });
415
+ check("serialize: fin:false clears the FIN bit", (frag[0] & 0x80) === 0);
416
+ check("serialize: rsv1:true sets the RSV1 bit", (frag[0] & 0x40) !== 0);
417
+
418
+ // 16-bit + 64-bit extended-length encodings round-trip.
419
+ var r16 = new ws.FrameParser().push(ws.serializeFrame(ws.OPCODE_BINARY, Buffer.alloc(300)));
420
+ check("serialize: 16-bit length round-trips", r16[0].payload.length === 300);
421
+ var r64 = new ws.FrameParser().push(ws.serializeFrame(ws.OPCODE_BINARY, Buffer.alloc(70000)));
422
+ check("serialize: 64-bit length round-trips", r64[0].payload.length === 70000);
423
+
424
+ // Null payload => empty frame.
425
+ var empty = ws.serializeFrame(ws.OPCODE_PING, null);
426
+ check("serialize: null payload yields a zero-length frame", empty[1] === 0);
427
+
428
+ // Non-buffer/non-string payload throws.
429
+ var threw = null;
430
+ try { ws.serializeFrame(ws.OPCODE_TEXT, 12345); } catch (e) { threw = e; }
431
+ check("serialize: numeric payload throws WebSocketError",
432
+ threw && threw.isWebSocketError === true && threw.code === "ws/invalid-payload");
433
+ }
434
+
435
+ // ============================================================
436
+ // WebSocketConnection — send / ping / close surface
437
+ // ============================================================
438
+
439
+ function testConnectionSendVariants() {
440
+ var socket = makeSocket();
441
+ var conn = new ws.WebSocketConnection(socket, { closeGraceMs: 10 });
442
+ try {
443
+ check("conn: initial readyState is open", conn.readyState === "open");
444
+
445
+ conn.send("a string");
446
+ conn.send(Buffer.from([0xde, 0xad]));
447
+ conn.send(new Uint8Array([1, 2, 3]));
448
+ var frames = serverFrames(socket);
449
+ check("conn: string send emits a TEXT frame",
450
+ frames[0] && frames[0].opcode === ws.OPCODE_TEXT && frames[0].payload.toString() === "a string");
451
+ check("conn: Buffer send emits a BINARY frame",
452
+ frames[1] && frames[1].opcode === ws.OPCODE_BINARY);
453
+ check("conn: Uint8Array send routes through toBuffer to BINARY",
454
+ frames[2] && frames[2].opcode === ws.OPCODE_BINARY && frames[2].payload.length === 3);
455
+ } finally { teardown(conn, socket); }
456
+ }
457
+
458
+ function testConnectionSendInvalidPayload() {
459
+ var socket = makeSocket();
460
+ var conn = new ws.WebSocketConnection(socket, { closeGraceMs: 10 });
461
+ try {
462
+ var threw = null;
463
+ try { conn.send(12345); } catch (e) { threw = e; }
464
+ check("conn: send(non-buffer/non-string) throws WebSocketError",
465
+ threw && threw.isWebSocketError === true && threw.code === "ws/invalid-payload");
466
+ } finally { teardown(conn, socket); }
467
+ }
468
+
469
+ function testConnectionSendRejectsWhenClosed() {
470
+ var socket = makeSocket();
471
+ var conn = new ws.WebSocketConnection(socket, { closeGraceMs: 10 });
472
+ socket.emit("close"); // → transition to CLOSED
473
+ check("conn: closed after socket close", conn.readyState === "closed");
474
+ var threw = null;
475
+ try { conn.send("late"); } catch (e) { threw = e; }
476
+ check("conn: send() on a closed connection throws ws/closed",
477
+ threw && threw.isWebSocketError === true && threw.code === "ws/closed");
478
+ }
479
+
480
+ function testConnectionPing() {
481
+ var socket = makeSocket();
482
+ var conn = new ws.WebSocketConnection(socket, { closeGraceMs: 10 });
483
+ try {
484
+ conn.ping(Buffer.from("pong-me"));
485
+ var frames = serverFrames(socket);
486
+ check("conn: ping() emits a PING frame with the payload",
487
+ frames[0] && frames[0].opcode === ws.OPCODE_PING && frames[0].payload.toString() === "pong-me");
488
+ } finally { teardown(conn, socket); }
489
+
490
+ // ping() on a non-open connection is a silent no-op.
491
+ var s2 = makeSocket();
492
+ var c2 = new ws.WebSocketConnection(s2, { closeGraceMs: 10 });
493
+ s2.emit("close");
494
+ c2.ping(Buffer.from("ignored"));
495
+ check("conn: ping() after close writes nothing", serverFrames(s2).length === 0);
496
+ }
497
+
498
+ function testConnectionClose() {
499
+ var socket = makeSocket();
500
+ var conn = new ws.WebSocketConnection(socket, { closeGraceMs: 10 });
501
+ conn.close(1000, "bye");
502
+ check("conn: close() moves to closing state", conn.readyState === "closing");
503
+ var frames = serverFrames(socket);
504
+ check("conn: close() writes a CLOSE frame with the code + reason",
505
+ frames[0] && frames[0].opcode === ws.OPCODE_CLOSE &&
506
+ frames[0].payload.readUInt16BE(0) === 1000 &&
507
+ frames[0].payload.subarray(2).toString("utf8") === "bye");
508
+
509
+ // A second close() while not OPEN is a no-op.
510
+ var before = socket.written.length;
511
+ conn.close(1001, "again");
512
+ check("conn: second close() is a no-op", socket.written.length === before);
513
+ teardown(conn, socket);
514
+ }
515
+
516
+ async function testConnectionCloseGraceTimerFires() {
517
+ // When the peer never echoes the close frame, the grace timer fires,
518
+ // half-closes the socket, and transitions with wasClean:false.
519
+ await helpers.withTestTimeout("ws close: grace timer fires", async function () {
520
+ var socket = makeSocket();
521
+ var conn = new ws.WebSocketConnection(socket, { closeGraceMs: 10 });
522
+ var closeArgs = null;
523
+ conn.on("close", function (code, reason, wasClean) { closeArgs = { code: code, wasClean: wasClean }; });
524
+ conn.close(1000, "bye");
525
+ await helpers.waitUntil(function () { return conn.readyState === "closed"; },
526
+ { label: "ws close: grace timer transitioned to closed" });
527
+ check("conn: grace timer transitions closed with wasClean false (no peer echo)",
528
+ closeArgs && closeArgs.code === 1000 && closeArgs.wasClean === false);
529
+ check("conn: grace timer half-closes the socket", socket.ended === true);
530
+ }, { timeoutMs: 3000 });
531
+ }
532
+
533
+ function testConnectionCloseDefaultsCode() {
534
+ var socket = makeSocket();
535
+ var conn = new ws.WebSocketConnection(socket, { closeGraceMs: 10 });
536
+ conn.close();
537
+ var frames = serverFrames(socket);
538
+ check("conn: close() with no code defaults to 1000",
539
+ frames[0] && frames[0].payload.readUInt16BE(0) === 1000);
540
+ teardown(conn, socket);
541
+ }
542
+
543
+ // ============================================================
544
+ // WebSocketConnection — inbound frame handling
545
+ // ============================================================
546
+
547
+ function testConnectionReceiveMessages() {
548
+ var socket = makeSocket();
549
+ var conn = new ws.WebSocketConnection(socket, { closeGraceMs: 10 });
550
+ try {
551
+ var got = [];
552
+ conn.on("message", function (data, isBinary) { got.push({ data: data, isBinary: isBinary }); });
553
+ socket.emit("data", clientFrame(ws.OPCODE_TEXT, "hello text"));
554
+ socket.emit("data", clientFrame(ws.OPCODE_BINARY, Buffer.from([1, 2, 3, 4])));
555
+ check("conn: TEXT frame emits a string message (isBinary false)",
556
+ got[0] && got[0].data === "hello text" && got[0].isBinary === false);
557
+ check("conn: BINARY frame emits a Buffer message (isBinary true)",
558
+ got[1] && Buffer.isBuffer(got[1].data) && got[1].isBinary === true);
559
+ } finally { teardown(conn, socket); }
560
+ }
561
+
562
+ function testConnectionFragmentedMessage() {
563
+ var socket = makeSocket();
564
+ var conn = new ws.WebSocketConnection(socket, { closeGraceMs: 10 });
565
+ try {
566
+ var got = null;
567
+ conn.on("message", function (data) { got = data; });
568
+ socket.emit("data", clientFrame(ws.OPCODE_TEXT, "Hel", { fin: false }));
569
+ socket.emit("data", clientFrame(ws.OPCODE_CONTINUATION, "lo ", { fin: false }));
570
+ socket.emit("data", clientFrame(ws.OPCODE_CONTINUATION, "world"));
571
+ check("conn: fragmented TEXT reassembles across continuation frames",
572
+ got === "Hello world");
573
+ } finally { teardown(conn, socket); }
574
+ }
575
+
576
+ function testConnectionPingPong() {
577
+ var socket = makeSocket();
578
+ var conn = new ws.WebSocketConnection(socket, { closeGraceMs: 10 });
579
+ try {
580
+ var pingSeen = null, pongSeen = null;
581
+ conn.on("ping", function (p) { pingSeen = p; });
582
+ conn.on("pong", function (p) { pongSeen = p; });
583
+ socket.emit("data", clientFrame(ws.OPCODE_PING, Buffer.from("hb")));
584
+ check("conn: inbound PING emits 'ping'", pingSeen && pingSeen.toString() === "hb");
585
+ var frames = serverFrames(socket);
586
+ check("conn: inbound PING is auto-answered with a PONG echo",
587
+ frames.some(function (f) { return f.opcode === ws.OPCODE_PONG && f.payload.toString() === "hb"; }));
588
+ socket.emit("data", clientFrame(ws.OPCODE_PONG, Buffer.from("ok")));
589
+ check("conn: inbound PONG emits 'pong'", pongSeen && pongSeen.toString() === "ok");
590
+ } finally { teardown(conn, socket); }
591
+ }
592
+
593
+ // Every protocol-violation abort: assert the connection closes and (when
594
+ // a close frame is sent) carries the RFC 6455 close code.
595
+ function _abortCase(label, opts, frames, expectCode) {
596
+ var socket = makeSocket();
597
+ var conn = new ws.WebSocketConnection(socket, Object.assign({ closeGraceMs: 10 }, opts || {}));
598
+ var closeCode = null;
599
+ conn.on("close", function (code) { closeCode = code; });
600
+ for (var i = 0; i < frames.length; i++) socket.emit("data", frames[i]);
601
+ check(label + ": connection closed", conn.readyState === "closed");
602
+ if (expectCode != null) {
603
+ var sent = serverFrames(socket).filter(function (f) { return f.opcode === ws.OPCODE_CLOSE; });
604
+ check(label + ": abort close-code " + expectCode,
605
+ (sent[0] && sent[0].payload.readUInt16BE(0) === expectCode) || closeCode === expectCode);
606
+ }
607
+ teardown(conn, socket);
608
+ }
609
+
610
+ function testConnectionAbortBranches() {
611
+ // Unmasked client frame on h1 transport.
612
+ _abortCase("abort: unmasked h1 frame", {},
613
+ [ws.serializeFrame(ws.OPCODE_TEXT, "x")], ws.CLOSE_PROTOCOL_ERROR);
614
+
615
+ // Masked frame on h2 transport.
616
+ _abortCase("abort: masked h2 frame", { transport: "h2" },
617
+ [clientFrame(ws.OPCODE_TEXT, "x")], ws.CLOSE_PROTOCOL_ERROR);
618
+
619
+ // RSV2/RSV3 set without an extension (0x20 is the RSV2 flag bit).
620
+ _abortCase("abort: reserved rsv2 bit", {},
621
+ [withByte0Bit(clientFrame(ws.OPCODE_TEXT, "x"), 0x20)], ws.CLOSE_PROTOCOL_ERROR);
622
+
623
+ // RSV1 without permessage-deflate negotiated.
624
+ _abortCase("abort: rsv1 without deflate", {},
625
+ [clientFrame(ws.OPCODE_TEXT, "x", { rsv1: true })], ws.CLOSE_PROTOCOL_ERROR);
626
+
627
+ // RSV1 on a continuation frame (deflate negotiated, but RSV1 belongs
628
+ // on the START frame only).
629
+ _abortCase("abort: rsv1 on continuation", { permessageDeflate: { serverMaxWindowBits: 15, clientMaxWindowBits: 15 } },
630
+ [clientFrame(ws.OPCODE_CONTINUATION, "x", { rsv1: true })], ws.CLOSE_PROTOCOL_ERROR);
631
+
632
+ // Control frame > 125 bytes.
633
+ _abortCase("abort: oversized control frame", {},
634
+ [clientFrame(ws.OPCODE_PING, Buffer.alloc(126))], ws.CLOSE_PROTOCOL_ERROR);
635
+
636
+ // Fragmented control frame.
637
+ _abortCase("abort: fragmented control frame", {},
638
+ [clientFrame(ws.OPCODE_PING, Buffer.from("x"), { fin: false })], ws.CLOSE_PROTOCOL_ERROR);
639
+
640
+ // Continuation without a start frame.
641
+ _abortCase("abort: continuation without start", {},
642
+ [clientFrame(ws.OPCODE_CONTINUATION, "x")], ws.CLOSE_PROTOCOL_ERROR);
643
+
644
+ // New data frame during an open fragmentation sequence.
645
+ _abortCase("abort: new message during fragmentation", {},
646
+ [clientFrame(ws.OPCODE_TEXT, "a", { fin: false }), clientFrame(ws.OPCODE_TEXT, "b")],
647
+ ws.CLOSE_PROTOCOL_ERROR);
648
+
649
+ // Reserved (non-control) opcode 0x3.
650
+ _abortCase("abort: unknown opcode 0x3", {},
651
+ [clientFrame(0x3, "x")], ws.CLOSE_PROTOCOL_ERROR);
652
+
653
+ // Invalid UTF-8 in a TEXT frame.
654
+ _abortCase("abort: invalid utf-8 text", {},
655
+ [clientFrame(ws.OPCODE_TEXT, Buffer.from([0xff, 0xfe]))], ws.CLOSE_INVALID_PAYLOAD);
656
+
657
+ // Reassembled fragmented message exceeds maxMessageBytes.
658
+ _abortCase("abort: fragment exceeds maxMessageBytes", { maxMessageBytes: 4 },
659
+ [clientFrame(ws.OPCODE_TEXT, "abc", { fin: false }), clientFrame(ws.OPCODE_CONTINUATION, "def")],
660
+ ws.CLOSE_MESSAGE_TOO_BIG);
661
+
662
+ // Frame declared larger than maxFrameBytes — parser throws, _onData
663
+ // catches and aborts with the parser's close code.
664
+ _abortCase("abort: frame past maxFrameBytes", { maxMessageBytes: 4 },
665
+ [clientFrame(ws.OPCODE_BINARY, Buffer.alloc(100))], ws.CLOSE_MESSAGE_TOO_BIG);
666
+ }
667
+
668
+ function testConnectionCloseHandshake() {
669
+ // Peer-initiated clean close with a valid code + reason.
670
+ var socket = makeSocket();
671
+ var conn = new ws.WebSocketConnection(socket, { closeGraceMs: 10 });
672
+ var closeArgs = null;
673
+ conn.on("close", function (code, reason, wasClean) { closeArgs = { code: code, reason: reason, wasClean: wasClean }; });
674
+ socket.emit("data", clientFrame(ws.OPCODE_CLOSE, closePayload(1000, "done")));
675
+ check("conn: peer close transitions to closed", conn.readyState === "closed");
676
+ check("conn: peer close surfaces code+reason, wasClean true",
677
+ closeArgs && closeArgs.code === 1000 && closeArgs.reason === "done" && closeArgs.wasClean === true);
678
+ var echoed = serverFrames(socket).filter(function (f) { return f.opcode === ws.OPCODE_CLOSE; });
679
+ check("conn: peer close is echoed back (§5.5.1)",
680
+ echoed.length === 1 && echoed[0].payload.readUInt16BE(0) === 1000);
681
+ check("conn: underlying socket ended on clean close", socket.ended === true);
682
+
683
+ // Empty-body close => defaults to 1000.
684
+ var s2 = makeSocket();
685
+ var c2 = new ws.WebSocketConnection(s2, { closeGraceMs: 10 });
686
+ var code2 = null;
687
+ c2.on("close", function (code) { code2 = code; });
688
+ s2.emit("data", clientFrame(ws.OPCODE_CLOSE, Buffer.alloc(0)));
689
+ check("conn: empty-body close defaults to code 1000", code2 === 1000);
690
+
691
+ // Private-use close code (3000) is valid.
692
+ var s3 = makeSocket();
693
+ var c3 = new ws.WebSocketConnection(s3, { closeGraceMs: 10 });
694
+ var code3 = null;
695
+ c3.on("close", function (code) { code3 = code; });
696
+ s3.emit("data", clientFrame(ws.OPCODE_CLOSE, closePayload(3000, "app")));
697
+ check("conn: private-use close code 3000 accepted", code3 === 3000 && c3.readyState === "closed");
698
+ }
699
+
700
+ function testConnectionCloseFrameViolations() {
701
+ // 1-byte close body is malformed.
702
+ _abortCase("close-violation: 1-byte body", {},
703
+ [clientFrame(ws.OPCODE_CLOSE, Buffer.from([0x03]))], ws.CLOSE_PROTOCOL_ERROR);
704
+
705
+ // Reserved close code 1005 (local-only sentinel) refused on the wire.
706
+ _abortCase("close-violation: reserved code 1005", {},
707
+ [clientFrame(ws.OPCODE_CLOSE, closePayload(1005, ""))], ws.CLOSE_PROTOCOL_ERROR);
708
+
709
+ // Out-of-range close code 2000 (between 1011 and 3000).
710
+ _abortCase("close-violation: invalid code 2000", {},
711
+ [clientFrame(ws.OPCODE_CLOSE, closePayload(2000, ""))], ws.CLOSE_PROTOCOL_ERROR);
712
+
713
+ // Below-range close code 999.
714
+ _abortCase("close-violation: below-range code 999", {},
715
+ [clientFrame(ws.OPCODE_CLOSE, closePayload(999, ""))], ws.CLOSE_PROTOCOL_ERROR);
716
+
717
+ // Valid code but invalid UTF-8 in the reason.
718
+ _abortCase("close-violation: invalid utf-8 reason", {},
719
+ [clientFrame(ws.OPCODE_CLOSE, closePayload(1000, Buffer.from([0xff, 0xfe])))],
720
+ ws.CLOSE_INVALID_PAYLOAD);
721
+ }
722
+
723
+ // ============================================================
724
+ // WebSocketConnection — socket lifecycle transitions
725
+ // ============================================================
726
+
727
+ function testConnectionSocketErrorTransition() {
728
+ var socket = makeSocket();
729
+ var conn = new ws.WebSocketConnection(socket, { closeGraceMs: 10 });
730
+ var errSeen = null, closeArgs = null;
731
+ conn.on("error", function (e) { errSeen = e; });
732
+ conn.on("close", function (code, reason, wasClean) { closeArgs = { code: code, wasClean: wasClean }; });
733
+ socket.emit("error", new Error("boom"));
734
+ check("conn: socket error surfaces via 'error'", errSeen && errSeen.message === "boom");
735
+ check("conn: socket error transitions to closed 1006 wasClean false",
736
+ conn.readyState === "closed" && closeArgs.code === 1006 && closeArgs.wasClean === false);
737
+ check("conn: lastError captured", conn.lastError && conn.lastError.message === "boom");
738
+ }
739
+
740
+ function testConnectionSocketEndTransition() {
741
+ var socket = makeSocket();
742
+ var conn = new ws.WebSocketConnection(socket, { closeGraceMs: 10 });
743
+ var closeArgs = null;
744
+ conn.on("close", function (code, reason, wasClean) { closeArgs = { code: code, wasClean: wasClean }; });
745
+ socket.emit("end");
746
+ check("conn: socket end transitions to closed 1006",
747
+ conn.readyState === "closed" && closeArgs.code === 1006 && closeArgs.wasClean === false);
748
+ check("conn: socket end half-closes our writable side", socket.ended === true);
749
+ }
750
+
751
+ function testConnectionSendAfterSocketUnwritable() {
752
+ // Socket destroyed under us — send() detects the unwritable socket and
753
+ // routes through the abnormal-closure path instead of writing.
754
+ var socket = makeSocket();
755
+ var conn = new ws.WebSocketConnection(socket, { closeGraceMs: 10 });
756
+ var closeCode = null;
757
+ conn.on("close", function (code) { closeCode = code; });
758
+ socket.destroyed = true;
759
+ conn.send("x");
760
+ check("conn: send() to a destroyed socket transitions closed 1006",
761
+ conn.readyState === "closed" && closeCode === 1006);
762
+ check("conn: nothing framed to a destroyed socket", serverFrames(socket).length === 0);
763
+ }
764
+
765
+ function testConnectionSendWriteThrows() {
766
+ var socket = makeSocket({ writeThrows: true });
767
+ var conn = new ws.WebSocketConnection(socket, { closeGraceMs: 10 });
768
+ var closeArgs = null;
769
+ conn.on("close", function (code, reason, wasClean) { closeArgs = { code: code, wasClean: wasClean }; });
770
+ conn.send("x");
771
+ check("conn: socket.write throwing transitions closed 1006 wasClean false",
772
+ conn.readyState === "closed" && closeArgs.code === 1006 && closeArgs.wasClean === false);
773
+ }
774
+
775
+ // ============================================================
776
+ // WebSocketConnection — permessage-deflate send/receive
777
+ // ============================================================
778
+
779
+ function testConnectionDeflateSend() {
780
+ var socket = makeSocket();
781
+ var conn = new ws.WebSocketConnection(socket, {
782
+ closeGraceMs: 10,
783
+ permessageDeflate: { serverMaxWindowBits: 15, clientMaxWindowBits: 15 },
784
+ });
785
+ try {
786
+ conn.send("compress me ".repeat(40));
787
+ var frames = serverFrames(socket);
788
+ check("conn: deflate send marks the frame RSV1 (compressed)",
789
+ frames[0] && frames[0].rsv1 === true && frames[0].opcode === ws.OPCODE_TEXT);
790
+ check("conn: deflate send actually shrinks a repetitive payload",
791
+ frames[0].payload.length < ("compress me ".repeat(40)).length);
792
+ } finally { teardown(conn, socket); }
793
+ }
794
+
795
+ function testConnectionDeflateReceive() {
796
+ var socket = makeSocket();
797
+ var conn = new ws.WebSocketConnection(socket, {
798
+ closeGraceMs: 10,
799
+ permessageDeflate: { serverMaxWindowBits: 15, clientMaxWindowBits: 15 },
800
+ });
801
+ try {
802
+ var got = null;
803
+ conn.on("message", function (data) { got = data; });
804
+ var original = "inflate me ".repeat(30);
805
+ var raw = zlib.deflateRawSync(Buffer.from(original, "utf8"));
806
+ // Strip the RFC 7692 §7.2.1 trailing 0x00 0x00 0xff 0xff.
807
+ if (raw.length >= 4 && raw[raw.length - 4] === 0x00 && raw[raw.length - 3] === 0x00 &&
808
+ raw[raw.length - 2] === 0xff && raw[raw.length - 1] === 0xff) {
809
+ raw = raw.subarray(0, raw.length - 4);
810
+ }
811
+ socket.emit("data", clientFrame(ws.OPCODE_TEXT, raw, { rsv1: true }));
812
+ check("conn: compressed inbound frame inflates to the original text", got === original);
813
+ } finally { teardown(conn, socket); }
814
+ }
815
+
816
+ function testConnectionDeflateReceiveGarbage() {
817
+ // RSV1-flagged frame whose body is not valid deflate → inflate fails →
818
+ // abort CLOSE_INVALID_PAYLOAD.
819
+ _abortCase("deflate: undecodable compressed frame",
820
+ { permessageDeflate: { serverMaxWindowBits: 15, clientMaxWindowBits: 15 } },
821
+ [clientFrame(ws.OPCODE_TEXT, Buffer.from([0xff, 0xff, 0xff, 0xff]), { rsv1: true })],
822
+ ws.CLOSE_INVALID_PAYLOAD);
823
+ }
824
+
825
+ function testConnectionDeflateSendFailureFallsThrough() {
826
+ // A bad windowBits makes deflateRawSync throw; _sendDataFrame's catch
827
+ // falls through to an uncompressed send so the connection keeps working.
828
+ var socket = makeSocket();
829
+ var conn = new ws.WebSocketConnection(socket, {
830
+ closeGraceMs: 10,
831
+ permessageDeflate: { serverMaxWindowBits: 3, clientMaxWindowBits: 15 }, // 3 is out of deflate's 9..15 range
832
+ });
833
+ try {
834
+ conn.send("payload");
835
+ var frames = serverFrames(socket);
836
+ check("conn: deflate failure sends the frame uncompressed (no RSV1)",
837
+ frames[0] && frames[0].rsv1 === false && frames[0].payload.toString() === "payload");
838
+ } finally { teardown(conn, socket); }
839
+ }
840
+
841
+ // ============================================================
842
+ // WebSocketConnection — heartbeat (real timers)
843
+ // ============================================================
844
+
845
+ async function testHeartbeat() {
846
+ // Healthy heartbeat: within the pong window, the timer emits a PING.
847
+ await helpers.withTestTimeout("ws heartbeat: healthy ping", async function () {
848
+ var socket = makeSocket();
849
+ var conn = new ws.WebSocketConnection(socket, {
850
+ closeGraceMs: 10, pingIntervalMs: 20, pongTimeoutMs: 5000,
851
+ });
852
+ try {
853
+ await helpers.waitUntil(function () {
854
+ return serverFrames(socket).some(function (f) { return f.opcode === ws.OPCODE_PING; });
855
+ }, { label: "ws heartbeat: PING emitted by the interval timer" });
856
+ check("conn: heartbeat emits a PING within the interval", true);
857
+ } finally { teardown(conn, socket); }
858
+ }, { timeoutMs: 3000 });
859
+
860
+ // Unresponsive peer: no pong before pongTimeoutMs → abort 1011.
861
+ await helpers.withTestTimeout("ws heartbeat: pong timeout", async function () {
862
+ var socket = makeSocket();
863
+ var conn = new ws.WebSocketConnection(socket, {
864
+ closeGraceMs: 10, pingIntervalMs: 20, pongTimeoutMs: 1,
865
+ });
866
+ var closeCode = null;
867
+ conn.on("close", function (code) { closeCode = code; });
868
+ await helpers.waitUntil(function () {
869
+ return conn.readyState === "closed";
870
+ }, { label: "ws heartbeat: abort on pong timeout" });
871
+ check("conn: pong timeout aborts with CLOSE_INTERNAL_ERROR (1011)",
872
+ closeCode === ws.CLOSE_INTERNAL_ERROR && closeCode === 1011);
873
+ teardown(conn, socket);
874
+ }, { timeoutMs: 3000 });
875
+ }
876
+
877
+ // ============================================================
878
+ // handleUpgrade — h1 entry point
879
+ // ============================================================
880
+
881
+ function testHandleUpgradeGuidThrows() {
882
+ var socket = makeSocket();
883
+ var threw = null;
884
+ try { ws.handleUpgrade(upgradeReq(), socket, null, { handshakeGuid: "not-a-uuid" }); }
885
+ catch (e) { threw = e; }
886
+ check("handleUpgrade: malformed handshakeGuid throws at config time",
887
+ threw && /UUID-shaped/.test(threw.message));
888
+
889
+ var t2 = null;
890
+ try { ws.handleUpgrade(upgradeReq(), socket, null, { handshakeGuid: 123 }); }
891
+ catch (e) { t2 = e; }
892
+ check("handleUpgrade: non-string handshakeGuid throws", t2 !== null);
893
+
894
+ var t3 = null;
895
+ try { ws.handleUpgrade(upgradeReq(), socket, null, { handshakeGuid: "x".repeat(65) }); }
896
+ catch (e) { t3 = e; }
897
+ check("handleUpgrade: over-long handshakeGuid throws", t3 !== null);
898
+
899
+ // A valid UUID-shaped override is accepted and used.
900
+ var s2 = makeSocket();
901
+ var conn = ws.handleUpgrade(upgradeReq(), s2, null, { handshakeGuid: "12345678-1234-1234-1234-1234567890ab" });
902
+ check("handleUpgrade: valid custom GUID completes the upgrade", conn !== null);
903
+ check("handleUpgrade: custom-GUID Accept matches computeAcceptKey",
904
+ String(s2.written[0]).indexOf("Sec-WebSocket-Accept: " +
905
+ ws.computeAcceptKey(RFC_KEY, "12345678-1234-1234-1234-1234567890ab")) !== -1);
906
+ teardown(conn, s2);
907
+ }
908
+
909
+ function testHandleUpgradeRefusals() {
910
+ // Bad handshake → 405, socket destroyed, returns null.
911
+ var s1 = makeSocket();
912
+ var r1 = ws.handleUpgrade({ method: "POST", url: "/ws", headers: upgradeReq().headers }, s1, null, {});
913
+ check("handleUpgrade: bad method returns null", r1 === null);
914
+ check("handleUpgrade: bad method writes 405 + destroys socket",
915
+ /HTTP\/1\.1 405 Method Not Allowed/.test(String(s1.written[0])) && s1.destroyed === true);
916
+
917
+ // Origin mismatch → 403.
918
+ var s2 = makeSocket();
919
+ var r2 = ws.handleUpgrade(upgradeReq({ origin: "https://evil.example.com" }), s2, null, {});
920
+ check("handleUpgrade: origin mismatch returns null", r2 === null);
921
+ check("handleUpgrade: origin mismatch writes 403 Forbidden",
922
+ /HTTP\/1\.1 403 Forbidden/.test(String(s2.written[0])));
923
+ }
924
+
925
+ function testHandleUpgradeSuccess() {
926
+ var socket = makeSocket();
927
+ var conn = ws.handleUpgrade(upgradeReq(), socket, null, {});
928
+ check("handleUpgrade: success returns a WebSocketConnection",
929
+ conn instanceof ws.WebSocketConnection);
930
+ var resp = String(socket.written[0]);
931
+ check("handleUpgrade: success writes the 101 response",
932
+ resp.indexOf("HTTP/1.1 101 Switching Protocols") === 0 &&
933
+ resp.indexOf("Sec-WebSocket-Accept: " + RFC_ACCEPT) !== -1);
934
+ check("handleUpgrade: open readyState after success", conn.readyState === "open");
935
+ teardown(conn, socket);
936
+ }
937
+
938
+ function testHandleUpgradeSubprotocolAndDeflate() {
939
+ var socket = makeSocket();
940
+ var conn = ws.handleUpgrade(upgradeReq({
941
+ "sec-websocket-protocol": "chat.v2, chat.v1",
942
+ "sec-websocket-extensions": "permessage-deflate; server_max_window_bits=10; client_max_window_bits=12",
943
+ }), socket, null, { subprotocols: ["chat.v1"] });
944
+ var resp = String(socket.written[0]);
945
+ check("handleUpgrade: negotiates the supported subprotocol",
946
+ conn.subprotocol === "chat.v1" && /Sec-WebSocket-Protocol: chat\.v1/.test(resp));
947
+ check("handleUpgrade: echoes a permessage-deflate extension header",
948
+ /Sec-WebSocket-Extensions: permessage-deflate;/.test(resp));
949
+ check("handleUpgrade: window-bits echoed in the extension response",
950
+ /server_max_window_bits=10/.test(resp) && /client_max_window_bits=12/.test(resp));
951
+ check("handleUpgrade: connection carries negotiated deflate state",
952
+ conn._permessageDeflate && conn._permessageDeflate.negotiated === true);
953
+ teardown(conn, socket);
954
+ }
955
+
956
+ function testHandleUpgradeDeflateDisabledAndUnknownParam() {
957
+ // Operator opts out of permessage-deflate even though the client offers it.
958
+ var s1 = makeSocket();
959
+ var c1 = ws.handleUpgrade(upgradeReq({ "sec-websocket-extensions": "permessage-deflate" }),
960
+ s1, null, { permessageDeflate: false });
961
+ check("handleUpgrade: permessageDeflate:false skips the extension",
962
+ String(s1.written[0]).indexOf("Sec-WebSocket-Extensions") === -1 && c1._permessageDeflate === null);
963
+ teardown(c1, s1);
964
+
965
+ // An unknown extension parameter makes negotiation decline.
966
+ var s2 = makeSocket();
967
+ var c2 = ws.handleUpgrade(upgradeReq({ "sec-websocket-extensions": "permessage-deflate; bogus_param=1" }),
968
+ s2, null, {});
969
+ check("handleUpgrade: unknown deflate param declines negotiation",
970
+ String(s2.written[0]).indexOf("Sec-WebSocket-Extensions") === -1 && c2._permessageDeflate === null);
971
+ teardown(c2, s2);
972
+ }
973
+
974
+ function testHandleUpgradeHeadPrefeed() {
975
+ // Bytes buffered between headers and the upgrade handler are pre-fed
976
+ // into the parser. Use a PING so the connection's auto-PONG lands in
977
+ // socket.written and proves the head was processed.
978
+ var socket = makeSocket();
979
+ var head = clientFrame(ws.OPCODE_PING, Buffer.from("early"));
980
+ var conn = ws.handleUpgrade(upgradeReq(), socket, head, {});
981
+ var frames = serverFrames(socket);
982
+ check("handleUpgrade: head buffer is pre-fed (auto-PONG emitted)",
983
+ frames.some(function (f) { return f.opcode === ws.OPCODE_PONG && f.payload.toString() === "early"; }));
984
+ teardown(conn, socket);
985
+ }
986
+
987
+ function testHandleUpgradeWriteThrows() {
988
+ var socket = makeSocket({ writeThrows: true });
989
+ var conn = ws.handleUpgrade(upgradeReq(), socket, null, {});
990
+ check("handleUpgrade: 101 write failure returns null + destroys socket",
991
+ conn === null && socket.destroyed === true);
992
+ }
993
+
994
+ // ============================================================
995
+ // handleExtendedConnect — h2 entry point (RFC 8441)
996
+ // ============================================================
997
+
998
+ function h2Headers(extra) {
999
+ return Object.assign({
1000
+ ":method": "CONNECT",
1001
+ ":protocol": "websocket",
1002
+ }, extra || {});
1003
+ }
1004
+
1005
+ function testHandleExtendedConnectRefusals() {
1006
+ // Not a CONNECT.
1007
+ var s1 = makeH2Stream();
1008
+ var r1 = ws.handleExtendedConnect(s1, h2Headers({ ":method": "GET" }), {});
1009
+ check("h2: non-CONNECT method refused 400 + null",
1010
+ r1 === null && s1.responded && s1.responded[":status"] === 400);
1011
+
1012
+ // CONNECT but wrong :protocol.
1013
+ var s2 = makeH2Stream();
1014
+ var r2 = ws.handleExtendedConnect(s2, h2Headers({ ":protocol": "ftp" }), {});
1015
+ check("h2: wrong :protocol refused 400 + null",
1016
+ r2 === null && s2.responded && s2.responded[":status"] === 400);
1017
+
1018
+ // Origin refusal (Origin present, no Host → default same-origin fails).
1019
+ var s3 = makeH2Stream();
1020
+ var r3 = ws.handleExtendedConnect(s3, h2Headers({ origin: "https://evil.example.com" }), {});
1021
+ check("h2: origin refusal returns 403 + null",
1022
+ r3 === null && s3.responded && s3.responded[":status"] === 403);
1023
+ }
1024
+
1025
+ function testHandleExtendedConnectSuccess() {
1026
+ var stream = makeH2Stream();
1027
+ var conn = ws.handleExtendedConnect(stream, h2Headers({ "sec-websocket-protocol": "chat.v1" }),
1028
+ { subprotocols: ["chat.v1"] });
1029
+ check("h2: success returns a WebSocketConnection", conn instanceof ws.WebSocketConnection);
1030
+ check("h2: responds :status 200 (not 101)", stream.responded && stream.responded[":status"] === 200);
1031
+ check("h2: negotiated subprotocol echoed in response headers",
1032
+ stream.responded["sec-websocket-protocol"] === "chat.v1" && conn.subprotocol === "chat.v1");
1033
+ check("h2: connection uses h2 transport", conn.transport === "h2");
1034
+
1035
+ // h2 frames MUST NOT be masked — an unmasked inbound frame is accepted.
1036
+ var got = null;
1037
+ conn.on("message", function (data) { got = data; });
1038
+ stream.emit("data", ws.serializeFrame(ws.OPCODE_TEXT, "over h2"));
1039
+ check("h2: unmasked inbound frame delivered as a message", got === "over h2");
1040
+ teardown(conn, stream);
1041
+ }
1042
+
1043
+ function testHandleExtendedConnectRespondThrows() {
1044
+ var stream = makeH2Stream({ respondThrows: true });
1045
+ var conn = ws.handleExtendedConnect(stream, h2Headers(), {});
1046
+ check("h2: respond() failure returns null + closes stream",
1047
+ conn === null && stream.closed === true);
1048
+ }
1049
+
1050
+ function testHandleExtendedConnectRefusalRespondThrows() {
1051
+ // A refusal whose stream.respond() throws hits _refuseH2Connect's
1052
+ // catch, which falls back to stream.close().
1053
+ var stream = makeH2Stream({ respondThrows: true });
1054
+ var conn = ws.handleExtendedConnect(stream, h2Headers({ ":method": "GET" }), {});
1055
+ check("h2: refusal respond() failure falls back to stream.close()",
1056
+ conn === null && stream.closed === true);
1057
+ }
1058
+
1059
+ // ============================================================
1060
+ // Defensive / fallback branch coverage
1061
+ // ============================================================
1062
+
1063
+ function testValidateHeaderFallbacks() {
1064
+ // Connection header entirely absent (upgrade present) — the `|| ""`
1065
+ // fallback in the token test.
1066
+ var noConn = upgradeReq();
1067
+ delete noConn.headers.connection;
1068
+ check("validate: absent Connection header refused",
1069
+ ws.validateUpgradeRequest(noConn, {}).ok === false);
1070
+
1071
+ // A valid handshake with a non-string url reaches the credential
1072
+ // scan with a non-string reqUrl (returns null → accepted).
1073
+ var noUrl = upgradeReq();
1074
+ delete noUrl.url;
1075
+ check("validate: valid handshake with no url accepted",
1076
+ ws.validateUpgradeRequest(noUrl, {}).ok === true);
1077
+
1078
+ // Trailing '?' yields an empty query string.
1079
+ check("validate: empty query string ('/ws?') accepted",
1080
+ ws.validateUpgradeRequest(upgradeReq({}, "/ws?"), {}).ok === true);
1081
+ }
1082
+
1083
+ function testPureHelpersMissingHeaders() {
1084
+ // negotiateSubprotocol with req.headers undefined → `|| {}` fallback.
1085
+ check("negotiate: undefined req.headers returns null",
1086
+ ws.negotiateSubprotocol({}, ["chat.v1"]) === null);
1087
+ // isOriginAllowed with req.headers undefined → `|| {}` fallback, no
1088
+ // Origin → non-browser bypass.
1089
+ check("origin: undefined req.headers bypasses to true",
1090
+ ws.isOriginAllowed({}, undefined) === true);
1091
+ }
1092
+
1093
+ function testParseExtensionHeaderEdges() {
1094
+ var out = ws._parseExtensionHeader(
1095
+ "permessage-deflate; server_no_context_takeover; =bad; __proto__=evil; token=\"q\", , foo");
1096
+ check("ext-edge: empty-name entry skipped, two extensions parsed",
1097
+ Array.isArray(out) && out.length === 2 && out[1].name === "foo");
1098
+ var p = out[0].params;
1099
+ check("ext-edge: valueless param materializes as boolean true",
1100
+ p.server_no_context_takeover === true);
1101
+ check("ext-edge: empty parameter key ('=bad') dropped",
1102
+ !Object.prototype.hasOwnProperty.call(p, ""));
1103
+ check("ext-edge: poisoned parameter key ('__proto__') dropped",
1104
+ !Object.prototype.hasOwnProperty.call(p, "__proto__"));
1105
+ check("ext-edge: quoted parameter value is unquoted",
1106
+ p.token === "q");
1107
+ }
1108
+
1109
+ function testHandleUpgradeDeflateDefaultsAndNameSkip() {
1110
+ // A non-deflate extension precedes deflate (name-mismatch skip), and
1111
+ // deflate is offered with no window-bits (both default to 15).
1112
+ var s1 = makeSocket();
1113
+ var c1 = ws.handleUpgrade(upgradeReq({ "sec-websocket-extensions": "foo; x=1, permessage-deflate" }),
1114
+ s1, null, {});
1115
+ check("handleUpgrade: deflate negotiated after skipping a foreign extension",
1116
+ c1._permessageDeflate && c1._permessageDeflate.negotiated === true);
1117
+ check("handleUpgrade: no window-bits => both default to 15",
1118
+ c1._permessageDeflate.serverMaxWindowBits === 15 && c1._permessageDeflate.clientMaxWindowBits === 15);
1119
+ check("handleUpgrade: bare deflate response omits window-bits echo",
1120
+ String(s1.written[0]).indexOf("max_window_bits") === -1);
1121
+ teardown(c1, s1);
1122
+
1123
+ // Non-numeric window bits parse-fail into the 15 default.
1124
+ var s2 = makeSocket();
1125
+ var c2 = ws.handleUpgrade(upgradeReq({ "sec-websocket-extensions": "permessage-deflate; client_max_window_bits=abc" }),
1126
+ s2, null, {});
1127
+ check("handleUpgrade: non-numeric window-bits defaults to 15",
1128
+ c2._permessageDeflate.clientMaxWindowBits === 15);
1129
+ teardown(c2, s2);
1130
+
1131
+ // Valueless window-bits params (offered with no '=value') are the
1132
+ // `=== true` case: the extension is honoured but no bits are echoed
1133
+ // and both windows default to 15.
1134
+ var s3 = makeSocket();
1135
+ var c3 = ws.handleUpgrade(upgradeReq({
1136
+ "sec-websocket-extensions": "permessage-deflate; server_max_window_bits; client_max_window_bits",
1137
+ }), s3, null, {});
1138
+ check("handleUpgrade: valueless window-bits honoured, defaults to 15",
1139
+ c3._permessageDeflate.serverMaxWindowBits === 15 && c3._permessageDeflate.clientMaxWindowBits === 15);
1140
+ check("handleUpgrade: valueless window-bits not echoed in the response",
1141
+ String(s3.written[0]).indexOf("max_window_bits=") === -1);
1142
+ teardown(c3, s3);
1143
+ }
1144
+
1145
+ function testEntryPointsNoOpts() {
1146
+ // handleUpgrade / handleExtendedConnect with the opts argument omitted
1147
+ // exercise the `opts || {}` default.
1148
+ var s1 = makeSocket();
1149
+ var c1 = ws.handleUpgrade(upgradeReq(), s1);
1150
+ check("handleUpgrade: omitted opts uses defaults",
1151
+ c1 instanceof ws.WebSocketConnection);
1152
+ teardown(c1, s1);
1153
+
1154
+ var s2 = makeH2Stream();
1155
+ var c2 = ws.handleExtendedConnect(s2, h2Headers());
1156
+ check("h2: omitted opts uses defaults",
1157
+ c2 instanceof ws.WebSocketConnection && c2.transport === "h2");
1158
+ teardown(c2, s2);
1159
+ }
1160
+
1161
+ function testConnectionConstructorNoOpts() {
1162
+ var socket = makeSocket();
1163
+ var conn = new ws.WebSocketConnection(socket); // opts omitted → `opts || {}`
1164
+ check("conn: constructs with no opts (defaults applied)",
1165
+ conn.readyState === "open" && conn.transport === "h1" && conn.subprotocol === null);
1166
+ teardown(conn, socket);
1167
+ }
1168
+
1169
+ function testConnectionErrorFallbackAndNoListener() {
1170
+ // Error object without a message → the "socket error" reason fallback.
1171
+ var s1 = makeSocket();
1172
+ var c1 = new ws.WebSocketConnection(s1, { closeGraceMs: 10 });
1173
+ var seen1 = null, closeCode1 = null;
1174
+ c1.on("error", function (e) { seen1 = e; });
1175
+ c1.on("close", function (code) { closeCode1 = code; });
1176
+ s1.emit("error", {}); // truthy err, no .message
1177
+ check("conn: messageless socket error still transitions closed 1006",
1178
+ c1.readyState === "closed" && closeCode1 === 1006 && seen1 !== null);
1179
+
1180
+ // Error present but NO 'error' listener → the emit is gated (no throw).
1181
+ var s2 = makeSocket();
1182
+ var c2 = new ws.WebSocketConnection(s2, { closeGraceMs: 10 });
1183
+ var closeCode2 = null;
1184
+ c2.on("close", function (code) { closeCode2 = code; });
1185
+ s2.emit("error", new Error("unheard"));
1186
+ check("conn: socket error with no 'error' listener closes without throwing",
1187
+ c2.readyState === "closed" && closeCode2 === 1006 && c2.lastError.message === "unheard");
1188
+ }
1189
+
1190
+ function testConnectionIdempotentTransitions() {
1191
+ // Second transition after CLOSED is a no-op (the error handler calls
1192
+ // _transitionToClosed directly, unguarded).
1193
+ var s1 = makeSocket();
1194
+ var c1 = new ws.WebSocketConnection(s1, { closeGraceMs: 10 });
1195
+ var closeCount = 0, firstCode = null;
1196
+ c1.on("error", function () { /* absorb */ });
1197
+ c1.on("close", function (code) { closeCount += 1; if (firstCode === null) firstCode = code; });
1198
+ s1.emit("close"); // first transition (1006)
1199
+ s1.emit("error", new Error("after")); // second transition — early return
1200
+ check("conn: 'close' emitted exactly once across repeat transitions",
1201
+ closeCount === 1 && firstCode === 1006);
1202
+
1203
+ // _abort after CLOSED early-returns: feed a protocol-violating frame
1204
+ // after the connection is already closed.
1205
+ var s2 = makeSocket();
1206
+ var c2 = new ws.WebSocketConnection(s2, { closeGraceMs: 10 });
1207
+ var closeCount2 = 0;
1208
+ c2.on("close", function () { closeCount2 += 1; });
1209
+ s2.emit("close");
1210
+ s2.emit("data", ws.serializeFrame(ws.OPCODE_TEXT, "x")); // unmasked → would abort, but already closed
1211
+ check("conn: abort after close is a no-op (single close event)",
1212
+ c2.readyState === "closed" && closeCount2 === 1);
1213
+ }
1214
+
1215
+ async function run() {
1216
+ // Handshake helpers
1217
+ testWebSocketError();
1218
+ testBuildUpgradeResponse();
1219
+ testComputeAcceptKeyCustomGuid();
1220
+ testValidateUpgradeRequest();
1221
+ testValidateCredentialQueryRefusal();
1222
+ testValidateHeaderFallbacks();
1223
+ testNegotiateSubprotocol();
1224
+ testIsOriginAllowed();
1225
+ testPureHelpersMissingHeaders();
1226
+ testParseExtensionHeaderEdges();
1227
+
1228
+ // Frame layer
1229
+ testFrameParserRoundTrip();
1230
+ testFrameParserExtendedLengths();
1231
+ testFrameParserIncremental();
1232
+ testFrameParserFrameTooLarge();
1233
+ testFrameParser64BitOverflow();
1234
+ testSerializeFrame();
1235
+
1236
+ // Connection — send/ping/close
1237
+ testConnectionSendVariants();
1238
+ testConnectionSendInvalidPayload();
1239
+ testConnectionSendRejectsWhenClosed();
1240
+ testConnectionPing();
1241
+ testConnectionClose();
1242
+ await testConnectionCloseGraceTimerFires();
1243
+ testConnectionCloseDefaultsCode();
1244
+
1245
+ // Connection — inbound frames
1246
+ testConnectionReceiveMessages();
1247
+ testConnectionFragmentedMessage();
1248
+ testConnectionPingPong();
1249
+ testConnectionAbortBranches();
1250
+ testConnectionCloseHandshake();
1251
+ testConnectionCloseFrameViolations();
1252
+
1253
+ // Connection — socket lifecycle
1254
+ testConnectionSocketErrorTransition();
1255
+ testConnectionSocketEndTransition();
1256
+ testConnectionSendAfterSocketUnwritable();
1257
+ testConnectionSendWriteThrows();
1258
+ testConnectionConstructorNoOpts();
1259
+ testConnectionErrorFallbackAndNoListener();
1260
+ testConnectionIdempotentTransitions();
1261
+
1262
+ // Connection — permessage-deflate
1263
+ testConnectionDeflateSend();
1264
+ testConnectionDeflateReceive();
1265
+ testConnectionDeflateReceiveGarbage();
1266
+ testConnectionDeflateSendFailureFallsThrough();
1267
+
1268
+ // Connection — heartbeat (real timers)
1269
+ await testHeartbeat();
1270
+
1271
+ // Server-side entry points
1272
+ testHandleUpgradeGuidThrows();
1273
+ testHandleUpgradeRefusals();
1274
+ testHandleUpgradeSuccess();
1275
+ testHandleUpgradeSubprotocolAndDeflate();
1276
+ testHandleUpgradeDeflateDisabledAndUnknownParam();
1277
+ testHandleUpgradeDeflateDefaultsAndNameSkip();
1278
+ testHandleUpgradeHeadPrefeed();
1279
+ testHandleUpgradeWriteThrows();
1280
+ testHandleExtendedConnectRefusals();
1281
+ testHandleExtendedConnectSuccess();
1282
+ testHandleExtendedConnectRespondThrows();
1283
+ testHandleExtendedConnectRefusalRespondThrows();
1284
+ testEntryPointsNoOpts();
1285
+ }
1286
+
1287
+ module.exports = { run: run };
1288
+
1289
+ if (require.main === module) {
1290
+ run().then(
1291
+ function () { console.log("[websocket] OK — " + helpers.getChecks() + " checks passed"); },
1292
+ function (e) { console.error("FAIL:", e); process.exit(1); }
1293
+ );
1294
+ }