1 | "use strict";
|
2 |
|
3 | Object.defineProperty(exports, "__esModule", {
|
4 | value: true
|
5 | });
|
6 | exports.getInitialProps = getInitialProps;
|
7 | exports.getInitialContext = getInitialContext;
|
8 | exports.createSimpleClassInstance = createSimpleClassInstance;
|
9 | exports.createClassInstanceForFirstRenderOnly = createClassInstanceForFirstRenderOnly;
|
10 | exports.createClassInstance = createClassInstance;
|
11 | exports.evaluateClassConstructor = evaluateClassConstructor;
|
12 | exports.applyGetDerivedStateFromProps = applyGetDerivedStateFromProps;
|
13 |
|
14 | var _realm = require("../realm.js");
|
15 |
|
16 | var _index = require("../values/index.js");
|
17 |
|
18 | var t = _interopRequireWildcard(require("@babel/types"));
|
19 |
|
20 | var _utils = require("./utils.js");
|
21 |
|
22 | var _errors = require("./errors.js");
|
23 |
|
24 | var _index2 = require("../methods/index.js");
|
25 |
|
26 | var _singletons = require("../singletons.js");
|
27 |
|
28 | var _invariant = _interopRequireDefault(require("../invariant.js"));
|
29 |
|
30 | var _traverse = _interopRequireDefault(require("@babel/traverse"));
|
31 |
|
32 | var _errors2 = require("../errors.js");
|
33 |
|
34 | var _ShapeInformation = require("../utils/ShapeInformation.js");
|
35 |
|
36 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
37 |
|
38 | function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = Object.defineProperty && Object.getOwnPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : {}; if (desc.get || desc.set) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } } newObj.default = obj; return newObj; } }
|
39 |
|
40 |
|
41 |
|
42 |
|
43 |
|
44 |
|
45 |
|
46 |
|
47 |
|
48 | const lifecycleMethods = new Set(["componentWillUnmount", "componentDidMount", "componentWillMount", "componentDidUpdate", "componentWillUpdate", "componentDidCatch", "componentWillReceiveProps"]);
|
49 | const whitelistedProperties = new Set(["props", "context", "refs", "setState"]);
|
50 |
|
51 | function getInitialProps(realm, componentType, {
|
52 | modelString
|
53 | }) {
|
54 | let componentModel = modelString !== undefined ? JSON.parse(modelString) : undefined;
|
55 |
|
56 | let shape = _ShapeInformation.ShapeInformation.createForReactComponentProps(componentModel);
|
57 |
|
58 | let propsName = null;
|
59 |
|
60 | if (componentType !== null) {
|
61 | if ((0, _utils.valueIsClassComponent)(realm, componentType)) {
|
62 | propsName = "this.props";
|
63 | } else {
|
64 |
|
65 | if (componentType.$FormalParameters.length > 0) {
|
66 | let firstParam = componentType.$FormalParameters[0];
|
67 |
|
68 | if (t.isIdentifier(firstParam)) {
|
69 | propsName = firstParam.name;
|
70 | }
|
71 | }
|
72 | }
|
73 | }
|
74 |
|
75 | let abstractPropsObject = _index.AbstractValue.createAbstractObject(realm, propsName || "props", shape);
|
76 |
|
77 | (0, _invariant.default)(abstractPropsObject instanceof _index.AbstractObjectValue);
|
78 | (0, _utils.flagPropsWithNoPartialKeyOrRef)(realm, abstractPropsObject);
|
79 | abstractPropsObject.makeFinal();
|
80 | return abstractPropsObject;
|
81 | }
|
82 |
|
83 | function getInitialContext(realm, componentType) {
|
84 | let contextName = null;
|
85 |
|
86 | if ((0, _utils.valueIsClassComponent)(realm, componentType)) {
|
87 |
|
88 | let superTypeParameters = componentType.$SuperTypeParameters;
|
89 | contextName = "this.context";
|
90 |
|
91 | if (superTypeParameters !== undefined) {
|
92 | throw new _errors.ExpectedBailOut("context on class components not yet supported");
|
93 | }
|
94 | } else {
|
95 |
|
96 | if (componentType.$FormalParameters.length > 1) {
|
97 | let secondParam = componentType.$FormalParameters[1];
|
98 |
|
99 | if (t.isIdentifier(secondParam)) {
|
100 | contextName = secondParam.name;
|
101 | }
|
102 | }
|
103 | }
|
104 |
|
105 | let value = _index.AbstractValue.createAbstractObject(realm, contextName || "context");
|
106 |
|
107 | return value;
|
108 | }
|
109 |
|
110 | function visitClassMethodAstForThisUsage(realm, method) {
|
111 | let formalParameters = method.$FormalParameters;
|
112 | let code = method.$ECMAScriptCode;
|
113 | (0, _traverse.default)(t.file(t.program([t.expressionStatement(t.functionExpression(null, formalParameters, code))])), {
|
114 | ThisExpression(path) {
|
115 | let parentNode = path.parentPath.node;
|
116 |
|
117 | if (!t.isMemberExpression(parentNode)) {
|
118 | throw new _errors.SimpleClassBailOut(`possible leakage of independent "this" reference found`);
|
119 | }
|
120 | }
|
121 |
|
122 | }, null, {});
|
123 | }
|
124 |
|
125 | function createSimpleClassInstance(realm, componentType, props, context) {
|
126 | let componentPrototype = (0, _index2.Get)(realm, componentType, "prototype");
|
127 | (0, _invariant.default)(componentPrototype instanceof _index.ObjectValue);
|
128 |
|
129 | let instance = new _index.ObjectValue(realm, componentPrototype, "this", true);
|
130 | let allowedPropertyAccess = new Set(["props", "context"]);
|
131 |
|
132 | for (let [name] of componentPrototype.properties) {
|
133 | if (lifecycleMethods.has(name)) {
|
134 |
|
135 | throw new _errors.SimpleClassBailOut("lifecycle methods are not supported on simple classes");
|
136 | } else if (name !== "constructor") {
|
137 | allowedPropertyAccess.add(name);
|
138 | let method = (0, _index2.Get)(realm, componentPrototype, name);
|
139 |
|
140 | if (method instanceof _index.ECMAScriptSourceFunctionValue) {
|
141 | visitClassMethodAstForThisUsage(realm, method);
|
142 | }
|
143 |
|
144 | _singletons.Properties.Set(realm, instance, name, method, true);
|
145 | }
|
146 | }
|
147 |
|
148 |
|
149 | _singletons.Properties.Set(realm, instance, "props", props, true);
|
150 |
|
151 |
|
152 | _singletons.Properties.Set(realm, instance, "context", context, true);
|
153 |
|
154 |
|
155 |
|
156 | let $GetOwnProperty = instance.$GetOwnProperty;
|
157 |
|
158 | instance.$GetOwnProperty = P => {
|
159 | if (!allowedPropertyAccess.has(P)) {
|
160 |
|
161 | throw new _errors.SimpleClassBailOut("access to basic class instance properties is not supported on simple classes");
|
162 | }
|
163 |
|
164 | return $GetOwnProperty.call(instance, P);
|
165 | };
|
166 |
|
167 |
|
168 | instance.refuseSerialization = false;
|
169 |
|
170 | return instance;
|
171 | }
|
172 |
|
173 | function deeplyApplyInstancePrototypeProperties(realm, instance, componentPrototype, classMetadata) {
|
174 | let {
|
175 | instanceProperties,
|
176 | instanceSymbols
|
177 | } = classMetadata;
|
178 | let proto = componentPrototype.$Prototype;
|
179 |
|
180 | if (proto instanceof _index.ObjectValue && proto !== realm.intrinsics.ObjectPrototype) {
|
181 | deeplyApplyInstancePrototypeProperties(realm, instance, proto, classMetadata);
|
182 | }
|
183 |
|
184 | for (let [name] of componentPrototype.properties) {
|
185 |
|
186 | if (name !== "constructor" && !instanceProperties.has(name)) {
|
187 | _singletons.Properties.Set(realm, instance, name, (0, _index2.Get)(realm, componentPrototype, name), true);
|
188 | }
|
189 | }
|
190 |
|
191 | for (let [symbol] of componentPrototype.symbols) {
|
192 |
|
193 | if (!instanceSymbols.has(symbol)) {
|
194 | _singletons.Properties.Set(realm, instance, symbol, (0, _index2.Get)(realm, componentPrototype, symbol), true);
|
195 | }
|
196 | }
|
197 | }
|
198 |
|
199 | function createClassInstanceForFirstRenderOnly(realm, componentType, props, context, evaluatedNode) {
|
200 | let instance = (0, _utils.getValueFromFunctionCall)(realm, componentType, realm.intrinsics.undefined, [props, context], true);
|
201 | let objectAssign = (0, _index2.Get)(realm, realm.intrinsics.Object, "assign");
|
202 | (0, _invariant.default)(objectAssign instanceof _index.ECMAScriptFunctionValue);
|
203 | let objectAssignCall = objectAssign.$Call;
|
204 | (0, _invariant.default)(objectAssignCall !== undefined);
|
205 | (0, _invariant.default)(instance instanceof _index.ObjectValue);
|
206 | instance.refuseSerialization = true;
|
207 |
|
208 | _singletons.Properties.Set(realm, instance, "props", props, true);
|
209 |
|
210 |
|
211 | _singletons.Properties.Set(realm, instance, "context", context, true);
|
212 |
|
213 | let state = (0, _index2.Get)(realm, instance, "state");
|
214 |
|
215 | if (state instanceof _index.AbstractObjectValue || state instanceof _index.ObjectValue) {
|
216 | state.makeFinal();
|
217 | }
|
218 |
|
219 |
|
220 | let setState = new _index.NativeFunctionValue(realm, undefined, `setState`, 1, (_context, [stateToUpdate, callback]) => {
|
221 | (0, _invariant.default)(instance instanceof _index.ObjectValue);
|
222 | let prevState = (0, _index2.Get)(realm, instance, "state");
|
223 | (0, _invariant.default)(prevState instanceof _index.ObjectValue);
|
224 |
|
225 | if (stateToUpdate instanceof _index.ECMAScriptSourceFunctionValue && stateToUpdate.$Call) {
|
226 | stateToUpdate = stateToUpdate.$Call(instance, [prevState]);
|
227 | }
|
228 |
|
229 | if (stateToUpdate instanceof _index.ObjectValue) {
|
230 | let newState = new _index.ObjectValue(realm, realm.intrinsics.ObjectPrototype);
|
231 | objectAssignCall(realm.intrinsics.undefined, [newState, prevState]);
|
232 | newState.makeFinal();
|
233 |
|
234 | for (let [key, binding] of stateToUpdate.properties) {
|
235 | if (binding && binding.descriptor && binding.descriptor.enumerable) {
|
236 | let value = (0, _utils.getProperty)(realm, stateToUpdate, key);
|
237 | (0, _utils.hardModifyReactObjectPropertyBinding)(realm, newState, key, value);
|
238 | }
|
239 | }
|
240 |
|
241 | _singletons.Properties.Set(realm, instance, "state", newState, true);
|
242 | }
|
243 |
|
244 | if (callback instanceof _index.ECMAScriptSourceFunctionValue && callback.$Call) {
|
245 | callback.$Call(instance, []);
|
246 | }
|
247 |
|
248 | return realm.intrinsics.undefined;
|
249 | });
|
250 | setState.intrinsicName = "(function() {})";
|
251 |
|
252 | _singletons.Properties.Set(realm, instance, "setState", setState, true);
|
253 |
|
254 | instance.refuseSerialization = false;
|
255 | return instance;
|
256 | }
|
257 |
|
258 | function createClassInstance(realm, componentType, props, context, classMetadata) {
|
259 | let componentPrototype = (0, _index2.Get)(realm, componentType, "prototype");
|
260 | (0, _invariant.default)(componentPrototype instanceof _index.ObjectValue);
|
261 |
|
262 | let instance = new _index.ObjectValue(realm, componentPrototype, "this", true);
|
263 | deeplyApplyInstancePrototypeProperties(realm, instance, componentPrototype, classMetadata);
|
264 |
|
265 | _singletons.Properties.Set(realm, instance, "refs", _index.AbstractValue.createAbstractObject(realm, "this.refs"), true);
|
266 |
|
267 |
|
268 | _singletons.Properties.Set(realm, instance, "props", props, true);
|
269 |
|
270 |
|
271 | _singletons.Properties.Set(realm, instance, "context", context, true);
|
272 |
|
273 |
|
274 | instance.refuseSerialization = false;
|
275 |
|
276 | let value = _index.AbstractValue.createAbstractObject(realm, "this", instance);
|
277 |
|
278 | (0, _invariant.default)(value instanceof _index.AbstractObjectValue);
|
279 | return value;
|
280 | }
|
281 |
|
282 | function evaluateClassConstructor(realm, constructorFunc, props, context) {
|
283 | let instanceProperties = new Set();
|
284 | let instanceSymbols = new Set();
|
285 | realm.evaluatePure(() => realm.evaluateForEffects(() => {
|
286 | let instance = (0, _index2.Construct)(realm, constructorFunc, [props, context]);
|
287 | (0, _invariant.default)(instance instanceof _index.ObjectValue);
|
288 |
|
289 | for (let [propertyName] of instance.properties) {
|
290 | if (!whitelistedProperties.has(propertyName)) {
|
291 | instanceProperties.add(propertyName);
|
292 | }
|
293 | }
|
294 |
|
295 | for (let [symbol] of instance.symbols) {
|
296 | instanceSymbols.add(symbol);
|
297 | }
|
298 |
|
299 | return instance;
|
300 | },
|
301 |
|
302 | null, `react component constructor: ${constructorFunc.getName()}`),
|
303 |
|
304 | null);
|
305 | return {
|
306 | instanceProperties,
|
307 | instanceSymbols
|
308 | };
|
309 | }
|
310 |
|
311 | function applyGetDerivedStateFromProps(realm, getDerivedStateFromProps, instance, props) {
|
312 | let prevState = (0, _index2.Get)(realm, instance, "state");
|
313 | let getDerivedStateFromPropsCall = getDerivedStateFromProps.$Call;
|
314 | (0, _invariant.default)(getDerivedStateFromPropsCall !== undefined);
|
315 | let partialState = getDerivedStateFromPropsCall(realm.intrinsics.null, [props, prevState]);
|
316 |
|
317 | const deriveState = state => {
|
318 | let objectAssign = (0, _index2.Get)(realm, realm.intrinsics.Object, "assign");
|
319 | (0, _invariant.default)(objectAssign instanceof _index.ECMAScriptFunctionValue);
|
320 | let objectAssignCall = objectAssign.$Call;
|
321 | (0, _invariant.default)(objectAssignCall !== undefined);
|
322 |
|
323 | if (state instanceof _index.AbstractValue && !(state instanceof _index.AbstractObjectValue)) {
|
324 | const kind = state.kind;
|
325 |
|
326 | if (kind === "conditional") {
|
327 | let condition = state.args[0];
|
328 | let a = deriveState(state.args[1]);
|
329 | let b = deriveState(state.args[2]);
|
330 | (0, _invariant.default)(condition instanceof _index.AbstractValue);
|
331 |
|
332 | if (a === null && b === null) {
|
333 | return null;
|
334 | } else if (a === null) {
|
335 | (0, _invariant.default)(b instanceof _index.Value);
|
336 | return _index.AbstractValue.createFromConditionalOp(realm, condition, realm.intrinsics.false, b);
|
337 | } else if (b === null) {
|
338 | (0, _invariant.default)(a instanceof _index.Value);
|
339 | return _index.AbstractValue.createFromConditionalOp(realm, condition, a, realm.intrinsics.false);
|
340 | } else {
|
341 | (0, _invariant.default)(a instanceof _index.Value);
|
342 | (0, _invariant.default)(b instanceof _index.Value);
|
343 | return _index.AbstractValue.createFromConditionalOp(realm, condition, a, b);
|
344 | }
|
345 | } else if (kind === "||" || kind === "&&") {
|
346 | let a = deriveState(state.args[0]);
|
347 | let b = deriveState(state.args[1]);
|
348 |
|
349 | if (b === null) {
|
350 | (0, _invariant.default)(a instanceof _index.Value);
|
351 | return _index.AbstractValue.createFromLogicalOp(realm, kind, a, realm.intrinsics.false);
|
352 | } else {
|
353 | (0, _invariant.default)(a instanceof _index.Value);
|
354 | (0, _invariant.default)(b instanceof _index.Value);
|
355 | return _index.AbstractValue.createFromLogicalOp(realm, kind, a, b);
|
356 | }
|
357 | } else {
|
358 | (0, _invariant.default)(state.args !== undefined, "TODO: unknown abstract value passed to deriveState");
|
359 |
|
360 |
|
361 | let a = _index.AbstractValue.createFromBinaryOp(realm, "!==", state, realm.intrinsics.null);
|
362 |
|
363 | let b = _index.AbstractValue.createFromBinaryOp(realm, "!==", state, realm.intrinsics.undefined);
|
364 |
|
365 | let c = _index.AbstractValue.createFromLogicalOp(realm, "&&", a, b);
|
366 |
|
367 | (0, _invariant.default)(c instanceof _index.AbstractValue);
|
368 | let newState = new _index.ObjectValue(realm, realm.intrinsics.ObjectPrototype);
|
369 | let preludeGenerator = realm.preludeGenerator;
|
370 | (0, _invariant.default)(preludeGenerator !== undefined);
|
371 |
|
372 |
|
373 |
|
374 |
|
375 | _index.AbstractValue.createTemporalObjectAssign(realm, newState, [prevState, state]);
|
376 |
|
377 | newState.makeSimple();
|
378 | newState.makePartial();
|
379 | newState.makeFinal();
|
380 |
|
381 | let conditional = _index.AbstractValue.createFromLogicalOp(realm, "&&", c, newState);
|
382 |
|
383 | return conditional;
|
384 | }
|
385 | } else if (state !== realm.intrinsics.null && state !== realm.intrinsics.undefined) {
|
386 | let newState = new _index.ObjectValue(realm, realm.intrinsics.ObjectPrototype);
|
387 |
|
388 | try {
|
389 | objectAssignCall(realm.intrinsics.undefined, [newState, prevState, state]);
|
390 | } catch (e) {
|
391 | if (realm.isInPureScope() && e instanceof _errors2.FatalError) {
|
392 | let preludeGenerator = realm.preludeGenerator;
|
393 | (0, _invariant.default)(preludeGenerator !== undefined);
|
394 |
|
395 | _index.AbstractValue.createTemporalObjectAssign(realm, newState, [prevState, state]);
|
396 |
|
397 | newState.makeSimple();
|
398 | newState.makePartial();
|
399 | return newState;
|
400 | }
|
401 |
|
402 | throw e;
|
403 | }
|
404 |
|
405 | newState.makeFinal();
|
406 | return newState;
|
407 | } else {
|
408 | return null;
|
409 | }
|
410 | };
|
411 |
|
412 | let newState = deriveState(partialState);
|
413 |
|
414 | if (newState !== null) {
|
415 | if (newState instanceof _index.AbstractValue) {
|
416 | newState = _index.AbstractValue.createFromLogicalOp(realm, "||", newState, prevState);
|
417 | }
|
418 |
|
419 | (0, _invariant.default)(newState instanceof _index.Value);
|
420 |
|
421 | _singletons.Properties.Set(realm, instance, "state", newState, true);
|
422 | }
|
423 | }
|
424 |
|
\ | No newline at end of file |