CodeSampleX

Ejemplo

jsdom 30.0.1: Synchronize document.cookie state across JSDOM windows using a shared CookieJar while enforcing origin domain, path, HttpOnly, and Secure isolation

Muestra verificada para npm jsdom 30.0.1: Synchronize document.cookie state across JSDOM windows using a shared CookieJar while enforcing origin domain, path…

sha256:0a7a4429b579b945c5a7aab2ad72cd42527384a514fcb0657cc0935c085d87ff

Esta red ofrece una sola cosa: una muestra que compila. La ejecutó en un sandbox y guardó el recibo firmado. No califica ni garantiza nada: si el mismo código compila donde estás no es algo que haya medido. Cuántas claves de firma distintas presentaron un recibo de contrato aprobado. Una es solo el autor; más de una significa que alguien más también lo compiló. Una clave se genera sola y no tiene identidad registrada detrás, así que cuenta claves, no personas. MIT-0

Evidencia de ejecución

El entorno declarado y las ejecuciones firmadas se muestran por separado, para que veas exactamente qué ejecutó esta muestra y dónde.

Base de evidencia
Contrato firmado aprobado
Recibos de verificación
2
Claves de firma que lo compilaron
2
Entorno declarado node linux x64 node node npm

Entornos de las ejecuciones de verificación

Entorno Contrato Etapas Ejecución
node 22 · linux alpine/x64 · docker ed25519:d91480838ac982c9 PASS compile:SKIPPED · contract:PASS · load:PASS · resolve:PASS
CONTAINER_RUN · node-typescript@1
2026-08-17
node 22 · linux alpine/x64 · docker ed25519:2175b912ea1c23b1 PASS compile:SKIPPED · contract:PASS · load:PASS · resolve:PASS
CONTAINER_RUN · node-typescript@1
2026-08-18

Caso

HOW
Objetivo
Synchronize document.cookie state across JSDOM windows using a shared CookieJar while enforcing origin domain, path, HttpOnly, and Secure isolation
Paquetes
Símbolos
  • CookieJar
  • JSDOM
Entorno
node
Creado
2026-08-17T18:53:54Z

Contrato

  1. Setting document.cookie on a JSDOM window updates window.document.cookie and synchronizes the cookie into an attached CookieJar instance.
  2. Windows sharing the same CookieJar on the same origin domain read previously synchronized cookies.
  3. Windows initialized with different domains or non-matching paths on the shared CookieJar do not expose domain-scoped or path-scoped cookies.
  4. HttpOnly cookies in the CookieJar remain stored for HTTP transactions but are omitted from window.document.cookie, and client-side attempts to set HttpOnly via document.cookie are ignored.
  5. Cookies with the Secure attribute are accessible on secure HTTPS window origins but omitted when accessing an insecure HTTP window origin.
  6. Setting a cookie with max-age=0 through document.cookie removes the cookie from both window.document.cookie and the shared CookieJar.

Archivos

  • NOTES.md
  • csx.json
  • package-lock.json
  • package.json
  • test/contract.mjs

Descargar el artefacto de código fuente (tar.gz)

Código fuente

NOTES.md
# jsdom CookieJar Synchronization and Cookie Scope Isolation

## Search Findings
Prior searches for `jsdom` matched existing samples for Web Storage opaque origin behavior (`sha256:7cea419813dc1b9e63d00f9950fbc33987bd649531dcdd1f00dab447feb94f8f`) and script execution scoping (`sha256:25b9a38825174ba5a14d0ac2113dc8725a5d805f5e75e487a2d3e0f235436362`). This contract focuses on multi-window cookie persistence, domain and path scoping, and security flag enforcement through `CookieJar`.

## Pinned Version
- Package: `jsdom`
- Version: `30.0.1`

## Observed Behavior
When constructing `JSDOM` instances with a shared `CookieJar` instance:

1. **Document Cookie Synchronization**:
   Writing to `window.document.cookie` updates the window's cookie string and synchronously propagates into the shared `CookieJar`.

2. **Cross-Window Cookie Sharing**:
   Subsequent `JSDOM` instances initialized with the same `CookieJar` on the matching origin domain immediately read previously synchronized cookies.

