source: frontend/node_modules/@babel/plugin-transform-optional-chaining/lib/index.js

Last change on this file was 9af201e, checked in by MBK <marija.karapandzova@…>, 12 days ago

Fix frontend appearance

  • Property mode set to 100644
File size: 9.0 KB
Line 
1'use strict';
2
3Object.defineProperty(exports, '__esModule', { value: true });
4
5var helperPluginUtils = require('@babel/helper-plugin-utils');
6var core = require('@babel/core');
7var helperSkipTransparentExpressionWrappers = require('@babel/helper-skip-transparent-expression-wrappers');
8
9function willPathCastToBoolean(path) {
10 const maybeWrapped = findOutermostTransparentParent(path);
11 const {
12 node,
13 parentPath
14 } = maybeWrapped;
15 if (parentPath.isLogicalExpression()) {
16 const {
17 operator,
18 right
19 } = parentPath.node;
20 if (operator === "&&" || operator === "||" || operator === "??" && node === right) {
21 return willPathCastToBoolean(parentPath);
22 }
23 }
24 if (parentPath.isSequenceExpression()) {
25 const {
26 expressions
27 } = parentPath.node;
28 if (expressions[expressions.length - 1] === node) {
29 return willPathCastToBoolean(parentPath);
30 } else {
31 return true;
32 }
33 }
34 return parentPath.isConditional({
35 test: node
36 }) || parentPath.isUnaryExpression({
37 operator: "!"
38 }) || parentPath.isForStatement({
39 test: node
40 }) || parentPath.isWhile({
41 test: node
42 });
43}
44function findOutermostTransparentParent(path) {
45 let maybeWrapped = path;
46 path.findParent(p => {
47 if (!helperSkipTransparentExpressionWrappers.isTransparentExprWrapper(p.node)) return true;
48 maybeWrapped = p;
49 });
50 return maybeWrapped;
51}
52
53const last = arr => arr[arr.length - 1];
54function isSimpleMemberExpression(expression) {
55 expression = helperSkipTransparentExpressionWrappers.skipTransparentExprWrapperNodes(expression);
56 return core.types.isIdentifier(expression) || core.types.isSuper(expression) || core.types.isMemberExpression(expression) && !expression.computed && isSimpleMemberExpression(expression.object);
57}
58function needsMemoize(path) {
59 let optionalPath = path;
60 const {
61 scope
62 } = path;
63 while (optionalPath.isOptionalMemberExpression() || optionalPath.isOptionalCallExpression()) {
64 const {
65 node
66 } = optionalPath;
67 const childPath = helperSkipTransparentExpressionWrappers.skipTransparentExprWrappers(optionalPath.isOptionalMemberExpression() ? optionalPath.get("object") : optionalPath.get("callee"));
68 if (node.optional) {
69 return !scope.isStatic(childPath.node);
70 }
71 optionalPath = childPath;
72 }
73}
74const NULLISH_CHECK = core.template.expression(`%%check%% === null || %%ref%% === void 0`);
75const NULLISH_CHECK_NO_DDA = core.template.expression(`%%check%% == null`);
76const NULLISH_CHECK_NEG = core.template.expression(`%%check%% !== null && %%ref%% !== void 0`);
77const NULLISH_CHECK_NO_DDA_NEG = core.template.expression(`%%check%% != null`);
78function transformOptionalChain(path, {
79 pureGetters,
80 noDocumentAll
81}, replacementPath, ifNullish, wrapLast) {
82 const {
83 scope
84 } = path;
85 if (scope.path.isPattern() && needsMemoize(path)) {
86 replacementPath.replaceWith(core.template.expression.ast`(() => ${replacementPath.node})()`);
87 return;
88 }
89 const optionals = [];
90 let optionalPath = path;
91 while (optionalPath.isOptionalMemberExpression() || optionalPath.isOptionalCallExpression()) {
92 const {
93 node
94 } = optionalPath;
95 if (node.optional) {
96 optionals.push(node);
97 }
98 if (optionalPath.isOptionalMemberExpression()) {
99 optionalPath.node.type = "MemberExpression";
100 optionalPath = helperSkipTransparentExpressionWrappers.skipTransparentExprWrappers(optionalPath.get("object"));
101 } else if (optionalPath.isOptionalCallExpression()) {
102 optionalPath.node.type = "CallExpression";
103 optionalPath = helperSkipTransparentExpressionWrappers.skipTransparentExprWrappers(optionalPath.get("callee"));
104 }
105 }
106 if (optionals.length === 0) {
107 return;
108 }
109 const checks = [];
110 let tmpVar;
111 for (let i = optionals.length - 1; i >= 0; i--) {
112 const node = optionals[i];
113 const isCall = core.types.isCallExpression(node);
114 const chainWithTypes = isCall ? node.callee : node.object;
115 const chain = helperSkipTransparentExpressionWrappers.skipTransparentExprWrapperNodes(chainWithTypes);
116 let ref;
117 let check;
118 if (isCall && core.types.isIdentifier(chain, {
119 name: "eval"
120 })) {
121 check = ref = chain;
122 node.callee = core.types.sequenceExpression([core.types.numericLiteral(0), ref]);
123 } else if (pureGetters && isCall && isSimpleMemberExpression(chain)) {
124 check = ref = node.callee;
125 } else if (scope.isStatic(chain)) {
126 check = ref = chainWithTypes;
127 } else {
128 if (!tmpVar || isCall) {
129 tmpVar = scope.generateUidIdentifierBasedOnNode(chain);
130 scope.push({
131 id: core.types.cloneNode(tmpVar)
132 });
133 }
134 ref = tmpVar;
135 check = core.types.assignmentExpression("=", core.types.cloneNode(tmpVar), chainWithTypes);
136 if (isCall) {
137 node.callee = ref;
138 } else {
139 node.object = ref;
140 }
141 }
142 if (isCall && core.types.isMemberExpression(chain)) {
143 if (pureGetters && isSimpleMemberExpression(chain)) {
144 node.callee = chainWithTypes;
145 } else {
146 const {
147 object
148 } = chain;
149 let context;
150 if (core.types.isSuper(object)) {
151 context = core.types.thisExpression();
152 } else {
153 const memoized = scope.maybeGenerateMemoised(object);
154 if (memoized) {
155 context = memoized;
156 chain.object = core.types.assignmentExpression("=", memoized, object);
157 } else {
158 context = object;
159 }
160 }
161 node.arguments.unshift(core.types.cloneNode(context));
162 node.callee = core.types.memberExpression(node.callee, core.types.identifier("call"));
163 }
164 }
165 const data = {
166 check: core.types.cloneNode(check),
167 ref: core.types.cloneNode(ref)
168 };
169 Object.defineProperty(data, "ref", {
170 enumerable: false
171 });
172 checks.push(data);
173 }
174 let result = replacementPath.node;
175 if (wrapLast) result = wrapLast(result);
176 const ifNullishBoolean = core.types.isBooleanLiteral(ifNullish);
177 const ifNullishFalse = ifNullishBoolean && ifNullish.value === false;
178 const ifNullishVoid = !ifNullishBoolean && core.types.isUnaryExpression(ifNullish, {
179 operator: "void"
180 });
181 const isEvaluationValueIgnored = core.types.isExpressionStatement(replacementPath.parent) && !replacementPath.isCompletionRecord() || core.types.isSequenceExpression(replacementPath.parent) && last(replacementPath.parent.expressions) !== replacementPath.node;
182 const tpl = ifNullishFalse ? noDocumentAll ? NULLISH_CHECK_NO_DDA_NEG : NULLISH_CHECK_NEG : noDocumentAll ? NULLISH_CHECK_NO_DDA : NULLISH_CHECK;
183 const logicalOp = ifNullishFalse ? "&&" : "||";
184 const check = checks.map(tpl).reduce((expr, check) => core.types.logicalExpression(logicalOp, expr, check));
185 replacementPath.replaceWith(ifNullishBoolean || ifNullishVoid && isEvaluationValueIgnored ? core.types.logicalExpression(logicalOp, check, result) : core.types.conditionalExpression(check, ifNullish, result));
186}
187function transform(path, assumptions) {
188 const {
189 scope
190 } = path;
191 const maybeWrapped = findOutermostTransparentParent(path);
192 const {
193 parentPath
194 } = maybeWrapped;
195 if (parentPath.isUnaryExpression({
196 operator: "delete"
197 })) {
198 transformOptionalChain(path, assumptions, parentPath, core.types.booleanLiteral(true));
199 } else {
200 let wrapLast;
201 if (parentPath.isCallExpression({
202 callee: maybeWrapped.node
203 }) && path.isOptionalMemberExpression()) {
204 wrapLast = replacement => {
205 const object = helperSkipTransparentExpressionWrappers.skipTransparentExprWrapperNodes(replacement.object);
206 let baseRef;
207 if (!assumptions.pureGetters || !isSimpleMemberExpression(object)) {
208 baseRef = scope.maybeGenerateMemoised(object);
209 if (baseRef) {
210 replacement.object = core.types.assignmentExpression("=", baseRef, object);
211 }
212 }
213 return core.types.callExpression(core.types.memberExpression(replacement, core.types.identifier("bind")), [core.types.cloneNode(baseRef != null ? baseRef : object)]);
214 };
215 }
216 transformOptionalChain(path, assumptions, path, willPathCastToBoolean(maybeWrapped) ? core.types.booleanLiteral(false) : scope.buildUndefinedNode(), wrapLast);
217 }
218}
219
220var index = helperPluginUtils.declare((api, options) => {
221 var _api$assumption, _api$assumption2;
222 api.assertVersion("^7.0.0-0 || ^8.0.0-0 || >8.0.0-alpha <8.0.0-beta");
223 const {
224 loose = false
225 } = options;
226 const noDocumentAll = (_api$assumption = api.assumption("noDocumentAll")) != null ? _api$assumption : loose;
227 const pureGetters = (_api$assumption2 = api.assumption("pureGetters")) != null ? _api$assumption2 : loose;
228 return {
229 name: "transform-optional-chaining",
230 manipulateOptions: (_, parser) => parser.plugins.push("optionalChaining"),
231 visitor: {
232 "OptionalCallExpression|OptionalMemberExpression"(path) {
233 transform(path, {
234 noDocumentAll,
235 pureGetters
236 });
237 }
238 }
239 };
240});
241
242exports.default = index;
243exports.transform = transform;
244exports.transformOptionalChain = transformOptionalChain;
245//# sourceMappingURL=index.js.map
Note: See TracBrowser for help on using the repository browser.