1 // Copyright 2014 PDFium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
6
7 #include "xfa/fxfa/fm2js/cxfa_fmexpression.h"
8
9 #include <utility>
10
11 #include "core/fxcrt/cfx_widetextbuf.h"
12 #include "xfa/fxfa/fm2js/cxfa_fmsimpleexpression.h"
13 #include "xfa/fxfa/fm2js/cxfa_fmtojavascriptdepth.h"
14
15 namespace {
16
17 const wchar_t RUNTIMEBLOCKTEMPARRAY[] = L"pfm_ary";
18
19 const wchar_t RUNTIMEBLOCKTEMPARRAYINDEX[] = L"pfm_ary_idx";
20
21 const wchar_t kLessEqual[] = L" <= ";
22 const wchar_t kGreaterEqual[] = L" >= ";
23 const wchar_t kPlusEqual[] = L" += ";
24 const wchar_t kMinusEqual[] = L" -= ";
25
26 } // namespace
27
CXFA_FMExpression(uint32_t line)28 CXFA_FMExpression::CXFA_FMExpression(uint32_t line)
29 : m_type(XFA_FM_EXPTYPE_UNKNOWN), m_line(line) {}
30
CXFA_FMExpression(uint32_t line,XFA_FM_EXPTYPE type)31 CXFA_FMExpression::CXFA_FMExpression(uint32_t line, XFA_FM_EXPTYPE type)
32 : m_type(type), m_line(line) {}
33
ToJavaScript(CFX_WideTextBuf & javascript)34 bool CXFA_FMExpression::ToJavaScript(CFX_WideTextBuf& javascript) {
35 CXFA_FMToJavaScriptDepth depthManager;
36 return !CXFA_IsTooBig(javascript) && depthManager.IsWithinMaxDepth();
37 }
38
ToImpliedReturnJS(CFX_WideTextBuf & javascript)39 bool CXFA_FMExpression::ToImpliedReturnJS(CFX_WideTextBuf& javascript) {
40 CXFA_FMToJavaScriptDepth depthManager;
41 return !CXFA_IsTooBig(javascript) && depthManager.IsWithinMaxDepth();
42 }
43
CXFA_FMFunctionDefinition(uint32_t line,bool isGlobal,const WideStringView & wsName,std::vector<WideStringView> && arguments,std::vector<std::unique_ptr<CXFA_FMExpression>> && expressions)44 CXFA_FMFunctionDefinition::CXFA_FMFunctionDefinition(
45 uint32_t line,
46 bool isGlobal,
47 const WideStringView& wsName,
48 std::vector<WideStringView>&& arguments,
49 std::vector<std::unique_ptr<CXFA_FMExpression>>&& expressions)
50 : CXFA_FMExpression(line, XFA_FM_EXPTYPE_FUNC),
51 m_wsName(wsName),
52 m_pArguments(std::move(arguments)),
53 m_pExpressions(std::move(expressions)),
54 m_isGlobal(isGlobal) {}
55
~CXFA_FMFunctionDefinition()56 CXFA_FMFunctionDefinition::~CXFA_FMFunctionDefinition() {}
57
ToJavaScript(CFX_WideTextBuf & javascript)58 bool CXFA_FMFunctionDefinition::ToJavaScript(CFX_WideTextBuf& javascript) {
59 CXFA_FMToJavaScriptDepth depthManager;
60 if (CXFA_IsTooBig(javascript) || !depthManager.IsWithinMaxDepth())
61 return false;
62
63 if (m_isGlobal && m_pExpressions.empty()) {
64 javascript << L"// comments only";
65 return !CXFA_IsTooBig(javascript);
66 }
67 if (m_isGlobal) {
68 javascript << L"(\n";
69 }
70 javascript << L"function ";
71 if (!m_wsName.IsEmpty() && m_wsName[0] == L'!') {
72 WideString tempName =
73 EXCLAMATION_IN_IDENTIFIER + m_wsName.Right(m_wsName.GetLength() - 1);
74 javascript << tempName;
75 } else {
76 javascript << m_wsName;
77 }
78 javascript << L"(";
79 bool bNeedComma = false;
80 for (const auto& identifier : m_pArguments) {
81 if (bNeedComma)
82 javascript << L", ";
83 if (identifier[0] == L'!') {
84 WideString tempIdentifier = EXCLAMATION_IN_IDENTIFIER +
85 identifier.Right(identifier.GetLength() - 1);
86 javascript << tempIdentifier;
87 } else {
88 javascript << identifier;
89 }
90 bNeedComma = true;
91 }
92 javascript << L")\n{\n";
93 javascript << L"var ";
94 javascript << RUNTIMEFUNCTIONRETURNVALUE;
95 javascript << L" = null;\n";
96 for (const auto& expr : m_pExpressions) {
97 bool ret;
98 if (expr == m_pExpressions.back())
99 ret = expr->ToImpliedReturnJS(javascript);
100 else
101 ret = expr->ToJavaScript(javascript);
102
103 if (!ret)
104 return false;
105 }
106 javascript << L"return ";
107 if (m_isGlobal) {
108 javascript << XFA_FM_EXPTypeToString(GETFMVALUE);
109 javascript << L"(";
110 javascript << RUNTIMEFUNCTIONRETURNVALUE;
111 javascript << L")";
112 } else {
113 javascript << RUNTIMEFUNCTIONRETURNVALUE;
114 }
115 javascript << L";\n}\n";
116 if (m_isGlobal) {
117 javascript << L").call(this);\n";
118 }
119 return !CXFA_IsTooBig(javascript);
120 }
121
ToImpliedReturnJS(CFX_WideTextBuf & javascript)122 bool CXFA_FMFunctionDefinition::ToImpliedReturnJS(CFX_WideTextBuf& javascript) {
123 CXFA_FMToJavaScriptDepth depthManager;
124 return !CXFA_IsTooBig(javascript) && depthManager.IsWithinMaxDepth();
125 }
126
CXFA_FMVarExpression(uint32_t line,const WideStringView & wsName,std::unique_ptr<CXFA_FMExpression> pInit)127 CXFA_FMVarExpression::CXFA_FMVarExpression(
128 uint32_t line,
129 const WideStringView& wsName,
130 std::unique_ptr<CXFA_FMExpression> pInit)
131 : CXFA_FMExpression(line, XFA_FM_EXPTYPE_VAR),
132 m_wsName(wsName),
133 m_pInit(std::move(pInit)) {}
134
~CXFA_FMVarExpression()135 CXFA_FMVarExpression::~CXFA_FMVarExpression() {}
136
ToJavaScript(CFX_WideTextBuf & javascript)137 bool CXFA_FMVarExpression::ToJavaScript(CFX_WideTextBuf& javascript) {
138 CXFA_FMToJavaScriptDepth depthManager;
139 if (CXFA_IsTooBig(javascript) || !depthManager.IsWithinMaxDepth())
140 return false;
141
142 javascript << L"var ";
143 WideString tempName(m_wsName);
144 if (m_wsName[0] == L'!') {
145 tempName =
146 EXCLAMATION_IN_IDENTIFIER + m_wsName.Right(m_wsName.GetLength() - 1);
147 }
148 javascript << tempName;
149 javascript << L" = ";
150 if (m_pInit) {
151 if (!m_pInit->ToJavaScript(javascript))
152 return false;
153 javascript << tempName;
154 javascript << L" = ";
155 javascript << XFA_FM_EXPTypeToString(VARFILTER);
156 javascript << L"(";
157 javascript << tempName;
158 javascript << L");\n";
159 } else {
160 javascript << L"\"\";\n";
161 }
162 return !CXFA_IsTooBig(javascript);
163 }
164
ToImpliedReturnJS(CFX_WideTextBuf & javascript)165 bool CXFA_FMVarExpression::ToImpliedReturnJS(CFX_WideTextBuf& javascript) {
166 CXFA_FMToJavaScriptDepth depthManager;
167 if (CXFA_IsTooBig(javascript) || !depthManager.IsWithinMaxDepth())
168 return false;
169
170 javascript << L"var ";
171 WideString tempName(m_wsName);
172 if (m_wsName[0] == L'!') {
173 tempName =
174 EXCLAMATION_IN_IDENTIFIER + m_wsName.Right(m_wsName.GetLength() - 1);
175 }
176 javascript << tempName;
177 javascript << L" = ";
178 if (m_pInit) {
179 if (!m_pInit->ToJavaScript(javascript))
180 return false;
181 javascript << tempName;
182 javascript << L" = ";
183 javascript << XFA_FM_EXPTypeToString(VARFILTER);
184 javascript << L"(";
185 javascript << tempName;
186 javascript << L");\n";
187 } else {
188 javascript << L"\"\";\n";
189 }
190 javascript << RUNTIMEFUNCTIONRETURNVALUE;
191 javascript << L" = ";
192 javascript << tempName;
193 javascript << L";\n";
194 return !CXFA_IsTooBig(javascript);
195 }
196
CXFA_FMExpExpression(uint32_t line,std::unique_ptr<CXFA_FMSimpleExpression> pExpression)197 CXFA_FMExpExpression::CXFA_FMExpExpression(
198 uint32_t line,
199 std::unique_ptr<CXFA_FMSimpleExpression> pExpression)
200 : CXFA_FMExpression(line, XFA_FM_EXPTYPE_EXP),
201 m_pExpression(std::move(pExpression)) {}
202
~CXFA_FMExpExpression()203 CXFA_FMExpExpression::~CXFA_FMExpExpression() {}
204
ToJavaScript(CFX_WideTextBuf & javascript)205 bool CXFA_FMExpExpression::ToJavaScript(CFX_WideTextBuf& javascript) {
206 CXFA_FMToJavaScriptDepth depthManager;
207 if (CXFA_IsTooBig(javascript) || !depthManager.IsWithinMaxDepth())
208 return false;
209
210 bool ret = m_pExpression->ToJavaScript(javascript);
211 if (m_pExpression->GetOperatorToken() != TOKassign)
212 javascript << L";\n";
213 return ret;
214 }
215
ToImpliedReturnJS(CFX_WideTextBuf & javascript)216 bool CXFA_FMExpExpression::ToImpliedReturnJS(CFX_WideTextBuf& javascript) {
217 CXFA_FMToJavaScriptDepth depthManager;
218 if (CXFA_IsTooBig(javascript) || !depthManager.IsWithinMaxDepth())
219 return false;
220
221 if (m_pExpression->GetOperatorToken() == TOKassign)
222 return m_pExpression->ToImpliedReturnJS(javascript);
223
224 if (m_pExpression->GetOperatorToken() == TOKstar ||
225 m_pExpression->GetOperatorToken() == TOKdotstar ||
226 m_pExpression->GetOperatorToken() == TOKdotscream ||
227 m_pExpression->GetOperatorToken() == TOKdotdot ||
228 m_pExpression->GetOperatorToken() == TOKdot) {
229 javascript << RUNTIMEFUNCTIONRETURNVALUE;
230 javascript << L" = ";
231 javascript << XFA_FM_EXPTypeToString(GETFMVALUE);
232 javascript << L"(";
233 if (!m_pExpression->ToJavaScript(javascript))
234 return false;
235 javascript << L");\n";
236 return !CXFA_IsTooBig(javascript);
237 }
238
239 javascript << RUNTIMEFUNCTIONRETURNVALUE;
240 javascript << L" = ";
241 if (!m_pExpression->ToJavaScript(javascript))
242 return false;
243 javascript << L";\n";
244 return !CXFA_IsTooBig(javascript);
245 }
246
CXFA_FMBlockExpression(uint32_t line,std::vector<std::unique_ptr<CXFA_FMExpression>> && pExpressionList)247 CXFA_FMBlockExpression::CXFA_FMBlockExpression(
248 uint32_t line,
249 std::vector<std::unique_ptr<CXFA_FMExpression>>&& pExpressionList)
250 : CXFA_FMExpression(line, XFA_FM_EXPTYPE_BLOCK),
251 m_ExpressionList(std::move(pExpressionList)) {}
252
~CXFA_FMBlockExpression()253 CXFA_FMBlockExpression::~CXFA_FMBlockExpression() {}
254
ToJavaScript(CFX_WideTextBuf & javascript)255 bool CXFA_FMBlockExpression::ToJavaScript(CFX_WideTextBuf& javascript) {
256 CXFA_FMToJavaScriptDepth depthManager;
257 if (CXFA_IsTooBig(javascript) || !depthManager.IsWithinMaxDepth())
258 return false;
259
260 javascript << L"{\n";
261 for (const auto& expr : m_ExpressionList) {
262 if (!expr->ToJavaScript(javascript))
263 return false;
264 }
265 javascript << L"}\n";
266 return !CXFA_IsTooBig(javascript);
267 }
268
ToImpliedReturnJS(CFX_WideTextBuf & javascript)269 bool CXFA_FMBlockExpression::ToImpliedReturnJS(CFX_WideTextBuf& javascript) {
270 CXFA_FMToJavaScriptDepth depthManager;
271 if (CXFA_IsTooBig(javascript) || !depthManager.IsWithinMaxDepth())
272 return false;
273
274 javascript << L"{\n";
275 for (const auto& expr : m_ExpressionList) {
276 bool ret;
277 if (expr == m_ExpressionList.back())
278 ret = expr->ToImpliedReturnJS(javascript);
279 else
280 ret = expr->ToJavaScript(javascript);
281
282 if (!ret)
283 return false;
284 }
285 javascript << L"}\n";
286 return !CXFA_IsTooBig(javascript);
287 }
288
CXFA_FMDoExpression(uint32_t line,std::unique_ptr<CXFA_FMExpression> pList)289 CXFA_FMDoExpression::CXFA_FMDoExpression(
290 uint32_t line,
291 std::unique_ptr<CXFA_FMExpression> pList)
292 : CXFA_FMExpression(line), m_pList(std::move(pList)) {}
293
~CXFA_FMDoExpression()294 CXFA_FMDoExpression::~CXFA_FMDoExpression() {}
295
ToJavaScript(CFX_WideTextBuf & javascript)296 bool CXFA_FMDoExpression::ToJavaScript(CFX_WideTextBuf& javascript) {
297 CXFA_FMToJavaScriptDepth depthManager;
298 if (CXFA_IsTooBig(javascript) || !depthManager.IsWithinMaxDepth())
299 return false;
300
301 return m_pList->ToJavaScript(javascript);
302 }
303
ToImpliedReturnJS(CFX_WideTextBuf & javascript)304 bool CXFA_FMDoExpression::ToImpliedReturnJS(CFX_WideTextBuf& javascript) {
305 CXFA_FMToJavaScriptDepth depthManager;
306 if (CXFA_IsTooBig(javascript) || !depthManager.IsWithinMaxDepth())
307 return false;
308
309 return m_pList->ToImpliedReturnJS(javascript);
310 }
311
CXFA_FMIfExpression(uint32_t line,std::unique_ptr<CXFA_FMSimpleExpression> pExpression,std::unique_ptr<CXFA_FMExpression> pIfExpression,std::unique_ptr<CXFA_FMExpression> pElseExpression)312 CXFA_FMIfExpression::CXFA_FMIfExpression(
313 uint32_t line,
314 std::unique_ptr<CXFA_FMSimpleExpression> pExpression,
315 std::unique_ptr<CXFA_FMExpression> pIfExpression,
316 std::unique_ptr<CXFA_FMExpression> pElseExpression)
317 : CXFA_FMExpression(line, XFA_FM_EXPTYPE_IF),
318 m_pExpression(std::move(pExpression)),
319 m_pIfExpression(std::move(pIfExpression)),
320 m_pElseExpression(std::move(pElseExpression)) {}
321
~CXFA_FMIfExpression()322 CXFA_FMIfExpression::~CXFA_FMIfExpression() {}
323
ToJavaScript(CFX_WideTextBuf & javascript)324 bool CXFA_FMIfExpression::ToJavaScript(CFX_WideTextBuf& javascript) {
325 CXFA_FMToJavaScriptDepth depthManager;
326 if (CXFA_IsTooBig(javascript) || !depthManager.IsWithinMaxDepth())
327 return false;
328
329 javascript << L"if (";
330 if (m_pExpression) {
331 javascript << XFA_FM_EXPTypeToString(GETFMVALUE);
332 javascript << L"(";
333 if (!m_pExpression->ToJavaScript(javascript))
334 return false;
335 javascript << L")";
336 }
337 javascript << L")\n";
338 if (CXFA_IsTooBig(javascript))
339 return false;
340
341 if (m_pIfExpression) {
342 if (!m_pIfExpression->ToJavaScript(javascript))
343 return false;
344 if (CXFA_IsTooBig(javascript))
345 return false;
346 }
347
348 if (m_pElseExpression) {
349 if (m_pElseExpression->GetExpType() == XFA_FM_EXPTYPE_IF) {
350 javascript << L"else\n";
351 javascript << L"{\n";
352 if (!m_pElseExpression->ToJavaScript(javascript))
353 return false;
354 javascript << L"}\n";
355 } else {
356 javascript << L"else\n";
357 if (!m_pElseExpression->ToJavaScript(javascript))
358 return false;
359 }
360 }
361 return !CXFA_IsTooBig(javascript);
362 }
363
ToImpliedReturnJS(CFX_WideTextBuf & javascript)364 bool CXFA_FMIfExpression::ToImpliedReturnJS(CFX_WideTextBuf& javascript) {
365 CXFA_FMToJavaScriptDepth depthManager;
366 if (CXFA_IsTooBig(javascript) || !depthManager.IsWithinMaxDepth())
367 return false;
368
369 javascript << RUNTIMEFUNCTIONRETURNVALUE;
370 javascript << L" = 0;\n";
371 javascript << L"if (";
372 if (m_pExpression) {
373 javascript << XFA_FM_EXPTypeToString(GETFMVALUE);
374 javascript << L"(";
375 if (!m_pExpression->ToJavaScript(javascript))
376 return false;
377 javascript << L")";
378 }
379 javascript << L")\n";
380 if (CXFA_IsTooBig(javascript))
381 return false;
382
383 if (m_pIfExpression) {
384 if (!m_pIfExpression->ToImpliedReturnJS(javascript))
385 return false;
386 if (CXFA_IsTooBig(javascript))
387 return false;
388 }
389 if (m_pElseExpression) {
390 if (m_pElseExpression->GetExpType() == XFA_FM_EXPTYPE_IF) {
391 javascript << L"else\n";
392 javascript << L"{\n";
393 if (!m_pElseExpression->ToImpliedReturnJS(javascript))
394 return false;
395 javascript << L"}\n";
396 } else {
397 javascript << L"else\n";
398 if (!m_pElseExpression->ToImpliedReturnJS(javascript))
399 return false;
400 }
401 }
402 return !CXFA_IsTooBig(javascript);
403 }
404
~CXFA_FMLoopExpression()405 CXFA_FMLoopExpression::~CXFA_FMLoopExpression() {}
406
ToJavaScript(CFX_WideTextBuf & javascript)407 bool CXFA_FMLoopExpression::ToJavaScript(CFX_WideTextBuf& javascript) {
408 CXFA_FMToJavaScriptDepth depthManager;
409 return !CXFA_IsTooBig(javascript) && depthManager.IsWithinMaxDepth();
410 }
411
ToImpliedReturnJS(CFX_WideTextBuf & javascript)412 bool CXFA_FMLoopExpression::ToImpliedReturnJS(CFX_WideTextBuf& javascript) {
413 CXFA_FMToJavaScriptDepth depthManager;
414 return !CXFA_IsTooBig(javascript) && depthManager.IsWithinMaxDepth();
415 }
416
CXFA_FMWhileExpression(uint32_t line,std::unique_ptr<CXFA_FMSimpleExpression> pCondition,std::unique_ptr<CXFA_FMExpression> pExpression)417 CXFA_FMWhileExpression::CXFA_FMWhileExpression(
418 uint32_t line,
419 std::unique_ptr<CXFA_FMSimpleExpression> pCondition,
420 std::unique_ptr<CXFA_FMExpression> pExpression)
421 : CXFA_FMLoopExpression(line),
422 m_pCondition(std::move(pCondition)),
423 m_pExpression(std::move(pExpression)) {}
424
~CXFA_FMWhileExpression()425 CXFA_FMWhileExpression::~CXFA_FMWhileExpression() {}
426
ToJavaScript(CFX_WideTextBuf & javascript)427 bool CXFA_FMWhileExpression::ToJavaScript(CFX_WideTextBuf& javascript) {
428 CXFA_FMToJavaScriptDepth depthManager;
429 if (CXFA_IsTooBig(javascript) || !depthManager.IsWithinMaxDepth())
430 return false;
431
432 javascript << L"while (";
433 if (!m_pCondition->ToJavaScript(javascript))
434 return false;
435 javascript << L")\n";
436 if (CXFA_IsTooBig(javascript))
437 return false;
438
439 if (!m_pExpression->ToJavaScript(javascript))
440 return false;
441 return !CXFA_IsTooBig(javascript);
442 }
443
ToImpliedReturnJS(CFX_WideTextBuf & javascript)444 bool CXFA_FMWhileExpression::ToImpliedReturnJS(CFX_WideTextBuf& javascript) {
445 CXFA_FMToJavaScriptDepth depthManager;
446 if (CXFA_IsTooBig(javascript) || !depthManager.IsWithinMaxDepth())
447 return false;
448
449 javascript << RUNTIMEFUNCTIONRETURNVALUE;
450 javascript << L" = 0;\n";
451 javascript << L"while (";
452 if (!m_pCondition->ToJavaScript(javascript))
453 return false;
454 javascript << L")\n";
455 if (CXFA_IsTooBig(javascript))
456 return false;
457
458 if (!m_pExpression->ToImpliedReturnJS(javascript))
459 return false;
460 return !CXFA_IsTooBig(javascript);
461 }
462
CXFA_FMBreakExpression(uint32_t line)463 CXFA_FMBreakExpression::CXFA_FMBreakExpression(uint32_t line)
464 : CXFA_FMExpression(line, XFA_FM_EXPTYPE_BREAK) {}
465
~CXFA_FMBreakExpression()466 CXFA_FMBreakExpression::~CXFA_FMBreakExpression() {}
467
ToJavaScript(CFX_WideTextBuf & javascript)468 bool CXFA_FMBreakExpression::ToJavaScript(CFX_WideTextBuf& javascript) {
469 CXFA_FMToJavaScriptDepth depthManager;
470 if (CXFA_IsTooBig(javascript) || !depthManager.IsWithinMaxDepth())
471 return false;
472
473 javascript << RUNTIMEFUNCTIONRETURNVALUE;
474 javascript << L" = 0;\n";
475 javascript << L"break;\n";
476 return !CXFA_IsTooBig(javascript);
477 }
478
ToImpliedReturnJS(CFX_WideTextBuf & javascript)479 bool CXFA_FMBreakExpression::ToImpliedReturnJS(CFX_WideTextBuf& javascript) {
480 CXFA_FMToJavaScriptDepth depthManager;
481 if (CXFA_IsTooBig(javascript) || !depthManager.IsWithinMaxDepth())
482 return false;
483
484 javascript << RUNTIMEFUNCTIONRETURNVALUE;
485 javascript << L" = 0;\n";
486 javascript << L"break;\n";
487 return !CXFA_IsTooBig(javascript);
488 }
489
CXFA_FMContinueExpression(uint32_t line)490 CXFA_FMContinueExpression::CXFA_FMContinueExpression(uint32_t line)
491 : CXFA_FMExpression(line, XFA_FM_EXPTYPE_CONTINUE) {}
492
~CXFA_FMContinueExpression()493 CXFA_FMContinueExpression::~CXFA_FMContinueExpression() {}
494
ToJavaScript(CFX_WideTextBuf & javascript)495 bool CXFA_FMContinueExpression::ToJavaScript(CFX_WideTextBuf& javascript) {
496 CXFA_FMToJavaScriptDepth depthManager;
497 if (CXFA_IsTooBig(javascript) || !depthManager.IsWithinMaxDepth())
498 return false;
499
500 javascript << RUNTIMEFUNCTIONRETURNVALUE;
501 javascript << L" = 0;\n";
502 javascript << L"continue;\n";
503 return !CXFA_IsTooBig(javascript);
504 }
505
ToImpliedReturnJS(CFX_WideTextBuf & javascript)506 bool CXFA_FMContinueExpression::ToImpliedReturnJS(CFX_WideTextBuf& javascript) {
507 CXFA_FMToJavaScriptDepth depthManager;
508 if (CXFA_IsTooBig(javascript) || !depthManager.IsWithinMaxDepth())
509 return false;
510
511 javascript << RUNTIMEFUNCTIONRETURNVALUE;
512 javascript << L" = 0;\n";
513 javascript << L"continue;\n";
514 return !CXFA_IsTooBig(javascript);
515 }
516
CXFA_FMForExpression(uint32_t line,const WideStringView & wsVariant,std::unique_ptr<CXFA_FMSimpleExpression> pAssignment,std::unique_ptr<CXFA_FMSimpleExpression> pAccessor,int32_t iDirection,std::unique_ptr<CXFA_FMSimpleExpression> pStep,std::unique_ptr<CXFA_FMExpression> pList)517 CXFA_FMForExpression::CXFA_FMForExpression(
518 uint32_t line,
519 const WideStringView& wsVariant,
520 std::unique_ptr<CXFA_FMSimpleExpression> pAssignment,
521 std::unique_ptr<CXFA_FMSimpleExpression> pAccessor,
522 int32_t iDirection,
523 std::unique_ptr<CXFA_FMSimpleExpression> pStep,
524 std::unique_ptr<CXFA_FMExpression> pList)
525 : CXFA_FMLoopExpression(line),
526 m_wsVariant(wsVariant),
527 m_pAssignment(std::move(pAssignment)),
528 m_pAccessor(std::move(pAccessor)),
529 m_bDirection(iDirection == 1),
530 m_pStep(std::move(pStep)),
531 m_pList(std::move(pList)) {}
532
~CXFA_FMForExpression()533 CXFA_FMForExpression::~CXFA_FMForExpression() {}
534
ToJavaScript(CFX_WideTextBuf & javascript)535 bool CXFA_FMForExpression::ToJavaScript(CFX_WideTextBuf& javascript) {
536 CXFA_FMToJavaScriptDepth depthManager;
537 if (CXFA_IsTooBig(javascript) || !depthManager.IsWithinMaxDepth())
538 return false;
539
540 javascript << L"{\nvar ";
541 WideString tempVariant;
542 if (m_wsVariant[0] == L'!') {
543 tempVariant = EXCLAMATION_IN_IDENTIFIER +
544 m_wsVariant.Right(m_wsVariant.GetLength() - 1);
545 javascript << tempVariant;
546 } else {
547 tempVariant = m_wsVariant;
548 javascript << m_wsVariant;
549 }
550 javascript << L" = null;\n";
551 javascript << L"for (";
552 javascript << tempVariant;
553 javascript << L" = ";
554 javascript << XFA_FM_EXPTypeToString(GETFMVALUE);
555 javascript << L"(";
556 if (!m_pAssignment->ToJavaScript(javascript))
557 return false;
558 javascript << L"); ";
559 javascript << tempVariant;
560
561 javascript << (m_bDirection ? kLessEqual : kGreaterEqual);
562 javascript << XFA_FM_EXPTypeToString(GETFMVALUE);
563 javascript << L"(";
564 if (!m_pAccessor->ToJavaScript(javascript))
565 return false;
566 javascript << L"); ";
567 javascript << tempVariant;
568 javascript << (m_bDirection ? kPlusEqual : kMinusEqual);
569 if (CXFA_IsTooBig(javascript))
570 return false;
571
572 if (m_pStep) {
573 javascript << XFA_FM_EXPTypeToString(GETFMVALUE);
574 javascript << L"(";
575 if (!m_pStep->ToJavaScript(javascript))
576 return false;
577 javascript << L")";
578 } else {
579 javascript << L"1";
580 }
581 javascript << L")\n";
582 if (!m_pList->ToJavaScript(javascript))
583 return false;
584 javascript << L"}\n";
585 return !CXFA_IsTooBig(javascript);
586 }
587
ToImpliedReturnJS(CFX_WideTextBuf & javascript)588 bool CXFA_FMForExpression::ToImpliedReturnJS(CFX_WideTextBuf& javascript) {
589 CXFA_FMToJavaScriptDepth depthManager;
590 if (CXFA_IsTooBig(javascript) || !depthManager.IsWithinMaxDepth())
591 return false;
592
593 javascript << RUNTIMEFUNCTIONRETURNVALUE;
594 javascript << L" = 0;\n";
595 javascript << L"{\nvar ";
596 WideString tempVariant;
597 if (m_wsVariant[0] == L'!') {
598 tempVariant = EXCLAMATION_IN_IDENTIFIER +
599 m_wsVariant.Right(m_wsVariant.GetLength() - 1);
600 javascript << tempVariant;
601 } else {
602 tempVariant = m_wsVariant;
603 javascript << m_wsVariant;
604 }
605 javascript << L" = null;\n";
606 javascript << L"for (";
607 javascript << tempVariant;
608 javascript << L" = ";
609 javascript << XFA_FM_EXPTypeToString(GETFMVALUE);
610 javascript << L"(";
611 if (!m_pAssignment->ToJavaScript(javascript))
612 return false;
613 javascript << L"); ";
614 javascript << tempVariant;
615
616 javascript << (m_bDirection ? kLessEqual : kGreaterEqual);
617 javascript << XFA_FM_EXPTypeToString(GETFMVALUE);
618 javascript << L"(";
619 if (!m_pAccessor->ToJavaScript(javascript))
620 return false;
621 javascript << L"); ";
622 javascript << tempVariant;
623 javascript << L" += ";
624 javascript << (m_bDirection ? kPlusEqual : kMinusEqual);
625 if (CXFA_IsTooBig(javascript))
626 return false;
627
628 if (m_pStep) {
629 javascript << XFA_FM_EXPTypeToString(GETFMVALUE);
630 javascript << L"(";
631 if (!m_pStep->ToJavaScript(javascript))
632 return false;
633 javascript << L")";
634 if (CXFA_IsTooBig(javascript))
635 return false;
636 } else {
637 javascript << L"1";
638 }
639 javascript << L")\n";
640 if (!m_pList->ToImpliedReturnJS(javascript))
641 return false;
642 javascript << L"}\n";
643 return !CXFA_IsTooBig(javascript);
644 }
645
CXFA_FMForeachExpression(uint32_t line,const WideStringView & wsIdentifier,std::vector<std::unique_ptr<CXFA_FMSimpleExpression>> && pAccessors,std::unique_ptr<CXFA_FMExpression> pList)646 CXFA_FMForeachExpression::CXFA_FMForeachExpression(
647 uint32_t line,
648 const WideStringView& wsIdentifier,
649 std::vector<std::unique_ptr<CXFA_FMSimpleExpression>>&& pAccessors,
650 std::unique_ptr<CXFA_FMExpression> pList)
651 : CXFA_FMLoopExpression(line),
652 m_wsIdentifier(wsIdentifier),
653 m_pAccessors(std::move(pAccessors)),
654 m_pList(std::move(pList)) {}
655
~CXFA_FMForeachExpression()656 CXFA_FMForeachExpression::~CXFA_FMForeachExpression() {}
657
ToJavaScript(CFX_WideTextBuf & javascript)658 bool CXFA_FMForeachExpression::ToJavaScript(CFX_WideTextBuf& javascript) {
659 CXFA_FMToJavaScriptDepth depthManager;
660 if (CXFA_IsTooBig(javascript) || !depthManager.IsWithinMaxDepth())
661 return false;
662
663 javascript << L"{\n";
664 javascript << L"var ";
665 if (m_wsIdentifier[0] == L'!') {
666 WideString tempIdentifier =
667 EXCLAMATION_IN_IDENTIFIER +
668 m_wsIdentifier.Right(m_wsIdentifier.GetLength() - 1);
669 javascript << tempIdentifier;
670 } else {
671 javascript << m_wsIdentifier;
672 }
673 javascript << L" = null;\n";
674 javascript << L"var ";
675 javascript << RUNTIMEBLOCKTEMPARRAY;
676 javascript << L" = ";
677 javascript << XFA_FM_EXPTypeToString(CONCATFMOBJECT);
678 javascript << L"(";
679
680 for (const auto& expr : m_pAccessors) {
681 if (!expr->ToJavaScript(javascript))
682 return false;
683 if (expr != m_pAccessors.back())
684 javascript << L", ";
685 }
686 javascript << L");\n";
687 javascript << L"var ";
688 javascript << RUNTIMEBLOCKTEMPARRAYINDEX;
689 javascript << (L" = 0;\n");
690 javascript << L"while(";
691 javascript << RUNTIMEBLOCKTEMPARRAYINDEX;
692 javascript << L" < ";
693 javascript << RUNTIMEBLOCKTEMPARRAY;
694 javascript << L".length)\n{\n";
695 if (m_wsIdentifier[0] == L'!') {
696 WideString tempIdentifier =
697 EXCLAMATION_IN_IDENTIFIER +
698 m_wsIdentifier.Right(m_wsIdentifier.GetLength() - 1);
699 javascript << tempIdentifier;
700 } else {
701 javascript << m_wsIdentifier;
702 }
703 javascript << L" = ";
704 javascript << RUNTIMEBLOCKTEMPARRAY;
705 javascript << L"[";
706 javascript << RUNTIMEBLOCKTEMPARRAYINDEX;
707 javascript << L"++];\n";
708 if (!m_pList->ToJavaScript(javascript))
709 return false;
710 javascript << L"}\n";
711 javascript << L"}\n";
712 return !CXFA_IsTooBig(javascript);
713 }
714
ToImpliedReturnJS(CFX_WideTextBuf & javascript)715 bool CXFA_FMForeachExpression::ToImpliedReturnJS(CFX_WideTextBuf& javascript) {
716 CXFA_FMToJavaScriptDepth depthManager;
717 if (CXFA_IsTooBig(javascript) || !depthManager.IsWithinMaxDepth())
718 return false;
719
720 javascript << RUNTIMEFUNCTIONRETURNVALUE;
721 javascript << L" = 0;\n";
722 javascript << L"{\n";
723 javascript << L"var ";
724 if (m_wsIdentifier[0] == L'!') {
725 WideString tempIdentifier =
726 EXCLAMATION_IN_IDENTIFIER +
727 m_wsIdentifier.Right(m_wsIdentifier.GetLength() - 1);
728 javascript << tempIdentifier;
729 } else {
730 javascript << m_wsIdentifier;
731 }
732 javascript << L" = null;\n";
733 javascript << L"var ";
734 javascript << RUNTIMEBLOCKTEMPARRAY;
735 javascript << L" = ";
736 javascript << XFA_FM_EXPTypeToString(CONCATFMOBJECT);
737 javascript << L"(";
738 for (const auto& expr : m_pAccessors) {
739 if (!expr->ToJavaScript(javascript))
740 return false;
741 if (expr != m_pAccessors.back())
742 javascript << L", ";
743 }
744 javascript << L");\n";
745 javascript << L"var ";
746 javascript << RUNTIMEBLOCKTEMPARRAYINDEX;
747 javascript << L" = 0;\n";
748 javascript << L"while(";
749 javascript << RUNTIMEBLOCKTEMPARRAYINDEX;
750 javascript << L" < ";
751 javascript << RUNTIMEBLOCKTEMPARRAY;
752 javascript << L".length)\n{\n";
753 if (m_wsIdentifier[0] == L'!') {
754 WideString tempIdentifier =
755 EXCLAMATION_IN_IDENTIFIER +
756 m_wsIdentifier.Right(m_wsIdentifier.GetLength() - 1);
757 javascript << tempIdentifier;
758 } else {
759 javascript << m_wsIdentifier;
760 }
761 javascript << L" = ";
762 javascript << RUNTIMEBLOCKTEMPARRAY;
763 javascript << L"[";
764 javascript << RUNTIMEBLOCKTEMPARRAYINDEX;
765 javascript << L"++];\n";
766 if (!m_pList->ToImpliedReturnJS(javascript))
767 return false;
768 javascript << L"}\n";
769 javascript << L"}\n";
770 return !CXFA_IsTooBig(javascript);
771 }
772