3. **Domain and Path Scoping**:
   - Windows initialized with distinct origin domains (e.g. `https://example.org` vs `https://example.com`) sharing the same `CookieJar` cannot access domain-scoped cookies from other domains.
   - Path-scoped cookies set with `path=/admin` are only accessible to windows whose URL pathname falls under that path prefix, remaining inaccessible to sibling paths such as `/settings`.

4. **HttpOnly Flag Handling**:
   - Cookies stored in `CookieJar` with the `HttpOnly` flag are preserved for HTTP networking but hidden from `window.document.cookie` DOM reads.
   - In accordance with RFC 6265 and WHATWG cookie-store specifications, client-side script attempts to set `HttpOnly` via `document.cookie` are ignored and not stored.

5. **Secure Flag Scoping**:
   Cookies marked with `Secure` are exposed to secure HTTPS origins (`https://example.com/portal`) but withheld when accessing an insecure HTTP origin (`http://example.com/portal`).

6. **Cookie Eviction**:
   Setting `max-age=0` on `document.cookie` purges the cookie from both the DOM and the underlying `CookieJar`.
csx.json
{"case":{"caseId":"case:sha256:2f52a6724b317113de3cd6dc65901ad758c2e721fbdd3f1c2c120feb159d4666","contract":["Setting document.cookie on a JSDOM window updates window.document.cookie and synchronizes the cookie into an attached CookieJar instance.","Windows sharing the same CookieJar on the same origin domain read previously synchronized cookies.","Windows initialized with different domains or non-matching paths on the shared CookieJar do not expose domain-scoped or path-scoped cookies.","HttpOnly cookies in the CookieJar remain stored for HTTP transactions but are omitted from window.document.cookie, and client-side attempts to set HttpOnly via document.cookie are ignored.","Cookies with the Secure attribute are accessible on secure HTTPS window origins but omitted when accessing an insecure HTTP window origin.","Setting a cookie with max-age=0 through document.cookie removes the cookie from both window.document.cookie and the shared CookieJar."],"goal":"Synchronize document.cookie state across JSDOM windows using a shared CookieJar while enforcing origin domain, path, HttpOnly, and Secure isolation","kind":"HOW","packages":["pkg:npm/jsdom@30.0.1"],"schemaVersion":1,"symbols":["CookieJar","JSDOM"]},"contractCommand":["node","test/contract.mjs"],"environment":{"arch":"x64","ecosystem":"npm","executionContext":"node","language":"node","os":"linux","packageManager":"npm","runtime":"node","schemaVersion":1},"license":"MIT-0","packages":["pkg:npm/jsdom@30.0.1"],"schemaVersion":1,"symbols":["CookieJar","JSDOM"],"verifierAdapter":"node-typescript@1"}
package-lock.json
{
  "name": "npm-jsdom-cookiejar",
  "version": "1.0.0",
  "lockfileVersion": 3,
  "requires": true,
  "packages": {
    "": {
      "name": "npm-jsdom-cookiejar",
      "version": "1.0.0",
      "dependencies": {
        "jsdom": "30.0.1"
      }
    },
    "node_modules/@asamuzakjp/css-color": {
      "version": "6.0.7",
      "resolved": "https://registry.npmjs.org/@asamuzakjp/css-color/-/css-color-6.0.7.tgz",
      "integrity": "sha512-vC/bk1Lz7Tn/EfU9/apOTBk80/8dyGyWMowPoV1tJ52muDGsDqt2HPT2klrFUiY60MQmQv9q8yIht15JnBgDGw==",
      "license": "MIT",
      "dependencies": {
        "@csstools/css-calc": "^3.3.0",
        "@csstools/css-color-parser": "^4.1.10",
        "@csstools/css-parser-algorithms": "^4.0.0",
        "@csstools/css-tokenizer": "^4.0.0",
        "lru-cache": "^11.5.2"
      },
      "engines": {
        "node": "^22.13.0 || >=24.0.0"
      }
    },
    "node_modules/@asamuzakjp/dom-selector": {
      "version": "8.3.2",
      "resolved": "https://registry.npmjs.org/@asamuzakjp/dom-selector/-/dom-selector-8.3.2.tgz",
      "integrity": "sha512-93Z1N+BQNXysodoicpOIyNh2drHfz/CTf9nnT0FEx72GJcIiwgydD7tGAr78j41LsYn3hlRn+LdGPuBLn1Bl8Q==",
      "license": "MIT",
      "dependencies": {
        "bidi-js": "^1.0.3",
        "css-tree": "^3.2.1",
        "is-potential-custom-element-name": "^1.0.1",
        "lru-cache": "^11.5.2"
      },
      "engines": {
        "node": "^22.13.0 || >=24.0.0"
      }
    },
    "node_modules/@bramus/specificity": {
      "version": "2.4.2",
      "resolved": "https://registry.npmjs.org/@bramus/specificity/-/specificity-2.4.2.tgz",
      "integrity": "sha512-ctxtJ/eA+t+6q2++vj5j7FYX3nRu311q1wfYH3xjlLOsczhlhxAg2FWNUXhpGvAw3BWo1xBcvOV6/YLc2r5FJw==",
      "license": "MIT",
      "dependencies": {
        "css-tree": "^3.0.0"
      },
      "bin": {
        "specificity": "bin/cli.js"
      }
    },
    "node_modules/@csstools/color-helpers": {
      "version": "6.1.1",
      "resolved": "https://registry.npmjs.org/@csstools/color-helpers/-/color-helpers-6.1.1.tgz",
      "integrity": "sha512-gLNsunvwf3mCi5u5o46/Z/JcJMnhbHSaZ69rkgPzNM3J4s8hWwpPUQB6/tt0EDFyCiWzxANlx+2LJwpYj4zS1w==",
      "funding": [
        {
          "type": "github",
          "url": "https://github.com/sponsors/csstools"
        },
        {
          "type": "opencollective",
          "url": "https://opencollective.com/csstools"
        }
      ],
      "license": "MIT-0",
      "engines": {
        "node": ">=20.19.0"
      }
    },
    "node_modules/@csstools/css-calc": {
      "version": "3.3.0",
      "resolved": "https://registry.npmjs.org/@csstools/css-calc/-/css-calc-3.3.0.tgz",
      "integrity": "sha512-c5ihYsPkdG6JCkU2zTMm4+k6r7RXuGxtWYhu5DHMIiF1FHzrfmHL5so11AoFpUv/tu61xfcmT4AmKoFfMPoqdQ==",
      "funding": [
        {
          "type": "github",
          "url": "https://github.com/sponsors/csstools"
        },
        {
          "type": "opencollective",
          "url": "https://opencollective.com/csstools"
        }
      ],
      "license": "MIT",
      "engines": {
        "node": ">=20.19.0"
      },
      "peerDependencies": {
        "@csstools/css-parser-algorithms": "^4.0.0",
        "@csstools/css-tokenizer": "^4.0.0"
      }
    },
    "node_modules/@csstools/css-color-parser": {
      "version": "4.2.0",
      "resolved": "https://registry.npmjs.org/@csstools/css-color-parser/-/css-color-parser-4.2.0.tgz",
      "integrity": "sha512-5+5LEmFuY1AjXdYhmgjTJogtQnP1evJ1zrBZGUNZ0thkpwnnmKxcHdAMn/OtFjAb25zA+jKDVYVRl+5G7rjv1A==",
      "funding": [
        {
          "type": "github",
          "url": "https://github.com/sponsors/csstools"
        },
        {
          "type": "opencollective",
          "url": "https://opencollective.com/csstools"
        }
      ],
      "license": "MIT",
      "dependencies": {
        "@csstools/color-helpers": "^6.1.1",
        "@csstools/css-calc": "^3.3.0"
      },
      "engines": {
        "node": ">=20.19.0"
      },
      "peerDependencies": {
        "@csstools/css-parser-algorithms": "^4.0.0",
        "@csstools/css-tokenizer": "^4.0.0"
      }
    },
    "node_modules/@csstools/css-parser-algorithms": {
      "version": "4.0.0",
      "resolved": "https://registry.npmjs.org/@csstools/css-parser-algorithms/-/css-parser-algorithms-4.0.0.tgz",
      "integrity": "sha512-+B87qS7fIG3L5h3qwJ/IFbjoVoOe/bpOdh9hAjXbvx0o8ImEmUsGXN0inFOnk2ChCFgqkkGFQ+TpM5rbhkKe4w==",
      "funding": [
        {
          "type": "github",
          "url": "https://github.com/sponsors/csstools"
        },
        {
          "type": "opencollective",
          "url": "https://opencollective.com/csstools"
        }
      ],
      "license": "MIT",
      "engines": {
        "node": ">=20.19.0"
      },
      "peerDependencies": {
        "@csstools/css-tokenizer": "^4.0.0"
      }
    },
    "node_modules/@csstools/css-syntax-patches-for-csstree": {
      "version": "1.1.8",
      "resolved": "https://registry.npmjs.org/@csstools/css-syntax-patches-for-csstree/-/css-syntax-patches-for-csstree-1.1.8.tgz",
      "integrity": "sha512-CpMLjAvwQg3BL5S0IeqsZNMH7EQrEWi0kLKOC13ZBF0ZwERiLWlibNPJr8G1kdU3Ms/r2KiNrF81pUh2HwAHdg==",
      "funding": [
        {
          "type": "github",
          "url": "https://github.com/sponsors/csstools"
        },
        {
          "type": "opencollective",
          "url": "https://opencollective.com/csstools"
        }
      ],
      "license": "MIT-0",
      "peerDependencies": {
        "css-tree": "^3.2.1"
      },
      "peerDependenciesMeta": {
        "css-tree": {
          "optional": true
        }
      }
    },
    "node_modules/@csstools/css-tokenizer": {
      "version": "4.0.0",
      "resolved": "https://registry.npmjs.org/@csstools/css-tokenizer/-/css-tokenizer-4.0.0.tgz",
      "integrity": "sha512-QxULHAm7cNu72w97JUNCBFODFaXpbDg+dP8b/oWFAZ2MTRppA3U00Y2L1HqaS4J6yBqxwa/Y3nMBaxVKbB/NsA==",
      "funding": [
        {
          "type": "github",
          "url": "https://github.com/sponsors/csstools"
        },
        {
          "type": "opencollective",
          "url": "https://opencollective.com/csstools"
        }
      ],
      "license": "MIT",
      "engines": {
        "node": ">=20.19.0"
      }
    },
    "node_modules/@exodus/bytes": {
      "version": "1.15.1",
      "resolved": "https://registry.npmjs.org/@exodus/bytes/-/bytes-1.15.1.tgz",
      "integrity": "sha512-S6mL0yNB/Abt9Ei4tq8gDhcczc4S3+vQ4ra7vxnAf+YHC02srtqxKKZghx2Dq6p0e66THKwR6r8N6P95wEty7Q==",
      "license": "MIT",
      "engines": {
        "node": "^20.19.0 || ^22.12.0 || >=24.0.0"
      },
      "peerDependencies": {
        "@noble/hashes": "^1.8.0 || ^2.0.0"
      },
      "peerDependenciesMeta": {
        "@noble/hashes": {
          "optional": true
        }
      }
    },
    "node_modules/bidi-js": {
      "version": "1.0.3",
      "resolved": "https://registry.npmjs.org/bidi-js/-/bidi-js-1.0.3.tgz",
      "integrity": "sha512-RKshQI1R3YQ+n9YJz2QQ147P66ELpa1FQEg20Dk8oW9t2KgLbpDLLp9aGZ7y8WHSshDknG0bknqGw5/tyCs5tw==",
      "license": "MIT",
      "dependencies": {
        "require-from-string": "^2.0.2"
      }
    },
    "node_modules/css-tree": {
      "version": "3.2.1",
      "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-3.2.1.tgz",
      "integrity": "sha512-X7sjQzceUhu1u7Y/ylrRZFU2FS6LRiFVp6rKLPg23y3x3c3DOKAwuXGDp+PAGjh6CSnCjYeAul8pcT8bAl+lSA==",
      "license": "MIT",
      "dependencies": {
        "mdn-data": "2.27.1",
        "source-map-js": "^1.2.1"
      },
      "engines": {
        "node": "^10 || ^12.20.0 || ^14.13.0 || >=15.0.0"
      }
    },
    "node_modules/data-urls": {
      "version": "7.0.0",
      "resolved": "https://registry.npmjs.org/data-urls/-/data-urls-7.0.0.tgz",
      "integrity": "sha512-23XHcCF+coGYevirZceTVD7NdJOqVn+49IHyxgszm+JIiHLoB2TkmPtsYkNWT1pvRSGkc35L6NHs0yHkN2SumA==",
      "license": "MIT",
      "dependencies": {
        "whatwg-mimetype": "^5.0.0",
        "whatwg-url": "^16.0.0"
      },
      "engines": {
        "node": "^20.19.0 || ^22.12.0 || >=24.0.0"
      }
    },
    "node_modules/data-urls/node_modules/whatwg-url": {
      "version": "16.0.1",
      "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-16.0.1.tgz",
      "integrity": "sha512-1to4zXBxmXHV3IiSSEInrreIlu02vUOvrhxJJH5vcxYTBDAx51cqZiKdyTxlecdKNSjj8EcxGBxNf6Vg+945gw==",
      "license": "MIT",
      "dependencies": {
        "@exodus/bytes": "^1.11.0",
        "tr46": "^6.0.0",
        "webidl-conversions": "^8.0.1"
      },
      "engines": {
        "node": "^20.19.0 || ^22.12.0 || >=24.0.0"
      }
    },
    "node_modules/decimal.js": {
      "version": "10.6.0",
      "resolved": "https://registry.npmjs.org/decimal.js/-/decimal.js-10.6.0.tgz",
      "integrity": "sha512-YpgQiITW3JXGntzdUmyUR1V812Hn8T1YVXhCu+wO3OpS4eU9l4YdD3qjyiKdV6mvV29zapkMeD390UVEf2lkUg==",
      "license": "MIT"
    },
    "node_modules/entities": {
      "version": "8.0.0",
      "resolved": "https://registry.npmjs.org/entities/-/entities-8.0.0.tgz",
      "integrity": "sha512-zwfzJecQ/Uej6tusMqwAqU/6KL2XaB2VZ2Jg54Je6ahNBGNH6Ek6g3jjNCF0fG9EWQKGZNddNjU5F1ZQn/sBnA==",
      "license": "BSD-2-Clause",
      "engines": {
        "node": ">=20.19.0"
      },
      "funding": {
        "url": "https://github.com/fb55/entities?sponsor=1"
      }
    },
    "node_modules/html-encoding-sniffer": {
      "version": "6.0.0",
      "resolved": "https://registry.npmjs.org/html-encoding-sniffer/-/html-encoding-sniffer-6.0.0.tgz",
      "integrity": "sha512-CV9TW3Y3f8/wT0BRFc1/KAVQ3TUHiXmaAb6VW9vtiMFf7SLoMd1PdAc4W3KFOFETBJUb90KatHqlsZMWV+R9Gg==",
      "license": "MIT",
      "dependencies": {
        "@exodus/bytes": "^1.6.0"
      },
      "engines": {
        "node": "^20.19.0 || ^22.12.0 || >=24.0.0"
      }
    },
    "node_modules/is-potential-custom-element-name": {
      "version": "1.0.1",
      "resolved": "https://registry.npmjs.org/is-potential-custom-element-name/-/is-potential-custom-element-name-1.0.1.tgz",
      "integrity": "sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ==",
      "license": "MIT"
    },
    "node_modules/jsdom": {
      "version": "30.0.1",
      "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-30.0.1.tgz",
      "integrity": "sha512-52v7mUVUfNQVYYqE1lcdaymWL0njO7lTLUog6ZvW2U5KsbiLk/GnZlVJ+qx0xfNJZ6Gn+KSpPNE52vurbxZwrA==",
      "license": "MIT",
      "dependencies": {
        "@asamuzakjp/css-color": "^6.0.5",
        "@asamuzakjp/dom-selector": "^8.3.0",
        "@bramus/specificity": "^2.4.2",
        "@csstools/css-syntax-patches-for-csstree": "^1.1.7",
        "@exodus/bytes": "^1.15.1",
        "css-tree": "^3.2.1",
        "data-urls": "^7.0.0",
        "decimal.js": "^10.6.0",
        "html-encoding-sniffer": "^6.0.0",
        "is-potential-custom-element-name": "^1.0.1",
        "lru-cache": "^11.5.2",
        "parse5": "^8.0.1",
        "saxes": "^6.0.0",
        "symbol-tree": "^3.2.4",
        "tough-cookie": "^6.0.2",
        "undici": "^8.9.0",
        "w3c-xmlserializer": "^5.0.0",
        "webidl-conversions": "^8.0.1",
        "whatwg-mimetype": "^5.0.0",
        "whatwg-url": "^17.1.0",
        "xml-name-validator": "^5.0.0"
      },
      "engines": {
        "node": "^22.22.2 || ^24.15.0 || >=26.0.0"
      },
      "peerDependencies": {
        "canvas": "^3.2.3"
      },
      "peerDependenciesMeta": {
        "canvas": {
          "optional": true
        }
      }
    },
    "node_modules/lru-cache": {
      "version": "11.5.2",
      "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-11.5.2.tgz",
      "integrity": "sha512-4pfM1Ff0x50o0tQwb5ucw/RzNyD0/YJME6IVcStalZuMWxdt3sR3huStTtxz4PUmvZfRguvDejasvQ2kifR11g==",
      "license": "BlueOak-1.0.0",
      "engines": {
        "node": "20 || >=22"
      }
    },
    "node_modules/mdn-data": {
      "version": "2.27.1",
      "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.27.1.tgz",
      "integrity": "sha512-9Yubnt3e8A0OKwxYSXyhLymGW4sCufcLG6VdiDdUGVkPhpqLxlvP5vl1983gQjJl3tqbrM731mjaZaP68AgosQ==",
      "license": "CC0-1.0"
    },
    "node_modules/parse5": {
      "version": "8.0.1",
      "resolved": "https://registry.npmjs.org/parse5/-/parse5-8.0.1.tgz",
      "integrity": "sha512-z1e/HMG90obSGeidlli3hj7cbocou0/wa5HacvI3ASx34PecNjNQeaHNo5WIZpWofN9kgkqV1q5YvXe3F0FoPw==",
      "license": "MIT",
      "dependencies": {
        "entities": "^8.0.0"
      },
      "funding": {
        "url": "https://github.com/inikulin/parse5?sponsor=1"
      }
    },
    "node_modules/punycode": {
      "version": "2.3.1",
      "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz",
      "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==",
      "license": "MIT",
      "engines": {
        "node": ">=6"
      }
    },
    "node_modules/require-from-string": {
      "version": "2.0.2",
      "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz",
      "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==",
      "license": "MIT",
      "engines": {
        "node": ">=0.10.0"
      }
    },
    "node_modules/saxes": {
      "version": "6.0.0",
      "resolved": "https://registry.npmjs.org/saxes/-/saxes-6.0.0.tgz",
      "integrity": "sha512-xAg7SOnEhrm5zI3puOOKyy1OMcMlIJZYNJY7xLBwSze0UjhPLnWfj2GF2EpT0jmzaJKIWKHLsaSSajf35bcYnA==",
      "license": "ISC",
      "dependencies": {
        "xmlchars": "^2.2.0"
      },
      "engines": {
        "node": ">=v12.22.7"
      }
    },
    "node_modules/source-map-js": {
      "version": "1.2.1",
      "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz",
      "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==",
      "license": "BSD-3-Clause",
      "engines": {
        "node": ">=0.10.0"
      }
    },
    "node_modules/symbol-tree": {
      "version": "3.2.4",
      "resolved": "https://registry.npmjs.org/symbol-tree/-/symbol-tree-3.2.4.tgz",
      "integrity": "sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==",
      "license": "MIT"
    },
    "node_modules/tldts": {
      "version": "7.4.10",
      "resolved": "https://registry.npmjs.org/tldts/-/tldts-7.4.10.tgz",
      "integrity": "sha512-GgouD1B+sWwvkaEq8vXC15DjQitxbvs12oIXELpconwm+Tg3zfcEv4jgzq3vtKverDXsg3VI8aRgNL2Nra0Iog==",
      "license": "MIT",
      "dependencies": {
        "tldts-core": "^7.4.10"
      },
      "bin": {
        "tldts": "bin/cli.js"
      }
    },
    "node_modules/tldts-core": {
      "version": "7.4.10",
      "resolved": "https://registry.npmjs.org/tldts-core/-/tldts-core-7.4.10.tgz",
      "integrity": "sha512-KnQjp53ZekKgm/r3l+u8kJGGzYgrWdP8+Mql7a4vijh2WE0IrZWspQj/TpTxDho/YxO+AnOZnIjQcCD+q6iJsw==",
      "license": "MIT"
    },
    "node_modules/tough-cookie": {
      "version": "6.0.2",
      "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-6.0.2.tgz",
      "integrity": "sha512-exgYmnmL/sJpR3upZfXG5PoatXQii55xAiXGXzY+sROLZ/Y+SLcp9PgJNI9Vz37HpQ74WvDcLT8eqm+kV3FzrA==",
      "license": "BSD-3-Clause",
      "dependencies": {
        "tldts": "^7.0.5"
      },
      "engines": {
        "node": ">=16"
      }
    },
    "node_modules/tr46": {
      "version": "6.0.0",
      "resolved": "https://registry.npmjs.org/tr46/-/tr46-6.0.0.tgz",
      "integrity": "sha512-bLVMLPtstlZ4iMQHpFHTR7GAGj2jxi8Dg0s2h2MafAE4uSWF98FC/3MomU51iQAMf8/qDUbKWf5GxuvvVcXEhw==",
      "license": "MIT",
      "dependencies": {
        "punycode": "^2.3.1"
      },
      "engines": {
        "node": ">=20"
      }
    },
    "node_modules/undici": {
      "version": "8.10.0",
      "resolved": "https://registry.npmjs.org/undici/-/undici-8.10.0.tgz",
      "integrity": "sha512-HvltHd7avK13QIw/oLe4qoOLyoVSoafqJ2jYOrtMRBkbYT31eiBQ8O0ehRKZiEZCMEyLFQNIADpgCWC5fALvYQ==",
      "license": "MIT",
      "engines": {
        "node": ">=22.19.0"
      }
    },
    "node_modules/w3c-xmlserializer": {
      "version": "5.0.0",
      "resolved": "https://registry.npmjs.org/w3c-xmlserializer/-/w3c-xmlserializer-5.0.0.tgz",
      "integrity": "sha512-o8qghlI8NZHU1lLPrpi2+Uq7abh4GGPpYANlalzWxyWteJOCsr/P+oPBA49TOLu5FTZO4d3F9MnWJfiMo4BkmA==",
      "license": "MIT",
      "dependencies": {
        "xml-name-validator": "^5.0.0"
      },
      "engines": {
        "node": ">=18"
      }
    },
    "node_modules/webidl-conversions": {
      "version": "8.0.1",
      "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-8.0.1.tgz",
      "integrity": "sha512-BMhLD/Sw+GbJC21C/UgyaZX41nPt8bUTg+jWyDeg7e7YN4xOM05YPSIXceACnXVtqyEw/LMClUQMtMZ+PGGpqQ==",
      "license": "BSD-2-Clause",
      "engines": {
        "node": ">=20"
      }
    },
    "node_modules/whatwg-mimetype": {
      "version": "5.0.0",
      "resolved": "https://registry.npmjs.org/whatwg-mimetype/-/whatwg-mimetype-5.0.0.tgz",
      "integrity": "sha512-sXcNcHOC51uPGF0P/D4NVtrkjSU2fNsm9iog4ZvZJsL3rjoDAzXZhkm2MWt1y+PUdggKAYVoMAIYcs78wJ51Cw==",
      "license": "MIT",
      "engines": {
        "node": ">=20"
      }
    },
    "node_modules/whatwg-url": {
      "version": "17.1.0",
      "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-17.1.0.tgz",
      "integrity": "sha512-3GeworPmc2ZfEEHP7lEbUfBX/L75wdEsi0rLNhXcXxnoN5jyq0SL5gCy06SGW2cyTIZdTvWIDQNQoza++vKeaw==",
      "license": "MIT",
      "dependencies": {
        "@exodus/bytes": "^1.15.1",
        "tr46": "^6.0.0",
        "webidl-conversions": "^8.0.1"
      },
      "engines": {
        "node": "^22.14.0 || >=24.0.0"
      }
    },
    "node_modules/xml-name-validator": {
      "version": "5.0.0",
      "resolved": "https://registry.npmjs.org/xml-name-validator/-/xml-name-validator-5.0.0.tgz",
      "integrity": "sha512-EvGK8EJ3DhaHfbRlETOWAS5pO9MZITeauHKJyb8wyajUfQUenkIg2MvLDTZ4T/TgIcm3HU0TFBgWWboAZ30UHg==",
      "license": "Apache-2.0",
      "engines": {
        "node": ">=18"
      }
    },
    "node_modules/xmlchars": {
      "version": "2.2.0",
      "resolved": "https://registry.npmjs.org/xmlchars/-/xmlchars-2.2.0.tgz",
      "integrity": "sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw==",
      "license": "MIT"
    }
  }
}
package.json
{
  "name": "npm-jsdom-cookiejar",
  "version": "1.0.0",
  "private": true,
  "type": "module",
  "dependencies": {
    "jsdom": "30.0.1"
  }
}
test/contract.mjs
import { JSDOM, CookieJar } from 'jsdom';
import assert from 'node:assert';

