From 4d85b1263289845554de482639636aef3e2c8d5c Mon Sep 17 00:00:00 2001 From: Brian Vaughn Date: Mon, 29 Oct 2018 11:03:16 -0700 Subject: [PATCH 1/4] Add support for React.memo --- backend/attachRendererFiber.js | 31 ++++++++++++++++--------------- 1 file changed, 16 insertions(+), 15 deletions(-) diff --git a/backend/attachRendererFiber.js b/backend/attachRendererFiber.js index a7e061b105..1029d22752 100644 --- a/backend/attachRendererFiber.js +++ b/backend/attachRendererFiber.js @@ -106,10 +106,10 @@ function getInternalReactConstants(version) { CONTEXT_PROVIDER_SYMBOL_STRING: 'Symbol(react.provider)', FORWARD_REF_NUMBER: 0xead0, FORWARD_REF_SYMBOL_STRING: 'Symbol(react.forward_ref)', + MEMO_NUMBER: 0xead3, + MEMO_SYMBOL_STRING: 'Symbol(react.memo)', PROFILER_NUMBER: 0xead2, PROFILER_SYMBOL_STRING: 'Symbol(react.profiler)', - PURE_NUMBER: 0xead3, - PURE_SYMBOL_STRING: 'Symbol(react.pure)', STRICT_MODE_NUMBER: 0xeacc, STRICT_MODE_SYMBOL_STRING: 'Symbol(react.strict_mode)', SUSPENSE_NUMBER: 0xead1, @@ -143,6 +143,8 @@ function attachRendererFiber(hook: Hook, rid: string, renderer: ReactRenderer): HostText, Fragment, ForwardRef, + MemoComponent, + SimpleMemoComponent, } = ReactTypeOfWork; var { CONCURRENT_MODE_NUMBER, @@ -154,8 +156,6 @@ function attachRendererFiber(hook: Hook, rid: string, renderer: ReactRenderer): CONTEXT_PROVIDER_SYMBOL_STRING, PROFILER_NUMBER, PROFILER_SYMBOL_STRING, - PURE_NUMBER, - PURE_SYMBOL_STRING, STRICT_MODE_NUMBER, STRICT_MODE_SYMBOL_STRING, SUSPENSE_NUMBER, @@ -166,6 +166,7 @@ function attachRendererFiber(hook: Hook, rid: string, renderer: ReactRenderer): // TODO: we might want to change the data structure // once we no longer suppport Stack versions of `getData`. function getDataFiber(fiber: Object): DataType { + var elementType = fiber.elementType; var type = fiber.type; var key = fiber.key; var ref = fiber.ref; @@ -279,6 +280,17 @@ function attachRendererFiber(hook: Hook, rid: string, renderer: ReactRenderer): nodeType = 'Wrapper'; children = []; break; + case MemoComponent: + case SimpleMemoComponent: + nodeType = 'Special'; + if (elementType.displayName) { + name = elementType.displayName; + } else { + const displayName = type.displayName || type.name; + name = displayName ? `Memo(${displayName})` : 'Memo'; + } + children = []; + break; default: const symbolOrNumber = typeof type === 'object' && type !== null ? type.$$typeof @@ -289,17 +301,6 @@ function attachRendererFiber(hook: Hook, rid: string, renderer: ReactRenderer): : symbolOrNumber; switch (switchValue) { - case PURE_NUMBER: - case PURE_SYMBOL_STRING: - nodeType = 'Special'; - if (type.displayName) { - name = type.displayName; - } else { - const displayName = type.render.displayName || type.render.name; - name = displayName ? `Pure(${displayName})` : 'Pure'; - } - children = []; - break; case CONCURRENT_MODE_NUMBER: case CONCURRENT_MODE_SYMBOL_STRING: case DEPRECATED_ASYNC_MODE_SYMBOL_STRING: From ef8c92dac481a2643955ae30dc7ae7167c7e4baa Mon Sep 17 00:00:00 2001 From: Brian Vaughn Date: Mon, 29 Oct 2018 14:24:53 -0700 Subject: [PATCH 2/4] Handle IncompleteClassComponent and IndeterminateComponent in getDataFiber() --- backend/attachRendererFiber.js | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/backend/attachRendererFiber.js b/backend/attachRendererFiber.js index 1029d22752..78d5827022 100644 --- a/backend/attachRendererFiber.js +++ b/backend/attachRendererFiber.js @@ -40,6 +40,7 @@ function getInternalReactConstants(version) { HostPortal: 4, HostRoot: 3, HostText: 6, + IncompleteClassComponent: 17, IndeterminateComponent: 2, LazyComponent: 16, MemoComponent: 14, @@ -63,6 +64,7 @@ function getInternalReactConstants(version) { HostPortal: 6, HostRoot: 5, HostText: 8, + IncompleteClassComponent: -1, // Doesn't exist yet IndeterminateComponent: 4, LazyComponent: -1, // Doesn't exist yet MemoComponent: -1, // Doesn't exist yet @@ -86,6 +88,7 @@ function getInternalReactConstants(version) { HostPortal: 4, HostRoot: 3, HostText: 6, + IncompleteClassComponent: -1, // Doesn't exist yet IndeterminateComponent: 0, LazyComponent: -1, // Doesn't exist yet MemoComponent: -1, // Doesn't exist yet @@ -137,12 +140,14 @@ function attachRendererFiber(hook: Hook, rid: string, renderer: ReactRenderer): FunctionalComponent, ClassComponent, ContextConsumer, + Fragment, + ForwardRef, HostRoot, HostPortal, HostComponent, HostText, - Fragment, - ForwardRef, + IncompleteClassComponent, + IndeterminateComponent, MemoComponent, SimpleMemoComponent, } = ReactTypeOfWork; @@ -197,8 +202,10 @@ function attachRendererFiber(hook: Hook, rid: string, renderer: ReactRenderer): // TODO: Add support for new tags LazyComponent, MemoComponent, and SimpleMemoComponent switch (fiber.tag) { - case FunctionalComponent: case ClassComponent: + case FunctionalComponent: + case IncompleteClassComponent: + case IndeterminateComponent: nodeType = 'Composite'; name = getDisplayName(resolvedType); publicInstance = fiber.stateNode; From 34ed7bee3f96d788b3b7f98c4992d76e956ef5d7 Mon Sep 17 00:00:00 2001 From: Brian Vaughn Date: Tue, 30 Oct 2018 15:36:53 -0700 Subject: [PATCH 3/4] Store properly updates parent-child map for reparented fibers --- frontend/Store.js | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/frontend/Store.js b/frontend/Store.js index efc5530f4a..5f0eae0ab0 100644 --- a/frontend/Store.js +++ b/frontend/Store.js @@ -647,6 +647,12 @@ class Store extends EventEmitter { } _mountComponent(data: DataType) { + if (this._nodes.has(data.id)) { + // This node has been re-parented. + this._updateComponent(data); + return; + } + var map = Map(data).set('renders', 1); if (data.nodeType === 'Composite') { map = map.set('collapsed', true); @@ -663,16 +669,18 @@ class Store extends EventEmitter { } _updateComponent(data: DataType) { - var node = this.get(data.id); + var id = data.id; + var node = this.get(id); if (!node) { return; } data.renders = node.get('renders') + 1; - this._nodes = this._nodes.mergeIn([data.id], Map(data)); + this._nodes = this._nodes.mergeIn([id], Map(data)); if (data.children && data.children.forEach) { data.children.forEach(cid => { - if (!this._parents.get(cid)) { - this._parents = this._parents.set(cid, data.id); + var pid = this._parents.get(cid); + if (!pid) { + this._parents = this._parents.set(cid, id); var childNode = this._nodes.get(cid); var childID = childNode.get('id'); if ( @@ -687,6 +695,9 @@ class Store extends EventEmitter { this.emit('searchRoots'); this.highlightSearch(); } + } else if (pid !== id) { + // This node has been re-parented. + this._parents = this._parents.set(cid, id); } }); } From f65be830adad1183c6e54aff3a1f4dd2e54b15ac Mon Sep 17 00:00:00 2001 From: Brian Vaughn Date: Wed, 31 Oct 2018 10:05:37 -0700 Subject: [PATCH 4/4] Remove outdated TODO comment --- backend/attachRendererFiber.js | 2 -- 1 file changed, 2 deletions(-) diff --git a/backend/attachRendererFiber.js b/backend/attachRendererFiber.js index 78d5827022..f3b72d5f05 100644 --- a/backend/attachRendererFiber.js +++ b/backend/attachRendererFiber.js @@ -199,8 +199,6 @@ function attachRendererFiber(hook: Hook, rid: string, renderer: ReactRenderer): } } - // TODO: Add support for new tags LazyComponent, MemoComponent, and SimpleMemoComponent - switch (fiber.tag) { case ClassComponent: case FunctionalComponent: