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) {