Skip to content
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: refactor reactive membrane to use weakmap instead of targetslot #34

Conversation

ravijayaramappa
Copy link
Contributor

@ravijayaramappa ravijayaramappa commented Mar 12, 2019

This PR is addressing two issues

  1. A reactive object looses its reactivity, when the reactive membrane is requested for a read-only version of the object. The caveat here is that the reactive proxy is wrapped in an external proxy(for example, the locker proxy).
    The root cause here is two fold:
    a. When requested for a read-only version of a reactive object, the reactive membrane tries to identify the reactive state of the original object by unwrapping the reactive proxy.
    b. The unwrap mechanism uses a symbol lookup which is handled by the proxy get trap. If the reactive proxy is wrapped in an external proxy, the unwrap mechanism is not supposed to work because the reactive membrane should not be able to demarshal(unwrap) an external proxy.
    Currently, the symbol lookup resolves and returns the original value to the external proxy and the external proxy can transform the original value. This transformed value is returned to the reactive membrane and it in turn wraps that transformed value in a read only proxy.
    Untitled document

  2. The unwrapProxy() api on the reactive membrane instance is returning the distorted value. It is expected to return the original value that is represented by the reactive/read-only proxy.

Issue - W-5925656

@ravijayaramappa ravijayaramappa changed the title fix: refactor reactive membrane to use weakmap instead of targetslot fix: refactor reactive membrane to use weakmap instead of targetslot [WIP] Mar 12, 2019
@ravijayaramappa ravijayaramappa changed the title fix: refactor reactive membrane to use weakmap instead of targetslot [WIP] fix: refactor reactive membrane to use weakmap instead of targetslot Mar 12, 2019
Copy link
Contributor

@caridy caridy left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM. As for the suggestion from @davidturissini to unwrap to the distorted value instead of the original value, we found a reason for the change to make sense, which is, once you unwrap during the getProxy or getReadOnlyProxy, you then call distortion callback, which should always get the original value rather than the already distorted value, otherwise it is really easy to trip down in the implementation of the valueDistortion routine.

const original = getTarget(item);
if (original) {
const original = unwrap(item);
if (original !== item) {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this to handle a proxy within a proxy?

Copy link
Contributor Author

@ravijayaramappa ravijayaramappa Mar 13, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes. As per my understanding, getTarget(item) is a check to see if item is proxy. If it is, then it recursively extracts that proxy. The new logic is "Can this value be unwrapped? If yes, then its a proxy, recursively extract."

@@ -63,9 +65,6 @@ export class ReactiveProxyHandler {
}
get(shadowTarget: ReactiveMembraneShadowTarget, key: PropertyKey): any {
const { originalTarget, membrane } = this;
if (key === TargetSlot) {
return originalTarget;

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍

ObjectDefineProperty(this, 'readOnly', { value: proxy });
return proxy;
}
} as ReactiveState;

objectGraph.set(value, reactiveState);
objectGraph.set(distortedValue, reactiveState);

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why do we want to use distorderValue here instead of value?

Copy link
Contributor Author

@ravijayaramappa ravijayaramappa Mar 13, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Because of two reasons

  • The handler's behavior is based on the distorted value. So the object graph should have a 1:1 relationship with the value that it is encapsulating.
  • Handles both deterministic and non-deterministic distortion
    • If distortion is deterministic, then there is a 1:1 mapping between value <-> distortedValue. So we can use either, it makes no difference.
    • If distortion is non-deterministic,
      • And, the object graph is keyed by value, then we will always produce the same ReactiveState for a given value. We are removing the non-deterministic nature of the distortion. Which may be or may not be desirable.
      • On the other hand, if the object graph is keyed by distortedValue, then we will produce a ReactiveState for every unique distortion.

Copy link

@davidturissini davidturissini left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good, couple questions

@ravijayaramappa ravijayaramappa merged commit 4aa7e41 into salesforce:master Mar 13, 2019
@ravijayaramappa ravijayaramappa deleted the ravi/master/refactor-targetslot branch March 13, 2019 22:04
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants