UNPKG

9.87 kBJavaScriptView Raw
1"use strict";
2
3Object.defineProperty(exports, "__esModule", {
4 value: true
5});
6exports.optimizeReactComponentTreeRoot = optimizeReactComponentTreeRoot;
7exports.applyOptimizedReactComponents = applyOptimizedReactComponents;
8
9var _realm = require("../realm.js");
10
11var _index = require("../values/index.js");
12
13var _utils = require("../serializer/utils.js");
14
15var _utils2 = require("./utils.js");
16
17var _types = require("../serializer/types.js");
18
19var _reconcilation = require("./reconcilation.js");
20
21var _errors = require("./errors.js");
22
23var _singletons = require("../singletons.js");
24
25var _index2 = require("../methods/index.js");
26
27var _invariant = _interopRequireDefault(require("../invariant.js"));
28
29var _logger = require("../utils/logger.js");
30
31function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
32
33/**
34 * Copyright (c) 2017-present, Facebook, Inc.
35 * All rights reserved.
36 *
37 * This source code is licensed under the BSD-style license found in the
38 * LICENSE file in the root directory of this source tree. An additional grant
39 * of patent rights can be found in the PATENTS file in the same directory.
40 */
41
42/* strict-local */
43function applyWriteEffectsForOptimizedComponent(realm, componentType, _effects, componentTreeState, evaluatedNode, writeEffects, environmentRecordIdAfterGlobalCode) {
44 let effects = _effects;
45 let additionalFunctionEffects = (0, _utils.createAdditionalEffects)(realm, effects, false, "ReactAdditionalFunctionEffects", environmentRecordIdAfterGlobalCode);
46
47 if (additionalFunctionEffects === null) {
48 throw new _errors.ReconcilerFatalError(`Failed to optimize React component tree for "${evaluatedNode.name}" due to an unsupported completion`, evaluatedNode);
49 }
50
51 effects = additionalFunctionEffects.effects;
52 let value = effects.result;
53
54 if (value === realm.intrinsics.undefined) {
55 // if we get undefined, then this component tree failed and a message was already logged
56 // in the reconciler
57 return;
58 }
59
60 if ((0, _utils2.valueIsClassComponent)(realm, componentType)) {
61 if (componentTreeState.status === "SIMPLE") {
62 // if the root component was a class and is now simple, we can convert it from a class
63 // component to a functional component
64 (0, _utils2.convertSimpleClassComponentToFunctionalComponent)(realm, componentType, additionalFunctionEffects);
65 (0, _utils2.normalizeFunctionalComponentParamaters)(componentType);
66 writeEffects.set(componentType, additionalFunctionEffects);
67 } else {
68 let prototype = (0, _index2.Get)(realm, componentType, "prototype");
69 (0, _invariant.default)(prototype instanceof _index.ObjectValue);
70 let renderMethod = (0, _index2.Get)(realm, prototype, "render");
71 (0, _invariant.default)(renderMethod instanceof _index.ECMAScriptSourceFunctionValue);
72 writeEffects.set(renderMethod, additionalFunctionEffects);
73 }
74 } else {
75 if (componentTreeState.status === "COMPLEX") {
76 (0, _utils2.convertFunctionalComponentToComplexClassComponent)(realm, componentType, componentTreeState.componentType, additionalFunctionEffects);
77 let prototype = (0, _index2.Get)(realm, componentType, "prototype");
78 (0, _invariant.default)(prototype instanceof _index.ObjectValue);
79 let renderMethod = (0, _index2.Get)(realm, prototype, "render");
80 (0, _invariant.default)(renderMethod instanceof _index.ECMAScriptSourceFunctionValue);
81 writeEffects.set(renderMethod, additionalFunctionEffects);
82 } else {
83 (0, _utils2.normalizeFunctionalComponentParamaters)(componentType);
84 writeEffects.set(componentType, additionalFunctionEffects);
85 }
86 } // apply contextTypes for legacy context
87
88
89 if (componentTreeState.contextTypes.size > 0) {
90 let contextTypes = new _index.ObjectValue(realm, realm.intrinsics.ObjectPrototype);
91 let noOpFunc = (0, _utils2.createNoopFunction)(realm);
92
93 for (let key of componentTreeState.contextTypes) {
94 _singletons.Properties.Set(realm, contextTypes, key, noOpFunc, true);
95 }
96
97 _singletons.Properties.Set(realm, componentType, "contextTypes", contextTypes, true);
98 }
99}
100
101function optimizeReactComponentTreeBranches(realm, reconciler, writeEffects, environmentRecordIdAfterGlobalCode, logger) {
102 if (realm.react.verbose && reconciler.branchedComponentTrees.length > 0) {
103 logger.logInformation(` Evaluating React component tree branches...`);
104 } // for now we just use abstract props/context, in the future we'll create a new branch with a new component
105 // that used the props/context. It will extend the original component and only have a render method
106
107
108 for (let _ref of reconciler.branchedComponentTrees) {
109 let {
110 rootValue: branchRootValue,
111 evaluatedNode
112 } = _ref;
113 let branchComponentType = (0, _utils2.getComponentTypeFromRootValue)(realm, branchRootValue);
114
115 if (branchComponentType === null) {
116 evaluatedNode.status = "UNKNOWN_TYPE";
117 continue;
118 } // so we don't process the same component multiple times (we might change this logic later)
119
120
121 if (reconciler.hasEvaluatedRootNode(branchComponentType, evaluatedNode)) {
122 continue;
123 }
124
125 reconciler.clearComponentTreeState();
126
127 if (realm.react.verbose) {
128 logger.logInformation(` Evaluating ${evaluatedNode.name} (branch)`);
129 }
130
131 let branchEffects = reconciler.resolveReactComponentTree(branchComponentType, null, null, evaluatedNode);
132
133 if (realm.react.verbose) {
134 logger.logInformation(` ✔ ${evaluatedNode.name} (branch)`);
135 }
136
137 let branchComponentTreeState = reconciler.componentTreeState;
138 applyWriteEffectsForOptimizedComponent(realm, branchComponentType, branchEffects, branchComponentTreeState, evaluatedNode, writeEffects, environmentRecordIdAfterGlobalCode);
139 }
140}
141
142function optimizeReactNestedClosures(realm, reconciler, writeEffects, environmentRecordIdAfterGlobalCode, logger) {
143 if (realm.react.verbose && reconciler.nestedOptimizedClosures.length > 0) {
144 logger.logInformation(` Evaluating nested closures...`);
145 }
146
147 for (let _ref2 of reconciler.nestedOptimizedClosures) {
148 let {
149 func,
150 evaluatedNode,
151 nestedEffects,
152 componentType,
153 context
154 } = _ref2;
155
156 if (reconciler.hasEvaluatedNestedClosure(func)) {
157 continue;
158 }
159
160 if (func instanceof _index.ECMAScriptSourceFunctionValue && reconciler.hasEvaluatedRootNode(func, evaluatedNode)) {
161 continue;
162 }
163
164 if (realm.react.verbose) {
165 logger.logInformation(` Evaluating function "${(0, _utils2.getComponentName)(realm, func)}"`);
166 }
167
168 let closureEffects = reconciler.resolveNestedOptimizedClosure(func, nestedEffects, componentType, context, evaluatedNode);
169
170 if (realm.react.verbose) {
171 logger.logInformation(` ✔ function "${(0, _utils2.getComponentName)(realm, func)}"`);
172 }
173
174 let additionalFunctionEffects = (0, _utils.createAdditionalEffects)(realm, closureEffects, true, "ReactNestedAdditionalFunctionEffects", environmentRecordIdAfterGlobalCode);
175 (0, _invariant.default)(additionalFunctionEffects);
176
177 if (func instanceof _index.BoundFunctionValue) {
178 (0, _invariant.default)(func.$BoundTargetFunction instanceof _index.ECMAScriptSourceFunctionValue);
179 writeEffects.set(func.$BoundTargetFunction, additionalFunctionEffects);
180 } else {
181 writeEffects.set(func, additionalFunctionEffects);
182 }
183 }
184}
185
186function optimizeReactComponentTreeRoot(realm, componentRoot, config, writeEffects, environmentRecordIdAfterGlobalCode, logger, statistics) {
187 let reconciler = new _reconcilation.Reconciler(realm, config, statistics, logger);
188 let componentType = (0, _utils2.getComponentTypeFromRootValue)(realm, componentRoot);
189
190 if (componentType === null) {
191 return;
192 }
193
194 let evaluatedRootNode = (0, _utils2.createReactEvaluatedNode)("ROOT", (0, _utils2.getComponentName)(realm, componentType));
195 statistics.evaluatedRootNodes.push(evaluatedRootNode);
196
197 if (reconciler.hasEvaluatedRootNode(componentType, evaluatedRootNode)) {
198 return;
199 }
200
201 if (realm.react.verbose) {
202 logger.logInformation(` Evaluating ${evaluatedRootNode.name} (root)`);
203 }
204
205 let componentTreeEffects = reconciler.resolveReactComponentTree(componentType, null, null, evaluatedRootNode);
206
207 if (realm.react.verbose) {
208 logger.logInformation(` ✔ ${evaluatedRootNode.name} (root)`);
209 }
210
211 applyWriteEffectsForOptimizedComponent(realm, componentType, componentTreeEffects, reconciler.componentTreeState, evaluatedRootNode, writeEffects, environmentRecordIdAfterGlobalCode);
212 let startingComponentTreeBranches = 0;
213
214 do {
215 startingComponentTreeBranches = reconciler.branchedComponentTrees.length;
216 optimizeReactComponentTreeBranches(realm, reconciler, writeEffects, environmentRecordIdAfterGlobalCode, logger);
217
218 if (realm.react.optimizeNestedFunctions) {
219 optimizeReactNestedClosures(realm, reconciler, writeEffects, environmentRecordIdAfterGlobalCode, logger);
220 }
221 } while (startingComponentTreeBranches !== reconciler.branchedComponentTrees.length);
222}
223
224function applyOptimizedReactComponents(realm, writeEffects, environmentRecordIdAfterGlobalCode) {
225 for (let _ref3 of realm.react.optimizedNestedClosuresToWrite) {
226 let {
227 effects,
228 func
229 } = _ref3;
230 let additionalFunctionEffects = (0, _utils.createAdditionalEffects)(realm, effects, true, "ReactNestedAdditionalFunctionEffects", environmentRecordIdAfterGlobalCode);
231 (0, _invariant.default)(additionalFunctionEffects);
232
233 if (func instanceof _index.BoundFunctionValue) {
234 (0, _invariant.default)(func.$BoundTargetFunction instanceof _index.ECMAScriptSourceFunctionValue);
235 writeEffects.set(func.$BoundTargetFunction, additionalFunctionEffects);
236 } else {
237 writeEffects.set(func, additionalFunctionEffects);
238 }
239 }
240}
241//# sourceMappingURL=optimizing.js.map
\No newline at end of file