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