[PR #541] [CLOSED] fix(replay): pin the replay timezone and map undefined to null #2061

Closed
opened 2026-10-16 21:13:51 +00:00 by bsakaguchi · 0 comments
Owner

📋 Pull Request Information

Original PR: https://github.com/morluto/rea/pull/541
Author: @morluto
Created: 10/5/2026
Status: ❌ Closed

Base: main ← Head: cleanup/replay-confinement


📝 Commits (1)

  • a2955d6 fix(replay): pin the replay timezone and map undefined to null

📊 Changes

2 files changed (+64 additions, -0 deletions)

View changed files

📝 src/replay/JavaScriptReplayWorker.ts (+13 -0)
📝 tests/boundary/providers/replay/javascriptReplayWorker.test.ts (+51 -0)

📄 Description

Completes the replay confinement and projection-policy decisions.

Timezone was the real confinement leak — not the globals the review guessed. The suggested culprits crypto and performance are already absent from the vm context (typeof crypto is undefined), so there was nothing to remove. The actual leak is Intl, which is present: new Intl.DateTimeFormat().resolvedOptions().timeZone and Date.prototype.toLocaleString() both read the host zone, so the same artifact replayed on two machines produced different output. Reproduced directly — host zone Asia/Hong_Kong rendered 1970-01-01, 8:00:00 a.m., Asia/Tokyo rendered 9:00:00. The worker now pins process.env.TZ = "UTC" before anything touches a date, and the suite was re-run under TZ=Asia/Tokyo to prove the result no longer moves.

undefined now projects to null. [undefined] previously raised serialization_error while [ , ] (the hole for the same position, fixed in #522) returned null. JSON has one representation for "no value" here — JSON.stringify([undefined]) is [null] — so rejecting one and accepting the other was inconsistent. undefined maps to null; bigint, function and symbol still raise serialization_error because JSON genuinely cannot represent them, and a fabricated value would be worse than an explicit unknown.

One assertion deliberately weakened: toLocaleString output wording is ICU-build dependent (1/1/1970, 12:00:00 AM vs 1970-01-01, 12:00:00 a.m.), so the test asserts the pinned timezone and the UTC hour rather than an exact string. Asserting exact locale text would make this suite fail on a different Node ICU build without any behaviour having changed.

Tests: undefined maps to null, bigint still reports the reason, and the timezone case asserts UTC under a deliberately hostile host zone. Full suite green: 1926 passed.


🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.

## 📋 Pull Request Information **Original PR:** https://github.com/morluto/rea/pull/541 **Author:** [@morluto](https://github.com/morluto) **Created:** 10/5/2026 **Status:** ❌ Closed **Base:** `main` ← **Head:** `cleanup/replay-confinement` --- ### 📝 Commits (1) - [`a2955d6`](https://github.com/morluto/rea/commit/a2955d66074d588e877238f117700b9b68a03a3f) fix(replay): pin the replay timezone and map undefined to null ### 📊 Changes **2 files changed** (+64 additions, -0 deletions) <details> <summary>View changed files</summary> 📝 `src/replay/JavaScriptReplayWorker.ts` (+13 -0) 📝 `tests/boundary/providers/replay/javascriptReplayWorker.test.ts` (+51 -0) </details> ### 📄 Description Completes the replay confinement and projection-policy decisions. **Timezone was the real confinement leak — not the globals the review guessed.** The suggested culprits `crypto` and `performance` are already absent from the `vm` context (`typeof crypto` is `undefined`), so there was nothing to remove. The actual leak is `Intl`, which *is* present: `new Intl.DateTimeFormat().resolvedOptions().timeZone` and `Date.prototype.toLocaleString()` both read the host zone, so the same artifact replayed on two machines produced different output. Reproduced directly — host zone Asia/Hong_Kong rendered `1970-01-01, 8:00:00 a.m.`, Asia/Tokyo rendered `9:00:00`. The worker now pins `process.env.TZ = "UTC"` before anything touches a date, and the suite was re-run under `TZ=Asia/Tokyo` to prove the result no longer moves. **`undefined` now projects to `null`.** `[undefined]` previously raised `serialization_error` while `[ , ]` (the hole for the same position, fixed in #522) returned `null`. JSON has one representation for "no value" here — `JSON.stringify([undefined])` is `[null]` — so rejecting one and accepting the other was inconsistent. `undefined` maps to `null`; `bigint`, `function` and `symbol` still raise `serialization_error` because JSON genuinely cannot represent them, and a fabricated value would be worse than an explicit unknown. One assertion deliberately weakened: `toLocaleString` output wording is ICU-build dependent (`1/1/1970, 12:00:00 AM` vs `1970-01-01, 12:00:00 a.m.`), so the test asserts the pinned timezone and the UTC hour rather than an exact string. Asserting exact locale text would make this suite fail on a different Node ICU build without any behaviour having changed. Tests: `undefined` maps to null, `bigint` still reports the reason, and the timezone case asserts UTC under a deliberately hostile host zone. Full suite green: 1926 passed. --- <sub>🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.</sub>
bsakaguchi 2026-10-16 21:13:51 +00:00
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
morluto/rea#2061
No description provided.