Return Optional<CFX_WideTextBuf> from CFXJSE_FormcalcContext::Translate()

Avoid more out-parameters.

-- add more const
-- pass string to CXFA_IsTooBig() by const-ref while at it.

Change-Id: I49a4621d45779cce8226e4c79fde4c9380416ee0
Reviewed-on: https://pdfium-review.googlesource.com/c/pdfium/+/73550
Commit-Queue: Tom Sepez <tsepez@chromium.org>
Reviewed-by: Lei Zhang <thestig@chromium.org>
diff --git a/fxjs/xfa/cfxjse_engine.cpp b/fxjs/xfa/cfxjse_engine.cpp
index 4155d6d..adc6e68 100644
--- a/fxjs/xfa/cfxjse_engine.cpp
+++ b/fxjs/xfa/cfxjse_engine.cpp
@@ -139,12 +139,13 @@
       m_FM2JSContext = std::make_unique<CFXJSE_FormCalcContext>(
           GetIsolate(), m_JsContext.get(), m_pDocument.Get());
     }
-    CFX_WideTextBuf wsJavaScript;
-    if (!CFXJSE_FormCalcContext::Translate(wsScript, &wsJavaScript)) {
+    Optional<CFX_WideTextBuf> wsJavaScript =
+        CFXJSE_FormCalcContext::Translate(wsScript);
+    if (!wsJavaScript.has_value()) {
       hRetValue->SetUndefined();
       return false;
     }
-    btScript = FX_UTF8Encode(wsJavaScript.AsStringView());
+    btScript = FX_UTF8Encode(wsJavaScript.value().AsStringView());
   } else {
     btScript = FX_UTF8Encode(wsScript);
   }
diff --git a/fxjs/xfa/cfxjse_formcalc_context.cpp b/fxjs/xfa/cfxjse_formcalc_context.cpp
index f25c263..886820a 100644
--- a/fxjs/xfa/cfxjse_formcalc_context.cpp
+++ b/fxjs/xfa/cfxjse_formcalc_context.cpp
@@ -3200,10 +3200,10 @@
     return;
   }
 
-  CFX_WideTextBuf wsJavaScriptBuf;
-  if (!CFXJSE_FormCalcContext::Translate(
-          WideString::FromUTF8(bsUtf8Script.AsStringView()).AsStringView(),
-          &wsJavaScriptBuf)) {
+  WideString wsCalcScript = WideString::FromUTF8(bsUtf8Script.AsStringView());
+  Optional<CFX_WideTextBuf> wsJavaScriptBuf =
+      CFXJSE_FormCalcContext::Translate(wsCalcScript.AsStringView());
+  if (!wsJavaScriptBuf.has_value()) {
     pContext->ThrowCompilerErrorException();
     return;
   }
@@ -3213,8 +3213,8 @@
 
   auto returnValue = std::make_unique<CFXJSE_Value>(pIsolate);
   pNewContext->ExecuteScript(
-      FX_UTF8Encode(wsJavaScriptBuf.AsStringView()).c_str(), returnValue.get(),
-      nullptr);
+      FX_UTF8Encode(wsJavaScriptBuf.value().AsStringView()).c_str(),
+      returnValue.get(), nullptr);
 
   info.GetReturnValue().Set(returnValue->DirectGetValue());
 }
@@ -5010,16 +5010,16 @@
     return;
   }
 
-  WideString wsScript = WideString::FromUTF8(bsArg.AsStringView());
-  CFX_WideTextBuf wsJavaScriptBuf;
-  if (!CFXJSE_FormCalcContext::Translate(wsScript.AsStringView(),
-                                         &wsJavaScriptBuf)) {
+  WideString wsCalcScript = WideString::FromUTF8(bsArg.AsStringView());
+  Optional<CFX_WideTextBuf> wsJavaScriptBuf =
+      CFXJSE_FormCalcContext::Translate(wsCalcScript.AsStringView());
+  if (!wsJavaScriptBuf.has_value()) {
     pContext->ThrowCompilerErrorException();
     return;
   }
   info.GetReturnValue().Set(fxv8::NewStringHelper(
       info.GetIsolate(),
-      FX_UTF8Encode(wsJavaScriptBuf.AsStringView()).AsStringView()));
+      FX_UTF8Encode(wsJavaScriptBuf.value().AsStringView()).AsStringView()));
 }
 
 // static
@@ -5648,23 +5648,25 @@
 }
 
 // static.
