diff options
author | bobzel <zzzman@gmail.com> | 2022-12-21 19:38:29 -0500 |
---|---|---|
committer | bobzel <zzzman@gmail.com> | 2022-12-21 19:38:29 -0500 |
commit | 631826f13c67aef760bc7e76665e152f1f63bf5b (patch) | |
tree | 8733aac0da4fcdf12277bf204a63c68ac7ac20aa /src/fields/util.ts | |
parent | e373e66f8ed06f4501e00af8348f15ad113c7424 (diff) | |
parent | 4c0de84cf9a3d5be2f5058d514c8ca58e2004a4b (diff) |
cleaning up proxys and getFieldRef hopefully to be more understandable and efficient
Diffstat (limited to 'src/fields/util.ts')
-rw-r--r-- | src/fields/util.ts | 76 |
1 files changed, 30 insertions, 46 deletions
diff --git a/src/fields/util.ts b/src/fields/util.ts index 51c76b19a..285cbb4c6 100644 --- a/src/fields/util.ts +++ b/src/fields/util.ts @@ -1,4 +1,4 @@ -import { action, observable, runInAction, trace } from 'mobx'; +import { $mobx, action, observable, runInAction, trace } from 'mobx'; import { computedFn } from 'mobx-utils'; import { DocServer } from '../client/DocServer'; import { CollectionViewType } from '../client/documents/DocumentTypes'; @@ -28,7 +28,7 @@ import { UpdatingFromServer, WidthSym, } from './Doc'; -import { Id, OnUpdate, Parent, Self, SelfProxy, Update } from './FieldSymbols'; +import { Id, OnUpdate, Parent, SelfProxy, ToValue, Update } from './FieldSymbols'; import { List } from './List'; import { ObjectField } from './ObjectField'; import { PrefetchProxy, ProxyField } from './Proxy'; @@ -47,19 +47,6 @@ export function TraceMobx() { tracing && trace(); } -export interface GetterResult { - value: FieldResult; - shouldReturn?: boolean; -} -export type GetterPlugin = (receiver: any, prop: string | number, currentValue: any) => GetterResult | undefined; -const getterPlugins: GetterPlugin[] = []; - -export namespace Plugins { - export function addGetterPlugin(plugin: GetterPlugin) { - getterPlugins.push(plugin); - } -} - const _setterImpl = action(function (target: any, prop: string | symbol | number, value: any, receiver: any): boolean { if (SerializationHelper.IsSerializing()) { target[prop] = value; @@ -353,47 +340,44 @@ export function setter(target: any, in_prop: string | symbol | number, value: an return _setter(target, prop, value, receiver); } -export function getter(target: any, in_prop: string | symbol, receiver: any): any { - if (in_prop === 'constructor' || in_prop === 'toString' || in_prop === 'valueOf' || in_prop === 'factory' || in_prop === 'serializeInfo') return target[in_prop]; - if (in_prop === 'then') return undefined; //If we're being awaited - if (in_prop === AclSym) return target[AclSym]; - if (in_prop === LayoutSym) return target.__LAYOUT__; - if ((in_prop === HeightSym || in_prop === WidthSym) && GetEffectiveAcl(target) === AclPrivate) return returnZero; - if (typeof in_prop === 'symbol' || in_prop.startsWith('isMobX') || in_prop.startsWith('__')) return target.__fields[in_prop] || target[in_prop]; - if (GetEffectiveAcl(target) === AclPrivate) { - if (in_prop === 'author') return target.__fields[in_prop] || target[in_prop]; - return undefined; +export function getter(target: any, prop: string | symbol, proxy: any): any { + // prettier-ignore + switch (prop) { + case 'then' : return undefined; + case '__fields' : case '__id': + case 'constructor': case 'toString': case 'valueOf': + case 'factory': case 'serializeInfo': + return target[prop]; + case AclSym : return target[AclSym]; + case $mobx: return target.__fields[prop]; + case LayoutSym: return target.__Layout__; + case HeightSym: case WidthSym: if (GetEffectiveAcl(target) === AclPrivate) return returnZero; + default : + if (typeof prop === 'symbol') return target[prop]; + if (prop.startsWith('isMobX')) return target[prop]; + if (prop.startsWith('__')) return target[prop]; + if (GetEffectiveAcl(target) === AclPrivate && prop !== 'author') return undefined; } - const prop = in_prop.startsWith('_') ? in_prop.substring(1) : in_prop; - if (prop !== in_prop && target.__LAYOUT__) return target.__LAYOUT__[prop]; - if (SerializationHelper.IsSerializing()) return target[prop]; - return getFieldImpl(target, prop, receiver); + const layout_prop = prop.startsWith('_') ? prop.substring(1) : undefined; + if (layout_prop && target.__LAYOUT__) return target.__LAYOUT__[layout_prop]; + return getFieldImpl(target, layout_prop ?? prop, proxy); } -function getFieldImpl(target: any, prop: string | number, receiver: any, ignoreProto: boolean = false): any { - receiver = receiver || target[SelfProxy]; - let field = target.__fields[prop]; - for (const plugin of getterPlugins) { - const res = plugin(receiver, prop, field); - if (res === undefined) continue; - if (res.shouldReturn) { - return res.value; - } else { - field = res.value; - } - } - if (field === undefined && !ignoreProto && prop !== 'proto') { - const proto = getFieldImpl(target, 'proto', receiver, true); //TODO tfs: instead of receiver we could use target[SelfProxy]... I don't which semantics we want or if it really matters +function getFieldImpl(target: any, prop: string | number, proxy: any, ignoreProto: boolean = false): any { + const field = target.__fields[prop]; + const value = field?.[ToValue]?.(proxy); // converts ComputedFields to values, or unpacks ProxyFields into Proxys + if (value) return value.value; + if (!field && !ignoreProto && prop !== 'proto') { + const proto = getFieldImpl(target, 'proto', proxy, true); //TODO tfs: instead of proxy we could use target[SelfProxy]... I don't which semantics we want or if it really matters if (proto instanceof Doc && GetEffectiveAcl(proto) !== AclPrivate) { - return getFieldImpl(proto[Self], prop, receiver, ignoreProto); + return getFieldImpl(proto, prop, proxy, ignoreProto); } - return undefined; } return field; } export function getField(target: any, prop: string | number, ignoreProto: boolean = false): any { - return getFieldImpl(target, prop, undefined, ignoreProto); + return getFieldImpl(target, prop, target[SelfProxy], ignoreProto); } export function deleteProperty(target: any, prop: string | number | symbol) { |