-
Notifications
You must be signed in to change notification settings - Fork 27.4k
fix($parse): allow watching object/array literals #15274
Conversation
This sounds more like a feature than a fix. |
I wonder how much people would abuse this, without realizing it is inefficient :) |
|
||
var initialValue = destination[scopeName] = parentGet(scope); | ||
initialChanges[scopeName] = new SimpleChange(_UNINITIALIZED_VALUE, destination[scopeName]); | ||
|
||
removeWatch = scope.$watch(parentGet, function parentValueWatchAction(newValue, oldValue) { | ||
if (oldValue === newValue) { | ||
if (oldValue === initialValue || (deepWatch && equals(oldValue, initialValue))) { | ||
if (equals(oldValue, initialValue)) { |
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 different that what we had before. equals(oldValue, initialValue)
might be true even if oldValue !== initialValue
for non-literals. In that case, we don't want to return.
This line shouldn't change afaict.
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.
I was hoping to remove all "deepWatch" logic from here. I can just revert it, but any other ideas?
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.
I don't have any better idea 😞
The thing is we need to call $onChanges
synchronously (while the watchAction will only fire asynchronously), so we call $onChanges
manually. When the watchAction does fire for the first time we need to determine if the value has changed - i.e. if initialValue
is equal to oldValue
in the $watch
sense. That's why we need to differentiate between literals (compared using equals
) and non-literals (compared using ===
).
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.
I've undone this and added tests in a separate PR: #15300
I think this is a fix because today That said... I think I would prefer a BC where we stop using |
f927484
to
6b6f12c
Compare
@@ -3522,7 +3522,7 @@ function $CompileProvider($provide, $$sanitizeUriProvider) { | |||
} | |||
recordChanges(scopeName, newValue, oldValue); | |||
destination[scopeName] = newValue; | |||
}, deepWatch); |
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 probably makes sense to rename deepWatch
now that isn't not used for deep-watching 😃
It still feels more like a feature to me. It is only by chance that "shallow" literals started working at some point. 😃 LGTM (but it would be good for someone else to take a look as well) |
I think I'd actually prefer to close this in favour of only doing #15301 in 1.7. This PR makes literals consistent by expanding the deep-equals functionality of one-way-bindings to all watched literals. Where #15301 makes literals consistent by removing the deep-equals and instead (simple) watching only the variables within the literal. So we probably shouldn't expand the use of deep-equals if we plan to land #15301 and remove it... |
Works for me. Feel free to go ahead and close this in favor of #15301. |
Closing then... also note that I think the first commit in #15301 could go into 1.6, but I'll comment on that there... |
This moves the object/array-literal watching logic from $compile to $parse so it can by used by watchers anywhere (not only bindings).
By moving this to
$parse
we can potentially improve it more. Maybe pushing theequals
check intoexpressionInputDirtyCheck
for literals, then we can avoid creating the object and avoid callingequals
on the full object each digest?What kind of change does this PR introduce? (Bug fix, feature, docs update, ...)
bug fix
What is the current behavior? (You can also link to an open issue here)
watching object/array literals throws infdig if any inputs are non-simple values
What is the new behavior (if this is a feature change)?
watching object/array literals does what compile previously did to solve this
Does this PR introduce a breaking change?
no
Please check if the PR fulfills these requirements