Skip to content

📦🔥:keep non-plain objects whole in deep copies - #91

Merged
openinf-commit-queue[bot] merged 1 commit into
mainfrom
claude/project-thread-2s9ymn
Oct 1, 2026
Merged

openinf-commit-queue[bot] merged 1 commit into
mainfrom
claude/project-thread-2s9ymn

Conversation

@DerekNonGeneric

@DerekNonGeneric DerekNonGeneric commented Oct 1, 2026 •

Copy link
Copy Markdown
Member

Requested by DerekNonGeneric

Before: deepAssign({}, { fn, when: new Date(0), m: new Map(), re: /x/g }) returned { fn: {}, when: {}, m: {}, re: {} }. deepMixin did the same. deepMerge({ d: new Date(0) }, { d: new Date(5) }) kept the old date, because it merged one Date into the other and a Date has no own properties to copy.

After: functions, Dates, Maps, RegExps and class instances are assigned by reference, and only plain objects are copied or merged property by property.

This is the rule _copyDeep already follows inside arrays.

How: _mixin and deepMerge now check the source value with isPlainObject before they recurse. Tests for all three helpers fail on main and pass here.

Summary by CodeRabbit

  • Bug Fixes
    • Deep assignment and mixing now recursively copy plain objects and arrays while preserving other values—such as dates, maps, functions, and class instances—by reference.
    • Deep merging now replaces existing target values with source values such as dates and maps, rather than merging into those values.
  • Documentation
    • Clarified how deep assignment, mixing, and merging handle nested values.

deepAssign and deepMixin recursed into every object a source held, so a
function, a Date, a Map, a RegExp or a class instance came out as an
empty {}. They now copy only plain objects property by property and
assign everything else by reference, as _copyDeep already does inside
an array.

deepMerge, like the other two where the target already held an object,
merged a source Date or Map into the target's one. Neither carries its
state in own properties, so the target's old value survived. Only a
plain source object is merged now.

Signed-off-by: Derek Lewis <DerekNonGeneric@inf.is>
Assisted-by: Claude-Code:claude-opus-5
@coderabbitai

coderabbitai Bot commented Oct 1, 2026 •

Copy link
Copy Markdown

Review in Change Stack →

Navigate logical layers of code changes, visualize relationships, and explore their blast radius.

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Essentials

Run ID: 0ad6fc3a-7554-40ae-9fa5-3d19908e3ac4

📥 Commits

Reviewing files that changed from the base of the PR and between 45679ff and 81d778b.

📒 Files selected for processing (8)
  • .changeset/deep-copies-keep-objects.md
  • packages/util-object/src/_internal/_mixin.ts
  • packages/util-object/src/helpers/deep-assign.ts
  • packages/util-object/src/helpers/deep-merge.ts
  • packages/util-object/src/helpers/deep-mixin.ts
  • packages/util-object/test/helpers/deep-assign.ts
  • packages/util-object/test/helpers/deep-merge.ts
  • packages/util-object/test/helpers/deep-mixin.ts

Included review availability: This review used your included allowance. 3 included reviews remain after this review. Your included PR review attempts over the past 7 days set your current allowance at 4 reviews per hour.


📝 Walkthrough

Walkthrough

Deep assignment and mixin now recursively copy nested plain objects and arrays while retaining other values by reference. Deep merge now recursively merges plain source objects and replaces target values with other source values.

Changes

Deep copy and merge behavior

Layer / File(s) Summary
Deep assignment and mixin behavior
.changeset/deep-copies-keep-objects.md, packages/util-object/src/_internal/_mixin.ts, packages/util-object/src/helpers/deep-assign.ts, packages/util-object/src/helpers/deep-mixin.ts, packages/util-object/test/helpers/deep-assign.ts, packages/util-object/test/helpers/deep-mixin.ts
The shared mixin implementation recurses into plain objects. Documentation and tests specify that functions and non-plain objects, including dates, maps, regular expressions, and class instances, are assigned by reference.
Deep merge behavior
packages/util-object/src/helpers/deep-merge.ts, packages/util-object/test/helpers/deep-merge.ts
Deep merge now recurses only for plain source objects. Other source values replace target values. Tests verify that source Date and Map instances replace the target values.

Priority: ⬇️ Low

Estimated code review effort: 2 (Simple) | ~10 minutes

Change: Bug fix

Merge Risk: ⚪ Minimal · up to 81d77

The changes consistently preserve non-plain values by reference while retaining recursive handling for plain objects. No concrete merge-blocking risk is established; merge after normal checks pass.

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 2 functions across 7 files. (1 skipped: 1 …
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly summarizes the main change: non-plain objects remain intact during deep-copy operations. The emojis add noise but do not obscure the meaning.
✨ Finishing Touches
📝 Generate docstrings
  • Commit to this branch
  • Create a new PR
🧪 Generate unit tests (beta)
  • Commit to this branch
  • Create a new PR
  • Autopilot · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Autopilot is currently an internal CodeRabbit preview.


Comment @coderabbitai help to get the list of available commands.

@DerekNonGeneric DerekNonGeneric self-assigned this Oct 1, 2026
@DerekNonGeneric DerekNonGeneric added the 🚀 Status: Commit Queue Land this pull request when its checks pass label Oct 1, 2026 — with Claude
@openinf-commit-queue
openinf-commit-queue Bot merged commit 4f95bf7 into main Oct 1, 2026
10 checks passed
@openinf-commit-queue openinf-commit-queue Bot removed the 🚀 Status: Commit Queue Land this pull request when its checks pass label Oct 1, 2026
@openinf-commit-queue
openinf-commit-queue Bot deleted the claude/project-thread-2s9ymn branch October 1, 2026 00:43
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant