Skip to content

fix: preserve native Temporal values when cloning - #1722

Open
louisss1016 wants to merge 1 commit into
arktypeio:mainfrom
louisss1016:fix/1719-temporal-clone
Open

louisss1016 wants to merge 1 commit into
arktypeio:mainfrom
louisss1016:fix/1719-temporal-clone

Conversation

@louisss1016

Copy link
Copy Markdown

Summary

Closes #1719.

ArkType's default clone kept Temporal prototypes but lost the internal slots used by methods such as toString(). Preserve direct native Temporal instances from the current realm by recognizing the eight standard prototypes. Ordinary objects still follow the existing cloning rules, including objects with a Temporal-like string tag. TC39 Temporal documentation

Verification

  • Compared upstream 326cdce3 and this patch on Ubuntu 24.04 under WSL2 with Node 26.13.0, npm 10.9.3 and pnpm 10.19.0.
  • NODE_OPTIONS=--no-webstorage pnpm prChecks passed on both revisions. Each of the two runtime suites went from 1,813 to 1,817 passing tests. All 63 Attest tests and seven TypeScript compatibility tasks passed on both. Used the same Node option for both runs after a transient SQLite lock in the docs build.
  • pnpm testFiles ark/util/__tests__/clone.test.ts ark/type/__tests__/clone.test.ts passed all 20 focused tests. With the tests applied to unchanged source, three cases failed with the expected incompatible receiver error.
  • Checked all eight native Temporal types and the fallback when the Temporal global is absent. The public morph regression covers declared and retained properties and verifies that the input stays intact.

This change was developed and validated with OpenAI Codex assistance.

@github-project-automation github-project-automation Bot moved this to To do in arktypeio Nov 4, 2026
ssalbdivad added a commit that referenced this pull request Nov 9, 2026
Featherduster's morph path no longer reproduces #1719: transforms copy
on write, and copyOf already leaves any object whose toString tag is
not [object Object] in place, so a Temporal value beside a transformed
key passes through untouched. The new transform test pins that with a
native Temporal.Instant (skipped where the runtime has no Temporal).

@ark/util's public deepClone/shallowClone still had the 2.x bug: any
object that was not an exact builtin by `constructor` was rebuilt with
Object.create(prototype) plus its own properties, which throws
"incompatible receiver" on the first method call for every Temporal
type, DataView, URLSearchParams, AbortController and subclasses of
Map, Date, etc. It now follows the same toString-tag rule as copyOf,
which also covers a Temporal polyfill (Symbol.toStringTag) and a
Temporal from another realm, unlike matching the native Temporal
prototypes captured at module load (PR #1722 on main).

Remaining gaps, same as copyOf: an ordinary object with a custom
Symbol.toStringTag is shared rather than copied, a Date subclass is
shared rather than copied, and a class with #private fields still
breaks, since nothing observable separates it from a plain instance.

Closes #1719
ssalbdivad added a commit that referenced this pull request Nov 9, 2026
…uthors

Each fix below landed on featherduster from a port or an independent fix,
but each started from a reasonable community PR against 2.x, and the
CHANGELOG thanks every contributor whose work this release supersedes:

- #1721 (@RaphaelFakhri): fast-check keeps a regex's flags (#1720)
- #1722 (@louisss1016): Temporal values survive a morph / deepClone (#1719)
- #1725 (@RClaudiuM): an undefined discriminant case checks its key (#1724)
- #1715 (@SynthLuvr): ~standard.jsonSchema.input drops undefined (#1462);
  only its input half was taken, output keeps routing to fallback.unit

#1718 is not credited: 3.0 answers #1469 with jsonSchema meta rather than
its bare pattern key. #1705 and #1695 were already thanked.

Also notes that a cyclic index signature with no way out now generates
shrinking dictionaries instead of overflowing the stack (6f4dd5d).
@ssalbdivad ssalbdivad mentioned this pull request Nov 9, 2026

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: To do

Development

Successfully merging this pull request may close these issues.

Temporal values lose their internal slots when a type with morphs clones its input

1 participant