blob: 42aa5279b78df94a646e162bfa7c584a640924e6 [file] [log] [blame]
Dan Sinclair1770c022016-03-14 14:14:16 -04001// Copyright 2014 PDFium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
6
7#include "xfa/fxfa/fm2js/xfa_fm2jscontext.h"
8
9#include <time.h>
10
Dan Sinclaira8a28e02016-03-23 15:41:39 -040011#include "core/fxcrt/include/fx_ext.h"
Dan Sinclair1770c022016-03-14 14:14:16 -040012#include "xfa/fgas/localization/fgas_locale.h"
dsinclairdf4bc592016-03-31 20:34:43 -070013#include "xfa/fxfa/app/xfa_ffnotify.h"
dsinclaire80e9f82016-06-01 06:10:04 -070014#include "xfa/fxfa/fm2js/xfa_program.h"
Dan Sinclair1770c022016-03-14 14:14:16 -040015#include "xfa/fxfa/parser/xfa_document.h"
16#include "xfa/fxfa/parser/xfa_localevalue.h"
17#include "xfa/fxfa/parser/xfa_parser.h"
dsinclairdf4bc592016-03-31 20:34:43 -070018#include "xfa/fxfa/parser/xfa_parser_imp.h"
19#include "xfa/fxfa/parser/xfa_script_imp.h"
Dan Sinclair3a8051c2016-03-15 15:42:31 -040020#include "xfa/fxjse/cfxjse_arguments.h"
dsinclair769b1372016-06-08 13:12:41 -070021#include "xfa/fxjse/class.h"
dsinclair86fad992016-05-31 11:34:04 -070022#include "xfa/fxjse/value.h"
Dan Sinclair1770c022016-03-14 14:14:16 -040023
Dan Sinclair1770c022016-03-14 14:14:16 -040024namespace {
25
dsinclair48d91dd2016-05-31 11:54:01 -070026const double kFinancialPrecision = 0.00000001;
27
Dan Sinclair1770c022016-03-14 14:14:16 -040028struct XFA_FMHtmlReserveCode {
29 uint32_t m_uCode;
30 const FX_WCHAR* m_htmlReserve;
31};
dsinclair48d91dd2016-05-31 11:54:01 -070032
Dan Sinclair1770c022016-03-14 14:14:16 -040033struct XFA_FMHtmlHashedReserveCode {
34 uint32_t m_uHash;
Dan Sinclair1770c022016-03-14 14:14:16 -040035 uint32_t m_uCode;
36};
37
38const XFA_FMHtmlHashedReserveCode reservesForDecode[] = {
dsinclair89ba6de2016-05-31 12:11:22 -070039 {0x00018b62, /*L"Mu",*/ 924}, {0x00019083, /*L"Nu",*/ 925},
40 {0x00019ab9, /*L"Pi",*/ 928}, {0x0001c3c1, /*L"Xi",*/ 926},
41 {0x000210ac, /*L"ge",*/ 8805}, {0x000210bb, /*L"gt",*/ 62},
42 {0x00022a51, /*L"le",*/ 8804}, {0x00022a60, /*L"lt",*/ 60},
43 {0x00022f82, /*L"mu",*/ 956}, {0x00023493, /*L"ne",*/ 8800},
44 {0x00023497, /*L"ni",*/ 8715}, {0x000234a3, /*L"nu",*/ 957},
45 {0x000239c1, /*L"or",*/ 8744}, {0x00023ed9, /*L"pi",*/ 960},
46 {0x000267e1, /*L"xi",*/ 958}, {0x00c41789, /*L"lceil",*/ 8968},
47 {0x00eef34f, /*L"thetasym",*/ 977}, {0x012d7ead, /*L"lcirc",*/ 206},
48 {0x01637b56, /*L"agrave",*/ 224}, {0x020856da, /*L"crarr",*/ 8629},
49 {0x022188c3, /*L"gamma",*/ 947}, {0x033586d3, /*L"nbsp",*/ 160},
50 {0x04f4c358, /*L"nsub",*/ 8836}, {0x0581466a, /*L"dagger",*/ 8224},
51 {0x06b1f790, /*L"oelig",*/ 339}, {0x06e490d4, /*L"Chi",*/ 935},
52 {0x0718c6a1, /*L"ETH",*/ 208}, {0x07196ada, /*L"Eta",*/ 919},
53 {0x07f667ca, /*L"Ugrave",*/ 217}, {0x083a8a21, /*L"Phi",*/ 934},
54 {0x083ac28c, /*L"Psi",*/ 936}, {0x086f26a9, /*L"Rho",*/ 929},
55 {0x089b5b51, /*L"aring",*/ 229}, {0x08a39f4a, /*L"Tau",*/ 932},
56 {0x08b6188b, /*L"THORN",*/ 222}, {0x09ce792a, /*L"icirc",*/ 238},
57 {0x09f9d61e, /*L"amp",*/ 38}, {0x09f9db33, /*L"and",*/ 8743},
58 {0x09f9db36, /*L"ang",*/ 8736}, {0x0a2e3514, /*L"cap",*/ 8745},
59 {0x0a2e58f4, /*L"chi",*/ 967}, {0x0a2e9ba8, /*L"cup",*/ 8746},
60 {0x0a4897d0, /*L"deg",*/ 176}, {0x0a6332fa, /*L"eta",*/ 951},
61 {0x0a633301, /*L"eth",*/ 240}, {0x0acc4d4b, /*L"int",*/ 8747},
62 {0x0b1b3d35, /*L"loz",*/ 9674}, {0x0b1b4c8b, /*L"lrm",*/ 8206},
63 {0x0b4fd9b1, /*L"not",*/ 172}, {0x0b845241, /*L"phi",*/ 966},
64 {0x0b84576f, /*L"piv",*/ 982}, {0x0b848aac, /*L"psi",*/ 968},
65 {0x0bb8df5e, /*L"reg",*/ 174}, {0x0bb8eec9, /*L"rho",*/ 961},
66 {0x0bb9034b, /*L"rlm",*/ 8207}, {0x0bd33d14, /*L"shy",*/ 173},
67 {0x0bd34229, /*L"sim",*/ 8764}, {0x0bd37faa, /*L"sub",*/ 8834},
68 {0x0bd37fb5, /*L"sum",*/ 8721}, {0x0bd37fb8, /*L"sup",*/ 8835},
69 {0x0bed676a, /*L"tau",*/ 964}, {0x0c07f32e, /*L"uml",*/ 168},
70 {0x0c71032c, /*L"yen",*/ 165}, {0x0c7f2889, /*L"szlig",*/ 223},
71 {0x0c8badbb, /*L"zwj",*/ 8205}, {0x10ba4dba, /*L"Egrave",*/ 200},
72 {0x10f1ea24, /*L"para",*/ 182}, {0x10f1ea37, /*L"part",*/ 8706},
73 {0x115b2337, /*L"perp",*/ 8869}, {0x12b10d15, /*L"prod",*/ 8719},
74 {0x12b10d21, /*L"prop",*/ 8733}, {0x12dfa9f4, /*L"rfloor",*/ 8971},
75 {0x12eb4736, /*L"Agrave",*/ 192}, {0x12fff2b7, /*L"pund",*/ 163},
76 {0x13fda9f2, /*L"tilde",*/ 732}, {0x1417fd62, /*L"times",*/ 215},
77 {0x154fc726, /*L"ecirc",*/ 234}, {0x165aa451, /*L"sigma",*/ 963},
78 {0x1709124a, /*L"Dagger",*/ 8225}, {0x192f78d5, /*L"iexcl",*/ 161},
79 {0x1b7ed8d7, /*L"rArr",*/ 8658}, {0x1ec88c68, /*L"rang",*/ 9002},
80 {0x1ec8a0f7, /*L"rarr",*/ 8594}, {0x1eda07f3, /*L"atilde",*/ 227},
81 {0x1f3182c4, /*L"real",*/ 8476}, {0x1fc34f8b, /*L"yacute",*/ 253},
82 {0x20d11522, /*L"acirc",*/ 226}, {0x21933a9b, /*L"rsaquo",*/ 8250},
83 {0x21f44907, /*L"uacute",*/ 250}, {0x220cca72, /*L"acute",*/ 180},
84 {0x242cded1, /*L"alefsym",*/ 8501}, {0x2655c66a, /*L"delta",*/ 948},
85 {0x269e4b4d, /*L"exist",*/ 8707}, {0x273379fa, /*L"micro",*/ 181},
86 {0x27a37440, /*L"forall",*/ 8704}, {0x2854e62c, /*L"minus",*/ 8722},
87 {0x28636f81, /*L"cedil",*/ 184}, {0x2887357b, /*L"iacute",*/ 237},
88 {0x2994d5ff, /*L"frac12",*/ 189}, {0x2994d601, /*L"frac14",*/ 188},
89 {0x2994e043, /*L"frac34",*/ 190}, {0x2a1feb41, /*L"lambda",*/ 955},
90 {0x2ab215f3, /*L"apos",*/ 39}, {0x2ab82ef7, /*L"eacute",*/ 233},
91 {0x2b3592ef, /*L"auml",*/ 228}, {0x2ce92873, /*L"aacute",*/ 225},
92 {0x2daff48a, /*L"oslash",*/ 248}, {0x2ef68882, /*L"aelig",*/ 230},
93 {0x3061d3d3, /*L"Atilde",*/ 195}, {0x314b1b6b, /*L"Yacute",*/ 221},
94 {0x337c14e7, /*L"Uacute",*/ 218}, {0x37676aca, /*L"cent",*/ 162},
95 {0x37d0b841, /*L"circ",*/ 710}, {0x386e7947, /*L"cong",*/ 8773},
96 {0x386e839b, /*L"copy",*/ 169}, {0x3a0e225a, /*L"Epsilon",*/ 917},
97 {0x3ba7b721, /*L"Lambda",*/ 923}, {0x3bd9abe6, /*L"Alpha",*/ 913},
98 {0x3c3ffad7, /*L"Eacute",*/ 201}, {0x3cfaf69f, /*L"brvbar",*/ 166},
99 {0x3d54a489, /*L"omega",*/ 969}, {0x3e70f453, /*L"Aacute",*/ 193},
100 {0x3f37c06a, /*L"Oslash",*/ 216}, {0x40e1b34e, /*L"diams",*/ 9830},
101 {0x416596df, /*L"plusmn",*/ 177}, {0x4354ff16, /*L"Ucirc",*/ 219},
102 {0x454fce6a, /*L"Upsilon",*/ 933}, {0x4610ad35, /*L"emsp",*/ 8195},
103 {0x462afb76, /*L"ensp",*/ 8194}, {0x46e30073, /*L"euml",*/ 235},
104 {0x46e31a1b, /*L"euro",*/ 8364}, {0x46f2eada, /*L"lowast",*/ 8727},
105 {0x4dca26cf, /*L"Auml",*/ 196}, {0x4e2d6083, /*L"image",*/ 8465},
106 {0x4f964ee8, /*L"notin",*/ 8713}, {0x50917a7a, /*L"epsilon",*/ 949},
107 {0x52f9a4cd, /*L"Kappa",*/ 922}, {0x5496f410, /*L"Ocirc",*/ 212},
108 {0x568cbf34, /*L"zeta",*/ 950}, {0x57badd20, /*L"ntilde",*/ 241},
109 {0x58662109, /*L"zwnj",*/ 8204}, {0x5b39870f, /*L"empty",*/ 8709},
110 {0x5bd3268a, /*L"upsilon",*/ 965}, {0x5e2bf8a3, /*L"Gamma",*/ 915},
111 {0x5f73c13a, /*L"rsquo",*/ 8217}, {0x61f2bc4d, /*L"iota",*/ 953},
112 {0x625bbcf3, /*L"isin",*/ 8712}, {0x62906df7, /*L"iuml",*/ 239},
113 {0x64a5cb31, /*L"Aring",*/ 197}, {0x66f25c4a, /*L"sbquo",*/ 8218},
114 {0x6851ab60, /*L"spades",*/ 9824}, {0x6942a900, /*L"Ntilde",*/ 209},
115 {0x69779453, /*L"Euml",*/ 203}, {0x6cda6e23, /*L"current",*/ 164},
116 {0x70b5b634, /*L"lsquo",*/ 8216}, {0x715a3706, /*L"Ecirc",*/ 202},
117 {0x71e8bf8d, /*L"tdquo",*/ 8221}, {0x72651431, /*L"Sigma",*/ 931},
118 {0x7569813b, /*L"iquest",*/ 191}, {0x776a436a, /*L"equiv",*/ 8801},
119 {0x79215314, /*L"Zeta",*/ 918}, {0x79b81224, /*L"ograve",*/ 242},
120 {0x7c2f8b23, /*L"macr",*/ 175}, {0x7cdb8502, /*L"Acirc",*/ 194},
121 {0x8185c62e, /*L"ndash",*/ 8211}, {0x8260364a, /*L"Delta",*/ 916},
122 {0x846619ad, /*L"mdash",*/ 8212}, {0x8550fb50, /*L"OElig",*/ 338},
123 {0x88eb5b85, /*L"ldquo",*/ 8220}, {0x8b3fde04, /*L"Ograve",*/ 210},
124 {0x8bc5794b, /*L"ordf",*/ 170}, {0x8bc57952, /*L"ordm",*/ 186},
125 {0x8c14923d, /*L"ouml",*/ 246}, {0x8c5a7cd6, /*L"theta",*/ 952},
126 {0x8d61812b, /*L"thorn",*/ 254}, {0x912b95aa, /*L"asymp",*/ 8776},
127 {0x947faf81, /*L"middot",*/ 183}, {0x9629202e, /*L"lfloor",*/ 8970},
128 {0x972e9ec1, /*L"otilde",*/ 245}, {0x9748f231, /*L"otimes",*/ 8855},
129 {0x995f1469, /*L"Omega",*/ 937}, {0x99eb5349, /*L"quot",*/ 34},
130 {0x9aeb639e, /*L"hellip",*/ 8230}, {0xa0ae2f86, /*L"Scaron",*/ 352},
131 {0xa4dcb0d5, /*L"lsaquo",*/ 8249}, {0xa53dbf41, /*L"oacute",*/ 243},
132 {0xa5ae9e7b, /*L"bdquo",*/ 8222}, {0xa602d7ba, /*L"sdot",*/ 8901},
133 {0xa61ce86f, /*L"sect",*/ 167}, {0xa6e4c3d7, /*L"sigmaf",*/ 962},
134 {0xa7c1c74f, /*L"sube",*/ 8838}, {0xa7c20ee9, /*L"sup1",*/ 185},
135 {0xa7c20eea, /*L"sup2",*/ 178}, {0xa7c20eeb, /*L"sup3",*/ 179},
136 {0xa7c20f1d, /*L"supe",*/ 8839}, {0xa8b66aa1, /*L"Otilde",*/ 213},
137 {0xad958c42, /*L"AElig",*/ 198}, {0xaea9261d, /*L"Ouml",*/ 214},
138 {0xb040eafa, /*L"uArr",*/ 8657}, {0xb07c2e1c, /*L"beta",*/ 946},
139 {0xb220e92f, /*L"bull",*/ 8226}, {0xb22750c4, /*L"ccedil",*/ 231},
140 {0xb38ab31a, /*L"uarr",*/ 8593}, {0xb598b683, /*L"uuml",*/ 252},
141 {0xb6c58b21, /*L"Oacute",*/ 211}, {0xb6d2a617, /*L"oline",*/ 8254},
142 {0xba9fd989, /*L"dArr",*/ 8659}, {0xbb5ccd41, /*L"lgrave",*/ 204},
143 {0xbd39b44c, /*L"weierp",*/ 8472}, {0xbde9a1a9, /*L"darr",*/ 8595},
144 {0xc027e329, /*L"permil",*/ 8240}, {0xc2451389, /*L"upsih",*/ 978},
145 {0xc3af1ca4, /*L"Ccedil",*/ 199}, {0xcd164249, /*L"fnof",*/ 402},
146 {0xcf6c8467, /*L"hearts",*/ 9829}, {0xd1228390, /*L"trade",*/ 8482},
147 {0xd1462407, /*L"yuml",*/ 255}, {0xd2cf2253, /*L"oplus",*/ 8853},
148 {0xd310c1fc, /*L"Beta",*/ 914}, {0xd59c4d74, /*L"infin",*/ 8734},
149 {0xd64d470d, /*L"hArr",*/ 8660}, {0xd67d9c75, /*L"divide",*/ 247},
150 {0xd698dd37, /*L"Omicron",*/ 927}, {0xd82d4a63, /*L"Uuml",*/ 220},
151 {0xd9970f2d, /*L"harr",*/ 8596}, {0xda91fd99, /*L"clubs",*/ 9827},
152 {0xdbe5bdcc, /*L"there4",*/ 8756}, {0xdd7671bd, /*L"prime",*/ 8242},
153 {0xdfcf3c06, /*L"alpha",*/ 945}, {0xe0213063, /*L"saron",*/ 353},
154 {0xe1911d83, /*L"radic",*/ 8730}, {0xe2e75468, /*L"raquo",*/ 187},
155 {0xe6e27a5e, /*L"lacute",*/ 205}, {0xe74a8f36, /*L"ucirc",*/ 251},
156 {0xe864ecb6, /*L"Theta",*/ 920}, {0xecddde5e, /*L"nabla",*/ 8711},
157 {0xed1c3557, /*L"omicron",*/ 959}, {0xef82228f, /*L"rceil",*/ 8969},
158 {0xf1fab491, /*L"lArr",*/ 8656}, {0xf3dab7e7, /*L"Yuml",*/ 376},
159 {0xf4294962, /*L"laquo",*/ 171}, {0xf5446822, /*L"lang",*/ 9001},
160 {0xf5447cb1, /*L"larr",*/ 8592}, {0xf66e9bea, /*L"ugrave",*/ 249},
161 {0xf6b4ce70, /*L"lota",*/ 921}, {0xf6ef34ed, /*L"kappa",*/ 954},
162 {0xf72a3a56, /*L"thinsp",*/ 8201}, {0xf752801a, /*L"luml",*/ 207},
163 {0xf88c8430, /*L"ocirc",*/ 244}, {0xf9676178, /*L"frasl",*/ 8260},
164 {0xfd01885e, /*L"igrave",*/ 236}, {0xff3281da, /*L"egrave",*/ 232},
Dan Sinclair1770c022016-03-14 14:14:16 -0400165};
166
167const XFA_FMHtmlReserveCode reservesForEncode[] = {
168 {34, L"quot"}, {38, L"amp"}, {39, L"apos"},
169 {60, L"lt"}, {62, L"gt"}, {160, L"nbsp"},
170 {161, L"iexcl"}, {162, L"cent"}, {163, L"pund"},
171 {164, L"current"}, {165, L"yen"}, {166, L"brvbar"},
172 {167, L"sect"}, {168, L"uml"}, {169, L"copy"},
173 {170, L"ordf"}, {171, L"laquo"}, {172, L"not"},
174 {173, L"shy"}, {174, L"reg"}, {175, L"macr"},
175 {176, L"deg"}, {177, L"plusmn"}, {178, L"sup2"},
176 {179, L"sup3"}, {180, L"acute"}, {181, L"micro"},
177 {182, L"para"}, {183, L"middot"}, {184, L"cedil"},
178 {185, L"sup1"}, {186, L"ordm"}, {187, L"raquo"},
179 {188, L"frac14"}, {189, L"frac12"}, {190, L"frac34"},
180 {191, L"iquest"}, {192, L"Agrave"}, {193, L"Aacute"},
181 {194, L"Acirc"}, {195, L"Atilde"}, {196, L"Auml"},
182 {197, L"Aring"}, {198, L"AElig"}, {199, L"Ccedil"},
183 {200, L"Egrave"}, {201, L"Eacute"}, {202, L"Ecirc"},
184 {203, L"Euml"}, {204, L"lgrave"}, {205, L"lacute"},
185 {206, L"lcirc"}, {207, L"luml"}, {208, L"ETH"},
186 {209, L"Ntilde"}, {210, L"Ograve"}, {211, L"Oacute"},
187 {212, L"Ocirc"}, {213, L"Otilde"}, {214, L"Ouml"},
188 {215, L"times"}, {216, L"Oslash"}, {217, L"Ugrave"},
189 {218, L"Uacute"}, {219, L"Ucirc"}, {220, L"Uuml"},
190 {221, L"Yacute"}, {222, L"THORN"}, {223, L"szlig"},
191 {224, L"agrave"}, {225, L"aacute"}, {226, L"acirc"},
192 {227, L"atilde"}, {228, L"auml"}, {229, L"aring"},
193 {230, L"aelig"}, {231, L"ccedil"}, {232, L"egrave"},
194 {233, L"eacute"}, {234, L"ecirc"}, {235, L"euml"},
195 {236, L"igrave"}, {237, L"iacute"}, {238, L"icirc"},
196 {239, L"iuml"}, {240, L"eth"}, {241, L"ntilde"},
197 {242, L"ograve"}, {243, L"oacute"}, {244, L"ocirc"},
198 {245, L"otilde"}, {246, L"ouml"}, {247, L"divide"},
199 {248, L"oslash"}, {249, L"ugrave"}, {250, L"uacute"},
200 {251, L"ucirc"}, {252, L"uuml"}, {253, L"yacute"},
201 {254, L"thorn"}, {255, L"yuml"}, {338, L"OElig"},
202 {339, L"oelig"}, {352, L"Scaron"}, {353, L"saron"},
203 {376, L"Yuml"}, {402, L"fnof"}, {710, L"circ"},
204 {732, L"tilde"}, {913, L"Alpha"}, {914, L"Beta"},
205 {915, L"Gamma"}, {916, L"Delta"}, {917, L"Epsilon"},
206 {918, L"Zeta"}, {919, L"Eta"}, {920, L"Theta"},
207 {921, L"lota"}, {922, L"Kappa"}, {923, L"Lambda"},
208 {924, L"Mu"}, {925, L"Nu"}, {926, L"Xi"},
209 {927, L"Omicron"}, {928, L"Pi"}, {929, L"Rho"},
210 {931, L"Sigma"}, {932, L"Tau"}, {933, L"Upsilon"},
211 {934, L"Phi"}, {935, L"Chi"}, {936, L"Psi"},
212 {937, L"Omega"}, {945, L"alpha"}, {946, L"beta"},
213 {947, L"gamma"}, {948, L"delta"}, {949, L"epsilon"},
214 {950, L"zeta"}, {951, L"eta"}, {952, L"theta"},
215 {953, L"iota"}, {954, L"kappa"}, {955, L"lambda"},
216 {956, L"mu"}, {957, L"nu"}, {958, L"xi"},
217 {959, L"omicron"}, {960, L"pi"}, {961, L"rho"},
218 {962, L"sigmaf"}, {963, L"sigma"}, {964, L"tau"},
219 {965, L"upsilon"}, {966, L"phi"}, {967, L"chi"},
220 {968, L"psi"}, {969, L"omega"}, {977, L"thetasym"},
221 {978, L"upsih"}, {982, L"piv"}, {8194, L"ensp"},
222 {8195, L"emsp"}, {8201, L"thinsp"}, {8204, L"zwnj"},
223 {8205, L"zwj"}, {8206, L"lrm"}, {8207, L"rlm"},
224 {8211, L"ndash"}, {8212, L"mdash"}, {8216, L"lsquo"},
225 {8217, L"rsquo"}, {8218, L"sbquo"}, {8220, L"ldquo"},
226 {8221, L"tdquo"}, {8222, L"bdquo"}, {8224, L"dagger"},
227 {8225, L"Dagger"}, {8226, L"bull"}, {8230, L"hellip"},
228 {8240, L"permil"}, {8242, L"prime"}, {8249, L"lsaquo"},
229 {8250, L"rsaquo"}, {8254, L"oline"}, {8260, L"frasl"},
230 {8364, L"euro"}, {8465, L"image"}, {8472, L"weierp"},
231 {8476, L"real"}, {8482, L"trade"}, {8501, L"alefsym"},
232 {8592, L"larr"}, {8593, L"uarr"}, {8594, L"rarr"},
233 {8595, L"darr"}, {8596, L"harr"}, {8629, L"crarr"},
234 {8656, L"lArr"}, {8657, L"uArr"}, {8658, L"rArr"},
235 {8659, L"dArr"}, {8660, L"hArr"}, {8704, L"forall"},
236 {8706, L"part"}, {8707, L"exist"}, {8709, L"empty"},
237 {8711, L"nabla"}, {8712, L"isin"}, {8713, L"notin"},
238 {8715, L"ni"}, {8719, L"prod"}, {8721, L"sum"},
239 {8722, L"minus"}, {8727, L"lowast"}, {8730, L"radic"},
240 {8733, L"prop"}, {8734, L"infin"}, {8736, L"ang"},
241 {8743, L"and"}, {8744, L"or"}, {8745, L"cap"},
242 {8746, L"cup"}, {8747, L"int"}, {8756, L"there4"},
243 {8764, L"sim"}, {8773, L"cong"}, {8776, L"asymp"},
244 {8800, L"ne"}, {8801, L"equiv"}, {8804, L"le"},
245 {8805, L"ge"}, {8834, L"sub"}, {8835, L"sup"},
246 {8836, L"nsub"}, {8838, L"sube"}, {8839, L"supe"},
247 {8853, L"oplus"}, {8855, L"otimes"}, {8869, L"perp"},
248 {8901, L"sdot"}, {8968, L"lceil"}, {8969, L"rceil"},
249 {8970, L"lfloor"}, {8971, L"rfloor"}, {9001, L"lang"},
250 {9002, L"rang"}, {9674, L"loz"}, {9824, L"spades"},
251 {9827, L"clubs"}, {9829, L"hearts"}, {9830, L"diams"},
252};
253
tsepez1c9cfe12016-05-26 13:30:56 -0700254const FXJSE_FUNCTION_DESCRIPTOR formcalc_fm2js_functions[] = {
255 {"Abs", CXFA_FM2JSContext::Abs},
256 {"Avg", CXFA_FM2JSContext::Avg},
257 {"Ceil", CXFA_FM2JSContext::Ceil},
258 {"Count", CXFA_FM2JSContext::Count},
259 {"Floor", CXFA_FM2JSContext::Floor},
260 {"Max", CXFA_FM2JSContext::Max},
261 {"Min", CXFA_FM2JSContext::Min},
262 {"Mod", CXFA_FM2JSContext::Mod},
263 {"Round", CXFA_FM2JSContext::Round},
264 {"Sum", CXFA_FM2JSContext::Sum},
265 {"Date", CXFA_FM2JSContext::Date},
266 {"Date2Num", CXFA_FM2JSContext::Date2Num},
267 {"DateFmt", CXFA_FM2JSContext::DateFmt},
268 {"IsoDate2Num", CXFA_FM2JSContext::IsoDate2Num},
269 {"IsoTime2Num", CXFA_FM2JSContext::IsoTime2Num},
270 {"LocalDateFmt", CXFA_FM2JSContext::LocalDateFmt},
271 {"LocalTimeFmt", CXFA_FM2JSContext::LocalTimeFmt},
272 {"Num2Date", CXFA_FM2JSContext::Num2Date},
273 {"Num2GMTime", CXFA_FM2JSContext::Num2GMTime},
274 {"Num2Time", CXFA_FM2JSContext::Num2Time},
275 {"Time", CXFA_FM2JSContext::Time},
276 {"Time2Num", CXFA_FM2JSContext::Time2Num},
277 {"TimeFmt", CXFA_FM2JSContext::TimeFmt},
278 {"Apr", CXFA_FM2JSContext::Apr},
279 {"Cterm", CXFA_FM2JSContext::CTerm},
280 {"FV", CXFA_FM2JSContext::FV},
281 {"Ipmt", CXFA_FM2JSContext::IPmt},
282 {"NPV", CXFA_FM2JSContext::NPV},
283 {"Pmt", CXFA_FM2JSContext::Pmt},
284 {"PPmt", CXFA_FM2JSContext::PPmt},
285 {"PV", CXFA_FM2JSContext::PV},
286 {"Rate", CXFA_FM2JSContext::Rate},
287 {"Term", CXFA_FM2JSContext::Term},
288 {"Choose", CXFA_FM2JSContext::Choose},
289 {"Exists", CXFA_FM2JSContext::Exists},
290 {"HasValue", CXFA_FM2JSContext::HasValue},
291 {"Oneof", CXFA_FM2JSContext::Oneof},
292 {"Within", CXFA_FM2JSContext::Within},
293 {"If", CXFA_FM2JSContext::If},
294 {"Eval", CXFA_FM2JSContext::Eval},
295 {"Translate", CXFA_FM2JSContext::eval_translation},
296 {"Ref", CXFA_FM2JSContext::Ref},
297 {"UnitType", CXFA_FM2JSContext::UnitType},
298 {"UnitValue", CXFA_FM2JSContext::UnitValue},
299 {"At", CXFA_FM2JSContext::At},
300 {"Concat", CXFA_FM2JSContext::Concat},
301 {"Decode", CXFA_FM2JSContext::Decode},
302 {"Encode", CXFA_FM2JSContext::Encode},
303 {"Format", CXFA_FM2JSContext::Format},
304 {"Left", CXFA_FM2JSContext::Left},
305 {"Len", CXFA_FM2JSContext::Len},
306 {"Lower", CXFA_FM2JSContext::Lower},
307 {"Ltrim", CXFA_FM2JSContext::Ltrim},
308 {"Parse", CXFA_FM2JSContext::Parse},
309 {"Replace", CXFA_FM2JSContext::Replace},
310 {"Right", CXFA_FM2JSContext::Right},
311 {"Rtrim", CXFA_FM2JSContext::Rtrim},
312 {"Space", CXFA_FM2JSContext::Space},
313 {"Str", CXFA_FM2JSContext::Str},
314 {"Stuff", CXFA_FM2JSContext::Stuff},
315 {"Substr", CXFA_FM2JSContext::Substr},
316 {"Uuid", CXFA_FM2JSContext::Uuid},
317 {"Upper", CXFA_FM2JSContext::Upper},
318 {"WordNum", CXFA_FM2JSContext::WordNum},
319 {"Get", CXFA_FM2JSContext::Get},
320 {"Post", CXFA_FM2JSContext::Post},
321 {"Put", CXFA_FM2JSContext::Put},
322 {"positive_operator", CXFA_FM2JSContext::positive_operator},
323 {"negative_operator", CXFA_FM2JSContext::negative_operator},
324 {"logical_or_operator", CXFA_FM2JSContext::logical_or_operator},
325 {"logical_and_operator", CXFA_FM2JSContext::logical_and_operator},
326 {"logical_not_operator", CXFA_FM2JSContext::logical_not_operator},
327 {"equality_operator", CXFA_FM2JSContext::equality_operator},
328 {"notequality_operator", CXFA_FM2JSContext::notequality_operator},
329 {"less_operator", CXFA_FM2JSContext::less_operator},
330 {"lessequal_operator", CXFA_FM2JSContext::lessequal_operator},
331 {"greater_operator", CXFA_FM2JSContext::greater_operator},
332 {"greaterequal_operator", CXFA_FM2JSContext::greaterequal_operator},
333 {"plus_operator", CXFA_FM2JSContext::plus_operator},
334 {"minus_operator", CXFA_FM2JSContext::minus_operator},
335 {"multiple_operator", CXFA_FM2JSContext::multiple_operator},
336 {"divide_operator", CXFA_FM2JSContext::divide_operator},
337 {"assign_value_operator", CXFA_FM2JSContext::assign_value_operator},
338 {"dot_accessor", CXFA_FM2JSContext::dot_accessor},
339 {"dotdot_accessor", CXFA_FM2JSContext::dotdot_accessor},
340 {"concat_fm_object", CXFA_FM2JSContext::concat_fm_object},
341 {"is_fm_object", CXFA_FM2JSContext::is_fm_object},
342 {"is_fm_array", CXFA_FM2JSContext::is_fm_array},
343 {"get_fm_value", CXFA_FM2JSContext::get_fm_value},
344 {"get_fm_jsobj", CXFA_FM2JSContext::get_fm_jsobj},
345 {"fm_var_filter", CXFA_FM2JSContext::fm_var_filter},
346};
347
348const FXJSE_CLASS_DESCRIPTOR formcalc_fm2js_descriptor = {
349 "XFA_FM2JS_FormCalcClass", // name
350 nullptr, // constructor
351 nullptr, // properties
352 formcalc_fm2js_functions, // methods
353 0, // number of properties
354 FX_ArraySize(formcalc_fm2js_functions), // number of methods
355 nullptr, // dynamic prop type
356 nullptr, // dynamic prop getter
357 nullptr, // dynamic prop setter
358 nullptr, // dynamic prop deleter
359 nullptr, // dynamic prop method call
360};
361
dsinclair0c268e92016-05-17 14:04:14 -0700362const uint8_t g_sAltTable_Date[] = {
ochangf6be1452016-06-01 12:20:03 -0700363 255, 255, 255, 3, 9, 255, 255, 255, 255, 255, 255,
364 255, 2, 255, 255, 255, 255, 255, 255, 255, 255, 255,
365 255, 255, 1, 255, 255, 255, 255, 255, 255, 255, 255,
dsinclair0c268e92016-05-17 14:04:14 -0700366};
ochangf6be1452016-06-01 12:20:03 -0700367static_assert(FX_ArraySize(g_sAltTable_Date) == L'a' - L'A' + 1,
368 "Invalid g_sAltTable_Date size.");
dsinclair0c268e92016-05-17 14:04:14 -0700369
370const uint8_t g_sAltTable_Time[] = {
ochangf6be1452016-06-01 12:20:03 -0700371 14, 255, 255, 3, 9, 255, 255, 15, 255, 255, 255,
372 255, 6, 255, 255, 255, 255, 255, 7, 255, 255, 255,
373 255, 255, 1, 17, 255, 255, 255, 255, 255, 255, 255,
dsinclair0c268e92016-05-17 14:04:14 -0700374};
ochangf6be1452016-06-01 12:20:03 -0700375static_assert(FX_ArraySize(g_sAltTable_Time) == L'a' - L'A' + 1,
376 "Invalid g_sAltTable_Time size.");
dsinclair0c268e92016-05-17 14:04:14 -0700377
378void AlternateDateTimeSymbols(CFX_WideString& wsPattern,
379 const CFX_WideString& wsAltSymbols,
380 const uint8_t* pAltTable) {
381 int32_t nLength = wsPattern.GetLength();
382 FX_BOOL bInConstRange = FALSE;
383 FX_BOOL bEscape = FALSE;
ochangf6be1452016-06-01 12:20:03 -0700384 int32_t i = 0;
dsinclair0c268e92016-05-17 14:04:14 -0700385 while (i < nLength) {
386 FX_WCHAR wc = wsPattern[i];
387 if (wc == L'\'') {
388 bInConstRange = !bInConstRange;
389 if (bEscape) {
390 i++;
391 } else {
392 wsPattern.Delete(i);
393 nLength--;
394 }
395 bEscape = !bEscape;
396 continue;
397 }
ochangf6be1452016-06-01 12:20:03 -0700398 if (!bInConstRange && wc >= L'A' && wc <= L'a') {
399 uint8_t nAlt = pAltTable[wc - L'A'];
dsinclair48d91dd2016-05-31 11:54:01 -0700400 if (nAlt != 255)
dsinclair0c268e92016-05-17 14:04:14 -0700401 wsPattern.SetAt(i, wsAltSymbols[nAlt]);
dsinclair0c268e92016-05-17 14:04:14 -0700402 }
403 i++;
404 bEscape = FALSE;
405 }
406}
407
dsinclair48d91dd2016-05-31 11:54:01 -0700408bool PatternStringType(const CFX_ByteStringC& szPattern,
409 uint32_t& patternType) {
410 CFX_WideString wsPattern = CFX_WideString::FromUTF8(szPattern);
411 if (FX_WSTRC(L"datetime") == wsPattern.Left(8)) {
412 patternType = XFA_VT_DATETIME;
413 return true;
414 }
415 if (FX_WSTRC(L"date") == wsPattern.Left(4)) {
416 patternType = wsPattern.Find(L"time") > 0 ? XFA_VT_DATETIME : XFA_VT_DATE;
417 return true;
418 }
419 if (FX_WSTRC(L"time") == wsPattern.Left(4)) {
420 patternType = XFA_VT_TIME;
421 return true;
422 }
423 if (FX_WSTRC(L"text") == wsPattern.Left(4)) {
424 patternType = XFA_VT_TEXT;
425 return true;
426 }
427 if (FX_WSTRC(L"num") == wsPattern.Left(3)) {
428 if (FX_WSTRC(L"integer") == wsPattern.Mid(4, 7)) {
429 patternType = XFA_VT_INTEGER;
430 } else if (FX_WSTRC(L"decimal") == wsPattern.Mid(4, 7)) {
431 patternType = XFA_VT_DECIMAL;
432 } else if (FX_WSTRC(L"currency") == wsPattern.Mid(4, 8)) {
433 patternType = XFA_VT_FLOAT;
434 } else if (FX_WSTRC(L"percent") == wsPattern.Mid(4, 7)) {
435 patternType = XFA_VT_FLOAT;
436 } else {
437 patternType = XFA_VT_FLOAT;
438 }
439 return true;
440 }
441
442 patternType = XFA_VT_NULL;
443 wsPattern.MakeLower();
444 const FX_WCHAR* pData = wsPattern.c_str();
445 int32_t iLength = wsPattern.GetLength();
446 int32_t iIndex = 0;
447 FX_BOOL bSingleQuotation = FALSE;
448 FX_WCHAR patternChar;
449 while (iIndex < iLength) {
dsinclair2b6d64e2016-06-06 11:39:42 -0700450 patternChar = pData[iIndex];
dsinclair48d91dd2016-05-31 11:54:01 -0700451 if (patternChar == 0x27) {
452 bSingleQuotation = !bSingleQuotation;
453 } else if (!bSingleQuotation &&
454 (patternChar == 'y' || patternChar == 'j')) {
455 patternType = XFA_VT_DATE;
456 iIndex++;
457 FX_WCHAR timePatternChar;
458 while (iIndex < iLength) {
dsinclair2b6d64e2016-06-06 11:39:42 -0700459 timePatternChar = pData[iIndex];
dsinclair48d91dd2016-05-31 11:54:01 -0700460 if (timePatternChar == 0x27) {
461 bSingleQuotation = !bSingleQuotation;
462 } else if (!bSingleQuotation && timePatternChar == 't') {
463 patternType = XFA_VT_DATETIME;
464 break;
465 }
466 iIndex++;
467 }
468 break;
469 } else if (!bSingleQuotation &&
470 (patternChar == 'h' || patternChar == 'k')) {
471 patternType = XFA_VT_TIME;
472 break;
473 } else if (!bSingleQuotation &&
474 (patternChar == 'a' || patternChar == 'x' ||
475 patternChar == 'o' || patternChar == '0')) {
476 patternType = XFA_VT_TEXT;
477 if (patternChar == 'x' || patternChar == 'o' || patternChar == '0') {
478 break;
479 }
480 } else if (!bSingleQuotation &&
481 (patternChar == 'z' || patternChar == 's' ||
482 patternChar == 'e' || patternChar == 'v' ||
483 patternChar == '8' || patternChar == ',' ||
484 patternChar == '.' || patternChar == '$')) {
485 patternType = XFA_VT_FLOAT;
486 if (patternChar == 'v' || patternChar == '8' || patternChar == '$') {
487 break;
488 }
489 }
490 iIndex++;
491 }
492 if (patternType == XFA_VT_NULL) {
493 patternType = XFA_VT_TEXT | XFA_VT_FLOAT;
494 }
495 return false;
496}
497
dsinclair8f3074b2016-06-02 17:45:25 -0700498CXFA_FM2JSContext* ToJSContext(CFXJSE_Value* pValue, CFXJSE_Class* pClass) {
499 return static_cast<CXFA_FM2JSContext*>(pValue->ToHostObject(pClass));
500}
501
dsinclair2b6d64e2016-06-06 11:39:42 -0700502bool IsWhitespace(char c) {
503 return c == 0x20 || c == 0x09 || c == 0x0B || c == 0x0C || c == 0x0A ||
504 c == 0x0D;
505}
506
Dan Sinclair1770c022016-03-14 14:14:16 -0400507} // namespace
508
dsinclair48d91dd2016-05-31 11:54:01 -0700509// static
dsinclair12a6b0c2016-05-26 11:14:08 -0700510void CXFA_FM2JSContext::Abs(CFXJSE_Value* pThis,
Dan Sinclair1770c022016-03-14 14:14:16 -0400511 const CFX_ByteStringC& szFuncName,
512 CFXJSE_Arguments& args) {
dsinclair89ba6de2016-05-31 12:11:22 -0700513 if (args.GetLength() != 1) {
dsinclair8f3074b2016-06-02 17:45:25 -0700514 ToJSContext(pThis, nullptr)
515 ->ThrowException(XFA_IDS_INCORRECT_NUMBER_OF_METHOD, L"Abs");
dsinclair89ba6de2016-05-31 12:11:22 -0700516 return;
Dan Sinclair1770c022016-03-14 14:14:16 -0400517 }
dsinclair89ba6de2016-05-31 12:11:22 -0700518
519 std::unique_ptr<CFXJSE_Value> argOne = args.GetValue(0);
520 if (ValueIsNull(pThis, argOne.get())) {
dsinclairf27aeec2016-06-07 19:36:18 -0700521 args.GetReturnValue()->SetNull();
dsinclair89ba6de2016-05-31 12:11:22 -0700522 return;
523 }
524
525 FX_DOUBLE dValue = ValueToDouble(pThis, argOne.get());
526 if (dValue < 0)
527 dValue = -dValue;
528
dsinclairf27aeec2016-06-07 19:36:18 -0700529 args.GetReturnValue()->SetDouble(dValue);
Dan Sinclair1770c022016-03-14 14:14:16 -0400530}
dsinclair48d91dd2016-05-31 11:54:01 -0700531
532// static
dsinclair12a6b0c2016-05-26 11:14:08 -0700533void CXFA_FM2JSContext::Avg(CFXJSE_Value* pThis,
Dan Sinclair1770c022016-03-14 14:14:16 -0400534 const CFX_ByteStringC& szFuncName,
535 CFXJSE_Arguments& args) {
dsinclair89ba6de2016-05-31 12:11:22 -0700536 int32_t argc = args.GetLength();
537 if (argc < 1) {
dsinclairf27aeec2016-06-07 19:36:18 -0700538 args.GetReturnValue()->SetNull();
dsinclair89ba6de2016-05-31 12:11:22 -0700539 return;
540 }
541
dsinclair8f3074b2016-06-02 17:45:25 -0700542 v8::Isolate* pIsolate = ToJSContext(pThis, nullptr)->GetScriptRuntime();
Dan Sinclair1770c022016-03-14 14:14:16 -0400543 uint32_t uCount = 0;
544 FX_DOUBLE dSum = 0.0;
dsinclair89ba6de2016-05-31 12:11:22 -0700545 for (int32_t i = 0; i < argc; i++) {
546 std::unique_ptr<CFXJSE_Value> argValue = args.GetValue(i);
dsinclair769b1372016-06-08 13:12:41 -0700547 if (argValue->IsNull())
dsinclair89ba6de2016-05-31 12:11:22 -0700548 continue;
dsinclair86fad992016-05-31 11:34:04 -0700549
dsinclair769b1372016-06-08 13:12:41 -0700550 if (!argValue->IsArray()) {
dsinclair89ba6de2016-05-31 12:11:22 -0700551 dSum += ValueToDouble(pThis, argValue.get());
552 uCount++;
553 continue;
554 }
555
556 std::unique_ptr<CFXJSE_Value> lengthValue(new CFXJSE_Value(pIsolate));
dsinclairf27aeec2016-06-07 19:36:18 -0700557 argValue->GetObjectProperty("length", lengthValue.get());
558 int32_t iLength = lengthValue->ToInteger();
dsinclair89ba6de2016-05-31 12:11:22 -0700559
560 if (iLength > 2) {
561 std::unique_ptr<CFXJSE_Value> propertyValue(new CFXJSE_Value(pIsolate));
dsinclairf27aeec2016-06-07 19:36:18 -0700562 argValue->GetObjectPropertyByIdx(1, propertyValue.get());
dsinclair89ba6de2016-05-31 12:11:22 -0700563
564 std::unique_ptr<CFXJSE_Value> jsObjectValue(new CFXJSE_Value(pIsolate));
dsinclair769b1372016-06-08 13:12:41 -0700565 if (propertyValue->IsNull()) {
dsinclair89ba6de2016-05-31 12:11:22 -0700566 for (int32_t j = 2; j < iLength; j++) {
dsinclairf27aeec2016-06-07 19:36:18 -0700567 argValue->GetObjectPropertyByIdx(j, jsObjectValue.get());
dsinclair89ba6de2016-05-31 12:11:22 -0700568 std::unique_ptr<CFXJSE_Value> defaultPropValue(
dsinclair86fad992016-05-31 11:34:04 -0700569 new CFXJSE_Value(pIsolate));
dsinclair89ba6de2016-05-31 12:11:22 -0700570 GetObjectDefaultValue(jsObjectValue.get(), defaultPropValue.get());
dsinclair769b1372016-06-08 13:12:41 -0700571 if (defaultPropValue->IsNull())
dsinclair89ba6de2016-05-31 12:11:22 -0700572 continue;
573
574 dSum += ValueToDouble(pThis, defaultPropValue.get());
575 uCount++;
Dan Sinclair1770c022016-03-14 14:14:16 -0400576 }
577 } else {
dsinclair89ba6de2016-05-31 12:11:22 -0700578 for (int32_t j = 2; j < iLength; j++) {
dsinclairf27aeec2016-06-07 19:36:18 -0700579 argValue->GetObjectPropertyByIdx(j, jsObjectValue.get());
dsinclair89ba6de2016-05-31 12:11:22 -0700580 std::unique_ptr<CFXJSE_Value> newPropertyValue(
581 new CFXJSE_Value(pIsolate));
dsinclair2f5582f2016-06-09 11:48:23 -0700582 jsObjectValue->GetObjectProperty(
583 propertyValue->ToString().AsStringC(), newPropertyValue.get());
dsinclair769b1372016-06-08 13:12:41 -0700584 if (newPropertyValue->IsNull())
dsinclair89ba6de2016-05-31 12:11:22 -0700585 continue;
586
587 dSum += ValueToDouble(pThis, newPropertyValue.get());
588 uCount++;
589 }
Dan Sinclair1770c022016-03-14 14:14:16 -0400590 }
Dan Sinclair1770c022016-03-14 14:14:16 -0400591 }
Dan Sinclair1770c022016-03-14 14:14:16 -0400592 }
dsinclair89ba6de2016-05-31 12:11:22 -0700593 if (uCount == 0) {
dsinclairf27aeec2016-06-07 19:36:18 -0700594 args.GetReturnValue()->SetNull();
dsinclair89ba6de2016-05-31 12:11:22 -0700595 return;
Dan Sinclair1770c022016-03-14 14:14:16 -0400596 }
dsinclair89ba6de2016-05-31 12:11:22 -0700597
dsinclairf27aeec2016-06-07 19:36:18 -0700598 args.GetReturnValue()->SetDouble(dSum / uCount);
Dan Sinclair1770c022016-03-14 14:14:16 -0400599}
dsinclair48d91dd2016-05-31 11:54:01 -0700600
601// static
dsinclair12a6b0c2016-05-26 11:14:08 -0700602void CXFA_FM2JSContext::Ceil(CFXJSE_Value* pThis,
Dan Sinclair1770c022016-03-14 14:14:16 -0400603 const CFX_ByteStringC& szFuncName,
604 CFXJSE_Arguments& args) {
dsinclair89ba6de2016-05-31 12:11:22 -0700605 if (args.GetLength() != 1) {
dsinclair8f3074b2016-06-02 17:45:25 -0700606 ToJSContext(pThis, nullptr)
607 ->ThrowException(XFA_IDS_INCORRECT_NUMBER_OF_METHOD, L"Ceil");
dsinclair89ba6de2016-05-31 12:11:22 -0700608 return;
Dan Sinclair1770c022016-03-14 14:14:16 -0400609 }
dsinclair89ba6de2016-05-31 12:11:22 -0700610
611 std::unique_ptr<CFXJSE_Value> argValue = GetSimpleValue(pThis, args, 0);
612 if (ValueIsNull(pThis, argValue.get())) {
dsinclairf27aeec2016-06-07 19:36:18 -0700613 args.GetReturnValue()->SetNull();
dsinclair89ba6de2016-05-31 12:11:22 -0700614 return;
615 }
616
dsinclairf27aeec2016-06-07 19:36:18 -0700617 args.GetReturnValue()->SetFloat(
618 FXSYS_ceil(ValueToFloat(pThis, argValue.get())));
Dan Sinclair1770c022016-03-14 14:14:16 -0400619}
dsinclair48d91dd2016-05-31 11:54:01 -0700620
621// static
dsinclair12a6b0c2016-05-26 11:14:08 -0700622void CXFA_FM2JSContext::Count(CFXJSE_Value* pThis,
Dan Sinclair1770c022016-03-14 14:14:16 -0400623 const CFX_ByteStringC& szFuncName,
624 CFXJSE_Arguments& args) {
dsinclair8f3074b2016-06-02 17:45:25 -0700625 CXFA_FM2JSContext* pContext = ToJSContext(pThis, nullptr);
dsinclairec3da5b2016-05-25 16:42:05 -0700626 v8::Isolate* pIsolate = pContext->GetScriptRuntime();
dsinclair89ba6de2016-05-31 12:11:22 -0700627 int32_t iCount = 0;
dsinclair48d91dd2016-05-31 11:54:01 -0700628 for (int32_t i = 0; i < args.GetLength(); i++) {
dsinclair86fad992016-05-31 11:34:04 -0700629 std::unique_ptr<CFXJSE_Value> argValue = args.GetValue(i);
dsinclair769b1372016-06-08 13:12:41 -0700630 if (argValue->IsNull())
Dan Sinclair1770c022016-03-14 14:14:16 -0400631 continue;
dsinclair89ba6de2016-05-31 12:11:22 -0700632
dsinclair769b1372016-06-08 13:12:41 -0700633 if (argValue->IsArray()) {
dsinclair86fad992016-05-31 11:34:04 -0700634 std::unique_ptr<CFXJSE_Value> lengthValue(new CFXJSE_Value(pIsolate));
dsinclairf27aeec2016-06-07 19:36:18 -0700635 argValue->GetObjectProperty("length", lengthValue.get());
dsinclair86fad992016-05-31 11:34:04 -0700636
dsinclairf27aeec2016-06-07 19:36:18 -0700637 int32_t iLength = lengthValue->ToInteger();
dsinclair89ba6de2016-05-31 12:11:22 -0700638 if (iLength <= 2) {
dsinclair2235b7b2016-06-02 07:42:25 -0700639 pContext->ThrowException(XFA_IDS_ARGUMENT_MISMATCH);
dsinclair89ba6de2016-05-31 12:11:22 -0700640 return;
641 }
642
643 std::unique_ptr<CFXJSE_Value> propertyValue(new CFXJSE_Value(pIsolate));
644 std::unique_ptr<CFXJSE_Value> jsObjectValue(new CFXJSE_Value(pIsolate));
645 std::unique_ptr<CFXJSE_Value> newPropertyValue(
646 new CFXJSE_Value(pIsolate));
dsinclairf27aeec2016-06-07 19:36:18 -0700647 argValue->GetObjectPropertyByIdx(1, propertyValue.get());
648 argValue->GetObjectPropertyByIdx(2, jsObjectValue.get());
dsinclair769b1372016-06-08 13:12:41 -0700649 if (propertyValue->IsNull()) {
weilidb444d22016-06-02 15:48:15 -0700650 for (int32_t j = 2; j < iLength; j++) {
dsinclairf27aeec2016-06-07 19:36:18 -0700651 argValue->GetObjectPropertyByIdx(j, jsObjectValue.get());
dsinclair89ba6de2016-05-31 12:11:22 -0700652 GetObjectDefaultValue(jsObjectValue.get(), newPropertyValue.get());
dsinclair769b1372016-06-08 13:12:41 -0700653 if (!newPropertyValue->IsNull())
dsinclair89ba6de2016-05-31 12:11:22 -0700654 iCount++;
Dan Sinclair1770c022016-03-14 14:14:16 -0400655 }
Dan Sinclair1770c022016-03-14 14:14:16 -0400656 } else {
weilidb444d22016-06-02 15:48:15 -0700657 for (int32_t j = 2; j < iLength; j++) {
dsinclairf27aeec2016-06-07 19:36:18 -0700658 argValue->GetObjectPropertyByIdx(j, jsObjectValue.get());
dsinclair2f5582f2016-06-09 11:48:23 -0700659 jsObjectValue->GetObjectProperty(
660 propertyValue->ToString().AsStringC(), newPropertyValue.get());
dsinclair769b1372016-06-08 13:12:41 -0700661 iCount += newPropertyValue->IsNull() ? 0 : 1;
dsinclair89ba6de2016-05-31 12:11:22 -0700662 }
Dan Sinclair1770c022016-03-14 14:14:16 -0400663 }
dsinclair769b1372016-06-08 13:12:41 -0700664 } else if (argValue->IsObject()) {
dsinclair86fad992016-05-31 11:34:04 -0700665 std::unique_ptr<CFXJSE_Value> newPropertyValue(
666 new CFXJSE_Value(pIsolate));
667 GetObjectDefaultValue(argValue.get(), newPropertyValue.get());
dsinclair769b1372016-06-08 13:12:41 -0700668 if (!newPropertyValue->IsNull())
dsinclair89ba6de2016-05-31 12:11:22 -0700669 iCount++;
Dan Sinclair1770c022016-03-14 14:14:16 -0400670 } else {
dsinclair89ba6de2016-05-31 12:11:22 -0700671 iCount++;
Dan Sinclair1770c022016-03-14 14:14:16 -0400672 }
Dan Sinclair1770c022016-03-14 14:14:16 -0400673 }
dsinclairf27aeec2016-06-07 19:36:18 -0700674 args.GetReturnValue()->SetInteger(iCount);
Dan Sinclair1770c022016-03-14 14:14:16 -0400675}
dsinclair48d91dd2016-05-31 11:54:01 -0700676
677// static
dsinclair12a6b0c2016-05-26 11:14:08 -0700678void CXFA_FM2JSContext::Floor(CFXJSE_Value* pThis,
Dan Sinclair1770c022016-03-14 14:14:16 -0400679 const CFX_ByteStringC& szFuncName,
680 CFXJSE_Arguments& args) {
dsinclair89ba6de2016-05-31 12:11:22 -0700681 if (args.GetLength() != 1) {
dsinclair8f3074b2016-06-02 17:45:25 -0700682 ToJSContext(pThis, nullptr)
683 ->ThrowException(XFA_IDS_INCORRECT_NUMBER_OF_METHOD, L"Floor");
dsinclair89ba6de2016-05-31 12:11:22 -0700684 return;
Dan Sinclair1770c022016-03-14 14:14:16 -0400685 }
dsinclair89ba6de2016-05-31 12:11:22 -0700686
687 std::unique_ptr<CFXJSE_Value> argValue = GetSimpleValue(pThis, args, 0);
688 if (ValueIsNull(pThis, argValue.get())) {
dsinclairf27aeec2016-06-07 19:36:18 -0700689 args.GetReturnValue()->SetNull();
dsinclair89ba6de2016-05-31 12:11:22 -0700690 return;
691 }
692
dsinclairf27aeec2016-06-07 19:36:18 -0700693 args.GetReturnValue()->SetFloat(
694 FXSYS_floor(ValueToFloat(pThis, argValue.get())));
Dan Sinclair1770c022016-03-14 14:14:16 -0400695}
dsinclair48d91dd2016-05-31 11:54:01 -0700696
697// static
dsinclair12a6b0c2016-05-26 11:14:08 -0700698void CXFA_FM2JSContext::Max(CFXJSE_Value* pThis,
Dan Sinclair1770c022016-03-14 14:14:16 -0400699 const CFX_ByteStringC& szFuncName,
700 CFXJSE_Arguments& args) {
dsinclair8f3074b2016-06-02 17:45:25 -0700701 CXFA_FM2JSContext* pContext = ToJSContext(pThis, nullptr);
dsinclairec3da5b2016-05-25 16:42:05 -0700702 v8::Isolate* pIsolate = pContext->GetScriptRuntime();
Dan Sinclair1770c022016-03-14 14:14:16 -0400703 uint32_t uCount = 0;
704 FX_DOUBLE dMaxValue = 0.0;
dsinclair48d91dd2016-05-31 11:54:01 -0700705 for (int32_t i = 0; i < args.GetLength(); i++) {
dsinclair86fad992016-05-31 11:34:04 -0700706 std::unique_ptr<CFXJSE_Value> argValue = args.GetValue(i);
dsinclair769b1372016-06-08 13:12:41 -0700707 if (argValue->IsNull())
Dan Sinclair1770c022016-03-14 14:14:16 -0400708 continue;
dsinclair89ba6de2016-05-31 12:11:22 -0700709
dsinclair769b1372016-06-08 13:12:41 -0700710 if (argValue->IsArray()) {
dsinclair86fad992016-05-31 11:34:04 -0700711 std::unique_ptr<CFXJSE_Value> lengthValue(new CFXJSE_Value(pIsolate));
dsinclairf27aeec2016-06-07 19:36:18 -0700712 argValue->GetObjectProperty("length", lengthValue.get());
713 int32_t iLength = lengthValue->ToInteger();
dsinclair89ba6de2016-05-31 12:11:22 -0700714 if (iLength <= 2) {
dsinclair2235b7b2016-06-02 07:42:25 -0700715 pContext->ThrowException(XFA_IDS_ARGUMENT_MISMATCH);
dsinclair89ba6de2016-05-31 12:11:22 -0700716 return;
717 }
dsinclair86fad992016-05-31 11:34:04 -0700718
dsinclair89ba6de2016-05-31 12:11:22 -0700719 std::unique_ptr<CFXJSE_Value> propertyValue(new CFXJSE_Value(pIsolate));
720 std::unique_ptr<CFXJSE_Value> jsObjectValue(new CFXJSE_Value(pIsolate));
721 std::unique_ptr<CFXJSE_Value> newPropertyValue(
722 new CFXJSE_Value(pIsolate));
dsinclairf27aeec2016-06-07 19:36:18 -0700723 argValue->GetObjectPropertyByIdx(1, propertyValue.get());
724 argValue->GetObjectPropertyByIdx(2, jsObjectValue.get());
dsinclair769b1372016-06-08 13:12:41 -0700725 if (propertyValue->IsNull()) {
weilidb444d22016-06-02 15:48:15 -0700726 for (int32_t j = 2; j < iLength; j++) {
dsinclairf27aeec2016-06-07 19:36:18 -0700727 argValue->GetObjectPropertyByIdx(j, jsObjectValue.get());
dsinclair89ba6de2016-05-31 12:11:22 -0700728 GetObjectDefaultValue(jsObjectValue.get(), newPropertyValue.get());
dsinclair769b1372016-06-08 13:12:41 -0700729 if (newPropertyValue->IsNull())
dsinclair89ba6de2016-05-31 12:11:22 -0700730 continue;
731
732 uCount++;
733 FX_DOUBLE dValue = ValueToDouble(pThis, newPropertyValue.get());
734 dMaxValue = (uCount == 1) ? dValue : std::max(dMaxValue, dValue);
Dan Sinclair1770c022016-03-14 14:14:16 -0400735 }
Dan Sinclair1770c022016-03-14 14:14:16 -0400736 } else {
weilidb444d22016-06-02 15:48:15 -0700737 for (int32_t j = 2; j < iLength; j++) {
dsinclairf27aeec2016-06-07 19:36:18 -0700738 argValue->GetObjectPropertyByIdx(j, jsObjectValue.get());
dsinclair2f5582f2016-06-09 11:48:23 -0700739 jsObjectValue->GetObjectProperty(
740 propertyValue->ToString().AsStringC(), newPropertyValue.get());
dsinclair769b1372016-06-08 13:12:41 -0700741 if (newPropertyValue->IsNull())
dsinclair89ba6de2016-05-31 12:11:22 -0700742 continue;
743
744 uCount++;
745 FX_DOUBLE dValue = ValueToDouble(pThis, newPropertyValue.get());
746 dMaxValue = (uCount == 1) ? dValue : std::max(dMaxValue, dValue);
747 }
Dan Sinclair1770c022016-03-14 14:14:16 -0400748 }
dsinclair769b1372016-06-08 13:12:41 -0700749 } else if (argValue->IsObject()) {
dsinclair86fad992016-05-31 11:34:04 -0700750 std::unique_ptr<CFXJSE_Value> newPropertyValue(
751 new CFXJSE_Value(pIsolate));
752 GetObjectDefaultValue(argValue.get(), newPropertyValue.get());
dsinclair769b1372016-06-08 13:12:41 -0700753 if (newPropertyValue->IsNull())
dsinclair89ba6de2016-05-31 12:11:22 -0700754 continue;
755
756 uCount++;
757 FX_DOUBLE dValue = ValueToDouble(pThis, newPropertyValue.get());
758 dMaxValue = (uCount == 1) ? dValue : std::max(dMaxValue, dValue);
Dan Sinclair1770c022016-03-14 14:14:16 -0400759 } else {
760 uCount++;
dsinclair89ba6de2016-05-31 12:11:22 -0700761 FX_DOUBLE dValue = ValueToDouble(pThis, argValue.get());
762 dMaxValue = (uCount == 1) ? dValue : std::max(dMaxValue, dValue);
Dan Sinclair1770c022016-03-14 14:14:16 -0400763 }
Dan Sinclair1770c022016-03-14 14:14:16 -0400764 }
dsinclair89ba6de2016-05-31 12:11:22 -0700765 if (uCount == 0) {
dsinclairf27aeec2016-06-07 19:36:18 -0700766 args.GetReturnValue()->SetNull();
dsinclair89ba6de2016-05-31 12:11:22 -0700767 return;
Dan Sinclair1770c022016-03-14 14:14:16 -0400768 }
dsinclair89ba6de2016-05-31 12:11:22 -0700769
dsinclairf27aeec2016-06-07 19:36:18 -0700770 args.GetReturnValue()->SetDouble(dMaxValue);
Dan Sinclair1770c022016-03-14 14:14:16 -0400771}
dsinclair48d91dd2016-05-31 11:54:01 -0700772
773// static
dsinclair12a6b0c2016-05-26 11:14:08 -0700774void CXFA_FM2JSContext::Min(CFXJSE_Value* pThis,
Dan Sinclair1770c022016-03-14 14:14:16 -0400775 const CFX_ByteStringC& szFuncName,
776 CFXJSE_Arguments& args) {
dsinclair8f3074b2016-06-02 17:45:25 -0700777 CXFA_FM2JSContext* pContext = ToJSContext(pThis, nullptr);
dsinclairec3da5b2016-05-25 16:42:05 -0700778 v8::Isolate* pIsolate = pContext->GetScriptRuntime();
Dan Sinclair1770c022016-03-14 14:14:16 -0400779 uint32_t uCount = 0;
780 FX_DOUBLE dMinValue = 0.0;
dsinclair48d91dd2016-05-31 11:54:01 -0700781 for (int32_t i = 0; i < args.GetLength(); i++) {
dsinclair86fad992016-05-31 11:34:04 -0700782 std::unique_ptr<CFXJSE_Value> argValue = args.GetValue(i);
dsinclair769b1372016-06-08 13:12:41 -0700783 if (argValue->IsNull())
Dan Sinclair1770c022016-03-14 14:14:16 -0400784 continue;
dsinclairdbdcb812016-06-01 20:07:22 -0700785
dsinclair769b1372016-06-08 13:12:41 -0700786 if (argValue->IsArray()) {
dsinclair86fad992016-05-31 11:34:04 -0700787 std::unique_ptr<CFXJSE_Value> lengthValue(new CFXJSE_Value(pIsolate));
dsinclairf27aeec2016-06-07 19:36:18 -0700788 argValue->GetObjectProperty("length", lengthValue.get());
789 int32_t iLength = lengthValue->ToInteger();
dsinclairdbdcb812016-06-01 20:07:22 -0700790 if (iLength <= 2) {
dsinclair2235b7b2016-06-02 07:42:25 -0700791 pContext->ThrowException(XFA_IDS_ARGUMENT_MISMATCH);
dsinclairdbdcb812016-06-01 20:07:22 -0700792 return;
793 }
794
795 std::unique_ptr<CFXJSE_Value> propertyValue(new CFXJSE_Value(pIsolate));
796 std::unique_ptr<CFXJSE_Value> jsObjectValue(new CFXJSE_Value(pIsolate));
797 std::unique_ptr<CFXJSE_Value> newPropertyValue(
798 new CFXJSE_Value(pIsolate));
dsinclairf27aeec2016-06-07 19:36:18 -0700799 argValue->GetObjectPropertyByIdx(1, propertyValue.get());
800 argValue->GetObjectPropertyByIdx(2, jsObjectValue.get());
dsinclair769b1372016-06-08 13:12:41 -0700801 if (propertyValue->IsNull()) {
weilidb444d22016-06-02 15:48:15 -0700802 for (int32_t j = 2; j < iLength; j++) {
dsinclairf27aeec2016-06-07 19:36:18 -0700803 argValue->GetObjectPropertyByIdx(j, jsObjectValue.get());
dsinclairdbdcb812016-06-01 20:07:22 -0700804 GetObjectDefaultValue(jsObjectValue.get(), newPropertyValue.get());
dsinclair769b1372016-06-08 13:12:41 -0700805 if (newPropertyValue->IsNull())
dsinclairdbdcb812016-06-01 20:07:22 -0700806 continue;
807
808 uCount++;
809 FX_DOUBLE dValue = ValueToDouble(pThis, newPropertyValue.get());
810 dMinValue = uCount == 1 ? dValue : std::min(dMinValue, dValue);
Dan Sinclair1770c022016-03-14 14:14:16 -0400811 }
Dan Sinclair1770c022016-03-14 14:14:16 -0400812 } else {
weilidb444d22016-06-02 15:48:15 -0700813 for (int32_t j = 2; j < iLength; j++) {
dsinclairf27aeec2016-06-07 19:36:18 -0700814 argValue->GetObjectPropertyByIdx(j, jsObjectValue.get());
dsinclair2f5582f2016-06-09 11:48:23 -0700815 jsObjectValue->GetObjectProperty(
816 propertyValue->ToString().AsStringC(), newPropertyValue.get());
dsinclair769b1372016-06-08 13:12:41 -0700817 if (newPropertyValue->IsNull())
dsinclairdbdcb812016-06-01 20:07:22 -0700818 continue;
819
820 uCount++;
821 FX_DOUBLE dValue = ValueToDouble(pThis, newPropertyValue.get());
822 dMinValue = uCount == 1 ? dValue : std::min(dMinValue, dValue);
823 }
Dan Sinclair1770c022016-03-14 14:14:16 -0400824 }
dsinclair769b1372016-06-08 13:12:41 -0700825 } else if (argValue->IsObject()) {
dsinclair86fad992016-05-31 11:34:04 -0700826 std::unique_ptr<CFXJSE_Value> newPropertyValue(
827 new CFXJSE_Value(pIsolate));
828 GetObjectDefaultValue(argValue.get(), newPropertyValue.get());
dsinclair769b1372016-06-08 13:12:41 -0700829 if (newPropertyValue->IsNull())
dsinclairdbdcb812016-06-01 20:07:22 -0700830 continue;
831
832 uCount++;
833 FX_DOUBLE dValue = ValueToDouble(pThis, newPropertyValue.get());
834 dMinValue = uCount == 1 ? dValue : std::min(dMinValue, dValue);
Dan Sinclair1770c022016-03-14 14:14:16 -0400835 } else {
836 uCount++;
dsinclairdbdcb812016-06-01 20:07:22 -0700837 FX_DOUBLE dValue = ValueToDouble(pThis, argValue.get());
838 dMinValue = uCount == 1 ? dValue : std::min(dMinValue, dValue);
Dan Sinclair1770c022016-03-14 14:14:16 -0400839 }
Dan Sinclair1770c022016-03-14 14:14:16 -0400840 }
dsinclairdbdcb812016-06-01 20:07:22 -0700841 if (uCount == 0) {
dsinclairf27aeec2016-06-07 19:36:18 -0700842 args.GetReturnValue()->SetNull();
dsinclairdbdcb812016-06-01 20:07:22 -0700843 return;
Dan Sinclair1770c022016-03-14 14:14:16 -0400844 }
dsinclairdbdcb812016-06-01 20:07:22 -0700845
dsinclairf27aeec2016-06-07 19:36:18 -0700846 args.GetReturnValue()->SetDouble(dMinValue);
Dan Sinclair1770c022016-03-14 14:14:16 -0400847}
dsinclair48d91dd2016-05-31 11:54:01 -0700848
849// static
dsinclair12a6b0c2016-05-26 11:14:08 -0700850void CXFA_FM2JSContext::Mod(CFXJSE_Value* pThis,
Dan Sinclair1770c022016-03-14 14:14:16 -0400851 const CFX_ByteStringC& szFuncName,
852 CFXJSE_Arguments& args) {
dsinclair8f3074b2016-06-02 17:45:25 -0700853 CXFA_FM2JSContext* pContext = ToJSContext(pThis, nullptr);
dsinclairdbdcb812016-06-01 20:07:22 -0700854 if (args.GetLength() != 2) {
dsinclair2235b7b2016-06-02 07:42:25 -0700855 pContext->ThrowException(XFA_IDS_INCORRECT_NUMBER_OF_METHOD, L"Mod");
dsinclairdbdcb812016-06-01 20:07:22 -0700856 return;
Dan Sinclair1770c022016-03-14 14:14:16 -0400857 }
dsinclairdbdcb812016-06-01 20:07:22 -0700858
859 std::unique_ptr<CFXJSE_Value> argOne = args.GetValue(0);
860 std::unique_ptr<CFXJSE_Value> argTwo = args.GetValue(1);
dsinclair769b1372016-06-08 13:12:41 -0700861 if (argOne->IsNull() || argTwo->IsNull()) {
dsinclairf27aeec2016-06-07 19:36:18 -0700862 args.GetReturnValue()->SetNull();
dsinclairdbdcb812016-06-01 20:07:22 -0700863 return;
864 }
865
866 bool argOneResult;
867 FX_DOUBLE dDividend = ExtractDouble(pThis, argOne.get(), &argOneResult);
868 bool argTwoResult;
869 FX_DOUBLE dDivisor = ExtractDouble(pThis, argTwo.get(), &argTwoResult);
870 if (!argOneResult || !argTwoResult) {
dsinclair2235b7b2016-06-02 07:42:25 -0700871 pContext->ThrowException(XFA_IDS_ARGUMENT_MISMATCH);
dsinclairdbdcb812016-06-01 20:07:22 -0700872 return;
873 }
874
875 if (dDivisor == 0.0) {
dsinclair2235b7b2016-06-02 07:42:25 -0700876 pContext->ThrowException(XFA_IDS_DIVIDE_ZERO);
dsinclairdbdcb812016-06-01 20:07:22 -0700877 return;
878 }
879
dsinclairf27aeec2016-06-07 19:36:18 -0700880 args.GetReturnValue()->SetDouble(dDividend -
881 dDivisor * (int32_t)(dDividend / dDivisor));
Dan Sinclair1770c022016-03-14 14:14:16 -0400882}
dsinclair48d91dd2016-05-31 11:54:01 -0700883
884// static
dsinclair12a6b0c2016-05-26 11:14:08 -0700885void CXFA_FM2JSContext::Round(CFXJSE_Value* pThis,
Dan Sinclair1770c022016-03-14 14:14:16 -0400886 const CFX_ByteStringC& szFuncName,
887 CFXJSE_Arguments& args) {
dsinclair8f3074b2016-06-02 17:45:25 -0700888 CXFA_FM2JSContext* pContext = ToJSContext(pThis, nullptr);
Dan Sinclair1770c022016-03-14 14:14:16 -0400889 int32_t argc = args.GetLength();
dsinclair2b6d64e2016-06-06 11:39:42 -0700890 if (argc < 1 || argc > 2) {
dsinclair2235b7b2016-06-02 07:42:25 -0700891 pContext->ThrowException(XFA_IDS_INCORRECT_NUMBER_OF_METHOD, L"Round");
dsinclairdbdcb812016-06-01 20:07:22 -0700892 return;
Dan Sinclair1770c022016-03-14 14:14:16 -0400893 }
dsinclairdbdcb812016-06-01 20:07:22 -0700894
895 std::unique_ptr<CFXJSE_Value> argOne = args.GetValue(0);
dsinclair769b1372016-06-08 13:12:41 -0700896 if (argOne->IsNull()) {
dsinclairf27aeec2016-06-07 19:36:18 -0700897 args.GetReturnValue()->SetNull();
dsinclairdbdcb812016-06-01 20:07:22 -0700898 return;
899 }
900
901 bool dValueRet;
902 FX_DOUBLE dValue = ExtractDouble(pThis, argOne.get(), &dValueRet);
903 if (!dValueRet) {
dsinclair2235b7b2016-06-02 07:42:25 -0700904 pContext->ThrowException(XFA_IDS_ARGUMENT_MISMATCH);
dsinclairdbdcb812016-06-01 20:07:22 -0700905 return;
906 }
907
908 uint8_t uPrecision = 0;
dsinclair2b6d64e2016-06-06 11:39:42 -0700909 if (argc > 1) {
dsinclairdbdcb812016-06-01 20:07:22 -0700910 std::unique_ptr<CFXJSE_Value> argTwo = args.GetValue(1);
dsinclair769b1372016-06-08 13:12:41 -0700911 if (argTwo->IsNull()) {
dsinclairf27aeec2016-06-07 19:36:18 -0700912 args.GetReturnValue()->SetNull();
dsinclairdbdcb812016-06-01 20:07:22 -0700913 return;
914 }
915
916 bool dPrecisionRet;
917 FX_DOUBLE dPrecision = ExtractDouble(pThis, argTwo.get(), &dPrecisionRet);
918 if (!dPrecisionRet) {
dsinclair2235b7b2016-06-02 07:42:25 -0700919 pContext->ThrowException(XFA_IDS_ARGUMENT_MISMATCH);
dsinclairdbdcb812016-06-01 20:07:22 -0700920 return;
921 }
922
923 uPrecision =
924 static_cast<uint8_t>(std::min(std::max(dPrecision, 0.0), 12.0));
925 }
926
927 CFX_Decimal decimalValue((FX_FLOAT)dValue, uPrecision);
928 CFX_WideString wsValue = decimalValue;
dsinclairf27aeec2016-06-07 19:36:18 -0700929 args.GetReturnValue()->SetString(wsValue.UTF8Encode().AsStringC());
Dan Sinclair1770c022016-03-14 14:14:16 -0400930}
dsinclair48d91dd2016-05-31 11:54:01 -0700931
932// static
dsinclair12a6b0c2016-05-26 11:14:08 -0700933void CXFA_FM2JSContext::Sum(CFXJSE_Value* pThis,
Dan Sinclair1770c022016-03-14 14:14:16 -0400934 const CFX_ByteStringC& szFuncName,
935 CFXJSE_Arguments& args) {
dsinclairdbdcb812016-06-01 20:07:22 -0700936 int32_t argc = args.GetLength();
937 if (argc == 0) {
dsinclairf27aeec2016-06-07 19:36:18 -0700938 args.GetReturnValue()->SetNull();
dsinclairdbdcb812016-06-01 20:07:22 -0700939 return;
940 }
941
dsinclair8f3074b2016-06-02 17:45:25 -0700942 CXFA_FM2JSContext* pContext = ToJSContext(pThis, nullptr);
dsinclairec3da5b2016-05-25 16:42:05 -0700943 v8::Isolate* pIsolate = pContext->GetScriptRuntime();
Dan Sinclair1770c022016-03-14 14:14:16 -0400944 uint32_t uCount = 0;
945 FX_DOUBLE dSum = 0.0;
dsinclairdbdcb812016-06-01 20:07:22 -0700946 for (int32_t i = 0; i < argc; i++) {
947 std::unique_ptr<CFXJSE_Value> argValue = args.GetValue(i);
dsinclair769b1372016-06-08 13:12:41 -0700948 if (argValue->IsNull())
dsinclairdbdcb812016-06-01 20:07:22 -0700949 continue;
950
dsinclair769b1372016-06-08 13:12:41 -0700951 if (argValue->IsArray()) {
dsinclairdbdcb812016-06-01 20:07:22 -0700952 std::unique_ptr<CFXJSE_Value> lengthValue(new CFXJSE_Value(pIsolate));
dsinclairf27aeec2016-06-07 19:36:18 -0700953 argValue->GetObjectProperty("length", lengthValue.get());
954 int32_t iLength = lengthValue->ToInteger();
dsinclairdbdcb812016-06-01 20:07:22 -0700955 if (iLength <= 2) {
dsinclair2235b7b2016-06-02 07:42:25 -0700956 pContext->ThrowException(XFA_IDS_ARGUMENT_MISMATCH);
dsinclairdbdcb812016-06-01 20:07:22 -0700957 return;
958 }
959
960 std::unique_ptr<CFXJSE_Value> propertyValue(new CFXJSE_Value(pIsolate));
dsinclairf27aeec2016-06-07 19:36:18 -0700961 argValue->GetObjectPropertyByIdx(1, propertyValue.get());
dsinclairdbdcb812016-06-01 20:07:22 -0700962 std::unique_ptr<CFXJSE_Value> jsObjectValue(new CFXJSE_Value(pIsolate));
963 std::unique_ptr<CFXJSE_Value> newPropertyValue(
964 new CFXJSE_Value(pIsolate));
dsinclair769b1372016-06-08 13:12:41 -0700965 if (propertyValue->IsNull()) {
dsinclairdbdcb812016-06-01 20:07:22 -0700966 for (int32_t j = 2; j < iLength; j++) {
dsinclairf27aeec2016-06-07 19:36:18 -0700967 argValue->GetObjectPropertyByIdx(j, jsObjectValue.get());
dsinclairdbdcb812016-06-01 20:07:22 -0700968 GetObjectDefaultValue(jsObjectValue.get(), newPropertyValue.get());
dsinclair769b1372016-06-08 13:12:41 -0700969 if (newPropertyValue->IsNull())
dsinclairdbdcb812016-06-01 20:07:22 -0700970 continue;
971
972 dSum += ValueToDouble(pThis, jsObjectValue.get());
Dan Sinclair1770c022016-03-14 14:14:16 -0400973 uCount++;
974 }
Dan Sinclair1770c022016-03-14 14:14:16 -0400975 } else {
dsinclairdbdcb812016-06-01 20:07:22 -0700976 for (int32_t j = 2; j < iLength; j++) {
dsinclairf27aeec2016-06-07 19:36:18 -0700977 argValue->GetObjectPropertyByIdx(j, jsObjectValue.get());
dsinclair2f5582f2016-06-09 11:48:23 -0700978 jsObjectValue->GetObjectProperty(
979 propertyValue->ToString().AsStringC(), newPropertyValue.get());
dsinclair769b1372016-06-08 13:12:41 -0700980 if (newPropertyValue->IsNull())
dsinclairdbdcb812016-06-01 20:07:22 -0700981 continue;
982
983 dSum += ValueToDouble(pThis, newPropertyValue.get());
984 uCount++;
985 }
Dan Sinclair1770c022016-03-14 14:14:16 -0400986 }
dsinclair769b1372016-06-08 13:12:41 -0700987 } else if (argValue->IsObject()) {
dsinclairdbdcb812016-06-01 20:07:22 -0700988 std::unique_ptr<CFXJSE_Value> newPropertyValue(
989 new CFXJSE_Value(pIsolate));
990 GetObjectDefaultValue(argValue.get(), newPropertyValue.get());
dsinclair769b1372016-06-08 13:12:41 -0700991 if (newPropertyValue->IsNull())
dsinclairdbdcb812016-06-01 20:07:22 -0700992 continue;
993
994 dSum += ValueToDouble(pThis, argValue.get());
995 uCount++;
996 } else {
997 dSum += ValueToDouble(pThis, argValue.get());
998 uCount++;
Dan Sinclair1770c022016-03-14 14:14:16 -0400999 }
Dan Sinclair1770c022016-03-14 14:14:16 -04001000 }
dsinclairdbdcb812016-06-01 20:07:22 -07001001 if (uCount == 0) {
dsinclairf27aeec2016-06-07 19:36:18 -07001002 args.GetReturnValue()->SetNull();
dsinclairdbdcb812016-06-01 20:07:22 -07001003 return;
Dan Sinclair1770c022016-03-14 14:14:16 -04001004 }
dsinclairdbdcb812016-06-01 20:07:22 -07001005
dsinclairf27aeec2016-06-07 19:36:18 -07001006 args.GetReturnValue()->SetDouble(dSum);
Dan Sinclair1770c022016-03-14 14:14:16 -04001007}
dsinclair48d91dd2016-05-31 11:54:01 -07001008
1009// static
dsinclair12a6b0c2016-05-26 11:14:08 -07001010void CXFA_FM2JSContext::Date(CFXJSE_Value* pThis,
Dan Sinclair1770c022016-03-14 14:14:16 -04001011 const CFX_ByteStringC& szFuncName,
1012 CFXJSE_Arguments& args) {
dsinclairdbdcb812016-06-01 20:07:22 -07001013 if (args.GetLength() != 0) {
dsinclair8f3074b2016-06-02 17:45:25 -07001014 ToJSContext(pThis, nullptr)
1015 ->ThrowException(XFA_IDS_INCORRECT_NUMBER_OF_METHOD, L"Date");
dsinclairdbdcb812016-06-01 20:07:22 -07001016 return;
Dan Sinclair1770c022016-03-14 14:14:16 -04001017 }
dsinclairdbdcb812016-06-01 20:07:22 -07001018
1019 time_t currentTime;
1020 time(&currentTime);
1021 struct tm* pTmStruct = gmtime(&currentTime);
1022
1023 CFX_ByteString bufferYear;
1024 CFX_ByteString bufferMon;
1025 CFX_ByteString bufferDay;
1026 bufferYear.Format("%d", pTmStruct->tm_year + 1900);
1027 bufferMon.Format("%02d", pTmStruct->tm_mon + 1);
1028 bufferDay.Format("%02d", pTmStruct->tm_mday);
1029
1030 CFX_ByteString bufferCurrent = bufferYear + bufferMon + bufferDay;
dsinclairf27aeec2016-06-07 19:36:18 -07001031 args.GetReturnValue()->SetInteger(DateString2Num(bufferCurrent.AsStringC()));
Dan Sinclair1770c022016-03-14 14:14:16 -04001032}
dsinclair48d91dd2016-05-31 11:54:01 -07001033
1034// static
dsinclair12a6b0c2016-05-26 11:14:08 -07001035void CXFA_FM2JSContext::Date2Num(CFXJSE_Value* pThis,
Dan Sinclair1770c022016-03-14 14:14:16 -04001036 const CFX_ByteStringC& szFuncName,
1037 CFXJSE_Arguments& args) {
1038 int32_t argc = args.GetLength();
dsinclair2b6d64e2016-06-06 11:39:42 -07001039 if (argc < 1 || argc > 3) {
dsinclair8f3074b2016-06-02 17:45:25 -07001040 ToJSContext(pThis, nullptr)
1041 ->ThrowException(XFA_IDS_INCORRECT_NUMBER_OF_METHOD, L"Date2Num");
dsinclairdbdcb812016-06-01 20:07:22 -07001042 return;
Dan Sinclair1770c022016-03-14 14:14:16 -04001043 }
dsinclairdbdcb812016-06-01 20:07:22 -07001044
1045 std::unique_ptr<CFXJSE_Value> dateValue = GetSimpleValue(pThis, args, 0);
1046 if (ValueIsNull(pThis, dateValue.get())) {
dsinclairf27aeec2016-06-07 19:36:18 -07001047 args.GetReturnValue()->SetNull();
dsinclairdbdcb812016-06-01 20:07:22 -07001048 return;
1049 }
1050
1051 CFX_ByteString dateString;
1052 ValueToUTF8String(dateValue.get(), dateString);
1053
1054 CFX_ByteString formatString;
1055 if (argc > 1) {
1056 std::unique_ptr<CFXJSE_Value> formatValue = GetSimpleValue(pThis, args, 1);
1057 if (ValueIsNull(pThis, formatValue.get())) {
dsinclairf27aeec2016-06-07 19:36:18 -07001058 args.GetReturnValue()->SetNull();
dsinclairdbdcb812016-06-01 20:07:22 -07001059 return;
1060 }
1061 ValueToUTF8String(formatValue.get(), formatString);
1062 }
1063
1064 CFX_ByteString localString;
dsinclair2b6d64e2016-06-06 11:39:42 -07001065 if (argc > 2) {
dsinclairdbdcb812016-06-01 20:07:22 -07001066 std::unique_ptr<CFXJSE_Value> localValue = GetSimpleValue(pThis, args, 2);
1067 if (ValueIsNull(pThis, localValue.get())) {
dsinclairf27aeec2016-06-07 19:36:18 -07001068 args.GetReturnValue()->SetNull();
dsinclairdbdcb812016-06-01 20:07:22 -07001069 return;
1070 }
1071 ValueToUTF8String(localValue.get(), localString);
1072 }
1073
1074 CFX_ByteString szIsoDateString;
1075 if (!Local2IsoDate(pThis, dateString.AsStringC(), formatString.AsStringC(),
1076 localString.AsStringC(), szIsoDateString)) {
dsinclairf27aeec2016-06-07 19:36:18 -07001077 args.GetReturnValue()->SetInteger(0);
dsinclairdbdcb812016-06-01 20:07:22 -07001078 return;
1079 }
1080
dsinclairf27aeec2016-06-07 19:36:18 -07001081 args.GetReturnValue()->SetInteger(
1082 DateString2Num(szIsoDateString.AsStringC()));
Dan Sinclair1770c022016-03-14 14:14:16 -04001083}
dsinclair48d91dd2016-05-31 11:54:01 -07001084
1085// static
dsinclair12a6b0c2016-05-26 11:14:08 -07001086void CXFA_FM2JSContext::DateFmt(CFXJSE_Value* pThis,
Dan Sinclair1770c022016-03-14 14:14:16 -04001087 const CFX_ByteStringC& szFuncName,
1088 CFXJSE_Arguments& args) {
1089 int32_t argc = args.GetLength();
dsinclair2b6d64e2016-06-06 11:39:42 -07001090 if (argc > 2) {
dsinclair8f3074b2016-06-02 17:45:25 -07001091 ToJSContext(pThis, nullptr)
1092 ->ThrowException(XFA_IDS_INCORRECT_NUMBER_OF_METHOD, L"Date2Num");
dsinclairdbdcb812016-06-01 20:07:22 -07001093 return;
Dan Sinclair1770c022016-03-14 14:14:16 -04001094 }
dsinclairdbdcb812016-06-01 20:07:22 -07001095
1096 int32_t iStyle = 0;
1097 if (argc > 0) {
1098 std::unique_ptr<CFXJSE_Value> argStyle = GetSimpleValue(pThis, args, 0);
dsinclair769b1372016-06-08 13:12:41 -07001099 if (argStyle->IsNull()) {
dsinclairf27aeec2016-06-07 19:36:18 -07001100 args.GetReturnValue()->SetNull();
dsinclairdbdcb812016-06-01 20:07:22 -07001101 return;
1102 }
1103
1104 iStyle = (int32_t)ValueToFloat(pThis, argStyle.get());
1105 if (iStyle < 0 || iStyle > 4)
1106 iStyle = 0;
1107 }
1108
1109 CFX_ByteString szLocal;
dsinclair2b6d64e2016-06-06 11:39:42 -07001110 if (argc > 1) {
dsinclairdbdcb812016-06-01 20:07:22 -07001111 std::unique_ptr<CFXJSE_Value> argLocal = GetSimpleValue(pThis, args, 1);
dsinclair769b1372016-06-08 13:12:41 -07001112 if (argLocal->IsNull()) {
dsinclairf27aeec2016-06-07 19:36:18 -07001113 args.GetReturnValue()->SetNull();
dsinclairdbdcb812016-06-01 20:07:22 -07001114 return;
1115 }
1116 ValueToUTF8String(argLocal.get(), szLocal);
1117 }
1118
1119 CFX_ByteString formatStr;
1120 GetStandardDateFormat(pThis, iStyle, szLocal.AsStringC(), formatStr);
dsinclairf27aeec2016-06-07 19:36:18 -07001121 args.GetReturnValue()->SetString(formatStr.AsStringC());
Dan Sinclair1770c022016-03-14 14:14:16 -04001122}
dsinclair48d91dd2016-05-31 11:54:01 -07001123
1124// static
dsinclair12a6b0c2016-05-26 11:14:08 -07001125void CXFA_FM2JSContext::IsoDate2Num(CFXJSE_Value* pThis,
Dan Sinclair1770c022016-03-14 14:14:16 -04001126 const CFX_ByteStringC& szFuncName,
1127 CFXJSE_Arguments& args) {
dsinclairdbdcb812016-06-01 20:07:22 -07001128 if (args.GetLength() != 1) {
dsinclair8f3074b2016-06-02 17:45:25 -07001129 ToJSContext(pThis, nullptr)
1130 ->ThrowException(XFA_IDS_INCORRECT_NUMBER_OF_METHOD, L"IsoDate2Num");
dsinclairdbdcb812016-06-01 20:07:22 -07001131 return;
Dan Sinclair1770c022016-03-14 14:14:16 -04001132 }
dsinclairdbdcb812016-06-01 20:07:22 -07001133
1134 std::unique_ptr<CFXJSE_Value> argOne = GetSimpleValue(pThis, args, 0);
dsinclair769b1372016-06-08 13:12:41 -07001135 if (argOne->IsNull()) {
dsinclairf27aeec2016-06-07 19:36:18 -07001136 args.GetReturnValue()->SetNull();
dsinclairdbdcb812016-06-01 20:07:22 -07001137 return;
1138 }
1139
1140 CFX_ByteString szArgString;
1141 ValueToUTF8String(argOne.get(), szArgString);
dsinclairf27aeec2016-06-07 19:36:18 -07001142 args.GetReturnValue()->SetInteger(DateString2Num(szArgString.AsStringC()));
Dan Sinclair1770c022016-03-14 14:14:16 -04001143}
dsinclair48d91dd2016-05-31 11:54:01 -07001144
1145// static
dsinclair12a6b0c2016-05-26 11:14:08 -07001146void CXFA_FM2JSContext::IsoTime2Num(CFXJSE_Value* pThis,
Dan Sinclair1770c022016-03-14 14:14:16 -04001147 const CFX_ByteStringC& szFuncName,
1148 CFXJSE_Arguments& args) {
dsinclair8f3074b2016-06-02 17:45:25 -07001149 CXFA_FM2JSContext* pContext = ToJSContext(pThis, nullptr);
dsinclairdbdcb812016-06-01 20:07:22 -07001150 if (args.GetLength() != 1) {
dsinclair2235b7b2016-06-02 07:42:25 -07001151 pContext->ThrowException(XFA_IDS_INCORRECT_NUMBER_OF_METHOD,
1152 L"IsoTime2Num");
dsinclairdbdcb812016-06-01 20:07:22 -07001153 return;
Dan Sinclair1770c022016-03-14 14:14:16 -04001154 }
dsinclairdbdcb812016-06-01 20:07:22 -07001155
1156 std::unique_ptr<CFXJSE_Value> argOne = GetSimpleValue(pThis, args, 0);
1157 if (ValueIsNull(pThis, argOne.get())) {
dsinclairf27aeec2016-06-07 19:36:18 -07001158 args.GetReturnValue()->SetNull();
dsinclairdbdcb812016-06-01 20:07:22 -07001159 return;
1160 }
1161
1162 CXFA_Document* pDoc = pContext->GetDocument();
1163 CXFA_LocaleMgr* pMgr = pDoc->GetLocalMgr();
1164
1165 CFX_ByteString szArgString;
1166 ValueToUTF8String(argOne.get(), szArgString);
1167 szArgString = szArgString.Mid(szArgString.Find('T', 0) + 1);
1168 if (szArgString.IsEmpty()) {
dsinclairf27aeec2016-06-07 19:36:18 -07001169 args.GetReturnValue()->SetInteger(0);
dsinclairdbdcb812016-06-01 20:07:22 -07001170 return;
1171 }
1172
1173 CXFA_LocaleValue timeValue(
1174 XFA_VT_TIME, CFX_WideString::FromUTF8(szArgString.AsStringC()), pMgr);
1175 if (!timeValue.IsValid()) {
dsinclairf27aeec2016-06-07 19:36:18 -07001176 args.GetReturnValue()->SetInteger(0);
dsinclairdbdcb812016-06-01 20:07:22 -07001177 return;
1178 }
1179
1180 CFX_Unitime uniTime = timeValue.GetTime();
1181 int32_t hour = uniTime.GetHour();
1182 int32_t min = uniTime.GetMinute();
1183 int32_t second = uniTime.GetSecond();
1184 int32_t milSecond = uniTime.GetMillisecond();
1185
1186 FX_TIMEZONE tzLocale;
1187 pMgr->GetDefLocale()->GetTimeZone(tzLocale);
1188
1189 // TODO(dsinclair): See if there is other time conversion code in pdfium and
1190 // consolidate.
1191 int32_t mins = hour * 60 + min;
1192 mins -= (tzLocale.tzHour * 60);
1193 while (mins > 1440)
1194 mins -= 1440;
1195 while (mins < 0)
1196 mins += 1440;
1197 hour = mins / 60;
1198 min = mins % 60;
dsinclairf27aeec2016-06-07 19:36:18 -07001199
1200 args.GetReturnValue()->SetInteger(hour * 3600000 + min * 60000 +
1201 second * 1000 + milSecond + 1);
Dan Sinclair1770c022016-03-14 14:14:16 -04001202}
dsinclair48d91dd2016-05-31 11:54:01 -07001203
1204// static
dsinclair12a6b0c2016-05-26 11:14:08 -07001205void CXFA_FM2JSContext::LocalDateFmt(CFXJSE_Value* pThis,
Dan Sinclair1770c022016-03-14 14:14:16 -04001206 const CFX_ByteStringC& szFuncName,
1207 CFXJSE_Arguments& args) {
1208 int32_t argc = args.GetLength();
dsinclair2b6d64e2016-06-06 11:39:42 -07001209 if (argc > 2) {
dsinclair8f3074b2016-06-02 17:45:25 -07001210 ToJSContext(pThis, nullptr)
1211 ->ThrowException(XFA_IDS_INCORRECT_NUMBER_OF_METHOD, L"LocalDateFmt");
dsinclair2b6d64e2016-06-06 11:39:42 -07001212 return;
Dan Sinclair1770c022016-03-14 14:14:16 -04001213 }
dsinclair2b6d64e2016-06-06 11:39:42 -07001214
1215 int32_t iStyle = 0;
1216 if (argc > 0) {
1217 std::unique_ptr<CFXJSE_Value> argStyle = GetSimpleValue(pThis, args, 0);
dsinclair769b1372016-06-08 13:12:41 -07001218 if (argStyle->IsNull()) {
dsinclairf27aeec2016-06-07 19:36:18 -07001219 args.GetReturnValue()->SetNull();
dsinclair2b6d64e2016-06-06 11:39:42 -07001220 return;
1221 }
1222 iStyle = (int32_t)ValueToFloat(pThis, argStyle.get());
1223 if (iStyle > 4 || iStyle < 0)
1224 iStyle = 0;
1225 }
1226
1227 CFX_ByteString szLocal;
1228 if (argc > 1) {
1229 std::unique_ptr<CFXJSE_Value> argLocal = GetSimpleValue(pThis, args, 1);
dsinclair769b1372016-06-08 13:12:41 -07001230 if (argLocal->IsNull()) {
dsinclairf27aeec2016-06-07 19:36:18 -07001231 args.GetReturnValue()->SetNull();
dsinclair2b6d64e2016-06-06 11:39:42 -07001232 return;
1233 }
1234 ValueToUTF8String(argLocal.get(), szLocal);
1235 }
1236
1237 CFX_ByteString formatStr;
1238 GetLocalDateFormat(pThis, iStyle, szLocal.AsStringC(), formatStr, FALSE);
dsinclairf27aeec2016-06-07 19:36:18 -07001239 args.GetReturnValue()->SetString(formatStr.AsStringC());
Dan Sinclair1770c022016-03-14 14:14:16 -04001240}
dsinclair48d91dd2016-05-31 11:54:01 -07001241
1242// static
dsinclair12a6b0c2016-05-26 11:14:08 -07001243void CXFA_FM2JSContext::LocalTimeFmt(CFXJSE_Value* pThis,
Dan Sinclair1770c022016-03-14 14:14:16 -04001244 const CFX_ByteStringC& szFuncName,
1245 CFXJSE_Arguments& args) {
1246 int32_t argc = args.GetLength();
dsinclair2b6d64e2016-06-06 11:39:42 -07001247 if (argc > 2) {
dsinclair8f3074b2016-06-02 17:45:25 -07001248 ToJSContext(pThis, nullptr)
1249 ->ThrowException(XFA_IDS_INCORRECT_NUMBER_OF_METHOD, L"LocalTimeFmt");
dsinclair2b6d64e2016-06-06 11:39:42 -07001250 return;
Dan Sinclair1770c022016-03-14 14:14:16 -04001251 }
dsinclair2b6d64e2016-06-06 11:39:42 -07001252
1253 int32_t iStyle = 0;
1254 if (argc > 0) {
1255 std::unique_ptr<CFXJSE_Value> argStyle = GetSimpleValue(pThis, args, 0);
dsinclair769b1372016-06-08 13:12:41 -07001256 if (argStyle->IsNull()) {
dsinclairf27aeec2016-06-07 19:36:18 -07001257 args.GetReturnValue()->SetNull();
dsinclair2b6d64e2016-06-06 11:39:42 -07001258 return;
1259 }
1260 iStyle = (int32_t)ValueToFloat(pThis, argStyle.get());
1261 if (iStyle > 4 || iStyle < 0)
1262 iStyle = 0;
1263 }
1264
1265 CFX_ByteString szLocal;
1266 if (argc > 1) {
1267 std::unique_ptr<CFXJSE_Value> argLocal = GetSimpleValue(pThis, args, 1);
dsinclair769b1372016-06-08 13:12:41 -07001268 if (argLocal->IsNull()) {
dsinclairf27aeec2016-06-07 19:36:18 -07001269 args.GetReturnValue()->SetNull();
dsinclair2b6d64e2016-06-06 11:39:42 -07001270 return;
1271 }
1272 ValueToUTF8String(argLocal.get(), szLocal);
1273 }
1274
1275 CFX_ByteString formatStr;
1276 GetLocalTimeFormat(pThis, iStyle, szLocal.AsStringC(), formatStr, FALSE);
dsinclairf27aeec2016-06-07 19:36:18 -07001277 args.GetReturnValue()->SetString(formatStr.AsStringC());
Dan Sinclair1770c022016-03-14 14:14:16 -04001278}
dsinclair48d91dd2016-05-31 11:54:01 -07001279
1280// static
dsinclair12a6b0c2016-05-26 11:14:08 -07001281void CXFA_FM2JSContext::Num2Date(CFXJSE_Value* pThis,
Dan Sinclair1770c022016-03-14 14:14:16 -04001282 const CFX_ByteStringC& szFuncName,
1283 CFXJSE_Arguments& args) {
1284 int32_t argc = args.GetLength();
dsinclair2b6d64e2016-06-06 11:39:42 -07001285 if (argc < 1 || argc > 3) {
dsinclair8f3074b2016-06-02 17:45:25 -07001286 ToJSContext(pThis, nullptr)
1287 ->ThrowException(XFA_IDS_INCORRECT_NUMBER_OF_METHOD, L"Num2Date");
dsinclair2b6d64e2016-06-06 11:39:42 -07001288 return;
Dan Sinclair1770c022016-03-14 14:14:16 -04001289 }
dsinclair2b6d64e2016-06-06 11:39:42 -07001290
1291 std::unique_ptr<CFXJSE_Value> dateValue = GetSimpleValue(pThis, args, 0);
1292 if (ValueIsNull(pThis, dateValue.get())) {
dsinclairf27aeec2016-06-07 19:36:18 -07001293 args.GetReturnValue()->SetNull();
dsinclair2b6d64e2016-06-06 11:39:42 -07001294 return;
1295 }
1296 int32_t dDate = (int32_t)ValueToFloat(pThis, dateValue.get());
1297 if (dDate < 1) {
dsinclairf27aeec2016-06-07 19:36:18 -07001298 args.GetReturnValue()->SetNull();
dsinclair2b6d64e2016-06-06 11:39:42 -07001299 return;
1300 }
1301
1302 CFX_ByteString formatString;
1303 if (argc > 1) {
1304 std::unique_ptr<CFXJSE_Value> formatValue = GetSimpleValue(pThis, args, 1);
1305 if (ValueIsNull(pThis, formatValue.get())) {
dsinclairf27aeec2016-06-07 19:36:18 -07001306 args.GetReturnValue()->SetNull();
dsinclair2b6d64e2016-06-06 11:39:42 -07001307 return;
1308 }
1309 ValueToUTF8String(formatValue.get(), formatString);
1310 }
1311
1312 CFX_ByteString localString;
1313 if (argc > 2) {
1314 std::unique_ptr<CFXJSE_Value> localValue = GetSimpleValue(pThis, args, 2);
1315 if (ValueIsNull(pThis, localValue.get())) {
dsinclairf27aeec2016-06-07 19:36:18 -07001316 args.GetReturnValue()->SetNull();
dsinclair2b6d64e2016-06-06 11:39:42 -07001317 return;
1318 }
1319 ValueToUTF8String(localValue.get(), localString);
1320 }
1321
1322 int32_t iYear = 1900;
1323 int32_t iMonth = 1;
1324 int32_t iDay = 1;
1325 int32_t i = 0;
1326 while (dDate > 0) {
1327 if (iMonth == 2) {
1328 if ((!((iYear + i) % 4) && ((iYear + i) % 100)) || !((iYear + i) % 400)) {
1329 if (dDate > 29) {
1330 ++iMonth;
1331 if (iMonth > 12) {
1332 iMonth = 1;
1333 ++i;
1334 }
1335 iDay = 1;
1336 dDate -= 29;
1337 } else {
1338 iDay += static_cast<int32_t>(dDate) - 1;
1339 dDate = 0;
1340 }
1341 } else {
1342 if (dDate > 28) {
1343 ++iMonth;
1344 if (iMonth > 12) {
1345 iMonth = 1;
1346 ++i;
1347 }
1348 iDay = 1;
1349 dDate -= 28;
1350 } else {
1351 iDay += static_cast<int32_t>(dDate) - 1;
1352 dDate = 0;
1353 }
1354 }
1355 } else if (iMonth < 8) {
1356 if ((iMonth % 2 == 0)) {
1357 if (dDate > 30) {
1358 ++iMonth;
1359 if (iMonth > 12) {
1360 iMonth = 1;
1361 ++i;
1362 }
1363 iDay = 1;
1364 dDate -= 30;
1365 } else {
1366 iDay += static_cast<int32_t>(dDate) - 1;
1367 dDate = 0;
1368 }
1369 } else {
1370 if (dDate > 31) {
1371 ++iMonth;
1372 if (iMonth > 12) {
1373 iMonth = 1;
1374 ++i;
1375 }
1376 iDay = 1;
1377 dDate -= 31;
1378 } else {
1379 iDay += static_cast<int32_t>(dDate) - 1;
1380 dDate = 0;
1381 }
1382 }
1383 } else {
1384 if (iMonth % 2 != 0) {
1385 if (dDate > 30) {
1386 ++iMonth;
1387 if (iMonth > 12) {
1388 iMonth = 1;
1389 ++i;
1390 }
1391 iDay = 1;
1392 dDate -= 30;
1393 } else {
1394 iDay += static_cast<int32_t>(dDate) - 1;
1395 dDate = 0;
1396 }
1397 } else {
1398 if (dDate > 31) {
1399 ++iMonth;
1400 if (iMonth > 12) {
1401 iMonth = 1;
1402 ++i;
1403 }
1404 iDay = 1;
1405 dDate -= 31;
1406 } else {
1407 iDay += static_cast<int32_t>(dDate) - 1;
1408 dDate = 0;
1409 }
1410 }
1411 }
1412 }
1413
1414 CFX_ByteString szIsoDateString;
1415 szIsoDateString.Format("%d%02d%02d", iYear + i, iMonth, iDay);
1416 CFX_ByteString szLocalDateString;
1417 IsoDate2Local(pThis, szIsoDateString.AsStringC(), formatString.AsStringC(),
1418 localString.AsStringC(), szLocalDateString);
dsinclairf27aeec2016-06-07 19:36:18 -07001419 args.GetReturnValue()->SetString(szLocalDateString.AsStringC());
Dan Sinclair1770c022016-03-14 14:14:16 -04001420}
dsinclair48d91dd2016-05-31 11:54:01 -07001421
1422// static
dsinclair12a6b0c2016-05-26 11:14:08 -07001423void CXFA_FM2JSContext::Num2GMTime(CFXJSE_Value* pThis,
Dan Sinclair1770c022016-03-14 14:14:16 -04001424 const CFX_ByteStringC& szFuncName,
1425 CFXJSE_Arguments& args) {
1426 int32_t argc = args.GetLength();
dsinclair2b6d64e2016-06-06 11:39:42 -07001427 if (argc < 1 || argc > 3) {
dsinclair8f3074b2016-06-02 17:45:25 -07001428 ToJSContext(pThis, nullptr)
1429 ->ThrowException(XFA_IDS_INCORRECT_NUMBER_OF_METHOD, L"Num2GMTime");
dsinclair2b6d64e2016-06-06 11:39:42 -07001430 return;
Dan Sinclair1770c022016-03-14 14:14:16 -04001431 }
dsinclair2b6d64e2016-06-06 11:39:42 -07001432
1433 std::unique_ptr<CFXJSE_Value> timeValue = GetSimpleValue(pThis, args, 0);
dsinclair769b1372016-06-08 13:12:41 -07001434 if (timeValue->IsNull()) {
dsinclairf27aeec2016-06-07 19:36:18 -07001435 args.GetReturnValue()->SetNull();
dsinclair2b6d64e2016-06-06 11:39:42 -07001436 return;
1437 }
1438 int32_t iTime = (int32_t)ValueToFloat(pThis, timeValue.get());
1439 if (FXSYS_abs(iTime) < 1.0) {
dsinclairf27aeec2016-06-07 19:36:18 -07001440 args.GetReturnValue()->SetNull();
dsinclair2b6d64e2016-06-06 11:39:42 -07001441 return;
1442 }
1443
1444 CFX_ByteString formatString;
1445 if (argc > 1) {
1446 std::unique_ptr<CFXJSE_Value> formatValue = GetSimpleValue(pThis, args, 1);
dsinclair769b1372016-06-08 13:12:41 -07001447 if (formatValue->IsNull()) {
dsinclairf27aeec2016-06-07 19:36:18 -07001448 args.GetReturnValue()->SetNull();
dsinclair2b6d64e2016-06-06 11:39:42 -07001449 return;
1450 }
1451 ValueToUTF8String(formatValue.get(), formatString);
1452 }
1453
1454 CFX_ByteString localString;
1455 if (argc > 2) {
1456 std::unique_ptr<CFXJSE_Value> localValue = GetSimpleValue(pThis, args, 2);
dsinclair769b1372016-06-08 13:12:41 -07001457 if (localValue->IsNull()) {
dsinclairf27aeec2016-06-07 19:36:18 -07001458 args.GetReturnValue()->SetNull();
dsinclair2b6d64e2016-06-06 11:39:42 -07001459 return;
1460 }
1461 ValueToUTF8String(localValue.get(), localString);
1462 }
1463
1464 CFX_ByteString szGMTTimeString;
1465 Num2AllTime(pThis, iTime, formatString.AsStringC(), localString.AsStringC(),
1466 TRUE, szGMTTimeString);
dsinclairf27aeec2016-06-07 19:36:18 -07001467 args.GetReturnValue()->SetString(szGMTTimeString.AsStringC());
Dan Sinclair1770c022016-03-14 14:14:16 -04001468}
dsinclair48d91dd2016-05-31 11:54:01 -07001469
1470// static
dsinclair12a6b0c2016-05-26 11:14:08 -07001471void CXFA_FM2JSContext::Num2Time(CFXJSE_Value* pThis,
Dan Sinclair1770c022016-03-14 14:14:16 -04001472 const CFX_ByteStringC& szFuncName,
1473 CFXJSE_Arguments& args) {
1474 int32_t argc = args.GetLength();
dsinclair2b6d64e2016-06-06 11:39:42 -07001475 if (argc < 1 || argc > 3) {
dsinclair8f3074b2016-06-02 17:45:25 -07001476 ToJSContext(pThis, nullptr)
1477 ->ThrowException(XFA_IDS_INCORRECT_NUMBER_OF_METHOD, L"Num2Time");
dsinclair2b6d64e2016-06-06 11:39:42 -07001478 return;
Dan Sinclair1770c022016-03-14 14:14:16 -04001479 }
dsinclair2b6d64e2016-06-06 11:39:42 -07001480
1481 std::unique_ptr<CFXJSE_Value> timeValue = GetSimpleValue(pThis, args, 0);
dsinclair769b1372016-06-08 13:12:41 -07001482 if (timeValue->IsNull()) {
dsinclairf27aeec2016-06-07 19:36:18 -07001483 args.GetReturnValue()->SetNull();
dsinclair2b6d64e2016-06-06 11:39:42 -07001484 return;
1485 }
1486 FX_FLOAT fTime = ValueToFloat(pThis, timeValue.get());
1487 if (FXSYS_fabs(fTime) < 1.0) {
dsinclairf27aeec2016-06-07 19:36:18 -07001488 args.GetReturnValue()->SetNull();
dsinclair2b6d64e2016-06-06 11:39:42 -07001489 return;
1490 }
1491
1492 CFX_ByteString formatString;
1493 if (argc > 1) {
1494 std::unique_ptr<CFXJSE_Value> formatValue = GetSimpleValue(pThis, args, 1);
dsinclair769b1372016-06-08 13:12:41 -07001495 if (formatValue->IsNull()) {
dsinclairf27aeec2016-06-07 19:36:18 -07001496 args.GetReturnValue()->SetNull();
dsinclair2b6d64e2016-06-06 11:39:42 -07001497 return;
1498 }
1499 ValueToUTF8String(formatValue.get(), formatString);
1500 }
1501
1502 CFX_ByteString localString;
1503 if (argc > 2) {
1504 std::unique_ptr<CFXJSE_Value> localValue = GetSimpleValue(pThis, args, 2);
dsinclair769b1372016-06-08 13:12:41 -07001505 if (localValue->IsNull()) {
dsinclairf27aeec2016-06-07 19:36:18 -07001506 args.GetReturnValue()->SetNull();
dsinclair2b6d64e2016-06-06 11:39:42 -07001507 return;
1508 }
1509 ValueToUTF8String(localValue.get(), localString);
1510 }
1511
1512 CFX_ByteString szLocalTimeString;
1513 Num2AllTime(pThis, (int32_t)fTime, formatString.AsStringC(),
1514 localString.AsStringC(), FALSE, szLocalTimeString);
dsinclairf27aeec2016-06-07 19:36:18 -07001515 args.GetReturnValue()->SetString(szLocalTimeString.AsStringC());
Dan Sinclair1770c022016-03-14 14:14:16 -04001516}
dsinclair48d91dd2016-05-31 11:54:01 -07001517
1518// static
dsinclair12a6b0c2016-05-26 11:14:08 -07001519void CXFA_FM2JSContext::Time(CFXJSE_Value* pThis,
Dan Sinclair1770c022016-03-14 14:14:16 -04001520 const CFX_ByteStringC& szFuncName,
1521 CFXJSE_Arguments& args) {
dsinclair2b6d64e2016-06-06 11:39:42 -07001522 if (args.GetLength() != 0) {
dsinclair8f3074b2016-06-02 17:45:25 -07001523 ToJSContext(pThis, nullptr)
1524 ->ThrowException(XFA_IDS_INCORRECT_NUMBER_OF_METHOD, L"Time");
dsinclair2b6d64e2016-06-06 11:39:42 -07001525 return;
Dan Sinclair1770c022016-03-14 14:14:16 -04001526 }
dsinclair2b6d64e2016-06-06 11:39:42 -07001527
1528 time_t now;
1529 time(&now);
1530
1531 struct tm* pGmt = gmtime(&now);
dsinclairf27aeec2016-06-07 19:36:18 -07001532 args.GetReturnValue()->SetInteger(
1533 (pGmt->tm_hour * 3600 + pGmt->tm_min * 60 + pGmt->tm_sec) * 1000);
Dan Sinclair1770c022016-03-14 14:14:16 -04001534}
dsinclair48d91dd2016-05-31 11:54:01 -07001535
1536// static
dsinclair12a6b0c2016-05-26 11:14:08 -07001537void CXFA_FM2JSContext::Time2Num(CFXJSE_Value* pThis,
Dan Sinclair1770c022016-03-14 14:14:16 -04001538 const CFX_ByteStringC& szFuncName,
1539 CFXJSE_Arguments& args) {
1540 int32_t argc = args.GetLength();
dsinclair2b6d64e2016-06-06 11:39:42 -07001541 if (argc < 1 || argc > 3) {
dsinclair8f3074b2016-06-02 17:45:25 -07001542 ToJSContext(pThis, nullptr)
1543 ->ThrowException(XFA_IDS_INCORRECT_NUMBER_OF_METHOD, L"Time2Num");
dsinclair2b6d64e2016-06-06 11:39:42 -07001544 return;
Dan Sinclair1770c022016-03-14 14:14:16 -04001545 }
dsinclair2b6d64e2016-06-06 11:39:42 -07001546
1547 CFX_ByteString timeString;
1548 std::unique_ptr<CFXJSE_Value> timeValue = GetSimpleValue(pThis, args, 0);
1549 if (ValueIsNull(pThis, timeValue.get())) {
dsinclairf27aeec2016-06-07 19:36:18 -07001550 args.GetReturnValue()->SetNull();
dsinclair2b6d64e2016-06-06 11:39:42 -07001551 return;
1552 }
1553 ValueToUTF8String(timeValue.get(), timeString);
1554
1555 CFX_ByteString formatString;
1556 if (argc > 1) {
1557 std::unique_ptr<CFXJSE_Value> formatValue = GetSimpleValue(pThis, args, 1);
1558 if (ValueIsNull(pThis, formatValue.get())) {
dsinclairf27aeec2016-06-07 19:36:18 -07001559 args.GetReturnValue()->SetNull();
dsinclair2b6d64e2016-06-06 11:39:42 -07001560 return;
1561 }
1562 ValueToUTF8String(formatValue.get(), formatString);
1563 }
1564
1565 CFX_ByteString localString;
1566 if (argc > 2) {
1567 std::unique_ptr<CFXJSE_Value> localValue = GetSimpleValue(pThis, args, 2);
1568 if (ValueIsNull(pThis, localValue.get())) {
dsinclairf27aeec2016-06-07 19:36:18 -07001569 args.GetReturnValue()->SetNull();
dsinclair2b6d64e2016-06-06 11:39:42 -07001570 return;
1571 }
1572 ValueToUTF8String(localValue.get(), localString);
1573 }
1574
1575 CXFA_Document* pDoc = ToJSContext(pThis, nullptr)->GetDocument();
1576 CXFA_LocaleMgr* pMgr = pDoc->GetLocalMgr();
1577 IFX_Locale* pLocale = nullptr;
1578 if (localString.IsEmpty()) {
1579 CXFA_Node* pThisNode = ToNode(pDoc->GetScriptContext()->GetThisObject());
1580 ASSERT(pThisNode);
1581
1582 CXFA_WidgetData widgetData(pThisNode);
1583 pLocale = widgetData.GetLocal();
1584 } else {
1585 pLocale = pMgr->GetLocaleByName(
1586 CFX_WideString::FromUTF8(localString.AsStringC()));
1587 }
1588
1589 CFX_WideString wsFormat;
1590 if (formatString.IsEmpty())
1591 pLocale->GetTimePattern(FX_LOCALEDATETIMESUBCATEGORY_Default, wsFormat);
1592 else
1593 wsFormat = CFX_WideString::FromUTF8(formatString.AsStringC());
1594
dsinclaircf7f3222016-06-08 20:34:02 -07001595 wsFormat = L"time{" + wsFormat + L"}";
dsinclair2b6d64e2016-06-06 11:39:42 -07001596 CXFA_LocaleValue localeValue(XFA_VT_TIME,
1597 CFX_WideString::FromUTF8(timeString.AsStringC()),
1598 wsFormat, pLocale, pMgr);
1599 if (!localeValue.IsValid()) {
dsinclairf27aeec2016-06-07 19:36:18 -07001600 args.GetReturnValue()->SetInteger(0);
dsinclair2b6d64e2016-06-06 11:39:42 -07001601 return;
1602 }
1603
1604 CFX_Unitime uniTime = localeValue.GetTime();
1605 int32_t hour = uniTime.GetHour();
1606 int32_t min = uniTime.GetMinute();
1607 int32_t second = uniTime.GetSecond();
1608 int32_t milSecond = uniTime.GetMillisecond();
1609 int32_t mins = hour * 60 + min;
1610 CXFA_TimeZoneProvider* pProvider = CXFA_TimeZoneProvider::Get();
1611 if (pProvider) {
1612 FX_TIMEZONE tz;
1613 pProvider->GetTimeZone(tz);
1614 mins -= (tz.tzHour * 60);
1615 while (mins > 1440)
1616 mins -= 1440;
1617 while (mins < 0)
1618 mins += 1440;
1619
1620 hour = mins / 60;
1621 min = mins % 60;
1622 }
dsinclairf27aeec2016-06-07 19:36:18 -07001623 args.GetReturnValue()->SetInteger(hour * 3600000 + min * 60000 +
1624 second * 1000 + milSecond + 1);
Dan Sinclair1770c022016-03-14 14:14:16 -04001625}
dsinclair48d91dd2016-05-31 11:54:01 -07001626
1627// static
dsinclair12a6b0c2016-05-26 11:14:08 -07001628void CXFA_FM2JSContext::TimeFmt(CFXJSE_Value* pThis,
Dan Sinclair1770c022016-03-14 14:14:16 -04001629 const CFX_ByteStringC& szFuncName,
1630 CFXJSE_Arguments& args) {
1631 int32_t argc = args.GetLength();
dsinclair2b6d64e2016-06-06 11:39:42 -07001632 if (argc > 2) {
dsinclair8f3074b2016-06-02 17:45:25 -07001633 ToJSContext(pThis, nullptr)
1634 ->ThrowException(XFA_IDS_INCORRECT_NUMBER_OF_METHOD, L"TimeFmt");
dsinclair2b6d64e2016-06-06 11:39:42 -07001635 return;
Dan Sinclair1770c022016-03-14 14:14:16 -04001636 }
dsinclair2b6d64e2016-06-06 11:39:42 -07001637
1638 int32_t iStyle = 0;
1639 if (argc > 0) {
1640 std::unique_ptr<CFXJSE_Value> argStyle = GetSimpleValue(pThis, args, 0);
dsinclair769b1372016-06-08 13:12:41 -07001641 if (argStyle->IsNull()) {
dsinclairf27aeec2016-06-07 19:36:18 -07001642 args.GetReturnValue()->SetNull();
dsinclair2b6d64e2016-06-06 11:39:42 -07001643 return;
1644 }
1645 iStyle = (int32_t)ValueToFloat(pThis, argStyle.get());
1646 if (iStyle > 4 || iStyle < 0)
1647 iStyle = 0;
1648 }
1649
1650 CFX_ByteString szLocal;
1651 if (argc > 1) {
1652 std::unique_ptr<CFXJSE_Value> argLocal = GetSimpleValue(pThis, args, 1);
dsinclair769b1372016-06-08 13:12:41 -07001653 if (argLocal->IsNull()) {
dsinclairf27aeec2016-06-07 19:36:18 -07001654 args.GetReturnValue()->SetNull();
dsinclair2b6d64e2016-06-06 11:39:42 -07001655 return;
1656 }
1657 ValueToUTF8String(argLocal.get(), szLocal);
1658 }
1659
1660 CFX_ByteString formatStr;
1661 GetStandardTimeFormat(pThis, iStyle, szLocal.AsStringC(), formatStr);
dsinclairf27aeec2016-06-07 19:36:18 -07001662 args.GetReturnValue()->SetString(formatStr.AsStringC());
Dan Sinclair1770c022016-03-14 14:14:16 -04001663}
dsinclair48d91dd2016-05-31 11:54:01 -07001664
1665// static
Dan Sinclair1770c022016-03-14 14:14:16 -04001666FX_BOOL CXFA_FM2JSContext::IsIsoDateFormat(const FX_CHAR* pData,
1667 int32_t iLength,
1668 int32_t& iStyle,
1669 int32_t& iYear,
1670 int32_t& iMonth,
1671 int32_t& iDay) {
1672 iYear = 0;
1673 iMonth = 1;
1674 iDay = 1;
dsinclair2b6d64e2016-06-06 11:39:42 -07001675
1676 if (iLength < 4)
1677 return FALSE;
1678
Dan Sinclair1770c022016-03-14 14:14:16 -04001679 FX_CHAR strYear[5];
1680 strYear[4] = '\0';
1681 for (int32_t i = 0; i < 4; ++i) {
dsinclair2b6d64e2016-06-06 11:39:42 -07001682 if (pData[i] > '9' || pData[i] < '0')
1683 return FALSE;
1684
1685 strYear[i] = pData[i];
Dan Sinclair1770c022016-03-14 14:14:16 -04001686 }
1687 iYear = FXSYS_atoi(strYear);
1688 iStyle = 0;
dsinclair2b6d64e2016-06-06 11:39:42 -07001689 if (iLength == 4)
1690 return TRUE;
1691
1692 iStyle = pData[4] == '-' ? 1 : 0;
1693
Dan Sinclair1770c022016-03-14 14:14:16 -04001694 FX_CHAR strTemp[3];
1695 strTemp[2] = '\0';
dsinclair2b6d64e2016-06-06 11:39:42 -07001696 int32_t iPosOff = iStyle == 0 ? 4 : 5;
1697 if ((pData[iPosOff] > '9' || pData[iPosOff] < '0') ||
1698 (pData[iPosOff + 1] > '9' || pData[iPosOff + 1] < '0'))
1699 return FALSE;
1700
1701 strTemp[0] = pData[iPosOff];
1702 strTemp[1] = pData[iPosOff + 1];
Dan Sinclair1770c022016-03-14 14:14:16 -04001703 iMonth = FXSYS_atoi(strTemp);
dsinclair2b6d64e2016-06-06 11:39:42 -07001704 if (iMonth > 12 || iMonth < 1)
1705 return FALSE;
1706
Dan Sinclair1770c022016-03-14 14:14:16 -04001707 if (iStyle == 0) {
1708 iPosOff += 2;
dsinclair2b6d64e2016-06-06 11:39:42 -07001709 if (iLength == 6)
1710 return TRUE;
Dan Sinclair1770c022016-03-14 14:14:16 -04001711 } else {
1712 iPosOff += 3;
dsinclair2b6d64e2016-06-06 11:39:42 -07001713 if (iLength == 7)
1714 return TRUE;
Dan Sinclair1770c022016-03-14 14:14:16 -04001715 }
dsinclair2b6d64e2016-06-06 11:39:42 -07001716 if ((pData[iPosOff] > '9' || pData[iPosOff] < '0') ||
1717 (pData[iPosOff + 1] > '9' || pData[iPosOff + 1] < '0'))
1718 return FALSE;
1719
1720 strTemp[0] = pData[iPosOff];
1721 strTemp[1] = pData[iPosOff + 1];
Dan Sinclair1770c022016-03-14 14:14:16 -04001722 iDay = FXSYS_atoi(strTemp);
dsinclair2b6d64e2016-06-06 11:39:42 -07001723 if (iPosOff + 2 < iLength)
1724 return FALSE;
1725
Dan Sinclair1770c022016-03-14 14:14:16 -04001726 if ((!(iYear % 4) && (iYear % 100)) || !(iYear % 400)) {
dsinclair2b6d64e2016-06-06 11:39:42 -07001727 if (iMonth == 2 && iDay > 29)
1728 return FALSE;
Dan Sinclair1770c022016-03-14 14:14:16 -04001729 } else {
dsinclair2b6d64e2016-06-06 11:39:42 -07001730 if (iMonth == 2 && iDay > 28)
1731 return FALSE;
1732 }
1733 if (iMonth != 2) {
1734 if (iMonth < 8) {
1735 if (iDay > (iMonth % 2 == 0 ? 30 : 31))
1736 return FALSE;
1737 } else if (iDay > (iMonth % 2 == 0 ? 31 : 30)) {
1738 return FALSE;
Dan Sinclair1770c022016-03-14 14:14:16 -04001739 }
1740 }
dsinclair2b6d64e2016-06-06 11:39:42 -07001741 return TRUE;
Dan Sinclair1770c022016-03-14 14:14:16 -04001742}
dsinclair48d91dd2016-05-31 11:54:01 -07001743
1744// static
Dan Sinclair1770c022016-03-14 14:14:16 -04001745FX_BOOL CXFA_FM2JSContext::IsIsoTimeFormat(const FX_CHAR* pData,
1746 int32_t iLength,
1747 int32_t& iHour,
1748 int32_t& iMinute,
1749 int32_t& iSecond,
1750 int32_t& iMilliSecond,
1751 int32_t& iZoneHour,
1752 int32_t& iZoneMinute) {
1753 iHour = 0;
1754 iMinute = 0;
1755 iSecond = 0;
1756 iMilliSecond = 0;
1757 iZoneHour = 0;
1758 iZoneMinute = 0;
dsinclair2b6d64e2016-06-06 11:39:42 -07001759 if (!pData)
Dan Sinclair1770c022016-03-14 14:14:16 -04001760 return FALSE;
dsinclair2b6d64e2016-06-06 11:39:42 -07001761
Dan Sinclair1770c022016-03-14 14:14:16 -04001762 FX_CHAR strTemp[3];
1763 strTemp[2] = '\0';
Dan Sinclair1770c022016-03-14 14:14:16 -04001764 int32_t iZone = 0;
dsinclair2b6d64e2016-06-06 11:39:42 -07001765 int32_t i = 0;
Dan Sinclair1770c022016-03-14 14:14:16 -04001766 while (i < iLength) {
dsinclair2b6d64e2016-06-06 11:39:42 -07001767 if ((pData[i] > '9' || pData[i] < '0') && pData[i] != ':') {
Dan Sinclair1770c022016-03-14 14:14:16 -04001768 iZone = i;
1769 break;
1770 }
1771 ++i;
1772 }
dsinclair2b6d64e2016-06-06 11:39:42 -07001773 if (i == iLength)
Dan Sinclair1770c022016-03-14 14:14:16 -04001774 iZone = iLength;
dsinclair2b6d64e2016-06-06 11:39:42 -07001775
Dan Sinclair1770c022016-03-14 14:14:16 -04001776 int32_t iPos = 0;
dsinclair2b6d64e2016-06-06 11:39:42 -07001777 int32_t iIndex = 0;
Dan Sinclair1770c022016-03-14 14:14:16 -04001778 while (iIndex < iZone) {
dsinclair2b6d64e2016-06-06 11:39:42 -07001779 if (iIndex >= iZone)
Dan Sinclair1770c022016-03-14 14:14:16 -04001780 break;
dsinclair2b6d64e2016-06-06 11:39:42 -07001781
1782 if (pData[iIndex] > '9' || pData[iIndex] < '0')
1783 return FALSE;
1784
1785 strTemp[0] = pData[iIndex];
1786 if (pData[iIndex + 1] > '9' || pData[iIndex + 1] < '0')
1787 return FALSE;
1788
1789 strTemp[1] = pData[iIndex + 1];
1790 if (FXSYS_atoi(strTemp) > 60)
1791 return FALSE;
1792
1793 if (pData[2] == ':') {
Dan Sinclair1770c022016-03-14 14:14:16 -04001794 if (iPos == 0) {
1795 iHour = FXSYS_atoi(strTemp);
1796 ++iPos;
1797 } else if (iPos == 1) {
1798 iMinute = FXSYS_atoi(strTemp);
1799 ++iPos;
1800 } else {
1801 iSecond = FXSYS_atoi(strTemp);
1802 }
1803 iIndex += 3;
1804 } else {
1805 if (iPos == 0) {
1806 iHour = FXSYS_atoi(strTemp);
1807 ++iPos;
1808 } else if (iPos == 1) {
1809 iMinute = FXSYS_atoi(strTemp);
1810 ++iPos;
1811 } else if (iPos == 2) {
1812 iSecond = FXSYS_atoi(strTemp);
1813 ++iPos;
1814 }
1815 iIndex += 2;
1816 }
1817 }
dsinclair2b6d64e2016-06-06 11:39:42 -07001818 if (pData[iIndex] == '.') {
Dan Sinclair1770c022016-03-14 14:14:16 -04001819 ++iIndex;
weilidb444d22016-06-02 15:48:15 -07001820 FX_CHAR strSec[4];
1821 strSec[3] = '\0';
dsinclair2b6d64e2016-06-06 11:39:42 -07001822 if (pData[iIndex] > '9' || pData[iIndex] < '0')
1823 return FALSE;
1824
1825 strSec[0] = pData[iIndex];
1826 if (pData[iIndex + 1] > '9' || pData[iIndex + 1] < '0')
1827 return FALSE;
1828
1829 strSec[1] = pData[iIndex + 1];
1830 if (pData[iIndex + 2] > '9' || pData[iIndex + 2] < '0')
1831 return FALSE;
1832
1833 strSec[2] = pData[iIndex + 2];
weilidb444d22016-06-02 15:48:15 -07001834 iMilliSecond = FXSYS_atoi(strSec);
Dan Sinclair1770c022016-03-14 14:14:16 -04001835 if (iMilliSecond > 100) {
1836 iMilliSecond = 0;
dsinclair2b6d64e2016-06-06 11:39:42 -07001837 return FALSE;
Dan Sinclair1770c022016-03-14 14:14:16 -04001838 }
1839 iIndex += 3;
1840 }
dsinclair2b6d64e2016-06-06 11:39:42 -07001841 if (pData[iIndex] == 'z' || pData[iIndex] == 'Z')
1842 return TRUE;
1843
Dan Sinclair1770c022016-03-14 14:14:16 -04001844 int32_t iSign = 1;
dsinclair2b6d64e2016-06-06 11:39:42 -07001845 if (pData[iIndex] == '+') {
Dan Sinclair1770c022016-03-14 14:14:16 -04001846 ++iIndex;
dsinclair2b6d64e2016-06-06 11:39:42 -07001847 } else if (pData[iIndex] == '-') {
Dan Sinclair1770c022016-03-14 14:14:16 -04001848 iSign = -1;
1849 ++iIndex;
1850 }
1851 iPos = 0;
1852 while (iIndex < iLength) {
dsinclair2b6d64e2016-06-06 11:39:42 -07001853 if (iIndex >= iLength)
1854 return FALSE;
1855 if (pData[iIndex] > '9' || pData[iIndex] < '0')
1856 return FALSE;
1857
1858 strTemp[0] = pData[iIndex];
1859 if (pData[iIndex + 1] > '9' || pData[iIndex + 1] < '0')
1860 return FALSE;
1861
1862 strTemp[1] = pData[iIndex + 1];
1863 if (FXSYS_atoi(strTemp) > 60)
1864 return FALSE;
1865
1866 if (pData[2] == ':') {
Dan Sinclair1770c022016-03-14 14:14:16 -04001867 if (iPos == 0) {
1868 iZoneHour = FXSYS_atoi(strTemp);
1869 } else if (iPos == 1) {
1870 iZoneMinute = FXSYS_atoi(strTemp);
1871 }
1872 iIndex += 3;
1873 } else {
1874 if (!iPos) {
1875 iZoneHour = FXSYS_atoi(strTemp);
1876 ++iPos;
1877 } else if (iPos == 1) {
1878 iZoneMinute = FXSYS_atoi(strTemp);
1879 ++iPos;
1880 }
1881 iIndex += 2;
1882 }
1883 }
dsinclair2b6d64e2016-06-06 11:39:42 -07001884 if (iIndex < iLength)
1885 return FALSE;
1886
Dan Sinclair1770c022016-03-14 14:14:16 -04001887 iZoneHour *= iSign;
dsinclair2b6d64e2016-06-06 11:39:42 -07001888 return TRUE;
Dan Sinclair1770c022016-03-14 14:14:16 -04001889}
dsinclair48d91dd2016-05-31 11:54:01 -07001890
1891// static
Dan Sinclair1770c022016-03-14 14:14:16 -04001892FX_BOOL CXFA_FM2JSContext::IsIsoDateTimeFormat(const FX_CHAR* pData,
1893 int32_t iLength,
1894 int32_t& iYear,
1895 int32_t& iMonth,
1896 int32_t& iDay,
1897 int32_t& iHour,
1898 int32_t& iMinute,
1899 int32_t& iSecond,
1900 int32_t& iMillionSecond,
1901 int32_t& iZoneHour,
1902 int32_t& iZoneMinute) {
1903 iYear = 0;
1904 iMonth = 0;
1905 iDay = 0;
1906 iHour = 0;
1907 iMinute = 0;
1908 iSecond = 0;
dsinclair2b6d64e2016-06-06 11:39:42 -07001909 if (!pData)
Dan Sinclair1770c022016-03-14 14:14:16 -04001910 return FALSE;
dsinclair2b6d64e2016-06-06 11:39:42 -07001911
Dan Sinclair1770c022016-03-14 14:14:16 -04001912 int32_t iIndex = 0;
dsinclair2b6d64e2016-06-06 11:39:42 -07001913 while (pData[iIndex] != 'T' && pData[iIndex] != 't') {
1914 if (iIndex >= iLength)
1915 return FALSE;
Dan Sinclair1770c022016-03-14 14:14:16 -04001916 ++iIndex;
1917 }
dsinclair2b6d64e2016-06-06 11:39:42 -07001918 if (iIndex != 8 && iIndex != 10)
1919 return FALSE;
1920
Dan Sinclair1770c022016-03-14 14:14:16 -04001921 int32_t iStyle = -1;
dsinclair2b6d64e2016-06-06 11:39:42 -07001922 if (!IsIsoDateFormat(pData, iIndex, iStyle, iYear, iMonth, iDay))
1923 return FALSE;
1924 if (pData[iIndex] != 'T' && pData[iIndex] != 't')
1925 return TRUE;
1926
Dan Sinclair1770c022016-03-14 14:14:16 -04001927 ++iIndex;
1928 if (((iLength - iIndex > 13) && (iLength - iIndex < 6)) &&
1929 (iLength - iIndex != 15)) {
dsinclair2b6d64e2016-06-06 11:39:42 -07001930 return TRUE;
Dan Sinclair1770c022016-03-14 14:14:16 -04001931 }
dsinclair2b6d64e2016-06-06 11:39:42 -07001932 if (!IsIsoTimeFormat(pData + iIndex, iLength - iIndex, iHour, iMinute,
1933 iSecond, iMillionSecond, iZoneHour, iZoneMinute)) {
1934 return FALSE;
Dan Sinclair1770c022016-03-14 14:14:16 -04001935 }
dsinclair2b6d64e2016-06-06 11:39:42 -07001936
1937 return TRUE;
Dan Sinclair1770c022016-03-14 14:14:16 -04001938}
dsinclair48d91dd2016-05-31 11:54:01 -07001939
1940// static
dsinclair12a6b0c2016-05-26 11:14:08 -07001941FX_BOOL CXFA_FM2JSContext::Local2IsoDate(CFXJSE_Value* pThis,
Dan Sinclair1770c022016-03-14 14:14:16 -04001942 const CFX_ByteStringC& szDate,
1943 const CFX_ByteStringC& szFormat,
1944 const CFX_ByteStringC& szLocale,
1945 CFX_ByteString& strIsoDate) {
dsinclair8f3074b2016-06-02 17:45:25 -07001946 CXFA_Document* pDoc = ToJSContext(pThis, nullptr)->GetDocument();
dsinclair2b6d64e2016-06-06 11:39:42 -07001947 if (!pDoc)
Dan Sinclair1770c022016-03-14 14:14:16 -04001948 return FALSE;
dsinclair2b6d64e2016-06-06 11:39:42 -07001949
1950 CXFA_LocaleMgr* pMgr = pDoc->GetLocalMgr();
dsinclair48d91dd2016-05-31 11:54:01 -07001951 IFX_Locale* pLocale = nullptr;
Dan Sinclair1770c022016-03-14 14:14:16 -04001952 if (szLocale.IsEmpty()) {
1953 CXFA_Node* pThisNode = ToNode(pDoc->GetScriptContext()->GetThisObject());
dsinclair43854a52016-04-27 12:26:00 -07001954 ASSERT(pThisNode);
dsinclair2b6d64e2016-06-06 11:39:42 -07001955
Dan Sinclair1770c022016-03-14 14:14:16 -04001956 CXFA_WidgetData widgetData(pThisNode);
1957 pLocale = widgetData.GetLocal();
1958 } else {
tsepezafe94302016-05-13 17:21:31 -07001959 pLocale = pMgr->GetLocaleByName(CFX_WideString::FromUTF8(szLocale));
Dan Sinclair1770c022016-03-14 14:14:16 -04001960 }
dsinclair2b6d64e2016-06-06 11:39:42 -07001961 if (!pLocale)
Dan Sinclair1770c022016-03-14 14:14:16 -04001962 return FALSE;
dsinclair2b6d64e2016-06-06 11:39:42 -07001963
Dan Sinclair1770c022016-03-14 14:14:16 -04001964 CFX_WideString wsFormat;
dsinclair2b6d64e2016-06-06 11:39:42 -07001965 if (szFormat.IsEmpty())
Dan Sinclair1770c022016-03-14 14:14:16 -04001966 pLocale->GetDatePattern(FX_LOCALEDATETIMESUBCATEGORY_Default, wsFormat);
dsinclair2b6d64e2016-06-06 11:39:42 -07001967 else
tsepez6fe7d212016-04-06 10:51:14 -07001968 wsFormat = CFX_WideString::FromUTF8(szFormat);
dsinclair2b6d64e2016-06-06 11:39:42 -07001969
tsepez6fe7d212016-04-06 10:51:14 -07001970 CXFA_LocaleValue widgetValue(XFA_VT_DATE, CFX_WideString::FromUTF8(szDate),
dsinclair2b6d64e2016-06-06 11:39:42 -07001971 wsFormat, pLocale, pMgr);
Dan Sinclair1770c022016-03-14 14:14:16 -04001972 CFX_Unitime dt = widgetValue.GetDate();
1973 strIsoDate.Format("%4d-%02d-%02d", dt.GetYear(), dt.GetMonth(), dt.GetDay());
1974 return TRUE;
1975}
dsinclair48d91dd2016-05-31 11:54:01 -07001976
1977// static
dsinclair12a6b0c2016-05-26 11:14:08 -07001978FX_BOOL CXFA_FM2JSContext::Local2IsoTime(CFXJSE_Value* pThis,
Dan Sinclair1770c022016-03-14 14:14:16 -04001979 const CFX_ByteStringC& szTime,
1980 const CFX_ByteStringC& szFormat,
1981 const CFX_ByteStringC& szLocale,
1982 CFX_ByteString& strIsoTime) {
dsinclair8f3074b2016-06-02 17:45:25 -07001983 CXFA_Document* pDoc = ToJSContext(pThis, nullptr)->GetDocument();
dsinclair2b6d64e2016-06-06 11:39:42 -07001984 if (!pDoc)
Dan Sinclair1770c022016-03-14 14:14:16 -04001985 return FALSE;
dsinclair2b6d64e2016-06-06 11:39:42 -07001986
1987 CXFA_LocaleMgr* pMgr = pDoc->GetLocalMgr();
dsinclair48d91dd2016-05-31 11:54:01 -07001988 IFX_Locale* pLocale = nullptr;
Dan Sinclair1770c022016-03-14 14:14:16 -04001989 if (szLocale.IsEmpty()) {
1990 CXFA_Node* pThisNode = ToNode(pDoc->GetScriptContext()->GetThisObject());
dsinclair43854a52016-04-27 12:26:00 -07001991 ASSERT(pThisNode);
dsinclair2b6d64e2016-06-06 11:39:42 -07001992
Dan Sinclair1770c022016-03-14 14:14:16 -04001993 CXFA_WidgetData widgetData(pThisNode);
1994 pLocale = widgetData.GetLocal();
1995 } else {
tsepezafe94302016-05-13 17:21:31 -07001996 pLocale = pMgr->GetLocaleByName(CFX_WideString::FromUTF8(szLocale));
Dan Sinclair1770c022016-03-14 14:14:16 -04001997 }
dsinclair2b6d64e2016-06-06 11:39:42 -07001998 if (!pLocale)
Dan Sinclair1770c022016-03-14 14:14:16 -04001999 return FALSE;
dsinclair2b6d64e2016-06-06 11:39:42 -07002000
Dan Sinclair1770c022016-03-14 14:14:16 -04002001 CFX_WideString wsFormat;
dsinclair2b6d64e2016-06-06 11:39:42 -07002002 if (szFormat.IsEmpty())
Dan Sinclair1770c022016-03-14 14:14:16 -04002003 pLocale->GetTimePattern(FX_LOCALEDATETIMESUBCATEGORY_Default, wsFormat);
dsinclair2b6d64e2016-06-06 11:39:42 -07002004 else
tsepez6fe7d212016-04-06 10:51:14 -07002005 wsFormat = CFX_WideString::FromUTF8(szFormat);
dsinclair2b6d64e2016-06-06 11:39:42 -07002006
dsinclaircf7f3222016-06-08 20:34:02 -07002007 wsFormat = L"time{" + wsFormat + L"}";
tsepez6fe7d212016-04-06 10:51:14 -07002008 CXFA_LocaleValue widgetValue(XFA_VT_TIME, CFX_WideString::FromUTF8(szTime),
dsinclair2b6d64e2016-06-06 11:39:42 -07002009 wsFormat, pLocale, pMgr);
Dan Sinclair1770c022016-03-14 14:14:16 -04002010 CFX_Unitime utime = widgetValue.GetTime();
2011 strIsoTime.Format("%02d:%02d:%02d.%03d", utime.GetHour(), utime.GetMinute(),
2012 utime.GetSecond(), utime.GetMillisecond());
2013 return TRUE;
2014}
dsinclair48d91dd2016-05-31 11:54:01 -07002015
2016// static
dsinclair12a6b0c2016-05-26 11:14:08 -07002017FX_BOOL CXFA_FM2JSContext::IsoDate2Local(CFXJSE_Value* pThis,
Dan Sinclair1770c022016-03-14 14:14:16 -04002018 const CFX_ByteStringC& szDate,
2019 const CFX_ByteStringC& szFormat,
2020 const CFX_ByteStringC& szLocale,
2021 CFX_ByteString& strLocalDate) {
dsinclair8f3074b2016-06-02 17:45:25 -07002022 CXFA_Document* pDoc = ToJSContext(pThis, nullptr)->GetDocument();
dsinclair2b6d64e2016-06-06 11:39:42 -07002023 if (!pDoc)
Dan Sinclair1770c022016-03-14 14:14:16 -04002024 return FALSE;
dsinclair2b6d64e2016-06-06 11:39:42 -07002025
2026 CXFA_LocaleMgr* pMgr = pDoc->GetLocalMgr();
dsinclair48d91dd2016-05-31 11:54:01 -07002027 IFX_Locale* pLocale = nullptr;
Dan Sinclair1770c022016-03-14 14:14:16 -04002028 if (szLocale.IsEmpty()) {
2029 CXFA_Node* pThisNode = ToNode(pDoc->GetScriptContext()->GetThisObject());
dsinclair43854a52016-04-27 12:26:00 -07002030 ASSERT(pThisNode);
Dan Sinclair1770c022016-03-14 14:14:16 -04002031 CXFA_WidgetData widgetData(pThisNode);
2032 pLocale = widgetData.GetLocal();
2033 } else {
tsepezafe94302016-05-13 17:21:31 -07002034 pLocale = pMgr->GetLocaleByName(CFX_WideString::FromUTF8(szLocale));
Dan Sinclair1770c022016-03-14 14:14:16 -04002035 }
dsinclair2b6d64e2016-06-06 11:39:42 -07002036 if (!pLocale)
Dan Sinclair1770c022016-03-14 14:14:16 -04002037 return FALSE;
dsinclair2b6d64e2016-06-06 11:39:42 -07002038
Dan Sinclair1770c022016-03-14 14:14:16 -04002039 CFX_WideString wsFormat;
dsinclair2b6d64e2016-06-06 11:39:42 -07002040 if (szFormat.IsEmpty())
Dan Sinclair1770c022016-03-14 14:14:16 -04002041 pLocale->GetDatePattern(FX_LOCALEDATETIMESUBCATEGORY_Default, wsFormat);
dsinclair2b6d64e2016-06-06 11:39:42 -07002042 else
tsepez6fe7d212016-04-06 10:51:14 -07002043 wsFormat = CFX_WideString::FromUTF8(szFormat);
dsinclair2b6d64e2016-06-06 11:39:42 -07002044
tsepez6fe7d212016-04-06 10:51:14 -07002045 CXFA_LocaleValue widgetValue(XFA_VT_DATE, CFX_WideString::FromUTF8(szDate),
dsinclair2b6d64e2016-06-06 11:39:42 -07002046 pMgr);
Dan Sinclair1770c022016-03-14 14:14:16 -04002047 CFX_WideString wsRet;
2048 widgetValue.FormatPatterns(wsRet, wsFormat, pLocale,
2049 XFA_VALUEPICTURE_Display);
tsepezbd9748d2016-04-13 21:40:19 -07002050 strLocalDate = FX_UTF8Encode(wsRet.c_str(), wsRet.GetLength());
Dan Sinclair1770c022016-03-14 14:14:16 -04002051 return TRUE;
2052}
dsinclair48d91dd2016-05-31 11:54:01 -07002053
2054// static
dsinclair12a6b0c2016-05-26 11:14:08 -07002055FX_BOOL CXFA_FM2JSContext::IsoTime2Local(CFXJSE_Value* pThis,
Dan Sinclair1770c022016-03-14 14:14:16 -04002056 const CFX_ByteStringC& szTime,
2057 const CFX_ByteStringC& szFormat,
2058 const CFX_ByteStringC& szLocale,
2059 CFX_ByteString& strLocalTime) {
dsinclair8f3074b2016-06-02 17:45:25 -07002060 CXFA_Document* pDoc = ToJSContext(pThis, nullptr)->GetDocument();
dsinclair2b6d64e2016-06-06 11:39:42 -07002061 if (!pDoc)
Dan Sinclair1770c022016-03-14 14:14:16 -04002062 return FALSE;
dsinclair2b6d64e2016-06-06 11:39:42 -07002063
2064 CXFA_LocaleMgr* pMgr = pDoc->GetLocalMgr();
dsinclair48d91dd2016-05-31 11:54:01 -07002065 IFX_Locale* pLocale = nullptr;
Dan Sinclair1770c022016-03-14 14:14:16 -04002066 if (szLocale.IsEmpty()) {
2067 CXFA_Node* pThisNode = ToNode(pDoc->GetScriptContext()->GetThisObject());
dsinclair43854a52016-04-27 12:26:00 -07002068 ASSERT(pThisNode);
Dan Sinclair1770c022016-03-14 14:14:16 -04002069 CXFA_WidgetData widgetData(pThisNode);
2070 pLocale = widgetData.GetLocal();
2071 } else {
tsepezafe94302016-05-13 17:21:31 -07002072 pLocale = pMgr->GetLocaleByName(CFX_WideString::FromUTF8(szLocale));
Dan Sinclair1770c022016-03-14 14:14:16 -04002073 }
dsinclair2b6d64e2016-06-06 11:39:42 -07002074 if (!pLocale)
Dan Sinclair1770c022016-03-14 14:14:16 -04002075 return FALSE;
dsinclair2b6d64e2016-06-06 11:39:42 -07002076
Dan Sinclair1770c022016-03-14 14:14:16 -04002077 CFX_WideString wsFormat;
dsinclair2b6d64e2016-06-06 11:39:42 -07002078 if (szFormat.IsEmpty())
Dan Sinclair1770c022016-03-14 14:14:16 -04002079 pLocale->GetTimePattern(FX_LOCALEDATETIMESUBCATEGORY_Default, wsFormat);
dsinclair2b6d64e2016-06-06 11:39:42 -07002080 else
tsepez6fe7d212016-04-06 10:51:14 -07002081 wsFormat = CFX_WideString::FromUTF8(szFormat);
dsinclair2b6d64e2016-06-06 11:39:42 -07002082
dsinclaircf7f3222016-06-08 20:34:02 -07002083 wsFormat = L"time{" + wsFormat + L"}";
tsepez6fe7d212016-04-06 10:51:14 -07002084 CXFA_LocaleValue widgetValue(XFA_VT_TIME, CFX_WideString::FromUTF8(szTime),
dsinclair2b6d64e2016-06-06 11:39:42 -07002085 pMgr);
Dan Sinclair1770c022016-03-14 14:14:16 -04002086 CFX_WideString wsRet;
2087 widgetValue.FormatPatterns(wsRet, wsFormat, pLocale,
2088 XFA_VALUEPICTURE_Display);
tsepezbd9748d2016-04-13 21:40:19 -07002089 strLocalTime = FX_UTF8Encode(wsRet.c_str(), wsRet.GetLength());
Dan Sinclair1770c022016-03-14 14:14:16 -04002090 return TRUE;
2091}
dsinclair48d91dd2016-05-31 11:54:01 -07002092
2093// static
dsinclair12a6b0c2016-05-26 11:14:08 -07002094FX_BOOL CXFA_FM2JSContext::GetGMTTime(CFXJSE_Value* pThis,
Dan Sinclair1770c022016-03-14 14:14:16 -04002095 const CFX_ByteStringC& szTime,
2096 const CFX_ByteStringC& szFormat,
2097 const CFX_ByteStringC& szLocale,
2098 CFX_ByteString& strGMTTime) {
dsinclair8f3074b2016-06-02 17:45:25 -07002099 CXFA_Document* pDoc = ToJSContext(pThis, nullptr)->GetDocument();
dsinclair2b6d64e2016-06-06 11:39:42 -07002100 if (!pDoc)
Dan Sinclair1770c022016-03-14 14:14:16 -04002101 return FALSE;
dsinclair2b6d64e2016-06-06 11:39:42 -07002102
2103 CXFA_LocaleMgr* pMgr = pDoc->GetLocalMgr();
dsinclair48d91dd2016-05-31 11:54:01 -07002104 IFX_Locale* pLocale = nullptr;
Dan Sinclair1770c022016-03-14 14:14:16 -04002105 if (szLocale.IsEmpty()) {
2106 CXFA_Node* pThisNode = ToNode(pDoc->GetScriptContext()->GetThisObject());
dsinclair43854a52016-04-27 12:26:00 -07002107 ASSERT(pThisNode);
Dan Sinclair1770c022016-03-14 14:14:16 -04002108 CXFA_WidgetData widgetData(pThisNode);
2109 pLocale = widgetData.GetLocal();
2110 } else {
tsepezafe94302016-05-13 17:21:31 -07002111 pLocale = pMgr->GetLocaleByName(CFX_WideString::FromUTF8(szLocale));
Dan Sinclair1770c022016-03-14 14:14:16 -04002112 }
dsinclair2b6d64e2016-06-06 11:39:42 -07002113 if (!pLocale)
Dan Sinclair1770c022016-03-14 14:14:16 -04002114 return FALSE;
dsinclair2b6d64e2016-06-06 11:39:42 -07002115
Dan Sinclair1770c022016-03-14 14:14:16 -04002116 CFX_WideString wsFormat;
dsinclair2b6d64e2016-06-06 11:39:42 -07002117 if (szFormat.IsEmpty())
Dan Sinclair1770c022016-03-14 14:14:16 -04002118 pLocale->GetTimePattern(FX_LOCALEDATETIMESUBCATEGORY_Default, wsFormat);
dsinclair2b6d64e2016-06-06 11:39:42 -07002119 else
tsepez6fe7d212016-04-06 10:51:14 -07002120 wsFormat = CFX_WideString::FromUTF8(szFormat);
dsinclair2b6d64e2016-06-06 11:39:42 -07002121
dsinclaircf7f3222016-06-08 20:34:02 -07002122 wsFormat = L"time{" + wsFormat + L"}";
tsepez6fe7d212016-04-06 10:51:14 -07002123 CXFA_LocaleValue widgetValue(XFA_VT_TIME, CFX_WideString::FromUTF8(szTime),
dsinclair2b6d64e2016-06-06 11:39:42 -07002124 pMgr);
Dan Sinclair1770c022016-03-14 14:14:16 -04002125 CFX_WideString wsRet;
2126 widgetValue.FormatPatterns(wsRet, wsFormat, pLocale,
2127 XFA_VALUEPICTURE_Display);
tsepezbd9748d2016-04-13 21:40:19 -07002128 strGMTTime = FX_UTF8Encode(wsRet.c_str(), wsRet.GetLength());
Dan Sinclair1770c022016-03-14 14:14:16 -04002129 return TRUE;
2130}
dsinclair48d91dd2016-05-31 11:54:01 -07002131
2132// static
Dan Sinclair1770c022016-03-14 14:14:16 -04002133int32_t CXFA_FM2JSContext::DateString2Num(const CFX_ByteStringC& szDateString) {
Dan Sinclair1770c022016-03-14 14:14:16 -04002134 int32_t iLength = szDateString.GetLength();
Dan Sinclair1770c022016-03-14 14:14:16 -04002135 int32_t iYear = 0;
2136 int32_t iMonth = 0;
2137 int32_t iDay = 0;
Dan Sinclair1770c022016-03-14 14:14:16 -04002138 if (iLength <= 10) {
dsinclair2b6d64e2016-06-06 11:39:42 -07002139 int32_t iStyle = -1;
2140 if (!IsIsoDateFormat(szDateString.c_str(), iLength, iStyle, iYear, iMonth,
2141 iDay)) {
2142 return 0;
2143 }
Dan Sinclair1770c022016-03-14 14:14:16 -04002144 } else {
dsinclair2b6d64e2016-06-06 11:39:42 -07002145 int32_t iHour = 0;
2146 int32_t iMinute = 0;
2147 int32_t iSecond = 0;
2148 int32_t iMilliSecond = 0;
2149 int32_t iZoneHour = 0;
2150 int32_t iZoneMinute = 0;
2151 if (!IsIsoDateTimeFormat(szDateString.c_str(), iLength, iYear, iMonth, iDay,
2152 iHour, iMinute, iSecond, iMilliSecond, iZoneHour,
2153 iZoneMinute)) {
2154 return 0;
2155 }
Dan Sinclair1770c022016-03-14 14:14:16 -04002156 }
dsinclair2b6d64e2016-06-06 11:39:42 -07002157
Dan Sinclair1770c022016-03-14 14:14:16 -04002158 FX_FLOAT dDays = 0;
2159 int32_t i = 1;
dsinclair2b6d64e2016-06-06 11:39:42 -07002160 if (iYear < 1900)
2161 return 0;
2162
2163 while (iYear - i >= 1900) {
2164 dDays +=
2165 ((!((iYear - i) % 4) && ((iYear - i) % 100)) || !((iYear - i) % 400))
2166 ? 366
2167 : 365;
2168 ++i;
Dan Sinclair1770c022016-03-14 14:14:16 -04002169 }
dsinclair2b6d64e2016-06-06 11:39:42 -07002170 i = 1;
2171 while (i < iMonth) {
2172 if (i == 2)
2173 dDays += ((!(iYear % 4) && (iYear % 100)) || !(iYear % 400)) ? 29 : 28;
2174 else if (i <= 7)
2175 dDays += (i % 2 == 0) ? 30 : 31;
2176 else
2177 dDays += (i % 2 == 0) ? 31 : 30;
2178
2179 ++i;
2180 }
2181 i = 0;
2182 while (iDay - i > 0) {
2183 dDays += 1;
2184 ++i;
Dan Sinclair1770c022016-03-14 14:14:16 -04002185 }
2186 return (int32_t)dDays;
2187}
dsinclair0c268e92016-05-17 14:04:14 -07002188
dsinclair48d91dd2016-05-31 11:54:01 -07002189// static
dsinclair12a6b0c2016-05-26 11:14:08 -07002190void CXFA_FM2JSContext::GetLocalDateFormat(CFXJSE_Value* pThis,
Dan Sinclair1770c022016-03-14 14:14:16 -04002191 int32_t iStyle,
2192 const CFX_ByteStringC& szLocalStr,
2193 CFX_ByteString& strFormat,
2194 FX_BOOL bStandard) {
2195 FX_LOCALEDATETIMESUBCATEGORY strStyle;
2196 switch (iStyle) {
Dan Sinclair1770c022016-03-14 14:14:16 -04002197 case 1:
2198 strStyle = FX_LOCALEDATETIMESUBCATEGORY_Short;
2199 break;
Dan Sinclair1770c022016-03-14 14:14:16 -04002200 case 3:
2201 strStyle = FX_LOCALEDATETIMESUBCATEGORY_Long;
2202 break;
2203 case 4:
2204 strStyle = FX_LOCALEDATETIMESUBCATEGORY_Full;
2205 break;
dsinclair2b6d64e2016-06-06 11:39:42 -07002206 case 0:
2207 case 2:
Dan Sinclair1770c022016-03-14 14:14:16 -04002208 default:
2209 strStyle = FX_LOCALEDATETIMESUBCATEGORY_Medium;
2210 break;
2211 }
dsinclair8f3074b2016-06-02 17:45:25 -07002212 CXFA_Document* pDoc = ToJSContext(pThis, nullptr)->GetDocument();
dsinclair2b6d64e2016-06-06 11:39:42 -07002213 if (!pDoc)
Dan Sinclair1770c022016-03-14 14:14:16 -04002214 return;
dsinclair2b6d64e2016-06-06 11:39:42 -07002215
dsinclair48d91dd2016-05-31 11:54:01 -07002216 IFX_Locale* pLocale = nullptr;
Dan Sinclair1770c022016-03-14 14:14:16 -04002217 if (szLocalStr.IsEmpty()) {
2218 CXFA_Node* pThisNode = ToNode(pDoc->GetScriptContext()->GetThisObject());
dsinclair43854a52016-04-27 12:26:00 -07002219 ASSERT(pThisNode);
dsinclair2b6d64e2016-06-06 11:39:42 -07002220
Dan Sinclair1770c022016-03-14 14:14:16 -04002221 CXFA_WidgetData widgetData(pThisNode);
2222 pLocale = widgetData.GetLocal();
2223 } else {
dsinclair2b6d64e2016-06-06 11:39:42 -07002224 pLocale = pDoc->GetLocalMgr()->GetLocaleByName(
2225 CFX_WideString::FromUTF8(szLocalStr));
Dan Sinclair1770c022016-03-14 14:14:16 -04002226 }
dsinclair2b6d64e2016-06-06 11:39:42 -07002227 if (!pLocale)
Dan Sinclair1770c022016-03-14 14:14:16 -04002228 return;
dsinclair2b6d64e2016-06-06 11:39:42 -07002229
Dan Sinclair1770c022016-03-14 14:14:16 -04002230 CFX_WideString strRet;
2231 pLocale->GetDatePattern(strStyle, strRet);
2232 if (!bStandard) {
2233 CFX_WideString wsSymbols;
2234 pLocale->GetDateTimeSymbols(wsSymbols);
dsinclair0c268e92016-05-17 14:04:14 -07002235 AlternateDateTimeSymbols(strRet, wsSymbols, g_sAltTable_Date);
Dan Sinclair1770c022016-03-14 14:14:16 -04002236 }
tsepezbd9748d2016-04-13 21:40:19 -07002237 strFormat = FX_UTF8Encode(strRet.c_str(), strRet.GetLength());
Dan Sinclair1770c022016-03-14 14:14:16 -04002238}
dsinclair48d91dd2016-05-31 11:54:01 -07002239
2240// static
dsinclair12a6b0c2016-05-26 11:14:08 -07002241void CXFA_FM2JSContext::GetLocalTimeFormat(CFXJSE_Value* pThis,
Dan Sinclair1770c022016-03-14 14:14:16 -04002242 int32_t iStyle,
2243 const CFX_ByteStringC& szLocalStr,
2244 CFX_ByteString& strFormat,
2245 FX_BOOL bStandard) {
2246 FX_LOCALEDATETIMESUBCATEGORY strStyle;
2247 switch (iStyle) {
Dan Sinclair1770c022016-03-14 14:14:16 -04002248 case 1:
2249 strStyle = FX_LOCALEDATETIMESUBCATEGORY_Short;
2250 break;
Dan Sinclair1770c022016-03-14 14:14:16 -04002251 case 3:
2252 strStyle = FX_LOCALEDATETIMESUBCATEGORY_Long;
2253 break;
2254 case 4:
2255 strStyle = FX_LOCALEDATETIMESUBCATEGORY_Full;
2256 break;
dsinclair2b6d64e2016-06-06 11:39:42 -07002257 case 0:
2258 case 2:
Dan Sinclair1770c022016-03-14 14:14:16 -04002259 default:
2260 strStyle = FX_LOCALEDATETIMESUBCATEGORY_Medium;
2261 break;
2262 }
dsinclair8f3074b2016-06-02 17:45:25 -07002263 CXFA_Document* pDoc = ToJSContext(pThis, nullptr)->GetDocument();
dsinclair2b6d64e2016-06-06 11:39:42 -07002264 if (!pDoc)
Dan Sinclair1770c022016-03-14 14:14:16 -04002265 return;
dsinclair2b6d64e2016-06-06 11:39:42 -07002266
dsinclair48d91dd2016-05-31 11:54:01 -07002267 IFX_Locale* pLocale = nullptr;
Dan Sinclair1770c022016-03-14 14:14:16 -04002268 if (szLocalStr.IsEmpty()) {
2269 CXFA_Node* pThisNode = ToNode(pDoc->GetScriptContext()->GetThisObject());
dsinclair43854a52016-04-27 12:26:00 -07002270 ASSERT(pThisNode);
dsinclair2b6d64e2016-06-06 11:39:42 -07002271
Dan Sinclair1770c022016-03-14 14:14:16 -04002272 CXFA_WidgetData widgetData(pThisNode);
2273 pLocale = widgetData.GetLocal();
2274 } else {
dsinclair2b6d64e2016-06-06 11:39:42 -07002275 pLocale = pDoc->GetLocalMgr()->GetLocaleByName(
2276 CFX_WideString::FromUTF8(szLocalStr));
Dan Sinclair1770c022016-03-14 14:14:16 -04002277 }
dsinclair2b6d64e2016-06-06 11:39:42 -07002278 if (!pLocale)
Dan Sinclair1770c022016-03-14 14:14:16 -04002279 return;
dsinclair2b6d64e2016-06-06 11:39:42 -07002280
Dan Sinclair1770c022016-03-14 14:14:16 -04002281 CFX_WideString strRet;
2282 pLocale->GetTimePattern(strStyle, strRet);
2283 if (!bStandard) {
2284 CFX_WideString wsSymbols;
2285 pLocale->GetDateTimeSymbols(wsSymbols);
dsinclair0c268e92016-05-17 14:04:14 -07002286 AlternateDateTimeSymbols(strRet, wsSymbols, g_sAltTable_Time);
Dan Sinclair1770c022016-03-14 14:14:16 -04002287 }
tsepezbd9748d2016-04-13 21:40:19 -07002288 strFormat = FX_UTF8Encode(strRet.c_str(), strRet.GetLength());
Dan Sinclair1770c022016-03-14 14:14:16 -04002289}
dsinclair48d91dd2016-05-31 11:54:01 -07002290
2291// static
dsinclair12a6b0c2016-05-26 11:14:08 -07002292void CXFA_FM2JSContext::GetStandardDateFormat(CFXJSE_Value* pThis,
Dan Sinclair1770c022016-03-14 14:14:16 -04002293 int32_t iStyle,
2294 const CFX_ByteStringC& szLocalStr,
2295 CFX_ByteString& strFormat) {
dsinclair12a6b0c2016-05-26 11:14:08 -07002296 GetLocalDateFormat(pThis, iStyle, szLocalStr, strFormat, TRUE);
Dan Sinclair1770c022016-03-14 14:14:16 -04002297}
dsinclair48d91dd2016-05-31 11:54:01 -07002298
2299// static
dsinclair12a6b0c2016-05-26 11:14:08 -07002300void CXFA_FM2JSContext::GetStandardTimeFormat(CFXJSE_Value* pThis,
Dan Sinclair1770c022016-03-14 14:14:16 -04002301 int32_t iStyle,
2302 const CFX_ByteStringC& szLocalStr,
2303 CFX_ByteString& strFormat) {
dsinclair12a6b0c2016-05-26 11:14:08 -07002304 GetLocalTimeFormat(pThis, iStyle, szLocalStr, strFormat, TRUE);
Dan Sinclair1770c022016-03-14 14:14:16 -04002305}
dsinclair48d91dd2016-05-31 11:54:01 -07002306
2307// static
dsinclair12a6b0c2016-05-26 11:14:08 -07002308void CXFA_FM2JSContext::Num2AllTime(CFXJSE_Value* pThis,
Dan Sinclair1770c022016-03-14 14:14:16 -04002309 int32_t iTime,
2310 const CFX_ByteStringC& szFormat,
2311 const CFX_ByteStringC& szLocale,
2312 FX_BOOL bGM,
2313 CFX_ByteString& strTime) {
2314 int32_t iHour = 0;
2315 int32_t iMin = 0;
2316 int32_t iSec = 0;
Dan Sinclair1770c022016-03-14 14:14:16 -04002317 iHour = static_cast<int>(iTime) / 3600000;
2318 iMin = (static_cast<int>(iTime) - iHour * 3600000) / 60000;
2319 iSec = (static_cast<int>(iTime) - iHour * 3600000 - iMin * 60000) / 1000;
dsinclair2b6d64e2016-06-06 11:39:42 -07002320
Dan Sinclair1770c022016-03-14 14:14:16 -04002321 if (!bGM) {
dsinclair2b6d64e2016-06-06 11:39:42 -07002322 int32_t iZoneHour = 0;
2323 int32_t iZoneMin = 0;
2324 int32_t iZoneSec = 0;
Dan Sinclair1770c022016-03-14 14:14:16 -04002325 GetLocalTimeZone(iZoneHour, iZoneMin, iZoneSec);
2326 iHour += iZoneHour;
2327 iMin += iZoneMin;
2328 iSec += iZoneSec;
2329 }
dsinclair2b6d64e2016-06-06 11:39:42 -07002330
2331 FX_BOOL iRet = FALSE;
Dan Sinclair1770c022016-03-14 14:14:16 -04002332 CFX_ByteString strIsoTime;
2333 strIsoTime.Format("%02d:%02d:%02d", iHour, iMin, iSec);
2334 if (bGM) {
tsepez4c3debb2016-04-08 12:20:38 -07002335 iRet =
dsinclair12a6b0c2016-05-26 11:14:08 -07002336 GetGMTTime(pThis, strIsoTime.AsStringC(), szFormat, szLocale, strTime);
Dan Sinclair1770c022016-03-14 14:14:16 -04002337 } else {
dsinclair12a6b0c2016-05-26 11:14:08 -07002338 iRet = IsoTime2Local(pThis, strIsoTime.AsStringC(), szFormat, szLocale,
tsepez28f97ff2016-04-04 16:41:35 -07002339 strTime);
Dan Sinclair1770c022016-03-14 14:14:16 -04002340 }
dsinclair2b6d64e2016-06-06 11:39:42 -07002341 if (!iRet)
Dan Sinclair1770c022016-03-14 14:14:16 -04002342 strTime = "";
Dan Sinclair1770c022016-03-14 14:14:16 -04002343}
2344
dsinclair48d91dd2016-05-31 11:54:01 -07002345// static
Dan Sinclair1770c022016-03-14 14:14:16 -04002346void CXFA_FM2JSContext::GetLocalTimeZone(int32_t& iHour,
2347 int32_t& iMin,
2348 int32_t& iSec) {
2349 time_t now;
2350 time(&now);
dsinclair2b6d64e2016-06-06 11:39:42 -07002351
Dan Sinclair1770c022016-03-14 14:14:16 -04002352 struct tm* pGmt = gmtime(&now);
Dan Sinclair1770c022016-03-14 14:14:16 -04002353 struct tm* pLocal = localtime(&now);
dsinclair2b6d64e2016-06-06 11:39:42 -07002354 iHour = pLocal->tm_hour - pGmt->tm_hour;
2355 iMin = pLocal->tm_min - pGmt->tm_min;
2356 iSec = pLocal->tm_sec - pGmt->tm_sec;
Dan Sinclair1770c022016-03-14 14:14:16 -04002357}
dsinclair48d91dd2016-05-31 11:54:01 -07002358
2359// static
dsinclair12a6b0c2016-05-26 11:14:08 -07002360void CXFA_FM2JSContext::Apr(CFXJSE_Value* pThis,
Dan Sinclair1770c022016-03-14 14:14:16 -04002361 const CFX_ByteStringC& szFuncName,
2362 CFXJSE_Arguments& args) {
dsinclair8f3074b2016-06-02 17:45:25 -07002363 CXFA_FM2JSContext* pContext = ToJSContext(pThis, nullptr);
dsinclair96a05f42016-06-07 06:48:02 -07002364 if (args.GetLength() != 3) {
dsinclair2235b7b2016-06-02 07:42:25 -07002365 pContext->ThrowException(XFA_IDS_INCORRECT_NUMBER_OF_METHOD, L"Apr");
dsinclair96a05f42016-06-07 06:48:02 -07002366 return;
Dan Sinclair1770c022016-03-14 14:14:16 -04002367 }
dsinclair96a05f42016-06-07 06:48:02 -07002368
2369 std::unique_ptr<CFXJSE_Value> argOne = GetSimpleValue(pThis, args, 0);
2370 std::unique_ptr<CFXJSE_Value> argTwo = GetSimpleValue(pThis, args, 1);
2371 std::unique_ptr<CFXJSE_Value> argThree = GetSimpleValue(pThis, args, 2);
2372 if (ValueIsNull(pThis, argOne.get()) || ValueIsNull(pThis, argTwo.get()) ||
2373 ValueIsNull(pThis, argThree.get())) {
dsinclairf27aeec2016-06-07 19:36:18 -07002374 args.GetReturnValue()->SetNull();
dsinclair96a05f42016-06-07 06:48:02 -07002375 return;
2376 }
2377
2378 FX_DOUBLE nPrincipal = ValueToDouble(pThis, argOne.get());
2379 FX_DOUBLE nPayment = ValueToDouble(pThis, argTwo.get());
2380 FX_DOUBLE nPeriods = ValueToDouble(pThis, argThree.get());
2381 if (nPrincipal <= 0 || nPayment <= 0 || nPeriods <= 0) {
2382 pContext->ThrowException(XFA_IDS_ARGUMENT_MISMATCH);
2383 return;
2384 }
2385
2386 FX_DOUBLE r =
2387 2 * (nPeriods * nPayment - nPrincipal) / (nPeriods * nPrincipal);
2388 FX_DOUBLE nTemp = 1;
2389 for (int32_t i = 0; i < nPeriods; ++i)
2390 nTemp *= (1 + r);
2391
2392 FX_DOUBLE nRet = r * nTemp / (nTemp - 1) - nPayment / nPrincipal;
2393 while (fabs(nRet) > kFinancialPrecision) {
2394 FX_DOUBLE nDerivative =
2395 ((nTemp + r * nPeriods * (nTemp / (1 + r))) * (nTemp - 1) -
2396 (r * nTemp * nPeriods * (nTemp / (1 + r)))) /
2397 ((nTemp - 1) * (nTemp - 1));
2398 if (nDerivative == 0) {
dsinclairf27aeec2016-06-07 19:36:18 -07002399 args.GetReturnValue()->SetNull();
dsinclair96a05f42016-06-07 06:48:02 -07002400 return;
2401 }
2402
2403 r = r - nRet / nDerivative;
2404 nTemp = 1;
2405 for (int32_t i = 0; i < nPeriods; ++i) {
2406 nTemp *= (1 + r);
2407 }
2408 nRet = r * nTemp / (nTemp - 1) - nPayment / nPrincipal;
2409 }
dsinclairf27aeec2016-06-07 19:36:18 -07002410 args.GetReturnValue()->SetDouble(r * 12);
Dan Sinclair1770c022016-03-14 14:14:16 -04002411}
dsinclair48d91dd2016-05-31 11:54:01 -07002412
2413// static
dsinclair12a6b0c2016-05-26 11:14:08 -07002414void CXFA_FM2JSContext::CTerm(CFXJSE_Value* pThis,
Dan Sinclair1770c022016-03-14 14:14:16 -04002415 const CFX_ByteStringC& szFuncName,
2416 CFXJSE_Arguments& args) {
dsinclair8f3074b2016-06-02 17:45:25 -07002417 CXFA_FM2JSContext* pContext = ToJSContext(pThis, nullptr);
dsinclair96a05f42016-06-07 06:48:02 -07002418 if (args.GetLength() != 3) {
dsinclair2235b7b2016-06-02 07:42:25 -07002419 pContext->ThrowException(XFA_IDS_INCORRECT_NUMBER_OF_METHOD, L"CTerm");
dsinclair96a05f42016-06-07 06:48:02 -07002420 return;
Dan Sinclair1770c022016-03-14 14:14:16 -04002421 }
dsinclair96a05f42016-06-07 06:48:02 -07002422
2423 std::unique_ptr<CFXJSE_Value> argOne = GetSimpleValue(pThis, args, 0);
2424 std::unique_ptr<CFXJSE_Value> argTwo = GetSimpleValue(pThis, args, 1);
2425 std::unique_ptr<CFXJSE_Value> argThree = GetSimpleValue(pThis, args, 2);
2426 if (ValueIsNull(pThis, argOne.get()) || ValueIsNull(pThis, argTwo.get()) ||
2427 ValueIsNull(pThis, argThree.get())) {
dsinclairf27aeec2016-06-07 19:36:18 -07002428 args.GetReturnValue()->SetNull();
dsinclair96a05f42016-06-07 06:48:02 -07002429 return;
2430 }
2431
2432 FX_FLOAT nRate = ValueToFloat(pThis, argOne.get());
2433 FX_FLOAT nFutureValue = ValueToFloat(pThis, argTwo.get());
2434 FX_FLOAT nInitAmount = ValueToFloat(pThis, argThree.get());
2435 if ((nRate <= 0) || (nFutureValue <= 0) || (nInitAmount <= 0)) {
2436 pContext->ThrowException(XFA_IDS_ARGUMENT_MISMATCH);
2437 return;
2438 }
2439
dsinclairf27aeec2016-06-07 19:36:18 -07002440 args.GetReturnValue()->SetFloat(
2441 FXSYS_log((FX_FLOAT)(nFutureValue / nInitAmount)) /
2442 FXSYS_log((FX_FLOAT)(1 + nRate)));
Dan Sinclair1770c022016-03-14 14:14:16 -04002443}
dsinclair48d91dd2016-05-31 11:54:01 -07002444
2445// static
dsinclair12a6b0c2016-05-26 11:14:08 -07002446void CXFA_FM2JSContext::FV(CFXJSE_Value* pThis,
Dan Sinclair1770c022016-03-14 14:14:16 -04002447 const CFX_ByteStringC& szFuncName,
2448 CFXJSE_Arguments& args) {
dsinclair8f3074b2016-06-02 17:45:25 -07002449 CXFA_FM2JSContext* pContext = ToJSContext(pThis, nullptr);
dsinclair96a05f42016-06-07 06:48:02 -07002450 if (args.GetLength() != 3) {
dsinclair2235b7b2016-06-02 07:42:25 -07002451 pContext->ThrowException(XFA_IDS_INCORRECT_NUMBER_OF_METHOD, L"FV");
dsinclair96a05f42016-06-07 06:48:02 -07002452 return;
Dan Sinclair1770c022016-03-14 14:14:16 -04002453 }
dsinclair96a05f42016-06-07 06:48:02 -07002454
2455 std::unique_ptr<CFXJSE_Value> argOne = GetSimpleValue(pThis, args, 0);
2456 std::unique_ptr<CFXJSE_Value> argTwo = GetSimpleValue(pThis, args, 1);
2457 std::unique_ptr<CFXJSE_Value> argThree = GetSimpleValue(pThis, args, 2);
2458 if (ValueIsNull(pThis, argOne.get()) || ValueIsNull(pThis, argTwo.get()) ||
2459 ValueIsNull(pThis, argThree.get())) {
dsinclairf27aeec2016-06-07 19:36:18 -07002460 args.GetReturnValue()->SetNull();
dsinclair96a05f42016-06-07 06:48:02 -07002461 return;
2462 }
2463
2464 FX_DOUBLE nAmount = ValueToDouble(pThis, argOne.get());
2465 FX_DOUBLE nRate = ValueToDouble(pThis, argTwo.get());
2466 FX_DOUBLE nPeriod = ValueToDouble(pThis, argThree.get());
2467 if ((nRate < 0) || (nPeriod <= 0) || (nAmount <= 0)) {
2468 pContext->ThrowException(XFA_IDS_ARGUMENT_MISMATCH);
2469 return;
2470 }
2471
2472 FX_DOUBLE dResult = 0;
2473 if (nRate) {
2474 FX_DOUBLE nTemp = 1;
2475 for (int i = 0; i < nPeriod; ++i) {
2476 nTemp *= 1 + nRate;
2477 }
2478 dResult = nAmount * (nTemp - 1) / nRate;
2479 } else {
2480 dResult = nAmount * nPeriod;
2481 }
2482
dsinclairf27aeec2016-06-07 19:36:18 -07002483 args.GetReturnValue()->SetDouble(dResult);
Dan Sinclair1770c022016-03-14 14:14:16 -04002484}
dsinclair48d91dd2016-05-31 11:54:01 -07002485
2486// static
dsinclair12a6b0c2016-05-26 11:14:08 -07002487void CXFA_FM2JSContext::IPmt(CFXJSE_Value* pThis,
Dan Sinclair1770c022016-03-14 14:14:16 -04002488 const CFX_ByteStringC& szFuncName,
2489 CFXJSE_Arguments& args) {
dsinclair8f3074b2016-06-02 17:45:25 -07002490 CXFA_FM2JSContext* pContext = ToJSContext(pThis, nullptr);
dsinclair96a05f42016-06-07 06:48:02 -07002491 if (args.GetLength() != 5) {
dsinclair2235b7b2016-06-02 07:42:25 -07002492 pContext->ThrowException(XFA_IDS_INCORRECT_NUMBER_OF_METHOD, L"IPmt");
dsinclair96a05f42016-06-07 06:48:02 -07002493 return;
Dan Sinclair1770c022016-03-14 14:14:16 -04002494 }
dsinclair96a05f42016-06-07 06:48:02 -07002495
2496 std::unique_ptr<CFXJSE_Value> argOne = GetSimpleValue(pThis, args, 0);
2497 std::unique_ptr<CFXJSE_Value> argTwo = GetSimpleValue(pThis, args, 1);
2498 std::unique_ptr<CFXJSE_Value> argThree = GetSimpleValue(pThis, args, 2);
2499 std::unique_ptr<CFXJSE_Value> argFour = GetSimpleValue(pThis, args, 3);
2500 std::unique_ptr<CFXJSE_Value> argFive = GetSimpleValue(pThis, args, 4);
2501 if (ValueIsNull(pThis, argOne.get()) || ValueIsNull(pThis, argTwo.get()) ||
2502 ValueIsNull(pThis, argThree.get()) || ValueIsNull(pThis, argFour.get()) ||
2503 ValueIsNull(pThis, argFive.get())) {
dsinclairf27aeec2016-06-07 19:36:18 -07002504 args.GetReturnValue()->SetNull();
dsinclair96a05f42016-06-07 06:48:02 -07002505 return;
2506 }
2507
2508 FX_FLOAT nPrincipalAmount = ValueToFloat(pThis, argOne.get());
2509 FX_FLOAT nRate = ValueToFloat(pThis, argTwo.get());
2510 FX_FLOAT nPayment = ValueToFloat(pThis, argThree.get());
2511 FX_FLOAT nFirstMonth = ValueToFloat(pThis, argFour.get());
2512 FX_FLOAT nNumberOfMonths = ValueToFloat(pThis, argFive.get());
2513 if ((nPrincipalAmount <= 0) || (nRate <= 0) || (nPayment <= 0) ||
2514 (nFirstMonth < 0) || (nNumberOfMonths < 0)) {
2515 pContext->ThrowException(XFA_IDS_ARGUMENT_MISMATCH);
2516 return;
2517 }
2518
2519 FX_FLOAT nRateOfMonth = nRate / 12;
2520 int32_t iNums = (int32_t)(
2521 (FXSYS_log10((FX_FLOAT)(nPayment / nPrincipalAmount)) -
2522 FXSYS_log10((FX_FLOAT)(nPayment / nPrincipalAmount - nRateOfMonth))) /
2523 FXSYS_log10((FX_FLOAT)(1 + nRateOfMonth)));
2524 int32_t iEnd = std::min((int32_t)(nFirstMonth + nNumberOfMonths - 1), iNums);
2525
2526 if (nPayment < nPrincipalAmount * nRateOfMonth) {
dsinclairf27aeec2016-06-07 19:36:18 -07002527 args.GetReturnValue()->SetFloat(0);
dsinclair96a05f42016-06-07 06:48:02 -07002528 return;
2529 }
2530
2531 int32_t i = 0;
2532 for (i = 0; i < nFirstMonth - 1; ++i)
2533 nPrincipalAmount -= nPayment - nPrincipalAmount * nRateOfMonth;
2534
2535 FX_FLOAT nSum = 0;
2536 for (; i < iEnd; ++i) {
2537 nSum += nPrincipalAmount * nRateOfMonth;
2538 nPrincipalAmount -= nPayment - nPrincipalAmount * nRateOfMonth;
2539 }
dsinclairf27aeec2016-06-07 19:36:18 -07002540 args.GetReturnValue()->SetFloat(nSum);
Dan Sinclair1770c022016-03-14 14:14:16 -04002541}
dsinclair48d91dd2016-05-31 11:54:01 -07002542
2543// static
dsinclair12a6b0c2016-05-26 11:14:08 -07002544void CXFA_FM2JSContext::NPV(CFXJSE_Value* pThis,
Dan Sinclair1770c022016-03-14 14:14:16 -04002545 const CFX_ByteStringC& szFuncName,
2546 CFXJSE_Arguments& args) {
dsinclair8f3074b2016-06-02 17:45:25 -07002547 CXFA_FM2JSContext* pContext = ToJSContext(pThis, nullptr);
Dan Sinclair1770c022016-03-14 14:14:16 -04002548 int32_t argc = args.GetLength();
dsinclair96a05f42016-06-07 06:48:02 -07002549 if (argc < 3) {
dsinclair2235b7b2016-06-02 07:42:25 -07002550 pContext->ThrowException(XFA_IDS_INCORRECT_NUMBER_OF_METHOD, L"NPV");
dsinclair96a05f42016-06-07 06:48:02 -07002551 return;
Dan Sinclair1770c022016-03-14 14:14:16 -04002552 }
dsinclair96a05f42016-06-07 06:48:02 -07002553
2554 std::vector<std::unique_ptr<CFXJSE_Value>> argValues;
2555 for (int32_t i = 0; i < argc; i++) {
2556 argValues.push_back(GetSimpleValue(pThis, args, i));
2557 if (ValueIsNull(pThis, argValues[i].get())) {
dsinclairf27aeec2016-06-07 19:36:18 -07002558 args.GetReturnValue()->SetNull();
dsinclair96a05f42016-06-07 06:48:02 -07002559 return;
2560 }
2561 }
2562
2563 FX_DOUBLE nRate = ValueToDouble(pThis, argValues[0].get());
2564 if (nRate <= 0) {
2565 pContext->ThrowException(XFA_IDS_ARGUMENT_MISMATCH);
2566 return;
2567 }
2568
2569 std::vector<FX_DOUBLE> data(argc - 1);
2570 for (int32_t i = 1; i < argc; i++)
2571 data.push_back(ValueToDouble(pThis, argValues[i].get()));
2572
2573 FX_DOUBLE nSum = 0;
2574 int32_t iIndex = 0;
2575 for (int32_t i = 0; i < argc - 1; i++) {
2576 FX_DOUBLE nTemp = 1;
2577 for (int32_t j = 0; j <= i; j++)
2578 nTemp *= 1 + nRate;
2579
2580 FX_DOUBLE nNum = data[iIndex++];
2581 nSum += nNum / nTemp;
2582 }
dsinclairf27aeec2016-06-07 19:36:18 -07002583 args.GetReturnValue()->SetDouble(nSum);
Dan Sinclair1770c022016-03-14 14:14:16 -04002584}
dsinclair48d91dd2016-05-31 11:54:01 -07002585
2586// static
dsinclair12a6b0c2016-05-26 11:14:08 -07002587void CXFA_FM2JSContext::Pmt(CFXJSE_Value* pThis,
Dan Sinclair1770c022016-03-14 14:14:16 -04002588 const CFX_ByteStringC& szFuncName,
2589 CFXJSE_Arguments& args) {
dsinclair8f3074b2016-06-02 17:45:25 -07002590 CXFA_FM2JSContext* pContext = ToJSContext(pThis, nullptr);
dsinclair96a05f42016-06-07 06:48:02 -07002591 if (args.GetLength() != 3) {
dsinclair2235b7b2016-06-02 07:42:25 -07002592 pContext->ThrowException(XFA_IDS_INCORRECT_NUMBER_OF_METHOD, L"Pmt");
dsinclair96a05f42016-06-07 06:48:02 -07002593 return;
Dan Sinclair1770c022016-03-14 14:14:16 -04002594 }
dsinclair96a05f42016-06-07 06:48:02 -07002595
2596 std::unique_ptr<CFXJSE_Value> argOne = GetSimpleValue(pThis, args, 0);
2597 std::unique_ptr<CFXJSE_Value> argTwo = GetSimpleValue(pThis, args, 1);
2598 std::unique_ptr<CFXJSE_Value> argThree = GetSimpleValue(pThis, args, 2);
2599 if (ValueIsNull(pThis, argOne.get()) || ValueIsNull(pThis, argTwo.get()) ||
2600 ValueIsNull(pThis, argThree.get())) {
dsinclairf27aeec2016-06-07 19:36:18 -07002601 args.GetReturnValue()->SetNull();
dsinclair96a05f42016-06-07 06:48:02 -07002602 return;
2603 }
2604
2605 FX_FLOAT nPrincipal = ValueToFloat(pThis, argOne.get());
2606 FX_FLOAT nRate = ValueToFloat(pThis, argTwo.get());
2607 FX_FLOAT nPeriods = ValueToFloat(pThis, argThree.get());
2608 if ((nPrincipal <= 0) || (nRate <= 0) || (nPeriods <= 0)) {
2609 pContext->ThrowException(XFA_IDS_ARGUMENT_MISMATCH);
2610 return;
2611 }
2612
2613 FX_FLOAT nTmp = 1 + nRate;
2614 FX_FLOAT nSum = nTmp;
2615 for (int32_t i = 0; i < nPeriods - 1; ++i)
2616 nSum *= nTmp;
2617
dsinclairf27aeec2016-06-07 19:36:18 -07002618 args.GetReturnValue()->SetFloat((nPrincipal * nRate * nSum) / (nSum - 1));
Dan Sinclair1770c022016-03-14 14:14:16 -04002619}
dsinclair48d91dd2016-05-31 11:54:01 -07002620
2621// static
dsinclair12a6b0c2016-05-26 11:14:08 -07002622void CXFA_FM2JSContext::PPmt(CFXJSE_Value* pThis,
Dan Sinclair1770c022016-03-14 14:14:16 -04002623 const CFX_ByteStringC& szFuncName,
2624 CFXJSE_Arguments& args) {
dsinclair8f3074b2016-06-02 17:45:25 -07002625 CXFA_FM2JSContext* pContext = ToJSContext(pThis, nullptr);
dsinclair96a05f42016-06-07 06:48:02 -07002626 if (args.GetLength() != 5) {
dsinclair2235b7b2016-06-02 07:42:25 -07002627 pContext->ThrowException(XFA_IDS_INCORRECT_NUMBER_OF_METHOD, L"PPmt");
dsinclair96a05f42016-06-07 06:48:02 -07002628 return;
Dan Sinclair1770c022016-03-14 14:14:16 -04002629 }
dsinclair96a05f42016-06-07 06:48:02 -07002630
2631 std::unique_ptr<CFXJSE_Value> argOne = GetSimpleValue(pThis, args, 0);
2632 std::unique_ptr<CFXJSE_Value> argTwo = GetSimpleValue(pThis, args, 1);
2633 std::unique_ptr<CFXJSE_Value> argThree = GetSimpleValue(pThis, args, 2);
2634 std::unique_ptr<CFXJSE_Value> argFour = GetSimpleValue(pThis, args, 3);
2635 std::unique_ptr<CFXJSE_Value> argFive = GetSimpleValue(pThis, args, 4);
2636 if (ValueIsNull(pThis, argOne.get()) || ValueIsNull(pThis, argTwo.get()) ||
2637 ValueIsNull(pThis, argThree.get()) || ValueIsNull(pThis, argFour.get()) ||
2638 ValueIsNull(pThis, argFive.get())) {
dsinclairf27aeec2016-06-07 19:36:18 -07002639 args.GetReturnValue()->SetNull();
dsinclair96a05f42016-06-07 06:48:02 -07002640 return;
2641 }
2642
2643 FX_FLOAT nPrincipalAmount = ValueToFloat(pThis, argOne.get());
2644 FX_FLOAT nRate = ValueToFloat(pThis, argTwo.get());
2645 FX_FLOAT nPayment = ValueToFloat(pThis, argThree.get());
2646 FX_FLOAT nFirstMonth = ValueToFloat(pThis, argFour.get());
2647 FX_FLOAT nNumberOfMonths = ValueToFloat(pThis, argFive.get());
2648 if ((nPrincipalAmount <= 0) || (nRate <= 0) || (nPayment <= 0) ||
2649 (nFirstMonth < 0) || (nNumberOfMonths < 0)) {
2650 pContext->ThrowException(XFA_IDS_ARGUMENT_MISMATCH);
2651 return;
2652 }
2653
2654 FX_FLOAT nRateOfMonth = nRate / 12;
2655 int32_t iNums = (int32_t)(
2656 (FXSYS_log10((FX_FLOAT)(nPayment / nPrincipalAmount)) -
2657 FXSYS_log10((FX_FLOAT)(nPayment / nPrincipalAmount - nRateOfMonth))) /
2658 FXSYS_log10((FX_FLOAT)(1 + nRateOfMonth)));
2659 int32_t iEnd = std::min((int32_t)(nFirstMonth + nNumberOfMonths - 1), iNums);
2660 if (nPayment < nPrincipalAmount * nRateOfMonth) {
2661 pContext->ThrowException(XFA_IDS_ARGUMENT_MISMATCH);
2662 return;
2663 }
2664
2665 int32_t i = 0;
2666 for (i = 0; i < nFirstMonth - 1; ++i)
2667 nPrincipalAmount -= nPayment - nPrincipalAmount * nRateOfMonth;
2668
2669 FX_FLOAT nTemp = 0;
2670 FX_FLOAT nSum = 0;
2671 for (; i < iEnd; ++i) {
2672 nTemp = nPayment - nPrincipalAmount * nRateOfMonth;
2673 nSum += nTemp;
2674 nPrincipalAmount -= nTemp;
2675 }
dsinclairf27aeec2016-06-07 19:36:18 -07002676 args.GetReturnValue()->SetFloat(nSum);
Dan Sinclair1770c022016-03-14 14:14:16 -04002677}
dsinclair48d91dd2016-05-31 11:54:01 -07002678
2679// static
dsinclair12a6b0c2016-05-26 11:14:08 -07002680void CXFA_FM2JSContext::PV(CFXJSE_Value* pThis,
Dan Sinclair1770c022016-03-14 14:14:16 -04002681 const CFX_ByteStringC& szFuncName,
2682 CFXJSE_Arguments& args) {
dsinclair8f3074b2016-06-02 17:45:25 -07002683 CXFA_FM2JSContext* pContext = ToJSContext(pThis, nullptr);
dsinclair96a05f42016-06-07 06:48:02 -07002684 if (args.GetLength() != 3) {
dsinclair2235b7b2016-06-02 07:42:25 -07002685 pContext->ThrowException(XFA_IDS_INCORRECT_NUMBER_OF_METHOD, L"PV");
dsinclair96a05f42016-06-07 06:48:02 -07002686 return;
Dan Sinclair1770c022016-03-14 14:14:16 -04002687 }
dsinclair96a05f42016-06-07 06:48:02 -07002688
2689 std::unique_ptr<CFXJSE_Value> argOne = GetSimpleValue(pThis, args, 0);
2690 std::unique_ptr<CFXJSE_Value> argTwo = GetSimpleValue(pThis, args, 1);
2691 std::unique_ptr<CFXJSE_Value> argThree = GetSimpleValue(pThis, args, 2);
2692 if (ValueIsNull(pThis, argOne.get()) || ValueIsNull(pThis, argTwo.get()) ||
2693 ValueIsNull(pThis, argThree.get())) {
dsinclairf27aeec2016-06-07 19:36:18 -07002694 args.GetReturnValue()->SetNull();
dsinclair96a05f42016-06-07 06:48:02 -07002695 return;
2696 }
2697
2698 FX_DOUBLE nAmount = ValueToDouble(pThis, argOne.get());
2699 FX_DOUBLE nRate = ValueToDouble(pThis, argTwo.get());
2700 FX_DOUBLE nPeriod = ValueToDouble(pThis, argThree.get());
2701 if ((nAmount <= 0) || (nRate < 0) || (nPeriod <= 0)) {
2702 pContext->ThrowException(XFA_IDS_ARGUMENT_MISMATCH);
2703 return;
2704 }
2705
2706 FX_DOUBLE nTemp = 1;
2707 for (int32_t i = 0; i < nPeriod; ++i)
2708 nTemp *= 1 + nRate;
2709
2710 nTemp = 1 / nTemp;
dsinclairf27aeec2016-06-07 19:36:18 -07002711 args.GetReturnValue()->SetDouble(nAmount * ((1 - nTemp) / nRate));
Dan Sinclair1770c022016-03-14 14:14:16 -04002712}
dsinclair48d91dd2016-05-31 11:54:01 -07002713
2714// static
dsinclair12a6b0c2016-05-26 11:14:08 -07002715void CXFA_FM2JSContext::Rate(CFXJSE_Value* pThis,
Dan Sinclair1770c022016-03-14 14:14:16 -04002716 const CFX_ByteStringC& szFuncName,
2717 CFXJSE_Arguments& args) {
dsinclair8f3074b2016-06-02 17:45:25 -07002718 CXFA_FM2JSContext* pContext = ToJSContext(pThis, nullptr);
dsinclair96a05f42016-06-07 06:48:02 -07002719 if (args.GetLength() != 3) {
dsinclair2235b7b2016-06-02 07:42:25 -07002720 pContext->ThrowException(XFA_IDS_INCORRECT_NUMBER_OF_METHOD, L"Rate");
dsinclair96a05f42016-06-07 06:48:02 -07002721 return;
Dan Sinclair1770c022016-03-14 14:14:16 -04002722 }
dsinclair96a05f42016-06-07 06:48:02 -07002723
2724 std::unique_ptr<CFXJSE_Value> argOne = GetSimpleValue(pThis, args, 0);
2725 std::unique_ptr<CFXJSE_Value> argTwo = GetSimpleValue(pThis, args, 1);
2726 std::unique_ptr<CFXJSE_Value> argThree = GetSimpleValue(pThis, args, 2);
2727 if (ValueIsNull(pThis, argOne.get()) || ValueIsNull(pThis, argTwo.get()) ||
2728 ValueIsNull(pThis, argThree.get())) {
dsinclairf27aeec2016-06-07 19:36:18 -07002729 args.GetReturnValue()->SetNull();
dsinclair96a05f42016-06-07 06:48:02 -07002730 return;
2731 }
2732
2733 FX_FLOAT nFuture = ValueToFloat(pThis, argOne.get());
2734 FX_FLOAT nPresent = ValueToFloat(pThis, argTwo.get());
2735 FX_FLOAT nTotalNumber = ValueToFloat(pThis, argThree.get());
2736 if ((nFuture <= 0) || (nPresent < 0) || (nTotalNumber <= 0)) {
2737 pContext->ThrowException(XFA_IDS_ARGUMENT_MISMATCH);
2738 return;
2739 }
2740
dsinclairf27aeec2016-06-07 19:36:18 -07002741 args.GetReturnValue()->SetFloat(
2742 FXSYS_pow((FX_FLOAT)(nFuture / nPresent), (FX_FLOAT)(1 / nTotalNumber)) -
2743 1);
Dan Sinclair1770c022016-03-14 14:14:16 -04002744}
dsinclair48d91dd2016-05-31 11:54:01 -07002745
2746// static
dsinclair12a6b0c2016-05-26 11:14:08 -07002747void CXFA_FM2JSContext::Term(CFXJSE_Value* pThis,
Dan Sinclair1770c022016-03-14 14:14:16 -04002748 const CFX_ByteStringC& szFuncName,
2749 CFXJSE_Arguments& args) {
dsinclair8f3074b2016-06-02 17:45:25 -07002750 CXFA_FM2JSContext* pContext = ToJSContext(pThis, nullptr);
dsinclair96a05f42016-06-07 06:48:02 -07002751 if (args.GetLength() != 3) {
dsinclair2235b7b2016-06-02 07:42:25 -07002752 pContext->ThrowException(XFA_IDS_INCORRECT_NUMBER_OF_METHOD, L"Term");
dsinclair96a05f42016-06-07 06:48:02 -07002753 return;
Dan Sinclair1770c022016-03-14 14:14:16 -04002754 }
dsinclair96a05f42016-06-07 06:48:02 -07002755
2756 std::unique_ptr<CFXJSE_Value> argOne = GetSimpleValue(pThis, args, 0);
2757 std::unique_ptr<CFXJSE_Value> argTwo = GetSimpleValue(pThis, args, 1);
2758 std::unique_ptr<CFXJSE_Value> argThree = GetSimpleValue(pThis, args, 2);
2759 if (ValueIsNull(pThis, argOne.get()) || ValueIsNull(pThis, argTwo.get()) ||
2760 ValueIsNull(pThis, argThree.get())) {
dsinclairf27aeec2016-06-07 19:36:18 -07002761 args.GetReturnValue()->SetNull();
dsinclair96a05f42016-06-07 06:48:02 -07002762 return;
2763 }
2764
2765 FX_FLOAT nMount = ValueToFloat(pThis, argOne.get());
2766 FX_FLOAT nRate = ValueToFloat(pThis, argTwo.get());
2767 FX_FLOAT nFuture = ValueToFloat(pThis, argThree.get());
2768 if ((nMount <= 0) || (nRate <= 0) || (nFuture <= 0)) {
2769 pContext->ThrowException(XFA_IDS_ARGUMENT_MISMATCH);
2770 return;
2771 }
2772
dsinclairf27aeec2016-06-07 19:36:18 -07002773 args.GetReturnValue()->SetFloat(
2774 FXSYS_log((FX_FLOAT)(nFuture / nMount * nRate) + 1) /
2775 FXSYS_log((FX_FLOAT)(1 + nRate)));
Dan Sinclair1770c022016-03-14 14:14:16 -04002776}
dsinclair48d91dd2016-05-31 11:54:01 -07002777
2778// static
dsinclair12a6b0c2016-05-26 11:14:08 -07002779void CXFA_FM2JSContext::Choose(CFXJSE_Value* pThis,
Dan Sinclair1770c022016-03-14 14:14:16 -04002780 const CFX_ByteStringC& szFuncName,
2781 CFXJSE_Arguments& args) {
dsinclair8f3074b2016-06-02 17:45:25 -07002782 CXFA_FM2JSContext* pContext = ToJSContext(pThis, nullptr);
Dan Sinclair1770c022016-03-14 14:14:16 -04002783 int32_t argc = args.GetLength();
dsinclair96a05f42016-06-07 06:48:02 -07002784 if (argc < 2) {
dsinclair2235b7b2016-06-02 07:42:25 -07002785 pContext->ThrowException(XFA_IDS_INCORRECT_NUMBER_OF_METHOD, L"Choose");
dsinclair96a05f42016-06-07 06:48:02 -07002786 return;
Dan Sinclair1770c022016-03-14 14:14:16 -04002787 }
dsinclair96a05f42016-06-07 06:48:02 -07002788
2789 std::unique_ptr<CFXJSE_Value> argOne = args.GetValue(0);
2790 if (ValueIsNull(pThis, argOne.get())) {
dsinclairf27aeec2016-06-07 19:36:18 -07002791 args.GetReturnValue()->SetNull();
dsinclair96a05f42016-06-07 06:48:02 -07002792 return;
2793 }
2794
2795 int32_t iIndex = (int32_t)ValueToFloat(pThis, argOne.get());
2796 if (iIndex < 1) {
dsinclairf27aeec2016-06-07 19:36:18 -07002797 args.GetReturnValue()->SetString("");
dsinclair96a05f42016-06-07 06:48:02 -07002798 return;
2799 }
2800
2801 FX_BOOL bFound = FALSE;
2802 FX_BOOL bStopCounterFlags = FALSE;
2803 int32_t iArgIndex = 1;
2804 int32_t iValueIndex = 0;
2805 v8::Isolate* pIsolate = pContext->GetScriptRuntime();
2806 while (!bFound && !bStopCounterFlags && (iArgIndex < argc)) {
2807 std::unique_ptr<CFXJSE_Value> argIndexValue = args.GetValue(iArgIndex);
dsinclair769b1372016-06-08 13:12:41 -07002808 if (argIndexValue->IsArray()) {
dsinclair96a05f42016-06-07 06:48:02 -07002809 std::unique_ptr<CFXJSE_Value> lengthValue(new CFXJSE_Value(pIsolate));
dsinclairf27aeec2016-06-07 19:36:18 -07002810 argIndexValue->GetObjectProperty("length", lengthValue.get());
2811 int32_t iLength = lengthValue->ToInteger();
dsinclair96a05f42016-06-07 06:48:02 -07002812 if (iLength > 3)
2813 bStopCounterFlags = TRUE;
2814
2815 iValueIndex += (iLength - 2);
2816 if (iValueIndex >= iIndex) {
2817 std::unique_ptr<CFXJSE_Value> propertyValue(new CFXJSE_Value(pIsolate));
2818 std::unique_ptr<CFXJSE_Value> jsObjectValue(new CFXJSE_Value(pIsolate));
2819 std::unique_ptr<CFXJSE_Value> newPropertyValue(
2820 new CFXJSE_Value(pIsolate));
dsinclairf27aeec2016-06-07 19:36:18 -07002821 argIndexValue->GetObjectPropertyByIdx(1, propertyValue.get());
2822 argIndexValue->GetObjectPropertyByIdx(
2823 (iLength - 1) - (iValueIndex - iIndex), jsObjectValue.get());
dsinclair769b1372016-06-08 13:12:41 -07002824 if (propertyValue->IsNull()) {
dsinclair96a05f42016-06-07 06:48:02 -07002825 GetObjectDefaultValue(jsObjectValue.get(), newPropertyValue.get());
2826 } else {
dsinclair2f5582f2016-06-09 11:48:23 -07002827 jsObjectValue->GetObjectProperty(
2828 propertyValue->ToString().AsStringC(), newPropertyValue.get());
dsinclair96a05f42016-06-07 06:48:02 -07002829 }
2830 CFX_ByteString bsChoosed;
2831 ValueToUTF8String(newPropertyValue.get(), bsChoosed);
dsinclairf27aeec2016-06-07 19:36:18 -07002832 args.GetReturnValue()->SetString(bsChoosed.AsStringC());
dsinclair96a05f42016-06-07 06:48:02 -07002833 bFound = TRUE;
2834 }
2835 } else {
2836 iValueIndex++;
2837 if (iValueIndex == iIndex) {
2838 CFX_ByteString bsChoosed;
2839 ValueToUTF8String(argIndexValue.get(), bsChoosed);
dsinclairf27aeec2016-06-07 19:36:18 -07002840 args.GetReturnValue()->SetString(bsChoosed.AsStringC());
dsinclair96a05f42016-06-07 06:48:02 -07002841 bFound = TRUE;
2842 }
2843 }
2844 iArgIndex++;
2845 }
2846 if (!bFound)
dsinclairf27aeec2016-06-07 19:36:18 -07002847 args.GetReturnValue()->SetString("");
Dan Sinclair1770c022016-03-14 14:14:16 -04002848}
dsinclair48d91dd2016-05-31 11:54:01 -07002849
2850// static
dsinclair12a6b0c2016-05-26 11:14:08 -07002851void CXFA_FM2JSContext::Exists(CFXJSE_Value* pThis,
Dan Sinclair1770c022016-03-14 14:14:16 -04002852 const CFX_ByteStringC& szFuncName,
2853 CFXJSE_Arguments& args) {
dsinclair96a05f42016-06-07 06:48:02 -07002854 if (args.GetLength() != 1) {
dsinclair8f3074b2016-06-02 17:45:25 -07002855 ToJSContext(pThis, nullptr)
2856 ->ThrowException(XFA_IDS_INCORRECT_NUMBER_OF_METHOD, L"Exists");
dsinclair96a05f42016-06-07 06:48:02 -07002857 return;
Dan Sinclair1770c022016-03-14 14:14:16 -04002858 }
dsinclair769b1372016-06-08 13:12:41 -07002859 args.GetReturnValue()->SetInteger(args.GetValue(0)->IsObject());
Dan Sinclair1770c022016-03-14 14:14:16 -04002860}
dsinclair48d91dd2016-05-31 11:54:01 -07002861
2862// static
dsinclair12a6b0c2016-05-26 11:14:08 -07002863void CXFA_FM2JSContext::HasValue(CFXJSE_Value* pThis,
Dan Sinclair1770c022016-03-14 14:14:16 -04002864 const CFX_ByteStringC& szFuncName,
2865 CFXJSE_Arguments& args) {
dsinclair96a05f42016-06-07 06:48:02 -07002866 if (args.GetLength() != 1) {
dsinclair8f3074b2016-06-02 17:45:25 -07002867 ToJSContext(pThis, nullptr)
2868 ->ThrowException(XFA_IDS_INCORRECT_NUMBER_OF_METHOD, L"HasValue");
dsinclair96a05f42016-06-07 06:48:02 -07002869 return;
Dan Sinclair1770c022016-03-14 14:14:16 -04002870 }
dsinclair96a05f42016-06-07 06:48:02 -07002871
2872 std::unique_ptr<CFXJSE_Value> argOne = GetSimpleValue(pThis, args, 0);
dsinclair769b1372016-06-08 13:12:41 -07002873 if (!argOne->IsString()) {
2874 args.GetReturnValue()->SetInteger(argOne->IsNumber() ||
2875 argOne->IsBoolean());
dsinclair96a05f42016-06-07 06:48:02 -07002876 return;
2877 }
2878
dsinclair2f5582f2016-06-09 11:48:23 -07002879 CFX_ByteString valueStr = argOne->ToString();
dsinclair96a05f42016-06-07 06:48:02 -07002880 valueStr.TrimLeft();
dsinclairf27aeec2016-06-07 19:36:18 -07002881 args.GetReturnValue()->SetInteger(!valueStr.IsEmpty());
Dan Sinclair1770c022016-03-14 14:14:16 -04002882}
dsinclair48d91dd2016-05-31 11:54:01 -07002883
2884// static
dsinclair12a6b0c2016-05-26 11:14:08 -07002885void CXFA_FM2JSContext::Oneof(CFXJSE_Value* pThis,
Dan Sinclair1770c022016-03-14 14:14:16 -04002886 const CFX_ByteStringC& szFuncName,
2887 CFXJSE_Arguments& args) {
dsinclair96a05f42016-06-07 06:48:02 -07002888 if (args.GetLength() < 2) {
dsinclair8f3074b2016-06-02 17:45:25 -07002889 ToJSContext(pThis, nullptr)
2890 ->ThrowException(XFA_IDS_INCORRECT_NUMBER_OF_METHOD, L"Oneof");
dsinclair96a05f42016-06-07 06:48:02 -07002891 return;
Dan Sinclair1770c022016-03-14 14:14:16 -04002892 }
dsinclair96a05f42016-06-07 06:48:02 -07002893
2894 FX_BOOL bFlags = FALSE;
2895 std::unique_ptr<CFXJSE_Value> argOne = GetSimpleValue(pThis, args, 0);
2896 CFXJSE_Value** parametersValue = nullptr;
2897 int32_t iCount = 0;
2898 unfoldArgs(pThis, args, parametersValue, iCount, 1);
2899 for (int32_t i = 0; i < iCount; i++) {
2900 if (simpleValueCompare(pThis, argOne.get(), parametersValue[i])) {
2901 bFlags = TRUE;
2902 break;
2903 }
2904 }
2905 for (int32_t i = 0; i < iCount; i++)
2906 delete parametersValue[i];
2907 FX_Free(parametersValue);
2908
dsinclairf27aeec2016-06-07 19:36:18 -07002909 args.GetReturnValue()->SetInteger(bFlags);
Dan Sinclair1770c022016-03-14 14:14:16 -04002910}
dsinclair48d91dd2016-05-31 11:54:01 -07002911
2912// static
dsinclair12a6b0c2016-05-26 11:14:08 -07002913void CXFA_FM2JSContext::Within(CFXJSE_Value* pThis,
Dan Sinclair1770c022016-03-14 14:14:16 -04002914 const CFX_ByteStringC& szFuncName,
2915 CFXJSE_Arguments& args) {
dsinclair759de382016-06-07 14:10:16 -07002916 if (args.GetLength() != 3) {
dsinclair8f3074b2016-06-02 17:45:25 -07002917 ToJSContext(pThis, nullptr)
2918 ->ThrowException(XFA_IDS_INCORRECT_NUMBER_OF_METHOD, L"Within");
dsinclair759de382016-06-07 14:10:16 -07002919 return;
Dan Sinclair1770c022016-03-14 14:14:16 -04002920 }
dsinclair759de382016-06-07 14:10:16 -07002921
2922 std::unique_ptr<CFXJSE_Value> argOne = GetSimpleValue(pThis, args, 0);
dsinclair769b1372016-06-08 13:12:41 -07002923 if (argOne->IsNull()) {
dsinclairf27aeec2016-06-07 19:36:18 -07002924 args.GetReturnValue()->SetUndefined();
dsinclair759de382016-06-07 14:10:16 -07002925 return;
2926 }
2927
2928 std::unique_ptr<CFXJSE_Value> argLow = GetSimpleValue(pThis, args, 1);
2929 std::unique_ptr<CFXJSE_Value> argHigh = GetSimpleValue(pThis, args, 2);
dsinclair769b1372016-06-08 13:12:41 -07002930 if (argOne->IsNumber()) {
dsinclair759de382016-06-07 14:10:16 -07002931 FX_FLOAT oneNumber = ValueToFloat(pThis, argOne.get());
2932 FX_FLOAT lowNumber = ValueToFloat(pThis, argLow.get());
2933 FX_FLOAT heightNumber = ValueToFloat(pThis, argHigh.get());
dsinclairf27aeec2016-06-07 19:36:18 -07002934 args.GetReturnValue()->SetInteger((oneNumber >= lowNumber) &&
2935 (oneNumber <= heightNumber));
dsinclair759de382016-06-07 14:10:16 -07002936 return;
2937 }
2938
2939 CFX_ByteString oneString;
2940 CFX_ByteString lowString;
2941 CFX_ByteString heightString;
2942 ValueToUTF8String(argOne.get(), oneString);
2943 ValueToUTF8String(argLow.get(), lowString);
2944 ValueToUTF8String(argHigh.get(), heightString);
dsinclairf27aeec2016-06-07 19:36:18 -07002945 args.GetReturnValue()->SetInteger(
2946 (oneString.Compare(lowString.AsStringC()) >= 0) &&
2947 (oneString.Compare(heightString.AsStringC()) <= 0));
Dan Sinclair1770c022016-03-14 14:14:16 -04002948}
dsinclair48d91dd2016-05-31 11:54:01 -07002949
2950// static
dsinclair12a6b0c2016-05-26 11:14:08 -07002951void CXFA_FM2JSContext::If(CFXJSE_Value* pThis,
Dan Sinclair1770c022016-03-14 14:14:16 -04002952 const CFX_ByteStringC& szFuncName,
2953 CFXJSE_Arguments& args) {
dsinclair759de382016-06-07 14:10:16 -07002954 if (args.GetLength() != 3) {
dsinclair8f3074b2016-06-02 17:45:25 -07002955 ToJSContext(pThis, nullptr)
2956 ->ThrowException(XFA_IDS_INCORRECT_NUMBER_OF_METHOD, L"If");
dsinclair759de382016-06-07 14:10:16 -07002957 return;
Dan Sinclair1770c022016-03-14 14:14:16 -04002958 }
dsinclair759de382016-06-07 14:10:16 -07002959
dsinclairf27aeec2016-06-07 19:36:18 -07002960 args.GetReturnValue()->Assign(GetSimpleValue(pThis, args, 0)->ToBoolean()
2961 ? GetSimpleValue(pThis, args, 1).get()
2962 : GetSimpleValue(pThis, args, 2).get());
Dan Sinclair1770c022016-03-14 14:14:16 -04002963}
dsinclair48d91dd2016-05-31 11:54:01 -07002964
2965// static
dsinclair12a6b0c2016-05-26 11:14:08 -07002966void CXFA_FM2JSContext::Eval(CFXJSE_Value* pThis,
Dan Sinclair1770c022016-03-14 14:14:16 -04002967 const CFX_ByteStringC& szFuncName,
2968 CFXJSE_Arguments& args) {
dsinclair8f3074b2016-06-02 17:45:25 -07002969 CXFA_FM2JSContext* pContext = ToJSContext(pThis, nullptr);
dsinclair759de382016-06-07 14:10:16 -07002970 if (args.GetLength() != 1) {
dsinclair2235b7b2016-06-02 07:42:25 -07002971 pContext->ThrowException(XFA_IDS_INCORRECT_NUMBER_OF_METHOD, L"Eval");
dsinclair759de382016-06-07 14:10:16 -07002972 return;
Dan Sinclair1770c022016-03-14 14:14:16 -04002973 }
dsinclair759de382016-06-07 14:10:16 -07002974
2975 v8::Isolate* pIsolate = pContext->GetScriptRuntime();
2976 std::unique_ptr<CFXJSE_Value> scriptValue = GetSimpleValue(pThis, args, 0);
2977 CFX_ByteString utf8ScriptString;
2978 ValueToUTF8String(scriptValue.get(), utf8ScriptString);
2979 if (utf8ScriptString.IsEmpty()) {
dsinclairf27aeec2016-06-07 19:36:18 -07002980 args.GetReturnValue()->SetNull();
dsinclair759de382016-06-07 14:10:16 -07002981 return;
2982 }
2983
2984 CFX_WideTextBuf wsJavaScriptBuf;
2985 CFX_WideString wsError;
2986 CXFA_FM2JSContext::Translate(
2987 CFX_WideString::FromUTF8(utf8ScriptString.AsStringC()).AsStringC(),
2988 wsJavaScriptBuf, wsError);
dsinclair769b1372016-06-08 13:12:41 -07002989 std::unique_ptr<CFXJSE_Context> pNewContext(
2990 CFXJSE_Context::Create(pIsolate, nullptr, nullptr));
dsinclair759de382016-06-07 14:10:16 -07002991
2992 std::unique_ptr<CFXJSE_Value> returnValue(new CFXJSE_Value(pIsolate));
2993 CFX_WideString javaScript(wsJavaScriptBuf.AsStringC());
dsinclair769b1372016-06-08 13:12:41 -07002994 pNewContext->ExecuteScript(
dsinclair759de382016-06-07 14:10:16 -07002995 FX_UTF8Encode(javaScript.c_str(), javaScript.GetLength()).c_str(),
2996 returnValue.get());
2997
dsinclairf27aeec2016-06-07 19:36:18 -07002998 args.GetReturnValue()->Assign(returnValue.get());
Dan Sinclair1770c022016-03-14 14:14:16 -04002999}
dsinclair48d91dd2016-05-31 11:54:01 -07003000
3001// static
dsinclair12a6b0c2016-05-26 11:14:08 -07003002void CXFA_FM2JSContext::Ref(CFXJSE_Value* pThis,
Dan Sinclair1770c022016-03-14 14:14:16 -04003003 const CFX_ByteStringC& szFuncName,
3004 CFXJSE_Arguments& args) {
dsinclair8f3074b2016-06-02 17:45:25 -07003005 CXFA_FM2JSContext* pContext = ToJSContext(pThis, nullptr);
dsinclairec3da5b2016-05-25 16:42:05 -07003006 v8::Isolate* pIsolate = pContext->GetScriptRuntime();
dsinclair759de382016-06-07 14:10:16 -07003007 if (args.GetLength() != 1) {
dsinclair2235b7b2016-06-02 07:42:25 -07003008 pContext->ThrowException(XFA_IDS_INCORRECT_NUMBER_OF_METHOD, L"Ref");
dsinclair759de382016-06-07 14:10:16 -07003009 return;
Dan Sinclair1770c022016-03-14 14:14:16 -04003010 }
dsinclair759de382016-06-07 14:10:16 -07003011
3012 std::unique_ptr<CFXJSE_Value> argOne = args.GetValue(0);
dsinclair769b1372016-06-08 13:12:41 -07003013 if (!argOne->IsArray() && !argOne->IsObject() && !argOne->IsBoolean() &&
3014 !argOne->IsString() && !argOne->IsNull() && !argOne->IsNumber()) {
dsinclair759de382016-06-07 14:10:16 -07003015 pContext->ThrowException(XFA_IDS_ARGUMENT_MISMATCH);
3016 return;
3017 }
3018
dsinclair769b1372016-06-08 13:12:41 -07003019 if (argOne->IsBoolean() || argOne->IsString() || argOne->IsNumber()) {
dsinclairf27aeec2016-06-07 19:36:18 -07003020 args.GetReturnValue()->Assign(argOne.get());
dsinclair759de382016-06-07 14:10:16 -07003021 return;
3022 }
3023
3024 CFXJSE_Value* rgValues[3];
3025 for (int32_t i = 0; i < 3; i++)
3026 rgValues[i] = new CFXJSE_Value(pIsolate);
3027
3028 int intVal = 3;
dsinclair769b1372016-06-08 13:12:41 -07003029 if (argOne->IsNull()) {
3030 // TODO(dsinclair): Why is this 4 when the others are all 3?
dsinclair759de382016-06-07 14:10:16 -07003031 intVal = 4;
dsinclairf27aeec2016-06-07 19:36:18 -07003032 rgValues[2]->SetNull();
dsinclair769b1372016-06-08 13:12:41 -07003033 } else if (argOne->IsArray()) {
dsinclair759de382016-06-07 14:10:16 -07003034#ifndef NDEBUG
3035 std::unique_ptr<CFXJSE_Value> lengthValue(new CFXJSE_Value(pIsolate));
dsinclairf27aeec2016-06-07 19:36:18 -07003036 argOne->GetObjectProperty("length", lengthValue.get());
3037 ASSERT(lengthValue->ToInteger() >= 3);
dsinclair759de382016-06-07 14:10:16 -07003038#endif
3039
3040 std::unique_ptr<CFXJSE_Value> propertyValue(new CFXJSE_Value(pIsolate));
3041 std::unique_ptr<CFXJSE_Value> jsObjectValue(new CFXJSE_Value(pIsolate));
dsinclairf27aeec2016-06-07 19:36:18 -07003042 argOne->GetObjectPropertyByIdx(1, propertyValue.get());
3043 argOne->GetObjectPropertyByIdx(2, jsObjectValue.get());
dsinclair769b1372016-06-08 13:12:41 -07003044 if (!propertyValue->IsNull() || jsObjectValue->IsNull()) {
dsinclair759de382016-06-07 14:10:16 -07003045 for (int32_t i = 0; i < 3; i++)
3046 delete rgValues[i];
3047
3048 pContext->ThrowException(XFA_IDS_ARGUMENT_MISMATCH);
3049 return;
3050 }
3051
dsinclairf27aeec2016-06-07 19:36:18 -07003052 rgValues[2]->Assign(jsObjectValue.get());
dsinclair769b1372016-06-08 13:12:41 -07003053 } else if (argOne->IsObject()) {
dsinclairf27aeec2016-06-07 19:36:18 -07003054 rgValues[2]->Assign(argOne.get());
dsinclair759de382016-06-07 14:10:16 -07003055 }
3056
dsinclairf27aeec2016-06-07 19:36:18 -07003057 rgValues[0]->SetInteger(intVal);
3058 rgValues[1]->SetNull();
3059 args.GetReturnValue()->SetArray(3, rgValues);
dsinclair759de382016-06-07 14:10:16 -07003060
3061 for (int32_t i = 0; i < 3; i++)
3062 delete rgValues[i];
Dan Sinclair1770c022016-03-14 14:14:16 -04003063}
dsinclair48d91dd2016-05-31 11:54:01 -07003064
3065// static
dsinclair12a6b0c2016-05-26 11:14:08 -07003066void CXFA_FM2JSContext::UnitType(CFXJSE_Value* pThis,
Dan Sinclair1770c022016-03-14 14:14:16 -04003067 const CFX_ByteStringC& szFuncName,
3068 CFXJSE_Arguments& args) {
dsinclair759de382016-06-07 14:10:16 -07003069 if (args.GetLength() != 1) {
dsinclair8f3074b2016-06-02 17:45:25 -07003070 ToJSContext(pThis, nullptr)
3071 ->ThrowException(XFA_IDS_INCORRECT_NUMBER_OF_METHOD, L"UnitType");
dsinclair759de382016-06-07 14:10:16 -07003072 return;
3073 }
3074
3075 std::unique_ptr<CFXJSE_Value> unitspanValue = GetSimpleValue(pThis, args, 0);
dsinclair769b1372016-06-08 13:12:41 -07003076 if (unitspanValue->IsNull()) {
dsinclairf27aeec2016-06-07 19:36:18 -07003077 args.GetReturnValue()->SetNull();
dsinclair759de382016-06-07 14:10:16 -07003078 return;
3079 }
3080
3081 CFX_ByteString unitspanString;
3082 ValueToUTF8String(unitspanValue.get(), unitspanString);
3083 if (unitspanString.IsEmpty()) {
dsinclairf27aeec2016-06-07 19:36:18 -07003084 args.GetReturnValue()->SetString("in");
dsinclair759de382016-06-07 14:10:16 -07003085 return;
3086 }
3087
3088 enum XFA_FM2JS_VALUETYPE_ParserStatus {
3089 VALUETYPE_START,
3090 VALUETYPE_HAVEINVALIDCHAR,
3091 VALUETYPE_HAVEDIGIT,
3092 VALUETYPE_HAVEDIGITWHITE,
3093 VALUETYPE_ISCM,
3094 VALUETYPE_ISMM,
3095 VALUETYPE_ISPT,
3096 VALUETYPE_ISMP,
3097 VALUETYPE_ISIN,
3098 };
3099 unitspanString.MakeLower();
3100 CFX_WideString wsTypeString =
3101 CFX_WideString::FromUTF8(unitspanString.AsStringC());
3102 const FX_WCHAR* pData = wsTypeString.c_str();
3103 int32_t u = 0;
3104 int32_t uLen = wsTypeString.GetLength();
3105 while (IsWhitespace(pData[u]))
3106 u++;
3107
3108 XFA_FM2JS_VALUETYPE_ParserStatus eParserStatus = VALUETYPE_START;
3109 FX_WCHAR typeChar;
3110 // TODO(dsinclair): Cleanup this parser, figure out what the various checks
3111 // are for.
3112 while (u < uLen) {
3113 typeChar = pData[u];
3114 if (IsWhitespace(typeChar)) {
3115 if (eParserStatus != VALUETYPE_HAVEDIGIT &&
3116 eParserStatus != VALUETYPE_HAVEDIGITWHITE) {
3117 eParserStatus = VALUETYPE_ISIN;
3118 break;
3119 }
3120 eParserStatus = VALUETYPE_HAVEDIGITWHITE;
3121 } else if ((typeChar >= '0' && typeChar <= '9') || typeChar == '-' ||
3122 typeChar == '.') {
3123 if (eParserStatus == VALUETYPE_HAVEDIGITWHITE) {
3124 eParserStatus = VALUETYPE_ISIN;
3125 break;
3126 }
3127 eParserStatus = VALUETYPE_HAVEDIGIT;
3128 } else if ((typeChar == 'c' || typeChar == 'p') && (u + 1 < uLen)) {
3129 FX_WCHAR nextChar = pData[u + 1];
3130 if ((eParserStatus == VALUETYPE_START ||
3131 eParserStatus == VALUETYPE_HAVEDIGIT ||
3132 eParserStatus == VALUETYPE_HAVEDIGITWHITE) &&
3133 (nextChar > '9' || nextChar < '0') && nextChar != '.' &&
3134 nextChar != '-') {
3135 eParserStatus = (typeChar == 'c') ? VALUETYPE_ISCM : VALUETYPE_ISPT;
3136 break;
3137 }
3138 eParserStatus = VALUETYPE_HAVEINVALIDCHAR;
3139 } else if (typeChar == 'm' && (u + 1 < uLen)) {
3140 FX_WCHAR nextChar = pData[u + 1];
3141 if ((eParserStatus == VALUETYPE_START ||
3142 eParserStatus == VALUETYPE_HAVEDIGIT ||
3143 eParserStatus == VALUETYPE_HAVEDIGITWHITE) &&
3144 (nextChar > '9' || nextChar < '0') && nextChar != '.' &&
3145 nextChar != '-') {
3146 eParserStatus = VALUETYPE_ISMM;
3147 if (nextChar == 'p' || ((u + 5 < uLen) && pData[u + 1] == 'i' &&
3148 pData[u + 2] == 'l' && pData[u + 3] == 'l' &&
3149 pData[u + 4] == 'i' && pData[u + 5] == 'p')) {
3150 eParserStatus = VALUETYPE_ISMP;
3151 }
3152 break;
3153 }
3154 } else {
3155 eParserStatus = VALUETYPE_HAVEINVALIDCHAR;
3156 }
3157 u++;
3158 }
3159 switch (eParserStatus) {
3160 case VALUETYPE_ISCM:
dsinclairf27aeec2016-06-07 19:36:18 -07003161 args.GetReturnValue()->SetString("cm");
dsinclair759de382016-06-07 14:10:16 -07003162 break;
3163 case VALUETYPE_ISMM:
dsinclairf27aeec2016-06-07 19:36:18 -07003164 args.GetReturnValue()->SetString("mm");
dsinclair759de382016-06-07 14:10:16 -07003165 break;
3166 case VALUETYPE_ISPT:
dsinclairf27aeec2016-06-07 19:36:18 -07003167 args.GetReturnValue()->SetString("pt");
dsinclair759de382016-06-07 14:10:16 -07003168 break;
3169 case VALUETYPE_ISMP:
dsinclairf27aeec2016-06-07 19:36:18 -07003170 args.GetReturnValue()->SetString("mp");
dsinclair759de382016-06-07 14:10:16 -07003171 break;
3172 default:
dsinclairf27aeec2016-06-07 19:36:18 -07003173 args.GetReturnValue()->SetString("in");
dsinclair759de382016-06-07 14:10:16 -07003174 break;
Dan Sinclair1770c022016-03-14 14:14:16 -04003175 }
3176}
dsinclair48d91dd2016-05-31 11:54:01 -07003177
3178// static
dsinclair12a6b0c2016-05-26 11:14:08 -07003179void CXFA_FM2JSContext::UnitValue(CFXJSE_Value* pThis,
Dan Sinclair1770c022016-03-14 14:14:16 -04003180 const CFX_ByteStringC& szFuncName,
3181 CFXJSE_Arguments& args) {
3182 int32_t argc = args.GetLength();
dsinclair759de382016-06-07 14:10:16 -07003183 if (argc < 1 || argc > 2) {
dsinclair8f3074b2016-06-02 17:45:25 -07003184 ToJSContext(pThis, nullptr)
3185 ->ThrowException(XFA_IDS_INCORRECT_NUMBER_OF_METHOD, L"UnitValue");
dsinclair759de382016-06-07 14:10:16 -07003186 return;
Dan Sinclair1770c022016-03-14 14:14:16 -04003187 }
dsinclair759de382016-06-07 14:10:16 -07003188
3189 std::unique_ptr<CFXJSE_Value> unitspanValue = GetSimpleValue(pThis, args, 0);
dsinclair769b1372016-06-08 13:12:41 -07003190 if (unitspanValue->IsNull()) {
dsinclairf27aeec2016-06-07 19:36:18 -07003191 args.GetReturnValue()->SetNull();
dsinclair759de382016-06-07 14:10:16 -07003192 return;
3193 }
3194
3195 CFX_ByteString unitspanString;
3196 ValueToUTF8String(unitspanValue.get(), unitspanString);
3197 const FX_CHAR* pData = unitspanString.c_str();
3198 if (!pData) {
dsinclairf27aeec2016-06-07 19:36:18 -07003199 args.GetReturnValue()->SetInteger(0);
dsinclair759de382016-06-07 14:10:16 -07003200 return;
3201 }
3202
3203 int32_t u = 0;
3204 while (IsWhitespace(pData[u]))
3205 ++u;
3206
3207 while (u < unitspanString.GetLength()) {
3208 if ((pData[u] > '9' || pData[u] < '0') && pData[u] != '.' &&
3209 pData[u] != '-') {
3210 break;
3211 }
3212 ++u;
3213 }
3214
3215 FX_CHAR* pTemp = nullptr;
3216 FX_DOUBLE dFirstNumber = strtod(pData, &pTemp);
3217 while (IsWhitespace(pData[u]))
3218 ++u;
3219
3220 int32_t uLen = unitspanString.GetLength();
3221 CFX_ByteString strFirstUnit;
3222 while (u < uLen) {
3223 if (pData[u] == ' ')
3224 break;
3225
3226 strFirstUnit += pData[u];
3227 ++u;
3228 }
3229 strFirstUnit.MakeLower();
3230
3231 CFX_ByteString strUnit;
3232 if (argc > 1) {
3233 std::unique_ptr<CFXJSE_Value> unitValue = GetSimpleValue(pThis, args, 1);
3234 CFX_ByteString unitTempString;
3235 ValueToUTF8String(unitValue.get(), unitTempString);
3236 const FX_CHAR* pChar = unitTempString.c_str();
3237 int32_t uVal = 0;
3238 while (IsWhitespace(pChar[uVal]))
3239 ++uVal;
3240
3241 while (uVal < unitTempString.GetLength()) {
3242 if ((pChar[uVal] > '9' || pChar[uVal] < '0') && pChar[uVal] != '.') {
3243 break;
3244 }
3245 ++uVal;
3246 }
3247 while (IsWhitespace(pChar[uVal]))
3248 ++uVal;
3249
3250 int32_t uValLen = unitTempString.GetLength();
3251 while (uVal < uValLen) {
3252 if (pChar[uVal] == ' ')
3253 break;
3254
3255 strUnit += pChar[uVal];
3256 ++uVal;
3257 }
3258 strUnit.MakeLower();
3259 } else {
3260 strUnit = strFirstUnit;
3261 }
3262
3263 FX_DOUBLE dResult = 0;
3264 if (strFirstUnit == "in" || strFirstUnit == "inches") {
3265 if (strUnit == "mm" || strUnit == "millimeters")
3266 dResult = dFirstNumber * 25.4;
3267 else if (strUnit == "cm" || strUnit == "centimeters")
3268 dResult = dFirstNumber * 2.54;
3269 else if (strUnit == "pt" || strUnit == "points")
3270 dResult = dFirstNumber / 72;
3271 else if (strUnit == "mp" || strUnit == "millipoints")
3272 dResult = dFirstNumber / 72000;
3273 else
3274 dResult = dFirstNumber;
3275 } else if (strFirstUnit == "mm" || strFirstUnit == "millimeters") {
3276 if (strUnit == "mm" || strUnit == "millimeters")
3277 dResult = dFirstNumber;
3278 else if (strUnit == "cm" || strUnit == "centimeters")
3279 dResult = dFirstNumber / 10;
3280 else if (strUnit == "pt" || strUnit == "points")
3281 dResult = dFirstNumber / 25.4 / 72;
3282 else if (strUnit == "mp" || strUnit == "millipoints")
3283 dResult = dFirstNumber / 25.4 / 72000;
3284 else
3285 dResult = dFirstNumber / 25.4;
3286 } else if (strFirstUnit == "cm" || strFirstUnit == "centimeters") {
3287 if (strUnit == "mm" || strUnit == "millimeters")
3288 dResult = dFirstNumber * 10;
3289 else if (strUnit == "cm" || strUnit == "centimeters")
3290 dResult = dFirstNumber;
3291 else if (strUnit == "pt" || strUnit == "points")
3292 dResult = dFirstNumber / 2.54 / 72;
3293 else if (strUnit == "mp" || strUnit == "millipoints")
3294 dResult = dFirstNumber / 2.54 / 72000;
3295 else
3296 dResult = dFirstNumber / 2.54;
3297 } else if (strFirstUnit == "pt" || strFirstUnit == "points") {
3298 if (strUnit == "mm" || strUnit == "millimeters")
3299 dResult = dFirstNumber / 72 * 25.4;
3300 else if (strUnit == "cm" || strUnit == "centimeters")
3301 dResult = dFirstNumber / 72 * 2.54;
3302 else if (strUnit == "pt" || strUnit == "points")
3303 dResult = dFirstNumber;
3304 else if (strUnit == "mp" || strUnit == "millipoints")
3305 dResult = dFirstNumber * 1000;
3306 else
3307 dResult = dFirstNumber / 72;
3308 } else if (strFirstUnit == "mp" || strFirstUnit == "millipoints") {
3309 if (strUnit == "mm" || strUnit == "millimeters")
3310 dResult = dFirstNumber / 72000 * 25.4;
3311 else if (strUnit == "cm" || strUnit == "centimeters")
3312 dResult = dFirstNumber / 72000 * 2.54;
3313 else if (strUnit == "pt" || strUnit == "points")
3314 dResult = dFirstNumber / 1000;
3315 else if (strUnit == "mp" || strUnit == "millipoints")
3316 dResult = dFirstNumber;
3317 else
3318 dResult = dFirstNumber / 72000;
3319 }
dsinclairf27aeec2016-06-07 19:36:18 -07003320 args.GetReturnValue()->SetDouble(dResult);
Dan Sinclair1770c022016-03-14 14:14:16 -04003321}
dsinclair48d91dd2016-05-31 11:54:01 -07003322
3323// static
dsinclair12a6b0c2016-05-26 11:14:08 -07003324void CXFA_FM2JSContext::At(CFXJSE_Value* pThis,
Dan Sinclair1770c022016-03-14 14:14:16 -04003325 const CFX_ByteStringC& szFuncName,
3326 CFXJSE_Arguments& args) {
dsinclair759de382016-06-07 14:10:16 -07003327 if (args.GetLength() != 2) {
dsinclair8f3074b2016-06-02 17:45:25 -07003328 ToJSContext(pThis, nullptr)
3329 ->ThrowException(XFA_IDS_INCORRECT_NUMBER_OF_METHOD, L"At");
dsinclair759de382016-06-07 14:10:16 -07003330 return;
Dan Sinclair1770c022016-03-14 14:14:16 -04003331 }
dsinclair759de382016-06-07 14:10:16 -07003332
3333 std::unique_ptr<CFXJSE_Value> argOne = GetSimpleValue(pThis, args, 0);
3334 std::unique_ptr<CFXJSE_Value> argTwo = GetSimpleValue(pThis, args, 1);
3335 if (ValueIsNull(pThis, argOne.get()) || ValueIsNull(pThis, argTwo.get())) {
dsinclairf27aeec2016-06-07 19:36:18 -07003336 args.GetReturnValue()->SetNull();
dsinclair759de382016-06-07 14:10:16 -07003337 return;
3338 }
3339
3340 CFX_ByteString stringTwo;
3341 ValueToUTF8String(argTwo.get(), stringTwo);
3342 if (stringTwo.IsEmpty()) {
dsinclairf27aeec2016-06-07 19:36:18 -07003343 args.GetReturnValue()->SetInteger(1);
dsinclair759de382016-06-07 14:10:16 -07003344 return;
3345 }
3346
3347 CFX_ByteString stringOne;
3348 ValueToUTF8String(argOne.get(), stringOne);
3349 FX_STRSIZE iPosition = stringOne.Find(stringTwo.AsStringC());
dsinclairf27aeec2016-06-07 19:36:18 -07003350 args.GetReturnValue()->SetInteger(iPosition + 1);
Dan Sinclair1770c022016-03-14 14:14:16 -04003351}
dsinclair48d91dd2016-05-31 11:54:01 -07003352
3353// static
dsinclair12a6b0c2016-05-26 11:14:08 -07003354void CXFA_FM2JSContext::Concat(CFXJSE_Value* pThis,
Dan Sinclair1770c022016-03-14 14:14:16 -04003355 const CFX_ByteStringC& szFuncName,
3356 CFXJSE_Arguments& args) {
Dan Sinclair1770c022016-03-14 14:14:16 -04003357 int32_t argc = args.GetLength();
dsinclair759de382016-06-07 14:10:16 -07003358 if (argc < 1) {
dsinclair8f3074b2016-06-02 17:45:25 -07003359 ToJSContext(pThis, nullptr)
3360 ->ThrowException(XFA_IDS_INCORRECT_NUMBER_OF_METHOD, L"Concat");
dsinclair759de382016-06-07 14:10:16 -07003361 return;
Dan Sinclair1770c022016-03-14 14:14:16 -04003362 }
dsinclair759de382016-06-07 14:10:16 -07003363
3364 CFX_ByteString resultString;
3365 FX_BOOL bAllNull = TRUE;
3366 for (int32_t i = 0; i < argc; i++) {
3367 std::unique_ptr<CFXJSE_Value> value = GetSimpleValue(pThis, args, i);
3368 if (ValueIsNull(pThis, value.get()))
3369 continue;
3370
3371 bAllNull = FALSE;
3372
3373 CFX_ByteString valueStr;
3374 ValueToUTF8String(value.get(), valueStr);
3375 resultString += valueStr;
3376 }
3377
3378 if (bAllNull) {
dsinclairf27aeec2016-06-07 19:36:18 -07003379 args.GetReturnValue()->SetNull();
dsinclair759de382016-06-07 14:10:16 -07003380 return;
3381 }
3382
dsinclairf27aeec2016-06-07 19:36:18 -07003383 args.GetReturnValue()->SetString(resultString.AsStringC());
Dan Sinclair1770c022016-03-14 14:14:16 -04003384}
dsinclair48d91dd2016-05-31 11:54:01 -07003385
3386// static
dsinclair12a6b0c2016-05-26 11:14:08 -07003387void CXFA_FM2JSContext::Decode(CFXJSE_Value* pThis,
Dan Sinclair1770c022016-03-14 14:14:16 -04003388 const CFX_ByteStringC& szFuncName,
3389 CFXJSE_Arguments& args) {
Dan Sinclair1770c022016-03-14 14:14:16 -04003390 int32_t argc = args.GetLength();
dsinclair759de382016-06-07 14:10:16 -07003391 if (argc < 1 || argc > 2) {
3392 ToJSContext(pThis, nullptr)
3393 ->ThrowException(XFA_IDS_INCORRECT_NUMBER_OF_METHOD, L"Decode");
3394 return;
3395 }
3396
Dan Sinclair1770c022016-03-14 14:14:16 -04003397 if (argc == 1) {
dsinclair86fad992016-05-31 11:34:04 -07003398 std::unique_ptr<CFXJSE_Value> argOne = GetSimpleValue(pThis, args, 0);
3399 if (ValueIsNull(pThis, argOne.get())) {
dsinclairf27aeec2016-06-07 19:36:18 -07003400 args.GetReturnValue()->SetNull();
dsinclair759de382016-06-07 14:10:16 -07003401 return;
Dan Sinclair1770c022016-03-14 14:14:16 -04003402 }
dsinclair759de382016-06-07 14:10:16 -07003403
3404 CFX_ByteString toDecodeString;
3405 ValueToUTF8String(argOne.get(), toDecodeString);
3406 CFX_ByteTextBuf resultBuf;
3407 DecodeURL(toDecodeString.AsStringC(), resultBuf);
dsinclairf27aeec2016-06-07 19:36:18 -07003408 args.GetReturnValue()->SetString(resultBuf.AsStringC());
dsinclair759de382016-06-07 14:10:16 -07003409 return;
Dan Sinclair1770c022016-03-14 14:14:16 -04003410 }
dsinclair759de382016-06-07 14:10:16 -07003411
3412 std::unique_ptr<CFXJSE_Value> argOne = GetSimpleValue(pThis, args, 0);
3413 std::unique_ptr<CFXJSE_Value> argTwo = GetSimpleValue(pThis, args, 1);
3414 if (ValueIsNull(pThis, argOne.get()) || ValueIsNull(pThis, argTwo.get())) {
dsinclairf27aeec2016-06-07 19:36:18 -07003415 args.GetReturnValue()->SetNull();
dsinclair759de382016-06-07 14:10:16 -07003416 return;
3417 }
3418
3419 CFX_ByteString toDecodeString;
3420 ValueToUTF8String(argOne.get(), toDecodeString);
3421
3422 CFX_ByteString identifyString;
3423 ValueToUTF8String(argTwo.get(), identifyString);
3424
3425 CFX_ByteTextBuf resultBuf;
3426 if (identifyString.EqualNoCase("html"))
3427 DecodeHTML(toDecodeString.AsStringC(), resultBuf);
3428 else if (identifyString.EqualNoCase("xml"))
3429 DecodeXML(toDecodeString.AsStringC(), resultBuf);
3430 else
3431 DecodeURL(toDecodeString.AsStringC(), resultBuf);
3432
dsinclairf27aeec2016-06-07 19:36:18 -07003433 args.GetReturnValue()->SetString(resultBuf.AsStringC());
Dan Sinclair1770c022016-03-14 14:14:16 -04003434}
dsinclair48d91dd2016-05-31 11:54:01 -07003435
3436// static
Dan Sinclair1770c022016-03-14 14:14:16 -04003437void CXFA_FM2JSContext::DecodeURL(const CFX_ByteStringC& szURLString,
3438 CFX_ByteTextBuf& szResultString) {
tsepez6fe7d212016-04-06 10:51:14 -07003439 CFX_WideString wsURLString = CFX_WideString::FromUTF8(szURLString);
tsepezbd9748d2016-04-13 21:40:19 -07003440 const FX_WCHAR* pData = wsURLString.c_str();
Dan Sinclair1770c022016-03-14 14:14:16 -04003441 int32_t i = 0;
Dan Sinclair1770c022016-03-14 14:14:16 -04003442 CFX_WideTextBuf wsResultBuf;
dsinclair759de382016-06-07 14:10:16 -07003443 while (i < wsURLString.GetLength()) {
3444 FX_WCHAR ch = pData[i];
3445 if ('%' != ch) {
Dan Sinclair1770c022016-03-14 14:14:16 -04003446 wsResultBuf.AppendChar(ch);
dsinclair759de382016-06-07 14:10:16 -07003447 ++i;
3448 continue;
Dan Sinclair1770c022016-03-14 14:14:16 -04003449 }
dsinclair759de382016-06-07 14:10:16 -07003450
3451 FX_WCHAR chTemp = 0;
3452 int32_t iCount = 0;
3453 while (iCount < 2) {
3454 ++i;
3455 ch = pData[i];
3456 if (ch <= '9' && ch >= '0') {
3457 // TODO(dsinclair): Premultiply and add rather then scale.
3458 chTemp += (ch - '0') * (!iCount ? 16 : 1);
3459 } else if (ch <= 'F' && ch >= 'A') {
3460 chTemp += (ch - 'A' + 10) * (!iCount ? 16 : 1);
3461 } else if (ch <= 'f' && ch >= 'a') {
3462 chTemp += (ch - 'a' + 10) * (!iCount ? 16 : 1);
3463 } else {
3464 wsResultBuf.Clear();
3465 return;
3466 }
3467 ++iCount;
3468 }
3469 wsResultBuf.AppendChar(chTemp);
Dan Sinclair1770c022016-03-14 14:14:16 -04003470 ++i;
3471 }
3472 wsResultBuf.AppendChar(0);
dsinclair759de382016-06-07 14:10:16 -07003473
Dan Sinclair1770c022016-03-14 14:14:16 -04003474 szResultString.Clear();
3475 szResultString << FX_UTF8Encode(wsResultBuf.GetBuffer(),
tsepez28f97ff2016-04-04 16:41:35 -07003476 wsResultBuf.GetLength())
tsepez4c3debb2016-04-08 12:20:38 -07003477 .AsStringC();
Dan Sinclair1770c022016-03-14 14:14:16 -04003478}
dsinclair48d91dd2016-05-31 11:54:01 -07003479
3480// static
Dan Sinclair1770c022016-03-14 14:14:16 -04003481void CXFA_FM2JSContext::DecodeHTML(const CFX_ByteStringC& szHTMLString,
3482 CFX_ByteTextBuf& szResultString) {
tsepez6fe7d212016-04-06 10:51:14 -07003483 CFX_WideString wsHTMLString = CFX_WideString::FromUTF8(szHTMLString);
Dan Sinclair1770c022016-03-14 14:14:16 -04003484 FX_WCHAR strString[9];
3485 int32_t iStrIndex = 0;
3486 int32_t iLen = wsHTMLString.GetLength();
3487 int32_t i = 0;
3488 int32_t iCode = 0;
tsepezbd9748d2016-04-13 21:40:19 -07003489 const FX_WCHAR* pData = wsHTMLString.c_str();
Dan Sinclair1770c022016-03-14 14:14:16 -04003490 CFX_WideTextBuf wsResultBuf;
3491 while (i < iLen) {
dsinclair759de382016-06-07 14:10:16 -07003492 FX_WCHAR ch = pData[i];
3493 if (ch != '&') {
Dan Sinclair1770c022016-03-14 14:14:16 -04003494 wsResultBuf.AppendChar(ch);
3495 ++i;
3496 continue;
3497 }
dsinclair759de382016-06-07 14:10:16 -07003498
3499 ++i;
3500 ch = pData[i];
3501 if (ch == '#') {
3502 ++i;
3503 ch = pData[i];
3504 if (ch != 'x' && ch != 'X') {
3505 wsResultBuf.Clear();
3506 return;
3507 }
3508
3509 ++i;
3510 ch = pData[i];
3511 if ((ch >= '0' && ch <= '9') || (ch <= 'f' && ch >= 'a') ||
3512 (ch <= 'F' && ch >= 'A')) {
3513 while (ch != ';' && i < iLen) {
3514 if (ch >= '0' && ch <= '9') {
3515 iCode += ch - '0';
3516 } else if (ch <= 'f' && ch >= 'a') {
3517 iCode += ch - 'a' + 10;
3518 } else if (ch <= 'F' && ch >= 'A') {
3519 iCode += ch - 'A' + 10;
3520 } else {
3521 wsResultBuf.Clear();
3522 return;
3523 }
3524 ++i;
3525 // TODO(dsinclair): Postmultiply seems wrong, start at zero
3526 // and pre-multiply then can remove the post divide.
3527 iCode *= 16;
3528 ch = pData[i];
3529 }
3530 iCode /= 16;
3531 }
3532 } else {
3533 while (ch != ';' && i < iLen) {
3534 strString[iStrIndex++] = ch;
3535 ++i;
3536 ch = pData[i];
3537 }
3538 strString[iStrIndex] = 0;
3539 }
Dan Sinclair1770c022016-03-14 14:14:16 -04003540 uint32_t iData = 0;
3541 if (HTMLSTR2Code(strString, iData)) {
3542 wsResultBuf.AppendChar((FX_WCHAR)iData);
3543 } else {
3544 wsResultBuf.AppendChar(iCode);
3545 }
3546 iStrIndex = 0;
3547 strString[iStrIndex] = 0;
3548 ++i;
3549 }
3550 wsResultBuf.AppendChar(0);
dsinclair759de382016-06-07 14:10:16 -07003551
Dan Sinclair1770c022016-03-14 14:14:16 -04003552 szResultString.Clear();
3553 szResultString << FX_UTF8Encode(wsResultBuf.GetBuffer(),
tsepez28f97ff2016-04-04 16:41:35 -07003554 wsResultBuf.GetLength())
tsepez4c3debb2016-04-08 12:20:38 -07003555 .AsStringC();
Dan Sinclair1770c022016-03-14 14:14:16 -04003556}
dsinclair48d91dd2016-05-31 11:54:01 -07003557
3558// static
Dan Sinclair1770c022016-03-14 14:14:16 -04003559void CXFA_FM2JSContext::DecodeXML(const CFX_ByteStringC& szXMLString,
3560 CFX_ByteTextBuf& szResultString) {
tsepez6fe7d212016-04-06 10:51:14 -07003561 CFX_WideString wsXMLString = CFX_WideString::FromUTF8(szXMLString);
Dan Sinclair1770c022016-03-14 14:14:16 -04003562 FX_WCHAR strString[9];
3563 int32_t iStrIndex = 0;
3564 int32_t iLen = wsXMLString.GetLength();
3565 int32_t i = 0;
3566 int32_t iCode = 0;
3567 FX_WCHAR ch = 0;
tsepezbd9748d2016-04-13 21:40:19 -07003568 const FX_WCHAR* pData = wsXMLString.c_str();
Dan Sinclair1770c022016-03-14 14:14:16 -04003569 CFX_WideTextBuf wsXMLBuf;
3570 while (i < iLen) {
dsinclair2b6d64e2016-06-06 11:39:42 -07003571 ch = pData[i];
dsinclair759de382016-06-07 14:10:16 -07003572 if (ch != '&') {
Dan Sinclair1770c022016-03-14 14:14:16 -04003573 wsXMLBuf.AppendChar(ch);
3574 ++i;
3575 continue;
3576 }
dsinclair759de382016-06-07 14:10:16 -07003577
3578 // TODO(dsinclair): This is very similar to DecodeHTML, can they be
3579 // combined?
3580 ++i;
3581 ch = pData[i];
3582 if (ch == '#') {
3583 ++i;
3584 ch = pData[i];
3585 if (ch != 'x' && ch != 'X') {
3586 wsXMLBuf.Clear();
3587 return;
3588 }
3589
3590 ++i;
3591 ch = pData[i];
3592 if ((ch >= '0' && ch <= '9') || (ch <= 'f' && ch >= 'a') ||
3593 (ch <= 'F' && ch >= 'A')) {
3594 while (ch != ';') {
3595 if (ch >= '0' && ch <= '9') {
3596 iCode += ch - '0';
3597 } else if (ch <= 'f' && ch >= 'a') {
3598 iCode += ch - 'a' + 10;
3599 } else if (ch <= 'F' && ch >= 'A') {
3600 iCode += ch - 'A' + 10;
3601 } else {
3602 wsXMLBuf.Clear();
3603 return;
3604 }
3605 ++i;
3606 iCode *= 16;
3607 ch = pData[i];
3608 }
3609 iCode /= 16;
3610 }
3611 } else {
3612 while (ch != ';' && i < iLen) {
3613 strString[iStrIndex++] = ch;
3614 ++i;
3615 ch = pData[i];
3616 }
3617 strString[iStrIndex] = 0;
3618 }
3619
Dan Sinclair1770c022016-03-14 14:14:16 -04003620 const FX_WCHAR* const strName[] = {L"quot", L"amp", L"apos", L"lt", L"gt"};
3621 int32_t iIndex = 0;
3622 while (iIndex < 5) {
3623 if (FXSYS_memcmp(strString, strName[iIndex],
3624 FXSYS_wcslen(strName[iIndex])) == 0) {
3625 break;
3626 }
3627 ++iIndex;
3628 }
3629 switch (iIndex) {
3630 case 0:
3631 wsXMLBuf.AppendChar('"');
3632 break;
3633 case 1:
3634 wsXMLBuf.AppendChar('&');
3635 break;
3636 case 2:
3637 wsXMLBuf.AppendChar('\'');
3638 break;
3639 case 3:
3640 wsXMLBuf.AppendChar('<');
3641 break;
3642 case 4:
3643 wsXMLBuf.AppendChar('>');
3644 break;
3645 default:
3646 wsXMLBuf.AppendChar(iCode);
3647 break;
3648 }
3649 iStrIndex = 0;
3650 strString[iStrIndex] = 0;
3651 ++i;
3652 iCode = 0;
3653 }
3654 wsXMLBuf.AppendChar(0);
dsinclair759de382016-06-07 14:10:16 -07003655
Dan Sinclair1770c022016-03-14 14:14:16 -04003656 szResultString.Clear();
tsepez28f97ff2016-04-04 16:41:35 -07003657 szResultString << FX_UTF8Encode(wsXMLBuf.GetBuffer(), wsXMLBuf.GetLength())
tsepez4c3debb2016-04-08 12:20:38 -07003658 .AsStringC();
Dan Sinclair1770c022016-03-14 14:14:16 -04003659}
dsinclair48d91dd2016-05-31 11:54:01 -07003660
3661// static
dsinclair12a6b0c2016-05-26 11:14:08 -07003662void CXFA_FM2JSContext::Encode(CFXJSE_Value* pThis,
Dan Sinclair1770c022016-03-14 14:14:16 -04003663 const CFX_ByteStringC& szFuncName,
3664 CFXJSE_Arguments& args) {
Dan Sinclair1770c022016-03-14 14:14:16 -04003665 int32_t argc = args.GetLength();
dsinclaircf7f3222016-06-08 20:34:02 -07003666 if (argc < 1 || argc > 2) {
3667 ToJSContext(pThis, nullptr)
3668 ->ThrowException(XFA_IDS_INCORRECT_NUMBER_OF_METHOD, L"Encode");
3669 return;
3670 }
3671
Dan Sinclair1770c022016-03-14 14:14:16 -04003672 if (argc == 1) {
dsinclair86fad992016-05-31 11:34:04 -07003673 std::unique_ptr<CFXJSE_Value> argOne = GetSimpleValue(pThis, args, 0);
3674 if (ValueIsNull(pThis, argOne.get())) {
dsinclairf27aeec2016-06-07 19:36:18 -07003675 args.GetReturnValue()->SetNull();
dsinclaircf7f3222016-06-08 20:34:02 -07003676 return;
Dan Sinclair1770c022016-03-14 14:14:16 -04003677 }
dsinclaircf7f3222016-06-08 20:34:02 -07003678
3679 CFX_ByteString toEncodeString;
3680 ValueToUTF8String(argOne.get(), toEncodeString);
3681 CFX_ByteTextBuf resultBuf;
3682 EncodeURL(toEncodeString.AsStringC(), resultBuf);
3683 args.GetReturnValue()->SetString(resultBuf.AsStringC());
3684 return;
Dan Sinclair1770c022016-03-14 14:14:16 -04003685 }
dsinclaircf7f3222016-06-08 20:34:02 -07003686
3687 std::unique_ptr<CFXJSE_Value> argOne = GetSimpleValue(pThis, args, 0);
3688 std::unique_ptr<CFXJSE_Value> argTwo = GetSimpleValue(pThis, args, 1);
3689 if (ValueIsNull(pThis, argOne.get()) || ValueIsNull(pThis, argTwo.get())) {
3690 args.GetReturnValue()->SetNull();
3691 return;
3692 }
3693
3694 CFX_ByteString toEncodeString;
3695 ValueToUTF8String(argOne.get(), toEncodeString);
3696 CFX_ByteString identifyString;
3697 ValueToUTF8String(argTwo.get(), identifyString);
3698 CFX_ByteTextBuf resultBuf;
3699 if (identifyString.EqualNoCase("html"))
3700 EncodeHTML(toEncodeString.AsStringC(), resultBuf);
3701 else if (identifyString.EqualNoCase("xml"))
3702 EncodeXML(toEncodeString.AsStringC(), resultBuf);
3703 else
3704 EncodeURL(toEncodeString.AsStringC(), resultBuf);
3705
3706 args.GetReturnValue()->SetString(resultBuf.AsStringC());
Dan Sinclair1770c022016-03-14 14:14:16 -04003707}
dsinclair48d91dd2016-05-31 11:54:01 -07003708
3709// static
Dan Sinclair1770c022016-03-14 14:14:16 -04003710void CXFA_FM2JSContext::EncodeURL(const CFX_ByteStringC& szURLString,
3711 CFX_ByteTextBuf& szResultBuf) {
tsepez6fe7d212016-04-06 10:51:14 -07003712 CFX_WideString wsURLString = CFX_WideString::FromUTF8(szURLString);
Dan Sinclair1770c022016-03-14 14:14:16 -04003713 CFX_WideTextBuf wsResultBuf;
Dan Sinclair1770c022016-03-14 14:14:16 -04003714 FX_WCHAR strEncode[4];
3715 strEncode[0] = '%';
3716 strEncode[3] = 0;
3717 FX_WCHAR strUnsafe[] = {' ', '<', '>', '"', '#', '%', '{', '}',
3718 '|', '\\', '^', '~', '[', ']', '`'};
3719 FX_WCHAR strReserved[] = {';', '/', '?', ':', '@', '=', '&'};
3720 FX_WCHAR strSpecial[] = {'$', '-', '+', '!', '*', '\'', '(', ')', ','};
3721 const FX_WCHAR* strCode = L"0123456789abcdef";
dsinclaircf7f3222016-06-08 20:34:02 -07003722 for (int32_t u = 0; u < wsURLString.GetLength(); ++u) {
3723 FX_WCHAR ch = wsURLString.GetAt(u);
Dan Sinclair1770c022016-03-14 14:14:16 -04003724 int32_t i = 0;
dsinclaircf7f3222016-06-08 20:34:02 -07003725 int32_t iCount = FX_ArraySize(strUnsafe);
Dan Sinclair1770c022016-03-14 14:14:16 -04003726 while (i < iCount) {
3727 if (ch == strUnsafe[i]) {
3728 int32_t iIndex = ch / 16;
3729 strEncode[1] = strCode[iIndex];
3730 strEncode[2] = strCode[ch - iIndex * 16];
3731 wsResultBuf << FX_WSTRC(strEncode);
3732 break;
3733 }
3734 ++i;
3735 }
dsinclaircf7f3222016-06-08 20:34:02 -07003736 if (i < iCount)
Dan Sinclair1770c022016-03-14 14:14:16 -04003737 continue;
dsinclaircf7f3222016-06-08 20:34:02 -07003738
Dan Sinclair1770c022016-03-14 14:14:16 -04003739 i = 0;
dsinclaircf7f3222016-06-08 20:34:02 -07003740 iCount = FX_ArraySize(strReserved);
Dan Sinclair1770c022016-03-14 14:14:16 -04003741 while (i < iCount) {
3742 if (ch == strReserved[i]) {
3743 int32_t iIndex = ch / 16;
3744 strEncode[1] = strCode[iIndex];
3745 strEncode[2] = strCode[ch - iIndex * 16];
3746 wsResultBuf << FX_WSTRC(strEncode);
3747 break;
3748 }
3749 ++i;
3750 }
dsinclaircf7f3222016-06-08 20:34:02 -07003751 if (i < iCount)
Dan Sinclair1770c022016-03-14 14:14:16 -04003752 continue;
dsinclaircf7f3222016-06-08 20:34:02 -07003753
Dan Sinclair1770c022016-03-14 14:14:16 -04003754 i = 0;
dsinclaircf7f3222016-06-08 20:34:02 -07003755 iCount = FX_ArraySize(strSpecial);
Dan Sinclair1770c022016-03-14 14:14:16 -04003756 while (i < iCount) {
3757 if (ch == strSpecial[i]) {
3758 wsResultBuf.AppendChar(ch);
3759 break;
3760 }
3761 ++i;
3762 }
dsinclaircf7f3222016-06-08 20:34:02 -07003763 if (i < iCount)
Dan Sinclair1770c022016-03-14 14:14:16 -04003764 continue;
dsinclaircf7f3222016-06-08 20:34:02 -07003765
3766 if ((ch >= 0x80 && ch <= 0xff) || ch <= 0x1f || ch == 0x7f) {
Dan Sinclair1770c022016-03-14 14:14:16 -04003767 int32_t iIndex = ch / 16;
3768 strEncode[1] = strCode[iIndex];
3769 strEncode[2] = strCode[ch - iIndex * 16];
3770 wsResultBuf << FX_WSTRC(strEncode);
3771 } else if (ch >= 0x20 && ch <= 0x7e) {
3772 wsResultBuf.AppendChar(ch);
3773 } else {
ochangf6be1452016-06-01 12:20:03 -07003774 const FX_WCHAR iRadix = 16;
Dan Sinclair1770c022016-03-14 14:14:16 -04003775 CFX_WideString strTmp;
3776 while (ch >= iRadix) {
3777 FX_WCHAR tmp = strCode[ch % iRadix];
3778 ch /= iRadix;
3779 strTmp += tmp;
3780 }
3781 strTmp += strCode[ch];
3782 int32_t iLen = strTmp.GetLength();
dsinclaircf7f3222016-06-08 20:34:02 -07003783 if (iLen < 2)
Dan Sinclair1770c022016-03-14 14:14:16 -04003784 break;
dsinclaircf7f3222016-06-08 20:34:02 -07003785
Dan Sinclair1770c022016-03-14 14:14:16 -04003786 int32_t iIndex = 0;
3787 if (iLen % 2 != 0) {
3788 strEncode[1] = '0';
3789 strEncode[2] = strTmp.GetAt(iLen - 1);
3790 iIndex = iLen - 2;
3791 } else {
3792 strEncode[1] = strTmp.GetAt(iLen - 1);
3793 strEncode[2] = strTmp.GetAt(iLen - 2);
3794 iIndex = iLen - 3;
3795 }
3796 wsResultBuf << FX_WSTRC(strEncode);
3797 while (iIndex > 0) {
3798 strEncode[1] = strTmp.GetAt(iIndex);
3799 strEncode[2] = strTmp.GetAt(iIndex - 1);
3800 iIndex -= 2;
3801 wsResultBuf << FX_WSTRC(strEncode);
3802 }
3803 }
3804 }
3805 wsResultBuf.AppendChar(0);
3806 szResultBuf.Clear();
dsinclaircf7f3222016-06-08 20:34:02 -07003807
tsepez28f97ff2016-04-04 16:41:35 -07003808 szResultBuf << FX_UTF8Encode(wsResultBuf.GetBuffer(), wsResultBuf.GetLength())
tsepez4c3debb2016-04-08 12:20:38 -07003809 .AsStringC();
Dan Sinclair1770c022016-03-14 14:14:16 -04003810}
dsinclair48d91dd2016-05-31 11:54:01 -07003811
3812// static
Dan Sinclair1770c022016-03-14 14:14:16 -04003813void CXFA_FM2JSContext::EncodeHTML(const CFX_ByteStringC& szHTMLString,
3814 CFX_ByteTextBuf& szResultBuf) {
dsinclair179bebb2016-04-05 11:02:18 -07003815 CFX_ByteString str = szHTMLString.c_str();
tsepez4c3debb2016-04-08 12:20:38 -07003816 CFX_WideString wsHTMLString = CFX_WideString::FromUTF8(str.AsStringC());
Dan Sinclair1770c022016-03-14 14:14:16 -04003817 const FX_WCHAR* strCode = L"0123456789abcdef";
3818 FX_WCHAR strEncode[9];
3819 strEncode[0] = '&';
3820 strEncode[1] = '#';
3821 strEncode[2] = 'x';
3822 strEncode[5] = ';';
3823 strEncode[6] = 0;
3824 strEncode[7] = ';';
3825 strEncode[8] = 0;
3826 CFX_WideTextBuf wsResultBuf;
Dan Sinclair1770c022016-03-14 14:14:16 -04003827 int32_t iLen = wsHTMLString.GetLength();
3828 int32_t i = 0;
tsepezbd9748d2016-04-13 21:40:19 -07003829 const FX_WCHAR* pData = wsHTMLString.c_str();
Dan Sinclair1770c022016-03-14 14:14:16 -04003830 while (i < iLen) {
dsinclaircf7f3222016-06-08 20:34:02 -07003831 uint32_t ch = pData[i];
3832 CFX_WideString htmlReserve;
Dan Sinclair1770c022016-03-14 14:14:16 -04003833 if (HTMLCode2STR(ch, htmlReserve)) {
3834 wsResultBuf.AppendChar(L'&');
3835 wsResultBuf << htmlReserve;
3836 wsResultBuf.AppendChar(L';');
dsinclaircf7f3222016-06-08 20:34:02 -07003837 } else if (ch >= 32 && ch <= 126) {
3838 wsResultBuf.AppendChar((FX_WCHAR)ch);
3839 } else if (ch < 256) {
3840 int32_t iIndex = ch / 16;
3841 strEncode[3] = strCode[iIndex];
3842 strEncode[4] = strCode[ch - iIndex * 16];
3843 strEncode[5] = ';';
3844 strEncode[6] = 0;
3845 wsResultBuf << FX_WSTRC(strEncode);
Dan Sinclair1770c022016-03-14 14:14:16 -04003846 } else {
dsinclaircf7f3222016-06-08 20:34:02 -07003847 int32_t iBigByte = ch / 256;
3848 int32_t iLittleByte = ch % 256;
3849 strEncode[3] = strCode[iBigByte / 16];
3850 strEncode[4] = strCode[iBigByte % 16];
3851 strEncode[5] = strCode[iLittleByte / 16];
3852 strEncode[6] = strCode[iLittleByte % 16];
3853 wsResultBuf << FX_WSTRC(strEncode);
Dan Sinclair1770c022016-03-14 14:14:16 -04003854 }
3855 ++i;
3856 }
3857 wsResultBuf.AppendChar(0);
3858 szResultBuf.Clear();
dsinclaircf7f3222016-06-08 20:34:02 -07003859
tsepez28f97ff2016-04-04 16:41:35 -07003860 szResultBuf << FX_UTF8Encode(wsResultBuf.GetBuffer(), wsResultBuf.GetLength())
tsepez4c3debb2016-04-08 12:20:38 -07003861 .AsStringC();
Dan Sinclair1770c022016-03-14 14:14:16 -04003862}
dsinclair48d91dd2016-05-31 11:54:01 -07003863
3864// static
Dan Sinclair1770c022016-03-14 14:14:16 -04003865void CXFA_FM2JSContext::EncodeXML(const CFX_ByteStringC& szXMLString,
3866 CFX_ByteTextBuf& szResultBuf) {
tsepez6fe7d212016-04-06 10:51:14 -07003867 CFX_WideString wsXMLString = CFX_WideString::FromUTF8(szXMLString);
Dan Sinclair1770c022016-03-14 14:14:16 -04003868 CFX_WideTextBuf wsResultBuf;
Dan Sinclair1770c022016-03-14 14:14:16 -04003869 FX_WCHAR strEncode[9];
3870 strEncode[0] = '&';
3871 strEncode[1] = '#';
3872 strEncode[2] = 'x';
3873 strEncode[5] = ';';
3874 strEncode[6] = 0;
3875 strEncode[7] = ';';
3876 strEncode[8] = 0;
Dan Sinclair1770c022016-03-14 14:14:16 -04003877 const FX_WCHAR* strCode = L"0123456789abcdef";
tsepezbd9748d2016-04-13 21:40:19 -07003878 const FX_WCHAR* pData = wsXMLString.c_str();
dsinclaircf7f3222016-06-08 20:34:02 -07003879 for (int32_t u = 0; u < wsXMLString.GetLength(); ++u) {
3880 FX_WCHAR ch = pData[u];
Dan Sinclair1770c022016-03-14 14:14:16 -04003881 switch (ch) {
3882 case '"':
3883 wsResultBuf.AppendChar('&');
dsinclaircf7f3222016-06-08 20:34:02 -07003884 wsResultBuf << CFX_WideStringC(L"quot");
Dan Sinclair1770c022016-03-14 14:14:16 -04003885 wsResultBuf.AppendChar(';');
3886 break;
3887 case '&':
3888 wsResultBuf.AppendChar('&');
dsinclaircf7f3222016-06-08 20:34:02 -07003889 wsResultBuf << CFX_WideStringC(L"amp");
Dan Sinclair1770c022016-03-14 14:14:16 -04003890 wsResultBuf.AppendChar(';');
3891 break;
3892 case '\'':
3893 wsResultBuf.AppendChar('&');
dsinclaircf7f3222016-06-08 20:34:02 -07003894 wsResultBuf << CFX_WideStringC(L"apos");
Dan Sinclair1770c022016-03-14 14:14:16 -04003895 wsResultBuf.AppendChar(';');
3896 break;
3897 case '<':
3898 wsResultBuf.AppendChar('&');
dsinclaircf7f3222016-06-08 20:34:02 -07003899 wsResultBuf << CFX_WideStringC(L"lt");
Dan Sinclair1770c022016-03-14 14:14:16 -04003900 wsResultBuf.AppendChar(';');
3901 break;
3902 case '>':
3903 wsResultBuf.AppendChar('&');
dsinclaircf7f3222016-06-08 20:34:02 -07003904 wsResultBuf << CFX_WideStringC(L"gt");
Dan Sinclair1770c022016-03-14 14:14:16 -04003905 wsResultBuf.AppendChar(';');
3906 break;
3907 default: {
3908 if (ch >= 32 && ch <= 126) {
3909 wsResultBuf.AppendChar(ch);
3910 } else if (ch < 256) {
dsinclaircf7f3222016-06-08 20:34:02 -07003911 int32_t iIndex = ch / 16;
Dan Sinclair1770c022016-03-14 14:14:16 -04003912 strEncode[3] = strCode[iIndex];
3913 strEncode[4] = strCode[ch - iIndex * 16];
3914 strEncode[5] = ';';
3915 strEncode[6] = 0;
3916 wsResultBuf << FX_WSTRC(strEncode);
3917 } else {
3918 int32_t iBigByte = ch / 256;
3919 int32_t iLittleByte = ch % 256;
3920 strEncode[3] = strCode[iBigByte / 16];
3921 strEncode[4] = strCode[iBigByte % 16];
3922 strEncode[5] = strCode[iLittleByte / 16];
3923 strEncode[6] = strCode[iLittleByte % 16];
3924 wsResultBuf << FX_WSTRC(strEncode);
3925 }
dsinclaircf7f3222016-06-08 20:34:02 -07003926 break;
3927 }
Dan Sinclair1770c022016-03-14 14:14:16 -04003928 }
3929 }
3930 wsResultBuf.AppendChar(0);
3931 szResultBuf.Clear();
dsinclaircf7f3222016-06-08 20:34:02 -07003932
tsepez28f97ff2016-04-04 16:41:35 -07003933 szResultBuf << FX_UTF8Encode(wsResultBuf.GetBuffer(), wsResultBuf.GetLength())
tsepez4c3debb2016-04-08 12:20:38 -07003934 .AsStringC();
Dan Sinclair1770c022016-03-14 14:14:16 -04003935}
dsinclair48d91dd2016-05-31 11:54:01 -07003936
3937// static
Dan Sinclair1770c022016-03-14 14:14:16 -04003938FX_BOOL CXFA_FM2JSContext::HTMLSTR2Code(const CFX_WideStringC& pData,
3939 uint32_t& iCode) {
tsepezb6853cf2016-04-25 11:23:43 -07003940 uint32_t uHash = FX_HashCode_GetW(pData, false);
3941 int32_t iStart = 0;
3942 int32_t iEnd = FX_ArraySize(reservesForDecode) - 1;
Dan Sinclair1770c022016-03-14 14:14:16 -04003943 do {
tsepezb6853cf2016-04-25 11:23:43 -07003944 int32_t iMid = (iStart + iEnd) / 2;
3945 XFA_FMHtmlHashedReserveCode htmlhashedreservecode = reservesForDecode[iMid];
Dan Sinclair1770c022016-03-14 14:14:16 -04003946 if (uHash == htmlhashedreservecode.m_uHash) {
3947 iCode = htmlhashedreservecode.m_uCode;
3948 return TRUE;
tsepezb6853cf2016-04-25 11:23:43 -07003949 }
dsinclaircf7f3222016-06-08 20:34:02 -07003950
3951 if (uHash < htmlhashedreservecode.m_uHash)
Dan Sinclair1770c022016-03-14 14:14:16 -04003952 iEnd = iMid - 1;
dsinclaircf7f3222016-06-08 20:34:02 -07003953 else
Dan Sinclair1770c022016-03-14 14:14:16 -04003954 iStart = iMid + 1;
Dan Sinclair1770c022016-03-14 14:14:16 -04003955 } while (iStart <= iEnd);
3956 return FALSE;
3957}
dsinclair48d91dd2016-05-31 11:54:01 -07003958
3959// static
Dan Sinclair1770c022016-03-14 14:14:16 -04003960FX_BOOL CXFA_FM2JSContext::HTMLCode2STR(uint32_t iCode,
3961 CFX_WideString& wsHTMLReserve) {
dsinclaircf7f3222016-06-08 20:34:02 -07003962 int32_t iStart = 0;
3963 int32_t iEnd = FX_ArraySize(reservesForEncode) - 1;
Dan Sinclair1770c022016-03-14 14:14:16 -04003964 do {
dsinclaircf7f3222016-06-08 20:34:02 -07003965 int32_t iMid = (iStart + iEnd) / 2;
3966 XFA_FMHtmlReserveCode htmlreservecode = reservesForEncode[iMid];
Dan Sinclair1770c022016-03-14 14:14:16 -04003967 if (iCode == htmlreservecode.m_uCode) {
3968 wsHTMLReserve = htmlreservecode.m_htmlReserve;
3969 return TRUE;
Dan Sinclair1770c022016-03-14 14:14:16 -04003970 }
dsinclaircf7f3222016-06-08 20:34:02 -07003971
3972 if (iCode < htmlreservecode.m_uCode)
3973 iEnd = iMid - 1;
3974 else
3975 iStart = iMid + 1;
Dan Sinclair1770c022016-03-14 14:14:16 -04003976 } while (iStart <= iEnd);
3977 return FALSE;
3978}
dsinclair48d91dd2016-05-31 11:54:01 -07003979
3980// static
dsinclair12a6b0c2016-05-26 11:14:08 -07003981void CXFA_FM2JSContext::Format(CFXJSE_Value* pThis,
Dan Sinclair1770c022016-03-14 14:14:16 -04003982 const CFX_ByteStringC& szFuncName,
3983 CFXJSE_Arguments& args) {
dsinclair8f3074b2016-06-02 17:45:25 -07003984 CXFA_FM2JSContext* pContext = ToJSContext(pThis, nullptr);
dsinclaircf7f3222016-06-08 20:34:02 -07003985 if (args.GetLength() < 2) {
dsinclair2235b7b2016-06-02 07:42:25 -07003986 pContext->ThrowException(XFA_IDS_INCORRECT_NUMBER_OF_METHOD, L"Format");
dsinclaircf7f3222016-06-08 20:34:02 -07003987 return;
Dan Sinclair1770c022016-03-14 14:14:16 -04003988 }
dsinclaircf7f3222016-06-08 20:34:02 -07003989
3990 std::unique_ptr<CFXJSE_Value> argOne = GetSimpleValue(pThis, args, 0);
3991 CFX_ByteString szPattern;
3992 ValueToUTF8String(argOne.get(), szPattern);
3993
3994 std::unique_ptr<CFXJSE_Value> argTwo = GetSimpleValue(pThis, args, 1);
3995 CFX_ByteString szValue;
3996 ValueToUTF8String(argTwo.get(), szValue);
3997
3998 CXFA_Document* pDoc = pContext->GetDocument();
3999 CXFA_LocaleMgr* pMgr = pDoc->GetLocalMgr();
4000 CXFA_Node* pThisNode = ToNode(pDoc->GetScriptContext()->GetThisObject());
4001 ASSERT(pThisNode);
4002
4003 CXFA_WidgetData widgetData(pThisNode);
4004 IFX_Locale* pLocale = widgetData.GetLocal();
4005 uint32_t patternType;
4006 CFX_WideString wsPattern = CFX_WideString::FromUTF8(szPattern.AsStringC());
4007 CFX_WideString wsValue = CFX_WideString::FromUTF8(szValue.AsStringC());
4008 if (!PatternStringType(szPattern.AsStringC(), patternType)) {
4009 switch (patternType) {
4010 case XFA_VT_DATETIME: {
4011 FX_STRSIZE iTChar = wsPattern.Find(L'T');
4012 CFX_WideString wsDatePattern(L"date{");
4013 wsDatePattern += wsPattern.Left(iTChar) + L"} ";
4014
4015 CFX_WideString wsTimePattern(L"time{");
4016 wsTimePattern += wsPattern.Mid(iTChar + 1) + L"}";
4017 wsPattern = wsDatePattern + wsTimePattern;
4018 } break;
4019 case XFA_VT_DATE: {
4020 wsPattern = L"date{" + wsPattern + L"}";
4021 } break;
4022 case XFA_VT_TIME: {
4023 wsPattern = L"time{" + wsPattern + L"}";
4024 } break;
4025 case XFA_VT_TEXT: {
4026 wsPattern = L"text{" + wsPattern + L"}";
4027 } break;
4028 case XFA_VT_FLOAT: {
4029 wsPattern = L"num{" + wsPattern + L"}";
4030 } break;
4031 default: {
4032 CFX_WideString wsTestPattern;
4033 wsTestPattern = L"num{" + wsPattern + L"}";
4034 CXFA_LocaleValue tempLocaleValue(XFA_VT_FLOAT, wsValue, wsTestPattern,
4035 pLocale, pMgr);
4036 if (tempLocaleValue.IsValid()) {
4037 wsPattern = wsTestPattern;
4038 patternType = XFA_VT_FLOAT;
4039 } else {
4040 wsTestPattern = L"text{" + wsPattern + L"}";
4041 wsPattern = wsTestPattern;
4042 patternType = XFA_VT_TEXT;
4043 }
4044 } break;
4045 }
4046 }
4047 CXFA_LocaleValue localeValue(patternType, wsValue, wsPattern, pLocale, pMgr);
4048 CFX_WideString wsRet;
4049 if (!localeValue.FormatPatterns(wsRet, wsPattern, pLocale,
4050 XFA_VALUEPICTURE_Display)) {
4051 args.GetReturnValue()->SetString("");
4052 return;
4053 }
4054
4055 args.GetReturnValue()->SetString(
4056 FX_UTF8Encode(wsRet.c_str(), wsRet.GetLength()).AsStringC());
Dan Sinclair1770c022016-03-14 14:14:16 -04004057}
dsinclair48d91dd2016-05-31 11:54:01 -07004058
4059// static
dsinclair12a6b0c2016-05-26 11:14:08 -07004060void CXFA_FM2JSContext::Left(CFXJSE_Value* pThis,
Dan Sinclair1770c022016-03-14 14:14:16 -04004061 const CFX_ByteStringC& szFuncName,
4062 CFXJSE_Arguments& args) {
dsinclaircf7f3222016-06-08 20:34:02 -07004063 if (args.GetLength() != 2) {
dsinclair8f3074b2016-06-02 17:45:25 -07004064 ToJSContext(pThis, nullptr)
4065 ->ThrowException(XFA_IDS_INCORRECT_NUMBER_OF_METHOD, L"Left");
dsinclaircf7f3222016-06-08 20:34:02 -07004066 return;
Dan Sinclair1770c022016-03-14 14:14:16 -04004067 }
dsinclaircf7f3222016-06-08 20:34:02 -07004068
4069 std::unique_ptr<CFXJSE_Value> argOne = GetSimpleValue(pThis, args, 0);
4070 std::unique_ptr<CFXJSE_Value> argTwo = GetSimpleValue(pThis, args, 1);
4071 if ((ValueIsNull(pThis, argOne.get())) ||
4072 (ValueIsNull(pThis, argTwo.get()))) {
4073 args.GetReturnValue()->SetNull();
4074 return;
4075 }
4076
4077 CFX_ByteString sourceString;
4078 ValueToUTF8String(argOne.get(), sourceString);
4079 int32_t count = std::max(0, ValueToInteger(pThis, argTwo.get()));
4080 args.GetReturnValue()->SetString(sourceString.Left(count).AsStringC());
Dan Sinclair1770c022016-03-14 14:14:16 -04004081}
dsinclair48d91dd2016-05-31 11:54:01 -07004082
4083// static
dsinclair12a6b0c2016-05-26 11:14:08 -07004084void CXFA_FM2JSContext::Len(CFXJSE_Value* pThis,
Dan Sinclair1770c022016-03-14 14:14:16 -04004085 const CFX_ByteStringC& szFuncName,
4086 CFXJSE_Arguments& args) {
dsinclaircf7f3222016-06-08 20:34:02 -07004087 if (args.GetLength() != 1) {
dsinclair8f3074b2016-06-02 17:45:25 -07004088 ToJSContext(pThis, nullptr)
4089 ->ThrowException(XFA_IDS_INCORRECT_NUMBER_OF_METHOD, L"Len");
dsinclaircf7f3222016-06-08 20:34:02 -07004090 return;
Dan Sinclair1770c022016-03-14 14:14:16 -04004091 }
dsinclaircf7f3222016-06-08 20:34:02 -07004092
4093 std::unique_ptr<CFXJSE_Value> argOne = GetSimpleValue(pThis, args, 0);
4094 if (ValueIsNull(pThis, argOne.get())) {
4095 args.GetReturnValue()->SetNull();
4096 return;
4097 }
4098
4099 CFX_ByteString sourceString;
4100 ValueToUTF8String(argOne.get(), sourceString);
4101 args.GetReturnValue()->SetInteger(sourceString.GetLength());
Dan Sinclair1770c022016-03-14 14:14:16 -04004102}
dsinclair48d91dd2016-05-31 11:54:01 -07004103
4104// static
dsinclair12a6b0c2016-05-26 11:14:08 -07004105void CXFA_FM2JSContext::Lower(CFXJSE_Value* pThis,
Dan Sinclair1770c022016-03-14 14:14:16 -04004106 const CFX_ByteStringC& szFuncName,
4107 CFXJSE_Arguments& args) {
4108 int32_t argc = args.GetLength();
dsinclaircf7f3222016-06-08 20:34:02 -07004109 if (argc < 1 || argc > 2) {
dsinclair8f3074b2016-06-02 17:45:25 -07004110 ToJSContext(pThis, nullptr)
4111 ->ThrowException(XFA_IDS_INCORRECT_NUMBER_OF_METHOD, L"Lower");
dsinclaircf7f3222016-06-08 20:34:02 -07004112 return;
Dan Sinclair1770c022016-03-14 14:14:16 -04004113 }
dsinclaircf7f3222016-06-08 20:34:02 -07004114
4115 CFX_ByteString argString;
4116 std::unique_ptr<CFXJSE_Value> argOne = GetSimpleValue(pThis, args, 0);
4117 if (ValueIsNull(pThis, argOne.get())) {
4118 args.GetReturnValue()->SetNull();
4119 return;
4120 }
4121
4122 ValueToUTF8String(argOne.get(), argString);
4123 CFX_WideTextBuf lowStringBuf;
4124 CFX_WideString wsArgString = CFX_WideString::FromUTF8(argString.AsStringC());
4125 const FX_WCHAR* pData = wsArgString.c_str();
4126 int32_t i = 0;
4127 while (i < argString.GetLength()) {
4128 int32_t ch = pData[i];
4129 if ((ch >= 0x41 && ch <= 0x5A) || (ch >= 0xC0 && ch <= 0xDE))
4130 ch += 32;
4131 else if (ch == 0x100 || ch == 0x102 || ch == 0x104)
4132 ch += 1;
4133
4134 lowStringBuf.AppendChar(ch);
4135 ++i;
4136 }
4137 lowStringBuf.AppendChar(0);
4138
4139 args.GetReturnValue()->SetString(
4140 FX_UTF8Encode(lowStringBuf.GetBuffer(), lowStringBuf.GetLength())
4141 .AsStringC());
Dan Sinclair1770c022016-03-14 14:14:16 -04004142}
dsinclair48d91dd2016-05-31 11:54:01 -07004143
4144// static
dsinclair12a6b0c2016-05-26 11:14:08 -07004145void CXFA_FM2JSContext::Ltrim(CFXJSE_Value* pThis,
Dan Sinclair1770c022016-03-14 14:14:16 -04004146 const CFX_ByteStringC& szFuncName,
4147 CFXJSE_Arguments& args) {
dsinclaircf7f3222016-06-08 20:34:02 -07004148 if (args.GetLength() != 1) {
dsinclair8f3074b2016-06-02 17:45:25 -07004149 ToJSContext(pThis, nullptr)
4150 ->ThrowException(XFA_IDS_INCORRECT_NUMBER_OF_METHOD, L"Ltrim");
dsinclaircf7f3222016-06-08 20:34:02 -07004151 return;
Dan Sinclair1770c022016-03-14 14:14:16 -04004152 }
dsinclaircf7f3222016-06-08 20:34:02 -07004153
4154 std::unique_ptr<CFXJSE_Value> argOne = GetSimpleValue(pThis, args, 0);
4155 if (ValueIsNull(pThis, argOne.get())) {
4156 args.GetReturnValue()->SetNull();
4157 return;
4158 }
4159
4160 CFX_ByteString sourceString;
4161 ValueToUTF8String(argOne.get(), sourceString);
4162 sourceString.TrimLeft();
4163 args.GetReturnValue()->SetString(sourceString.AsStringC());
Dan Sinclair1770c022016-03-14 14:14:16 -04004164}
dsinclair48d91dd2016-05-31 11:54:01 -07004165
4166// static
dsinclair12a6b0c2016-05-26 11:14:08 -07004167void CXFA_FM2JSContext::Parse(CFXJSE_Value* pThis,
Dan Sinclair1770c022016-03-14 14:14:16 -04004168 const CFX_ByteStringC& szFuncName,
4169 CFXJSE_Arguments& args) {
dsinclair8f3074b2016-06-02 17:45:25 -07004170 CXFA_FM2JSContext* pContext = ToJSContext(pThis, nullptr);
dsinclaircf7f3222016-06-08 20:34:02 -07004171 if (args.GetLength() != 2) {
dsinclair2235b7b2016-06-02 07:42:25 -07004172 pContext->ThrowException(XFA_IDS_INCORRECT_NUMBER_OF_METHOD, L"Parse");
dsinclaircf7f3222016-06-08 20:34:02 -07004173 return;
4174 }
4175
4176 std::unique_ptr<CFXJSE_Value> argOne = GetSimpleValue(pThis, args, 0);
4177 std::unique_ptr<CFXJSE_Value> argTwo = GetSimpleValue(pThis, args, 1);
4178 if (ValueIsNull(pThis, argTwo.get())) {
4179 args.GetReturnValue()->SetNull();
4180 return;
4181 }
4182
4183 CFX_ByteString szPattern;
4184 ValueToUTF8String(argOne.get(), szPattern);
4185 CFX_ByteString szValue;
4186 ValueToUTF8String(argTwo.get(), szValue);
4187
4188 CXFA_Document* pDoc = pContext->GetDocument();
4189 CXFA_LocaleMgr* pMgr = pDoc->GetLocalMgr();
4190 CXFA_Node* pThisNode = ToNode(pDoc->GetScriptContext()->GetThisObject());
4191 ASSERT(pThisNode);
4192
4193 CXFA_WidgetData widgetData(pThisNode);
4194 IFX_Locale* pLocale = widgetData.GetLocal();
4195 CFX_WideString wsPattern = CFX_WideString::FromUTF8(szPattern.AsStringC());
4196 CFX_WideString wsValue = CFX_WideString::FromUTF8(szValue.AsStringC());
4197 uint32_t patternType;
4198 if (PatternStringType(szPattern.AsStringC(), patternType)) {
4199 CXFA_LocaleValue localeValue(patternType, wsValue, wsPattern, pLocale,
4200 pMgr);
4201 if (!localeValue.IsValid()) {
4202 args.GetReturnValue()->SetString("");
4203 return;
4204 }
4205 args.GetReturnValue()->SetString(
4206 FX_UTF8Encode(localeValue.GetValue()).AsStringC());
4207 return;
4208 }
4209
4210 switch (patternType) {
4211 case XFA_VT_DATETIME: {
4212 FX_STRSIZE iTChar = wsPattern.Find(L'T');
4213 CFX_WideString wsDatePattern(L"date{" + wsPattern.Left(iTChar) + L"} ");
4214 CFX_WideString wsTimePattern(L"time{" + wsPattern.Mid(iTChar + 1) + L"}");
4215 wsPattern = wsDatePattern + wsTimePattern;
4216 CXFA_LocaleValue localeValue(patternType, wsValue, wsPattern, pLocale,
4217 pMgr);
4218 if (!localeValue.IsValid()) {
4219 args.GetReturnValue()->SetString("");
4220 return;
4221 }
4222 args.GetReturnValue()->SetString(
4223 FX_UTF8Encode(localeValue.GetValue()).AsStringC());
4224 return;
4225 }
4226 case XFA_VT_DATE: {
4227 wsPattern = L"date{" + wsPattern + L"}";
4228 CXFA_LocaleValue localeValue(patternType, wsValue, wsPattern, pLocale,
4229 pMgr);
4230 if (!localeValue.IsValid()) {
4231 args.GetReturnValue()->SetString("");
4232 return;
4233 }
4234 args.GetReturnValue()->SetString(
4235 FX_UTF8Encode(localeValue.GetValue()).AsStringC());
4236 return;
4237 }
4238 case XFA_VT_TIME: {
4239 wsPattern = L"time{" + wsPattern + L"}";
4240 CXFA_LocaleValue localeValue(patternType, wsValue, wsPattern, pLocale,
4241 pMgr);
4242 if (!localeValue.IsValid()) {
4243 args.GetReturnValue()->SetString("");
4244 return;
4245 }
4246 args.GetReturnValue()->SetString(
4247 FX_UTF8Encode(localeValue.GetValue()).AsStringC());
4248 return;
4249 }
4250 case XFA_VT_TEXT: {
4251 wsPattern = L"text{" + wsPattern + L"}";
4252 CXFA_LocaleValue localeValue(XFA_VT_TEXT, wsValue, wsPattern, pLocale,
4253 pMgr);
4254 if (!localeValue.IsValid()) {
4255 args.GetReturnValue()->SetString("");
4256 return;
4257 }
4258 args.GetReturnValue()->SetString(
4259 FX_UTF8Encode(localeValue.GetValue()).AsStringC());
4260 return;
4261 }
4262 case XFA_VT_FLOAT: {
4263 wsPattern = L"num{" + wsPattern + L"}";
4264 CXFA_LocaleValue localeValue(XFA_VT_FLOAT, wsValue, wsPattern, pLocale,
4265 pMgr);
4266 if (!localeValue.IsValid()) {
4267 args.GetReturnValue()->SetString("");
4268 return;
4269 }
4270 args.GetReturnValue()->SetDouble(localeValue.GetDoubleNum());
4271 return;
4272 }
4273 default: {
4274 CFX_WideString wsTestPattern;
4275 wsTestPattern = L"num{" + wsPattern + L"}";
4276 CXFA_LocaleValue localeValue(XFA_VT_FLOAT, wsValue, wsTestPattern,
4277 pLocale, pMgr);
4278 if (localeValue.IsValid()) {
4279 args.GetReturnValue()->SetDouble(localeValue.GetDoubleNum());
4280 return;
4281 }
4282
4283 wsTestPattern = L"text{" + wsPattern + L"}";
4284 CXFA_LocaleValue localeValue2(XFA_VT_TEXT, wsValue, wsTestPattern,
4285 pLocale, pMgr);
4286 if (!localeValue2.IsValid()) {
4287 args.GetReturnValue()->SetString("");
4288 return;
4289 }
4290 args.GetReturnValue()->SetString(
4291 FX_UTF8Encode(localeValue2.GetValue()).AsStringC());
4292 return;
4293 }
Dan Sinclair1770c022016-03-14 14:14:16 -04004294 }
4295}
dsinclair48d91dd2016-05-31 11:54:01 -07004296
4297// static
dsinclair12a6b0c2016-05-26 11:14:08 -07004298void CXFA_FM2JSContext::Replace(CFXJSE_Value* pThis,
Dan Sinclair1770c022016-03-14 14:14:16 -04004299 const CFX_ByteStringC& szFuncName,
4300 CFXJSE_Arguments& args) {
4301 int32_t argc = args.GetLength();
dsinclaircf7f3222016-06-08 20:34:02 -07004302 if (argc < 2 || argc > 3) {
dsinclair8f3074b2016-06-02 17:45:25 -07004303 ToJSContext(pThis, nullptr)
4304 ->ThrowException(XFA_IDS_INCORRECT_NUMBER_OF_METHOD, L"Replace");
dsinclaircf7f3222016-06-08 20:34:02 -07004305 return;
Dan Sinclair1770c022016-03-14 14:14:16 -04004306 }
dsinclaircf7f3222016-06-08 20:34:02 -07004307
4308 std::unique_ptr<CFXJSE_Value> argOne = GetSimpleValue(pThis, args, 0);
4309 std::unique_ptr<CFXJSE_Value> argTwo = GetSimpleValue(pThis, args, 1);
4310 CFX_ByteString oneString;
4311 CFX_ByteString twoString;
4312 if (!ValueIsNull(pThis, argOne.get()) && !ValueIsNull(pThis, argTwo.get())) {
4313 ValueToUTF8String(argOne.get(), oneString);
4314 ValueToUTF8String(argTwo.get(), twoString);
4315 }
4316
4317 CFX_ByteString threeString;
4318 if (argc > 2) {
4319 std::unique_ptr<CFXJSE_Value> argThree = GetSimpleValue(pThis, args, 2);
4320 ValueToUTF8String(argThree.get(), threeString);
4321 }
4322
4323 int32_t iFindLen = twoString.GetLength();
4324 CFX_ByteTextBuf resultString;
4325 int32_t iFindIndex = 0;
4326 for (int32_t u = 0; u < oneString.GetLength(); ++u) {
4327 uint8_t ch = oneString.GetAt(u);
4328 if (ch != twoString.GetAt(iFindIndex)) {
4329 resultString.AppendChar(ch);
4330 continue;
4331 }
4332
4333 int32_t iTemp = u + 1;
4334 ++iFindIndex;
4335 while (iFindIndex < iFindLen) {
4336 uint8_t chTemp = oneString.GetAt(iTemp);
4337 if (chTemp != twoString.GetAt(iFindIndex)) {
4338 iFindIndex = 0;
4339 break;
4340 }
4341
4342 ++iTemp;
4343 ++iFindIndex;
4344 }
4345 if (iFindIndex == iFindLen) {
4346 resultString << threeString.AsStringC();
4347 u += iFindLen - 1;
4348 iFindIndex = 0;
4349 } else {
4350 resultString.AppendChar(ch);
4351 }
4352 }
4353 resultString.AppendChar(0);
4354 args.GetReturnValue()->SetString(resultString.AsStringC());
Dan Sinclair1770c022016-03-14 14:14:16 -04004355}
dsinclair48d91dd2016-05-31 11:54:01 -07004356
4357// static
dsinclair12a6b0c2016-05-26 11:14:08 -07004358void CXFA_FM2JSContext::Right(CFXJSE_Value* pThis,
Dan Sinclair1770c022016-03-14 14:14:16 -04004359 const CFX_ByteStringC& szFuncName,
4360 CFXJSE_Arguments& args) {
dsinclaircf7f3222016-06-08 20:34:02 -07004361 if (args.GetLength() != 2) {
dsinclair8f3074b2016-06-02 17:45:25 -07004362 ToJSContext(pThis, nullptr)
4363 ->ThrowException(XFA_IDS_INCORRECT_NUMBER_OF_METHOD, L"Right");
dsinclaircf7f3222016-06-08 20:34:02 -07004364 return;
Dan Sinclair1770c022016-03-14 14:14:16 -04004365 }
dsinclaircf7f3222016-06-08 20:34:02 -07004366
4367 std::unique_ptr<CFXJSE_Value> argOne = GetSimpleValue(pThis, args, 0);
4368 std::unique_ptr<CFXJSE_Value> argTwo = GetSimpleValue(pThis, args, 1);
4369 if ((ValueIsNull(pThis, argOne.get())) ||
4370 (ValueIsNull(pThis, argTwo.get()))) {
4371 args.GetReturnValue()->SetNull();
4372 return;
4373 }
4374
4375 CFX_ByteString sourceString;
4376 ValueToUTF8String(argOne.get(), sourceString);
4377 int32_t count = std::max(0, ValueToInteger(pThis, argTwo.get()));
4378 args.GetReturnValue()->SetString(sourceString.Right(count).AsStringC());
Dan Sinclair1770c022016-03-14 14:14:16 -04004379}
dsinclair48d91dd2016-05-31 11:54:01 -07004380
4381// static
dsinclair12a6b0c2016-05-26 11:14:08 -07004382void CXFA_FM2JSContext::Rtrim(CFXJSE_Value* pThis,
Dan Sinclair1770c022016-03-14 14:14:16 -04004383 const CFX_ByteStringC& szFuncName,
4384 CFXJSE_Arguments& args) {
dsinclaircf7f3222016-06-08 20:34:02 -07004385 if (args.GetLength() != 1) {
dsinclair8f3074b2016-06-02 17:45:25 -07004386 ToJSContext(pThis, nullptr)
4387 ->ThrowException(XFA_IDS_INCORRECT_NUMBER_OF_METHOD, L"Rtrim");
dsinclaircf7f3222016-06-08 20:34:02 -07004388 return;
Dan Sinclair1770c022016-03-14 14:14:16 -04004389 }
dsinclaircf7f3222016-06-08 20:34:02 -07004390
4391 std::unique_ptr<CFXJSE_Value> argOne = GetSimpleValue(pThis, args, 0);
4392 if (ValueIsNull(pThis, argOne.get())) {
4393 args.GetReturnValue()->SetNull();
4394 return;
4395 }
4396
4397 CFX_ByteString sourceString;
4398 ValueToUTF8String(argOne.get(), sourceString);
4399 sourceString.TrimRight();
4400 args.GetReturnValue()->SetString(sourceString.AsStringC());
Dan Sinclair1770c022016-03-14 14:14:16 -04004401}
dsinclair48d91dd2016-05-31 11:54:01 -07004402
4403// static
dsinclair12a6b0c2016-05-26 11:14:08 -07004404void CXFA_FM2JSContext::Space(CFXJSE_Value* pThis,
Dan Sinclair1770c022016-03-14 14:14:16 -04004405 const CFX_ByteStringC& szFuncName,
4406 CFXJSE_Arguments& args) {
dsinclaircf7f3222016-06-08 20:34:02 -07004407 if (args.GetLength() != 1) {
dsinclair8f3074b2016-06-02 17:45:25 -07004408 ToJSContext(pThis, nullptr)
4409 ->ThrowException(XFA_IDS_INCORRECT_NUMBER_OF_METHOD, L"Space");
dsinclaircf7f3222016-06-08 20:34:02 -07004410 return;
Dan Sinclair1770c022016-03-14 14:14:16 -04004411 }
dsinclaircf7f3222016-06-08 20:34:02 -07004412
4413 std::unique_ptr<CFXJSE_Value> argOne = GetSimpleValue(pThis, args, 0);
4414 if (argOne->IsNull()) {
4415 args.GetReturnValue()->SetNull();
4416 return;
4417 }
4418
4419 int32_t count = std::max(0, ValueToInteger(pThis, argOne.get()));
4420 CFX_ByteTextBuf spaceString;
4421 int32_t index = 0;
4422 while (index < count) {
4423 spaceString.AppendByte(' ');
4424 index++;
4425 }
4426 spaceString.AppendByte(0);
4427 args.GetReturnValue()->SetString(spaceString.AsStringC());
Dan Sinclair1770c022016-03-14 14:14:16 -04004428}
dsinclair48d91dd2016-05-31 11:54:01 -07004429
4430// static
dsinclair12a6b0c2016-05-26 11:14:08 -07004431void CXFA_FM2JSContext::Str(CFXJSE_Value* pThis,
Dan Sinclair1770c022016-03-14 14:14:16 -04004432 const CFX_ByteStringC& szFuncName,
4433 CFXJSE_Arguments& args) {
4434 int32_t argc = args.GetLength();
dsinclaircf7f3222016-06-08 20:34:02 -07004435 if (argc < 1 || argc > 3) {
dsinclair8f3074b2016-06-02 17:45:25 -07004436 ToJSContext(pThis, nullptr)
4437 ->ThrowException(XFA_IDS_INCORRECT_NUMBER_OF_METHOD, L"Str");
dsinclaircf7f3222016-06-08 20:34:02 -07004438 return;
Dan Sinclair1770c022016-03-14 14:14:16 -04004439 }
dsinclaircf7f3222016-06-08 20:34:02 -07004440
4441 std::unique_ptr<CFXJSE_Value> numberValue = GetSimpleValue(pThis, args, 0);
4442 if (numberValue->IsNull()) {
4443 args.GetReturnValue()->SetNull();
4444 return;
4445 }
4446 FX_FLOAT fNumber = ValueToFloat(pThis, numberValue.get());
4447
4448 int32_t iWidth = 10;
4449 if (argc > 1) {
4450 std::unique_ptr<CFXJSE_Value> widthValue = GetSimpleValue(pThis, args, 1);
4451 iWidth = static_cast<int32_t>(ValueToFloat(pThis, widthValue.get()));
4452 }
4453
4454 int32_t iPrecision = 0;
4455 if (argc > 2) {
4456 std::unique_ptr<CFXJSE_Value> precisionValue =
4457 GetSimpleValue(pThis, args, 2);
4458 iPrecision = std::max(
4459 0, static_cast<int32_t>(ValueToFloat(pThis, precisionValue.get())));
4460 }
4461
4462 CFX_ByteString numberString;
4463 CFX_ByteString formatStr = "%";
4464 if (iPrecision) {
4465 formatStr += ".";
4466 formatStr += CFX_ByteString::FormatInteger(iPrecision);
4467 }
4468 formatStr += "f";
4469 numberString.Format(formatStr.c_str(), fNumber);
4470
4471 const FX_CHAR* pData = numberString.c_str();
4472 int32_t iLength = numberString.GetLength();
4473 int32_t u = 0;
4474 while (u < iLength) {
4475 if (pData[u] == '.')
4476 break;
4477
4478 ++u;
4479 }
4480
4481 CFX_ByteTextBuf resultBuf;
4482 if (u > iWidth || (iPrecision + u) >= iWidth) {
4483 int32_t i = 0;
4484 while (i < iWidth) {
4485 resultBuf.AppendChar('*');
4486 ++i;
4487 }
4488 resultBuf.AppendChar(0);
4489 args.GetReturnValue()->SetString(resultBuf.AsStringC());
4490 return;
4491 }
4492
4493 if (u == iLength) {
4494 if (iLength > iWidth) {
4495 int32_t i = 0;
4496 while (i < iWidth) {
4497 resultBuf.AppendChar('*');
4498 ++i;
4499 }
4500 } else {
4501 int32_t i = 0;
4502 while (i < iWidth - iLength) {
4503 resultBuf.AppendChar(' ');
4504 ++i;
4505 }
4506 resultBuf << pData;
4507 }
4508 args.GetReturnValue()->SetString(resultBuf.AsStringC());
4509 return;
4510 }
4511
4512 int32_t iLeavingSpace = iWidth - u - iPrecision;
4513 if (iPrecision != 0)
4514 iLeavingSpace--;
4515
4516 int32_t i = 0;
4517 while (i < iLeavingSpace) {
4518 resultBuf.AppendChar(' ');
4519 ++i;
4520 }
4521 i = 0;
4522 while (i < u) {
4523 resultBuf.AppendChar(pData[i]);
4524 ++i;
4525 }
4526 if (iPrecision != 0)
4527 resultBuf.AppendChar('.');
4528
4529 u++;
4530 i = 0;
4531 while (u < iLength) {
4532 if (i >= iPrecision)
4533 break;
4534
4535 resultBuf.AppendChar(pData[u]);
4536 ++i;
4537 ++u;
4538 }
4539 while (i < iPrecision) {
4540 resultBuf.AppendChar('0');
4541 ++i;
4542 }
4543 resultBuf.AppendChar(0);
4544 args.GetReturnValue()->SetString(resultBuf.AsStringC());
Dan Sinclair1770c022016-03-14 14:14:16 -04004545}
dsinclair48d91dd2016-05-31 11:54:01 -07004546
4547// static
dsinclair12a6b0c2016-05-26 11:14:08 -07004548void CXFA_FM2JSContext::Stuff(CFXJSE_Value* pThis,
Dan Sinclair1770c022016-03-14 14:14:16 -04004549 const CFX_ByteStringC& szFuncName,
4550 CFXJSE_Arguments& args) {
4551 int32_t argc = args.GetLength();
dsinclaircf7f3222016-06-08 20:34:02 -07004552 if (argc < 3 || argc > 4) {
dsinclair8f3074b2016-06-02 17:45:25 -07004553 ToJSContext(pThis, nullptr)
4554 ->ThrowException(XFA_IDS_INCORRECT_NUMBER_OF_METHOD, L"Stuff");
dsinclaircf7f3222016-06-08 20:34:02 -07004555 return;
Dan Sinclair1770c022016-03-14 14:14:16 -04004556 }
dsinclaircf7f3222016-06-08 20:34:02 -07004557
4558 CFX_ByteString sourceString;
4559 CFX_ByteString insertString;
4560 int32_t iLength = 0;
4561 int32_t iStart = 0;
4562 int32_t iDelete = 0;
4563 std::unique_ptr<CFXJSE_Value> sourceValue = GetSimpleValue(pThis, args, 0);
4564 std::unique_ptr<CFXJSE_Value> startValue = GetSimpleValue(pThis, args, 1);
4565 std::unique_ptr<CFXJSE_Value> deleteValue = GetSimpleValue(pThis, args, 2);
4566 if (!sourceValue->IsNull() && !startValue->IsNull() &&
4567 !deleteValue->IsNull()) {
4568 ValueToUTF8String(sourceValue.get(), sourceString);
4569 iLength = sourceString.GetLength();
4570 iStart = std::min(iLength, std::max(1, static_cast<int32_t>(ValueToFloat(
4571 pThis, startValue.get()))));
4572 iDelete = std::max(
4573 0, static_cast<int32_t>(ValueToFloat(pThis, deleteValue.get())));
4574 }
4575
4576 if (argc > 3) {
4577 std::unique_ptr<CFXJSE_Value> insertValue = GetSimpleValue(pThis, args, 3);
4578 ValueToUTF8String(insertValue.get(), insertString);
4579 }
4580
4581 iStart -= 1;
4582 CFX_ByteTextBuf resultString;
4583 int32_t i = 0;
4584 while (i < iStart) {
4585 resultString.AppendChar(sourceString.GetAt(i));
4586 ++i;
4587 }
4588 resultString << insertString.AsStringC();
4589 i = iStart + iDelete;
4590 while (i < iLength) {
4591 resultString.AppendChar(sourceString.GetAt(i));
4592 ++i;
4593 }
4594 resultString.AppendChar(0);
4595 args.GetReturnValue()->SetString(resultString.AsStringC());
Dan Sinclair1770c022016-03-14 14:14:16 -04004596}
dsinclair48d91dd2016-05-31 11:54:01 -07004597
4598// static
dsinclair12a6b0c2016-05-26 11:14:08 -07004599void CXFA_FM2JSContext::Substr(CFXJSE_Value* pThis,
Dan Sinclair1770c022016-03-14 14:14:16 -04004600 const CFX_ByteStringC& szFuncName,
4601 CFXJSE_Arguments& args) {
dsinclaircf7f3222016-06-08 20:34:02 -07004602 if (args.GetLength() != 3) {
dsinclair8f3074b2016-06-02 17:45:25 -07004603 ToJSContext(pThis, nullptr)
4604 ->ThrowException(XFA_IDS_INCORRECT_NUMBER_OF_METHOD, L"Substr");
dsinclaircf7f3222016-06-08 20:34:02 -07004605 return;
Dan Sinclair1770c022016-03-14 14:14:16 -04004606 }
dsinclaircf7f3222016-06-08 20:34:02 -07004607
4608 std::unique_ptr<CFXJSE_Value> stringValue = GetSimpleValue(pThis, args, 0);
4609 std::unique_ptr<CFXJSE_Value> startValue = GetSimpleValue(pThis, args, 1);
4610 std::unique_ptr<CFXJSE_Value> endValue = GetSimpleValue(pThis, args, 2);
4611 if (ValueIsNull(pThis, stringValue.get()) ||
4612 (ValueIsNull(pThis, startValue.get())) ||
4613 (ValueIsNull(pThis, endValue.get()))) {
4614 args.GetReturnValue()->SetNull();
4615 return;
4616 }
4617
4618 CFX_ByteString szSourceStr;
4619 int32_t iStart = 0;
4620 int32_t iCount = 0;
4621 ValueToUTF8String(stringValue.get(), szSourceStr);
4622 int32_t iLength = szSourceStr.GetLength();
4623 if (iLength == 0) {
4624 args.GetReturnValue()->SetString("");
4625 return;
4626 }
4627
4628 iStart = std::min(
4629 iLength,
4630 std::max(1, static_cast<int32_t>(ValueToFloat(pThis, startValue.get()))));
4631 iCount =
4632 std::max(0, static_cast<int32_t>(ValueToFloat(pThis, endValue.get())));
4633
4634 iStart -= 1;
4635 args.GetReturnValue()->SetString(szSourceStr.Mid(iStart, iCount).AsStringC());
Dan Sinclair1770c022016-03-14 14:14:16 -04004636}
dsinclair48d91dd2016-05-31 11:54:01 -07004637
4638// static
dsinclair12a6b0c2016-05-26 11:14:08 -07004639void CXFA_FM2JSContext::Uuid(CFXJSE_Value* pThis,
Dan Sinclair1770c022016-03-14 14:14:16 -04004640 const CFX_ByteStringC& szFuncName,
4641 CFXJSE_Arguments& args) {
4642 int32_t argc = args.GetLength();
dsinclaircf7f3222016-06-08 20:34:02 -07004643 if (argc < 0 || argc > 1) {
dsinclair8f3074b2016-06-02 17:45:25 -07004644 ToJSContext(pThis, nullptr)
4645 ->ThrowException(XFA_IDS_INCORRECT_NUMBER_OF_METHOD, L"Uuid");
dsinclaircf7f3222016-06-08 20:34:02 -07004646 return;
Dan Sinclair1770c022016-03-14 14:14:16 -04004647 }
dsinclaircf7f3222016-06-08 20:34:02 -07004648
4649 int32_t iNum = 0;
4650 if (argc > 0) {
4651 std::unique_ptr<CFXJSE_Value> argOne = GetSimpleValue(pThis, args, 0);
4652 iNum = static_cast<int32_t>(ValueToFloat(pThis, argOne.get()));
4653 }
4654 FX_GUID guid;
4655 FX_GUID_CreateV4(&guid);
4656
4657 CFX_ByteString bsUId;
4658 FX_GUID_ToString(&guid, bsUId, iNum);
4659 args.GetReturnValue()->SetString(bsUId.AsStringC());
Dan Sinclair1770c022016-03-14 14:14:16 -04004660}
dsinclair48d91dd2016-05-31 11:54:01 -07004661
4662// static
dsinclair12a6b0c2016-05-26 11:14:08 -07004663void CXFA_FM2JSContext::Upper(CFXJSE_Value* pThis,
Dan Sinclair1770c022016-03-14 14:14:16 -04004664 const CFX_ByteStringC& szFuncName,
4665 CFXJSE_Arguments& args) {
4666 int32_t argc = args.GetLength();
dsinclaircf7f3222016-06-08 20:34:02 -07004667 if (argc < 1 || argc > 2) {
dsinclair8f3074b2016-06-02 17:45:25 -07004668 ToJSContext(pThis, nullptr)
4669 ->ThrowException(XFA_IDS_INCORRECT_NUMBER_OF_METHOD, L"Upper");
dsinclaircf7f3222016-06-08 20:34:02 -07004670 return;
Dan Sinclair1770c022016-03-14 14:14:16 -04004671 }
dsinclaircf7f3222016-06-08 20:34:02 -07004672
4673 std::unique_ptr<CFXJSE_Value> argOne = GetSimpleValue(pThis, args, 0);
4674 if (ValueIsNull(pThis, argOne.get())) {
4675 args.GetReturnValue()->SetNull();
4676 return;
4677 }
4678
4679 CFX_ByteString argString;
4680 ValueToUTF8String(argOne.get(), argString);
4681
4682 CFX_WideTextBuf upperStringBuf;
4683 CFX_WideString wsArgString = CFX_WideString::FromUTF8(argString.AsStringC());
4684 const FX_WCHAR* pData = wsArgString.c_str();
4685 int32_t i = 0;
4686 while (i < wsArgString.GetLength()) {
4687 int32_t ch = pData[i];
4688 if ((ch >= 0x61 && ch <= 0x7A) || (ch >= 0xE0 && ch <= 0xFE))
4689 ch -= 32;
4690 else if (ch == 0x101 || ch == 0x103 || ch == 0x105)
4691 ch -= 1;
4692
4693 upperStringBuf.AppendChar(ch);
4694 ++i;
4695 }
4696 upperStringBuf.AppendChar(0);
4697
4698 args.GetReturnValue()->SetString(
4699 FX_UTF8Encode(upperStringBuf.GetBuffer(), upperStringBuf.GetLength())
4700 .AsStringC());
Dan Sinclair1770c022016-03-14 14:14:16 -04004701}
dsinclair48d91dd2016-05-31 11:54:01 -07004702
4703// static
dsinclair12a6b0c2016-05-26 11:14:08 -07004704void CXFA_FM2JSContext::WordNum(CFXJSE_Value* pThis,
Dan Sinclair1770c022016-03-14 14:14:16 -04004705 const CFX_ByteStringC& szFuncName,
4706 CFXJSE_Arguments& args) {
4707 int32_t argc = args.GetLength();
dsinclaircf7f3222016-06-08 20:34:02 -07004708 if (argc < 1 || argc > 3) {
dsinclair8f3074b2016-06-02 17:45:25 -07004709 ToJSContext(pThis, nullptr)
4710 ->ThrowException(XFA_IDS_INCORRECT_NUMBER_OF_METHOD, L"WordNum");
dsinclaircf7f3222016-06-08 20:34:02 -07004711 return;
Dan Sinclair1770c022016-03-14 14:14:16 -04004712 }
dsinclaircf7f3222016-06-08 20:34:02 -07004713
4714 std::unique_ptr<CFXJSE_Value> numberValue = GetSimpleValue(pThis, args, 0);
4715 if (numberValue->IsNull()) {
4716 args.GetReturnValue()->SetNull();
4717 return;
4718 }
4719 FX_FLOAT fNumber = ValueToFloat(pThis, numberValue.get());
4720
4721 int32_t iIdentifier = 0;
4722 if (argc > 1) {
4723 std::unique_ptr<CFXJSE_Value> identifierValue =
4724 GetSimpleValue(pThis, args, 1);
4725 if (identifierValue->IsNull()) {
4726 args.GetReturnValue()->SetNull();
4727 return;
4728 }
4729 iIdentifier =
4730 static_cast<int32_t>(ValueToFloat(pThis, identifierValue.get()));
4731 }
4732
4733 CFX_ByteString localeString;
4734 if (argc > 2) {
4735 std::unique_ptr<CFXJSE_Value> localeValue = GetSimpleValue(pThis, args, 2);
4736 if (localeValue->IsNull()) {
4737 args.GetReturnValue()->SetNull();
4738 return;
4739 }
4740 ValueToUTF8String(localeValue.get(), localeString);
4741 }
4742
4743 if (fNumber < 0.0f || fNumber > 922337203685477550.0f) {
4744 args.GetReturnValue()->SetString("*");
4745 return;
4746 }
4747
4748 CFX_ByteString numberString;
4749 numberString.Format("%.2f", fNumber);
4750
4751 CFX_ByteTextBuf resultBuf;
4752 WordUS(numberString.AsStringC(), iIdentifier, resultBuf);
4753 args.GetReturnValue()->SetString(resultBuf.AsStringC());
Dan Sinclair1770c022016-03-14 14:14:16 -04004754}
dsinclair48d91dd2016-05-31 11:54:01 -07004755
4756// static
Dan Sinclair1770c022016-03-14 14:14:16 -04004757void CXFA_FM2JSContext::TrillionUS(const CFX_ByteStringC& szData,
4758 CFX_ByteTextBuf& strBuf) {
4759 CFX_ByteStringC pUnits[] = {"zero", "one", "two", "three", "four",
4760 "five", "six", "seven", "eight", "nine"};
4761 CFX_ByteStringC pCapUnits[] = {"Zero", "One", "Two", "Three", "Four",
4762 "Five", "Six", "Seven", "Eight", "Nine"};
4763 CFX_ByteStringC pTens[] = {"Ten", "Eleven", "Twelve", "Thirteen",
4764 "Fourteen", "Fifteen", "Sixteen", "Seventeen",
4765 "Eighteen", "Nineteen"};
4766 CFX_ByteStringC pLastTens[] = {"Twenty", "Thirty", "Forty", "Fifty",
4767 "Sixty", "Seventy", "Eighty", "Ninety"};
4768 CFX_ByteStringC pComm[] = {" Hundred ", " Thousand ", " Million ",
4769 " Billion ", "Trillion"};
dsinclair179bebb2016-04-05 11:02:18 -07004770 const FX_CHAR* pData = szData.c_str();
Dan Sinclair1770c022016-03-14 14:14:16 -04004771 int32_t iLength = szData.GetLength();
dsinclair947c8732016-06-08 20:40:30 -07004772 int32_t iComm = 0;
4773 if (iLength > 12)
Dan Sinclair1770c022016-03-14 14:14:16 -04004774 iComm = 4;
dsinclair947c8732016-06-08 20:40:30 -07004775 else if (iLength > 9)
Dan Sinclair1770c022016-03-14 14:14:16 -04004776 iComm = 3;
dsinclair947c8732016-06-08 20:40:30 -07004777 else if (iLength > 6)
Dan Sinclair1770c022016-03-14 14:14:16 -04004778 iComm = 2;
dsinclair947c8732016-06-08 20:40:30 -07004779 else if (iLength > 3)
Dan Sinclair1770c022016-03-14 14:14:16 -04004780 iComm = 1;
dsinclair947c8732016-06-08 20:40:30 -07004781
Dan Sinclair1770c022016-03-14 14:14:16 -04004782 int32_t iFirstCount = iLength % 3;
dsinclair947c8732016-06-08 20:40:30 -07004783 if (iFirstCount == 0)
Dan Sinclair1770c022016-03-14 14:14:16 -04004784 iFirstCount = 3;
dsinclair947c8732016-06-08 20:40:30 -07004785
4786 int32_t iIndex = 0;
Dan Sinclair1770c022016-03-14 14:14:16 -04004787 if (iFirstCount == 3) {
dsinclair2b6d64e2016-06-06 11:39:42 -07004788 if (pData[iIndex] != '0') {
4789 strBuf << pCapUnits[pData[iIndex] - '0'];
Dan Sinclair1770c022016-03-14 14:14:16 -04004790 strBuf << pComm[0];
4791 }
dsinclair2b6d64e2016-06-06 11:39:42 -07004792 if (pData[iIndex + 1] == '0') {
4793 strBuf << pCapUnits[pData[iIndex + 2] - '0'];
Dan Sinclair1770c022016-03-14 14:14:16 -04004794 } else {
dsinclair2b6d64e2016-06-06 11:39:42 -07004795 if (pData[iIndex + 1] > '1') {
4796 strBuf << pLastTens[pData[iIndex + 1] - '2'];
Dan Sinclair1770c022016-03-14 14:14:16 -04004797 strBuf << "-";
dsinclair2b6d64e2016-06-06 11:39:42 -07004798 strBuf << pUnits[pData[iIndex + 2] - '0'];
4799 } else if (pData[iIndex + 1] == '1') {
4800 strBuf << pTens[pData[iIndex + 2] - '0'];
4801 } else if (pData[iIndex + 1] == '0') {
4802 strBuf << pCapUnits[pData[iIndex + 2] - '0'];
Dan Sinclair1770c022016-03-14 14:14:16 -04004803 }
4804 }
4805 iIndex += 3;
4806 } else if (iFirstCount == 2) {
dsinclair2b6d64e2016-06-06 11:39:42 -07004807 if (pData[iIndex] == '0') {
4808 strBuf << pCapUnits[pData[iIndex + 1] - '0'];
Dan Sinclair1770c022016-03-14 14:14:16 -04004809 } else {
dsinclair2b6d64e2016-06-06 11:39:42 -07004810 if (pData[iIndex] > '1') {
4811 strBuf << pLastTens[pData[iIndex] - '2'];
Dan Sinclair1770c022016-03-14 14:14:16 -04004812 strBuf << "-";
dsinclair2b6d64e2016-06-06 11:39:42 -07004813 strBuf << pUnits[pData[iIndex + 1] - '0'];
4814 } else if (pData[iIndex] == '1') {
4815 strBuf << pTens[pData[iIndex + 1] - '0'];
4816 } else if (pData[iIndex] == '0') {
4817 strBuf << pCapUnits[pData[iIndex + 1] - '0'];
Dan Sinclair1770c022016-03-14 14:14:16 -04004818 }
4819 }
4820 iIndex += 2;
4821 } else if (iFirstCount == 1) {
dsinclair2b6d64e2016-06-06 11:39:42 -07004822 strBuf << pCapUnits[pData[iIndex] - '0'];
Dan Sinclair1770c022016-03-14 14:14:16 -04004823 iIndex += 1;
4824 }
4825 if (iLength > 3 && iFirstCount > 0) {
4826 strBuf << pComm[iComm];
4827 --iComm;
4828 }
4829 while (iIndex < iLength) {
dsinclair2b6d64e2016-06-06 11:39:42 -07004830 if (pData[iIndex] != '0') {
4831 strBuf << pCapUnits[pData[iIndex] - '0'];
Dan Sinclair1770c022016-03-14 14:14:16 -04004832 strBuf << pComm[0];
4833 }
dsinclair2b6d64e2016-06-06 11:39:42 -07004834 if (pData[iIndex + 1] == '0') {
4835 strBuf << pCapUnits[pData[iIndex + 2] - '0'];
Dan Sinclair1770c022016-03-14 14:14:16 -04004836 } else {
dsinclair2b6d64e2016-06-06 11:39:42 -07004837 if (pData[iIndex + 1] > '1') {
4838 strBuf << pLastTens[pData[iIndex + 1] - '2'];
Dan Sinclair1770c022016-03-14 14:14:16 -04004839 strBuf << "-";
dsinclair2b6d64e2016-06-06 11:39:42 -07004840 strBuf << pUnits[pData[iIndex + 2] - '0'];
4841 } else if (pData[iIndex + 1] == '1') {
4842 strBuf << pTens[pData[iIndex + 2] - '0'];
4843 } else if (pData[iIndex + 1] == '0') {
4844 strBuf << pCapUnits[pData[iIndex + 2] - '0'];
Dan Sinclair1770c022016-03-14 14:14:16 -04004845 }
4846 }
4847 if (iIndex < iLength - 3) {
4848 strBuf << pComm[iComm];
4849 --iComm;
4850 }
4851 iIndex += 3;
4852 }
4853}
dsinclair48d91dd2016-05-31 11:54:01 -07004854
4855// static
Dan Sinclair1770c022016-03-14 14:14:16 -04004856void CXFA_FM2JSContext::WordUS(const CFX_ByteStringC& szData,
4857 int32_t iStyle,
4858 CFX_ByteTextBuf& strBuf) {
dsinclair179bebb2016-04-05 11:02:18 -07004859 const FX_CHAR* pData = szData.c_str();
Dan Sinclair1770c022016-03-14 14:14:16 -04004860 int32_t iLength = szData.GetLength();
dsinclair947c8732016-06-08 20:40:30 -07004861 if (iStyle < 0 || iStyle > 2) {
4862 return;
4863 }
4864
4865 int32_t iIndex = 0;
4866 while (iIndex < iLength) {
4867 if (pData[iIndex] == '.')
Dan Sinclair1770c022016-03-14 14:14:16 -04004868 break;
dsinclair947c8732016-06-08 20:40:30 -07004869 ++iIndex;
4870 }
4871 int32_t iInteger = iIndex;
4872 iIndex = 0;
4873 while (iIndex < iInteger) {
4874 int32_t iCount = (iInteger - iIndex) % 12;
4875 if (!iCount && iInteger - iIndex > 0)
4876 iCount = 12;
4877
4878 TrillionUS(CFX_ByteStringC(pData + iIndex, iCount), strBuf);
4879 iIndex += iCount;
4880 if (iIndex < iInteger)
4881 strBuf << " Trillion ";
4882 }
4883
4884 if (iStyle > 0)
4885 strBuf << " Dollars";
4886
4887 if (iStyle > 1 && iInteger < iLength) {
4888 strBuf << " And ";
4889 iIndex = iInteger + 1;
4890 while (iIndex < iLength) {
4891 int32_t iCount = (iLength - iIndex) % 12;
4892 if (!iCount && iLength - iIndex > 0)
4893 iCount = 12;
4894
4895 TrillionUS(CFX_ByteStringC(pData + iIndex, iCount), strBuf);
4896 iIndex += iCount;
4897 if (iIndex < iLength)
4898 strBuf << " Trillion ";
4899 }
4900 strBuf << " Cents";
Dan Sinclair1770c022016-03-14 14:14:16 -04004901 }
4902}
dsinclair48d91dd2016-05-31 11:54:01 -07004903
4904// static
dsinclair12a6b0c2016-05-26 11:14:08 -07004905void CXFA_FM2JSContext::Get(CFXJSE_Value* pThis,
Dan Sinclair1770c022016-03-14 14:14:16 -04004906 const CFX_ByteStringC& szFuncName,
4907 CFXJSE_Arguments& args) {
dsinclair8f3074b2016-06-02 17:45:25 -07004908 CXFA_FM2JSContext* pContext = ToJSContext(pThis, nullptr);
dsinclair947c8732016-06-08 20:40:30 -07004909 if (args.GetLength() != 1) {
dsinclair2235b7b2016-06-02 07:42:25 -07004910 pContext->ThrowException(XFA_IDS_INCORRECT_NUMBER_OF_METHOD, L"Get");
dsinclair947c8732016-06-08 20:40:30 -07004911 return;
Dan Sinclair1770c022016-03-14 14:14:16 -04004912 }
dsinclair947c8732016-06-08 20:40:30 -07004913
4914 CXFA_Document* pDoc = pContext->GetDocument();
4915 if (!pDoc)
4916 return;
4917
4918 IXFA_AppProvider* pAppProvider =
4919 pDoc->GetParser()->GetNotify()->GetAppProvider();
4920 if (!pAppProvider)
4921 return;
4922
4923 std::unique_ptr<CFXJSE_Value> argOne = GetSimpleValue(pThis, args, 0);
4924 CFX_ByteString urlString;
4925 ValueToUTF8String(argOne.get(), urlString);
4926 IFX_FileRead* pFile = pAppProvider->DownloadURL(
4927 CFX_WideString::FromUTF8(urlString.AsStringC()));
4928 if (!pFile)
4929 return;
4930
4931 int32_t size = pFile->GetSize();
4932 std::unique_ptr<uint8_t> pData(FX_Alloc(uint8_t, size));
4933 pFile->ReadBlock(pData.get(), size);
4934 args.GetReturnValue()->SetString(CFX_ByteStringC(pData.get(), size));
4935 pFile->Release();
Dan Sinclair1770c022016-03-14 14:14:16 -04004936}
dsinclair48d91dd2016-05-31 11:54:01 -07004937
4938// static
dsinclair12a6b0c2016-05-26 11:14:08 -07004939void CXFA_FM2JSContext::Post(CFXJSE_Value* pThis,
Dan Sinclair1770c022016-03-14 14:14:16 -04004940 const CFX_ByteStringC& szFuncName,
4941 CFXJSE_Arguments& args) {
dsinclair8f3074b2016-06-02 17:45:25 -07004942 CXFA_FM2JSContext* pContext = ToJSContext(pThis, nullptr);
Dan Sinclair1770c022016-03-14 14:14:16 -04004943 int32_t argc = args.GetLength();
dsinclair947c8732016-06-08 20:40:30 -07004944 if (argc < 2 || argc > 5) {
dsinclair2235b7b2016-06-02 07:42:25 -07004945 pContext->ThrowException(XFA_IDS_INCORRECT_NUMBER_OF_METHOD, L"Post");
dsinclair947c8732016-06-08 20:40:30 -07004946 return;
Dan Sinclair1770c022016-03-14 14:14:16 -04004947 }
dsinclair947c8732016-06-08 20:40:30 -07004948
4949 CXFA_Document* pDoc = pContext->GetDocument();
4950 if (!pDoc)
4951 return;
4952
4953 IXFA_AppProvider* pAppProvider =
4954 pDoc->GetParser()->GetNotify()->GetAppProvider();
4955 if (!pAppProvider)
4956 return;
4957
4958 CFX_ByteString bsURL;
4959 std::unique_ptr<CFXJSE_Value> argOne = GetSimpleValue(pThis, args, 0);
4960 ValueToUTF8String(argOne.get(), bsURL);
4961
4962 CFX_ByteString bsData;
4963 std::unique_ptr<CFXJSE_Value> argTwo = GetSimpleValue(pThis, args, 1);
4964 ValueToUTF8String(argTwo.get(), bsData);
4965
4966 CFX_ByteString bsContentType;
4967 if (argc > 2) {
4968 std::unique_ptr<CFXJSE_Value> argThree = GetSimpleValue(pThis, args, 2);
4969 ValueToUTF8String(argThree.get(), bsContentType);
4970 }
4971
4972 CFX_ByteString bsEncode;
4973 if (argc > 3) {
4974 std::unique_ptr<CFXJSE_Value> argFour = GetSimpleValue(pThis, args, 3);
4975 ValueToUTF8String(argFour.get(), bsEncode);
4976 }
4977
4978 CFX_ByteString bsHeader;
4979 if (argc > 4) {
4980 std::unique_ptr<CFXJSE_Value> argFive = GetSimpleValue(pThis, args, 4);
4981 ValueToUTF8String(argFive.get(), bsHeader);
4982 }
4983
4984 CFX_WideString decodedResponse;
4985 if (!pAppProvider->PostRequestURL(
4986 CFX_WideString::FromUTF8(bsURL.AsStringC()),
4987 CFX_WideString::FromUTF8(bsData.AsStringC()),
4988 CFX_WideString::FromUTF8(bsContentType.AsStringC()),
4989 CFX_WideString::FromUTF8(bsEncode.AsStringC()),
4990 CFX_WideString::FromUTF8(bsHeader.AsStringC()), decodedResponse)) {
4991 pContext->ThrowException(XFA_IDS_SERVER_DENY);
4992 return;
4993 }
4994
4995 args.GetReturnValue()->SetString(
4996 FX_UTF8Encode(decodedResponse.c_str(), decodedResponse.GetLength())
4997 .AsStringC());
Dan Sinclair1770c022016-03-14 14:14:16 -04004998}
dsinclair48d91dd2016-05-31 11:54:01 -07004999
5000// static
dsinclair12a6b0c2016-05-26 11:14:08 -07005001void CXFA_FM2JSContext::Put(CFXJSE_Value* pThis,
Dan Sinclair1770c022016-03-14 14:14:16 -04005002 const CFX_ByteStringC& szFuncName,
5003 CFXJSE_Arguments& args) {
dsinclair8f3074b2016-06-02 17:45:25 -07005004 CXFA_FM2JSContext* pContext = ToJSContext(pThis, nullptr);
Dan Sinclair1770c022016-03-14 14:14:16 -04005005 int32_t argc = args.GetLength();
dsinclair947c8732016-06-08 20:40:30 -07005006 if (argc < 2 || argc > 3) {
dsinclair2235b7b2016-06-02 07:42:25 -07005007 pContext->ThrowException(XFA_IDS_INCORRECT_NUMBER_OF_METHOD, L"Put");
dsinclair947c8732016-06-08 20:40:30 -07005008 return;
Dan Sinclair1770c022016-03-14 14:14:16 -04005009 }
dsinclair947c8732016-06-08 20:40:30 -07005010
5011 CXFA_Document* pDoc = pContext->GetDocument();
5012 if (!pDoc)
5013 return;
5014
5015 IXFA_AppProvider* pAppProvider =
5016 pDoc->GetParser()->GetNotify()->GetAppProvider();
5017 if (!pAppProvider)
5018 return;
5019
5020 CFX_ByteString bsURL;
5021 std::unique_ptr<CFXJSE_Value> argOne = GetSimpleValue(pThis, args, 0);
5022 ValueToUTF8String(argOne.get(), bsURL);
5023
5024 CFX_ByteString bsData;
5025 std::unique_ptr<CFXJSE_Value> argTwo = GetSimpleValue(pThis, args, 1);
5026 ValueToUTF8String(argTwo.get(), bsData);
5027
5028 CFX_ByteString bsEncode;
5029 if (argc > 2) {
5030 std::unique_ptr<CFXJSE_Value> argThree = GetSimpleValue(pThis, args, 2);
5031 ValueToUTF8String(argThree.get(), bsEncode);
5032 }
5033
5034 if (!pAppProvider->PutRequestURL(
5035 CFX_WideString::FromUTF8(bsURL.AsStringC()),
5036 CFX_WideString::FromUTF8(bsData.AsStringC()),
5037 CFX_WideString::FromUTF8(bsEncode.AsStringC()))) {
5038 pContext->ThrowException(XFA_IDS_SERVER_DENY);
5039 return;
5040 }
5041
5042 args.GetReturnValue()->SetString("");
Dan Sinclair1770c022016-03-14 14:14:16 -04005043}
dsinclair48d91dd2016-05-31 11:54:01 -07005044
5045// static
dsinclair12a6b0c2016-05-26 11:14:08 -07005046void CXFA_FM2JSContext::assign_value_operator(CFXJSE_Value* pThis,
Dan Sinclair1770c022016-03-14 14:14:16 -04005047 const CFX_ByteStringC& szFuncName,
5048 CFXJSE_Arguments& args) {
dsinclair8f3074b2016-06-02 17:45:25 -07005049 CXFA_FM2JSContext* pContext = ToJSContext(pThis, nullptr);
dsinclair947c8732016-06-08 20:40:30 -07005050 if (args.GetLength() != 2) {
5051 pContext->ThrowException(XFA_IDS_COMPILER_ERROR);
5052 return;
5053 }
5054
5055 std::unique_ptr<CFXJSE_Value> lValue = args.GetValue(0);
5056 std::unique_ptr<CFXJSE_Value> rValue = GetSimpleValue(pThis, args, 1);
5057 if (lValue->IsArray()) {
5058 v8::Isolate* pIsolate = pContext->GetScriptRuntime();
5059 std::unique_ptr<CFXJSE_Value> leftLengthValue(new CFXJSE_Value(pIsolate));
5060 lValue->GetObjectProperty("length", leftLengthValue.get());
5061 int32_t iLeftLength = leftLengthValue->ToInteger();
5062 std::unique_ptr<CFXJSE_Value> jsObjectValue(new CFXJSE_Value(pIsolate));
5063 std::unique_ptr<CFXJSE_Value> propertyValue(new CFXJSE_Value(pIsolate));
5064 lValue->GetObjectPropertyByIdx(1, propertyValue.get());
5065 if (propertyValue->IsNull()) {
5066 for (int32_t i = 2; i < iLeftLength; i++) {
5067 lValue->GetObjectPropertyByIdx(i, jsObjectValue.get());
5068 if (!SetObjectDefaultValue(jsObjectValue.get(), rValue.get())) {
5069 pContext->ThrowException(XFA_IDS_NOT_DEFAUL_VALUE);
5070 return;
Dan Sinclair1770c022016-03-14 14:14:16 -04005071 }
5072 }
dsinclair947c8732016-06-08 20:40:30 -07005073 } else {
dsinclair947c8732016-06-08 20:40:30 -07005074 for (int32_t i = 2; i < iLeftLength; i++) {
5075 lValue->GetObjectPropertyByIdx(i, jsObjectValue.get());
dsinclair2f5582f2016-06-09 11:48:23 -07005076 jsObjectValue->SetObjectProperty(propertyValue->ToString().AsStringC(),
5077 rValue.get());
Dan Sinclair1770c022016-03-14 14:14:16 -04005078 }
5079 }
dsinclair947c8732016-06-08 20:40:30 -07005080 } else if (lValue->IsObject()) {
5081 if (!SetObjectDefaultValue(lValue.get(), rValue.get())) {
5082 pContext->ThrowException(XFA_IDS_NOT_DEFAUL_VALUE);
5083 return;
5084 }
Dan Sinclair1770c022016-03-14 14:14:16 -04005085 }
dsinclair947c8732016-06-08 20:40:30 -07005086 args.GetReturnValue()->Assign(rValue.get());
Dan Sinclair1770c022016-03-14 14:14:16 -04005087}
dsinclair48d91dd2016-05-31 11:54:01 -07005088
5089// static
dsinclair12a6b0c2016-05-26 11:14:08 -07005090void CXFA_FM2JSContext::logical_or_operator(CFXJSE_Value* pThis,
Dan Sinclair1770c022016-03-14 14:14:16 -04005091 const CFX_ByteStringC& szFuncName,
5092 CFXJSE_Arguments& args) {
dsinclair947c8732016-06-08 20:40:30 -07005093 if (args.GetLength() != 2) {
dsinclair8f3074b2016-06-02 17:45:25 -07005094 ToJSContext(pThis, nullptr)->ThrowException(XFA_IDS_COMPILER_ERROR);
dsinclair947c8732016-06-08 20:40:30 -07005095 return;
Dan Sinclair1770c022016-03-14 14:14:16 -04005096 }
dsinclair947c8732016-06-08 20:40:30 -07005097
5098 std::unique_ptr<CFXJSE_Value> argFirst = GetSimpleValue(pThis, args, 0);
5099 std::unique_ptr<CFXJSE_Value> argSecond = GetSimpleValue(pThis, args, 1);
5100 if (argFirst->IsNull() && argSecond->IsNull()) {
5101 args.GetReturnValue()->SetNull();
5102 return;
5103 }
5104
5105 FX_FLOAT first = ValueToFloat(pThis, argFirst.get());
5106 FX_FLOAT second = ValueToFloat(pThis, argSecond.get());
5107 args.GetReturnValue()->SetInteger((first || second) ? 1 : 0);
Dan Sinclair1770c022016-03-14 14:14:16 -04005108}
dsinclair48d91dd2016-05-31 11:54:01 -07005109
5110// static
dsinclair12a6b0c2016-05-26 11:14:08 -07005111void CXFA_FM2JSContext::logical_and_operator(CFXJSE_Value* pThis,
Dan Sinclair1770c022016-03-14 14:14:16 -04005112 const CFX_ByteStringC& szFuncName,
5113 CFXJSE_Arguments& args) {
dsinclair947c8732016-06-08 20:40:30 -07005114 if (args.GetLength() != 2) {
dsinclair8f3074b2016-06-02 17:45:25 -07005115 ToJSContext(pThis, nullptr)->ThrowException(XFA_IDS_COMPILER_ERROR);
dsinclair947c8732016-06-08 20:40:30 -07005116 return;
Dan Sinclair1770c022016-03-14 14:14:16 -04005117 }
dsinclair947c8732016-06-08 20:40:30 -07005118
5119 std::unique_ptr<CFXJSE_Value> argFirst = GetSimpleValue(pThis, args, 0);
5120 std::unique_ptr<CFXJSE_Value> argSecond = GetSimpleValue(pThis, args, 1);
5121 if (argFirst->IsNull() && argSecond->IsNull()) {
5122 args.GetReturnValue()->SetNull();
5123 return;
5124 }
5125
5126 FX_FLOAT first = ValueToFloat(pThis, argFirst.get());
5127 FX_FLOAT second = ValueToFloat(pThis, argSecond.get());
5128 args.GetReturnValue()->SetInteger((first && second) ? 1 : 0);
Dan Sinclair1770c022016-03-14 14:14:16 -04005129}
dsinclair48d91dd2016-05-31 11:54:01 -07005130
5131// static
dsinclair12a6b0c2016-05-26 11:14:08 -07005132void CXFA_FM2JSContext::equality_operator(CFXJSE_Value* pThis,
Dan Sinclair1770c022016-03-14 14:14:16 -04005133 const CFX_ByteStringC& szFuncName,
5134 CFXJSE_Arguments& args) {
dsinclair947c8732016-06-08 20:40:30 -07005135 if (args.GetLength() != 2) {
dsinclair8f3074b2016-06-02 17:45:25 -07005136 ToJSContext(pThis, nullptr)->ThrowException(XFA_IDS_COMPILER_ERROR);
dsinclair947c8732016-06-08 20:40:30 -07005137 return;
Dan Sinclair1770c022016-03-14 14:14:16 -04005138 }
dsinclair947c8732016-06-08 20:40:30 -07005139
5140 if (fm_ref_equal(pThis, args)) {
5141 args.GetReturnValue()->SetInteger(1);
5142 return;
5143 }
5144
5145 std::unique_ptr<CFXJSE_Value> argFirst = GetSimpleValue(pThis, args, 0);
5146 std::unique_ptr<CFXJSE_Value> argSecond = GetSimpleValue(pThis, args, 1);
5147 if (argFirst->IsNull() || argSecond->IsNull()) {
5148 args.GetReturnValue()->SetInteger(
5149 (argFirst->IsNull() && argSecond->IsNull()) ? 1 : 0);
5150 return;
5151 }
5152
5153 if (argFirst->IsString() && argSecond->IsString()) {
dsinclair2f5582f2016-06-09 11:48:23 -07005154 args.GetReturnValue()->SetInteger(argFirst->ToString() ==
5155 argSecond->ToString());
dsinclair947c8732016-06-08 20:40:30 -07005156 return;
5157 }
5158
5159 FX_DOUBLE first = ValueToDouble(pThis, argFirst.get());
5160 FX_DOUBLE second = ValueToDouble(pThis, argSecond.get());
5161 args.GetReturnValue()->SetInteger((first == second) ? 1 : 0);
Dan Sinclair1770c022016-03-14 14:14:16 -04005162}
dsinclair48d91dd2016-05-31 11:54:01 -07005163
5164// static
dsinclair12a6b0c2016-05-26 11:14:08 -07005165void CXFA_FM2JSContext::notequality_operator(CFXJSE_Value* pThis,
Dan Sinclair1770c022016-03-14 14:14:16 -04005166 const CFX_ByteStringC& szFuncName,
5167 CFXJSE_Arguments& args) {
dsinclair947c8732016-06-08 20:40:30 -07005168 if (args.GetLength() != 2) {
dsinclair8f3074b2016-06-02 17:45:25 -07005169 ToJSContext(pThis, nullptr)->ThrowException(XFA_IDS_COMPILER_ERROR);
dsinclair947c8732016-06-08 20:40:30 -07005170 return;
Dan Sinclair1770c022016-03-14 14:14:16 -04005171 }
dsinclair947c8732016-06-08 20:40:30 -07005172
5173 if (fm_ref_equal(pThis, args)) {
5174 args.GetReturnValue()->SetInteger(0);
5175 return;
5176 }
5177
5178 std::unique_ptr<CFXJSE_Value> argFirst = GetSimpleValue(pThis, args, 0);
5179 std::unique_ptr<CFXJSE_Value> argSecond = GetSimpleValue(pThis, args, 1);
5180 if (argFirst->IsNull() || argSecond->IsNull()) {
5181 args.GetReturnValue()->SetInteger(
5182 (argFirst->IsNull() && argSecond->IsNull()) ? 0 : 1);
5183 return;
5184 }
5185
5186 if (argFirst->IsString() && argSecond->IsString()) {
dsinclair2f5582f2016-06-09 11:48:23 -07005187 args.GetReturnValue()->SetInteger(argFirst->ToString() !=
5188 argSecond->ToString());
dsinclair947c8732016-06-08 20:40:30 -07005189 return;
5190 }
5191
5192 FX_DOUBLE first = ValueToDouble(pThis, argFirst.get());
5193 FX_DOUBLE second = ValueToDouble(pThis, argSecond.get());
5194 args.GetReturnValue()->SetInteger(first != second);
Dan Sinclair1770c022016-03-14 14:14:16 -04005195}
dsinclair48d91dd2016-05-31 11:54:01 -07005196
5197// static
dsinclair12a6b0c2016-05-26 11:14:08 -07005198FX_BOOL CXFA_FM2JSContext::fm_ref_equal(CFXJSE_Value* pThis,
Dan Sinclair1770c022016-03-14 14:14:16 -04005199 CFXJSE_Arguments& args) {
dsinclair86fad992016-05-31 11:34:04 -07005200 std::unique_ptr<CFXJSE_Value> argFirst = args.GetValue(0);
5201 std::unique_ptr<CFXJSE_Value> argSecond = args.GetValue(1);
dsinclair947c8732016-06-08 20:40:30 -07005202 if (!argFirst->IsArray() || !argSecond->IsArray())
5203 return FALSE;
5204
5205 v8::Isolate* pIsolate = ToJSContext(pThis, nullptr)->GetScriptRuntime();
5206 std::unique_ptr<CFXJSE_Value> firstFlagValue(new CFXJSE_Value(pIsolate));
5207 std::unique_ptr<CFXJSE_Value> secondFlagValue(new CFXJSE_Value(pIsolate));
5208 argFirst->GetObjectPropertyByIdx(0, firstFlagValue.get());
5209 argSecond->GetObjectPropertyByIdx(0, secondFlagValue.get());
5210 if (firstFlagValue->ToInteger() != 3 || secondFlagValue->ToInteger() != 3)
5211 return FALSE;
5212
5213 std::unique_ptr<CFXJSE_Value> firstJSObject(new CFXJSE_Value(pIsolate));
5214 std::unique_ptr<CFXJSE_Value> secondJSObject(new CFXJSE_Value(pIsolate));
5215 argFirst->GetObjectPropertyByIdx(2, firstJSObject.get());
5216 argSecond->GetObjectPropertyByIdx(2, secondJSObject.get());
5217 if (firstJSObject->IsNull() || secondJSObject->IsNull())
5218 return FALSE;
5219
5220 return (firstJSObject->ToHostObject(nullptr) ==
5221 secondJSObject->ToHostObject(nullptr));
Dan Sinclair1770c022016-03-14 14:14:16 -04005222}
dsinclair48d91dd2016-05-31 11:54:01 -07005223
5224// static
dsinclair12a6b0c2016-05-26 11:14:08 -07005225void CXFA_FM2JSContext::less_operator(CFXJSE_Value* pThis,
Dan Sinclair1770c022016-03-14 14:14:16 -04005226 const CFX_ByteStringC& szFuncName,
5227 CFXJSE_Arguments& args) {
dsinclair947c8732016-06-08 20:40:30 -07005228 if (args.GetLength() != 2) {
dsinclair8f3074b2016-06-02 17:45:25 -07005229 ToJSContext(pThis, nullptr)->ThrowException(XFA_IDS_COMPILER_ERROR);
dsinclair947c8732016-06-08 20:40:30 -07005230 return;
Dan Sinclair1770c022016-03-14 14:14:16 -04005231 }
dsinclair947c8732016-06-08 20:40:30 -07005232
5233 std::unique_ptr<CFXJSE_Value> argFirst = GetSimpleValue(pThis, args, 0);
5234 std::unique_ptr<CFXJSE_Value> argSecond = GetSimpleValue(pThis, args, 1);
5235 if (argFirst->IsNull() || argSecond->IsNull()) {
5236 args.GetReturnValue()->SetInteger(0);
5237 return;
5238 }
5239
5240 if (argFirst->IsString() && argSecond->IsString()) {
dsinclair947c8732016-06-08 20:40:30 -07005241 args.GetReturnValue()->SetInteger(
dsinclair2f5582f2016-06-09 11:48:23 -07005242 argFirst->ToString().Compare(argSecond->ToString().AsStringC()) == -1);
dsinclair947c8732016-06-08 20:40:30 -07005243 return;
5244 }
5245
5246 FX_DOUBLE first = ValueToDouble(pThis, argFirst.get());
5247 FX_DOUBLE second = ValueToDouble(pThis, argSecond.get());
5248 args.GetReturnValue()->SetInteger((first < second) ? 1 : 0);
Dan Sinclair1770c022016-03-14 14:14:16 -04005249}
dsinclair48d91dd2016-05-31 11:54:01 -07005250
5251// static
dsinclair12a6b0c2016-05-26 11:14:08 -07005252void CXFA_FM2JSContext::lessequal_operator(CFXJSE_Value* pThis,
Dan Sinclair1770c022016-03-14 14:14:16 -04005253 const CFX_ByteStringC& szFuncName,
5254 CFXJSE_Arguments& args) {
dsinclair947c8732016-06-08 20:40:30 -07005255 if (args.GetLength() != 2) {
dsinclair8f3074b2016-06-02 17:45:25 -07005256 ToJSContext(pThis, nullptr)->ThrowException(XFA_IDS_COMPILER_ERROR);
dsinclair947c8732016-06-08 20:40:30 -07005257 return;
Dan Sinclair1770c022016-03-14 14:14:16 -04005258 }
dsinclair947c8732016-06-08 20:40:30 -07005259
5260 std::unique_ptr<CFXJSE_Value> argFirst = GetSimpleValue(pThis, args, 0);
5261 std::unique_ptr<CFXJSE_Value> argSecond = GetSimpleValue(pThis, args, 1);
5262 if (argFirst->IsNull() || argSecond->IsNull()) {
5263 args.GetReturnValue()->SetInteger(
5264 (argFirst->IsNull() && argSecond->IsNull()) ? 1 : 0);
5265 return;
5266 }
5267
5268 if (argFirst->IsString() && argSecond->IsString()) {
dsinclair947c8732016-06-08 20:40:30 -07005269 args.GetReturnValue()->SetInteger(
dsinclair2f5582f2016-06-09 11:48:23 -07005270 argFirst->ToString().Compare(argSecond->ToString().AsStringC()) != 1);
dsinclair947c8732016-06-08 20:40:30 -07005271 return;
5272 }
5273
5274 FX_DOUBLE first = ValueToDouble(pThis, argFirst.get());
5275 FX_DOUBLE second = ValueToDouble(pThis, argSecond.get());
5276 args.GetReturnValue()->SetInteger((first <= second) ? 1 : 0);
Dan Sinclair1770c022016-03-14 14:14:16 -04005277}
dsinclair48d91dd2016-05-31 11:54:01 -07005278
5279// static
dsinclair12a6b0c2016-05-26 11:14:08 -07005280void CXFA_FM2JSContext::greater_operator(CFXJSE_Value* pThis,
Dan Sinclair1770c022016-03-14 14:14:16 -04005281 const CFX_ByteStringC& szFuncName,
5282 CFXJSE_Arguments& args) {
dsinclair947c8732016-06-08 20:40:30 -07005283 if (args.GetLength() != 2) {
dsinclair8f3074b2016-06-02 17:45:25 -07005284 ToJSContext(pThis, nullptr)->ThrowException(XFA_IDS_COMPILER_ERROR);
dsinclair947c8732016-06-08 20:40:30 -07005285 return;
Dan Sinclair1770c022016-03-14 14:14:16 -04005286 }
dsinclair947c8732016-06-08 20:40:30 -07005287
5288 std::unique_ptr<CFXJSE_Value> argFirst = GetSimpleValue(pThis, args, 0);
5289 std::unique_ptr<CFXJSE_Value> argSecond = GetSimpleValue(pThis, args, 1);
5290 if (argFirst->IsNull() || argSecond->IsNull()) {
5291 args.GetReturnValue()->SetInteger(0);
5292 return;
5293 }
5294
5295 if (argFirst->IsString() && argSecond->IsString()) {
dsinclair947c8732016-06-08 20:40:30 -07005296 args.GetReturnValue()->SetInteger(
dsinclair2f5582f2016-06-09 11:48:23 -07005297 argFirst->ToString().Compare(argSecond->ToString().AsStringC()) == 1);
dsinclair947c8732016-06-08 20:40:30 -07005298 return;
5299 }
5300
5301 FX_DOUBLE first = ValueToDouble(pThis, argFirst.get());
5302 FX_DOUBLE second = ValueToDouble(pThis, argSecond.get());
5303 args.GetReturnValue()->SetInteger((first > second) ? 1 : 0);
Dan Sinclair1770c022016-03-14 14:14:16 -04005304}
dsinclair48d91dd2016-05-31 11:54:01 -07005305
5306// static
dsinclair12a6b0c2016-05-26 11:14:08 -07005307void CXFA_FM2JSContext::greaterequal_operator(CFXJSE_Value* pThis,
Dan Sinclair1770c022016-03-14 14:14:16 -04005308 const CFX_ByteStringC& szFuncName,
5309 CFXJSE_Arguments& args) {
dsinclair947c8732016-06-08 20:40:30 -07005310 if (args.GetLength() != 2) {
dsinclair8f3074b2016-06-02 17:45:25 -07005311 ToJSContext(pThis, nullptr)->ThrowException(XFA_IDS_COMPILER_ERROR);
dsinclair947c8732016-06-08 20:40:30 -07005312 return;
Dan Sinclair1770c022016-03-14 14:14:16 -04005313 }
dsinclair947c8732016-06-08 20:40:30 -07005314
5315 std::unique_ptr<CFXJSE_Value> argFirst = GetSimpleValue(pThis, args, 0);
5316 std::unique_ptr<CFXJSE_Value> argSecond = GetSimpleValue(pThis, args, 1);
5317 if (argFirst->IsNull() || argSecond->IsNull()) {
5318 args.GetReturnValue()->SetInteger(
5319 (argFirst->IsNull() && argSecond->IsNull()) ? 1 : 0);
5320 return;
5321 }
5322
5323 if (argFirst->IsString() && argSecond->IsString()) {
dsinclair947c8732016-06-08 20:40:30 -07005324 args.GetReturnValue()->SetInteger(
dsinclair2f5582f2016-06-09 11:48:23 -07005325 argFirst->ToString().Compare(argSecond->ToString().AsStringC()) != -1);
dsinclair947c8732016-06-08 20:40:30 -07005326 return;
5327 }
5328
5329 FX_DOUBLE first = ValueToDouble(pThis, argFirst.get());
5330 FX_DOUBLE second = ValueToDouble(pThis, argSecond.get());
5331 args.GetReturnValue()->SetInteger((first >= second) ? 1 : 0);
Dan Sinclair1770c022016-03-14 14:14:16 -04005332}
dsinclair48d91dd2016-05-31 11:54:01 -07005333
5334// static
dsinclair12a6b0c2016-05-26 11:14:08 -07005335void CXFA_FM2JSContext::plus_operator(CFXJSE_Value* pThis,
Dan Sinclair1770c022016-03-14 14:14:16 -04005336 const CFX_ByteStringC& szFuncName,
5337 CFXJSE_Arguments& args) {
dsinclair947c8732016-06-08 20:40:30 -07005338 if (args.GetLength() != 2) {
dsinclair8f3074b2016-06-02 17:45:25 -07005339 ToJSContext(pThis, nullptr)->ThrowException(XFA_IDS_COMPILER_ERROR);
dsinclair947c8732016-06-08 20:40:30 -07005340 return;
Dan Sinclair1770c022016-03-14 14:14:16 -04005341 }
dsinclair947c8732016-06-08 20:40:30 -07005342
5343 std::unique_ptr<CFXJSE_Value> argFirst = args.GetValue(0);
5344 std::unique_ptr<CFXJSE_Value> argSecond = args.GetValue(1);
5345 if (ValueIsNull(pThis, argFirst.get()) &&
5346 ValueIsNull(pThis, argSecond.get())) {
5347 args.GetReturnValue()->SetNull();
5348 return;
5349 }
5350
5351 FX_DOUBLE first = ValueToDouble(pThis, argFirst.get());
5352 FX_DOUBLE second = ValueToDouble(pThis, argSecond.get());
5353 args.GetReturnValue()->SetDouble(first + second);
Dan Sinclair1770c022016-03-14 14:14:16 -04005354}
dsinclair48d91dd2016-05-31 11:54:01 -07005355
5356// static
dsinclair12a6b0c2016-05-26 11:14:08 -07005357void CXFA_FM2JSContext::minus_operator(CFXJSE_Value* pThis,
Dan Sinclair1770c022016-03-14 14:14:16 -04005358 const CFX_ByteStringC& szFuncName,
5359 CFXJSE_Arguments& args) {
dsinclair947c8732016-06-08 20:40:30 -07005360 if (args.GetLength() != 2) {
dsinclair8f3074b2016-06-02 17:45:25 -07005361 ToJSContext(pThis, nullptr)->ThrowException(XFA_IDS_COMPILER_ERROR);
dsinclair947c8732016-06-08 20:40:30 -07005362 return;
Dan Sinclair1770c022016-03-14 14:14:16 -04005363 }
dsinclair947c8732016-06-08 20:40:30 -07005364
5365 std::unique_ptr<CFXJSE_Value> argFirst = GetSimpleValue(pThis, args, 0);
5366 std::unique_ptr<CFXJSE_Value> argSecond = GetSimpleValue(pThis, args, 1);
5367 if (argFirst->IsNull() && argSecond->IsNull()) {
5368 args.GetReturnValue()->SetNull();
5369 return;
5370 }
5371
5372 FX_DOUBLE first = ValueToDouble(pThis, argFirst.get());
5373 FX_DOUBLE second = ValueToDouble(pThis, argSecond.get());
5374 args.GetReturnValue()->SetDouble(first - second);
Dan Sinclair1770c022016-03-14 14:14:16 -04005375}
dsinclair48d91dd2016-05-31 11:54:01 -07005376
5377// static
dsinclair12a6b0c2016-05-26 11:14:08 -07005378void CXFA_FM2JSContext::multiple_operator(CFXJSE_Value* pThis,
Dan Sinclair1770c022016-03-14 14:14:16 -04005379 const CFX_ByteStringC& szFuncName,
5380 CFXJSE_Arguments& args) {
dsinclair947c8732016-06-08 20:40:30 -07005381 if (args.GetLength() != 2) {
dsinclair8f3074b2016-06-02 17:45:25 -07005382 ToJSContext(pThis, nullptr)->ThrowException(XFA_IDS_COMPILER_ERROR);
dsinclair947c8732016-06-08 20:40:30 -07005383 return;
Dan Sinclair1770c022016-03-14 14:14:16 -04005384 }
dsinclair947c8732016-06-08 20:40:30 -07005385
5386 std::unique_ptr<CFXJSE_Value> argFirst = GetSimpleValue(pThis, args, 0);
5387 std::unique_ptr<CFXJSE_Value> argSecond = GetSimpleValue(pThis, args, 1);
5388 if (argFirst->IsNull() && argSecond->IsNull()) {
5389 args.GetReturnValue()->SetNull();
5390 return;
5391 }
5392
5393 FX_DOUBLE first = ValueToDouble(pThis, argFirst.get());
5394 FX_DOUBLE second = ValueToDouble(pThis, argSecond.get());
5395 args.GetReturnValue()->SetDouble(first * second);
Dan Sinclair1770c022016-03-14 14:14:16 -04005396}
dsinclair48d91dd2016-05-31 11:54:01 -07005397
5398// static
dsinclair12a6b0c2016-05-26 11:14:08 -07005399void CXFA_FM2JSContext::divide_operator(CFXJSE_Value* pThis,
Dan Sinclair1770c022016-03-14 14:14:16 -04005400 const CFX_ByteStringC& szFuncName,
5401 CFXJSE_Arguments& args) {
dsinclair8f3074b2016-06-02 17:45:25 -07005402 CXFA_FM2JSContext* pContext = ToJSContext(pThis, nullptr);
dsinclair947c8732016-06-08 20:40:30 -07005403 if (args.GetLength() != 2) {
dsinclair2235b7b2016-06-02 07:42:25 -07005404 pContext->ThrowException(XFA_IDS_COMPILER_ERROR);
dsinclair947c8732016-06-08 20:40:30 -07005405 return;
Dan Sinclair1770c022016-03-14 14:14:16 -04005406 }
dsinclair947c8732016-06-08 20:40:30 -07005407
5408 std::unique_ptr<CFXJSE_Value> argFirst = GetSimpleValue(pThis, args, 0);
5409 std::unique_ptr<CFXJSE_Value> argSecond = GetSimpleValue(pThis, args, 1);
5410 if (argFirst->IsNull() && argSecond->IsNull()) {
5411 args.GetReturnValue()->SetNull();
5412 return;
5413 }
5414
5415 FX_DOUBLE second = ValueToDouble(pThis, argSecond.get());
5416 if (second == 0.0) {
5417 pContext->ThrowException(XFA_IDS_DIVIDE_ZERO);
5418 return;
5419 }
5420
5421 FX_DOUBLE first = ValueToDouble(pThis, argFirst.get());
5422 args.GetReturnValue()->SetDouble(first / second);
Dan Sinclair1770c022016-03-14 14:14:16 -04005423}
dsinclair48d91dd2016-05-31 11:54:01 -07005424
5425// static
dsinclair12a6b0c2016-05-26 11:14:08 -07005426void CXFA_FM2JSContext::positive_operator(CFXJSE_Value* pThis,
Dan Sinclair1770c022016-03-14 14:14:16 -04005427 const CFX_ByteStringC& szFuncName,
5428 CFXJSE_Arguments& args) {
dsinclair947c8732016-06-08 20:40:30 -07005429 if (args.GetLength() != 1) {
dsinclair8f3074b2016-06-02 17:45:25 -07005430 ToJSContext(pThis, nullptr)->ThrowException(XFA_IDS_COMPILER_ERROR);
dsinclair947c8732016-06-08 20:40:30 -07005431 return;
Dan Sinclair1770c022016-03-14 14:14:16 -04005432 }
dsinclair947c8732016-06-08 20:40:30 -07005433
5434 std::unique_ptr<CFXJSE_Value> argOne = GetSimpleValue(pThis, args, 0);
5435 if (argOne->IsNull()) {
5436 args.GetReturnValue()->SetNull();
5437 return;
5438 }
5439 args.GetReturnValue()->SetDouble(0.0 + ValueToDouble(pThis, argOne.get()));
Dan Sinclair1770c022016-03-14 14:14:16 -04005440}
dsinclair48d91dd2016-05-31 11:54:01 -07005441
5442// static
dsinclair12a6b0c2016-05-26 11:14:08 -07005443void CXFA_FM2JSContext::negative_operator(CFXJSE_Value* pThis,
Dan Sinclair1770c022016-03-14 14:14:16 -04005444 const CFX_ByteStringC& szFuncName,
5445 CFXJSE_Arguments& args) {
dsinclair947c8732016-06-08 20:40:30 -07005446 if (args.GetLength() != 1) {
dsinclair8f3074b2016-06-02 17:45:25 -07005447 ToJSContext(pThis, nullptr)->ThrowException(XFA_IDS_COMPILER_ERROR);
dsinclair947c8732016-06-08 20:40:30 -07005448 return;
Dan Sinclair1770c022016-03-14 14:14:16 -04005449 }
dsinclair947c8732016-06-08 20:40:30 -07005450
5451 std::unique_ptr<CFXJSE_Value> argOne = GetSimpleValue(pThis, args, 0);
5452 if (argOne->IsNull()) {
5453 args.GetReturnValue()->SetNull();
5454 return;
5455 }
5456 args.GetReturnValue()->SetDouble(0.0 - ValueToDouble(pThis, argOne.get()));
Dan Sinclair1770c022016-03-14 14:14:16 -04005457}
dsinclair48d91dd2016-05-31 11:54:01 -07005458
5459// static
dsinclair12a6b0c2016-05-26 11:14:08 -07005460void CXFA_FM2JSContext::logical_not_operator(CFXJSE_Value* pThis,
Dan Sinclair1770c022016-03-14 14:14:16 -04005461 const CFX_ByteStringC& szFuncName,
5462 CFXJSE_Arguments& args) {
dsinclair947c8732016-06-08 20:40:30 -07005463 if (args.GetLength() != 1) {
dsinclair8f3074b2016-06-02 17:45:25 -07005464 ToJSContext(pThis, nullptr)->ThrowException(XFA_IDS_COMPILER_ERROR);
dsinclair947c8732016-06-08 20:40:30 -07005465 return;
Dan Sinclair1770c022016-03-14 14:14:16 -04005466 }
dsinclair947c8732016-06-08 20:40:30 -07005467
5468 std::unique_ptr<CFXJSE_Value> argOne = GetSimpleValue(pThis, args, 0);
5469 if (argOne->IsNull()) {
5470 args.GetReturnValue()->SetNull();
5471 return;
5472 }
5473
5474 FX_DOUBLE first = ValueToDouble(pThis, argOne.get());
5475 args.GetReturnValue()->SetInteger((first == 0.0) ? 1 : 0);
Dan Sinclair1770c022016-03-14 14:14:16 -04005476}
dsinclair48d91dd2016-05-31 11:54:01 -07005477
5478// static
dsinclair12a6b0c2016-05-26 11:14:08 -07005479void CXFA_FM2JSContext::dot_accessor(CFXJSE_Value* pThis,
Dan Sinclair1770c022016-03-14 14:14:16 -04005480 const CFX_ByteStringC& szFuncName,
5481 CFXJSE_Arguments& args) {
dsinclair8f3074b2016-06-02 17:45:25 -07005482 CXFA_FM2JSContext* pContext = ToJSContext(pThis, nullptr);
dsinclairec3da5b2016-05-25 16:42:05 -07005483 v8::Isolate* pIsolate = pContext->GetScriptRuntime();
Dan Sinclair1770c022016-03-14 14:14:16 -04005484 int32_t argc = args.GetLength();
dsinclairbd136fb2016-06-09 11:47:51 -07005485 if (argc < 4 || argc > 5) {
dsinclair2235b7b2016-06-02 07:42:25 -07005486 pContext->ThrowException(XFA_IDS_COMPILER_ERROR);
dsinclairbd136fb2016-06-09 11:47:51 -07005487 return;
Dan Sinclair1770c022016-03-14 14:14:16 -04005488 }
dsinclairbd136fb2016-06-09 11:47:51 -07005489
5490 bool bIsStar = true;
5491 int32_t iIndexValue = 0;
5492 if (argc > 4) {
5493 bIsStar = false;
5494 iIndexValue = ValueToInteger(pThis, args.GetValue(4).get());
5495 }
5496
5497 CFX_ByteString szName = args.GetUTF8String(2);
5498 CFX_ByteString szSomExp;
5499 GenerateSomExpression(szName.AsStringC(), args.GetInt32(3), iIndexValue,
5500 bIsStar, szSomExp);
5501
5502 std::unique_ptr<CFXJSE_Value> argAccessor = args.GetValue(0);
5503 if (argAccessor->IsArray()) {
5504 std::unique_ptr<CFXJSE_Value> pLengthValue(new CFXJSE_Value(pIsolate));
5505 argAccessor->GetObjectProperty("length", pLengthValue.get());
5506 int32_t iLength = pLengthValue->ToInteger();
5507 CFXJSE_Value*** hResolveValues = FX_Alloc(CFXJSE_Value**, iLength - 2);
5508 int32_t* iSizes = FX_Alloc(int32_t, iLength - 2);
5509 for (int32_t i = 0; i < (iLength - 2); i++)
5510 iSizes[i] = 0;
5511
5512 std::unique_ptr<CFXJSE_Value> hJSObjValue(new CFXJSE_Value(pIsolate));
5513 FX_BOOL bAttribute = FALSE;
5514 int32_t iCounter = 0;
5515 for (int32_t i = 2; i < iLength; i++) {
5516 argAccessor->GetObjectPropertyByIdx(i, hJSObjValue.get());
5517
5518 XFA_RESOLVENODE_RS resoveNodeRS;
5519 if (ResolveObjects(pThis, hJSObjValue.get(), szSomExp.AsStringC(),
5520 resoveNodeRS, TRUE, szName.IsEmpty()) > 0) {
5521 ParseResolveResult(pThis, resoveNodeRS, hJSObjValue.get(),
5522 hResolveValues[i - 2], iSizes[i - 2], bAttribute);
5523 iCounter += iSizes[i - 2];
5524 }
5525 }
5526 if (iCounter < 1) {
5527 CFX_WideString wsPropertyName =
5528 CFX_WideString::FromUTF8(szName.AsStringC());
5529 CFX_WideString wsSomExpression =
5530 CFX_WideString::FromUTF8(szSomExp.AsStringC());
5531 pContext->ThrowException(XFA_IDS_ACCESS_PROPERTY_IN_NOT_OBJECT,
5532 wsPropertyName.c_str(), wsSomExpression.c_str());
5533 return;
5534 }
5535
5536 CFXJSE_Value** rgValues = FX_Alloc(CFXJSE_Value*, iCounter + 2);
5537 for (int32_t i = 0; i < (iCounter + 2); i++)
5538 rgValues[i] = new CFXJSE_Value(pIsolate);
5539
5540 rgValues[0]->SetInteger(1);
5541 if (bAttribute)
5542 rgValues[1]->SetString(szName.AsStringC());
5543 else
5544 rgValues[1]->SetNull();
5545
5546 int32_t iIndex = 2;
5547 for (int32_t i = 0; i < iLength - 2; i++) {
5548 for (int32_t j = 0; j < iSizes[i]; j++) {
5549 rgValues[iIndex]->Assign(hResolveValues[i][j]);
5550 iIndex++;
5551 }
5552 }
5553 args.GetReturnValue()->SetArray(iCounter + 2, rgValues);
5554
5555 for (int32_t i = 0; i < (iCounter + 2); i++)
5556 delete rgValues[i];
5557 FX_Free(rgValues);
5558
5559 for (int32_t i = 0; i < iLength - 2; i++) {
5560 for (int32_t j = 0; j < iSizes[i]; j++)
5561 delete hResolveValues[i][j];
5562
5563 if (iSizes[i] > 0)
5564 FX_Free(hResolveValues[i]);
5565 }
5566 FX_Free(hResolveValues);
5567 FX_Free(iSizes);
5568
5569 return;
5570 }
5571
5572 XFA_RESOLVENODE_RS resoveNodeRS;
5573 int32_t iRet = 0;
5574 CFX_ByteString bsAccessorName = args.GetUTF8String(1);
5575 if (argAccessor->IsObject() ||
5576 (argAccessor->IsNull() && bsAccessorName.IsEmpty())) {
5577 iRet = ResolveObjects(pThis, argAccessor.get(), szSomExp.AsStringC(),
5578 resoveNodeRS, TRUE, szName.IsEmpty());
5579 } else if (!argAccessor->IsObject() && !bsAccessorName.IsEmpty() &&
5580 GetObjectByName(pThis, argAccessor.get(),
5581 bsAccessorName.AsStringC())) {
5582 iRet = ResolveObjects(pThis, argAccessor.get(), szSomExp.AsStringC(),
5583 resoveNodeRS, TRUE, szName.IsEmpty());
5584 }
5585 if (iRet < 1) {
5586 CFX_WideString wsPropertyName =
5587 CFX_WideString::FromUTF8(szName.AsStringC());
5588 CFX_WideString wsSomExpression =
5589 CFX_WideString::FromUTF8(szSomExp.AsStringC());
5590 pContext->ThrowException(XFA_IDS_ACCESS_PROPERTY_IN_NOT_OBJECT,
5591 wsPropertyName.c_str(), wsSomExpression.c_str());
5592 return;
5593 }
5594
5595 CFXJSE_Value** hResolveValues;
5596 int32_t iSize = 0;
5597 FX_BOOL bAttribute = FALSE;
5598 ParseResolveResult(pThis, resoveNodeRS, argAccessor.get(), hResolveValues,
5599 iSize, bAttribute);
5600 CFXJSE_Value** rgValues = FX_Alloc(CFXJSE_Value*, iSize + 2);
5601 for (int32_t i = 0; i < (iSize + 2); i++)
5602 rgValues[i] = new CFXJSE_Value(pIsolate);
5603
5604 rgValues[0]->SetInteger(1);
5605 if (bAttribute)
5606 rgValues[1]->SetString(szName.AsStringC());
5607 else
5608 rgValues[1]->SetNull();
5609
5610 for (int32_t i = 0; i < iSize; i++)
5611 rgValues[i + 2]->Assign(hResolveValues[i]);
5612
5613 args.GetReturnValue()->SetArray(iSize + 2, rgValues);
5614 for (int32_t i = 0; i < (iSize + 2); i++)
5615 delete rgValues[i];
5616 FX_Free(rgValues);
5617
5618 for (int32_t i = 0; i < iSize; i++)
5619 delete hResolveValues[i];
5620 FX_Free(hResolveValues);
Dan Sinclair1770c022016-03-14 14:14:16 -04005621}
dsinclair48d91dd2016-05-31 11:54:01 -07005622
5623// static
dsinclair12a6b0c2016-05-26 11:14:08 -07005624void CXFA_FM2JSContext::dotdot_accessor(CFXJSE_Value* pThis,
Dan Sinclair1770c022016-03-14 14:14:16 -04005625 const CFX_ByteStringC& szFuncName,
5626 CFXJSE_Arguments& args) {
dsinclair8f3074b2016-06-02 17:45:25 -07005627 CXFA_FM2JSContext* pContext = ToJSContext(pThis, nullptr);
dsinclairec3da5b2016-05-25 16:42:05 -07005628 v8::Isolate* pIsolate = pContext->GetScriptRuntime();
Dan Sinclair1770c022016-03-14 14:14:16 -04005629 int32_t argc = args.GetLength();
dsinclairbd136fb2016-06-09 11:47:51 -07005630 if (argc < 4 || argc > 5) {
dsinclair2235b7b2016-06-02 07:42:25 -07005631 pContext->ThrowException(XFA_IDS_COMPILER_ERROR);
dsinclairbd136fb2016-06-09 11:47:51 -07005632 return;
Dan Sinclair1770c022016-03-14 14:14:16 -04005633 }
dsinclairbd136fb2016-06-09 11:47:51 -07005634
5635 bool bIsStar = true;
5636 int32_t iIndexValue = 0;
5637 if (argc > 4) {
5638 bIsStar = false;
5639 iIndexValue = ValueToInteger(pThis, args.GetValue(4).get());
5640 }
5641
5642 CFX_ByteString szSomExp;
5643 CFX_ByteString szName = args.GetUTF8String(2);
5644 GenerateSomExpression(szName.AsStringC(), args.GetInt32(3), iIndexValue,
5645 bIsStar, szSomExp);
5646
5647 std::unique_ptr<CFXJSE_Value> argAccessor = args.GetValue(0);
5648 if (argAccessor->IsArray()) {
5649 std::unique_ptr<CFXJSE_Value> pLengthValue(new CFXJSE_Value(pIsolate));
5650 argAccessor->GetObjectProperty("length", pLengthValue.get());
5651 int32_t iLength = pLengthValue->ToInteger();
5652 int32_t iCounter = 0;
5653
5654 CFXJSE_Value*** hResolveValues = FX_Alloc(CFXJSE_Value**, iLength - 2);
5655 int32_t* iSizes = FX_Alloc(int32_t, iLength - 2);
5656 std::unique_ptr<CFXJSE_Value> hJSObjValue(new CFXJSE_Value(pIsolate));
5657 FX_BOOL bAttribute = FALSE;
5658 for (int32_t i = 2; i < iLength; i++) {
5659 argAccessor->GetObjectPropertyByIdx(i, hJSObjValue.get());
5660 XFA_RESOLVENODE_RS resoveNodeRS;
5661 if (ResolveObjects(pThis, hJSObjValue.get(), szSomExp.AsStringC(),
5662 resoveNodeRS, FALSE) > 0) {
5663 ParseResolveResult(pThis, resoveNodeRS, hJSObjValue.get(),
5664 hResolveValues[i - 2], iSizes[i - 2], bAttribute);
5665 iCounter += iSizes[i - 2];
5666 }
5667 }
5668 if (iCounter < 1) {
5669 CFX_WideString wsPropertyName =
5670 CFX_WideString::FromUTF8(szName.AsStringC());
5671 CFX_WideString wsSomExpression =
5672 CFX_WideString::FromUTF8(szSomExp.AsStringC());
5673 pContext->ThrowException(XFA_IDS_ACCESS_PROPERTY_IN_NOT_OBJECT,
5674 wsPropertyName.c_str(), wsSomExpression.c_str());
5675 return;
5676 }
5677
5678 CFXJSE_Value** rgValues = FX_Alloc(CFXJSE_Value*, iCounter + 2);
5679 for (int32_t i = 0; i < (iCounter + 2); i++)
5680 rgValues[i] = new CFXJSE_Value(pIsolate);
5681
5682 rgValues[0]->SetInteger(1);
5683 if (bAttribute)
5684 rgValues[1]->SetString(szName.AsStringC());
5685 else
5686 rgValues[1]->SetNull();
5687
5688 int32_t iIndex = 2;
5689 for (int32_t i = 0; i < iLength - 2; i++) {
5690 for (int32_t j = 0; j < iSizes[i]; j++) {
5691 rgValues[iIndex]->Assign(hResolveValues[i][j]);
5692 iIndex++;
5693 }
5694 }
5695 args.GetReturnValue()->SetArray(iCounter + 2, rgValues);
5696 for (int32_t i = 0; i < (iCounter + 2); i++)
5697 delete rgValues[i];
5698 FX_Free(rgValues);
5699
5700 for (int32_t i = 0; i < iLength - 2; i++) {
5701 for (int32_t j = 0; j < iSizes[i]; j++)
5702 delete hResolveValues[i][j];
5703 FX_Free(hResolveValues[i]);
5704 }
5705 FX_Free(hResolveValues);
5706 FX_Free(iSizes);
5707 return;
5708 }
5709
5710 XFA_RESOLVENODE_RS resoveNodeRS;
5711 int32_t iRet = 0;
5712 CFX_ByteString bsAccessorName = args.GetUTF8String(1);
5713 if (argAccessor->IsObject() ||
5714 (argAccessor->IsNull() && bsAccessorName.IsEmpty())) {
5715 iRet = ResolveObjects(pThis, argAccessor.get(), szSomExp.AsStringC(),
5716 resoveNodeRS, FALSE);
5717 } else if (!argAccessor->IsObject() && !bsAccessorName.IsEmpty() &&
5718 GetObjectByName(pThis, argAccessor.get(),
5719 bsAccessorName.AsStringC())) {
5720 iRet = ResolveObjects(pThis, argAccessor.get(), szSomExp.AsStringC(),
5721 resoveNodeRS, FALSE);
5722 }
5723 if (iRet < 1) {
5724 CFX_WideString wsPropertyName =
5725 CFX_WideString::FromUTF8(szName.AsStringC());
5726 CFX_WideString wsSomExpression =
5727 CFX_WideString::FromUTF8(szSomExp.AsStringC());
5728 pContext->ThrowException(XFA_IDS_ACCESS_PROPERTY_IN_NOT_OBJECT,
5729 wsPropertyName.c_str(), wsSomExpression.c_str());
5730 return;
5731 }
5732
5733 CFXJSE_Value** hResolveValues;
5734 int32_t iSize = 0;
5735 FX_BOOL bAttribute = FALSE;
5736 ParseResolveResult(pThis, resoveNodeRS, argAccessor.get(), hResolveValues,
5737 iSize, bAttribute);
5738 CFXJSE_Value** rgValues = FX_Alloc(CFXJSE_Value*, iSize + 2);
5739 for (int32_t i = 0; i < (iSize + 2); i++)
5740 rgValues[i] = new CFXJSE_Value(pIsolate);
5741
5742 rgValues[0]->SetInteger(1);
5743 if (bAttribute)
5744 rgValues[1]->SetString(szName.AsStringC());
5745 else
5746 rgValues[1]->SetNull();
5747
5748 for (int32_t i = 0; i < iSize; i++)
5749 rgValues[i + 2]->Assign(hResolveValues[i]);
5750
5751 args.GetReturnValue()->SetArray(iSize + 2, rgValues);
5752
5753 for (int32_t i = 0; i < (iSize + 2); i++)
5754 delete rgValues[i];
5755 FX_Free(rgValues);
5756
5757 for (int32_t i = 0; i < iSize; i++)
5758 delete hResolveValues[i];
5759 FX_Free(hResolveValues);
Dan Sinclair1770c022016-03-14 14:14:16 -04005760}
dsinclair48d91dd2016-05-31 11:54:01 -07005761
5762// static
dsinclair12a6b0c2016-05-26 11:14:08 -07005763void CXFA_FM2JSContext::eval_translation(CFXJSE_Value* pThis,
Dan Sinclair1770c022016-03-14 14:14:16 -04005764 const CFX_ByteStringC& szFuncName,
5765 CFXJSE_Arguments& args) {
dsinclair8f3074b2016-06-02 17:45:25 -07005766 CXFA_FM2JSContext* pContext = ToJSContext(pThis, nullptr);
dsinclairbd136fb2016-06-09 11:47:51 -07005767 if (args.GetLength() != 1) {
dsinclair2235b7b2016-06-02 07:42:25 -07005768 pContext->ThrowException(XFA_IDS_INCORRECT_NUMBER_OF_METHOD, L"Eval");
dsinclairbd136fb2016-06-09 11:47:51 -07005769 return;
Dan Sinclair1770c022016-03-14 14:14:16 -04005770 }
dsinclairbd136fb2016-06-09 11:47:51 -07005771
5772 std::unique_ptr<CFXJSE_Value> argOne = GetSimpleValue(pThis, args, 0);
5773 CFX_ByteString argString;
5774 ValueToUTF8String(argOne.get(), argString);
5775 if (argString.IsEmpty()) {
5776 pContext->ThrowException(XFA_IDS_ARGUMENT_MISMATCH);
5777 return;
5778 }
5779
5780 CFX_WideString scriptString = CFX_WideString::FromUTF8(argString.AsStringC());
5781 CFX_WideTextBuf wsJavaScriptBuf;
5782 CFX_WideString wsError;
5783 CXFA_FM2JSContext::Translate(scriptString.AsStringC(), wsJavaScriptBuf,
5784 wsError);
5785 if (!wsError.IsEmpty()) {
5786 pContext->ThrowException(XFA_IDS_COMPILER_ERROR);
5787 return;
5788 }
5789
5790 CFX_WideString javaScript = wsJavaScriptBuf.MakeString();
5791 args.GetReturnValue()->SetString(
5792 FX_UTF8Encode(javaScript.c_str(), javaScript.GetLength()).AsStringC());
Dan Sinclair1770c022016-03-14 14:14:16 -04005793}
dsinclair48d91dd2016-05-31 11:54:01 -07005794
5795// static
dsinclair12a6b0c2016-05-26 11:14:08 -07005796void CXFA_FM2JSContext::is_fm_object(CFXJSE_Value* pThis,
Dan Sinclair1770c022016-03-14 14:14:16 -04005797 const CFX_ByteStringC& szFuncName,
5798 CFXJSE_Arguments& args) {
dsinclairbd136fb2016-06-09 11:47:51 -07005799 if (args.GetLength() != 1) {
dsinclairf27aeec2016-06-07 19:36:18 -07005800 args.GetReturnValue()->SetBoolean(FALSE);
dsinclairbd136fb2016-06-09 11:47:51 -07005801 return;
Dan Sinclair1770c022016-03-14 14:14:16 -04005802 }
dsinclairbd136fb2016-06-09 11:47:51 -07005803
5804 std::unique_ptr<CFXJSE_Value> argOne = args.GetValue(0);
5805 args.GetReturnValue()->SetBoolean(argOne->IsObject());
Dan Sinclair1770c022016-03-14 14:14:16 -04005806}
dsinclair48d91dd2016-05-31 11:54:01 -07005807
5808// static
dsinclair12a6b0c2016-05-26 11:14:08 -07005809void CXFA_FM2JSContext::is_fm_array(CFXJSE_Value* pThis,
Dan Sinclair1770c022016-03-14 14:14:16 -04005810 const CFX_ByteStringC& szFuncName,
5811 CFXJSE_Arguments& args) {
dsinclairbd136fb2016-06-09 11:47:51 -07005812 if (args.GetLength() != 1) {
dsinclairf27aeec2016-06-07 19:36:18 -07005813 args.GetReturnValue()->SetBoolean(FALSE);
dsinclairbd136fb2016-06-09 11:47:51 -07005814 return;
Dan Sinclair1770c022016-03-14 14:14:16 -04005815 }
dsinclairbd136fb2016-06-09 11:47:51 -07005816
5817 std::unique_ptr<CFXJSE_Value> argOne = args.GetValue(0);
5818 args.GetReturnValue()->SetBoolean(argOne->IsArray());
Dan Sinclair1770c022016-03-14 14:14:16 -04005819}
dsinclair48d91dd2016-05-31 11:54:01 -07005820
5821// static
dsinclair12a6b0c2016-05-26 11:14:08 -07005822void CXFA_FM2JSContext::get_fm_value(CFXJSE_Value* pThis,
Dan Sinclair1770c022016-03-14 14:14:16 -04005823 const CFX_ByteStringC& szFuncName,
5824 CFXJSE_Arguments& args) {
dsinclair8f3074b2016-06-02 17:45:25 -07005825 CXFA_FM2JSContext* pContext = ToJSContext(pThis, nullptr);
dsinclairbd136fb2016-06-09 11:47:51 -07005826 if (args.GetLength() != 1) {
dsinclair2235b7b2016-06-02 07:42:25 -07005827 pContext->ThrowException(XFA_IDS_COMPILER_ERROR);
dsinclairbd136fb2016-06-09 11:47:51 -07005828 return;
Dan Sinclair1770c022016-03-14 14:14:16 -04005829 }
dsinclairbd136fb2016-06-09 11:47:51 -07005830
5831 std::unique_ptr<CFXJSE_Value> argOne = args.GetValue(0);
5832 if (argOne->IsArray()) {
5833 v8::Isolate* pIsolate = pContext->GetScriptRuntime();
5834 std::unique_ptr<CFXJSE_Value> propertyValue(new CFXJSE_Value(pIsolate));
5835 std::unique_ptr<CFXJSE_Value> jsObjectValue(new CFXJSE_Value(pIsolate));
5836 argOne->GetObjectPropertyByIdx(1, propertyValue.get());
5837 argOne->GetObjectPropertyByIdx(2, jsObjectValue.get());
5838 if (propertyValue->IsNull()) {
5839 GetObjectDefaultValue(jsObjectValue.get(), args.GetReturnValue());
5840 return;
5841 }
5842
dsinclair2f5582f2016-06-09 11:48:23 -07005843 jsObjectValue->GetObjectProperty(propertyValue->ToString().AsStringC(),
dsinclairbd136fb2016-06-09 11:47:51 -07005844 args.GetReturnValue());
5845 return;
5846 }
5847
5848 if (argOne->IsObject()) {
5849 GetObjectDefaultValue(argOne.get(), args.GetReturnValue());
5850 return;
5851 }
5852
5853 args.GetReturnValue()->Assign(argOne.get());
Dan Sinclair1770c022016-03-14 14:14:16 -04005854}
dsinclair48d91dd2016-05-31 11:54:01 -07005855
5856// static
dsinclair12a6b0c2016-05-26 11:14:08 -07005857void CXFA_FM2JSContext::get_fm_jsobj(CFXJSE_Value* pThis,
Dan Sinclair1770c022016-03-14 14:14:16 -04005858 const CFX_ByteStringC& szFuncName,
5859 CFXJSE_Arguments& args) {
dsinclairbd136fb2016-06-09 11:47:51 -07005860 if (args.GetLength() != 1) {
5861 ToJSContext(pThis, nullptr)->ThrowException(XFA_IDS_COMPILER_ERROR);
5862 return;
Dan Sinclair1770c022016-03-14 14:14:16 -04005863 }
dsinclairbd136fb2016-06-09 11:47:51 -07005864
5865 std::unique_ptr<CFXJSE_Value> argOne = args.GetValue(0);
5866 if (!argOne->IsArray()) {
5867 args.GetReturnValue()->Assign(argOne.get());
5868 return;
5869 }
5870
5871#ifndef NDEBUG
5872 CXFA_FM2JSContext* pContext = ToJSContext(pThis, nullptr);
5873 v8::Isolate* pIsolate = pContext->GetScriptRuntime();
5874 std::unique_ptr<CFXJSE_Value> lengthValue(new CFXJSE_Value(pIsolate));
5875 argOne->GetObjectProperty("length", lengthValue.get());
5876 ASSERT(lengthValue->ToInteger() >= 3);
5877#endif
5878
5879 argOne->GetObjectPropertyByIdx(2, args.GetReturnValue());
Dan Sinclair1770c022016-03-14 14:14:16 -04005880}
dsinclair48d91dd2016-05-31 11:54:01 -07005881
5882// static
dsinclair12a6b0c2016-05-26 11:14:08 -07005883void CXFA_FM2JSContext::fm_var_filter(CFXJSE_Value* pThis,
Dan Sinclair1770c022016-03-14 14:14:16 -04005884 const CFX_ByteStringC& szFuncName,
5885 CFXJSE_Arguments& args) {
dsinclair8f3074b2016-06-02 17:45:25 -07005886 CXFA_FM2JSContext* pContext = ToJSContext(pThis, nullptr);
dsinclairbd136fb2016-06-09 11:47:51 -07005887 if (args.GetLength() != 1) {
dsinclair2235b7b2016-06-02 07:42:25 -07005888 pContext->ThrowException(XFA_IDS_COMPILER_ERROR);
dsinclairbd136fb2016-06-09 11:47:51 -07005889 return;
Dan Sinclair1770c022016-03-14 14:14:16 -04005890 }
dsinclairbd136fb2016-06-09 11:47:51 -07005891
5892 v8::Isolate* pIsolate = pContext->GetScriptRuntime();
5893 std::unique_ptr<CFXJSE_Value> argOne = args.GetValue(0);
5894 if (!argOne->IsArray()) {
5895 std::unique_ptr<CFXJSE_Value> simpleValue = GetSimpleValue(pThis, args, 0);
5896 args.GetReturnValue()->Assign(simpleValue.get());
5897 return;
5898 }
5899
5900#ifndef NDEBUG
5901 std::unique_ptr<CFXJSE_Value> lengthValue(new CFXJSE_Value(pIsolate));
5902 argOne->GetObjectProperty("length", lengthValue.get());
5903 ASSERT(lengthValue->ToInteger() >= 3);
5904#endif
5905
5906 std::unique_ptr<CFXJSE_Value> flagsValue(new CFXJSE_Value(pIsolate));
5907 argOne->GetObjectPropertyByIdx(0, flagsValue.get());
5908 int32_t iFlags = flagsValue->ToInteger();
5909 if (iFlags != 3 && iFlags != 4) {
5910 std::unique_ptr<CFXJSE_Value> simpleValue = GetSimpleValue(pThis, args, 0);
5911 args.GetReturnValue()->Assign(simpleValue.get());
5912 return;
5913 }
5914
5915 if (iFlags == 4) {
5916 CFXJSE_Value* rgValues[3];
5917 for (int32_t i = 0; i < 3; i++)
5918 rgValues[i] = new CFXJSE_Value(pIsolate);
5919
5920 rgValues[0]->SetInteger(3);
5921 rgValues[1]->SetNull();
5922 rgValues[2]->SetNull();
5923 args.GetReturnValue()->SetArray(3, rgValues);
5924 for (int32_t i = 0; i < 3; i++)
5925 delete rgValues[i];
5926
5927 return;
5928 }
5929
5930 std::unique_ptr<CFXJSE_Value> objectValue(new CFXJSE_Value(pIsolate));
5931 argOne->GetObjectPropertyByIdx(2, objectValue.get());
5932 if (objectValue->IsNull()) {
5933 pContext->ThrowException(XFA_IDS_COMPILER_ERROR);
5934 return;
5935 }
5936 args.GetReturnValue()->Assign(argOne.get());
Dan Sinclair1770c022016-03-14 14:14:16 -04005937}
dsinclair48d91dd2016-05-31 11:54:01 -07005938
5939// static
dsinclair12a6b0c2016-05-26 11:14:08 -07005940void CXFA_FM2JSContext::concat_fm_object(CFXJSE_Value* pThis,
Dan Sinclair1770c022016-03-14 14:14:16 -04005941 const CFX_ByteStringC& szFuncName,
5942 CFXJSE_Arguments& args) {
dsinclair8f3074b2016-06-02 17:45:25 -07005943 v8::Isolate* pIsolate = ToJSContext(pThis, nullptr)->GetScriptRuntime();
Dan Sinclair1770c022016-03-14 14:14:16 -04005944 uint32_t iLength = 0;
dsinclair48d91dd2016-05-31 11:54:01 -07005945 int32_t argc = args.GetLength();
dsinclair86fad992016-05-31 11:34:04 -07005946 std::vector<std::unique_ptr<CFXJSE_Value>> argValues;
dsinclair48d91dd2016-05-31 11:54:01 -07005947 for (int32_t i = 0; i < argc; i++) {
dsinclair86fad992016-05-31 11:34:04 -07005948 argValues.push_back(args.GetValue(i));
dsinclair769b1372016-06-08 13:12:41 -07005949 if (argValues[i]->IsArray()) {
dsinclair86fad992016-05-31 11:34:04 -07005950 std::unique_ptr<CFXJSE_Value> lengthValue(new CFXJSE_Value(pIsolate));
dsinclairf27aeec2016-06-07 19:36:18 -07005951 argValues[i]->GetObjectProperty("length", lengthValue.get());
5952 int32_t length = lengthValue->ToInteger();
Dan Sinclair1770c022016-03-14 14:14:16 -04005953 iLength = iLength + ((length > 2) ? (length - 2) : 0);
Dan Sinclair1770c022016-03-14 14:14:16 -04005954 }
5955 iLength += 1;
5956 }
dsinclairbd136fb2016-06-09 11:47:51 -07005957
dsinclair12a6b0c2016-05-26 11:14:08 -07005958 CFXJSE_Value** returnValues = FX_Alloc(CFXJSE_Value*, iLength);
dsinclair86fad992016-05-31 11:34:04 -07005959 for (int32_t i = 0; i < (int32_t)iLength; i++)
5960 returnValues[i] = new CFXJSE_Value(pIsolate);
5961
Dan Sinclair1770c022016-03-14 14:14:16 -04005962 int32_t index = 0;
dsinclair48d91dd2016-05-31 11:54:01 -07005963 for (int32_t i = 0; i < argc; i++) {
dsinclair769b1372016-06-08 13:12:41 -07005964 if (argValues[i]->IsArray()) {
dsinclair86fad992016-05-31 11:34:04 -07005965 std::unique_ptr<CFXJSE_Value> lengthValue(new CFXJSE_Value(pIsolate));
dsinclairf27aeec2016-06-07 19:36:18 -07005966 argValues[i]->GetObjectProperty("length", lengthValue.get());
5967 int32_t length = lengthValue->ToInteger();
Dan Sinclair1770c022016-03-14 14:14:16 -04005968 for (int32_t j = 2; j < length; j++) {
dsinclairf27aeec2016-06-07 19:36:18 -07005969 argValues[i]->GetObjectPropertyByIdx(j, returnValues[index]);
Dan Sinclair1770c022016-03-14 14:14:16 -04005970 index++;
5971 }
Dan Sinclair1770c022016-03-14 14:14:16 -04005972 }
dsinclairf27aeec2016-06-07 19:36:18 -07005973 returnValues[index]->Assign(argValues[i].get());
Dan Sinclair1770c022016-03-14 14:14:16 -04005974 index++;
5975 }
dsinclairf27aeec2016-06-07 19:36:18 -07005976 args.GetReturnValue()->SetArray(iLength, returnValues);
dsinclair86fad992016-05-31 11:34:04 -07005977 for (int32_t i = 0; i < (int32_t)iLength; i++)
5978 delete returnValues[i];
5979
Dan Sinclair1770c022016-03-14 14:14:16 -04005980 FX_Free(returnValues);
5981}
dsinclair48d91dd2016-05-31 11:54:01 -07005982
5983// static
dsinclair86fad992016-05-31 11:34:04 -07005984std::unique_ptr<CFXJSE_Value> CXFA_FM2JSContext::GetSimpleValue(
5985 CFXJSE_Value* pThis,
5986 CFXJSE_Arguments& args,
5987 uint32_t index) {
dsinclair8f3074b2016-06-02 17:45:25 -07005988 v8::Isolate* pIsolate = ToJSContext(pThis, nullptr)->GetScriptRuntime();
dsinclair43854a52016-04-27 12:26:00 -07005989 ASSERT(index < (uint32_t)args.GetLength());
dsinclairbd136fb2016-06-09 11:47:51 -07005990
dsinclair86fad992016-05-31 11:34:04 -07005991 std::unique_ptr<CFXJSE_Value> argIndex = args.GetValue(index);
dsinclairbd136fb2016-06-09 11:47:51 -07005992 if (!argIndex->IsArray() && !argIndex->IsObject())
5993 return argIndex;
5994
dsinclair769b1372016-06-08 13:12:41 -07005995 if (argIndex->IsArray()) {
dsinclair86fad992016-05-31 11:34:04 -07005996 std::unique_ptr<CFXJSE_Value> lengthValue(new CFXJSE_Value(pIsolate));
dsinclairf27aeec2016-06-07 19:36:18 -07005997 argIndex->GetObjectProperty("length", lengthValue.get());
5998 int32_t iLength = lengthValue->ToInteger();
dsinclair86fad992016-05-31 11:34:04 -07005999 std::unique_ptr<CFXJSE_Value> simpleValue(new CFXJSE_Value(pIsolate));
dsinclairbd136fb2016-06-09 11:47:51 -07006000 if (iLength < 3) {
dsinclairf27aeec2016-06-07 19:36:18 -07006001 simpleValue.get()->SetUndefined();
dsinclairbd136fb2016-06-09 11:47:51 -07006002 return simpleValue;
Dan Sinclair1770c022016-03-14 14:14:16 -04006003 }
dsinclairbd136fb2016-06-09 11:47:51 -07006004
6005 std::unique_ptr<CFXJSE_Value> propertyValue(new CFXJSE_Value(pIsolate));
6006 std::unique_ptr<CFXJSE_Value> jsObjectValue(new CFXJSE_Value(pIsolate));
6007 argIndex->GetObjectPropertyByIdx(1, propertyValue.get());
6008 argIndex->GetObjectPropertyByIdx(2, jsObjectValue.get());
6009 if (propertyValue->IsNull()) {
6010 GetObjectDefaultValue(jsObjectValue.get(), simpleValue.get());
6011 return simpleValue;
6012 }
6013
dsinclair2f5582f2016-06-09 11:48:23 -07006014 jsObjectValue->GetObjectProperty(propertyValue->ToString().AsStringC(),
dsinclairbd136fb2016-06-09 11:47:51 -07006015 simpleValue.get());
Dan Sinclair1770c022016-03-14 14:14:16 -04006016 return simpleValue;
Dan Sinclair1770c022016-03-14 14:14:16 -04006017 }
dsinclairbd136fb2016-06-09 11:47:51 -07006018
6019 std::unique_ptr<CFXJSE_Value> defaultValue(new CFXJSE_Value(pIsolate));
6020 GetObjectDefaultValue(argIndex.get(), defaultValue.get());
6021 return defaultValue;
Dan Sinclair1770c022016-03-14 14:14:16 -04006022}
dsinclair12a6b0c2016-05-26 11:14:08 -07006023
dsinclair48d91dd2016-05-31 11:54:01 -07006024// static
dsinclair12a6b0c2016-05-26 11:14:08 -07006025FX_BOOL CXFA_FM2JSContext::ValueIsNull(CFXJSE_Value* pThis, CFXJSE_Value* arg) {
dsinclairbd136fb2016-06-09 11:47:51 -07006026 if (!arg || arg->IsNull())
6027 return TRUE;
6028
6029 if (!arg->IsArray() && !arg->IsObject())
6030 return FALSE;
6031
dsinclair8f3074b2016-06-02 17:45:25 -07006032 v8::Isolate* pIsolate = ToJSContext(pThis, nullptr)->GetScriptRuntime();
dsinclairbd136fb2016-06-09 11:47:51 -07006033 if (arg->IsArray()) {
dsinclair12a6b0c2016-05-26 11:14:08 -07006034 int32_t iLength = hvalue_get_array_length(pThis, arg);
dsinclairbd136fb2016-06-09 11:47:51 -07006035 if (iLength < 3)
6036 return TRUE;
6037
6038 std::unique_ptr<CFXJSE_Value> propertyValue(new CFXJSE_Value(pIsolate));
6039 std::unique_ptr<CFXJSE_Value> jsObjectValue(new CFXJSE_Value(pIsolate));
6040 arg->GetObjectPropertyByIdx(1, propertyValue.get());
6041 arg->GetObjectPropertyByIdx(2, jsObjectValue.get());
6042 if (propertyValue->IsNull()) {
6043 std::unique_ptr<CFXJSE_Value> defaultValue(new CFXJSE_Value(pIsolate));
6044 GetObjectDefaultValue(jsObjectValue.get(), defaultValue.get());
6045 return defaultValue->IsNull();
Dan Sinclair1770c022016-03-14 14:14:16 -04006046 }
dsinclairbd136fb2016-06-09 11:47:51 -07006047
dsinclairbd136fb2016-06-09 11:47:51 -07006048 std::unique_ptr<CFXJSE_Value> newPropertyValue(new CFXJSE_Value(pIsolate));
dsinclair2f5582f2016-06-09 11:48:23 -07006049 jsObjectValue->GetObjectProperty(propertyValue->ToString().AsStringC(),
dsinclairbd136fb2016-06-09 11:47:51 -07006050 newPropertyValue.get());
6051 return newPropertyValue->IsNull();
Dan Sinclair1770c022016-03-14 14:14:16 -04006052 }
dsinclairbd136fb2016-06-09 11:47:51 -07006053
6054 std::unique_ptr<CFXJSE_Value> defaultValue(new CFXJSE_Value(pIsolate));
6055 GetObjectDefaultValue(arg, defaultValue.get());
6056 return defaultValue->IsNull();
Dan Sinclair1770c022016-03-14 14:14:16 -04006057}
dsinclair12a6b0c2016-05-26 11:14:08 -07006058
dsinclair48d91dd2016-05-31 11:54:01 -07006059// static
dsinclair12a6b0c2016-05-26 11:14:08 -07006060int32_t CXFA_FM2JSContext::hvalue_get_array_length(CFXJSE_Value* pThis,
6061 CFXJSE_Value* arg) {
dsinclair769b1372016-06-08 13:12:41 -07006062 if (!arg || !arg->IsArray())
6063 return 0;
6064
dsinclair8f3074b2016-06-02 17:45:25 -07006065 v8::Isolate* pIsolate = ToJSContext(pThis, nullptr)->GetScriptRuntime();
dsinclair769b1372016-06-08 13:12:41 -07006066 std::unique_ptr<CFXJSE_Value> lengthValue(new CFXJSE_Value(pIsolate));
6067 arg->GetObjectProperty("length", lengthValue.get());
6068 return lengthValue->ToInteger();
Dan Sinclair1770c022016-03-14 14:14:16 -04006069}
dsinclair48d91dd2016-05-31 11:54:01 -07006070
6071// static
dsinclair12a6b0c2016-05-26 11:14:08 -07006072FX_BOOL CXFA_FM2JSContext::simpleValueCompare(CFXJSE_Value* pThis,
6073 CFXJSE_Value* firstValue,
6074 CFXJSE_Value* secondValue) {
dsinclair769b1372016-06-08 13:12:41 -07006075 if (!firstValue)
6076 return FALSE;
6077
dsinclair769b1372016-06-08 13:12:41 -07006078 if (firstValue->IsString()) {
Dan Sinclair1770c022016-03-14 14:14:16 -04006079 CFX_ByteString firstString, secondString;
dsinclair12a6b0c2016-05-26 11:14:08 -07006080 ValueToUTF8String(firstValue, firstString);
6081 ValueToUTF8String(secondValue, secondString);
dsinclairbd136fb2016-06-09 11:47:51 -07006082 return firstString == secondString;
6083 }
6084 if (firstValue->IsNumber()) {
dsinclair12a6b0c2016-05-26 11:14:08 -07006085 FX_FLOAT first = ValueToFloat(pThis, firstValue);
6086 FX_FLOAT second = ValueToFloat(pThis, secondValue);
dsinclairbd136fb2016-06-09 11:47:51 -07006087 return (first == second);
Dan Sinclair1770c022016-03-14 14:14:16 -04006088 }
dsinclairbd136fb2016-06-09 11:47:51 -07006089 if (firstValue->IsBoolean())
6090 return (firstValue->ToBoolean() == secondValue->ToBoolean());
6091
6092 return firstValue->IsNull() && secondValue && secondValue->IsNull();
Dan Sinclair1770c022016-03-14 14:14:16 -04006093}
dsinclair48d91dd2016-05-31 11:54:01 -07006094
6095// static
dsinclair12a6b0c2016-05-26 11:14:08 -07006096void CXFA_FM2JSContext::unfoldArgs(CFXJSE_Value* pThis,
Dan Sinclair1770c022016-03-14 14:14:16 -04006097 CFXJSE_Arguments& args,
dsinclair12a6b0c2016-05-26 11:14:08 -07006098 CFXJSE_Value**& resultValues,
Dan Sinclair1770c022016-03-14 14:14:16 -04006099 int32_t& iCount,
6100 int32_t iStart) {
Dan Sinclair1770c022016-03-14 14:14:16 -04006101 iCount = 0;
dsinclairbd136fb2016-06-09 11:47:51 -07006102
6103 v8::Isolate* pIsolate = ToJSContext(pThis, nullptr)->GetScriptRuntime();
Dan Sinclair1770c022016-03-14 14:14:16 -04006104 int32_t argc = args.GetLength();
dsinclair86fad992016-05-31 11:34:04 -07006105 std::vector<std::unique_ptr<CFXJSE_Value>> argsValue;
6106 for (int32_t i = 0; i < argc - iStart; i++) {
6107 argsValue.push_back(args.GetValue(i + iStart));
dsinclair769b1372016-06-08 13:12:41 -07006108 if (argsValue[i]->IsArray()) {
dsinclair86fad992016-05-31 11:34:04 -07006109 std::unique_ptr<CFXJSE_Value> lengthValue(new CFXJSE_Value(pIsolate));
dsinclairf27aeec2016-06-07 19:36:18 -07006110 argsValue[i]->GetObjectProperty("length", lengthValue.get());
6111 int32_t iLength = lengthValue->ToInteger();
Dan Sinclair1770c022016-03-14 14:14:16 -04006112 iCount += ((iLength > 2) ? (iLength - 2) : 0);
6113 } else {
6114 iCount += 1;
6115 }
6116 }
dsinclair12a6b0c2016-05-26 11:14:08 -07006117 resultValues = FX_Alloc(CFXJSE_Value*, iCount);
dsinclair86fad992016-05-31 11:34:04 -07006118 for (int32_t i = 0; i < iCount; i++)
6119 resultValues[i] = new CFXJSE_Value(pIsolate);
6120
Dan Sinclair1770c022016-03-14 14:14:16 -04006121 int32_t index = 0;
dsinclair86fad992016-05-31 11:34:04 -07006122 for (int32_t i = 0; i < argc - iStart; i++) {
dsinclair769b1372016-06-08 13:12:41 -07006123 if (argsValue[i]->IsArray()) {
dsinclair86fad992016-05-31 11:34:04 -07006124 std::unique_ptr<CFXJSE_Value> lengthValue(new CFXJSE_Value(pIsolate));
dsinclairf27aeec2016-06-07 19:36:18 -07006125 argsValue[i]->GetObjectProperty("length", lengthValue.get());
6126 int32_t iLength = lengthValue->ToInteger();
dsinclairbd136fb2016-06-09 11:47:51 -07006127 if (iLength < 3)
6128 continue;
6129
6130 std::unique_ptr<CFXJSE_Value> propertyValue(new CFXJSE_Value(pIsolate));
6131 std::unique_ptr<CFXJSE_Value> jsObjectValue(new CFXJSE_Value(pIsolate));
6132 argsValue[i]->GetObjectPropertyByIdx(1, propertyValue.get());
6133 if (propertyValue->IsNull()) {
6134 for (int32_t j = 2; j < iLength; j++) {
6135 argsValue[i]->GetObjectPropertyByIdx(j, jsObjectValue.get());
6136 GetObjectDefaultValue(jsObjectValue.get(), resultValues[index]);
6137 index++;
6138 }
6139 } else {
dsinclairbd136fb2016-06-09 11:47:51 -07006140 for (int32_t j = 2; j < iLength; j++) {
6141 argsValue[i]->GetObjectPropertyByIdx(j, jsObjectValue.get());
dsinclair2f5582f2016-06-09 11:48:23 -07006142 jsObjectValue->GetObjectProperty(
6143 propertyValue->ToString().AsStringC(), resultValues[index]);
dsinclairbd136fb2016-06-09 11:47:51 -07006144 index++;
Dan Sinclair1770c022016-03-14 14:14:16 -04006145 }
Dan Sinclair1770c022016-03-14 14:14:16 -04006146 }
dsinclair769b1372016-06-08 13:12:41 -07006147 } else if (argsValue[i]->IsObject()) {
dsinclair86fad992016-05-31 11:34:04 -07006148 GetObjectDefaultValue(argsValue[i].get(), resultValues[index]);
Dan Sinclair1770c022016-03-14 14:14:16 -04006149 index++;
6150 } else {
dsinclairf27aeec2016-06-07 19:36:18 -07006151 resultValues[index]->Assign(argsValue[i].get());
Dan Sinclair1770c022016-03-14 14:14:16 -04006152 index++;
6153 }
6154 }
Dan Sinclair1770c022016-03-14 14:14:16 -04006155}
dsinclair86fad992016-05-31 11:34:04 -07006156
dsinclair48d91dd2016-05-31 11:54:01 -07006157// static
dsinclair8f3074b2016-06-02 17:45:25 -07006158void CXFA_FM2JSContext::GetObjectDefaultValue(CFXJSE_Value* pValue,
dsinclair12a6b0c2016-05-26 11:14:08 -07006159 CFXJSE_Value* pDefaultValue) {
dsinclair8f3074b2016-06-02 17:45:25 -07006160 CXFA_Node* pNode = ToNode(CXFA_ScriptContext::ToObject(pValue, nullptr));
6161 if (!pNode) {
dsinclairf27aeec2016-06-07 19:36:18 -07006162 pDefaultValue->SetNull();
dsinclair8f3074b2016-06-02 17:45:25 -07006163 return;
Dan Sinclair1770c022016-03-14 14:14:16 -04006164 }
dsinclair8f3074b2016-06-02 17:45:25 -07006165 pNode->Script_Som_DefaultValue(pDefaultValue, FALSE, (XFA_ATTRIBUTE)-1);
Dan Sinclair1770c022016-03-14 14:14:16 -04006166}
dsinclair48d91dd2016-05-31 11:54:01 -07006167
6168// static
dsinclair8f3074b2016-06-02 17:45:25 -07006169FX_BOOL CXFA_FM2JSContext::SetObjectDefaultValue(CFXJSE_Value* pValue,
dsinclair12a6b0c2016-05-26 11:14:08 -07006170 CFXJSE_Value* hNewValue) {
dsinclair8f3074b2016-06-02 17:45:25 -07006171 CXFA_Node* pNode = ToNode(CXFA_ScriptContext::ToObject(pValue, nullptr));
6172 if (!pNode)
6173 return FALSE;
6174
6175 pNode->Script_Som_DefaultValue(hNewValue, TRUE, (XFA_ATTRIBUTE)-1);
6176 return TRUE;
Dan Sinclair1770c022016-03-14 14:14:16 -04006177}
dsinclair48d91dd2016-05-31 11:54:01 -07006178
6179// static
Dan Sinclair1770c022016-03-14 14:14:16 -04006180void CXFA_FM2JSContext::GenerateSomExpression(const CFX_ByteStringC& szName,
6181 int32_t iIndexFlags,
6182 int32_t iIndexValue,
dsinclairbd136fb2016-06-09 11:47:51 -07006183 bool bIsStar,
Dan Sinclair1770c022016-03-14 14:14:16 -04006184 CFX_ByteString& szSomExp) {
6185 if (bIsStar) {
6186 szSomExp = szName + "[*]";
6187 return;
6188 }
6189 if (iIndexFlags == 0) {
6190 szSomExp = szName;
6191 return;
6192 }
6193 if (iIndexFlags == 1 || iIndexValue == 0) {
6194 szSomExp = szName + "[" +
6195 CFX_ByteString::FormatInteger(iIndexValue, FXFORMAT_SIGNED) +
6196 "]";
6197 } else if (iIndexFlags == 2) {
6198 szSomExp = (iIndexValue < 0) ? (szName + "[-") : (szName + "[+");
6199 iIndexValue = (iIndexValue < 0) ? (0 - iIndexValue) : iIndexValue;
6200 szSomExp += CFX_ByteString::FormatInteger(iIndexValue);
6201 szSomExp += "]";
6202 } else {
6203 szSomExp = (iIndexValue < 0) ? (szName + "[") : (szName + "[-");
6204 iIndexValue = (iIndexValue < 0) ? (0 - iIndexValue) : iIndexValue;
6205 szSomExp += CFX_ByteString::FormatInteger(iIndexValue);
6206 szSomExp += "]";
6207 }
6208}
dsinclair48d91dd2016-05-31 11:54:01 -07006209
6210// static
Dan Sinclair1770c022016-03-14 14:14:16 -04006211FX_BOOL CXFA_FM2JSContext::GetObjectByName(
dsinclair12a6b0c2016-05-26 11:14:08 -07006212 CFXJSE_Value* pThis,
6213 CFXJSE_Value* accessorValue,
Dan Sinclair1770c022016-03-14 14:14:16 -04006214 const CFX_ByteStringC& szAccessorName) {
dsinclair8f3074b2016-06-02 17:45:25 -07006215 CXFA_Document* pDoc = ToJSContext(pThis, nullptr)->GetDocument();
dsinclairbd136fb2016-06-09 11:47:51 -07006216 if (!pDoc)
6217 return FALSE;
6218
dsinclairdf4bc592016-03-31 20:34:43 -07006219 CXFA_ScriptContext* pScriptContext = pDoc->GetScriptContext();
Dan Sinclair1770c022016-03-14 14:14:16 -04006220 XFA_RESOLVENODE_RS resoveNodeRS;
tsepez736f28a2016-03-25 14:19:51 -07006221 uint32_t dwFlags = XFA_RESOLVENODE_Children | XFA_RESOLVENODE_Properties |
Dan Sinclair1770c022016-03-14 14:14:16 -04006222 XFA_RESOLVENODE_Siblings | XFA_RESOLVENODE_Parent;
6223 int32_t iRet = pScriptContext->ResolveObjects(
6224 pScriptContext->GetThisObject(),
tsepez4c3debb2016-04-08 12:20:38 -07006225 CFX_WideString::FromUTF8(szAccessorName).AsStringC(), resoveNodeRS,
tsepez6fe7d212016-04-06 10:51:14 -07006226 dwFlags);
Dan Sinclair1770c022016-03-14 14:14:16 -04006227 if (iRet >= 1 && resoveNodeRS.dwFlags == XFA_RESOVENODE_RSTYPE_Nodes) {
dsinclairf27aeec2016-06-07 19:36:18 -07006228 accessorValue->Assign(
6229 pScriptContext->GetJSValueFromMap(resoveNodeRS.nodes.GetAt(0)));
dsinclairbd136fb2016-06-09 11:47:51 -07006230 return TRUE;
Dan Sinclair1770c022016-03-14 14:14:16 -04006231 }
dsinclairbd136fb2016-06-09 11:47:51 -07006232 return FALSE;
Dan Sinclair1770c022016-03-14 14:14:16 -04006233}
dsinclair48d91dd2016-05-31 11:54:01 -07006234
6235// static
dsinclair12a6b0c2016-05-26 11:14:08 -07006236int32_t CXFA_FM2JSContext::ResolveObjects(CFXJSE_Value* pThis,
6237 CFXJSE_Value* pRefValue,
Dan Sinclair1770c022016-03-14 14:14:16 -04006238 const CFX_ByteStringC& bsSomExp,
6239 XFA_RESOLVENODE_RS& resoveNodeRS,
6240 FX_BOOL bdotAccessor,
6241 FX_BOOL bHasNoResolveName) {
dsinclair8f3074b2016-06-02 17:45:25 -07006242 CXFA_Document* pDoc = ToJSContext(pThis, nullptr)->GetDocument();
dsinclairbd136fb2016-06-09 11:47:51 -07006243 if (!pDoc)
6244 return -1;
6245
6246 CFX_WideString wsSomExpression = CFX_WideString::FromUTF8(bsSomExp);
dsinclairdf4bc592016-03-31 20:34:43 -07006247 CXFA_ScriptContext* pScriptContext = pDoc->GetScriptContext();
dsinclair48d91dd2016-05-31 11:54:01 -07006248 CXFA_Object* pNode = nullptr;
tsepez736f28a2016-03-25 14:19:51 -07006249 uint32_t dFlags = 0UL;
Dan Sinclair1770c022016-03-14 14:14:16 -04006250 if (bdotAccessor) {
dsinclair769b1372016-06-08 13:12:41 -07006251 if (pRefValue && pRefValue->IsNull()) {
Dan Sinclair1770c022016-03-14 14:14:16 -04006252 pNode = pScriptContext->GetThisObject();
6253 dFlags = XFA_RESOLVENODE_Siblings | XFA_RESOLVENODE_Parent;
6254 } else {
dsinclair8f3074b2016-06-02 17:45:25 -07006255 pNode = CXFA_ScriptContext::ToObject(pRefValue, nullptr);
dsinclair43854a52016-04-27 12:26:00 -07006256 ASSERT(pNode);
Dan Sinclair1770c022016-03-14 14:14:16 -04006257 if (bHasNoResolveName) {
6258 CFX_WideString wsName;
dsinclairbd136fb2016-06-09 11:47:51 -07006259 if (CXFA_Node* pXFANode = pNode->AsNode())
Dan Sinclair1770c022016-03-14 14:14:16 -04006260 pXFANode->GetAttribute(XFA_ATTRIBUTE_Name, wsName, FALSE);
dsinclairbd136fb2016-06-09 11:47:51 -07006261
Dan Sinclair1770c022016-03-14 14:14:16 -04006262 if (wsName.IsEmpty()) {
6263 CFX_WideStringC className;
6264 pNode->GetClassName(className);
6265 wsName = FX_WSTRC(L"#") + className;
6266 }
6267 wsSomExpression = wsName + wsSomExpression;
6268 dFlags = XFA_RESOLVENODE_Siblings;
6269 } else {
6270 dFlags = (bsSomExp == "*")
6271 ? (XFA_RESOLVENODE_Children)
6272 : (XFA_RESOLVENODE_Children | XFA_RESOLVENODE_Attributes |
6273 XFA_RESOLVENODE_Properties);
6274 }
6275 }
6276 } else {
dsinclair8f3074b2016-06-02 17:45:25 -07006277 pNode = CXFA_ScriptContext::ToObject(pRefValue, nullptr);
Dan Sinclair1770c022016-03-14 14:14:16 -04006278 dFlags = XFA_RESOLVENODE_AnyChild;
6279 }
dsinclairbd136fb2016-06-09 11:47:51 -07006280 return pScriptContext->ResolveObjects(pNode, wsSomExpression.AsStringC(),
tsepezfc58ad12016-04-05 12:22:15 -07006281 resoveNodeRS, dFlags);
Dan Sinclair1770c022016-03-14 14:14:16 -04006282}
dsinclair48d91dd2016-05-31 11:54:01 -07006283
6284// static
Dan Sinclair1770c022016-03-14 14:14:16 -04006285void CXFA_FM2JSContext::ParseResolveResult(
dsinclair12a6b0c2016-05-26 11:14:08 -07006286 CFXJSE_Value* pThis,
Dan Sinclair1770c022016-03-14 14:14:16 -04006287 const XFA_RESOLVENODE_RS& resoveNodeRS,
dsinclair12a6b0c2016-05-26 11:14:08 -07006288 CFXJSE_Value* pParentValue,
6289 CFXJSE_Value**& resultValues,
Dan Sinclair1770c022016-03-14 14:14:16 -04006290 int32_t& iSize,
6291 FX_BOOL& bAttribute) {
Dan Sinclair1770c022016-03-14 14:14:16 -04006292 iSize = 0;
dsinclair48d91dd2016-05-31 11:54:01 -07006293 resultValues = nullptr;
dsinclairbd136fb2016-06-09 11:47:51 -07006294
6295 CXFA_FM2JSContext* pContext = ToJSContext(pThis, nullptr);
6296 v8::Isolate* pIsolate = pContext->GetScriptRuntime();
Dan Sinclair1770c022016-03-14 14:14:16 -04006297 if (resoveNodeRS.dwFlags == XFA_RESOVENODE_RSTYPE_Nodes) {
6298 bAttribute = FALSE;
6299 iSize = resoveNodeRS.nodes.GetSize();
dsinclair12a6b0c2016-05-26 11:14:08 -07006300 resultValues = FX_Alloc(CFXJSE_Value*, iSize);
Dan Sinclair1770c022016-03-14 14:14:16 -04006301 for (int32_t i = 0; i < iSize; i++) {
dsinclair86fad992016-05-31 11:34:04 -07006302 resultValues[i] = new CFXJSE_Value(pIsolate);
dsinclairf27aeec2016-06-07 19:36:18 -07006303 resultValues[i]->Assign(
Dan Sinclair1770c022016-03-14 14:14:16 -04006304 pContext->GetDocument()->GetScriptContext()->GetJSValueFromMap(
6305 resoveNodeRS.nodes.GetAt(i)));
6306 }
dsinclairbd136fb2016-06-09 11:47:51 -07006307 return;
Dan Sinclair1770c022016-03-14 14:14:16 -04006308 }
dsinclairbd136fb2016-06-09 11:47:51 -07006309
6310 CXFA_ValueArray objectProperties(pIsolate);
6311 int32_t iRet = resoveNodeRS.GetAttributeResult(objectProperties);
6312 bAttribute = (iRet == 0);
6313 if (!bAttribute) {
6314 iSize = iRet;
6315 resultValues = FX_Alloc(CFXJSE_Value*, iSize);
6316 for (int32_t i = 0; i < iSize; i++) {
6317 resultValues[i] = new CFXJSE_Value(pIsolate);
6318 resultValues[i]->Assign(objectProperties[i]);
6319 }
6320 return;
6321 }
6322
6323 if (!pParentValue || !pParentValue->IsObject())
6324 return;
6325
6326 iSize = 1;
6327 resultValues = FX_Alloc(CFXJSE_Value*, 1);
6328 resultValues[0] = new CFXJSE_Value(pIsolate);
6329 resultValues[0]->Assign(pParentValue);
Dan Sinclair1770c022016-03-14 14:14:16 -04006330}
dsinclair48d91dd2016-05-31 11:54:01 -07006331
6332// static
dsinclair12a6b0c2016-05-26 11:14:08 -07006333int32_t CXFA_FM2JSContext::ValueToInteger(CFXJSE_Value* pThis,
6334 CFXJSE_Value* pValue) {
dsinclair769b1372016-06-08 13:12:41 -07006335 if (!pValue)
6336 return 0;
6337
dsinclair8f3074b2016-06-02 17:45:25 -07006338 v8::Isolate* pIsolate = ToJSContext(pThis, nullptr)->GetScriptRuntime();
dsinclair769b1372016-06-08 13:12:41 -07006339 if (pValue->IsArray()) {
dsinclair86fad992016-05-31 11:34:04 -07006340 std::unique_ptr<CFXJSE_Value> propertyValue(new CFXJSE_Value(pIsolate));
6341 std::unique_ptr<CFXJSE_Value> jsObjectValue(new CFXJSE_Value(pIsolate));
6342 std::unique_ptr<CFXJSE_Value> newPropertyValue(new CFXJSE_Value(pIsolate));
dsinclairf27aeec2016-06-07 19:36:18 -07006343 pValue->GetObjectPropertyByIdx(1, propertyValue.get());
6344 pValue->GetObjectPropertyByIdx(2, jsObjectValue.get());
dsinclair769b1372016-06-08 13:12:41 -07006345 if (propertyValue->IsNull()) {
dsinclair86fad992016-05-31 11:34:04 -07006346 GetObjectDefaultValue(jsObjectValue.get(), newPropertyValue.get());
dsinclairbd136fb2016-06-09 11:47:51 -07006347 return ValueToInteger(pThis, newPropertyValue.get());
Dan Sinclair1770c022016-03-14 14:14:16 -04006348 }
dsinclairbd136fb2016-06-09 11:47:51 -07006349
dsinclair2f5582f2016-06-09 11:48:23 -07006350 jsObjectValue->GetObjectProperty(propertyValue->ToString().AsStringC(),
dsinclairbd136fb2016-06-09 11:47:51 -07006351 newPropertyValue.get());
6352 return ValueToInteger(pThis, newPropertyValue.get());
6353 }
6354 if (pValue->IsObject()) {
dsinclair86fad992016-05-31 11:34:04 -07006355 std::unique_ptr<CFXJSE_Value> newPropertyValue(new CFXJSE_Value(pIsolate));
6356 GetObjectDefaultValue(pValue, newPropertyValue.get());
dsinclairbd136fb2016-06-09 11:47:51 -07006357 return ValueToInteger(pThis, newPropertyValue.get());
6358 }
dsinclair2f5582f2016-06-09 11:48:23 -07006359 if (pValue->IsString())
6360 return FXSYS_atoi(pValue->ToString().c_str());
dsinclairbd136fb2016-06-09 11:47:51 -07006361 return pValue->ToInteger();
Dan Sinclair1770c022016-03-14 14:14:16 -04006362}
dsinclair48d91dd2016-05-31 11:54:01 -07006363
6364// static
dsinclair12a6b0c2016-05-26 11:14:08 -07006365FX_FLOAT CXFA_FM2JSContext::ValueToFloat(CFXJSE_Value* pThis,
6366 CFXJSE_Value* arg) {
dsinclair769b1372016-06-08 13:12:41 -07006367 if (!arg)
6368 return 0.0f;
6369
dsinclair8f3074b2016-06-02 17:45:25 -07006370 v8::Isolate* pIsolate = ToJSContext(pThis, nullptr)->GetScriptRuntime();
dsinclair769b1372016-06-08 13:12:41 -07006371 if (arg->IsArray()) {
dsinclair86fad992016-05-31 11:34:04 -07006372 std::unique_ptr<CFXJSE_Value> propertyValue(new CFXJSE_Value(pIsolate));
6373 std::unique_ptr<CFXJSE_Value> jsObjectValue(new CFXJSE_Value(pIsolate));
6374 std::unique_ptr<CFXJSE_Value> newPropertyValue(new CFXJSE_Value(pIsolate));
dsinclairf27aeec2016-06-07 19:36:18 -07006375 arg->GetObjectPropertyByIdx(1, propertyValue.get());
6376 arg->GetObjectPropertyByIdx(2, jsObjectValue.get());
dsinclair769b1372016-06-08 13:12:41 -07006377 if (propertyValue->IsNull()) {
dsinclair86fad992016-05-31 11:34:04 -07006378 GetObjectDefaultValue(jsObjectValue.get(), newPropertyValue.get());
dsinclairbd136fb2016-06-09 11:47:51 -07006379 return ValueToFloat(pThis, newPropertyValue.get());
Dan Sinclair1770c022016-03-14 14:14:16 -04006380 }
dsinclair2f5582f2016-06-09 11:48:23 -07006381 jsObjectValue->GetObjectProperty(propertyValue->ToString().AsStringC(),
dsinclairbd136fb2016-06-09 11:47:51 -07006382 newPropertyValue.get());
6383 return ValueToFloat(pThis, newPropertyValue.get());
6384 }
6385 if (arg->IsObject()) {
dsinclair86fad992016-05-31 11:34:04 -07006386 std::unique_ptr<CFXJSE_Value> newPropertyValue(new CFXJSE_Value(pIsolate));
6387 GetObjectDefaultValue(arg, newPropertyValue.get());
dsinclairbd136fb2016-06-09 11:47:51 -07006388 return ValueToFloat(pThis, newPropertyValue.get());
6389 }
dsinclair2f5582f2016-06-09 11:48:23 -07006390 if (arg->IsString())
6391 return (FX_FLOAT)XFA_ByteStringToDouble(arg->ToString().AsStringC());
dsinclairbd136fb2016-06-09 11:47:51 -07006392 if (arg->IsUndefined())
6393 return 0;
6394
6395 return arg->ToFloat();
Dan Sinclair1770c022016-03-14 14:14:16 -04006396}
dsinclair48d91dd2016-05-31 11:54:01 -07006397
6398// static
dsinclair12a6b0c2016-05-26 11:14:08 -07006399FX_DOUBLE CXFA_FM2JSContext::ValueToDouble(CFXJSE_Value* pThis,
6400 CFXJSE_Value* arg) {
dsinclair769b1372016-06-08 13:12:41 -07006401 if (!arg)
6402 return 0;
6403
dsinclair8f3074b2016-06-02 17:45:25 -07006404 v8::Isolate* pIsolate = ToJSContext(pThis, nullptr)->GetScriptRuntime();
dsinclair769b1372016-06-08 13:12:41 -07006405 if (arg->IsArray()) {
dsinclair86fad992016-05-31 11:34:04 -07006406 std::unique_ptr<CFXJSE_Value> propertyValue(new CFXJSE_Value(pIsolate));
6407 std::unique_ptr<CFXJSE_Value> jsObjectValue(new CFXJSE_Value(pIsolate));
6408 std::unique_ptr<CFXJSE_Value> newPropertyValue(new CFXJSE_Value(pIsolate));
dsinclairf27aeec2016-06-07 19:36:18 -07006409 arg->GetObjectPropertyByIdx(1, propertyValue.get());
6410 arg->GetObjectPropertyByIdx(2, jsObjectValue.get());
dsinclair769b1372016-06-08 13:12:41 -07006411 if (propertyValue->IsNull()) {
dsinclair86fad992016-05-31 11:34:04 -07006412 GetObjectDefaultValue(jsObjectValue.get(), newPropertyValue.get());
dsinclairbd136fb2016-06-09 11:47:51 -07006413 return ValueToDouble(pThis, newPropertyValue.get());
Dan Sinclair1770c022016-03-14 14:14:16 -04006414 }
dsinclair2f5582f2016-06-09 11:48:23 -07006415 jsObjectValue->GetObjectProperty(propertyValue->ToString().AsStringC(),
dsinclairbd136fb2016-06-09 11:47:51 -07006416 newPropertyValue.get());
6417 return ValueToDouble(pThis, newPropertyValue.get());
6418 }
6419 if (arg->IsObject()) {
dsinclair86fad992016-05-31 11:34:04 -07006420 std::unique_ptr<CFXJSE_Value> newPropertyValue(new CFXJSE_Value(pIsolate));
6421 GetObjectDefaultValue(arg, newPropertyValue.get());
dsinclairbd136fb2016-06-09 11:47:51 -07006422 return ValueToDouble(pThis, newPropertyValue.get());
6423 }
dsinclair2f5582f2016-06-09 11:48:23 -07006424 if (arg->IsString())
6425 return XFA_ByteStringToDouble(arg->ToString().AsStringC());
dsinclairbd136fb2016-06-09 11:47:51 -07006426 if (arg->IsUndefined())
6427 return 0;
6428 return arg->ToDouble();
Dan Sinclair1770c022016-03-14 14:14:16 -04006429}
tsepez1c9cfe12016-05-26 13:30:56 -07006430
dsinclairdbdcb812016-06-01 20:07:22 -07006431// static.
6432double CXFA_FM2JSContext::ExtractDouble(CFXJSE_Value* pThis,
6433 CFXJSE_Value* src,
6434 bool* ret) {
6435 ASSERT(ret);
dsinclairdbdcb812016-06-01 20:07:22 -07006436 *ret = true;
6437
dsinclair769b1372016-06-08 13:12:41 -07006438 if (!src)
6439 return 0;
6440
dsinclairbd136fb2016-06-09 11:47:51 -07006441 if (!src->IsArray())
6442 return ValueToDouble(pThis, src);
dsinclairdbdcb812016-06-01 20:07:22 -07006443
dsinclairbd136fb2016-06-09 11:47:51 -07006444 v8::Isolate* pIsolate = ToJSContext(pThis, nullptr)->GetScriptRuntime();
6445 std::unique_ptr<CFXJSE_Value> lengthValue(new CFXJSE_Value(pIsolate));
6446 src->GetObjectProperty("length", lengthValue.get());
6447 int32_t iLength = lengthValue->ToInteger();
6448 if (iLength <= 2) {
6449 *ret = false;
6450 return 0.0;
dsinclairdbdcb812016-06-01 20:07:22 -07006451 }
dsinclairbd136fb2016-06-09 11:47:51 -07006452
6453 std::unique_ptr<CFXJSE_Value> propertyValue(new CFXJSE_Value(pIsolate));
6454 std::unique_ptr<CFXJSE_Value> jsObjectValue(new CFXJSE_Value(pIsolate));
6455 src->GetObjectPropertyByIdx(1, propertyValue.get());
6456 src->GetObjectPropertyByIdx(2, jsObjectValue.get());
6457 if (propertyValue->IsNull())
6458 return ValueToDouble(pThis, jsObjectValue.get());
6459
dsinclairbd136fb2016-06-09 11:47:51 -07006460 std::unique_ptr<CFXJSE_Value> newPropertyValue(new CFXJSE_Value(pIsolate));
dsinclair2f5582f2016-06-09 11:48:23 -07006461 jsObjectValue->GetObjectProperty(propertyValue->ToString().AsStringC(),
dsinclairbd136fb2016-06-09 11:47:51 -07006462 newPropertyValue.get());
6463 return ValueToDouble(pThis, newPropertyValue.get());
dsinclairdbdcb812016-06-01 20:07:22 -07006464}
6465
dsinclair48d91dd2016-05-31 11:54:01 -07006466// static
dsinclair12a6b0c2016-05-26 11:14:08 -07006467void CXFA_FM2JSContext::ValueToUTF8String(CFXJSE_Value* arg,
6468 CFX_ByteString& szOutputString) {
dsinclair769b1372016-06-08 13:12:41 -07006469 if (!arg)
6470 return;
6471
dsinclair2f5582f2016-06-09 11:48:23 -07006472 if (arg->IsNull() || arg->IsUndefined())
Dan Sinclair1770c022016-03-14 14:14:16 -04006473 szOutputString = "";
dsinclair2f5582f2016-06-09 11:48:23 -07006474 else if (arg->IsBoolean())
dsinclairf27aeec2016-06-07 19:36:18 -07006475 szOutputString = arg->ToBoolean() ? "1" : "0";
dsinclair2f5582f2016-06-09 11:48:23 -07006476 else
6477 szOutputString = arg->ToString();
Dan Sinclair1770c022016-03-14 14:14:16 -04006478}
tsepez1c9cfe12016-05-26 13:30:56 -07006479
dsinclaire80e9f82016-06-01 06:10:04 -07006480// static.
6481int32_t CXFA_FM2JSContext::Translate(const CFX_WideStringC& wsFormcalc,
6482 CFX_WideTextBuf& wsJavascript,
6483 CFX_WideString& wsError) {
6484 if (wsFormcalc.IsEmpty()) {
6485 wsJavascript.Clear();
6486 wsError.clear();
6487 return 0;
6488 }
6489 int32_t status = 0;
6490 CXFA_FMProgram program;
6491 status = program.Init(wsFormcalc);
6492 if (status) {
6493 wsError = program.GetError().message;
6494 return status;
6495 }
6496 status = program.ParseProgram();
6497 if (status) {
6498 wsError = program.GetError().message;
6499 return status;
6500 }
6501 program.TranslateProgram(wsJavascript);
6502 return 0;
6503}
6504
dsinclair48d91dd2016-05-31 11:54:01 -07006505CXFA_FM2JSContext::CXFA_FM2JSContext(v8::Isolate* pScriptIsolate,
6506 CFXJSE_Context* pScriptContext,
6507 CXFA_Document* pDoc)
6508 : m_pIsolate(pScriptIsolate),
dsinclair769b1372016-06-08 13:12:41 -07006509 m_pFMClass(
6510 CFXJSE_Class::Create(pScriptContext, &formcalc_fm2js_descriptor)),
dsinclair48d91dd2016-05-31 11:54:01 -07006511 m_pValue(new CFXJSE_Value(pScriptIsolate)),
6512 m_pDocument(pDoc) {
dsinclairf27aeec2016-06-07 19:36:18 -07006513 m_pValue.get()->SetNull();
6514 m_pValue.get()->SetObject(this, m_pFMClass);
Dan Sinclair1770c022016-03-14 14:14:16 -04006515}
tsepez1c9cfe12016-05-26 13:30:56 -07006516
dsinclair48d91dd2016-05-31 11:54:01 -07006517CXFA_FM2JSContext::~CXFA_FM2JSContext() {}
6518
dsinclair12a6b0c2016-05-26 11:14:08 -07006519void CXFA_FM2JSContext::GlobalPropertyGetter(CFXJSE_Value* pValue) {
dsinclairf27aeec2016-06-07 19:36:18 -07006520 pValue->Assign(m_pValue.get());
Dan Sinclair1770c022016-03-14 14:14:16 -04006521}
tsepez5c4dd352016-05-26 13:57:58 -07006522
dsinclair2235b7b2016-06-02 07:42:25 -07006523void CXFA_FM2JSContext::ThrowException(int32_t iStringID, ...) {
Dan Sinclair1770c022016-03-14 14:14:16 -04006524 IXFA_AppProvider* pAppProvider = m_pDocument->GetNotify()->GetAppProvider();
dsinclair43854a52016-04-27 12:26:00 -07006525 ASSERT(pAppProvider);
Dan Sinclair1770c022016-03-14 14:14:16 -04006526 CFX_WideString wsFormat;
6527 pAppProvider->LoadString(iStringID, wsFormat);
6528 CFX_WideString wsMessage;
6529 va_list arg_ptr;
6530 va_start(arg_ptr, iStringID);
tsepezbd9748d2016-04-13 21:40:19 -07006531 wsMessage.FormatV(wsFormat.c_str(), arg_ptr);
Dan Sinclair1770c022016-03-14 14:14:16 -04006532 va_end(arg_ptr);
tsepez28f97ff2016-04-04 16:41:35 -07006533 FXJSE_ThrowMessage(
dsinclair769b1372016-06-08 13:12:41 -07006534 FX_UTF8Encode(wsMessage.c_str(), wsMessage.GetLength()).AsStringC());
Dan Sinclair1770c022016-03-14 14:14:16 -04006535}