From 8d5a147b79cd80d2f52ada5b286d24ad6f7fbf01 Mon Sep 17 00:00:00 2001 From: Dan Abramov Date: Wed, 7 Jun 2017 21:28:02 +0100 Subject: [PATCH 1/2] Bail out on fibers that returned false from shouldComponentUpdate --- backend/ReactTypeOfSideEffect.js | 26 ++++++++++++++++++++++++++ backend/attachRendererFiber.js | 7 +++++++ 2 files changed, 33 insertions(+) create mode 100644 backend/ReactTypeOfSideEffect.js diff --git a/backend/ReactTypeOfSideEffect.js b/backend/ReactTypeOfSideEffect.js new file mode 100644 index 0000000000..ac089cb9c4 --- /dev/null +++ b/backend/ReactTypeOfSideEffect.js @@ -0,0 +1,26 @@ +/** + * Copyright (c) 2015-present, Facebook, Inc. + * All rights reserved. + * + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. + * + * @flow + */ +'use strict'; + +// Copied from React repo. + +module.exports = { + NoEffect: 0, // 0b00000000 + Bailout: 1, // 0b00000001 + Placement: 2, // 0b00000010 + Update: 4, // 0b00000100 + PlacementAndUpdate: 6, // 0b00000110 + Deletion: 8, // 0b00001000 + ContentReset: 16, // 0b00010000 + Callback: 32, // 0b00100000 + Err: 64, // 0b01000000 + Ref: 128, // 0b10000000 +}; diff --git a/backend/attachRendererFiber.js b/backend/attachRendererFiber.js index 5a2a0b2898..d447738c33 100644 --- a/backend/attachRendererFiber.js +++ b/backend/attachRendererFiber.js @@ -16,6 +16,9 @@ var { ClassComponent, HostRoot, } = require('./ReactTypeOfWork'); +var { + Bailout, +} = require('./ReactTypeOfSideEffect'); function attachRendererFiber(hook: Hook, rid: string, renderer: ReactRenderer): Helpers { // This is a slightly annoying indirection. @@ -39,6 +42,10 @@ function attachRendererFiber(hook: Hook, rid: string, renderer: ReactRenderer): function hasDataChanged(prevFiber, nextFiber) { if (prevFiber.tag === ClassComponent) { + // Skip subtrees that bailed out with shouldComponentUpdate. + if ((nextFiber.effectTag & Bailout) === Bailout) { + return false; + } // Only classes have context. if (prevFiber.stateNode.context !== nextFiber.stateNode.context) { return true; From b397124db304309155b3f1777180ad47ca04d8ba Mon Sep 17 00:00:00 2001 From: Dan Abramov Date: Thu, 8 Jun 2017 21:18:41 +0100 Subject: [PATCH 2/2] Inline constant and flip flag to match React PR --- backend/ReactTypeOfSideEffect.js | 26 -------------------------- backend/attachRendererFiber.js | 12 +++++++----- 2 files changed, 7 insertions(+), 31 deletions(-) delete mode 100644 backend/ReactTypeOfSideEffect.js diff --git a/backend/ReactTypeOfSideEffect.js b/backend/ReactTypeOfSideEffect.js deleted file mode 100644 index ac089cb9c4..0000000000 --- a/backend/ReactTypeOfSideEffect.js +++ /dev/null @@ -1,26 +0,0 @@ -/** - * Copyright (c) 2015-present, Facebook, Inc. - * All rights reserved. - * - * This source code is licensed under the BSD-style license found in the - * LICENSE file in the root directory of this source tree. An additional grant - * of patent rights can be found in the PATENTS file in the same directory. - * - * @flow - */ -'use strict'; - -// Copied from React repo. - -module.exports = { - NoEffect: 0, // 0b00000000 - Bailout: 1, // 0b00000001 - Placement: 2, // 0b00000010 - Update: 4, // 0b00000100 - PlacementAndUpdate: 6, // 0b00000110 - Deletion: 8, // 0b00001000 - ContentReset: 16, // 0b00010000 - Callback: 32, // 0b00100000 - Err: 64, // 0b01000000 - Ref: 128, // 0b10000000 -}; diff --git a/backend/attachRendererFiber.js b/backend/attachRendererFiber.js index d447738c33..c24c827536 100644 --- a/backend/attachRendererFiber.js +++ b/backend/attachRendererFiber.js @@ -16,9 +16,9 @@ var { ClassComponent, HostRoot, } = require('./ReactTypeOfWork'); -var { - Bailout, -} = require('./ReactTypeOfSideEffect'); + +// Inlined from ReactTypeOfSideEffect +var PerformedWork = 1; function attachRendererFiber(hook: Hook, rid: string, renderer: ReactRenderer): Helpers { // This is a slightly annoying indirection. @@ -42,10 +42,12 @@ function attachRendererFiber(hook: Hook, rid: string, renderer: ReactRenderer): function hasDataChanged(prevFiber, nextFiber) { if (prevFiber.tag === ClassComponent) { - // Skip subtrees that bailed out with shouldComponentUpdate. - if ((nextFiber.effectTag & Bailout) === Bailout) { + // Skip if the class performed no work (shouldComponentUpdate bailout). + // eslint-disable-next-line no-bitwise + if ((nextFiber.effectTag & PerformedWork) !== PerformedWork) { return false; } + // Only classes have context. if (prevFiber.stateNode.context !== nextFiber.stateNode.context) { return true;