-bool CFXJSE_FormCalcContext::Translate(WideStringView wsFormcalc,
-                                       CFX_WideTextBuf* wsJavascript) {
-  if (wsFormcalc.IsEmpty()) {
-    wsJavascript->Clear();
-    return true;
-  }
+Optional<CFX_WideTextBuf> CFXJSE_FormCalcContext::Translate(
+    WideStringView wsFormcalc) {
+  if (wsFormcalc.IsEmpty())
+    return CFX_WideTextBuf();
 
   CXFA_FMParser parser(wsFormcalc);
   std::unique_ptr<CXFA_FMAST> ast = parser.Parse();
   if (!ast || parser.HasError())
-    return false;
+    return pdfium::nullopt;
 
   CXFA_FMToJavaScriptDepth::Reset();
-  if (!ast->ToJavaScript(wsJavascript))
-    return false;
+  Optional<CFX_WideTextBuf> wsJavaScript = ast->ToJavaScript();
+  if (!wsJavaScript.has_value())
+    return pdfium::nullopt;
 
-  return !CXFA_IsTooBig(wsJavascript);
+  if (CXFA_IsTooBig(wsJavaScript.value()))
+    return pdfium::nullopt;
+
+  return wsJavaScript;
 }
 
 CFXJSE_FormCalcContext::CFXJSE_FormCalcContext(v8::Isolate* pScriptIsolate,
diff --git a/fxjs/xfa/cfxjse_formcalc_context.h b/fxjs/xfa/cfxjse_formcalc_context.h
index 13085ea..8858d0e 100644
--- a/fxjs/xfa/cfxjse_formcalc_context.h
+++ b/fxjs/xfa/cfxjse_formcalc_context.h
@@ -12,6 +12,7 @@
 
 #include "core/fxcrt/unowned_ptr.h"
 #include "fxjs/xfa/fxjse.h"
+#include "third_party/base/optional.h"
 #include "xfa/fxfa/parser/xfa_resolvenode_rs.h"
 
 class CFXJSE_Context;
@@ -299,9 +300,7 @@
   static double ExtractDouble(CFXJSE_HostObject* pThis,
                               CFXJSE_Value* src,
                               bool* ret);
-
-  static bool Translate(WideStringView wsFormcalc,
-                        CFX_WideTextBuf* wsJavascript);
+  static Optional<CFX_WideTextBuf> Translate(WideStringView wsFormcalc);
 
   void GlobalPropertyGetter(CFXJSE_Value* pValue);
 
diff --git a/testing/fuzzers/pdf_fm2js_fuzzer.cc b/testing/fuzzers/pdf_fm2js_fuzzer.cc
index 67daa46..929b811 100644
--- a/testing/fuzzers/pdf_fm2js_fuzzer.cc
+++ b/testing/fuzzers/pdf_fm2js_fuzzer.cc
@@ -11,13 +11,7 @@
 #include "fxjs/xfa/cfxjse_formcalc_context.h"
 
 extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
-  FX_SAFE_SIZE_T safe_size = size;
-  if (!safe_size.IsValid())
-    return 0;
-
-  CFX_WideTextBuf js;
-  WideString input =
-      WideString::FromUTF8(ByteStringView(data, safe_size.ValueOrDie()));
-  CFXJSE_FormCalcContext::Translate(input.AsStringView(), &js);
+  WideString input = WideString::FromUTF8(ByteStringView(data, size));
+  CFXJSE_FormCalcContext::Translate(input.AsStringView());
   return 0;
 }
diff --git a/xfa/fxfa/fm2js/cxfa_fmexpression.cpp b/xfa/fxfa/fm2js/cxfa_fmexpression.cpp
index a87ecca..98be02b 100644
--- a/xfa/fxfa/fm2js/cxfa_fmexpression.cpp
+++ b/xfa/fxfa/fm2js/cxfa_fmexpression.cpp
@@ -45,9 +45,9 @@
 CXFA_FMFunctionDefinition::~CXFA_FMFunctionDefinition() = default;
 
 bool CXFA_FMFunctionDefinition::ToJavaScript(CFX_WideTextBuf* js,
-                                             ReturnType type) {
+                                             ReturnType type) const {
   CXFA_FMToJavaScriptDepth depthManager;
-  if (CXFA_IsTooBig(js) || !depthManager.IsWithinMaxDepth())
+  if (CXFA_IsTooBig(*js) || !depthManager.IsWithinMaxDepth())
     return false;
 
   if (m_wsName.IsEmpty())
@@ -73,7 +73,7 @@
   *js << "return pfm_ret;\n";
   *js << "}\n";
 
-  return !CXFA_IsTooBig(js);
+  return !CXFA_IsTooBig(*js);
 }
 
 CXFA_FMAST::CXFA_FMAST(
@@ -82,35 +82,38 @@
 
 CXFA_FMAST::~CXFA_FMAST() = default;
 
-bool CXFA_FMAST::ToJavaScript(CFX_WideTextBuf* js) {
+Optional<CFX_WideTextBuf> CXFA_FMAST::ToJavaScript() const {
+  CFX_WideTextBuf js;
   if (expressions_.empty()) {
-    *js << "// comments only";
-    return !CXFA_IsTooBig(js);
+    js << "// comments only";
+    return js;
   }
 
-  *js << "(function() {\n";
-  *js << "let pfm_method_runner = function(obj, cb) {\n";
-  *js << "  if (pfm_rt.is_ary(obj)) {\n";
-  *js << "    let pfm_method_return = null;\n";
-  *js << "    for (var idx = obj.length -1; idx > 1; idx--) {\n";
-  *js << "      pfm_method_return = cb(obj[idx]);\n";
-  *js << "    }\n";
-  *js << "    return pfm_method_return;\n";
-  *js << "  }\n";
-  *js << "  return cb(obj);\n";
-  *js << "};\n";
-  *js << "var pfm_ret = null;\n";
-
+  js << "(function() {\n";
+  js << "let pfm_method_runner = function(obj, cb) {\n";
+  js << "  if (pfm_rt.is_ary(obj)) {\n";
+  js << "    let pfm_method_return = null;\n";
+  js << "    for (var idx = obj.length -1; idx > 1; idx--) {\n";
+  js << "      pfm_method_return = cb(obj[idx]);\n";
+  js << "    }\n";
+  js << "    return pfm_method_return;\n";
+  js << "  }\n";
+  js << "  return cb(obj);\n";
+  js << "};\n";
+  js << "var pfm_ret = null;\n";
   for (const auto& expr : expressions_) {
     ReturnType ret_type = expr == expressions_.back() ? ReturnType::kImplied
                                                       : ReturnType::kInfered;
-    if (!expr->ToJavaScript(js, ret_type))
-      return false;
+    if (!expr->ToJavaScript(&js, ret_type))
+      return pdfium::nullopt;
   }
+  js << "return pfm_rt.get_val(pfm_ret);\n";
+  js << "}).call(this);";
 
-  *js << "return pfm_rt.get_val(pfm_ret);\n";
-  *js << "}).call(this);";
-  return !CXFA_IsTooBig(js);
+  if (CXFA_IsTooBig(js))
+    return pdfium::nullopt;
+
+  return js;
 }
 
 CXFA_FMVarExpression::CXFA_FMVarExpression(
@@ -120,9 +123,10 @@
 
 CXFA_FMVarExpression::~CXFA_FMVarExpression() = default;
 
-bool CXFA_FMVarExpression::ToJavaScript(CFX_WideTextBuf* js, ReturnType type) {
+bool CXFA_FMVarExpression::ToJavaScript(CFX_WideTextBuf* js,
+                                        ReturnType type) const {
   CXFA_FMToJavaScriptDepth depthManager;
-  if (CXFA_IsTooBig(js) || !depthManager.IsWithinMaxDepth())
+  if (CXFA_IsTooBig(*js) || !depthManager.IsWithinMaxDepth())
     return false;
 
   WideString tempName = IdentifierToName(m_wsName);
@@ -140,7 +144,7 @@
   if (type == ReturnType::kImplied)
     *js << "pfm_ret = " << tempName << ";\n";
 
-  return !CXFA_IsTooBig(js);
+  return !CXFA_IsTooBig(*js);
 }
 
 CXFA_FMExpExpression::CXFA_FMExpExpression(
@@ -149,9 +153,10 @@
 
 CXFA_FMExpExpression::~CXFA_FMExpExpression() = default;
 
-bool CXFA_FMExpExpression::ToJavaScript(CFX_WideTextBuf* js, ReturnType type) {
+bool CXFA_FMExpExpression::ToJavaScript(CFX_WideTextBuf* js,
+                                        ReturnType type) const {
   CXFA_FMToJavaScriptDepth depthManager;
-  if (CXFA_IsTooBig(js) || !depthManager.IsWithinMaxDepth())
+  if (CXFA_IsTooBig(*js) || !depthManager.IsWithinMaxDepth())
     return false;
 
   if (type == ReturnType::kInfered) {
@@ -175,7 +180,7 @@
       return false;
 
     *js << ");\n";
-    return !CXFA_IsTooBig(js);
+    return !CXFA_IsTooBig(*js);
   }
 
   *js << "pfm_ret = ";
@@ -183,7 +188,7 @@
     return false;
 
   *js << ";\n";
-  return !CXFA_IsTooBig(js);
+  return !CXFA_IsTooBig(*js);
 }
 
 CXFA_FMBlockExpression::CXFA_FMBlockExpression(
@@ -193,9 +198,9 @@
 CXFA_FMBlockExpression::~CXFA_FMBlockExpression() = default;
 
 bool CXFA_FMBlockExpression::ToJavaScript(CFX_WideTextBuf* js,
-                                          ReturnType type) {
+                                          ReturnType type) const {
   CXFA_FMToJavaScriptDepth depthManager;
-  if (CXFA_IsTooBig(js) || !depthManager.IsWithinMaxDepth())
+  if (CXFA_IsTooBig(*js) || !depthManager.IsWithinMaxDepth())
     return false;
 
   *js << "{\n";
@@ -213,7 +218,7 @@
   }
   *js << "}\n";
 
-  return !CXFA_IsTooBig(js);
+  return !CXFA_IsTooBig(*js);
 }
 
 CXFA_FMDoExpression::CXFA_FMDoExpression(
@@ -222,9 +227,10 @@
 
 CXFA_FMDoExpression::~CXFA_FMDoExpression() = default;
 
-bool CXFA_FMDoExpression::ToJavaScript(CFX_WideTextBuf* js, ReturnType type) {
+bool CXFA_FMDoExpression::ToJavaScript(CFX_WideTextBuf* js,
+                                       ReturnType type) const {
   CXFA_FMToJavaScriptDepth depthManager;
-  if (CXFA_IsTooBig(js) || !depthManager.IsWithinMaxDepth())
+  if (CXFA_IsTooBig(*js) || !depthManager.IsWithinMaxDepth())
     return false;
 
   return m_pList->ToJavaScript(js, type);
@@ -245,9 +251,10 @@
 
 CXFA_FMIfExpression::~CXFA_FMIfExpression() = default;
 
-bool CXFA_FMIfExpression::ToJavaScript(CFX_WideTextBuf* js, ReturnType type) {
+bool CXFA_FMIfExpression::ToJavaScript(CFX_WideTextBuf* js,
+                                       ReturnType type) const {
   CXFA_FMToJavaScriptDepth depthManager;
-  if (CXFA_IsTooBig(js) || !depthManager.IsWithinMaxDepth())
+  if (CXFA_IsTooBig(*js) || !depthManager.IsWithinMaxDepth())
     return false;
 
   if (type == ReturnType::kImplied)
@@ -258,13 +265,13 @@
     return false;
   *js << "))\n";
 
-  if (CXFA_IsTooBig(js))
+  if (CXFA_IsTooBig(*js))
     return false;
 
   if (m_pIfExpression) {
     if (!m_pIfExpression->ToJavaScript(js, type))
       return false;
-    if (CXFA_IsTooBig(js))
+    if (CXFA_IsTooBig(*js))
       return false;
   }
 
@@ -279,7 +286,7 @@
     if (!m_pElseExpression->ToJavaScript(js, type))
       return false;
   }
-  return !CXFA_IsTooBig(js);
+  return !CXFA_IsTooBig(*js);
 }
 
 CXFA_FMWhileExpression::CXFA_FMWhileExpression(
@@ -292,9 +299,9 @@
 CXFA_FMWhileExpression::~CXFA_FMWhileExpression() = default;
 
 bool CXFA_FMWhileExpression::ToJavaScript(CFX_WideTextBuf* js,
-                                          ReturnType type) {
+                                          ReturnType type) const {
   CXFA_FMToJavaScriptDepth depthManager;
-  if (CXFA_IsTooBig(js) || !depthManager.IsWithinMaxDepth())
+  if (CXFA_IsTooBig(*js) || !depthManager.IsWithinMaxDepth())
     return false;
 
   if (type == ReturnType::kImplied)
@@ -305,13 +312,13 @@
     return false;
 
   *js << ")\n";
-  if (CXFA_IsTooBig(js))
+  if (CXFA_IsTooBig(*js))
     return false;
 
   if (!m_pExpression->ToJavaScript(js, type))
     return false;
 
-  return !CXFA_IsTooBig(js);
+  return !CXFA_IsTooBig(*js);
 }
 
 CXFA_FMBreakExpression::CXFA_FMBreakExpression() : CXFA_FMExpression() {}
@@ -319,13 +326,13 @@
 CXFA_FMBreakExpression::~CXFA_FMBreakExpression() = default;
 
 bool CXFA_FMBreakExpression::ToJavaScript(CFX_WideTextBuf* js,
-                                          ReturnType type) {
+                                          ReturnType type) const {
   CXFA_FMToJavaScriptDepth depthManager;
-  if (CXFA_IsTooBig(js) || !depthManager.IsWithinMaxDepth())
+  if (CXFA_IsTooBig(*js) || !depthManager.IsWithinMaxDepth())
     return false;
 
   *js << "pfm_ret = 0;\nbreak;\n";
-  return !CXFA_IsTooBig(js);
+  return !CXFA_IsTooBig(*js);
 }
 
 CXFA_FMContinueExpression::CXFA_FMContinueExpression() : CXFA_FMExpression() {}
@@ -333,13 +340,13 @@
 CXFA_FMContinueExpression::~CXFA_FMContinueExpression() = default;
 
 bool CXFA_FMContinueExpression::ToJavaScript(CFX_WideTextBuf* js,
-                                             ReturnType type) {
+                                             ReturnType type) const {
   CXFA_FMToJavaScriptDepth depthManager;
-  if (CXFA_IsTooBig(js) || !depthManager.IsWithinMaxDepth())
+  if (CXFA_IsTooBig(*js) || !depthManager.IsWithinMaxDepth())
     return false;
 
   *js << "pfm_ret = 0;\ncontinue;\n";
-  return !CXFA_IsTooBig(js);
+  return !CXFA_IsTooBig(*js);
 }
 
 CXFA_FMForExpression::CXFA_FMForExpression(
@@ -359,9 +366,10 @@
 
 CXFA_FMForExpression::~CXFA_FMForExpression() = default;
 
-bool CXFA_FMForExpression::ToJavaScript(CFX_WideTextBuf* js, ReturnType type) {
+bool CXFA_FMForExpression::ToJavaScript(CFX_WideTextBuf* js,
+                                        ReturnType type) const {
   CXFA_FMToJavaScriptDepth depthManager;
-  if (CXFA_IsTooBig(js) || !depthManager.IsWithinMaxDepth())
+  if (CXFA_IsTooBig(*js) || !depthManager.IsWithinMaxDepth())
     return false;
 
   if (type == ReturnType::kImplied)
@@ -393,14 +401,14 @@
     *js << "1";
   }
   *js << ")\n";
-  if (CXFA_IsTooBig(js))
+  if (CXFA_IsTooBig(*js))
     return false;
 
   if (!m_pList->ToJavaScript(js, type))
     return false;
 
   *js << "}\n";
-  return !CXFA_IsTooBig(js);
+  return !CXFA_IsTooBig(*js);
 }
 
 CXFA_FMForeachExpression::CXFA_FMForeachExpression(
@@ -415,9 +423,9 @@
 CXFA_FMForeachExpression::~CXFA_FMForeachExpression() = default;
 
 bool CXFA_FMForeachExpression::ToJavaScript(CFX_WideTextBuf* js,
-                                            ReturnType type) {
+                                            ReturnType type) const {
   CXFA_FMToJavaScriptDepth depthManager;
-  if (CXFA_IsTooBig(js) || !depthManager.IsWithinMaxDepth())
+  if (CXFA_IsTooBig(*js) || !depthManager.IsWithinMaxDepth())
     return false;
 
   if (type == ReturnType::kImplied)
@@ -441,8 +449,8 @@
   *js << tmpName << " = pfm_ary[pfm_ary_idx++];\n";
   if (!m_pList->ToJavaScript(js, type))
     return false;
-  *js << "}\n";  // while
 
+  *js << "}\n";  // while
   *js << "}\n";  // block
-  return !CXFA_IsTooBig(js);
+  return !CXFA_IsTooBig(*js);
 }
diff --git a/xfa/fxfa/fm2js/cxfa_fmexpression.h b/xfa/fxfa/fm2js/cxfa_fmexpression.h
index 8b5bd78..f8f54b8 100644
--- a/xfa/fxfa/fm2js/cxfa_fmexpression.h
+++ b/xfa/fxfa/fm2js/cxfa_fmexpression.h
@@ -10,6 +10,7 @@
 #include <memory>
 #include <vector>
 
+#include "third_party/base/optional.h"
 #include "xfa/fxfa/fm2js/cxfa_fmsimpleexpression.h"
 
 class CFX_WideTextBuf;
@@ -17,7 +18,7 @@
 class CXFA_FMExpression {
  public:
   virtual ~CXFA_FMExpression() = default;
-  virtual bool ToJavaScript(CFX_WideTextBuf* js, ReturnType type) = 0;
+  virtual bool ToJavaScript(CFX_WideTextBuf* js, ReturnType type) const = 0;
 
  protected:
   CXFA_FMExpression();
@@ -31,7 +32,7 @@
       std::vector<std::unique_ptr<CXFA_FMExpression>>&& expressions);
   ~CXFA_FMFunctionDefinition() override;
 
-  bool ToJavaScript(CFX_WideTextBuf* js, ReturnType type) override;
+  bool ToJavaScript(CFX_WideTextBuf* js, ReturnType type) const override;
 
  private:
   const WideStringView m_wsName;
@@ -45,7 +46,7 @@
                        std::unique_ptr<CXFA_FMSimpleExpression> pInit);
   ~CXFA_FMVarExpression() override;
 
-  bool ToJavaScript(CFX_WideTextBuf* js, ReturnType type) override;
+  bool ToJavaScript(CFX_WideTextBuf* js, ReturnType type) const override;
 
  private:
   WideStringView const m_wsName;
@@ -58,7 +59,7 @@
       std::unique_ptr<CXFA_FMSimpleExpression> pExpression);
   ~CXFA_FMExpExpression() override;
 
-  bool ToJavaScript(CFX_WideTextBuf* js, ReturnType type) override;
+  bool ToJavaScript(CFX_WideTextBuf* js, ReturnType type) const override;
 
  private:
   std::unique_ptr<CXFA_FMSimpleExpression> const m_pExpression;
@@ -70,7 +71,7 @@
       std::vector<std::unique_ptr<CXFA_FMExpression>>&& pExpressionList);
   ~CXFA_FMBlockExpression() override;
 
-  bool ToJavaScript(CFX_WideTextBuf* js, ReturnType type) override;
+  bool ToJavaScript(CFX_WideTextBuf* js, ReturnType type) const override;
 
  private:
   std::vector<std::unique_ptr<CXFA_FMExpression>> const m_ExpressionList;
@@ -81,7 +82,7 @@
   explicit CXFA_FMDoExpression(std::unique_ptr<CXFA_FMExpression> pList);
   ~CXFA_FMDoExpression() override;
 
-  bool ToJavaScript(CFX_WideTextBuf* js, ReturnType type) override;
+  bool ToJavaScript(CFX_WideTextBuf* js, ReturnType type) const override;
 
  private:
   std::unique_ptr<CXFA_FMExpression> const m_pList;
@@ -96,7 +97,7 @@
       std::unique_ptr<CXFA_FMExpression> pElseExpression);
   ~CXFA_FMIfExpression() override;
 
-  bool ToJavaScript(CFX_WideTextBuf* js, ReturnType type) override;
+  bool ToJavaScript(CFX_WideTextBuf* js, ReturnType type) const override;
 
  private:
   std::unique_ptr<CXFA_FMSimpleExpression> const m_pExpression;
@@ -111,7 +112,7 @@
                          std::unique_ptr<CXFA_FMExpression> pExpression);
   ~CXFA_FMWhileExpression() override;
 
-  bool ToJavaScript(CFX_WideTextBuf* js, ReturnType type) override;
+  bool ToJavaScript(CFX_WideTextBuf* js, ReturnType type) const override;
 
  private:
   std::unique_ptr<CXFA_FMSimpleExpression> const m_pCondition;
@@ -123,7 +124,7 @@
   CXFA_FMBreakExpression();
   ~CXFA_FMBreakExpression() override;
 
-  bool ToJavaScript(CFX_WideTextBuf* js, ReturnType type) override;
+  bool ToJavaScript(CFX_WideTextBuf* js, ReturnType type) const override;
 };
 
 class CXFA_FMContinueExpression final : public CXFA_FMExpression {
@@ -131,7 +132,7 @@
   CXFA_FMContinueExpression();
   ~CXFA_FMContinueExpression() override;
 
-  bool ToJavaScript(CFX_WideTextBuf* js, ReturnType type) override;
+  bool ToJavaScript(CFX_WideTextBuf* js, ReturnType type) const override;
 };
 
 class CXFA_FMForExpression final : public CXFA_FMExpression {
@@ -144,7 +145,7 @@
                        std::unique_ptr<CXFA_FMExpression> pList);
   ~CXFA_FMForExpression() override;
 
-  bool ToJavaScript(CFX_WideTextBuf* js, ReturnType type) override;
+  bool ToJavaScript(CFX_WideTextBuf* js, ReturnType type) const override;
 
  private:
   const WideStringView m_wsVariant;
@@ -164,7 +165,7 @@
       std::unique_ptr<CXFA_FMExpression> pList);
   ~CXFA_FMForeachExpression() override;
 
-  bool ToJavaScript(CFX_WideTextBuf* js, ReturnType type) override;
+  bool ToJavaScript(CFX_WideTextBuf* js, ReturnType type) const override;
 
  private:
   const WideStringView m_wsIdentifier;
@@ -178,7 +179,7 @@
       std::vector<std::unique_ptr<CXFA_FMExpression>> expressions);
   ~CXFA_FMAST();
 
-  bool ToJavaScript(CFX_WideTextBuf* js);
+  Optional<CFX_WideTextBuf> ToJavaScript() const;
 
  private:
   std::vector<std::unique_ptr<CXFA_FMExpression>> const expressions_;
diff --git a/xfa/fxfa/fm2js/cxfa_fmparser_unittest.cpp b/xfa/fxfa/fm2js/cxfa_fmparser_unittest.cpp
index 50fa577..64f1a0b 100644
--- a/xfa/fxfa/fm2js/cxfa_fmparser_unittest.cpp
+++ b/xfa/fxfa/fm2js/cxfa_fmparser_unittest.cpp
@@ -15,10 +15,10 @@
   EXPECT_FALSE(parser->HasError());
 
   CXFA_FMToJavaScriptDepth::Reset();
-  CFX_WideTextBuf buf;
-  EXPECT_TRUE(ast->ToJavaScript(&buf));
+  Optional<CFX_WideTextBuf> buf = ast->ToJavaScript();
+  ASSERT_TRUE(buf.has_value());
   // TODO(dsinclair): This is a little weird .....
-  EXPECT_STREQ(L"// comments only", buf.MakeString().c_str());
+  EXPECT_STREQ(L"// comments only", buf.value().MakeString().c_str());
 }
 
 TEST(CXFA_FMParserTest, CommentOnlyIsError) {
@@ -30,9 +30,9 @@
   // EXPECT_TRUE(parser->HasError());
 
   CXFA_FMToJavaScriptDepth::Reset();
-  CFX_WideTextBuf buf;
-  EXPECT_TRUE(ast->ToJavaScript(&buf));
-  EXPECT_STREQ(L"// comments only", buf.MakeString().c_str());
+  Optional<CFX_WideTextBuf> buf = ast->ToJavaScript();
+  ASSERT_TRUE(buf.has_value());
+  EXPECT_STREQ(L"// comments only", buf.value().MakeString().c_str());
 }
 
 TEST(CXFA_FMParserTest, CommentThenValue) {
@@ -59,9 +59,9 @@
   EXPECT_FALSE(parser->HasError());
 
   CXFA_FMToJavaScriptDepth::Reset();
-  CFX_WideTextBuf buf;
-  EXPECT_TRUE(ast->ToJavaScript(&buf));
-  EXPECT_STREQ(ret, buf.MakeString().c_str());
+  Optional<CFX_WideTextBuf> buf = ast->ToJavaScript();
+  ASSERT_TRUE(buf.has_value());
+  EXPECT_STREQ(ret, buf.value().MakeString().c_str());
 }
 
 TEST(CXFA_FMParserTest, Parse) {
@@ -128,9 +128,9 @@
   EXPECT_FALSE(parser->HasError());
 
   CXFA_FMToJavaScriptDepth::Reset();
-  CFX_WideTextBuf buf;
-  EXPECT_TRUE(ast->ToJavaScript(&buf));
-  EXPECT_EQ(ret, buf.AsStringView());
+  Optional<CFX_WideTextBuf> buf = ast->ToJavaScript();
+  ASSERT_TRUE(buf.has_value());
+  EXPECT_EQ(ret, buf.value().AsStringView());
 }
 
 TEST(CXFA_FMParserTest, MaxParseDepth) {
@@ -190,9 +190,9 @@
   EXPECT_FALSE(parser->HasError());
 
   CXFA_FMToJavaScriptDepth::Reset();
-  CFX_WideTextBuf buf;
-  EXPECT_TRUE(ast->ToJavaScript(&buf));
-  EXPECT_STREQ(ret, buf.MakeString().c_str());
+  Optional<CFX_WideTextBuf> buf = ast->ToJavaScript();
+  ASSERT_TRUE(buf.has_value());
+  EXPECT_STREQ(ret, buf.value().MakeString().c_str());
 }
 
 TEST(CXFA_FMParserTest, ParseFuncWithoutParams) {
@@ -228,9 +228,9 @@
   EXPECT_FALSE(parser->HasError());
 
   CXFA_FMToJavaScriptDepth::Reset();
-  CFX_WideTextBuf buf;
-  EXPECT_TRUE(ast->ToJavaScript(&buf));
-  EXPECT_STREQ(ret, buf.MakeString().c_str());
+  Optional<CFX_WideTextBuf> buf = ast->ToJavaScript();
+  ASSERT_TRUE(buf.has_value());
+  EXPECT_STREQ(ret, buf.value().MakeString().c_str());
 }
 
 TEST(CXFA_FMParserTest, ParseFuncWithBadParamsList) {
@@ -312,9 +312,9 @@
   EXPECT_FALSE(parser->HasError());
 
   CXFA_FMToJavaScriptDepth::Reset();
-  CFX_WideTextBuf buf;
-  EXPECT_TRUE(ast->ToJavaScript(&buf));
-  EXPECT_STREQ(ret, buf.MakeString().c_str());
+  Optional<CFX_WideTextBuf> buf = ast->ToJavaScript();
+  ASSERT_TRUE(buf.has_value());
+  EXPECT_STREQ(ret, buf.value().MakeString().c_str());
 }
 
 TEST(CXFA_FMParserTest, ParseCallBig) {
@@ -353,9 +353,9 @@
   EXPECT_FALSE(parser->HasError());
 
   CXFA_FMToJavaScriptDepth::Reset();
-  CFX_WideTextBuf buf;
-  EXPECT_TRUE(ast->ToJavaScript(&buf));
-  EXPECT_STREQ(ret, buf.MakeString().c_str());
+  Optional<CFX_WideTextBuf> buf = ast->ToJavaScript();
+  ASSERT_TRUE(buf.has_value());
+  EXPECT_STREQ(ret, buf.value().MakeString().c_str());
 }
 
 TEST(CXFA_FMParserTest, ParseVar) {
@@ -384,9 +384,9 @@
   EXPECT_FALSE(parser->HasError());
 
   CXFA_FMToJavaScriptDepth::Reset();
-  CFX_WideTextBuf buf;
-  EXPECT_TRUE(ast->ToJavaScript(&buf));
-  EXPECT_STREQ(ret, buf.MakeString().c_str());
+  Optional<CFX_WideTextBuf> buf = ast->ToJavaScript();
+  ASSERT_TRUE(buf.has_value());
+  EXPECT_STREQ(ret, buf.value().MakeString().c_str());
 }
 
 TEST(CXFA_FMParserTest, ParseFunctionCallNoArguments) {
@@ -416,9 +416,9 @@
   std::unique_ptr<CXFA_FMAST> ast = parser->Parse();
   EXPECT_FALSE(parser->HasError());
   CXFA_FMToJavaScriptDepth::Reset();
-  CFX_WideTextBuf buf;
-  EXPECT_TRUE(ast->ToJavaScript(&buf));
-  EXPECT_STREQ(ret, buf.MakeString().c_str());
+  Optional<CFX_WideTextBuf> buf = ast->ToJavaScript();
+  ASSERT_TRUE(buf.has_value());
+  EXPECT_STREQ(ret, buf.value().MakeString().c_str());
 }
 
 TEST(CXFA_FMParserTest, ParseFunctionCallSingleArgument) {
@@ -448,9 +448,9 @@
   std::unique_ptr<CXFA_FMAST> ast = parser->Parse();
   EXPECT_FALSE(parser->HasError());
   CXFA_FMToJavaScriptDepth::Reset();
-  CFX_WideTextBuf buf;
-  EXPECT_TRUE(ast->ToJavaScript(&buf));
-  EXPECT_STREQ(ret, buf.MakeString().c_str());
+  Optional<CFX_WideTextBuf> buf = ast->ToJavaScript();
+  ASSERT_TRUE(buf.has_value());
+  EXPECT_STREQ(ret, buf.value().MakeString().c_str());
 }
 
 TEST(CXFA_FMParserTest, ParseFunctionCallMultipleArguments) {
@@ -480,9 +480,9 @@
   std::unique_ptr<CXFA_FMAST> ast = parser->Parse();
   EXPECT_FALSE(parser->HasError());
   CXFA_FMToJavaScriptDepth::Reset();
-  CFX_WideTextBuf buf;
-  EXPECT_TRUE(ast->ToJavaScript(&buf));
-  EXPECT_STREQ(ret, buf.MakeString().c_str());
+  Optional<CFX_WideTextBuf> buf = ast->ToJavaScript();
+  ASSERT_TRUE(buf.has_value());
+  EXPECT_STREQ(ret, buf.value().MakeString().c_str());
 }
 
 TEST(CXFA_FMParserTest, ParseFunctionCallMissingCommas) {
diff --git a/xfa/fxfa/fm2js/cxfa_fmsimpleexpression.cpp b/xfa/fxfa/fm2js/cxfa_fmsimpleexpression.cpp
index db3cd11..2371c44 100644
--- a/xfa/fxfa/fm2js/cxfa_fmsimpleexpression.cpp
+++ b/xfa/fxfa/fm2js/cxfa_fmsimpleexpression.cpp
@@ -141,11 +141,11 @@
 
 bool CXFA_FMNullExpression::ToJavaScript(CFX_WideTextBuf* js, ReturnType type) {
   CXFA_FMToJavaScriptDepth depthManager;
-  if (CXFA_IsTooBig(js) || !depthManager.IsWithinMaxDepth())
+  if (CXFA_IsTooBig(*js) || !depthManager.IsWithinMaxDepth())
     return false;
 
   *js << "null";
-  return !CXFA_IsTooBig(js);
+  return !CXFA_IsTooBig(*js);
 }
 
 CXFA_FMNumberExpression::CXFA_FMNumberExpression(WideStringView wsNumber)
@@ -156,11 +156,11 @@
 bool CXFA_FMNumberExpression::ToJavaScript(CFX_WideTextBuf* js,
                                            ReturnType type) {
   CXFA_FMToJavaScriptDepth depthManager;
-  if (CXFA_IsTooBig(js) || !depthManager.IsWithinMaxDepth())
+  if (CXFA_IsTooBig(*js) || !depthManager.IsWithinMaxDepth())
     return false;
 
   *js << m_wsNumber;
-  return !CXFA_IsTooBig(js);
+  return !CXFA_IsTooBig(*js);
 }
 
 CXFA_FMStringExpression::CXFA_FMStringExpression(WideStringView wsString)
@@ -171,13 +171,13 @@
 bool CXFA_FMStringExpression::ToJavaScript(CFX_WideTextBuf* js,
                                            ReturnType type) {
   CXFA_FMToJavaScriptDepth depthManager;
-  if (CXFA_IsTooBig(js) || !depthManager.IsWithinMaxDepth())
+  if (CXFA_IsTooBig(*js) || !depthManager.IsWithinMaxDepth())
     return false;
 
   WideString tempStr(m_wsString);
   if (tempStr.GetLength() <= 2) {
     *js << tempStr;
-    return !CXFA_IsTooBig(js);
+    return !CXFA_IsTooBig(*js);
   }
 
   *js << "\"";
@@ -199,7 +199,7 @@
     }
   }
   *js << "\"";
-  return !CXFA_IsTooBig(js);
+  return !CXFA_IsTooBig(*js);
 }
 
 CXFA_FMIdentifierExpression::CXFA_FMIdentifierExpression(
@@ -211,7 +211,7 @@
 bool CXFA_FMIdentifierExpression::ToJavaScript(CFX_WideTextBuf* js,
                                                ReturnType type) {
   CXFA_FMToJavaScriptDepth depthManager;
-  if (CXFA_IsTooBig(js) || !depthManager.IsWithinMaxDepth())
+  if (CXFA_IsTooBig(*js) || !depthManager.IsWithinMaxDepth())
     return false;
 
   if (m_wsIdentifier.EqualsASCII("$"))
@@ -235,7 +235,7 @@
   else
     *js << m_wsIdentifier;
 
-  return !CXFA_IsTooBig(js);
+  return !CXFA_IsTooBig(*js);
 }
 
 CXFA_FMAssignExpression::CXFA_FMAssignExpression(
@@ -249,7 +249,7 @@
 bool CXFA_FMAssignExpression::ToJavaScript(CFX_WideTextBuf* js,
                                            ReturnType type) {
   CXFA_FMToJavaScriptDepth depthManager;
-  if (CXFA_IsTooBig(js) || !depthManager.IsWithinMaxDepth())
+  if (CXFA_IsTooBig(*js) || !depthManager.IsWithinMaxDepth())
     return false;
 
   CFX_WideTextBuf tempExp1;
@@ -278,7 +278,7 @@
     *js << "(" << tempExp1 << ", " << tempExp2 << ");\n";
     *js << "}\n";
   }
-  return !CXFA_IsTooBig(js);
+  return !CXFA_IsTooBig(*js);
 }
 
 CXFA_FMBinExpression::CXFA_FMBinExpression(
@@ -293,7 +293,7 @@
 
 bool CXFA_FMBinExpression::ToJavaScript(CFX_WideTextBuf* js, ReturnType type) {
   CXFA_FMToJavaScriptDepth depthManager;
-  if (CXFA_IsTooBig(js) || !depthManager.IsWithinMaxDepth())
+  if (CXFA_IsTooBig(*js) || !depthManager.IsWithinMaxDepth())
     return false;
 
   *js << "pfm_rt." << m_OpName << "(";
@@ -303,7 +303,7 @@
   if (!GetSecondExpression()->ToJavaScript(js, ReturnType::kInfered))
     return false;
   *js << ")";
-  return !CXFA_IsTooBig(js);
+  return !CXFA_IsTooBig(*js);
 }
 
 CXFA_FMLogicalOrExpression::CXFA_FMLogicalOrExpression(
@@ -399,14 +399,14 @@
 bool CXFA_FMUnaryExpression::ToJavaScript(CFX_WideTextBuf* js,
                                           ReturnType type) {
   CXFA_FMToJavaScriptDepth depthManager;
-  if (CXFA_IsTooBig(js) || !depthManager.IsWithinMaxDepth())
+  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);
+  return !CXFA_IsTooBig(*js);
 }
 
 CXFA_FMPosExpression::CXFA_FMPosExpression(
@@ -467,7 +467,7 @@
 
 bool CXFA_FMCallExpression::ToJavaScript(CFX_WideTextBuf* js, ReturnType type) {
   CXFA_FMToJavaScriptDepth depthManager;
-  if (CXFA_IsTooBig(js) || !depthManager.IsWithinMaxDepth())
+  if (CXFA_IsTooBig(*js) || !depthManager.IsWithinMaxDepth())
     return false;
 
   CFX_WideTextBuf funcName;
@@ -506,7 +506,7 @@
       }
     }
     *js << ")";
-    return !CXFA_IsTooBig(js);
+    return !CXFA_IsTooBig(*js);
   }
 
   bool isEvalFunc = false;
@@ -554,7 +554,7 @@
   if (isEvalFunc)
     *js << ")";
 
-  return !CXFA_IsTooBig(js);
+  return !CXFA_IsTooBig(*js);
 }
 
 CXFA_FMDotAccessorExpression::CXFA_FMDotAccessorExpression(
@@ -572,7 +572,7 @@
 bool CXFA_FMDotAccessorExpression::ToJavaScript(CFX_WideTextBuf* js,
                                                 ReturnType type) {
   CXFA_FMToJavaScriptDepth depthManager;
-  if (CXFA_IsTooBig(js) || !depthManager.IsWithinMaxDepth())
+  if (CXFA_IsTooBig(*js) || !depthManager.IsWithinMaxDepth())
     return false;
 
   *js << "pfm_rt.dot_acc(";
@@ -607,7 +607,7 @@
     return false;
 
   *js << ")";
-  return !CXFA_IsTooBig(js);
+  return !CXFA_IsTooBig(*js);
 }
 
 CXFA_FMIndexExpression::CXFA_FMIndexExpression(
@@ -624,7 +624,7 @@
 bool CXFA_FMIndexExpression::ToJavaScript(CFX_WideTextBuf* js,
                                           ReturnType type) {
   CXFA_FMToJavaScriptDepth depthManager;
-  if (CXFA_IsTooBig(js) || !depthManager.IsWithinMaxDepth())
+  if (CXFA_IsTooBig(*js) || !depthManager.IsWithinMaxDepth())
     return false;
 
   switch (m_accessorIndex) {
@@ -644,7 +644,7 @@
       *js << "0";
   }
   if (m_bIsStarIndex)
-    return !CXFA_IsTooBig(js);
+    return !CXFA_IsTooBig(*js);
 
   *js << ", ";
   if (m_pExp) {
@@ -653,7 +653,7 @@
   } else {
     *js << "0";
   }
-  return !CXFA_IsTooBig(js);
+  return !CXFA_IsTooBig(*js);
 }
 
 CXFA_FMDotDotAccessorExpression::CXFA_FMDotDotAccessorExpression(
@@ -671,7 +671,7 @@
 bool CXFA_FMDotDotAccessorExpression::ToJavaScript(CFX_WideTextBuf* js,
                                                    ReturnType type) {
   CXFA_FMToJavaScriptDepth depthManager;
-  if (CXFA_IsTooBig(js) || !depthManager.IsWithinMaxDepth())
+  if (CXFA_IsTooBig(*js) || !depthManager.IsWithinMaxDepth())
     return false;
 
   CXFA_FMSimpleExpression* exp1 = GetFirstExpression();
@@ -690,7 +690,7 @@
   if (!exp2->ToJavaScript(js, ReturnType::kInfered))
     return false;
   *js << ")";
-  return !CXFA_IsTooBig(js);
+  return !CXFA_IsTooBig(*js);
 }
 
 CXFA_FMMethodCallExpression::CXFA_FMMethodCallExpression(
@@ -705,7 +705,7 @@
 bool CXFA_FMMethodCallExpression::ToJavaScript(CFX_WideTextBuf* js,
                                                ReturnType type) {
   CXFA_FMToJavaScriptDepth depthManager;
-  if (CXFA_IsTooBig(js) || !depthManager.IsWithinMaxDepth())
+  if (CXFA_IsTooBig(*js) || !depthManager.IsWithinMaxDepth())
     return false;
 
   CFX_WideTextBuf buf;
@@ -720,9 +720,9 @@
   *js << ";\n";
   *js << "  });\n";
   *js << "}).call(this)";
-  return !CXFA_IsTooBig(js);
+  return !CXFA_IsTooBig(*js);
 }
 
-bool CXFA_IsTooBig(const CFX_WideTextBuf* js) {
-  return js->GetSize() >= 256 * 1024 * 1024;
+bool CXFA_IsTooBig(const CFX_WideTextBuf& js) {
+  return js.GetSize() >= 256 * 1024 * 1024;
 }
diff --git a/xfa/fxfa/fm2js/cxfa_fmsimpleexpression.h b/xfa/fxfa/fm2js/cxfa_fmsimpleexpression.h
index 6657b56..81c341c 100644
--- a/xfa/fxfa/fm2js/cxfa_fmsimpleexpression.h
+++ b/xfa/fxfa/fm2js/cxfa_fmsimpleexpression.h
@@ -333,6 +333,6 @@
   bool ToJavaScript(CFX_WideTextBuf* js, ReturnType type) override;
 };
 
-bool CXFA_IsTooBig(const CFX_WideTextBuf* js);
+bool CXFA_IsTooBig(const CFX_WideTextBuf& js);
 
 #endif  // XFA_FXFA_FM2JS_CXFA_FMSIMPLEEXPRESSION_H_