UNPKG

17.6 kBJavaScriptView Raw
1"use strict";
2
3Object.defineProperty(exports, "__esModule", {
4 value: true
5});
6exports.cloneReactElement = cloneReactElement;
7exports.createReactElement = createReactElement;
8exports.traverseReactElement = traverseReactElement;
9
10var _index = require("../domains/index.js");
11
12var _index2 = require("../values/index.js");
13
14var _singletons = require("../singletons.js");
15
16var _invariant = _interopRequireDefault(require("../invariant.js"));
17
18var _index3 = require("../methods/index.js");
19
20var _utils = require("./utils.js");
21
22var _BinaryExpression = require("../evaluators/BinaryExpression.js");
23
24var _errors = require("../errors.js");
25
26var _generator = require("../utils/generator.js");
27
28function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
29
30/**
31 * Copyright (c) 2017-present, Facebook, Inc.
32 * All rights reserved.
33 *
34 * This source code is licensed under the BSD-style license found in the
35 * LICENSE file in the root directory of this source tree. An additional grant
36 * of patent rights can be found in the PATENTS file in the same directory.
37 */
38function createPropsObject(realm, type, config, children) {
39 // If we're in "rendering" a React component tree, we should have an active reconciler
40 let activeReconciler = realm.react.activeReconciler;
41 let firstRenderOnly = activeReconciler !== undefined ? activeReconciler.componentTreeConfig.firstRenderOnly : false;
42 let defaultProps = type instanceof _index2.ObjectValue || type instanceof _index2.AbstractObjectValue ? (0, _index3.Get)(realm, type, "defaultProps") : realm.intrinsics.undefined;
43
44 let props = _singletons.Create.ObjectCreate(realm, realm.intrinsics.ObjectPrototype);
45
46 props.makeFinal();
47 realm.react.reactProps.add(props);
48 let key = realm.intrinsics.null;
49 let ref = realm.intrinsics.null;
50
51 if (!(0, _utils.hasNoPartialKeyOrRef)(realm, config)) {
52 // if either are abstract, this will impact the reconcilation process
53 // and ultimately prevent us from folding ReactElements properly
54 let diagnostic = new _errors.CompilerDiagnostic(`unable to evaluate "key" and "ref" on a ReactElement due to an abstract config passed to createElement`, realm.currentLocation, "PP0025", "FatalError");
55 realm.handleError(diagnostic);
56 if (realm.handleError(diagnostic) === "Fail") throw new _errors.FatalError();
57 }
58
59 let possibleKey = (0, _index3.Get)(realm, config, "key");
60
61 if (possibleKey !== realm.intrinsics.null && possibleKey !== realm.intrinsics.undefined) {
62 // if the config has been marked as having no partial key or ref and the possible key
63 // is abstract, yet the config doesn't have a key property, then the key can remain null
64 let keyNotNeeded = (0, _utils.hasNoPartialKeyOrRef)(realm, config) && possibleKey instanceof _index2.AbstractValue && config instanceof _index2.ObjectValue && !config.properties.has("key");
65
66 if (!keyNotNeeded) {
67 key = (0, _BinaryExpression.computeBinary)(realm, "+", realm.intrinsics.emptyString, possibleKey);
68 }
69 }
70
71 let possibleRef = (0, _index3.Get)(realm, config, "ref");
72
73 if (possibleRef !== realm.intrinsics.null && possibleRef !== realm.intrinsics.undefined && !firstRenderOnly) {
74 // if the config has been marked as having no partial key or ref and the possible ref
75 // is abstract, yet the config doesn't have a ref property, then the ref can remain null
76 let refNotNeeded = (0, _utils.hasNoPartialKeyOrRef)(realm, config) && possibleRef instanceof _index2.AbstractValue && config instanceof _index2.ObjectValue && !config.properties.has("ref");
77
78 if (!refNotNeeded) {
79 ref = possibleRef;
80 }
81 }
82
83 const setProp = (name, value) => {
84 if (name !== "__self" && name !== "__source" && name !== "key" && name !== "ref") {
85 (0, _invariant.default)(props instanceof _index2.ObjectValue);
86 (0, _utils.hardModifyReactObjectPropertyBinding)(realm, props, name, value);
87 }
88 };
89
90 const applyProperties = () => {
91 if (config instanceof _index2.ObjectValue) {
92 for (let [propKey, binding] of config.properties) {
93 if (binding && binding.descriptor && binding.descriptor.enumerable) {
94 setProp(propKey, (0, _index3.Get)(realm, config, propKey));
95 }
96 }
97 }
98 };
99
100 if (config instanceof _index2.AbstractObjectValue && config.isPartialObject() || config instanceof _index2.ObjectValue && config.isPartialObject() && config.isSimpleObject()) {
101 // create a new props object that will be the target of the Object.assign
102 props = _singletons.Create.ObjectCreate(realm, realm.intrinsics.ObjectPrototype);
103 realm.react.reactProps.add(props);
104 (0, _utils.applyObjectAssignConfigsForReactElement)(realm, props, [config]);
105 props.makeFinal();
106
107 if (children !== undefined) {
108 (0, _utils.hardModifyReactObjectPropertyBinding)(realm, props, "children", children);
109 } // handle default props on a partial/abstract config
110
111
112 if (defaultProps !== realm.intrinsics.undefined) {
113 let defaultPropsEvaluated = 0; // first see if we can apply all the defaultProps without needing the helper
114
115 if (defaultProps instanceof _index2.ObjectValue && !defaultProps.isPartialObject()) {
116 for (let [propName, binding] of defaultProps.properties) {
117 if (binding.descriptor !== undefined && binding.descriptor.value !== realm.intrinsics.undefined) {
118 // see if we have this on our props object
119 let propBinding = props.properties.get(propName); // if the binding exists and value is abstract, it might be undefined
120 // so in that case we need the helper, otherwise we can continue
121
122 if (propBinding !== undefined && !(propBinding.descriptor && propBinding.descriptor.value instanceof _index2.AbstractValue)) {
123 defaultPropsEvaluated++; // if the value we have is undefined, we can apply the defaultProp
124
125 if (propBinding.descriptor && propBinding.descriptor.value === realm.intrinsics.undefined) {
126 (0, _utils.hardModifyReactObjectPropertyBinding)(realm, props, propName, (0, _index3.Get)(realm, defaultProps, propName));
127 }
128 }
129 }
130 }
131 } // if defaultPropsEvaluated === the amount of properties defaultProps has, then we've successfully
132 // ensured all the defaultProps have already been dealt with, so we don't need the helper
133
134
135 if (!(defaultProps instanceof _index2.ObjectValue) || defaultProps.isPartialObject() || defaultPropsEvaluated !== defaultProps.properties.size) {
136 props.makePartial();
137 props.makeSimple(); // if the props has any properties that are "undefined", we need to make them abstract
138 // as the helper function applies defaultProps on values that are undefined or do not
139 // exist
140
141 for (let [propName, binding] of props.properties) {
142 if (binding.descriptor !== undefined && binding.descriptor.value === realm.intrinsics.undefined) {
143 (0, _utils.hardModifyReactObjectPropertyBinding)(realm, props, propName, _index2.AbstractValue.createFromType(realm, _index2.Value));
144 }
145 } // if we have children and they are abstract, they might be undefined at runtime
146
147
148 if (children !== undefined && children instanceof _index2.AbstractValue) {
149 // children === undefined ? defaultProps.children : children;
150 let condition = _index2.AbstractValue.createFromBinaryOp(realm, "===", children, realm.intrinsics.undefined);
151
152 (0, _invariant.default)(defaultProps instanceof _index2.AbstractObjectValue || defaultProps instanceof _index2.ObjectValue);
153
154 let conditionalChildren = _index2.AbstractValue.createFromConditionalOp(realm, condition, (0, _index3.Get)(realm, defaultProps, "children"), children);
155
156 (0, _utils.hardModifyReactObjectPropertyBinding)(realm, props, "children", conditionalChildren);
157 }
158
159 let defaultPropsHelper = realm.react.defaultPropsHelper;
160 (0, _invariant.default)(defaultPropsHelper !== undefined);
161 let snapshot = props.getSnapshot();
162 props.temporalAlias = snapshot;
163 let temporalArgs = [defaultPropsHelper, snapshot, defaultProps];
164
165 let temporalTo = _index2.AbstractValue.createTemporalFromBuildFunction(realm, _index2.ObjectValue, temporalArgs, (0, _generator.createOperationDescriptor)("REACT_DEFAULT_PROPS_HELPER"), {
166 skipInvariant: true
167 });
168
169 (0, _invariant.default)(temporalTo instanceof _index2.AbstractObjectValue);
170
171 if (props instanceof _index2.AbstractObjectValue) {
172 temporalTo.values = props.values;
173 } else {
174 (0, _invariant.default)(props instanceof _index2.ObjectValue);
175 temporalTo.values = new _index.ValuesDomain(props);
176 }
177
178 props.temporalAlias = temporalTo;
179 }
180 }
181 } else {
182 applyProperties();
183
184 if (children !== undefined) {
185 setProp("children", children);
186 }
187
188 if (defaultProps instanceof _index2.ObjectValue) {
189 for (let [propKey, binding] of defaultProps.properties) {
190 if (binding && binding.descriptor && binding.descriptor.enumerable) {
191 if ((0, _index3.Get)(realm, props, propKey) === realm.intrinsics.undefined) {
192 setProp(propKey, (0, _index3.Get)(realm, defaultProps, propKey));
193 }
194 }
195 }
196 } else if (defaultProps instanceof _index2.AbstractObjectValue) {
197 (0, _invariant.default)(false, "TODO: we need to eventually support this");
198 }
199 }
200
201 (0, _invariant.default)(props instanceof _index2.ObjectValue); // We know the props has no keys because if it did it would have thrown above
202 // so we can remove them the props we create.
203
204 (0, _utils.flagPropsWithNoPartialKeyOrRef)(realm, props);
205 return {
206 key,
207 props,
208 ref
209 };
210}
211
212function splitReactElementsByConditionalType(realm, condValue, consequentVal, alternateVal, config, children) {
213 return realm.evaluateWithAbstractConditional(condValue, () => {
214 return realm.evaluateForEffects(() => createReactElement(realm, consequentVal, config, children), null, "splitReactElementsByConditionalType consequent");
215 }, () => {
216 return realm.evaluateForEffects(() => createReactElement(realm, alternateVal, config, children), null, "splitReactElementsByConditionalType alternate");
217 });
218}
219
220function splitReactElementsByConditionalConfig(realm, condValue, consequentVal, alternateVal, type, children) {
221 return realm.evaluateWithAbstractConditional(condValue, () => {
222 return realm.evaluateForEffects(() => createReactElement(realm, type, consequentVal, children), null, "splitReactElementsByConditionalConfig consequent");
223 }, () => {
224 return realm.evaluateForEffects(() => createReactElement(realm, type, alternateVal, children), null, "splitReactElementsByConditionalConfig alternate");
225 });
226}
227
228function cloneReactElement(realm, reactElement, config, children) {
229 let props = _singletons.Create.ObjectCreate(realm, realm.intrinsics.ObjectPrototype);
230
231 realm.react.reactProps.add(props);
232
233 const setProp = (name, value) => {
234 if (name !== "__self" && name !== "__source" && name !== "key" && name !== "ref") {
235 (0, _invariant.default)(props instanceof _index2.ObjectValue);
236 (0, _utils.hardModifyReactObjectPropertyBinding)(realm, props, name, value);
237 }
238 };
239
240 (0, _utils.applyObjectAssignConfigsForReactElement)(realm, props, [config]);
241 props.makeFinal();
242 let key = (0, _utils.getProperty)(realm, reactElement, "key");
243 let ref = (0, _utils.getProperty)(realm, reactElement, "ref");
244 let type = (0, _utils.getProperty)(realm, reactElement, "type");
245
246 if (!(config instanceof _index2.NullValue)) {
247 let possibleKey = (0, _index3.Get)(realm, config, "key");
248
249 if (possibleKey !== realm.intrinsics.null && possibleKey !== realm.intrinsics.undefined) {
250 // if the config has been marked as having no partial key or ref and the possible key
251 // is abstract, yet the config doesn't have a key property, then the key can remain null
252 let keyNotNeeded = (0, _utils.hasNoPartialKeyOrRef)(realm, config) && possibleKey instanceof _index2.AbstractValue && config instanceof _index2.ObjectValue && !config.properties.has("key");
253
254 if (!keyNotNeeded) {
255 key = (0, _BinaryExpression.computeBinary)(realm, "+", realm.intrinsics.emptyString, possibleKey);
256 }
257 }
258
259 let possibleRef = (0, _index3.Get)(realm, config, "ref");
260
261 if (possibleRef !== realm.intrinsics.null && possibleRef !== realm.intrinsics.undefined) {
262 // if the config has been marked as having no partial key or ref and the possible ref
263 // is abstract, yet the config doesn't have a ref property, then the ref can remain null
264 let refNotNeeded = (0, _utils.hasNoPartialKeyOrRef)(realm, config) && possibleRef instanceof _index2.AbstractValue && config instanceof _index2.ObjectValue && !config.properties.has("ref");
265
266 if (!refNotNeeded) {
267 ref = possibleRef;
268 }
269 }
270
271 let defaultProps = type instanceof _index2.ObjectValue || type instanceof _index2.AbstractObjectValue ? (0, _index3.Get)(realm, type, "defaultProps") : realm.intrinsics.undefined;
272
273 if (defaultProps instanceof _index2.ObjectValue) {
274 for (let [propKey, binding] of defaultProps.properties) {
275 if (binding && binding.descriptor && binding.descriptor.enumerable) {
276 if ((0, _index3.Get)(realm, props, propKey) === realm.intrinsics.undefined) {
277 setProp(propKey, (0, _index3.Get)(realm, defaultProps, propKey));
278 }
279 }
280 }
281 } else if (defaultProps instanceof _index2.AbstractObjectValue) {
282 (0, _invariant.default)(false, "TODO: we need to eventually support this");
283 }
284 }
285
286 if (children !== undefined) {
287 (0, _utils.hardModifyReactObjectPropertyBinding)(realm, props, "children", children);
288 } else {
289 let elementProps = (0, _utils.getProperty)(realm, reactElement, "props");
290 (0, _invariant.default)(elementProps instanceof _index2.ObjectValue);
291 let elementChildren = (0, _utils.getProperty)(realm, elementProps, "children");
292 (0, _utils.hardModifyReactObjectPropertyBinding)(realm, props, "children", elementChildren);
293 }
294
295 return (0, _utils.createInternalReactElement)(realm, type, key, ref, props);
296}
297
298function createReactElement(realm, type, config, children) {
299 if (type instanceof _index2.AbstractValue && type.kind === "conditional") {
300 let [condValue, consequentVal, alternateVal] = type.args;
301 (0, _invariant.default)(condValue instanceof _index2.AbstractValue);
302 return splitReactElementsByConditionalType(realm, condValue, consequentVal, alternateVal, config, children);
303 } else if (config instanceof _index2.AbstractObjectValue && config.kind === "conditional") {
304 let [condValue, consequentVal, alternateVal] = config.args;
305 (0, _invariant.default)(condValue instanceof _index2.AbstractValue);
306 (0, _invariant.default)(consequentVal instanceof _index2.ObjectValue || consequentVal instanceof _index2.AbstractObjectValue);
307 (0, _invariant.default)(alternateVal instanceof _index2.ObjectValue || alternateVal instanceof _index2.AbstractObjectValue);
308 return splitReactElementsByConditionalConfig(realm, condValue, consequentVal, alternateVal, type, children);
309 }
310
311 let {
312 key,
313 props,
314 ref
315 } = createPropsObject(realm, type, config, children);
316 return (0, _utils.createInternalReactElement)(realm, type, key, ref, props);
317}
318
319function traverseReactElement(realm, reactElement, traversalVisitor) {
320 let typeValue = (0, _utils.getProperty)(realm, reactElement, "type");
321 traversalVisitor.visitType(typeValue);
322 let keyValue = (0, _utils.getProperty)(realm, reactElement, "key");
323
324 if (keyValue !== realm.intrinsics.null && keyValue !== realm.intrinsics.undefined) {
325 traversalVisitor.visitKey(keyValue);
326 }
327
328 let refValue = (0, _utils.getProperty)(realm, reactElement, "ref");
329
330 if (refValue !== realm.intrinsics.null && refValue !== realm.intrinsics.undefined) {
331 traversalVisitor.visitRef(refValue);
332 }
333
334 const handleChildren = () => {
335 // handle children
336 (0, _invariant.default)(propsValue instanceof _index2.ObjectValue);
337
338 if (propsValue.properties.has("children")) {
339 let childrenValue = (0, _utils.getProperty)(realm, propsValue, "children");
340
341 if (childrenValue !== realm.intrinsics.undefined && childrenValue !== realm.intrinsics.null) {
342 if (childrenValue instanceof _index2.ArrayValue && !childrenValue.intrinsicName) {
343 let childrenLength = (0, _utils.getProperty)(realm, childrenValue, "length");
344 let childrenLengthValue = 0;
345
346 if (childrenLength instanceof _index2.NumberValue) {
347 childrenLengthValue = childrenLength.value;
348
349 for (let i = 0; i < childrenLengthValue; i++) {
350 let child = (0, _utils.getProperty)(realm, childrenValue, "" + i);
351 traversalVisitor.visitChildNode(child);
352 }
353 }
354 } else {
355 traversalVisitor.visitChildNode(childrenValue);
356 }
357 }
358 }
359 };
360
361 let propsValue = (0, _utils.getProperty)(realm, reactElement, "props");
362
363 if (propsValue instanceof _index2.AbstractValue) {
364 // visit object, as it's going to be spread
365 traversalVisitor.visitAbstractOrPartialProps(propsValue);
366 } else if (propsValue instanceof _index2.ObjectValue) {
367 if (propsValue.isPartialObject()) {
368 traversalVisitor.visitAbstractOrPartialProps(propsValue);
369 handleChildren();
370 } else {
371 traversalVisitor.visitConcreteProps(propsValue);
372 handleChildren();
373 }
374 }
375}
376//# sourceMappingURL=elements.js.map
\No newline at end of file