693 lines
22 KiB
C++
693 lines
22 KiB
C++
// Copyright 2014 PDFium Authors. All rights reserved.
|
|
// Use of this source code is governed by a BSD-style license that can be
|
|
// found in the LICENSE file.
|
|
|
|
// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
|
|
|
|
#include "xfa/fxfa/fm2js/cxfa_fmsimpleexpression.h"
|
|
|
|
#include <algorithm>
|
|
#include <utility>
|
|
|
|
#include "core/fxcrt/autorestorer.h"
|
|
#include "core/fxcrt/cfx_widetextbuf.h"
|
|
#include "core/fxcrt/fx_extension.h"
|
|
#include "third_party/base/logging.h"
|
|
#include "xfa/fxfa/fm2js/cxfa_fmtojavascriptdepth.h"
|
|
|
|
namespace {
|
|
|
|
const wchar_t* const g_BuiltInFuncs[] = {
|
|
L"Abs", L"Apr", L"At", L"Avg",
|
|
L"Ceil", L"Choose", L"Concat", L"Count",
|
|
L"Cterm", L"Date", L"Date2Num", L"DateFmt",
|
|
L"Decode", L"Encode", L"Eval", L"Exists",
|
|
L"Floor", L"Format", L"FV", L"Get",
|
|
L"HasValue", L"If", L"Ipmt", L"IsoDate2Num",
|
|
L"IsoTime2Num", L"Left", L"Len", L"LocalDateFmt",
|
|
L"LocalTimeFmt", L"Lower", L"Ltrim", L"Max",
|
|
L"Min", L"Mod", L"NPV", L"Num2Date",
|
|
L"Num2GMTime", L"Num2Time", L"Oneof", L"Parse",
|
|
L"Pmt", L"Post", L"PPmt", L"Put",
|
|
L"PV", L"Rate", L"Ref", L"Replace",
|
|
L"Right", L"Round", L"Rtrim", L"Space",
|
|
L"Str", L"Stuff", L"Substr", L"Sum",
|
|
L"Term", L"Time", L"Time2Num", L"TimeFmt",
|
|
L"UnitType", L"UnitValue", L"Upper", L"Uuid",
|
|
L"Within", L"WordNum",
|
|
};
|
|
|
|
const size_t g_BuiltInFuncsMaxLen = 12;
|
|
|
|
struct XFA_FMSOMMethod {
|
|
const wchar_t* m_wsSomMethodName;
|
|
uint32_t m_dParameters;
|
|
};
|
|
|
|
const XFA_FMSOMMethod gs_FMSomMethods[] = {
|
|
{L"absPage", 0x01},
|
|
{L"absPageInBatch", 0x01},
|
|
{L"absPageSpan", 0x01},
|
|
{L"append", 0x01},
|
|
{L"clear", 0x01},
|
|
{L"formNodes", 0x01},
|
|
{L"h", 0x01},
|
|
{L"insert", 0x03},
|
|
{L"isRecordGroup", 0x01},
|
|
{L"page", 0x01},
|
|
{L"pageSpan", 0x01},
|
|
{L"remove", 0x01},
|
|
{L"saveFilteredXML", 0x01},
|
|
{L"setElement", 0x01},
|
|
{L"sheet", 0x01},
|
|
{L"sheetInBatch", 0x01},
|
|
{L"sign", 0x61},
|
|
{L"verify", 0x0d},
|
|
{L"w", 0x01},
|
|
{L"x", 0x01},
|
|
{L"y", 0x01},
|
|
};
|
|
|
|
} // namespace
|
|
|
|
CXFA_FMSimpleExpression::CXFA_FMSimpleExpression(XFA_FM_TOKEN op) : m_op(op) {}
|
|
|
|
XFA_FM_TOKEN CXFA_FMSimpleExpression::GetOperatorToken() const {
|
|
return m_op;
|
|
}
|
|
|
|
CXFA_FMNullExpression::CXFA_FMNullExpression()
|
|
: CXFA_FMSimpleExpression(TOKnull) {}
|
|
|
|
bool CXFA_FMNullExpression::ToJavaScript(CFX_WideTextBuf* js, ReturnType type) {
|
|
CXFA_FMToJavaScriptDepth depthManager;
|
|
if (CXFA_IsTooBig(js) || !depthManager.IsWithinMaxDepth())
|
|
return false;
|
|
|
|
*js << "null";
|
|
return !CXFA_IsTooBig(js);
|
|
}
|
|
|
|
CXFA_FMNumberExpression::CXFA_FMNumberExpression(WideStringView wsNumber)
|
|
: CXFA_FMSimpleExpression(TOKnumber), m_wsNumber(wsNumber) {}
|
|
|
|
CXFA_FMNumberExpression::~CXFA_FMNumberExpression() = default;
|
|
|
|
bool CXFA_FMNumberExpression::ToJavaScript(CFX_WideTextBuf* js,
|
|
ReturnType type) {
|
|
CXFA_FMToJavaScriptDepth depthManager;
|
|
if (CXFA_IsTooBig(js) || !depthManager.IsWithinMaxDepth())
|
|
return false;
|
|
|
|
*js << m_wsNumber;
|
|
return !CXFA_IsTooBig(js);
|
|
}
|
|
|
|
CXFA_FMStringExpression::CXFA_FMStringExpression(WideStringView wsString)
|
|
: CXFA_FMSimpleExpression(TOKstring), m_wsString(wsString) {}
|
|
|
|
CXFA_FMStringExpression::~CXFA_FMStringExpression() = default;
|
|
|
|
bool CXFA_FMStringExpression::ToJavaScript(CFX_WideTextBuf* js,
|
|
ReturnType type) {
|
|
CXFA_FMToJavaScriptDepth depthManager;
|
|
if (CXFA_IsTooBig(js) || !depthManager.IsWithinMaxDepth())
|
|
return false;
|
|
|
|
WideString tempStr(m_wsString);
|
|
if (tempStr.GetLength() <= 2) {
|
|
*js << tempStr;
|
|
return !CXFA_IsTooBig(js);
|
|
}
|
|
|
|
*js << "\"";
|
|
for (size_t i = 1; i < tempStr.GetLength() - 1; i++) {
|
|
wchar_t oneChar = tempStr[i];
|
|
switch (oneChar) {
|
|
case L'\"':
|
|
++i;
|
|
*js << "\\\"";
|
|
break;
|
|
case 0x0d:
|
|
break;
|
|
case 0x0a:
|
|
*js << "\\n";
|
|
break;
|
|
default:
|
|
js->AppendChar(oneChar);
|
|
break;
|
|
}
|
|
}
|
|
*js << "\"";
|
|
return !CXFA_IsTooBig(js);
|
|
}
|
|
|
|
CXFA_FMIdentifierExpression::CXFA_FMIdentifierExpression(
|
|
WideStringView wsIdentifier)
|
|
: CXFA_FMSimpleExpression(TOKidentifier), m_wsIdentifier(wsIdentifier) {}
|
|
|
|
CXFA_FMIdentifierExpression::~CXFA_FMIdentifierExpression() = default;
|
|
|
|
bool CXFA_FMIdentifierExpression::ToJavaScript(CFX_WideTextBuf* js,
|
|
ReturnType type) {
|
|
CXFA_FMToJavaScriptDepth depthManager;
|
|
if (CXFA_IsTooBig(js) || !depthManager.IsWithinMaxDepth())
|
|
return false;
|
|
|
|
if (m_wsIdentifier.EqualsASCII("$"))
|
|
*js << "this";
|
|
else if (m_wsIdentifier.EqualsASCII("!"))
|
|
*js << "xfa.datasets";
|
|
else if (m_wsIdentifier.EqualsASCII("$data"))
|
|
*js << "xfa.datasets.data";
|
|
else if (m_wsIdentifier.EqualsASCII("$event"))
|
|
*js << "xfa.event";
|
|
else if (m_wsIdentifier.EqualsASCII("$form"))
|
|
*js << "xfa.form";
|
|
else if (m_wsIdentifier.EqualsASCII("$host"))
|
|
*js << "xfa.host";
|
|
else if (m_wsIdentifier.EqualsASCII("$layout"))
|
|
*js << "xfa.layout";
|
|
else if (m_wsIdentifier.EqualsASCII("$template"))
|
|
*js << "xfa.template";
|
|
else if (m_wsIdentifier[0] == L'!')
|
|
*js << "pfm__excl__" << m_wsIdentifier.Last(m_wsIdentifier.GetLength() - 1);
|
|
else
|
|
*js << m_wsIdentifier;
|
|
|
|
return !CXFA_IsTooBig(js);
|
|
}
|
|
|
|
CXFA_FMAssignExpression::CXFA_FMAssignExpression(
|
|
XFA_FM_TOKEN op,
|
|
std::unique_ptr<CXFA_FMSimpleExpression> pExp1,
|
|
std::unique_ptr<CXFA_FMSimpleExpression> pExp2)
|
|
: CXFA_FMSimpleExpression(op),
|
|
m_pExp1(std::move(pExp1)),
|
|
m_pExp2(std::move(pExp2)) {}
|
|
|
|
CXFA_FMAssignExpression::~CXFA_FMAssignExpression() = default;
|
|
|
|
bool CXFA_FMAssignExpression::ToJavaScript(CFX_WideTextBuf* js,
|
|
ReturnType type) {
|
|
CXFA_FMToJavaScriptDepth depthManager;
|
|
if (CXFA_IsTooBig(js) || !depthManager.IsWithinMaxDepth())
|
|
return false;
|
|
|
|
CFX_WideTextBuf tempExp1;
|
|
if (!m_pExp1->ToJavaScript(&tempExp1, ReturnType::kInfered))
|
|
return false;
|
|
|
|
*js << "if (pfm_rt.is_obj(" << tempExp1 << "))\n{\n";
|
|
if (type == ReturnType::kImplied)
|
|
*js << "pfm_ret = ";
|
|
|
|
CFX_WideTextBuf tempExp2;
|
|
if (!m_pExp2->ToJavaScript(&tempExp2, ReturnType::kInfered))
|
|
return false;
|
|
|
|
*js << "pfm_rt.asgn_val_op(" << tempExp1 << ", " << tempExp2 << ");\n}\n";
|
|
|
|
if (m_pExp1->GetOperatorToken() == TOKidentifier &&
|
|
!tempExp1.AsStringView().EqualsASCII("this")) {
|
|
*js << "else\n{\n";
|
|
if (type == ReturnType::kImplied)
|
|
*js << "pfm_ret = ";
|
|
|
|
*js << tempExp1 << " = pfm_rt.asgn_val_op";
|
|
*js << "(" << tempExp1 << ", " << tempExp2 << ");\n";
|
|
*js << "}\n";
|
|
}
|
|
return !CXFA_IsTooBig(js);
|
|
}
|
|
|
|
CXFA_FMBinExpression::CXFA_FMBinExpression(
|
|
const WideString& opName,
|
|
XFA_FM_TOKEN op,
|
|
std::unique_ptr<CXFA_FMSimpleExpression> pExp1,
|
|
std::unique_ptr<CXFA_FMSimpleExpression> pExp2)
|
|
: CXFA_FMSimpleExpression(op),
|
|
m_OpName(opName),
|
|
m_pExp1(std::move(pExp1)),
|
|
m_pExp2(std::move(pExp2)) {}
|
|
|
|
CXFA_FMBinExpression::~CXFA_FMBinExpression() = default;
|
|
|
|
bool CXFA_FMBinExpression::ToJavaScript(CFX_WideTextBuf* js, ReturnType type) {
|
|
CXFA_FMToJavaScriptDepth depthManager;
|
|
if (CXFA_IsTooBig(js) || !depthManager.IsWithinMaxDepth())
|
|
return false;
|
|
|
|
*js << "pfm_rt." << m_OpName << "(";
|
|
if (!m_pExp1->ToJavaScript(js, ReturnType::kInfered))
|
|
return false;
|
|
*js << ", ";
|
|
if (!m_pExp2->ToJavaScript(js, ReturnType::kInfered))
|
|
return false;
|
|
*js << ")";
|
|
return !CXFA_IsTooBig(js);
|
|
}
|
|
|
|
CXFA_FMLogicalOrExpression::CXFA_FMLogicalOrExpression(
|
|
XFA_FM_TOKEN op,
|
|
std::unique_ptr<CXFA_FMSimpleExpression> pExp1,
|
|
std::unique_ptr<CXFA_FMSimpleExpression> pExp2)
|
|
: CXFA_FMBinExpression(L"log_or_op",
|
|
op,
|
|
std::move(pExp1),
|
|
std::move(pExp2)) {}
|
|
|
|
CXFA_FMLogicalAndExpression::CXFA_FMLogicalAndExpression(
|
|
XFA_FM_TOKEN op,
|
|
std::unique_ptr<CXFA_FMSimpleExpression> pExp1,
|
|
std::unique_ptr<CXFA_FMSimpleExpression> pExp2)
|
|
: CXFA_FMBinExpression(L"log_and_op",
|
|
op,
|
|
std::move(pExp1),
|
|
std::move(pExp2)) {}
|
|
|
|
CXFA_FMEqualExpression::CXFA_FMEqualExpression(
|
|
XFA_FM_TOKEN op,
|
|
std::unique_ptr<CXFA_FMSimpleExpression> pExp1,
|
|
std::unique_ptr<CXFA_FMSimpleExpression> pExp2)
|
|
: CXFA_FMBinExpression(L"eq_op",
|
|
op,
|
|
std::move(pExp1),
|
|
std::move(pExp2)) {}
|
|
|
|
CXFA_FMNotEqualExpression::CXFA_FMNotEqualExpression(
|
|
XFA_FM_TOKEN op,
|
|
std::unique_ptr<CXFA_FMSimpleExpression> pExp1,
|
|
std::unique_ptr<CXFA_FMSimpleExpression> pExp2)
|
|
: CXFA_FMBinExpression(L"neq_op",
|
|
op,
|
|
std::move(pExp1),
|
|
std::move(pExp2)) {}
|
|
|
|
CXFA_FMGtExpression::CXFA_FMGtExpression(
|
|
XFA_FM_TOKEN op,
|
|
std::unique_ptr<CXFA_FMSimpleExpression> pExp1,
|
|
std::unique_ptr<CXFA_FMSimpleExpression> pExp2)
|
|
: CXFA_FMBinExpression(L"gt_op",
|
|
op,
|
|
std::move(pExp1),
|
|
std::move(pExp2)) {}
|
|
|
|
CXFA_FMGeExpression::CXFA_FMGeExpression(
|
|
XFA_FM_TOKEN op,
|
|
std::unique_ptr<CXFA_FMSimpleExpression> pExp1,
|
|
std::unique_ptr<CXFA_FMSimpleExpression> pExp2)
|
|
: CXFA_FMBinExpression(L"ge_op",
|
|
op,
|
|
std::move(pExp1),
|
|
std::move(pExp2)) {}
|
|
|
|
CXFA_FMLtExpression::CXFA_FMLtExpression(
|
|
XFA_FM_TOKEN op,
|
|
std::unique_ptr<CXFA_FMSimpleExpression> pExp1,
|
|
std::unique_ptr<CXFA_FMSimpleExpression> pExp2)
|
|
: CXFA_FMBinExpression(L"lt_op",
|
|
op,
|
|
std::move(pExp1),
|
|
std::move(pExp2)) {}
|
|
|
|
CXFA_FMLeExpression::CXFA_FMLeExpression(
|
|
XFA_FM_TOKEN op,
|
|
std::unique_ptr<CXFA_FMSimpleExpression> pExp1,
|
|
std::unique_ptr<CXFA_FMSimpleExpression> pExp2)
|
|
: CXFA_FMBinExpression(L"le_op",
|
|
op,
|
|
std::move(pExp1),
|
|
std::move(pExp2)) {}
|
|
|
|
CXFA_FMPlusExpression::CXFA_FMPlusExpression(
|
|
XFA_FM_TOKEN op,
|
|
std::unique_ptr<CXFA_FMSimpleExpression> pExp1,
|
|
std::unique_ptr<CXFA_FMSimpleExpression> pExp2)
|
|
: CXFA_FMBinExpression(L"plus_op",
|
|
op,
|
|
std::move(pExp1),
|
|
std::move(pExp2)) {}
|
|
|
|
CXFA_FMMinusExpression::CXFA_FMMinusExpression(
|
|
XFA_FM_TOKEN op,
|
|
std::unique_ptr<CXFA_FMSimpleExpression> pExp1,
|
|
std::unique_ptr<CXFA_FMSimpleExpression> pExp2)
|
|
: CXFA_FMBinExpression(L"minus_op",
|
|
op,
|
|
std::move(pExp1),
|
|
std::move(pExp2)) {}
|
|
|
|
CXFA_FMMulExpression::CXFA_FMMulExpression(
|
|
XFA_FM_TOKEN op,
|
|
std::unique_ptr<CXFA_FMSimpleExpression> pExp1,
|
|
std::unique_ptr<CXFA_FMSimpleExpression> pExp2)
|
|
: CXFA_FMBinExpression(L"mul_op",
|
|
op,
|
|
std::move(pExp1),
|
|
std::move(pExp2)) {}
|
|
|
|
CXFA_FMDivExpression::CXFA_FMDivExpression(
|
|
XFA_FM_TOKEN op,
|
|
std::unique_ptr<CXFA_FMSimpleExpression> pExp1,
|
|
std::unique_ptr<CXFA_FMSimpleExpression> pExp2)
|
|
: CXFA_FMBinExpression(L"div_op",
|
|
op,
|
|
std::move(pExp1),
|
|
std::move(pExp2)) {}
|
|
|
|
CXFA_FMUnaryExpression::CXFA_FMUnaryExpression(
|
|
const WideString& opName,
|
|
XFA_FM_TOKEN op,
|
|
std::unique_ptr<CXFA_FMSimpleExpression> pExp)
|
|
: CXFA_FMSimpleExpression(op), m_OpName(opName), m_pExp(std::move(pExp)) {}
|
|
|
|
CXFA_FMUnaryExpression::~CXFA_FMUnaryExpression() = default;
|
|
|
|
bool CXFA_FMUnaryExpression::ToJavaScript(CFX_WideTextBuf* js,
|
|
ReturnType type) {
|
|
CXFA_FMToJavaScriptDepth depthManager;
|
|
if (CXFA_IsTooBig(js) || !depthManager.IsWithinMaxDepth())
|
|
return false;
|
|
|
|
*js << "pfm_rt." << m_OpName.c_str() << "(";
|
|
if (!m_pExp->ToJavaScript(js, ReturnType::kInfered))
|
|
return false;
|
|
*js << ")";
|
|
return !CXFA_IsTooBig(js);
|
|
}
|
|
|
|
CXFA_FMPosExpression::CXFA_FMPosExpression(
|
|
std::unique_ptr<CXFA_FMSimpleExpression> pExp)
|
|
: CXFA_FMUnaryExpression(L"pos_op", TOKplus, std::move(pExp)) {}
|
|
|
|
CXFA_FMNegExpression::CXFA_FMNegExpression(
|
|
std::unique_ptr<CXFA_FMSimpleExpression> pExp)
|
|
: CXFA_FMUnaryExpression(L"neg_op", TOKminus, std::move(pExp)) {}
|
|
|
|
CXFA_FMNotExpression::CXFA_FMNotExpression(
|
|
std::unique_ptr<CXFA_FMSimpleExpression> pExp)
|
|
: CXFA_FMUnaryExpression(L"log_not_op", TOKksnot, std::move(pExp)) {}
|
|
|
|
CXFA_FMCallExpression::CXFA_FMCallExpression(
|
|
std::unique_ptr<CXFA_FMSimpleExpression> pExp,
|
|
std::vector<std::unique_ptr<CXFA_FMSimpleExpression>>&& pArguments,
|
|
bool bIsSomMethod)
|
|
: CXFA_FMSimpleExpression(TOKcall),
|
|
m_pExp(std::move(pExp)),
|
|
m_bIsSomMethod(bIsSomMethod),
|
|
m_Arguments(std::move(pArguments)) {}
|
|
|
|
CXFA_FMCallExpression::~CXFA_FMCallExpression() {}
|
|
|
|
bool CXFA_FMCallExpression::IsBuiltInFunc(CFX_WideTextBuf* funcName) {
|
|
if (funcName->GetLength() > g_BuiltInFuncsMaxLen)
|
|
return false;
|
|
|
|
WideString str = funcName->MakeString();
|
|
const wchar_t* const* pMatchResult = std::lower_bound(
|
|
std::begin(g_BuiltInFuncs), std::end(g_BuiltInFuncs), str,
|
|
[](const wchar_t* iter, const WideString& val) -> bool {
|
|
return val.CompareNoCase(iter) > 0;
|
|
});
|
|
if (pMatchResult != std::end(g_BuiltInFuncs) &&
|
|
!str.CompareNoCase(*pMatchResult)) {
|
|
funcName->Clear();
|
|
*funcName << *pMatchResult;
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
uint32_t CXFA_FMCallExpression::IsMethodWithObjParam(
|
|
const WideString& methodName) {
|
|
const XFA_FMSOMMethod* result = std::lower_bound(
|
|
std::begin(gs_FMSomMethods), std::end(gs_FMSomMethods), methodName,
|
|
[](const XFA_FMSOMMethod iter, const WideString& val) {
|
|
return val.Compare(iter.m_wsSomMethodName) > 0;
|
|
});
|
|
if (result != std::end(gs_FMSomMethods) &&
|
|
!methodName.Compare(result->m_wsSomMethodName)) {
|
|
return result->m_dParameters;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
bool CXFA_FMCallExpression::ToJavaScript(CFX_WideTextBuf* js, ReturnType type) {
|
|
CXFA_FMToJavaScriptDepth depthManager;
|
|
if (CXFA_IsTooBig(js) || !depthManager.IsWithinMaxDepth())
|
|
return false;
|
|
|
|
CFX_WideTextBuf funcName;
|
|
if (!m_pExp->ToJavaScript(&funcName, ReturnType::kInfered))
|
|
return false;
|
|
|
|
if (m_bIsSomMethod) {
|
|
*js << funcName << "(";
|
|
uint32_t methodPara = IsMethodWithObjParam(funcName.MakeString());
|
|
if (methodPara > 0) {
|
|
for (size_t i = 0; i < m_Arguments.size(); ++i) {
|
|
// Currently none of our expressions use objects for a parameter over
|
|
// the 6th. Make sure we don't overflow the shift when doing this
|
|
// check. If we ever need more the 32 object params we can revisit.
|
|
*js << "pfm_rt.get_";
|
|
if (i < 32 && (methodPara & (0x01 << i)) > 0)
|
|
*js << "jsobj";
|
|
else
|
|
*js << "val";
|
|
|
|
*js << "(";
|
|
if (!m_Arguments[i]->ToJavaScript(js, ReturnType::kInfered))
|
|
return false;
|
|
*js << ")";
|
|
if (i + 1 < m_Arguments.size())
|
|
*js << ", ";
|
|
}
|
|
} else {
|
|
for (const auto& expr : m_Arguments) {
|
|
*js << "pfm_rt.get_val(";
|
|
if (!expr->ToJavaScript(js, ReturnType::kInfered))
|
|
return false;
|
|
*js << ")";
|
|
if (expr != m_Arguments.back())
|
|
*js << ", ";
|
|
}
|
|
}
|
|
*js << ")";
|
|
return !CXFA_IsTooBig(js);
|
|
}
|
|
|
|
bool isEvalFunc = false;
|
|
bool isExistsFunc = false;
|
|
if (!IsBuiltInFunc(&funcName)) {
|
|
// If a function is not a SomMethod or a built-in then the input was
|
|
// invalid, so failing. The scanner/lexer should catch this, but currently
|
|
// doesn't. This failure will bubble up to the top-level and cause the
|
|
// transpile to fail.
|
|
return false;
|
|
}
|
|
|
|
if (funcName.AsStringView().EqualsASCII("Eval")) {
|
|
isEvalFunc = true;
|
|
*js << "eval.call(this, pfm_rt.Translate";
|
|
} else {
|
|
if (funcName.AsStringView().EqualsASCII("Exists"))
|
|
isExistsFunc = true;
|
|
|
|
*js << "pfm_rt." << funcName;
|
|
}
|
|
|
|
*js << "(";
|
|
if (isExistsFunc) {
|
|
*js << "\n(\nfunction ()\n{\ntry\n{\n";
|
|
if (!m_Arguments.empty()) {
|
|
*js << "return ";
|
|
if (!m_Arguments[0]->ToJavaScript(js, ReturnType::kInfered))
|
|
return false;
|
|
*js << ";\n}\n";
|
|
} else {
|
|
*js << "return 0;\n}\n";
|
|
}
|
|
*js << "catch(accessExceptions)\n";
|
|
*js << "{\nreturn 0;\n}\n}\n).call(this)\n";
|
|
} else {
|
|
for (const auto& expr : m_Arguments) {
|
|
if (!expr->ToJavaScript(js, ReturnType::kInfered))
|
|
return false;
|
|
if (expr != m_Arguments.back())
|
|
*js << ", ";
|
|
}
|
|
}
|
|
*js << ")";
|
|
if (isEvalFunc)
|
|
*js << ")";
|
|
|
|
return !CXFA_IsTooBig(js);
|
|
}
|
|
|
|
CXFA_FMDotAccessorExpression::CXFA_FMDotAccessorExpression(
|
|
std::unique_ptr<CXFA_FMSimpleExpression> pAccessor,
|
|
XFA_FM_TOKEN op,
|
|
WideStringView wsIdentifier,
|
|
std::unique_ptr<CXFA_FMSimpleExpression> pIndexExp)
|
|
: CXFA_FMSimpleExpression(op),
|
|
m_wsIdentifier(wsIdentifier),
|
|
m_pExp1(std::move(pAccessor)),
|
|
m_pExp2(std::move(pIndexExp)) {}
|
|
|
|
CXFA_FMDotAccessorExpression::~CXFA_FMDotAccessorExpression() = default;
|
|
|
|
bool CXFA_FMDotAccessorExpression::ToJavaScript(CFX_WideTextBuf* js,
|
|
ReturnType type) {
|
|
CXFA_FMToJavaScriptDepth depthManager;
|
|
if (CXFA_IsTooBig(js) || !depthManager.IsWithinMaxDepth())
|
|
return false;
|
|
|
|
*js << "pfm_rt.dot_acc(";
|
|
|
|
CFX_WideTextBuf tempExp1;
|
|
if (m_pExp1) {
|
|
if (!m_pExp1->ToJavaScript(&tempExp1, ReturnType::kInfered))
|
|
return false;
|
|
|
|
*js << tempExp1;
|
|
} else {
|
|
*js << "null";
|
|
}
|
|
*js << ", \"";
|
|
|
|
if (m_pExp1 && m_pExp1->GetOperatorToken() == TOKidentifier)
|
|
*js << tempExp1;
|
|
|
|
*js << "\", ";
|
|
if (m_op == TOKdotscream)
|
|
*js << "\"#" << m_wsIdentifier << "\", ";
|
|
else if (m_op == TOKdotstar)
|
|
*js << "\"*\", ";
|
|
else if (m_op == TOKcall)
|
|
*js << "\"\", ";
|
|
else
|
|
*js << "\"" << m_wsIdentifier << "\", ";
|
|
|
|
if (!m_pExp2->ToJavaScript(js, ReturnType::kInfered))
|
|
return false;
|
|
|
|
*js << ")";
|
|
return !CXFA_IsTooBig(js);
|
|
}
|
|
|
|
CXFA_FMIndexExpression::CXFA_FMIndexExpression(
|
|
XFA_FM_AccessorIndex accessorIndex,
|
|
std::unique_ptr<CXFA_FMSimpleExpression> pIndexExp,
|
|
bool bIsStarIndex)
|
|
: CXFA_FMSimpleExpression(TOKlbracket),
|
|
m_pExp(std::move(pIndexExp)),
|
|
m_accessorIndex(accessorIndex),
|
|
m_bIsStarIndex(bIsStarIndex) {}
|
|
|
|
CXFA_FMIndexExpression::~CXFA_FMIndexExpression() = default;
|
|
|
|
bool CXFA_FMIndexExpression::ToJavaScript(CFX_WideTextBuf* js,
|
|
ReturnType type) {
|
|
CXFA_FMToJavaScriptDepth depthManager;
|
|
if (CXFA_IsTooBig(js) || !depthManager.IsWithinMaxDepth())
|
|
return false;
|
|
|
|
switch (m_accessorIndex) {
|
|
case ACCESSOR_NO_INDEX:
|
|
*js << "0";
|
|
break;
|
|
case ACCESSOR_NO_RELATIVEINDEX:
|
|
*js << "1";
|
|
break;
|
|
case ACCESSOR_POSITIVE_INDEX:
|
|
*js << "2";
|
|
break;
|
|
case ACCESSOR_NEGATIVE_INDEX:
|
|
*js << "3";
|
|
break;
|
|
default:
|
|
*js << "0";
|
|
}
|
|
if (m_bIsStarIndex)
|
|
return !CXFA_IsTooBig(js);
|
|
|
|
*js << ", ";
|
|
if (m_pExp) {
|
|
if (!m_pExp->ToJavaScript(js, ReturnType::kInfered))
|
|
return false;
|
|
} else {
|
|
*js << "0";
|
|
}
|
|
return !CXFA_IsTooBig(js);
|
|
}
|
|
|
|
CXFA_FMDotDotAccessorExpression::CXFA_FMDotDotAccessorExpression(
|
|
std::unique_ptr<CXFA_FMSimpleExpression> pAccessor,
|
|
XFA_FM_TOKEN op,
|
|
WideStringView wsIdentifier,
|
|
std::unique_ptr<CXFA_FMSimpleExpression> pIndexExp)
|
|
: CXFA_FMSimpleExpression(op),
|
|
m_wsIdentifier(wsIdentifier),
|
|
m_pExp1(std::move(pAccessor)),
|
|
m_pExp2(std::move(pIndexExp)) {}
|
|
|
|
CXFA_FMDotDotAccessorExpression::~CXFA_FMDotDotAccessorExpression() = default;
|
|
|
|
bool CXFA_FMDotDotAccessorExpression::ToJavaScript(CFX_WideTextBuf* js,
|
|
ReturnType type) {
|
|
CXFA_FMToJavaScriptDepth depthManager;
|
|
if (CXFA_IsTooBig(js) || !depthManager.IsWithinMaxDepth())
|
|
return false;
|
|
|
|
*js << "pfm_rt.dotdot_acc(";
|
|
if (!m_pExp1->ToJavaScript(js, ReturnType::kInfered))
|
|
return false;
|
|
*js << ", "
|
|
<< "\"";
|
|
if (m_pExp1->GetOperatorToken() == TOKidentifier) {
|
|
if (!m_pExp1->ToJavaScript(js, ReturnType::kInfered))
|
|
return false;
|
|
}
|
|
|
|
*js << "\", \"" << m_wsIdentifier << "\", ";
|
|
if (!m_pExp2->ToJavaScript(js, ReturnType::kInfered))
|
|
return false;
|
|
*js << ")";
|
|
return !CXFA_IsTooBig(js);
|
|
}
|
|
|
|
CXFA_FMMethodCallExpression::CXFA_FMMethodCallExpression(
|
|
std::unique_ptr<CXFA_FMSimpleExpression> pAccessorExp1,
|
|
std::unique_ptr<CXFA_FMSimpleExpression> pCallExp)
|
|
: CXFA_FMSimpleExpression(TOKdot),
|
|
m_pExp1(std::move(pAccessorExp1)),
|
|
m_pExp2(std::move(pCallExp)) {}
|
|
|
|
CXFA_FMMethodCallExpression::~CXFA_FMMethodCallExpression() = default;
|
|
|
|
bool CXFA_FMMethodCallExpression::ToJavaScript(CFX_WideTextBuf* js,
|
|
ReturnType type) {
|
|
CXFA_FMToJavaScriptDepth depthManager;
|
|
if (CXFA_IsTooBig(js) || !depthManager.IsWithinMaxDepth())
|
|
return false;
|
|
|
|
CFX_WideTextBuf buf;
|
|
if (!m_pExp1->ToJavaScript(&buf, ReturnType::kInfered))
|
|
return false;
|
|
|
|
*js << "(function() {\n";
|
|
*js << " return pfm_method_runner(" << buf << ", function(obj) {\n";
|
|
*js << " return obj.";
|
|
if (!m_pExp2->ToJavaScript(js, ReturnType::kInfered))
|
|
return false;
|
|
*js << ";\n";
|
|
*js << " });\n";
|
|
*js << "}).call(this)";
|
|
return !CXFA_IsTooBig(js);
|
|
}
|
|
|
|
bool CXFA_IsTooBig(const CFX_WideTextBuf* js) {
|
|
return js->GetSize() >= 256 * 1024 * 1024;
|
|
}
|