Home | History | Annotate | Download | only in fm2js
      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 
     28 CXFA_FMExpression::CXFA_FMExpression(uint32_t line)
     29     : m_type(XFA_FM_EXPTYPE_UNKNOWN), m_line(line) {}
     30 
     31 CXFA_FMExpression::CXFA_FMExpression(uint32_t line, XFA_FM_EXPTYPE type)
     32     : m_type(type), m_line(line) {}
     33 
     34 bool CXFA_FMExpression::ToJavaScript(CFX_WideTextBuf& javascript) {
     35   CXFA_FMToJavaScriptDepth depthManager;
     36   return !CXFA_IsTooBig(javascript) && depthManager.IsWithinMaxDepth();
     37 }
     38 
     39 bool CXFA_FMExpression::ToImpliedReturnJS(CFX_WideTextBuf& javascript) {
     40   CXFA_FMToJavaScriptDepth depthManager;
     41   return !CXFA_IsTooBig(javascript) && depthManager.IsWithinMaxDepth();
     42 }
     43 
     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 
     56 CXFA_FMFunctionDefinition::~CXFA_FMFunctionDefinition() {}
     57 
     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 
    122 bool CXFA_FMFunctionDefinition::ToImpliedReturnJS(CFX_WideTextBuf& javascript) {
    123   CXFA_FMToJavaScriptDepth depthManager;
    124   return !CXFA_IsTooBig(javascript) && depthManager.IsWithinMaxDepth();
    125 }
    126 
    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 
    135 CXFA_FMVarExpression::~CXFA_FMVarExpression() {}
    136 
    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 
    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 
    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 
    203 CXFA_FMExpExpression::~CXFA_FMExpExpression() {}
    204 
    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 
    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 
    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 
    253 CXFA_FMBlockExpression::~CXFA_FMBlockExpression() {}
    254 
    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 
    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 
    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 
    294 CXFA_FMDoExpression::~CXFA_FMDoExpression() {}
    295 
    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 
    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 
    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 
    322 CXFA_FMIfExpression::~CXFA_FMIfExpression() {}
    323 
    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 
    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 
    405 CXFA_FMLoopExpression::~CXFA_FMLoopExpression() {}
    406 
    407 bool CXFA_FMLoopExpression::ToJavaScript(CFX_WideTextBuf& javascript) {
    408   CXFA_FMToJavaScriptDepth depthManager;
    409   return !CXFA_IsTooBig(javascript) && depthManager.IsWithinMaxDepth();
    410 }
    411 
    412 bool CXFA_FMLoopExpression::ToImpliedReturnJS(CFX_WideTextBuf& javascript) {
    413   CXFA_FMToJavaScriptDepth depthManager;
    414   return !CXFA_IsTooBig(javascript) && depthManager.IsWithinMaxDepth();
    415 }
    416 
    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 
    425 CXFA_FMWhileExpression::~CXFA_FMWhileExpression() {}
    426 
    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 
    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 
    463 CXFA_FMBreakExpression::CXFA_FMBreakExpression(uint32_t line)
    464     : CXFA_FMExpression(line, XFA_FM_EXPTYPE_BREAK) {}
    465 
    466 CXFA_FMBreakExpression::~CXFA_FMBreakExpression() {}
    467 
    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 
    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 
    490 CXFA_FMContinueExpression::CXFA_FMContinueExpression(uint32_t line)
    491     : CXFA_FMExpression(line, XFA_FM_EXPTYPE_CONTINUE) {}
    492 
    493 CXFA_FMContinueExpression::~CXFA_FMContinueExpression() {}
    494 
    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 
    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 
    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 
    533 CXFA_FMForExpression::~CXFA_FMForExpression() {}
    534 
    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 
    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 
    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 
    656 CXFA_FMForeachExpression::~CXFA_FMForeachExpression() {}
    657 
    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 
    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