fix: membrane consolidation to work with env virtualization#49
fix: membrane consolidation to work with env virtualization#49
Conversation
src/reactive-handler.ts
Outdated
| /* No op */ | ||
| } | ||
| construct(target: ReactiveMembraneShadowTarget, argArray: any, newTarget?: any): any { | ||
| construct(shadowTarget: ReactiveMembraneShadowTarget, argArray: any, newTarget?: any): any { |
There was a problem hiding this comment.
just to keep consistency
src/reactive-handler.ts
Outdated
| lockShadowTarget(membrane, shadowTarget, originalTarget); | ||
| preventExtensions(originalTarget); | ||
| return true; | ||
| return preventExtensionsMembraneTrap.call(this, shadowTarget); |
This comment was marked as resolved.
This comment was marked as resolved.
Sorry, something went wrong.
There was a problem hiding this comment.
well, we are not doing much optimizations around this... copying again into the shadow target should not be a problem, it is just overhead, but the reality is that must of these proxies will never be non-configurable.
src/reactive-membrane.ts
Outdated
|
|
||
| export function wrapDescriptor(membrane: ReactiveMembrane, descriptor: PropertyDescriptor, getValue: (membrane: ReactiveMembrane, originalValue: any) => any): PropertyDescriptor { | ||
| const { set, get } = descriptor; | ||
| const reserveGetterMap = new WeakMap<() => any, () => any>(); |
There was a problem hiding this comment.
the reverse maps are used to unwrap accessor descriptors back into their original values, we were leaking membrane generated accessor wrappers into the original target when redefining properties :(
- need tests
src/reactive-membrane.ts
Outdated
| } else { | ||
| const { set: originalSet, get: originalGet } = descriptor; | ||
| if (!isUndefined(originalGet)) { | ||
| const get = handler.wrapGetter(originalGet); |
There was a problem hiding this comment.
not longer creating a new function every time... instead using the weakmap for caching and identity preservation
src/reactive-membrane.ts
Outdated
| descriptor.get = get; | ||
| } | ||
| if (!isUndefined(originalSet)) { | ||
| const set = handler.wrapSetter(originalSet); |
src/reactive-membrane.ts
Outdated
| // dealing with a data descriptor | ||
| descriptor.value = unwrap(descriptor.value); | ||
| } else { | ||
| const { set, get } = descriptor; |
There was a problem hiding this comment.
the previous unwrap was not even unwrapping accessors :(
src/reactive-membrane.ts
Outdated
| return descriptor; | ||
| } | ||
|
|
||
| export function copyDescriptorIntoShadowTarget( |
src/reactive-membrane.ts
Outdated
| return desc; | ||
| } | ||
|
|
||
| if (desc.configurable === false) { |
There was a problem hiding this comment.
this is probably the block with the bigger changes... in the previous version of this, from each handler, the descriptor from the shadowTarget was read, and used when possible... that on itself poses many problems, but the most important one is the following:
-
you might get an old value from an old installed non-configurable descriptor that is writable, e.g.: array.length
-
need tests
src/reactive-membrane.ts
Outdated
| shadowTarget: ReactiveMembraneShadowTarget | ||
| ): boolean { | ||
| const { originalTarget } = this; | ||
| if (isExtensible(shadowTarget)) { |
There was a problem hiding this comment.
improve it to support proxy as targets, something that wasn't really work before.
src/read-only-handler.ts
Outdated
| export class ReadOnlyHandler { | ||
| private originalTarget: any; | ||
| private membrane: ReactiveMembrane; | ||
| export class ReadOnlyHandler implements MembraneProxyHandler { |
There was a problem hiding this comment.
this is pretty much the same as the previous file... same comments apply here.
src/read-only-handler.ts
Outdated
| return setterMap.get(originalSet) as (v: any) => void; | ||
| } | ||
| const handler = this; | ||
| function set(this: any, v: any) { |
There was a problem hiding this comment.
@ravijayaramappa this is probably the biggest difference. In the old code, the setter on read-only handlers was always undefined, but getting it to undefined will imply that we will not be able to unwrap it to the original implementation anymore. Instead, we are producing a setter, but it throws when invoked. That seems to be equivalent in behavior, but it is an observable difference. Also, in production, it doesn't throw, it doesn't do anything.
src/reactive-membrane.ts
Outdated
| // Note: by accessing the descriptor, the key is marked as observed | ||
| // but access to the value, setter or getter (if available) cannot observe | ||
| // mutations, just like regular methods, in which case we just do nothing. | ||
| return wrapDescriptor(this, desc); |
This comment was marked as resolved.
This comment was marked as resolved.
Sorry, something went wrong.
src/reactive-handler.ts
Outdated
| lockShadowTarget(membrane, shadowTarget, originalTarget); | ||
| preventExtensions(originalTarget); | ||
| return true; | ||
| return preventExtensionsMembraneTrap.call(this, shadowTarget); |
This comment was marked as resolved.
This comment was marked as resolved.
Sorry, something went wrong.
Co-authored-by: Ravi Jayaramappa <ravi.jayaramappa@salesforce.com>
apapko
left a comment
There was a problem hiding this comment.
Few question and minor recommendations.
Co-authored-by: Pierre-Marie Dartus <p.dartus@salesforce.com>
Co-authored-by: Ravi Jayaramappa <ravi.jayaramappa@salesforce.com>
Uh oh!
There was an error while loading. Please reload this page.