-
Notifications
You must be signed in to change notification settings - Fork 27.4k
fix($parse): allow assignment on objects in locals #10322
Conversation
CLAs look good, thanks! |
If this lands, it would be good to update the docs as well. BTW, the whole concept of |
I have to admit that I did not read the patch with a lot of care, but it looks like there are cases that this PR is not handling Eg |
I think that specific case already works. Should probably add more tests similar to that though... |
@gkalpak I agree it is a little weird but I think it should be consistent. Think of |
d0e87f3
to
c0a08e9
Compare
I've updated the tests to better cover the 3 different |
@jbedard, you think you mean:
which does already work. After this PR, the above snippet will result in Do I miss something ? |
@gkalpak you're right it needs the brackets. The issue is that the assignment went to |
Not really 😄 If @IgorMinar thought this should be added, then it probably should :) |
Note that we are never assigning to locals but are fetching the |
missing: documentation of the extra parameter to |
It is adding some code for something that I don't really expect anyone to actually use, though |
I agree it isn't really useful, or at least I've never wanted to modify an object in locals. I think it is logically correct though: |
@@ -937,8 +938,8 @@ function getterFn(path, options, fullExp) { | |||
} | |||
|
|||
fn.sharedGetter = true; | |||
fn.assign = function(self, value) { | |||
return setter(self, path, value, path); | |||
fn.assign = function(self, value, locals) { |
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.
this is what I'm referring to, @jbedard
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.
This is just 1 of 3 assign
implementations though. The others already had the third param so it is nothing new, it was just missing from this implementation...
You want to document it to make it public though?
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.
there's no reason not to document it --- nobody has a good reason to use it anyways, but we aren't using it as a private API anywhere
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.
It's used within this file, just this version (unlike the other 2/3) did not support it...
Hi @jbedard, sorry to insist on this same point once again, but the patch as-is is not handling many cases. Here are a few expect(function() {
$rootScope.$eval('{c: null}.c.d = 1');
}).toThrowMinErr(/* */);
delete $rootScope.x;
$rootScope.$eval('x[a][b] = true', {a: 'foo', b: 'bar'});
expect($rootScope.x.foo.bar).toBe(true);
delete $rootScope.x;
$parse('x[a][b]').assign($rootScope, true, {a: 'foo', b: 'bar'});
expect($rootScope.x.foo.bar).toBe(true);
delete $rootScope.x;
$parse('x[a].bar').assign($rootScope, true, {a: 'foo'});
expect($rootScope.x.foo.bar).toBe(true); |
just like these, there are several cases than need new tests |
@lgalfaso sorry I guess didn't understand your original point, thanks for clarifying! I think those are all from the |
@jbedard yep, it is a bigger patch than what it looks like... that is why it was a 1.4 candidate :) |
I still think it won't be too bad, but I'll try it later and report back. Thanks for the test cases! |
please, do not get me wrong, I think it is possible but it is a patch that needs some careful work |
c0a08e9
to
8a06651
Compare
@lgalfaso for the The other cases are fixed. Those were introduced in c03ad24 which did not pass the locals through (unlike the non object creating case that has always passed it through). |
8a06651
to
a96a0ca
Compare
if (!o) object.assign(scope, o = {}); | ||
return setter(o, field, value, expression); | ||
if (!o) object.assign(scope, o = {}, locals); | ||
return setter(o, null, field, value, expression); |
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.
why not pass the locals
in here too?
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.
Because we are specifically assigning to a property on the object o
which was already fetched from the scope/locals. For example with (object).b = 1
... (object)
is evaluated using scope+locals, but the .b = 1
should only be evaluated on the object returned from (object)
.
This seems reasonable to me - if we are providing an object in the var obj = { name: 'outer' };
function changeObj() {
var obj = { name: 'inner' };
expect(obj.name).toEqual('inner');
obj.value = 42;
expect(obj.value).toEqual(42);
}
changeObj();
expect(obj.name).toEqual('outer');
expect(obj.value).toBeUndefined(); |
a96a0ca
to
4cfcb83
Compare
Updated and rebased. |
Fixes #4664
I saw this issue on the 1.4 list but the fix seems simple...