-
Notifications
You must be signed in to change notification settings - Fork 27
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
fix: issue with array methods that re-assign indexes #45
Open
ahmedkandel
wants to merge
2
commits into
salesforce:master
Choose a base branch
from
ahmedkandel:fix-array-methods
base: master
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from 1 commit
Commits
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains 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
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.
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.
Ok, this change does makes sense, but I think it should be a lot more generic. Let me loop more folks into this because IIRC there are some history around this. /cc @ravijayaramappa @davidturissini
I believe
defineProperty
is doing the right thing by unwrapping the value in the descriptor when setting it into the original target. The set trap should do the same all the time by just simply unwrap the value before setting that up. The question is, what are the implications of such generalization.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.
unwrapping the value all the time will cause some issues:
writeAndRead.baz[0].foo
will return 'qux' not 'bar'p.y[1]
will yield an object but not a proxyThat's why I had to narrow the scope to array items re-assignment. Also by checking
originalTarget.includes(unwrapProxy(value))
we make sure we conserve a proxy value if it does exist.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.
@ahmedkandel thanks for bringing this up, now I remember a lot more about this. Ok, let me try to articulate my position on this:
I don't think this is an array specific issue, I think it is a fundamental issue, it also affects objects of those objects have functions that carry mutation similars to those done by the array intrinsics.
yes, readOnly proxies have particular semantics that have to be preserved, should not be that hard IMO.
Now, let me state the problem, the way I see it:
Lets use a code of colors, which I find easier to understand, in this library we have two colors: yellow and blue:
Operations to control by this membrane for RW:
a.
Reflect.set(yellowRWObject, key, blueValue)
as a result, a blueValue should be set into the target of the yellowRWObject (that target is another blueValue). (no unwrapping needed)b.
Reflect.set(yellowRWObject, key, yellowROValue)
as a result, a yellowROValue should be set into the target of the yellowRWObject (that target is another blueValue). I call this a leaking escape hatch, which is a necessary evil to avoid making a RO value a RW value by all means. (no unwrapping needed)c.
Reflect.set(yellowRWObject, key, yellowRWValue)
as a result, the target of the yellowRWValue should be set into the target of the yellowRWObject (that target is another blueValue). (unwrapping needed)Operations to control by this membrane for RO Objects are not that important because they just throw for all cases.
What all this tell us, is that the only condition that needs to be added is for the case where a RO value is about to be set into a RW value as a property, in which case no unwrapping should be done (case b above), while for the rest, should require unwrapping attempts.
In terms of the code, let me adjust my proposal:
We can either create that new method (with a better name), or reuse something else. This will also have to be changed in
unwrapDescriptor
method, which is used bydefineProperty
trap to accommodate that as well since it is faulty as well today.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.
Exactly @caridy, I was thinking about this implementation with a little change in (case c above).
When setting
yellowRWValue
, maybe the user has the intention to set a proxyyellowValue
, notblueVlaue
described in my previous comment (case 2 above). While I think it is rare and we can clarify in the documentation that it is not allowed toset()
proxy values to a property as it will get unwarped. Also becauseget()
will always return a proxy whenever the value is observable "membrane is applicable to an entire object graph" so no need for the user to do it by himself.In this case, generalizing value unwrapping in
ReactiveProxyHandler
.set()
anddefineProperty()
traps except for read-only proxy valuesyellowROValue
is a better fix.We can add a new method to
ReactiveMembrane
maybe we name itsafeUnwrapValue
that returnunwrappedValue
if not ayellowROValue
.Another approach is to add a condition to
ReadOnlyHandler
.get()
trapThen we can check it later
if (value[isReadOnlyProxy]) ...
I think the new method approach is better. I will commit it so we could start discussing it.