Fix R.clone returning the same reference for Error objects#3533
Merged
Conversation
R.clone fell through to the default switch branch for Error values and returned the source error itself, so clone(error) === error and mutating the result mutated the original, violating clone's contract. Clone errors into a fresh object that shares the source prototype (so subtypes and instanceof are preserved) and deep-clone own properties, carrying over the non-enumerable message, stack and AggregateError errors. Closes ramda#3390
Coverage Summary> ramda@0.32.0 coverage:summary
> BABEL_ENV=cjs nyc --reporter=text-summary mocha -- --reporter=min --require @babel/register
�[2J�[1;3H
1210 passing (855ms)
=============================== Coverage summary ===============================
Statements : 94.04% ( 2523/2683 )
Branches : 85.84% ( 982/1144 )
Functions : 93.38% ( 564/604 )
Lines : 94.3% ( 2365/2508 )
================================================================================ |
kedashoe
approved these changes
Jun 26, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
R.clonedocuments that it "creates a deep copy of the source that can be used in place of the source object without retaining any references to it." ForErrorvalues this is broken:type(value)returns'Error', which is not handled in_clone's switch, so it falls through todefault: return valueand hands back the same error.This is issue #3390. A core contributor confirmed it there ("we do not attempt to handle
Error") and suggested the fix should "create a newErrorwith some properties set on it" — which is what this PR does.Fix
Add an
'Error'case to_clonethat:Object.create(Object.getPrototypeOf(value)), so the subtype andinstanceofare preserved (TypeErrorstays aTypeError, customErrorsubclasses stay their class);copyhelper to deep-clone own enumerable properties and register the clone for circular-reference handling;message,stackanderrors(AggregateError) own properties, deep-cloning them like everything else.Using
Object.createon the prototype (rather than calling the constructor) avoids constructor side effects and correctly handlesAggregateError, whose constructor takes an iterable of errors as its first argument.Tests
Added regression tests to
test/clone.jscovering: no retained reference + deep-cloned own properties + preservedmessage/stack; prototype preservation forTypeError/RangeError/SyntaxError/ReferenceError; andAggregateErrorincluding its non-enumerableerrors.Expected "actual" not to be reference-equal to "expected").1213 passing) andeslintis clean.Closes #3390