-
-
Notifications
You must be signed in to change notification settings - Fork 141
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
[WIP] Rewrite to use native Proxy #627
Conversation
export default class ChangesetArrayProxyHandler<T extends Input> implements IChangesetProxyHandler<T> { | ||
constructor(source: T, _options?: ProxyOptions) { | ||
if (source?.constructor?.name === 'ArrayProxy') { | ||
this.__sourceProxy = source as ArrayProxy<any>; |
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.
these should either by symbol properties, or private properties, as they may conflict with folks data
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.
you mean __sourceProxy etc?
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 think these do conflict. Proxy is not a wrapper that falls back to the internals like Ember.ObjectProxy. It explicitly calls in with get
and set
and you do your own fallback. __sourceProxy is private api so it's not available through get and set, and if there was a name conflict it would fall through to the proxied object correctly.
|
||
public get(_target: T, key: string): any { | ||
// extra stuff | ||
switch (key) { |
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.
you can shorten this by doing if (typeof this.readArray[key] === 'function') return this.readArray[key];
, etc
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.
If you notice I have two different ways of doing it
readArray[key] returns the proxy or the source if there's no changes
writeArray[key] creates a proxy if it doesn't exist and returns it
I thought about using a map to choose which one to return. Otherwise readKeys.includes[key]
etc
Thoughts?
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.
typeof this.readArray[key] === 'function'
doesn't work - typescript expects the index to be a number. Is there a way to iterate methods on an array without [key]?
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 aw not sure
@action | ||
public getValue(key: string | symbol) { | ||
switch (key) { | ||
// backwards compatible |
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.
yay back compat
@@ -0,0 +1,7 @@ | |||
export default function isUnchanged(a: any, b: any) { |
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'm loving all these utilities
So, I like where this is going, but the real implementation is here: https://github.com/validated-changeset/validated-changeset |
I didn't realise. But looking at it, |
is true -- but it's also where most of the complexity comes in. is the goal to eliminate the need for validated-changeset? and fwiw, I think it is possible to a better native proxy design with validated-changeset and provide deep reactivity as well -- but, I want to make sure I know what your goals are? |
My goals are to have ember-changes et working for deep nesting without get and set. If that means submitting to validated- changeset instead then that's fine by me |
Ah ok, we can probably do even less work then. Thanks for clarifying! |
} | ||
|
||
public get isValid(): boolean { | ||
// TODO: validate this level |
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.
Todo!
// TODO: validate this level | ||
|
||
// now look at all the nested proxies | ||
for (var proxy of this.__nestedProxies.values()) { |
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 reimplement these behaviors? Couldn't you return tte value from the underlying validated-changeset?
throw `changeset.${key} is readonly`; | ||
} | ||
// nested keys are separated by dots | ||
var [localKey, subkey] = splitKey(key as string); |
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.
What about deeply nested keys? Maybe 5+ layers deep?
// have to use get() here because source might be an EmberProxy | ||
const oldValue = get(this.__source, localKey); | ||
const unchanged = isUnchanged(value, oldValue); | ||
let changes = this.__changes; |
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.
Wait, does this PR remove and re-implement validated-changeset?
Sorry if obvious
closing in favour of adopted-ember-addons/validated-changeset#150 |
Work in progress. Using existing test suite plus some more edge cases and preserving public API.
Enables developer to use normal JS semantics:
Really useful for having nested components:
PersonForm doesn't have to know that this is a changeset. The save and rollback can be at a higher level.