Skip to content

fix: merge symbol keys#162

Open
mvtandas wants to merge 1 commit intounjs:mainfrom
mvtandas:fix/symbol-keys-merge
Open

fix: merge symbol keys#162
mvtandas wants to merge 1 commit intounjs:mainfrom
mvtandas:fix/symbol-keys-merge

Conversation

@mvtandas
Copy link
Copy Markdown

@mvtandas mvtandas commented Apr 13, 2026

Summary

Fixes #145

Object.keys() does not iterate over Symbol keys, causing them to be silently dropped during merge. This changes the iteration to Reflect.ownKeys() which includes both string and symbol keys.

Root Cause

for (const key of Object.keys(baseObject)) { // ← skips Symbol keys

The spread in { ...defaults } already copies symbol keys from defaults, but symbol keys from baseObject were ignored.

Fix

- for (const key of Object.keys(baseObject as Record<string, any>)) {
+ for (const key of Reflect.ownKeys(baseObject as Record<string | symbol, any>)) {

Tests

Added 3 test cases:

  • merges symbol keys — full merge with override + array concat
  • preserves symbol keys from defaults — symbol key in defaults only
  • overrides symbol keys from base — symbol key in base overrides default

All 26 tests pass. Lint and type checks clean.

Summary by CodeRabbit

  • New Features

    • Extended property merging to properly handle symbol-keyed properties and non-enumerable keys in addition to traditional enumerable string keys
  • Tests

    • Added test cases covering symbol key handling including merging with array value concatenation, preserving defaults, and allowing base object overrides

`Object.keys()` does not iterate over Symbol keys, causing them to be
ignored during merge. This changes the iteration to `Reflect.ownKeys()`
which includes both string and symbol keys.

The spread operator in `{ ...defaults }` already copies symbol keys
from the defaults object, but symbol keys from `baseObject` were
silently dropped.

Fixes unjs#145
@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Apr 13, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 59c5b906-5c60-4422-a2da-9420b5457e2b

📥 Commits

Reviewing files that changed from the base of the PR and between 80c0146 and 90ab0a5.

📒 Files selected for processing (2)
  • src/defu.ts
  • test/defu.test.ts

📝 Walkthrough

Walkthrough

The defu function was updated to handle symbol keys by replacing Object.keys() with Reflect.ownKeys() for property iteration. Property access was adjusted to safely support symbol indexing. Three test cases validate symbol key merging, preservation, and override behavior.

Changes

Cohort / File(s) Summary
Core Symbol Key Support
src/defu.ts
Replaced Object.keys() with Reflect.ownKeys() to iterate over symbol-keyed properties in addition to string keys. Adjusted property access via type cast to enable safe indexing with symbol keys. Skip logic for "__proto__" and "constructor" preserved.
Symbol Key Test Coverage
test/defu.test.ts
Added three test cases: merging symbol keys with array concatenation, preserving symbol properties from defaults on empty base, and allowing symbol key overrides from base object.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~8 minutes

Suggested reviewers

  • pi0

Poem

🔮 A symbol walked into a merge, so mystical and bold,
Where once it hid from Object.keys, now Reflect makes it unfold,
With ownKeys as the magic wand, no secret stays concealed,
Symbol merging, properly sealed! ✨

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed Title 'fix: merge symbol keys' directly describes the primary change—replacing Object.keys with Reflect.ownKeys to handle Symbol-keyed properties.
Linked Issues check ✅ Passed All code changes directly address issue #145: Reflect.ownKeys now iterates Symbol keys from the base object, matching the expected behavior with array concatenation and property override handling.
Out of Scope Changes check ✅ Passed All changes are scoped to the Symbol-key merge functionality: the iteration mechanism in src/defu.ts and three focused test cases in test/defu.test.ts.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

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

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.

Symbol keys are not merged

1 participant