diff options
author | Dan Sinclair <dsinclair@chromium.org> | 2018-05-10 14:01:25 +0000 |
---|---|---|
committer | Chromium commit bot <commit-bot@chromium.org> | 2018-05-10 14:01:25 +0000 |
commit | 35557c3ce83cc6e26f07cf5d5c520ee6afd39a67 (patch) | |
tree | 69a5c3322c00807c3e04fb5172cfc8b4a6c6f694 /xfa/fxfa | |
parent | ad18d2fba9dd5833a2e34bfe90c8e3c9a485e805 (diff) | |
download | pdfium-35557c3ce83cc6e26f07cf5d5c520ee6afd39a67.tar.xz |
Change formcalc javascript method output
This CL changes the formcalc JS conversion code so that method calls no
longer generate exponential amounts of JavaScript.
Previously we'd duplicate the code to call into a method twice. This
would then generate twice once for arrays and once for other types of
object. This CL changes the code to wrap the actual method call into
a JavaScript function which will be used from both the array and
non-array calling code.
For the referenced bug, the generated JS originally needed a buffer of
365meg to generate. With this CL, it needs a buffer of 7.5k.
Bug: chromium:814840
Change-Id: Ibb5993fa52b7c13b20b325cf8848a306f82ae014
Reviewed-on: https://pdfium-review.googlesource.com/32312
Reviewed-by: Henrique Nakashima <hnakashima@chromium.org>
Reviewed-by: Ryan Harrison <rharrison@chromium.org>
Commit-Queue: dsinclair <dsinclair@chromium.org>
Diffstat (limited to 'xfa/fxfa')
-rw-r--r-- | xfa/fxfa/fm2js/cxfa_fmparser_unittest.cpp | 86 | ||||
-rw-r--r-- | xfa/fxfa/fm2js/cxfa_fmsimpleexpression.cpp | 27 |
2 files changed, 100 insertions, 13 deletions
diff --git a/xfa/fxfa/fm2js/cxfa_fmparser_unittest.cpp b/xfa/fxfa/fm2js/cxfa_fmparser_unittest.cpp index 1eedebfcca..0dba59c3bb 100644 --- a/xfa/fxfa/fm2js/cxfa_fmparser_unittest.cpp +++ b/xfa/fxfa/fm2js/cxfa_fmparser_unittest.cpp @@ -257,3 +257,89 @@ TEST(CXFA_FMParserTest, ParseDepthWithWideTree) { EXPECT_TRUE(parser->HasError()); } } + +TEST(CXFA_FMParserTest, ParseCallSmall) { + const wchar_t input[] = {L"i.f(O)"}; + const wchar_t ret[] = { + L"(function() {\n" + L"var pfm_ret = null;\n" + L"pfm_ret = pfm_rt.get_val((function () {\n" + L"let pfm_cb = function(obj) {\n" + L"return obj.f(pfm_rt.get_val(O));\n" + L"};\n" + L"if (pfm_rt.is_ary(i)) {\n" + L"let method_return_value = null;\n" + L"for (var index = i.length - 1; index > 1; index--) {\n" + L"method_return_value = pfm_cb(i[index]);\n" + L"}\n" + L"return method_return_value;\n" + L"} else {\n" + L"return pfm_cb(i);\n" + L"}}).call(this));\n" + L"return pfm_rt.get_val(pfm_ret);\n" + L"}).call(this);"}; + + auto parser = pdfium::MakeUnique<CXFA_FMParser>(input); + std::unique_ptr<CXFA_FMAST> ast = parser->Parse(); + EXPECT_FALSE(parser->HasError()); + + CXFA_FMToJavaScriptDepth::Reset(); + CFX_WideTextBuf buf; + EXPECT_TRUE(ast->ToJavaScript(buf)); + EXPECT_EQ(ret, buf.AsStringView()); +} + +TEST(CXFA_FMParserTest, ParseCallBig) { + const wchar_t input[] = {L"i.f(O.e(O.e(O)))"}; + const wchar_t ret[] = { + L"(function() {\n" + L"var pfm_ret = null;\n" + L"pfm_ret = pfm_rt.get_val((function () {\n" + L"let pfm_cb = function(obj) {\n" + L"return obj.f(pfm_rt.get_val((function () {\n" + L"let pfm_cb = function(obj) {\n" + L"return obj.e(pfm_rt.get_val((function () {\n" + L"let pfm_cb = function(obj) {\n" + L"return obj.e(pfm_rt.get_val(O));\n" + L"};\n" + L"if (pfm_rt.is_ary(O)) {\n" + L"let method_return_value = null;\n" + L"for (var index = O.length - 1; index > 1; index--) {\n" + L"method_return_value = pfm_cb(O[index]);\n" + L"}\n" + L"return method_return_value;\n" + L"} else {\n" + L"return pfm_cb(O);\n" + L"}}).call(this)));\n" + L"};\n" + L"if (pfm_rt.is_ary(O)) {\n" + L"let method_return_value = null;\n" + L"for (var index = O.length - 1; index > 1; index--) {\n" + L"method_return_value = pfm_cb(O[index]);\n" + L"}\n" + L"return method_return_value;\n" + L"} else {\n" + L"return pfm_cb(O);\n" + L"}}).call(this)));\n" + L"};\n" + L"if (pfm_rt.is_ary(i)) {\n" + L"let method_return_value = null;\n" + L"for (var index = i.length - 1; index > 1; index--) {\n" + L"method_return_value = pfm_cb(i[index]);\n" + L"}\n" + L"return method_return_value;\n" + L"} else {\n" + L"return pfm_cb(i);\n" + L"}}).call(this));\n" + L"return pfm_rt.get_val(pfm_ret);\n" + L"}).call(this);"}; + + auto parser = pdfium::MakeUnique<CXFA_FMParser>(input); + std::unique_ptr<CXFA_FMAST> ast = parser->Parse(); + EXPECT_FALSE(parser->HasError()); + + CXFA_FMToJavaScriptDepth::Reset(); + CFX_WideTextBuf buf; + EXPECT_TRUE(ast->ToJavaScript(buf)); + EXPECT_EQ(ret, buf.AsStringView()); +} diff --git a/xfa/fxfa/fm2js/cxfa_fmsimpleexpression.cpp b/xfa/fxfa/fm2js/cxfa_fmsimpleexpression.cpp index 0cfb37e8d0..069899311e 100644 --- a/xfa/fxfa/fm2js/cxfa_fmsimpleexpression.cpp +++ b/xfa/fxfa/fm2js/cxfa_fmsimpleexpression.cpp @@ -672,25 +672,26 @@ bool CXFA_FMMethodCallExpression::ToJavaScript(CFX_WideTextBuf& js, if (CXFA_IsTooBig(js) || !depthManager.IsWithinMaxDepth()) return false; - CFX_WideTextBuf exp2_txt; - if (!m_pExp2->ToJavaScript(exp2_txt, ReturnType::kInfered)) + CFX_WideTextBuf buf; + if (!m_pExp1->ToJavaScript(buf, ReturnType::kInfered)) return false; - js << L"(\nfunction ()\n{\n"; - js << L"var method_return_value = null;\n"; - js << L"var accessor_object = "; - if (!m_pExp1->ToJavaScript(js, ReturnType::kInfered)) + js << L"(function () {\n"; + js << L"let pfm_cb = function(obj) {\n"; + js << L"return obj."; + if (!m_pExp2->ToJavaScript(js, ReturnType::kInfered)) return false; js << L";\n"; - js << L"if (pfm_rt.is_ary(accessor_object))\n{\n"; - js << L"for(var index = accessor_object.length - 1; index > 1; " - L"index--)\n{\n"; - js << L"method_return_value = accessor_object[index]." << exp2_txt << L";\n"; - js << L"}\n}\nelse\n{\n"; - js << L"method_return_value = accessor_object." << exp2_txt << L";\n"; + js << L"};\n"; + js << L"if (pfm_rt.is_ary(" << buf << L")) {\n"; + js << L"let method_return_value = null;\n"; + js << L"for (var index = " << buf << L".length - 1; index > 1; index--) {\n"; + js << L"method_return_value = pfm_cb(" << buf << L"[index]);\n"; js << L"}\n"; js << L"return method_return_value;\n"; - js << L"}\n).call(this)"; + js << L"} else {\n"; + js << L"return pfm_cb(" << buf << L");\n"; + js << L"}}).call(this)"; return !CXFA_IsTooBig(js); } |