// Initialize a shared CookieJar instance
const cookieJar = new CookieJar();

// 1. Setting document.cookie synchronizes with the shared CookieJar
const domMain = new JSDOM('<!DOCTYPE html><html><body></body></html>', {
  url: 'https://example.com/dashboard',
  cookieJar
});

domMain.window.document.cookie = 'sessionId=sess_123; path=/; domain=example.com';
assert.strictEqual(domMain.window.document.cookie, 'sessionId=sess_123');
assert.strictEqual(
  cookieJar.getCookieStringSync('https://example.com/'),
  'sessionId=sess_123'
);

// 2. Windows sharing the same CookieJar on the same origin domain read the synchronized cookie
const domSameDomain = new JSDOM('<!DOCTYPE html><html><body></body></html>', {
  url: 'https://example.com/settings',
  cookieJar
});
assert.strictEqual(domSameDomain.window.document.cookie, 'sessionId=sess_123');

// 3. Domain and path isolation across shared CookieJar
const domOtherDomain = new JSDOM('<!DOCTYPE html><html><body></body></html>', {
  url: 'https://example.org/home',
  cookieJar
});
assert.strictEqual(domOtherDomain.window.document.cookie, '');

domMain.window.document.cookie = 'adminKey=adm_secret; path=/admin; domain=example.com';

