From c6857c5bc523201103c624761744fe651b2675fa Mon Sep 17 00:00:00 2001 From: * <*> Date: Mon, 5 Jun 2023 18:53:22 +0800 Subject: [PATCH 1/3] Match-id-b88442c85aaf06a604c65a19c68060ba9cb9e44e --- libs/horizon/src/dom/DOMExternal.ts | 4 +- libs/horizon/src/dom/DOMOperator.ts | 18 +++-- .../DOMPropertiesHandler.ts | 12 ++-- .../dom/DOMPropertiesHandler/StyleHandler.ts | 2 +- libs/horizon/src/dom/SelectionRangeHandler.ts | 2 +- libs/horizon/src/external/ChildrenUtil.ts | 64 +++++++++--------- libs/horizon/src/external/JSXElement.ts | 9 ++- libs/horizon/src/horizonx/adapters/redux.ts | 3 +- libs/horizon/src/horizonx/devtools/index.ts | 4 +- .../src/horizonx/proxy/HooklessObserver.ts | 3 - libs/horizon/src/horizonx/proxy/Observer.ts | 2 +- .../src/horizonx/proxy/ProxyHandler.ts | 6 +- .../proxy/handlers/CollectionProxyHandler.ts | 4 +- .../src/horizonx/proxy/handlers/MapProxy.ts | 31 ++++----- .../proxy/handlers/ObjectProxyHandler.ts | 3 +- .../src/horizonx/proxy/handlers/SetProxy.ts | 31 ++++----- .../horizonx/proxy/handlers/WeakMapProxy.ts | 65 ++++++++++--------- .../horizonx/proxy/handlers/WeakSetProxy.ts | 17 ++--- 18 files changed, 152 insertions(+), 128 deletions(-) diff --git a/libs/horizon/src/dom/DOMExternal.ts b/libs/horizon/src/dom/DOMExternal.ts index dbd78da4..6c459952 100644 --- a/libs/horizon/src/dom/DOMExternal.ts +++ b/libs/horizon/src/dom/DOMExternal.ts @@ -73,7 +73,7 @@ function executeRender(children: any, container: Container, callback?: Callback) } function findDOMNode(domOrEle?: Element): null | Element | Text { - if (domOrEle == null) { + if (domOrEle === null || domOrEle === undefined) { return null; } @@ -103,7 +103,7 @@ function removeRootEventLister(container: Container) { // 卸载入口 function destroy(container: Container): boolean { - if (container && container._treeRoot) { + if (container._treeRoot) { syncUpdates(() => { executeRender(null, container, () => { removeRootEventLister(container); diff --git a/libs/horizon/src/dom/DOMOperator.ts b/libs/horizon/src/dom/DOMOperator.ts index f83893e5..55c218ae 100644 --- a/libs/horizon/src/dom/DOMOperator.ts +++ b/libs/horizon/src/dom/DOMOperator.ts @@ -46,7 +46,7 @@ function getChildNS(parentNS: string | null, tagName: string): string { return NSS.html; } - if (parentNS == null || parentNS === NSS.html) { + if (parentNS === null || parentNS === NSS.html) { // 没有父命名空间,或父命名空间为xhtml return NSS[tagName] ?? NSS.html; } @@ -130,7 +130,8 @@ export function isTextChild(type: string, props: Props): boolean { return ( props.dangerouslySetInnerHTML && typeof props.dangerouslySetInnerHTML === 'object' && - props.dangerouslySetInnerHTML.__html != null + props.dangerouslySetInnerHTML.__html !== null && + props.dangerouslySetInnerHTML.__html !== undefined ); } } @@ -148,7 +149,7 @@ export function submitDomUpdate(tag: string, vNode: VNode) { if (tag === DomComponent) { // DomComponent类型 - if (element != null) { + if (element !== null || element !== undefined) { const type = vNode.type; const changeList = vNode.changeList; vNode.changeList = null; @@ -158,7 +159,14 @@ export function submitDomUpdate(tag: string, vNode: VNode) { updateVNodeProps(element, newProps); // 应用diff更新Properties. // 当一个选中的radio改变名称,浏览器使另一个radio的复选框为false. - if (type === 'input' && newProps.type === 'radio' && newProps.name != null && newProps.checked != null) { + if ( + type === 'input' + && newProps.type === 'radio' + && newProps.name !== null + && newProps.name !== undefined + && newProps.checked !== null + && newProps.checked !== undefined + ) { updateCommonProp(element, 'checked', newProps.checked, true); } const isNativeTag = isNativeElement(type, newProps); @@ -204,7 +212,7 @@ export function hideDom(tag: string, dom: Element | Text) { // 不隐藏元素 export function unHideDom(tag: string, dom: Element | Text, props: Props) { if (tag === DomComponent) { - dom.style.display = adjustStyleValue('display', props?.style?.display ?? ''); + dom.style.display = adjustStyleValue('display', props.style?.display ?? ''); } else if (tag === DomText) { dom.textContent = props; } diff --git a/libs/horizon/src/dom/DOMPropertiesHandler/DOMPropertiesHandler.ts b/libs/horizon/src/dom/DOMPropertiesHandler/DOMPropertiesHandler.ts index 5c0773c1..ede38907 100644 --- a/libs/horizon/src/dom/DOMPropertiesHandler/DOMPropertiesHandler.ts +++ b/libs/horizon/src/dom/DOMPropertiesHandler/DOMPropertiesHandler.ts @@ -48,7 +48,7 @@ export function setDomProps(dom: Element, props: Object, isNativeTag: boolean, i } } else if (propName === 'dangerouslySetInnerHTML') { dom.innerHTML = propVal.__html; - } else if (!isInit || propVal != null) { + } else if (!isInit || propVal !== null || propVal !== undefined) { updateCommonProp(dom, propName, propVal, isNativeTag); } } @@ -70,7 +70,7 @@ export function compareProps(oldProps: Object, newProps: Object): Object { for (let i = 0; i < oldPropsLength; i++) { propName = keysOfOldProps[i]; // 新属性中包含该属性或者该属性为空值的属性不需要处理 - if ( oldProps[propName] == null || keysOfNewProps.includes(propName)) { + if ( oldProps[propName] === null || oldProps[propName] === undefined || keysOfNewProps.includes(propName)) { continue; } @@ -103,9 +103,13 @@ export function compareProps(oldProps: Object, newProps: Object): Object { for (let i = 0; i < keysOfNewProps.length; i++) { propName = keysOfNewProps[i]; newPropValue = newProps[propName]; - oldPropValue = oldProps != null ? oldProps[propName] : null; + oldPropValue = oldProps !== null ? oldProps[propName] : null; - if (newPropValue === oldPropValue || (newPropValue == null && oldPropValue == null)) { + if ( + newPropValue === oldPropValue + || ((newPropValue === null || newPropValue === undefined) + && (oldPropValue === null || oldPropValue === undefined)) + ) { // 新旧属性值未发生变化,或者新旧属性皆为空值,不需要进行处理 continue; } diff --git a/libs/horizon/src/dom/DOMPropertiesHandler/StyleHandler.ts b/libs/horizon/src/dom/DOMPropertiesHandler/StyleHandler.ts index e2fca141..522fa956 100644 --- a/libs/horizon/src/dom/DOMPropertiesHandler/StyleHandler.ts +++ b/libs/horizon/src/dom/DOMPropertiesHandler/StyleHandler.ts @@ -67,7 +67,7 @@ export function adjustStyleValue(name, value) { if (typeof value === 'number' && value !== 0 && isNeedUnitCSS(name)) { validValue = `${value}px`; - } else if (value === '' || value == null || typeof value === 'boolean') { + } else if (value === '' || value === null || value === undefined || typeof value === 'boolean') { validValue = ''; } diff --git a/libs/horizon/src/dom/SelectionRangeHandler.ts b/libs/horizon/src/dom/SelectionRangeHandler.ts index e09e0dad..f9488f9b 100644 --- a/libs/horizon/src/dom/SelectionRangeHandler.ts +++ b/libs/horizon/src/dom/SelectionRangeHandler.ts @@ -30,7 +30,7 @@ function setSelectionRange(dom: HTMLInputElement | HTMLTextAreaElement, range) { const { start, end } = range; let realEnd = end; - if (realEnd == null) { + if (realEnd === null || realEnd === undefined) { realEnd = start; } diff --git a/libs/horizon/src/external/ChildrenUtil.ts b/libs/horizon/src/external/ChildrenUtil.ts index 3624a736..55f66e3c 100644 --- a/libs/horizon/src/external/ChildrenUtil.ts +++ b/libs/horizon/src/external/ChildrenUtil.ts @@ -21,44 +21,13 @@ import { BELONG_CLASS_VNODE_KEY } from '../renderer/vnode/VNode'; // 生成key function getItemKey(item: any, index: number): string { - if (typeof item === 'object' && item !== null && item.key != null) { + if (typeof item === 'object' && item !== null && item.key !== null && item.key !== undefined) { return '.$' + item.key; } // 使用36进制减少生成字符串的长度以节省空间 return '.' + index.toString(36); } -function mapChildrenToArray(children: any, arr: Array, prefix: string, callback?: Function): number | void { - const type = typeof children; - switch (type) { - // 继承原有规格,undefined和boolean类型按照null处理 - case 'undefined': - case 'boolean': - callMapFun(null, arr, prefix, callback); - return; - case 'number': - case 'string': - callMapFun(children, arr, prefix, callback); - return; - case 'object': - if (children === null) { - callMapFun(null, arr, prefix, callback); - return; - } - const vtype = children.vtype; - if (vtype === TYPE_COMMON_ELEMENT || vtype === TYPE_PORTAL) { - callMapFun(children, arr, prefix, callback); - return; - } - if (Array.isArray(children)) { - processArrayChildren(children, arr, prefix, callback); - return; - } - throw new Error('Object is invalid as a Horizon child. '); - // No Default - } -} - function processArrayChildren(children: any, arr: Array, prefix: string, callback: Function) { for (let i = 0; i < children.length; i++) { const childItem = children[i]; @@ -93,6 +62,37 @@ function callMapFun(children: any, arr: Array, prefix: string, callback: Fu } } +function mapChildrenToArray(children: any, arr: Array, prefix: string, callback?: Function): number | void { + const type = typeof children; + switch (type) { + // 继承原有规格,undefined和boolean类型按照null处理 + case 'undefined': + case 'boolean': + callMapFun(null, arr, prefix, callback); + return; + case 'number': + case 'string': + callMapFun(children, arr, prefix, callback); + return; + case 'object': + if (children === null) { + callMapFun(null, arr, prefix, callback); + return; + } + const vtype = children.vtype; + if (vtype === TYPE_COMMON_ELEMENT || vtype === TYPE_PORTAL) { + callMapFun(children, arr, prefix, callback); + return; + } + if (Array.isArray(children)) { + processArrayChildren(children, arr, prefix, callback); + return; + } + throw new Error('Object is invalid as a Horizon child. '); + // No Default + } +} + // 在 children 里的每个直接子节点上调用一个函数,并将 this 设置为 thisArg function mapChildren(children: any, func: Function, context?: any): Array { if (children === null || children === undefined) { diff --git a/libs/horizon/src/external/JSXElement.ts b/libs/horizon/src/external/JSXElement.ts index 5ff3db84..e54e2054 100644 --- a/libs/horizon/src/external/JSXElement.ts +++ b/libs/horizon/src/external/JSXElement.ts @@ -72,10 +72,15 @@ function mergeDefault(sourceObj, defaultObj) { // ['key', 'ref', '__source', '__self']属性不从setting获取 const keyArray = ['key', 'ref', '__source', '__self']; +function getSettingArgs(setting, isClone, type) { + const key = setting && setting.key !== undefined ? String(setting.key) : (isClone ? type.key : null); + const ref = setting && setting.ref !== undefined ? setting.ref : (isClone ? type.ref : null); + return { key, ref }; +} + function buildElement(isClone, type, setting, children) { // setting中的值优先级最高,clone情况下从 type 中取值,创建情况下直接赋值为 null - const key = (setting && setting.key !== undefined) ? String(setting.key) : (isClone ? type.key : null); - const ref = (setting && setting.ref !== undefined) ? setting.ref : (isClone ? type.ref : null); + const { key, ref } = getSettingArgs(setting, isClone, type); const props = isClone ? { ...type.props } : {}; let vNode = isClone ? type[BELONG_CLASS_VNODE_KEY] : getProcessingClassVNode(); diff --git a/libs/horizon/src/horizonx/adapters/redux.ts b/libs/horizon/src/horizonx/adapters/redux.ts index 97b7a483..ffffc59f 100644 --- a/libs/horizon/src/horizonx/adapters/redux.ts +++ b/libs/horizon/src/horizonx/adapters/redux.ts @@ -140,7 +140,8 @@ export function createStore(reducer: Reducer, preloadedState?: any, enhancers?): } export function combineReducers(reducers: { [key: string]: Reducer }): Reducer { - return (state = {}, action) => { + return (state, action) => { + state = state || {}; const newState = {}; Object.entries(reducers).forEach(([key, reducer]) => { newState[key] = reducer(state[key], action); diff --git a/libs/horizon/src/horizonx/devtools/index.ts b/libs/horizon/src/horizonx/devtools/index.ts index 64a0f189..eda6d696 100644 --- a/libs/horizon/src/horizonx/devtools/index.ts +++ b/libs/horizon/src/horizonx/devtools/index.ts @@ -145,7 +145,7 @@ function getAffectedComponents() { const process = Array.from(allStores[key].$config.state._horizonObserver.keyVNodes.values()); while (process.length) { let pivot = process.shift() as { tag: 'string' }; - if (pivot?.tag) subRes.add(pivot); + if (pivot.tag) subRes.add(pivot); if (pivot?.toString() === '[object Set]') Array.from(pivot).forEach(item => process.push(item)); } res[key] = Array.from(subRes).map(vnode => { @@ -192,7 +192,7 @@ window.addEventListener('message', messageEvent => { const store = getStore(data.storeId); if (!store?.[data.action]) return; - const action = store.$queue?.[data.action]; + const action = store.$queue[data.action]; const params = data.params; action(...params); } diff --git a/libs/horizon/src/horizonx/proxy/HooklessObserver.ts b/libs/horizon/src/horizonx/proxy/HooklessObserver.ts index a47ad752..c823ef0e 100644 --- a/libs/horizon/src/horizonx/proxy/HooklessObserver.ts +++ b/libs/horizon/src/horizonx/proxy/HooklessObserver.ts @@ -41,9 +41,6 @@ export class HooklessObserver implements IObserver { triggerChangeListeners(mutation: any): void { this.listeners.forEach(listener => { - if (!listener) { - return; - } listener(mutation); }); } diff --git a/libs/horizon/src/horizonx/proxy/Observer.ts b/libs/horizon/src/horizonx/proxy/Observer.ts index b1aa43d7..de009283 100644 --- a/libs/horizon/src/horizonx/proxy/Observer.ts +++ b/libs/horizon/src/horizonx/proxy/Observer.ts @@ -81,7 +81,7 @@ export class Observer implements IObserver { const vNodes = this.keyVNodes.get(key); //NOTE: using Set directly can lead to deadlock const vNodeArray = Array.from(vNodes || []); - vNodeArray?.forEach((vNode: VNode) => { + vNodeArray.forEach((vNode: VNode) => { if (vNode.isStoreChange) { // VNode已经被触发过,不再重复触发 return; diff --git a/libs/horizon/src/horizonx/proxy/ProxyHandler.ts b/libs/horizon/src/horizonx/proxy/ProxyHandler.ts index be83bee5..b20a6dfb 100644 --- a/libs/horizon/src/horizonx/proxy/ProxyHandler.ts +++ b/libs/horizon/src/horizonx/proxy/ProxyHandler.ts @@ -31,7 +31,9 @@ export function getObserver(rawObj: any): Observer { return rawObj[OBSERVER_KEY]; } -export function createProxy(rawObj: any, isHookObserver = true, listener: { current: (...args) => any }): any { +export function createProxy(rawObj: any, isHookObserver: boolean, listener: { current: (...args) => any }): any { + isHookObserver = isHookObserver || true; + // 不是对象(是原始数据类型)不用代理 if (!(rawObj && isObject(rawObj))) { return rawObj; @@ -83,7 +85,7 @@ export function createProxy(rawObj: any, isHookObserver = true, listener: { curr // 原生对象 或 函数 proxyObj = createObjectProxy(rawObj, false, { current: change => { - listener?.current(change); + listener.current(change); }, }); } diff --git a/libs/horizon/src/horizonx/proxy/handlers/CollectionProxyHandler.ts b/libs/horizon/src/horizonx/proxy/handlers/CollectionProxyHandler.ts index 1b0f0d37..e6d4309c 100644 --- a/libs/horizon/src/horizonx/proxy/handlers/CollectionProxyHandler.ts +++ b/libs/horizon/src/horizonx/proxy/handlers/CollectionProxyHandler.ts @@ -21,9 +21,11 @@ import { createMapProxy } from './MapProxy'; export function createCollectionProxy( rawObj: Object, - hookObserver = true, + hookObserver: boolean, listener: { current: (...args) => any } ): Object { + hookObserver = hookObserver || true; + if (isWeakSet(rawObj)) { return createWeakSetProxy(rawObj, hookObserver, listener); } diff --git a/libs/horizon/src/horizonx/proxy/handlers/MapProxy.ts b/libs/horizon/src/horizonx/proxy/handlers/MapProxy.ts index dd51f07f..0921cf7a 100644 --- a/libs/horizon/src/horizonx/proxy/handlers/MapProxy.ts +++ b/libs/horizon/src/horizonx/proxy/handlers/MapProxy.ts @@ -20,7 +20,8 @@ import { isPanelActive } from '../../devtools'; const COLLECTION_CHANGE = '_collectionChange'; -export function createMapProxy(rawObj: Object, hookObserver = true, listener: { current: (...args) => any }): Object { +export function createMapProxy(rawObj: Object, hookObserver: boolean, listener: { current: (...args) => any }): Object { + hookObserver = hookObserver || true; let listeners: ((mutation) => {})[] = []; let oldData: [any, any][] = []; let proxies = new Map(); @@ -314,6 +315,20 @@ export function createMapProxy(rawObj: Object, hookObserver = true, listener: { return wrapIterator(rawObj, rawObj.entries(), 'entries'); } + const handler = { + get, + set, + delete: deleteFun, + clear, + has, + entries, + forEach, + keys, + values, + // 判断Symbol类型,兼容IE + [typeof Symbol === 'function' ? Symbol.iterator : '@@iterator']: forOf, + }; + function get(rawObj: { size: number }, key: any, receiver: any): any { if (key === 'size') { return size(rawObj); @@ -357,20 +372,6 @@ export function createMapProxy(rawObj: Object, hookObserver = true, listener: { return Reflect.get(rawObj, key, receiver); } ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - const handler = { - get, - set, - delete: deleteFun, - clear, - has, - entries, - forEach, - keys, - values, - // 判断Symbol类型,兼容IE - [typeof Symbol === 'function' ? Symbol.iterator : '@@iterator']: forOf, - }; - ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// const boundHandler = {}; Object.entries(handler).forEach(([id, val]) => { boundHandler[id] = (...args: any[]) => { diff --git a/libs/horizon/src/horizonx/proxy/handlers/ObjectProxyHandler.ts b/libs/horizon/src/horizonx/proxy/handlers/ObjectProxyHandler.ts index 0afa6583..28aeb1f2 100644 --- a/libs/horizon/src/horizonx/proxy/handlers/ObjectProxyHandler.ts +++ b/libs/horizon/src/horizonx/proxy/handlers/ObjectProxyHandler.ts @@ -41,9 +41,10 @@ function set(rawObj: object, key: string, value: any, receiver: any): boolean { export function createObjectProxy( rawObj: T, - singleLevel = false, + singleLevel: boolean, listener: { current: (...args) => any } ): ProxyHandler { + singleLevel = singleLevel || false; let listeners = [] as ((...args) => void)[]; function get(rawObj: object, key: string | symbol, receiver: any): any { diff --git a/libs/horizon/src/horizonx/proxy/handlers/SetProxy.ts b/libs/horizon/src/horizonx/proxy/handlers/SetProxy.ts index b0409ad6..e5efb07b 100644 --- a/libs/horizon/src/horizonx/proxy/handlers/SetProxy.ts +++ b/libs/horizon/src/horizonx/proxy/handlers/SetProxy.ts @@ -20,9 +20,10 @@ const COLLECTION_CHANGE = '_collectionChange'; export function createSetProxy( rawObj: T, - hookObserver = true, + hookObserver: boolean, listener: { current: (...args) => any } ): ProxyHandler { + hookObserver = hookObserver || true; let listeners: ((mutation) => {})[] = []; let proxies = new WeakMap(); @@ -129,6 +130,20 @@ export function createSetProxy( return rawObj.size; } ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + const handler = { + get, + add, + delete: deleteFun, + has, + clear, + forEach, + forOf, + entries, + keys, + values, + [typeof Symbol === 'function' ? Symbol.iterator : '@@iterator']: forOf, + }; + function get(rawObj: { size: number }, key: any, receiver: any): any { if (Object.prototype.hasOwnProperty.call(handler, key)) { const value = Reflect.get(handler, key, receiver); @@ -267,20 +282,6 @@ export function createSetProxy( }); } ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - const handler = { - get, - add, - delete: deleteFun, - has, - clear, - forEach, - forOf, - entries, - keys, - values, - [typeof Symbol === 'function' ? Symbol.iterator : '@@iterator']: forOf, - }; - ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// getObserver(rawObj).addListener(change => { if (!change.parents) change.parents = []; change.parents.push(rawObj); diff --git a/libs/horizon/src/horizonx/proxy/handlers/WeakMapProxy.ts b/libs/horizon/src/horizonx/proxy/handlers/WeakMapProxy.ts index d5f87ff3..3792dc4d 100644 --- a/libs/horizon/src/horizonx/proxy/handlers/WeakMapProxy.ts +++ b/libs/horizon/src/horizonx/proxy/handlers/WeakMapProxy.ts @@ -22,11 +22,43 @@ const COLLECTION_CHANGE = '_collectionChange'; export function createWeakMapProxy( rawObj: Object, - hookObserver = true, + hookObserver: boolean, listener: { current: (...args) => any } ): Object { + hookObserver = hookObserver ||true; let listeners: ((mutation) => {})[] = []; + const handler = { + get, + set, + add, + delete: deleteFun, + clear, + has, + }; + + function getFun(rawObj: { get: (key: any) => any }, key: any) { + const observer = getObserver(rawObj); + observer.useProp(key); + + const value = rawObj.get(key); + // 对于value也需要进一步代理 + const valProxy = createProxy(value, hookObserverMap.get(rawObj), { + current: change => { + if (!change.parents) change.parents = []; + change.parents.push(rawObj); + let mutation = resolveMutation( + { ...rawObj, [key]: change.mutation.from }, + { ...rawObj, [key]: change.mutation.to } + ); + listener.current({ ...change, mutation }); + listeners.forEach(lst => lst({ ...change, mutation })); + }, + }); + + return valProxy; + } + function get(rawObj: { size: number }, key: any, receiver: any): any { if (key === 'get') { return getFun.bind(null, rawObj); @@ -66,28 +98,6 @@ export function createWeakMapProxy( return Reflect.get(rawObj, key, receiver); } - function getFun(rawObj: { get: (key: any) => any }, key: any) { - const observer = getObserver(rawObj); - observer.useProp(key); - - const value = rawObj.get(key); - // 对于value也需要进一步代理 - const valProxy = createProxy(value, hookObserverMap.get(rawObj), { - current: change => { - if (!change.parents) change.parents = []; - change.parents.push(rawObj); - let mutation = resolveMutation( - { ...rawObj, [key]: change.mutation.from }, - { ...rawObj, [key]: change.mutation.to } - ); - listener.current({ ...change, mutation }); - listeners.forEach(lst => lst({ ...change, mutation })); - }, - }); - - return valProxy; - } - // Map的set方法 function set( rawObj: { get: (key: any) => any; set: (key: any, value: any) => any; has: (key: any) => boolean }, @@ -171,15 +181,6 @@ export function createWeakMapProxy( return false; } ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - const handler = { - get, - set, - add, - delete: deleteFun, - clear, - has, - }; - ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// getObserver(rawObj).addListener(change => { if (!change.parents) change.parents = []; change.parents.push(rawObj); diff --git a/libs/horizon/src/horizonx/proxy/handlers/WeakSetProxy.ts b/libs/horizon/src/horizonx/proxy/handlers/WeakSetProxy.ts index 27becbe9..4fd6b788 100644 --- a/libs/horizon/src/horizonx/proxy/handlers/WeakSetProxy.ts +++ b/libs/horizon/src/horizonx/proxy/handlers/WeakSetProxy.ts @@ -18,12 +18,20 @@ import { createProxy, getObserver, hookObserverMap } from '../ProxyHandler'; export function createWeakSetProxy( rawObj: T, - hookObserver = true, + hookObserver: boolean, listener: { current: (...args) => any } ): ProxyHandler { + hookObserver = hookObserver || true; let listeners: ((mutation) => {})[] = []; let proxies = new WeakMap(); + const handler = { + get, + add, + delete: deleteFun, + has, + }; + function get(rawObj: { size: number }, key: any, receiver: any): any { if (Object.prototype.hasOwnProperty.call(handler, key)) { const value = Reflect.get(handler, key, receiver); @@ -109,13 +117,6 @@ export function createWeakSetProxy( return false; } ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - const handler = { - get, - add, - delete: deleteFun, - has, - }; - ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// getObserver(rawObj).addListener(change => { if (!change.parents) change.parents = []; change.parents.push(rawObj); From dd7b65c45ac8cda1313f70f1614b6e4c20e86ddb Mon Sep 17 00:00:00 2001 From: * <*> Date: Wed, 7 Jun 2023 14:50:36 +0800 Subject: [PATCH 2/3] Match-id-b3271adc745fbcd1091dfc0f70385d726500f682 --- libs/horizon/src/dom/DOMOperator.ts | 6 ++-- .../DOMPropertiesHandler.ts | 6 ++-- libs/horizon/src/external/JSXElement.ts | 9 ++---- libs/horizon/src/horizonx/CommonUtils.ts | 3 +- libs/horizon/src/horizonx/devtools/index.ts | 29 +++++++++++-------- libs/horizon/src/horizonx/proxy/Observer.ts | 4 --- .../src/horizonx/proxy/ProxyHandler.ts | 27 +++++++++-------- .../proxy/handlers/ArrayProxyHandler.ts | 2 +- .../proxy/handlers/CollectionProxyHandler.ts | 14 ++++----- .../src/horizonx/proxy/handlers/MapProxy.ts | 13 +++++---- .../proxy/handlers/ObjectProxyHandler.ts | 7 ++--- .../src/horizonx/proxy/handlers/SetProxy.ts | 5 ++-- .../horizonx/proxy/handlers/WeakMapProxy.ts | 7 ++--- .../horizonx/proxy/handlers/WeakSetProxy.ts | 5 ++-- 14 files changed, 67 insertions(+), 70 deletions(-) diff --git a/libs/horizon/src/dom/DOMOperator.ts b/libs/horizon/src/dom/DOMOperator.ts index 55c218ae..809a0ae8 100644 --- a/libs/horizon/src/dom/DOMOperator.ts +++ b/libs/horizon/src/dom/DOMOperator.ts @@ -149,7 +149,7 @@ export function submitDomUpdate(tag: string, vNode: VNode) { if (tag === DomComponent) { // DomComponent类型 - if (element !== null || element !== undefined) { + if (element !== null && element !== undefined) { const type = vNode.type; const changeList = vNode.changeList; vNode.changeList = null; @@ -210,9 +210,9 @@ export function hideDom(tag: string, dom: Element | Text) { } // 不隐藏元素 -export function unHideDom(tag: string, dom: Element | Text, props: Props) { +export function unHideDom(tag: string, dom: Element | Text, props?: Props) { if (tag === DomComponent) { - dom.style.display = adjustStyleValue('display', props.style?.display ?? ''); + dom.style.display = adjustStyleValue('display', props?.style?.display ?? ''); } else if (tag === DomText) { dom.textContent = props; } diff --git a/libs/horizon/src/dom/DOMPropertiesHandler/DOMPropertiesHandler.ts b/libs/horizon/src/dom/DOMPropertiesHandler/DOMPropertiesHandler.ts index ede38907..bdf59af7 100644 --- a/libs/horizon/src/dom/DOMPropertiesHandler/DOMPropertiesHandler.ts +++ b/libs/horizon/src/dom/DOMPropertiesHandler/DOMPropertiesHandler.ts @@ -48,7 +48,7 @@ export function setDomProps(dom: Element, props: Object, isNativeTag: boolean, i } } else if (propName === 'dangerouslySetInnerHTML') { dom.innerHTML = propVal.__html; - } else if (!isInit || propVal !== null || propVal !== undefined) { + } else if (!isInit || (propVal !== null && propVal !== undefined)) { updateCommonProp(dom, propName, propVal, isNativeTag); } } @@ -103,7 +103,7 @@ export function compareProps(oldProps: Object, newProps: Object): Object { for (let i = 0; i < keysOfNewProps.length; i++) { propName = keysOfNewProps[i]; newPropValue = newProps[propName]; - oldPropValue = oldProps !== null ? oldProps[propName] : null; + oldPropValue = oldProps !== null && oldProps !== undefined ? oldProps[propName] : null; if ( newPropValue === oldPropValue @@ -144,7 +144,7 @@ export function compareProps(oldProps: Object, newProps: Object): Object { } else if (propName === 'dangerouslySetInnerHTML') { newHTML = newPropValue ? newPropValue.__html : undefined; oldHTML = oldPropValue ? oldPropValue.__html : undefined; - if (newHTML != null) { + if (newHTML !== null && newHTML !== undefined) { if (oldHTML !== newHTML) { toUpdateProps[propName] = newPropValue; } diff --git a/libs/horizon/src/external/JSXElement.ts b/libs/horizon/src/external/JSXElement.ts index e54e2054..5ff3db84 100644 --- a/libs/horizon/src/external/JSXElement.ts +++ b/libs/horizon/src/external/JSXElement.ts @@ -72,15 +72,10 @@ function mergeDefault(sourceObj, defaultObj) { // ['key', 'ref', '__source', '__self']属性不从setting获取 const keyArray = ['key', 'ref', '__source', '__self']; -function getSettingArgs(setting, isClone, type) { - const key = setting && setting.key !== undefined ? String(setting.key) : (isClone ? type.key : null); - const ref = setting && setting.ref !== undefined ? setting.ref : (isClone ? type.ref : null); - return { key, ref }; -} - function buildElement(isClone, type, setting, children) { // setting中的值优先级最高,clone情况下从 type 中取值,创建情况下直接赋值为 null - const { key, ref } = getSettingArgs(setting, isClone, type); + const key = (setting && setting.key !== undefined) ? String(setting.key) : (isClone ? type.key : null); + const ref = (setting && setting.ref !== undefined) ? setting.ref : (isClone ? type.ref : null); const props = isClone ? { ...type.props } : {}; let vNode = isClone ? type[BELONG_CLASS_VNODE_KEY] : getProcessingClassVNode(); diff --git a/libs/horizon/src/horizonx/CommonUtils.ts b/libs/horizon/src/horizonx/CommonUtils.ts index cf2c2bb8..b42ff3be 100644 --- a/libs/horizon/src/horizonx/CommonUtils.ts +++ b/libs/horizon/src/horizonx/CommonUtils.ts @@ -115,7 +115,8 @@ export function resolveMutation(from, to) { if (res[i].mutation) found = true; } } - // TODO: resolve shifts + + // need to resolve shifts return { mutation: found, items: res, from, to }; } diff --git a/libs/horizon/src/horizonx/devtools/index.ts b/libs/horizon/src/horizonx/devtools/index.ts index eda6d696..711c0d62 100644 --- a/libs/horizon/src/horizonx/devtools/index.ts +++ b/libs/horizon/src/horizonx/devtools/index.ts @@ -116,18 +116,22 @@ function makeStoreSnapshot({ type, data }) { export const devtools = { // returns vNode id from horizon devtools getVNodeId: vNode => { - if (!isPanelActive()) return; + if (!isPanelActive()) { + return null; + } window['__HORIZON_DEV_HOOK__'].send(); // update list first return window['__HORIZON_DEV_HOOK__'].getVnodeId(vNode); }, // sends horizonx devtool message to extension emit: (type, data) => { - if (!isPanelActive()) return; + if (!isPanelActive()) { + return; + } window.postMessage({ type: 'HORIZON_DEV_TOOLS', payload: makeStoreSnapshot({ type, data }), from: 'dev tool hook', - }); + }, ''); }, }; @@ -135,7 +139,7 @@ export const devtools = { function getAffectedComponents() { const allStores = getAllStores(); const keys = Object.keys(allStores); - let res = {}; + const res = {}; keys.forEach(key => { if (!allStores[key].$config.state._horizonObserver.keyVNodes) { res[key] = []; @@ -144,17 +148,17 @@ function getAffectedComponents() { const subRes = new Set(); const process = Array.from(allStores[key].$config.state._horizonObserver.keyVNodes.values()); while (process.length) { - let pivot = process.shift() as { tag: 'string' }; + const pivot = process.shift() as { tag: 'string' }; if (pivot.tag) subRes.add(pivot); - if (pivot?.toString() === '[object Set]') Array.from(pivot).forEach(item => process.push(item)); + if (pivot.toString() === '[object Set]') Array.from(pivot).forEach(item => process.push(item)); } - res[key] = Array.from(subRes).map(vnode => { + res[key] = Array.from(subRes).map(vNode => { return { - name: vnode?.type + name: vNode?.type .toString() .replace(/\{.*\}/, '{...}') .replace('function ', ''), - nodeId: window.__HORIZON_DEV_HOOK__.getVnodeId(vnode), + nodeId: window.__HORIZON_DEV_HOOK__.getVnodeId(vNode), }; }); }); @@ -163,7 +167,7 @@ function getAffectedComponents() { } // listens to messages from background -window.addEventListener('message', messageEvent => { +window.addEventListener('message', (messageEvent?) => { if (messageEvent?.data?.payload?.type === 'horizonx request observed components') { // get observed components setTimeout(() => { @@ -171,7 +175,7 @@ window.addEventListener('message', messageEvent => { type: 'HORIZON_DEV_TOOLS', payload: { type: OBSERVED_COMPONENTS, data: getAffectedComponents() }, from: 'dev tool hook', - }); + }, ''); }, 100); } @@ -216,6 +220,7 @@ window.addEventListener('message', messageEvent => { console.error(err); } } - // TODO:implement add and delete element + + // need to implement add and delete element } }); diff --git a/libs/horizon/src/horizonx/proxy/Observer.ts b/libs/horizon/src/horizonx/proxy/Observer.ts index de009283..bb5dae3d 100644 --- a/libs/horizon/src/horizonx/proxy/Observer.ts +++ b/libs/horizon/src/horizonx/proxy/Observer.ts @@ -97,10 +97,6 @@ export class Observer implements IObserver { } triggerUpdate(vNode: VNode): void { - if (!vNode) { - return; - } - // 触发VNode更新 launchUpdateFromVNode(vNode); } diff --git a/libs/horizon/src/horizonx/proxy/ProxyHandler.ts b/libs/horizon/src/horizonx/proxy/ProxyHandler.ts index b20a6dfb..b2ff5cdd 100644 --- a/libs/horizon/src/horizonx/proxy/ProxyHandler.ts +++ b/libs/horizon/src/horizonx/proxy/ProxyHandler.ts @@ -62,11 +62,12 @@ export function createProxy(rawObj: any, isHookObserver: boolean, listener: { cu // 创建Proxy let proxyObj; if (!isHookObserver) { - proxyObj = createObjectProxy(rawObj, true, { - current: change => { - listener.current(change); + proxyObj = createObjectProxy(rawObj, { + current: change => { + listener.current(change); + }, }, - }); + true); } else if (isArray(rawObj)) { // 数组 proxyObj = createArrayProxy(rawObj as [], { @@ -76,18 +77,20 @@ export function createProxy(rawObj: any, isHookObserver: boolean, listener: { cu }); } else if (isCollection(rawObj)) { // 集合 - proxyObj = createCollectionProxy(rawObj, true, { - current: change => { - listener.current(change); + proxyObj = createCollectionProxy(rawObj, { + current: change => { + listener.current(change); + }, }, - }); + true); } else { // 原生对象 或 函数 - proxyObj = createObjectProxy(rawObj, false, { - current: change => { - listener.current(change); + proxyObj = createObjectProxy(rawObj, { + current: change => { + listener.current(change); + }, }, - }); + false); } proxyMap.set(rawObj, proxyObj); diff --git a/libs/horizon/src/horizonx/proxy/handlers/ArrayProxyHandler.ts b/libs/horizon/src/horizonx/proxy/handlers/ArrayProxyHandler.ts index 669f560a..630abd53 100644 --- a/libs/horizon/src/horizonx/proxy/handlers/ArrayProxyHandler.ts +++ b/libs/horizon/src/horizonx/proxy/handlers/ArrayProxyHandler.ts @@ -35,7 +35,7 @@ function set(rawObj: any[], key: string, value: any, receiver: any) { if (!isSame(newValue, oldValue)) { // 值不一样,触发监听器 - if (observer.watchers?.[key]) { + if (observer.watchers[key]) { observer.watchers[key].forEach(cb => { cb(key, oldValue, newValue, mutation); }); diff --git a/libs/horizon/src/horizonx/proxy/handlers/CollectionProxyHandler.ts b/libs/horizon/src/horizonx/proxy/handlers/CollectionProxyHandler.ts index e6d4309c..e5b4407e 100644 --- a/libs/horizon/src/horizonx/proxy/handlers/CollectionProxyHandler.ts +++ b/libs/horizon/src/horizonx/proxy/handlers/CollectionProxyHandler.ts @@ -21,19 +21,17 @@ import { createMapProxy } from './MapProxy'; export function createCollectionProxy( rawObj: Object, - hookObserver: boolean, - listener: { current: (...args) => any } + listener: { current: (...args) => any }, + hookObserver = true ): Object { - hookObserver = hookObserver || true; - if (isWeakSet(rawObj)) { - return createWeakSetProxy(rawObj, hookObserver, listener); + return createWeakSetProxy(rawObj, listener, hookObserver); } if (isSet(rawObj)) { - return createSetProxy(rawObj, hookObserver, listener); + return createSetProxy(rawObj, listener, hookObserver); } if (isWeakMap(rawObj)) { - return createWeakMapProxy(rawObj, hookObserver, listener); + return createWeakMapProxy(rawObj, listener, hookObserver); } - return createMapProxy(rawObj, hookObserver, listener); + return createMapProxy(rawObj, listener, hookObserver); } diff --git a/libs/horizon/src/horizonx/proxy/handlers/MapProxy.ts b/libs/horizon/src/horizonx/proxy/handlers/MapProxy.ts index 0921cf7a..6fd0b03d 100644 --- a/libs/horizon/src/horizonx/proxy/handlers/MapProxy.ts +++ b/libs/horizon/src/horizonx/proxy/handlers/MapProxy.ts @@ -20,14 +20,17 @@ import { isPanelActive } from '../../devtools'; const COLLECTION_CHANGE = '_collectionChange'; -export function createMapProxy(rawObj: Object, hookObserver: boolean, listener: { current: (...args) => any }): Object { - hookObserver = hookObserver || true; +export function createMapProxy( + rawObj: Object, + listener: { current: (...args) => any }, + hookObserver = true +): Object { let listeners: ((mutation) => {})[] = []; let oldData: [any, any][] = []; let proxies = new Map(); ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - function getFun(rawObj: { get: (key: any) => any; has: (key: any) => boolean }, key: any) { + function getFun(rawObj: { get: (key: any) => any; has: (key: any) => boolean }, key: any): any { const keyProxy = rawObj.has(key) ? key : proxies.get(key); if (!keyProxy) return; const observer = getObserver(rawObj); @@ -61,7 +64,7 @@ export function createMapProxy(rawObj: Object, hookObserver: boolean, listener: }, key: any, value: any - ) { + ): any { if (rawObj.has(key) || rawObj.has(proxies.get(key))) { // VALUE CHANGE (whole value for selected key is changed) const oldValue = rawObj.get(proxies.get(key)); @@ -71,7 +74,7 @@ export function createMapProxy(rawObj: Object, hookObserver: boolean, listener: const observer = getObserver(rawObj); observer.setProp(COLLECTION_CHANGE, mutation); - if (observer.watchers?.[key]) { + if (observer.watchers[key]) { observer.watchers[key].forEach(cb => { cb(key, oldValue, value, mutation); }); diff --git a/libs/horizon/src/horizonx/proxy/handlers/ObjectProxyHandler.ts b/libs/horizon/src/horizonx/proxy/handlers/ObjectProxyHandler.ts index 28aeb1f2..4f7448ab 100644 --- a/libs/horizon/src/horizonx/proxy/handlers/ObjectProxyHandler.ts +++ b/libs/horizon/src/horizonx/proxy/handlers/ObjectProxyHandler.ts @@ -29,7 +29,7 @@ function set(rawObj: object, key: string, value: any, receiver: any): boolean { const mutation = isPanelActive() ? resolveMutation(oldObject, rawObj) : resolveMutation(null, rawObj); if (!isSame(newValue, oldValue)) { - if (observer.watchers?.[key]) { + if (observer.watchers[key]) { observer.watchers[key].forEach(cb => { cb(key, oldValue, newValue, mutation); }); @@ -41,10 +41,9 @@ function set(rawObj: object, key: string, value: any, receiver: any): boolean { export function createObjectProxy( rawObj: T, - singleLevel: boolean, - listener: { current: (...args) => any } + listener: { current: (...args) => any }, + singleLevel = false ): ProxyHandler { - singleLevel = singleLevel || false; let listeners = [] as ((...args) => void)[]; function get(rawObj: object, key: string | symbol, receiver: any): any { diff --git a/libs/horizon/src/horizonx/proxy/handlers/SetProxy.ts b/libs/horizon/src/horizonx/proxy/handlers/SetProxy.ts index e5efb07b..3eeeebd0 100644 --- a/libs/horizon/src/horizonx/proxy/handlers/SetProxy.ts +++ b/libs/horizon/src/horizonx/proxy/handlers/SetProxy.ts @@ -20,10 +20,9 @@ const COLLECTION_CHANGE = '_collectionChange'; export function createSetProxy( rawObj: T, - hookObserver: boolean, - listener: { current: (...args) => any } + listener: { current: (...args) => any }, + hookObserver = true ): ProxyHandler { - hookObserver = hookObserver || true; let listeners: ((mutation) => {})[] = []; let proxies = new WeakMap(); diff --git a/libs/horizon/src/horizonx/proxy/handlers/WeakMapProxy.ts b/libs/horizon/src/horizonx/proxy/handlers/WeakMapProxy.ts index 3792dc4d..30c32fd8 100644 --- a/libs/horizon/src/horizonx/proxy/handlers/WeakMapProxy.ts +++ b/libs/horizon/src/horizonx/proxy/handlers/WeakMapProxy.ts @@ -22,10 +22,9 @@ const COLLECTION_CHANGE = '_collectionChange'; export function createWeakMapProxy( rawObj: Object, - hookObserver: boolean, - listener: { current: (...args) => any } + listener: { current: (...args) => any }, + hookObserver = true ): Object { - hookObserver = hookObserver ||true; let listeners: ((mutation) => {})[] = []; const handler = { @@ -117,7 +116,7 @@ export function createWeakMapProxy( } if (valChange) { - if (observer.watchers?.[key]) { + if (observer.watchers[key]) { observer.watchers[key].forEach(cb => { cb(key, oldValue, newValue, mutation); }); diff --git a/libs/horizon/src/horizonx/proxy/handlers/WeakSetProxy.ts b/libs/horizon/src/horizonx/proxy/handlers/WeakSetProxy.ts index 4fd6b788..a9914be9 100644 --- a/libs/horizon/src/horizonx/proxy/handlers/WeakSetProxy.ts +++ b/libs/horizon/src/horizonx/proxy/handlers/WeakSetProxy.ts @@ -18,10 +18,9 @@ import { createProxy, getObserver, hookObserverMap } from '../ProxyHandler'; export function createWeakSetProxy( rawObj: T, - hookObserver: boolean, - listener: { current: (...args) => any } + listener: { current: (...args) => any }, + hookObserver = true, ): ProxyHandler { - hookObserver = hookObserver || true; let listeners: ((mutation) => {})[] = []; let proxies = new WeakMap(); From 914425a54511569271d45b148ad0ace460261ba7 Mon Sep 17 00:00:00 2001 From: * <*> Date: Wed, 7 Jun 2023 16:33:34 +0800 Subject: [PATCH 3/3] Match-id-930581f027f9f3c888ded7e7eac3fb5f165bcb4e --- .../src/horizonx/proxy/ProxyHandler.ts | 4 +- .../proxy/handlers/ArrayProxyHandler.ts | 8 +- .../src/horizonx/proxy/handlers/MapProxy.ts | 198 ++++++++++-------- .../proxy/handlers/ObjectProxyHandler.ts | 8 +- .../src/horizonx/proxy/handlers/SetProxy.ts | 44 ++-- .../horizonx/proxy/handlers/WeakMapProxy.ts | 26 +-- .../horizonx/proxy/handlers/WeakSetProxy.ts | 24 ++- .../src/horizonx/store/StoreHandler.ts | 2 +- 8 files changed, 169 insertions(+), 145 deletions(-) diff --git a/libs/horizon/src/horizonx/proxy/ProxyHandler.ts b/libs/horizon/src/horizonx/proxy/ProxyHandler.ts index b2ff5cdd..d37cca1a 100644 --- a/libs/horizon/src/horizonx/proxy/ProxyHandler.ts +++ b/libs/horizon/src/horizonx/proxy/ProxyHandler.ts @@ -31,9 +31,7 @@ export function getObserver(rawObj: any): Observer { return rawObj[OBSERVER_KEY]; } -export function createProxy(rawObj: any, isHookObserver: boolean, listener: { current: (...args) => any }): any { - isHookObserver = isHookObserver || true; - +export function createProxy(rawObj: any, listener: { current: (...args) => any }, isHookObserver = true): any { // 不是对象(是原始数据类型)不用代理 if (!(rawObj && isObject(rawObj))) { return rawObj; diff --git a/libs/horizon/src/horizonx/proxy/handlers/ArrayProxyHandler.ts b/libs/horizon/src/horizonx/proxy/handlers/ArrayProxyHandler.ts index 630abd53..ea94e4a0 100644 --- a/libs/horizon/src/horizonx/proxy/handlers/ArrayProxyHandler.ts +++ b/libs/horizon/src/horizonx/proxy/handlers/ArrayProxyHandler.ts @@ -35,7 +35,7 @@ function set(rawObj: any[], key: string, value: any, receiver: any) { if (!isSame(newValue, oldValue)) { // 值不一样,触发监听器 - if (observer.watchers[key]) { + if (observer.watchers?.[key]) { observer.watchers[key].forEach(cb => { cb(key, oldValue, newValue, mutation); }); @@ -97,7 +97,7 @@ export function createArrayProxy(rawObj: any[], listener: { current: (...args) = // 对于value也需要进一步代理 const valProxy = singleLevel ? value - : createProxy(value, hookObserverMap.get(rawObj), { + : createProxy(value, { current: change => { if (!change.parents) change.parents = []; change.parents.push(rawObj); @@ -108,7 +108,9 @@ export function createArrayProxy(rawObj: any[], listener: { current: (...args) = listener.current(mutation); listeners.forEach(lst => lst(mutation)); }, - }); + }, + hookObserverMap.get(rawObj) + ); return valProxy; } diff --git a/libs/horizon/src/horizonx/proxy/handlers/MapProxy.ts b/libs/horizon/src/horizonx/proxy/handlers/MapProxy.ts index 6fd0b03d..03accb28 100644 --- a/libs/horizon/src/horizonx/proxy/handlers/MapProxy.ts +++ b/libs/horizon/src/horizonx/proxy/handlers/MapProxy.ts @@ -38,18 +38,20 @@ export function createMapProxy( const value = rawObj.get(keyProxy); // 对于value也需要进一步代理 - const valProxy = createProxy(value, hookObserverMap.get(rawObj), { - current: change => { - if (!change.parents) change.parents = []; - change.parents.push(rawObj); - let mutation = resolveMutation( - { ...rawObj, [key]: change.mutation.from }, - { ...rawObj, [key]: change.mutation.to } - ); - listener.current({ ...change, mutation }); - listeners.forEach(lst => lst({ ...change, mutation })); + const valProxy = createProxy(value, { + current: change => { + if (!change.parents) change.parents = []; + change.parents.push(rawObj); + let mutation = resolveMutation( + { ...rawObj, [key]: change.mutation.from }, + { ...rawObj, [key]: change.mutation.to } + ); + listener.current({ ...change, mutation }); + listeners.forEach(lst => lst({ ...change, mutation })); + }, }, - }); + hookObserverMap.get(rawObj) + ); return valProxy; } @@ -84,19 +86,21 @@ export function createMapProxy( oldData = [...Array.from(rawObj.entries())]; } else { // NEW VALUE - const keyProxy = createProxy(key, hookObserverMap.get(rawObj), { - current: change => { - // KEY CHANGE - if (!change.parents) change.parents = []; - change.parents.push(rawObj); - let mutation = resolveMutation( - { ...rawObj, ['_keyChange']: change.mutation.from }, - { ...rawObj, ['_keyChange']: change.mutation.to } - ); - listener.current({ ...change, mutation }); - listeners.forEach(lst => lst({ ...change, mutation })); + const keyProxy = createProxy(key, { + current: change => { + // KEY CHANGE + if (!change.parents) change.parents = []; + change.parents.push(rawObj); + let mutation = resolveMutation( + { ...rawObj, ['_keyChange']: change.mutation.from }, + { ...rawObj, ['_keyChange']: change.mutation.to } + ); + listener.current({ ...change, mutation }); + listeners.forEach(lst => lst({ ...change, mutation })); + }, }, - }); + hookObserverMap.get(rawObj) + ); proxies.set(key, keyProxy); rawObj.set(keyProxy, value); @@ -180,32 +184,36 @@ export function createMapProxy( const observer = getObserver(rawObj); observer.useProp(COLLECTION_CHANGE); rawObj.forEach((value, key) => { - const keyProxy = createProxy(value, hookObserverMap.get(rawObj), { - current: change => { - //KEY ATTRIBUTES CHANGED - if (!change.parents) change.parents = []; - change.parents.push(rawObj); - let mutation = resolveMutation( - { ...rawObj, ['_keyChange']: change.mutation.from }, - { ...rawObj, ['_keyChange']: change.mutation.to } - ); - listener.current({ ...change, mutation }); - listeners.forEach(lst => lst({ ...change, mutation })); + const keyProxy = createProxy(value, { + current: change => { + //KEY ATTRIBUTES CHANGED + if (!change.parents) change.parents = []; + change.parents.push(rawObj); + let mutation = resolveMutation( + { ...rawObj, ['_keyChange']: change.mutation.from }, + { ...rawObj, ['_keyChange']: change.mutation.to } + ); + listener.current({ ...change, mutation }); + listeners.forEach(lst => lst({ ...change, mutation })); + }, }, - }); - const valProxy = createProxy(key, hookObserverMap.get(rawObj), { - current: change => { - // VALUE ATTRIBUTE CHANGED - if (!change.parents) change.parents = []; - change.parents.push(rawObj); - let mutation = resolveMutation( - { ...rawObj, key: change.mutation.from }, - { ...rawObj, key: change.mutation.to } - ); - listener.current({ ...change, mutation }); - listeners.forEach(lst => lst({ ...change, mutation })); + hookObserverMap.get(rawObj) + ); + const valProxy = createProxy(key, { + current: change => { + // VALUE ATTRIBUTE CHANGED + if (!change.parents) change.parents = []; + change.parents.push(rawObj); + let mutation = resolveMutation( + { ...rawObj, key: change.mutation.from }, + { ...rawObj, key: change.mutation.to } + ); + listener.current({ ...change, mutation }); + listeners.forEach(lst => lst({ ...change, mutation })); + }, }, - }); + hookObserverMap.get(rawObj) + ); // 最后一个参数要返回代理对象 return callback(keyProxy, valProxy, rawObj); }); @@ -221,18 +229,20 @@ export function createMapProxy( const { value, done } = rawIt.next(); if (done) { return { - value: createProxy(value, hookObserver, { - current: change => { - if (!change.parents) change.parents = []; - change.parents.push(rawObj); - let mutation = resolveMutation( - { ...rawObj, [value]: change.mutation.from }, - { ...rawObj, [value]: change.mutation.to } - ); - listener.current({ ...change, mutation }); - listeners.forEach(lst => lst({ ...change, mutation })); + value: createProxy(value, { + current: change => { + if (!change.parents) change.parents = []; + change.parents.push(rawObj); + let mutation = resolveMutation( + { ...rawObj, [value]: change.mutation.from }, + { ...rawObj, [value]: change.mutation.to } + ); + listener.current({ ...change, mutation }); + listeners.forEach(lst => lst({ ...change, mutation })); + }, }, - }), + hookObserver + ), done, }; } @@ -242,45 +252,51 @@ export function createMapProxy( if (type === 'entries') { //ENTRY CHANGED newVal = [ - createProxy(value[0], hookObserver, { - current: change => { - if (!change.parents) change.parents = []; - change.parents.push(rawObj); - let mutation = resolveMutation( - { ...rawObj, ['itemChange']: { key: change.mutation.from, value: value[1] } }, - { ...rawObj, ['itemChange']: { key: change.mutation.to, value: value[1] } } - ); - listener.current({ ...change, mutation }); - listeners.forEach(lst => lst({ ...change, mutation })); + createProxy(value[0], { + current: change => { + if (!change.parents) change.parents = []; + change.parents.push(rawObj); + let mutation = resolveMutation( + { ...rawObj, ['itemChange']: { key: change.mutation.from, value: value[1] } }, + { ...rawObj, ['itemChange']: { key: change.mutation.to, value: value[1] } } + ); + listener.current({ ...change, mutation }); + listeners.forEach(lst => lst({ ...change, mutation })); + }, }, - }), - createProxy(value[1], hookObserver, { - current: change => { - if (!change.parents) change.parents = []; - change.parents.push(rawObj); - let mutation = resolveMutation( - { ...rawObj, item: { key: value[0], value: change.mutation.from } }, - { ...rawObj, item: { key: value[0], value: change.mutation.to } } - ); - listener.current({ ...change, mutation }); - listeners.forEach(lst => lst({ ...change, mutation })); + hookObserver + ), + createProxy(value[1], { + current: change => { + if (!change.parents) change.parents = []; + change.parents.push(rawObj); + let mutation = resolveMutation( + { ...rawObj, item: { key: value[0], value: change.mutation.from } }, + { ...rawObj, item: { key: value[0], value: change.mutation.to } } + ); + listener.current({ ...change, mutation }); + listeners.forEach(lst => lst({ ...change, mutation })); + }, }, - }), + hookObserver + ), ]; } else { // SINGLE VALUE CHANGED - newVal = createProxy(value, hookObserver, { - current: change => { - if (!change.parents) change.parents = []; - change.parents.push(rawObj); - let mutation = resolveMutation( - { ...rawObj, [type === 'keys' ? 'key' : 'value']: change.mutation.from }, - { ...rawObj, [type === 'keys' ? 'key' : 'value']: change.mutation.to } - ); - listener.current({ ...change, mutation }); - listeners.forEach(lst => lst({ ...change, mutation })); + newVal = createProxy(value, { + current: change => { + if (!change.parents) change.parents = []; + change.parents.push(rawObj); + let mutation = resolveMutation( + { ...rawObj, [type === 'keys' ? 'key' : 'value']: change.mutation.from }, + { ...rawObj, [type === 'keys' ? 'key' : 'value']: change.mutation.to } + ); + listener.current({ ...change, mutation }); + listeners.forEach(lst => lst({ ...change, mutation })); + }, }, - }); + hookObserver + ); } return { value: newVal, done }; diff --git a/libs/horizon/src/horizonx/proxy/handlers/ObjectProxyHandler.ts b/libs/horizon/src/horizonx/proxy/handlers/ObjectProxyHandler.ts index 4f7448ab..1a216477 100644 --- a/libs/horizon/src/horizonx/proxy/handlers/ObjectProxyHandler.ts +++ b/libs/horizon/src/horizonx/proxy/handlers/ObjectProxyHandler.ts @@ -29,7 +29,7 @@ function set(rawObj: object, key: string, value: any, receiver: any): boolean { const mutation = isPanelActive() ? resolveMutation(oldObject, rawObj) : resolveMutation(null, rawObj); if (!isSame(newValue, oldValue)) { - if (observer.watchers[key]) { + if (observer.watchers?.[key]) { observer.watchers[key].forEach(cb => { cb(key, oldValue, newValue, mutation); }); @@ -87,7 +87,7 @@ export function createObjectProxy( // 对于value也需要进一步代理 const valProxy = singleLevel ? value - : createProxy(value, hookObserverMap.get(rawObj), { + : createProxy(value, { current: change => { if (!change.parents) change.parents = []; change.parents.push(rawObj); @@ -98,7 +98,9 @@ export function createObjectProxy( listener.current({ ...change, mutation }); listeners.forEach(lst => lst({ ...change, mutation })); }, - }); + }, + hookObserverMap.get(rawObj) + ); return valProxy; } diff --git a/libs/horizon/src/horizonx/proxy/handlers/SetProxy.ts b/libs/horizon/src/horizonx/proxy/handlers/SetProxy.ts index 3eeeebd0..e5b19e4f 100644 --- a/libs/horizon/src/horizonx/proxy/handlers/SetProxy.ts +++ b/libs/horizon/src/horizonx/proxy/handlers/SetProxy.ts @@ -29,26 +29,28 @@ export function createSetProxy( // Set的add方法 function add(rawObj: { add: (any) => void; has: (any) => boolean; values: () => any[] }, value: any): Object { if (!rawObj.has(proxies.get(value))) { - const proxy = createProxy(value, hookObserverMap.get(rawObj), { - current: change => { - if (!change.parents) change.parents = []; - change.parents.push(rawObj); - let mutation = resolveMutation( - { ...rawObj, valueChange: change.mutation.from }, - { ...rawObj, valueChange: change.mutation.to } - ); - listener.current({ - ...change, - mutation, - }); - listeners.forEach(lst => - lst({ + const proxy = createProxy(value, { + current: change => { + if (!change.parents) change.parents = []; + change.parents.push(rawObj); + let mutation = resolveMutation( + { ...rawObj, valueChange: change.mutation.from }, + { ...rawObj, valueChange: change.mutation.to } + ); + listener.current({ ...change, mutation, - }) - ); + }); + listeners.forEach(lst => + lst({ + ...change, + mutation, + }) + ); + }, }, - }); + hookObserverMap.get(rawObj) + ); const oldValues = Array.from(rawObj.values()); proxies.set(value, proxy); @@ -210,13 +212,13 @@ export function createSetProxy( }; const { value, done } = rawIt.next(); if (done) { - return { value: createProxy(value, hookObserver, currentListener), done }; + return { value: createProxy(value, currentListener, hookObserver), done }; } observer.useProp(COLLECTION_CHANGE); let newVal; - newVal = createProxy(value, hookObserver, currentListener); + newVal = createProxy(value, currentListener, hookObserver); return { value: newVal, done }; }, @@ -274,8 +276,8 @@ export function createSetProxy( ); }, }; - const valProxy = createProxy(value, hookObserverMap.get(rawObj), currentListener); - const keyProxy = createProxy(key, hookObserverMap.get(rawObj), currentListener); + const valProxy = createProxy(value, currentListener, hookObserverMap.get(rawObj)); + const keyProxy = createProxy(key, currentListener, hookObserverMap.get(rawObj)); // 最后一个参数要返回代理对象 return callback(valProxy, keyProxy, rawObj); }); diff --git a/libs/horizon/src/horizonx/proxy/handlers/WeakMapProxy.ts b/libs/horizon/src/horizonx/proxy/handlers/WeakMapProxy.ts index 30c32fd8..70124cb6 100644 --- a/libs/horizon/src/horizonx/proxy/handlers/WeakMapProxy.ts +++ b/libs/horizon/src/horizonx/proxy/handlers/WeakMapProxy.ts @@ -42,18 +42,20 @@ export function createWeakMapProxy( const value = rawObj.get(key); // 对于value也需要进一步代理 - const valProxy = createProxy(value, hookObserverMap.get(rawObj), { - current: change => { - if (!change.parents) change.parents = []; - change.parents.push(rawObj); - let mutation = resolveMutation( - { ...rawObj, [key]: change.mutation.from }, - { ...rawObj, [key]: change.mutation.to } - ); - listener.current({ ...change, mutation }); - listeners.forEach(lst => lst({ ...change, mutation })); + const valProxy = createProxy(value, { + current: change => { + if (!change.parents) change.parents = []; + change.parents.push(rawObj); + let mutation = resolveMutation( + { ...rawObj, [key]: change.mutation.from }, + { ...rawObj, [key]: change.mutation.to } + ); + listener.current({ ...change, mutation }); + listeners.forEach(lst => lst({ ...change, mutation })); + }, }, - }); + hookObserverMap.get(rawObj) + ); return valProxy; } @@ -116,7 +118,7 @@ export function createWeakMapProxy( } if (valChange) { - if (observer.watchers[key]) { + if (observer.watchers?.[key]) { observer.watchers[key].forEach(cb => { cb(key, oldValue, newValue, mutation); }); diff --git a/libs/horizon/src/horizonx/proxy/handlers/WeakSetProxy.ts b/libs/horizon/src/horizonx/proxy/handlers/WeakSetProxy.ts index a9914be9..baaa6a2b 100644 --- a/libs/horizon/src/horizonx/proxy/handlers/WeakSetProxy.ts +++ b/libs/horizon/src/horizonx/proxy/handlers/WeakSetProxy.ts @@ -66,18 +66,20 @@ export function createWeakSetProxy( // Set的add方法 function add(rawObj: { add: (any) => void; has: (any) => boolean }, value: any): Object { if (!rawObj.has(proxies.get(value))) { - const proxy = createProxy(value, hookObserverMap.get(rawObj), { - current: change => { - if (!change.parents) change.parents = []; - change.parents.push(rawObj); - let mutation = resolveMutation( - { ...rawObj, [value]: change.mutation.from }, - { ...rawObj, [value]: change.mutation.to } - ); - listener.current({ ...change, mutation }); - listeners.forEach(lst => lst({ ...change, mutation })); + const proxy = createProxy(value, { + current: change => { + if (!change.parents) change.parents = []; + change.parents.push(rawObj); + let mutation = resolveMutation( + { ...rawObj, [value]: change.mutation.from }, + { ...rawObj, [value]: change.mutation.to } + ); + listener.current({ ...change, mutation }); + listeners.forEach(lst => lst({ ...change, mutation })); + }, }, - }); + hookObserverMap.get(rawObj) + ); proxies.set(value, proxy); diff --git a/libs/horizon/src/horizonx/store/StoreHandler.ts b/libs/horizon/src/horizonx/store/StoreHandler.ts index 2afd33f2..469ff88b 100644 --- a/libs/horizon/src/horizonx/store/StoreHandler.ts +++ b/libs/horizon/src/horizonx/store/StoreHandler.ts @@ -161,7 +161,7 @@ export function createStore, C extend current: listener => {}, }; - const proxyObj = createProxy(config.state, !config.options?.isReduxAdapter, listener); + const proxyObj = createProxy(config.state, listener, !config.options?.isReduxAdapter); proxyObj.$pending = false;