• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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/xfa_expression.h"
8 
9 #include <utility>
10 
11 #include "core/fxcrt/fx_basic.h"
12 
13 namespace {
14 
15 const FX_WCHAR RUNTIMEBLOCKTEMPARRAY[] =
16     L"foxit_xfa_formcalc_runtime_block_temp_array";
17 
18 const FX_WCHAR RUNTIMEBLOCKTEMPARRAYINDEX[] =
19     L"foxit_xfa_formcalc_runtime_block_temp_array_index";
20 
21 }  // namespace
22 
CXFA_FMExpression(uint32_t line)23 CXFA_FMExpression::CXFA_FMExpression(uint32_t line)
24     : m_type(XFA_FM_EXPTYPE_UNKNOWN), m_line(line) {}
25 
CXFA_FMExpression(uint32_t line,XFA_FM_EXPTYPE type)26 CXFA_FMExpression::CXFA_FMExpression(uint32_t line, XFA_FM_EXPTYPE type)
27     : m_type(type), m_line(line) {}
28 
ToJavaScript(CFX_WideTextBuf & javascript)29 void CXFA_FMExpression::ToJavaScript(CFX_WideTextBuf& javascript) {}
30 
ToImpliedReturnJS(CFX_WideTextBuf & javascript)31 void CXFA_FMExpression::ToImpliedReturnJS(CFX_WideTextBuf& javascript) {}
32 
CXFA_FMFunctionDefinition(uint32_t line,bool isGlobal,const CFX_WideStringC & wsName,std::vector<CFX_WideStringC> && arguments,std::vector<std::unique_ptr<CXFA_FMExpression>> && expressions)33 CXFA_FMFunctionDefinition::CXFA_FMFunctionDefinition(
34     uint32_t line,
35     bool isGlobal,
36     const CFX_WideStringC& wsName,
37     std::vector<CFX_WideStringC>&& arguments,
38     std::vector<std::unique_ptr<CXFA_FMExpression>>&& expressions)
39     : CXFA_FMExpression(line, XFA_FM_EXPTYPE_FUNC),
40       m_wsName(wsName),
41       m_pArguments(std::move(arguments)),
42       m_pExpressions(std::move(expressions)),
43       m_isGlobal(isGlobal) {}
44 
~CXFA_FMFunctionDefinition()45 CXFA_FMFunctionDefinition::~CXFA_FMFunctionDefinition() {}
46 
ToJavaScript(CFX_WideTextBuf & javascript)47 void CXFA_FMFunctionDefinition::ToJavaScript(CFX_WideTextBuf& javascript) {
48   if (m_isGlobal && m_pExpressions.empty()) {
49     javascript << L"// comments only";
50     return;
51   }
52   if (m_isGlobal) {
53     javascript << L"(\n";
54   }
55   javascript << L"function ";
56   if (m_wsName.GetAt(0) == L'!') {
57     CFX_WideString tempName = EXCLAMATION_IN_IDENTIFIER + m_wsName.Mid(1);
58     javascript << tempName;
59   } else {
60     javascript << m_wsName;
61   }
62   javascript << L"(";
63   bool bNeedComma = false;
64   for (const auto& identifier : m_pArguments) {
65     if (bNeedComma)
66       javascript << L", ";
67     if (identifier.GetAt(0) == L'!') {
68       CFX_WideString tempIdentifier =
69           EXCLAMATION_IN_IDENTIFIER + identifier.Mid(1);
70       javascript << tempIdentifier;
71     } else {
72       javascript << identifier;
73     }
74     bNeedComma = true;
75   }
76   javascript << L")\n{\n";
77   javascript << L"var ";
78   javascript << RUNTIMEFUNCTIONRETURNVALUE;
79   javascript << L" = null;\n";
80   for (const auto& expr : m_pExpressions) {
81     if (expr == m_pExpressions.back())
82       expr->ToImpliedReturnJS(javascript);
83     else
84       expr->ToJavaScript(javascript);
85   }
86   javascript << L"return ";
87   if (m_isGlobal) {
88     javascript << XFA_FM_EXPTypeToString(GETFMVALUE);
89     javascript << L"(";
90     javascript << RUNTIMEFUNCTIONRETURNVALUE;
91     javascript << L")";
92   } else {
93     javascript << RUNTIMEFUNCTIONRETURNVALUE;
94   }
95   javascript << L";\n}\n";
96   if (m_isGlobal) {
97     javascript << L").call(this);\n";
98   }
99 }
100 
ToImpliedReturnJS(CFX_WideTextBuf &)101 void CXFA_FMFunctionDefinition::ToImpliedReturnJS(CFX_WideTextBuf&) {}
102 
CXFA_FMVarExpression(uint32_t line,const CFX_WideStringC & wsName,std::unique_ptr<CXFA_FMExpression> pInit)103 CXFA_FMVarExpression::CXFA_FMVarExpression(
104     uint32_t line,
105     const CFX_WideStringC& wsName,
106     std::unique_ptr<CXFA_FMExpression> pInit)
107     : CXFA_FMExpression(line, XFA_FM_EXPTYPE_VAR),
108       m_wsName(wsName),
109       m_pInit(std::move(pInit)) {}
110 
~CXFA_FMVarExpression()111 CXFA_FMVarExpression::~CXFA_FMVarExpression() {}
112 
ToJavaScript(CFX_WideTextBuf & javascript)113 void CXFA_FMVarExpression::ToJavaScript(CFX_WideTextBuf& javascript) {
114   javascript << L"var ";
115   CFX_WideString tempName(m_wsName);
116   if (m_wsName.GetAt(0) == L'!') {
117     tempName = EXCLAMATION_IN_IDENTIFIER + m_wsName.Mid(1);
118   }
119   javascript << tempName;
120   javascript << L" = ";
121   if (m_pInit) {
122     m_pInit->ToJavaScript(javascript);
123     javascript << tempName;
124     javascript << L" = ";
125     javascript << XFA_FM_EXPTypeToString(VARFILTER);
126     javascript << L"(";
127     javascript << tempName;
128     javascript << L");\n";
129   } else {
130     javascript << L"\"\";\n";
131   }
132 }
133 
ToImpliedReturnJS(CFX_WideTextBuf & javascript)134 void CXFA_FMVarExpression::ToImpliedReturnJS(CFX_WideTextBuf& javascript) {
135   javascript << L"var ";
136   CFX_WideString tempName(m_wsName);
137   if (m_wsName.GetAt(0) == L'!') {
138     tempName = EXCLAMATION_IN_IDENTIFIER + m_wsName.Mid(1);
139   }
140   javascript << tempName;
141   javascript << L" = ";
142   if (m_pInit) {
143     m_pInit->ToJavaScript(javascript);
144     javascript << tempName;
145     javascript << L" = ";
146     javascript << XFA_FM_EXPTypeToString(VARFILTER);
147     javascript << L"(";
148     javascript << tempName;
149     javascript << L");\n";
150   } else {
151     javascript << L"\"\";\n";
152   }
153   javascript << RUNTIMEFUNCTIONRETURNVALUE;
154   javascript << L" = ";
155   javascript << tempName;
156   javascript << L";\n";
157 }
158 
CXFA_FMExpExpression(uint32_t line,std::unique_ptr<CXFA_FMSimpleExpression> pExpression)159 CXFA_FMExpExpression::CXFA_FMExpExpression(
160     uint32_t line,
161     std::unique_ptr<CXFA_FMSimpleExpression> pExpression)
162     : CXFA_FMExpression(line, XFA_FM_EXPTYPE_EXP),
163       m_pExpression(std::move(pExpression)) {}
164 
~CXFA_FMExpExpression()165 CXFA_FMExpExpression::~CXFA_FMExpExpression() {}
166 
ToJavaScript(CFX_WideTextBuf & javascript)167 void CXFA_FMExpExpression::ToJavaScript(CFX_WideTextBuf& javascript) {
168   if (m_pExpression->GetOperatorToken() == TOKassign) {
169     m_pExpression->ToJavaScript(javascript);
170   } else {
171     m_pExpression->ToJavaScript(javascript);
172     javascript << L";\n";
173   }
174 }
175 
ToImpliedReturnJS(CFX_WideTextBuf & javascript)176 void CXFA_FMExpExpression::ToImpliedReturnJS(CFX_WideTextBuf& javascript) {
177   if (m_pExpression->GetOperatorToken() == TOKassign) {
178     m_pExpression->ToImpliedReturnJS(javascript);
179   } else {
180     if (m_pExpression->GetOperatorToken() == TOKstar ||
181         m_pExpression->GetOperatorToken() == TOKdotstar ||
182         m_pExpression->GetOperatorToken() == TOKdotscream ||
183         m_pExpression->GetOperatorToken() == TOKdotdot ||
184         m_pExpression->GetOperatorToken() == TOKdot) {
185       javascript << RUNTIMEFUNCTIONRETURNVALUE;
186       javascript << L" = ";
187       javascript << XFA_FM_EXPTypeToString(GETFMVALUE);
188       javascript << L"(";
189       m_pExpression->ToJavaScript(javascript);
190       javascript << L");\n";
191     } else {
192       javascript << RUNTIMEFUNCTIONRETURNVALUE;
193       javascript << L" = ";
194       m_pExpression->ToJavaScript(javascript);
195       javascript << L";\n";
196     }
197   }
198 }
199 
CXFA_FMBlockExpression(uint32_t line,std::vector<std::unique_ptr<CXFA_FMExpression>> && pExpressionList)200 CXFA_FMBlockExpression::CXFA_FMBlockExpression(
201     uint32_t line,
202     std::vector<std::unique_ptr<CXFA_FMExpression>>&& pExpressionList)
203     : CXFA_FMExpression(line, XFA_FM_EXPTYPE_BLOCK),
204       m_ExpressionList(std::move(pExpressionList)) {}
205 
~CXFA_FMBlockExpression()206 CXFA_FMBlockExpression::~CXFA_FMBlockExpression() {}
207 
ToJavaScript(CFX_WideTextBuf & javascript)208 void CXFA_FMBlockExpression::ToJavaScript(CFX_WideTextBuf& javascript) {
209   javascript << L"{\n";
210   for (const auto& expr : m_ExpressionList)
211     expr->ToJavaScript(javascript);
212   javascript << L"}\n";
213 }
214 
ToImpliedReturnJS(CFX_WideTextBuf & javascript)215 void CXFA_FMBlockExpression::ToImpliedReturnJS(CFX_WideTextBuf& javascript) {
216   javascript << L"{\n";
217   for (const auto& expr : m_ExpressionList) {
218     if (expr == m_ExpressionList.back())
219       expr->ToImpliedReturnJS(javascript);
220     else
221       expr->ToJavaScript(javascript);
222   }
223   javascript << L"}\n";
224 }
225 
CXFA_FMDoExpression(uint32_t line,std::unique_ptr<CXFA_FMExpression> pList)226 CXFA_FMDoExpression::CXFA_FMDoExpression(
227     uint32_t line,
228     std::unique_ptr<CXFA_FMExpression> pList)
229     : CXFA_FMExpression(line), m_pList(std::move(pList)) {}
230 
~CXFA_FMDoExpression()231 CXFA_FMDoExpression::~CXFA_FMDoExpression() {}
232 
ToJavaScript(CFX_WideTextBuf & javascript)233 void CXFA_FMDoExpression::ToJavaScript(CFX_WideTextBuf& javascript) {
234   m_pList->ToJavaScript(javascript);
235 }
236 
ToImpliedReturnJS(CFX_WideTextBuf & javascript)237 void CXFA_FMDoExpression::ToImpliedReturnJS(CFX_WideTextBuf& javascript) {
238   m_pList->ToImpliedReturnJS(javascript);
239 }
240 
CXFA_FMIfExpression(uint32_t line,std::unique_ptr<CXFA_FMSimpleExpression> pExpression,std::unique_ptr<CXFA_FMExpression> pIfExpression,std::unique_ptr<CXFA_FMExpression> pElseExpression)241 CXFA_FMIfExpression::CXFA_FMIfExpression(
242     uint32_t line,
243     std::unique_ptr<CXFA_FMSimpleExpression> pExpression,
244     std::unique_ptr<CXFA_FMExpression> pIfExpression,
245     std::unique_ptr<CXFA_FMExpression> pElseExpression)
246     : CXFA_FMExpression(line, XFA_FM_EXPTYPE_IF),
247       m_pExpression(std::move(pExpression)),
248       m_pIfExpression(std::move(pIfExpression)),
249       m_pElseExpression(std::move(pElseExpression)) {}
250 
~CXFA_FMIfExpression()251 CXFA_FMIfExpression::~CXFA_FMIfExpression() {}
252 
ToJavaScript(CFX_WideTextBuf & javascript)253 void CXFA_FMIfExpression::ToJavaScript(CFX_WideTextBuf& javascript) {
254   javascript << L"if (";
255   if (m_pExpression) {
256     javascript << XFA_FM_EXPTypeToString(GETFMVALUE);
257     javascript << L"(";
258     m_pExpression->ToJavaScript(javascript);
259     javascript << L")";
260   }
261   javascript << L")\n";
262   if (m_pIfExpression) {
263     m_pIfExpression->ToJavaScript(javascript);
264   }
265   if (m_pElseExpression) {
266     if (m_pElseExpression->GetExpType() == XFA_FM_EXPTYPE_IF) {
267       javascript << L"else\n";
268       javascript << L"{\n";
269       m_pElseExpression->ToJavaScript(javascript);
270       javascript << L"}\n";
271     } else {
272       javascript << L"else\n";
273       m_pElseExpression->ToJavaScript(javascript);
274     }
275   }
276 }
277 
ToImpliedReturnJS(CFX_WideTextBuf & javascript)278 void CXFA_FMIfExpression::ToImpliedReturnJS(CFX_WideTextBuf& javascript) {
279   javascript << RUNTIMEFUNCTIONRETURNVALUE;
280   javascript << L" = 0;\n";
281   javascript << L"if (";
282   if (m_pExpression) {
283     javascript << XFA_FM_EXPTypeToString(GETFMVALUE);
284     javascript << L"(";
285     m_pExpression->ToJavaScript(javascript);
286     javascript << L")";
287   }
288   javascript << L")\n";
289   if (m_pIfExpression) {
290     m_pIfExpression->ToImpliedReturnJS(javascript);
291   }
292   if (m_pElseExpression) {
293     if (m_pElseExpression->GetExpType() == XFA_FM_EXPTYPE_IF) {
294       javascript << L"else\n";
295       javascript << L"{\n";
296       m_pElseExpression->ToImpliedReturnJS(javascript);
297       javascript << L"}\n";
298     } else {
299       javascript << L"else\n";
300       m_pElseExpression->ToImpliedReturnJS(javascript);
301     }
302   }
303 }
304 
~CXFA_FMLoopExpression()305 CXFA_FMLoopExpression::~CXFA_FMLoopExpression() {}
306 
ToJavaScript(CFX_WideTextBuf & javascript)307 void CXFA_FMLoopExpression::ToJavaScript(CFX_WideTextBuf& javascript) {}
308 
ToImpliedReturnJS(CFX_WideTextBuf &)309 void CXFA_FMLoopExpression::ToImpliedReturnJS(CFX_WideTextBuf&) {}
310 
CXFA_FMWhileExpression(uint32_t line,std::unique_ptr<CXFA_FMSimpleExpression> pCondition,std::unique_ptr<CXFA_FMExpression> pExpression)311 CXFA_FMWhileExpression::CXFA_FMWhileExpression(
312     uint32_t line,
313     std::unique_ptr<CXFA_FMSimpleExpression> pCondition,
314     std::unique_ptr<CXFA_FMExpression> pExpression)
315     : CXFA_FMLoopExpression(line),
316       m_pCondition(std::move(pCondition)),
317       m_pExpression(std::move(pExpression)) {}
318 
~CXFA_FMWhileExpression()319 CXFA_FMWhileExpression::~CXFA_FMWhileExpression() {}
320 
ToJavaScript(CFX_WideTextBuf & javascript)321 void CXFA_FMWhileExpression::ToJavaScript(CFX_WideTextBuf& javascript) {
322   javascript << L"while (";
323   m_pCondition->ToJavaScript(javascript);
324   javascript << L")\n";
325   m_pExpression->ToJavaScript(javascript);
326 }
327 
ToImpliedReturnJS(CFX_WideTextBuf & javascript)328 void CXFA_FMWhileExpression::ToImpliedReturnJS(CFX_WideTextBuf& javascript) {
329   javascript << RUNTIMEFUNCTIONRETURNVALUE;
330   javascript << L" = 0;\n";
331   javascript << L"while (";
332   m_pCondition->ToJavaScript(javascript);
333   javascript << L")\n";
334   m_pExpression->ToImpliedReturnJS(javascript);
335 }
336 
CXFA_FMBreakExpression(uint32_t line)337 CXFA_FMBreakExpression::CXFA_FMBreakExpression(uint32_t line)
338     : CXFA_FMExpression(line, XFA_FM_EXPTYPE_BREAK) {}
339 
~CXFA_FMBreakExpression()340 CXFA_FMBreakExpression::~CXFA_FMBreakExpression() {}
341 
ToJavaScript(CFX_WideTextBuf & javascript)342 void CXFA_FMBreakExpression::ToJavaScript(CFX_WideTextBuf& javascript) {
343   javascript << RUNTIMEFUNCTIONRETURNVALUE;
344   javascript << L" = 0;\n";
345   javascript << L"break;\n";
346 }
347 
ToImpliedReturnJS(CFX_WideTextBuf & javascript)348 void CXFA_FMBreakExpression::ToImpliedReturnJS(CFX_WideTextBuf& javascript) {
349   javascript << RUNTIMEFUNCTIONRETURNVALUE;
350   javascript << L" = 0;\n";
351   javascript << L"break;\n";
352 }
353 
CXFA_FMContinueExpression(uint32_t line)354 CXFA_FMContinueExpression::CXFA_FMContinueExpression(uint32_t line)
355     : CXFA_FMExpression(line, XFA_FM_EXPTYPE_CONTINUE) {}
356 
~CXFA_FMContinueExpression()357 CXFA_FMContinueExpression::~CXFA_FMContinueExpression() {}
358 
ToJavaScript(CFX_WideTextBuf & javascript)359 void CXFA_FMContinueExpression::ToJavaScript(CFX_WideTextBuf& javascript) {
360   javascript << RUNTIMEFUNCTIONRETURNVALUE;
361   javascript << L" = 0;\n";
362   javascript << L"continue;\n";
363 }
364 
ToImpliedReturnJS(CFX_WideTextBuf & javascript)365 void CXFA_FMContinueExpression::ToImpliedReturnJS(CFX_WideTextBuf& javascript) {
366   javascript << RUNTIMEFUNCTIONRETURNVALUE;
367   javascript << L" = 0;\n";
368   javascript << L"continue;\n";
369 }
370 
CXFA_FMForExpression(uint32_t line,const CFX_WideStringC & 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)371 CXFA_FMForExpression::CXFA_FMForExpression(
372     uint32_t line,
373     const CFX_WideStringC& wsVariant,
374     std::unique_ptr<CXFA_FMSimpleExpression> pAssignment,
375     std::unique_ptr<CXFA_FMSimpleExpression> pAccessor,
376     int32_t iDirection,
377     std::unique_ptr<CXFA_FMSimpleExpression> pStep,
378     std::unique_ptr<CXFA_FMExpression> pList)
379     : CXFA_FMLoopExpression(line),
380       m_wsVariant(wsVariant),
381       m_pAssignment(std::move(pAssignment)),
382       m_pAccessor(std::move(pAccessor)),
383       m_iDirection(iDirection),
384       m_pStep(std::move(pStep)),
385       m_pList(std::move(pList)) {}
386 
~CXFA_FMForExpression()387 CXFA_FMForExpression::~CXFA_FMForExpression() {}
388 
ToJavaScript(CFX_WideTextBuf & javascript)389 void CXFA_FMForExpression::ToJavaScript(CFX_WideTextBuf& javascript) {
390   javascript << L"{\nvar ";
391   CFX_WideString tempVariant;
392   if (m_wsVariant.GetAt(0) == L'!') {
393     tempVariant = EXCLAMATION_IN_IDENTIFIER + m_wsVariant.Mid(1);
394     javascript << tempVariant;
395   } else {
396     tempVariant = m_wsVariant;
397     javascript << m_wsVariant;
398   }
399   javascript << L" = null;\n";
400   javascript << L"for (";
401   javascript << tempVariant;
402   javascript << L" = ";
403   javascript << XFA_FM_EXPTypeToString(GETFMVALUE);
404   javascript << L"(";
405   m_pAssignment->ToJavaScript(javascript);
406   javascript << L"); ";
407   javascript << tempVariant;
408   if (m_iDirection == 1) {
409     javascript << L" <= ";
410     javascript << XFA_FM_EXPTypeToString(GETFMVALUE);
411     javascript << L"(";
412     m_pAccessor->ToJavaScript(javascript);
413     javascript << L"); ";
414     javascript << tempVariant;
415     javascript << L" += ";
416   } else {
417     javascript << L" >= ";
418     javascript << XFA_FM_EXPTypeToString(GETFMVALUE);
419     javascript << L"(";
420     m_pAccessor->ToJavaScript(javascript);
421     javascript << L"); ";
422     javascript << tempVariant;
423     javascript << L" -= ";
424   }
425   if (m_pStep) {
426     javascript << XFA_FM_EXPTypeToString(GETFMVALUE);
427     javascript << L"(";
428     m_pStep->ToJavaScript(javascript);
429     javascript << L")";
430   } else {
431     javascript << L"1";
432   }
433   javascript << L")\n";
434   m_pList->ToJavaScript(javascript);
435   javascript << L"}\n";
436 }
437 
ToImpliedReturnJS(CFX_WideTextBuf & javascript)438 void CXFA_FMForExpression::ToImpliedReturnJS(CFX_WideTextBuf& javascript) {
439   javascript << RUNTIMEFUNCTIONRETURNVALUE;
440   javascript << L" = 0;\n";
441   javascript << L"{\nvar ";
442   CFX_WideString tempVariant;
443   if (m_wsVariant.GetAt(0) == L'!') {
444     tempVariant = EXCLAMATION_IN_IDENTIFIER + m_wsVariant.Mid(1);
445     javascript << tempVariant;
446   } else {
447     tempVariant = m_wsVariant;
448     javascript << m_wsVariant;
449   }
450   javascript << L" = null;\n";
451   javascript << L"for (";
452   javascript << tempVariant;
453   javascript << L" = ";
454   javascript << XFA_FM_EXPTypeToString(GETFMVALUE);
455   javascript << L"(";
456   m_pAssignment->ToJavaScript(javascript);
457   javascript << L"); ";
458   javascript << tempVariant;
459   if (m_iDirection == 1) {
460     javascript << L" <= ";
461     javascript << XFA_FM_EXPTypeToString(GETFMVALUE);
462     javascript << L"(";
463     m_pAccessor->ToJavaScript(javascript);
464     javascript << L"); ";
465     javascript << tempVariant;
466     javascript << L" += ";
467   } else {
468     javascript << L" >= ";
469     javascript << XFA_FM_EXPTypeToString(GETFMVALUE);
470     javascript << L"(";
471     m_pAccessor->ToJavaScript(javascript);
472     javascript << L"); ";
473     javascript << tempVariant;
474     javascript << L" -= ";
475   }
476   if (m_pStep) {
477     javascript << XFA_FM_EXPTypeToString(GETFMVALUE);
478     javascript << L"(";
479     m_pStep->ToJavaScript(javascript);
480     javascript << L")";
481   } else {
482     javascript << L"1";
483   }
484   javascript << L")\n";
485   m_pList->ToImpliedReturnJS(javascript);
486   javascript << L"}\n";
487 }
488 
CXFA_FMForeachExpression(uint32_t line,const CFX_WideStringC & wsIdentifier,std::vector<std::unique_ptr<CXFA_FMSimpleExpression>> && pAccessors,std::unique_ptr<CXFA_FMExpression> pList)489 CXFA_FMForeachExpression::CXFA_FMForeachExpression(
490     uint32_t line,
491     const CFX_WideStringC& wsIdentifier,
492     std::vector<std::unique_ptr<CXFA_FMSimpleExpression>>&& pAccessors,
493     std::unique_ptr<CXFA_FMExpression> pList)
494     : CXFA_FMLoopExpression(line),
495       m_wsIdentifier(wsIdentifier),
496       m_pAccessors(std::move(pAccessors)),
497       m_pList(std::move(pList)) {}
498 
~CXFA_FMForeachExpression()499 CXFA_FMForeachExpression::~CXFA_FMForeachExpression() {}
500 
ToJavaScript(CFX_WideTextBuf & javascript)501 void CXFA_FMForeachExpression::ToJavaScript(CFX_WideTextBuf& javascript) {
502   javascript << L"{\n";
503   javascript << L"var ";
504   if (m_wsIdentifier.GetAt(0) == L'!') {
505     CFX_WideString tempIdentifier =
506         EXCLAMATION_IN_IDENTIFIER + m_wsIdentifier.Mid(1);
507     javascript << tempIdentifier;
508   } else {
509     javascript << m_wsIdentifier;
510   }
511   javascript << L" = null;\n";
512   javascript << L"var ";
513   javascript << RUNTIMEBLOCKTEMPARRAY;
514   javascript << L" = ";
515   javascript << XFA_FM_EXPTypeToString(CONCATFMOBJECT);
516   javascript << L"(";
517 
518   for (const auto& expr : m_pAccessors) {
519     expr->ToJavaScript(javascript);
520     if (expr != m_pAccessors.back())
521       javascript << L", ";
522   }
523   javascript << L");\n";
524   javascript << L"var ";
525   javascript << RUNTIMEBLOCKTEMPARRAYINDEX;
526   javascript << (L" = 0;\n");
527   javascript << L"while(";
528   javascript << RUNTIMEBLOCKTEMPARRAYINDEX;
529   javascript << L" < ";
530   javascript << RUNTIMEBLOCKTEMPARRAY;
531   javascript << L".length)\n{\n";
532   if (m_wsIdentifier.GetAt(0) == L'!') {
533     CFX_WideString tempIdentifier =
534         EXCLAMATION_IN_IDENTIFIER + m_wsIdentifier.Mid(1);
535     javascript << tempIdentifier;
536   } else {
537     javascript << m_wsIdentifier;
538   }
539   javascript << L" = ";
540   javascript << RUNTIMEBLOCKTEMPARRAY;
541   javascript << L"[";
542   javascript << RUNTIMEBLOCKTEMPARRAYINDEX;
543   javascript << L"++];\n";
544   m_pList->ToJavaScript(javascript);
545   javascript << L"}\n";
546   javascript << L"}\n";
547 }
548 
ToImpliedReturnJS(CFX_WideTextBuf & javascript)549 void CXFA_FMForeachExpression::ToImpliedReturnJS(CFX_WideTextBuf& javascript) {
550   javascript << RUNTIMEFUNCTIONRETURNVALUE;
551   javascript << L" = 0;\n";
552   javascript << L"{\n";
553   javascript << L"var ";
554   if (m_wsIdentifier.GetAt(0) == L'!') {
555     CFX_WideString tempIdentifier =
556         EXCLAMATION_IN_IDENTIFIER + m_wsIdentifier.Mid(1);
557     javascript << tempIdentifier;
558   } else {
559     javascript << m_wsIdentifier;
560   }
561   javascript << L" = null;\n";
562   javascript << L"var ";
563   javascript << RUNTIMEBLOCKTEMPARRAY;
564   javascript << L" = ";
565   javascript << XFA_FM_EXPTypeToString(CONCATFMOBJECT);
566   javascript << L"(";
567   for (const auto& expr : m_pAccessors) {
568     expr->ToJavaScript(javascript);
569     if (expr != m_pAccessors.back())
570       javascript << L", ";
571   }
572   javascript << L");\n";
573   javascript << L"var ";
574   javascript << RUNTIMEBLOCKTEMPARRAYINDEX;
575   javascript << L" = 0;\n";
576   javascript << L"while(";
577   javascript << RUNTIMEBLOCKTEMPARRAYINDEX;
578   javascript << L" < ";
579   javascript << RUNTIMEBLOCKTEMPARRAY;
580   javascript << L".length)\n{\n";
581   if (m_wsIdentifier.GetAt(0) == L'!') {
582     CFX_WideString tempIdentifier =
583         EXCLAMATION_IN_IDENTIFIER + m_wsIdentifier.Mid(1);
584     javascript << tempIdentifier;
585   } else {
586     javascript << m_wsIdentifier;
587   }
588   javascript << L" = ";
589   javascript << RUNTIMEBLOCKTEMPARRAY;
590   javascript << L"[";
591   javascript << RUNTIMEBLOCKTEMPARRAYINDEX;
592   javascript << L"++];\n";
593   m_pList->ToImpliedReturnJS(javascript);
594   javascript << L"}\n";
595   javascript << L"}\n";
596 }
597