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_simpleexpression.h" 8 9 #include <utility> 10 11 #include "core/fxcrt/fx_ext.h" 12 13 namespace { 14 15 const FX_WCHAR* const gs_lpStrExpFuncName[] = { 16 L"foxit_xfa_formcalc_runtime.assign_value_operator", 17 L"foxit_xfa_formcalc_runtime.logical_or_operator", 18 L"foxit_xfa_formcalc_runtime.logical_and_operator", 19 L"foxit_xfa_formcalc_runtime.equality_operator", 20 L"foxit_xfa_formcalc_runtime.notequality_operator", 21 L"foxit_xfa_formcalc_runtime.less_operator", 22 L"foxit_xfa_formcalc_runtime.lessequal_operator", 23 L"foxit_xfa_formcalc_runtime.greater_operator", 24 L"foxit_xfa_formcalc_runtime.greaterequal_operator", 25 L"foxit_xfa_formcalc_runtime.plus_operator", 26 L"foxit_xfa_formcalc_runtime.minus_operator", 27 L"foxit_xfa_formcalc_runtime.multiple_operator", 28 L"foxit_xfa_formcalc_runtime.divide_operator", 29 L"foxit_xfa_formcalc_runtime.positive_operator", 30 L"foxit_xfa_formcalc_runtime.negative_operator", 31 L"foxit_xfa_formcalc_runtime.logical_not_operator", 32 L"foxit_xfa_formcalc_runtime.", 33 L"foxit_xfa_formcalc_runtime.dot_accessor", 34 L"foxit_xfa_formcalc_runtime.dotdot_accessor", 35 L"foxit_xfa_formcalc_runtime.concat_fm_object", 36 L"foxit_xfa_formcalc_runtime.is_fm_object", 37 L"foxit_xfa_formcalc_runtime.is_fm_array", 38 L"foxit_xfa_formcalc_runtime.get_fm_value", 39 L"foxit_xfa_formcalc_runtime.get_fm_jsobj", 40 L"foxit_xfa_formcalc_runtime.fm_var_filter", 41 }; 42 43 struct XFA_FMBuildInFunc { 44 uint32_t m_uHash; 45 const FX_WCHAR* m_buildinfunc; 46 }; 47 48 const XFA_FMBuildInFunc g_BuildInFuncs[] = { 49 {0x0001f1f5, L"At"}, {0x00020b9c, L"FV"}, 50 {0x00021aef, L"If"}, {0x00023ee6, L"PV"}, 51 {0x04b5c9ee, L"Encode"}, {0x08e96685, L"DateFmt"}, 52 {0x09f99db6, L"Abs"}, {0x09f9e583, L"Apr"}, 53 {0x09fa043e, L"Avg"}, {0x0a9782a0, L"Get"}, 54 {0x0b1b09df, L"Len"}, {0x0b3543a6, L"Max"}, 55 {0x0b356ca4, L"Min"}, {0x0b358b60, L"Mod"}, 56 {0x0b4fded4, L"NPV"}, {0x0b846bf1, L"Pmt"}, 57 {0x0b8494f9, L"Put"}, {0x0bb8df5d, L"Ref"}, 58 {0x0bd37a99, L"Str"}, {0x0bd37fb5, L"Sum"}, 59 {0x1048469b, L"Cterm"}, {0x11e03660, L"Exists"}, 60 {0x126236e6, L"Post"}, {0x127c6661, L"PPmt"}, 61 {0x193ade3e, L"Right"}, {0x1ec8ab2c, L"Rate"}, 62 {0x20e476dc, L"IsoTime2Num"}, {0x23eb6816, L"TimeFmt"}, 63 {0x24fb17b0, L"LocalDateFmt"}, {0x28dee6e9, L"Format"}, 64 {0x2d0890b8, L"Term"}, {0x2d71b00f, L"Time"}, 65 {0x2f890fb1, L"Num2Time"}, {0x3767511d, L"Ceil"}, 66 {0x3ffd1941, L"LocalTimeFmt"}, {0x442f68c8, L"Round"}, 67 {0x46fd1128, L"Eval"}, {0x4d629440, L"Date2Num"}, 68 {0x4dcf25f8, L"Concat"}, {0x4e00255d, L"UnitValue"}, 69 {0x55a5cc29, L"Lower"}, {0x5e43e04c, L"WordNum"}, 70 {0x620ce6ba, L"Ipmt"}, {0x6f544d49, L"Count"}, 71 {0x7e241013, L"Within"}, {0x9b9a6e2b, L"IsoDate2Num"}, 72 {0xb2c941c2, L"UnitType"}, {0xb598a1f7, L"Uuid"}, 73 {0xbde9abde, L"Date"}, {0xc0010b80, L"Num2Date"}, 74 {0xc1f6144c, L"Upper"}, {0xc44028f7, L"Oneof"}, 75 {0xc62c1b2c, L"Space"}, {0xd0ff50f9, L"HasValue"}, 76 {0xd1537042, L"Floor"}, {0xd2ac9cf1, L"Time2Num"}, 77 {0xd907aee5, L"Num2GMTime"}, {0xdf24f7c4, L"Decode"}, 78 {0xe2664803, L"Substr"}, {0xe3e7b528, L"Stuff"}, 79 {0xe6792d4e, L"Rtrim"}, {0xe8c23f5b, L"Parse"}, 80 {0xea18d121, L"Choose"}, {0xebfef69c, L"Replace"}, 81 {0xf5ad782b, L"Left"}, {0xf7bb2248, L"Ltrim"}, 82 }; 83 84 struct XFA_FMSOMMethod { 85 uint32_t m_uHash; 86 const FX_WCHAR* m_wsSomMethodName; 87 uint32_t m_dParameters; 88 }; 89 const XFA_FMSOMMethod gs_FMSomMethods[] = { 90 {0x00000068, L"h", 0x01}, 91 {0x00000077, L"w", 0x01}, 92 {0x00000078, L"x", 0x01}, 93 {0x00000079, L"y", 0x01}, 94 {0x05eb5b0f, L"pageSpan", 0x01}, 95 {0x10f1b1bd, L"page", 0x01}, 96 {0x3bf1c2a5, L"absPageSpan", 0x01}, 97 {0x3c752495, L"verify", 0x0d}, 98 {0x44c352ad, L"formNodes", 0x01}, 99 {0x5775c2cc, L"absPageInBatch", 0x01}, 100 {0x5ee00996, L"setElement", 0x01}, 101 {0x7033bfd5, L"insert", 0x03}, 102 {0x8c5feb32, L"sheetInBatch", 0x01}, 103 {0x8f3a8379, L"sheet", 0x01}, 104 {0x92dada4f, L"saveFilteredXML", 0x01}, 105 {0x9cab7cae, L"remove", 0x01}, 106 {0xa68635f1, L"sign", 0x61}, 107 {0xaac241c8, L"isRecordGroup", 0x01}, 108 {0xd8ed1467, L"clear", 0x01}, 109 {0xda12e518, L"append", 0x01}, 110 {0xe74f0653, L"absPage", 0x01}, 111 }; 112 113 } // namespace 114 115 CFX_WideStringC XFA_FM_EXPTypeToString( 116 XFA_FM_SimpleExpressionType simpleExpType) { 117 return gs_lpStrExpFuncName[simpleExpType]; 118 } 119 120 CXFA_FMSimpleExpression::CXFA_FMSimpleExpression(uint32_t line, XFA_FM_TOKEN op) 121 : m_line(line), m_op(op) {} 122 123 void CXFA_FMSimpleExpression::ToJavaScript(CFX_WideTextBuf& javascript) {} 124 125 void CXFA_FMSimpleExpression::ToImpliedReturnJS(CFX_WideTextBuf& javascript) {} 126 127 XFA_FM_TOKEN CXFA_FMSimpleExpression::GetOperatorToken() const { 128 return m_op; 129 } 130 131 CXFA_FMNullExpression::CXFA_FMNullExpression(uint32_t line) 132 : CXFA_FMSimpleExpression(line, TOKnull) {} 133 134 void CXFA_FMNullExpression::ToJavaScript(CFX_WideTextBuf& javascript) { 135 javascript << L"null"; 136 } 137 138 CXFA_FMNumberExpression::CXFA_FMNumberExpression(uint32_t line, 139 CFX_WideStringC wsNumber) 140 : CXFA_FMSimpleExpression(line, TOKnumber), m_wsNumber(wsNumber) {} 141 142 CXFA_FMNumberExpression::~CXFA_FMNumberExpression() {} 143 144 void CXFA_FMNumberExpression::ToJavaScript(CFX_WideTextBuf& javascript) { 145 javascript << m_wsNumber; 146 } 147 148 CXFA_FMStringExpression::CXFA_FMStringExpression(uint32_t line, 149 CFX_WideStringC wsString) 150 : CXFA_FMSimpleExpression(line, TOKstring), m_wsString(wsString) {} 151 152 CXFA_FMStringExpression::~CXFA_FMStringExpression() {} 153 154 void CXFA_FMStringExpression::ToJavaScript(CFX_WideTextBuf& javascript) { 155 CFX_WideString tempStr(m_wsString); 156 if (tempStr.GetLength() > 2) { 157 javascript.AppendChar(L'\"'); 158 FX_WCHAR oneChar; 159 for (int16_t i = 1; i < tempStr.GetLength() - 1; i++) { 160 oneChar = tempStr[i]; 161 switch (oneChar) { 162 case L'\"': { 163 i++; 164 javascript << L"\\\""; 165 } break; 166 case 0x0d: 167 break; 168 case 0x0a: { 169 javascript << L"\\n"; 170 } break; 171 default: { javascript.AppendChar(oneChar); } break; 172 } 173 } 174 javascript.AppendChar(L'\"'); 175 } else { 176 javascript << tempStr; 177 } 178 } 179 180 CXFA_FMIdentifierExpression::CXFA_FMIdentifierExpression( 181 uint32_t line, 182 CFX_WideStringC wsIdentifier) 183 : CXFA_FMSimpleExpression(line, TOKidentifier), 184 m_wsIdentifier(wsIdentifier) {} 185 186 CXFA_FMIdentifierExpression::~CXFA_FMIdentifierExpression() {} 187 188 void CXFA_FMIdentifierExpression::ToJavaScript(CFX_WideTextBuf& javascript) { 189 CFX_WideString tempStr(m_wsIdentifier); 190 if (tempStr == L"$") { 191 tempStr = L"this"; 192 } else if (tempStr == L"!") { 193 tempStr = L"xfa.datasets"; 194 } else if (tempStr == L"$data") { 195 tempStr = L"xfa.datasets.data"; 196 } else if (tempStr == L"$event") { 197 tempStr = L"xfa.event"; 198 } else if (tempStr == L"$form") { 199 tempStr = L"xfa.form"; 200 } else if (tempStr == L"$host") { 201 tempStr = L"xfa.host"; 202 } else if (tempStr == L"$layout") { 203 tempStr = L"xfa.layout"; 204 } else if (tempStr == L"$template") { 205 tempStr = L"xfa.template"; 206 } else if (tempStr[0] == L'!') { 207 tempStr = EXCLAMATION_IN_IDENTIFIER + tempStr.Mid(1); 208 } 209 javascript << tempStr; 210 } 211 212 CXFA_FMUnaryExpression::CXFA_FMUnaryExpression( 213 uint32_t line, 214 XFA_FM_TOKEN op, 215 std::unique_ptr<CXFA_FMSimpleExpression> pExp) 216 : CXFA_FMSimpleExpression(line, op), m_pExp(std::move(pExp)) {} 217 218 CXFA_FMUnaryExpression::~CXFA_FMUnaryExpression() {} 219 220 void CXFA_FMUnaryExpression::ToJavaScript(CFX_WideTextBuf& javascript) {} 221 222 CXFA_FMBinExpression::CXFA_FMBinExpression( 223 uint32_t line, 224 XFA_FM_TOKEN op, 225 std::unique_ptr<CXFA_FMSimpleExpression> pExp1, 226 std::unique_ptr<CXFA_FMSimpleExpression> pExp2) 227 : CXFA_FMSimpleExpression(line, op), 228 m_pExp1(std::move(pExp1)), 229 m_pExp2(std::move(pExp2)) {} 230 231 CXFA_FMBinExpression::~CXFA_FMBinExpression() {} 232 233 void CXFA_FMBinExpression::ToJavaScript(CFX_WideTextBuf& javascript) {} 234 235 CXFA_FMAssignExpression::CXFA_FMAssignExpression( 236 uint32_t line, 237 XFA_FM_TOKEN op, 238 std::unique_ptr<CXFA_FMSimpleExpression> pExp1, 239 std::unique_ptr<CXFA_FMSimpleExpression> pExp2) 240 : CXFA_FMBinExpression(line, op, std::move(pExp1), std::move(pExp2)) {} 241 242 void CXFA_FMAssignExpression::ToJavaScript(CFX_WideTextBuf& javascript) { 243 javascript << L"if ("; 244 javascript << gs_lpStrExpFuncName[ISFMOBJECT]; 245 javascript << L"("; 246 m_pExp1->ToJavaScript(javascript); 247 javascript << L"))\n{\n"; 248 javascript << gs_lpStrExpFuncName[ASSIGN]; 249 javascript << L"("; 250 m_pExp1->ToJavaScript(javascript); 251 javascript << L", "; 252 m_pExp2->ToJavaScript(javascript); 253 javascript << L");\n}\n"; 254 CFX_WideTextBuf tempExp1; 255 m_pExp1->ToJavaScript(tempExp1); 256 if (m_pExp1->GetOperatorToken() == TOKidentifier && 257 tempExp1.AsStringC() != L"this") { 258 javascript << L"else\n{\n"; 259 javascript << tempExp1; 260 javascript << L" = "; 261 javascript << gs_lpStrExpFuncName[ASSIGN]; 262 javascript << L"("; 263 m_pExp1->ToJavaScript(javascript); 264 javascript << L", "; 265 m_pExp2->ToJavaScript(javascript); 266 javascript << L");\n}\n"; 267 } 268 } 269 270 void CXFA_FMAssignExpression::ToImpliedReturnJS(CFX_WideTextBuf& javascript) { 271 javascript << L"if ("; 272 javascript << gs_lpStrExpFuncName[ISFMOBJECT]; 273 javascript << L"("; 274 m_pExp1->ToJavaScript(javascript); 275 javascript << L"))\n{\n"; 276 javascript << RUNTIMEFUNCTIONRETURNVALUE; 277 javascript << L" = "; 278 javascript << gs_lpStrExpFuncName[ASSIGN]; 279 javascript << L"("; 280 m_pExp1->ToJavaScript(javascript); 281 javascript << L", "; 282 m_pExp2->ToJavaScript(javascript); 283 javascript << L");\n}\n"; 284 CFX_WideTextBuf tempExp1; 285 m_pExp1->ToJavaScript(tempExp1); 286 if (m_pExp1->GetOperatorToken() == TOKidentifier && 287 tempExp1.AsStringC() != L"this") { 288 javascript << L"else\n{\n"; 289 javascript << RUNTIMEFUNCTIONRETURNVALUE; 290 javascript << L" = "; 291 javascript << tempExp1; 292 javascript << L" = "; 293 javascript << gs_lpStrExpFuncName[ASSIGN]; 294 javascript << L"("; 295 m_pExp1->ToJavaScript(javascript); 296 javascript << L", "; 297 m_pExp2->ToJavaScript(javascript); 298 javascript << L");\n}\n"; 299 } 300 } 301 302 CXFA_FMLogicalOrExpression::CXFA_FMLogicalOrExpression( 303 uint32_t line, 304 XFA_FM_TOKEN op, 305 std::unique_ptr<CXFA_FMSimpleExpression> pExp1, 306 std::unique_ptr<CXFA_FMSimpleExpression> pExp2) 307 : CXFA_FMBinExpression(line, op, std::move(pExp1), std::move(pExp2)) {} 308 309 void CXFA_FMLogicalOrExpression::ToJavaScript(CFX_WideTextBuf& javascript) { 310 javascript << gs_lpStrExpFuncName[LOGICALOR]; 311 javascript << L"("; 312 m_pExp1->ToJavaScript(javascript); 313 javascript << L", "; 314 m_pExp2->ToJavaScript(javascript); 315 javascript << L")"; 316 } 317 318 CXFA_FMLogicalAndExpression::CXFA_FMLogicalAndExpression( 319 uint32_t line, 320 XFA_FM_TOKEN op, 321 std::unique_ptr<CXFA_FMSimpleExpression> pExp1, 322 std::unique_ptr<CXFA_FMSimpleExpression> pExp2) 323 : CXFA_FMBinExpression(line, op, std::move(pExp1), std::move(pExp2)) {} 324 325 void CXFA_FMLogicalAndExpression::ToJavaScript(CFX_WideTextBuf& javascript) { 326 javascript << gs_lpStrExpFuncName[LOGICALAND]; 327 javascript << L"("; 328 m_pExp1->ToJavaScript(javascript); 329 javascript << L", "; 330 m_pExp2->ToJavaScript(javascript); 331 javascript << L")"; 332 } 333 334 CXFA_FMEqualityExpression::CXFA_FMEqualityExpression( 335 uint32_t line, 336 XFA_FM_TOKEN op, 337 std::unique_ptr<CXFA_FMSimpleExpression> pExp1, 338 std::unique_ptr<CXFA_FMSimpleExpression> pExp2) 339 : CXFA_FMBinExpression(line, op, std::move(pExp1), std::move(pExp2)) {} 340 341 void CXFA_FMEqualityExpression::ToJavaScript(CFX_WideTextBuf& javascript) { 342 switch (m_op) { 343 case TOKeq: 344 case TOKkseq: 345 javascript << gs_lpStrExpFuncName[EQUALITY]; 346 break; 347 case TOKne: 348 case TOKksne: 349 javascript << gs_lpStrExpFuncName[NOTEQUALITY]; 350 break; 351 default: 352 ASSERT(false); 353 break; 354 } 355 javascript << L"("; 356 m_pExp1->ToJavaScript(javascript); 357 javascript << L", "; 358 m_pExp2->ToJavaScript(javascript); 359 javascript << L")"; 360 } 361 362 CXFA_FMRelationalExpression::CXFA_FMRelationalExpression( 363 uint32_t line, 364 XFA_FM_TOKEN op, 365 std::unique_ptr<CXFA_FMSimpleExpression> pExp1, 366 std::unique_ptr<CXFA_FMSimpleExpression> pExp2) 367 : CXFA_FMBinExpression(line, op, std::move(pExp1), std::move(pExp2)) {} 368 369 void CXFA_FMRelationalExpression::ToJavaScript(CFX_WideTextBuf& javascript) { 370 switch (m_op) { 371 case TOKlt: 372 case TOKkslt: 373 javascript << gs_lpStrExpFuncName[LESS]; 374 break; 375 case TOKgt: 376 case TOKksgt: 377 javascript << gs_lpStrExpFuncName[GREATER]; 378 break; 379 case TOKle: 380 case TOKksle: 381 javascript << gs_lpStrExpFuncName[LESSEQUAL]; 382 break; 383 case TOKge: 384 case TOKksge: 385 javascript << gs_lpStrExpFuncName[GREATEREQUAL]; 386 break; 387 default: 388 ASSERT(false); 389 break; 390 } 391 javascript << L"("; 392 m_pExp1->ToJavaScript(javascript); 393 javascript << L", "; 394 m_pExp2->ToJavaScript(javascript); 395 javascript << L")"; 396 } 397 398 CXFA_FMAdditiveExpression::CXFA_FMAdditiveExpression( 399 uint32_t line, 400 XFA_FM_TOKEN op, 401 std::unique_ptr<CXFA_FMSimpleExpression> pExp1, 402 std::unique_ptr<CXFA_FMSimpleExpression> pExp2) 403 : CXFA_FMBinExpression(line, op, std::move(pExp1), std::move(pExp2)) {} 404 405 void CXFA_FMAdditiveExpression::ToJavaScript(CFX_WideTextBuf& javascript) { 406 switch (m_op) { 407 case TOKplus: 408 javascript << gs_lpStrExpFuncName[PLUS]; 409 break; 410 case TOKminus: 411 javascript << gs_lpStrExpFuncName[MINUS]; 412 break; 413 default: 414 ASSERT(false); 415 break; 416 } 417 javascript << L"("; 418 m_pExp1->ToJavaScript(javascript); 419 javascript << L", "; 420 m_pExp2->ToJavaScript(javascript); 421 javascript << L")"; 422 } 423 424 CXFA_FMMultiplicativeExpression::CXFA_FMMultiplicativeExpression( 425 uint32_t line, 426 XFA_FM_TOKEN op, 427 std::unique_ptr<CXFA_FMSimpleExpression> pExp1, 428 std::unique_ptr<CXFA_FMSimpleExpression> pExp2) 429 : CXFA_FMBinExpression(line, op, std::move(pExp1), std::move(pExp2)) {} 430 431 void CXFA_FMMultiplicativeExpression::ToJavaScript( 432 CFX_WideTextBuf& javascript) { 433 switch (m_op) { 434 case TOKmul: 435 javascript << gs_lpStrExpFuncName[MULTIPLE]; 436 break; 437 case TOKdiv: 438 javascript << gs_lpStrExpFuncName[DIVIDE]; 439 break; 440 default: 441 ASSERT(false); 442 break; 443 } 444 javascript << L"("; 445 m_pExp1->ToJavaScript(javascript); 446 javascript << L", "; 447 m_pExp2->ToJavaScript(javascript); 448 javascript << L")"; 449 } 450 451 CXFA_FMPosExpression::CXFA_FMPosExpression( 452 uint32_t line, 453 std::unique_ptr<CXFA_FMSimpleExpression> pExp) 454 : CXFA_FMUnaryExpression(line, TOKplus, std::move(pExp)) {} 455 456 void CXFA_FMPosExpression::ToJavaScript(CFX_WideTextBuf& javascript) { 457 javascript << gs_lpStrExpFuncName[POSITIVE]; 458 javascript << L"("; 459 m_pExp->ToJavaScript(javascript); 460 javascript << L")"; 461 } 462 463 CXFA_FMNegExpression::CXFA_FMNegExpression( 464 uint32_t line, 465 std::unique_ptr<CXFA_FMSimpleExpression> pExp) 466 : CXFA_FMUnaryExpression(line, TOKminus, std::move(pExp)) {} 467 468 void CXFA_FMNegExpression::ToJavaScript(CFX_WideTextBuf& javascript) { 469 javascript << gs_lpStrExpFuncName[NEGATIVE]; 470 javascript << L"("; 471 m_pExp->ToJavaScript(javascript); 472 javascript << L")"; 473 } 474 475 CXFA_FMNotExpression::CXFA_FMNotExpression( 476 uint32_t line, 477 std::unique_ptr<CXFA_FMSimpleExpression> pExp) 478 : CXFA_FMUnaryExpression(line, TOKksnot, std::move(pExp)) {} 479 480 void CXFA_FMNotExpression::ToJavaScript(CFX_WideTextBuf& javascript) { 481 javascript << gs_lpStrExpFuncName[NOT]; 482 javascript << L"("; 483 m_pExp->ToJavaScript(javascript); 484 javascript << L")"; 485 } 486 487 CXFA_FMCallExpression::CXFA_FMCallExpression( 488 uint32_t line, 489 std::unique_ptr<CXFA_FMSimpleExpression> pExp, 490 std::vector<std::unique_ptr<CXFA_FMSimpleExpression>>&& pArguments, 491 bool bIsSomMethod) 492 : CXFA_FMUnaryExpression(line, TOKcall, std::move(pExp)), 493 m_bIsSomMethod(bIsSomMethod), 494 m_Arguments(std::move(pArguments)) {} 495 496 CXFA_FMCallExpression::~CXFA_FMCallExpression() {} 497 498 bool CXFA_FMCallExpression::IsBuildInFunc(CFX_WideTextBuf* funcName) { 499 uint32_t uHash = FX_HashCode_GetW(funcName->AsStringC(), true); 500 const XFA_FMBuildInFunc* pEnd = g_BuildInFuncs + FX_ArraySize(g_BuildInFuncs); 501 const XFA_FMBuildInFunc* pFunc = 502 std::lower_bound(g_BuildInFuncs, pEnd, uHash, 503 [](const XFA_FMBuildInFunc& func, uint32_t hash) { 504 return func.m_uHash < hash; 505 }); 506 if (pFunc < pEnd && uHash == pFunc->m_uHash) { 507 funcName->Clear(); 508 *funcName << pFunc->m_buildinfunc; 509 return true; 510 } 511 return false; 512 } 513 514 uint32_t CXFA_FMCallExpression::IsMethodWithObjParam( 515 const CFX_WideStringC& methodName) { 516 uint32_t uHash = FX_HashCode_GetW(methodName, false); 517 XFA_FMSOMMethod somMethodWithObjPara; 518 uint32_t parameters = 0x00; 519 int32_t iStart = 0, 520 iEnd = (sizeof(gs_FMSomMethods) / sizeof(gs_FMSomMethods[0])) - 1; 521 int32_t iMid = (iStart + iEnd) / 2; 522 do { 523 iMid = (iStart + iEnd) / 2; 524 somMethodWithObjPara = gs_FMSomMethods[iMid]; 525 if (uHash == somMethodWithObjPara.m_uHash) { 526 parameters = somMethodWithObjPara.m_dParameters; 527 break; 528 } else if (uHash < somMethodWithObjPara.m_uHash) { 529 iEnd = iMid - 1; 530 } else { 531 iStart = iMid + 1; 532 } 533 } while (iStart <= iEnd); 534 return parameters; 535 } 536 537 void CXFA_FMCallExpression::ToJavaScript(CFX_WideTextBuf& javascript) { 538 CFX_WideTextBuf funcName; 539 m_pExp->ToJavaScript(funcName); 540 if (m_bIsSomMethod) { 541 javascript << funcName; 542 javascript << L"("; 543 uint32_t methodPara = IsMethodWithObjParam(funcName.AsStringC()); 544 if (methodPara > 0) { 545 for (size_t i = 0; i < m_Arguments.size(); ++i) { 546 // Currently none of our expressions use objects for a parameter over 547 // the 6th. Make sure we don't overflow the shift when doing this 548 // check. If we ever need more the 32 object params we can revisit. 549 if (i < 32 && (methodPara & (0x01 << i)) > 0) { 550 javascript << gs_lpStrExpFuncName[GETFMJSOBJ]; 551 } else { 552 javascript << gs_lpStrExpFuncName[GETFMVALUE]; 553 } 554 javascript << L"("; 555 const auto& expr = m_Arguments[i]; 556 expr->ToJavaScript(javascript); 557 javascript << L")"; 558 if (i + 1 < m_Arguments.size()) { 559 javascript << L", "; 560 } 561 } 562 } else { 563 for (const auto& expr : m_Arguments) { 564 javascript << gs_lpStrExpFuncName[GETFMVALUE]; 565 javascript << L"("; 566 expr->ToJavaScript(javascript); 567 javascript << L")"; 568 if (expr != m_Arguments.back()) 569 javascript << L", "; 570 } 571 } 572 javascript << L")"; 573 } else { 574 bool isEvalFunc = false; 575 bool isExistsFunc = false; 576 if (IsBuildInFunc(&funcName)) { 577 if (funcName.AsStringC() == L"Eval") { 578 isEvalFunc = true; 579 javascript << L"eval.call(this, "; 580 javascript << gs_lpStrExpFuncName[CALL]; 581 javascript << L"Translate"; 582 } else if (funcName.AsStringC() == L"Exists") { 583 isExistsFunc = true; 584 javascript << gs_lpStrExpFuncName[CALL]; 585 javascript << funcName; 586 } else { 587 javascript << gs_lpStrExpFuncName[CALL]; 588 javascript << funcName; 589 } 590 } else { 591 javascript << funcName; 592 } 593 javascript << L"("; 594 if (isExistsFunc) { 595 javascript << L"\n(\nfunction ()\n{\ntry\n{\n"; 596 if (!m_Arguments.empty()) { 597 const auto& expr = m_Arguments[0]; 598 javascript << L"return "; 599 expr->ToJavaScript(javascript); 600 javascript << L";\n}\n"; 601 } else { 602 javascript << L"return 0;\n}\n"; 603 } 604 javascript 605 << L"catch(accessExceptions)\n{\nreturn 0;\n}\n}\n).call(this)\n"; 606 } else { 607 for (const auto& expr : m_Arguments) { 608 expr->ToJavaScript(javascript); 609 if (expr != m_Arguments.back()) 610 javascript << L", "; 611 } 612 } 613 javascript << L")"; 614 if (isEvalFunc) { 615 javascript << L")"; 616 } 617 } 618 } 619 620 CXFA_FMDotAccessorExpression::CXFA_FMDotAccessorExpression( 621 uint32_t line, 622 std::unique_ptr<CXFA_FMSimpleExpression> pAccessor, 623 XFA_FM_TOKEN op, 624 CFX_WideStringC wsIdentifier, 625 std::unique_ptr<CXFA_FMSimpleExpression> pIndexExp) 626 : CXFA_FMBinExpression(line, 627 op, 628 std::move(pAccessor), 629 std::move(pIndexExp)), 630 m_wsIdentifier(wsIdentifier) {} 631 632 CXFA_FMDotAccessorExpression::~CXFA_FMDotAccessorExpression() {} 633 634 void CXFA_FMDotAccessorExpression::ToJavaScript(CFX_WideTextBuf& javascript) { 635 javascript << gs_lpStrExpFuncName[DOT]; 636 javascript << L"("; 637 if (m_pExp1) { 638 m_pExp1->ToJavaScript(javascript); 639 } else { 640 javascript << L"null"; 641 } 642 javascript << L", "; 643 javascript << L"\""; 644 if (m_pExp1 && m_pExp1->GetOperatorToken() == TOKidentifier) { 645 m_pExp1->ToJavaScript(javascript); 646 } 647 javascript << L"\", "; 648 if (m_op == TOKdotscream) { 649 javascript << L"\"#"; 650 javascript << m_wsIdentifier; 651 javascript << L"\", "; 652 } else if (m_op == TOKdotstar) { 653 javascript << L"\"*\", "; 654 } else if (m_op == TOKcall) { 655 javascript << L"\"\", "; 656 } else { 657 javascript << L"\""; 658 javascript << m_wsIdentifier; 659 javascript << L"\", "; 660 } 661 m_pExp2->ToJavaScript(javascript); 662 javascript << L")"; 663 } 664 665 CXFA_FMIndexExpression::CXFA_FMIndexExpression( 666 uint32_t line, 667 XFA_FM_AccessorIndex accessorIndex, 668 std::unique_ptr<CXFA_FMSimpleExpression> pIndexExp, 669 bool bIsStarIndex) 670 : CXFA_FMUnaryExpression(line, TOKlbracket, std::move(pIndexExp)), 671 m_accessorIndex(accessorIndex), 672 m_bIsStarIndex(bIsStarIndex) {} 673 674 void CXFA_FMIndexExpression::ToJavaScript(CFX_WideTextBuf& javascript) { 675 switch (m_accessorIndex) { 676 case ACCESSOR_NO_INDEX: 677 javascript << L"0"; 678 break; 679 case ACCESSOR_NO_RELATIVEINDEX: 680 javascript << L"1"; 681 break; 682 case ACCESSOR_POSITIVE_INDEX: 683 javascript << L"2"; 684 break; 685 case ACCESSOR_NEGATIVE_INDEX: 686 javascript << L"3"; 687 break; 688 default: 689 javascript << L"0"; 690 } 691 if (!m_bIsStarIndex) { 692 javascript << L", "; 693 if (m_pExp) { 694 m_pExp->ToJavaScript(javascript); 695 } else { 696 javascript << L"0"; 697 } 698 } 699 } 700 701 CXFA_FMDotDotAccessorExpression::CXFA_FMDotDotAccessorExpression( 702 uint32_t line, 703 std::unique_ptr<CXFA_FMSimpleExpression> pAccessor, 704 XFA_FM_TOKEN op, 705 CFX_WideStringC wsIdentifier, 706 std::unique_ptr<CXFA_FMSimpleExpression> pIndexExp) 707 : CXFA_FMBinExpression(line, 708 op, 709 std::move(pAccessor), 710 std::move(pIndexExp)), 711 m_wsIdentifier(wsIdentifier) {} 712 713 CXFA_FMDotDotAccessorExpression::~CXFA_FMDotDotAccessorExpression() {} 714 715 void CXFA_FMDotDotAccessorExpression::ToJavaScript( 716 CFX_WideTextBuf& javascript) { 717 javascript << gs_lpStrExpFuncName[DOTDOT]; 718 javascript << L"("; 719 m_pExp1->ToJavaScript(javascript); 720 javascript << L", "; 721 javascript << L"\""; 722 if (m_pExp1 && m_pExp1->GetOperatorToken() == TOKidentifier) { 723 m_pExp1->ToJavaScript(javascript); 724 } 725 javascript << L"\", "; 726 javascript << L"\""; 727 javascript << m_wsIdentifier; 728 javascript << L"\", "; 729 m_pExp2->ToJavaScript(javascript); 730 javascript << L")"; 731 } 732 733 CXFA_FMMethodCallExpression::CXFA_FMMethodCallExpression( 734 uint32_t line, 735 std::unique_ptr<CXFA_FMSimpleExpression> pAccessorExp1, 736 std::unique_ptr<CXFA_FMSimpleExpression> pCallExp) 737 : CXFA_FMBinExpression(line, 738 TOKdot, 739 std::move(pAccessorExp1), 740 std::move(pCallExp)) {} 741 742 void CXFA_FMMethodCallExpression::ToJavaScript(CFX_WideTextBuf& javascript) { 743 javascript << L"(\nfunction ()\n{\n"; 744 javascript << L"var method_return_value = null;\n"; 745 javascript << L"var accessor_object = "; 746 m_pExp1->ToJavaScript(javascript); 747 javascript << L";\n"; 748 javascript << L"if ("; 749 javascript << gs_lpStrExpFuncName[ISFMARRAY]; 750 javascript << L"(accessor_object))\n{\n"; 751 javascript << L"for(var index = accessor_object.length - 1; index > 1; " 752 L"index--)\n{\n"; 753 javascript << L"method_return_value = accessor_object[index]."; 754 m_pExp2->ToJavaScript(javascript); 755 javascript << L";\n}\n}\n"; 756 javascript << L"else\n{\nmethod_return_value = accessor_object."; 757 m_pExp2->ToJavaScript(javascript); 758 javascript << L";\n}\n"; 759 javascript << L"return method_return_value;\n"; 760 javascript << L"}\n).call(this)"; 761 } 762