Consolidate some common logic in cfxjse_formcalccontext.cpp. Nearly identical code appears in 5 places. Since this is being called infrequently and as a callback from javascript, the overhead of an indirect function call associated with lambda captures should be acceptable. Change-Id: I9f8b0d0d9d4433ba9b204442eba413149d8d9e0d Reviewed-on: https://pdfium-review.googlesource.com/c/pdfium/+/76291 Commit-Queue: Tom Sepez <tsepez@chromium.org> Reviewed-by: Daniel Hosseinian <dhoss@chromium.org>
diff --git a/fxjs/xfa/cfxjse_formcalc_context.cpp b/fxjs/xfa/cfxjse_formcalc_context.cpp index dfd60b3..3b0d235 100644 --- a/fxjs/xfa/cfxjse_formcalc_context.cpp +++ b/fxjs/xfa/cfxjse_formcalc_context.cpp
@@ -1731,73 +1731,19 @@ void CFXJSE_FormCalcContext::Avg( CFXJSE_HostObject* pThis, const v8::FunctionCallbackInfo<v8::Value>& info) { - int32_t argc = info.Length(); - if (argc < 1) { - info.GetReturnValue().SetNull(); - return; - } - - v8::Isolate* pIsolate = ToFormCalcContext(pThis)->GetIsolate(); uint32_t uCount = 0; double dSum = 0.0; - for (int32_t i = 0; i < argc; i++) { - auto argValue = std::make_unique<CFXJSE_Value>(info.GetIsolate(), info[i]); - if (argValue->IsNull(pIsolate)) - continue; + auto fn = [&uCount, &dSum](v8::Isolate* pIsolate, CFXJSE_Value* pValue) { + dSum += ValueToDouble(pIsolate, pValue->GetValue(pIsolate)); + uCount++; + }; + if (!ToFormCalcContext(pThis)->ApplyToExpansion(fn, info, /*bStrict=*/false)) + return; - if (!argValue->IsArray(pIsolate)) { - dSum += ValueToDouble(pIsolate, argValue->GetValue(pIsolate)); - uCount++; - continue; - } - - auto lengthValue = std::make_unique<CFXJSE_Value>(); - argValue->GetObjectProperty(pIsolate, "length", lengthValue.get()); - int32_t iLength = lengthValue->ToInteger(pIsolate); - - if (iLength > 2) { - auto propertyValue = std::make_unique<CFXJSE_Value>(); - argValue->GetObjectPropertyByIdx(pIsolate, 1, propertyValue.get()); - - auto jsObjectValue = std::make_unique<CFXJSE_Value>(); - if (propertyValue->IsNull(pIsolate)) { - for (int32_t j = 2; j < iLength; j++) { - argValue->GetObjectPropertyByIdx(pIsolate, j, jsObjectValue.get()); - if (!jsObjectValue->IsObject(pIsolate)) - continue; - - auto defaultPropValue = std::make_unique<CFXJSE_Value>( - pIsolate, - GetObjectDefaultValue( - pIsolate, - jsObjectValue->GetValue(pIsolate).As<v8::Object>())); - if (defaultPropValue->IsNull(pIsolate)) - continue; - - dSum += ValueToDouble(pIsolate, defaultPropValue->GetValue(pIsolate)); - uCount++; - } - } else { - for (int32_t j = 2; j < iLength; j++) { - argValue->GetObjectPropertyByIdx(pIsolate, j, jsObjectValue.get()); - auto newPropertyValue = std::make_unique<CFXJSE_Value>(); - jsObjectValue->GetObjectProperty( - pIsolate, propertyValue->ToString(pIsolate).AsStringView(), - newPropertyValue.get()); - if (newPropertyValue->IsNull(pIsolate)) - continue; - - dSum += ValueToDouble(pIsolate, newPropertyValue->GetValue(pIsolate)); - uCount++; - } - } - } - } if (uCount == 0) { info.GetReturnValue().SetNull(); return; } - info.GetReturnValue().Set(dSum / uCount); } @@ -1823,63 +1769,13 @@ void CFXJSE_FormCalcContext::Count( CFXJSE_HostObject* pThis, const v8::FunctionCallbackInfo<v8::Value>& info) { - CFXJSE_FormCalcContext* pContext = ToFormCalcContext(pThis); - v8::Isolate* pIsolate = pContext->GetIsolate(); - int32_t iCount = 0; - for (int32_t i = 0; i < info.Length(); i++) { - auto argValue = std::make_unique<CFXJSE_Value>(info.GetIsolate(), info[i]); - if (argValue->IsNull(pIsolate)) - continue; + uint32_t iCount = 0; + auto fn = [&iCount](v8::Isolate* pIsolate, CFXJSE_Value* pvalue) { + ++iCount; + }; + if (!ToFormCalcContext(pThis)->ApplyToExpansion(fn, info, /*bStrict=*/true)) + return; - if (argValue->IsArray(pIsolate)) { - auto lengthValue = std::make_unique<CFXJSE_Value>(); - argValue->GetObjectProperty(pIsolate, "length", lengthValue.get()); - - int32_t iLength = lengthValue->ToInteger(pIsolate); - if (iLength <= 2) { - pContext->ThrowArgumentMismatchException(); - return; - } - - auto propertyValue = std::make_unique<CFXJSE_Value>(); - auto jsObjectValue = std::make_unique<CFXJSE_Value>(); - auto newPropertyValue = std::make_unique<CFXJSE_Value>(); - argValue->GetObjectPropertyByIdx(pIsolate, 1, propertyValue.get()); - argValue->GetObjectPropertyByIdx(pIsolate, 2, jsObjectValue.get()); - if (propertyValue->IsNull(pIsolate)) { - for (int32_t j = 2; j < iLength; j++) { - argValue->GetObjectPropertyByIdx(pIsolate, j, jsObjectValue.get()); - if (!jsObjectValue->IsObject(pIsolate)) - continue; - - newPropertyValue->ForceSetValue( - pIsolate, - GetObjectDefaultValue( - pIsolate, - jsObjectValue->GetValue(pIsolate).As<v8::Object>())); - if (!newPropertyValue->IsNull(pIsolate)) - iCount++; - } - } else { - for (int32_t j = 2; j < iLength; j++) { - argValue->GetObjectPropertyByIdx(pIsolate, j, jsObjectValue.get()); - jsObjectValue->GetObjectProperty( - pIsolate, propertyValue->ToString(pIsolate).AsStringView(), - newPropertyValue.get()); - iCount += newPropertyValue->IsNull(pIsolate) ? 0 : 1; - } - } - } else if (argValue->IsObject(pIsolate)) { - auto newPropertyValue = std::make_unique<CFXJSE_Value>( - pIsolate, - GetObjectDefaultValue(pIsolate, - argValue->GetValue(pIsolate).As<v8::Object>())); - if (!newPropertyValue->IsNull(pIsolate)) - iCount++; - } else { - iCount++; - } - } info.GetReturnValue().Set(iCount); } @@ -1905,82 +1801,16 @@ void CFXJSE_FormCalcContext::Max( CFXJSE_HostObject* pThis, const v8::FunctionCallbackInfo<v8::Value>& info) { - CFXJSE_FormCalcContext* pContext = ToFormCalcContext(pThis); - v8::Isolate* pIsolate = pContext->GetIsolate(); uint32_t uCount = 0; double dMaxValue = 0.0; - for (int32_t i = 0; i < info.Length(); i++) { - auto argValue = std::make_unique<CFXJSE_Value>(info.GetIsolate(), info[i]); - if (argValue->IsNull(info.GetIsolate())) - continue; + auto fn = [&uCount, &dMaxValue](v8::Isolate* pIsolate, CFXJSE_Value* pValue) { + ++uCount; + double dValue = ValueToDouble(pIsolate, pValue->GetValue(pIsolate)); + dMaxValue = uCount == 1 ? dValue : std::max(dMaxValue, dValue); + }; + if (!ToFormCalcContext(pThis)->ApplyToExpansion(fn, info, /*bStrict=*/true)) + return; - if (argValue->IsArray(info.GetIsolate())) { - auto lengthValue = std::make_unique<CFXJSE_Value>(); - argValue->GetObjectProperty(info.GetIsolate(), "length", - lengthValue.get()); - int32_t iLength = lengthValue->ToInteger(info.GetIsolate()); - if (iLength <= 2) { - pContext->ThrowArgumentMismatchException(); - return; - } - - auto propertyValue = std::make_unique<CFXJSE_Value>(); - auto jsObjectValue = std::make_unique<CFXJSE_Value>(); - auto newPropertyValue = std::make_unique<CFXJSE_Value>(); - argValue->GetObjectPropertyByIdx(pIsolate, 1, propertyValue.get()); - argValue->GetObjectPropertyByIdx(pIsolate, 2, jsObjectValue.get()); - if (propertyValue->IsNull(pIsolate)) { - for (int32_t j = 2; j < iLength; j++) { - argValue->GetObjectPropertyByIdx(pIsolate, j, jsObjectValue.get()); - if (!jsObjectValue->IsObject(pIsolate)) - continue; - - newPropertyValue->ForceSetValue( - pIsolate, - GetObjectDefaultValue( - pIsolate, - jsObjectValue->GetValue(pIsolate).As<v8::Object>())); - if (newPropertyValue->IsNull(pIsolate)) - continue; - - uCount++; - double dValue = - ValueToDouble(pIsolate, newPropertyValue->GetValue(pIsolate)); - dMaxValue = (uCount == 1) ? dValue : std::max(dMaxValue, dValue); - } - } else { - for (int32_t j = 2; j < iLength; j++) { - argValue->GetObjectPropertyByIdx(pIsolate, j, jsObjectValue.get()); - jsObjectValue->GetObjectProperty( - pIsolate, propertyValue->ToString(pIsolate).AsStringView(), - newPropertyValue.get()); - if (newPropertyValue->IsNull(pIsolate)) - continue; - - uCount++; - double dValue = - ValueToDouble(pIsolate, newPropertyValue->GetValue(pIsolate)); - dMaxValue = (uCount == 1) ? dValue : std::max(dMaxValue, dValue); - } - } - } else if (argValue->IsObject(pIsolate)) { - auto newPropertyValue = std::make_unique<CFXJSE_Value>( - pIsolate, - GetObjectDefaultValue(pIsolate, - argValue->GetValue(pIsolate).As<v8::Object>())); - if (newPropertyValue->IsNull(pIsolate)) - continue; - - uCount++; - double dValue = - ValueToDouble(pIsolate, newPropertyValue->GetValue(pIsolate)); - dMaxValue = (uCount == 1) ? dValue : std::max(dMaxValue, dValue); - } else { - uCount++; - double dValue = ValueToDouble(pIsolate, argValue->GetValue(pIsolate)); - dMaxValue = (uCount == 1) ? dValue : std::max(dMaxValue, dValue); - } - } if (uCount == 0) { info.GetReturnValue().SetNull(); return; @@ -1992,86 +1822,20 @@ void CFXJSE_FormCalcContext::Min( CFXJSE_HostObject* pThis, const v8::FunctionCallbackInfo<v8::Value>& info) { - CFXJSE_FormCalcContext* pContext = ToFormCalcContext(pThis); - v8::Isolate* pIsolate = pContext->GetIsolate(); uint32_t uCount = 0; double dMinValue = 0.0; - for (int32_t i = 0; i < info.Length(); i++) { - auto argValue = std::make_unique<CFXJSE_Value>(info.GetIsolate(), info[i]); - if (argValue->IsNull(pIsolate)) - continue; + auto fn = [&uCount, &dMinValue](v8::Isolate* pIsolate, CFXJSE_Value* pValue) { + ++uCount; + double dValue = ValueToDouble(pIsolate, pValue->GetValue(pIsolate)); + dMinValue = uCount == 1 ? dValue : std::min(dMinValue, dValue); + }; + if (!ToFormCalcContext(pThis)->ApplyToExpansion(fn, info, /*bStrict=*/true)) + return; - if (argValue->IsArray(pIsolate)) { - auto lengthValue = std::make_unique<CFXJSE_Value>(); - argValue->GetObjectProperty(pIsolate, "length", lengthValue.get()); - int32_t iLength = lengthValue->ToInteger(pIsolate); - if (iLength <= 2) { - pContext->ThrowArgumentMismatchException(); - return; - } - - auto propertyValue = std::make_unique<CFXJSE_Value>(); - auto jsObjectValue = std::make_unique<CFXJSE_Value>(); - auto newPropertyValue = std::make_unique<CFXJSE_Value>(); - argValue->GetObjectPropertyByIdx(pIsolate, 1, propertyValue.get()); - argValue->GetObjectPropertyByIdx(pIsolate, 2, jsObjectValue.get()); - if (propertyValue->IsNull(pIsolate)) { - for (int32_t j = 2; j < iLength; j++) { - argValue->GetObjectPropertyByIdx(pIsolate, j, jsObjectValue.get()); - if (!jsObjectValue->IsObject(pIsolate)) - continue; - - newPropertyValue->ForceSetValue( - pIsolate, - GetObjectDefaultValue( - pIsolate, - jsObjectValue->GetValue(pIsolate).As<v8::Object>())); - if (newPropertyValue->IsNull(pIsolate)) - continue; - - uCount++; - double dValue = - ValueToDouble(pIsolate, newPropertyValue->GetValue(pIsolate)); - dMinValue = uCount == 1 ? dValue : std::min(dMinValue, dValue); - } - } else { - for (int32_t j = 2; j < iLength; j++) { - argValue->GetObjectPropertyByIdx(pIsolate, j, jsObjectValue.get()); - jsObjectValue->GetObjectProperty( - pIsolate, propertyValue->ToString(pIsolate).AsStringView(), - newPropertyValue.get()); - if (newPropertyValue->IsNull(pIsolate)) - continue; - - uCount++; - double dValue = - ValueToDouble(pIsolate, newPropertyValue->GetValue(pIsolate)); - dMinValue = uCount == 1 ? dValue : std::min(dMinValue, dValue); - } - } - } else if (argValue->IsObject(pIsolate)) { - auto newPropertyValue = std::make_unique<CFXJSE_Value>( - pIsolate, - GetObjectDefaultValue(pIsolate, - argValue->GetValue(pIsolate).As<v8::Object>())); - if (newPropertyValue->IsNull(pIsolate)) - continue; - - uCount++; - double dValue = - ValueToDouble(pIsolate, newPropertyValue->GetValue(pIsolate)); - dMinValue = uCount == 1 ? dValue : std::min(dMinValue, dValue); - } else { - uCount++; - double dValue = ValueToDouble(pIsolate, argValue->GetValue(pIsolate)); - dMinValue = uCount == 1 ? dValue : std::min(dMinValue, dValue); - } - } if (uCount == 0) { info.GetReturnValue().SetNull(); return; } - info.GetReturnValue().Set(dMinValue); } @@ -2164,93 +1928,19 @@ void CFXJSE_FormCalcContext::Sum( CFXJSE_HostObject* pThis, const v8::FunctionCallbackInfo<v8::Value>& info) { - int32_t argc = info.Length(); - if (argc == 0) { - info.GetReturnValue().SetNull(); - return; - } - - CFXJSE_FormCalcContext* pContext = ToFormCalcContext(pThis); uint32_t uCount = 0; double dSum = 0.0; - for (int32_t i = 0; i < argc; i++) { - auto argValue = std::make_unique<CFXJSE_Value>(info.GetIsolate(), info[i]); - if (argValue->IsNull(info.GetIsolate())) - continue; + auto fn = [&uCount, &dSum](v8::Isolate* pIsolate, CFXJSE_Value* pValue) { + ++uCount; + dSum += ValueToDouble(pIsolate, pValue->GetValue(pIsolate)); + }; + if (!ToFormCalcContext(pThis)->ApplyToExpansion(fn, info, /*bStrict=*/true)) + return; - if (argValue->IsArray(info.GetIsolate())) { - auto lengthValue = std::make_unique<CFXJSE_Value>(); - argValue->GetObjectProperty(info.GetIsolate(), "length", - lengthValue.get()); - int32_t iLength = lengthValue->ToInteger(info.GetIsolate()); - if (iLength <= 2) { - pContext->ThrowArgumentMismatchException(); - return; - } - - auto propertyValue = std::make_unique<CFXJSE_Value>(); - argValue->GetObjectPropertyByIdx(info.GetIsolate(), 1, - propertyValue.get()); - auto jsObjectValue = std::make_unique<CFXJSE_Value>(); - auto newPropertyValue = std::make_unique<CFXJSE_Value>(); - if (propertyValue->IsNull(info.GetIsolate())) { - for (int32_t j = 2; j < iLength; j++) { - argValue->GetObjectPropertyByIdx(info.GetIsolate(), j, - jsObjectValue.get()); - if (!jsObjectValue->IsObject(info.GetIsolate())) - continue; - - newPropertyValue->ForceSetValue( - info.GetIsolate(), - GetObjectDefaultValue( - info.GetIsolate(), - jsObjectValue->GetValue(info.GetIsolate()).As<v8::Object>())); - if (newPropertyValue->IsNull(info.GetIsolate())) - continue; - - dSum += ValueToDouble(info.GetIsolate(), - jsObjectValue->GetValue(info.GetIsolate())); - uCount++; - } - } else { - for (int32_t j = 2; j < iLength; j++) { - argValue->GetObjectPropertyByIdx(info.GetIsolate(), j, - jsObjectValue.get()); - jsObjectValue->GetObjectProperty( - info.GetIsolate(), - propertyValue->ToString(info.GetIsolate()).AsStringView(), - newPropertyValue.get()); - if (newPropertyValue->IsNull(info.GetIsolate())) - continue; - - dSum += ValueToDouble(info.GetIsolate(), - newPropertyValue->GetValue(info.GetIsolate())); - uCount++; - } - } - } else if (argValue->IsObject(info.GetIsolate())) { - auto newPropertyValue = std::make_unique<CFXJSE_Value>( - info.GetIsolate(), - GetObjectDefaultValue( - info.GetIsolate(), - argValue->GetValue(info.GetIsolate()).As<v8::Object>())); - if (newPropertyValue->IsNull(info.GetIsolate())) - continue; - - dSum += ValueToDouble(info.GetIsolate(), - argValue->GetValue(info.GetIsolate())); - uCount++; - } else { - dSum += ValueToDouble(info.GetIsolate(), - argValue->GetValue(info.GetIsolate())); - uCount++; - } - } if (uCount == 0) { info.GetReturnValue().SetNull(); return; } - info.GetReturnValue().Set(dSum); } @@ -5862,6 +5552,76 @@ info.GetReturnValue().Set(pReturn->DirectGetValue()); } +bool CFXJSE_FormCalcContext::ApplyToExpansion( + std::function<void(v8::Isolate*, CFXJSE_Value*)> fn, + const v8::FunctionCallbackInfo<v8::Value>& info, + bool bStrict) { + v8::Isolate* pIsolate = info.GetIsolate(); + for (int32_t i = 0; i < info.Length(); i++) { + auto argValue = std::make_unique<CFXJSE_Value>(pIsolate, info[i]); + if (argValue->IsNull(pIsolate)) + continue; + + if (argValue->IsArray(pIsolate)) { + auto lengthValue = std::make_unique<CFXJSE_Value>(); + argValue->GetObjectProperty(pIsolate, "length", lengthValue.get()); + + int32_t iLength = lengthValue->ToInteger(pIsolate); + if (iLength <= 2) { + if (!bStrict) + continue; + + ThrowArgumentMismatchException(); + return false; + } + + auto propertyValue = std::make_unique<CFXJSE_Value>(); + auto jsObjectValue = std::make_unique<CFXJSE_Value>(); + auto newPropertyValue = std::make_unique<CFXJSE_Value>(); + argValue->GetObjectPropertyByIdx(pIsolate, 1, propertyValue.get()); + argValue->GetObjectPropertyByIdx(pIsolate, 2, jsObjectValue.get()); + if (propertyValue->IsNull(pIsolate)) { + for (int32_t j = 2; j < iLength; j++) { + argValue->GetObjectPropertyByIdx(pIsolate, j, jsObjectValue.get()); + if (!jsObjectValue->IsObject(pIsolate)) + continue; + + newPropertyValue->ForceSetValue( + pIsolate, + GetObjectDefaultValue( + pIsolate, + jsObjectValue->GetValue(pIsolate).As<v8::Object>())); + if (!newPropertyValue->IsNull(pIsolate)) + fn(pIsolate, newPropertyValue.get()); + } + } else { + for (int32_t j = 2; j < iLength; j++) { + argValue->GetObjectPropertyByIdx(pIsolate, j, jsObjectValue.get()); + jsObjectValue->GetObjectProperty( + pIsolate, propertyValue->ToString(pIsolate).AsStringView(), + newPropertyValue.get()); + if (!newPropertyValue->IsNull(pIsolate)) + fn(pIsolate, newPropertyValue.get()); + } + } + continue; + } + + if (argValue->IsObject(pIsolate)) { + auto newPropertyValue = std::make_unique<CFXJSE_Value>( + pIsolate, + GetObjectDefaultValue(pIsolate, + argValue->GetValue(pIsolate).As<v8::Object>())); + if (!newPropertyValue->IsNull(pIsolate)) + fn(pIsolate, newPropertyValue.get()); + continue; + } + + fn(pIsolate, argValue.get()); + } + return true; +} + void CFXJSE_FormCalcContext::ThrowNoDefaultPropertyException( ByteStringView name) const { ThrowException(WideString::FromUTF8(name) +
diff --git a/fxjs/xfa/cfxjse_formcalc_context.h b/fxjs/xfa/cfxjse_formcalc_context.h index c382ab8..79fb2ee 100644 --- a/fxjs/xfa/cfxjse_formcalc_context.h +++ b/fxjs/xfa/cfxjse_formcalc_context.h
@@ -7,6 +7,7 @@ #ifndef FXJS_XFA_CFXJSE_FORMCALC_CONTEXT_H_ #define FXJS_XFA_CFXJSE_FORMCALC_CONTEXT_H_ +#include <functional> #include <memory> #include <vector> @@ -276,18 +277,22 @@ v8::Isolate* GetIsolate() const { return m_pIsolate.Get(); } CXFA_Document* GetDocument() const { return m_pDocument.Get(); } + bool ApplyToExpansion(std::function<void(v8::Isolate*, CFXJSE_Value*)> fn, + const v8::FunctionCallbackInfo<v8::Value>& info, + bool bStrict); + private: static void DotAccessorCommon(CFXJSE_HostObject* pThis, const v8::FunctionCallbackInfo<v8::Value>& info, bool bDotAccessor); + void ThrowArgumentMismatchException() const; void ThrowNoDefaultPropertyException(ByteStringView name) const; void ThrowCompilerErrorException() const; void ThrowDivideByZeroException() const; void ThrowServerDeniedException() const; void ThrowPropertyNotInObjectException(const WideString& name, const WideString& exp) const; - void ThrowArgumentMismatchException() const; void ThrowParamCountMismatchException(const WideString& method) const; void ThrowException(const WideString& str) const;