From ffac5e4ec00a8a1108f1acc0f8a05fc961713ec0 Mon Sep 17 00:00:00 2001 From: zoomchan-cxj Date: Mon, 6 Dec 2021 11:53:28 +0800 Subject: [PATCH] fix(hippy-react): fixed cached fiberNode event handler problem --- .../hippy-react/src/events/dispatcher.ts | 44 +++++++++++-------- .../packages/hippy-react/src/events/event.ts | 2 - .../hippy-react/src/renderer/host-configs.ts | 10 +++-- 3 files changed, 31 insertions(+), 25 deletions(-) diff --git a/framework/js/packages/hippy-react/src/events/dispatcher.ts b/framework/js/packages/hippy-react/src/events/dispatcher.ts index 4b0fabc47..d562ad57a 100644 --- a/framework/js/packages/hippy-react/src/events/dispatcher.ts +++ b/framework/js/packages/hippy-react/src/events/dispatcher.ts @@ -35,7 +35,7 @@ interface NativeEvent { const eventHubs = new Map(); const componentName = ['%c[event]%c', 'color: green', 'color: auto']; -function registerNativeEventHub(eventName: string) { +function registerNativeEventHub(eventName: any) { trace(...componentName, 'registerNativeEventHub', eventName); if (typeof eventName !== 'string') { throw new TypeError(`Invalid eventName for registerNativeEventHub: ${eventName}`); @@ -49,14 +49,14 @@ function registerNativeEventHub(eventName: string) { return targetEventHub; } -function getHippyEventHub(eventName: string) { +function getHippyEventHub(eventName: any) { if (typeof eventName !== 'string') { throw new TypeError(`Invalid eventName for getHippyEventHub: ${eventName}`); } return eventHubs.get(eventName) || null; } -function unregisterNativeEventHub(eventName: string) { +function unregisterNativeEventHub(eventName: any) { if (typeof eventName !== 'string') { throw new TypeError(`Invalid eventName for unregisterNativeEventHub: ${eventName}`); } @@ -81,7 +81,12 @@ function receiveNativeEvent(nativeEvent: EventParam) { currEventHub.notifyEvent(eventParams); } -interface ListenerObj { eventName: string, listener: Function, isCapture: boolean, target: Element } +interface ListenerObj { + eventName: string; + listener: Function; + isCapture: boolean; + currentTarget: Element; +} /** * convertEventName - convert all special event name @@ -114,7 +119,7 @@ function doCaptureAndBubbleLoop(originalEventName: string, nativeEvent: NativeEv const eventQueue: ListenerObj[] = []; let nextNodeItem: Fiber | null = nodeItem; let eventName = originalEventName; - // capture and bubble loop + // capture and bubbling loop while (nextNodeItem) { eventName = convertEventName(eventName, nextNodeItem); const captureName = `${eventName}Capture`; @@ -124,7 +129,7 @@ function doCaptureAndBubbleLoop(originalEventName: string, nativeEvent: NativeEv eventName: captureName, listener: nextNodeItem.memoizedProps[captureName], isCapture: true, - target: getElementFromFiber(nextNodeItem), + currentTarget: getElementFromFiber(nextNodeItem), }); } if (isNodePropFunction(eventName, nextNodeItem)) { @@ -133,7 +138,7 @@ function doCaptureAndBubbleLoop(originalEventName: string, nativeEvent: NativeEv eventName, listener: nextNodeItem.memoizedProps[eventName], isCapture: false, - target: getElementFromFiber(nextNodeItem), + currentTarget: getElementFromFiber(nextNodeItem), }); } nextNodeItem = nextNodeItem.return; @@ -145,15 +150,16 @@ function doCaptureAndBubbleLoop(originalEventName: string, nativeEvent: NativeEv if (eventQueue.length > 0) { let listenerObj: ListenerObj | undefined; let isStopBubble: any = false; - const targetElementNode = getElementFromFiber(nodeItem); + const targetNode = getElementFromFiber(nodeItem); while (!isStopBubble && (listenerObj = eventQueue.shift()) !== undefined) { try { - const syntheticEvent = new Event(listenerObj.eventName, listenerObj.target, targetElementNode); + const { eventName, currentTarget: currentTargetNode, listener, isCapture } = listenerObj; + const syntheticEvent = new Event(eventName, currentTargetNode, targetNode); Object.assign(syntheticEvent, nativeEvent); - if (listenerObj.isCapture) { - listenerObj.listener(syntheticEvent); + if (isCapture) { + listener(syntheticEvent); } else { - isStopBubble = listenerObj.listener(syntheticEvent); + isStopBubble = listener(syntheticEvent); // If callback have no return, use global bubble config to set isStopBubble. if (typeof isStopBubble !== 'boolean') { isStopBubble = !isGlobalBubble(); @@ -171,7 +177,7 @@ function doCaptureAndBubbleLoop(originalEventName: string, nativeEvent: NativeEv } /** - * doBubbleLoop - process only bubble phase + * doBubbleLoop - process only bubbling phase * @param {string} originalEventName * @param {NativeEvent} nativeEvent * @param {Fiber} nodeItem @@ -180,14 +186,14 @@ function doBubbleLoop(originalEventName: string, nativeEvent: NativeEvent, nodeI let isStopBubble: any = false; let nextNodeItem: Fiber | null = nodeItem; let eventName = originalEventName; - const targetElementNode = getElementFromFiber(nodeItem); - // only bubble loop + const targetNode = getElementFromFiber(nodeItem); + // only bubbling loop do { eventName = convertEventName(eventName, nextNodeItem); if (isNodePropFunction(eventName, nextNodeItem)) { try { - const elementNode = getElementFromFiber(nextNodeItem); - const syntheticEvent = new Event(eventName, elementNode, targetElementNode); + const currentTargetNode = getElementFromFiber(nextNodeItem); + const syntheticEvent = new Event(eventName, currentTargetNode, targetNode); Object.assign(syntheticEvent, nativeEvent); isStopBubble = nextNodeItem.memoizedProps[eventName](syntheticEvent); // If callback have no return, use global bubble config to set isStopBubble. @@ -227,7 +233,7 @@ function receiveNativeGesture(nativeEvent: NativeEvent) { eventName = convertEventName(eventName, targetNode); const captureName = `${eventName}Capture`; const nextNodeItem: Fiber = targetNode; - // if current target has no capture listener, only do bubble phase loop to improve performance + // if current target has no capture listener, only do bubbling phase loop to improve performance if (targetNode.memoizedProps && typeof targetNode.memoizedProps[captureName] !== 'function') { hasCapturePhase = false; } @@ -238,7 +244,7 @@ function receiveNativeGesture(nativeEvent: NativeEvent) { } } -function receiveUIComponentEvent(nativeEvent: string[]) { +function receiveUIComponentEvent(nativeEvent: any[]) { trace(...componentName, 'receiveUIComponentEvent', nativeEvent); if (!nativeEvent || !Array.isArray(nativeEvent) || nativeEvent.length < 2) { return; diff --git a/framework/js/packages/hippy-react/src/events/event.ts b/framework/js/packages/hippy-react/src/events/event.ts index db652d13a..4b628a674 100644 --- a/framework/js/packages/hippy-react/src/events/event.ts +++ b/framework/js/packages/hippy-react/src/events/event.ts @@ -18,8 +18,6 @@ * limitations under the License. */ -import { isGlobalBubble } from '../utils'; - interface Event { type: string; bubbles: boolean; diff --git a/framework/js/packages/hippy-react/src/renderer/host-configs.ts b/framework/js/packages/hippy-react/src/renderer/host-configs.ts index 665f8a81a..9dfba0651 100644 --- a/framework/js/packages/hippy-react/src/renderer/host-configs.ts +++ b/framework/js/packages/hippy-react/src/renderer/host-configs.ts @@ -53,7 +53,12 @@ function commitTextUpdate() {} function commitUpdate( instance: any, updatePayload: any, + type: string, + oldProps: Props, + newProps: Props, + workInProgress: any, ): void { + preCacheFiberNode(workInProgress, instance.nodeId); Object.keys(updatePayload).forEach(attr => instance.setAttribute(attr, updatePayload[attr])); } @@ -155,10 +160,7 @@ function prepareUpdate( break; } default: { - // FIXME: Cancel a event listener - if (typeof oldPropValue === 'function' && typeof newPropValue === 'function') { - // just skip it if meets function - } else if (!isEqual(oldPropValue, newPropValue)) { + if (!isEqual(oldPropValue, newPropValue)) { updatePayload[key] = newPropValue; } }