-
Notifications
You must be signed in to change notification settings - Fork 41
Fixed merge for substitutions #138
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
Oops, seems like there are some failing tests... I will fix that |
@@ -394,7 +395,7 @@ public IHoconElement Clone(IHoconElement newParent) | |||
var clone = new HoconObject(newParent); | |||
foreach (var kvp in this) | |||
{ | |||
clone.SetField(kvp.Key, kvp.Value); | |||
clone.SetField(kvp.Key, kvp.Value.CloneValue(clone) as HoconField); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We need to clone all child elements as well, to make deep copy of referenced subtree
@@ -184,7 +184,7 @@ private HoconValue ResolveSubstitution(HoconSubstitution sub) | |||
|
|||
// third case, regular substitution | |||
_root.GetObject().TryGetValue(sub.Path, out var field); | |||
return field; | |||
return field?.Clone(field.Parent) as HoconValue; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Returning clone of the references sub-tree, which is safe for modifications
* Added failing test * Make substitution to use deep copy + fixed deep clone for some types * NRE fix * Fixed deep clone to take substitutions into account
Close #127
The basic idea of the fix is that in current implementation substitution takes value "by reference" - which means that when object merge occurs the initial value, referenced in substitution, is modified. This could lead to lots of issues, not only with the once described in closing issue.
So the fix is basically make substitution to just deeply copy referenced sub-tree, so that it was safe to modify.
In the edge case when we do not need to modify referenced object we could still keep the "be reference" behavior instead of "by value". Not sure if it will save much performance and if it is important at all. But checking if we are somehow, somewhere modifying substituted value (not to say that we could reference one sub-tree, that includes another substitution that could also be modified then) - too complicated. So let's just take it by value and sleep soundly at night.