7#include "fxjs/xfa/cfxjse_formcalc_context.h"
20#include "core/fxcrt/cfx_datetime.h"
21#include "core/fxcrt/code_point_view.h"
22#include "core/fxcrt/data_vector.h"
23#include "core/fxcrt/fx_extension.h"
24#include "core/fxcrt/fx_random.h"
25#include "core/fxcrt/fx_safe_types.h"
26#include "core/fxcrt/widetext_buffer.h"
28#include "fxjs/xfa/cfxjse_class.h"
29#include "fxjs/xfa/cfxjse_context.h"
30#include "fxjs/xfa/cfxjse_engine.h"
31#include "fxjs/xfa/cfxjse_value.h"
32#include "fxjs/xfa/cjx_object.h"
33#include "third_party/abseil-cpp/absl/types/optional.h"
34#include "third_party/base/check_op.h"
35#include "third_party/base/numerics/safe_conversions.h"
36#include "v8/include/v8-container.h"
37#include "v8/include/v8-function-callback.h"
38#include "v8/include/v8-local-handle.h"
39#include "v8/include/v8-object.h"
40#include "v8/include/v8-primitive.h"
41#include "xfa/fgas/crt/cfgas_decimal.h"
42#include "xfa/fxfa/cxfa_ffnotify.h"
43#include "xfa/fxfa/formcalc/cxfa_fmparser.h"
44#include "xfa/fxfa/formcalc/cxfa_fmtojavascriptdepth.h"
45#include "xfa/fxfa/parser/cxfa_document.h"
46#include "xfa/fxfa/parser/cxfa_localevalue.h"
47#include "xfa/fxfa/parser/cxfa_node.h"
48#include "xfa/fxfa/parser/cxfa_thisproxy.h"
49#include "xfa/fxfa/parser/cxfa_timezoneprovider.h"
50#include "xfa/fxfa/parser/gced_locale_iface.h"
51#include "xfa/fxfa/parser/xfa_utils.h"
53using pdfium::
fxjse::kClassTag;
54using pdfium::
fxjse::kFuncTag;
59constexpr int kMaxCharCount = 15654908;
61const double kFinancialPrecision = 0.00000001;
63const wchar_t kStrCode[] = L"0123456789abcdef";
65struct XFA_FMHtmlReserveCode {
68 const char m_htmlReserve[10];
72const XFA_FMHtmlReserveCode kReservesForDecode[] = {
73 {198,
"AElig"}, {193,
"Aacute"}, {194,
"Acirc"}, {192,
"Agrave"},
74 {913,
"Alpha"}, {197,
"Aring"}, {195,
"Atilde"}, {196,
"Auml"},
75 {914,
"Beta"}, {199,
"Ccedil"}, {935,
"Chi"}, {8225,
"Dagger"},
76 {916,
"Delta"}, {208,
"ETH"}, {201,
"Eacute"}, {202,
"Ecirc"},
77 {200,
"Egrave"}, {917,
"Epsilon"}, {919,
"Eta"}, {203,
"Euml"},
78 {915,
"Gamma"}, {922,
"Kappa"}, {923,
"Lambda"}, {924,
"Mu"},
79 {209,
"Ntilde"}, {925,
"Nu"}, {338,
"OElig"}, {211,
"Oacute"},
80 {212,
"Ocirc"}, {210,
"Ograve"}, {937,
"Omega"}, {927,
"Omicron"},
81 {216,
"Oslash"}, {213,
"Otilde"}, {214,
"Ouml"}, {934,
"Phi"},
82 {928,
"Pi"}, {936,
"Psi"}, {929,
"Rho"}, {352,
"Scaron"},
83 {931,
"Sigma"}, {222,
"THORN"}, {932,
"Tau"}, {920,
"Theta"},
84 {218,
"Uacute"}, {219,
"Ucirc"}, {217,
"Ugrave"}, {933,
"Upsilon"},
85 {220,
"Uuml"}, {926,
"Xi"}, {221,
"Yacute"}, {376,
"Yuml"},
86 {918,
"Zeta"}, {225,
"aacute"}, {226,
"acirc"}, {180,
"acute"},
87 {230,
"aelig"}, {224,
"agrave"}, {8501,
"alefsym"}, {945,
"alpha"},
88 {38,
"amp"}, {8743,
"and"}, {8736,
"ang"}, {39,
"apos"},
89 {229,
"aring"}, {8776,
"asymp"}, {227,
"atilde"}, {228,
"auml"},
90 {8222,
"bdquo"}, {946,
"beta"}, {166,
"brvbar"}, {8226,
"bull"},
91 {8745,
"cap"}, {231,
"ccedil"}, {184,
"cedil"}, {162,
"cent"},
92 {967,
"chi"}, {710,
"circ"}, {9827,
"clubs"}, {8773,
"cong"},
93 {169,
"copy"}, {8629,
"crarr"}, {8746,
"cup"}, {164,
"current"},
94 {8659,
"dArr"}, {8224,
"dagger"}, {8595,
"darr"}, {176,
"deg"},
95 {948,
"delta"}, {9830,
"diams"}, {247,
"divide"}, {233,
"eacute"},
96 {234,
"ecirc"}, {232,
"egrave"}, {8709,
"empty"}, {8195,
"emsp"},
97 {8194,
"ensp"}, {949,
"epsilon"}, {8801,
"equiv"}, {951,
"eta"},
98 {240,
"eth"}, {235,
"euml"}, {8364,
"euro"}, {8707,
"exist"},
99 {402,
"fnof"}, {8704,
"forall"}, {189,
"frac12"}, {188,
"frac14"},
100 {190,
"frac34"}, {8260,
"frasl"}, {947,
"gamma"}, {8805,
"ge"},
101 {62,
"gt"}, {8660,
"hArr"}, {8596,
"harr"}, {9829,
"hearts"},
102 {8230,
"hellip"}, {237,
"iacute"}, {238,
"icirc"}, {161,
"iexcl"},
103 {236,
"igrave"}, {8465,
"image"}, {8734,
"infin"}, {8747,
"int"},
104 {953,
"iota"}, {191,
"iquest"}, {8712,
"isin"}, {239,
"iuml"},
105 {954,
"kappa"}, {8656,
"lArr"}, {205,
"lacute"}, {955,
"lambda"},
106 {9001,
"lang"}, {171,
"laquo"}, {8592,
"larr"}, {8968,
"lceil"},
107 {206,
"lcirc"}, {8220,
"ldquo"}, {8804,
"le"}, {8970,
"lfloor"},
108 {204,
"lgrave"}, {921,
"lota"}, {8727,
"lowast"}, {9674,
"loz"},
109 {8206,
"lrm"}, {8249,
"lsaquo"}, {8216,
"lsquo"}, {60,
"lt"},
110 {207,
"luml"}, {175,
"macr"}, {8212,
"mdash"}, {181,
"micro"},
111 {183,
"middot"}, {8722,
"minus"}, {956,
"mu"}, {8711,
"nabla"},
112 {160,
"nbsp"}, {8211,
"ndash"}, {8800,
"ne"}, {8715,
"ni"},
113 {172,
"not"}, {8713,
"notin"}, {8836,
"nsub"}, {241,
"ntilde"},
114 {957,
"nu"}, {243,
"oacute"}, {244,
"ocirc"}, {339,
"oelig"},
115 {242,
"ograve"}, {8254,
"oline"}, {969,
"omega"}, {959,
"omicron"},
116 {8853,
"oplus"}, {8744,
"or"}, {170,
"ordf"}, {186,
"ordm"},
117 {248,
"oslash"}, {245,
"otilde"}, {8855,
"otimes"}, {246,
"ouml"},
118 {182,
"para"}, {8706,
"part"}, {8240,
"permil"}, {8869,
"perp"},
119 {966,
"phi"}, {960,
"pi"}, {982,
"piv"}, {177,
"plusmn"},
120 {8242,
"prime"}, {8719,
"prod"}, {8733,
"prop"}, {968,
"psi"},
121 {163,
"pund"}, {34,
"quot"}, {8658,
"rArr"}, {8730,
"radic"},
122 {9002,
"rang"}, {187,
"raquo"}, {8594,
"rarr"}, {8969,
"rceil"},
123 {8476,
"real"}, {174,
"reg"}, {8971,
"rfloor"}, {961,
"rho"},
124 {8207,
"rlm"}, {8250,
"rsaquo"}, {8217,
"rsquo"}, {353,
"saron"},
125 {8218,
"sbquo"}, {8901,
"sdot"}, {167,
"sect"}, {173,
"shy"},
126 {963,
"sigma"}, {962,
"sigmaf"}, {8764,
"sim"}, {9824,
"spades"},
127 {8834,
"sub"}, {8838,
"sube"}, {8721,
"sum"}, {8835,
"sup"},
128 {185,
"sup1"}, {178,
"sup2"}, {179,
"sup3"}, {8839,
"supe"},
129 {223,
"szlig"}, {964,
"tau"}, {8221,
"tdquo"}, {8756,
"there4"},
130 {952,
"theta"}, {977,
"thetasym"}, {8201,
"thinsp"}, {254,
"thorn"},
131 {732,
"tilde"}, {215,
"times"}, {8482,
"trade"}, {8657,
"uArr"},
132 {250,
"uacute"}, {8593,
"uarr"}, {251,
"ucirc"}, {249,
"ugrave"},
133 {168,
"uml"}, {978,
"upsih"}, {965,
"upsilon"}, {252,
"uuml"},
134 {8472,
"weierp"}, {958,
"xi"}, {253,
"yacute"}, {165,
"yen"},
135 {255,
"yuml"}, {950,
"zeta"}, {8205,
"zwj"}, {8204,
"zwnj"},
139const XFA_FMHtmlReserveCode kReservesForEncode[] = {
140 {34,
"quot"}, {38,
"amp"}, {39,
"apos"}, {60,
"lt"},
141 {62,
"gt"}, {160,
"nbsp"}, {161,
"iexcl"}, {162,
"cent"},
142 {163,
"pund"}, {164,
"current"}, {165,
"yen"}, {166,
"brvbar"},
143 {167,
"sect"}, {168,
"uml"}, {169,
"copy"}, {170,
"ordf"},
144 {171,
"laquo"}, {172,
"not"}, {173,
"shy"}, {174,
"reg"},
145 {175,
"macr"}, {176,
"deg"}, {177,
"plusmn"}, {178,
"sup2"},
146 {179,
"sup3"}, {180,
"acute"}, {181,
"micro"}, {182,
"para"},
147 {183,
"middot"}, {184,
"cedil"}, {185,
"sup1"}, {186,
"ordm"},
148 {187,
"raquo"}, {188,
"frac14"}, {189,
"frac12"}, {190,
"frac34"},
149 {191,
"iquest"}, {192,
"Agrave"}, {193,
"Aacute"}, {194,
"Acirc"},
150 {195,
"Atilde"}, {196,
"Auml"}, {197,
"Aring"}, {198,
"AElig"},
151 {199,
"Ccedil"}, {200,
"Egrave"}, {201,
"Eacute"}, {202,
"Ecirc"},
152 {203,
"Euml"}, {204,
"lgrave"}, {205,
"lacute"}, {206,
"lcirc"},
153 {207,
"luml"}, {208,
"ETH"}, {209,
"Ntilde"}, {210,
"Ograve"},
154 {211,
"Oacute"}, {212,
"Ocirc"}, {213,
"Otilde"}, {214,
"Ouml"},
155 {215,
"times"}, {216,
"Oslash"}, {217,
"Ugrave"}, {218,
"Uacute"},
156 {219,
"Ucirc"}, {220,
"Uuml"}, {221,
"Yacute"}, {222,
"THORN"},
157 {223,
"szlig"}, {224,
"agrave"}, {225,
"aacute"}, {226,
"acirc"},
158 {227,
"atilde"}, {228,
"auml"}, {229,
"aring"}, {230,
"aelig"},
159 {231,
"ccedil"}, {232,
"egrave"}, {233,
"eacute"}, {234,
"ecirc"},
160 {235,
"euml"}, {236,
"igrave"}, {237,
"iacute"}, {238,
"icirc"},
161 {239,
"iuml"}, {240,
"eth"}, {241,
"ntilde"}, {242,
"ograve"},
162 {243,
"oacute"}, {244,
"ocirc"}, {245,
"otilde"}, {246,
"ouml"},
163 {247,
"divide"}, {248,
"oslash"}, {249,
"ugrave"}, {250,
"uacute"},
164 {251,
"ucirc"}, {252,
"uuml"}, {253,
"yacute"}, {254,
"thorn"},
165 {255,
"yuml"}, {338,
"OElig"}, {339,
"oelig"}, {352,
"Scaron"},
166 {353,
"saron"}, {376,
"Yuml"}, {402,
"fnof"}, {710,
"circ"},
167 {732,
"tilde"}, {913,
"Alpha"}, {914,
"Beta"}, {915,
"Gamma"},
168 {916,
"Delta"}, {917,
"Epsilon"}, {918,
"Zeta"}, {919,
"Eta"},
169 {920,
"Theta"}, {921,
"lota"}, {922,
"Kappa"}, {923,
"Lambda"},
170 {924,
"Mu"}, {925,
"Nu"}, {926,
"Xi"}, {927,
"Omicron"},
171 {928,
"Pi"}, {929,
"Rho"}, {931,
"Sigma"}, {932,
"Tau"},
172 {933,
"Upsilon"}, {934,
"Phi"}, {935,
"Chi"}, {936,
"Psi"},
173 {937,
"Omega"}, {945,
"alpha"}, {946,
"beta"}, {947,
"gamma"},
174 {948,
"delta"}, {949,
"epsilon"}, {950,
"zeta"}, {951,
"eta"},
175 {952,
"theta"}, {953,
"iota"}, {954,
"kappa"}, {955,
"lambda"},
176 {956,
"mu"}, {957,
"nu"}, {958,
"xi"}, {959,
"omicron"},
177 {960,
"pi"}, {961,
"rho"}, {962,
"sigmaf"}, {963,
"sigma"},
178 {964,
"tau"}, {965,
"upsilon"}, {966,
"phi"}, {967,
"chi"},
179 {968,
"psi"}, {969,
"omega"}, {977,
"thetasym"}, {978,
"upsih"},
180 {982,
"piv"}, {8194,
"ensp"}, {8195,
"emsp"}, {8201,
"thinsp"},
181 {8204,
"zwnj"}, {8205,
"zwj"}, {8206,
"lrm"}, {8207,
"rlm"},
182 {8211,
"ndash"}, {8212,
"mdash"}, {8216,
"lsquo"}, {8217,
"rsquo"},
183 {8218,
"sbquo"}, {8220,
"ldquo"}, {8221,
"tdquo"}, {8222,
"bdquo"},
184 {8224,
"dagger"}, {8225,
"Dagger"}, {8226,
"bull"}, {8230,
"hellip"},
185 {8240,
"permil"}, {8242,
"prime"}, {8249,
"lsaquo"}, {8250,
"rsaquo"},
186 {8254,
"oline"}, {8260,
"frasl"}, {8364,
"euro"}, {8465,
"image"},
187 {8472,
"weierp"}, {8476,
"real"}, {8482,
"trade"}, {8501,
"alefsym"},
188 {8592,
"larr"}, {8593,
"uarr"}, {8594,
"rarr"}, {8595,
"darr"},
189 {8596,
"harr"}, {8629,
"crarr"}, {8656,
"lArr"}, {8657,
"uArr"},
190 {8658,
"rArr"}, {8659,
"dArr"}, {8660,
"hArr"}, {8704,
"forall"},
191 {8706,
"part"}, {8707,
"exist"}, {8709,
"empty"}, {8711,
"nabla"},
192 {8712,
"isin"}, {8713,
"notin"}, {8715,
"ni"}, {8719,
"prod"},
193 {8721,
"sum"}, {8722,
"minus"}, {8727,
"lowast"}, {8730,
"radic"},
194 {8733,
"prop"}, {8734,
"infin"}, {8736,
"ang"}, {8743,
"and"},
195 {8744,
"or"}, {8745,
"cap"}, {8746,
"cup"}, {8747,
"int"},
196 {8756,
"there4"}, {8764,
"sim"}, {8773,
"cong"}, {8776,
"asymp"},
197 {8800,
"ne"}, {8801,
"equiv"}, {8804,
"le"}, {8805,
"ge"},
198 {8834,
"sub"}, {8835,
"sup"}, {8836,
"nsub"}, {8838,
"sube"},
199 {8839,
"supe"}, {8853,
"oplus"}, {8855,
"otimes"}, {8869,
"perp"},
200 {8901,
"sdot"}, {8968,
"lceil"}, {8969,
"rceil"}, {8970,
"lfloor"},
201 {8971,
"rfloor"}, {9001,
"lang"}, {9002,
"rang"}, {9674,
"loz"},
202 {9824,
"spades"}, {9827,
"clubs"}, {9829,
"hearts"}, {9830,
"diams"},
206 {
kFuncTag,
"Abs", CFXJSE_FormCalcContext::Abs},
207 {
kFuncTag,
"Avg", CFXJSE_FormCalcContext::Avg},
208 {
kFuncTag,
"Ceil", CFXJSE_FormCalcContext::Ceil},
209 {
kFuncTag,
"Count", CFXJSE_FormCalcContext::Count},
210 {
kFuncTag,
"Floor", CFXJSE_FormCalcContext::Floor},
211 {
kFuncTag,
"Max", CFXJSE_FormCalcContext::Max},
212 {
kFuncTag,
"Min", CFXJSE_FormCalcContext::Min},
213 {
kFuncTag,
"Mod", CFXJSE_FormCalcContext::Mod},
214 {
kFuncTag,
"Round", CFXJSE_FormCalcContext::Round},
215 {
kFuncTag,
"Sum", CFXJSE_FormCalcContext::Sum},
216 {
kFuncTag,
"Date", CFXJSE_FormCalcContext::Date},
217 {
kFuncTag,
"Date2Num", CFXJSE_FormCalcContext::Date2Num},
218 {
kFuncTag,
"DateFmt", CFXJSE_FormCalcContext::DateFmt},
219 {
kFuncTag,
"IsoDate2Num", CFXJSE_FormCalcContext::IsoDate2Num},
220 {
kFuncTag,
"IsoTime2Num", CFXJSE_FormCalcContext::IsoTime2Num},
221 {
kFuncTag,
"LocalDateFmt", CFXJSE_FormCalcContext::LocalDateFmt},
222 {
kFuncTag,
"LocalTimeFmt", CFXJSE_FormCalcContext::LocalTimeFmt},
223 {
kFuncTag,
"Num2Date", CFXJSE_FormCalcContext::Num2Date},
224 {
kFuncTag,
"Num2GMTime", CFXJSE_FormCalcContext::Num2GMTime},
225 {
kFuncTag,
"Num2Time", CFXJSE_FormCalcContext::Num2Time},
226 {
kFuncTag,
"Time", CFXJSE_FormCalcContext::Time},
227 {
kFuncTag,
"Time2Num", CFXJSE_FormCalcContext::Time2Num},
228 {
kFuncTag,
"TimeFmt", CFXJSE_FormCalcContext::TimeFmt},
229 {
kFuncTag,
"Apr", CFXJSE_FormCalcContext::Apr},
230 {
kFuncTag,
"Cterm", CFXJSE_FormCalcContext::CTerm},
231 {
kFuncTag,
"FV", CFXJSE_FormCalcContext::FV},
232 {
kFuncTag,
"Ipmt", CFXJSE_FormCalcContext::IPmt},
233 {
kFuncTag,
"NPV", CFXJSE_FormCalcContext::NPV},
234 {
kFuncTag,
"Pmt", CFXJSE_FormCalcContext::Pmt},
235 {
kFuncTag,
"PPmt", CFXJSE_FormCalcContext::PPmt},
236 {
kFuncTag,
"PV", CFXJSE_FormCalcContext::PV},
237 {
kFuncTag,
"Rate", CFXJSE_FormCalcContext::Rate},
238 {
kFuncTag,
"Term", CFXJSE_FormCalcContext::Term},
239 {
kFuncTag,
"Choose", CFXJSE_FormCalcContext::Choose},
240 {
kFuncTag,
"Exists", CFXJSE_FormCalcContext::Exists},
241 {
kFuncTag,
"HasValue", CFXJSE_FormCalcContext::HasValue},
242 {
kFuncTag,
"Oneof", CFXJSE_FormCalcContext::Oneof},
243 {
kFuncTag,
"Within", CFXJSE_FormCalcContext::Within},
244 {
kFuncTag,
"If", CFXJSE_FormCalcContext::If},
245 {
kFuncTag,
"Eval", CFXJSE_FormCalcContext::Eval},
246 {
kFuncTag,
"Translate", CFXJSE_FormCalcContext::eval_translation},
247 {
kFuncTag,
"Ref", CFXJSE_FormCalcContext::Ref},
248 {
kFuncTag,
"UnitType", CFXJSE_FormCalcContext::UnitType},
249 {
kFuncTag,
"UnitValue", CFXJSE_FormCalcContext::UnitValue},
250 {
kFuncTag,
"At", CFXJSE_FormCalcContext::At},
251 {
kFuncTag,
"Concat", CFXJSE_FormCalcContext::Concat},
252 {
kFuncTag,
"Decode", CFXJSE_FormCalcContext::Decode},
253 {
kFuncTag,
"Encode", CFXJSE_FormCalcContext::Encode},
254 {
kFuncTag,
"Format", CFXJSE_FormCalcContext::Format},
255 {
kFuncTag,
"Left", CFXJSE_FormCalcContext::Left},
256 {
kFuncTag,
"Len", CFXJSE_FormCalcContext::Len},
257 {
kFuncTag,
"Lower", CFXJSE_FormCalcContext::Lower},
258 {
kFuncTag,
"Ltrim", CFXJSE_FormCalcContext::Ltrim},
259 {
kFuncTag,
"Parse", CFXJSE_FormCalcContext::Parse},
260 {
kFuncTag,
"Replace", CFXJSE_FormCalcContext::Replace},
261 {
kFuncTag,
"Right", CFXJSE_FormCalcContext::Right},
262 {
kFuncTag,
"Rtrim", CFXJSE_FormCalcContext::Rtrim},
263 {
kFuncTag,
"Space", CFXJSE_FormCalcContext::Space},
264 {
kFuncTag,
"Str", CFXJSE_FormCalcContext::Str},
265 {
kFuncTag,
"Stuff", CFXJSE_FormCalcContext::Stuff},
266 {
kFuncTag,
"Substr", CFXJSE_FormCalcContext::Substr},
267 {
kFuncTag,
"Uuid", CFXJSE_FormCalcContext::Uuid},
268 {
kFuncTag,
"Upper", CFXJSE_FormCalcContext::Upper},
269 {
kFuncTag,
"WordNum", CFXJSE_FormCalcContext::WordNum},
270 {
kFuncTag,
"Get", CFXJSE_FormCalcContext::Get},
271 {
kFuncTag,
"Post", CFXJSE_FormCalcContext::Post},
272 {
kFuncTag,
"Put", CFXJSE_FormCalcContext::Put},
273 {
kFuncTag,
"pos_op", CFXJSE_FormCalcContext::positive_operator},
274 {
kFuncTag,
"neg_op", CFXJSE_FormCalcContext::negative_operator},
275 {
kFuncTag,
"log_or_op", CFXJSE_FormCalcContext::logical_or_operator},
276 {
kFuncTag,
"log_and_op", CFXJSE_FormCalcContext::logical_and_operator},
277 {
kFuncTag,
"log_not_op", CFXJSE_FormCalcContext::logical_not_operator},
278 {
kFuncTag,
"eq_op", CFXJSE_FormCalcContext::equality_operator},
279 {
kFuncTag,
"neq_op", CFXJSE_FormCalcContext::notequality_operator},
280 {
kFuncTag,
"lt_op", CFXJSE_FormCalcContext::less_operator},
281 {
kFuncTag,
"le_op", CFXJSE_FormCalcContext::lessequal_operator},
282 {
kFuncTag,
"gt_op", CFXJSE_FormCalcContext::greater_operator},
283 {
kFuncTag,
"ge_op", CFXJSE_FormCalcContext::greaterequal_operator},
284 {
kFuncTag,
"plus_op", CFXJSE_FormCalcContext::plus_operator},
285 {
kFuncTag,
"minus_op", CFXJSE_FormCalcContext::minus_operator},
286 {
kFuncTag,
"mul_op", CFXJSE_FormCalcContext::multiple_operator},
287 {
kFuncTag,
"div_op", CFXJSE_FormCalcContext::divide_operator},
288 {
kFuncTag,
"asgn_val_op", CFXJSE_FormCalcContext::assign_value_operator},
289 {
kFuncTag,
"dot_acc", CFXJSE_FormCalcContext::dot_accessor},
290 {
kFuncTag,
"dotdot_acc", CFXJSE_FormCalcContext::dotdot_accessor},
291 {
kFuncTag,
"concat_obj", CFXJSE_FormCalcContext::concat_fm_object},
292 {
kFuncTag,
"is_obj", CFXJSE_FormCalcContext::is_fm_object},
293 {
kFuncTag,
"is_ary", CFXJSE_FormCalcContext::is_fm_array},
294 {
kFuncTag,
"get_val", CFXJSE_FormCalcContext::get_fm_value},
295 {
kFuncTag,
"get_jsobj", CFXJSE_FormCalcContext::get_fm_jsobj},
296 {
kFuncTag,
"var_filter", CFXJSE_FormCalcContext::fm_var_filter},
299const uint8_t kAltTableDate[] = {
300 255, 255, 255, 3, 9, 255, 255, 255, 255, 255, 255,
301 255, 2, 255, 255, 255, 255, 255, 255, 255, 255, 255,
302 255, 255, 1, 255, 255, 255, 255, 255, 255, 255, 255,
304static_assert(
std::size(kAltTableDate) == L'a' - L'A' + 1,
305 "Invalid kAltTableDate size.");
307const uint8_t kAltTableTime[] = {
308 14, 255, 255, 3, 9, 255, 255, 15, 255, 255, 255,
309 255, 6, 255, 255, 255, 255, 255, 7, 255, 255, 255,
310 255, 255, 1, 17, 255, 255, 255, 255, 255, 255, 255,
312static_assert(
std::size(kAltTableTime) == L'a' - L'A' + 1,
313 "Invalid kAltTableTime size.");
315void AlternateDateTimeSymbols(WideString* pPattern,
316 const WideString& wsAltSymbols,
318 const uint8_t* pAltTable = bIsDate ? kAltTableDate : kAltTableTime;
319 int32_t nLength = pPattern->GetLength();
320 bool bInConstRange =
false;
321 bool bEscape =
false;
323 while (i < nLength) {
324 wchar_t wc = (*pPattern)
[i
];
326 bInConstRange = !bInConstRange;
336 if (!bInConstRange && wc >= L'A' && wc <= L'a') {
337 uint8_t nAlt = pAltTable[wc - L'A'];
339 pPattern->SetAt(i, wsAltSymbols
[nAlt
]);
347 ByteStringView bsPattern) {
349 if (L"datetime" == wsPattern.First(8))
351 if (L"date" == wsPattern.First(4)) {
352 auto pos = wsPattern.Find(L"time");
353 if (pos.has_value() && pos.value() != 0)
357 if (L"time" == wsPattern.First(4))
359 if (L"text" == wsPattern.First(4))
361 if (L"num" == wsPattern.First(3)) {
362 if (L"integer" == wsPattern.Substr(4, 7))
364 if (L"decimal" == wsPattern.Substr(4, 7))
366 if (L"currency" == wsPattern.Substr(4, 8))
368 if (L"percent" == wsPattern.Substr(4, 7))
375 const wchar_t* pData = wsPattern
.c_str();
376 int32_t iLength = wsPattern.GetLength();
378 bool bSingleQuotation =
false;
379 while (iIndex < iLength) {
380 wchar_t wsPatternChar = pData[iIndex];
381 if (wsPatternChar == 0x27) {
382 bSingleQuotation = !bSingleQuotation;
386 if (bSingleQuotation) {
391 if (wsPatternChar ==
'h' || wsPatternChar ==
'k')
393 if (wsPatternChar ==
'x' || wsPatternChar ==
'o' || wsPatternChar ==
'0')
395 if (wsPatternChar ==
'v' || wsPatternChar ==
'8' || wsPatternChar ==
'$')
397 if (wsPatternChar ==
'y' || wsPatternChar ==
'j') {
399 wchar_t timePatternChar;
400 while (iIndex < iLength) {
401 timePatternChar = pData[iIndex];
402 if (timePatternChar == 0x27) {
403 bSingleQuotation = !bSingleQuotation;
407 if (!bSingleQuotation && timePatternChar ==
't')
414 if (wsPatternChar ==
'a') {
416 }
else if (wsPatternChar ==
'z' || wsPatternChar ==
's' ||
417 wsPatternChar ==
'e' || wsPatternChar ==
',' ||
418 wsPatternChar ==
'.') {
423 return {
false, type};
431 CXFA_LocaleMgr* pMgr,
432 ByteStringView bsLocale) {
433 if (!bsLocale.IsEmpty())
440WideString FormatFromString(
LocaleIface* pLocale, ByteStringView bsFormat) {
441 if (!bsFormat.IsEmpty())
462ByteString GetLocalDateTimeFormat(CXFA_Document* pDoc,
464 ByteStringView bsLocale,
468 LocaleIface* pLocale = LocaleFromString(pDoc, pMgr, bsLocale);
480bool IsWhitespace(
char c) {
481 return c == 0x20 || c == 0x09 || c == 0x0B || c == 0x0C || c == 0x0A ||
485bool IsPartOfNumber(
char ch) {
486 return isdigit(ch) || ch ==
'-' || ch ==
'.';
489bool IsPartOfNumberW(
wchar_t ch) {
493ByteString GUIDString(
bool bSeparator) {
496 data[6] = (data[6] & 0x0F) | 0x40;
501 pdfium::span<
char> pBuf = bsGUID.GetBuffer(40);
502 size_t out_index = 0;
503 for (size_t i = 0; i < 16; ++i, out_index += 2) {
504 if (bSeparator && (i == 4 || i == 6 || i == 8 || i == 10))
505 pBuf[out_index++] = L'-';
507 FXSYS_IntToTwoHexChars(data[i], &pBuf[out_index]);
510 bsGUID.ReleaseBuffer(bSeparator ? 36 : 32);
514void GetLocalTimeZone(int32_t* pHour, int32_t* pMin, int32_t* pSec) {
518 struct tm* pGmt = gmtime(&now);
520 *pHour = pLocal->tm_hour - pGmt->tm_hour;
521 *pMin = pLocal->tm_min - pGmt->tm_min;
522 *pSec = pLocal->tm_sec - pGmt->tm_sec;
525bool HTMLSTR2Code(
const WideString& pData, uint32_t* iCode) {
526 auto cmpFunc = [](
const XFA_FMHtmlReserveCode& iter, ByteStringView val) {
527 return strcmp(val.unterminated_c_str(), iter.m_htmlReserve) > 0;
532 const XFA_FMHtmlReserveCode* result =
std::lower_bound(
533 std::begin(kReservesForDecode),
std::end(kReservesForDecode),
534 temp.AsStringView(), cmpFunc);
535 if (result !=
std::end(kReservesForDecode) &&
536 !strcmp(temp
.c_str(), result->m_htmlReserve)) {
537 *iCode = result->m_uCode;
543bool HTMLCode2STR(uint32_t iCode, WideString* wsHTMLReserve) {
544 auto cmpFunc = [](
const XFA_FMHtmlReserveCode iter,
const uint32_t& val) {
545 return iter.m_uCode < val;
547 const XFA_FMHtmlReserveCode* result =
548 std::lower_bound(
std::begin(kReservesForEncode),
549 std::end(kReservesForEncode), iCode, cmpFunc);
550 if (result !=
std::end(kReservesForEncode) && result->m_uCode == iCode) {
551 *wsHTMLReserve = WideString
::FromASCII(result->m_htmlReserve);
557WideString DecodeURL(
const WideString& wsURL) {
558 const wchar_t* pData = wsURL
.c_str();
559 size_t iLen = wsURL.GetLength();
560 WideTextBuffer wsResultBuf;
561 for (size_t i = 0; i < iLen; ++i) {
562 wchar_t ch = pData[i];
585WideString DecodeMLInternal(
const WideString& wsHTML,
bool bIsHTML) {
586 const wchar_t* pData = wsHTML
.c_str();
587 size_t iLen = wsHTML.GetLength();
588 WideTextBuffer wsResultBuf;
589 for (size_t i = 0; i < iLen; ++i) {
590 wchar_t ch = pData[i];
603 if (ch !=
'x' && ch !=
'X')
609 while (ch !=
';' && i < iLen) {
623 size_t iStrIndex = 0;
624 while (ch !=
';' && i < iLen) {
626 szBuffer[iStrIndex++] = ch;
631 szBuffer[iStrIndex] = 0;
634 if (HTMLSTR2Code(szBuffer, &iData))
637 if (wcscmp(szBuffer, L"quot") == 0)
639 else if (wcscmp(szBuffer, L"amp") == 0)
641 else if (wcscmp(szBuffer, L"apos") == 0)
643 else if (wcscmp(szBuffer, L"lt") == 0)
645 else if (wcscmp(szBuffer, L"gt") == 0)
652WideString DecodeHTML(
const WideString& wsHTML) {
653 return DecodeMLInternal(wsHTML,
true);
656WideString DecodeXML(
const WideString& wsXML) {
657 return DecodeMLInternal(wsXML,
false);
660WideString EncodeURL(
const ByteString& bsURL) {
661 static constexpr char32_t kStrUnsafe[] = {
' ',
'<',
'>',
'"',
'#',
662 '%',
'{',
'}',
'|',
'\\',
663 '^',
'~',
'[',
']',
'`'};
664 static constexpr char32_t kStrReserved[] = {
';',
'/',
'?',
':',
666 static constexpr char32_t kStrSpecial[] = {
'$',
'-',
'+',
'!',
'*',
667 '\'',
'(',
')',
','};
669 WideString wsURL = WideString
::FromUTF8(bsURL.AsStringView()
);
670 WideTextBuffer wsResultBuf;
671 wchar_t encode_buffer[3];
672 encode_buffer[0] =
'%';
673 for (
char32_t ch : pdfium::CodePointView(wsURL.AsStringView())) {
675 size_t iCount = std::size(kStrUnsafe);
677 if (ch == kStrUnsafe[i]) {
678 int32_t iIndex = ch / 16;
679 encode_buffer[1] = kStrCode[iIndex];
680 encode_buffer[2] = kStrCode[ch - iIndex * 16];
681 wsResultBuf << WideStringView(encode_buffer, 3);
690 iCount = std::size(kStrReserved);
692 if (ch == kStrReserved[i]) {
693 int32_t iIndex = ch / 16;
694 encode_buffer[1] = kStrCode[iIndex];
695 encode_buffer[2] = kStrCode[ch - iIndex * 16];
696 wsResultBuf << WideStringView(encode_buffer, 3);
705 iCount = std::size(kStrSpecial);
707 if (ch == kStrSpecial[i]) {
708 wsResultBuf.AppendChar(ch);
716 if ((ch >= 0x80 && ch <= 0xff) || ch <= 0x1f || ch == 0x7f) {
717 int32_t iIndex = ch / 16;
718 encode_buffer[1] = kStrCode[iIndex];
719 encode_buffer[2] = kStrCode[ch - iIndex * 16];
720 wsResultBuf << WideStringView(encode_buffer, 3);
721 }
else if (ch >= 0x20 && ch <= 0x7e) {
722 wsResultBuf.AppendChar(ch);
724 const wchar_t iRadix = 16;
726 while (ch >= iRadix) {
727 wchar_t tmp = kStrCode[ch % iRadix];
731 wsBuffer += kStrCode[ch];
732 int32_t iLen = wsBuffer.GetLength();
738 encode_buffer[1] =
'0';
739 encode_buffer[2] = wsBuffer[iLen - 1];
742 encode_buffer[1] = wsBuffer[iLen - 1];
743 encode_buffer[2] = wsBuffer[iLen - 2];
746 wsResultBuf << WideStringView(encode_buffer, 3);
748 encode_buffer[1] = wsBuffer[iIndex];
749 encode_buffer[2] = wsBuffer[iIndex - 1];
751 wsResultBuf << WideStringView(encode_buffer, 3);
758WideString EncodeHTML(
const ByteString& bsHTML) {
759 WideString wsHTML = WideString
::FromUTF8(bsHTML.AsStringView()
);
760 wchar_t encode_buffer[8];
761 encode_buffer[0] =
'&';
762 encode_buffer[1] =
'#';
763 encode_buffer[2] =
'x';
764 WideTextBuffer wsResultBuf;
765 for (
char32_t ch : pdfium::CodePointView(wsHTML.AsStringView())) {
766 WideString htmlReserve;
767 if (HTMLCode2STR(ch, &htmlReserve)) {
768 wsResultBuf.AppendChar(L'&');
769 wsResultBuf << htmlReserve;
770 wsResultBuf.AppendChar(L';');
771 }
else if (ch >= 32 && ch <= 126) {
772 wsResultBuf.AppendChar(
static_cast<
wchar_t>(ch));
773 }
else if (ch < 256) {
774 int32_t iIndex = ch / 16;
775 encode_buffer[3] = kStrCode[iIndex];
776 encode_buffer[4] = kStrCode[ch - iIndex * 16];
777 encode_buffer[5] =
';';
778 wsResultBuf << WideStringView(encode_buffer, 6);
779 }
else if (ch < 65536) {
780 int32_t iBigByte = ch / 256;
781 int32_t iLittleByte = ch % 256;
782 encode_buffer[3] = kStrCode[iBigByte / 16];
783 encode_buffer[4] = kStrCode[iBigByte % 16];
784 encode_buffer[5] = kStrCode[iLittleByte / 16];
785 encode_buffer[6] = kStrCode[iLittleByte % 16];
786 encode_buffer[7] =
';';
787 wsResultBuf << WideStringView(encode_buffer, 8);
795WideString EncodeXML(
const ByteString& bsXML) {
796 WideString wsXML = WideString
::FromUTF8(bsXML.AsStringView()
);
797 WideTextBuffer wsResultBuf;
798 wchar_t encode_buffer[8];
799 encode_buffer[0] =
'&';
800 encode_buffer[1] =
'#';
801 encode_buffer[2] =
'x';
802 for (
char32_t ch : pdfium::CodePointView(wsXML.AsStringView())) {
805 wsResultBuf.AppendChar(
'&');
806 wsResultBuf << WideStringView(L"quot");
807 wsResultBuf.AppendChar(
';');
810 wsResultBuf.AppendChar(
'&');
811 wsResultBuf << WideStringView(L"amp");
812 wsResultBuf.AppendChar(
';');
815 wsResultBuf.AppendChar(
'&');
816 wsResultBuf << WideStringView(L"apos");
817 wsResultBuf.AppendChar(
';');
820 wsResultBuf.AppendChar(
'&');
821 wsResultBuf << WideStringView(L"lt");
822 wsResultBuf.AppendChar(
';');
825 wsResultBuf.AppendChar(
'&');
826 wsResultBuf << WideStringView(L"gt");
827 wsResultBuf.AppendChar(
';');
830 if (ch >= 32 && ch <= 126) {
831 wsResultBuf.AppendChar(
static_cast<
wchar_t>(ch));
832 }
else if (ch < 256) {
833 int32_t iIndex = ch / 16;
834 encode_buffer[3] = kStrCode[iIndex];
835 encode_buffer[4] = kStrCode[ch - iIndex * 16];
836 encode_buffer[5] =
';';
837 wsResultBuf << WideStringView(encode_buffer, 6);
838 }
else if (ch < 65536) {
839 int32_t iBigByte = ch / 256;
840 int32_t iLittleByte = ch % 256;
841 encode_buffer[3] = kStrCode[iBigByte / 16];
842 encode_buffer[4] = kStrCode[iBigByte % 16];
843 encode_buffer[5] = kStrCode[iLittleByte / 16];
844 encode_buffer[6] = kStrCode[iLittleByte % 16];
845 encode_buffer[7] =
';';
846 wsResultBuf << WideStringView(encode_buffer, 8);
857ByteString TrillionUS(ByteStringView bsData) {
858 static const char kUnits[][6] = {
"zero",
"one",
"two",
"three",
"four",
859 "five",
"six",
"seven",
"eight",
"nine"};
860 static const char kCapUnits[][6] = {
"Zero",
"One",
"Two",
"Three",
"Four",
861 "Five",
"Six",
"Seven",
"Eight",
"Nine"};
862 static const char kTens[][10] = {
863 "Ten",
"Eleven",
"Twelve",
"Thirteen",
"Fourteen",
864 "Fifteen",
"Sixteen",
"Seventeen",
"Eighteen",
"Nineteen"};
865 static const char kLastTens[][8] = {
"Twenty",
"Thirty",
"Forty",
"Fifty",
866 "Sixty",
"Seventy",
"Eighty",
"Ninety"};
867 static const char kComm[][11] = {
" Hundred ",
" Thousand ",
" Million ",
868 " Billion ",
"Trillion"};
869 const char* pData = bsData.unterminated_c_str();
870 int32_t iLength = bsData.GetLength();
874 else if (iLength > 9)
876 else if (iLength > 6)
878 else if (iLength > 3)
881 int32_t iFirstCount = iLength % 3;
882 if (iFirstCount == 0)
887 if (iFirstCount == 3) {
888 if (pData[iIndex] !=
'0') {
889 strBuf
+= kCapUnits[pData[iIndex] -
'0'];
892 if (pData[iIndex + 1] ==
'0') {
893 strBuf
+= kCapUnits[pData[iIndex + 2] -
'0'];
895 if (pData[iIndex + 1] >
'1') {
896 strBuf
+= kLastTens[pData[iIndex + 1] -
'2'];
898 strBuf
+= kUnits[pData[iIndex + 2] -
'0'];
899 }
else if (pData[iIndex + 1] ==
'1') {
900 strBuf
+= kTens[pData[iIndex + 2] -
'0'];
901 }
else if (pData[iIndex + 1] ==
'0') {
902 strBuf
+= kCapUnits[pData[iIndex + 2] -
'0'];
906 }
else if (iFirstCount == 2) {
907 if (pData[iIndex] ==
'0') {
908 strBuf
+= kCapUnits[pData[iIndex + 1] -
'0'];
910 if (pData[iIndex] >
'1') {
911 strBuf
+= kLastTens[pData[iIndex] -
'2'];
913 strBuf
+= kUnits[pData[iIndex + 1] -
'0'];
914 }
else if (pData[iIndex] ==
'1') {
915 strBuf
+= kTens[pData[iIndex + 1] -
'0'];
916 }
else if (pData[iIndex] ==
'0') {
917 strBuf
+= kCapUnits[pData[iIndex + 1] -
'0'];
921 }
else if (iFirstCount == 1) {
922 strBuf
+= kCapUnits[pData[iIndex] -
'0'];
925 if (iLength > 3 && iFirstCount > 0) {
926 strBuf
+= kComm[iComm];
929 while (iIndex < iLength) {
930 if (pData[iIndex] !=
'0') {
931 strBuf
+= kCapUnits[pData[iIndex] -
'0'];
934 if (pData[iIndex + 1] ==
'0') {
935 strBuf
+= kCapUnits[pData[iIndex + 2] -
'0'];
937 if (pData[iIndex + 1] >
'1') {
938 strBuf
+= kLastTens[pData[iIndex + 1] -
'2'];
940 strBuf
+= kUnits[pData[iIndex + 2] -
'0'];
941 }
else if (pData[iIndex + 1] ==
'1') {
942 strBuf
+= kTens[pData[iIndex + 2] -
'0'];
943 }
else if (pData[iIndex + 1] ==
'0') {
944 strBuf
+= kCapUnits[pData[iIndex + 2] -
'0'];
947 if (iIndex < iLength - 3) {
948 strBuf
+= kComm[iComm];
956ByteString WordUS(ByteStringView bsData, int32_t iStyle) {
957 if (iStyle < 0 || iStyle > 2)
960 int32_t iLength = bsData.GetLength();
963 while (iIndex < iLength) {
964 if (bsData[iIndex] ==
'.')
968 int32_t iInteger = iIndex;
970 while (iIndex < iInteger) {
971 int32_t iCount = (iInteger - iIndex) % 12;
972 if (!iCount && iInteger - iIndex > 0)
975 strBuf += TrillionUS(bsData.Substr(iIndex, iCount));
977 if (iIndex < iInteger)
978 strBuf
+= " Trillion ";
982 strBuf
+= " Dollars";
984 if (iStyle > 1 && iInteger < iLength) {
986 iIndex = iInteger + 1;
987 while (iIndex < iLength) {
988 int32_t iCount = (iLength - iIndex) % 12;
989 if (!iCount && iLength - iIndex > 0)
992 strBuf += TrillionUS(bsData.Substr(iIndex, iCount));
994 if (iIndex < iLength)
995 strBuf
+= " Trillion ";
1002v8::Local<v8::Value> GetObjectDefaultValue(
v8::Isolate* pIsolate,
1003 v8::Local<v8::Object> pObject) {
1006 return fxv8::NewNullHelper(pIsolate);
1008 v8::Local<v8::Value> value;
1009 pNode->JSObject()->ScriptSomDefaultValue(pIsolate, &value,
false,
1010 XFA_Attribute::Unknown);
1014bool SetObjectDefaultValue(
v8::Isolate* pIsolate,
1015 v8::Local<v8::Object> pObject,
1016 v8::Local<v8::Value> hNewValue) {
1021 pNode->JSObject()->ScriptSomDefaultValue(pIsolate, &hNewValue,
true,
1026v8::Local<v8::Value> GetExtractedValue(
v8::Isolate* pIsolate,
1027 v8::Local<v8::Value> pValue) {
1028 if (pValue.IsEmpty())
1029 return v8::Local<v8::Value>();
1032 v8::Local<v8::Array> arr = pValue.As<v8::Array>();
1033 uint32_t iLength = fxv8::GetArrayLengthHelper(arr);
1035 return fxv8::NewUndefinedHelper(pIsolate);
1037 v8::Local<v8::Value> propertyValue =
1038 fxv8::ReentrantGetArrayElementHelper(pIsolate, arr, 1);
1039 v8::Local<v8::Value> jsValue =
1040 fxv8::ReentrantGetArrayElementHelper(pIsolate, arr, 2);
1041 if (!fxv8::IsObject(jsValue))
1042 return fxv8::NewUndefinedHelper(pIsolate);
1044 v8::Local<v8::Object> jsObjectValue = jsValue.As<v8::Object>();
1045 if (fxv8::IsNull(propertyValue))
1046 return GetObjectDefaultValue(pIsolate, jsObjectValue);
1049 fxv8::ReentrantToByteStringHelper(pIsolate, propertyValue);
1050 return fxv8::ReentrantGetObjectPropertyHelper(pIsolate, jsObjectValue,
1051 bsName.AsStringView());
1054 if (fxv8::IsObject(pValue))
1055 return GetObjectDefaultValue(pIsolate, pValue.As<v8::Object>());
1060v8::Local<v8::Value> GetSimpleValue(
1061 const v8::FunctionCallbackInfo<v8::Value>& info,
1063 DCHECK(index <
static_cast<uint32_t>(info.Length()));
1064 return GetExtractedValue(info.GetIsolate(), info[index]);
1067bool ValueIsNull(
v8::Isolate* pIsolate, v8::Local<v8::Value> arg) {
1068 v8::Local<v8::Value> extracted = GetExtractedValue(pIsolate, arg);
1069 return extracted.IsEmpty() || fxv8::IsNull(extracted);
1072int32_t ValueToInteger(
v8::Isolate* pIsolate, v8::Local<v8::Value> arg) {
1073 v8::Local<v8::Value> extracted = GetExtractedValue(pIsolate, arg);
1074 if (extracted.IsEmpty())
1077 if (fxv8::IsObject(extracted) || fxv8::IsArray(extracted))
1078 return ValueToInteger(pIsolate, extracted);
1080 if (fxv8::IsString(extracted)) {
1081 ByteString bsValue = fxv8::ReentrantToByteStringHelper(pIsolate, extracted);
1085 return fxv8::ReentrantToInt32Helper(pIsolate, extracted);
1088float ValueToFloat(
v8::Isolate* pIsolate, v8::Local<v8::Value> arg) {
1089 v8::Local<v8::Value> extracted = GetExtractedValue(pIsolate, arg);
1090 if (extracted.IsEmpty())
1093 if (fxv8::IsUndefined(extracted))
1096 if (fxv8::IsObject(extracted) || fxv8::IsArray(extracted))
1097 return ValueToFloat(pIsolate, extracted);
1099 if (fxv8::IsString(extracted)) {
1100 ByteString bsValue = fxv8::ReentrantToByteStringHelper(pIsolate, extracted);
1101 return strtof(bsValue
.c_str(),
nullptr);
1104 return fxv8::ReentrantToFloatHelper(pIsolate, extracted);
1107double ValueToDouble(
v8::Isolate* pIsolate, v8::Local<v8::Value> arg) {
1108 v8::Local<v8::Value> extracted = GetExtractedValue(pIsolate, arg);
1109 if (extracted.IsEmpty())
1112 if (fxv8::IsUndefined(extracted))
1115 if (fxv8::IsObject(extracted) || fxv8::IsArray(extracted))
1116 return ValueToDouble(pIsolate, extracted);
1118 if (fxv8::IsString(extracted)) {
1119 ByteString bsValue = fxv8::ReentrantToByteStringHelper(pIsolate, extracted);
1120 return strtod(bsValue
.c_str(),
nullptr);
1123 return fxv8::ReentrantToDoubleHelper(pIsolate, extracted);
1126absl::optional<
double> ExtractDouble(
v8::Isolate* pIsolate,
1127 v8::Local<v8::Value> src) {
1131 if (!fxv8::IsArray(src))
1132 return ValueToDouble(pIsolate, src);
1134 v8::Local<v8::Array> arr = src.As<v8::Array>();
1135 uint32_t iLength = fxv8::GetArrayLengthHelper(arr);
1137 return absl::nullopt;
1139 v8::Local<v8::Value> propertyValue =
1140 fxv8::ReentrantGetArrayElementHelper(pIsolate, arr, 1);
1141 v8::Local<v8::Value> jsValue =
1142 fxv8::ReentrantGetArrayElementHelper(pIsolate, arr, 2);
1143 if (fxv8::IsNull(propertyValue) || !fxv8::IsObject(jsValue))
1144 return ValueToDouble(pIsolate, jsValue);
1147 fxv8::ReentrantToByteStringHelper(pIsolate, propertyValue);
1148 return ValueToDouble(
1149 pIsolate, fxv8::ReentrantGetObjectPropertyHelper(
1150 pIsolate, jsValue.As<v8::Object>(), bsName.AsStringView()));
1153ByteString ValueToUTF8String(
v8::Isolate* pIsolate, v8::Local<v8::Value> arg) {
1155 return ByteString
();
1158 return ByteString
();
1166bool SimpleValueCompare(
v8::Isolate* pIsolate,
1167 v8::Local<v8::Value> firstValue,
1168 v8::Local<v8::Value> secondValue) {
1169 if (firstValue.IsEmpty())
1173 const ByteString first = ValueToUTF8String(pIsolate, firstValue);
1174 const ByteString second = ValueToUTF8String(pIsolate, secondValue);
1175 return first
== second;
1178 const float first = ValueToFloat(pIsolate, firstValue);
1179 const float second = ValueToFloat(pIsolate, secondValue);
1180 return first == second;
1185 return first == second;
1190v8::LocalVector<v8::Value> UnfoldArgs(
1191 const v8::FunctionCallbackInfo<v8::Value>& info) {
1192 v8::LocalVector<v8::Value> results(info.GetIsolate());
1193 v8::Isolate* pIsolate = info.GetIsolate();
1194 for (
int i = 1; i < info.Length(); ++i) {
1195 v8::Local<v8::Value> arg = info[i];
1196 if (fxv8::IsArray(arg)) {
1197 v8::Local<v8::Array> arr = arg.As<v8::Array>();
1198 uint32_t iLength = fxv8::GetArrayLengthHelper(arr);
1202 v8::Local<v8::Value> propertyValue =
1203 fxv8::ReentrantGetArrayElementHelper(pIsolate, arr, 1);
1205 for (uint32_t j = 2; j < iLength; j++) {
1206 v8::Local<v8::Value> jsValue =
1207 fxv8::ReentrantGetArrayElementHelper(pIsolate, arr, j);
1209 if (!fxv8::IsObject(jsValue)) {
1210 results.push_back(fxv8::NewUndefinedHelper(pIsolate));
1211 }
else if (fxv8::IsNull(propertyValue)) {
1213 GetObjectDefaultValue(pIsolate, jsValue.As<v8::Object>()));
1216 fxv8::ReentrantToByteStringHelper(pIsolate, propertyValue);
1217 results.push_back(fxv8::ReentrantGetObjectPropertyHelper(
1218 pIsolate, jsValue.As<v8::Object>(), bsName.AsStringView()));
1221 }
else if (fxv8::IsObject(arg)) {
1222 results.push_back(GetObjectDefaultValue(pIsolate, arg.As<v8::Object>()));
1224 results.push_back(arg);
1232 ByteStringView bsAccessorName) {
1235 return v8::Local<v8::Value>();
1238 absl::optional<CFXJSE_Engine::ResolveResult> maybeResult =
1239 pScriptContext->ResolveObjects(
1240 pScriptContext->GetThisObject(),
1241 WideString::FromUTF8(bsAccessorName).AsStringView(),
1242 Mask<XFA_ResolveFlag>{
1243 XFA_ResolveFlag::kChildren, XFA_ResolveFlag::kProperties,
1244 XFA_ResolveFlag::kSiblings, XFA_ResolveFlag::kParent});
1245 if (!maybeResult.has_value() ||
1246 maybeResult.value().type != CFXJSE_Engine::ResolveResult::Type::kNodes ||
1247 maybeResult.value().objects.empty()) {
1248 return v8::Local<v8::Value>();
1250 return pScriptContext->GetOrCreateJSBindingFromMap(
1251 maybeResult.value().objects.front().Get());
1254absl::optional<CFXJSE_Engine::ResolveResult> ResolveObjects(
1256 v8::Local<v8::Value> pRefValue,
1257 ByteStringView bsSomExp,
1259 bool bHasNoResolveName) {
1262 return absl::nullopt;
1264 v8::Isolate* pIsolate = ToFormCalcContext(pHostObject)->GetIsolate();
1265 WideString wsSomExpression = WideString
::FromUTF8(bsSomExp
);
1276 return absl::nullopt;
1278 if (bHasNoResolveName) {
1281 absl::optional<WideString> ret =
1282 pXFANode->JSObject()->TryAttribute(XFA_Attribute::Name,
false);
1283 if (ret.has_value())
1284 wsName = ret.value();
1287 wsName = L"#" + WideString
::FromASCII(pNode->GetClassName()
);
1289 wsSomExpression
= wsName
+ wsSomExpression;
1292 dwFlags = (bsSomExp ==
"*")
1303 return pScriptContext->ResolveObjects(pNode, wsSomExpression.AsStringView(),
1307v8::LocalVector<v8::Value> ParseResolveResult(
1310 v8::Local<v8::Value> pParentValue,
1312 CFXJSE_FormCalcContext* pContext = ToFormCalcContext(pHostObject);
1313 v8::Isolate* pIsolate = pContext->GetIsolate();
1314 v8::LocalVector<v8::Value> resultValues(pIsolate);
1317 *bAttribute =
false;
1319 for (
auto& pObject : resolveNodeRS.objects) {
1320 resultValues.push_back(
1321 pScriptContext->GetOrCreateJSBindingFromMap(pObject.Get()));
1323 return resultValues;
1329 for (
auto& pObject : resolveNodeRS.objects) {
1330 v8::Local<v8::Value> pValue;
1331 CJX_Object* jsObject = pObject->JSObject();
1332 (*resolveNodeRS.script_attribute.callback)(
1333 pIsolate, jsObject, &pValue,
false,
1334 resolveNodeRS.script_attribute.attribute);
1335 resultValues.push_back(pValue);
1336 *bAttribute =
false;
1339 if (*bAttribute && fxv8::IsObject(pParentValue))
1340 resultValues.push_back(pParentValue);
1342 return resultValues;
1346int GetValidatedPaymentPeriods(
v8::Isolate* isolate, v8::Local<v8::Value> arg) {
1347 double periods = ValueToDouble(isolate, arg);
1349 periods >
static_cast<
double>(
std::numeric_limits<int32_t>::max())) {
1353 return static_cast<
int>(periods);
1360 "XFA_FormCalcClass",
1362 std::size(kFormCalcFunctions),
1370void CFXJSE_FormCalcContext::Abs(
1372 const v8::FunctionCallbackInfo<v8::Value>& info) {
1373 if (info.Length() != 1) {
1374 ToFormCalcContext(pThis)->ThrowParamCountMismatchException(
"Abs");
1378 if (ValueIsNull(info.GetIsolate(), info[0])) {
1379 info.GetReturnValue().SetNull();
1382 double dValue = ValueToDouble(info.GetIsolate(), info[0]);
1386 info.GetReturnValue().Set(dValue);
1390void CFXJSE_FormCalcContext::Avg(
1392 const v8::FunctionCallbackInfo<v8::Value>& info) {
1393 uint32_t uCount = 0;
1395 auto fn = [&uCount, &dSum](
v8::Isolate* pIsolate,
1396 v8::Local<v8::Value> pValue) {
1397 dSum += ValueToDouble(pIsolate, pValue);
1400 if (!ToFormCalcContext(pThis)->ApplyToExpansion(fn, info,
false))
1404 info.GetReturnValue().SetNull();
1407 info.GetReturnValue().Set(dSum / uCount);
1411void CFXJSE_FormCalcContext::Ceil(
1413 const v8::FunctionCallbackInfo<v8::Value>& info) {
1414 if (info.Length() != 1) {
1415 ToFormCalcContext(pThis)->ThrowParamCountMismatchException(
"Ceil");
1419 v8::Local<v8::Value> argValue = GetSimpleValue(info, 0);
1420 if (ValueIsNull(info.GetIsolate(), argValue)) {
1421 info.GetReturnValue().SetNull();
1425 info.GetReturnValue().Set(ceil(ValueToFloat(info.GetIsolate(), argValue)));
1429void CFXJSE_FormCalcContext::Count(
1431 const v8::FunctionCallbackInfo<v8::Value>& info) {
1432 uint32_t iCount = 0;
1433 auto fn = [&iCount](
v8::Isolate* pIsolate, v8::Local<v8::Value> pvalue) {
1436 if (!ToFormCalcContext(pThis)->ApplyToExpansion(fn, info,
true))
1439 info.GetReturnValue().Set(iCount);
1443void CFXJSE_FormCalcContext::Floor(
1445 const v8::FunctionCallbackInfo<v8::Value>& info) {
1446 if (info.Length() != 1) {
1447 ToFormCalcContext(pThis)->ThrowParamCountMismatchException(
"Floor");
1451 v8::Local<v8::Value> argValue = GetSimpleValue(info, 0);
1452 if (ValueIsNull(info.GetIsolate(), argValue)) {
1453 info.GetReturnValue().SetNull();
1457 info.GetReturnValue().Set(floor(ValueToFloat(info.GetIsolate(), argValue)));
1461void CFXJSE_FormCalcContext::Max(
1463 const v8::FunctionCallbackInfo<v8::Value>& info) {
1464 uint32_t uCount = 0;
1465 double dMaxValue = 0.0;
1466 auto fn = [&uCount, &dMaxValue](
v8::Isolate* pIsolate,
1467 v8::Local<v8::Value> pValue) {
1469 double dValue = ValueToDouble(pIsolate, pValue);
1470 dMaxValue = uCount == 1 ? dValue :
std::max(dMaxValue, dValue);
1472 if (!ToFormCalcContext(pThis)->ApplyToExpansion(fn, info,
true))
1476 info.GetReturnValue().SetNull();
1479 info.GetReturnValue().Set(dMaxValue);
1483void CFXJSE_FormCalcContext::Min(
1485 const v8::FunctionCallbackInfo<v8::Value>& info) {
1486 uint32_t uCount = 0;
1487 double dMinValue = 0.0;
1488 auto fn = [&uCount, &dMinValue](
v8::Isolate* pIsolate,
1489 v8::Local<v8::Value> pValue) {
1491 double dValue = ValueToDouble(pIsolate, pValue);
1492 dMinValue = uCount == 1 ? dValue :
std::min(dMinValue, dValue);
1494 if (!ToFormCalcContext(pThis)->ApplyToExpansion(fn, info,
true))
1498 info.GetReturnValue().SetNull();
1501 info.GetReturnValue().Set(dMinValue);
1505void CFXJSE_FormCalcContext::Mod(
1507 const v8::FunctionCallbackInfo<v8::Value>& info) {
1508 CFXJSE_FormCalcContext* pContext = ToFormCalcContext(pThis);
1509 if (info.Length() != 2) {
1510 pContext->ThrowParamCountMismatchException(
"Mod");
1515 info.GetReturnValue().SetNull();
1519 absl::optional<
double> maybe_dividend =
1520 ExtractDouble(info.GetIsolate(), info[0]);
1521 absl::optional<
double> maybe_divisor =
1522 ExtractDouble(info.GetIsolate(), info[1]);
1523 if (!maybe_dividend.has_value() || !maybe_divisor.has_value()) {
1524 pContext->ThrowArgumentMismatchException();
1528 double dividend = maybe_dividend.value();
1529 double divisor = maybe_divisor.value();
1530 if (divisor == 0.0) {
1531 pContext->ThrowDivideByZeroException();
1535 info.GetReturnValue().Set(dividend -
1536 divisor *
static_cast<int32_t>(dividend / divisor));
1540void CFXJSE_FormCalcContext::Round(
1542 const v8::FunctionCallbackInfo<v8::Value>& info) {
1543 CFXJSE_FormCalcContext* pContext = ToFormCalcContext(pThis);
1544 int32_t argc = info.Length();
1545 if (argc < 1 || argc > 2) {
1546 pContext->ThrowParamCountMismatchException(
"Round");
1551 info.GetReturnValue().SetNull();
1555 absl::optional<
double> maybe_value =
1556 ExtractDouble(info.GetIsolate(), info[0]);
1557 if (!maybe_value.has_value()) {
1558 pContext->ThrowArgumentMismatchException();
1562 double dValue = maybe_value.value();
1563 uint8_t uPrecision = 0;
1566 info.GetReturnValue().SetNull();
1569 absl::optional<
double> maybe_precision =
1570 ExtractDouble(info.GetIsolate(), info[1]);
1571 if (!maybe_precision.has_value()) {
1572 pContext->ThrowArgumentMismatchException();
1575 double dPrecision = maybe_precision.value();
1576 uPrecision =
static_cast<uint8_t>(
std::clamp(dPrecision, 0.0, 12.0));
1580 info.GetReturnValue().Set(decimalValue
.ToDouble());
1584void CFXJSE_FormCalcContext::Sum(
1586 const v8::FunctionCallbackInfo<v8::Value>& info) {
1587 uint32_t uCount = 0;
1589 auto fn = [&uCount, &dSum](
v8::Isolate* pIsolate,
1590 v8::Local<v8::Value> pValue) {
1592 dSum += ValueToDouble(pIsolate, pValue);
1594 if (!ToFormCalcContext(pThis)->ApplyToExpansion(fn, info,
true))
1598 info.GetReturnValue().SetNull();
1601 info.GetReturnValue().Set(dSum);
1605void CFXJSE_FormCalcContext::Date(
1607 const v8::FunctionCallbackInfo<v8::Value>& info) {
1608 if (info.Length() != 0) {
1609 ToFormCalcContext(pThis)->ThrowParamCountMismatchException(
"Date");
1615 struct tm* pTmStruct = gmtime(¤tTime);
1617 info.GetReturnValue().Set(DateString2Num(
1618 ByteString
::Format("%d%02d%02d", pTmStruct->tm_year + 1900
,
1619 pTmStruct->tm_mon + 1
, pTmStruct->tm_mday
)
1624void CFXJSE_FormCalcContext::Date2Num(
1626 const v8::FunctionCallbackInfo<v8::Value>& info) {
1627 int32_t argc = info.Length();
1628 if (argc < 1 || argc > 3) {
1629 ToFormCalcContext(pThis)->ThrowParamCountMismatchException(
"Date2Num");
1633 v8::Local<v8::Value> dateValue = GetSimpleValue(info, 0);
1634 if (ValueIsNull(info.GetIsolate(), dateValue)) {
1635 info.GetReturnValue().SetNull();
1639 ByteString bsDate = ValueToUTF8String(info.GetIsolate(), dateValue);
1640 ByteString bsFormat;
1642 v8::Local<v8::Value> formatValue = GetSimpleValue(info, 1);
1643 if (ValueIsNull(info.GetIsolate(), formatValue)) {
1644 info.GetReturnValue().SetNull();
1647 bsFormat = ValueToUTF8String(info.GetIsolate(), formatValue);
1650 ByteString bsLocale;
1652 v8::Local<v8::Value> localeValue = GetSimpleValue(info, 2);
1653 if (ValueIsNull(info.GetIsolate(), localeValue)) {
1654 info.GetReturnValue().SetNull();
1657 bsLocale = ValueToUTF8String(info.GetIsolate(), localeValue);
1660 ByteString bsIsoDate =
1662 bsLocale.AsStringView()
);
1663 info.GetReturnValue().Set(DateString2Num(bsIsoDate.AsStringView()));
1667void CFXJSE_FormCalcContext::DateFmt(
1669 const v8::FunctionCallbackInfo<v8::Value>& info) {
1670 int32_t argc = info.Length();
1672 ToFormCalcContext(pThis)->ThrowParamCountMismatchException(
"Date2Num");
1678 v8::Local<v8::Value> infotyle = GetSimpleValue(info, 0);
1679 if (fxv8::IsNull(infotyle)) {
1680 info.GetReturnValue().SetNull();
1684 iStyle =
static_cast<int32_t>(ValueToFloat(info.GetIsolate(), infotyle));
1685 if (iStyle < 0 || iStyle > 4)
1689 ByteString bsLocale;
1691 v8::Local<v8::Value> argLocale = GetSimpleValue(info, 1);
1692 if (fxv8::IsNull(argLocale)) {
1693 info.GetReturnValue().SetNull();
1696 bsLocale = ValueToUTF8String(info.GetIsolate(), argLocale);
1699 ByteString bsFormat =
1701 info.GetReturnValue().Set(
1702 fxv8::NewStringHelper(info.GetIsolate(), bsFormat.AsStringView()));
1706void CFXJSE_FormCalcContext::IsoDate2Num(
1708 const v8::FunctionCallbackInfo<v8::Value>& info) {
1709 if (info.Length() != 1) {
1710 ToFormCalcContext(pThis)->ThrowParamCountMismatchException(
"IsoDate2Num");
1713 v8::Local<v8::Value> argOne = GetSimpleValue(info, 0);
1714 if (fxv8::IsNull(argOne)) {
1715 info.GetReturnValue().SetNull();
1718 ByteString bsArg = ValueToUTF8String(info.GetIsolate(), argOne);
1719 info.GetReturnValue().Set(DateString2Num(bsArg.AsStringView()));
1723void CFXJSE_FormCalcContext::IsoTime2Num(
1725 const v8::FunctionCallbackInfo<v8::Value>& info) {
1726 CFXJSE_FormCalcContext* pContext = ToFormCalcContext(pThis);
1727 if (info.Length() != 1) {
1728 pContext->ThrowParamCountMismatchException(
"IsoTime2Num");
1732 v8::Local<v8::Value> argOne = GetSimpleValue(info, 0);
1733 if (ValueIsNull(info.GetIsolate(), argOne)) {
1734 info.GetReturnValue().SetNull();
1740 ByteString bsArg = ValueToUTF8String(info.GetIsolate(), argOne);
1741 auto pos = bsArg.Find(
'T', 0);
1742 if (!pos.has_value() || pos.value() == bsArg.GetLength() - 1) {
1743 info.GetReturnValue().Set(0);
1746 bsArg = bsArg.Last(bsArg.GetLength() - (pos.value() + 1));
1751 info.GetReturnValue().Set(0);
1763 int32_t mins = hour * 60 + min;
1772 info.GetReturnValue().Set(hour * 3600000 + min * 60000 + second * 1000 +
1777void CFXJSE_FormCalcContext::LocalDateFmt(
1779 const v8::FunctionCallbackInfo<v8::Value>& info) {
1780 int32_t argc = info.Length();
1782 ToFormCalcContext(pThis)->ThrowParamCountMismatchException(
"LocalDateFmt");
1788 v8::Local<v8::Value> infotyle = GetSimpleValue(info, 0);
1789 if (fxv8::IsNull(infotyle)) {
1790 info.GetReturnValue().SetNull();
1793 iStyle =
static_cast<int32_t>(ValueToFloat(info.GetIsolate(), infotyle));
1794 if (iStyle > 4 || iStyle < 0)
1798 ByteString bsLocale;
1800 v8::Local<v8::Value> argLocale = GetSimpleValue(info, 1);
1801 if (fxv8::IsNull(argLocale)) {
1802 info.GetReturnValue().SetNull();
1805 bsLocale = ValueToUTF8String(info.GetIsolate(), argLocale);
1808 ByteString bsFormat =
1810 info.GetReturnValue().Set(
1811 fxv8::NewStringHelper(info.GetIsolate(), bsFormat.AsStringView()));
1815void CFXJSE_FormCalcContext::LocalTimeFmt(
1817 const v8::FunctionCallbackInfo<v8::Value>& info) {
1818 int32_t argc = info.Length();
1820 ToFormCalcContext(pThis)->ThrowParamCountMismatchException(
"LocalTimeFmt");
1826 v8::Local<v8::Value> infotyle = GetSimpleValue(info, 0);
1827 if (fxv8::IsNull(infotyle)) {
1828 info.GetReturnValue().SetNull();
1831 iStyle =
static_cast<int32_t>(ValueToFloat(info.GetIsolate(), infotyle));
1832 if (iStyle > 4 || iStyle < 0)
1836 ByteString bsLocale;
1838 v8::Local<v8::Value> argLocale = GetSimpleValue(info, 1);
1839 if (fxv8::IsNull(argLocale)) {
1840 info.GetReturnValue().SetNull();
1843 bsLocale = ValueToUTF8String(info.GetIsolate(), argLocale);
1846 ByteString bsFormat =
1848 info.GetReturnValue().Set(
1849 fxv8::NewStringHelper(info.GetIsolate(), bsFormat.AsStringView()));
1853void CFXJSE_FormCalcContext::Num2Date(
1855 const v8::FunctionCallbackInfo<v8::Value>& info) {
1856 int32_t argc = info.Length();
1857 if (argc < 1 || argc > 3) {
1858 ToFormCalcContext(pThis)->ThrowParamCountMismatchException(
"Num2Date");
1862 v8::Local<v8::Value> dateValue = GetSimpleValue(info, 0);
1863 if (ValueIsNull(info.GetIsolate(), dateValue)) {
1864 info.GetReturnValue().SetNull();
1868 static_cast<int32_t>(ValueToFloat(info.GetIsolate(), dateValue));
1870 info.GetReturnValue().SetNull();
1874 ByteString bsFormat;
1876 v8::Local<v8::Value> formatValue = GetSimpleValue(info, 1);
1877 if (ValueIsNull(info.GetIsolate(), formatValue)) {
1878 info.GetReturnValue().SetNull();
1881 bsFormat = ValueToUTF8String(info.GetIsolate(), formatValue);
1884 ByteString bsLocale;
1886 v8::Local<v8::Value> localeValue = GetSimpleValue(info, 2);
1887 if (ValueIsNull(info.GetIsolate(), localeValue)) {
1888 info.GetReturnValue().SetNull();
1891 bsLocale = ValueToUTF8String(info.GetIsolate(), localeValue);
1894 int32_t iYear = 1900;
1900 if ((!((iYear + i) % 4) && ((iYear + i) % 100)) || !((iYear + i) % 400)) {
1910 iDay +=
static_cast<int32_t>(dDate) - 1;
1923 iDay +=
static_cast<int32_t>(dDate) - 1;
1927 }
else if (iMonth < 8) {
1928 if ((iMonth % 2 == 0)) {
1938 iDay +=
static_cast<int32_t>(dDate) - 1;
1951 iDay +=
static_cast<int32_t>(dDate) - 1;
1956 if (iMonth % 2 != 0) {
1966 iDay +=
static_cast<int32_t>(dDate) - 1;
1979 iDay +=
static_cast<int32_t>(dDate) - 1;
1988 ByteString
::Format("%d%02d%02d", iYear + i
, iMonth
, iDay
).AsStringView()
,
1989 bsFormat.AsStringView()
, bsLocale.AsStringView()
);
1990 info.GetReturnValue().Set(
1991 fxv8::NewStringHelper(info.GetIsolate(), bsLocalDate.AsStringView()));
1995void CFXJSE_FormCalcContext::Num2GMTime(
1997 const v8::FunctionCallbackInfo<v8::Value>& info) {
1998 int32_t argc = info.Length();
1999 if (argc < 1 || argc > 3) {
2000 ToFormCalcContext(pThis)->ThrowParamCountMismatchException(
"Num2GMTime");
2004 v8::Local<v8::Value> timeValue = GetSimpleValue(info, 0);
2005 if (fxv8::IsNull(timeValue)) {
2006 info.GetReturnValue().SetNull();
2010 static_cast<int32_t>(ValueToFloat(info.GetIsolate(), timeValue));
2011 if (abs(iTime) < 1.0) {
2012 info.GetReturnValue().SetNull();
2016 ByteString bsFormat;
2018 v8::Local<v8::Value> formatValue = GetSimpleValue(info, 1);
2019 if (fxv8::IsNull(formatValue)) {
2020 info.GetReturnValue().SetNull();
2023 bsFormat = ValueToUTF8String(info.GetIsolate(), formatValue);
2026 ByteString bsLocale;
2028 v8::Local<v8::Value> localeValue = GetSimpleValue(info, 2);
2029 if (fxv8::IsNull(localeValue)) {
2030 info.GetReturnValue().SetNull();
2033 bsLocale = ValueToUTF8String(info.GetIsolate(), localeValue);
2036 ByteString bsGMTTime =
Num2AllTime(pThis
, iTime
, bsFormat.AsStringView()
,
2037 bsLocale.AsStringView()
, true);
2038 info.GetReturnValue().Set(
2039 fxv8::NewStringHelper(info.GetIsolate(), bsGMTTime.AsStringView()));
2043void CFXJSE_FormCalcContext::Num2Time(
2045 const v8::FunctionCallbackInfo<v8::Value>& info) {
2046 int32_t argc = info.Length();
2047 if (argc < 1 || argc > 3) {
2048 ToFormCalcContext(pThis)->ThrowParamCountMismatchException(
"Num2Time");
2052 v8::Local<v8::Value> timeValue = GetSimpleValue(info, 0);
2053 if (fxv8::IsNull(timeValue)) {
2054 info.GetReturnValue().SetNull();
2057 float fTime = ValueToFloat(info.GetIsolate(), timeValue);
2058 if (fabs(fTime) < 1.0) {
2059 info.GetReturnValue().SetNull();
2063 ByteString bsFormat;
2065 v8::Local<v8::Value> formatValue = GetSimpleValue(info, 1);
2066 if (fxv8::IsNull(formatValue)) {
2067 info.GetReturnValue().SetNull();
2070 bsFormat = ValueToUTF8String(info.GetIsolate(), formatValue);
2073 ByteString bsLocale;
2075 v8::Local<v8::Value> localeValue = GetSimpleValue(info, 2);
2076 if (fxv8::IsNull(localeValue)) {
2077 info.GetReturnValue().SetNull();
2080 bsLocale = ValueToUTF8String(info.GetIsolate(), localeValue);
2083 ByteString bsLocalTime =
2084 Num2AllTime(pThis
, static_cast<int32_t>(fTime)
, bsFormat.AsStringView()
,
2085 bsLocale.AsStringView()
, false);
2086 info.GetReturnValue().Set(
2087 fxv8::NewStringHelper(info.GetIsolate(), bsLocalTime.AsStringView()));
2091void CFXJSE_FormCalcContext::Time(
2093 const v8::FunctionCallbackInfo<v8::Value>& info) {
2094 if (info.Length() != 0) {
2095 ToFormCalcContext(pThis)->ThrowParamCountMismatchException(
"Time");
2101 struct tm* pGmt = gmtime(&now);
2102 info.GetReturnValue().Set(
2103 (pGmt->tm_hour * 3600 + pGmt->tm_min * 60 + pGmt->tm_sec) * 1000);
2107void CFXJSE_FormCalcContext::Time2Num(
2109 const v8::FunctionCallbackInfo<v8::Value>& info) {
2110 int32_t argc = info.Length();
2111 if (argc < 1 || argc > 3) {
2112 ToFormCalcContext(pThis)->ThrowParamCountMismatchException(
"Time2Num");
2117 v8::Local<v8::Value> timeValue = GetSimpleValue(info, 0);
2118 if (ValueIsNull(info.GetIsolate(), timeValue)) {
2119 info.GetReturnValue().SetNull();
2122 bsTime = ValueToUTF8String(info.GetIsolate(), timeValue);
2124 ByteString bsFormat;
2126 v8::Local<v8::Value> formatValue = GetSimpleValue(info, 1);
2127 if (ValueIsNull(info.GetIsolate(), formatValue)) {
2128 info.GetReturnValue().SetNull();
2131 bsFormat = ValueToUTF8String(info.GetIsolate(), formatValue);
2134 ByteString bsLocale;
2136 v8::Local<v8::Value> localeValue = GetSimpleValue(info, 2);
2137 if (ValueIsNull(info.GetIsolate(), localeValue)) {
2138 info.GetReturnValue().SetNull();
2141 bsLocale = ValueToUTF8String(info.GetIsolate(), localeValue);
2156 WideString wsFormat;
2161 wsFormat = WideString
::FromUTF8(bsFormat.AsStringView()
);
2163 wsFormat
= L"time{"
+ wsFormat
+ L"}";
2166 wsFormat, pLocale, pMgr);
2168 info.GetReturnValue().Set(0);
2178 constexpr int kMinutesInDay = 24 * 60;
2179 int32_t minutes_with_tz =
2181 minutes_with_tz %= kMinutesInDay;
2182 if (minutes_with_tz < 0)
2183 minutes_with_tz += kMinutesInDay;
2185 hour = minutes_with_tz / 60;
2186 minute = minutes_with_tz % 60;
2187 info.GetReturnValue().Set(hour * 3600000 + minute * 60000 + second * 1000 +
2192void CFXJSE_FormCalcContext::TimeFmt(
2194 const v8::FunctionCallbackInfo<v8::Value>& info) {
2195 int32_t argc = info.Length();
2197 ToFormCalcContext(pThis)->ThrowParamCountMismatchException(
"TimeFmt");
2203 v8::Local<v8::Value> infotyle = GetSimpleValue(info, 0);
2204 if (fxv8::IsNull(infotyle)) {
2205 info.GetReturnValue().SetNull();
2208 iStyle =
static_cast<int32_t>(ValueToFloat(info.GetIsolate(), infotyle));
2209 if (iStyle > 4 || iStyle < 0)
2213 ByteString bsLocale;
2215 v8::Local<v8::Value> argLocale = GetSimpleValue(info, 1);
2216 if (fxv8::IsNull(argLocale)) {
2217 info.GetReturnValue().SetNull();
2220 bsLocale = ValueToUTF8String(info.GetIsolate(), argLocale);
2223 ByteString bsFormat =
2225 info.GetReturnValue().Set(
2226 fxv8::NewStringHelper(info.GetIsolate(), bsFormat.AsStringView()));
2231 ByteStringView bsDate,
2232 ByteStringView bsFormat,
2233 ByteStringView bsLocale) {
2236 return ByteString
();
2241 return ByteString
();
2243 WideString wsFormat = FormatFromString(pLocale, bsFormat);
2255 ByteStringView bsDate,
2256 ByteStringView bsFormat,
2257 ByteStringView bsLocale) {
2260 return ByteString
();
2265 return ByteString
();
2267 WideString wsFormat = FormatFromString(pLocale, bsFormat);
2277 ByteStringView bsTime,
2278 ByteStringView bsFormat,
2279 ByteStringView bsLocale) {
2282 return ByteString
();
2287 return ByteString
();
2289 WideString wsFormat = {
2290 L"time{", FormatFromString(pLocale, bsFormat).AsStringView(), L"}"};
2302 ByteStringView bsLocale,
2306 return ByteString
();
2308 return GetLocalDateTimeFormat(pDoc, iStyle, bsLocale, bStandard,
2315 ByteStringView bsLocale,
2319 return ByteString
();
2321 return GetLocalDateTimeFormat(pDoc, iStyle, bsLocale, bStandard,
2329 ByteStringView bsLocale) {
2337 ByteStringView bsLocale) {
2344 ByteStringView bsFormat,
2345 ByteStringView bsLocale,
2350 iHour =
static_cast<
int>(iTime) / 3600000;
2351 iMin = (
static_cast<
int>(iTime) - iHour * 3600000) / 60000;
2352 iSec = (
static_cast<
int>(iTime) - iHour * 3600000 - iMin * 60000) / 1000;
2358 GetLocalTimeZone(&iZoneHour, &iZoneMin, &iZoneSec);
2366 ByteString
::Format("%02d:%02d:%02d", iHour
, iMin
, iSec
).AsStringView()
,
2367 bsFormat
, bsLocale
);
2371void CFXJSE_FormCalcContext::Apr(
2373 const v8::FunctionCallbackInfo<v8::Value>& info) {
2374 CFXJSE_FormCalcContext* pContext = ToFormCalcContext(pThis);
2375 if (info.Length() != 3) {
2376 pContext->ThrowParamCountMismatchException(
"Apr");
2380 v8::Local<v8::Value> argOne = GetSimpleValue(info, 0);
2381 v8::Local<v8::Value> argTwo = GetSimpleValue(info, 1);
2382 v8::Local<v8::Value> argThree = GetSimpleValue(info, 2);
2383 if (ValueIsNull(info.GetIsolate(), argOne) ||
2384 ValueIsNull(info.GetIsolate(), argTwo) ||
2385 ValueIsNull(info.GetIsolate(), argThree)) {
2386 info.GetReturnValue().SetNull();
2390 double nPrincipal = ValueToDouble(info.GetIsolate(), argOne);
2391 double nPayment = ValueToDouble(info.GetIsolate(), argTwo);
2392 int nPeriods = GetValidatedPaymentPeriods(info.GetIsolate(), argThree);
2393 if (nPrincipal <= 0 || nPayment <= 0 || nPeriods == 0) {
2394 pContext->ThrowArgumentMismatchException();
2398 double r = 2 * (nPeriods * nPayment - nPrincipal) / (nPeriods * nPrincipal);
2400 for (int32_t i = 0; i < nPeriods; ++i)
2403 double nRet = r * nTemp / (nTemp - 1) - nPayment / nPrincipal;
2404 while (fabs(nRet) > kFinancialPrecision) {
2405 double nDerivative =
2406 ((nTemp + r * nPeriods * (nTemp / (1 + r))) * (nTemp - 1) -
2407 (r * nTemp * nPeriods * (nTemp / (1 + r)))) /
2408 ((nTemp - 1) * (nTemp - 1));
2409 if (nDerivative == 0) {
2410 info.GetReturnValue().SetNull();
2414 r = r - nRet / nDerivative;
2416 for (int32_t i = 0; i < nPeriods; ++i) {
2419 nRet = r * nTemp / (nTemp - 1) - nPayment / nPrincipal;
2421 info.GetReturnValue().Set(r * 12);
2425void CFXJSE_FormCalcContext::CTerm(
2427 const v8::FunctionCallbackInfo<v8::Value>& info) {
2428 CFXJSE_FormCalcContext* pContext = ToFormCalcContext(pThis);
2429 if (info.Length() != 3) {
2430 pContext->ThrowParamCountMismatchException(
"CTerm");
2434 v8::Local<v8::Value> argOne = GetSimpleValue(info, 0);
2435 v8::Local<v8::Value> argTwo = GetSimpleValue(info, 1);
2436 v8::Local<v8::Value> argThree = GetSimpleValue(info, 2);
2437 if (ValueIsNull(info.GetIsolate(), argOne) ||
2438 ValueIsNull(info.GetIsolate(), argTwo) ||
2439 ValueIsNull(info.GetIsolate(), argThree)) {
2440 info.GetReturnValue().SetNull();
2444 float nRate = ValueToFloat(info.GetIsolate(), argOne);
2445 float nFutureValue = ValueToFloat(info.GetIsolate(), argTwo);
2446 float nInitAmount = ValueToFloat(info.GetIsolate(), argThree);
2447 if ((nRate <= 0) || (nFutureValue <= 0) || (nInitAmount <= 0)) {
2448 pContext->ThrowArgumentMismatchException();
2452 info.GetReturnValue().Set(log((
float)(nFutureValue / nInitAmount)) /
2453 log((
float)(1 + nRate)));
2457void CFXJSE_FormCalcContext::FV(
2459 const v8::FunctionCallbackInfo<v8::Value>& info) {
2460 CFXJSE_FormCalcContext* pContext = ToFormCalcContext(pThis);
2461 if (info.Length() != 3) {
2462 pContext->ThrowParamCountMismatchException(
"FV");
2466 v8::Local<v8::Value> argOne = GetSimpleValue(info, 0);
2467 v8::Local<v8::Value> argTwo = GetSimpleValue(info, 1);
2468 v8::Local<v8::Value> argThree = GetSimpleValue(info, 2);
2469 if (ValueIsNull(info.GetIsolate(), argOne) ||
2470 ValueIsNull(info.GetIsolate(), argTwo) ||
2471 ValueIsNull(info.GetIsolate(), argThree)) {
2472 info.GetReturnValue().SetNull();
2476 double nAmount = ValueToDouble(info.GetIsolate(), argOne);
2477 double nRate = ValueToDouble(info.GetIsolate(), argTwo);
2478 int nPeriods = GetValidatedPaymentPeriods(info.GetIsolate(), argThree);
2479 if (nAmount <= 0 || nRate < 0 || nPeriods == 0) {
2480 pContext->ThrowArgumentMismatchException();
2487 for (
int i = 0; i < nPeriods; ++i) {
2490 dResult = nAmount * (nTemp - 1) / nRate;
2492 dResult = nAmount * nPeriods;
2495 info.GetReturnValue().Set(dResult);
2499void CFXJSE_FormCalcContext::IPmt(
2501 const v8::FunctionCallbackInfo<v8::Value>& info) {
2502 CFXJSE_FormCalcContext* pContext = ToFormCalcContext(pThis);
2503 if (info.Length() != 5) {
2504 pContext->ThrowParamCountMismatchException(
"IPmt");
2508 v8::Local<v8::Value> argOne = GetSimpleValue(info, 0);
2509 v8::Local<v8::Value> argTwo = GetSimpleValue(info, 1);
2510 v8::Local<v8::Value> argThree = GetSimpleValue(info, 2);
2511 v8::Local<v8::Value> argFour = GetSimpleValue(info, 3);
2512 v8::Local<v8::Value> argFive = GetSimpleValue(info, 4);
2513 if (ValueIsNull(info.GetIsolate(), argOne) ||
2514 ValueIsNull(info.GetIsolate(), argTwo) ||
2515 ValueIsNull(info.GetIsolate(), argThree) ||
2516 ValueIsNull(info.GetIsolate(), argFour) ||
2517 ValueIsNull(info.GetIsolate(), argFive)) {
2518 info.GetReturnValue().SetNull();
2522 float nPrincipalAmount = ValueToFloat(info.GetIsolate(), argOne);
2523 float nRate = ValueToFloat(info.GetIsolate(), argTwo);
2524 float nPayment = ValueToFloat(info.GetIsolate(), argThree);
2525 float nFirstMonth = ValueToFloat(info.GetIsolate(), argFour);
2526 float nNumberOfMonths = ValueToFloat(info.GetIsolate(), argFive);
2527 if ((nPrincipalAmount <= 0) || (nRate <= 0) || (nPayment <= 0) ||
2528 (nFirstMonth < 0) || (nNumberOfMonths < 0)) {
2529 pContext->ThrowArgumentMismatchException();
2533 float nRateOfMonth = nRate / 12;
2534 int32_t iNums =
static_cast<int32_t>(
2535 (log10((
float)(nPayment / nPrincipalAmount)) -
2536 log10((
float)(nPayment / nPrincipalAmount - nRateOfMonth))) /
2537 log10((
float)(1 + nRateOfMonth)));
2539 std::min(
static_cast<int32_t>(nFirstMonth + nNumberOfMonths - 1), iNums);
2541 if (nPayment < nPrincipalAmount * nRateOfMonth) {
2542 info.GetReturnValue().Set(0);
2547 for (i = 0; i < nFirstMonth - 1; ++i)
2548 nPrincipalAmount -= nPayment - nPrincipalAmount * nRateOfMonth;
2551 for (; i < iEnd; ++i) {
2552 nSum += nPrincipalAmount * nRateOfMonth;
2553 nPrincipalAmount -= nPayment - nPrincipalAmount * nRateOfMonth;
2555 info.GetReturnValue().Set(nSum);
2559void CFXJSE_FormCalcContext::NPV(
2561 const v8::FunctionCallbackInfo<v8::Value>& info) {
2562 CFXJSE_FormCalcContext* pContext = ToFormCalcContext(pThis);
2563 int32_t argc = info.Length();
2565 pContext->ThrowParamCountMismatchException(
"NPV");
2569 v8::Local<v8::Value> argValue = GetSimpleValue(info, 0);
2570 if (ValueIsNull(info.GetIsolate(), argValue)) {
2571 info.GetReturnValue().SetNull();
2575 double nRate = ValueToDouble(info.GetIsolate(), argValue);
2577 pContext->ThrowArgumentMismatchException();
2581 std::vector<
double> data;
2582 for (int32_t i = 1; i < argc; i++) {
2583 argValue = GetSimpleValue(info, i);
2584 if (ValueIsNull(info.GetIsolate(), argValue)) {
2585 info.GetReturnValue().SetNull();
2588 data.push_back(ValueToDouble(info.GetIsolate(), argValue));
2592 double nDivisor = 1.0 + nRate;
2593 while (!data.empty()) {
2594 nSum += data.back();
2598 info.GetReturnValue().Set(nSum);
2602void CFXJSE_FormCalcContext::Pmt(
2604 const v8::FunctionCallbackInfo<v8::Value>& info) {
2605 CFXJSE_FormCalcContext* pContext = ToFormCalcContext(pThis);
2606 if (info.Length() != 3) {
2607 pContext->ThrowParamCountMismatchException(
"Pmt");
2611 v8::Local<v8::Value> argOne = GetSimpleValue(info, 0);
2612 v8::Local<v8::Value> argTwo = GetSimpleValue(info, 1);
2613 v8::Local<v8::Value> argThree = GetSimpleValue(info, 2);
2614 if (ValueIsNull(info.GetIsolate(), argOne) ||
2615 ValueIsNull(info.GetIsolate(), argTwo) ||
2616 ValueIsNull(info.GetIsolate(), argThree)) {
2617 info.GetReturnValue().SetNull();
2621 double nPrincipal = ValueToDouble(info.GetIsolate(), argOne);
2622 double nRate = ValueToDouble(info.GetIsolate(), argTwo);
2623 int nPeriods = GetValidatedPaymentPeriods(info.GetIsolate(), argThree);
2624 if (nPrincipal <= 0 || nRate <= 0 || nPeriods == 0) {
2625 pContext->ThrowArgumentMismatchException();
2629 double nSum = pow(1.0 + nRate, nPeriods);
2630 info.GetReturnValue().Set((nPrincipal * nRate * nSum) / (nSum - 1));
2634void CFXJSE_FormCalcContext::PPmt(
2636 const v8::FunctionCallbackInfo<v8::Value>& info) {
2637 CFXJSE_FormCalcContext* pContext = ToFormCalcContext(pThis);
2638 if (info.Length() != 5) {
2639 pContext->ThrowParamCountMismatchException(
"PPmt");
2643 v8::Local<v8::Value> argOne = GetSimpleValue(info, 0);
2644 v8::Local<v8::Value> argTwo = GetSimpleValue(info, 1);
2645 v8::Local<v8::Value> argThree = GetSimpleValue(info, 2);
2646 v8::Local<v8::Value> argFour = GetSimpleValue(info, 3);
2647 v8::Local<v8::Value> argFive = GetSimpleValue(info, 4);
2648 if (ValueIsNull(info.GetIsolate(), argOne) ||
2649 ValueIsNull(info.GetIsolate(), argTwo) ||
2650 ValueIsNull(info.GetIsolate(), argThree) ||
2651 ValueIsNull(info.GetIsolate(), argFour) ||
2652 ValueIsNull(info.GetIsolate(), argFive)) {
2653 info.GetReturnValue().SetNull();
2657 float nPrincipalAmount = ValueToFloat(info.GetIsolate(), argOne);
2658 float nRate = ValueToFloat(info.GetIsolate(), argTwo);
2659 float nPayment = ValueToFloat(info.GetIsolate(), argThree);
2660 float nFirstMonth = ValueToFloat(info.GetIsolate(), argFour);
2661 float nNumberOfMonths = ValueToFloat(info.GetIsolate(), argFive);
2662 if ((nPrincipalAmount <= 0) || (nRate <= 0) || (nPayment <= 0) ||
2663 (nFirstMonth < 0) || (nNumberOfMonths < 0)) {
2664 pContext->ThrowArgumentMismatchException();
2668 float nRateOfMonth = nRate / 12;
2669 int32_t iNums =
static_cast<int32_t>(
2670 (log10((
float)(nPayment / nPrincipalAmount)) -
2671 log10((
float)(nPayment / nPrincipalAmount - nRateOfMonth))) /
2672 log10((
float)(1 + nRateOfMonth)));
2674 std::min(
static_cast<int32_t>(nFirstMonth + nNumberOfMonths - 1), iNums);
2675 if (nPayment < nPrincipalAmount * nRateOfMonth) {
2676 pContext->ThrowArgumentMismatchException();
2681 for (i = 0; i < nFirstMonth - 1; ++i)
2682 nPrincipalAmount -= nPayment - nPrincipalAmount * nRateOfMonth;
2686 for (; i < iEnd; ++i) {
2687 nTemp = nPayment - nPrincipalAmount * nRateOfMonth;
2689 nPrincipalAmount -= nTemp;
2691 info.GetReturnValue().Set(nSum);
2695void CFXJSE_FormCalcContext::PV(
2697 const v8::FunctionCallbackInfo<v8::Value>& info) {
2698 CFXJSE_FormCalcContext* pContext = ToFormCalcContext(pThis);
2699 if (info.Length() != 3) {
2700 pContext->ThrowParamCountMismatchException(
"PV");
2704 v8::Local<v8::Value> argOne = GetSimpleValue(info, 0);
2705 v8::Local<v8::Value> argTwo = GetSimpleValue(info, 1);
2706 v8::Local<v8::Value> argThree = GetSimpleValue(info, 2);
2707 if (ValueIsNull(info.GetIsolate(), argOne) ||
2708 ValueIsNull(info.GetIsolate(), argTwo) ||
2709 ValueIsNull(info.GetIsolate(), argThree)) {
2710 info.GetReturnValue().SetNull();
2714 double nAmount = ValueToDouble(info.GetIsolate(), argOne);
2715 double nRate = ValueToDouble(info.GetIsolate(), argTwo);
2716 int nPeriods = GetValidatedPaymentPeriods(info.GetIsolate(), argThree);
2717 if (nAmount <= 0 || nRate < 0 || nPeriods == 0) {
2718 pContext->ThrowArgumentMismatchException();
2722 double nTemp = 1 / pow(1.0 + nRate, nPeriods);
2723 info.GetReturnValue().Set(nAmount * ((1.0 - nTemp) / nRate));
2727void CFXJSE_FormCalcContext::Rate(
2729 const v8::FunctionCallbackInfo<v8::Value>& info) {
2730 CFXJSE_FormCalcContext* pContext = ToFormCalcContext(pThis);
2731 if (info.Length() != 3) {
2732 pContext->ThrowParamCountMismatchException(
"Rate");
2736 v8::Local<v8::Value> argOne = GetSimpleValue(info, 0);
2737 v8::Local<v8::Value> argTwo = GetSimpleValue(info, 1);
2738 v8::Local<v8::Value> argThree = GetSimpleValue(info, 2);
2739 if (ValueIsNull(info.GetIsolate(), argOne) ||
2740 ValueIsNull(info.GetIsolate(), argTwo) ||
2741 ValueIsNull(info.GetIsolate(), argThree)) {
2742 info.GetReturnValue().SetNull();
2746 float nFuture = ValueToFloat(info.GetIsolate(), argOne);
2747 float nPresent = ValueToFloat(info.GetIsolate(), argTwo);
2748 int nPeriods = GetValidatedPaymentPeriods(info.GetIsolate(), argThree);
2749 if (nFuture <= 0 || nPresent < 0 || nPeriods == 0) {
2750 pContext->ThrowArgumentMismatchException();
2754 info.GetReturnValue().Set(powf(nFuture / nPresent, 1.0f / nPeriods) - 1.0f);
2758void CFXJSE_FormCalcContext::Term(
2760 const v8::FunctionCallbackInfo<v8::Value>& info) {
2761 CFXJSE_FormCalcContext* pContext = ToFormCalcContext(pThis);
2762 if (info.Length() != 3) {
2763 pContext->ThrowParamCountMismatchException(
"Term");
2767 v8::Local<v8::Value> argOne = GetSimpleValue(info, 0);
2768 v8::Local<v8::Value> argTwo = GetSimpleValue(info, 1);
2769 v8::Local<v8::Value> argThree = GetSimpleValue(info, 2);
2770 if (ValueIsNull(info.GetIsolate(), argOne) ||
2771 ValueIsNull(info.GetIsolate(), argTwo) ||
2772 ValueIsNull(info.GetIsolate(), argThree)) {
2773 info.GetReturnValue().SetNull();
2777 float nMount = ValueToFloat(info.GetIsolate(), argOne);
2778 float nRate = ValueToFloat(info.GetIsolate(), argTwo);
2779 float nFuture = ValueToFloat(info.GetIsolate(), argThree);
2780 if ((nMount <= 0) || (nRate <= 0) || (nFuture <= 0)) {
2781 pContext->ThrowArgumentMismatchException();
2785 info.GetReturnValue().Set(log((
float)(nFuture / nMount * nRate) + 1) /
2786 log((
float)(1 + nRate)));
2790void CFXJSE_FormCalcContext::Choose(
2792 const v8::FunctionCallbackInfo<v8::Value>& info) {
2793 CFXJSE_FormCalcContext* pContext = ToFormCalcContext(pThis);
2794 int32_t argc = info.Length();
2796 pContext->ThrowParamCountMismatchException(
"Choose");
2800 if (ValueIsNull(info.GetIsolate(), info[0])) {
2801 info.GetReturnValue().SetNull();
2806 static_cast<int32_t>(ValueToFloat(info.GetIsolate(), info[0]));
2808 info.GetReturnValue().SetEmptyString();
2812 bool bFound =
false;
2813 bool bStopCounterFlags =
false;
2814 int32_t iArgIndex = 1;
2815 int32_t iValueIndex = 0;
2816 while (!bFound && !bStopCounterFlags && (iArgIndex < argc)) {
2817 v8::Local<v8::Value> argIndexValue = info[iArgIndex];
2818 if (fxv8::IsArray(argIndexValue)) {
2819 v8::Local<v8::Array> arr = argIndexValue.As<v8::Array>();
2820 uint32_t iLength = fxv8::GetArrayLengthHelper(arr);
2822 bStopCounterFlags =
true;
2824 iValueIndex += (iLength - 2);
2825 if (iValueIndex >= iIndex) {
2826 v8::Local<v8::Value> propertyValue =
2827 fxv8::ReentrantGetArrayElementHelper(info.GetIsolate(), arr, 1);
2828 v8::Local<v8::Value> jsValue = fxv8::ReentrantGetArrayElementHelper(
2829 info.GetIsolate(), arr, (iLength - 1) - (iValueIndex - iIndex));
2830 v8::Local<v8::Value> newPropertyValue;
2831 if (fxv8::IsObject(jsValue)) {
2832 v8::Local<v8::Object> jsObjectValue = jsValue.As<v8::Object>();
2833 if (fxv8::IsNull(propertyValue)) {
2835 GetObjectDefaultValue(info.GetIsolate(), jsObjectValue);
2837 ByteString bsName = fxv8::ReentrantToByteStringHelper(
2838 info.GetIsolate(), propertyValue);
2839 newPropertyValue = fxv8::ReentrantGetObjectPropertyHelper(
2840 info.GetIsolate(), jsObjectValue, bsName.AsStringView());
2843 ByteString bsChosen =
2844 ValueToUTF8String(info.GetIsolate(), newPropertyValue);
2845 info.GetReturnValue().Set(
2846 fxv8::NewStringHelper(info.GetIsolate(), bsChosen.AsStringView()));
2851 if (iValueIndex == iIndex) {
2852 ByteString bsChosen =
2853 ValueToUTF8String(info.GetIsolate(), argIndexValue);
2854 info.GetReturnValue().Set(
2855 fxv8::NewStringHelper(info.GetIsolate(), bsChosen.AsStringView()));
2862 info.GetReturnValue().SetEmptyString();
2866void CFXJSE_FormCalcContext::Exists(
2868 const v8::FunctionCallbackInfo<v8::Value>& info) {
2869 if (info.Length() != 1) {
2870 ToFormCalcContext(pThis)->ThrowParamCountMismatchException(
"Exists");
2877void CFXJSE_FormCalcContext::HasValue(
2879 const v8::FunctionCallbackInfo<v8::Value>& info) {
2880 if (info.Length() != 1) {
2881 ToFormCalcContext(pThis)->ThrowParamCountMismatchException(
"HasValue");
2885 v8::Local<v8::Value> argOne = GetSimpleValue(info, 0);
2886 if (!fxv8::IsString(argOne)) {
2887 info.GetReturnValue().Set(
2888 static_cast<
int>(fxv8::IsNumber(argOne) || fxv8::IsBoolean(argOne)));
2892 ByteString bsValue =
2893 fxv8::ReentrantToByteStringHelper(info.GetIsolate(), argOne);
2895 info.GetReturnValue().Set(
static_cast<
int>(!bsValue
.IsEmpty()));
2899void CFXJSE_FormCalcContext::Oneof(
2901 const v8::FunctionCallbackInfo<v8::Value>& info) {
2902 if (info.Length() < 2) {
2903 ToFormCalcContext(pThis)->ThrowParamCountMismatchException(
"Oneof");
2907 v8::Local<v8::Value> argOne = GetSimpleValue(info, 0);
2908 for (
const auto& value : UnfoldArgs(info)) {
2909 if (SimpleValueCompare(info.GetIsolate(), argOne, value)) {
2910 info.GetReturnValue().Set(1);
2914 info.GetReturnValue().Set(0);
2918void CFXJSE_FormCalcContext::Within(
2920 const v8::FunctionCallbackInfo<v8::Value>& info) {
2921 if (info.Length() != 3) {
2922 ToFormCalcContext(pThis)->ThrowParamCountMismatchException(
"Within");
2926 v8::Local<v8::Value> argOne = GetSimpleValue(info, 0);
2927 if (fxv8::IsNull(argOne)) {
2928 info.GetReturnValue().SetUndefined();
2932 v8::Local<v8::Value> argLow = GetSimpleValue(info, 1);
2933 v8::Local<v8::Value> argHigh = GetSimpleValue(info, 2);
2934 if (fxv8::IsNumber(argOne)) {
2935 float oneNumber = ValueToFloat(info.GetIsolate(), argOne);
2936 float lowNumber = ValueToFloat(info.GetIsolate(), argLow);
2937 float heightNumber = ValueToFloat(info.GetIsolate(), argHigh);
2938 info.GetReturnValue().Set(
static_cast<
int>((oneNumber >= lowNumber) &&
2939 (oneNumber <= heightNumber)));
2943 ByteString bsOne = ValueToUTF8String(info.GetIsolate(), argOne);
2944 ByteString bsLow = ValueToUTF8String(info.GetIsolate(), argLow);
2945 ByteString bsHeight = ValueToUTF8String(info.GetIsolate(), argHigh);
2946 info.GetReturnValue().Set(
2947 static_cast<
int>((bsOne
.Compare(bsLow.AsStringView()
) >= 0) &&
2948 (bsOne
.Compare(bsHeight.AsStringView()
) <= 0)));
2952void CFXJSE_FormCalcContext::If(
2954 const v8::FunctionCallbackInfo<v8::Value>& info) {
2955 if (info.Length() != 3) {
2956 ToFormCalcContext(pThis)->ThrowParamCountMismatchException(
"If");
2960 const bool condition = fxv8::ReentrantToBooleanHelper(
2961 info.GetIsolate(), GetSimpleValue(info, 0));
2963 info.GetReturnValue().Set(GetSimpleValue(info, condition ? 1 : 2));
2967void CFXJSE_FormCalcContext::Eval(
2969 const v8::FunctionCallbackInfo<v8::Value>& info) {
2970 CFXJSE_FormCalcContext* pContext = ToFormCalcContext(pThis);
2971 if (info.Length() != 1) {
2972 pContext->ThrowParamCountMismatchException(
"Eval");
2976 v8::Isolate* pIsolate = pContext->GetIsolate();
2977 v8::Local<v8::Value> scriptValue = GetSimpleValue(info, 0);
2978 ByteString bsUtf8Script = ValueToUTF8String(info.GetIsolate(), scriptValue);
2980 info.GetReturnValue().SetNull();
2984 WideString wsCalcScript = WideString
::FromUTF8(bsUtf8Script.AsStringView()
);
2985 absl::optional<WideTextBuffer> wsJavaScriptBuf =
2986 CFXJSE_FormCalcContext::Translate(pContext->GetDocument()->GetHeap(),
2987 wsCalcScript.AsStringView());
2988 if (!wsJavaScriptBuf.has_value()) {
2989 pContext->ThrowCompilerErrorException();
2992 std::unique_ptr<CFXJSE_Context> pNewContext =
2993 CFXJSE_Context::Create(pIsolate,
nullptr,
nullptr,
nullptr);
2995 ByteString bsScript = FX_UTF8Encode(wsJavaScriptBuf.value().AsStringView());
2997 bsScript.AsStringView(), v8::Local<v8::Object>());
2999 info.GetReturnValue().Set(result.value->DirectGetValue());
3003void CFXJSE_FormCalcContext::Ref(
3005 const v8::FunctionCallbackInfo<v8::Value>& info) {
3006 CFXJSE_FormCalcContext* pContext = ToFormCalcContext(pThis);
3007 if (info.Length() != 1) {
3008 pContext->ThrowParamCountMismatchException(
"Ref");
3012 v8::Local<v8::Value> argOne = info[0];
3013 if (fxv8::IsBoolean(argOne) || fxv8::IsString(argOne) ||
3014 fxv8::IsNumber(argOne)) {
3015 info.GetReturnValue().Set(argOne);
3019 v8::LocalVector<v8::Value> values(info.GetIsolate(), 3);
3021 if (fxv8::IsNull(argOne)) {
3024 values[2] = fxv8::NewNullHelper(info.GetIsolate());
3025 }
else if (fxv8::IsArray(argOne)) {
3026 v8::Local<v8::Array> arr = argOne.As<v8::Array>();
3027 v8::Local<v8::Value> propertyValue =
3028 fxv8::ReentrantGetArrayElementHelper(info.GetIsolate(), arr, 1);
3029 v8::Local<v8::Value> jsObjectValue =
3030 fxv8::ReentrantGetArrayElementHelper(info.GetIsolate(), arr, 2);
3031 if (!fxv8::IsNull(propertyValue) || fxv8::IsNull(jsObjectValue)) {
3032 pContext->ThrowArgumentMismatchException();
3035 values[2] = jsObjectValue;
3036 }
else if (fxv8::IsObject(argOne)) {
3039 pContext->ThrowArgumentMismatchException();
3043 values[0] = fxv8::NewNumberHelper(info.GetIsolate(), intVal);
3044 values[1] = fxv8::NewNullHelper(info.GetIsolate());
3045 info.GetReturnValue().Set(fxv8::NewArrayHelper(info.GetIsolate(), values));
3049void CFXJSE_FormCalcContext::UnitType(
3051 const v8::FunctionCallbackInfo<v8::Value>& info) {
3052 if (info.Length() != 1) {
3053 ToFormCalcContext(pThis)->ThrowParamCountMismatchException(
"UnitType");
3057 v8::Local<v8::Value> unitspanValue = GetSimpleValue(info, 0);
3058 if (fxv8::IsNull(unitspanValue)) {
3059 info.GetReturnValue().SetNull();
3063 ByteString bsUnitspan = ValueToUTF8String(info.GetIsolate(), unitspanValue);
3065 info.GetReturnValue().SetEmptyString();
3069 enum XFA_FormCalc_VALUETYPE_ParserStatus {
3071 VALUETYPE_HAVEINVALIDCHAR,
3072 VALUETYPE_HAVEDIGIT,
3073 VALUETYPE_HAVEDIGITWHITE,
3081 WideString wsType = WideString
::FromUTF8(bsUnitspan.AsStringView()
);
3082 const wchar_t* pData = wsType
.c_str();
3084 int32_t uLen = wsType.GetLength();
3085 while (IsWhitespace(pData[u]))
3088 XFA_FormCalc_VALUETYPE_ParserStatus eParserStatus = VALUETYPE_START;
3093 typeChar = pData[u];
3094 if (IsWhitespace(typeChar)) {
3095 if (eParserStatus != VALUETYPE_HAVEDIGIT &&
3096 eParserStatus != VALUETYPE_HAVEDIGITWHITE) {
3097 eParserStatus = VALUETYPE_ISIN;
3100 eParserStatus = VALUETYPE_HAVEDIGITWHITE;
3101 }
else if (IsPartOfNumberW(typeChar)) {
3102 if (eParserStatus == VALUETYPE_HAVEDIGITWHITE) {
3103 eParserStatus = VALUETYPE_ISIN;
3106 eParserStatus = VALUETYPE_HAVEDIGIT;
3107 }
else if ((typeChar ==
'c' || typeChar ==
'p') && (u + 1 < uLen)) {
3108 wchar_t nextChar = pData[u + 1];
3109 if ((eParserStatus == VALUETYPE_START ||
3110 eParserStatus == VALUETYPE_HAVEDIGIT ||
3111 eParserStatus == VALUETYPE_HAVEDIGITWHITE) &&
3112 !IsPartOfNumberW(nextChar)) {
3113 eParserStatus = (typeChar ==
'c') ? VALUETYPE_ISCM : VALUETYPE_ISPT;
3116 eParserStatus = VALUETYPE_HAVEINVALIDCHAR;
3117 }
else if (typeChar ==
'm' && (u + 1 < uLen)) {
3118 wchar_t nextChar = pData[u + 1];
3119 if ((eParserStatus == VALUETYPE_START ||
3120 eParserStatus == VALUETYPE_HAVEDIGIT ||
3121 eParserStatus == VALUETYPE_HAVEDIGITWHITE) &&
3122 !IsPartOfNumberW(nextChar)) {
3123 eParserStatus = VALUETYPE_ISMM;
3124 if (nextChar ==
'p' || ((u + 5 < uLen) && pData[u + 1] ==
'i' &&
3125 pData[u + 2] ==
'l' && pData[u + 3] ==
'l' &&
3126 pData[u + 4] ==
'i' && pData[u + 5] ==
'p')) {
3127 eParserStatus = VALUETYPE_ISMP;
3132 eParserStatus = VALUETYPE_HAVEINVALIDCHAR;
3136 switch (eParserStatus) {
3137 case VALUETYPE_ISCM:
3138 info.GetReturnValue().Set(fxv8::NewStringHelper(info.GetIsolate(),
"cm"));
3140 case VALUETYPE_ISMM:
3141 info.GetReturnValue().Set(fxv8::NewStringHelper(info.GetIsolate(),
"mm"));
3143 case VALUETYPE_ISPT:
3144 info.GetReturnValue().Set(fxv8::NewStringHelper(info.GetIsolate(),
"pt"));
3146 case VALUETYPE_ISMP:
3147 info.GetReturnValue().Set(fxv8::NewStringHelper(info.GetIsolate(),
"mp"));
3150 info.GetReturnValue().Set(fxv8::NewStringHelper(info.GetIsolate(),
"in"));
3156void CFXJSE_FormCalcContext::UnitValue(
3158 const v8::FunctionCallbackInfo<v8::Value>& info) {
3159 int32_t argc = info.Length();
3160 if (argc < 1 || argc > 2) {
3161 ToFormCalcContext(pThis)->ThrowParamCountMismatchException(
"UnitValue");
3165 v8::Local<v8::Value> unitspanValue = GetSimpleValue(info, 0);
3166 if (fxv8::IsNull(unitspanValue)) {
3167 info.GetReturnValue().SetNull();
3171 ByteString bsUnitspan = ValueToUTF8String(info.GetIsolate(), unitspanValue);
3172 const char* pData = bsUnitspan
.c_str();
3174 info.GetReturnValue().Set(0);
3179 while (IsWhitespace(pData[u]))
3182 while (u < bsUnitspan.GetLength()) {
3183 if (!IsPartOfNumber(pData[u]))
3188 char* pTemp =
nullptr;
3189 double dFirstNumber = strtod(pData, &pTemp);
3190 while (IsWhitespace(pData[u]))
3193 size_t uLen = bsUnitspan.GetLength();
3194 ByteString bsFirstUnit;
3196 if (pData[u] ==
' ')
3199 bsFirstUnit += pData[u];
3206 v8::Local<v8::Value> unitValue = GetSimpleValue(info, 1);
3207 ByteString bsUnitTemp = ValueToUTF8String(info.GetIsolate(), unitValue);
3208 const char* pChar = bsUnitTemp
.c_str();
3210 while (IsWhitespace(pChar[uVal]))
3213 while (uVal < bsUnitTemp.GetLength()) {
3214 if (!isdigit(pChar[uVal]) && pChar[uVal] !=
'.')
3218 while (IsWhitespace(pChar[uVal]))
3221 size_t uValLen = bsUnitTemp.GetLength();
3222 while (uVal < uValLen) {
3223 if (pChar[uVal] ==
' ')
3226 bsUnit += pChar[uVal];
3231 bsUnit
= bsFirstUnit;
3235 if (bsFirstUnit
== "in" || bsFirstUnit
== "inches") {
3236 if (bsUnit
== "mm" || bsUnit
== "millimeters")
3237 dResult = dFirstNumber * 25.4;
3238 else if (bsUnit
== "cm" || bsUnit
== "centimeters")
3239 dResult = dFirstNumber * 2.54;
3240 else if (bsUnit
== "pt" || bsUnit
== "points")
3241 dResult = dFirstNumber / 72;
3242 else if (bsUnit
== "mp" || bsUnit
== "millipoints")
3243 dResult = dFirstNumber / 72000;
3245 dResult = dFirstNumber;
3246 }
else if (bsFirstUnit
== "mm" || bsFirstUnit
== "millimeters") {
3247 if (bsUnit
== "mm" || bsUnit
== "millimeters")
3248 dResult = dFirstNumber;
3249 else if (bsUnit
== "cm" || bsUnit
== "centimeters")
3250 dResult = dFirstNumber / 10;
3251 else if (bsUnit
== "pt" || bsUnit
== "points")
3252 dResult = dFirstNumber / 25.4 / 72;
3253 else if (bsUnit
== "mp" || bsUnit
== "millipoints")
3254 dResult = dFirstNumber / 25.4 / 72000;
3256 dResult = dFirstNumber / 25.4;
3257 }
else if (bsFirstUnit
== "cm" || bsFirstUnit
== "centimeters") {
3258 if (bsUnit
== "mm" || bsUnit
== "millimeters")
3259 dResult = dFirstNumber * 10;
3260 else if (bsUnit
== "cm" || bsUnit
== "centimeters")
3261 dResult = dFirstNumber;
3262 else if (bsUnit
== "pt" || bsUnit
== "points")
3263 dResult = dFirstNumber / 2.54 / 72;
3264 else if (bsUnit
== "mp" || bsUnit
== "millipoints")
3265 dResult = dFirstNumber / 2.54 / 72000;
3267 dResult = dFirstNumber / 2.54;
3268 }
else if (bsFirstUnit
== "pt" || bsFirstUnit
== "points") {
3269 if (bsUnit
== "mm" || bsUnit
== "millimeters")
3270 dResult = dFirstNumber / 72 * 25.4;
3271 else if (bsUnit
== "cm" || bsUnit
== "centimeters")
3272 dResult = dFirstNumber / 72 * 2.54;
3273 else if (bsUnit
== "pt" || bsUnit
== "points")
3274 dResult = dFirstNumber;
3275 else if (bsUnit
== "mp" || bsUnit
== "millipoints")
3276 dResult = dFirstNumber * 1000;
3278 dResult = dFirstNumber / 72;
3279 }
else if (bsFirstUnit
== "mp" || bsFirstUnit
== "millipoints") {
3280 if (bsUnit
== "mm" || bsUnit
== "millimeters")
3281 dResult = dFirstNumber / 72000 * 25.4;
3282 else if (bsUnit
== "cm" || bsUnit
== "centimeters")
3283 dResult = dFirstNumber / 72000 * 2.54;
3284 else if (bsUnit
== "pt" || bsUnit
== "points")
3285 dResult = dFirstNumber / 1000;
3286 else if (bsUnit
== "mp" || bsUnit
== "millipoints")
3287 dResult = dFirstNumber;
3289 dResult = dFirstNumber / 72000;
3291 info.GetReturnValue().Set(dResult);
3295void CFXJSE_FormCalcContext::At(
3297 const v8::FunctionCallbackInfo<v8::Value>& info) {
3298 if (info.Length() != 2) {
3299 ToFormCalcContext(pThis)->ThrowParamCountMismatchException(
"At");
3303 v8::Local<v8::Value> argOne = GetSimpleValue(info, 0);
3304 v8::Local<v8::Value> argTwo = GetSimpleValue(info, 1);
3305 if (ValueIsNull(info.GetIsolate(), argOne) ||
3306 ValueIsNull(info.GetIsolate(), argTwo)) {
3307 info.GetReturnValue().SetNull();
3311 ByteString stringTwo = ValueToUTF8String(info.GetIsolate(), argTwo);
3313 info.GetReturnValue().Set(1);
3317 ByteString stringOne = ValueToUTF8String(info.GetIsolate(), argOne);
3318 auto pos = stringOne.Find(stringTwo.AsStringView());
3319 info.GetReturnValue().Set(
3320 static_cast<
int>(pos.has_value() ? pos.value() + 1 : 0));
3324void CFXJSE_FormCalcContext::Concat(
3326 const v8::FunctionCallbackInfo<v8::Value>& info) {
3327 int32_t argc = info.Length();
3329 ToFormCalcContext(pThis)->ThrowParamCountMismatchException(
"Concat");
3333 ByteString bsResult;
3334 bool bAllNull =
true;
3335 for (int32_t i = 0; i < argc; i++) {
3336 v8::Local<v8::Value> value = GetSimpleValue(info, i);
3337 if (ValueIsNull(info.GetIsolate(), value))
3341 bsResult += ValueToUTF8String(info.GetIsolate(), value);
3345 info.GetReturnValue().SetNull();
3348 info.GetReturnValue().Set(
3349 fxv8::NewStringHelper(info.GetIsolate(), bsResult.AsStringView()));
3353void CFXJSE_FormCalcContext::Decode(
3355 const v8::FunctionCallbackInfo<v8::Value>& info) {
3356 int32_t argc = info.Length();
3357 if (argc < 1 || argc > 2) {
3358 ToFormCalcContext(pThis)->ThrowParamCountMismatchException(
"Decode");
3363 v8::Local<v8::Value> argOne = GetSimpleValue(info, 0);
3364 if (ValueIsNull(info.GetIsolate(), argOne)) {
3365 info.GetReturnValue().SetNull();
3369 WideString decoded = DecodeURL(WideString::FromUTF8(
3370 ValueToUTF8String(info.GetIsolate(), argOne).AsStringView()));
3371 auto result = FX_UTF8Encode(decoded.AsStringView());
3372 info.GetReturnValue().Set(
3373 fxv8::NewStringHelper(info.GetIsolate(), result.AsStringView()));
3377 v8::Local<v8::Value> argOne = GetSimpleValue(info, 0);
3378 v8::Local<v8::Value> argTwo = GetSimpleValue(info, 1);
3379 if (ValueIsNull(info.GetIsolate(), argOne) ||
3380 ValueIsNull(info.GetIsolate(), argTwo)) {
3381 info.GetReturnValue().SetNull();
3385 ByteString bsToDecode = ValueToUTF8String(info.GetIsolate(), argOne);
3386 ByteString bsIdentify = ValueToUTF8String(info.GetIsolate(), argTwo);
3389 WideString wsToDecode = WideString
::FromUTF8(bsToDecode.AsStringView()
);
3392 decoded
= DecodeHTML(wsToDecode);
3394 decoded
= DecodeXML(wsToDecode);
3396 decoded
= DecodeURL(wsToDecode);
3398 auto result = FX_UTF8Encode(decoded.AsStringView());
3399 info.GetReturnValue().Set(
3400 fxv8::NewStringHelper(info.GetIsolate(), result.AsStringView()));
3404void CFXJSE_FormCalcContext::Encode(
3406 const v8::FunctionCallbackInfo<v8::Value>& info) {
3407 int32_t argc = info.Length();
3408 if (argc < 1 || argc > 2) {
3409 ToFormCalcContext(pThis)->ThrowParamCountMismatchException(
"Encode");
3414 v8::Local<v8::Value> argOne = GetSimpleValue(info, 0);
3415 if (ValueIsNull(info.GetIsolate(), argOne)) {
3416 info.GetReturnValue().SetNull();
3419 WideString encoded =
3420 EncodeURL(ValueToUTF8String(info.GetIsolate(), argOne));
3421 auto result = FX_UTF8Encode(encoded.AsStringView());
3422 info.GetReturnValue().Set(
3423 fxv8::NewStringHelper(info.GetIsolate(), result.AsStringView()));
3427 v8::Local<v8::Value> argOne = GetSimpleValue(info, 0);
3428 v8::Local<v8::Value> argTwo = GetSimpleValue(info, 1);
3429 if (ValueIsNull(info.GetIsolate(), argOne) ||
3430 ValueIsNull(info.GetIsolate(), argTwo)) {
3431 info.GetReturnValue().SetNull();
3435 ByteString bsToEncode = ValueToUTF8String(info.GetIsolate(), argOne);
3436 ByteString bsIdentify = ValueToUTF8String(info.GetIsolate(), argTwo);
3439 encoded
= EncodeHTML(bsToEncode);
3441 encoded
= EncodeXML(bsToEncode);
3443 encoded
= EncodeURL(bsToEncode);
3445 auto result = FX_UTF8Encode(encoded.AsStringView());
3446 info.GetReturnValue().Set(
3447 fxv8::NewStringHelper(info.GetIsolate(), result.AsStringView()));
3451void CFXJSE_FormCalcContext::Format(
3453 const v8::FunctionCallbackInfo<v8::Value>& info) {
3454 CFXJSE_FormCalcContext* pContext = ToFormCalcContext(pThis);
3455 if (info.Length() < 2) {
3456 pContext->ThrowParamCountMismatchException(
"Format");
3460 v8::Local<v8::Value> argOne = GetSimpleValue(info, 0);
3461 ByteString bsPattern = ValueToUTF8String(info.GetIsolate(), argOne);
3463 v8::Local<v8::Value> argTwo = GetSimpleValue(info, 1);
3464 ByteString bsValue = ValueToUTF8String(info.GetIsolate(), argTwo);
3470 WideString wsPattern = WideString
::FromUTF8(bsPattern.AsStringView()
);
3471 WideString wsValue = WideString
::FromUTF8(bsValue.AsStringView()
);
3472 bool bPatternIsString;
3474 std::tie(bPatternIsString, dwPatternType) =
3475 PatternStringType(bsPattern.AsStringView());
3476 if (!bPatternIsString) {
3477 switch (dwPatternType) {
3479 auto iTChar = wsPattern.Find(L'T');
3480 if (!iTChar.has_value()) {
3481 info.GetReturnValue().SetEmptyString();
3484 WideString wsDatePattern
(L"date{"
);
3485 wsDatePattern += wsPattern.First(iTChar.value()) + L"} ";
3487 WideString wsTimePattern
(L"time{"
);
3489 wsPattern.Last(wsPattern.GetLength() - (iTChar.value() + 1)) + L"}";
3490 wsPattern
= wsDatePattern
+ wsTimePattern;
3493 wsPattern
= L"date{"
+ wsPattern
+ L"}";
3496 wsPattern
= L"time{"
+ wsPattern
+ L"}";
3499 wsPattern
= L"text{"
+ wsPattern
+ L"}";
3502 wsPattern
= L"num{"
+ wsPattern
+ L"}";
3505 WideString wsTestPattern = L"num{"
+ wsPattern
+ L"}";
3507 wsValue
, wsTestPattern
, pLocale
, pMgr
);
3509 wsPattern =
std::move(wsTestPattern);
3512 wsPattern
= L"text{"
+ wsPattern
+ L"}";
3523 info.GetReturnValue().SetEmptyString();
3526 info.GetReturnValue().Set(
3527 fxv8::NewStringHelper(info.GetIsolate(), wsRet
.ToUTF8().AsStringView()));
3531void CFXJSE_FormCalcContext::Left(
3533 const v8::FunctionCallbackInfo<v8::Value>& info) {
3534 if (info.Length() != 2) {
3535 ToFormCalcContext(pThis)->ThrowParamCountMismatchException(
"Left");
3539 v8::Local<v8::Value> argOne = GetSimpleValue(info, 0);
3540 v8::Local<v8::Value> argTwo = GetSimpleValue(info, 1);
3541 if ((ValueIsNull(info.GetIsolate(), argOne)) ||
3542 (ValueIsNull(info.GetIsolate(), argTwo))) {
3543 info.GetReturnValue().SetNull();
3547 ByteString bsSource = ValueToUTF8String(info.GetIsolate(), argOne);
3548 int32_t count = std::max(0, ValueToInteger(info.GetIsolate(), argTwo));
3549 info.GetReturnValue().Set(fxv8::NewStringHelper(
3550 info.GetIsolate(), bsSource.First(count).AsStringView()));
3554void CFXJSE_FormCalcContext::Len(
3556 const v8::FunctionCallbackInfo<v8::Value>& info) {
3557 if (info.Length() != 1) {
3558 ToFormCalcContext(pThis)->ThrowParamCountMismatchException(
"Len");
3562 v8::Local<v8::Value> argOne = GetSimpleValue(info, 0);
3563 if (ValueIsNull(info.GetIsolate(), argOne)) {
3564 info.GetReturnValue().SetNull();
3568 ByteString bsSource = ValueToUTF8String(info.GetIsolate(), argOne);
3569 info.GetReturnValue().Set(
static_cast<
int>(bsSource.GetLength()));
3573void CFXJSE_FormCalcContext::Lower(
3575 const v8::FunctionCallbackInfo<v8::Value>& info) {
3576 int32_t argc = info.Length();
3577 if (argc < 1 || argc > 2) {
3578 ToFormCalcContext(pThis)->ThrowParamCountMismatchException(
"Lower");
3582 v8::Local<v8::Value> argOne = GetSimpleValue(info, 0);
3583 if (ValueIsNull(info.GetIsolate(), argOne)) {
3584 info.GetReturnValue().SetNull();
3588 WideTextBuffer szLowBuf;
3589 ByteString bsArg = ValueToUTF8String(info.GetIsolate(), argOne);
3590 WideString wsArg = WideString
::FromUTF8(bsArg.AsStringView()
);
3591 for (
wchar_t ch : wsArg) {
3592 if ((ch >= 0x41 && ch <= 0x5A) || (ch >= 0xC0 && ch <= 0xDE))
3594 else if (ch == 0x100 || ch == 0x102 || ch == 0x104)
3596 szLowBuf.AppendChar(ch);
3599 info.GetReturnValue().Set(
3600 fxv8::NewStringHelper(info.GetIsolate(), result.AsStringView()));
3604void CFXJSE_FormCalcContext::Ltrim(
3606 const v8::FunctionCallbackInfo<v8::Value>& info) {
3607 if (info.Length() != 1) {
3608 ToFormCalcContext(pThis)->ThrowParamCountMismatchException(
"Ltrim");
3612 v8::Local<v8::Value> argOne = GetSimpleValue(info, 0);
3613 if (ValueIsNull(info.GetIsolate(), argOne)) {
3614 info.GetReturnValue().SetNull();
3618 ByteString bsSource = ValueToUTF8String(info.GetIsolate(), argOne);
3620 info.GetReturnValue().Set(
3621 fxv8::NewStringHelper(info.GetIsolate(), bsSource.AsStringView()));
3625void CFXJSE_FormCalcContext::Parse(
3627 const v8::FunctionCallbackInfo<v8::Value>& info) {
3628 CFXJSE_FormCalcContext* pContext = ToFormCalcContext(pThis);
3629 if (info.Length() != 2) {
3630 pContext->ThrowParamCountMismatchException(
"Parse");
3634 v8::Local<v8::Value> argOne = GetSimpleValue(info, 0);
3635 v8::Local<v8::Value> argTwo = GetSimpleValue(info, 1);
3636 if (ValueIsNull(info.GetIsolate(), argTwo)) {
3637 info.GetReturnValue().SetNull();
3641 ByteString bsPattern = ValueToUTF8String(info.GetIsolate(), argOne);
3642 ByteString bsValue = ValueToUTF8String(info.GetIsolate(), argTwo);
3647 WideString wsPattern = WideString
::FromUTF8(bsPattern.AsStringView()
);
3648 WideString wsValue = WideString
::FromUTF8(bsValue.AsStringView()
);
3649 bool bPatternIsString;
3651 std::tie(bPatternIsString, dwPatternType) =
3652 PatternStringType(bsPattern.AsStringView());
3653 if (bPatternIsString) {
3657 info.GetReturnValue().SetEmptyString();
3661 info.GetReturnValue().Set(
3662 fxv8::NewStringHelper(info.GetIsolate(), result.AsStringView()));
3666 switch (dwPatternType) {
3668 auto iTChar = wsPattern.Find(L'T');
3669 if (!iTChar.has_value()) {
3670 info.GetReturnValue().SetEmptyString();
3673 WideString wsDatePattern(L"date{" + wsPattern.First(iTChar.value()) +
3675 WideString wsTimePattern(
3677 wsPattern.Last(wsPattern.GetLength() - (iTChar.value() + 1)) + L"}");
3678 wsPattern
= wsDatePattern
+ wsTimePattern;
3682 info.GetReturnValue().SetEmptyString();
3686 info.GetReturnValue().Set(
3687 fxv8::NewStringHelper(info.GetIsolate(), result.AsStringView()));
3691 wsPattern
= L"date{"
+ wsPattern
+ L"}";
3695 info.GetReturnValue().SetEmptyString();
3699 info.GetReturnValue().Set(
3700 fxv8::NewStringHelper(info.GetIsolate(), result.AsStringView()));
3704 wsPattern
= L"time{"
+ wsPattern
+ L"}";
3708 info.GetReturnValue().SetEmptyString();
3712 info.GetReturnValue().Set(
3713 fxv8::NewStringHelper(info.GetIsolate(), result.AsStringView()));
3717 wsPattern
= L"text{"
+ wsPattern
+ L"}";
3719 wsPattern
, pLocale
, pMgr
);
3721 info.GetReturnValue().SetEmptyString();
3725 info.GetReturnValue().Set(
3726 fxv8::NewStringHelper(info.GetIsolate(), result.AsStringView()));
3730 wsPattern
= L"num{"
+ wsPattern
+ L"}";
3732 wsPattern
, pLocale
, pMgr
);
3734 info.GetReturnValue().SetEmptyString();
3742 WideString wsTestPattern = L"num{"
+ wsPattern
+ L"}";
3744 wsValue
, wsTestPattern
, pLocale
, pMgr
);
3752 WideString wsTestPattern = L"text{"
+ wsPattern
+ L"}";
3754 wsValue
, wsTestPattern
, pLocale
, pMgr
);
3757 info.GetReturnValue().Set(
3758 fxv8::NewStringHelper(info.GetIsolate(), result.AsStringView()));
3762 info.GetReturnValue().SetEmptyString();
3769void CFXJSE_FormCalcContext::Replace(
3771 const v8::FunctionCallbackInfo<v8::Value>& info) {
3772 int32_t argc = info.Length();
3773 if (argc < 2 || argc > 3) {
3774 ToFormCalcContext(pThis)->ThrowParamCountMismatchException(
"Replace");
3778 v8::Local<v8::Value> argOne = GetSimpleValue(info, 0);
3779 v8::Local<v8::Value> argTwo = GetSimpleValue(info, 1);
3782 if (!ValueIsNull(info.GetIsolate(), argOne) &&
3783 !ValueIsNull(info.GetIsolate(), argTwo)) {
3784 bsOne = ValueToUTF8String(info.GetIsolate(), argOne);
3785 bsTwo = ValueToUTF8String(info.GetIsolate(), argTwo);
3790 v8::Local<v8::Value> argThree = GetSimpleValue(info, 2);
3791 bsThree = ValueToUTF8String(info.GetIsolate(), argThree);
3794 bsOne.Replace(bsTwo.AsStringView(), bsThree.AsStringView());
3795 info.GetReturnValue().Set(
3796 fxv8::NewStringHelper(info.GetIsolate(), bsOne.AsStringView()));
3800void CFXJSE_FormCalcContext::Right(
3802 const v8::FunctionCallbackInfo<v8::Value>& info) {
3803 if (info.Length() != 2) {
3804 ToFormCalcContext(pThis)->ThrowParamCountMismatchException(
"Right");
3808 v8::Local<v8::Value> argOne = GetSimpleValue(info, 0);
3809 v8::Local<v8::Value> argTwo = GetSimpleValue(info, 1);
3810 if ((ValueIsNull(info.GetIsolate(), argOne)) ||
3811 (ValueIsNull(info.GetIsolate(), argTwo))) {
3812 info.GetReturnValue().SetNull();
3816 ByteString bsSource = ValueToUTF8String(info.GetIsolate(), argOne);
3817 int32_t count = std::max(0, ValueToInteger(info.GetIsolate(), argTwo));
3818 info.GetReturnValue().Set(fxv8::NewStringHelper(
3819 info.GetIsolate(), bsSource.Last(count).AsStringView()));
3823void CFXJSE_FormCalcContext::Rtrim(
3825 const v8::FunctionCallbackInfo<v8::Value>& info) {
3826 if (info.Length() != 1) {
3827 ToFormCalcContext(pThis)->ThrowParamCountMismatchException(
"Rtrim");
3831 v8::Local<v8::Value> argOne = GetSimpleValue(info, 0);
3832 if (ValueIsNull(info.GetIsolate(), argOne)) {
3833 info.GetReturnValue().SetNull();
3837 ByteString bsSource = ValueToUTF8String(info.GetIsolate(), argOne);
3839 info.GetReturnValue().Set(
3840 fxv8::NewStringHelper(info.GetIsolate(), bsSource.AsStringView()));
3844void CFXJSE_FormCalcContext::Space(
3846 const v8::FunctionCallbackInfo<v8::Value>& info) {
3847 if (info.Length() != 1) {
3848 ToFormCalcContext(pThis)->ThrowParamCountMismatchException(
"Space");
3852 v8::Local<v8::Value> argOne = GetSimpleValue(info, 0);
3853 if (fxv8::IsNull(argOne)) {
3854 info.GetReturnValue().SetNull();
3858 int count = std::max(0, ValueToInteger(info.GetIsolate(), argOne));
3859 if (count > kMaxCharCount) {
3860 ToFormCalcContext(pThis)->ThrowException(
"String too long.");
3863 DataVector<
char> space_string(count,
' ');
3864 info.GetReturnValue().Set(
3865 fxv8::NewStringHelper(info.GetIsolate(), ByteStringView(space_string)));
3869void CFXJSE_FormCalcContext::Str(
3871 const v8::FunctionCallbackInfo<v8::Value>& info) {
3872 int32_t argc = info.Length();
3873 if (argc < 1 || argc > 3) {
3874 ToFormCalcContext(pThis)->ThrowParamCountMismatchException(
"Str");
3878 v8::Local<v8::Value> numberValue = GetSimpleValue(info, 0);
3879 if (fxv8::IsNull(numberValue)) {
3880 info.GetReturnValue().SetNull();
3883 float fNumber = ValueToFloat(info.GetIsolate(), numberValue);
3885 constexpr int32_t kDefaultWidth = 10;
3886 int32_t iWidth = kDefaultWidth;
3888 v8::Local<v8::Value> widthValue = GetSimpleValue(info, 1);
3889 iWidth =
static_cast<int32_t>(ValueToFloat(info.GetIsolate(), widthValue));
3890 if (iWidth > kMaxCharCount) {
3891 ToFormCalcContext(pThis)->ThrowException(
"String too long.");
3896 constexpr int32_t kDefaultPrecision = 0;
3897 int32_t iPrecision = kDefaultPrecision;
3899 constexpr int32_t kMaxPrecision = 15;
3900 v8::Local<v8::Value> precision_value = GetSimpleValue(info, 2);
3901 iPrecision = std::max(0,
static_cast<int32_t>(ValueToFloat(
3902 info.GetIsolate(), precision_value)));
3903 iPrecision =
std::min(iPrecision, kMaxPrecision);
3906 ByteString bsFormat =
"%";
3914 const char* pData = bsNumber
.c_str();
3915 int32_t iLength = bsNumber.GetLength();
3917 while (u < iLength) {
3918 if (pData[u] ==
'.')
3924 if (u > iWidth || (iPrecision + u) >= iWidth) {
3925 DataVector<
char> stars(std::max(iWidth, 0),
'*');
3926 info.GetReturnValue().Set(
3927 fxv8::NewStringHelper(info.GetIsolate(), ByteStringView(stars)));
3931 ByteString resultBuf;
3933 if (iLength > iWidth) {
3935 while (i < iWidth) {
3941 while (i < iWidth - iLength) {
3947 info.GetReturnValue().Set(
3948 fxv8::NewStringHelper(info.GetIsolate(), resultBuf.AsStringView()));
3952 int32_t iLeavingSpace = iWidth - u - iPrecision;
3953 if (iPrecision != 0)
3957 while (i < iLeavingSpace) {
3963 resultBuf
+= pData[i];
3966 if (iPrecision != 0)
3971 while (u < iLength) {
3972 if (i >= iPrecision)
3975 resultBuf
+= pData[u];
3979 while (i < iPrecision) {
3983 info.GetReturnValue().Set(
3984 fxv8::NewStringHelper(info.GetIsolate(), resultBuf.AsStringView()));
3988void CFXJSE_FormCalcContext::Stuff(
3990 const v8::FunctionCallbackInfo<v8::Value>& info) {
3991 int32_t argc = info.Length();
3992 if (argc < 3 || argc > 4) {
3993 ToFormCalcContext(pThis)->ThrowParamCountMismatchException(
"Stuff");
3997 v8::Local<v8::Value> sourceValue = GetSimpleValue(info, 0);
3998 v8::Local<v8::Value> startValue = GetSimpleValue(info, 1);
3999 v8::Local<v8::Value> deleteValue = GetSimpleValue(info, 2);
4000 if (fxv8::IsNull(sourceValue) || fxv8::IsNull(startValue) ||
4001 fxv8::IsNull(deleteValue)) {
4002 info.GetReturnValue().SetNull();
4007 int32_t iDelete = 0;
4008 ByteString bsSource = ValueToUTF8String(info.GetIsolate(), sourceValue);
4009 int32_t iLength = pdfium::base::checked_cast<int32_t>(bsSource.GetLength());
4011 iStart = std::clamp(
4012 static_cast<int32_t>(ValueToFloat(info.GetIsolate(), startValue)), 1,
4014 iDelete = std::clamp(
4015 static_cast<int32_t>(ValueToFloat(info.GetIsolate(), deleteValue)), 0,
4016 iLength - iStart + 1);
4019 ByteString bsInsert;
4021 v8::Local<v8::Value> insertValue = GetSimpleValue(info, 3);
4022 bsInsert = ValueToUTF8String(info.GetIsolate(), insertValue);
4026 ByteString bsResult = {bsSource.AsStringView().First(iStart),
4027 bsInsert.AsStringView(),
4028 bsSource.AsStringView().Substr(iStart + iDelete)};
4029 info.GetReturnValue().Set(
4030 fxv8::NewStringHelper(info.GetIsolate(), bsResult.AsStringView()));
4034void CFXJSE_FormCalcContext::Substr(
4036 const v8::FunctionCallbackInfo<v8::Value>& info) {
4037 if (info.Length() != 3) {
4038 ToFormCalcContext(pThis)->ThrowParamCountMismatchException(
"Substr");
4042 v8::Local<v8::Value> string_value = GetSimpleValue(info, 0);
4043 v8::Local<v8::Value> start_value = GetSimpleValue(info, 1);
4044 v8::Local<v8::Value> end_value = GetSimpleValue(info, 2);
4045 if (ValueIsNull(info.GetIsolate(), string_value) ||
4046 ValueIsNull(info.GetIsolate(), start_value) ||
4047 ValueIsNull(info.GetIsolate(), end_value)) {
4048 info.GetReturnValue().SetNull();
4052 ByteString bsSource = ValueToUTF8String(info.GetIsolate(), string_value);
4053 size_t iLength = bsSource.GetLength();
4055 info.GetReturnValue().SetEmptyString();
4062 std::max(ValueToInteger(info.GetIsolate(), start_value), 1) - 1;
4063 if (iStart >= iLength) {
4064 info.GetReturnValue().SetEmptyString();
4069 size_t iCount = std::max(ValueToInteger(info.GetIsolate(), end_value), 0);
4070 iCount =
std::min(iCount, iLength - iStart);
4071 info.GetReturnValue().Set(fxv8::NewStringHelper(
4072 info.GetIsolate(), bsSource.Substr(iStart, iCount).AsStringView()));
4076void CFXJSE_FormCalcContext::Uuid(
4078 const v8::FunctionCallbackInfo<v8::Value>& info) {
4079 int32_t argc = info.Length();
4080 if (argc < 0 || argc > 1) {
4081 ToFormCalcContext(pThis)->ThrowParamCountMismatchException(
"Uuid");
4087 v8::Local<v8::Value> argOne = GetSimpleValue(info, 0);
4088 iNum =
static_cast<int32_t>(ValueToFloat(info.GetIsolate(), argOne));
4090 info.GetReturnValue().Set(fxv8::NewStringHelper(
4091 info.GetIsolate(), GUIDString(!!iNum).AsStringView()));
4095void CFXJSE_FormCalcContext::Upper(
4097 const v8::FunctionCallbackInfo<v8::Value>& info) {
4098 int32_t argc = info.Length();
4099 if (argc < 1 || argc > 2) {
4100 ToFormCalcContext(pThis)->ThrowParamCountMismatchException(
"Upper");
4104 v8::Local<v8::Value> argOne = GetSimpleValue(info, 0);
4105 if (ValueIsNull(info.GetIsolate(), argOne)) {
4106 info.GetReturnValue().SetNull();
4110 ByteString bsArg = ValueToUTF8String(info.GetIsolate(), argOne);
4111 WideString wsArg = WideString
::FromUTF8(bsArg.AsStringView()
);
4112 WideString upperStringBuf;
4113 upperStringBuf.Reserve(wsArg.GetLength());
4114 for (
wchar_t ch : wsArg) {
4115 if ((ch >= 0x61 && ch <= 0x7A) || (ch >= 0xE0 && ch <= 0xFE))
4117 else if (ch == 0x101 || ch == 0x103 || ch == 0x105)
4120 upperStringBuf += ch;
4122 info.GetReturnValue().Set(fxv8::NewStringHelper(
4124 FX_UTF8Encode(upperStringBuf.AsStringView()).AsStringView()));
4128void CFXJSE_FormCalcContext::WordNum(
4130 const v8::FunctionCallbackInfo<v8::Value>& info) {
4131 int32_t argc = info.Length();
4132 if (argc < 1 || argc > 3) {
4133 ToFormCalcContext(pThis)->ThrowParamCountMismatchException(
"WordNum");
4137 v8::Local<v8::Value> numberValue = GetSimpleValue(info, 0);
4138 if (fxv8::IsNull(numberValue)) {
4139 info.GetReturnValue().SetNull();
4142 float fNumber = ValueToFloat(info.GetIsolate(), numberValue);
4144 int32_t iIdentifier = 0;
4146 v8::Local<v8::Value> identifierValue = GetSimpleValue(info, 1);
4147 if (fxv8::IsNull(identifierValue)) {
4148 info.GetReturnValue().SetNull();
4152 static_cast<int32_t>(ValueToFloat(info.GetIsolate(), identifierValue));
4155 ByteString bsLocale;
4157 v8::Local<v8::Value> localeValue = GetSimpleValue(info, 2);
4158 if (fxv8::IsNull(localeValue)) {
4159 info.GetReturnValue().SetNull();
4162 bsLocale = ValueToUTF8String(info.GetIsolate(), localeValue);
4165 if (isnan(fNumber) || fNumber < 0.0f || fNumber > 922337203685477550.0f) {
4166 info.GetReturnValue().Set(fxv8::NewStringHelper(info.GetIsolate(),
"*"));
4169 ByteString bsFormatted = ByteString
::Format("%.2f", fNumber
);
4170 ByteString bsWorded = WordUS(bsFormatted.AsStringView(), iIdentifier);
4171 info.GetReturnValue().Set(
4172 fxv8::NewStringHelper(info.GetIsolate(), bsWorded.AsStringView()));
4176void CFXJSE_FormCalcContext::Get(
4178 const v8::FunctionCallbackInfo<v8::Value>& info) {
4179 CFXJSE_FormCalcContext* pContext = ToFormCalcContext(pThis);
4180 if (info.Length() != 1) {
4181 pContext->ThrowParamCountMismatchException(
"Get");
4193 v8::Local<v8::Value> argOne = GetSimpleValue(info, 0);
4194 ByteString bsUrl = ValueToUTF8String(info.GetIsolate(), argOne);
4196 pAppProvider->DownloadURL(WideString::FromUTF8(bsUrl.AsStringView()));
4201 DataVector<uint8_t> dataBuf(size);
4204 (
void)pFile->ReadBlock(dataBuf);
4205 info.GetReturnValue().Set(
4206 fxv8::NewStringHelper(info.GetIsolate(), ByteStringView(dataBuf)));
4210void CFXJSE_FormCalcContext::Post(
4212 const v8::FunctionCallbackInfo<v8::Value>& info) {
4213 CFXJSE_FormCalcContext* pContext = ToFormCalcContext(pThis);
4214 int32_t argc = info.Length();
4215 if (argc < 2 || argc > 5) {
4216 pContext->ThrowParamCountMismatchException(
"Post");
4228 v8::Local<v8::Value> argOne = GetSimpleValue(info, 0);
4229 ByteString bsURL = ValueToUTF8String(info.GetIsolate(), argOne);
4231 v8::Local<v8::Value> argTwo = GetSimpleValue(info, 1);
4232 ByteString bsData = ValueToUTF8String(info.GetIsolate(), argTwo);
4234 ByteString bsContentType;
4236 v8::Local<v8::Value> argThree = GetSimpleValue(info, 2);
4237 bsContentType = ValueToUTF8String(info.GetIsolate(), argThree);
4240 ByteString bsEncode;
4242 v8::Local<v8::Value> argFour = GetSimpleValue(info, 3);
4243 bsEncode = ValueToUTF8String(info.GetIsolate(), argFour);
4246 ByteString bsHeader;
4248 v8::Local<v8::Value> argFive = GetSimpleValue(info, 4);
4249 bsHeader = ValueToUTF8String(info.GetIsolate(), argFive);
4252 WideString decodedResponse;
4258 WideString
::FromUTF8(bsHeader.AsStringView()
), decodedResponse
)) {
4259 pContext->ThrowServerDeniedException();
4262 info.GetReturnValue().Set(fxv8::NewStringHelper(
4263 info.GetIsolate(), decodedResponse
.ToUTF8().AsStringView()));
4267void CFXJSE_FormCalcContext::Put(
4269 const v8::FunctionCallbackInfo<v8::Value>& info) {
4270 CFXJSE_FormCalcContext* pContext = ToFormCalcContext(pThis);
4271 int32_t argc = info.Length();
4272 if (argc < 2 || argc > 3) {
4273 pContext->ThrowParamCountMismatchException(
"Put");
4285 v8::Local<v8::Value> argOne = GetSimpleValue(info, 0);
4286 ByteString bsURL = ValueToUTF8String(info.GetIsolate(), argOne);
4288 v8::Local<v8::Value> argTwo = GetSimpleValue(info, 1);
4289 ByteString bsData = ValueToUTF8String(info.GetIsolate(), argTwo);
4291 ByteString bsEncode;
4293 v8::Local<v8::Value> argThree = GetSimpleValue(info, 2);
4294 bsEncode = ValueToUTF8String(info.GetIsolate(), argThree);
4300 pContext->ThrowServerDeniedException();
4303 info.GetReturnValue().SetEmptyString();
4307void CFXJSE_FormCalcContext::assign_value_operator(
4309 const v8::FunctionCallbackInfo<v8::Value>& info) {
4310 v8::Isolate* pIsolate = info.GetIsolate();
4311 CFXJSE_FormCalcContext* pContext = ToFormCalcContext(pThis);
4312 if (info.Length() != 2) {
4313 pContext->ThrowCompilerErrorException();
4316 ByteStringView bsFuncName(
"asgn_val_op");
4317 v8::Local<v8::Value> lValue = info[0];
4318 v8::Local<v8::Value> rValue = GetSimpleValue(info, 1);
4319 if (fxv8::IsArray(lValue)) {
4320 v8::Local<v8::Array> arr = lValue.As<v8::Array>();
4321 uint32_t iLeftLength = fxv8::GetArrayLengthHelper(arr);
4322 v8::Local<v8::Value> propertyValue =
4323 fxv8::ReentrantGetArrayElementHelper(pIsolate, arr, 1);
4324 for (uint32_t i = 2; i < iLeftLength; i++) {
4325 v8::Local<v8::Value> jsValue =
4326 fxv8::ReentrantGetArrayElementHelper(pIsolate, arr, i);
4327 if (!fxv8::IsObject(jsValue)) {
4328 pContext->ThrowNoDefaultPropertyException(bsFuncName);
4331 v8::Local<v8::Object> jsObjectValue = jsValue.As<v8::Object>();
4332 if (fxv8::IsNull(propertyValue)) {
4333 if (!SetObjectDefaultValue(pIsolate, jsObjectValue, rValue)) {
4334 pContext->ThrowNoDefaultPropertyException(bsFuncName);
4338 fxv8::ReentrantPutObjectPropertyHelper(
4339 pIsolate, jsObjectValue,
4340 fxv8::ReentrantToByteStringHelper(pIsolate, propertyValue)
4345 }
else if (fxv8::IsObject(lValue)) {
4346 if (!SetObjectDefaultValue(pIsolate, lValue.As<v8::Object>(), rValue)) {
4347 pContext->ThrowNoDefaultPropertyException(bsFuncName);
4351 info.GetReturnValue().Set(rValue);
4355void CFXJSE_FormCalcContext::logical_or_operator(
4357 const v8::FunctionCallbackInfo<v8::Value>& info) {
4358 if (info.Length() != 2) {
4359 ToFormCalcContext(pThis)->ThrowCompilerErrorException();
4363 v8::Local<v8::Value> argFirst = GetSimpleValue(info, 0);
4364 v8::Local<v8::Value> argSecond = GetSimpleValue(info, 1);
4365 if (fxv8::IsNull(argFirst) && fxv8::IsNull(argSecond)) {
4366 info.GetReturnValue().SetNull();
4370 float first = ValueToFloat(info.GetIsolate(), argFirst);
4371 float second = ValueToFloat(info.GetIsolate(), argSecond);
4372 info.GetReturnValue().Set(
static_cast<
int>(first || second));
4376void CFXJSE_FormCalcContext::logical_and_operator(
4378 const v8::FunctionCallbackInfo<v8::Value>& info) {
4379 if (info.Length() != 2) {
4380 ToFormCalcContext(pThis)->ThrowCompilerErrorException();
4384 v8::Local<v8::Value> argFirst = GetSimpleValue(info, 0);
4385 v8::Local<v8::Value> argSecond = GetSimpleValue(info, 1);
4386 if (fxv8::IsNull(argFirst) && fxv8::IsNull(argSecond)) {
4387 info.GetReturnValue().SetNull();
4391 float first = ValueToFloat(info.GetIsolate(), argFirst);
4392 float second = ValueToFloat(info.GetIsolate(), argSecond);
4393 info.GetReturnValue().Set(
static_cast<
int>(first && second));
4397void CFXJSE_FormCalcContext::equality_operator(
4399 const v8::FunctionCallbackInfo<v8::Value>& info) {
4400 if (info.Length() != 2) {
4401 ToFormCalcContext(pThis)->ThrowCompilerErrorException();
4405 if (fm_ref_equal(pThis, info)) {
4406 info.GetReturnValue().Set(1);
4410 v8::Local<v8::Value> argFirst = GetSimpleValue(info, 0);
4411 v8::Local<v8::Value> argSecond = GetSimpleValue(info, 1);
4412 if (fxv8::IsNull(argFirst) || fxv8::IsNull(argSecond)) {
4413 info.GetReturnValue().Set(
4414 static_cast<
int>(fxv8::IsNull(argFirst) && fxv8::IsNull(argSecond)));
4418 if (fxv8::IsString(argFirst) && fxv8::IsString(argSecond)) {
4419 info.GetReturnValue().Set(
static_cast<
int>(
4420 fxv8::ReentrantToByteStringHelper(info.GetIsolate(), argFirst) ==
4421 fxv8::ReentrantToByteStringHelper(info.GetIsolate(), argSecond)));
4425 double first = ValueToDouble(info.GetIsolate(), argFirst);
4426 double second = ValueToDouble(info.GetIsolate(), argSecond);
4427 info.GetReturnValue().Set(
static_cast<
int>(first == second));
4431void CFXJSE_FormCalcContext::notequality_operator(
4433 const v8::FunctionCallbackInfo<v8::Value>& info) {
4434 if (info.Length() != 2) {
4435 ToFormCalcContext(pThis)->ThrowCompilerErrorException();
4439 if (fm_ref_equal(pThis, info)) {
4440 info.GetReturnValue().Set(0);
4444 v8::Local<v8::Value> argFirst = GetSimpleValue(info, 0);
4445 v8::Local<v8::Value> argSecond = GetSimpleValue(info, 1);
4446 if (fxv8::IsNull(argFirst) || fxv8::IsNull(argSecond)) {
4447 info.GetReturnValue().Set(
4448 static_cast<
int>(!fxv8::IsNull(argFirst) || !fxv8::IsNull(argSecond)));
4452 if (fxv8::IsString(argFirst) && fxv8::IsString(argSecond)) {
4453 info.GetReturnValue().Set(
static_cast<
int>(
4454 fxv8::ReentrantToByteStringHelper(info.GetIsolate(), argFirst) !=
4455 fxv8::ReentrantToByteStringHelper(info.GetIsolate(), argSecond)));
4459 double first = ValueToDouble(info.GetIsolate(), argFirst);
4460 double second = ValueToDouble(info.GetIsolate(), argSecond);
4461 info.GetReturnValue().Set(
static_cast<
int>(first != second));
4465bool CFXJSE_FormCalcContext::fm_ref_equal(
4467 const v8::FunctionCallbackInfo<v8::Value>& info) {
4468 v8::Local<v8::Value> argFirst = info[0];
4469 v8::Local<v8::Value> argSecond = info[1];
4470 if (!fxv8::IsArray(argFirst) || !fxv8::IsArray(argSecond))
4473 v8::Local<v8::Array> firstArr = argFirst.As<v8::Array>();
4474 v8::Local<v8::Array> secondArr = argSecond.As<v8::Array>();
4475 v8::Local<v8::Value> firstFlag =
4476 fxv8::ReentrantGetArrayElementHelper(info.GetIsolate(), firstArr, 0);
4477 v8::Local<v8::Value> secondFlag =
4478 fxv8::ReentrantGetArrayElementHelper(info.GetIsolate(), secondArr, 0);
4479 if (fxv8::ReentrantToInt32Helper(info.GetIsolate(), firstFlag) != 3 ||
4480 fxv8::ReentrantToInt32Helper(info.GetIsolate(), secondFlag) != 3) {
4484 v8::Local<v8::Value> firstValue =
4485 fxv8::ReentrantGetArrayElementHelper(info.GetIsolate(), firstArr, 2);
4486 v8::Local<v8::Value> secondValue =
4487 fxv8::ReentrantGetArrayElementHelper(info.GetIsolate(), secondArr, 2);
4489 if (fxv8::IsNull(firstValue) || fxv8::IsNull(secondValue))
4492 return FXJSE_RetrieveObjectBinding(firstValue) ==
4493 FXJSE_RetrieveObjectBinding(secondValue);
4497void CFXJSE_FormCalcContext::less_operator(
4499 const v8::FunctionCallbackInfo<v8::Value>& info) {
4500 if (info.Length() != 2) {
4501 ToFormCalcContext(pThis)->ThrowCompilerErrorException();
4505 v8::Local<v8::Value> argFirst = GetSimpleValue(info, 0);
4506 v8::Local<v8::Value> argSecond = GetSimpleValue(info, 1);
4507 if (fxv8::IsNull(argFirst) || fxv8::IsNull(argSecond)) {
4508 info.GetReturnValue().Set(0);
4512 if (fxv8::IsString(argFirst) && fxv8::IsString(argSecond)) {
4514 fxv8::ReentrantToByteStringHelper(info.GetIsolate(), argFirst);
4516 fxv8::ReentrantToByteStringHelper(info.GetIsolate(), argSecond);
4517 info.GetReturnValue().Set(bs1
.Compare(bs2.AsStringView()
) < 0);
4521 double first = ValueToDouble(info.GetIsolate(), argFirst);
4522 double second = ValueToDouble(info.GetIsolate(), argSecond);
4523 info.GetReturnValue().Set(
static_cast<
int>(first < second));
4527void CFXJSE_FormCalcContext::lessequal_operator(
4529 const v8::FunctionCallbackInfo<v8::Value>& info) {
4530 if (info.Length() != 2) {
4531 ToFormCalcContext(pThis)->ThrowCompilerErrorException();
4535 v8::Local<v8::Value> argFirst = GetSimpleValue(info, 0);
4536 v8::Local<v8::Value> argSecond = GetSimpleValue(info, 1);
4537 if (fxv8::IsNull(argFirst) || fxv8::IsNull(argSecond)) {
4538 info.GetReturnValue().Set(
4539 static_cast<
int>(fxv8::IsNull(argFirst) && fxv8::IsNull(argSecond)));
4543 if (fxv8::IsString(argFirst) && fxv8::IsString(argSecond)) {
4544 auto bs1 = fxv8::ReentrantToByteStringHelper(info.GetIsolate(), argFirst);
4545 auto bs2 = fxv8::ReentrantToByteStringHelper(info.GetIsolate(), argSecond);
4546 info.GetReturnValue().Set(bs1.Compare(bs2.AsStringView()) <= 0);
4550 double first = ValueToDouble(info.GetIsolate(), argFirst);
4551 double second = ValueToDouble(info.GetIsolate(), argSecond);
4552 info.GetReturnValue().Set(
static_cast<
int>(first <= second));
4556void CFXJSE_FormCalcContext::greater_operator(
4558 const v8::FunctionCallbackInfo<v8::Value>& info) {
4559 if (info.Length() != 2) {
4560 ToFormCalcContext(pThis)->ThrowCompilerErrorException();
4564 v8::Local<v8::Value> argFirst = GetSimpleValue(info, 0);
4565 v8::Local<v8::Value> argSecond = GetSimpleValue(info, 1);
4566 if (fxv8::IsNull(argFirst) || fxv8::IsNull(argSecond)) {
4567 info.GetReturnValue().Set(0);
4571 if (fxv8::IsString(argFirst) && fxv8::IsString(argSecond)) {
4572 auto bs1 = fxv8::ReentrantToByteStringHelper(info.GetIsolate(), argFirst);
4573 auto bs2 = fxv8::ReentrantToByteStringHelper(info.GetIsolate(), argSecond);
4574 info.GetReturnValue().Set(bs1.Compare(bs2.AsStringView()) > 0);
4578 double first = ValueToDouble(info.GetIsolate(), argFirst);
4579 double second = ValueToDouble(info.GetIsolate(), argSecond);
4580 info.GetReturnValue().Set(
static_cast<
int>(first > second));
4584void CFXJSE_FormCalcContext::greaterequal_operator(
4586 const v8::FunctionCallbackInfo<v8::Value>& info) {
4587 if (info.Length() != 2) {
4588 ToFormCalcContext(pThis)->ThrowCompilerErrorException();
4592 v8::Local<v8::Value> argFirst = GetSimpleValue(info, 0);
4593 v8::Local<v8::Value> argSecond = GetSimpleValue(info, 1);
4594 if (fxv8::IsNull(argFirst) || fxv8::IsNull(argSecond)) {
4595 info.GetReturnValue().Set(
4596 static_cast<
int>(fxv8::IsNull(argFirst) && fxv8::IsNull(argSecond)));
4600 if (fxv8::IsString(argFirst) && fxv8::IsString(argSecond)) {
4601 auto bs1 = fxv8::ReentrantToByteStringHelper(info.GetIsolate(), argFirst);
4602 auto bs2 = fxv8::ReentrantToByteStringHelper(info.GetIsolate(), argSecond);
4603 info.GetReturnValue().Set(bs1.Compare(bs2.AsStringView()) >= 0);
4607 double first = ValueToDouble(info.GetIsolate(), argFirst);
4608 double second = ValueToDouble(info.GetIsolate(), argSecond);
4609 info.GetReturnValue().Set(
static_cast<
int>(first >= second));
4613void CFXJSE_FormCalcContext::plus_operator(
4615 const v8::FunctionCallbackInfo<v8::Value>& info) {
4616 if (info.Length() != 2) {
4617 ToFormCalcContext(pThis)->ThrowCompilerErrorException();
4621 if (ValueIsNull(info.GetIsolate(), info[0]) &&
4622 ValueIsNull(info.GetIsolate(), info[1])) {
4623 info.GetReturnValue().SetNull();
4627 const double first = ValueToDouble(info.GetIsolate(), info[0]);
4628 const double second = ValueToDouble(info.GetIsolate(), info[1]);
4629 info.GetReturnValue().Set(first + second);
4633void CFXJSE_FormCalcContext::minus_operator(
4635 const v8::FunctionCallbackInfo<v8::Value>& info) {
4636 if (info.Length() != 2) {
4637 ToFormCalcContext(pThis)->ThrowCompilerErrorException();
4641 v8::Local<v8::Value> argFirst = GetSimpleValue(info, 0);
4642 v8::Local<v8::Value> argSecond = GetSimpleValue(info, 1);
4643 if (fxv8::IsNull(argFirst) && fxv8::IsNull(argSecond)) {
4644 info.GetReturnValue().SetNull();
4648 double first = ValueToDouble(info.GetIsolate(), argFirst);
4649 double second = ValueToDouble(info.GetIsolate(), argSecond);
4650 info.GetReturnValue().Set(first - second);
4654void CFXJSE_FormCalcContext::multiple_operator(
4656 const v8::FunctionCallbackInfo<v8::Value>& info) {
4657 if (info.Length() != 2) {
4658 ToFormCalcContext(pThis)->ThrowCompilerErrorException();
4662 v8::Local<v8::Value> argFirst = GetSimpleValue(info, 0);
4663 v8::Local<v8::Value> argSecond = GetSimpleValue(info, 1);
4664 if (fxv8::IsNull(argFirst) && fxv8::IsNull(argSecond)) {
4665 info.GetReturnValue().SetNull();
4669 double first = ValueToDouble(info.GetIsolate(), argFirst);
4670 double second = ValueToDouble(info.GetIsolate(), argSecond);
4671 info.GetReturnValue().Set(first * second);
4675void CFXJSE_FormCalcContext::divide_operator(
4677 const v8::FunctionCallbackInfo<v8::Value>& info) {
4678 CFXJSE_FormCalcContext* pContext = ToFormCalcContext(pThis);
4679 if (info.Length() != 2) {
4680 pContext->ThrowCompilerErrorException();
4684 v8::Local<v8::Value> argFirst = GetSimpleValue(info, 0);
4685 v8::Local<v8::Value> argSecond = GetSimpleValue(info, 1);
4686 if (fxv8::IsNull(argFirst) && fxv8::IsNull(argSecond)) {
4687 info.GetReturnValue().SetNull();
4691 double second = ValueToDouble(info.GetIsolate(), argSecond);
4692 if (second == 0.0) {
4693 pContext->ThrowDivideByZeroException();
4697 double first = ValueToDouble(info.GetIsolate(), argFirst);
4698 info.GetReturnValue().Set(first / second);
4702void CFXJSE_FormCalcContext::positive_operator(
4704 const v8::FunctionCallbackInfo<v8::Value>& info) {
4705 if (info.Length() != 1) {
4706 ToFormCalcContext(pThis)->ThrowCompilerErrorException();
4710 v8::Local<v8::Value> argOne = GetSimpleValue(info, 0);
4711 if (fxv8::IsNull(argOne)) {
4712 info.GetReturnValue().SetNull();
4715 info.GetReturnValue().Set(0.0 + ValueToDouble(info.GetIsolate(), argOne));
4719void CFXJSE_FormCalcContext::negative_operator(
4721 const v8::FunctionCallbackInfo<v8::Value>& info) {
4722 if (info.Length() != 1) {
4723 ToFormCalcContext(pThis)->ThrowCompilerErrorException();
4727 v8::Local<v8::Value> argOne = GetSimpleValue(info, 0);
4728 if (fxv8::IsNull(argOne)) {
4729 info.GetReturnValue().SetNull();
4732 info.GetReturnValue().Set(0.0 - ValueToDouble(info.GetIsolate(), argOne));
4736void CFXJSE_FormCalcContext::logical_not_operator(
4738 const v8::FunctionCallbackInfo<v8::Value>& info) {
4739 if (info.Length() != 1) {
4740 ToFormCalcContext(pThis)->ThrowCompilerErrorException();
4744 v8::Local<v8::Value> argOne = GetSimpleValue(info, 0);
4745 if (fxv8::IsNull(argOne)) {
4746 info.GetReturnValue().SetNull();
4750 double first = ValueToDouble(info.GetIsolate(), argOne);
4751 info.GetReturnValue().Set((first == 0.0) ? 1 : 0);
4755void CFXJSE_FormCalcContext::dot_accessor(
4757 const v8::FunctionCallbackInfo<v8::Value>& info) {
4758 DotAccessorCommon(pThis, info,
true);
4762void CFXJSE_FormCalcContext::dotdot_accessor(
4764 const v8::FunctionCallbackInfo<v8::Value>& info) {
4765 DotAccessorCommon(pThis, info,
false);
4769void CFXJSE_FormCalcContext::eval_translation(
4771 const v8::FunctionCallbackInfo<v8::Value>& info) {
4772 CFXJSE_FormCalcContext* pContext = ToFormCalcContext(pThis);
4773 if (info.Length() != 1) {
4774 pContext->ThrowParamCountMismatchException(
"Eval");
4778 v8::Local<v8::Value> argOne = GetSimpleValue(info, 0);
4779 ByteString bsArg = ValueToUTF8String(info.GetIsolate(), argOne);
4781 pContext->ThrowArgumentMismatchException();
4785 WideString wsCalcScript = WideString
::FromUTF8(bsArg.AsStringView()
);
4786 absl::optional<WideTextBuffer> wsJavaScriptBuf =
4787 CFXJSE_FormCalcContext::Translate(pContext->GetDocument()->GetHeap(),
4788 wsCalcScript.AsStringView());
4789 if (!wsJavaScriptBuf.has_value()) {
4790 pContext->ThrowCompilerErrorException();
4793 info.GetReturnValue().Set(fxv8::NewStringHelper(
4795 FX_UTF8Encode(wsJavaScriptBuf.value().AsStringView()).AsStringView()));
4799void CFXJSE_FormCalcContext::is_fm_object(
4801 const v8::FunctionCallbackInfo<v8::Value>& info) {
4803 info.GetReturnValue().Set(result);
4807void CFXJSE_FormCalcContext::is_fm_array(
4809 const v8::FunctionCallbackInfo<v8::Value>& info) {
4811 info.GetReturnValue().Set(result);
4815void CFXJSE_FormCalcContext::get_fm_value(
4817 const v8::FunctionCallbackInfo<v8::Value>& info) {
4818 CFXJSE_FormCalcContext* pContext = ToFormCalcContext(pThis);
4819 if (info.Length() != 1) {
4820 pContext->ThrowCompilerErrorException();
4824 v8::Local<v8::Value> argOne = info[0];
4825 if (fxv8::IsArray(argOne)) {
4826 v8::Local<v8::Array> arr = argOne.As<v8::Array>();
4827 v8::Local<v8::Value> propertyValue =
4828 fxv8::ReentrantGetArrayElementHelper(info.GetIsolate(), arr, 1);
4829 v8::Local<v8::Value> jsValue =
4830 fxv8::ReentrantGetArrayElementHelper(info.GetIsolate(), arr, 2);
4831 if (!fxv8::IsObject(jsValue)) {
4832 info.GetReturnValue().Set(fxv8::NewUndefinedHelper(info.GetIsolate()));
4835 v8::Local<v8::Object> jsObjectValue = jsValue.As<v8::Object>();
4836 if (fxv8::IsNull(propertyValue)) {
4837 info.GetReturnValue().Set(
4838 GetObjectDefaultValue(info.GetIsolate(), jsObjectValue));
4842 fxv8::ReentrantToByteStringHelper(info.GetIsolate(), propertyValue);
4843 info.GetReturnValue().Set(fxv8::ReentrantGetObjectPropertyHelper(
4844 info.GetIsolate(), jsObjectValue, bsName.AsStringView()));
4848 if (fxv8::IsObject(argOne)) {
4849 v8::Local<v8::Object> obj = argOne.As<v8::Object>();
4850 info.GetReturnValue().Set(GetObjectDefaultValue(info.GetIsolate(), obj));
4854 info.GetReturnValue().Set(argOne);
4858void CFXJSE_FormCalcContext::get_fm_jsobj(
4860 const v8::FunctionCallbackInfo<v8::Value>& info) {
4861 if (info.Length() != 1) {
4862 ToFormCalcContext(pThis)->ThrowCompilerErrorException();
4866 v8::Local<v8::Value> argOne = info[0];
4867 if (!fxv8::IsArray(argOne)) {
4868 info.GetReturnValue().Set(argOne);
4872 v8::Local<v8::Array> arr = argOne.As<v8::Array>();
4873 info.GetReturnValue().Set(
4874 fxv8::ReentrantGetArrayElementHelper(info.GetIsolate(), arr, 2));
4878void CFXJSE_FormCalcContext::fm_var_filter(
4880 const v8::FunctionCallbackInfo<v8::Value>& info) {
4881 CFXJSE_FormCalcContext* pContext = ToFormCalcContext(pThis);
4882 if (info.Length() != 1) {
4883 pContext->ThrowCompilerErrorException();
4887 v8::Local<v8::Value> argOne = info[0];
4888 if (!fxv8::IsArray(argOne)) {
4889 info.GetReturnValue().Set(GetSimpleValue(info, 0));
4893 v8::Local<v8::Array> arr = argOne.As<v8::Array>();
4894 v8::Local<v8::Value> flagsValue =
4895 fxv8::ReentrantGetArrayElementHelper(info.GetIsolate(), arr, 0);
4896 int32_t iFlags = fxv8::ReentrantToInt32Helper(info.GetIsolate(), flagsValue);
4897 if (iFlags != 3 && iFlags != 4) {
4898 info.GetReturnValue().Set(GetSimpleValue(info, 0));
4903 v8::LocalVector<v8::Value> values(info.GetIsolate(), 3);
4904 values[0] = fxv8::NewNumberHelper(info.GetIsolate(), 3);
4905 values[1] = fxv8::NewNullHelper(info.GetIsolate());
4906 values[2] = fxv8::NewNullHelper(info.GetIsolate());
4907 info.GetReturnValue().Set(fxv8::NewArrayHelper(info.GetIsolate(), values));
4911 v8::Local<v8::Value> objectValue =
4912 fxv8::ReentrantGetArrayElementHelper(info.GetIsolate(), arr, 2);
4913 if (fxv8::IsNull(objectValue)) {
4914 pContext->ThrowCompilerErrorException();
4917 info.GetReturnValue().Set(argOne);
4921void CFXJSE_FormCalcContext::concat_fm_object(
4923 const v8::FunctionCallbackInfo<v8::Value>& info) {
4924 v8::Isolate* pIsolate = ToFormCalcContext(pThis)->GetIsolate();
4925 v8::LocalVector<v8::Value> returnValues(pIsolate);
4926 for (
int i = 0; i < info.Length(); ++i) {
4928 v8::Local<v8::Array> arr = info[i].As<v8::Array>();
4929 uint32_t length = fxv8::GetArrayLengthHelper(arr);
4930 for (uint32_t j = 2; j < length; j++) {
4931 returnValues.push_back(
4932 fxv8::ReentrantGetArrayElementHelper(info.GetIsolate(), arr, j));
4935 returnValues.push_back(info[i]);
4937 info.GetReturnValue().Set(fxv8::NewArrayHelper(pIsolate, returnValues));
4941ByteString CFXJSE_FormCalcContext::GenerateSomExpression(ByteStringView bsName,
4942 int32_t iIndexFlags,
4943 int32_t iIndexValue,
4946 return ByteString(bsName,
"[*]");
4950 if (iIndexFlags == 0)
4951 return ByteString(bsName);
4953 if (iIndexFlags == 1 || iIndexValue == 0) {
4958 const bool bNegative = iIndexValue < 0;
4959 ByteString bsSomExp(bsName);
4960 if (iIndexFlags == 2) {
4961 bsSomExp
+= bNegative ?
"[-" :
"[+";
4963 DCHECK_EQ(iIndexFlags, 3);
4964 bsSomExp
+= bNegative ?
"[" :
"[-";
4967 FX_SAFE_INT32 safe_index = iIndexValue;
4969 safe_index = -safe_index;
4975absl::optional<WideTextBuffer> CFXJSE_FormCalcContext::Translate(
4977 WideStringView wsFormcalc) {
4978 if (wsFormcalc.IsEmpty())
4979 return WideTextBuffer();
4984 if (!ast || parser.HasError())
4985 return absl::nullopt;
4988 absl::optional<WideTextBuffer> wsJavaScript = ast->ToJavaScript();
4989 if (!wsJavaScript.has_value())
4990 return absl::nullopt;
4992 if (CXFA_IsTooBig(wsJavaScript.value()))
4993 return absl::nullopt;
4995 return wsJavaScript;
5000 CXFA_Document* pDoc)
5002 m_Value.Reset(m_pIsolate,
5004 m_pIsolate, CFXJSE_Class::Create(
5005 pScriptContext, &kFormCalcDescriptor,
false)
5006 ->GetTemplate(m_pIsolate)));
5016 return v8::Local<v8::Value>::New(m_pIsolate, m_Value);
5020void CFXJSE_FormCalcContext::DotAccessorCommon(
5022 const v8::FunctionCallbackInfo<v8::Value>& info,
5023 bool bDotAccessor) {
5024 CFXJSE_FormCalcContext* pContext = ToFormCalcContext(pThis);
5025 v8::Isolate* pIsolate = pContext->GetIsolate();
5026 int32_t argc = info.Length();
5027 if (argc < 4 || argc > 5) {
5028 pContext->ThrowCompilerErrorException();
5032 bool bIsStar =
true;
5033 int32_t iIndexValue = 0;
5036 iIndexValue = ValueToInteger(info.GetIsolate(), info[4]);
5039 const ByteString bsName =
5041 const bool bHasNoResolveName = bDotAccessor && bsName
.IsEmpty();
5042 ByteString bsSomExp = GenerateSomExpression(
5043 bsName.AsStringView(),
5047 v8::Local<v8::Value> argAccessor = info[0];
5048 if (fxv8::IsArray(argAccessor)) {
5049 v8::Local<v8::Array> arr = argAccessor.As<v8::Array>();
5050 uint32_t iLength = fxv8::GetArrayLengthHelper(arr);
5052 pContext->ThrowArgumentMismatchException();
5057 std::vector<v8::LocalVector<v8::Value>> resolveValues(
5058 iLength - 2, v8::LocalVector<v8::Value>(info.GetIsolate()));
5060 bool bAttribute =
false;
5061 bool bAllEmpty =
true;
5062 for (uint32_t i = 2; i < iLength; i++) {
5063 v8::Local<v8::Value> hJSObjValue =
5064 fxv8::ReentrantGetArrayElementHelper(info.GetIsolate(), arr, i);
5065 absl::optional<CFXJSE_Engine::ResolveResult> maybeResult =
5066 ResolveObjects(pThis, hJSObjValue, bsSomExp.AsStringView(),
5067 bDotAccessor, bHasNoResolveName);
5068 if (maybeResult.has_value()) {
5069 resolveValues[i - 2] = ParseResolveResult(pThis, maybeResult.value(),
5070 hJSObjValue, &bAttribute);
5071 bAllEmpty = bAllEmpty && resolveValues[i - 2].empty();
5075 pContext->ThrowPropertyNotInObjectException(bsName.AsStringView(),
5076 bsSomExp.AsStringView());
5080 v8::LocalVector<v8::Value> values(pIsolate);
5081 values.push_back(fxv8::NewNumberHelper(pIsolate, 1));
5083 bAttribute ? fxv8::NewStringHelper(pIsolate, bsName.AsStringView())
5085 : fxv8::NewNullHelper(pIsolate).As<v8::Value>());
5086 for (uint32_t i = 0; i < iLength - 2; i++) {
5087 for (size_t j = 0; j < resolveValues[i].size(); j++)
5088 values.push_back(resolveValues[i][j]);
5090 info.GetReturnValue().Set(fxv8::NewArrayHelper(pIsolate, values));
5094 absl::optional<CFXJSE_Engine::ResolveResult> maybeResult;
5095 ByteString bsAccessorName =
5097 if (fxv8::IsObject(argAccessor) ||
5098 (fxv8::IsNull(argAccessor) && bsAccessorName.IsEmpty())) {
5099 maybeResult = ResolveObjects(pThis, argAccessor, bsSomExp.AsStringView(),
5100 bDotAccessor, bHasNoResolveName);
5101 }
else if (!fxv8::IsObject(argAccessor) && !bsAccessorName.IsEmpty()) {
5102 v8::Local<v8::Value> obj =
5103 GetObjectForName(pThis, bsAccessorName.AsStringView());
5104 if (!obj.IsEmpty()) {
5106 maybeResult = ResolveObjects(pThis, argAccessor, bsSomExp.AsStringView(),
5107 bDotAccessor, bHasNoResolveName);
5110 if (!maybeResult.has_value()) {
5111 pContext->ThrowPropertyNotInObjectException(bsName.AsStringView(),
5112 bsSomExp.AsStringView());
5116 bool bAttribute =
false;
5117 v8::LocalVector<v8::Value> resolveValues =
5118 ParseResolveResult(pThis, maybeResult.value(), argAccessor, &bAttribute);
5120 v8::LocalVector<v8::Value> values(pIsolate, resolveValues.size() + 2);
5121 values[0] = fxv8::NewNumberHelper(pIsolate, 1);
5122 values[1] = bAttribute
5123 ? fxv8::NewStringHelper(pIsolate, bsName.AsStringView())
5125 : fxv8::NewNullHelper(pIsolate).As<v8::Value>();
5127 for (size_t i = 0; i < resolveValues.size(); i++)
5128 values[i + 2] = resolveValues[i];
5130 info.GetReturnValue().Set(fxv8::NewArrayHelper(pIsolate, values));
5134bool CFXJSE_FormCalcContext::IsIsoDateFormat(ByteStringView bsData,
5138 pdfium::span<
const char> pData = bsData.span();
5140 int32_t& iYear = *pYear;
5141 int32_t& iMonth = *pMonth;
5142 int32_t& iDay = *pDay;
5148 if (pData.size() < 4) {
5154 for (int32_t i = 0; i < 4; ++i) {
5155 if (!isdigit(pData[i])) {
5159 szYear[i] = pData[i];
5162 if (pData.size() == 4) {
5166 int32_t iStyle = pData[4] ==
'-' ? 1 : 0;
5167 size_t iPosOff = iStyle == 0 ? 4 : 5;
5168 if (!isdigit(pData[iPosOff]) || !isdigit(pData[iPosOff + 1])) {
5172 char szBuffer[3] = {};
5173 szBuffer[0] = pData[iPosOff];
5174 szBuffer[1] = pData[iPosOff + 1];
5176 if (iMonth > 12 || iMonth < 1) {
5182 if (pData.size() == 6) {
5187 if (pData.size() == 7) {
5191 if (!isdigit(pData[iPosOff]) || !isdigit(pData[iPosOff + 1])) {
5195 szBuffer[0] = pData[iPosOff];
5196 szBuffer[1] = pData[iPosOff + 1];
5198 if (iPosOff + 2 < pData.size()) {
5203 bool bIsLeap = (!(iYear % 4) && (iYear % 100)) || !(iYear % 400);
5204 return iDay <= (bIsLeap ? 29 : 28);
5208 return iDay <= (iMonth % 2 == 0 ? 30 : 31);
5210 return iDay <= (iMonth % 2 == 0 ? 31 : 30);
5214bool CFXJSE_FormCalcContext::IsIsoTimeFormat(ByteStringView bsData) {
5215 enum State { kHour, kMinute, kSecond, kZoneHour, kZoneMinute, kFinished };
5217 pdfium::span<
const char> pData = bsData.span();
5218 if (pData.empty()) {
5224 while (i < pData.size()) {
5225 if (!isdigit(pData[i]) && pData[i] !=
':') {
5231 if (i == pData.size()) {
5232 iZone = pData.size();
5235 char szBuffer[3] = {};
5236 State state = kHour;
5238 while (iIndex + 1 < iZone) {
5239 szBuffer[0] = pData[iIndex];
5240 szBuffer[1] = pData[iIndex + 1];
5241 if (!isdigit(szBuffer[0]) || !isdigit(szBuffer[1])) {
5245 if (state == kHour) {
5250 }
else if (state == kMinute) {
5255 }
else if (state == kSecond) {
5265 if (iIndex < iZone && pData[iIndex] ==
':') {
5270 if (iIndex < pData.size() && pData[iIndex] ==
'.') {
5271 constexpr int kSubSecondLength = 3;
5272 if (iIndex + kSubSecondLength >= pData.size()) {
5277 char szMilliSeconds[kSubSecondLength + 1] = {};
5278 for (
int j = 0; j < kSubSecondLength; ++j) {
5279 char c = pData[iIndex + j];
5283 szMilliSeconds[j] = c;
5288 iIndex += kSubSecondLength;
5291 if (iIndex < pData.size() && FXSYS_towlower(pData[iIndex]) ==
'z') {
5295 if (iIndex < pData.size()) {
5296 if (pData[iIndex] ==
'+') {
5298 }
else if (pData[iIndex] ==
'-') {
5303 while (iIndex + 1 < pData.size()) {
5304 szBuffer[0] = pData[iIndex];
5305 szBuffer[1] = pData[iIndex + 1];
5306 if (!isdigit(szBuffer[0]) || !isdigit(szBuffer[1])) {
5310 if (state == kZoneHour) {
5314 state = kZoneMinute;
5315 }
else if (state == kZoneMinute) {
5324 if (iIndex < pData.size() && pData[iIndex] ==
':') {
5330 return iIndex == pData.size();
5333bool CFXJSE_FormCalcContext::IsIsoDateTimeFormat(ByteStringView bsData,
5342 while (iIndex < bsData.GetLength()) {
5343 if (bsData[iIndex] ==
'T' || bsData[iIndex] ==
't') {
5348 if (iIndex == bsData.GetLength() || (iIndex != 8 && iIndex != 10)) {
5352 ByteStringView date_part = bsData.First(iIndex);
5353 ByteStringView time_part = bsData.Substr(iIndex + 1);
5354 return IsIsoDateFormat(date_part, pYear, pMonth, pDay) &&
5355 IsIsoTimeFormat(time_part);
5359int32_t CFXJSE_FormCalcContext::DateString2Num(ByteStringView bsDate) {
5363 if (bsDate.GetLength() <= 10) {
5364 if (!IsIsoDateFormat(bsDate, &iYear, &iMonth, &iDay)) {
5368 if (!IsIsoDateTimeFormat(bsDate, &iYear, &iMonth, &iDay)) {
5379 while (iYear - i >= 1900) {
5381 ((!((iYear - i) % 4) && ((iYear - i) % 100)) || !((iYear - i) % 400))
5387 while (i < iMonth) {
5389 dDays += ((!(iYear % 4) && (iYear % 100)) || !(iYear % 400)) ? 29 : 28;
5390 }
else if (i <= 7) {
5391 dDays += (i % 2 == 0) ? 30 : 31;
5393 dDays += (i % 2 == 0) ? 31 : 30;
5399 while (iDay - i > 0) {
5403 return static_cast<int32_t>(dDays);
5406bool CFXJSE_FormCalcContext::ApplyToExpansion(
5407 std::function<
void(
v8::Isolate*, v8::Local<v8::Value>)> fn,
5408 const v8::FunctionCallbackInfo<v8::Value>& info,
5410 v8::Isolate* pIsolate = info.GetIsolate();
5411 for (int32_t i = 0; i < info.Length(); i++) {
5412 v8::Local<v8::Value> argValue = info[i];
5413 if (fxv8::IsArray(argValue)) {
5414 if (!ApplyToArray(pIsolate, fn, argValue.As<v8::Array>()) && bStrict) {
5415 ThrowArgumentMismatchException();
5418 }
else if (fxv8::IsObject(argValue)) {
5419 ApplyToObject(pIsolate, fn, argValue.As<v8::Object>());
5420 }
else if (!fxv8::IsNull(argValue)) {
5421 fn(pIsolate, argValue);
5427bool CFXJSE_FormCalcContext::ApplyToArray(
5428 v8::Isolate* pIsolate,
5429 std::function<
void(
v8::Isolate*, v8::Local<v8::Value>)> fn,
5430 v8::Local<v8::Array> pArray) {
5431 uint32_t iLength = fxv8::GetArrayLengthHelper(pArray);
5435 v8::Local<v8::Value> propertyValue =
5436 fxv8::ReentrantGetArrayElementHelper(pIsolate, pArray, 1);
5439 const bool nullprop = fxv8::IsNull(propertyValue);
5441 bsName = fxv8::ReentrantToByteStringHelper(pIsolate, propertyValue);
5443 for (uint32_t j = 2; j < iLength; j++) {
5444 v8::Local<v8::Value> jsValue =
5445 fxv8::ReentrantGetArrayElementHelper(pIsolate, pArray, j);
5446 if (!fxv8::IsObject(jsValue))
5449 v8::Local<v8::Object> jsObjectValue = jsValue.As<v8::Object>();
5450 v8::Local<v8::Value> newPropertyValue =
5451 nullprop ? GetObjectDefaultValue(pIsolate, jsObjectValue)
5452 : fxv8::ReentrantGetObjectPropertyHelper(
5453 pIsolate, jsObjectValue, bsName.AsStringView());
5454 if (!fxv8::IsNull(newPropertyValue))
5455 fn(pIsolate, newPropertyValue);
5460void CFXJSE_FormCalcContext::ApplyToObject(
5461 v8::Isolate* pIsolate,
5462 std::function<
void(
v8::Isolate*, v8::Local<v8::Value>)> fn,
5463 v8::Local<v8::Object> pObject) {
5464 v8::Local<v8::Value> newPropertyValue =
5465 GetObjectDefaultValue(pIsolate, pObject);
5466 if (!fxv8::IsNull(newPropertyValue))
5467 fn(pIsolate, newPropertyValue);
5470void CFXJSE_FormCalcContext::ThrowNoDefaultPropertyException(
5471 ByteStringView name)
const {
5472 ByteString msg(name);
5473 msg
+= " doesn't have a default property.";
5474 ThrowException(msg.AsStringView());
5477void CFXJSE_FormCalcContext::ThrowCompilerErrorException()
const {
5478 ThrowException(
"Compiler error.");
5481void CFXJSE_FormCalcContext::ThrowDivideByZeroException()
const {
5482 ThrowException(
"Divide by zero.");
5485void CFXJSE_FormCalcContext::ThrowServerDeniedException()
const {
5486 ThrowException(
"Server does not permit operation.");
5489void CFXJSE_FormCalcContext::ThrowPropertyNotInObjectException(
5490 ByteStringView name,
5491 ByteStringView exp)
const {
5492 ByteString msg
("An attempt was made to reference property '");
5494 msg
+= "' of a non-object in SOM expression ";
5497 ThrowException(msg.AsStringView());
5500void CFXJSE_FormCalcContext::ThrowParamCountMismatchException(
5501 ByteStringView method)
const {
5502 ByteString msg
("Incorrect number of parameters calling method '");
5505 ThrowException(msg.AsStringView());
5508void CFXJSE_FormCalcContext::ThrowArgumentMismatchException()
const {
5509 ThrowException(
"Argument mismatch in property or function argument.");
5512void CFXJSE_FormCalcContext::ThrowException(ByteStringView str)
const {
5513 DCHECK(!str.IsEmpty());
5514 FXJSE_ThrowMessage(GetIsolate(), str);
const FXJSE_CLASS_DESCRIPTOR kFormCalcDescriptor
CFGAS_Decimal(float val, uint8_t scale)
XFA_SCRIPTATTRIBUTEINFO script_attribute
CXFA_Object * GetThisObject() const
friend class EventParamScope
v8::Local< v8::Value > GlobalPropertyGetter()
static ByteString Local2IsoDate(CFXJSE_HostObject *pThis, ByteStringView bsDate, ByteStringView bsFormat, ByteStringView bsLocale)
static ByteString Num2AllTime(CFXJSE_HostObject *pThis, int32_t iTime, ByteStringView bsFormat, ByteStringView bsLocale, bool bGM)
CXFA_Document * GetDocument() const
static ByteString GetStandardTimeFormat(CFXJSE_HostObject *pThis, int32_t iStyle, ByteStringView bsLocale)
static ByteString GetStandardDateFormat(CFXJSE_HostObject *pThis, int32_t iStyle, ByteStringView bsLocale)
CFXJSE_FormCalcContext * AsFormCalcContext() override
static ByteString GetLocalDateFormat(CFXJSE_HostObject *pThis, int32_t iStyle, ByteStringView bsLocale, bool bStandard)
~CFXJSE_FormCalcContext() override
CFXJSE_FormCalcContext(v8::Isolate *pIsolate, CFXJSE_Context *pScriptContext, CXFA_Document *pDoc)
static ByteString GetLocalTimeFormat(CFXJSE_HostObject *pThis, int32_t iStyle, ByteStringView bsLocale, bool bStandard)
static ByteString IsoDate2Local(CFXJSE_HostObject *pThis, ByteStringView bsDate, ByteStringView bsFormat, ByteStringView bsLocale)
static ByteString IsoTime2Local(CFXJSE_HostObject *pThis, ByteStringView bsTime, ByteStringView bsFormat, ByteStringView bsLocale)
virtual CFXJSE_FormCalcContext * AsFormCalcContext()
uint8_t GetSecond() const
uint8_t GetMinute() const
uint16_t GetMillisecond() const
CXFA_FFNotify * GetNotify() const
CXFA_LocaleMgr * GetLocaleMgr()
CFXJSE_Engine * GetScriptContext() const
virtual bool PostRequestURL(const WideString &wsURL, const WideString &wsData, const WideString &wsContentType, const WideString &wsEncode, const WideString &wsHeader, WideString &wsResponse)=0
virtual bool PutRequestURL(const WideString &wsURL, const WideString &wsData, const WideString &wsEncode)=0
CXFA_FFApp::CallbackIface * GetAppProvider()
CXFA_FMParser(cppgc::Heap *heap, CXFA_FMLexer *pLexer)
GCedLocaleIface * GetDefLocale() override
GCedLocaleIface * GetLocaleByName(const WideString &wsLocaleName) override
CXFA_LocaleValue(ValueType dwType, const WideString &wsValue, const WideString &wsFormat, GCedLocaleIface *pLocale, CXFA_LocaleMgr *pLocaleMgr)
double GetDoubleNum() const
CFX_DateTime GetTime() const
const WideString & GetValue() const
CFX_DateTime GetDate() const
bool FormatPatterns(WideString &wsResult, const WideString &wsFormat, GCedLocaleIface *pLocale, XFA_ValuePicture eValueType) const
GCedLocaleIface * GetLocale()
int GetTimeZoneInMinutes() const
virtual WideString GetDatePattern(DateTimeSubcategory eType) const =0
virtual int GetTimeZoneInMinutes() const =0
virtual WideString GetDateTimeSymbols() const =0
virtual WideString GetTimePattern(DateTimeSubcategory eType) const =0
ByteString(const char *ptr)
bool EqualNoCase(ByteStringView str) const
static ByteString Format(const char *pFormat,...)
ByteString & operator+=(const ByteString &str)
ByteString & operator+=(char ch)
static ByteString FormatInteger(int i)
bool operator==(const ByteString &other) const
bool operator==(const char *ptr) const
ByteString & operator+=(const char *str)
const char * c_str() const
ByteString & operator=(const ByteString &that)
int Compare(ByteStringView str) const
ByteString ToUTF8() const
WideString & operator=(WideString &&that) noexcept
static WideString FromUTF8(ByteStringView str)
CharType operator[](const size_t index) const
const wchar_t * c_str() const
WideString(const wchar_t *ptr)
ByteString ToASCII() const
static WideString FromASCII(ByteStringView str)
void AppendChar(wchar_t wch)
WideString MakeString() const
WideStringView AsStringView() const
CXFA_Node * ToNode(CXFA_Object *pObj)
time_t FXSYS_time(time_t *tloc)
int FXSYS_WideHexCharToInt(wchar_t c)
bool FXSYS_IsDecimalDigit(wchar_t c)
bool FXSYS_IsWideHexDigit(wchar_t c)
struct tm * FXSYS_localtime(const time_t *tp)
void FX_Random_GenerateMT(uint32_t *pBuffer, int32_t iCount)
int32_t FXSYS_atoi(const char *str)
ByteString operator+(const ByteString &str1, const ByteString &str2)
WideString operator+(const WideString &str1, const WideString &str2)
ByteString operator+(const ByteString &str1, const char *str2)
WideString operator+(const wchar_t *str1, const WideString &str2)
WideString operator+(const WideString &str1, const wchar_t *str2)
bool IsBoolean(v8::Local< v8::Value > value)
bool IsArray(v8::Local< v8::Value > value)
bool IsUndefined(v8::Local< v8::Value > value)
bool IsNumber(v8::Local< v8::Value > value)
bool IsObject(v8::Local< v8::Value > value)
bool IsString(v8::Local< v8::Value > value)
ByteString ReentrantToByteStringHelper(v8::Isolate *pIsolate, v8::Local< v8::Value > pValue)
bool ReentrantToBooleanHelper(v8::Isolate *pIsolate, v8::Local< v8::Value > pValue)
bool IsNull(v8::Local< v8::Value > value)
int32_t ReentrantToInt32Helper(v8::Isolate *pIsolate, v8::Local< v8::Value > pValue)
XFA_ScriptType eValueType
XFA_ATTRIBUTE_CALLBACK callback