From ae7da6ae480f97e8a7b14fdadd9deeef0ce8790f Mon Sep 17 00:00:00 2001 From: Calixte Denizet Date: Mon, 28 Nov 2022 15:53:17 +0100 Subject: [PATCH] [JS] By default, a text field value must be treated as a number (bug 1802888) --- src/scripting_api/field.js | 21 +++++++++++++---- src/scripting_api/util.js | 1 + test/integration/scripting_spec.js | 36 +++++++++++++++++++++++++++++ test/pdfs/.gitignore | 1 + test/pdfs/bug1802888.pdf | Bin 0 -> 7553 bytes test/unit/scripting_spec.js | 6 ++--- 6 files changed, 57 insertions(+), 8 deletions(-) create mode 100755 test/pdfs/bug1802888.pdf diff --git a/src/scripting_api/field.js b/src/scripting_api/field.js index bdb2add5f..59501b912 100644 --- a/src/scripting_api/field.js +++ b/src/scripting_api/field.js @@ -80,7 +80,7 @@ class Field extends PDFObject { this._page = data.page || 0; this._strokeColor = data.strokeColor || ["G", 0]; this._textColor = data.textColor || ["G", 0]; - this._value = data.value || ""; + this._value = null; this._kidIds = data.kidIds || null; this._fieldType = getFieldType(this._actions); this._siblings = data.siblings || null; @@ -88,6 +88,9 @@ class Field extends PDFObject { this._globalEval = data.globalEval; this._appObjects = data.appObjects; + + // The value is set depending on the field type. + this.value = data.value || ""; } get currentValueIndices() { @@ -243,12 +246,13 @@ class Field extends PDFObject { this._value = ""; } else if (typeof value === "string") { switch (this._fieldType) { + case FieldType.none: + this._value = !isNaN(value) ? parseFloat(value) : value; + break; case FieldType.number: case FieldType.percent: - value = parseFloat(value); - if (!isNaN(value)) { - this._value = value; - } + const number = parseFloat(value); + this._value = !isNaN(number) ? number : 0; break; default: this._value = value; @@ -563,6 +567,9 @@ class RadioButtonField extends Field { this._id = radioData.id; } } + + this._hasBeenInitialized = true; + this._value = data.value || ""; } get value() { @@ -570,6 +577,10 @@ class RadioButtonField extends Field { } set value(value) { + if (!this._hasBeenInitialized) { + return; + } + if (value === null || value === undefined) { this._value = ""; } diff --git a/src/scripting_api/util.js b/src/scripting_api/util.js index 262c1f0aa..8496683e3 100644 --- a/src/scripting_api/util.js +++ b/src/scripting_api/util.js @@ -297,6 +297,7 @@ class Util extends PDFObject { printx(cFormat, cSource) { // case + cSource = (cSource ?? "").toString(); const handlers = [x => x, x => x.toUpperCase(), x => x.toLowerCase()]; const buf = []; let i = 0; diff --git a/test/integration/scripting_spec.js b/test/integration/scripting_spec.js index 64467f644..81afb33d7 100644 --- a/test/integration/scripting_spec.js +++ b/test/integration/scripting_spec.js @@ -1562,4 +1562,40 @@ describe("Interaction", () => { ); }); }); + + describe("in bug1802888.pdf", () => { + let pages; + + beforeAll(async () => { + pages = await loadAndWait("bug1802888.pdf", getSelector("30R")); + }); + + afterAll(async () => { + await closePages(pages); + }); + + it("must check field value is treated by default as a number", async () => { + await Promise.all( + pages.map(async ([browserName, page]) => { + await page.waitForFunction( + "window.PDFViewerApplication.scriptingReady === true" + ); + + await page.type(getSelector("30R"), "123", { + delay: 10, + }); + await page.click(getSelector("31R")); + await page.type(getSelector("31R"), "456", { + delay: 10, + }); + await page.click(getSelector("26R")); + await page.click(getSelector("27R")); + await page.waitForFunction(`${getQuerySelector("26R")}.value !== ""`); + + const value = await page.$eval(getSelector("26R"), el => el.value); + expect(value).withContext(`In ${browserName}`).toEqual("579"); + }) + ); + }); + }); }); diff --git a/test/pdfs/.gitignore b/test/pdfs/.gitignore index a2f82e23b..f5b148498 100644 --- a/test/pdfs/.gitignore +++ b/test/pdfs/.gitignore @@ -556,3 +556,4 @@ !textfields.pdf !freetext_no_appearance.pdf !issue15690.pdf +!bug1802888.pdf diff --git a/test/pdfs/bug1802888.pdf b/test/pdfs/bug1802888.pdf new file mode 100755 index 0000000000000000000000000000000000000000..08ddcb5a3078adffe6abd0f91232e3e1ba7255e5 GIT binary patch literal 7553 zcmeHM3se(l77khv0*J4o)oMqC3QLlCWb!nm5JDh?2touDsSL>^M3W380|`{D)QVQY zTC7qnZq>T3^r^P1Y^ANN)Jmm_h;=QyT}y3o=>xa*h1z!iNqEE>ck4O3=j@(i&Ph&Y z=D+v9_q*SJb8l``hEl~vdBV`Bo-aaK_Y>G z52r(@5Ke;l2quE(g4;SsgyA@x0_8!t5P?t;o-db&k~RaQ1M>9>Wn=u2J(Q%LGLRXB z-Rb~4CQ_DCtIYx7aE6^UnDsPehfqu|hgD_^P1<3Vg`i1~2&`7-$&`pvk{|-MBuY>L zf-5AdM1F!2MH3U0A_V2*av6$aiDIQ7Nr^~QiX>bq5vvr61fc@K5Rp)UCdu<*waq}f z@_^$Q&RiHN2xSb+gwsfyi7tW!V#b;>#!&&BNl`R}3f#}L05lL^4C~5^NjNu?G{QM~ zD1<>MfWSf9Nx~Y+F8Zvn&@ir`ps?VhQ4>P;#XnWTTO;<1&=H(~aV_tRPg(YE>*3a8 zd&fl{J)FY($4ezQC$C_QW|f$Oehy^=6bID|;_09XJMFTQ#!xmA%8rUkN>_!lhcFIh z^F<@L`T`6>QNfT?VjP50B!IIZ9D%bT33{8!1qB7Bf`U#1Yt;J3LiVh9Xw8Bt;_&Tj z_a~yGSI!(QqO#H+H0^kAlydEJRaG}9JZ)?WZcPgbk$t`6))(>ZA02Kk8UKQD18>#Z z#bW{yR!|4q9a^W4+bY35E9NREu;n+p{wuo6ZPCOl(ZdLl6uS@WcWUq%*Li)0f6Tx+Ux+-CaPE+y$invtR?9hJP4t z3-XIrUm;kch-mGTdA zdru#-z8$w&fL5*r|v*s)VI}sAF%Se-jz8|PCvP8 zV@(pLZ9zkAZsuN>Zm*%WvtcuO{B%Rq#O&4>&8+>kA989J$YP4Lxf5pZN;gmM<$Ro5 zcVWC^4L*C0|FOC?@4EaZe;L!P7>Iu+JhlS2uqO8(L#(m$*B#h#_Tc2Vg6B`4#51>k zwryKW+8?Uh-@LR)qSzI(qvzQBPoAHw3IDL=+#iFVFTM60duDBHE7v?JyuZv@cJ*0f zYWC*KFZ_|6zgF}{Yy9qIn(ElTBaeRi|l6Sa=f9pnd^U1}_YpS1zmc>Y# z$$jZz{d=)T)>*_`YLZ`@l6*w=Ok@3Alz2J1zYo4;>G9(< z?6>5RCr&(UI_SsitNP+P^>E`8>5|{R7;cQszEHmKn{z*Aba%W8`o zO#ZQ*g)eNJxm$3;v9{;SH^<2j9^E4>R}3^bFCI91a9r)4>(BP4esZZO@cde;qrPKx zSyj)t6aJS@@miOxn%d1a-{j{mSr)&iDVwWPFSY$<<@CnL{c6A3ufkIDA3oBVs@`;_*__c|UlHT?yGh-1=@l<- zbuK;p2^`xPjl71xSp!LHAM9McsR>&g$=&*gs@fv!n7l6I>y{6@r5)QZX_n-`u8RqQ zDRAYfM`9{nVWO>Pn?AoWBl{^=3%rdE>CI{y`+CLV;3Yd>{X8)v<49!LHr7Ln9#l-` zJb7c4an@6fXYj>I0h`X)g3BT&z3tyOqdV$sWbKZyMUCI`He|i?_{;}63;Vu~_G_Fv zb(H!Czr>2Jrct%E7xzqgjW`mU9yqNwFwcCbBld^YeH=krbf{5#;PIYKg1~8-$Eqha zzfqRg|ML9Y;225Ad)IzyH61zhQEGaTtn6s|=B0|Jvx53pHxO@rb1^b)`{k8>RWoT>x*U#EV?SsdaL@?4YnD7>20Z8 zenI}XIhXg;Zcp;hpLNvm$T6~la^#0uoG^3w zBTwBF7T+kJ@#zY`8o!$4f^X(UTwim3*7{}2{*_(T!d+P{`Tow*3vXN<8}~|h*q>q) z6D_PyS#KxDch4$oDOxtMY|NE>aoyP79C7_Mr+RslW^J;w?ZVB!M$tcxo%m#Z>yh!V zFPL;;-t*FdX-@Tx%eSF)$-uO({j<9sU;NVMw_*=1 z*!ffC?xO4M-B;NV|_; zS$CZ>SSJl8C1fN4`4IRu2@b`F6P&w{ziWEKa*&L@8OS~zOQH9lHm$PvR%i1B|HR6J z?K^uWY=6E=vEjY+h=zwU7i@T?fAPY)ja%v$T1;cQ&Ifj}>w;1^ss4TV>geN~Huagn zl(h8u(Z|!csp)4Pc(wEyAwK$evQp(|c4%g;YVK@k$o;XP^4hHp%jV2sO5pR;W_SB= zjw#v(!MJPoMu$r#6cK>rjomGGV|WIVf#5nsl)ZP~DQ7BYZt3xpv8S%3d>o_Uwx!MO za(=8ik>1v>$wBr%@JdMMHBGzLU-R{t`bRhE!guwpW(6f8jbWWjO{*;#y26C5!5L3v z7OGJtrQ4~QV0)M47r^@K2k<^0Zg_P-gE8gvh4^rdma9$k*gRASj|5!yn5&r3FC}TH zkTjWXaS{E8-j9IHhPa3vffmsgCz3_xlnOhURWVnmuUM*=7$P2%vt=%+%UWy&Wi{lo zT5JxfD=vZnJsK$m-qFO7>xU>-oZ+6*X>vXc-fc({550i}_I$H&A*k&xto zvI)arL<}P+7nMj+M2bm<8j%P&)04>T2BS1nsT$l5T*XBc(R8sChMi6)&&lUeb`y+B zBoY|GU<~7e6CoHF#k85SL5yCakSe9)A|i&HA7<}C$E?M} z8`&H@x05_QWrbZtF${`j*q4w&KP*#RYPYyeGw5N`LRy(#0mz{~ThNOCQU@kQfwaI|hu6wq z=oljR9a?-@GT0Hi*Zx9}dk4y{qbQ5q!`(qFAkZg3(L$VCXr^PBzKYKS4vR65bKYWJ z8V!1>5wu7IEhmbLEoMEzunq=ck-;O6yw=XbLJ6Nw@VU5v zAh|dp)N>_bT)@@yNil(f7h({(&CqJSW$)0dwt=SKrYDE=l9)t55E#KVVkpkV^&&l& zzyu^0kw}DMk-OD&DZ*ouI z-iPZxT=#^)JuSY^uKRG^69V_N_&&S-V{oxY8X_bV<+b?N=jZQT_`i^=_6uOnIQdJzSh#$?V!LL;Q zkkz5Z1$%LP<%@w`FJ^9SNNs+utc>YugW{1)A8vUKUH&KLdUuZU@H+>1;I9z(4C!AC z@K~cBReg6nBrT-Inb2ASwd4gBUa4C1b^N*6c`G;p0jeo2*Taq$-U#c#SRm${J%N!v O!0{U1p{Q_peD_cG^H-w) literal 0 HcmV?d00001 diff --git a/test/unit/scripting_spec.js b/test/unit/scripting_spec.js index bfcc10a56..87274f7ee 100644 --- a/test/unit/scripting_spec.js +++ b/test/unit/scripting_spec.js @@ -346,7 +346,7 @@ describe("Scripting", function () { expect(send_queue.has(refId)).toEqual(true); expect(send_queue.get(refId)).toEqual({ id: refId, - value: "123", + value: 123, }); }); @@ -826,7 +826,7 @@ describe("Scripting", function () { expect(send_queue.get(refId)).toEqual({ id: refId, siblings: null, - value: "123456.789", + value: 123456.789, formattedValue: null, }); }); @@ -1006,7 +1006,7 @@ describe("Scripting", function () { expect(send_queue.get(refId)).toEqual({ id: refId, siblings: null, - value: "321", + value: 321, formattedValue: null, }); });