7#include "fxjs/xfa/cfxjse_formcalc_context.h"
22#include "core/fxcrt/cfx_datetime.h"
23#include "core/fxcrt/check_op.h"
24#include "core/fxcrt/code_point_view.h"
25#include "core/fxcrt/compiler_specific.h"
26#include "core/fxcrt/containers/contains.h"
27#include "core/fxcrt/data_vector.h"
28#include "core/fxcrt/fx_extension.h"
29#include "core/fxcrt/fx_random.h"
30#include "core/fxcrt/fx_safe_types.h"
31#include "core/fxcrt/numerics/safe_conversions.h"
32#include "core/fxcrt/span_util.h"
33#include "core/fxcrt/widetext_buffer.h"
35#include "fxjs/xfa/cfxjse_class.h"
36#include "fxjs/xfa/cfxjse_context.h"
37#include "fxjs/xfa/cfxjse_engine.h"
38#include "fxjs/xfa/cfxjse_value.h"
39#include "fxjs/xfa/cjx_object.h"
40#include "v8/include/v8-container.h"
41#include "v8/include/v8-function-callback.h"
42#include "v8/include/v8-local-handle.h"
43#include "v8/include/v8-object.h"
44#include "v8/include/v8-primitive.h"
45#include "xfa/fgas/crt/cfgas_decimal.h"
46#include "xfa/fxfa/cxfa_ffnotify.h"
47#include "xfa/fxfa/formcalc/cxfa_fmparser.h"
48#include "xfa/fxfa/formcalc/cxfa_fmtojavascriptdepth.h"
49#include "xfa/fxfa/parser/cxfa_document.h"
50#include "xfa/fxfa/parser/cxfa_localevalue.h"
51#include "xfa/fxfa/parser/cxfa_node.h"
52#include "xfa/fxfa/parser/cxfa_thisproxy.h"
53#include "xfa/fxfa/parser/cxfa_timezoneprovider.h"
54#include "xfa/fxfa/parser/gced_locale_iface.h"
55#include "xfa/fxfa/parser/xfa_utils.h"
63constexpr int kMaxCharCount = 15654908;
65const double kFinancialPrecision = 0.00000001;
67constexpr std::array<
wchar_t, 16> kStrCode = {
68 {L'0', L'1', L'2', L'3', L'4', L'5', L'6', L'7', L'8', L'9', L'a', L'b',
69 L'c', L'd', L'e', L'f'}};
71struct XFA_FMHtmlReserveCode {
74 const char m_htmlReserve[10];
78const XFA_FMHtmlReserveCode kReservesForDecode[] = {
79 {198,
"AElig"}, {193,
"Aacute"}, {194,
"Acirc"}, {192,
"Agrave"},
80 {913,
"Alpha"}, {197,
"Aring"}, {195,
"Atilde"}, {196,
"Auml"},
81 {914,
"Beta"}, {199,
"Ccedil"}, {935,
"Chi"}, {8225,
"Dagger"},
82 {916,
"Delta"}, {208,
"ETH"}, {201,
"Eacute"}, {202,
"Ecirc"},
83 {200,
"Egrave"}, {917,
"Epsilon"}, {919,
"Eta"}, {203,
"Euml"},
84 {915,
"Gamma"}, {922,
"Kappa"}, {923,
"Lambda"}, {924,
"Mu"},
85 {209,
"Ntilde"}, {925,
"Nu"}, {338,
"OElig"}, {211,
"Oacute"},
86 {212,
"Ocirc"}, {210,
"Ograve"}, {937,
"Omega"}, {927,
"Omicron"},
87 {216,
"Oslash"}, {213,
"Otilde"}, {214,
"Ouml"}, {934,
"Phi"},
88 {928,
"Pi"}, {936,
"Psi"}, {929,
"Rho"}, {352,
"Scaron"},
89 {931,
"Sigma"}, {222,
"THORN"}, {932,
"Tau"}, {920,
"Theta"},
90 {218,
"Uacute"}, {219,
"Ucirc"}, {217,
"Ugrave"}, {933,
"Upsilon"},
91 {220,
"Uuml"}, {926,
"Xi"}, {221,
"Yacute"}, {376,
"Yuml"},
92 {918,
"Zeta"}, {225,
"aacute"}, {226,
"acirc"}, {180,
"acute"},
93 {230,
"aelig"}, {224,
"agrave"}, {8501,
"alefsym"}, {945,
"alpha"},
94 {38,
"amp"}, {8743,
"and"}, {8736,
"ang"}, {39,
"apos"},
95 {229,
"aring"}, {8776,
"asymp"}, {227,
"atilde"}, {228,
"auml"},
96 {8222,
"bdquo"}, {946,
"beta"}, {166,
"brvbar"}, {8226,
"bull"},
97 {8745,
"cap"}, {231,
"ccedil"}, {184,
"cedil"}, {162,
"cent"},
98 {967,
"chi"}, {710,
"circ"}, {9827,
"clubs"}, {8773,
"cong"},
99 {169,
"copy"}, {8629,
"crarr"}, {8746,
"cup"}, {164,
"current"},
100 {8659,
"dArr"}, {8224,
"dagger"}, {8595,
"darr"}, {176,
"deg"},
101 {948,
"delta"}, {9830,
"diams"}, {247,
"divide"}, {233,
"eacute"},
102 {234,
"ecirc"}, {232,
"egrave"}, {8709,
"empty"}, {8195,
"emsp"},
103 {8194,
"ensp"}, {949,
"epsilon"}, {8801,
"equiv"}, {951,
"eta"},
104 {240,
"eth"}, {235,
"euml"}, {8364,
"euro"}, {8707,
"exist"},
105 {402,
"fnof"}, {8704,
"forall"}, {189,
"frac12"}, {188,
"frac14"},
106 {190,
"frac34"}, {8260,
"frasl"}, {947,
"gamma"}, {8805,
"ge"},
107 {62,
"gt"}, {8660,
"hArr"}, {8596,
"harr"}, {9829,
"hearts"},
108 {8230,
"hellip"}, {237,
"iacute"}, {238,
"icirc"}, {161,
"iexcl"},
109 {236,
"igrave"}, {8465,
"image"}, {8734,
"infin"}, {8747,
"int"},
110 {953,
"iota"}, {191,
"iquest"}, {8712,
"isin"}, {239,
"iuml"},
111 {954,
"kappa"}, {8656,
"lArr"}, {205,
"lacute"}, {955,
"lambda"},
112 {9001,
"lang"}, {171,
"laquo"}, {8592,
"larr"}, {8968,
"lceil"},
113 {206,
"lcirc"}, {8220,
"ldquo"}, {8804,
"le"}, {8970,
"lfloor"},
114 {204,
"lgrave"}, {921,
"lota"}, {8727,
"lowast"}, {9674,
"loz"},
115 {8206,
"lrm"}, {8249,
"lsaquo"}, {8216,
"lsquo"}, {60,
"lt"},
116 {207,
"luml"}, {175,
"macr"}, {8212,
"mdash"}, {181,
"micro"},
117 {183,
"middot"}, {8722,
"minus"}, {956,
"mu"}, {8711,
"nabla"},
118 {160,
"nbsp"}, {8211,
"ndash"}, {8800,
"ne"}, {8715,
"ni"},
119 {172,
"not"}, {8713,
"notin"}, {8836,
"nsub"}, {241,
"ntilde"},
120 {957,
"nu"}, {243,
"oacute"}, {244,
"ocirc"}, {339,
"oelig"},
121 {242,
"ograve"}, {8254,
"oline"}, {969,
"omega"}, {959,
"omicron"},
122 {8853,
"oplus"}, {8744,
"or"}, {170,
"ordf"}, {186,
"ordm"},
123 {248,
"oslash"}, {245,
"otilde"}, {8855,
"otimes"}, {246,
"ouml"},
124 {182,
"para"}, {8706,
"part"}, {8240,
"permil"}, {8869,
"perp"},
125 {966,
"phi"}, {960,
"pi"}, {982,
"piv"}, {177,
"plusmn"},
126 {8242,
"prime"}, {8719,
"prod"}, {8733,
"prop"}, {968,
"psi"},
127 {163,
"pund"}, {34,
"quot"}, {8658,
"rArr"}, {8730,
"radic"},
128 {9002,
"rang"}, {187,
"raquo"}, {8594,
"rarr"}, {8969,
"rceil"},
129 {8476,
"real"}, {174,
"reg"}, {8971,
"rfloor"}, {961,
"rho"},
130 {8207,
"rlm"}, {8250,
"rsaquo"}, {8217,
"rsquo"}, {353,
"saron"},
131 {8218,
"sbquo"}, {8901,
"sdot"}, {167,
"sect"}, {173,
"shy"},
132 {963,
"sigma"}, {962,
"sigmaf"}, {8764,
"sim"}, {9824,
"spades"},
133 {8834,
"sub"}, {8838,
"sube"}, {8721,
"sum"}, {8835,
"sup"},
134 {185,
"sup1"}, {178,
"sup2"}, {179,
"sup3"}, {8839,
"supe"},
135 {223,
"szlig"}, {964,
"tau"}, {8221,
"tdquo"}, {8756,
"there4"},
136 {952,
"theta"}, {977,
"thetasym"}, {8201,
"thinsp"}, {254,
"thorn"},
137 {732,
"tilde"}, {215,
"times"}, {8482,
"trade"}, {8657,
"uArr"},
138 {250,
"uacute"}, {8593,
"uarr"}, {251,
"ucirc"}, {249,
"ugrave"},
139 {168,
"uml"}, {978,
"upsih"}, {965,
"upsilon"}, {252,
"uuml"},
140 {8472,
"weierp"}, {958,
"xi"}, {253,
"yacute"}, {165,
"yen"},
141 {255,
"yuml"}, {950,
"zeta"}, {8205,
"zwj"}, {8204,
"zwnj"},
145const XFA_FMHtmlReserveCode kReservesForEncode[] = {
146 {34,
"quot"}, {38,
"amp"}, {39,
"apos"}, {60,
"lt"},
147 {62,
"gt"}, {160,
"nbsp"}, {161,
"iexcl"}, {162,
"cent"},
148 {163,
"pund"}, {164,
"current"}, {165,
"yen"}, {166,
"brvbar"},
149 {167,
"sect"}, {168,
"uml"}, {169,
"copy"}, {170,
"ordf"},
150 {171,
"laquo"}, {172,
"not"}, {173,
"shy"}, {174,
"reg"},
151 {175,
"macr"}, {176,
"deg"}, {177,
"plusmn"}, {178,
"sup2"},
152 {179,
"sup3"}, {180,
"acute"}, {181,
"micro"}, {182,
"para"},
153 {183,
"middot"}, {184,
"cedil"}, {185,
"sup1"}, {186,
"ordm"},
154 {187,
"raquo"}, {188,
"frac14"}, {189,
"frac12"}, {190,
"frac34"},
155 {191,
"iquest"}, {192,
"Agrave"}, {193,
"Aacute"}, {194,
"Acirc"},
156 {195,
"Atilde"}, {196,
"Auml"}, {197,
"Aring"}, {198,
"AElig"},
157 {199,
"Ccedil"}, {200,
"Egrave"}, {201,
"Eacute"}, {202,
"Ecirc"},
158 {203,
"Euml"}, {204,
"lgrave"}, {205,
"lacute"}, {206,
"lcirc"},
159 {207,
"luml"}, {208,
"ETH"}, {209,
"Ntilde"}, {210,
"Ograve"},
160 {211,
"Oacute"}, {212,
"Ocirc"}, {213,
"Otilde"}, {214,
"Ouml"},
161 {215,
"times"}, {216,
"Oslash"}, {217,
"Ugrave"}, {218,
"Uacute"},
162 {219,
"Ucirc"}, {220,
"Uuml"}, {221,
"Yacute"}, {222,
"THORN"},
163 {223,
"szlig"}, {224,
"agrave"}, {225,
"aacute"}, {226,
"acirc"},
164 {227,
"atilde"}, {228,
"auml"}, {229,
"aring"}, {230,
"aelig"},
165 {231,
"ccedil"}, {232,
"egrave"}, {233,
"eacute"}, {234,
"ecirc"},
166 {235,
"euml"}, {236,
"igrave"}, {237,
"iacute"}, {238,
"icirc"},
167 {239,
"iuml"}, {240,
"eth"}, {241,
"ntilde"}, {242,
"ograve"},
168 {243,
"oacute"}, {244,
"ocirc"}, {245,
"otilde"}, {246,
"ouml"},
169 {247,
"divide"}, {248,
"oslash"}, {249,
"ugrave"}, {250,
"uacute"},
170 {251,
"ucirc"}, {252,
"uuml"}, {253,
"yacute"}, {254,
"thorn"},
171 {255,
"yuml"}, {338,
"OElig"}, {339,
"oelig"}, {352,
"Scaron"},
172 {353,
"saron"}, {376,
"Yuml"}, {402,
"fnof"}, {710,
"circ"},
173 {732,
"tilde"}, {913,
"Alpha"}, {914,
"Beta"}, {915,
"Gamma"},
174 {916,
"Delta"}, {917,
"Epsilon"}, {918,
"Zeta"}, {919,
"Eta"},
175 {920,
"Theta"}, {921,
"lota"}, {922,
"Kappa"}, {923,
"Lambda"},
176 {924,
"Mu"}, {925,
"Nu"}, {926,
"Xi"}, {927,
"Omicron"},
177 {928,
"Pi"}, {929,
"Rho"}, {931,
"Sigma"}, {932,
"Tau"},
178 {933,
"Upsilon"}, {934,
"Phi"}, {935,
"Chi"}, {936,
"Psi"},
179 {937,
"Omega"}, {945,
"alpha"}, {946,
"beta"}, {947,
"gamma"},
180 {948,
"delta"}, {949,
"epsilon"}, {950,
"zeta"}, {951,
"eta"},
181 {952,
"theta"}, {953,
"iota"}, {954,
"kappa"}, {955,
"lambda"},
182 {956,
"mu"}, {957,
"nu"}, {958,
"xi"}, {959,
"omicron"},
183 {960,
"pi"}, {961,
"rho"}, {962,
"sigmaf"}, {963,
"sigma"},
184 {964,
"tau"}, {965,
"upsilon"}, {966,
"phi"}, {967,
"chi"},
185 {968,
"psi"}, {969,
"omega"}, {977,
"thetasym"}, {978,
"upsih"},
186 {982,
"piv"}, {8194,
"ensp"}, {8195,
"emsp"}, {8201,
"thinsp"},
187 {8204,
"zwnj"}, {8205,
"zwj"}, {8206,
"lrm"}, {8207,
"rlm"},
188 {8211,
"ndash"}, {8212,
"mdash"}, {8216,
"lsquo"}, {8217,
"rsquo"},
189 {8218,
"sbquo"}, {8220,
"ldquo"}, {8221,
"tdquo"}, {8222,
"bdquo"},
190 {8224,
"dagger"}, {8225,
"Dagger"}, {8226,
"bull"}, {8230,
"hellip"},
191 {8240,
"permil"}, {8242,
"prime"}, {8249,
"lsaquo"}, {8250,
"rsaquo"},
192 {8254,
"oline"}, {8260,
"frasl"}, {8364,
"euro"}, {8465,
"image"},
193 {8472,
"weierp"}, {8476,
"real"}, {8482,
"trade"}, {8501,
"alefsym"},
194 {8592,
"larr"}, {8593,
"uarr"}, {8594,
"rarr"}, {8595,
"darr"},
195 {8596,
"harr"}, {8629,
"crarr"}, {8656,
"lArr"}, {8657,
"uArr"},
196 {8658,
"rArr"}, {8659,
"dArr"}, {8660,
"hArr"}, {8704,
"forall"},
197 {8706,
"part"}, {8707,
"exist"}, {8709,
"empty"}, {8711,
"nabla"},
198 {8712,
"isin"}, {8713,
"notin"}, {8715,
"ni"}, {8719,
"prod"},
199 {8721,
"sum"}, {8722,
"minus"}, {8727,
"lowast"}, {8730,
"radic"},
200 {8733,
"prop"}, {8734,
"infin"}, {8736,
"ang"}, {8743,
"and"},
201 {8744,
"or"}, {8745,
"cap"}, {8746,
"cup"}, {8747,
"int"},
202 {8756,
"there4"}, {8764,
"sim"}, {8773,
"cong"}, {8776,
"asymp"},
203 {8800,
"ne"}, {8801,
"equiv"}, {8804,
"le"}, {8805,
"ge"},
204 {8834,
"sub"}, {8835,
"sup"}, {8836,
"nsub"}, {8838,
"sube"},
205 {8839,
"supe"}, {8853,
"oplus"}, {8855,
"otimes"}, {8869,
"perp"},
206 {8901,
"sdot"}, {8968,
"lceil"}, {8969,
"rceil"}, {8970,
"lfloor"},
207 {8971,
"rfloor"}, {9001,
"lang"}, {9002,
"rang"}, {9674,
"loz"},
208 {9824,
"spades"}, {9827,
"clubs"}, {9829,
"hearts"}, {9830,
"diams"},
212 {
kFuncTag,
"Abs", CFXJSE_FormCalcContext::Abs},
213 {
kFuncTag,
"Avg", CFXJSE_FormCalcContext::Avg},
214 {
kFuncTag,
"Ceil", CFXJSE_FormCalcContext::Ceil},
215 {
kFuncTag,
"Count", CFXJSE_FormCalcContext::Count},
216 {
kFuncTag,
"Floor", CFXJSE_FormCalcContext::Floor},
217 {
kFuncTag,
"Max", CFXJSE_FormCalcContext::Max},
218 {
kFuncTag,
"Min", CFXJSE_FormCalcContext::Min},
219 {
kFuncTag,
"Mod", CFXJSE_FormCalcContext::Mod},
220 {
kFuncTag,
"Round", CFXJSE_FormCalcContext::Round},
221 {
kFuncTag,
"Sum", CFXJSE_FormCalcContext::Sum},
222 {
kFuncTag,
"Date", CFXJSE_FormCalcContext::Date},
223 {
kFuncTag,
"Date2Num", CFXJSE_FormCalcContext::Date2Num},
224 {
kFuncTag,
"DateFmt", CFXJSE_FormCalcContext::DateFmt},
225 {
kFuncTag,
"IsoDate2Num", CFXJSE_FormCalcContext::IsoDate2Num},
226 {
kFuncTag,
"IsoTime2Num", CFXJSE_FormCalcContext::IsoTime2Num},
227 {
kFuncTag,
"LocalDateFmt", CFXJSE_FormCalcContext::LocalDateFmt},
228 {
kFuncTag,
"LocalTimeFmt", CFXJSE_FormCalcContext::LocalTimeFmt},
229 {
kFuncTag,
"Num2Date", CFXJSE_FormCalcContext::Num2Date},
230 {
kFuncTag,
"Num2GMTime", CFXJSE_FormCalcContext::Num2GMTime},
231 {
kFuncTag,
"Num2Time", CFXJSE_FormCalcContext::Num2Time},
232 {
kFuncTag,
"Time", CFXJSE_FormCalcContext::Time},
233 {
kFuncTag,
"Time2Num", CFXJSE_FormCalcContext::Time2Num},
234 {
kFuncTag,
"TimeFmt", CFXJSE_FormCalcContext::TimeFmt},
235 {
kFuncTag,
"Apr", CFXJSE_FormCalcContext::Apr},
236 {
kFuncTag,
"Cterm", CFXJSE_FormCalcContext::CTerm},
237 {
kFuncTag,
"FV", CFXJSE_FormCalcContext::FV},
238 {
kFuncTag,
"Ipmt", CFXJSE_FormCalcContext::IPmt},
239 {
kFuncTag,
"NPV", CFXJSE_FormCalcContext::NPV},
240 {
kFuncTag,
"Pmt", CFXJSE_FormCalcContext::Pmt},
241 {
kFuncTag,
"PPmt", CFXJSE_FormCalcContext::PPmt},
242 {
kFuncTag,
"PV", CFXJSE_FormCalcContext::PV},
243 {
kFuncTag,
"Rate", CFXJSE_FormCalcContext::Rate},
244 {
kFuncTag,
"Term", CFXJSE_FormCalcContext::Term},
245 {
kFuncTag,
"Choose", CFXJSE_FormCalcContext::Choose},
246 {
kFuncTag,
"Exists", CFXJSE_FormCalcContext::Exists},
247 {
kFuncTag,
"HasValue", CFXJSE_FormCalcContext::HasValue},
248 {
kFuncTag,
"Oneof", CFXJSE_FormCalcContext::Oneof},
249 {
kFuncTag,
"Within", CFXJSE_FormCalcContext::Within},
250 {
kFuncTag,
"If", CFXJSE_FormCalcContext::If},
251 {
kFuncTag,
"Eval", CFXJSE_FormCalcContext::Eval},
252 {
kFuncTag,
"Translate", CFXJSE_FormCalcContext::eval_translation},
253 {
kFuncTag,
"Ref", CFXJSE_FormCalcContext::Ref},
254 {
kFuncTag,
"UnitType", CFXJSE_FormCalcContext::UnitType},
255 {
kFuncTag,
"UnitValue", CFXJSE_FormCalcContext::UnitValue},
256 {
kFuncTag,
"At", CFXJSE_FormCalcContext::At},
257 {
kFuncTag,
"Concat", CFXJSE_FormCalcContext::Concat},
258 {
kFuncTag,
"Decode", CFXJSE_FormCalcContext::Decode},
259 {
kFuncTag,
"Encode", CFXJSE_FormCalcContext::Encode},
260 {
kFuncTag,
"Format", CFXJSE_FormCalcContext::Format},
261 {
kFuncTag,
"Left", CFXJSE_FormCalcContext::Left},
262 {
kFuncTag,
"Len", CFXJSE_FormCalcContext::Len},
263 {
kFuncTag,
"Lower", CFXJSE_FormCalcContext::Lower},
264 {
kFuncTag,
"Ltrim", CFXJSE_FormCalcContext::Ltrim},
265 {
kFuncTag,
"Parse", CFXJSE_FormCalcContext::Parse},
266 {
kFuncTag,
"Replace", CFXJSE_FormCalcContext::Replace},
267 {
kFuncTag,
"Right", CFXJSE_FormCalcContext::Right},
268 {
kFuncTag,
"Rtrim", CFXJSE_FormCalcContext::Rtrim},
269 {
kFuncTag,
"Space", CFXJSE_FormCalcContext::Space},
270 {
kFuncTag,
"Str", CFXJSE_FormCalcContext::Str},
271 {
kFuncTag,
"Stuff", CFXJSE_FormCalcContext::Stuff},
272 {
kFuncTag,
"Substr", CFXJSE_FormCalcContext::Substr},
273 {
kFuncTag,
"Uuid", CFXJSE_FormCalcContext::Uuid},
274 {
kFuncTag,
"Upper", CFXJSE_FormCalcContext::Upper},
275 {
kFuncTag,
"WordNum", CFXJSE_FormCalcContext::WordNum},
276 {
kFuncTag,
"Get", CFXJSE_FormCalcContext::Get},
277 {
kFuncTag,
"Post", CFXJSE_FormCalcContext::Post},
278 {
kFuncTag,
"Put", CFXJSE_FormCalcContext::Put},
279 {
kFuncTag,
"pos_op", CFXJSE_FormCalcContext::positive_operator},
280 {
kFuncTag,
"neg_op", CFXJSE_FormCalcContext::negative_operator},
281 {
kFuncTag,
"log_or_op", CFXJSE_FormCalcContext::logical_or_operator},
282 {
kFuncTag,
"log_and_op", CFXJSE_FormCalcContext::logical_and_operator},
283 {
kFuncTag,
"log_not_op", CFXJSE_FormCalcContext::logical_not_operator},
284 {
kFuncTag,
"eq_op", CFXJSE_FormCalcContext::equality_operator},
285 {
kFuncTag,
"neq_op", CFXJSE_FormCalcContext::notequality_operator},
286 {
kFuncTag,
"lt_op", CFXJSE_FormCalcContext::less_operator},
287 {
kFuncTag,
"le_op", CFXJSE_FormCalcContext::lessequal_operator},
288 {
kFuncTag,
"gt_op", CFXJSE_FormCalcContext::greater_operator},
289 {
kFuncTag,
"ge_op", CFXJSE_FormCalcContext::greaterequal_operator},
290 {
kFuncTag,
"plus_op", CFXJSE_FormCalcContext::plus_operator},
291 {
kFuncTag,
"minus_op", CFXJSE_FormCalcContext::minus_operator},
292 {
kFuncTag,
"mul_op", CFXJSE_FormCalcContext::multiple_operator},
293 {
kFuncTag,
"div_op", CFXJSE_FormCalcContext::divide_operator},
294 {
kFuncTag,
"asgn_val_op", CFXJSE_FormCalcContext::assign_value_operator},
295 {
kFuncTag,
"dot_acc", CFXJSE_FormCalcContext::dot_accessor},
296 {
kFuncTag,
"dotdot_acc", CFXJSE_FormCalcContext::dotdot_accessor},
297 {
kFuncTag,
"concat_obj", CFXJSE_FormCalcContext::concat_fm_object},
298 {
kFuncTag,
"is_obj", CFXJSE_FormCalcContext::is_fm_object},
299 {
kFuncTag,
"is_ary", CFXJSE_FormCalcContext::is_fm_array},
300 {
kFuncTag,
"get_val", CFXJSE_FormCalcContext::get_fm_value},
301 {
kFuncTag,
"get_jsobj", CFXJSE_FormCalcContext::get_fm_jsobj},
302 {
kFuncTag,
"var_filter", CFXJSE_FormCalcContext::fm_var_filter},
305const uint8_t kAltTableDate[] = {
306 255, 255, 255, 3, 9, 255, 255, 255, 255, 255, 255,
307 255, 2, 255, 255, 255, 255, 255, 255, 255, 255, 255,
308 255, 255, 1, 255, 255, 255, 255, 255, 255, 255, 255,
310static_assert(
std::size(kAltTableDate) == L'a' - L'A' + 1,
311 "Invalid kAltTableDate size.");
313const uint8_t kAltTableTime[] = {
314 14, 255, 255, 3, 9, 255, 255, 15, 255, 255, 255,
315 255, 6, 255, 255, 255, 255, 255, 7, 255, 255, 255,
316 255, 255, 1, 17, 255, 255, 255, 255, 255, 255, 255,
318static_assert(
std::size(kAltTableTime) == L'a' - L'A' + 1,
319 "Invalid kAltTableTime size.");
321void AlternateDateTimeSymbols(
WideString* pPattern,
324 const uint8_t* pAltTable = bIsDate ? kAltTableDate : kAltTableTime;
325 int32_t nLength = pPattern->GetLength();
326 bool bInConstRange =
false;
327 bool bEscape =
false;
330 while (i < nLength) {
331 wchar_t wc = (*pPattern)[i];
333 bInConstRange = !bInConstRange;
343 if (!bInConstRange && wc >= L'A' && wc <= L'a') {
344 uint8_t nAlt = pAltTable[wc - L'A'];
346 pPattern->SetAt(i, wsAltSymbols[nAlt]);
358 if (wsPattern.First(8).EqualsASCII(
"datetime")) {
361 if (wsPattern.First(4).EqualsASCII(
"date")) {
362 auto pos = wsPattern.Find(L"time");
363 if (pos.has_value() && pos.value() != 0) {
368 if (wsPattern.First(4).EqualsASCII(
"time")) {
371 if (wsPattern.First(4).EqualsASCII(
"text")) {
374 if (wsPattern.First(3).EqualsASCII(
"num")) {
375 if (wsPattern.Substr(4, 7).EqualsASCII(
"integer")) {
378 if (wsPattern.Substr(4, 7).EqualsASCII(
"decimal")) {
381 if (wsPattern.Substr(4, 8).EqualsASCII(
"currency")) {
384 if (wsPattern.Substr(4, 7).EqualsASCII(
"percent")) {
392 const wchar_t* pData = wsPattern.c_str();
393 int32_t iLength = wsPattern.GetLength();
395 bool bSingleQuotation =
false;
397 while (iIndex < iLength) {
398 wchar_t wsPatternChar = pData[iIndex];
399 if (wsPatternChar == 0x27) {
400 bSingleQuotation = !bSingleQuotation;
404 if (bSingleQuotation) {
409 if (wsPatternChar ==
'h' || wsPatternChar ==
'k') {
412 if (wsPatternChar ==
'x' || wsPatternChar ==
'o' ||
413 wsPatternChar ==
'0') {
416 if (wsPatternChar ==
'v' || wsPatternChar ==
'8' ||
417 wsPatternChar ==
'$') {
420 if (wsPatternChar ==
'y' || wsPatternChar ==
'j') {
422 wchar_t timePatternChar;
423 while (iIndex < iLength) {
424 timePatternChar = pData[iIndex];
425 if (timePatternChar == 0x27) {
426 bSingleQuotation = !bSingleQuotation;
430 if (!bSingleQuotation && timePatternChar ==
't') {
438 if (wsPatternChar ==
'a') {
440 }
else if (wsPatternChar ==
'z' || wsPatternChar ==
's' ||
441 wsPatternChar ==
'e' || wsPatternChar ==
',' ||
442 wsPatternChar ==
'.') {
447 return {
false, type};
456 CXFA_LocaleMgr* pMgr,
458 if (!bsLocale.IsEmpty())
466 if (!bsFormat.IsEmpty())
487ByteString GetLocalDateTimeFormat(CXFA_Document* pDoc,
493 LocaleIface* pLocale = LocaleFromString(pDoc, pMgr, bsLocale);
505bool IsWhitespace(
char c) {
506 return c == 0x20 || c == 0x09 || c == 0x0B || c == 0x0C || c == 0x0A ||
510bool IsPartOfNumber(
char ch) {
511 return isdigit(ch) || ch ==
'-' || ch ==
'.';
514bool IsPartOfNumberW(
wchar_t ch) {
519 std::array<uint8_t, 16> data;
520 FX_Random_GenerateMT(
fxcrt::reinterpret_span<uint32_t, uint8_t>(data));
521 data[6] = (data[6] & 0x0F) | 0x40;
526 pdfium::span<
char> pBuf = bsGUID.GetBuffer(40);
527 size_t out_index = 0;
528 for (size_t i = 0; i < 16; ++i, out_index += 2) {
529 if (bSeparator && (i == 4 || i == 6 || i == 8 || i == 10)) {
530 pBuf[out_index++] = L'-';
532 FXSYS_IntToTwoHexChars(data[i], &pBuf[out_index]);
535 bsGUID.ReleaseBuffer(bSeparator ? 36 : 32);
539void GetLocalTimeZone(int32_t* pHour, int32_t* pMin, int32_t* pSec) {
543 struct tm* pGmt = gmtime(&now);
545 *pHour = pLocal->tm_hour - pGmt->tm_hour;
546 *pMin = pLocal->tm_min - pGmt->tm_min;
547 *pSec = pLocal->tm_sec - pGmt->tm_sec;
550bool HTMLSTR2Code(
const WideString& pData, uint32_t* iCode) {
551 auto cmpFunc = [](
const XFA_FMHtmlReserveCode& iter,
ByteStringView val) {
552 return strcmp(val.unterminated_c_str(), iter.m_htmlReserve) > 0;
557 const XFA_FMHtmlReserveCode* result =
std::lower_bound(
558 std::begin(kReservesForDecode),
std::end(kReservesForDecode),
559 temp.AsStringView(), cmpFunc);
560 if (result !=
std::end(kReservesForDecode) &&
561 !strcmp(temp.c_str(), result->m_htmlReserve)) {
562 *iCode = result->m_uCode;
568bool HTMLCode2STR(uint32_t iCode,
WideString* wsHTMLReserve) {
569 auto cmpFunc = [](
const XFA_FMHtmlReserveCode iter,
const uint32_t& val) {
570 return iter.m_uCode < val;
572 const XFA_FMHtmlReserveCode* result =
573 std::lower_bound(
std::begin(kReservesForEncode),
574 std::end(kReservesForEncode), iCode, cmpFunc);
575 if (result !=
std::end(kReservesForEncode) && result->m_uCode == iCode) {
583 const wchar_t* pData = wsURL.c_str();
584 size_t iLen = wsURL.GetLength();
585 WideTextBuffer wsResultBuf;
587 for (size_t i = 0; i < iLen; ++i) {
588 wchar_t ch = pData[i];
614 const wchar_t* pData = wsHTML.c_str();
615 size_t iLen = wsHTML.GetLength();
616 WideTextBuffer wsResultBuf;
618 for (size_t i = 0; i < iLen; ++i) {
619 wchar_t ch = pData[i];
633 if (ch !=
'x' && ch !=
'X') {
640 while (ch !=
';' && i < iLen) {
656 size_t iStrIndex = 0;
657 while (ch !=
';' && i < iLen) {
659 szBuffer[iStrIndex++] = ch;
666 szBuffer[iStrIndex] = 0;
669 if (HTMLSTR2Code(szBuffer, &iData)) {
673 if (wcscmp(szBuffer, L"quot") == 0) {
675 }
else if (wcscmp(szBuffer, L"amp") == 0) {
677 }
else if (wcscmp(szBuffer, L"apos") == 0) {
679 }
else if (wcscmp(szBuffer, L"lt") == 0) {
681 }
else if (wcscmp(szBuffer, L"gt") == 0) {
691 return DecodeMLInternal(wsHTML,
true);
695 return DecodeMLInternal(wsXML,
false);
699 static constexpr char32_t kStrUnsafe[] = {
' ',
'<',
'>',
'"',
'#',
700 '%',
'{',
'}',
'|',
'\\',
701 '^',
'~',
'[',
']',
'`'};
702 static constexpr char32_t kStrReserved[] = {
';',
'/',
'?',
':',
706 WideTextBuffer wsResultBuf;
707 std::array<
wchar_t, 3> encode_buffer = {L'%'};
708 for (
char32_t ch : pdfium::CodePointView(wsURL.AsStringView())) {
709 if (ch <= 0x1f || (ch >= 0x7f && ch <= 0xff) ||
710 pdfium::Contains(kStrUnsafe, ch) ||
711 pdfium::Contains(kStrReserved, ch)) {
712 int32_t iIndex = ch / 16;
713 encode_buffer[1] = kStrCode[iIndex];
714 encode_buffer[2] = kStrCode[ch - iIndex * 16];
715 wsResultBuf << WideStringView(encode_buffer);
718 if (ch >= 0x20 && ch <= 0x7e) {
719 wsResultBuf.AppendChar(ch);
722 const wchar_t iRadix = 16;
724 while (ch >= iRadix) {
725 wchar_t tmp = kStrCode[ch % iRadix];
729 wsBuffer += kStrCode[ch];
730 int32_t iLen = wsBuffer.GetLength();
737 encode_buffer[1] =
'0';
738 encode_buffer[2] = wsBuffer[iLen - 1];
741 encode_buffer[1] = wsBuffer[iLen - 1];
742 encode_buffer[2] = wsBuffer[iLen - 2];
745 wsResultBuf << WideStringView(encode_buffer);
747 encode_buffer[1] = wsBuffer[iIndex];
748 encode_buffer[2] = wsBuffer[iIndex - 1];
750 wsResultBuf << WideStringView(encode_buffer);
758 std::array<
wchar_t, 8> encode_buffer;
759 encode_buffer[0] =
'&';
760 encode_buffer[1] =
'#';
761 encode_buffer[2] =
'x';
762 WideTextBuffer wsResultBuf;
763 for (
char32_t ch : pdfium::CodePointView(wsHTML.AsStringView())) {
764 WideString htmlReserve;
765 if (HTMLCode2STR(ch, &htmlReserve)) {
766 wsResultBuf.AppendChar(L'&');
767 wsResultBuf << htmlReserve;
768 wsResultBuf.AppendChar(L';');
769 }
else if (ch >= 32 && ch <= 126) {
770 wsResultBuf.AppendChar(
static_cast<
wchar_t>(ch));
771 }
else if (ch < 256) {
772 int32_t iIndex = ch / 16;
773 encode_buffer[3] = kStrCode[iIndex];
774 encode_buffer[4] = kStrCode[ch - iIndex * 16];
775 encode_buffer[5] =
';';
776 wsResultBuf << WideStringView(encode_buffer).First(6);
777 }
else if (ch < 65536) {
778 int32_t iBigByte = ch / 256;
779 int32_t iLittleByte = ch % 256;
780 encode_buffer[3] = kStrCode[iBigByte / 16];
781 encode_buffer[4] = kStrCode[iBigByte % 16];
782 encode_buffer[5] = kStrCode[iLittleByte / 16];
783 encode_buffer[6] = kStrCode[iLittleByte % 16];
784 encode_buffer[7] =
';';
785 wsResultBuf << WideStringView(encode_buffer).First(8);
795 WideTextBuffer wsResultBuf;
796 std::array<
wchar_t, 8> encode_buffer;
797 encode_buffer[0] =
'&';
798 encode_buffer[1] =
'#';
799 encode_buffer[2] =
'x';
800 for (
char32_t ch : pdfium::CodePointView(wsXML.AsStringView())) {
803 wsResultBuf.AppendChar(
'&');
804 wsResultBuf << WideStringView(L"quot");
805 wsResultBuf.AppendChar(
';');
808 wsResultBuf.AppendChar(
'&');
809 wsResultBuf << WideStringView(L"amp");
810 wsResultBuf.AppendChar(
';');
813 wsResultBuf.AppendChar(
'&');
814 wsResultBuf << WideStringView(L"apos");
815 wsResultBuf.AppendChar(
';');
818 wsResultBuf.AppendChar(
'&');
819 wsResultBuf << WideStringView(L"lt");
820 wsResultBuf.AppendChar(
';');
823 wsResultBuf.AppendChar(
'&');
824 wsResultBuf << WideStringView(L"gt");
825 wsResultBuf.AppendChar(
';');
828 if (ch >= 32 && ch <= 126) {
829 wsResultBuf.AppendChar(
static_cast<
wchar_t>(ch));
830 }
else if (ch < 256) {
831 int32_t iIndex = ch / 16;
832 encode_buffer[3] = kStrCode[iIndex];
833 encode_buffer[4] = kStrCode[ch - iIndex * 16];
834 encode_buffer[5] =
';';
835 wsResultBuf << WideStringView(encode_buffer).First(6);
836 }
else if (ch < 65536) {
837 int32_t iBigByte = ch / 256;
838 int32_t iLittleByte = ch % 256;
839 encode_buffer[3] = kStrCode[iBigByte / 16];
840 encode_buffer[4] = kStrCode[iBigByte % 16];
841 encode_buffer[5] = kStrCode[iLittleByte / 16];
842 encode_buffer[6] = kStrCode[iLittleByte % 16];
843 encode_buffer[7] =
';';
844 wsResultBuf << WideStringView(encode_buffer).First(8);
856 static const char kUnits[][6] = {
"zero",
"one",
"two",
"three",
"four",
857 "five",
"six",
"seven",
"eight",
"nine"};
858 static const char kCapUnits[][6] = {
"Zero",
"One",
"Two",
"Three",
"Four",
859 "Five",
"Six",
"Seven",
"Eight",
"Nine"};
860 static const char kTens[][10] = {
861 "Ten",
"Eleven",
"Twelve",
"Thirteen",
"Fourteen",
862 "Fifteen",
"Sixteen",
"Seventeen",
"Eighteen",
"Nineteen"};
863 static const char kLastTens[][8] = {
"Twenty",
"Thirty",
"Forty",
"Fifty",
864 "Sixty",
"Seventy",
"Eighty",
"Ninety"};
865 static const char kComm[][11] = {
" Hundred ",
" Thousand ",
" Million ",
866 " Billion ",
"Trillion"};
867 const char* pData = bsData.unterminated_c_str();
868 int32_t iLength = bsData.GetLength();
872 else if (iLength > 9)
874 else if (iLength > 6)
876 else if (iLength > 3)
879 int32_t iFirstCount = iLength % 3;
880 if (iFirstCount == 0)
886 if (iFirstCount == 3) {
887 if (pData[iIndex] !=
'0') {
888 strBuf
+= kCapUnits[pData[iIndex] -
'0'];
891 if (pData[iIndex + 1] ==
'0') {
892 strBuf
+= kCapUnits[pData[iIndex + 2] -
'0'];
894 if (pData[iIndex + 1] >
'1') {
895 strBuf
+= kLastTens[pData[iIndex + 1] -
'2'];
897 strBuf
+= kUnits[pData[iIndex + 2] -
'0'];
898 }
else if (pData[iIndex + 1] ==
'1') {
899 strBuf
+= kTens[pData[iIndex + 2] -
'0'];
900 }
else if (pData[iIndex + 1] ==
'0') {
901 strBuf
+= kCapUnits[pData[iIndex + 2] -
'0'];
905 }
else if (iFirstCount == 2) {
906 if (pData[iIndex] ==
'0') {
907 strBuf
+= kCapUnits[pData[iIndex + 1] -
'0'];
909 if (pData[iIndex] >
'1') {
910 strBuf
+= kLastTens[pData[iIndex] -
'2'];
912 strBuf
+= kUnits[pData[iIndex + 1] -
'0'];
913 }
else if (pData[iIndex] ==
'1') {
914 strBuf
+= kTens[pData[iIndex + 1] -
'0'];
915 }
else if (pData[iIndex] ==
'0') {
916 strBuf
+= kCapUnits[pData[iIndex + 1] -
'0'];
920 }
else if (iFirstCount == 1) {
921 strBuf
+= kCapUnits[pData[iIndex] -
'0'];
924 if (iLength > 3 && iFirstCount > 0) {
925 strBuf
+= kComm[iComm];
928 while (iIndex < iLength) {
929 if (pData[iIndex] !=
'0') {
930 strBuf
+= kCapUnits[pData[iIndex] -
'0'];
933 if (pData[iIndex + 1] ==
'0') {
934 strBuf
+= kCapUnits[pData[iIndex + 2] -
'0'];
936 if (pData[iIndex + 1] >
'1') {
937 strBuf
+= kLastTens[pData[iIndex + 1] -
'2'];
939 strBuf
+= kUnits[pData[iIndex + 2] -
'0'];
940 }
else if (pData[iIndex + 1] ==
'1') {
941 strBuf
+= kTens[pData[iIndex + 2] -
'0'];
942 }
else if (pData[iIndex + 1] ==
'0') {
943 strBuf
+= kCapUnits[pData[iIndex + 2] -
'0'];
946 if (iIndex < iLength - 3) {
947 strBuf
+= kComm[iComm];
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);
1082 return FXSYS_atoi(bsValue.c_str());
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);
1126std::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 std::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) {
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);
1235 return v8::Local<v8::Value>();
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() ||
1247 maybeResult.value().objects.empty()) {
1248 return v8::Local<v8::Value>();
1250 return pScriptContext->GetOrCreateJSBindingFromMap(
1251 maybeResult.value().objects.front().Get());
1256 v8::Local<v8::Value> pRefValue,
1259 bool bHasNoResolveName) {
1262 return std::nullopt;
1264 v8::Isolate* pIsolate = ToFormCalcContext(pHostObject)->GetIsolate();
1276 return std::nullopt;
1278 if (bHasNoResolveName) {
1282 pXFANode->JSObject()->TryAttribute(XFA_Attribute::Name,
false);
1283 if (ret.has_value())
1284 wsName = ret.value();
1286 if (wsName.IsEmpty())
1289 wsSomExpression
= wsName
+ wsSomExpression;
1292 dwFlags = (bsSomExp ==
"*")
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",
1369void CFXJSE_FormCalcContext::Abs(
1371 const v8::FunctionCallbackInfo<v8::Value>& info) {
1372 if (info.Length() != 1) {
1373 ToFormCalcContext(pThis)->ThrowParamCountMismatchException(
"Abs");
1377 if (ValueIsNull(info.GetIsolate(), info[0])) {
1378 info.GetReturnValue().SetNull();
1381 double dValue = ValueToDouble(info.GetIsolate(), info[0]);
1385 info.GetReturnValue().Set(dValue);
1389void CFXJSE_FormCalcContext::Avg(
1391 const v8::FunctionCallbackInfo<v8::Value>& info) {
1392 uint32_t uCount = 0;
1394 auto fn = [&uCount, &dSum](
v8::Isolate* pIsolate,
1395 v8::Local<v8::Value> pValue) {
1396 dSum += ValueToDouble(pIsolate, pValue);
1399 if (!ToFormCalcContext(pThis)->ApplyToExpansion(fn, info,
false))
1403 info.GetReturnValue().SetNull();
1406 info.GetReturnValue().Set(dSum / uCount);
1410void CFXJSE_FormCalcContext::Ceil(
1412 const v8::FunctionCallbackInfo<v8::Value>& info) {
1413 if (info.Length() != 1) {
1414 ToFormCalcContext(pThis)->ThrowParamCountMismatchException(
"Ceil");
1418 v8::Local<v8::Value> argValue = GetSimpleValue(info, 0);
1419 if (ValueIsNull(info.GetIsolate(), argValue)) {
1420 info.GetReturnValue().SetNull();
1424 info.GetReturnValue().Set(ceil(ValueToFloat(info.GetIsolate(), argValue)));
1428void CFXJSE_FormCalcContext::Count(
1430 const v8::FunctionCallbackInfo<v8::Value>& info) {
1431 uint32_t iCount = 0;
1432 auto fn = [&iCount](
v8::Isolate* pIsolate, v8::Local<v8::Value> pvalue) {
1435 if (!ToFormCalcContext(pThis)->ApplyToExpansion(fn, info,
true))
1438 info.GetReturnValue().Set(iCount);
1442void CFXJSE_FormCalcContext::Floor(
1444 const v8::FunctionCallbackInfo<v8::Value>& info) {
1445 if (info.Length() != 1) {
1446 ToFormCalcContext(pThis)->ThrowParamCountMismatchException(
"Floor");
1450 v8::Local<v8::Value> argValue = GetSimpleValue(info, 0);
1451 if (ValueIsNull(info.GetIsolate(), argValue)) {
1452 info.GetReturnValue().SetNull();
1456 info.GetReturnValue().Set(floor(ValueToFloat(info.GetIsolate(), argValue)));
1460void CFXJSE_FormCalcContext::Max(
1462 const v8::FunctionCallbackInfo<v8::Value>& info) {
1463 uint32_t uCount = 0;
1464 double dMaxValue = 0.0;
1465 auto fn = [&uCount, &dMaxValue](
v8::Isolate* pIsolate,
1466 v8::Local<v8::Value> pValue) {
1468 double dValue = ValueToDouble(pIsolate, pValue);
1469 dMaxValue = uCount == 1 ? dValue :
std::max(dMaxValue, dValue);
1471 if (!ToFormCalcContext(pThis)->ApplyToExpansion(fn, info,
true))
1475 info.GetReturnValue().SetNull();
1478 info.GetReturnValue().Set(dMaxValue);
1482void CFXJSE_FormCalcContext::Min(
1484 const v8::FunctionCallbackInfo<v8::Value>& info) {
1485 uint32_t uCount = 0;
1486 double dMinValue = 0.0;
1487 auto fn = [&uCount, &dMinValue](
v8::Isolate* pIsolate,
1488 v8::Local<v8::Value> pValue) {
1490 double dValue = ValueToDouble(pIsolate, pValue);
1491 dMinValue = uCount == 1 ? dValue :
std::min(dMinValue, dValue);
1493 if (!ToFormCalcContext(pThis)->ApplyToExpansion(fn, info,
true))
1497 info.GetReturnValue().SetNull();
1500 info.GetReturnValue().Set(dMinValue);
1504void CFXJSE_FormCalcContext::Mod(
1506 const v8::FunctionCallbackInfo<v8::Value>& info) {
1507 CFXJSE_FormCalcContext* pContext = ToFormCalcContext(pThis);
1508 if (info.Length() != 2) {
1509 pContext->ThrowParamCountMismatchException(
"Mod");
1514 info.GetReturnValue().SetNull();
1518 std::optional<
double> maybe_dividend =
1519 ExtractDouble(info.GetIsolate(), info[0]);
1520 std::optional<
double> maybe_divisor =
1521 ExtractDouble(info.GetIsolate(), info[1]);
1522 if (!maybe_dividend.has_value() || !maybe_divisor.has_value()) {
1523 pContext->ThrowArgumentMismatchException();
1527 double dividend = maybe_dividend.value();
1528 double divisor = maybe_divisor.value();
1529 if (divisor == 0.0) {
1530 pContext->ThrowDivideByZeroException();
1534 info.GetReturnValue().Set(dividend -
1535 divisor *
static_cast<int32_t>(dividend / divisor));
1539void CFXJSE_FormCalcContext::Round(
1541 const v8::FunctionCallbackInfo<v8::Value>& info) {
1542 CFXJSE_FormCalcContext* pContext = ToFormCalcContext(pThis);
1543 int32_t argc = info.Length();
1544 if (argc < 1 || argc > 2) {
1545 pContext->ThrowParamCountMismatchException(
"Round");
1550 info.GetReturnValue().SetNull();
1554 std::optional<
double> maybe_value = ExtractDouble(info.GetIsolate(), info[0]);
1555 if (!maybe_value.has_value()) {
1556 pContext->ThrowArgumentMismatchException();
1560 double dValue = maybe_value.value();
1561 uint8_t uPrecision = 0;
1564 info.GetReturnValue().SetNull();
1567 std::optional<
double> maybe_precision =
1568 ExtractDouble(info.GetIsolate(), info[1]);
1569 if (!maybe_precision.has_value()) {
1570 pContext->ThrowArgumentMismatchException();
1573 double dPrecision = maybe_precision.value();
1574 uPrecision =
static_cast<uint8_t>(
std::clamp(dPrecision, 0.0, 12.0));
1578 info.GetReturnValue().Set(decimalValue
.ToDouble());
1582void CFXJSE_FormCalcContext::Sum(
1584 const v8::FunctionCallbackInfo<v8::Value>& info) {
1585 uint32_t uCount = 0;
1587 auto fn = [&uCount, &dSum](
v8::Isolate* pIsolate,
1588 v8::Local<v8::Value> pValue) {
1590 dSum += ValueToDouble(pIsolate, pValue);
1592 if (!ToFormCalcContext(pThis)->ApplyToExpansion(fn, info,
true))
1596 info.GetReturnValue().SetNull();
1599 info.GetReturnValue().Set(dSum);
1603void CFXJSE_FormCalcContext::Date(
1605 const v8::FunctionCallbackInfo<v8::Value>& info) {
1606 if (info.Length() != 0) {
1607 ToFormCalcContext(pThis)->ThrowParamCountMismatchException(
"Date");
1613 struct tm* pTmStruct = gmtime(¤tTime);
1615 info.GetReturnValue().Set(DateString2Num(
1617 pTmStruct->tm_mon + 1
, pTmStruct->tm_mday
)
1622void CFXJSE_FormCalcContext::Date2Num(
1624 const v8::FunctionCallbackInfo<v8::Value>& info) {
1625 int32_t argc = info.Length();
1626 if (argc < 1 || argc > 3) {
1627 ToFormCalcContext(pThis)->ThrowParamCountMismatchException(
"Date2Num");
1631 v8::Local<v8::Value> dateValue = GetSimpleValue(info, 0);
1632 if (ValueIsNull(info.GetIsolate(), dateValue)) {
1633 info.GetReturnValue().SetNull();
1637 ByteString bsDate = ValueToUTF8String(info.GetIsolate(), dateValue);
1640 v8::Local<v8::Value> formatValue = GetSimpleValue(info, 1);
1641 if (ValueIsNull(info.GetIsolate(), formatValue)) {
1642 info.GetReturnValue().SetNull();
1645 bsFormat = ValueToUTF8String(info.GetIsolate(), formatValue);
1650 v8::Local<v8::Value> localeValue = GetSimpleValue(info, 2);
1651 if (ValueIsNull(info.GetIsolate(), localeValue)) {
1652 info.GetReturnValue().SetNull();
1655 bsLocale = ValueToUTF8String(info.GetIsolate(), localeValue);
1660 bsLocale.AsStringView()
);
1661 info.GetReturnValue().Set(DateString2Num(bsIsoDate.AsStringView()));
1665void CFXJSE_FormCalcContext::DateFmt(
1667 const v8::FunctionCallbackInfo<v8::Value>& info) {
1668 int32_t argc = info.Length();
1670 ToFormCalcContext(pThis)->ThrowParamCountMismatchException(
"Date2Num");
1676 v8::Local<v8::Value> infotyle = GetSimpleValue(info, 0);
1677 if (fxv8::IsNull(infotyle)) {
1678 info.GetReturnValue().SetNull();
1682 iStyle =
static_cast<int32_t>(ValueToFloat(info.GetIsolate(), infotyle));
1683 if (iStyle < 0 || iStyle > 4)
1689 v8::Local<v8::Value> argLocale = GetSimpleValue(info, 1);
1690 if (fxv8::IsNull(argLocale)) {
1691 info.GetReturnValue().SetNull();
1694 bsLocale = ValueToUTF8String(info.GetIsolate(), argLocale);
1699 info.GetReturnValue().Set(
1700 fxv8::NewStringHelper(info.GetIsolate(), bsFormat.AsStringView()));
1704void CFXJSE_FormCalcContext::IsoDate2Num(
1706 const v8::FunctionCallbackInfo<v8::Value>& info) {
1707 if (info.Length() != 1) {
1708 ToFormCalcContext(pThis)->ThrowParamCountMismatchException(
"IsoDate2Num");
1711 v8::Local<v8::Value> argOne = GetSimpleValue(info, 0);
1712 if (fxv8::IsNull(argOne)) {
1713 info.GetReturnValue().SetNull();
1716 ByteString bsArg = ValueToUTF8String(info.GetIsolate(), argOne);
1717 info.GetReturnValue().Set(DateString2Num(bsArg.AsStringView()));
1721void CFXJSE_FormCalcContext::IsoTime2Num(
1723 const v8::FunctionCallbackInfo<v8::Value>& info) {
1724 CFXJSE_FormCalcContext* pContext = ToFormCalcContext(pThis);
1725 if (info.Length() != 1) {
1726 pContext->ThrowParamCountMismatchException(
"IsoTime2Num");
1730 v8::Local<v8::Value> argOne = GetSimpleValue(info, 0);
1731 if (ValueIsNull(info.GetIsolate(), argOne)) {
1732 info.GetReturnValue().SetNull();
1738 ByteString bsArg = ValueToUTF8String(info.GetIsolate(), argOne);
1739 auto pos = bsArg.Find(
'T', 0);
1740 if (!pos.has_value() || pos.value() == bsArg.GetLength() - 1) {
1741 info.GetReturnValue().Set(0);
1744 bsArg = bsArg.Last(bsArg.GetLength() - (pos.value() + 1));
1749 info.GetReturnValue().Set(0);
1761 int32_t mins = hour * 60 + min;
1770 info.GetReturnValue().Set(hour * 3600000 + min * 60000 + second * 1000 +
1775void CFXJSE_FormCalcContext::LocalDateFmt(
1777 const v8::FunctionCallbackInfo<v8::Value>& info) {
1778 int32_t argc = info.Length();
1780 ToFormCalcContext(pThis)->ThrowParamCountMismatchException(
"LocalDateFmt");
1786 v8::Local<v8::Value> infotyle = GetSimpleValue(info, 0);
1787 if (fxv8::IsNull(infotyle)) {
1788 info.GetReturnValue().SetNull();
1791 iStyle =
static_cast<int32_t>(ValueToFloat(info.GetIsolate(), infotyle));
1792 if (iStyle > 4 || iStyle < 0)
1798 v8::Local<v8::Value> argLocale = GetSimpleValue(info, 1);
1799 if (fxv8::IsNull(argLocale)) {
1800 info.GetReturnValue().SetNull();
1803 bsLocale = ValueToUTF8String(info.GetIsolate(), argLocale);
1808 info.GetReturnValue().Set(
1809 fxv8::NewStringHelper(info.GetIsolate(), bsFormat.AsStringView()));
1813void CFXJSE_FormCalcContext::LocalTimeFmt(
1815 const v8::FunctionCallbackInfo<v8::Value>& info) {
1816 int32_t argc = info.Length();
1818 ToFormCalcContext(pThis)->ThrowParamCountMismatchException(
"LocalTimeFmt");
1824 v8::Local<v8::Value> infotyle = GetSimpleValue(info, 0);
1825 if (fxv8::IsNull(infotyle)) {
1826 info.GetReturnValue().SetNull();
1829 iStyle =
static_cast<int32_t>(ValueToFloat(info.GetIsolate(), infotyle));
1830 if (iStyle > 4 || iStyle < 0)
1836 v8::Local<v8::Value> argLocale = GetSimpleValue(info, 1);
1837 if (fxv8::IsNull(argLocale)) {
1838 info.GetReturnValue().SetNull();
1841 bsLocale = ValueToUTF8String(info.GetIsolate(), argLocale);
1846 info.GetReturnValue().Set(
1847 fxv8::NewStringHelper(info.GetIsolate(), bsFormat.AsStringView()));
1851void CFXJSE_FormCalcContext::Num2Date(
1853 const v8::FunctionCallbackInfo<v8::Value>& info) {
1854 int32_t argc = info.Length();
1855 if (argc < 1 || argc > 3) {
1856 ToFormCalcContext(pThis)->ThrowParamCountMismatchException(
"Num2Date");
1860 v8::Local<v8::Value> dateValue = GetSimpleValue(info, 0);
1861 if (ValueIsNull(info.GetIsolate(), dateValue)) {
1862 info.GetReturnValue().SetNull();
1866 static_cast<int32_t>(ValueToFloat(info.GetIsolate(), dateValue));
1868 info.GetReturnValue().SetNull();
1874 v8::Local<v8::Value> formatValue = GetSimpleValue(info, 1);
1875 if (ValueIsNull(info.GetIsolate(), formatValue)) {
1876 info.GetReturnValue().SetNull();
1879 bsFormat = ValueToUTF8String(info.GetIsolate(), formatValue);
1884 v8::Local<v8::Value> localeValue = GetSimpleValue(info, 2);
1885 if (ValueIsNull(info.GetIsolate(), localeValue)) {
1886 info.GetReturnValue().SetNull();
1889 bsLocale = ValueToUTF8String(info.GetIsolate(), localeValue);
1892 int32_t iYear = 1900;
1898 if ((!((iYear + i) % 4) && ((iYear + i) % 100)) || !((iYear + i) % 400)) {
1908 iDay +=
static_cast<int32_t>(dDate) - 1;
1921 iDay +=
static_cast<int32_t>(dDate) - 1;
1925 }
else if (iMonth < 8) {
1926 if ((iMonth % 2 == 0)) {
1936 iDay +=
static_cast<int32_t>(dDate) - 1;
1949 iDay +=
static_cast<int32_t>(dDate) - 1;
1954 if (iMonth % 2 != 0) {
1964 iDay +=
static_cast<int32_t>(dDate) - 1;
1977 iDay +=
static_cast<int32_t>(dDate) - 1;
1987 bsFormat.AsStringView()
, bsLocale.AsStringView()
);
1988 info.GetReturnValue().Set(
1989 fxv8::NewStringHelper(info.GetIsolate(), bsLocalDate.AsStringView()));
1993void CFXJSE_FormCalcContext::Num2GMTime(
1995 const v8::FunctionCallbackInfo<v8::Value>& info) {
1996 int32_t argc = info.Length();
1997 if (argc < 1 || argc > 3) {
1998 ToFormCalcContext(pThis)->ThrowParamCountMismatchException(
"Num2GMTime");
2002 v8::Local<v8::Value> timeValue = GetSimpleValue(info, 0);
2003 if (fxv8::IsNull(timeValue)) {
2004 info.GetReturnValue().SetNull();
2008 static_cast<int32_t>(ValueToFloat(info.GetIsolate(), timeValue));
2009 if (abs(iTime) < 1.0) {
2010 info.GetReturnValue().SetNull();
2016 v8::Local<v8::Value> formatValue = GetSimpleValue(info, 1);
2017 if (fxv8::IsNull(formatValue)) {
2018 info.GetReturnValue().SetNull();
2021 bsFormat = ValueToUTF8String(info.GetIsolate(), formatValue);
2026 v8::Local<v8::Value> localeValue = GetSimpleValue(info, 2);
2027 if (fxv8::IsNull(localeValue)) {
2028 info.GetReturnValue().SetNull();
2031 bsLocale = ValueToUTF8String(info.GetIsolate(), localeValue);
2035 bsLocale.AsStringView()
, true);
2036 info.GetReturnValue().Set(
2037 fxv8::NewStringHelper(info.GetIsolate(), bsGMTTime.AsStringView()));
2041void CFXJSE_FormCalcContext::Num2Time(
2043 const v8::FunctionCallbackInfo<v8::Value>& info) {
2044 int32_t argc = info.Length();
2045 if (argc < 1 || argc > 3) {
2046 ToFormCalcContext(pThis)->ThrowParamCountMismatchException(
"Num2Time");
2050 v8::Local<v8::Value> timeValue = GetSimpleValue(info, 0);
2051 if (fxv8::IsNull(timeValue)) {
2052 info.GetReturnValue().SetNull();
2055 float fTime = ValueToFloat(info.GetIsolate(), timeValue);
2056 if (fabs(fTime) < 1.0) {
2057 info.GetReturnValue().SetNull();
2063 v8::Local<v8::Value> formatValue = GetSimpleValue(info, 1);
2064 if (fxv8::IsNull(formatValue)) {
2065 info.GetReturnValue().SetNull();
2068 bsFormat = ValueToUTF8String(info.GetIsolate(), formatValue);
2073 v8::Local<v8::Value> localeValue = GetSimpleValue(info, 2);
2074 if (fxv8::IsNull(localeValue)) {
2075 info.GetReturnValue().SetNull();
2078 bsLocale = ValueToUTF8String(info.GetIsolate(), localeValue);
2082 Num2AllTime(pThis
, static_cast<int32_t>(fTime)
, bsFormat.AsStringView()
,
2083 bsLocale.AsStringView()
, false);
2084 info.GetReturnValue().Set(
2085 fxv8::NewStringHelper(info.GetIsolate(), bsLocalTime.AsStringView()));
2089void CFXJSE_FormCalcContext::Time(
2091 const v8::FunctionCallbackInfo<v8::Value>& info) {
2092 if (info.Length() != 0) {
2093 ToFormCalcContext(pThis)->ThrowParamCountMismatchException(
"Time");
2099 struct tm* pGmt = gmtime(&now);
2100 info.GetReturnValue().Set(
2101 (pGmt->tm_hour * 3600 + pGmt->tm_min * 60 + pGmt->tm_sec) * 1000);
2105void CFXJSE_FormCalcContext::Time2Num(
2107 const v8::FunctionCallbackInfo<v8::Value>& info) {
2108 int32_t argc = info.Length();
2109 if (argc < 1 || argc > 3) {
2110 ToFormCalcContext(pThis)->ThrowParamCountMismatchException(
"Time2Num");
2115 v8::Local<v8::Value> timeValue = GetSimpleValue(info, 0);
2116 if (ValueIsNull(info.GetIsolate(), timeValue)) {
2117 info.GetReturnValue().SetNull();
2120 bsTime = ValueToUTF8String(info.GetIsolate(), timeValue);
2124 v8::Local<v8::Value> formatValue = GetSimpleValue(info, 1);
2125 if (ValueIsNull(info.GetIsolate(), formatValue)) {
2126 info.GetReturnValue().SetNull();
2129 bsFormat = ValueToUTF8String(info.GetIsolate(), formatValue);
2134 v8::Local<v8::Value> localeValue = GetSimpleValue(info, 2);
2135 if (ValueIsNull(info.GetIsolate(), localeValue)) {
2136 info.GetReturnValue().SetNull();
2139 bsLocale = ValueToUTF8String(info.GetIsolate(), localeValue);
2145 if (!bsLocale.IsEmpty()) {
2155 if (bsFormat.IsEmpty()) {
2161 wsFormat
= L"time{"
+ wsFormat
+ L"}";
2164 wsFormat, pLocale, pMgr);
2166 info.GetReturnValue().Set(0);
2176 constexpr int kMinutesInDay = 24 * 60;
2177 int32_t minutes_with_tz =
2179 minutes_with_tz %= kMinutesInDay;
2180 if (minutes_with_tz < 0)
2181 minutes_with_tz += kMinutesInDay;
2183 hour = minutes_with_tz / 60;
2184 minute = minutes_with_tz % 60;
2185 info.GetReturnValue().Set(hour * 3600000 + minute * 60000 + second * 1000 +
2190void CFXJSE_FormCalcContext::TimeFmt(
2192 const v8::FunctionCallbackInfo<v8::Value>& info) {
2193 int32_t argc = info.Length();
2195 ToFormCalcContext(pThis)->ThrowParamCountMismatchException(
"TimeFmt");
2201 v8::Local<v8::Value> infotyle = GetSimpleValue(info, 0);
2202 if (fxv8::IsNull(infotyle)) {
2203 info.GetReturnValue().SetNull();
2206 iStyle =
static_cast<int32_t>(ValueToFloat(info.GetIsolate(), infotyle));
2207 if (iStyle > 4 || iStyle < 0)
2213 v8::Local<v8::Value> argLocale = GetSimpleValue(info, 1);
2214 if (fxv8::IsNull(argLocale)) {
2215 info.GetReturnValue().SetNull();
2218 bsLocale = ValueToUTF8String(info.GetIsolate(), argLocale);
2223 info.GetReturnValue().Set(
2224 fxv8::NewStringHelper(info.GetIsolate(), bsFormat.AsStringView()));
2241 WideString wsFormat = FormatFromString(pLocale, bsFormat);
2265 WideString wsFormat = FormatFromString(pLocale, bsFormat);
2288 L"time{", FormatFromString(pLocale, bsFormat).AsStringView(), L"}"};
2306 return GetLocalDateTimeFormat(pDoc, iStyle, bsLocale, bStandard,
2319 return GetLocalDateTimeFormat(pDoc, iStyle, bsLocale, bStandard,
2348 iHour =
static_cast<
int>(iTime) / 3600000;
2349 iMin = (
static_cast<
int>(iTime) - iHour * 3600000) / 60000;
2350 iSec = (
static_cast<
int>(iTime) - iHour * 3600000 - iMin * 60000) / 1000;
2356 GetLocalTimeZone(&iZoneHour, &iZoneMin, &iZoneSec);
2365 bsFormat
, bsLocale
);
2369void CFXJSE_FormCalcContext::Apr(
2371 const v8::FunctionCallbackInfo<v8::Value>& info) {
2372 CFXJSE_FormCalcContext* pContext = ToFormCalcContext(pThis);
2373 if (info.Length() != 3) {
2374 pContext->ThrowParamCountMismatchException(
"Apr");
2378 v8::Local<v8::Value> argOne = GetSimpleValue(info, 0);
2379 v8::Local<v8::Value> argTwo = GetSimpleValue(info, 1);
2380 v8::Local<v8::Value> argThree = GetSimpleValue(info, 2);
2381 if (ValueIsNull(info.GetIsolate(), argOne) ||
2382 ValueIsNull(info.GetIsolate(), argTwo) ||
2383 ValueIsNull(info.GetIsolate(), argThree)) {
2384 info.GetReturnValue().SetNull();
2388 double nPrincipal = ValueToDouble(info.GetIsolate(), argOne);
2389 double nPayment = ValueToDouble(info.GetIsolate(), argTwo);
2390 int nPeriods = GetValidatedPaymentPeriods(info.GetIsolate(), argThree);
2391 if (nPrincipal <= 0 || nPayment <= 0 || nPeriods == 0) {
2392 pContext->ThrowArgumentMismatchException();
2396 double r = 2 * (nPeriods * nPayment - nPrincipal) / (nPeriods * nPrincipal);
2398 for (int32_t i = 0; i < nPeriods; ++i)
2401 double nRet = r * nTemp / (nTemp - 1) - nPayment / nPrincipal;
2402 while (fabs(nRet) > kFinancialPrecision) {
2403 double nDerivative =
2404 ((nTemp + r * nPeriods * (nTemp / (1 + r))) * (nTemp - 1) -
2405 (r * nTemp * nPeriods * (nTemp / (1 + r)))) /
2406 ((nTemp - 1) * (nTemp - 1));
2407 if (nDerivative == 0) {
2408 info.GetReturnValue().SetNull();
2412 r = r - nRet / nDerivative;
2414 for (int32_t i = 0; i < nPeriods; ++i) {
2417 nRet = r * nTemp / (nTemp - 1) - nPayment / nPrincipal;
2419 info.GetReturnValue().Set(r * 12);
2423void CFXJSE_FormCalcContext::CTerm(
2425 const v8::FunctionCallbackInfo<v8::Value>& info) {
2426 CFXJSE_FormCalcContext* pContext = ToFormCalcContext(pThis);
2427 if (info.Length() != 3) {
2428 pContext->ThrowParamCountMismatchException(
"CTerm");
2432 v8::Local<v8::Value> argOne = GetSimpleValue(info, 0);
2433 v8::Local<v8::Value> argTwo = GetSimpleValue(info, 1);
2434 v8::Local<v8::Value> argThree = GetSimpleValue(info, 2);
2435 if (ValueIsNull(info.GetIsolate(), argOne) ||
2436 ValueIsNull(info.GetIsolate(), argTwo) ||
2437 ValueIsNull(info.GetIsolate(), argThree)) {
2438 info.GetReturnValue().SetNull();
2442 float nRate = ValueToFloat(info.GetIsolate(), argOne);
2443 float nFutureValue = ValueToFloat(info.GetIsolate(), argTwo);
2444 float nInitAmount = ValueToFloat(info.GetIsolate(), argThree);
2445 if ((nRate <= 0) || (nFutureValue <= 0) || (nInitAmount <= 0)) {
2446 pContext->ThrowArgumentMismatchException();
2450 info.GetReturnValue().Set(log((
float)(nFutureValue / nInitAmount)) /
2451 log((
float)(1 + nRate)));
2455void CFXJSE_FormCalcContext::FV(
2457 const v8::FunctionCallbackInfo<v8::Value>& info) {
2458 CFXJSE_FormCalcContext* pContext = ToFormCalcContext(pThis);
2459 if (info.Length() != 3) {
2460 pContext->ThrowParamCountMismatchException(
"FV");
2464 v8::Local<v8::Value> argOne = GetSimpleValue(info, 0);
2465 v8::Local<v8::Value> argTwo = GetSimpleValue(info, 1);
2466 v8::Local<v8::Value> argThree = GetSimpleValue(info, 2);
2467 if (ValueIsNull(info.GetIsolate(), argOne) ||
2468 ValueIsNull(info.GetIsolate(), argTwo) ||
2469 ValueIsNull(info.GetIsolate(), argThree)) {
2470 info.GetReturnValue().SetNull();
2474 double nAmount = ValueToDouble(info.GetIsolate(), argOne);
2475 double nRate = ValueToDouble(info.GetIsolate(), argTwo);
2476 int nPeriods = GetValidatedPaymentPeriods(info.GetIsolate(), argThree);
2477 if (nAmount <= 0 || nRate < 0 || nPeriods == 0) {
2478 pContext->ThrowArgumentMismatchException();
2485 for (
int i = 0; i < nPeriods; ++i) {
2488 dResult = nAmount * (nTemp - 1) / nRate;
2490 dResult = nAmount * nPeriods;
2493 info.GetReturnValue().Set(dResult);
2497void CFXJSE_FormCalcContext::IPmt(
2499 const v8::FunctionCallbackInfo<v8::Value>& info) {
2500 CFXJSE_FormCalcContext* pContext = ToFormCalcContext(pThis);
2501 if (info.Length() != 5) {
2502 pContext->ThrowParamCountMismatchException(
"IPmt");
2506 v8::Local<v8::Value> argOne = GetSimpleValue(info, 0);
2507 v8::Local<v8::Value> argTwo = GetSimpleValue(info, 1);
2508 v8::Local<v8::Value> argThree = GetSimpleValue(info, 2);
2509 v8::Local<v8::Value> argFour = GetSimpleValue(info, 3);
2510 v8::Local<v8::Value> argFive = GetSimpleValue(info, 4);
2511 if (ValueIsNull(info.GetIsolate(), argOne) ||
2512 ValueIsNull(info.GetIsolate(), argTwo) ||
2513 ValueIsNull(info.GetIsolate(), argThree) ||
2514 ValueIsNull(info.GetIsolate(), argFour) ||
2515 ValueIsNull(info.GetIsolate(), argFive)) {
2516 info.GetReturnValue().SetNull();
2520 float nPrincipalAmount = ValueToFloat(info.GetIsolate(), argOne);
2521 float nRate = ValueToFloat(info.GetIsolate(), argTwo);
2522 float nPayment = ValueToFloat(info.GetIsolate(), argThree);
2523 float nFirstMonth = ValueToFloat(info.GetIsolate(), argFour);
2524 float nNumberOfMonths = ValueToFloat(info.GetIsolate(), argFive);
2525 if ((nPrincipalAmount <= 0) || (nRate <= 0) || (nPayment <= 0) ||
2526 (nFirstMonth < 0) || (nNumberOfMonths < 0)) {
2527 pContext->ThrowArgumentMismatchException();
2531 float nRateOfMonth = nRate / 12;
2532 int32_t iNums =
static_cast<int32_t>(
2533 (log10((
float)(nPayment / nPrincipalAmount)) -
2534 log10((
float)(nPayment / nPrincipalAmount - nRateOfMonth))) /
2535 log10((
float)(1 + nRateOfMonth)));
2537 std::min(
static_cast<int32_t>(nFirstMonth + nNumberOfMonths - 1), iNums);
2539 if (nPayment < nPrincipalAmount * nRateOfMonth) {
2540 info.GetReturnValue().Set(0);
2545 for (i = 0; i < nFirstMonth - 1; ++i)
2546 nPrincipalAmount -= nPayment - nPrincipalAmount * nRateOfMonth;
2549 for (; i < iEnd; ++i) {
2550 nSum += nPrincipalAmount * nRateOfMonth;
2551 nPrincipalAmount -= nPayment - nPrincipalAmount * nRateOfMonth;
2553 info.GetReturnValue().Set(nSum);
2557void CFXJSE_FormCalcContext::NPV(
2559 const v8::FunctionCallbackInfo<v8::Value>& info) {
2560 CFXJSE_FormCalcContext* pContext = ToFormCalcContext(pThis);
2561 int32_t argc = info.Length();
2563 pContext->ThrowParamCountMismatchException(
"NPV");
2567 v8::Local<v8::Value> argValue = GetSimpleValue(info, 0);
2568 if (ValueIsNull(info.GetIsolate(), argValue)) {
2569 info.GetReturnValue().SetNull();
2573 double nRate = ValueToDouble(info.GetIsolate(), argValue);
2575 pContext->ThrowArgumentMismatchException();
2579 std::vector<
double> data;
2580 for (int32_t i = 1; i < argc; i++) {
2581 argValue = GetSimpleValue(info, i);
2582 if (ValueIsNull(info.GetIsolate(), argValue)) {
2583 info.GetReturnValue().SetNull();
2586 data.push_back(ValueToDouble(info.GetIsolate(), argValue));
2590 double nDivisor = 1.0 + nRate;
2591 while (!data.empty()) {
2592 nSum += data.back();
2596 info.GetReturnValue().Set(nSum);
2600void CFXJSE_FormCalcContext::Pmt(
2602 const v8::FunctionCallbackInfo<v8::Value>& info) {
2603 CFXJSE_FormCalcContext* pContext = ToFormCalcContext(pThis);
2604 if (info.Length() != 3) {
2605 pContext->ThrowParamCountMismatchException(
"Pmt");
2609 v8::Local<v8::Value> argOne = GetSimpleValue(info, 0);
2610 v8::Local<v8::Value> argTwo = GetSimpleValue(info, 1);
2611 v8::Local<v8::Value> argThree = GetSimpleValue(info, 2);
2612 if (ValueIsNull(info.GetIsolate(), argOne) ||
2613 ValueIsNull(info.GetIsolate(), argTwo) ||
2614 ValueIsNull(info.GetIsolate(), argThree)) {
2615 info.GetReturnValue().SetNull();
2619 double nPrincipal = ValueToDouble(info.GetIsolate(), argOne);
2620 double nRate = ValueToDouble(info.GetIsolate(), argTwo);
2621 int nPeriods = GetValidatedPaymentPeriods(info.GetIsolate(), argThree);
2622 if (nPrincipal <= 0 || nRate <= 0 || nPeriods == 0) {
2623 pContext->ThrowArgumentMismatchException();
2627 double nSum = pow(1.0 + nRate, nPeriods);
2628 info.GetReturnValue().Set((nPrincipal * nRate * nSum) / (nSum - 1));
2632void CFXJSE_FormCalcContext::PPmt(
2634 const v8::FunctionCallbackInfo<v8::Value>& info) {
2635 CFXJSE_FormCalcContext* pContext = ToFormCalcContext(pThis);
2636 if (info.Length() != 5) {
2637 pContext->ThrowParamCountMismatchException(
"PPmt");
2641 v8::Local<v8::Value> argOne = GetSimpleValue(info, 0);
2642 v8::Local<v8::Value> argTwo = GetSimpleValue(info, 1);
2643 v8::Local<v8::Value> argThree = GetSimpleValue(info, 2);
2644 v8::Local<v8::Value> argFour = GetSimpleValue(info, 3);
2645 v8::Local<v8::Value> argFive = GetSimpleValue(info, 4);
2646 if (ValueIsNull(info.GetIsolate(), argOne) ||
2647 ValueIsNull(info.GetIsolate(), argTwo) ||
2648 ValueIsNull(info.GetIsolate(), argThree) ||
2649 ValueIsNull(info.GetIsolate(), argFour) ||
2650 ValueIsNull(info.GetIsolate(), argFive)) {
2651 info.GetReturnValue().SetNull();
2655 float nPrincipalAmount = ValueToFloat(info.GetIsolate(), argOne);
2656 float nRate = ValueToFloat(info.GetIsolate(), argTwo);
2657 float nPayment = ValueToFloat(info.GetIsolate(), argThree);
2658 float nFirstMonth = ValueToFloat(info.GetIsolate(), argFour);
2659 float nNumberOfMonths = ValueToFloat(info.GetIsolate(), argFive);
2660 if ((nPrincipalAmount <= 0) || (nRate <= 0) || (nPayment <= 0) ||
2661 (nFirstMonth < 0) || (nNumberOfMonths < 0)) {
2662 pContext->ThrowArgumentMismatchException();
2666 float nRateOfMonth = nRate / 12;
2667 int32_t iNums =
static_cast<int32_t>(
2668 (log10((
float)(nPayment / nPrincipalAmount)) -
2669 log10((
float)(nPayment / nPrincipalAmount - nRateOfMonth))) /
2670 log10((
float)(1 + nRateOfMonth)));
2672 std::min(
static_cast<int32_t>(nFirstMonth + nNumberOfMonths - 1), iNums);
2673 if (nPayment < nPrincipalAmount * nRateOfMonth) {
2674 pContext->ThrowArgumentMismatchException();
2679 for (i = 0; i < nFirstMonth - 1; ++i)
2680 nPrincipalAmount -= nPayment - nPrincipalAmount * nRateOfMonth;
2684 for (; i < iEnd; ++i) {
2685 nTemp = nPayment - nPrincipalAmount * nRateOfMonth;
2687 nPrincipalAmount -= nTemp;
2689 info.GetReturnValue().Set(nSum);
2693void CFXJSE_FormCalcContext::PV(
2695 const v8::FunctionCallbackInfo<v8::Value>& info) {
2696 CFXJSE_FormCalcContext* pContext = ToFormCalcContext(pThis);
2697 if (info.Length() != 3) {
2698 pContext->ThrowParamCountMismatchException(
"PV");
2702 v8::Local<v8::Value> argOne = GetSimpleValue(info, 0);
2703 v8::Local<v8::Value> argTwo = GetSimpleValue(info, 1);
2704 v8::Local<v8::Value> argThree = GetSimpleValue(info, 2);
2705 if (ValueIsNull(info.GetIsolate(), argOne) ||
2706 ValueIsNull(info.GetIsolate(), argTwo) ||
2707 ValueIsNull(info.GetIsolate(), argThree)) {
2708 info.GetReturnValue().SetNull();
2712 double nAmount = ValueToDouble(info.GetIsolate(), argOne);
2713 double nRate = ValueToDouble(info.GetIsolate(), argTwo);
2714 int nPeriods = GetValidatedPaymentPeriods(info.GetIsolate(), argThree);
2715 if (nAmount <= 0 || nRate < 0 || nPeriods == 0) {
2716 pContext->ThrowArgumentMismatchException();
2720 double nTemp = 1 / pow(1.0 + nRate, nPeriods);
2721 info.GetReturnValue().Set(nAmount * ((1.0 - nTemp) / nRate));
2725void CFXJSE_FormCalcContext::Rate(
2727 const v8::FunctionCallbackInfo<v8::Value>& info) {
2728 CFXJSE_FormCalcContext* pContext = ToFormCalcContext(pThis);
2729 if (info.Length() != 3) {
2730 pContext->ThrowParamCountMismatchException(
"Rate");
2734 v8::Local<v8::Value> argOne = GetSimpleValue(info, 0);
2735 v8::Local<v8::Value> argTwo = GetSimpleValue(info, 1);
2736 v8::Local<v8::Value> argThree = GetSimpleValue(info, 2);
2737 if (ValueIsNull(info.GetIsolate(), argOne) ||
2738 ValueIsNull(info.GetIsolate(), argTwo) ||
2739 ValueIsNull(info.GetIsolate(), argThree)) {
2740 info.GetReturnValue().SetNull();
2744 float nFuture = ValueToFloat(info.GetIsolate(), argOne);
2745 float nPresent = ValueToFloat(info.GetIsolate(), argTwo);
2746 int nPeriods = GetValidatedPaymentPeriods(info.GetIsolate(), argThree);
2747 if (nFuture <= 0 || nPresent < 0 || nPeriods == 0) {
2748 pContext->ThrowArgumentMismatchException();
2752 info.GetReturnValue().Set(powf(nFuture / nPresent, 1.0f / nPeriods) - 1.0f);
2756void CFXJSE_FormCalcContext::Term(
2758 const v8::FunctionCallbackInfo<v8::Value>& info) {
2759 CFXJSE_FormCalcContext* pContext = ToFormCalcContext(pThis);
2760 if (info.Length() != 3) {
2761 pContext->ThrowParamCountMismatchException(
"Term");
2765 v8::Local<v8::Value> argOne = GetSimpleValue(info, 0);
2766 v8::Local<v8::Value> argTwo = GetSimpleValue(info, 1);
2767 v8::Local<v8::Value> argThree = GetSimpleValue(info, 2);
2768 if (ValueIsNull(info.GetIsolate(), argOne) ||
2769 ValueIsNull(info.GetIsolate(), argTwo) ||
2770 ValueIsNull(info.GetIsolate(), argThree)) {
2771 info.GetReturnValue().SetNull();
2775 float nMount = ValueToFloat(info.GetIsolate(), argOne);
2776 float nRate = ValueToFloat(info.GetIsolate(), argTwo);
2777 float nFuture = ValueToFloat(info.GetIsolate(), argThree);
2778 if ((nMount <= 0) || (nRate <= 0) || (nFuture <= 0)) {
2779 pContext->ThrowArgumentMismatchException();
2783 info.GetReturnValue().Set(log((
float)(nFuture / nMount * nRate) + 1) /
2784 log((
float)(1 + nRate)));
2788void CFXJSE_FormCalcContext::Choose(
2790 const v8::FunctionCallbackInfo<v8::Value>& info) {
2791 CFXJSE_FormCalcContext* pContext = ToFormCalcContext(pThis);
2792 int32_t argc = info.Length();
2794 pContext->ThrowParamCountMismatchException(
"Choose");
2798 if (ValueIsNull(info.GetIsolate(), info[0])) {
2799 info.GetReturnValue().SetNull();
2804 static_cast<int32_t>(ValueToFloat(info.GetIsolate(), info[0]));
2806 info.GetReturnValue().SetEmptyString();
2810 bool bFound =
false;
2811 bool bStopCounterFlags =
false;
2812 int32_t iArgIndex = 1;
2813 int32_t iValueIndex = 0;
2814 while (!bFound && !bStopCounterFlags && (iArgIndex < argc)) {
2815 v8::Local<v8::Value> argIndexValue = info[iArgIndex];
2816 if (fxv8::IsArray(argIndexValue)) {
2817 v8::Local<v8::Array> arr = argIndexValue.As<v8::Array>();
2818 uint32_t iLength = fxv8::GetArrayLengthHelper(arr);
2820 bStopCounterFlags =
true;
2822 iValueIndex += (iLength - 2);
2823 if (iValueIndex >= iIndex) {
2824 v8::Local<v8::Value> propertyValue =
2825 fxv8::ReentrantGetArrayElementHelper(info.GetIsolate(), arr, 1);
2826 v8::Local<v8::Value> jsValue = fxv8::ReentrantGetArrayElementHelper(
2827 info.GetIsolate(), arr, (iLength - 1) - (iValueIndex - iIndex));
2828 v8::Local<v8::Value> newPropertyValue;
2829 if (fxv8::IsObject(jsValue)) {
2830 v8::Local<v8::Object> jsObjectValue = jsValue.As<v8::Object>();
2831 if (fxv8::IsNull(propertyValue)) {
2833 GetObjectDefaultValue(info.GetIsolate(), jsObjectValue);
2835 ByteString bsName = fxv8::ReentrantToByteStringHelper(
2836 info.GetIsolate(), propertyValue);
2837 newPropertyValue = fxv8::ReentrantGetObjectPropertyHelper(
2838 info.GetIsolate(), jsObjectValue, bsName.AsStringView());
2842 ValueToUTF8String(info.GetIsolate(), newPropertyValue);
2843 info.GetReturnValue().Set(
2844 fxv8::NewStringHelper(info.GetIsolate(), bsChosen.AsStringView()));
2849 if (iValueIndex == iIndex) {
2851 ValueToUTF8String(info.GetIsolate(), argIndexValue);
2852 info.GetReturnValue().Set(
2853 fxv8::NewStringHelper(info.GetIsolate(), bsChosen.AsStringView()));
2860 info.GetReturnValue().SetEmptyString();
2864void CFXJSE_FormCalcContext::Exists(
2866 const v8::FunctionCallbackInfo<v8::Value>& info) {
2867 if (info.Length() != 1) {
2868 ToFormCalcContext(pThis)->ThrowParamCountMismatchException(
"Exists");
2875void CFXJSE_FormCalcContext::HasValue(
2877 const v8::FunctionCallbackInfo<v8::Value>& info) {
2878 if (info.Length() != 1) {
2879 ToFormCalcContext(pThis)->ThrowParamCountMismatchException(
"HasValue");
2883 v8::Local<v8::Value> argOne = GetSimpleValue(info, 0);
2884 if (!fxv8::IsString(argOne)) {
2885 info.GetReturnValue().Set(
2886 static_cast<
int>(fxv8::IsNumber(argOne) || fxv8::IsBoolean(argOne)));
2891 fxv8::ReentrantToByteStringHelper(info.GetIsolate(), argOne);
2893 info.GetReturnValue().Set(
static_cast<
int>(!bsValue.IsEmpty()));
2897void CFXJSE_FormCalcContext::Oneof(
2899 const v8::FunctionCallbackInfo<v8::Value>& info) {
2900 if (info.Length() < 2) {
2901 ToFormCalcContext(pThis)->ThrowParamCountMismatchException(
"Oneof");
2905 v8::Local<v8::Value> argOne = GetSimpleValue(info, 0);
2906 for (
const auto& value : UnfoldArgs(info)) {
2907 if (SimpleValueCompare(info.GetIsolate(), argOne, value)) {
2908 info.GetReturnValue().Set(1);
2912 info.GetReturnValue().Set(0);
2916void CFXJSE_FormCalcContext::Within(
2918 const v8::FunctionCallbackInfo<v8::Value>& info) {
2919 if (info.Length() != 3) {
2920 ToFormCalcContext(pThis)->ThrowParamCountMismatchException(
"Within");
2924 v8::Local<v8::Value> argOne = GetSimpleValue(info, 0);
2925 if (fxv8::IsNull(argOne)) {
2926 info.GetReturnValue().SetUndefined();
2930 v8::Local<v8::Value> argLow = GetSimpleValue(info, 1);
2931 v8::Local<v8::Value> argHigh = GetSimpleValue(info, 2);
2932 if (fxv8::IsNumber(argOne)) {
2933 float oneNumber = ValueToFloat(info.GetIsolate(), argOne);
2934 float lowNumber = ValueToFloat(info.GetIsolate(), argLow);
2935 float heightNumber = ValueToFloat(info.GetIsolate(), argHigh);
2936 info.GetReturnValue().Set(
static_cast<
int>((oneNumber >= lowNumber) &&
2937 (oneNumber <= heightNumber)));
2941 ByteString bsOne = ValueToUTF8String(info.GetIsolate(), argOne);
2942 ByteString bsLow = ValueToUTF8String(info.GetIsolate(), argLow);
2943 ByteString bsHeight = ValueToUTF8String(info.GetIsolate(), argHigh);
2944 info.GetReturnValue().Set(
2945 static_cast<
int>((bsOne
.Compare(bsLow.AsStringView()
) >= 0) &&
2946 (bsOne
.Compare(bsHeight.AsStringView()
) <= 0)));
2950void CFXJSE_FormCalcContext::If(
2952 const v8::FunctionCallbackInfo<v8::Value>& info) {
2953 if (info.Length() != 3) {
2954 ToFormCalcContext(pThis)->ThrowParamCountMismatchException(
"If");
2958 const bool condition = fxv8::ReentrantToBooleanHelper(
2959 info.GetIsolate(), GetSimpleValue(info, 0));
2961 info.GetReturnValue().Set(GetSimpleValue(info, condition ? 1 : 2));
2965void CFXJSE_FormCalcContext::Eval(
2967 const v8::FunctionCallbackInfo<v8::Value>& info) {
2968 CFXJSE_FormCalcContext* pContext = ToFormCalcContext(pThis);
2969 if (info.Length() != 1) {
2970 pContext->ThrowParamCountMismatchException(
"Eval");
2974 v8::Isolate* pIsolate = pContext->GetIsolate();
2975 v8::Local<v8::Value> scriptValue = GetSimpleValue(info, 0);
2976 ByteString bsUtf8Script = ValueToUTF8String(info.GetIsolate(), scriptValue);
2977 if (bsUtf8Script.IsEmpty()) {
2978 info.GetReturnValue().SetNull();
2983 std::optional<WideTextBuffer> wsJavaScriptBuf =
2984 CFXJSE_FormCalcContext::Translate(pContext->GetDocument()->GetHeap(),
2985 wsCalcScript.AsStringView());
2986 if (!wsJavaScriptBuf.has_value()) {
2987 pContext->ThrowCompilerErrorException();
2990 std::unique_ptr<CFXJSE_Context> pNewContext =
2991 CFXJSE_Context::Create(pIsolate,
nullptr,
nullptr,
nullptr);
2993 ByteString bsScript = FX_UTF8Encode(wsJavaScriptBuf.value().AsStringView());
2995 bsScript.AsStringView(), v8::Local<v8::Object>());
2997 info.GetReturnValue().Set(result.value->DirectGetValue());
3001void CFXJSE_FormCalcContext::Ref(
3003 const v8::FunctionCallbackInfo<v8::Value>& info) {
3004 CFXJSE_FormCalcContext* pContext = ToFormCalcContext(pThis);
3005 if (info.Length() != 1) {
3006 pContext->ThrowParamCountMismatchException(
"Ref");
3010 v8::Local<v8::Value> argOne = info[0];
3011 if (fxv8::IsBoolean(argOne) || fxv8::IsString(argOne) ||
3012 fxv8::IsNumber(argOne)) {
3013 info.GetReturnValue().Set(argOne);
3017 v8::LocalVector<v8::Value> values(info.GetIsolate(), 3);
3019 if (fxv8::IsNull(argOne)) {
3022 values[2] = fxv8::NewNullHelper(info.GetIsolate());
3023 }
else if (fxv8::IsArray(argOne)) {
3024 v8::Local<v8::Array> arr = argOne.As<v8::Array>();
3025 v8::Local<v8::Value> propertyValue =
3026 fxv8::ReentrantGetArrayElementHelper(info.GetIsolate(), arr, 1);
3027 v8::Local<v8::Value> jsObjectValue =
3028 fxv8::ReentrantGetArrayElementHelper(info.GetIsolate(), arr, 2);
3029 if (!fxv8::IsNull(propertyValue) || fxv8::IsNull(jsObjectValue)) {
3030 pContext->ThrowArgumentMismatchException();
3033 values[2] = jsObjectValue;
3034 }
else if (fxv8::IsObject(argOne)) {
3037 pContext->ThrowArgumentMismatchException();
3041 values[0] = fxv8::NewNumberHelper(info.GetIsolate(), intVal);
3042 values[1] = fxv8::NewNullHelper(info.GetIsolate());
3043 info.GetReturnValue().Set(fxv8::NewArrayHelper(info.GetIsolate(), values));
3047void CFXJSE_FormCalcContext::UnitType(
3049 const v8::FunctionCallbackInfo<v8::Value>& info) {
3050 if (info.Length() != 1) {
3051 ToFormCalcContext(pThis)->ThrowParamCountMismatchException(
"UnitType");
3055 v8::Local<v8::Value> unitspanValue = GetSimpleValue(info, 0);
3056 if (fxv8::IsNull(unitspanValue)) {
3057 info.GetReturnValue().SetNull();
3061 ByteString bsUnitspan = ValueToUTF8String(info.GetIsolate(), unitspanValue);
3062 if (bsUnitspan.IsEmpty()) {
3063 info.GetReturnValue().SetEmptyString();
3067 enum XFA_FormCalc_VALUETYPE_ParserStatus {
3069 VALUETYPE_HAVEINVALIDCHAR,
3070 VALUETYPE_HAVEDIGIT,
3071 VALUETYPE_HAVEDIGITWHITE,
3080 const wchar_t* pData = wsType.c_str();
3082 int32_t uLen = wsType.GetLength();
3084 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(
3139 fxv8::NewStringHelper(info.GetIsolate(),
"cm"));
3141 case VALUETYPE_ISMM:
3142 info.GetReturnValue().Set(
3143 fxv8::NewStringHelper(info.GetIsolate(),
"mm"));
3145 case VALUETYPE_ISPT:
3146 info.GetReturnValue().Set(
3147 fxv8::NewStringHelper(info.GetIsolate(),
"pt"));
3149 case VALUETYPE_ISMP:
3150 info.GetReturnValue().Set(
3151 fxv8::NewStringHelper(info.GetIsolate(),
"mp"));
3154 info.GetReturnValue().Set(
3155 fxv8::NewStringHelper(info.GetIsolate(),
"in"));
3162void CFXJSE_FormCalcContext::UnitValue(
3164 const v8::FunctionCallbackInfo<v8::Value>& info) {
3165 int32_t argc = info.Length();
3166 if (argc < 1 || argc > 2) {
3167 ToFormCalcContext(pThis)->ThrowParamCountMismatchException(
"UnitValue");
3171 v8::Local<v8::Value> unitspanValue = GetSimpleValue(info, 0);
3172 if (fxv8::IsNull(unitspanValue)) {
3173 info.GetReturnValue().SetNull();
3177 ByteString bsUnitspan = ValueToUTF8String(info.GetIsolate(), unitspanValue);
3178 const char* pData = bsUnitspan.c_str();
3180 info.GetReturnValue().Set(0);
3186 while (IsWhitespace(pData[u])) {
3190 while (u < bsUnitspan.GetLength()) {
3191 if (!IsPartOfNumber(pData[u])) {
3197 char* pTemp =
nullptr;
3198 double dFirstNumber = strtod(pData, &pTemp);
3199 while (IsWhitespace(pData[u])) {
3203 size_t uLen = bsUnitspan.GetLength();
3206 if (pData[u] ==
' ') {
3210 bsFirstUnit += pData[u];
3217 v8::Local<v8::Value> unitValue = GetSimpleValue(info, 1);
3218 ByteString bsUnitTemp = ValueToUTF8String(info.GetIsolate(), unitValue);
3219 const char* pChar = bsUnitTemp.c_str();
3221 while (IsWhitespace(pChar[uVal])) {
3225 while (uVal < bsUnitTemp.GetLength()) {
3226 if (!isdigit(pChar[uVal]) && pChar[uVal] !=
'.') {
3231 while (IsWhitespace(pChar[uVal])) {
3235 size_t uValLen = bsUnitTemp.GetLength();
3236 while (uVal < uValLen) {
3237 if (pChar[uVal] ==
' ') {
3241 bsUnit += pChar[uVal];
3246 bsUnit
= bsFirstUnit;
3250 if (bsFirstUnit
== "in" || bsFirstUnit
== "inches") {
3251 if (bsUnit
== "mm" || bsUnit
== "millimeters") {
3252 dResult = dFirstNumber * 25.4;
3253 }
else if (bsUnit
== "cm" || bsUnit
== "centimeters") {
3254 dResult = dFirstNumber * 2.54;
3255 }
else if (bsUnit
== "pt" || bsUnit
== "points") {
3256 dResult = dFirstNumber / 72;
3257 }
else if (bsUnit
== "mp" || bsUnit
== "millipoints") {
3258 dResult = dFirstNumber / 72000;
3260 dResult = dFirstNumber;
3262 }
else if (bsFirstUnit
== "mm" || bsFirstUnit
== "millimeters") {
3263 if (bsUnit
== "mm" || bsUnit
== "millimeters") {
3264 dResult = dFirstNumber;
3265 }
else if (bsUnit
== "cm" || bsUnit
== "centimeters") {
3266 dResult = dFirstNumber / 10;
3267 }
else if (bsUnit
== "pt" || bsUnit
== "points") {
3268 dResult = dFirstNumber / 25.4 / 72;
3269 }
else if (bsUnit
== "mp" || bsUnit
== "millipoints") {
3270 dResult = dFirstNumber / 25.4 / 72000;
3272 dResult = dFirstNumber / 25.4;
3274 }
else if (bsFirstUnit
== "cm" || bsFirstUnit
== "centimeters") {
3275 if (bsUnit
== "mm" || bsUnit
== "millimeters") {
3276 dResult = dFirstNumber * 10;
3277 }
else if (bsUnit
== "cm" || bsUnit
== "centimeters") {
3278 dResult = dFirstNumber;
3279 }
else if (bsUnit
== "pt" || bsUnit
== "points") {
3280 dResult = dFirstNumber / 2.54 / 72;
3281 }
else if (bsUnit
== "mp" || bsUnit
== "millipoints") {
3282 dResult = dFirstNumber / 2.54 / 72000;
3284 dResult = dFirstNumber / 2.54;
3286 }
else if (bsFirstUnit
== "pt" || bsFirstUnit
== "points") {
3287 if (bsUnit
== "mm" || bsUnit
== "millimeters") {
3288 dResult = dFirstNumber / 72 * 25.4;
3289 }
else if (bsUnit
== "cm" || bsUnit
== "centimeters") {
3290 dResult = dFirstNumber / 72 * 2.54;
3291 }
else if (bsUnit
== "pt" || bsUnit
== "points") {
3292 dResult = dFirstNumber;
3293 }
else if (bsUnit
== "mp" || bsUnit
== "millipoints") {
3294 dResult = dFirstNumber * 1000;
3296 dResult = dFirstNumber / 72;
3298 }
else if (bsFirstUnit
== "mp" || bsFirstUnit
== "millipoints") {
3299 if (bsUnit
== "mm" || bsUnit
== "millimeters") {
3300 dResult = dFirstNumber / 72000 * 25.4;
3301 }
else if (bsUnit
== "cm" || bsUnit
== "centimeters") {
3302 dResult = dFirstNumber / 72000 * 2.54;
3303 }
else if (bsUnit
== "pt" || bsUnit
== "points") {
3304 dResult = dFirstNumber / 1000;
3305 }
else if (bsUnit
== "mp" || bsUnit
== "millipoints") {
3306 dResult = dFirstNumber;
3308 dResult = dFirstNumber / 72000;
3311 info.GetReturnValue().Set(dResult);
3316void CFXJSE_FormCalcContext::At(
3318 const v8::FunctionCallbackInfo<v8::Value>& info) {
3319 if (info.Length() != 2) {
3320 ToFormCalcContext(pThis)->ThrowParamCountMismatchException(
"At");
3324 v8::Local<v8::Value> argOne = GetSimpleValue(info, 0);
3325 v8::Local<v8::Value> argTwo = GetSimpleValue(info, 1);
3326 if (ValueIsNull(info.GetIsolate(), argOne) ||
3327 ValueIsNull(info.GetIsolate(), argTwo)) {
3328 info.GetReturnValue().SetNull();
3332 ByteString stringTwo = ValueToUTF8String(info.GetIsolate(), argTwo);
3333 if (stringTwo.IsEmpty()) {
3334 info.GetReturnValue().Set(1);
3338 ByteString stringOne = ValueToUTF8String(info.GetIsolate(), argOne);
3339 auto pos = stringOne.Find(stringTwo.AsStringView());
3340 info.GetReturnValue().Set(
3341 static_cast<
int>(pos.has_value() ? pos.value() + 1 : 0));
3345void CFXJSE_FormCalcContext::Concat(
3347 const v8::FunctionCallbackInfo<v8::Value>& info) {
3348 int32_t argc = info.Length();
3350 ToFormCalcContext(pThis)->ThrowParamCountMismatchException(
"Concat");
3355 bool bAllNull =
true;
3356 for (int32_t i = 0; i < argc; i++) {
3357 v8::Local<v8::Value> value = GetSimpleValue(info, i);
3358 if (ValueIsNull(info.GetIsolate(), value))
3362 bsResult += ValueToUTF8String(info.GetIsolate(), value);
3366 info.GetReturnValue().SetNull();
3369 info.GetReturnValue().Set(
3370 fxv8::NewStringHelper(info.GetIsolate(), bsResult.AsStringView()));
3374void CFXJSE_FormCalcContext::Decode(
3376 const v8::FunctionCallbackInfo<v8::Value>& info) {
3377 int32_t argc = info.Length();
3378 if (argc < 1 || argc > 2) {
3379 ToFormCalcContext(pThis)->ThrowParamCountMismatchException(
"Decode");
3384 v8::Local<v8::Value> argOne = GetSimpleValue(info, 0);
3385 if (ValueIsNull(info.GetIsolate(), argOne)) {
3386 info.GetReturnValue().SetNull();
3390 WideString decoded = DecodeURL(WideString::FromUTF8(
3391 ValueToUTF8String(info.GetIsolate(), argOne).AsStringView()));
3392 auto result = FX_UTF8Encode(decoded.AsStringView());
3393 info.GetReturnValue().Set(
3394 fxv8::NewStringHelper(info.GetIsolate(), result.AsStringView()));
3398 v8::Local<v8::Value> argOne = GetSimpleValue(info, 0);
3399 v8::Local<v8::Value> argTwo = GetSimpleValue(info, 1);
3400 if (ValueIsNull(info.GetIsolate(), argOne) ||
3401 ValueIsNull(info.GetIsolate(), argTwo)) {
3402 info.GetReturnValue().SetNull();
3406 ByteString bsToDecode = ValueToUTF8String(info.GetIsolate(), argOne);
3407 ByteString bsIdentify = ValueToUTF8String(info.GetIsolate(), argTwo);
3413 decoded
= DecodeHTML(wsToDecode);
3415 decoded
= DecodeXML(wsToDecode);
3417 decoded
= DecodeURL(wsToDecode);
3419 auto result = FX_UTF8Encode(decoded.AsStringView());
3420 info.GetReturnValue().Set(
3421 fxv8::NewStringHelper(info.GetIsolate(), result.AsStringView()));
3425void CFXJSE_FormCalcContext::Encode(
3427 const v8::FunctionCallbackInfo<v8::Value>& info) {
3428 int32_t argc = info.Length();
3429 if (argc < 1 || argc > 2) {
3430 ToFormCalcContext(pThis)->ThrowParamCountMismatchException(
"Encode");
3435 v8::Local<v8::Value> argOne = GetSimpleValue(info, 0);
3436 if (ValueIsNull(info.GetIsolate(), argOne)) {
3437 info.GetReturnValue().SetNull();
3441 EncodeURL(ValueToUTF8String(info.GetIsolate(), argOne));
3442 auto result = FX_UTF8Encode(encoded.AsStringView());
3443 info.GetReturnValue().Set(
3444 fxv8::NewStringHelper(info.GetIsolate(), result.AsStringView()));
3448 v8::Local<v8::Value> argOne = GetSimpleValue(info, 0);
3449 v8::Local<v8::Value> argTwo = GetSimpleValue(info, 1);
3450 if (ValueIsNull(info.GetIsolate(), argOne) ||
3451 ValueIsNull(info.GetIsolate(), argTwo)) {
3452 info.GetReturnValue().SetNull();
3456 ByteString bsToEncode = ValueToUTF8String(info.GetIsolate(), argOne);
3457 ByteString bsIdentify = ValueToUTF8String(info.GetIsolate(), argTwo);
3460 encoded
= EncodeHTML(bsToEncode);
3462 encoded
= EncodeXML(bsToEncode);
3464 encoded
= EncodeURL(bsToEncode);
3466 auto result = FX_UTF8Encode(encoded.AsStringView());
3467 info.GetReturnValue().Set(
3468 fxv8::NewStringHelper(info.GetIsolate(), result.AsStringView()));
3472void CFXJSE_FormCalcContext::Format(
3474 const v8::FunctionCallbackInfo<v8::Value>& info) {
3475 CFXJSE_FormCalcContext* pContext = ToFormCalcContext(pThis);
3476 if (info.Length() < 2) {
3477 pContext->ThrowParamCountMismatchException(
"Format");
3481 v8::Local<v8::Value> argOne = GetSimpleValue(info, 0);
3482 ByteString bsPattern = ValueToUTF8String(info.GetIsolate(), argOne);
3484 v8::Local<v8::Value> argTwo = GetSimpleValue(info, 1);
3485 ByteString bsValue = ValueToUTF8String(info.GetIsolate(), argTwo);
3493 auto [bPatternIsString, dwPatternType] =
3494 PatternStringType(bsPattern.AsStringView());
3495 if (!bPatternIsString) {
3496 switch (dwPatternType) {
3497 case CXFA_LocaleValue::ValueType::kDateTime: {
3498 auto iTChar = wsPattern.Find(L'T');
3499 if (!iTChar.has_value()) {
3500 info.GetReturnValue().SetEmptyString();
3504 wsDatePattern += wsPattern.First(iTChar.value()) + L"} ";
3508 wsPattern.Last(wsPattern.GetLength() - (iTChar.value() + 1)) + L"}";
3509 wsPattern = wsDatePattern + wsTimePattern;
3511 case CXFA_LocaleValue::ValueType::kDate: {
3512 wsPattern
= L"date{"
+ wsPattern
+ L"}";
3514 case CXFA_LocaleValue::ValueType::kTime: {
3515 wsPattern
= L"time{"
+ wsPattern
+ L"}";
3517 case CXFA_LocaleValue::ValueType::kText: {
3518 wsPattern
= L"text{"
+ wsPattern
+ L"}";
3520 case CXFA_LocaleValue::ValueType::kFloat: {
3521 wsPattern
= L"num{"
+ wsPattern
+ L"}";
3526 wsValue
, wsTestPattern
, pLocale
, pMgr
);
3528 wsPattern =
std::move(wsTestPattern);
3529 dwPatternType = CXFA_LocaleValue::ValueType::kFloat;
3531 wsPattern
= L"text{"
+ wsPattern
+ L"}";
3532 dwPatternType = CXFA_LocaleValue::ValueType::kText;
3542 info.GetReturnValue().SetEmptyString();
3545 info.GetReturnValue().Set(
3546 fxv8::NewStringHelper(info.GetIsolate(), wsRet
.ToUTF8().AsStringView()));
3550void CFXJSE_FormCalcContext::Left(
3552 const v8::FunctionCallbackInfo<v8::Value>& info) {
3553 if (info.Length() != 2) {
3554 ToFormCalcContext(pThis)->ThrowParamCountMismatchException(
"Left");
3558 v8::Local<v8::Value> argOne = GetSimpleValue(info, 0);
3559 v8::Local<v8::Value> argTwo = GetSimpleValue(info, 1);
3560 if ((ValueIsNull(info.GetIsolate(), argOne)) ||
3561 (ValueIsNull(info.GetIsolate(), argTwo))) {
3562 info.GetReturnValue().SetNull();
3566 ByteString bsSource = ValueToUTF8String(info.GetIsolate(), argOne);
3567 int32_t count = std::max(0, ValueToInteger(info.GetIsolate(), argTwo));
3568 info.GetReturnValue().Set(fxv8::NewStringHelper(
3569 info.GetIsolate(), bsSource.First(count).AsStringView()));
3573void CFXJSE_FormCalcContext::Len(
3575 const v8::FunctionCallbackInfo<v8::Value>& info) {
3576 if (info.Length() != 1) {
3577 ToFormCalcContext(pThis)->ThrowParamCountMismatchException(
"Len");
3581 v8::Local<v8::Value> argOne = GetSimpleValue(info, 0);
3582 if (ValueIsNull(info.GetIsolate(), argOne)) {
3583 info.GetReturnValue().SetNull();
3587 ByteString bsSource = ValueToUTF8String(info.GetIsolate(), argOne);
3588 info.GetReturnValue().Set(
static_cast<
int>(bsSource.GetLength()));
3592void CFXJSE_FormCalcContext::Lower(
3594 const v8::FunctionCallbackInfo<v8::Value>& info) {
3595 int32_t argc = info.Length();
3596 if (argc < 1 || argc > 2) {
3597 ToFormCalcContext(pThis)->ThrowParamCountMismatchException(
"Lower");
3601 v8::Local<v8::Value> argOne = GetSimpleValue(info, 0);
3602 if (ValueIsNull(info.GetIsolate(), argOne)) {
3603 info.GetReturnValue().SetNull();
3607 WideTextBuffer szLowBuf;
3608 ByteString bsArg = ValueToUTF8String(info.GetIsolate(), argOne);
3610 for (
wchar_t ch : wsArg) {
3611 if ((ch >= 0x41 && ch <= 0x5A) || (ch >= 0xC0 && ch <= 0xDE))
3613 else if (ch == 0x100 || ch == 0x102 || ch == 0x104)
3615 szLowBuf.AppendChar(ch);
3618 info.GetReturnValue().Set(
3619 fxv8::NewStringHelper(info.GetIsolate(), result.AsStringView()));
3623void CFXJSE_FormCalcContext::Ltrim(
3625 const v8::FunctionCallbackInfo<v8::Value>& info) {
3626 if (info.Length() != 1) {
3627 ToFormCalcContext(pThis)->ThrowParamCountMismatchException(
"Ltrim");
3631 v8::Local<v8::Value> argOne = GetSimpleValue(info, 0);
3632 if (ValueIsNull(info.GetIsolate(), argOne)) {
3633 info.GetReturnValue().SetNull();
3637 ByteString bsSource = ValueToUTF8String(info.GetIsolate(), argOne);
3639 info.GetReturnValue().Set(
3640 fxv8::NewStringHelper(info.GetIsolate(), bsSource.AsStringView()));
3644void CFXJSE_FormCalcContext::Parse(
3646 const v8::FunctionCallbackInfo<v8::Value>& info) {
3647 CFXJSE_FormCalcContext* pContext = ToFormCalcContext(pThis);
3648 if (info.Length() != 2) {
3649 pContext->ThrowParamCountMismatchException(
"Parse");
3653 v8::Local<v8::Value> argOne = GetSimpleValue(info, 0);
3654 v8::Local<v8::Value> argTwo = GetSimpleValue(info, 1);
3655 if (ValueIsNull(info.GetIsolate(), argTwo)) {
3656 info.GetReturnValue().SetNull();
3660 ByteString bsPattern = ValueToUTF8String(info.GetIsolate(), argOne);
3661 ByteString bsValue = ValueToUTF8String(info.GetIsolate(), argTwo);
3668 auto [bPatternIsString, dwPatternType] =
3669 PatternStringType(bsPattern.AsStringView());
3670 if (bPatternIsString) {
3674 info.GetReturnValue().SetEmptyString();
3678 info.GetReturnValue().Set(
3679 fxv8::NewStringHelper(info.GetIsolate(), result.AsStringView()));
3683 switch (dwPatternType) {
3684 case CXFA_LocaleValue::ValueType::kDateTime: {
3685 auto iTChar = wsPattern.Find(L'T');
3686 if (!iTChar.has_value()) {
3687 info.GetReturnValue().SetEmptyString();
3690 WideString wsDatePattern(L"date{" + wsPattern.First(iTChar.value()) +
3694 wsPattern.Last(wsPattern.GetLength() - (iTChar.value() + 1)) + L"}");
3695 wsPattern
= wsDatePattern
+ wsTimePattern;
3699 info.GetReturnValue().SetEmptyString();
3703 info.GetReturnValue().Set(
3704 fxv8::NewStringHelper(info.GetIsolate(), result.AsStringView()));
3707 case CXFA_LocaleValue::ValueType::kDate: {
3708 wsPattern
= L"date{"
+ wsPattern
+ L"}";
3712 info.GetReturnValue().SetEmptyString();
3716 info.GetReturnValue().Set(
3717 fxv8::NewStringHelper(info.GetIsolate(), result.AsStringView()));
3720 case CXFA_LocaleValue::ValueType::kTime: {
3721 wsPattern
= L"time{"
+ wsPattern
+ L"}";
3725 info.GetReturnValue().SetEmptyString();
3729 info.GetReturnValue().Set(
3730 fxv8::NewStringHelper(info.GetIsolate(), result.AsStringView()));
3733 case CXFA_LocaleValue::ValueType::kText: {
3734 wsPattern
= L"text{"
+ wsPattern
+ L"}";
3736 wsPattern
, pLocale
, pMgr
);
3738 info.GetReturnValue().SetEmptyString();
3742 info.GetReturnValue().Set(
3743 fxv8::NewStringHelper(info.GetIsolate(), result.AsStringView()));
3746 case CXFA_LocaleValue::ValueType::kFloat: {
3747 wsPattern
= L"num{"
+ wsPattern
+ L"}";
3749 wsPattern
, pLocale
, pMgr
);
3751 info.GetReturnValue().SetEmptyString();
3761 wsValue
, wsTestPattern
, pLocale
, pMgr
);
3769 WideString wsTestPattern = L"text{"
+ wsPattern
+ L"}";
3771 wsValue
, wsTestPattern
, pLocale
, pMgr
);
3774 info.GetReturnValue().Set(
3775 fxv8::NewStringHelper(info.GetIsolate(), result.AsStringView()));
3779 info.GetReturnValue().SetEmptyString();
3786void CFXJSE_FormCalcContext::Replace(
3788 const v8::FunctionCallbackInfo<v8::Value>& info) {
3789 int32_t argc = info.Length();
3790 if (argc < 2 || argc > 3) {
3791 ToFormCalcContext(pThis)->ThrowParamCountMismatchException(
"Replace");
3795 v8::Local<v8::Value> argOne = GetSimpleValue(info, 0);
3796 v8::Local<v8::Value> argTwo = GetSimpleValue(info, 1);
3799 if (!ValueIsNull(info.GetIsolate(), argOne) &&
3800 !ValueIsNull(info.GetIsolate(), argTwo)) {
3801 bsOne = ValueToUTF8String(info.GetIsolate(), argOne);
3802 bsTwo = ValueToUTF8String(info.GetIsolate(), argTwo);
3807 v8::Local<v8::Value> argThree = GetSimpleValue(info, 2);
3808 bsThree = ValueToUTF8String(info.GetIsolate(), argThree);
3811 bsOne.Replace(bsTwo.AsStringView(), bsThree.AsStringView());
3812 info.GetReturnValue().Set(
3813 fxv8::NewStringHelper(info.GetIsolate(), bsOne.AsStringView()));
3817void CFXJSE_FormCalcContext::Right(
3819 const v8::FunctionCallbackInfo<v8::Value>& info) {
3820 if (info.Length() != 2) {
3821 ToFormCalcContext(pThis)->ThrowParamCountMismatchException(
"Right");
3825 v8::Local<v8::Value> argOne = GetSimpleValue(info, 0);
3826 v8::Local<v8::Value> argTwo = GetSimpleValue(info, 1);
3827 if ((ValueIsNull(info.GetIsolate(), argOne)) ||
3828 (ValueIsNull(info.GetIsolate(), argTwo))) {
3829 info.GetReturnValue().SetNull();
3833 ByteString bsSource = ValueToUTF8String(info.GetIsolate(), argOne);
3834 int32_t count = std::max(0, ValueToInteger(info.GetIsolate(), argTwo));
3835 info.GetReturnValue().Set(fxv8::NewStringHelper(
3836 info.GetIsolate(), bsSource.Last(count).AsStringView()));
3840void CFXJSE_FormCalcContext::Rtrim(
3842 const v8::FunctionCallbackInfo<v8::Value>& info) {
3843 if (info.Length() != 1) {
3844 ToFormCalcContext(pThis)->ThrowParamCountMismatchException(
"Rtrim");
3848 v8::Local<v8::Value> argOne = GetSimpleValue(info, 0);
3849 if (ValueIsNull(info.GetIsolate(), argOne)) {
3850 info.GetReturnValue().SetNull();
3854 ByteString bsSource = ValueToUTF8String(info.GetIsolate(), argOne);
3856 info.GetReturnValue().Set(
3857 fxv8::NewStringHelper(info.GetIsolate(), bsSource.AsStringView()));
3861void CFXJSE_FormCalcContext::Space(
3863 const v8::FunctionCallbackInfo<v8::Value>& info) {
3864 if (info.Length() != 1) {
3865 ToFormCalcContext(pThis)->ThrowParamCountMismatchException(
"Space");
3869 v8::Local<v8::Value> argOne = GetSimpleValue(info, 0);
3870 if (fxv8::IsNull(argOne)) {
3871 info.GetReturnValue().SetNull();
3875 int count = std::max(0, ValueToInteger(info.GetIsolate(), argOne));
3876 if (count > kMaxCharCount) {
3877 ToFormCalcContext(pThis)->ThrowException(
"String too long.");
3880 DataVector<
char> space_string(count,
' ');
3881 info.GetReturnValue().Set(
3882 fxv8::NewStringHelper(info.GetIsolate(), ByteStringView(space_string)));
3886void CFXJSE_FormCalcContext::Str(
3888 const v8::FunctionCallbackInfo<v8::Value>& info) {
3889 int32_t argc = info.Length();
3890 if (argc < 1 || argc > 3) {
3891 ToFormCalcContext(pThis)->ThrowParamCountMismatchException(
"Str");
3895 v8::Local<v8::Value> numberValue = GetSimpleValue(info, 0);
3896 if (fxv8::IsNull(numberValue)) {
3897 info.GetReturnValue().SetNull();
3900 float fNumber = ValueToFloat(info.GetIsolate(), numberValue);
3902 constexpr int32_t kDefaultWidth = 10;
3903 int32_t iWidth = kDefaultWidth;
3905 v8::Local<v8::Value> widthValue = GetSimpleValue(info, 1);
3906 iWidth =
static_cast<int32_t>(ValueToFloat(info.GetIsolate(), widthValue));
3907 if (iWidth > kMaxCharCount) {
3908 ToFormCalcContext(pThis)->ThrowException(
"String too long.");
3913 constexpr int32_t kDefaultPrecision = 0;
3914 int32_t iPrecision = kDefaultPrecision;
3916 constexpr int32_t kMaxPrecision = 15;
3917 v8::Local<v8::Value> precision_value = GetSimpleValue(info, 2);
3918 iPrecision = std::max(0,
static_cast<int32_t>(ValueToFloat(
3919 info.GetIsolate(), precision_value)));
3920 iPrecision =
std::min(iPrecision, kMaxPrecision);
3931 const char* pData = bsNumber.c_str();
3932 int32_t iLength = bsNumber.GetLength();
3935 while (u < iLength) {
3936 if (pData[u] ==
'.') {
3943 if (u > iWidth || (iPrecision + u) >= iWidth) {
3944 DataVector<
char> stars(std::max(iWidth, 0),
'*');
3945 info.GetReturnValue().Set(
3946 fxv8::NewStringHelper(info.GetIsolate(), ByteStringView(stars)));
3952 if (iLength > iWidth) {
3954 while (i < iWidth) {
3960 while (i < iWidth - iLength) {
3966 info.GetReturnValue().Set(
3967 fxv8::NewStringHelper(info.GetIsolate(), resultBuf.AsStringView()));
3971 int32_t iLeavingSpace = iWidth - u - iPrecision;
3972 if (iPrecision != 0) {
3977 while (i < iLeavingSpace) {
3983 resultBuf
+= pData[i];
3986 if (iPrecision != 0) {
3992 while (u < iLength) {
3993 if (i >= iPrecision) {
3997 resultBuf
+= pData[u];
4001 while (i < iPrecision) {
4005 info.GetReturnValue().Set(
4006 fxv8::NewStringHelper(info.GetIsolate(), resultBuf.AsStringView()));
4011void CFXJSE_FormCalcContext::Stuff(
4013 const v8::FunctionCallbackInfo<v8::Value>& info) {
4014 int32_t argc = info.Length();
4015 if (argc < 3 || argc > 4) {
4016 ToFormCalcContext(pThis)->ThrowParamCountMismatchException(
"Stuff");
4020 v8::Local<v8::Value> sourceValue = GetSimpleValue(info, 0);
4021 v8::Local<v8::Value> startValue = GetSimpleValue(info, 1);
4022 v8::Local<v8::Value> deleteValue = GetSimpleValue(info, 2);
4023 if (fxv8::IsNull(sourceValue) || fxv8::IsNull(startValue) ||
4024 fxv8::IsNull(deleteValue)) {
4025 info.GetReturnValue().SetNull();
4030 int32_t iDelete = 0;
4031 ByteString bsSource = ValueToUTF8String(info.GetIsolate(), sourceValue);
4032 int32_t iLength =
pdfium::checked_cast<int32_t>(bsSource.GetLength());
4034 iStart = std::clamp(
4035 static_cast<int32_t>(ValueToFloat(info.GetIsolate(), startValue)), 1,
4037 iDelete = std::clamp(
4038 static_cast<int32_t>(ValueToFloat(info.GetIsolate(), deleteValue)), 0,
4039 iLength - iStart + 1);
4044 v8::Local<v8::Value> insertValue = GetSimpleValue(info, 3);
4045 bsInsert = ValueToUTF8String(info.GetIsolate(), insertValue);
4049 ByteString bsResult = {bsSource.AsStringView().First(iStart),
4050 bsInsert.AsStringView(),
4051 bsSource.AsStringView().Substr(iStart + iDelete)};
4052 info.GetReturnValue().Set(
4053 fxv8::NewStringHelper(info.GetIsolate(), bsResult.AsStringView()));
4057void CFXJSE_FormCalcContext::Substr(
4059 const v8::FunctionCallbackInfo<v8::Value>& info) {
4060 if (info.Length() != 3) {
4061 ToFormCalcContext(pThis)->ThrowParamCountMismatchException(
"Substr");
4065 v8::Local<v8::Value> string_value = GetSimpleValue(info, 0);
4066 v8::Local<v8::Value> start_value = GetSimpleValue(info, 1);
4067 v8::Local<v8::Value> end_value = GetSimpleValue(info, 2);
4068 if (ValueIsNull(info.GetIsolate(), string_value) ||
4069 ValueIsNull(info.GetIsolate(), start_value) ||
4070 ValueIsNull(info.GetIsolate(), end_value)) {
4071 info.GetReturnValue().SetNull();
4075 ByteString bsSource = ValueToUTF8String(info.GetIsolate(), string_value);
4076 size_t iLength = bsSource.GetLength();
4078 info.GetReturnValue().SetEmptyString();
4085 std::max(ValueToInteger(info.GetIsolate(), start_value), 1) - 1;
4086 if (iStart >= iLength) {
4087 info.GetReturnValue().SetEmptyString();
4092 size_t iCount = std::max(ValueToInteger(info.GetIsolate(), end_value), 0);
4093 iCount =
std::min(iCount, iLength - iStart);
4094 info.GetReturnValue().Set(fxv8::NewStringHelper(
4095 info.GetIsolate(), bsSource.Substr(iStart, iCount).AsStringView()));
4099void CFXJSE_FormCalcContext::Uuid(
4101 const v8::FunctionCallbackInfo<v8::Value>& info) {
4102 int32_t argc = info.Length();
4103 if (argc < 0 || argc > 1) {
4104 ToFormCalcContext(pThis)->ThrowParamCountMismatchException(
"Uuid");
4110 v8::Local<v8::Value> argOne = GetSimpleValue(info, 0);
4111 iNum =
static_cast<int32_t>(ValueToFloat(info.GetIsolate(), argOne));
4113 info.GetReturnValue().Set(fxv8::NewStringHelper(
4114 info.GetIsolate(), GUIDString(!!iNum).AsStringView()));
4118void CFXJSE_FormCalcContext::Upper(
4120 const v8::FunctionCallbackInfo<v8::Value>& info) {
4121 int32_t argc = info.Length();
4122 if (argc < 1 || argc > 2) {
4123 ToFormCalcContext(pThis)->ThrowParamCountMismatchException(
"Upper");
4127 v8::Local<v8::Value> argOne = GetSimpleValue(info, 0);
4128 if (ValueIsNull(info.GetIsolate(), argOne)) {
4129 info.GetReturnValue().SetNull();
4133 ByteString bsArg = ValueToUTF8String(info.GetIsolate(), argOne);
4136 upperStringBuf.Reserve(wsArg.GetLength());
4137 for (
wchar_t ch : wsArg) {
4138 if ((ch >= 0x61 && ch <= 0x7A) || (ch >= 0xE0 && ch <= 0xFE))
4140 else if (ch == 0x101 || ch == 0x103 || ch == 0x105)
4143 upperStringBuf += ch;
4145 info.GetReturnValue().Set(fxv8::NewStringHelper(
4147 FX_UTF8Encode(upperStringBuf.AsStringView()).AsStringView()));
4151void CFXJSE_FormCalcContext::WordNum(
4153 const v8::FunctionCallbackInfo<v8::Value>& info) {
4154 int32_t argc = info.Length();
4155 if (argc < 1 || argc > 3) {
4156 ToFormCalcContext(pThis)->ThrowParamCountMismatchException(
"WordNum");
4160 v8::Local<v8::Value> numberValue = GetSimpleValue(info, 0);
4161 if (fxv8::IsNull(numberValue)) {
4162 info.GetReturnValue().SetNull();
4165 float fNumber = ValueToFloat(info.GetIsolate(), numberValue);
4167 int32_t iIdentifier = 0;
4169 v8::Local<v8::Value> identifierValue = GetSimpleValue(info, 1);
4170 if (fxv8::IsNull(identifierValue)) {
4171 info.GetReturnValue().SetNull();
4175 static_cast<int32_t>(ValueToFloat(info.GetIsolate(), identifierValue));
4180 v8::Local<v8::Value> localeValue = GetSimpleValue(info, 2);
4181 if (fxv8::IsNull(localeValue)) {
4182 info.GetReturnValue().SetNull();
4185 bsLocale = ValueToUTF8String(info.GetIsolate(), localeValue);
4188 if (isnan(fNumber) || fNumber < 0.0f || fNumber > 922337203685477550.0f) {
4189 info.GetReturnValue().Set(fxv8::NewStringHelper(info.GetIsolate(),
"*"));
4193 ByteString bsWorded = WordUS(bsFormatted.AsStringView(), iIdentifier);
4194 info.GetReturnValue().Set(
4195 fxv8::NewStringHelper(info.GetIsolate(), bsWorded.AsStringView()));
4199void CFXJSE_FormCalcContext::Get(
4201 const v8::FunctionCallbackInfo<v8::Value>& info) {
4202 CFXJSE_FormCalcContext* pContext = ToFormCalcContext(pThis);
4203 if (info.Length() != 1) {
4204 pContext->ThrowParamCountMismatchException(
"Get");
4216 v8::Local<v8::Value> argOne = GetSimpleValue(info, 0);
4217 ByteString bsUrl = ValueToUTF8String(info.GetIsolate(), argOne);
4219 pAppProvider->DownloadURL(WideString::FromUTF8(bsUrl.AsStringView()));
4224 DataVector<uint8_t> data_buf(size);
4227 (
void)pFile->ReadBlockAtOffset(data_buf, 0);
4228 info.GetReturnValue().Set(
4229 fxv8::NewStringHelper(info.GetIsolate(), ByteStringView(data_buf)));
4233void CFXJSE_FormCalcContext::Post(
4235 const v8::FunctionCallbackInfo<v8::Value>& info) {
4236 CFXJSE_FormCalcContext* pContext = ToFormCalcContext(pThis);
4237 int32_t argc = info.Length();
4238 if (argc < 2 || argc > 5) {
4239 pContext->ThrowParamCountMismatchException(
"Post");
4251 v8::Local<v8::Value> argOne = GetSimpleValue(info, 0);
4252 ByteString bsURL = ValueToUTF8String(info.GetIsolate(), argOne);
4254 v8::Local<v8::Value> argTwo = GetSimpleValue(info, 1);
4255 ByteString bsData = ValueToUTF8String(info.GetIsolate(), argTwo);
4259 v8::Local<v8::Value> argThree = GetSimpleValue(info, 2);
4260 bsContentType = ValueToUTF8String(info.GetIsolate(), argThree);
4265 v8::Local<v8::Value> argFour = GetSimpleValue(info, 3);
4266 bsEncode = ValueToUTF8String(info.GetIsolate(), argFour);
4271 v8::Local<v8::Value> argFive = GetSimpleValue(info, 4);
4272 bsHeader = ValueToUTF8String(info.GetIsolate(), argFive);
4282 pContext->ThrowServerDeniedException();
4285 info.GetReturnValue().Set(fxv8::NewStringHelper(
4286 info.GetIsolate(), decodedResponse
.ToUTF8().AsStringView()));
4290void CFXJSE_FormCalcContext::Put(
4292 const v8::FunctionCallbackInfo<v8::Value>& info) {
4293 CFXJSE_FormCalcContext* pContext = ToFormCalcContext(pThis);
4294 int32_t argc = info.Length();
4295 if (argc < 2 || argc > 3) {
4296 pContext->ThrowParamCountMismatchException(
"Put");
4308 v8::Local<v8::Value> argOne = GetSimpleValue(info, 0);
4309 ByteString bsURL = ValueToUTF8String(info.GetIsolate(), argOne);
4311 v8::Local<v8::Value> argTwo = GetSimpleValue(info, 1);
4312 ByteString bsData = ValueToUTF8String(info.GetIsolate(), argTwo);
4316 v8::Local<v8::Value> argThree = GetSimpleValue(info, 2);
4317 bsEncode = ValueToUTF8String(info.GetIsolate(), argThree);
4323 pContext->ThrowServerDeniedException();
4326 info.GetReturnValue().SetEmptyString();
4330void CFXJSE_FormCalcContext::assign_value_operator(
4332 const v8::FunctionCallbackInfo<v8::Value>& info) {
4333 v8::Isolate* pIsolate = info.GetIsolate();
4334 CFXJSE_FormCalcContext* pContext = ToFormCalcContext(pThis);
4335 if (info.Length() != 2) {
4336 pContext->ThrowCompilerErrorException();
4340 v8::Local<v8::Value> lValue = info[0];
4341 v8::Local<v8::Value> rValue = GetSimpleValue(info, 1);
4342 if (fxv8::IsArray(lValue)) {
4343 v8::Local<v8::Array> arr = lValue.As<v8::Array>();
4344 uint32_t iLeftLength = fxv8::GetArrayLengthHelper(arr);
4345 v8::Local<v8::Value> propertyValue =
4346 fxv8::ReentrantGetArrayElementHelper(pIsolate, arr, 1);
4347 for (uint32_t i = 2; i < iLeftLength; i++) {
4348 v8::Local<v8::Value> jsValue =
4349 fxv8::ReentrantGetArrayElementHelper(pIsolate, arr, i);
4350 if (!fxv8::IsObject(jsValue)) {
4351 pContext->ThrowNoDefaultPropertyException(bsFuncName);
4354 v8::Local<v8::Object> jsObjectValue = jsValue.As<v8::Object>();
4355 if (fxv8::IsNull(propertyValue)) {
4356 if (!SetObjectDefaultValue(pIsolate, jsObjectValue, rValue)) {
4357 pContext->ThrowNoDefaultPropertyException(bsFuncName);
4361 fxv8::ReentrantPutObjectPropertyHelper(
4362 pIsolate, jsObjectValue,
4363 fxv8::ReentrantToByteStringHelper(pIsolate, propertyValue)
4368 }
else if (fxv8::IsObject(lValue)) {
4369 if (!SetObjectDefaultValue(pIsolate, lValue.As<v8::Object>(), rValue)) {
4370 pContext->ThrowNoDefaultPropertyException(bsFuncName);
4374 info.GetReturnValue().Set(rValue);
4378void CFXJSE_FormCalcContext::logical_or_operator(
4380 const v8::FunctionCallbackInfo<v8::Value>& info) {
4381 if (info.Length() != 2) {
4382 ToFormCalcContext(pThis)->ThrowCompilerErrorException();
4386 v8::Local<v8::Value> argFirst = GetSimpleValue(info, 0);
4387 v8::Local<v8::Value> argSecond = GetSimpleValue(info, 1);
4388 if (fxv8::IsNull(argFirst) && fxv8::IsNull(argSecond)) {
4389 info.GetReturnValue().SetNull();
4393 float first = ValueToFloat(info.GetIsolate(), argFirst);
4394 float second = ValueToFloat(info.GetIsolate(), argSecond);
4395 info.GetReturnValue().Set(
static_cast<
int>(first || second));
4399void CFXJSE_FormCalcContext::logical_and_operator(
4401 const v8::FunctionCallbackInfo<v8::Value>& info) {
4402 if (info.Length() != 2) {
4403 ToFormCalcContext(pThis)->ThrowCompilerErrorException();
4407 v8::Local<v8::Value> argFirst = GetSimpleValue(info, 0);
4408 v8::Local<v8::Value> argSecond = GetSimpleValue(info, 1);
4409 if (fxv8::IsNull(argFirst) && fxv8::IsNull(argSecond)) {
4410 info.GetReturnValue().SetNull();
4414 float first = ValueToFloat(info.GetIsolate(), argFirst);
4415 float second = ValueToFloat(info.GetIsolate(), argSecond);
4416 info.GetReturnValue().Set(
static_cast<
int>(first && second));
4420void CFXJSE_FormCalcContext::equality_operator(
4422 const v8::FunctionCallbackInfo<v8::Value>& info) {
4423 if (info.Length() != 2) {
4424 ToFormCalcContext(pThis)->ThrowCompilerErrorException();
4428 if (fm_ref_equal(pThis, info)) {
4429 info.GetReturnValue().Set(1);
4433 v8::Local<v8::Value> argFirst = GetSimpleValue(info, 0);
4434 v8::Local<v8::Value> argSecond = GetSimpleValue(info, 1);
4435 if (fxv8::IsNull(argFirst) || fxv8::IsNull(argSecond)) {
4436 info.GetReturnValue().Set(
4437 static_cast<
int>(fxv8::IsNull(argFirst) && fxv8::IsNull(argSecond)));
4441 if (fxv8::IsString(argFirst) && fxv8::IsString(argSecond)) {
4442 info.GetReturnValue().Set(
static_cast<
int>(
4443 fxv8::ReentrantToByteStringHelper(info.GetIsolate(), argFirst) ==
4444 fxv8::ReentrantToByteStringHelper(info.GetIsolate(), argSecond)));
4448 double first = ValueToDouble(info.GetIsolate(), argFirst);
4449 double second = ValueToDouble(info.GetIsolate(), argSecond);
4450 info.GetReturnValue().Set(
static_cast<
int>(first == second));
4454void CFXJSE_FormCalcContext::notequality_operator(
4456 const v8::FunctionCallbackInfo<v8::Value>& info) {
4457 if (info.Length() != 2) {
4458 ToFormCalcContext(pThis)->ThrowCompilerErrorException();
4462 if (fm_ref_equal(pThis, info)) {
4463 info.GetReturnValue().Set(0);
4467 v8::Local<v8::Value> argFirst = GetSimpleValue(info, 0);
4468 v8::Local<v8::Value> argSecond = GetSimpleValue(info, 1);
4469 if (fxv8::IsNull(argFirst) || fxv8::IsNull(argSecond)) {
4470 info.GetReturnValue().Set(
4471 static_cast<
int>(!fxv8::IsNull(argFirst) || !fxv8::IsNull(argSecond)));
4475 if (fxv8::IsString(argFirst) && fxv8::IsString(argSecond)) {
4476 info.GetReturnValue().Set(
static_cast<
int>(
4477 fxv8::ReentrantToByteStringHelper(info.GetIsolate(), argFirst) !=
4478 fxv8::ReentrantToByteStringHelper(info.GetIsolate(), argSecond)));
4482 double first = ValueToDouble(info.GetIsolate(), argFirst);
4483 double second = ValueToDouble(info.GetIsolate(), argSecond);
4484 info.GetReturnValue().Set(
static_cast<
int>(first != second));
4488bool CFXJSE_FormCalcContext::fm_ref_equal(
4490 const v8::FunctionCallbackInfo<v8::Value>& info) {
4491 v8::Local<v8::Value> argFirst = info[0];
4492 v8::Local<v8::Value> argSecond = info[1];
4493 if (!fxv8::IsArray(argFirst) || !fxv8::IsArray(argSecond))
4496 v8::Local<v8::Array> firstArr = argFirst.As<v8::Array>();
4497 v8::Local<v8::Array> secondArr = argSecond.As<v8::Array>();
4498 v8::Local<v8::Value> firstFlag =
4499 fxv8::ReentrantGetArrayElementHelper(info.GetIsolate(), firstArr, 0);
4500 v8::Local<v8::Value> secondFlag =
4501 fxv8::ReentrantGetArrayElementHelper(info.GetIsolate(), secondArr, 0);
4502 if (fxv8::ReentrantToInt32Helper(info.GetIsolate(), firstFlag) != 3 ||
4503 fxv8::ReentrantToInt32Helper(info.GetIsolate(), secondFlag) != 3) {
4507 v8::Local<v8::Value> firstValue =
4508 fxv8::ReentrantGetArrayElementHelper(info.GetIsolate(), firstArr, 2);
4509 v8::Local<v8::Value> secondValue =
4510 fxv8::ReentrantGetArrayElementHelper(info.GetIsolate(), secondArr, 2);
4512 if (fxv8::IsNull(firstValue) || fxv8::IsNull(secondValue))
4515 return FXJSE_RetrieveObjectBinding(firstValue) ==
4516 FXJSE_RetrieveObjectBinding(secondValue);
4520void CFXJSE_FormCalcContext::less_operator(
4522 const v8::FunctionCallbackInfo<v8::Value>& info) {
4523 if (info.Length() != 2) {
4524 ToFormCalcContext(pThis)->ThrowCompilerErrorException();
4528 v8::Local<v8::Value> argFirst = GetSimpleValue(info, 0);
4529 v8::Local<v8::Value> argSecond = GetSimpleValue(info, 1);
4530 if (fxv8::IsNull(argFirst) || fxv8::IsNull(argSecond)) {
4531 info.GetReturnValue().Set(0);
4535 if (fxv8::IsString(argFirst) && fxv8::IsString(argSecond)) {
4537 fxv8::ReentrantToByteStringHelper(info.GetIsolate(), argFirst);
4539 fxv8::ReentrantToByteStringHelper(info.GetIsolate(), argSecond);
4540 info.GetReturnValue().Set(bs1
.Compare(bs2.AsStringView()
) < 0);
4544 double first = ValueToDouble(info.GetIsolate(), argFirst);
4545 double second = ValueToDouble(info.GetIsolate(), argSecond);
4546 info.GetReturnValue().Set(
static_cast<
int>(first < second));
4550void CFXJSE_FormCalcContext::lessequal_operator(
4552 const v8::FunctionCallbackInfo<v8::Value>& info) {
4553 if (info.Length() != 2) {
4554 ToFormCalcContext(pThis)->ThrowCompilerErrorException();
4558 v8::Local<v8::Value> argFirst = GetSimpleValue(info, 0);
4559 v8::Local<v8::Value> argSecond = GetSimpleValue(info, 1);
4560 if (fxv8::IsNull(argFirst) || fxv8::IsNull(argSecond)) {
4561 info.GetReturnValue().Set(
4562 static_cast<
int>(fxv8::IsNull(argFirst) && fxv8::IsNull(argSecond)));
4566 if (fxv8::IsString(argFirst) && fxv8::IsString(argSecond)) {
4567 auto bs1 = fxv8::ReentrantToByteStringHelper(info.GetIsolate(), argFirst);
4568 auto bs2 = fxv8::ReentrantToByteStringHelper(info.GetIsolate(), argSecond);
4569 info.GetReturnValue().Set(bs1.Compare(bs2.AsStringView()) <= 0);
4573 double first = ValueToDouble(info.GetIsolate(), argFirst);
4574 double second = ValueToDouble(info.GetIsolate(), argSecond);
4575 info.GetReturnValue().Set(
static_cast<
int>(first <= second));
4579void CFXJSE_FormCalcContext::greater_operator(
4581 const v8::FunctionCallbackInfo<v8::Value>& info) {
4582 if (info.Length() != 2) {
4583 ToFormCalcContext(pThis)->ThrowCompilerErrorException();
4587 v8::Local<v8::Value> argFirst = GetSimpleValue(info, 0);
4588 v8::Local<v8::Value> argSecond = GetSimpleValue(info, 1);
4589 if (fxv8::IsNull(argFirst) || fxv8::IsNull(argSecond)) {
4590 info.GetReturnValue().Set(0);
4594 if (fxv8::IsString(argFirst) && fxv8::IsString(argSecond)) {
4595 auto bs1 = fxv8::ReentrantToByteStringHelper(info.GetIsolate(), argFirst);
4596 auto bs2 = fxv8::ReentrantToByteStringHelper(info.GetIsolate(), argSecond);
4597 info.GetReturnValue().Set(bs1.Compare(bs2.AsStringView()) > 0);
4601 double first = ValueToDouble(info.GetIsolate(), argFirst);
4602 double second = ValueToDouble(info.GetIsolate(), argSecond);
4603 info.GetReturnValue().Set(
static_cast<
int>(first > second));
4607void CFXJSE_FormCalcContext::greaterequal_operator(
4609 const v8::FunctionCallbackInfo<v8::Value>& info) {
4610 if (info.Length() != 2) {
4611 ToFormCalcContext(pThis)->ThrowCompilerErrorException();
4615 v8::Local<v8::Value> argFirst = GetSimpleValue(info, 0);
4616 v8::Local<v8::Value> argSecond = GetSimpleValue(info, 1);
4617 if (fxv8::IsNull(argFirst) || fxv8::IsNull(argSecond)) {
4618 info.GetReturnValue().Set(
4619 static_cast<
int>(fxv8::IsNull(argFirst) && fxv8::IsNull(argSecond)));
4623 if (fxv8::IsString(argFirst) && fxv8::IsString(argSecond)) {
4624 auto bs1 = fxv8::ReentrantToByteStringHelper(info.GetIsolate(), argFirst);
4625 auto bs2 = fxv8::ReentrantToByteStringHelper(info.GetIsolate(), argSecond);
4626 info.GetReturnValue().Set(bs1.Compare(bs2.AsStringView()) >= 0);
4630 double first = ValueToDouble(info.GetIsolate(), argFirst);
4631 double second = ValueToDouble(info.GetIsolate(), argSecond);
4632 info.GetReturnValue().Set(
static_cast<
int>(first >= second));
4636void CFXJSE_FormCalcContext::plus_operator(
4638 const v8::FunctionCallbackInfo<v8::Value>& info) {
4639 if (info.Length() != 2) {
4640 ToFormCalcContext(pThis)->ThrowCompilerErrorException();
4644 if (ValueIsNull(info.GetIsolate(), info[0]) &&
4645 ValueIsNull(info.GetIsolate(), info[1])) {
4646 info.GetReturnValue().SetNull();
4650 const double first = ValueToDouble(info.GetIsolate(), info[0]);
4651 const double second = ValueToDouble(info.GetIsolate(), info[1]);
4652 info.GetReturnValue().Set(first + second);
4656void CFXJSE_FormCalcContext::minus_operator(
4658 const v8::FunctionCallbackInfo<v8::Value>& info) {
4659 if (info.Length() != 2) {
4660 ToFormCalcContext(pThis)->ThrowCompilerErrorException();
4664 v8::Local<v8::Value> argFirst = GetSimpleValue(info, 0);
4665 v8::Local<v8::Value> argSecond = GetSimpleValue(info, 1);
4666 if (fxv8::IsNull(argFirst) && fxv8::IsNull(argSecond)) {
4667 info.GetReturnValue().SetNull();
4671 double first = ValueToDouble(info.GetIsolate(), argFirst);
4672 double second = ValueToDouble(info.GetIsolate(), argSecond);
4673 info.GetReturnValue().Set(first - second);
4677void CFXJSE_FormCalcContext::multiple_operator(
4679 const v8::FunctionCallbackInfo<v8::Value>& info) {
4680 if (info.Length() != 2) {
4681 ToFormCalcContext(pThis)->ThrowCompilerErrorException();
4685 v8::Local<v8::Value> argFirst = GetSimpleValue(info, 0);
4686 v8::Local<v8::Value> argSecond = GetSimpleValue(info, 1);
4687 if (fxv8::IsNull(argFirst) && fxv8::IsNull(argSecond)) {
4688 info.GetReturnValue().SetNull();
4692 double first = ValueToDouble(info.GetIsolate(), argFirst);
4693 double second = ValueToDouble(info.GetIsolate(), argSecond);
4694 info.GetReturnValue().Set(first * second);
4698void CFXJSE_FormCalcContext::divide_operator(
4700 const v8::FunctionCallbackInfo<v8::Value>& info) {
4701 CFXJSE_FormCalcContext* pContext = ToFormCalcContext(pThis);
4702 if (info.Length() != 2) {
4703 pContext->ThrowCompilerErrorException();
4707 v8::Local<v8::Value> argFirst = GetSimpleValue(info, 0);
4708 v8::Local<v8::Value> argSecond = GetSimpleValue(info, 1);
4709 if (fxv8::IsNull(argFirst) && fxv8::IsNull(argSecond)) {
4710 info.GetReturnValue().SetNull();
4714 double second = ValueToDouble(info.GetIsolate(), argSecond);
4715 if (second == 0.0) {
4716 pContext->ThrowDivideByZeroException();
4720 double first = ValueToDouble(info.GetIsolate(), argFirst);
4721 info.GetReturnValue().Set(first / second);
4725void CFXJSE_FormCalcContext::positive_operator(
4727 const v8::FunctionCallbackInfo<v8::Value>& info) {
4728 if (info.Length() != 1) {
4729 ToFormCalcContext(pThis)->ThrowCompilerErrorException();
4733 v8::Local<v8::Value> argOne = GetSimpleValue(info, 0);
4734 if (fxv8::IsNull(argOne)) {
4735 info.GetReturnValue().SetNull();
4738 info.GetReturnValue().Set(0.0 + ValueToDouble(info.GetIsolate(), argOne));
4742void CFXJSE_FormCalcContext::negative_operator(
4744 const v8::FunctionCallbackInfo<v8::Value>& info) {
4745 if (info.Length() != 1) {
4746 ToFormCalcContext(pThis)->ThrowCompilerErrorException();
4750 v8::Local<v8::Value> argOne = GetSimpleValue(info, 0);
4751 if (fxv8::IsNull(argOne)) {
4752 info.GetReturnValue().SetNull();
4755 info.GetReturnValue().Set(0.0 - ValueToDouble(info.GetIsolate(), argOne));
4759void CFXJSE_FormCalcContext::logical_not_operator(
4761 const v8::FunctionCallbackInfo<v8::Value>& info) {
4762 if (info.Length() != 1) {
4763 ToFormCalcContext(pThis)->ThrowCompilerErrorException();
4767 v8::Local<v8::Value> argOne = GetSimpleValue(info, 0);
4768 if (fxv8::IsNull(argOne)) {
4769 info.GetReturnValue().SetNull();
4773 double first = ValueToDouble(info.GetIsolate(), argOne);
4774 info.GetReturnValue().Set((first == 0.0) ? 1 : 0);
4778void CFXJSE_FormCalcContext::dot_accessor(
4780 const v8::FunctionCallbackInfo<v8::Value>& info) {
4781 DotAccessorCommon(pThis, info,
true);
4785void CFXJSE_FormCalcContext::dotdot_accessor(
4787 const v8::FunctionCallbackInfo<v8::Value>& info) {
4788 DotAccessorCommon(pThis, info,
false);
4792void CFXJSE_FormCalcContext::eval_translation(
4794 const v8::FunctionCallbackInfo<v8::Value>& info) {
4795 CFXJSE_FormCalcContext* pContext = ToFormCalcContext(pThis);
4796 if (info.Length() != 1) {
4797 pContext->ThrowParamCountMismatchException(
"Eval");
4801 v8::Local<v8::Value> argOne = GetSimpleValue(info, 0);
4802 ByteString bsArg = ValueToUTF8String(info.GetIsolate(), argOne);
4803 if (bsArg.IsEmpty()) {
4804 pContext->ThrowArgumentMismatchException();
4809 std::optional<WideTextBuffer> wsJavaScriptBuf =
4810 CFXJSE_FormCalcContext::Translate(pContext->GetDocument()->GetHeap(),
4811 wsCalcScript.AsStringView());
4812 if (!wsJavaScriptBuf.has_value()) {
4813 pContext->ThrowCompilerErrorException();
4816 info.GetReturnValue().Set(fxv8::NewStringHelper(
4818 FX_UTF8Encode(wsJavaScriptBuf.value().AsStringView()).AsStringView()));
4822void CFXJSE_FormCalcContext::is_fm_object(
4824 const v8::FunctionCallbackInfo<v8::Value>& info) {
4826 info.GetReturnValue().Set(result);
4830void CFXJSE_FormCalcContext::is_fm_array(
4832 const v8::FunctionCallbackInfo<v8::Value>& info) {
4834 info.GetReturnValue().Set(result);
4838void CFXJSE_FormCalcContext::get_fm_value(
4840 const v8::FunctionCallbackInfo<v8::Value>& info) {
4841 CFXJSE_FormCalcContext* pContext = ToFormCalcContext(pThis);
4842 if (info.Length() != 1) {
4843 pContext->ThrowCompilerErrorException();
4847 v8::Local<v8::Value> argOne = info[0];
4848 if (fxv8::IsArray(argOne)) {
4849 v8::Local<v8::Array> arr = argOne.As<v8::Array>();
4850 v8::Local<v8::Value> propertyValue =
4851 fxv8::ReentrantGetArrayElementHelper(info.GetIsolate(), arr, 1);
4852 v8::Local<v8::Value> jsValue =
4853 fxv8::ReentrantGetArrayElementHelper(info.GetIsolate(), arr, 2);
4854 if (!fxv8::IsObject(jsValue)) {
4855 info.GetReturnValue().Set(fxv8::NewUndefinedHelper(info.GetIsolate()));
4858 v8::Local<v8::Object> jsObjectValue = jsValue.As<v8::Object>();
4859 if (fxv8::IsNull(propertyValue)) {
4860 info.GetReturnValue().Set(
4861 GetObjectDefaultValue(info.GetIsolate(), jsObjectValue));
4865 fxv8::ReentrantToByteStringHelper(info.GetIsolate(), propertyValue);
4866 info.GetReturnValue().Set(fxv8::ReentrantGetObjectPropertyHelper(
4867 info.GetIsolate(), jsObjectValue, bsName.AsStringView()));
4871 if (fxv8::IsObject(argOne)) {
4872 v8::Local<v8::Object> obj = argOne.As<v8::Object>();
4873 info.GetReturnValue().Set(GetObjectDefaultValue(info.GetIsolate(), obj));
4877 info.GetReturnValue().Set(argOne);
4881void CFXJSE_FormCalcContext::get_fm_jsobj(
4883 const v8::FunctionCallbackInfo<v8::Value>& info) {
4884 if (info.Length() != 1) {
4885 ToFormCalcContext(pThis)->ThrowCompilerErrorException();
4889 v8::Local<v8::Value> argOne = info[0];
4890 if (!fxv8::IsArray(argOne)) {
4891 info.GetReturnValue().Set(argOne);
4895 v8::Local<v8::Array> arr = argOne.As<v8::Array>();
4896 info.GetReturnValue().Set(
4897 fxv8::ReentrantGetArrayElementHelper(info.GetIsolate(), arr, 2));
4901void CFXJSE_FormCalcContext::fm_var_filter(
4903 const v8::FunctionCallbackInfo<v8::Value>& info) {
4904 CFXJSE_FormCalcContext* pContext = ToFormCalcContext(pThis);
4905 if (info.Length() != 1) {
4906 pContext->ThrowCompilerErrorException();
4910 v8::Local<v8::Value> argOne = info[0];
4911 if (!fxv8::IsArray(argOne)) {
4912 info.GetReturnValue().Set(GetSimpleValue(info, 0));
4916 v8::Local<v8::Array> arr = argOne.As<v8::Array>();
4917 v8::Local<v8::Value> flagsValue =
4918 fxv8::ReentrantGetArrayElementHelper(info.GetIsolate(), arr, 0);
4919 int32_t iFlags = fxv8::ReentrantToInt32Helper(info.GetIsolate(), flagsValue);
4920 if (iFlags != 3 && iFlags != 4) {
4921 info.GetReturnValue().Set(GetSimpleValue(info, 0));
4926 v8::LocalVector<v8::Value> values(info.GetIsolate(), 3);
4927 values[0] = fxv8::NewNumberHelper(info.GetIsolate(), 3);
4928 values[1] = fxv8::NewNullHelper(info.GetIsolate());
4929 values[2] = fxv8::NewNullHelper(info.GetIsolate());
4930 info.GetReturnValue().Set(fxv8::NewArrayHelper(info.GetIsolate(), values));
4934 v8::Local<v8::Value> objectValue =
4935 fxv8::ReentrantGetArrayElementHelper(info.GetIsolate(), arr, 2);
4936 if (fxv8::IsNull(objectValue)) {
4937 pContext->ThrowCompilerErrorException();
4940 info.GetReturnValue().Set(argOne);
4944void CFXJSE_FormCalcContext::concat_fm_object(
4946 const v8::FunctionCallbackInfo<v8::Value>& info) {
4947 v8::Isolate* pIsolate = ToFormCalcContext(pThis)->GetIsolate();
4948 v8::LocalVector<v8::Value> returnValues(pIsolate);
4949 for (
int i = 0; i < info.Length(); ++i) {
4951 v8::Local<v8::Array> arr = info[i].As<v8::Array>();
4952 uint32_t length = fxv8::GetArrayLengthHelper(arr);
4953 for (uint32_t j = 2; j < length; j++) {
4954 returnValues.push_back(
4955 fxv8::ReentrantGetArrayElementHelper(info.GetIsolate(), arr, j));
4958 returnValues.push_back(info[i]);
4960 info.GetReturnValue().Set(fxv8::NewArrayHelper(pIsolate, returnValues));
4965 int32_t iIndexFlags,
4966 int32_t iIndexValue,
4973 if (iIndexFlags == 0)
4976 if (iIndexFlags == 1 || iIndexValue == 0) {
4981 const bool bNegative = iIndexValue < 0;
4983 if (iIndexFlags == 2) {
4984 bsSomExp
+= bNegative ?
"[-" :
"[+";
4987 bsSomExp
+= bNegative ?
"[" :
"[-";
4992 safe_index = -safe_index;
5001 if (wsFormcalc.IsEmpty())
5002 return WideTextBuffer();
5008 return std::nullopt;
5011 std::optional<WideTextBuffer> wsJavaScript = ast->ToJavaScript();
5012 if (!wsJavaScript.has_value())
5013 return std::nullopt;
5015 if (CXFA_IsTooBig(wsJavaScript.value()))
5016 return std::nullopt;
5018 return wsJavaScript;
5021CFXJSE_FormCalcContext::CFXJSE_FormCalcContext(
v8::Isolate* pIsolate,
5023 CXFA_Document* pDoc)
5024 : m_pIsolate(pIsolate), m_pDocument(pDoc) {
5025 m_Value.Reset(m_pIsolate,
5027 m_pIsolate, CFXJSE_Class::Create(
5028 pScriptContext, &kFormCalcDescriptor,
false)
5029 ->GetTemplate(m_pIsolate)));
5039 return v8::Local<v8::Value>::New(m_pIsolate, m_Value);
5043void CFXJSE_FormCalcContext::DotAccessorCommon(
5045 const v8::FunctionCallbackInfo<v8::Value>& info,
5046 bool bDotAccessor) {
5047 CFXJSE_FormCalcContext* pContext = ToFormCalcContext(pThis);
5048 v8::Isolate* pIsolate = pContext->GetIsolate();
5049 int32_t argc = info.Length();
5050 if (argc < 4 || argc > 5) {
5051 pContext->ThrowCompilerErrorException();
5055 bool bIsStar =
true;
5056 int32_t iIndexValue = 0;
5059 iIndexValue = ValueToInteger(info.GetIsolate(), info[4]);
5064 const bool bHasNoResolveName = bDotAccessor && bsName.IsEmpty();
5066 bsName.AsStringView(),
5070 v8::Local<v8::Value> argAccessor = info[0];
5071 if (fxv8::IsArray(argAccessor)) {
5072 v8::Local<v8::Array> arr = argAccessor.As<v8::Array>();
5073 uint32_t iLength = fxv8::GetArrayLengthHelper(arr);
5075 pContext->ThrowArgumentMismatchException();
5080 std::vector<v8::LocalVector<v8::Value>> resolveValues(
5081 iLength - 2, v8::LocalVector<v8::Value>(info.GetIsolate()));
5083 bool bAttribute =
false;
5084 bool bAllEmpty =
true;
5085 for (uint32_t i = 2; i < iLength; i++) {
5086 v8::Local<v8::Value> hJSObjValue =
5087 fxv8::ReentrantGetArrayElementHelper(info.GetIsolate(), arr, i);
5089 ResolveObjects(pThis, hJSObjValue, bsSomExp.AsStringView(),
5090 bDotAccessor, bHasNoResolveName);
5091 if (maybeResult.has_value()) {
5092 resolveValues[i - 2] = ParseResolveResult(pThis, maybeResult.value(),
5093 hJSObjValue, &bAttribute);
5094 bAllEmpty = bAllEmpty && resolveValues[i - 2].empty();
5098 pContext->ThrowPropertyNotInObjectException(bsName.AsStringView(),
5099 bsSomExp.AsStringView());
5103 v8::LocalVector<v8::Value> values(pIsolate);
5104 values.push_back(fxv8::NewNumberHelper(pIsolate, 1));
5106 bAttribute ? fxv8::NewStringHelper(pIsolate, bsName.AsStringView())
5108 : fxv8::NewNullHelper(pIsolate).As<v8::Value>());
5109 for (uint32_t i = 0; i < iLength - 2; i++) {
5110 for (size_t j = 0; j < resolveValues[i].size(); j++)
5111 values.push_back(resolveValues[i][j]);
5113 info.GetReturnValue().Set(fxv8::NewArrayHelper(pIsolate, values));
5120 if (fxv8::IsObject(argAccessor) ||
5121 (fxv8::IsNull(argAccessor) && bsAccessorName.IsEmpty())) {
5122 maybeResult = ResolveObjects(pThis, argAccessor, bsSomExp.AsStringView(),
5123 bDotAccessor, bHasNoResolveName);
5124 }
else if (!fxv8::IsObject(argAccessor) && !bsAccessorName.IsEmpty()) {
5125 v8::Local<v8::Value> obj =
5126 GetObjectForName(pThis, bsAccessorName.AsStringView());
5127 if (!obj.IsEmpty()) {
5129 maybeResult = ResolveObjects(pThis, argAccessor, bsSomExp.AsStringView(),
5130 bDotAccessor, bHasNoResolveName);
5133 if (!maybeResult.has_value()) {
5134 pContext->ThrowPropertyNotInObjectException(bsName.AsStringView(),
5135 bsSomExp.AsStringView());
5139 bool bAttribute =
false;
5140 v8::LocalVector<v8::Value> resolveValues =
5141 ParseResolveResult(pThis, maybeResult.value(), argAccessor, &bAttribute);
5143 v8::LocalVector<v8::Value> values(pIsolate, resolveValues.size() + 2);
5144 values[0] = fxv8::NewNumberHelper(pIsolate, 1);
5145 values[1] = bAttribute
5146 ? fxv8::NewStringHelper(pIsolate, bsName.AsStringView())
5148 : fxv8::NewNullHelper(pIsolate).As<v8::Value>();
5150 for (size_t i = 0; i < resolveValues.size(); i++)
5151 values[i + 2] = resolveValues[i];
5153 info.GetReturnValue().Set(fxv8::NewArrayHelper(pIsolate, values));
5157bool CFXJSE_FormCalcContext::IsIsoDateFormat(
ByteStringView bsData,
5161 pdfium::span<
const char> pData = bsData.span();
5163 int32_t& iYear = *pYear;
5164 int32_t& iMonth = *pMonth;
5165 int32_t& iDay = *pDay;
5171 if (pData.size() < 4) {
5175 std::array<
char, 5> szYear = {};
5176 for (int32_t i = 0; i < 4; ++i) {
5177 if (!isdigit(pData[i])) {
5180 szYear[i] = pData[i];
5182 iYear = FXSYS_atoi(szYear.data());
5183 if (pData.size() == 4) {
5187 int32_t iStyle = pData[4] ==
'-' ? 1 : 0;
5188 size_t iPosOff = iStyle == 0 ? 4 : 5;
5189 if (!isdigit(pData[iPosOff]) || !isdigit(pData[iPosOff + 1])) {
5193 char szBuffer[3] = {};
5194 szBuffer[0] = pData[iPosOff];
5195 szBuffer[1] = pData[iPosOff + 1];
5197 if (iMonth > 12 || iMonth < 1) {
5203 if (pData.size() == 6) {
5208 if (pData.size() == 7) {
5212 if (!isdigit(pData[iPosOff]) || !isdigit(pData[iPosOff + 1])) {
5216 szBuffer[0] = pData[iPosOff];
5217 szBuffer[1] = pData[iPosOff + 1];
5219 if (iPosOff + 2 < pData.size()) {
5224 bool bIsLeap = (!(iYear % 4) && (iYear % 100)) || !(iYear % 400);
5225 return iDay <= (bIsLeap ? 29 : 28);
5229 return iDay <= (iMonth % 2 == 0 ? 30 : 31);
5231 return iDay <= (iMonth % 2 == 0 ? 31 : 30);
5235bool CFXJSE_FormCalcContext::IsIsoTimeFormat(
ByteStringView bsData) {
5236 enum State { kHour, kMinute, kSecond, kZoneHour, kZoneMinute, kFinished };
5238 pdfium::span<
const char> pData = bsData.span();
5239 if (pData.empty()) {
5245 while (i < pData.size()) {
5246 if (!isdigit(pData[i]) && pData[i] !=
':') {
5252 if (i == pData.size()) {
5253 iZone = pData.size();
5256 char szBuffer[3] = {};
5257 State state = kHour;
5259 while (iIndex + 1 < iZone) {
5260 szBuffer[0] = pData[iIndex];
5261 szBuffer[1] = pData[iIndex + 1];
5262 if (!isdigit(szBuffer[0]) || !isdigit(szBuffer[1])) {
5266 if (state == kHour) {
5271 }
else if (state == kMinute) {
5276 }
else if (state == kSecond) {
5286 if (iIndex < iZone && pData[iIndex] ==
':') {
5291 if (iIndex < pData.size() && pData[iIndex] ==
'.') {
5292 constexpr int kSubSecondLength = 3;
5293 if (iIndex + kSubSecondLength >= pData.size()) {
5298 std::array<
char, kSubSecondLength + 1> szMilliSeconds = {};
5299 for (
int j = 0; j < kSubSecondLength; ++j) {
5300 char c = pData[iIndex + j];
5304 szMilliSeconds[j] = c;
5306 if (FXSYS_atoi(szMilliSeconds.data()) >= 1000) {
5309 iIndex += kSubSecondLength;
5312 if (iIndex < pData.size() && FXSYS_towlower(pData[iIndex]) ==
'z') {
5316 if (iIndex < pData.size()) {
5317 if (pData[iIndex] ==
'+') {
5319 }
else if (pData[iIndex] ==
'-') {
5324 while (iIndex + 1 < pData.size()) {
5325 szBuffer[0] = pData[iIndex];
5326 szBuffer[1] = pData[iIndex + 1];
5327 if (!isdigit(szBuffer[0]) || !isdigit(szBuffer[1])) {
5331 if (state == kZoneHour) {
5335 state = kZoneMinute;
5336 }
else if (state == kZoneMinute) {
5345 if (iIndex < pData.size() && pData[iIndex] ==
':') {
5351 return iIndex == pData.size();
5354bool CFXJSE_FormCalcContext::IsIsoDateTimeFormat(
ByteStringView bsData,
5363 while (iIndex < bsData.GetLength()) {
5364 if (bsData[iIndex] ==
'T' || bsData[iIndex] ==
't') {
5369 if (iIndex == bsData.GetLength() || (iIndex != 8 && iIndex != 10)) {
5375 return IsIsoDateFormat(date_part, pYear, pMonth, pDay) &&
5376 IsIsoTimeFormat(time_part);
5380int32_t CFXJSE_FormCalcContext::DateString2Num(
ByteStringView bsDate) {
5384 if (bsDate.GetLength() <= 10) {
5385 if (!IsIsoDateFormat(bsDate, &iYear, &iMonth, &iDay)) {
5389 if (!IsIsoDateTimeFormat(bsDate, &iYear, &iMonth, &iDay)) {
5400 while (iYear - i >= 1900) {
5402 ((!((iYear - i) % 4) && ((iYear - i) % 100)) || !((iYear - i) % 400))
5408 while (i < iMonth) {
5410 dDays += ((!(iYear % 4) && (iYear % 100)) || !(iYear % 400)) ? 29 : 28;
5411 }
else if (i <= 7) {
5412 dDays += (i % 2 == 0) ? 30 : 31;
5414 dDays += (i % 2 == 0) ? 31 : 30;
5420 while (iDay - i > 0) {
5424 return static_cast<int32_t>(dDays);
5427bool CFXJSE_FormCalcContext::ApplyToExpansion(
5428 std::function<
void(
v8::Isolate*, v8::Local<v8::Value>)> fn,
5429 const v8::FunctionCallbackInfo<v8::Value>& info,
5431 v8::Isolate* pIsolate = info.GetIsolate();
5432 for (int32_t i = 0; i < info.Length(); i++) {
5433 v8::Local<v8::Value> argValue = info[i];
5434 if (fxv8::IsArray(argValue)) {
5435 if (!ApplyToArray(pIsolate, fn, argValue.As<v8::Array>()) && bStrict) {
5436 ThrowArgumentMismatchException();
5439 }
else if (fxv8::IsObject(argValue)) {
5440 ApplyToObject(pIsolate, fn, argValue.As<v8::Object>());
5441 }
else if (!fxv8::IsNull(argValue)) {
5442 fn(pIsolate, argValue);
5448bool CFXJSE_FormCalcContext::ApplyToArray(
5449 v8::Isolate* pIsolate,
5450 std::function<
void(
v8::Isolate*, v8::Local<v8::Value>)> fn,
5451 v8::Local<v8::Array> pArray) {
5452 uint32_t iLength = fxv8::GetArrayLengthHelper(pArray);
5456 v8::Local<v8::Value> propertyValue =
5457 fxv8::ReentrantGetArrayElementHelper(pIsolate, pArray, 1);
5460 const bool nullprop = fxv8::IsNull(propertyValue);
5462 bsName = fxv8::ReentrantToByteStringHelper(pIsolate, propertyValue);
5464 for (uint32_t j = 2; j < iLength; j++) {
5465 v8::Local<v8::Value> jsValue =
5466 fxv8::ReentrantGetArrayElementHelper(pIsolate, pArray, j);
5467 if (!fxv8::IsObject(jsValue))
5470 v8::Local<v8::Object> jsObjectValue = jsValue.As<v8::Object>();
5471 v8::Local<v8::Value> newPropertyValue =
5472 nullprop ? GetObjectDefaultValue(pIsolate, jsObjectValue)
5473 : fxv8::ReentrantGetObjectPropertyHelper(
5474 pIsolate, jsObjectValue, bsName.AsStringView());
5475 if (!fxv8::IsNull(newPropertyValue))
5476 fn(pIsolate, newPropertyValue);
5481void CFXJSE_FormCalcContext::ApplyToObject(
5482 v8::Isolate* pIsolate,
5483 std::function<
void(
v8::Isolate*, v8::Local<v8::Value>)> fn,
5484 v8::Local<v8::Object> pObject) {
5485 v8::Local<v8::Value> newPropertyValue =
5486 GetObjectDefaultValue(pIsolate, pObject);
5487 if (!fxv8::IsNull(newPropertyValue))
5488 fn(pIsolate, newPropertyValue);
5491void CFXJSE_FormCalcContext::ThrowNoDefaultPropertyException(
5494 msg
+= " doesn't have a default property.";
5495 ThrowException(msg.AsStringView());
5498void CFXJSE_FormCalcContext::ThrowCompilerErrorException()
const {
5499 ThrowException(
"Compiler error.");
5502void CFXJSE_FormCalcContext::ThrowDivideByZeroException()
const {
5503 ThrowException(
"Divide by zero.");
5506void CFXJSE_FormCalcContext::ThrowServerDeniedException()
const {
5507 ThrowException(
"Server does not permit operation.");
5510void CFXJSE_FormCalcContext::ThrowPropertyNotInObjectException(
5513 ByteString msg
("An attempt was made to reference property '");
5515 msg
+= "' of a non-object in SOM expression ";
5518 ThrowException(msg.AsStringView());
5521void CFXJSE_FormCalcContext::ThrowParamCountMismatchException(
5523 ByteString msg
("Incorrect number of parameters calling method '");
5526 ThrowException(msg.AsStringView());
5529void CFXJSE_FormCalcContext::ThrowArgumentMismatchException()
const {
5530 ThrowException(
"Argument mismatch in property or function argument.");
5533void CFXJSE_FormCalcContext::ThrowException(
ByteStringView str)
const {
5535 FXJSE_ThrowMessage(GetIsolate(), str);
fxcrt::ByteString ByteString
const FXJSE_CLASS_DESCRIPTOR kFormCalcDescriptor
CFGAS_Decimal(float val, uint8_t scale)
XFA_SCRIPTATTRIBUTEINFO script_attribute
CXFA_Object * GetThisObject() const
friend class EventParamScope
std::optional< ResolveResult > ResolveObjects(CXFA_Object *refObject, WideStringView wsExpression, Mask< XFA_ResolveFlag > dwStyles)
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
static std::optional< WideTextBuffer > Translate(cppgc::Heap *pHeap, WideStringView wsFormcalc)
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)
void TrimWhitespaceFront()
ByteString & operator=(const ByteString &that)
int Compare(ByteStringView str) const
void TrimWhitespaceBack()
ByteString ToUTF8() const
WideString & operator=(WideString &&that) noexcept
static WideString FromUTF8(ByteStringView str)
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)
pdfium::CheckedNumeric< int32_t > FX_SAFE_INT32
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)
fxcrt::ByteStringView ByteStringView
fxcrt::WideStringView WideStringView
XFA_ScriptType eValueType
XFA_ATTRIBUTE_CALLBACK callback
fxcrt::WideString WideString