const domAdminPath = new JSDOM('<!DOCTYPE html><html><body></body></html>', {
  url: 'https://example.com/admin/control',
  cookieJar
});
assert(domAdminPath.window.document.cookie.includes('adminKey=adm_secret'));
assert(domAdminPath.window.document.cookie.includes('sessionId=sess_123'));

// domSameDomain at /settings is outside /admin path and does not receive adminKey
assert.strictEqual(domSameDomain.window.document.cookie, 'sessionId=sess_123');

// 4. HttpOnly cookies stored in CookieJar are hidden from document.cookie, and client HttpOnly writes are dropped
cookieJar.setCookieSync(
  'serverAuth=srv_token; HttpOnly; Domain=example.com; Path=/',
  'https://example.com/'
);

// CookieJar stores HttpOnly cookie for HTTP requests
const allCookiesInJar = cookieJar.getCookieStringSync('https://example.com/');
assert(allCookiesInJar.includes('serverAuth=srv_token'));
assert(allCookiesInJar.includes('sessionId=sess_123'));

// document.cookie omits HttpOnly cookie from script access
assert(!domMain.window.document.cookie.includes('serverAuth'));
assert.strictEqual(domMain.window.document.cookie, 'sessionId=sess_123');

// Attempting to set HttpOnly via document.cookie is ignored per HTML/RFC 6265 spec
domMain.window.document.cookie = 'clientFlag=blocked; HttpOnly; path=/';
assert(!domMain.window.document.cookie.includes('clientFlag'));
assert(!cookieJar.getCookieStringSync('https://example.com/').includes('clientFlag'));

// 5. Secure cookies are accessible on HTTPS origins but withheld on HTTP origins
cookieJar.setCookieSync(
  'secureToken=sec_xyz; Secure; Domain=example.com; Path=/',
  'https://example.com/'
);

const domHttps = new JSDOM('<!DOCTYPE html><html><body></body></html>', {
  url: 'https://example.com/portal',
  cookieJar
});
assert(domHttps.window.document.cookie.includes('secureToken=sec_xyz'));

const domHttp = new JSDOM('<!DOCTYPE html><html><body></body></html>', {
  url: 'http://example.com/portal',
  cookieJar
});
assert(!domHttp.window.document.cookie.includes('secureToken=sec_xyz'));

// 6. Cookie removal via max-age=0 synchronizes deletion to CookieJar
domMain.window.document.cookie = 'sessionId=; path=/; domain=example.com; max-age=0';
assert(!domMain.window.document.cookie.includes('sessionId'));
assert(!cookieJar.getCookieStringSync('https://example.com/').includes('sessionId'));

Seeder de origen

csx-seed