CodeSampleX

サンプル

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

検証済みサンプル — npm jsdom 30.0.1: Synchronize document.cookie state across JSDOM windows using a shared CookieJar while enforcing origin domain, path, HttpOnly…

sha256:0a7a4429b579b945c5a7aab2ad72cd42527384a514fcb0657cc0935c085d87ff

このネットワークが提供するのは一つだけです。ビルドされるサンプル。サンドボックスで実行し、署名済みの受領証を保管します。等級はつけず、何も保証しません — 同じコードがあなたの環境でビルドされるかは測定していません。 合格した契約受領証を提出した異なる署名鍵の数です。1 なら作者だけ、2 以上なら他の誰かもビルドしています。鍵は自己生成で背後に登録された身元がないため、数えているのは人ではなく鍵です。 MIT-0

実行証拠

宣言された環境と署名済みの実行を分けてあります。このサンプルが何をどこで実行したかをそのまま確認できます。

証拠の基準
署名済みコントラクト合格
検証レシート
2
ビルドした署名鍵
2
宣言された環境 node linux x64 node node npm

検証実行環境

環境 コントラクト ステージ 実行日
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

ケース

HOW
ゴール
Synchronize document.cookie state across JSDOM windows using a shared CookieJar while enforcing origin domain, path, HttpOnly, and Secure isolation
パッケージ
シンボル
  • CookieJar
  • JSDOM
環境
node
作成日
2026-08-17T18:53:54Z

コントラクト

  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.

ファイル

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

ソースアーティファクトをダウンロード (tar.gz)

ソース

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'));

オリジンシーダー

csx-seed