• 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/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