-
Notifications
You must be signed in to change notification settings - Fork 386
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
refactor(engine): avoiding proxies of proxies in membranes #183
Conversation
return unwrapped; | ||
} | ||
// piercing membrane is not that important, it goes second | ||
unwrapped = (value && getKey(value, TargetSlot)) || value; |
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.
simplification of the previous unwrapping method to work faster, no more for-loop, just plain and simple sequencial unwrapping until finding a match.
also I have reordered the sequence to have the most common case first.
Benchmark comparisonBase commit:
|
import { ReactiveMembrane, unwrap as observableUnwrap } from "observable-membrane"; | ||
import { observeMutation, notifyMutation } from "./watcher"; | ||
|
||
function format(value: 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.
code moved from reactive.ts to avoid circular deps.
if (process.env.NODE_ENV !== 'production') { | ||
// For now, if we determine that value is a piercing membrane | ||
// we want to throw a big error. | ||
if (replicaUnwrap(value) !== value) { |
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 one of the new tricks. This covers the case where:
- attempting to access a piercing membrane object (we call them replicas) via a reactive membrane.
For now, this only affects dev-mode, and it throws a big error. We can bikeshed on the text of the error!
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 throw? Why not just return the unwrapped version and let observable membrane handle it?
return value; | ||
} | ||
|
||
export const reactiveMembrane = new ReactiveMembrane(format, { |
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.
code from reactive.ts! intact!
}); | ||
|
||
// TODO: REMOVE THIS https://github.com/salesforce/lwc/issues/129 | ||
export function dangerousObjectMutation(obj: any): 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.
code from reactive.ts! intact!
if (!isReplicable(replicaRawValue)) { | ||
return replicaRawValue; | ||
} | ||
const reactiveRawValue = observableUnwrap(replicaRawValue); |
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 the second trick! which guarantees that:
- if you ever access a reactive object via a piercing membrane, what you get is the readonly version of the reactive object.
this.root.querySelector('x-foo').publicPropX; // what you get here is the readOnly version of `publicPropX` from `x-foo` instance.
@@ -1,39 +0,0 @@ | |||
import assert from './assert'; |
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.
folding this file into membrane.ts
@@ -58,3 +55,7 @@ export function observeMutation(target: object, key: PropertyKey) { | |||
ArrayPush.call(vm.deps, value); | |||
} | |||
} | |||
|
|||
import { scheduleRehydration, VM } from "./vm"; |
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.
moving these imports down helps with the circular deps problem
Benchmark comparisonBase commit:
|
@@ -10,7 +11,7 @@ describe('unwrap', () => { | |||
|
|||
it('should unwrap observable membrane object correctly', () => { | |||
const obj = {}; | |||
const proxy = membrane.getProxy(obj); | |||
const proxy = reactiveMembrane.getProxy(obj); | |||
expect(unwrap(proxy)).toBe(obj); |
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.
can we add test to unwrap and verify not proxy? what check is toBe
?
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 looks ok. I would prefer adding a membrane
folder, like what we do with decorators, but this'll do for now.
if (process.env.NODE_ENV !== 'production') { | ||
// For now, if we determine that value is a piercing membrane | ||
// we want to throw a big error. | ||
if (replicaUnwrap(value) !== value) { |
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 throw? Why not just return the unwrapped version and let observable membrane handle it?
const getKey = ProxyGetKey ? ProxyGetKey : (o: any, key: PropertyKey): any => o[key]; | ||
|
||
export function replicaUnwrap(value: any): any { | ||
// observable membrane goes first because it is in the critical path |
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 this comment makes sense here
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.
change base to 214/patch please We can cherry pick
* refactor(engine): avoid rewrapping of proxies * refactor(engine): prevent leaking double proxies via events or querySelector
* refactor(engine): avoid rewrapping of proxies * refactor(engine): prevent leaking double proxies via events or querySelector fix(aom): consolidating the aria dom property names (#192) wip: Remove slotting refactor(engine): conditinally use of native shadowRoot fix(engine): compat should also work with artificial shadow refactor(engine): adding slotting refactor(engine): adding slotting refactor(engine): conditionally piercing and default behaviors refactor(engine): minimizing the polyfilling on shadow-root to only AOM refactor(engine): implementing Pierre's suggestion to avoid patching shadow root prototype
Details
This PR prevents:
Does this PR introduce a breaking change?