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