Remove CFXJSE_Values from CFXJSE_FormCalcContext::Mod() and Round()
-- Return Optional<double> from ExtractDouble().
-- Add test for Mod(NaN).
Change-Id: I59e4e0eca0d8c7e315847b3a9132a8c922ecfad8
Reviewed-on: https://pdfium-review.googlesource.com/c/pdfium/+/76294
Reviewed-by: Daniel Hosseinian <dhoss@chromium.org>
Commit-Queue: Tom Sepez <tsepez@chromium.org>
diff --git a/fxjs/xfa/cfxjse_formcalc_context.cpp b/fxjs/xfa/cfxjse_formcalc_context.cpp
index 2d99496..c0193dd 100644
--- a/fxjs/xfa/cfxjse_formcalc_context.cpp
+++ b/fxjs/xfa/cfxjse_formcalc_context.cpp
@@ -21,6 +21,7 @@
#include "fxjs/xfa/cfxjse_engine.h"
#include "fxjs/xfa/cfxjse_value.h"
#include "fxjs/xfa/cjx_object.h"
+#include "third_party/base/optional.h"
#include "third_party/base/stl_util.h"
#include "xfa/fgas/crt/cfgas_decimal.h"
#include "xfa/fxfa/cxfa_ffnotify.h"
@@ -1446,25 +1447,18 @@
return fxv8::ReentrantToDoubleHelper(pIsolate, extracted);
}
-// TODO(tsepez): return Optional<double>.
-double ExtractDouble(v8::Isolate* pIsolate,
- v8::Local<v8::Value> src,
- bool* ret) {
- ASSERT(ret);
- *ret = true;
-
+Optional<double> ExtractDouble(v8::Isolate* pIsolate,
+ v8::Local<v8::Value> src) {
if (src.IsEmpty())
- return 0;
+ return 0.0;
if (!fxv8::IsArray(src))
return ValueToDouble(pIsolate, src);
v8::Local<v8::Array> arr = src.As<v8::Array>();
uint32_t iLength = fxv8::GetArrayLengthHelper(arr);
- if (iLength < 3) {
- *ret = false;
- return 0.0;
- }
+ if (iLength < 3)
+ return pdfium::nullopt;
v8::Local<v8::Value> propertyValue =
fxv8::ReentrantGetArrayElementHelper(pIsolate, arr, 1);
@@ -1852,31 +1846,27 @@
return;
}
- auto argOne = std::make_unique<CFXJSE_Value>(info.GetIsolate(), info[0]);
- auto argTwo = std::make_unique<CFXJSE_Value>(info.GetIsolate(), info[1]);
- if (argOne->IsNull(info.GetIsolate()) || argTwo->IsNull(info.GetIsolate())) {
+ if (fxv8::IsNull(info[0]) || fxv8::IsNull(info[1])) {
info.GetReturnValue().SetNull();
return;
}
- bool argOneResult;
- double dDividend = ExtractDouble(
- info.GetIsolate(), argOne->GetValue(info.GetIsolate()), &argOneResult);
- bool argTwoResult;
- double dDivisor = ExtractDouble(
- info.GetIsolate(), argTwo->GetValue(info.GetIsolate()), &argTwoResult);
- if (!argOneResult || !argTwoResult) {
+ Optional<double> maybe_dividend = ExtractDouble(info.GetIsolate(), info[0]);
+ Optional<double> maybe_divisor = ExtractDouble(info.GetIsolate(), info[1]);
+ if (!maybe_dividend.has_value() || !maybe_divisor.has_value()) {
pContext->ThrowArgumentMismatchException();
return;
}
- if (dDivisor == 0.0) {
+ double dividend = maybe_dividend.value();
+ double divisor = maybe_divisor.value();
+ if (divisor == 0.0) {
pContext->ThrowDivideByZeroException();
return;
}
- info.GetReturnValue().Set(
- dDividend - dDivisor * static_cast<int32_t>(dDividend / dDivisor));
+ info.GetReturnValue().Set(dividend -
+ divisor * static_cast<int32_t>(dividend / divisor));
}
// static
@@ -1890,36 +1880,31 @@
return;
}
- auto argOne = std::make_unique<CFXJSE_Value>(info.GetIsolate(), info[0]);
- if (argOne->IsNull(info.GetIsolate())) {
+ if (fxv8::IsNull(info[0])) {
info.GetReturnValue().SetNull();
return;
}
- bool dValueRet;
- double dValue = ExtractDouble(
- info.GetIsolate(), argOne->GetValue(info.GetIsolate()), &dValueRet);
- if (!dValueRet) {
+ Optional<double> maybe_value = ExtractDouble(info.GetIsolate(), info[0]);
+ if (!maybe_value.has_value()) {
pContext->ThrowArgumentMismatchException();
return;
}
+ double dValue = maybe_value.value();
uint8_t uPrecision = 0;
if (argc > 1) {
- auto argTwo = std::make_unique<CFXJSE_Value>(info.GetIsolate(), info[1]);
- if (argTwo->IsNull(info.GetIsolate())) {
+ if (fxv8::IsNull(info[1])) {
info.GetReturnValue().SetNull();
return;
}
-
- bool dPrecisionRet;
- double dPrecision = ExtractDouble(
- info.GetIsolate(), argTwo->GetValue(info.GetIsolate()), &dPrecisionRet);
- if (!dPrecisionRet) {
+ Optional<double> maybe_precision =
+ ExtractDouble(info.GetIsolate(), info[1]);
+ if (!maybe_precision.has_value()) {
pContext->ThrowArgumentMismatchException();
return;
}
-
+ double dPrecision = maybe_precision.value();
uPrecision = static_cast<uint8_t>(pdfium::clamp(dPrecision, 0.0, 12.0));
}
diff --git a/fxjs/xfa/cfxjse_formcalc_context_embeddertest.cpp b/fxjs/xfa/cfxjse_formcalc_context_embeddertest.cpp
index ad523a6..b2cd1d2 100644
--- a/fxjs/xfa/cfxjse_formcalc_context_embeddertest.cpp
+++ b/fxjs/xfa/cfxjse_formcalc_context_embeddertest.cpp
@@ -2,6 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+#include <cmath>
+
#include "fxjs/fxv8.h"
#include "fxjs/xfa/cfxjse_engine.h"
#include "fxjs/xfa/cfxjse_isolatetracker.h"
@@ -74,6 +76,15 @@
<< "Program: " << input;
}
+ void ExecuteExpectNaN(ByteStringView input) {
+ EXPECT_TRUE(Execute(input)) << "Program: " << input;
+
+ CFXJSE_ScopeUtil_IsolateHandleContext scope(GetScriptContext());
+ v8::Local<v8::Value> value = GetValue();
+ EXPECT_TRUE(fxv8::IsNumber(value));
+ EXPECT_TRUE(std::isnan(fxv8::ReentrantToDoubleHelper(isolate(), value)));
+ }
+
void ExecuteExpectString(ByteStringView input, const char* expected) {
EXPECT_TRUE(Execute(input)) << "Program: " << input;
@@ -288,6 +299,9 @@
for (size_t i = 0; i < pdfium::size(tests); ++i)
ExecuteExpectInt32(tests[i].program, tests[i].result);
+
+ ExecuteExpectNaN("Mod(10, NaN)");
+ ExecuteExpectNaN("Mod(10, Infinity)");
}
TEST_F(CFXJSE_FormCalcContextEmbedderTest, Round) {