Avoid N^2 copies in CXFA_FMDotAccessorExpression::ToJavaScript().

The local tempExp1 will be repeatedly copied into its caller's
tempExp1 getting larger each time as the recursion unwinds. The
cost now is we may have to generate a string twice, but we do
so into a single buffer.

The referenced bug seems recurse until we hit the 5000 frame
limit in the depth manager.

We'll probably need a follow-up bug to look at the other temporaries.

Bug: chromium:1274018
Change-Id: Ieafcc1e3e1aab412cbcb447f5bcb87d43ab364a2
Reviewed-on: https://pdfium-review.googlesource.com/c/pdfium/+/87732
Reviewed-by: Lei Zhang <thestig@chromium.org>
Commit-Queue: Tom Sepez <tsepez@chromium.org>
diff --git a/xfa/fxfa/fm2js/cxfa_fmexpression.cpp b/xfa/fxfa/fm2js/cxfa_fmexpression.cpp
index 6aac77f..ad3d5da 100644
--- a/xfa/fxfa/fm2js/cxfa_fmexpression.cpp
+++ b/xfa/fxfa/fm2js/cxfa_fmexpression.cpp
@@ -567,21 +567,22 @@
 
   *js << "pfm_rt.dot_acc(";
 
-  CFX_WideTextBuf tempExp1;
   CXFA_FMSimpleExpression* exp1 = GetFirstExpression();
   if (exp1) {
-    if (!exp1->ToJavaScript(&tempExp1, ReturnType::kInferred))
+    // Write directly to the buffer with each recursion. Creating
+    // and copying temporaries here becomes expensive when there
+    // is deep recursion, even though we may need to re-create the
+    // same thing again below. See https://crbug.com/1274018.
+    if (!exp1->ToJavaScript(js, ReturnType::kInferred))
       return false;
-
-    *js << tempExp1;
   } else {
     *js << "null";
   }
   *js << ", \"";
-
-  if (exp1 && exp1->GetOperatorToken() == TOKidentifier)
-    *js << tempExp1;
-
+  if (exp1 && exp1->GetOperatorToken() == TOKidentifier) {
+    if (!exp1->ToJavaScript(js, ReturnType::kInferred))
+      return false;
+  }
   *js << "\", ";
   if (GetOperatorToken() == TOKdotscream)
     *js << "\"#" << m_wsIdentifier << "\", ";