Skip to content
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

Arrays are not copied properly - keys are lost #52

Closed
arturog opened this issue Jul 11, 2017 · 9 comments
Closed

Arrays are not copied properly - keys are lost #52

arturog opened this issue Jul 11, 2017 · 9 comments

Comments

@arturog
Copy link

arturog commented Jul 11, 2017

Consider:

a = { items: [ { name: 'Superman', strength: 1000 }, { name: 'Jim', strength: 2 } ]
a.items.top = 0
a
// =>
// { items: 
//    [ { name: 'Superman', strength: 1000 },
//      { name: 'Jim', strength: 2 },
//      top: 0 ] }
c
=>
 { items: [
    { name: "Superman", strength: 1000 },
    { name: "Jim", strength: 2 }
  ] 
}
cmd = { items: { 1: { strength: { $set: 3 } } } }
b = update(a, cmd)
b
// =>
// { items: 
//    [ { name: 'Superman', strength: 1000 },
//      { name: 'Jim', strength: 3 } ] }

Notice the "top" key was lost. The culprit is (I believe) line 22 where it should be:

function copy(object) {
  if (object instanceof Array) {
-     return object.slice();
+     return assign(object.constructor(), object)
  } else if (object && typeof object === 'object') {
    var prototype = object.constructor && object.constructor.prototype

Keys should not be lost.

hoytech pushed a commit to hoytech/update-immutable that referenced this issue Jul 11, 2017
- Solves this issue where additional array keys were not preserved:
  kolodny/immutability-helper#52
@kolodny
Copy link
Owner

kolodny commented Jul 11, 2017

Thanks for the feedback. This has been fixed in 2.3.0

@kolodny kolodny closed this as completed Jul 11, 2017
@arturog
Copy link
Author

arturog commented Jul 11, 2017

Awwsome!

@arturog
Copy link
Author

arturog commented Jul 16, 2017

$push and $unshift lose keys as well. I had to change them. How do you reopen issues in github?

  $push: function(value, nextObject, spec) {
    invariantPushAndUnshift(nextObject, spec, '$push');
-   return value.length ? nextObject.concat(value) : nextObject;
+   if (value.length) {
+     nextObject = copy(nextObject)
+     nextObject.push.apply(nextObject, value)
+   }
+   return nextObject;
  },
  $unshift: function(value, nextObject, spec) {
    invariantPushAndUnshift(nextObject, spec, '$unshift');
-   return value.length ? value.concat(nextObject) : nextObject;
+   if (value.length) {
+     nextObject = copy(nextObject)
+     nextObject.unshift.apply(nextObject, value)
+   }
+   return nextObject;
  },

@kolodny
Copy link
Owner

kolodny commented Jul 17, 2017

$push and $unshift should lose keys. Consider the following:

var a = ['w','x','y']
a.foo = 'bar'
var b = a.concat(['z'])
b.foo === undefined

The reason why this isn't true in $set is because $set is a replacement for doing a[prop] = value which the object "returned" would retain any properties that existed in the array.

I'd suggest overriding the $push and $unshift directives to support non standard keys to be retained in the next object

@arturog
Copy link
Author

arturog commented Jul 17, 2017 via email

@kolodny
Copy link
Owner

kolodny commented Jul 18, 2017

Yes $push is basically a concat, meaning a new object is expected, as opposed to a set which is just reusing the old object

@arturog
Copy link
Author

arturog commented Jul 18, 2017 via email

hoytech added a commit to hoytech/update-immutable that referenced this issue Jul 19, 2017
@ghost
Copy link

ghost commented Feb 21, 2019

If $push is actually a concat, why is it called push?
Same goes for $splice, instead shouldn't it be named $slice? If applicable.

@jednano
Copy link
Collaborator

jednano commented Feb 21, 2019

I agree that $concat would be more indicative of how this feature works. Sounds like a good candidate for a breaking change, in fact.

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

No branches or pull requests

3 participants