blob: 8a7849f873f5d0aba6a188044f55248889b9c9ed [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
dsinclaira52ab742016-09-29 13:59:29 -070011#include "core/fxcrt/fx_ext.h"
dsinclair43554682016-09-29 17:29:48 -070012#include "fxjs/cfxjse_arguments.h"
13#include "fxjs/cfxjse_class.h"
14#include "fxjs/cfxjse_value.h"
Dan Sinclair1770c022016-03-14 14:14:16 -040015#include "xfa/fgas/localization/fgas_locale.h"
dsinclairdf4bc592016-03-31 20:34:43 -070016#include "xfa/fxfa/app/xfa_ffnotify.h"
dsinclaire80e9f82016-06-01 06:10:04 -070017#include "xfa/fxfa/fm2js/xfa_program.h"
dsinclair16280242016-07-21 12:03:47 -070018#include "xfa/fxfa/parser/cxfa_document.h"
dsinclair31f87402016-07-20 06:34:45 -070019#include "xfa/fxfa/parser/cxfa_scriptcontext.h"
Dan Sinclair1770c022016-03-14 14:14:16 -040020#include "xfa/fxfa/parser/xfa_localevalue.h"
Dan Sinclair1770c022016-03-14 14:14:16 -040021
Dan Sinclair1770c022016-03-14 14:14:16 -040022namespace {
23
dsinclair48d91dd2016-05-31 11:54:01 -070024const double kFinancialPrecision = 0.00000001;
25
Dan Sinclair1770c022016-03-14 14:14:16 -040026struct XFA_FMHtmlReserveCode {
27 uint32_t m_uCode;
28 const FX_WCHAR* m_htmlReserve;
29};
dsinclair48d91dd2016-05-31 11:54:01 -070030
Dan Sinclair1770c022016-03-14 14:14:16 -040031struct XFA_FMHtmlHashedReserveCode {
32 uint32_t m_uHash;
Dan Sinclair1770c022016-03-14 14:14:16 -040033 uint32_t m_uCode;
34};
35
36const XFA_FMHtmlHashedReserveCode reservesForDecode[] = {
dsinclair89ba6de2016-05-31 12:11:22 -070037 {0x00018b62, /*L"Mu",*/ 924}, {0x00019083, /*L"Nu",*/ 925},
38 {0x00019ab9, /*L"Pi",*/ 928}, {0x0001c3c1, /*L"Xi",*/ 926},
39 {0x000210ac, /*L"ge",*/ 8805}, {0x000210bb, /*L"gt",*/ 62},
40 {0x00022a51, /*L"le",*/ 8804}, {0x00022a60, /*L"lt",*/ 60},
41 {0x00022f82, /*L"mu",*/ 956}, {0x00023493, /*L"ne",*/ 8800},
42 {0x00023497, /*L"ni",*/ 8715}, {0x000234a3, /*L"nu",*/ 957},
43 {0x000239c1, /*L"or",*/ 8744}, {0x00023ed9, /*L"pi",*/ 960},
44 {0x000267e1, /*L"xi",*/ 958}, {0x00c41789, /*L"lceil",*/ 8968},
45 {0x00eef34f, /*L"thetasym",*/ 977}, {0x012d7ead, /*L"lcirc",*/ 206},
46 {0x01637b56, /*L"agrave",*/ 224}, {0x020856da, /*L"crarr",*/ 8629},
47 {0x022188c3, /*L"gamma",*/ 947}, {0x033586d3, /*L"nbsp",*/ 160},
48 {0x04f4c358, /*L"nsub",*/ 8836}, {0x0581466a, /*L"dagger",*/ 8224},
49 {0x06b1f790, /*L"oelig",*/ 339}, {0x06e490d4, /*L"Chi",*/ 935},
50 {0x0718c6a1, /*L"ETH",*/ 208}, {0x07196ada, /*L"Eta",*/ 919},
51 {0x07f667ca, /*L"Ugrave",*/ 217}, {0x083a8a21, /*L"Phi",*/ 934},
52 {0x083ac28c, /*L"Psi",*/ 936}, {0x086f26a9, /*L"Rho",*/ 929},
53 {0x089b5b51, /*L"aring",*/ 229}, {0x08a39f4a, /*L"Tau",*/ 932},
54 {0x08b6188b, /*L"THORN",*/ 222}, {0x09ce792a, /*L"icirc",*/ 238},
55 {0x09f9d61e, /*L"amp",*/ 38}, {0x09f9db33, /*L"and",*/ 8743},
56 {0x09f9db36, /*L"ang",*/ 8736}, {0x0a2e3514, /*L"cap",*/ 8745},
57 {0x0a2e58f4, /*L"chi",*/ 967}, {0x0a2e9ba8, /*L"cup",*/ 8746},
58 {0x0a4897d0, /*L"deg",*/ 176}, {0x0a6332fa, /*L"eta",*/ 951},
59 {0x0a633301, /*L"eth",*/ 240}, {0x0acc4d4b, /*L"int",*/ 8747},
60 {0x0b1b3d35, /*L"loz",*/ 9674}, {0x0b1b4c8b, /*L"lrm",*/ 8206},
61 {0x0b4fd9b1, /*L"not",*/ 172}, {0x0b845241, /*L"phi",*/ 966},
62 {0x0b84576f, /*L"piv",*/ 982}, {0x0b848aac, /*L"psi",*/ 968},
63 {0x0bb8df5e, /*L"reg",*/ 174}, {0x0bb8eec9, /*L"rho",*/ 961},
64 {0x0bb9034b, /*L"rlm",*/ 8207}, {0x0bd33d14, /*L"shy",*/ 173},
65 {0x0bd34229, /*L"sim",*/ 8764}, {0x0bd37faa, /*L"sub",*/ 8834},
66 {0x0bd37fb5, /*L"sum",*/ 8721}, {0x0bd37fb8, /*L"sup",*/ 8835},
67 {0x0bed676a, /*L"tau",*/ 964}, {0x0c07f32e, /*L"uml",*/ 168},
68 {0x0c71032c, /*L"yen",*/ 165}, {0x0c7f2889, /*L"szlig",*/ 223},
69 {0x0c8badbb, /*L"zwj",*/ 8205}, {0x10ba4dba, /*L"Egrave",*/ 200},
70 {0x10f1ea24, /*L"para",*/ 182}, {0x10f1ea37, /*L"part",*/ 8706},
71 {0x115b2337, /*L"perp",*/ 8869}, {0x12b10d15, /*L"prod",*/ 8719},
72 {0x12b10d21, /*L"prop",*/ 8733}, {0x12dfa9f4, /*L"rfloor",*/ 8971},
73 {0x12eb4736, /*L"Agrave",*/ 192}, {0x12fff2b7, /*L"pund",*/ 163},
74 {0x13fda9f2, /*L"tilde",*/ 732}, {0x1417fd62, /*L"times",*/ 215},
75 {0x154fc726, /*L"ecirc",*/ 234}, {0x165aa451, /*L"sigma",*/ 963},
76 {0x1709124a, /*L"Dagger",*/ 8225}, {0x192f78d5, /*L"iexcl",*/ 161},
77 {0x1b7ed8d7, /*L"rArr",*/ 8658}, {0x1ec88c68, /*L"rang",*/ 9002},
78 {0x1ec8a0f7, /*L"rarr",*/ 8594}, {0x1eda07f3, /*L"atilde",*/ 227},
79 {0x1f3182c4, /*L"real",*/ 8476}, {0x1fc34f8b, /*L"yacute",*/ 253},
80 {0x20d11522, /*L"acirc",*/ 226}, {0x21933a9b, /*L"rsaquo",*/ 8250},
81 {0x21f44907, /*L"uacute",*/ 250}, {0x220cca72, /*L"acute",*/ 180},
82 {0x242cded1, /*L"alefsym",*/ 8501}, {0x2655c66a, /*L"delta",*/ 948},
83 {0x269e4b4d, /*L"exist",*/ 8707}, {0x273379fa, /*L"micro",*/ 181},
84 {0x27a37440, /*L"forall",*/ 8704}, {0x2854e62c, /*L"minus",*/ 8722},
85 {0x28636f81, /*L"cedil",*/ 184}, {0x2887357b, /*L"iacute",*/ 237},
86 {0x2994d5ff, /*L"frac12",*/ 189}, {0x2994d601, /*L"frac14",*/ 188},
87 {0x2994e043, /*L"frac34",*/ 190}, {0x2a1feb41, /*L"lambda",*/ 955},
88 {0x2ab215f3, /*L"apos",*/ 39}, {0x2ab82ef7, /*L"eacute",*/ 233},
89 {0x2b3592ef, /*L"auml",*/ 228}, {0x2ce92873, /*L"aacute",*/ 225},
90 {0x2daff48a, /*L"oslash",*/ 248}, {0x2ef68882, /*L"aelig",*/ 230},
91 {0x3061d3d3, /*L"Atilde",*/ 195}, {0x314b1b6b, /*L"Yacute",*/ 221},
92 {0x337c14e7, /*L"Uacute",*/ 218}, {0x37676aca, /*L"cent",*/ 162},
93 {0x37d0b841, /*L"circ",*/ 710}, {0x386e7947, /*L"cong",*/ 8773},
94 {0x386e839b, /*L"copy",*/ 169}, {0x3a0e225a, /*L"Epsilon",*/ 917},
95 {0x3ba7b721, /*L"Lambda",*/ 923}, {0x3bd9abe6, /*L"Alpha",*/ 913},
96 {0x3c3ffad7, /*L"Eacute",*/ 201}, {0x3cfaf69f, /*L"brvbar",*/ 166},
97 {0x3d54a489, /*L"omega",*/ 969}, {0x3e70f453, /*L"Aacute",*/ 193},
98 {0x3f37c06a, /*L"Oslash",*/ 216}, {0x40e1b34e, /*L"diams",*/ 9830},
99 {0x416596df, /*L"plusmn",*/ 177}, {0x4354ff16, /*L"Ucirc",*/ 219},
100 {0x454fce6a, /*L"Upsilon",*/ 933}, {0x4610ad35, /*L"emsp",*/ 8195},
101 {0x462afb76, /*L"ensp",*/ 8194}, {0x46e30073, /*L"euml",*/ 235},
102 {0x46e31a1b, /*L"euro",*/ 8364}, {0x46f2eada, /*L"lowast",*/ 8727},
103 {0x4dca26cf, /*L"Auml",*/ 196}, {0x4e2d6083, /*L"image",*/ 8465},
104 {0x4f964ee8, /*L"notin",*/ 8713}, {0x50917a7a, /*L"epsilon",*/ 949},
105 {0x52f9a4cd, /*L"Kappa",*/ 922}, {0x5496f410, /*L"Ocirc",*/ 212},
106 {0x568cbf34, /*L"zeta",*/ 950}, {0x57badd20, /*L"ntilde",*/ 241},
107 {0x58662109, /*L"zwnj",*/ 8204}, {0x5b39870f, /*L"empty",*/ 8709},
108 {0x5bd3268a, /*L"upsilon",*/ 965}, {0x5e2bf8a3, /*L"Gamma",*/ 915},
109 {0x5f73c13a, /*L"rsquo",*/ 8217}, {0x61f2bc4d, /*L"iota",*/ 953},
110 {0x625bbcf3, /*L"isin",*/ 8712}, {0x62906df7, /*L"iuml",*/ 239},
111 {0x64a5cb31, /*L"Aring",*/ 197}, {0x66f25c4a, /*L"sbquo",*/ 8218},
112 {0x6851ab60, /*L"spades",*/ 9824}, {0x6942a900, /*L"Ntilde",*/ 209},
113 {0x69779453, /*L"Euml",*/ 203}, {0x6cda6e23, /*L"current",*/ 164},
114 {0x70b5b634, /*L"lsquo",*/ 8216}, {0x715a3706, /*L"Ecirc",*/ 202},
115 {0x71e8bf8d, /*L"tdquo",*/ 8221}, {0x72651431, /*L"Sigma",*/ 931},
116 {0x7569813b, /*L"iquest",*/ 191}, {0x776a436a, /*L"equiv",*/ 8801},
117 {0x79215314, /*L"Zeta",*/ 918}, {0x79b81224, /*L"ograve",*/ 242},
118 {0x7c2f8b23, /*L"macr",*/ 175}, {0x7cdb8502, /*L"Acirc",*/ 194},
119 {0x8185c62e, /*L"ndash",*/ 8211}, {0x8260364a, /*L"Delta",*/ 916},
120 {0x846619ad, /*L"mdash",*/ 8212}, {0x8550fb50, /*L"OElig",*/ 338},
121 {0x88eb5b85, /*L"ldquo",*/ 8220}, {0x8b3fde04, /*L"Ograve",*/ 210},
122 {0x8bc5794b, /*L"ordf",*/ 170}, {0x8bc57952, /*L"ordm",*/ 186},
123 {0x8c14923d, /*L"ouml",*/ 246}, {0x8c5a7cd6, /*L"theta",*/ 952},
124 {0x8d61812b, /*L"thorn",*/ 254}, {0x912b95aa, /*L"asymp",*/ 8776},
125 {0x947faf81, /*L"middot",*/ 183}, {0x9629202e, /*L"lfloor",*/ 8970},
126 {0x972e9ec1, /*L"otilde",*/ 245}, {0x9748f231, /*L"otimes",*/ 8855},
127 {0x995f1469, /*L"Omega",*/ 937}, {0x99eb5349, /*L"quot",*/ 34},
128 {0x9aeb639e, /*L"hellip",*/ 8230}, {0xa0ae2f86, /*L"Scaron",*/ 352},
129 {0xa4dcb0d5, /*L"lsaquo",*/ 8249}, {0xa53dbf41, /*L"oacute",*/ 243},
130 {0xa5ae9e7b, /*L"bdquo",*/ 8222}, {0xa602d7ba, /*L"sdot",*/ 8901},
131 {0xa61ce86f, /*L"sect",*/ 167}, {0xa6e4c3d7, /*L"sigmaf",*/ 962},
132 {0xa7c1c74f, /*L"sube",*/ 8838}, {0xa7c20ee9, /*L"sup1",*/ 185},
133 {0xa7c20eea, /*L"sup2",*/ 178}, {0xa7c20eeb, /*L"sup3",*/ 179},
134 {0xa7c20f1d, /*L"supe",*/ 8839}, {0xa8b66aa1, /*L"Otilde",*/ 213},
135 {0xad958c42, /*L"AElig",*/ 198}, {0xaea9261d, /*L"Ouml",*/ 214},
136 {0xb040eafa, /*L"uArr",*/ 8657}, {0xb07c2e1c, /*L"beta",*/ 946},
137 {0xb220e92f, /*L"bull",*/ 8226}, {0xb22750c4, /*L"ccedil",*/ 231},
138 {0xb38ab31a, /*L"uarr",*/ 8593}, {0xb598b683, /*L"uuml",*/ 252},
139 {0xb6c58b21, /*L"Oacute",*/ 211}, {0xb6d2a617, /*L"oline",*/ 8254},
140 {0xba9fd989, /*L"dArr",*/ 8659}, {0xbb5ccd41, /*L"lgrave",*/ 204},
141 {0xbd39b44c, /*L"weierp",*/ 8472}, {0xbde9a1a9, /*L"darr",*/ 8595},
142 {0xc027e329, /*L"permil",*/ 8240}, {0xc2451389, /*L"upsih",*/ 978},
143 {0xc3af1ca4, /*L"Ccedil",*/ 199}, {0xcd164249, /*L"fnof",*/ 402},
144 {0xcf6c8467, /*L"hearts",*/ 9829}, {0xd1228390, /*L"trade",*/ 8482},
145 {0xd1462407, /*L"yuml",*/ 255}, {0xd2cf2253, /*L"oplus",*/ 8853},
146 {0xd310c1fc, /*L"Beta",*/ 914}, {0xd59c4d74, /*L"infin",*/ 8734},
147 {0xd64d470d, /*L"hArr",*/ 8660}, {0xd67d9c75, /*L"divide",*/ 247},
148 {0xd698dd37, /*L"Omicron",*/ 927}, {0xd82d4a63, /*L"Uuml",*/ 220},
149 {0xd9970f2d, /*L"harr",*/ 8596}, {0xda91fd99, /*L"clubs",*/ 9827},
150 {0xdbe5bdcc, /*L"there4",*/ 8756}, {0xdd7671bd, /*L"prime",*/ 8242},
151 {0xdfcf3c06, /*L"alpha",*/ 945}, {0xe0213063, /*L"saron",*/ 353},
152 {0xe1911d83, /*L"radic",*/ 8730}, {0xe2e75468, /*L"raquo",*/ 187},
153 {0xe6e27a5e, /*L"lacute",*/ 205}, {0xe74a8f36, /*L"ucirc",*/ 251},
154 {0xe864ecb6, /*L"Theta",*/ 920}, {0xecddde5e, /*L"nabla",*/ 8711},
155 {0xed1c3557, /*L"omicron",*/ 959}, {0xef82228f, /*L"rceil",*/ 8969},
156 {0xf1fab491, /*L"lArr",*/ 8656}, {0xf3dab7e7, /*L"Yuml",*/ 376},
157 {0xf4294962, /*L"laquo",*/ 171}, {0xf5446822, /*L"lang",*/ 9001},
158 {0xf5447cb1, /*L"larr",*/ 8592}, {0xf66e9bea, /*L"ugrave",*/ 249},
159 {0xf6b4ce70, /*L"lota",*/ 921}, {0xf6ef34ed, /*L"kappa",*/ 954},
160 {0xf72a3a56, /*L"thinsp",*/ 8201}, {0xf752801a, /*L"luml",*/ 207},
161 {0xf88c8430, /*L"ocirc",*/ 244}, {0xf9676178, /*L"frasl",*/ 8260},
162 {0xfd01885e, /*L"igrave",*/ 236}, {0xff3281da, /*L"egrave",*/ 232},
Dan Sinclair1770c022016-03-14 14:14:16 -0400163};
164
165const XFA_FMHtmlReserveCode reservesForEncode[] = {
166 {34, L"quot"}, {38, L"amp"}, {39, L"apos"},
167 {60, L"lt"}, {62, L"gt"}, {160, L"nbsp"},
168 {161, L"iexcl"}, {162, L"cent"}, {163, L"pund"},
169 {164, L"current"}, {165, L"yen"}, {166, L"brvbar"},
170 {167, L"sect"}, {168, L"uml"}, {169, L"copy"},
171 {170, L"ordf"}, {171, L"laquo"}, {172, L"not"},
172 {173, L"shy"}, {174, L"reg"}, {175, L"macr"},
173 {176, L"deg"}, {177, L"plusmn"}, {178, L"sup2"},
174 {179, L"sup3"}, {180, L"acute"}, {181, L"micro"},
175 {182, L"para"}, {183, L"middot"}, {184, L"cedil"},
176 {185, L"sup1"}, {186, L"ordm"}, {187, L"raquo"},
177 {188, L"frac14"}, {189, L"frac12"}, {190, L"frac34"},
178 {191, L"iquest"}, {192, L"Agrave"}, {193, L"Aacute"},
179 {194, L"Acirc"}, {195, L"Atilde"}, {196, L"Auml"},
180 {197, L"Aring"}, {198, L"AElig"}, {199, L"Ccedil"},
181 {200, L"Egrave"}, {201, L"Eacute"}, {202, L"Ecirc"},
182 {203, L"Euml"}, {204, L"lgrave"}, {205, L"lacute"},
183 {206, L"lcirc"}, {207, L"luml"}, {208, L"ETH"},
184 {209, L"Ntilde"}, {210, L"Ograve"}, {211, L"Oacute"},
185 {212, L"Ocirc"}, {213, L"Otilde"}, {214, L"Ouml"},
186 {215, L"times"}, {216, L"Oslash"}, {217, L"Ugrave"},
187 {218, L"Uacute"}, {219, L"Ucirc"}, {220, L"Uuml"},
188 {221, L"Yacute"}, {222, L"THORN"}, {223, L"szlig"},
189 {224, L"agrave"}, {225, L"aacute"}, {226, L"acirc"},
190 {227, L"atilde"}, {228, L"auml"}, {229, L"aring"},
191 {230, L"aelig"}, {231, L"ccedil"}, {232, L"egrave"},
192 {233, L"eacute"}, {234, L"ecirc"}, {235, L"euml"},
193 {236, L"igrave"}, {237, L"iacute"}, {238, L"icirc"},
194 {239, L"iuml"}, {240, L"eth"}, {241, L"ntilde"},
195 {242, L"ograve"}, {243, L"oacute"}, {244, L"ocirc"},
196 {245, L"otilde"}, {246, L"ouml"}, {247, L"divide"},
197 {248, L"oslash"}, {249, L"ugrave"}, {250, L"uacute"},
198 {251, L"ucirc"}, {252, L"uuml"}, {253, L"yacute"},
199 {254, L"thorn"}, {255, L"yuml"}, {338, L"OElig"},
200 {339, L"oelig"}, {352, L"Scaron"}, {353, L"saron"},
201 {376, L"Yuml"}, {402, L"fnof"}, {710, L"circ"},
202 {732, L"tilde"}, {913, L"Alpha"}, {914, L"Beta"},
203 {915, L"Gamma"}, {916, L"Delta"}, {917, L"Epsilon"},
204 {918, L"Zeta"}, {919, L"Eta"}, {920, L"Theta"},
205 {921, L"lota"}, {922, L"Kappa"}, {923, L"Lambda"},
206 {924, L"Mu"}, {925, L"Nu"}, {926, L"Xi"},
207 {927, L"Omicron"}, {928, L"Pi"}, {929, L"Rho"},
208 {931, L"Sigma"}, {932, L"Tau"}, {933, L"Upsilon"},
209 {934, L"Phi"}, {935, L"Chi"}, {936, L"Psi"},
210 {937, L"Omega"}, {945, L"alpha"}, {946, L"beta"},
211 {947, L"gamma"}, {948, L"delta"}, {949, L"epsilon"},
212 {950, L"zeta"}, {951, L"eta"}, {952, L"theta"},
213 {953, L"iota"}, {954, L"kappa"}, {955, L"lambda"},
214 {956, L"mu"}, {957, L"nu"}, {958, L"xi"},
215 {959, L"omicron"}, {960, L"pi"}, {961, L"rho"},
216 {962, L"sigmaf"}, {963, L"sigma"}, {964, L"tau"},
217 {965, L"upsilon"}, {966, L"phi"}, {967, L"chi"},
218 {968, L"psi"}, {969, L"omega"}, {977, L"thetasym"},
219 {978, L"upsih"}, {982, L"piv"}, {8194, L"ensp"},
220 {8195, L"emsp"}, {8201, L"thinsp"}, {8204, L"zwnj"},
221 {8205, L"zwj"}, {8206, L"lrm"}, {8207, L"rlm"},
222 {8211, L"ndash"}, {8212, L"mdash"}, {8216, L"lsquo"},
223 {8217, L"rsquo"}, {8218, L"sbquo"}, {8220, L"ldquo"},
224 {8221, L"tdquo"}, {8222, L"bdquo"}, {8224, L"dagger"},
225 {8225, L"Dagger"}, {8226, L"bull"}, {8230, L"hellip"},
226 {8240, L"permil"}, {8242, L"prime"}, {8249, L"lsaquo"},
227 {8250, L"rsaquo"}, {8254, L"oline"}, {8260, L"frasl"},
228 {8364, L"euro"}, {8465, L"image"}, {8472, L"weierp"},
229 {8476, L"real"}, {8482, L"trade"}, {8501, L"alefsym"},
230 {8592, L"larr"}, {8593, L"uarr"}, {8594, L"rarr"},
231 {8595, L"darr"}, {8596, L"harr"}, {8629, L"crarr"},
232 {8656, L"lArr"}, {8657, L"uArr"}, {8658, L"rArr"},
233 {8659, L"dArr"}, {8660, L"hArr"}, {8704, L"forall"},
234 {8706, L"part"}, {8707, L"exist"}, {8709, L"empty"},
235 {8711, L"nabla"}, {8712, L"isin"}, {8713, L"notin"},
236 {8715, L"ni"}, {8719, L"prod"}, {8721, L"sum"},
237 {8722, L"minus"}, {8727, L"lowast"}, {8730, L"radic"},
238 {8733, L"prop"}, {8734, L"infin"}, {8736, L"ang"},
239 {8743, L"and"}, {8744, L"or"}, {8745, L"cap"},
240 {8746, L"cup"}, {8747, L"int"}, {8756, L"there4"},
241 {8764, L"sim"}, {8773, L"cong"}, {8776, L"asymp"},
242 {8800, L"ne"}, {8801, L"equiv"}, {8804, L"le"},
243 {8805, L"ge"}, {8834, L"sub"}, {8835, L"sup"},
244 {8836, L"nsub"}, {8838, L"sube"}, {8839, L"supe"},
245 {8853, L"oplus"}, {8855, L"otimes"}, {8869, L"perp"},
246 {8901, L"sdot"}, {8968, L"lceil"}, {8969, L"rceil"},
247 {8970, L"lfloor"}, {8971, L"rfloor"}, {9001, L"lang"},
248 {9002, L"rang"}, {9674, L"loz"}, {9824, L"spades"},
249 {9827, L"clubs"}, {9829, L"hearts"}, {9830, L"diams"},
250};
251
tsepez1c9cfe12016-05-26 13:30:56 -0700252const FXJSE_FUNCTION_DESCRIPTOR formcalc_fm2js_functions[] = {
253 {"Abs", CXFA_FM2JSContext::Abs},
254 {"Avg", CXFA_FM2JSContext::Avg},
255 {"Ceil", CXFA_FM2JSContext::Ceil},
256 {"Count", CXFA_FM2JSContext::Count},
257 {"Floor", CXFA_FM2JSContext::Floor},
258 {"Max", CXFA_FM2JSContext::Max},
259 {"Min", CXFA_FM2JSContext::Min},
260 {"Mod", CXFA_FM2JSContext::Mod},
261 {"Round", CXFA_FM2JSContext::Round},
262 {"Sum", CXFA_FM2JSContext::Sum},
263 {"Date", CXFA_FM2JSContext::Date},
264 {"Date2Num", CXFA_FM2JSContext::Date2Num},
265 {"DateFmt", CXFA_FM2JSContext::DateFmt},
266 {"IsoDate2Num", CXFA_FM2JSContext::IsoDate2Num},
267 {"IsoTime2Num", CXFA_FM2JSContext::IsoTime2Num},
268 {"LocalDateFmt", CXFA_FM2JSContext::LocalDateFmt},
269 {"LocalTimeFmt", CXFA_FM2JSContext::LocalTimeFmt},
270 {"Num2Date", CXFA_FM2JSContext::Num2Date},
271 {"Num2GMTime", CXFA_FM2JSContext::Num2GMTime},
272 {"Num2Time", CXFA_FM2JSContext::Num2Time},
273 {"Time", CXFA_FM2JSContext::Time},
274 {"Time2Num", CXFA_FM2JSContext::Time2Num},
275 {"TimeFmt", CXFA_FM2JSContext::TimeFmt},
276 {"Apr", CXFA_FM2JSContext::Apr},
277 {"Cterm", CXFA_FM2JSContext::CTerm},
278 {"FV", CXFA_FM2JSContext::FV},
279 {"Ipmt", CXFA_FM2JSContext::IPmt},
280 {"NPV", CXFA_FM2JSContext::NPV},
281 {"Pmt", CXFA_FM2JSContext::Pmt},
282 {"PPmt", CXFA_FM2JSContext::PPmt},
283 {"PV", CXFA_FM2JSContext::PV},
284 {"Rate", CXFA_FM2JSContext::Rate},
285 {"Term", CXFA_FM2JSContext::Term},
286 {"Choose", CXFA_FM2JSContext::Choose},
287 {"Exists", CXFA_FM2JSContext::Exists},
288 {"HasValue", CXFA_FM2JSContext::HasValue},
289 {"Oneof", CXFA_FM2JSContext::Oneof},
290 {"Within", CXFA_FM2JSContext::Within},
291 {"If", CXFA_FM2JSContext::If},
292 {"Eval", CXFA_FM2JSContext::Eval},
293 {"Translate", CXFA_FM2JSContext::eval_translation},
294 {"Ref", CXFA_FM2JSContext::Ref},
295 {"UnitType", CXFA_FM2JSContext::UnitType},
296 {"UnitValue", CXFA_FM2JSContext::UnitValue},
297 {"At", CXFA_FM2JSContext::At},
298 {"Concat", CXFA_FM2JSContext::Concat},
299 {"Decode", CXFA_FM2JSContext::Decode},
300 {"Encode", CXFA_FM2JSContext::Encode},
301 {"Format", CXFA_FM2JSContext::Format},
302 {"Left", CXFA_FM2JSContext::Left},
303 {"Len", CXFA_FM2JSContext::Len},
304 {"Lower", CXFA_FM2JSContext::Lower},
305 {"Ltrim", CXFA_FM2JSContext::Ltrim},
306 {"Parse", CXFA_FM2JSContext::Parse},
307 {"Replace", CXFA_FM2JSContext::Replace},
308 {"Right", CXFA_FM2JSContext::Right},
309 {"Rtrim", CXFA_FM2JSContext::Rtrim},
310 {"Space", CXFA_FM2JSContext::Space},
311 {"Str", CXFA_FM2JSContext::Str},
312 {"Stuff", CXFA_FM2JSContext::Stuff},
313 {"Substr", CXFA_FM2JSContext::Substr},
314 {"Uuid", CXFA_FM2JSContext::Uuid},
315 {"Upper", CXFA_FM2JSContext::Upper},
316 {"WordNum", CXFA_FM2JSContext::WordNum},
317 {"Get", CXFA_FM2JSContext::Get},
318 {"Post", CXFA_FM2JSContext::Post},
319 {"Put", CXFA_FM2JSContext::Put},
320 {"positive_operator", CXFA_FM2JSContext::positive_operator},
321 {"negative_operator", CXFA_FM2JSContext::negative_operator},
322 {"logical_or_operator", CXFA_FM2JSContext::logical_or_operator},
323 {"logical_and_operator", CXFA_FM2JSContext::logical_and_operator},
324 {"logical_not_operator", CXFA_FM2JSContext::logical_not_operator},
325 {"equality_operator", CXFA_FM2JSContext::equality_operator},
326 {"notequality_operator", CXFA_FM2JSContext::notequality_operator},
327 {"less_operator", CXFA_FM2JSContext::less_operator},
328 {"lessequal_operator", CXFA_FM2JSContext::lessequal_operator},
329 {"greater_operator", CXFA_FM2JSContext::greater_operator},
330 {"greaterequal_operator", CXFA_FM2JSContext::greaterequal_operator},
331 {"plus_operator", CXFA_FM2JSContext::plus_operator},
332 {"minus_operator", CXFA_FM2JSContext::minus_operator},
333 {"multiple_operator", CXFA_FM2JSContext::multiple_operator},
334 {"divide_operator", CXFA_FM2JSContext::divide_operator},
335 {"assign_value_operator", CXFA_FM2JSContext::assign_value_operator},
336 {"dot_accessor", CXFA_FM2JSContext::dot_accessor},
337 {"dotdot_accessor", CXFA_FM2JSContext::dotdot_accessor},
338 {"concat_fm_object", CXFA_FM2JSContext::concat_fm_object},
339 {"is_fm_object", CXFA_FM2JSContext::is_fm_object},
340 {"is_fm_array", CXFA_FM2JSContext::is_fm_array},
341 {"get_fm_value", CXFA_FM2JSContext::get_fm_value},
342 {"get_fm_jsobj", CXFA_FM2JSContext::get_fm_jsobj},
343 {"fm_var_filter", CXFA_FM2JSContext::fm_var_filter},
344};
345
346const FXJSE_CLASS_DESCRIPTOR formcalc_fm2js_descriptor = {
347 "XFA_FM2JS_FormCalcClass", // name
348 nullptr, // constructor
349 nullptr, // properties
350 formcalc_fm2js_functions, // methods
351 0, // number of properties
352 FX_ArraySize(formcalc_fm2js_functions), // number of methods
353 nullptr, // dynamic prop type
354 nullptr, // dynamic prop getter
355 nullptr, // dynamic prop setter
356 nullptr, // dynamic prop deleter
357 nullptr, // dynamic prop method call
358};
359
dsinclair0c268e92016-05-17 14:04:14 -0700360const uint8_t g_sAltTable_Date[] = {
ochangf6be1452016-06-01 12:20:03 -0700361 255, 255, 255, 3, 9, 255, 255, 255, 255, 255, 255,
362 255, 2, 255, 255, 255, 255, 255, 255, 255, 255, 255,
363 255, 255, 1, 255, 255, 255, 255, 255, 255, 255, 255,
dsinclair0c268e92016-05-17 14:04:14 -0700364};
ochangf6be1452016-06-01 12:20:03 -0700365static_assert(FX_ArraySize(g_sAltTable_Date) == L'a' - L'A' + 1,
366 "Invalid g_sAltTable_Date size.");
dsinclair0c268e92016-05-17 14:04:14 -0700367
368const uint8_t g_sAltTable_Time[] = {
ochangf6be1452016-06-01 12:20:03 -0700369 14, 255, 255, 3, 9, 255, 255, 15, 255, 255, 255,
370 255, 6, 255, 255, 255, 255, 255, 7, 255, 255, 255,
371 255, 255, 1, 17, 255, 255, 255, 255, 255, 255, 255,
dsinclair0c268e92016-05-17 14:04:14 -0700372};
ochangf6be1452016-06-01 12:20:03 -0700373static_assert(FX_ArraySize(g_sAltTable_Time) == L'a' - L'A' + 1,
374 "Invalid g_sAltTable_Time size.");
dsinclair0c268e92016-05-17 14:04:14 -0700375
376void AlternateDateTimeSymbols(CFX_WideString& wsPattern,
377 const CFX_WideString& wsAltSymbols,
378 const uint8_t* pAltTable) {
379 int32_t nLength = wsPattern.GetLength();
380 FX_BOOL bInConstRange = FALSE;
381 FX_BOOL bEscape = FALSE;
ochangf6be1452016-06-01 12:20:03 -0700382 int32_t i = 0;
dsinclair0c268e92016-05-17 14:04:14 -0700383 while (i < nLength) {
384 FX_WCHAR wc = wsPattern[i];
385 if (wc == L'\'') {
386 bInConstRange = !bInConstRange;
387 if (bEscape) {
388 i++;
389 } else {
390 wsPattern.Delete(i);
391 nLength--;
392 }
393 bEscape = !bEscape;
394 continue;
395 }
ochangf6be1452016-06-01 12:20:03 -0700396 if (!bInConstRange && wc >= L'A' && wc <= L'a') {
397 uint8_t nAlt = pAltTable[wc - L'A'];
dsinclair48d91dd2016-05-31 11:54:01 -0700398 if (nAlt != 255)
dsinclair0c268e92016-05-17 14:04:14 -0700399 wsPattern.SetAt(i, wsAltSymbols[nAlt]);
dsinclair0c268e92016-05-17 14:04:14 -0700400 }
401 i++;
402 bEscape = FALSE;
403 }
404}
405
dsinclair48d91dd2016-05-31 11:54:01 -0700406bool PatternStringType(const CFX_ByteStringC& szPattern,
407 uint32_t& patternType) {
408 CFX_WideString wsPattern = CFX_WideString::FromUTF8(szPattern);
409 if (FX_WSTRC(L"datetime") == wsPattern.Left(8)) {
410 patternType = XFA_VT_DATETIME;
411 return true;
412 }
413 if (FX_WSTRC(L"date") == wsPattern.Left(4)) {
414 patternType = wsPattern.Find(L"time") > 0 ? XFA_VT_DATETIME : XFA_VT_DATE;
415 return true;
416 }
417 if (FX_WSTRC(L"time") == wsPattern.Left(4)) {
418 patternType = XFA_VT_TIME;
419 return true;
420 }
421 if (FX_WSTRC(L"text") == wsPattern.Left(4)) {
422 patternType = XFA_VT_TEXT;
423 return true;
424 }
425 if (FX_WSTRC(L"num") == wsPattern.Left(3)) {
426 if (FX_WSTRC(L"integer") == wsPattern.Mid(4, 7)) {
427 patternType = XFA_VT_INTEGER;
428 } else if (FX_WSTRC(L"decimal") == wsPattern.Mid(4, 7)) {
429 patternType = XFA_VT_DECIMAL;
430 } else if (FX_WSTRC(L"currency") == wsPattern.Mid(4, 8)) {
431 patternType = XFA_VT_FLOAT;
432 } else if (FX_WSTRC(L"percent") == wsPattern.Mid(4, 7)) {
433 patternType = XFA_VT_FLOAT;
434 } else {
435 patternType = XFA_VT_FLOAT;
436 }
437 return true;
438 }
439
440 patternType = XFA_VT_NULL;
441 wsPattern.MakeLower();
442 const FX_WCHAR* pData = wsPattern.c_str();
443 int32_t iLength = wsPattern.GetLength();
444 int32_t iIndex = 0;
445 FX_BOOL bSingleQuotation = FALSE;
446 FX_WCHAR patternChar;
447 while (iIndex < iLength) {
dsinclair2b6d64e2016-06-06 11:39:42 -0700448 patternChar = pData[iIndex];
dsinclair48d91dd2016-05-31 11:54:01 -0700449 if (patternChar == 0x27) {
450 bSingleQuotation = !bSingleQuotation;
451 } else if (!bSingleQuotation &&
452 (patternChar == 'y' || patternChar == 'j')) {
453 patternType = XFA_VT_DATE;
454 iIndex++;
455 FX_WCHAR timePatternChar;
456 while (iIndex < iLength) {
dsinclair2b6d64e2016-06-06 11:39:42 -0700457 timePatternChar = pData[iIndex];
dsinclair48d91dd2016-05-31 11:54:01 -0700458 if (timePatternChar == 0x27) {
459 bSingleQuotation = !bSingleQuotation;
460 } else if (!bSingleQuotation && timePatternChar == 't') {
461 patternType = XFA_VT_DATETIME;
462 break;
463 }
464 iIndex++;
465 }
466 break;
467 } else if (!bSingleQuotation &&
468 (patternChar == 'h' || patternChar == 'k')) {
469 patternType = XFA_VT_TIME;
470 break;
471 } else if (!bSingleQuotation &&
472 (patternChar == 'a' || patternChar == 'x' ||
473 patternChar == 'o' || patternChar == '0')) {
474 patternType = XFA_VT_TEXT;
475 if (patternChar == 'x' || patternChar == 'o' || patternChar == '0') {
476 break;
477 }
478 } else if (!bSingleQuotation &&
479 (patternChar == 'z' || patternChar == 's' ||
480 patternChar == 'e' || patternChar == 'v' ||
481 patternChar == '8' || patternChar == ',' ||
482 patternChar == '.' || patternChar == '$')) {
483 patternType = XFA_VT_FLOAT;
484 if (patternChar == 'v' || patternChar == '8' || patternChar == '$') {
485 break;
486 }
487 }
488 iIndex++;
489 }
490 if (patternType == XFA_VT_NULL) {
491 patternType = XFA_VT_TEXT | XFA_VT_FLOAT;
492 }
493 return false;
494}
495
dsinclair8f3074b2016-06-02 17:45:25 -0700496CXFA_FM2JSContext* ToJSContext(CFXJSE_Value* pValue, CFXJSE_Class* pClass) {
497 return static_cast<CXFA_FM2JSContext*>(pValue->ToHostObject(pClass));
498}
499
dsinclair2b6d64e2016-06-06 11:39:42 -0700500bool IsWhitespace(char c) {
501 return c == 0x20 || c == 0x09 || c == 0x0B || c == 0x0C || c == 0x0A ||
502 c == 0x0D;
503}
504
Dan Sinclair1770c022016-03-14 14:14:16 -0400505} // namespace
506
dsinclair48d91dd2016-05-31 11:54:01 -0700507// static
dsinclair12a6b0c2016-05-26 11:14:08 -0700508void CXFA_FM2JSContext::Abs(CFXJSE_Value* pThis,
Dan Sinclair1770c022016-03-14 14:14:16 -0400509 const CFX_ByteStringC& szFuncName,
510 CFXJSE_Arguments& args) {
dsinclair89ba6de2016-05-31 12:11:22 -0700511 if (args.GetLength() != 1) {
dsinclair8f3074b2016-06-02 17:45:25 -0700512 ToJSContext(pThis, nullptr)
513 ->ThrowException(XFA_IDS_INCORRECT_NUMBER_OF_METHOD, L"Abs");
dsinclair89ba6de2016-05-31 12:11:22 -0700514 return;
Dan Sinclair1770c022016-03-14 14:14:16 -0400515 }
dsinclair89ba6de2016-05-31 12:11:22 -0700516
517 std::unique_ptr<CFXJSE_Value> argOne = args.GetValue(0);
518 if (ValueIsNull(pThis, argOne.get())) {
dsinclairf27aeec2016-06-07 19:36:18 -0700519 args.GetReturnValue()->SetNull();
dsinclair89ba6de2016-05-31 12:11:22 -0700520 return;
521 }
522
523 FX_DOUBLE dValue = ValueToDouble(pThis, argOne.get());
524 if (dValue < 0)
525 dValue = -dValue;
526
dsinclairf27aeec2016-06-07 19:36:18 -0700527 args.GetReturnValue()->SetDouble(dValue);
Dan Sinclair1770c022016-03-14 14:14:16 -0400528}
dsinclair48d91dd2016-05-31 11:54:01 -0700529
530// static
dsinclair12a6b0c2016-05-26 11:14:08 -0700531void CXFA_FM2JSContext::Avg(CFXJSE_Value* pThis,
Dan Sinclair1770c022016-03-14 14:14:16 -0400532 const CFX_ByteStringC& szFuncName,
533 CFXJSE_Arguments& args) {
dsinclair89ba6de2016-05-31 12:11:22 -0700534 int32_t argc = args.GetLength();
535 if (argc < 1) {
dsinclairf27aeec2016-06-07 19:36:18 -0700536 args.GetReturnValue()->SetNull();
dsinclair89ba6de2016-05-31 12:11:22 -0700537 return;
538 }
539
dsinclair8f3074b2016-06-02 17:45:25 -0700540 v8::Isolate* pIsolate = ToJSContext(pThis, nullptr)->GetScriptRuntime();
Dan Sinclair1770c022016-03-14 14:14:16 -0400541 uint32_t uCount = 0;
542 FX_DOUBLE dSum = 0.0;
dsinclair89ba6de2016-05-31 12:11:22 -0700543 for (int32_t i = 0; i < argc; i++) {
544 std::unique_ptr<CFXJSE_Value> argValue = args.GetValue(i);
dsinclair769b1372016-06-08 13:12:41 -0700545 if (argValue->IsNull())
dsinclair89ba6de2016-05-31 12:11:22 -0700546 continue;
dsinclair86fad992016-05-31 11:34:04 -0700547
dsinclair769b1372016-06-08 13:12:41 -0700548 if (!argValue->IsArray()) {
dsinclair89ba6de2016-05-31 12:11:22 -0700549 dSum += ValueToDouble(pThis, argValue.get());
550 uCount++;
551 continue;
552 }
553
554 std::unique_ptr<CFXJSE_Value> lengthValue(new CFXJSE_Value(pIsolate));
dsinclairf27aeec2016-06-07 19:36:18 -0700555 argValue->GetObjectProperty("length", lengthValue.get());
556 int32_t iLength = lengthValue->ToInteger();
dsinclair89ba6de2016-05-31 12:11:22 -0700557
558 if (iLength > 2) {
559 std::unique_ptr<CFXJSE_Value> propertyValue(new CFXJSE_Value(pIsolate));
dsinclairf27aeec2016-06-07 19:36:18 -0700560 argValue->GetObjectPropertyByIdx(1, propertyValue.get());
dsinclair89ba6de2016-05-31 12:11:22 -0700561
562 std::unique_ptr<CFXJSE_Value> jsObjectValue(new CFXJSE_Value(pIsolate));
dsinclair769b1372016-06-08 13:12:41 -0700563 if (propertyValue->IsNull()) {
dsinclair89ba6de2016-05-31 12:11:22 -0700564 for (int32_t j = 2; j < iLength; j++) {
dsinclairf27aeec2016-06-07 19:36:18 -0700565 argValue->GetObjectPropertyByIdx(j, jsObjectValue.get());
dsinclair89ba6de2016-05-31 12:11:22 -0700566 std::unique_ptr<CFXJSE_Value> defaultPropValue(
dsinclair86fad992016-05-31 11:34:04 -0700567 new CFXJSE_Value(pIsolate));
dsinclair89ba6de2016-05-31 12:11:22 -0700568 GetObjectDefaultValue(jsObjectValue.get(), defaultPropValue.get());
dsinclair769b1372016-06-08 13:12:41 -0700569 if (defaultPropValue->IsNull())
dsinclair89ba6de2016-05-31 12:11:22 -0700570 continue;
571
572 dSum += ValueToDouble(pThis, defaultPropValue.get());
573 uCount++;
Dan Sinclair1770c022016-03-14 14:14:16 -0400574 }
575 } else {
dsinclair89ba6de2016-05-31 12:11:22 -0700576 for (int32_t j = 2; j < iLength; j++) {
dsinclairf27aeec2016-06-07 19:36:18 -0700577 argValue->GetObjectPropertyByIdx(j, jsObjectValue.get());
dsinclair89ba6de2016-05-31 12:11:22 -0700578 std::unique_ptr<CFXJSE_Value> newPropertyValue(
579 new CFXJSE_Value(pIsolate));
dsinclair2f5582f2016-06-09 11:48:23 -0700580 jsObjectValue->GetObjectProperty(
581 propertyValue->ToString().AsStringC(), newPropertyValue.get());
dsinclair769b1372016-06-08 13:12:41 -0700582 if (newPropertyValue->IsNull())
dsinclair89ba6de2016-05-31 12:11:22 -0700583 continue;
584
585 dSum += ValueToDouble(pThis, newPropertyValue.get());
586 uCount++;
587 }
Dan Sinclair1770c022016-03-14 14:14:16 -0400588 }
Dan Sinclair1770c022016-03-14 14:14:16 -0400589 }
Dan Sinclair1770c022016-03-14 14:14:16 -0400590 }
dsinclair89ba6de2016-05-31 12:11:22 -0700591 if (uCount == 0) {
dsinclairf27aeec2016-06-07 19:36:18 -0700592 args.GetReturnValue()->SetNull();
dsinclair89ba6de2016-05-31 12:11:22 -0700593 return;
Dan Sinclair1770c022016-03-14 14:14:16 -0400594 }
dsinclair89ba6de2016-05-31 12:11:22 -0700595
dsinclairf27aeec2016-06-07 19:36:18 -0700596 args.GetReturnValue()->SetDouble(dSum / uCount);
Dan Sinclair1770c022016-03-14 14:14:16 -0400597}
dsinclair48d91dd2016-05-31 11:54:01 -0700598
599// static
dsinclair12a6b0c2016-05-26 11:14:08 -0700600void CXFA_FM2JSContext::Ceil(CFXJSE_Value* pThis,
Dan Sinclair1770c022016-03-14 14:14:16 -0400601 const CFX_ByteStringC& szFuncName,
602 CFXJSE_Arguments& args) {
dsinclair89ba6de2016-05-31 12:11:22 -0700603 if (args.GetLength() != 1) {
dsinclair8f3074b2016-06-02 17:45:25 -0700604 ToJSContext(pThis, nullptr)
605 ->ThrowException(XFA_IDS_INCORRECT_NUMBER_OF_METHOD, L"Ceil");
dsinclair89ba6de2016-05-31 12:11:22 -0700606 return;
Dan Sinclair1770c022016-03-14 14:14:16 -0400607 }
dsinclair89ba6de2016-05-31 12:11:22 -0700608
609 std::unique_ptr<CFXJSE_Value> argValue = GetSimpleValue(pThis, args, 0);
610 if (ValueIsNull(pThis, argValue.get())) {
dsinclairf27aeec2016-06-07 19:36:18 -0700611 args.GetReturnValue()->SetNull();
dsinclair89ba6de2016-05-31 12:11:22 -0700612 return;
613 }
614
dsinclairf27aeec2016-06-07 19:36:18 -0700615 args.GetReturnValue()->SetFloat(
616 FXSYS_ceil(ValueToFloat(pThis, argValue.get())));
Dan Sinclair1770c022016-03-14 14:14:16 -0400617}
dsinclair48d91dd2016-05-31 11:54:01 -0700618
619// static
dsinclair12a6b0c2016-05-26 11:14:08 -0700620void CXFA_FM2JSContext::Count(CFXJSE_Value* pThis,
Dan Sinclair1770c022016-03-14 14:14:16 -0400621 const CFX_ByteStringC& szFuncName,
622 CFXJSE_Arguments& args) {
dsinclair8f3074b2016-06-02 17:45:25 -0700623 CXFA_FM2JSContext* pContext = ToJSContext(pThis, nullptr);
dsinclairec3da5b2016-05-25 16:42:05 -0700624 v8::Isolate* pIsolate = pContext->GetScriptRuntime();
dsinclair89ba6de2016-05-31 12:11:22 -0700625 int32_t iCount = 0;
dsinclair48d91dd2016-05-31 11:54:01 -0700626 for (int32_t i = 0; i < args.GetLength(); i++) {
dsinclair86fad992016-05-31 11:34:04 -0700627 std::unique_ptr<CFXJSE_Value> argValue = args.GetValue(i);
dsinclair769b1372016-06-08 13:12:41 -0700628 if (argValue->IsNull())
Dan Sinclair1770c022016-03-14 14:14:16 -0400629 continue;
dsinclair89ba6de2016-05-31 12:11:22 -0700630
dsinclair769b1372016-06-08 13:12:41 -0700631 if (argValue->IsArray()) {
dsinclair86fad992016-05-31 11:34:04 -0700632 std::unique_ptr<CFXJSE_Value> lengthValue(new CFXJSE_Value(pIsolate));
dsinclairf27aeec2016-06-07 19:36:18 -0700633 argValue->GetObjectProperty("length", lengthValue.get());
dsinclair86fad992016-05-31 11:34:04 -0700634
dsinclairf27aeec2016-06-07 19:36:18 -0700635 int32_t iLength = lengthValue->ToInteger();
dsinclair89ba6de2016-05-31 12:11:22 -0700636 if (iLength <= 2) {
dsinclair2235b7b2016-06-02 07:42:25 -0700637 pContext->ThrowException(XFA_IDS_ARGUMENT_MISMATCH);
dsinclair89ba6de2016-05-31 12:11:22 -0700638 return;
639 }
640
641 std::unique_ptr<CFXJSE_Value> propertyValue(new CFXJSE_Value(pIsolate));
642 std::unique_ptr<CFXJSE_Value> jsObjectValue(new CFXJSE_Value(pIsolate));
643 std::unique_ptr<CFXJSE_Value> newPropertyValue(
644 new CFXJSE_Value(pIsolate));
dsinclairf27aeec2016-06-07 19:36:18 -0700645 argValue->GetObjectPropertyByIdx(1, propertyValue.get());
646 argValue->GetObjectPropertyByIdx(2, jsObjectValue.get());
dsinclair769b1372016-06-08 13:12:41 -0700647 if (propertyValue->IsNull()) {
weilidb444d22016-06-02 15:48:15 -0700648 for (int32_t j = 2; j < iLength; j++) {
dsinclairf27aeec2016-06-07 19:36:18 -0700649 argValue->GetObjectPropertyByIdx(j, jsObjectValue.get());
dsinclair89ba6de2016-05-31 12:11:22 -0700650 GetObjectDefaultValue(jsObjectValue.get(), newPropertyValue.get());
dsinclair769b1372016-06-08 13:12:41 -0700651 if (!newPropertyValue->IsNull())
dsinclair89ba6de2016-05-31 12:11:22 -0700652 iCount++;
Dan Sinclair1770c022016-03-14 14:14:16 -0400653 }
Dan Sinclair1770c022016-03-14 14:14:16 -0400654 } else {
weilidb444d22016-06-02 15:48:15 -0700655 for (int32_t j = 2; j < iLength; j++) {
dsinclairf27aeec2016-06-07 19:36:18 -0700656 argValue->GetObjectPropertyByIdx(j, jsObjectValue.get());
dsinclair2f5582f2016-06-09 11:48:23 -0700657 jsObjectValue->GetObjectProperty(
658 propertyValue->ToString().AsStringC(), newPropertyValue.get());
dsinclair769b1372016-06-08 13:12:41 -0700659 iCount += newPropertyValue->IsNull() ? 0 : 1;
dsinclair89ba6de2016-05-31 12:11:22 -0700660 }
Dan Sinclair1770c022016-03-14 14:14:16 -0400661 }
dsinclair769b1372016-06-08 13:12:41 -0700662 } else if (argValue->IsObject()) {
dsinclair86fad992016-05-31 11:34:04 -0700663 std::unique_ptr<CFXJSE_Value> newPropertyValue(
664 new CFXJSE_Value(pIsolate));
665 GetObjectDefaultValue(argValue.get(), newPropertyValue.get());
dsinclair769b1372016-06-08 13:12:41 -0700666 if (!newPropertyValue->IsNull())
dsinclair89ba6de2016-05-31 12:11:22 -0700667 iCount++;
Dan Sinclair1770c022016-03-14 14:14:16 -0400668 } else {
dsinclair89ba6de2016-05-31 12:11:22 -0700669 iCount++;
Dan Sinclair1770c022016-03-14 14:14:16 -0400670 }
Dan Sinclair1770c022016-03-14 14:14:16 -0400671 }
dsinclairf27aeec2016-06-07 19:36:18 -0700672 args.GetReturnValue()->SetInteger(iCount);
Dan Sinclair1770c022016-03-14 14:14:16 -0400673}
dsinclair48d91dd2016-05-31 11:54:01 -0700674
675// static
dsinclair12a6b0c2016-05-26 11:14:08 -0700676void CXFA_FM2JSContext::Floor(CFXJSE_Value* pThis,
Dan Sinclair1770c022016-03-14 14:14:16 -0400677 const CFX_ByteStringC& szFuncName,
678 CFXJSE_Arguments& args) {
dsinclair89ba6de2016-05-31 12:11:22 -0700679 if (args.GetLength() != 1) {
dsinclair8f3074b2016-06-02 17:45:25 -0700680 ToJSContext(pThis, nullptr)
681 ->ThrowException(XFA_IDS_INCORRECT_NUMBER_OF_METHOD, L"Floor");
dsinclair89ba6de2016-05-31 12:11:22 -0700682 return;
Dan Sinclair1770c022016-03-14 14:14:16 -0400683 }
dsinclair89ba6de2016-05-31 12:11:22 -0700684
685 std::unique_ptr<CFXJSE_Value> argValue = GetSimpleValue(pThis, args, 0);
686 if (ValueIsNull(pThis, argValue.get())) {
dsinclairf27aeec2016-06-07 19:36:18 -0700687 args.GetReturnValue()->SetNull();
dsinclair89ba6de2016-05-31 12:11:22 -0700688 return;
689 }
690
dsinclairf27aeec2016-06-07 19:36:18 -0700691 args.GetReturnValue()->SetFloat(
692 FXSYS_floor(ValueToFloat(pThis, argValue.get())));
Dan Sinclair1770c022016-03-14 14:14:16 -0400693}
dsinclair48d91dd2016-05-31 11:54:01 -0700694
695// static
dsinclair12a6b0c2016-05-26 11:14:08 -0700696void CXFA_FM2JSContext::Max(CFXJSE_Value* pThis,
Dan Sinclair1770c022016-03-14 14:14:16 -0400697 const CFX_ByteStringC& szFuncName,
698 CFXJSE_Arguments& args) {
dsinclair8f3074b2016-06-02 17:45:25 -0700699 CXFA_FM2JSContext* pContext = ToJSContext(pThis, nullptr);
dsinclairec3da5b2016-05-25 16:42:05 -0700700 v8::Isolate* pIsolate = pContext->GetScriptRuntime();
Dan Sinclair1770c022016-03-14 14:14:16 -0400701 uint32_t uCount = 0;
702 FX_DOUBLE dMaxValue = 0.0;
dsinclair48d91dd2016-05-31 11:54:01 -0700703 for (int32_t i = 0; i < args.GetLength(); i++) {
dsinclair86fad992016-05-31 11:34:04 -0700704 std::unique_ptr<CFXJSE_Value> argValue = args.GetValue(i);
dsinclair769b1372016-06-08 13:12:41 -0700705 if (argValue->IsNull())
Dan Sinclair1770c022016-03-14 14:14:16 -0400706 continue;
dsinclair89ba6de2016-05-31 12:11:22 -0700707
dsinclair769b1372016-06-08 13:12:41 -0700708 if (argValue->IsArray()) {
dsinclair86fad992016-05-31 11:34:04 -0700709 std::unique_ptr<CFXJSE_Value> lengthValue(new CFXJSE_Value(pIsolate));
dsinclairf27aeec2016-06-07 19:36:18 -0700710 argValue->GetObjectProperty("length", lengthValue.get());
711 int32_t iLength = lengthValue->ToInteger();
dsinclair89ba6de2016-05-31 12:11:22 -0700712 if (iLength <= 2) {
dsinclair2235b7b2016-06-02 07:42:25 -0700713 pContext->ThrowException(XFA_IDS_ARGUMENT_MISMATCH);
dsinclair89ba6de2016-05-31 12:11:22 -0700714 return;
715 }
dsinclair86fad992016-05-31 11:34:04 -0700716
dsinclair89ba6de2016-05-31 12:11:22 -0700717 std::unique_ptr<CFXJSE_Value> propertyValue(new CFXJSE_Value(pIsolate));
718 std::unique_ptr<CFXJSE_Value> jsObjectValue(new CFXJSE_Value(pIsolate));
719 std::unique_ptr<CFXJSE_Value> newPropertyValue(
720 new CFXJSE_Value(pIsolate));
dsinclairf27aeec2016-06-07 19:36:18 -0700721 argValue->GetObjectPropertyByIdx(1, propertyValue.get());
722 argValue->GetObjectPropertyByIdx(2, jsObjectValue.get());
dsinclair769b1372016-06-08 13:12:41 -0700723 if (propertyValue->IsNull()) {
weilidb444d22016-06-02 15:48:15 -0700724 for (int32_t j = 2; j < iLength; j++) {
dsinclairf27aeec2016-06-07 19:36:18 -0700725 argValue->GetObjectPropertyByIdx(j, jsObjectValue.get());
dsinclair89ba6de2016-05-31 12:11:22 -0700726 GetObjectDefaultValue(jsObjectValue.get(), newPropertyValue.get());
dsinclair769b1372016-06-08 13:12:41 -0700727 if (newPropertyValue->IsNull())
dsinclair89ba6de2016-05-31 12:11:22 -0700728 continue;
729
730 uCount++;
731 FX_DOUBLE dValue = ValueToDouble(pThis, newPropertyValue.get());
732 dMaxValue = (uCount == 1) ? dValue : std::max(dMaxValue, dValue);
Dan Sinclair1770c022016-03-14 14:14:16 -0400733 }
Dan Sinclair1770c022016-03-14 14:14:16 -0400734 } else {
weilidb444d22016-06-02 15:48:15 -0700735 for (int32_t j = 2; j < iLength; j++) {
dsinclairf27aeec2016-06-07 19:36:18 -0700736 argValue->GetObjectPropertyByIdx(j, jsObjectValue.get());
dsinclair2f5582f2016-06-09 11:48:23 -0700737 jsObjectValue->GetObjectProperty(
738 propertyValue->ToString().AsStringC(), newPropertyValue.get());
dsinclair769b1372016-06-08 13:12:41 -0700739 if (newPropertyValue->IsNull())
dsinclair89ba6de2016-05-31 12:11:22 -0700740 continue;
741
742 uCount++;
743 FX_DOUBLE dValue = ValueToDouble(pThis, newPropertyValue.get());
744 dMaxValue = (uCount == 1) ? dValue : std::max(dMaxValue, dValue);
745 }
Dan Sinclair1770c022016-03-14 14:14:16 -0400746 }
dsinclair769b1372016-06-08 13:12:41 -0700747 } else if (argValue->IsObject()) {
dsinclair86fad992016-05-31 11:34:04 -0700748 std::unique_ptr<CFXJSE_Value> newPropertyValue(
749 new CFXJSE_Value(pIsolate));
750 GetObjectDefaultValue(argValue.get(), newPropertyValue.get());
dsinclair769b1372016-06-08 13:12:41 -0700751 if (newPropertyValue->IsNull())
dsinclair89ba6de2016-05-31 12:11:22 -0700752 continue;
753
754 uCount++;
755 FX_DOUBLE dValue = ValueToDouble(pThis, newPropertyValue.get());
756 dMaxValue = (uCount == 1) ? dValue : std::max(dMaxValue, dValue);
Dan Sinclair1770c022016-03-14 14:14:16 -0400757 } else {
758 uCount++;
dsinclair89ba6de2016-05-31 12:11:22 -0700759 FX_DOUBLE dValue = ValueToDouble(pThis, argValue.get());
760 dMaxValue = (uCount == 1) ? dValue : std::max(dMaxValue, dValue);
Dan Sinclair1770c022016-03-14 14:14:16 -0400761 }
Dan Sinclair1770c022016-03-14 14:14:16 -0400762 }
dsinclair89ba6de2016-05-31 12:11:22 -0700763 if (uCount == 0) {
dsinclairf27aeec2016-06-07 19:36:18 -0700764 args.GetReturnValue()->SetNull();
dsinclair89ba6de2016-05-31 12:11:22 -0700765 return;
Dan Sinclair1770c022016-03-14 14:14:16 -0400766 }
dsinclair89ba6de2016-05-31 12:11:22 -0700767
dsinclairf27aeec2016-06-07 19:36:18 -0700768 args.GetReturnValue()->SetDouble(dMaxValue);
Dan Sinclair1770c022016-03-14 14:14:16 -0400769}
dsinclair48d91dd2016-05-31 11:54:01 -0700770
771// static
dsinclair12a6b0c2016-05-26 11:14:08 -0700772void CXFA_FM2JSContext::Min(CFXJSE_Value* pThis,
Dan Sinclair1770c022016-03-14 14:14:16 -0400773 const CFX_ByteStringC& szFuncName,
774 CFXJSE_Arguments& args) {
dsinclair8f3074b2016-06-02 17:45:25 -0700775 CXFA_FM2JSContext* pContext = ToJSContext(pThis, nullptr);
dsinclairec3da5b2016-05-25 16:42:05 -0700776 v8::Isolate* pIsolate = pContext->GetScriptRuntime();
Dan Sinclair1770c022016-03-14 14:14:16 -0400777 uint32_t uCount = 0;
778 FX_DOUBLE dMinValue = 0.0;
dsinclair48d91dd2016-05-31 11:54:01 -0700779 for (int32_t i = 0; i < args.GetLength(); i++) {
dsinclair86fad992016-05-31 11:34:04 -0700780 std::unique_ptr<CFXJSE_Value> argValue = args.GetValue(i);
dsinclair769b1372016-06-08 13:12:41 -0700781 if (argValue->IsNull())
Dan Sinclair1770c022016-03-14 14:14:16 -0400782 continue;
dsinclairdbdcb812016-06-01 20:07:22 -0700783
dsinclair769b1372016-06-08 13:12:41 -0700784 if (argValue->IsArray()) {
dsinclair86fad992016-05-31 11:34:04 -0700785 std::unique_ptr<CFXJSE_Value> lengthValue(new CFXJSE_Value(pIsolate));
dsinclairf27aeec2016-06-07 19:36:18 -0700786 argValue->GetObjectProperty("length", lengthValue.get());
787 int32_t iLength = lengthValue->ToInteger();
dsinclairdbdcb812016-06-01 20:07:22 -0700788 if (iLength <= 2) {
dsinclair2235b7b2016-06-02 07:42:25 -0700789 pContext->ThrowException(XFA_IDS_ARGUMENT_MISMATCH);
dsinclairdbdcb812016-06-01 20:07:22 -0700790 return;
791 }
792
793 std::unique_ptr<CFXJSE_Value> propertyValue(new CFXJSE_Value(pIsolate));
794 std::unique_ptr<CFXJSE_Value> jsObjectValue(new CFXJSE_Value(pIsolate));
795 std::unique_ptr<CFXJSE_Value> newPropertyValue(
796 new CFXJSE_Value(pIsolate));
dsinclairf27aeec2016-06-07 19:36:18 -0700797 argValue->GetObjectPropertyByIdx(1, propertyValue.get());
798 argValue->GetObjectPropertyByIdx(2, jsObjectValue.get());
dsinclair769b1372016-06-08 13:12:41 -0700799 if (propertyValue->IsNull()) {
weilidb444d22016-06-02 15:48:15 -0700800 for (int32_t j = 2; j < iLength; j++) {
dsinclairf27aeec2016-06-07 19:36:18 -0700801 argValue->GetObjectPropertyByIdx(j, jsObjectValue.get());
dsinclairdbdcb812016-06-01 20:07:22 -0700802 GetObjectDefaultValue(jsObjectValue.get(), newPropertyValue.get());
dsinclair769b1372016-06-08 13:12:41 -0700803 if (newPropertyValue->IsNull())
dsinclairdbdcb812016-06-01 20:07:22 -0700804 continue;
805
806 uCount++;
807 FX_DOUBLE dValue = ValueToDouble(pThis, newPropertyValue.get());
808 dMinValue = uCount == 1 ? dValue : std::min(dMinValue, dValue);
Dan Sinclair1770c022016-03-14 14:14:16 -0400809 }
Dan Sinclair1770c022016-03-14 14:14:16 -0400810 } else {
weilidb444d22016-06-02 15:48:15 -0700811 for (int32_t j = 2; j < iLength; j++) {
dsinclairf27aeec2016-06-07 19:36:18 -0700812 argValue->GetObjectPropertyByIdx(j, jsObjectValue.get());
dsinclair2f5582f2016-06-09 11:48:23 -0700813 jsObjectValue->GetObjectProperty(
814 propertyValue->ToString().AsStringC(), newPropertyValue.get());
dsinclair769b1372016-06-08 13:12:41 -0700815 if (newPropertyValue->IsNull())
dsinclairdbdcb812016-06-01 20:07:22 -0700816 continue;
817
818 uCount++;
819 FX_DOUBLE dValue = ValueToDouble(pThis, newPropertyValue.get());
820 dMinValue = uCount == 1 ? dValue : std::min(dMinValue, dValue);
821 }
Dan Sinclair1770c022016-03-14 14:14:16 -0400822 }
dsinclair769b1372016-06-08 13:12:41 -0700823 } else if (argValue->IsObject()) {
dsinclair86fad992016-05-31 11:34:04 -0700824 std::unique_ptr<CFXJSE_Value> newPropertyValue(
825 new CFXJSE_Value(pIsolate));
826 GetObjectDefaultValue(argValue.get(), newPropertyValue.get());
dsinclair769b1372016-06-08 13:12:41 -0700827 if (newPropertyValue->IsNull())
dsinclairdbdcb812016-06-01 20:07:22 -0700828 continue;
829
830 uCount++;
831 FX_DOUBLE dValue = ValueToDouble(pThis, newPropertyValue.get());
832 dMinValue = uCount == 1 ? dValue : std::min(dMinValue, dValue);
Dan Sinclair1770c022016-03-14 14:14:16 -0400833 } else {
834 uCount++;
dsinclairdbdcb812016-06-01 20:07:22 -0700835 FX_DOUBLE dValue = ValueToDouble(pThis, argValue.get());
836 dMinValue = uCount == 1 ? dValue : std::min(dMinValue, dValue);
Dan Sinclair1770c022016-03-14 14:14:16 -0400837 }
Dan Sinclair1770c022016-03-14 14:14:16 -0400838 }
dsinclairdbdcb812016-06-01 20:07:22 -0700839 if (uCount == 0) {
dsinclairf27aeec2016-06-07 19:36:18 -0700840 args.GetReturnValue()->SetNull();
dsinclairdbdcb812016-06-01 20:07:22 -0700841 return;
Dan Sinclair1770c022016-03-14 14:14:16 -0400842 }
dsinclairdbdcb812016-06-01 20:07:22 -0700843
dsinclairf27aeec2016-06-07 19:36:18 -0700844 args.GetReturnValue()->SetDouble(dMinValue);
Dan Sinclair1770c022016-03-14 14:14:16 -0400845}
dsinclair48d91dd2016-05-31 11:54:01 -0700846
847// static
dsinclair12a6b0c2016-05-26 11:14:08 -0700848void CXFA_FM2JSContext::Mod(CFXJSE_Value* pThis,
Dan Sinclair1770c022016-03-14 14:14:16 -0400849 const CFX_ByteStringC& szFuncName,
850 CFXJSE_Arguments& args) {
dsinclair8f3074b2016-06-02 17:45:25 -0700851 CXFA_FM2JSContext* pContext = ToJSContext(pThis, nullptr);
dsinclairdbdcb812016-06-01 20:07:22 -0700852 if (args.GetLength() != 2) {
dsinclair2235b7b2016-06-02 07:42:25 -0700853 pContext->ThrowException(XFA_IDS_INCORRECT_NUMBER_OF_METHOD, L"Mod");
dsinclairdbdcb812016-06-01 20:07:22 -0700854 return;
Dan Sinclair1770c022016-03-14 14:14:16 -0400855 }
dsinclairdbdcb812016-06-01 20:07:22 -0700856
857 std::unique_ptr<CFXJSE_Value> argOne = args.GetValue(0);
858 std::unique_ptr<CFXJSE_Value> argTwo = args.GetValue(1);
dsinclair769b1372016-06-08 13:12:41 -0700859 if (argOne->IsNull() || argTwo->IsNull()) {
dsinclairf27aeec2016-06-07 19:36:18 -0700860 args.GetReturnValue()->SetNull();
dsinclairdbdcb812016-06-01 20:07:22 -0700861 return;
862 }
863
864 bool argOneResult;
865 FX_DOUBLE dDividend = ExtractDouble(pThis, argOne.get(), &argOneResult);
866 bool argTwoResult;
867 FX_DOUBLE dDivisor = ExtractDouble(pThis, argTwo.get(), &argTwoResult);
868 if (!argOneResult || !argTwoResult) {
dsinclair2235b7b2016-06-02 07:42:25 -0700869 pContext->ThrowException(XFA_IDS_ARGUMENT_MISMATCH);
dsinclairdbdcb812016-06-01 20:07:22 -0700870 return;
871 }
872
873 if (dDivisor == 0.0) {
dsinclair2235b7b2016-06-02 07:42:25 -0700874 pContext->ThrowException(XFA_IDS_DIVIDE_ZERO);
dsinclairdbdcb812016-06-01 20:07:22 -0700875 return;
876 }
877
dsinclairf27aeec2016-06-07 19:36:18 -0700878 args.GetReturnValue()->SetDouble(dDividend -
879 dDivisor * (int32_t)(dDividend / dDivisor));
Dan Sinclair1770c022016-03-14 14:14:16 -0400880}
dsinclair48d91dd2016-05-31 11:54:01 -0700881
882// static
dsinclair12a6b0c2016-05-26 11:14:08 -0700883void CXFA_FM2JSContext::Round(CFXJSE_Value* pThis,
Dan Sinclair1770c022016-03-14 14:14:16 -0400884 const CFX_ByteStringC& szFuncName,
885 CFXJSE_Arguments& args) {
dsinclair8f3074b2016-06-02 17:45:25 -0700886 CXFA_FM2JSContext* pContext = ToJSContext(pThis, nullptr);
Dan Sinclair1770c022016-03-14 14:14:16 -0400887 int32_t argc = args.GetLength();
dsinclair2b6d64e2016-06-06 11:39:42 -0700888 if (argc < 1 || argc > 2) {
dsinclair2235b7b2016-06-02 07:42:25 -0700889 pContext->ThrowException(XFA_IDS_INCORRECT_NUMBER_OF_METHOD, L"Round");
dsinclairdbdcb812016-06-01 20:07:22 -0700890 return;
Dan Sinclair1770c022016-03-14 14:14:16 -0400891 }
dsinclairdbdcb812016-06-01 20:07:22 -0700892
893 std::unique_ptr<CFXJSE_Value> argOne = args.GetValue(0);
dsinclair769b1372016-06-08 13:12:41 -0700894 if (argOne->IsNull()) {
dsinclairf27aeec2016-06-07 19:36:18 -0700895 args.GetReturnValue()->SetNull();
dsinclairdbdcb812016-06-01 20:07:22 -0700896 return;
897 }
898
899 bool dValueRet;
900 FX_DOUBLE dValue = ExtractDouble(pThis, argOne.get(), &dValueRet);
901 if (!dValueRet) {
dsinclair2235b7b2016-06-02 07:42:25 -0700902 pContext->ThrowException(XFA_IDS_ARGUMENT_MISMATCH);
dsinclairdbdcb812016-06-01 20:07:22 -0700903 return;
904 }
905
906 uint8_t uPrecision = 0;
dsinclair2b6d64e2016-06-06 11:39:42 -0700907 if (argc > 1) {
dsinclairdbdcb812016-06-01 20:07:22 -0700908 std::unique_ptr<CFXJSE_Value> argTwo = args.GetValue(1);
dsinclair769b1372016-06-08 13:12:41 -0700909 if (argTwo->IsNull()) {
dsinclairf27aeec2016-06-07 19:36:18 -0700910 args.GetReturnValue()->SetNull();
dsinclairdbdcb812016-06-01 20:07:22 -0700911 return;
912 }
913
914 bool dPrecisionRet;
915 FX_DOUBLE dPrecision = ExtractDouble(pThis, argTwo.get(), &dPrecisionRet);
916 if (!dPrecisionRet) {
dsinclair2235b7b2016-06-02 07:42:25 -0700917 pContext->ThrowException(XFA_IDS_ARGUMENT_MISMATCH);
dsinclairdbdcb812016-06-01 20:07:22 -0700918 return;
919 }
920
921 uPrecision =
922 static_cast<uint8_t>(std::min(std::max(dPrecision, 0.0), 12.0));
923 }
924
925 CFX_Decimal decimalValue((FX_FLOAT)dValue, uPrecision);
926 CFX_WideString wsValue = decimalValue;
dsinclairf27aeec2016-06-07 19:36:18 -0700927 args.GetReturnValue()->SetString(wsValue.UTF8Encode().AsStringC());
Dan Sinclair1770c022016-03-14 14:14:16 -0400928}
dsinclair48d91dd2016-05-31 11:54:01 -0700929
930// static
dsinclair12a6b0c2016-05-26 11:14:08 -0700931void CXFA_FM2JSContext::Sum(CFXJSE_Value* pThis,
Dan Sinclair1770c022016-03-14 14:14:16 -0400932 const CFX_ByteStringC& szFuncName,
933 CFXJSE_Arguments& args) {
dsinclairdbdcb812016-06-01 20:07:22 -0700934 int32_t argc = args.GetLength();
935 if (argc == 0) {
dsinclairf27aeec2016-06-07 19:36:18 -0700936 args.GetReturnValue()->SetNull();
dsinclairdbdcb812016-06-01 20:07:22 -0700937 return;
938 }
939
dsinclair8f3074b2016-06-02 17:45:25 -0700940 CXFA_FM2JSContext* pContext = ToJSContext(pThis, nullptr);
dsinclairec3da5b2016-05-25 16:42:05 -0700941 v8::Isolate* pIsolate = pContext->GetScriptRuntime();
Dan Sinclair1770c022016-03-14 14:14:16 -0400942 uint32_t uCount = 0;
943 FX_DOUBLE dSum = 0.0;
dsinclairdbdcb812016-06-01 20:07:22 -0700944 for (int32_t i = 0; i < argc; i++) {
945 std::unique_ptr<CFXJSE_Value> argValue = args.GetValue(i);
dsinclair769b1372016-06-08 13:12:41 -0700946 if (argValue->IsNull())
dsinclairdbdcb812016-06-01 20:07:22 -0700947 continue;
948
dsinclair769b1372016-06-08 13:12:41 -0700949 if (argValue->IsArray()) {
dsinclairdbdcb812016-06-01 20:07:22 -0700950 std::unique_ptr<CFXJSE_Value> lengthValue(new CFXJSE_Value(pIsolate));
dsinclairf27aeec2016-06-07 19:36:18 -0700951 argValue->GetObjectProperty("length", lengthValue.get());
952 int32_t iLength = lengthValue->ToInteger();
dsinclairdbdcb812016-06-01 20:07:22 -0700953 if (iLength <= 2) {
dsinclair2235b7b2016-06-02 07:42:25 -0700954 pContext->ThrowException(XFA_IDS_ARGUMENT_MISMATCH);
dsinclairdbdcb812016-06-01 20:07:22 -0700955 return;
956 }
957
958 std::unique_ptr<CFXJSE_Value> propertyValue(new CFXJSE_Value(pIsolate));
dsinclairf27aeec2016-06-07 19:36:18 -0700959 argValue->GetObjectPropertyByIdx(1, propertyValue.get());
dsinclairdbdcb812016-06-01 20:07:22 -0700960 std::unique_ptr<CFXJSE_Value> jsObjectValue(new CFXJSE_Value(pIsolate));
961 std::unique_ptr<CFXJSE_Value> newPropertyValue(
962 new CFXJSE_Value(pIsolate));
dsinclair769b1372016-06-08 13:12:41 -0700963 if (propertyValue->IsNull()) {
dsinclairdbdcb812016-06-01 20:07:22 -0700964 for (int32_t j = 2; j < iLength; j++) {
dsinclairf27aeec2016-06-07 19:36:18 -0700965 argValue->GetObjectPropertyByIdx(j, jsObjectValue.get());
dsinclairdbdcb812016-06-01 20:07:22 -0700966 GetObjectDefaultValue(jsObjectValue.get(), newPropertyValue.get());
dsinclair769b1372016-06-08 13:12:41 -0700967 if (newPropertyValue->IsNull())
dsinclairdbdcb812016-06-01 20:07:22 -0700968 continue;
969
970 dSum += ValueToDouble(pThis, jsObjectValue.get());
Dan Sinclair1770c022016-03-14 14:14:16 -0400971 uCount++;
972 }
Dan Sinclair1770c022016-03-14 14:14:16 -0400973 } else {
dsinclairdbdcb812016-06-01 20:07:22 -0700974 for (int32_t j = 2; j < iLength; j++) {
dsinclairf27aeec2016-06-07 19:36:18 -0700975 argValue->GetObjectPropertyByIdx(j, jsObjectValue.get());
dsinclair2f5582f2016-06-09 11:48:23 -0700976 jsObjectValue->GetObjectProperty(
977 propertyValue->ToString().AsStringC(), newPropertyValue.get());
dsinclair769b1372016-06-08 13:12:41 -0700978 if (newPropertyValue->IsNull())
dsinclairdbdcb812016-06-01 20:07:22 -0700979 continue;
980
981 dSum += ValueToDouble(pThis, newPropertyValue.get());
982 uCount++;
983 }
Dan Sinclair1770c022016-03-14 14:14:16 -0400984 }
dsinclair769b1372016-06-08 13:12:41 -0700985 } else if (argValue->IsObject()) {
dsinclairdbdcb812016-06-01 20:07:22 -0700986 std::unique_ptr<CFXJSE_Value> newPropertyValue(
987 new CFXJSE_Value(pIsolate));
988 GetObjectDefaultValue(argValue.get(), newPropertyValue.get());
dsinclair769b1372016-06-08 13:12:41 -0700989 if (newPropertyValue->IsNull())
dsinclairdbdcb812016-06-01 20:07:22 -0700990 continue;
991
992 dSum += ValueToDouble(pThis, argValue.get());
993 uCount++;
994 } else {
995 dSum += ValueToDouble(pThis, argValue.get());
996 uCount++;
Dan Sinclair1770c022016-03-14 14:14:16 -0400997 }
Dan Sinclair1770c022016-03-14 14:14:16 -0400998 }
dsinclairdbdcb812016-06-01 20:07:22 -0700999 if (uCount == 0) {
dsinclairf27aeec2016-06-07 19:36:18 -07001000 args.GetReturnValue()->SetNull();
dsinclairdbdcb812016-06-01 20:07:22 -07001001 return;
Dan Sinclair1770c022016-03-14 14:14:16 -04001002 }
dsinclairdbdcb812016-06-01 20:07:22 -07001003
dsinclairf27aeec2016-06-07 19:36:18 -07001004 args.GetReturnValue()->SetDouble(dSum);
Dan Sinclair1770c022016-03-14 14:14:16 -04001005}
dsinclair48d91dd2016-05-31 11:54:01 -07001006
1007// static
dsinclair12a6b0c2016-05-26 11:14:08 -07001008void CXFA_FM2JSContext::Date(CFXJSE_Value* pThis,
Dan Sinclair1770c022016-03-14 14:14:16 -04001009 const CFX_ByteStringC& szFuncName,
1010 CFXJSE_Arguments& args) {
dsinclairdbdcb812016-06-01 20:07:22 -07001011 if (args.GetLength() != 0) {
dsinclair8f3074b2016-06-02 17:45:25 -07001012 ToJSContext(pThis, nullptr)
1013 ->ThrowException(XFA_IDS_INCORRECT_NUMBER_OF_METHOD, L"Date");
dsinclairdbdcb812016-06-01 20:07:22 -07001014 return;
Dan Sinclair1770c022016-03-14 14:14:16 -04001015 }
dsinclairdbdcb812016-06-01 20:07:22 -07001016
1017 time_t currentTime;
1018 time(&currentTime);
1019 struct tm* pTmStruct = gmtime(&currentTime);
1020
1021 CFX_ByteString bufferYear;
1022 CFX_ByteString bufferMon;
1023 CFX_ByteString bufferDay;
1024 bufferYear.Format("%d", pTmStruct->tm_year + 1900);
1025 bufferMon.Format("%02d", pTmStruct->tm_mon + 1);
1026 bufferDay.Format("%02d", pTmStruct->tm_mday);
1027
1028 CFX_ByteString bufferCurrent = bufferYear + bufferMon + bufferDay;
dsinclairf27aeec2016-06-07 19:36:18 -07001029 args.GetReturnValue()->SetInteger(DateString2Num(bufferCurrent.AsStringC()));
Dan Sinclair1770c022016-03-14 14:14:16 -04001030}
dsinclair48d91dd2016-05-31 11:54:01 -07001031
1032// static
dsinclair12a6b0c2016-05-26 11:14:08 -07001033void CXFA_FM2JSContext::Date2Num(CFXJSE_Value* pThis,
Dan Sinclair1770c022016-03-14 14:14:16 -04001034 const CFX_ByteStringC& szFuncName,
1035 CFXJSE_Arguments& args) {
1036 int32_t argc = args.GetLength();
dsinclair2b6d64e2016-06-06 11:39:42 -07001037 if (argc < 1 || argc > 3) {
dsinclair8f3074b2016-06-02 17:45:25 -07001038 ToJSContext(pThis, nullptr)
1039 ->ThrowException(XFA_IDS_INCORRECT_NUMBER_OF_METHOD, L"Date2Num");
dsinclairdbdcb812016-06-01 20:07:22 -07001040 return;
Dan Sinclair1770c022016-03-14 14:14:16 -04001041 }
dsinclairdbdcb812016-06-01 20:07:22 -07001042
1043 std::unique_ptr<CFXJSE_Value> dateValue = GetSimpleValue(pThis, args, 0);
1044 if (ValueIsNull(pThis, dateValue.get())) {
dsinclairf27aeec2016-06-07 19:36:18 -07001045 args.GetReturnValue()->SetNull();
dsinclairdbdcb812016-06-01 20:07:22 -07001046 return;
1047 }
1048
1049 CFX_ByteString dateString;
1050 ValueToUTF8String(dateValue.get(), dateString);
1051
1052 CFX_ByteString formatString;
1053 if (argc > 1) {
1054 std::unique_ptr<CFXJSE_Value> formatValue = GetSimpleValue(pThis, args, 1);
1055 if (ValueIsNull(pThis, formatValue.get())) {
dsinclairf27aeec2016-06-07 19:36:18 -07001056 args.GetReturnValue()->SetNull();
dsinclairdbdcb812016-06-01 20:07:22 -07001057 return;
1058 }
1059 ValueToUTF8String(formatValue.get(), formatString);
1060 }
1061
1062 CFX_ByteString localString;
dsinclair2b6d64e2016-06-06 11:39:42 -07001063 if (argc > 2) {
dsinclairdbdcb812016-06-01 20:07:22 -07001064 std::unique_ptr<CFXJSE_Value> localValue = GetSimpleValue(pThis, args, 2);
1065 if (ValueIsNull(pThis, localValue.get())) {
dsinclairf27aeec2016-06-07 19:36:18 -07001066 args.GetReturnValue()->SetNull();
dsinclairdbdcb812016-06-01 20:07:22 -07001067 return;
1068 }
1069 ValueToUTF8String(localValue.get(), localString);
1070 }
1071
1072 CFX_ByteString szIsoDateString;
1073 if (!Local2IsoDate(pThis, dateString.AsStringC(), formatString.AsStringC(),
1074 localString.AsStringC(), szIsoDateString)) {
dsinclairf27aeec2016-06-07 19:36:18 -07001075 args.GetReturnValue()->SetInteger(0);
dsinclairdbdcb812016-06-01 20:07:22 -07001076 return;
1077 }
1078
dsinclairf27aeec2016-06-07 19:36:18 -07001079 args.GetReturnValue()->SetInteger(
1080 DateString2Num(szIsoDateString.AsStringC()));
Dan Sinclair1770c022016-03-14 14:14:16 -04001081}
dsinclair48d91dd2016-05-31 11:54:01 -07001082
1083// static
dsinclair12a6b0c2016-05-26 11:14:08 -07001084void CXFA_FM2JSContext::DateFmt(CFXJSE_Value* pThis,
Dan Sinclair1770c022016-03-14 14:14:16 -04001085 const CFX_ByteStringC& szFuncName,
1086 CFXJSE_Arguments& args) {
1087 int32_t argc = args.GetLength();
dsinclair2b6d64e2016-06-06 11:39:42 -07001088 if (argc > 2) {
dsinclair8f3074b2016-06-02 17:45:25 -07001089 ToJSContext(pThis, nullptr)
1090 ->ThrowException(XFA_IDS_INCORRECT_NUMBER_OF_METHOD, L"Date2Num");
dsinclairdbdcb812016-06-01 20:07:22 -07001091 return;
Dan Sinclair1770c022016-03-14 14:14:16 -04001092 }
dsinclairdbdcb812016-06-01 20:07:22 -07001093
1094 int32_t iStyle = 0;
1095 if (argc > 0) {
1096 std::unique_ptr<CFXJSE_Value> argStyle = GetSimpleValue(pThis, args, 0);
dsinclair769b1372016-06-08 13:12:41 -07001097 if (argStyle->IsNull()) {
dsinclairf27aeec2016-06-07 19:36:18 -07001098 args.GetReturnValue()->SetNull();
dsinclairdbdcb812016-06-01 20:07:22 -07001099 return;
1100 }
1101
1102 iStyle = (int32_t)ValueToFloat(pThis, argStyle.get());
1103 if (iStyle < 0 || iStyle > 4)
1104 iStyle = 0;
1105 }
1106
1107 CFX_ByteString szLocal;
dsinclair2b6d64e2016-06-06 11:39:42 -07001108 if (argc > 1) {
dsinclairdbdcb812016-06-01 20:07:22 -07001109 std::unique_ptr<CFXJSE_Value> argLocal = GetSimpleValue(pThis, args, 1);
dsinclair769b1372016-06-08 13:12:41 -07001110 if (argLocal->IsNull()) {
dsinclairf27aeec2016-06-07 19:36:18 -07001111 args.GetReturnValue()->SetNull();
dsinclairdbdcb812016-06-01 20:07:22 -07001112 return;
1113 }
1114 ValueToUTF8String(argLocal.get(), szLocal);
1115 }
1116
1117 CFX_ByteString formatStr;
1118 GetStandardDateFormat(pThis, iStyle, szLocal.AsStringC(), formatStr);
dsinclairf27aeec2016-06-07 19:36:18 -07001119 args.GetReturnValue()->SetString(formatStr.AsStringC());
Dan Sinclair1770c022016-03-14 14:14:16 -04001120}
dsinclair48d91dd2016-05-31 11:54:01 -07001121
1122// static
dsinclair12a6b0c2016-05-26 11:14:08 -07001123void CXFA_FM2JSContext::IsoDate2Num(CFXJSE_Value* pThis,
Dan Sinclair1770c022016-03-14 14:14:16 -04001124 const CFX_ByteStringC& szFuncName,
1125 CFXJSE_Arguments& args) {
dsinclairdbdcb812016-06-01 20:07:22 -07001126 if (args.GetLength() != 1) {
dsinclair8f3074b2016-06-02 17:45:25 -07001127 ToJSContext(pThis, nullptr)
1128 ->ThrowException(XFA_IDS_INCORRECT_NUMBER_OF_METHOD, L"IsoDate2Num");
dsinclairdbdcb812016-06-01 20:07:22 -07001129 return;
Dan Sinclair1770c022016-03-14 14:14:16 -04001130 }
dsinclairdbdcb812016-06-01 20:07:22 -07001131
1132 std::unique_ptr<CFXJSE_Value> argOne = GetSimpleValue(pThis, args, 0);
dsinclair769b1372016-06-08 13:12:41 -07001133 if (argOne->IsNull()) {
dsinclairf27aeec2016-06-07 19:36:18 -07001134 args.GetReturnValue()->SetNull();
dsinclairdbdcb812016-06-01 20:07:22 -07001135 return;
1136 }
1137
1138 CFX_ByteString szArgString;
1139 ValueToUTF8String(argOne.get(), szArgString);
dsinclairf27aeec2016-06-07 19:36:18 -07001140 args.GetReturnValue()->SetInteger(DateString2Num(szArgString.AsStringC()));
Dan Sinclair1770c022016-03-14 14:14:16 -04001141}
dsinclair48d91dd2016-05-31 11:54:01 -07001142
1143// static
dsinclair12a6b0c2016-05-26 11:14:08 -07001144void CXFA_FM2JSContext::IsoTime2Num(CFXJSE_Value* pThis,
Dan Sinclair1770c022016-03-14 14:14:16 -04001145 const CFX_ByteStringC& szFuncName,
1146 CFXJSE_Arguments& args) {
dsinclair8f3074b2016-06-02 17:45:25 -07001147 CXFA_FM2JSContext* pContext = ToJSContext(pThis, nullptr);
dsinclairdbdcb812016-06-01 20:07:22 -07001148 if (args.GetLength() != 1) {
dsinclair2235b7b2016-06-02 07:42:25 -07001149 pContext->ThrowException(XFA_IDS_INCORRECT_NUMBER_OF_METHOD,
1150 L"IsoTime2Num");
dsinclairdbdcb812016-06-01 20:07:22 -07001151 return;
Dan Sinclair1770c022016-03-14 14:14:16 -04001152 }
dsinclairdbdcb812016-06-01 20:07:22 -07001153
1154 std::unique_ptr<CFXJSE_Value> argOne = GetSimpleValue(pThis, args, 0);
1155 if (ValueIsNull(pThis, argOne.get())) {
dsinclairf27aeec2016-06-07 19:36:18 -07001156 args.GetReturnValue()->SetNull();
dsinclairdbdcb812016-06-01 20:07:22 -07001157 return;
1158 }
1159
1160 CXFA_Document* pDoc = pContext->GetDocument();
1161 CXFA_LocaleMgr* pMgr = pDoc->GetLocalMgr();
1162
1163 CFX_ByteString szArgString;
1164 ValueToUTF8String(argOne.get(), szArgString);
1165 szArgString = szArgString.Mid(szArgString.Find('T', 0) + 1);
1166 if (szArgString.IsEmpty()) {
dsinclairf27aeec2016-06-07 19:36:18 -07001167 args.GetReturnValue()->SetInteger(0);
dsinclairdbdcb812016-06-01 20:07:22 -07001168 return;
1169 }
1170
1171 CXFA_LocaleValue timeValue(
1172 XFA_VT_TIME, CFX_WideString::FromUTF8(szArgString.AsStringC()), pMgr);
1173 if (!timeValue.IsValid()) {
dsinclairf27aeec2016-06-07 19:36:18 -07001174 args.GetReturnValue()->SetInteger(0);
dsinclairdbdcb812016-06-01 20:07:22 -07001175 return;
1176 }
1177
1178 CFX_Unitime uniTime = timeValue.GetTime();
1179 int32_t hour = uniTime.GetHour();
1180 int32_t min = uniTime.GetMinute();
1181 int32_t second = uniTime.GetSecond();
1182 int32_t milSecond = uniTime.GetMillisecond();
1183
1184 FX_TIMEZONE tzLocale;
1185 pMgr->GetDefLocale()->GetTimeZone(tzLocale);
1186
1187 // TODO(dsinclair): See if there is other time conversion code in pdfium and
1188 // consolidate.
1189 int32_t mins = hour * 60 + min;
1190 mins -= (tzLocale.tzHour * 60);
1191 while (mins > 1440)
1192 mins -= 1440;
1193 while (mins < 0)
1194 mins += 1440;
1195 hour = mins / 60;
1196 min = mins % 60;
dsinclairf27aeec2016-06-07 19:36:18 -07001197
1198 args.GetReturnValue()->SetInteger(hour * 3600000 + min * 60000 +
1199 second * 1000 + milSecond + 1);
Dan Sinclair1770c022016-03-14 14:14:16 -04001200}
dsinclair48d91dd2016-05-31 11:54:01 -07001201
1202// static
dsinclair12a6b0c2016-05-26 11:14:08 -07001203void CXFA_FM2JSContext::LocalDateFmt(CFXJSE_Value* pThis,
Dan Sinclair1770c022016-03-14 14:14:16 -04001204 const CFX_ByteStringC& szFuncName,
1205 CFXJSE_Arguments& args) {
1206 int32_t argc = args.GetLength();
dsinclair2b6d64e2016-06-06 11:39:42 -07001207 if (argc > 2) {
dsinclair8f3074b2016-06-02 17:45:25 -07001208 ToJSContext(pThis, nullptr)
1209 ->ThrowException(XFA_IDS_INCORRECT_NUMBER_OF_METHOD, L"LocalDateFmt");
dsinclair2b6d64e2016-06-06 11:39:42 -07001210 return;
Dan Sinclair1770c022016-03-14 14:14:16 -04001211 }
dsinclair2b6d64e2016-06-06 11:39:42 -07001212
1213 int32_t iStyle = 0;
1214 if (argc > 0) {
1215 std::unique_ptr<CFXJSE_Value> argStyle = GetSimpleValue(pThis, args, 0);
dsinclair769b1372016-06-08 13:12:41 -07001216 if (argStyle->IsNull()) {
dsinclairf27aeec2016-06-07 19:36:18 -07001217 args.GetReturnValue()->SetNull();
dsinclair2b6d64e2016-06-06 11:39:42 -07001218 return;
1219 }
1220 iStyle = (int32_t)ValueToFloat(pThis, argStyle.get());
1221 if (iStyle > 4 || iStyle < 0)
1222 iStyle = 0;
1223 }
1224
1225 CFX_ByteString szLocal;
1226 if (argc > 1) {
1227 std::unique_ptr<CFXJSE_Value> argLocal = GetSimpleValue(pThis, args, 1);
dsinclair769b1372016-06-08 13:12:41 -07001228 if (argLocal->IsNull()) {
dsinclairf27aeec2016-06-07 19:36:18 -07001229 args.GetReturnValue()->SetNull();
dsinclair2b6d64e2016-06-06 11:39:42 -07001230 return;
1231 }
1232 ValueToUTF8String(argLocal.get(), szLocal);
1233 }
1234
1235 CFX_ByteString formatStr;
1236 GetLocalDateFormat(pThis, iStyle, szLocal.AsStringC(), formatStr, FALSE);
dsinclairf27aeec2016-06-07 19:36:18 -07001237 args.GetReturnValue()->SetString(formatStr.AsStringC());
Dan Sinclair1770c022016-03-14 14:14:16 -04001238}
dsinclair48d91dd2016-05-31 11:54:01 -07001239
1240// static
dsinclair12a6b0c2016-05-26 11:14:08 -07001241void CXFA_FM2JSContext::LocalTimeFmt(CFXJSE_Value* pThis,
Dan Sinclair1770c022016-03-14 14:14:16 -04001242 const CFX_ByteStringC& szFuncName,
1243 CFXJSE_Arguments& args) {
1244 int32_t argc = args.GetLength();
dsinclair2b6d64e2016-06-06 11:39:42 -07001245 if (argc > 2) {
dsinclair8f3074b2016-06-02 17:45:25 -07001246 ToJSContext(pThis, nullptr)
1247 ->ThrowException(XFA_IDS_INCORRECT_NUMBER_OF_METHOD, L"LocalTimeFmt");
dsinclair2b6d64e2016-06-06 11:39:42 -07001248 return;
Dan Sinclair1770c022016-03-14 14:14:16 -04001249 }
dsinclair2b6d64e2016-06-06 11:39:42 -07001250
1251 int32_t iStyle = 0;
1252 if (argc > 0) {
1253 std::unique_ptr<CFXJSE_Value> argStyle = GetSimpleValue(pThis, args, 0);
dsinclair769b1372016-06-08 13:12:41 -07001254 if (argStyle->IsNull()) {
dsinclairf27aeec2016-06-07 19:36:18 -07001255 args.GetReturnValue()->SetNull();
dsinclair2b6d64e2016-06-06 11:39:42 -07001256 return;
1257 }
1258 iStyle = (int32_t)ValueToFloat(pThis, argStyle.get());
1259 if (iStyle > 4 || iStyle < 0)
1260 iStyle = 0;
1261 }
1262
1263 CFX_ByteString szLocal;
1264 if (argc > 1) {
1265 std::unique_ptr<CFXJSE_Value> argLocal = GetSimpleValue(pThis, args, 1);
dsinclair769b1372016-06-08 13:12:41 -07001266 if (argLocal->IsNull()) {
dsinclairf27aeec2016-06-07 19:36:18 -07001267 args.GetReturnValue()->SetNull();
dsinclair2b6d64e2016-06-06 11:39:42 -07001268 return;
1269 }
1270 ValueToUTF8String(argLocal.get(), szLocal);
1271 }
1272
1273 CFX_ByteString formatStr;
1274 GetLocalTimeFormat(pThis, iStyle, szLocal.AsStringC(), formatStr, FALSE);
dsinclairf27aeec2016-06-07 19:36:18 -07001275 args.GetReturnValue()->SetString(formatStr.AsStringC());
Dan Sinclair1770c022016-03-14 14:14:16 -04001276}
dsinclair48d91dd2016-05-31 11:54:01 -07001277
1278// static
dsinclair12a6b0c2016-05-26 11:14:08 -07001279void CXFA_FM2JSContext::Num2Date(CFXJSE_Value* pThis,
Dan Sinclair1770c022016-03-14 14:14:16 -04001280 const CFX_ByteStringC& szFuncName,
1281 CFXJSE_Arguments& args) {
1282 int32_t argc = args.GetLength();
dsinclair2b6d64e2016-06-06 11:39:42 -07001283 if (argc < 1 || argc > 3) {
dsinclair8f3074b2016-06-02 17:45:25 -07001284 ToJSContext(pThis, nullptr)
1285 ->ThrowException(XFA_IDS_INCORRECT_NUMBER_OF_METHOD, L"Num2Date");
dsinclair2b6d64e2016-06-06 11:39:42 -07001286 return;
Dan Sinclair1770c022016-03-14 14:14:16 -04001287 }
dsinclair2b6d64e2016-06-06 11:39:42 -07001288
1289 std::unique_ptr<CFXJSE_Value> dateValue = GetSimpleValue(pThis, args, 0);
1290 if (ValueIsNull(pThis, dateValue.get())) {
dsinclairf27aeec2016-06-07 19:36:18 -07001291 args.GetReturnValue()->SetNull();
dsinclair2b6d64e2016-06-06 11:39:42 -07001292 return;
1293 }
1294 int32_t dDate = (int32_t)ValueToFloat(pThis, dateValue.get());
1295 if (dDate < 1) {
dsinclairf27aeec2016-06-07 19:36:18 -07001296 args.GetReturnValue()->SetNull();
dsinclair2b6d64e2016-06-06 11:39:42 -07001297 return;
1298 }
1299
1300 CFX_ByteString formatString;
1301 if (argc > 1) {
1302 std::unique_ptr<CFXJSE_Value> formatValue = GetSimpleValue(pThis, args, 1);
1303 if (ValueIsNull(pThis, formatValue.get())) {
dsinclairf27aeec2016-06-07 19:36:18 -07001304 args.GetReturnValue()->SetNull();
dsinclair2b6d64e2016-06-06 11:39:42 -07001305 return;
1306 }
1307 ValueToUTF8String(formatValue.get(), formatString);
1308 }
1309
1310 CFX_ByteString localString;
1311 if (argc > 2) {
1312 std::unique_ptr<CFXJSE_Value> localValue = GetSimpleValue(pThis, args, 2);
1313 if (ValueIsNull(pThis, localValue.get())) {
dsinclairf27aeec2016-06-07 19:36:18 -07001314 args.GetReturnValue()->SetNull();
dsinclair2b6d64e2016-06-06 11:39:42 -07001315 return;
1316 }
1317 ValueToUTF8String(localValue.get(), localString);
1318 }
1319
1320 int32_t iYear = 1900;
1321 int32_t iMonth = 1;
1322 int32_t iDay = 1;
1323 int32_t i = 0;
1324 while (dDate > 0) {
1325 if (iMonth == 2) {
1326 if ((!((iYear + i) % 4) && ((iYear + i) % 100)) || !((iYear + i) % 400)) {
1327 if (dDate > 29) {
1328 ++iMonth;
1329 if (iMonth > 12) {
1330 iMonth = 1;
1331 ++i;
1332 }
1333 iDay = 1;
1334 dDate -= 29;
1335 } else {
1336 iDay += static_cast<int32_t>(dDate) - 1;
1337 dDate = 0;
1338 }
1339 } else {
1340 if (dDate > 28) {
1341 ++iMonth;
1342 if (iMonth > 12) {
1343 iMonth = 1;
1344 ++i;
1345 }
1346 iDay = 1;
1347 dDate -= 28;
1348 } else {
1349 iDay += static_cast<int32_t>(dDate) - 1;
1350 dDate = 0;
1351 }
1352 }
1353 } else if (iMonth < 8) {
1354 if ((iMonth % 2 == 0)) {
1355 if (dDate > 30) {
1356 ++iMonth;
1357 if (iMonth > 12) {
1358 iMonth = 1;
1359 ++i;
1360 }
1361 iDay = 1;
1362 dDate -= 30;
1363 } else {
1364 iDay += static_cast<int32_t>(dDate) - 1;
1365 dDate = 0;
1366 }
1367 } else {
1368 if (dDate > 31) {
1369 ++iMonth;
1370 if (iMonth > 12) {
1371 iMonth = 1;
1372 ++i;
1373 }
1374 iDay = 1;
1375 dDate -= 31;
1376 } else {
1377 iDay += static_cast<int32_t>(dDate) - 1;
1378 dDate = 0;
1379 }
1380 }
1381 } else {
1382 if (iMonth % 2 != 0) {
1383 if (dDate > 30) {
1384 ++iMonth;
1385 if (iMonth > 12) {
1386 iMonth = 1;
1387 ++i;
1388 }
1389 iDay = 1;
1390 dDate -= 30;
1391 } else {
1392 iDay += static_cast<int32_t>(dDate) - 1;
1393 dDate = 0;
1394 }
1395 } else {
1396 if (dDate > 31) {
1397 ++iMonth;
1398 if (iMonth > 12) {
1399 iMonth = 1;
1400 ++i;
1401 }
1402 iDay = 1;
1403 dDate -= 31;
1404 } else {
1405 iDay += static_cast<int32_t>(dDate) - 1;
1406 dDate = 0;
1407 }
1408 }
1409 }
1410 }
1411
1412 CFX_ByteString szIsoDateString;
1413 szIsoDateString.Format("%d%02d%02d", iYear + i, iMonth, iDay);
1414 CFX_ByteString szLocalDateString;
1415 IsoDate2Local(pThis, szIsoDateString.AsStringC(), formatString.AsStringC(),
1416 localString.AsStringC(), szLocalDateString);
dsinclairf27aeec2016-06-07 19:36:18 -07001417 args.GetReturnValue()->SetString(szLocalDateString.AsStringC());
Dan Sinclair1770c022016-03-14 14:14:16 -04001418}
dsinclair48d91dd2016-05-31 11:54:01 -07001419
1420// static
dsinclair12a6b0c2016-05-26 11:14:08 -07001421void CXFA_FM2JSContext::Num2GMTime(CFXJSE_Value* pThis,
Dan Sinclair1770c022016-03-14 14:14:16 -04001422 const CFX_ByteStringC& szFuncName,
1423 CFXJSE_Arguments& args) {
1424 int32_t argc = args.GetLength();
dsinclair2b6d64e2016-06-06 11:39:42 -07001425 if (argc < 1 || argc > 3) {
dsinclair8f3074b2016-06-02 17:45:25 -07001426 ToJSContext(pThis, nullptr)
1427 ->ThrowException(XFA_IDS_INCORRECT_NUMBER_OF_METHOD, L"Num2GMTime");
dsinclair2b6d64e2016-06-06 11:39:42 -07001428 return;
Dan Sinclair1770c022016-03-14 14:14:16 -04001429 }
dsinclair2b6d64e2016-06-06 11:39:42 -07001430
1431 std::unique_ptr<CFXJSE_Value> timeValue = GetSimpleValue(pThis, args, 0);
dsinclair769b1372016-06-08 13:12:41 -07001432 if (timeValue->IsNull()) {
dsinclairf27aeec2016-06-07 19:36:18 -07001433 args.GetReturnValue()->SetNull();
dsinclair2b6d64e2016-06-06 11:39:42 -07001434 return;
1435 }
1436 int32_t iTime = (int32_t)ValueToFloat(pThis, timeValue.get());
1437 if (FXSYS_abs(iTime) < 1.0) {
dsinclairf27aeec2016-06-07 19:36:18 -07001438 args.GetReturnValue()->SetNull();
dsinclair2b6d64e2016-06-06 11:39:42 -07001439 return;
1440 }
1441
1442 CFX_ByteString formatString;
1443 if (argc > 1) {
1444 std::unique_ptr<CFXJSE_Value> formatValue = GetSimpleValue(pThis, args, 1);
dsinclair769b1372016-06-08 13:12:41 -07001445 if (formatValue->IsNull()) {
dsinclairf27aeec2016-06-07 19:36:18 -07001446 args.GetReturnValue()->SetNull();
dsinclair2b6d64e2016-06-06 11:39:42 -07001447 return;
1448 }
1449 ValueToUTF8String(formatValue.get(), formatString);
1450 }
1451
1452 CFX_ByteString localString;
1453 if (argc > 2) {
1454 std::unique_ptr<CFXJSE_Value> localValue = GetSimpleValue(pThis, args, 2);
dsinclair769b1372016-06-08 13:12:41 -07001455 if (localValue->IsNull()) {
dsinclairf27aeec2016-06-07 19:36:18 -07001456 args.GetReturnValue()->SetNull();
dsinclair2b6d64e2016-06-06 11:39:42 -07001457 return;
1458 }
1459 ValueToUTF8String(localValue.get(), localString);
1460 }
1461
1462 CFX_ByteString szGMTTimeString;
1463 Num2AllTime(pThis, iTime, formatString.AsStringC(), localString.AsStringC(),
1464 TRUE, szGMTTimeString);
dsinclairf27aeec2016-06-07 19:36:18 -07001465 args.GetReturnValue()->SetString(szGMTTimeString.AsStringC());
Dan Sinclair1770c022016-03-14 14:14:16 -04001466}
dsinclair48d91dd2016-05-31 11:54:01 -07001467
1468// static
dsinclair12a6b0c2016-05-26 11:14:08 -07001469void CXFA_FM2JSContext::Num2Time(CFXJSE_Value* pThis,
Dan Sinclair1770c022016-03-14 14:14:16 -04001470 const CFX_ByteStringC& szFuncName,
1471 CFXJSE_Arguments& args) {
1472 int32_t argc = args.GetLength();
dsinclair2b6d64e2016-06-06 11:39:42 -07001473 if (argc < 1 || argc > 3) {
dsinclair8f3074b2016-06-02 17:45:25 -07001474 ToJSContext(pThis, nullptr)
1475 ->ThrowException(XFA_IDS_INCORRECT_NUMBER_OF_METHOD, L"Num2Time");
dsinclair2b6d64e2016-06-06 11:39:42 -07001476 return;
Dan Sinclair1770c022016-03-14 14:14:16 -04001477 }
dsinclair2b6d64e2016-06-06 11:39:42 -07001478
1479 std::unique_ptr<CFXJSE_Value> timeValue = GetSimpleValue(pThis, args, 0);
dsinclair769b1372016-06-08 13:12:41 -07001480 if (timeValue->IsNull()) {
dsinclairf27aeec2016-06-07 19:36:18 -07001481 args.GetReturnValue()->SetNull();
dsinclair2b6d64e2016-06-06 11:39:42 -07001482 return;
1483 }
1484 FX_FLOAT fTime = ValueToFloat(pThis, timeValue.get());
1485 if (FXSYS_fabs(fTime) < 1.0) {
dsinclairf27aeec2016-06-07 19:36:18 -07001486 args.GetReturnValue()->SetNull();
dsinclair2b6d64e2016-06-06 11:39:42 -07001487 return;
1488 }
1489
1490 CFX_ByteString formatString;
1491 if (argc > 1) {
1492 std::unique_ptr<CFXJSE_Value> formatValue = GetSimpleValue(pThis, args, 1);
dsinclair769b1372016-06-08 13:12:41 -07001493 if (formatValue->IsNull()) {
dsinclairf27aeec2016-06-07 19:36:18 -07001494 args.GetReturnValue()->SetNull();
dsinclair2b6d64e2016-06-06 11:39:42 -07001495 return;
1496 }
1497 ValueToUTF8String(formatValue.get(), formatString);
1498 }
1499
1500 CFX_ByteString localString;
1501 if (argc > 2) {
1502 std::unique_ptr<CFXJSE_Value> localValue = GetSimpleValue(pThis, args, 2);
dsinclair769b1372016-06-08 13:12:41 -07001503 if (localValue->IsNull()) {
dsinclairf27aeec2016-06-07 19:36:18 -07001504 args.GetReturnValue()->SetNull();
dsinclair2b6d64e2016-06-06 11:39:42 -07001505 return;
1506 }
1507 ValueToUTF8String(localValue.get(), localString);
1508 }
1509
1510 CFX_ByteString szLocalTimeString;
1511 Num2AllTime(pThis, (int32_t)fTime, formatString.AsStringC(),
1512 localString.AsStringC(), FALSE, szLocalTimeString);
dsinclairf27aeec2016-06-07 19:36:18 -07001513 args.GetReturnValue()->SetString(szLocalTimeString.AsStringC());
Dan Sinclair1770c022016-03-14 14:14:16 -04001514}
dsinclair48d91dd2016-05-31 11:54:01 -07001515
1516// static
dsinclair12a6b0c2016-05-26 11:14:08 -07001517void CXFA_FM2JSContext::Time(CFXJSE_Value* pThis,
Dan Sinclair1770c022016-03-14 14:14:16 -04001518 const CFX_ByteStringC& szFuncName,
1519 CFXJSE_Arguments& args) {
dsinclair2b6d64e2016-06-06 11:39:42 -07001520 if (args.GetLength() != 0) {
dsinclair8f3074b2016-06-02 17:45:25 -07001521 ToJSContext(pThis, nullptr)
1522 ->ThrowException(XFA_IDS_INCORRECT_NUMBER_OF_METHOD, L"Time");
dsinclair2b6d64e2016-06-06 11:39:42 -07001523 return;
Dan Sinclair1770c022016-03-14 14:14:16 -04001524 }
dsinclair2b6d64e2016-06-06 11:39:42 -07001525
1526 time_t now;
1527 time(&now);
1528
1529 struct tm* pGmt = gmtime(&now);
dsinclairf27aeec2016-06-07 19:36:18 -07001530 args.GetReturnValue()->SetInteger(
1531 (pGmt->tm_hour * 3600 + pGmt->tm_min * 60 + pGmt->tm_sec) * 1000);
Dan Sinclair1770c022016-03-14 14:14:16 -04001532}
dsinclair48d91dd2016-05-31 11:54:01 -07001533
1534// static
dsinclair12a6b0c2016-05-26 11:14:08 -07001535void CXFA_FM2JSContext::Time2Num(CFXJSE_Value* pThis,
Dan Sinclair1770c022016-03-14 14:14:16 -04001536 const CFX_ByteStringC& szFuncName,
1537 CFXJSE_Arguments& args) {
1538 int32_t argc = args.GetLength();
dsinclair2b6d64e2016-06-06 11:39:42 -07001539 if (argc < 1 || argc > 3) {
dsinclair8f3074b2016-06-02 17:45:25 -07001540 ToJSContext(pThis, nullptr)
1541 ->ThrowException(XFA_IDS_INCORRECT_NUMBER_OF_METHOD, L"Time2Num");
dsinclair2b6d64e2016-06-06 11:39:42 -07001542 return;
Dan Sinclair1770c022016-03-14 14:14:16 -04001543 }
dsinclair2b6d64e2016-06-06 11:39:42 -07001544
1545 CFX_ByteString timeString;
1546 std::unique_ptr<CFXJSE_Value> timeValue = GetSimpleValue(pThis, args, 0);
1547 if (ValueIsNull(pThis, timeValue.get())) {
dsinclairf27aeec2016-06-07 19:36:18 -07001548 args.GetReturnValue()->SetNull();
dsinclair2b6d64e2016-06-06 11:39:42 -07001549 return;
1550 }
1551 ValueToUTF8String(timeValue.get(), timeString);
1552
1553 CFX_ByteString formatString;
1554 if (argc > 1) {
1555 std::unique_ptr<CFXJSE_Value> formatValue = GetSimpleValue(pThis, args, 1);
1556 if (ValueIsNull(pThis, formatValue.get())) {
dsinclairf27aeec2016-06-07 19:36:18 -07001557 args.GetReturnValue()->SetNull();
dsinclair2b6d64e2016-06-06 11:39:42 -07001558 return;
1559 }
1560 ValueToUTF8String(formatValue.get(), formatString);
1561 }
1562
1563 CFX_ByteString localString;
1564 if (argc > 2) {
1565 std::unique_ptr<CFXJSE_Value> localValue = GetSimpleValue(pThis, args, 2);
1566 if (ValueIsNull(pThis, localValue.get())) {
dsinclairf27aeec2016-06-07 19:36:18 -07001567 args.GetReturnValue()->SetNull();
dsinclair2b6d64e2016-06-06 11:39:42 -07001568 return;
1569 }
1570 ValueToUTF8String(localValue.get(), localString);
1571 }
1572
1573 CXFA_Document* pDoc = ToJSContext(pThis, nullptr)->GetDocument();
1574 CXFA_LocaleMgr* pMgr = pDoc->GetLocalMgr();
1575 IFX_Locale* pLocale = nullptr;
1576 if (localString.IsEmpty()) {
1577 CXFA_Node* pThisNode = ToNode(pDoc->GetScriptContext()->GetThisObject());
1578 ASSERT(pThisNode);
1579
1580 CXFA_WidgetData widgetData(pThisNode);
1581 pLocale = widgetData.GetLocal();
1582 } else {
1583 pLocale = pMgr->GetLocaleByName(
1584 CFX_WideString::FromUTF8(localString.AsStringC()));
1585 }
1586
1587 CFX_WideString wsFormat;
1588 if (formatString.IsEmpty())
1589 pLocale->GetTimePattern(FX_LOCALEDATETIMESUBCATEGORY_Default, wsFormat);
1590 else
1591 wsFormat = CFX_WideString::FromUTF8(formatString.AsStringC());
1592
dsinclaircf7f3222016-06-08 20:34:02 -07001593 wsFormat = L"time{" + wsFormat + L"}";
dsinclair2b6d64e2016-06-06 11:39:42 -07001594 CXFA_LocaleValue localeValue(XFA_VT_TIME,
1595 CFX_WideString::FromUTF8(timeString.AsStringC()),
1596 wsFormat, pLocale, pMgr);
1597 if (!localeValue.IsValid()) {
dsinclairf27aeec2016-06-07 19:36:18 -07001598 args.GetReturnValue()->SetInteger(0);
dsinclair2b6d64e2016-06-06 11:39:42 -07001599 return;
1600 }
1601
1602 CFX_Unitime uniTime = localeValue.GetTime();
1603 int32_t hour = uniTime.GetHour();
1604 int32_t min = uniTime.GetMinute();
1605 int32_t second = uniTime.GetSecond();
1606 int32_t milSecond = uniTime.GetMillisecond();
1607 int32_t mins = hour * 60 + min;
1608 CXFA_TimeZoneProvider* pProvider = CXFA_TimeZoneProvider::Get();
1609 if (pProvider) {
1610 FX_TIMEZONE tz;
1611 pProvider->GetTimeZone(tz);
1612 mins -= (tz.tzHour * 60);
1613 while (mins > 1440)
1614 mins -= 1440;
1615 while (mins < 0)
1616 mins += 1440;
1617
1618 hour = mins / 60;
1619 min = mins % 60;
1620 }
dsinclairf27aeec2016-06-07 19:36:18 -07001621 args.GetReturnValue()->SetInteger(hour * 3600000 + min * 60000 +
1622 second * 1000 + milSecond + 1);
Dan Sinclair1770c022016-03-14 14:14:16 -04001623}
dsinclair48d91dd2016-05-31 11:54:01 -07001624
1625// static
dsinclair12a6b0c2016-05-26 11:14:08 -07001626void CXFA_FM2JSContext::TimeFmt(CFXJSE_Value* pThis,
Dan Sinclair1770c022016-03-14 14:14:16 -04001627 const CFX_ByteStringC& szFuncName,
1628 CFXJSE_Arguments& args) {
1629 int32_t argc = args.GetLength();
dsinclair2b6d64e2016-06-06 11:39:42 -07001630 if (argc > 2) {
dsinclair8f3074b2016-06-02 17:45:25 -07001631 ToJSContext(pThis, nullptr)
1632 ->ThrowException(XFA_IDS_INCORRECT_NUMBER_OF_METHOD, L"TimeFmt");
dsinclair2b6d64e2016-06-06 11:39:42 -07001633 return;
Dan Sinclair1770c022016-03-14 14:14:16 -04001634 }
dsinclair2b6d64e2016-06-06 11:39:42 -07001635
1636 int32_t iStyle = 0;
1637 if (argc > 0) {
1638 std::unique_ptr<CFXJSE_Value> argStyle = GetSimpleValue(pThis, args, 0);
dsinclair769b1372016-06-08 13:12:41 -07001639 if (argStyle->IsNull()) {
dsinclairf27aeec2016-06-07 19:36:18 -07001640 args.GetReturnValue()->SetNull();
dsinclair2b6d64e2016-06-06 11:39:42 -07001641 return;
1642 }
1643 iStyle = (int32_t)ValueToFloat(pThis, argStyle.get());
1644 if (iStyle > 4 || iStyle < 0)
1645 iStyle = 0;
1646 }
1647
1648 CFX_ByteString szLocal;
1649 if (argc > 1) {
1650 std::unique_ptr<CFXJSE_Value> argLocal = GetSimpleValue(pThis, args, 1);
dsinclair769b1372016-06-08 13:12:41 -07001651 if (argLocal->IsNull()) {
dsinclairf27aeec2016-06-07 19:36:18 -07001652 args.GetReturnValue()->SetNull();
dsinclair2b6d64e2016-06-06 11:39:42 -07001653 return;
1654 }
1655 ValueToUTF8String(argLocal.get(), szLocal);
1656 }
1657
1658 CFX_ByteString formatStr;
1659 GetStandardTimeFormat(pThis, iStyle, szLocal.AsStringC(), formatStr);
dsinclairf27aeec2016-06-07 19:36:18 -07001660 args.GetReturnValue()->SetString(formatStr.AsStringC());
Dan Sinclair1770c022016-03-14 14:14:16 -04001661}
dsinclair48d91dd2016-05-31 11:54:01 -07001662
1663// static
Dan Sinclair1770c022016-03-14 14:14:16 -04001664FX_BOOL CXFA_FM2JSContext::IsIsoDateFormat(const FX_CHAR* pData,
1665 int32_t iLength,
1666 int32_t& iStyle,
1667 int32_t& iYear,
1668 int32_t& iMonth,
1669 int32_t& iDay) {
1670 iYear = 0;
1671 iMonth = 1;
1672 iDay = 1;
dsinclair2b6d64e2016-06-06 11:39:42 -07001673
1674 if (iLength < 4)
1675 return FALSE;
1676
Dan Sinclair1770c022016-03-14 14:14:16 -04001677 FX_CHAR strYear[5];
1678 strYear[4] = '\0';
1679 for (int32_t i = 0; i < 4; ++i) {
dsinclair2b6d64e2016-06-06 11:39:42 -07001680 if (pData[i] > '9' || pData[i] < '0')
1681 return FALSE;
1682
1683 strYear[i] = pData[i];
Dan Sinclair1770c022016-03-14 14:14:16 -04001684 }
1685 iYear = FXSYS_atoi(strYear);
1686 iStyle = 0;
dsinclair2b6d64e2016-06-06 11:39:42 -07001687 if (iLength == 4)
1688 return TRUE;
1689
1690 iStyle = pData[4] == '-' ? 1 : 0;
1691
Dan Sinclair1770c022016-03-14 14:14:16 -04001692 FX_CHAR strTemp[3];
1693 strTemp[2] = '\0';
dsinclair2b6d64e2016-06-06 11:39:42 -07001694 int32_t iPosOff = iStyle == 0 ? 4 : 5;
1695 if ((pData[iPosOff] > '9' || pData[iPosOff] < '0') ||
1696 (pData[iPosOff + 1] > '9' || pData[iPosOff + 1] < '0'))
1697 return FALSE;
1698
1699 strTemp[0] = pData[iPosOff];
1700 strTemp[1] = pData[iPosOff + 1];
Dan Sinclair1770c022016-03-14 14:14:16 -04001701 iMonth = FXSYS_atoi(strTemp);
dsinclair2b6d64e2016-06-06 11:39:42 -07001702 if (iMonth > 12 || iMonth < 1)
1703 return FALSE;
1704
Dan Sinclair1770c022016-03-14 14:14:16 -04001705 if (iStyle == 0) {
1706 iPosOff += 2;
dsinclair2b6d64e2016-06-06 11:39:42 -07001707 if (iLength == 6)
1708 return TRUE;
Dan Sinclair1770c022016-03-14 14:14:16 -04001709 } else {
1710 iPosOff += 3;
dsinclair2b6d64e2016-06-06 11:39:42 -07001711 if (iLength == 7)
1712 return TRUE;
Dan Sinclair1770c022016-03-14 14:14:16 -04001713 }
dsinclair2b6d64e2016-06-06 11:39:42 -07001714 if ((pData[iPosOff] > '9' || pData[iPosOff] < '0') ||
1715 (pData[iPosOff + 1] > '9' || pData[iPosOff + 1] < '0'))
1716 return FALSE;
1717
1718 strTemp[0] = pData[iPosOff];
1719 strTemp[1] = pData[iPosOff + 1];
Dan Sinclair1770c022016-03-14 14:14:16 -04001720 iDay = FXSYS_atoi(strTemp);
dsinclair2b6d64e2016-06-06 11:39:42 -07001721 if (iPosOff + 2 < iLength)
1722 return FALSE;
1723
Dan Sinclair1770c022016-03-14 14:14:16 -04001724 if ((!(iYear % 4) && (iYear % 100)) || !(iYear % 400)) {
dsinclair2b6d64e2016-06-06 11:39:42 -07001725 if (iMonth == 2 && iDay > 29)
1726 return FALSE;
Dan Sinclair1770c022016-03-14 14:14:16 -04001727 } else {
dsinclair2b6d64e2016-06-06 11:39:42 -07001728 if (iMonth == 2 && iDay > 28)
1729 return FALSE;
1730 }
1731 if (iMonth != 2) {
1732 if (iMonth < 8) {
1733 if (iDay > (iMonth % 2 == 0 ? 30 : 31))
1734 return FALSE;
1735 } else if (iDay > (iMonth % 2 == 0 ? 31 : 30)) {
1736 return FALSE;
Dan Sinclair1770c022016-03-14 14:14:16 -04001737 }
1738 }
dsinclair2b6d64e2016-06-06 11:39:42 -07001739 return TRUE;
Dan Sinclair1770c022016-03-14 14:14:16 -04001740}
dsinclair48d91dd2016-05-31 11:54:01 -07001741
1742// static
Dan Sinclair1770c022016-03-14 14:14:16 -04001743FX_BOOL CXFA_FM2JSContext::IsIsoTimeFormat(const FX_CHAR* pData,
1744 int32_t iLength,
1745 int32_t& iHour,
1746 int32_t& iMinute,
1747 int32_t& iSecond,
1748 int32_t& iMilliSecond,
1749 int32_t& iZoneHour,
1750 int32_t& iZoneMinute) {
1751 iHour = 0;
1752 iMinute = 0;
1753 iSecond = 0;
1754 iMilliSecond = 0;
1755 iZoneHour = 0;
1756 iZoneMinute = 0;
dsinclair2b6d64e2016-06-06 11:39:42 -07001757 if (!pData)
Dan Sinclair1770c022016-03-14 14:14:16 -04001758 return FALSE;
dsinclair2b6d64e2016-06-06 11:39:42 -07001759
Dan Sinclair1770c022016-03-14 14:14:16 -04001760 FX_CHAR strTemp[3];
1761 strTemp[2] = '\0';
Dan Sinclair1770c022016-03-14 14:14:16 -04001762 int32_t iZone = 0;
dsinclair2b6d64e2016-06-06 11:39:42 -07001763 int32_t i = 0;
Dan Sinclair1770c022016-03-14 14:14:16 -04001764 while (i < iLength) {
dsinclair2b6d64e2016-06-06 11:39:42 -07001765 if ((pData[i] > '9' || pData[i] < '0') && pData[i] != ':') {
Dan Sinclair1770c022016-03-14 14:14:16 -04001766 iZone = i;
1767 break;
1768 }
1769 ++i;
1770 }
dsinclair2b6d64e2016-06-06 11:39:42 -07001771 if (i == iLength)
Dan Sinclair1770c022016-03-14 14:14:16 -04001772 iZone = iLength;
dsinclair2b6d64e2016-06-06 11:39:42 -07001773
Dan Sinclair1770c022016-03-14 14:14:16 -04001774 int32_t iPos = 0;
dsinclair2b6d64e2016-06-06 11:39:42 -07001775 int32_t iIndex = 0;
Dan Sinclair1770c022016-03-14 14:14:16 -04001776 while (iIndex < iZone) {
dsinclair2b6d64e2016-06-06 11:39:42 -07001777 if (iIndex >= iZone)
Dan Sinclair1770c022016-03-14 14:14:16 -04001778 break;
dsinclair2b6d64e2016-06-06 11:39:42 -07001779
1780 if (pData[iIndex] > '9' || pData[iIndex] < '0')
1781 return FALSE;
1782
1783 strTemp[0] = pData[iIndex];
1784 if (pData[iIndex + 1] > '9' || pData[iIndex + 1] < '0')
1785 return FALSE;
1786
1787 strTemp[1] = pData[iIndex + 1];
1788 if (FXSYS_atoi(strTemp) > 60)
1789 return FALSE;
1790
1791 if (pData[2] == ':') {
Dan Sinclair1770c022016-03-14 14:14:16 -04001792 if (iPos == 0) {
1793 iHour = FXSYS_atoi(strTemp);
1794 ++iPos;
1795 } else if (iPos == 1) {
1796 iMinute = FXSYS_atoi(strTemp);
1797 ++iPos;
1798 } else {
1799 iSecond = FXSYS_atoi(strTemp);
1800 }
1801 iIndex += 3;
1802 } else {
1803 if (iPos == 0) {
1804 iHour = FXSYS_atoi(strTemp);
1805 ++iPos;
1806 } else if (iPos == 1) {
1807 iMinute = FXSYS_atoi(strTemp);
1808 ++iPos;
1809 } else if (iPos == 2) {
1810 iSecond = FXSYS_atoi(strTemp);
1811 ++iPos;
1812 }
1813 iIndex += 2;
1814 }
1815 }
dsinclair2b6d64e2016-06-06 11:39:42 -07001816 if (pData[iIndex] == '.') {
Dan Sinclair1770c022016-03-14 14:14:16 -04001817 ++iIndex;
weilidb444d22016-06-02 15:48:15 -07001818 FX_CHAR strSec[4];
1819 strSec[3] = '\0';
dsinclair2b6d64e2016-06-06 11:39:42 -07001820 if (pData[iIndex] > '9' || pData[iIndex] < '0')
1821 return FALSE;
1822
1823 strSec[0] = pData[iIndex];
1824 if (pData[iIndex + 1] > '9' || pData[iIndex + 1] < '0')
1825 return FALSE;
1826
1827 strSec[1] = pData[iIndex + 1];
1828 if (pData[iIndex + 2] > '9' || pData[iIndex + 2] < '0')
1829 return FALSE;
1830
1831 strSec[2] = pData[iIndex + 2];
weilidb444d22016-06-02 15:48:15 -07001832 iMilliSecond = FXSYS_atoi(strSec);
Dan Sinclair1770c022016-03-14 14:14:16 -04001833 if (iMilliSecond > 100) {
1834 iMilliSecond = 0;
dsinclair2b6d64e2016-06-06 11:39:42 -07001835 return FALSE;
Dan Sinclair1770c022016-03-14 14:14:16 -04001836 }
1837 iIndex += 3;
1838 }
dsinclair2b6d64e2016-06-06 11:39:42 -07001839 if (pData[iIndex] == 'z' || pData[iIndex] == 'Z')
1840 return TRUE;
1841
Dan Sinclair1770c022016-03-14 14:14:16 -04001842 int32_t iSign = 1;
dsinclair2b6d64e2016-06-06 11:39:42 -07001843 if (pData[iIndex] == '+') {
Dan Sinclair1770c022016-03-14 14:14:16 -04001844 ++iIndex;
dsinclair2b6d64e2016-06-06 11:39:42 -07001845 } else if (pData[iIndex] == '-') {
Dan Sinclair1770c022016-03-14 14:14:16 -04001846 iSign = -1;
1847 ++iIndex;
1848 }
1849 iPos = 0;
1850 while (iIndex < iLength) {
dsinclair2b6d64e2016-06-06 11:39:42 -07001851 if (iIndex >= iLength)
1852 return FALSE;
1853 if (pData[iIndex] > '9' || pData[iIndex] < '0')
1854 return FALSE;
1855
1856 strTemp[0] = pData[iIndex];
1857 if (pData[iIndex + 1] > '9' || pData[iIndex + 1] < '0')
1858 return FALSE;
1859
1860 strTemp[1] = pData[iIndex + 1];
1861 if (FXSYS_atoi(strTemp) > 60)
1862 return FALSE;
1863
1864 if (pData[2] == ':') {
Dan Sinclair1770c022016-03-14 14:14:16 -04001865 if (iPos == 0) {
1866 iZoneHour = FXSYS_atoi(strTemp);
1867 } else if (iPos == 1) {
1868 iZoneMinute = FXSYS_atoi(strTemp);
1869 }
1870 iIndex += 3;
1871 } else {
1872 if (!iPos) {
1873 iZoneHour = FXSYS_atoi(strTemp);
1874 ++iPos;
1875 } else if (iPos == 1) {
1876 iZoneMinute = FXSYS_atoi(strTemp);
1877 ++iPos;
1878 }
1879 iIndex += 2;
1880 }
1881 }
dsinclair2b6d64e2016-06-06 11:39:42 -07001882 if (iIndex < iLength)
1883 return FALSE;
1884
Dan Sinclair1770c022016-03-14 14:14:16 -04001885 iZoneHour *= iSign;
dsinclair2b6d64e2016-06-06 11:39:42 -07001886 return TRUE;
Dan Sinclair1770c022016-03-14 14:14:16 -04001887}
dsinclair48d91dd2016-05-31 11:54:01 -07001888
1889// static
Dan Sinclair1770c022016-03-14 14:14:16 -04001890FX_BOOL CXFA_FM2JSContext::IsIsoDateTimeFormat(const FX_CHAR* pData,
1891 int32_t iLength,
1892 int32_t& iYear,
1893 int32_t& iMonth,
1894 int32_t& iDay,
1895 int32_t& iHour,
1896 int32_t& iMinute,
1897 int32_t& iSecond,
1898 int32_t& iMillionSecond,
1899 int32_t& iZoneHour,
1900 int32_t& iZoneMinute) {
1901 iYear = 0;
1902 iMonth = 0;
1903 iDay = 0;
1904 iHour = 0;
1905 iMinute = 0;
1906 iSecond = 0;
dsinclair2b6d64e2016-06-06 11:39:42 -07001907 if (!pData)
Dan Sinclair1770c022016-03-14 14:14:16 -04001908 return FALSE;
dsinclair2b6d64e2016-06-06 11:39:42 -07001909
Dan Sinclair1770c022016-03-14 14:14:16 -04001910 int32_t iIndex = 0;
dsinclair2b6d64e2016-06-06 11:39:42 -07001911 while (pData[iIndex] != 'T' && pData[iIndex] != 't') {
1912 if (iIndex >= iLength)
1913 return FALSE;
Dan Sinclair1770c022016-03-14 14:14:16 -04001914 ++iIndex;
1915 }
dsinclair2b6d64e2016-06-06 11:39:42 -07001916 if (iIndex != 8 && iIndex != 10)
1917 return FALSE;
1918
Dan Sinclair1770c022016-03-14 14:14:16 -04001919 int32_t iStyle = -1;
dsinclair2b6d64e2016-06-06 11:39:42 -07001920 if (!IsIsoDateFormat(pData, iIndex, iStyle, iYear, iMonth, iDay))
1921 return FALSE;
1922 if (pData[iIndex] != 'T' && pData[iIndex] != 't')
1923 return TRUE;
1924
Dan Sinclair1770c022016-03-14 14:14:16 -04001925 ++iIndex;
1926 if (((iLength - iIndex > 13) && (iLength - iIndex < 6)) &&
1927 (iLength - iIndex != 15)) {
dsinclair2b6d64e2016-06-06 11:39:42 -07001928 return TRUE;
Dan Sinclair1770c022016-03-14 14:14:16 -04001929 }
dsinclair2b6d64e2016-06-06 11:39:42 -07001930 if (!IsIsoTimeFormat(pData + iIndex, iLength - iIndex, iHour, iMinute,
1931 iSecond, iMillionSecond, iZoneHour, iZoneMinute)) {
1932 return FALSE;
Dan Sinclair1770c022016-03-14 14:14:16 -04001933 }
dsinclair2b6d64e2016-06-06 11:39:42 -07001934
1935 return TRUE;
Dan Sinclair1770c022016-03-14 14:14:16 -04001936}
dsinclair48d91dd2016-05-31 11:54:01 -07001937
1938// static
dsinclair12a6b0c2016-05-26 11:14:08 -07001939FX_BOOL CXFA_FM2JSContext::Local2IsoDate(CFXJSE_Value* pThis,
Dan Sinclair1770c022016-03-14 14:14:16 -04001940 const CFX_ByteStringC& szDate,
1941 const CFX_ByteStringC& szFormat,
1942 const CFX_ByteStringC& szLocale,
1943 CFX_ByteString& strIsoDate) {
dsinclair8f3074b2016-06-02 17:45:25 -07001944 CXFA_Document* pDoc = ToJSContext(pThis, nullptr)->GetDocument();
dsinclair2b6d64e2016-06-06 11:39:42 -07001945 if (!pDoc)
Dan Sinclair1770c022016-03-14 14:14:16 -04001946 return FALSE;
dsinclair2b6d64e2016-06-06 11:39:42 -07001947
1948 CXFA_LocaleMgr* pMgr = pDoc->GetLocalMgr();
dsinclair48d91dd2016-05-31 11:54:01 -07001949 IFX_Locale* pLocale = nullptr;
Dan Sinclair1770c022016-03-14 14:14:16 -04001950 if (szLocale.IsEmpty()) {
1951 CXFA_Node* pThisNode = ToNode(pDoc->GetScriptContext()->GetThisObject());
dsinclair43854a52016-04-27 12:26:00 -07001952 ASSERT(pThisNode);
dsinclair2b6d64e2016-06-06 11:39:42 -07001953
Dan Sinclair1770c022016-03-14 14:14:16 -04001954 CXFA_WidgetData widgetData(pThisNode);
1955 pLocale = widgetData.GetLocal();
1956 } else {
tsepezafe94302016-05-13 17:21:31 -07001957 pLocale = pMgr->GetLocaleByName(CFX_WideString::FromUTF8(szLocale));
Dan Sinclair1770c022016-03-14 14:14:16 -04001958 }
dsinclair2b6d64e2016-06-06 11:39:42 -07001959 if (!pLocale)
Dan Sinclair1770c022016-03-14 14:14:16 -04001960 return FALSE;
dsinclair2b6d64e2016-06-06 11:39:42 -07001961
Dan Sinclair1770c022016-03-14 14:14:16 -04001962 CFX_WideString wsFormat;
dsinclair2b6d64e2016-06-06 11:39:42 -07001963 if (szFormat.IsEmpty())
Dan Sinclair1770c022016-03-14 14:14:16 -04001964 pLocale->GetDatePattern(FX_LOCALEDATETIMESUBCATEGORY_Default, wsFormat);
dsinclair2b6d64e2016-06-06 11:39:42 -07001965 else
tsepez6fe7d212016-04-06 10:51:14 -07001966 wsFormat = CFX_WideString::FromUTF8(szFormat);
dsinclair2b6d64e2016-06-06 11:39:42 -07001967
tsepez6fe7d212016-04-06 10:51:14 -07001968 CXFA_LocaleValue widgetValue(XFA_VT_DATE, CFX_WideString::FromUTF8(szDate),
dsinclair2b6d64e2016-06-06 11:39:42 -07001969 wsFormat, pLocale, pMgr);
Dan Sinclair1770c022016-03-14 14:14:16 -04001970 CFX_Unitime dt = widgetValue.GetDate();
1971 strIsoDate.Format("%4d-%02d-%02d", dt.GetYear(), dt.GetMonth(), dt.GetDay());
1972 return TRUE;
1973}
dsinclair48d91dd2016-05-31 11:54:01 -07001974
1975// static
dsinclair12a6b0c2016-05-26 11:14:08 -07001976FX_BOOL CXFA_FM2JSContext::Local2IsoTime(CFXJSE_Value* pThis,
Dan Sinclair1770c022016-03-14 14:14:16 -04001977 const CFX_ByteStringC& szTime,
1978 const CFX_ByteStringC& szFormat,
1979 const CFX_ByteStringC& szLocale,
1980 CFX_ByteString& strIsoTime) {
dsinclair8f3074b2016-06-02 17:45:25 -07001981 CXFA_Document* pDoc = ToJSContext(pThis, nullptr)->GetDocument();
dsinclair2b6d64e2016-06-06 11:39:42 -07001982 if (!pDoc)
Dan Sinclair1770c022016-03-14 14:14:16 -04001983 return FALSE;
dsinclair2b6d64e2016-06-06 11:39:42 -07001984
1985 CXFA_LocaleMgr* pMgr = pDoc->GetLocalMgr();
dsinclair48d91dd2016-05-31 11:54:01 -07001986 IFX_Locale* pLocale = nullptr;
Dan Sinclair1770c022016-03-14 14:14:16 -04001987 if (szLocale.IsEmpty()) {
1988 CXFA_Node* pThisNode = ToNode(pDoc->GetScriptContext()->GetThisObject());
dsinclair43854a52016-04-27 12:26:00 -07001989 ASSERT(pThisNode);
dsinclair2b6d64e2016-06-06 11:39:42 -07001990
Dan Sinclair1770c022016-03-14 14:14:16 -04001991 CXFA_WidgetData widgetData(pThisNode);
1992 pLocale = widgetData.GetLocal();
1993 } else {
tsepezafe94302016-05-13 17:21:31 -07001994 pLocale = pMgr->GetLocaleByName(CFX_WideString::FromUTF8(szLocale));
Dan Sinclair1770c022016-03-14 14:14:16 -04001995 }
dsinclair2b6d64e2016-06-06 11:39:42 -07001996 if (!pLocale)
Dan Sinclair1770c022016-03-14 14:14:16 -04001997 return FALSE;
dsinclair2b6d64e2016-06-06 11:39:42 -07001998
Dan Sinclair1770c022016-03-14 14:14:16 -04001999 CFX_WideString wsFormat;
dsinclair2b6d64e2016-06-06 11:39:42 -07002000 if (szFormat.IsEmpty())
Dan Sinclair1770c022016-03-14 14:14:16 -04002001 pLocale->GetTimePattern(FX_LOCALEDATETIMESUBCATEGORY_Default, wsFormat);
dsinclair2b6d64e2016-06-06 11:39:42 -07002002 else
tsepez6fe7d212016-04-06 10:51:14 -07002003 wsFormat = CFX_WideString::FromUTF8(szFormat);
dsinclair2b6d64e2016-06-06 11:39:42 -07002004
dsinclaircf7f3222016-06-08 20:34:02 -07002005 wsFormat = L"time{" + wsFormat + L"}";
tsepez6fe7d212016-04-06 10:51:14 -07002006 CXFA_LocaleValue widgetValue(XFA_VT_TIME, CFX_WideString::FromUTF8(szTime),
dsinclair2b6d64e2016-06-06 11:39:42 -07002007 wsFormat, pLocale, pMgr);
Dan Sinclair1770c022016-03-14 14:14:16 -04002008 CFX_Unitime utime = widgetValue.GetTime();
2009 strIsoTime.Format("%02d:%02d:%02d.%03d", utime.GetHour(), utime.GetMinute(),
2010 utime.GetSecond(), utime.GetMillisecond());
2011 return TRUE;
2012}
dsinclair48d91dd2016-05-31 11:54:01 -07002013
2014// static
dsinclair12a6b0c2016-05-26 11:14:08 -07002015FX_BOOL CXFA_FM2JSContext::IsoDate2Local(CFXJSE_Value* pThis,
Dan Sinclair1770c022016-03-14 14:14:16 -04002016 const CFX_ByteStringC& szDate,
2017 const CFX_ByteStringC& szFormat,
2018 const CFX_ByteStringC& szLocale,
2019 CFX_ByteString& strLocalDate) {
dsinclair8f3074b2016-06-02 17:45:25 -07002020 CXFA_Document* pDoc = ToJSContext(pThis, nullptr)->GetDocument();
dsinclair2b6d64e2016-06-06 11:39:42 -07002021 if (!pDoc)
Dan Sinclair1770c022016-03-14 14:14:16 -04002022 return FALSE;
dsinclair2b6d64e2016-06-06 11:39:42 -07002023
2024 CXFA_LocaleMgr* pMgr = pDoc->GetLocalMgr();
dsinclair48d91dd2016-05-31 11:54:01 -07002025 IFX_Locale* pLocale = nullptr;
Dan Sinclair1770c022016-03-14 14:14:16 -04002026 if (szLocale.IsEmpty()) {
2027 CXFA_Node* pThisNode = ToNode(pDoc->GetScriptContext()->GetThisObject());
dsinclair43854a52016-04-27 12:26:00 -07002028 ASSERT(pThisNode);
Dan Sinclair1770c022016-03-14 14:14:16 -04002029 CXFA_WidgetData widgetData(pThisNode);
2030 pLocale = widgetData.GetLocal();
2031 } else {
tsepezafe94302016-05-13 17:21:31 -07002032 pLocale = pMgr->GetLocaleByName(CFX_WideString::FromUTF8(szLocale));
Dan Sinclair1770c022016-03-14 14:14:16 -04002033 }
dsinclair2b6d64e2016-06-06 11:39:42 -07002034 if (!pLocale)
Dan Sinclair1770c022016-03-14 14:14:16 -04002035 return FALSE;
dsinclair2b6d64e2016-06-06 11:39:42 -07002036
Dan Sinclair1770c022016-03-14 14:14:16 -04002037 CFX_WideString wsFormat;
dsinclair2b6d64e2016-06-06 11:39:42 -07002038 if (szFormat.IsEmpty())
Dan Sinclair1770c022016-03-14 14:14:16 -04002039 pLocale->GetDatePattern(FX_LOCALEDATETIMESUBCATEGORY_Default, wsFormat);
dsinclair2b6d64e2016-06-06 11:39:42 -07002040 else
tsepez6fe7d212016-04-06 10:51:14 -07002041 wsFormat = CFX_WideString::FromUTF8(szFormat);
dsinclair2b6d64e2016-06-06 11:39:42 -07002042
tsepez6fe7d212016-04-06 10:51:14 -07002043 CXFA_LocaleValue widgetValue(XFA_VT_DATE, CFX_WideString::FromUTF8(szDate),
dsinclair2b6d64e2016-06-06 11:39:42 -07002044 pMgr);
Dan Sinclair1770c022016-03-14 14:14:16 -04002045 CFX_WideString wsRet;
2046 widgetValue.FormatPatterns(wsRet, wsFormat, pLocale,
2047 XFA_VALUEPICTURE_Display);
tsepezbd9748d2016-04-13 21:40:19 -07002048 strLocalDate = FX_UTF8Encode(wsRet.c_str(), wsRet.GetLength());
Dan Sinclair1770c022016-03-14 14:14:16 -04002049 return TRUE;
2050}
dsinclair48d91dd2016-05-31 11:54:01 -07002051
2052// static
dsinclair12a6b0c2016-05-26 11:14:08 -07002053FX_BOOL CXFA_FM2JSContext::IsoTime2Local(CFXJSE_Value* pThis,
Dan Sinclair1770c022016-03-14 14:14:16 -04002054 const CFX_ByteStringC& szTime,
2055 const CFX_ByteStringC& szFormat,
2056 const CFX_ByteStringC& szLocale,
2057 CFX_ByteString& strLocalTime) {
dsinclair8f3074b2016-06-02 17:45:25 -07002058 CXFA_Document* pDoc = ToJSContext(pThis, nullptr)->GetDocument();
dsinclair2b6d64e2016-06-06 11:39:42 -07002059 if (!pDoc)
Dan Sinclair1770c022016-03-14 14:14:16 -04002060 return FALSE;
dsinclair2b6d64e2016-06-06 11:39:42 -07002061
2062 CXFA_LocaleMgr* pMgr = pDoc->GetLocalMgr();
dsinclair48d91dd2016-05-31 11:54:01 -07002063 IFX_Locale* pLocale = nullptr;
Dan Sinclair1770c022016-03-14 14:14:16 -04002064 if (szLocale.IsEmpty()) {
2065 CXFA_Node* pThisNode = ToNode(pDoc->GetScriptContext()->GetThisObject());
dsinclair43854a52016-04-27 12:26:00 -07002066 ASSERT(pThisNode);
Dan Sinclair1770c022016-03-14 14:14:16 -04002067 CXFA_WidgetData widgetData(pThisNode);
2068 pLocale = widgetData.GetLocal();
2069 } else {
tsepezafe94302016-05-13 17:21:31 -07002070 pLocale = pMgr->GetLocaleByName(CFX_WideString::FromUTF8(szLocale));
Dan Sinclair1770c022016-03-14 14:14:16 -04002071 }
dsinclair2b6d64e2016-06-06 11:39:42 -07002072 if (!pLocale)
Dan Sinclair1770c022016-03-14 14:14:16 -04002073 return FALSE;
dsinclair2b6d64e2016-06-06 11:39:42 -07002074
Dan Sinclair1770c022016-03-14 14:14:16 -04002075 CFX_WideString wsFormat;
dsinclair2b6d64e2016-06-06 11:39:42 -07002076 if (szFormat.IsEmpty())
Dan Sinclair1770c022016-03-14 14:14:16 -04002077 pLocale->GetTimePattern(FX_LOCALEDATETIMESUBCATEGORY_Default, wsFormat);
dsinclair2b6d64e2016-06-06 11:39:42 -07002078 else
tsepez6fe7d212016-04-06 10:51:14 -07002079 wsFormat = CFX_WideString::FromUTF8(szFormat);
dsinclair2b6d64e2016-06-06 11:39:42 -07002080
dsinclaircf7f3222016-06-08 20:34:02 -07002081 wsFormat = L"time{" + wsFormat + L"}";
tsepez6fe7d212016-04-06 10:51:14 -07002082 CXFA_LocaleValue widgetValue(XFA_VT_TIME, CFX_WideString::FromUTF8(szTime),
dsinclair2b6d64e2016-06-06 11:39:42 -07002083 pMgr);
Dan Sinclair1770c022016-03-14 14:14:16 -04002084 CFX_WideString wsRet;
2085 widgetValue.FormatPatterns(wsRet, wsFormat, pLocale,
2086 XFA_VALUEPICTURE_Display);
tsepezbd9748d2016-04-13 21:40:19 -07002087 strLocalTime = FX_UTF8Encode(wsRet.c_str(), wsRet.GetLength());
Dan Sinclair1770c022016-03-14 14:14:16 -04002088 return TRUE;
2089}
dsinclair48d91dd2016-05-31 11:54:01 -07002090
2091// static
dsinclair12a6b0c2016-05-26 11:14:08 -07002092FX_BOOL CXFA_FM2JSContext::GetGMTTime(CFXJSE_Value* pThis,
Dan Sinclair1770c022016-03-14 14:14:16 -04002093 const CFX_ByteStringC& szTime,
2094 const CFX_ByteStringC& szFormat,
2095 const CFX_ByteStringC& szLocale,
2096 CFX_ByteString& strGMTTime) {
dsinclair8f3074b2016-06-02 17:45:25 -07002097 CXFA_Document* pDoc = ToJSContext(pThis, nullptr)->GetDocument();
dsinclair2b6d64e2016-06-06 11:39:42 -07002098 if (!pDoc)
Dan Sinclair1770c022016-03-14 14:14:16 -04002099 return FALSE;
dsinclair2b6d64e2016-06-06 11:39:42 -07002100
2101 CXFA_LocaleMgr* pMgr = pDoc->GetLocalMgr();
dsinclair48d91dd2016-05-31 11:54:01 -07002102 IFX_Locale* pLocale = nullptr;
Dan Sinclair1770c022016-03-14 14:14:16 -04002103 if (szLocale.IsEmpty()) {
2104 CXFA_Node* pThisNode = ToNode(pDoc->GetScriptContext()->GetThisObject());
dsinclair43854a52016-04-27 12:26:00 -07002105 ASSERT(pThisNode);
Dan Sinclair1770c022016-03-14 14:14:16 -04002106 CXFA_WidgetData widgetData(pThisNode);
2107 pLocale = widgetData.GetLocal();
2108 } else {
tsepezafe94302016-05-13 17:21:31 -07002109 pLocale = pMgr->GetLocaleByName(CFX_WideString::FromUTF8(szLocale));
Dan Sinclair1770c022016-03-14 14:14:16 -04002110 }
dsinclair2b6d64e2016-06-06 11:39:42 -07002111 if (!pLocale)
Dan Sinclair1770c022016-03-14 14:14:16 -04002112 return FALSE;
dsinclair2b6d64e2016-06-06 11:39:42 -07002113
Dan Sinclair1770c022016-03-14 14:14:16 -04002114 CFX_WideString wsFormat;
dsinclair2b6d64e2016-06-06 11:39:42 -07002115 if (szFormat.IsEmpty())
Dan Sinclair1770c022016-03-14 14:14:16 -04002116 pLocale->GetTimePattern(FX_LOCALEDATETIMESUBCATEGORY_Default, wsFormat);
dsinclair2b6d64e2016-06-06 11:39:42 -07002117 else
tsepez6fe7d212016-04-06 10:51:14 -07002118 wsFormat = CFX_WideString::FromUTF8(szFormat);
dsinclair2b6d64e2016-06-06 11:39:42 -07002119
dsinclaircf7f3222016-06-08 20:34:02 -07002120 wsFormat = L"time{" + wsFormat + L"}";
tsepez6fe7d212016-04-06 10:51:14 -07002121 CXFA_LocaleValue widgetValue(XFA_VT_TIME, CFX_WideString::FromUTF8(szTime),
dsinclair2b6d64e2016-06-06 11:39:42 -07002122 pMgr);
Dan Sinclair1770c022016-03-14 14:14:16 -04002123 CFX_WideString wsRet;
2124 widgetValue.FormatPatterns(wsRet, wsFormat, pLocale,
2125 XFA_VALUEPICTURE_Display);
tsepezbd9748d2016-04-13 21:40:19 -07002126 strGMTTime = FX_UTF8Encode(wsRet.c_str(), wsRet.GetLength());
Dan Sinclair1770c022016-03-14 14:14:16 -04002127 return TRUE;
2128}
dsinclair48d91dd2016-05-31 11:54:01 -07002129
2130// static
Dan Sinclair1770c022016-03-14 14:14:16 -04002131int32_t CXFA_FM2JSContext::DateString2Num(const CFX_ByteStringC& szDateString) {
Dan Sinclair1770c022016-03-14 14:14:16 -04002132 int32_t iLength = szDateString.GetLength();
Dan Sinclair1770c022016-03-14 14:14:16 -04002133 int32_t iYear = 0;
2134 int32_t iMonth = 0;
2135 int32_t iDay = 0;
Dan Sinclair1770c022016-03-14 14:14:16 -04002136 if (iLength <= 10) {
dsinclair2b6d64e2016-06-06 11:39:42 -07002137 int32_t iStyle = -1;
2138 if (!IsIsoDateFormat(szDateString.c_str(), iLength, iStyle, iYear, iMonth,
2139 iDay)) {
2140 return 0;
2141 }
Dan Sinclair1770c022016-03-14 14:14:16 -04002142 } else {
dsinclair2b6d64e2016-06-06 11:39:42 -07002143 int32_t iHour = 0;
2144 int32_t iMinute = 0;
2145 int32_t iSecond = 0;
2146 int32_t iMilliSecond = 0;
2147 int32_t iZoneHour = 0;
2148 int32_t iZoneMinute = 0;
2149 if (!IsIsoDateTimeFormat(szDateString.c_str(), iLength, iYear, iMonth, iDay,
2150 iHour, iMinute, iSecond, iMilliSecond, iZoneHour,
2151 iZoneMinute)) {
2152 return 0;
2153 }
Dan Sinclair1770c022016-03-14 14:14:16 -04002154 }
dsinclair2b6d64e2016-06-06 11:39:42 -07002155
Dan Sinclair1770c022016-03-14 14:14:16 -04002156 FX_FLOAT dDays = 0;
2157 int32_t i = 1;
dsinclair2b6d64e2016-06-06 11:39:42 -07002158 if (iYear < 1900)
2159 return 0;
2160
2161 while (iYear - i >= 1900) {
2162 dDays +=
2163 ((!((iYear - i) % 4) && ((iYear - i) % 100)) || !((iYear - i) % 400))
2164 ? 366
2165 : 365;
2166 ++i;
Dan Sinclair1770c022016-03-14 14:14:16 -04002167 }
dsinclair2b6d64e2016-06-06 11:39:42 -07002168 i = 1;
2169 while (i < iMonth) {
2170 if (i == 2)
2171 dDays += ((!(iYear % 4) && (iYear % 100)) || !(iYear % 400)) ? 29 : 28;
2172 else if (i <= 7)
2173 dDays += (i % 2 == 0) ? 30 : 31;
2174 else
2175 dDays += (i % 2 == 0) ? 31 : 30;
2176
2177 ++i;
2178 }
2179 i = 0;
2180 while (iDay - i > 0) {
2181 dDays += 1;
2182 ++i;
Dan Sinclair1770c022016-03-14 14:14:16 -04002183 }
2184 return (int32_t)dDays;
2185}
dsinclair0c268e92016-05-17 14:04:14 -07002186
dsinclair48d91dd2016-05-31 11:54:01 -07002187// static
dsinclair12a6b0c2016-05-26 11:14:08 -07002188void CXFA_FM2JSContext::GetLocalDateFormat(CFXJSE_Value* pThis,
Dan Sinclair1770c022016-03-14 14:14:16 -04002189 int32_t iStyle,
2190 const CFX_ByteStringC& szLocalStr,
2191 CFX_ByteString& strFormat,
2192 FX_BOOL bStandard) {
2193 FX_LOCALEDATETIMESUBCATEGORY strStyle;
2194 switch (iStyle) {
Dan Sinclair1770c022016-03-14 14:14:16 -04002195 case 1:
2196 strStyle = FX_LOCALEDATETIMESUBCATEGORY_Short;
2197 break;
Dan Sinclair1770c022016-03-14 14:14:16 -04002198 case 3:
2199 strStyle = FX_LOCALEDATETIMESUBCATEGORY_Long;
2200 break;
2201 case 4:
2202 strStyle = FX_LOCALEDATETIMESUBCATEGORY_Full;
2203 break;
dsinclair2b6d64e2016-06-06 11:39:42 -07002204 case 0:
2205 case 2:
Dan Sinclair1770c022016-03-14 14:14:16 -04002206 default:
2207 strStyle = FX_LOCALEDATETIMESUBCATEGORY_Medium;
2208 break;
2209 }
dsinclair8f3074b2016-06-02 17:45:25 -07002210 CXFA_Document* pDoc = ToJSContext(pThis, nullptr)->GetDocument();
dsinclair2b6d64e2016-06-06 11:39:42 -07002211 if (!pDoc)
Dan Sinclair1770c022016-03-14 14:14:16 -04002212 return;
dsinclair2b6d64e2016-06-06 11:39:42 -07002213
dsinclair48d91dd2016-05-31 11:54:01 -07002214 IFX_Locale* pLocale = nullptr;
Dan Sinclair1770c022016-03-14 14:14:16 -04002215 if (szLocalStr.IsEmpty()) {
2216 CXFA_Node* pThisNode = ToNode(pDoc->GetScriptContext()->GetThisObject());
dsinclair43854a52016-04-27 12:26:00 -07002217 ASSERT(pThisNode);
dsinclair2b6d64e2016-06-06 11:39:42 -07002218
Dan Sinclair1770c022016-03-14 14:14:16 -04002219 CXFA_WidgetData widgetData(pThisNode);
2220 pLocale = widgetData.GetLocal();
2221 } else {
dsinclair2b6d64e2016-06-06 11:39:42 -07002222 pLocale = pDoc->GetLocalMgr()->GetLocaleByName(
2223 CFX_WideString::FromUTF8(szLocalStr));
Dan Sinclair1770c022016-03-14 14:14:16 -04002224 }
dsinclair2b6d64e2016-06-06 11:39:42 -07002225 if (!pLocale)
Dan Sinclair1770c022016-03-14 14:14:16 -04002226 return;
dsinclair2b6d64e2016-06-06 11:39:42 -07002227
Dan Sinclair1770c022016-03-14 14:14:16 -04002228 CFX_WideString strRet;
2229 pLocale->GetDatePattern(strStyle, strRet);
2230 if (!bStandard) {
2231 CFX_WideString wsSymbols;
2232 pLocale->GetDateTimeSymbols(wsSymbols);
dsinclair0c268e92016-05-17 14:04:14 -07002233 AlternateDateTimeSymbols(strRet, wsSymbols, g_sAltTable_Date);
Dan Sinclair1770c022016-03-14 14:14:16 -04002234 }
tsepezbd9748d2016-04-13 21:40:19 -07002235 strFormat = FX_UTF8Encode(strRet.c_str(), strRet.GetLength());
Dan Sinclair1770c022016-03-14 14:14:16 -04002236}
dsinclair48d91dd2016-05-31 11:54:01 -07002237
2238// static
dsinclair12a6b0c2016-05-26 11:14:08 -07002239void CXFA_FM2JSContext::GetLocalTimeFormat(CFXJSE_Value* pThis,
Dan Sinclair1770c022016-03-14 14:14:16 -04002240 int32_t iStyle,
2241 const CFX_ByteStringC& szLocalStr,
2242 CFX_ByteString& strFormat,
2243 FX_BOOL bStandard) {
2244 FX_LOCALEDATETIMESUBCATEGORY strStyle;
2245 switch (iStyle) {
Dan Sinclair1770c022016-03-14 14:14:16 -04002246 case 1:
2247 strStyle = FX_LOCALEDATETIMESUBCATEGORY_Short;
2248 break;
Dan Sinclair1770c022016-03-14 14:14:16 -04002249 case 3:
2250 strStyle = FX_LOCALEDATETIMESUBCATEGORY_Long;
2251 break;
2252 case 4:
2253 strStyle = FX_LOCALEDATETIMESUBCATEGORY_Full;
2254 break;
dsinclair2b6d64e2016-06-06 11:39:42 -07002255 case 0:
2256 case 2:
Dan Sinclair1770c022016-03-14 14:14:16 -04002257 default:
2258 strStyle = FX_LOCALEDATETIMESUBCATEGORY_Medium;
2259 break;
2260 }
dsinclair8f3074b2016-06-02 17:45:25 -07002261 CXFA_Document* pDoc = ToJSContext(pThis, nullptr)->GetDocument();
dsinclair2b6d64e2016-06-06 11:39:42 -07002262 if (!pDoc)
Dan Sinclair1770c022016-03-14 14:14:16 -04002263 return;
dsinclair2b6d64e2016-06-06 11:39:42 -07002264
dsinclair48d91dd2016-05-31 11:54:01 -07002265 IFX_Locale* pLocale = nullptr;
Dan Sinclair1770c022016-03-14 14:14:16 -04002266 if (szLocalStr.IsEmpty()) {
2267 CXFA_Node* pThisNode = ToNode(pDoc->GetScriptContext()->GetThisObject());
dsinclair43854a52016-04-27 12:26:00 -07002268 ASSERT(pThisNode);
dsinclair2b6d64e2016-06-06 11:39:42 -07002269
Dan Sinclair1770c022016-03-14 14:14:16 -04002270 CXFA_WidgetData widgetData(pThisNode);
2271 pLocale = widgetData.GetLocal();
2272 } else {
dsinclair2b6d64e2016-06-06 11:39:42 -07002273 pLocale = pDoc->GetLocalMgr()->GetLocaleByName(
2274 CFX_WideString::FromUTF8(szLocalStr));
Dan Sinclair1770c022016-03-14 14:14:16 -04002275 }
dsinclair2b6d64e2016-06-06 11:39:42 -07002276 if (!pLocale)
Dan Sinclair1770c022016-03-14 14:14:16 -04002277 return;
dsinclair2b6d64e2016-06-06 11:39:42 -07002278
Dan Sinclair1770c022016-03-14 14:14:16 -04002279 CFX_WideString strRet;
2280 pLocale->GetTimePattern(strStyle, strRet);
2281 if (!bStandard) {
2282 CFX_WideString wsSymbols;
2283 pLocale->GetDateTimeSymbols(wsSymbols);
dsinclair0c268e92016-05-17 14:04:14 -07002284 AlternateDateTimeSymbols(strRet, wsSymbols, g_sAltTable_Time);
Dan Sinclair1770c022016-03-14 14:14:16 -04002285 }
tsepezbd9748d2016-04-13 21:40:19 -07002286 strFormat = FX_UTF8Encode(strRet.c_str(), strRet.GetLength());
Dan Sinclair1770c022016-03-14 14:14:16 -04002287}
dsinclair48d91dd2016-05-31 11:54:01 -07002288
2289// static
dsinclair12a6b0c2016-05-26 11:14:08 -07002290void CXFA_FM2JSContext::GetStandardDateFormat(CFXJSE_Value* pThis,
Dan Sinclair1770c022016-03-14 14:14:16 -04002291 int32_t iStyle,
2292 const CFX_ByteStringC& szLocalStr,
2293 CFX_ByteString& strFormat) {
dsinclair12a6b0c2016-05-26 11:14:08 -07002294 GetLocalDateFormat(pThis, iStyle, szLocalStr, strFormat, TRUE);
Dan Sinclair1770c022016-03-14 14:14:16 -04002295}
dsinclair48d91dd2016-05-31 11:54:01 -07002296
2297// static
dsinclair12a6b0c2016-05-26 11:14:08 -07002298void CXFA_FM2JSContext::GetStandardTimeFormat(CFXJSE_Value* pThis,
Dan Sinclair1770c022016-03-14 14:14:16 -04002299 int32_t iStyle,
2300 const CFX_ByteStringC& szLocalStr,
2301 CFX_ByteString& strFormat) {
dsinclair12a6b0c2016-05-26 11:14:08 -07002302 GetLocalTimeFormat(pThis, iStyle, szLocalStr, strFormat, TRUE);
Dan Sinclair1770c022016-03-14 14:14:16 -04002303}
dsinclair48d91dd2016-05-31 11:54:01 -07002304
2305// static
dsinclair12a6b0c2016-05-26 11:14:08 -07002306void CXFA_FM2JSContext::Num2AllTime(CFXJSE_Value* pThis,
Dan Sinclair1770c022016-03-14 14:14:16 -04002307 int32_t iTime,
2308 const CFX_ByteStringC& szFormat,
2309 const CFX_ByteStringC& szLocale,
2310 FX_BOOL bGM,
2311 CFX_ByteString& strTime) {
2312 int32_t iHour = 0;
2313 int32_t iMin = 0;
2314 int32_t iSec = 0;
Dan Sinclair1770c022016-03-14 14:14:16 -04002315 iHour = static_cast<int>(iTime) / 3600000;
2316 iMin = (static_cast<int>(iTime) - iHour * 3600000) / 60000;
2317 iSec = (static_cast<int>(iTime) - iHour * 3600000 - iMin * 60000) / 1000;
dsinclair2b6d64e2016-06-06 11:39:42 -07002318
Dan Sinclair1770c022016-03-14 14:14:16 -04002319 if (!bGM) {
dsinclair2b6d64e2016-06-06 11:39:42 -07002320 int32_t iZoneHour = 0;
2321 int32_t iZoneMin = 0;
2322 int32_t iZoneSec = 0;
Dan Sinclair1770c022016-03-14 14:14:16 -04002323 GetLocalTimeZone(iZoneHour, iZoneMin, iZoneSec);
2324 iHour += iZoneHour;
2325 iMin += iZoneMin;
2326 iSec += iZoneSec;
2327 }
dsinclair2b6d64e2016-06-06 11:39:42 -07002328
2329 FX_BOOL iRet = FALSE;
Dan Sinclair1770c022016-03-14 14:14:16 -04002330 CFX_ByteString strIsoTime;
2331 strIsoTime.Format("%02d:%02d:%02d", iHour, iMin, iSec);
2332 if (bGM) {
tsepez4c3debb2016-04-08 12:20:38 -07002333 iRet =
dsinclair12a6b0c2016-05-26 11:14:08 -07002334 GetGMTTime(pThis, strIsoTime.AsStringC(), szFormat, szLocale, strTime);
Dan Sinclair1770c022016-03-14 14:14:16 -04002335 } else {
dsinclair12a6b0c2016-05-26 11:14:08 -07002336 iRet = IsoTime2Local(pThis, strIsoTime.AsStringC(), szFormat, szLocale,
tsepez28f97ff2016-04-04 16:41:35 -07002337 strTime);
Dan Sinclair1770c022016-03-14 14:14:16 -04002338 }
dsinclair2b6d64e2016-06-06 11:39:42 -07002339 if (!iRet)
Dan Sinclair1770c022016-03-14 14:14:16 -04002340 strTime = "";
Dan Sinclair1770c022016-03-14 14:14:16 -04002341}
2342
dsinclair48d91dd2016-05-31 11:54:01 -07002343// static
Dan Sinclair1770c022016-03-14 14:14:16 -04002344void CXFA_FM2JSContext::GetLocalTimeZone(int32_t& iHour,
2345 int32_t& iMin,
2346 int32_t& iSec) {
2347 time_t now;
2348 time(&now);
dsinclair2b6d64e2016-06-06 11:39:42 -07002349
Dan Sinclair1770c022016-03-14 14:14:16 -04002350 struct tm* pGmt = gmtime(&now);
Dan Sinclair1770c022016-03-14 14:14:16 -04002351 struct tm* pLocal = localtime(&now);
dsinclair2b6d64e2016-06-06 11:39:42 -07002352 iHour = pLocal->tm_hour - pGmt->tm_hour;
2353 iMin = pLocal->tm_min - pGmt->tm_min;
2354 iSec = pLocal->tm_sec - pGmt->tm_sec;
Dan Sinclair1770c022016-03-14 14:14:16 -04002355}
dsinclair48d91dd2016-05-31 11:54:01 -07002356
2357// static
dsinclair12a6b0c2016-05-26 11:14:08 -07002358void CXFA_FM2JSContext::Apr(CFXJSE_Value* pThis,
Dan Sinclair1770c022016-03-14 14:14:16 -04002359 const CFX_ByteStringC& szFuncName,
2360 CFXJSE_Arguments& args) {
dsinclair8f3074b2016-06-02 17:45:25 -07002361 CXFA_FM2JSContext* pContext = ToJSContext(pThis, nullptr);
dsinclair96a05f42016-06-07 06:48:02 -07002362 if (args.GetLength() != 3) {
dsinclair2235b7b2016-06-02 07:42:25 -07002363 pContext->ThrowException(XFA_IDS_INCORRECT_NUMBER_OF_METHOD, L"Apr");
dsinclair96a05f42016-06-07 06:48:02 -07002364 return;
Dan Sinclair1770c022016-03-14 14:14:16 -04002365 }
dsinclair96a05f42016-06-07 06:48:02 -07002366
2367 std::unique_ptr<CFXJSE_Value> argOne = GetSimpleValue(pThis, args, 0);
2368 std::unique_ptr<CFXJSE_Value> argTwo = GetSimpleValue(pThis, args, 1);
2369 std::unique_ptr<CFXJSE_Value> argThree = GetSimpleValue(pThis, args, 2);
2370 if (ValueIsNull(pThis, argOne.get()) || ValueIsNull(pThis, argTwo.get()) ||
2371 ValueIsNull(pThis, argThree.get())) {
dsinclairf27aeec2016-06-07 19:36:18 -07002372 args.GetReturnValue()->SetNull();
dsinclair96a05f42016-06-07 06:48:02 -07002373 return;
2374 }
2375
2376 FX_DOUBLE nPrincipal = ValueToDouble(pThis, argOne.get());
2377 FX_DOUBLE nPayment = ValueToDouble(pThis, argTwo.get());
2378 FX_DOUBLE nPeriods = ValueToDouble(pThis, argThree.get());
2379 if (nPrincipal <= 0 || nPayment <= 0 || nPeriods <= 0) {
2380 pContext->ThrowException(XFA_IDS_ARGUMENT_MISMATCH);
2381 return;
2382 }
2383
2384 FX_DOUBLE r =
2385 2 * (nPeriods * nPayment - nPrincipal) / (nPeriods * nPrincipal);
2386 FX_DOUBLE nTemp = 1;
2387 for (int32_t i = 0; i < nPeriods; ++i)
2388 nTemp *= (1 + r);
2389
2390 FX_DOUBLE nRet = r * nTemp / (nTemp - 1) - nPayment / nPrincipal;
2391 while (fabs(nRet) > kFinancialPrecision) {
2392 FX_DOUBLE nDerivative =
2393 ((nTemp + r * nPeriods * (nTemp / (1 + r))) * (nTemp - 1) -
2394 (r * nTemp * nPeriods * (nTemp / (1 + r)))) /
2395 ((nTemp - 1) * (nTemp - 1));
2396 if (nDerivative == 0) {
dsinclairf27aeec2016-06-07 19:36:18 -07002397 args.GetReturnValue()->SetNull();
dsinclair96a05f42016-06-07 06:48:02 -07002398 return;
2399 }
2400
2401 r = r - nRet / nDerivative;
2402 nTemp = 1;
2403 for (int32_t i = 0; i < nPeriods; ++i) {
2404 nTemp *= (1 + r);
2405 }
2406 nRet = r * nTemp / (nTemp - 1) - nPayment / nPrincipal;
2407 }
dsinclairf27aeec2016-06-07 19:36:18 -07002408 args.GetReturnValue()->SetDouble(r * 12);
Dan Sinclair1770c022016-03-14 14:14:16 -04002409}
dsinclair48d91dd2016-05-31 11:54:01 -07002410
2411// static
dsinclair12a6b0c2016-05-26 11:14:08 -07002412void CXFA_FM2JSContext::CTerm(CFXJSE_Value* pThis,
Dan Sinclair1770c022016-03-14 14:14:16 -04002413 const CFX_ByteStringC& szFuncName,
2414 CFXJSE_Arguments& args) {
dsinclair8f3074b2016-06-02 17:45:25 -07002415 CXFA_FM2JSContext* pContext = ToJSContext(pThis, nullptr);
dsinclair96a05f42016-06-07 06:48:02 -07002416 if (args.GetLength() != 3) {
dsinclair2235b7b2016-06-02 07:42:25 -07002417 pContext->ThrowException(XFA_IDS_INCORRECT_NUMBER_OF_METHOD, L"CTerm");
dsinclair96a05f42016-06-07 06:48:02 -07002418 return;
Dan Sinclair1770c022016-03-14 14:14:16 -04002419 }
dsinclair96a05f42016-06-07 06:48:02 -07002420
2421 std::unique_ptr<CFXJSE_Value> argOne = GetSimpleValue(pThis, args, 0);
2422 std::unique_ptr<CFXJSE_Value> argTwo = GetSimpleValue(pThis, args, 1);
2423 std::unique_ptr<CFXJSE_Value> argThree = GetSimpleValue(pThis, args, 2);
2424 if (ValueIsNull(pThis, argOne.get()) || ValueIsNull(pThis, argTwo.get()) ||
2425 ValueIsNull(pThis, argThree.get())) {
dsinclairf27aeec2016-06-07 19:36:18 -07002426 args.GetReturnValue()->SetNull();
dsinclair96a05f42016-06-07 06:48:02 -07002427 return;
2428 }
2429
2430 FX_FLOAT nRate = ValueToFloat(pThis, argOne.get());
2431 FX_FLOAT nFutureValue = ValueToFloat(pThis, argTwo.get());
2432 FX_FLOAT nInitAmount = ValueToFloat(pThis, argThree.get());
2433 if ((nRate <= 0) || (nFutureValue <= 0) || (nInitAmount <= 0)) {
2434 pContext->ThrowException(XFA_IDS_ARGUMENT_MISMATCH);
2435 return;
2436 }
2437
dsinclairf27aeec2016-06-07 19:36:18 -07002438 args.GetReturnValue()->SetFloat(
2439 FXSYS_log((FX_FLOAT)(nFutureValue / nInitAmount)) /
2440 FXSYS_log((FX_FLOAT)(1 + nRate)));
Dan Sinclair1770c022016-03-14 14:14:16 -04002441}
dsinclair48d91dd2016-05-31 11:54:01 -07002442
2443// static
dsinclair12a6b0c2016-05-26 11:14:08 -07002444void CXFA_FM2JSContext::FV(CFXJSE_Value* pThis,
Dan Sinclair1770c022016-03-14 14:14:16 -04002445 const CFX_ByteStringC& szFuncName,
2446 CFXJSE_Arguments& args) {
dsinclair8f3074b2016-06-02 17:45:25 -07002447 CXFA_FM2JSContext* pContext = ToJSContext(pThis, nullptr);
dsinclair96a05f42016-06-07 06:48:02 -07002448 if (args.GetLength() != 3) {
dsinclair2235b7b2016-06-02 07:42:25 -07002449 pContext->ThrowException(XFA_IDS_INCORRECT_NUMBER_OF_METHOD, L"FV");
dsinclair96a05f42016-06-07 06:48:02 -07002450 return;
Dan Sinclair1770c022016-03-14 14:14:16 -04002451 }
dsinclair96a05f42016-06-07 06:48:02 -07002452
2453 std::unique_ptr<CFXJSE_Value> argOne = GetSimpleValue(pThis, args, 0);
2454 std::unique_ptr<CFXJSE_Value> argTwo = GetSimpleValue(pThis, args, 1);
2455 std::unique_ptr<CFXJSE_Value> argThree = GetSimpleValue(pThis, args, 2);
2456 if (ValueIsNull(pThis, argOne.get()) || ValueIsNull(pThis, argTwo.get()) ||
2457 ValueIsNull(pThis, argThree.get())) {
dsinclairf27aeec2016-06-07 19:36:18 -07002458 args.GetReturnValue()->SetNull();
dsinclair96a05f42016-06-07 06:48:02 -07002459 return;
2460 }
2461
2462 FX_DOUBLE nAmount = ValueToDouble(pThis, argOne.get());
2463 FX_DOUBLE nRate = ValueToDouble(pThis, argTwo.get());
2464 FX_DOUBLE nPeriod = ValueToDouble(pThis, argThree.get());
2465 if ((nRate < 0) || (nPeriod <= 0) || (nAmount <= 0)) {
2466 pContext->ThrowException(XFA_IDS_ARGUMENT_MISMATCH);
2467 return;
2468 }
2469
2470 FX_DOUBLE dResult = 0;
2471 if (nRate) {
2472 FX_DOUBLE nTemp = 1;
2473 for (int i = 0; i < nPeriod; ++i) {
2474 nTemp *= 1 + nRate;
2475 }
2476 dResult = nAmount * (nTemp - 1) / nRate;
2477 } else {
2478 dResult = nAmount * nPeriod;
2479 }
2480
dsinclairf27aeec2016-06-07 19:36:18 -07002481 args.GetReturnValue()->SetDouble(dResult);
Dan Sinclair1770c022016-03-14 14:14:16 -04002482}
dsinclair48d91dd2016-05-31 11:54:01 -07002483
2484// static
dsinclair12a6b0c2016-05-26 11:14:08 -07002485void CXFA_FM2JSContext::IPmt(CFXJSE_Value* pThis,
Dan Sinclair1770c022016-03-14 14:14:16 -04002486 const CFX_ByteStringC& szFuncName,
2487 CFXJSE_Arguments& args) {
dsinclair8f3074b2016-06-02 17:45:25 -07002488 CXFA_FM2JSContext* pContext = ToJSContext(pThis, nullptr);
dsinclair96a05f42016-06-07 06:48:02 -07002489 if (args.GetLength() != 5) {
dsinclair2235b7b2016-06-02 07:42:25 -07002490 pContext->ThrowException(XFA_IDS_INCORRECT_NUMBER_OF_METHOD, L"IPmt");
dsinclair96a05f42016-06-07 06:48:02 -07002491 return;
Dan Sinclair1770c022016-03-14 14:14:16 -04002492 }
dsinclair96a05f42016-06-07 06:48:02 -07002493
2494 std::unique_ptr<CFXJSE_Value> argOne = GetSimpleValue(pThis, args, 0);
2495 std::unique_ptr<CFXJSE_Value> argTwo = GetSimpleValue(pThis, args, 1);
2496 std::unique_ptr<CFXJSE_Value> argThree = GetSimpleValue(pThis, args, 2);
2497 std::unique_ptr<CFXJSE_Value> argFour = GetSimpleValue(pThis, args, 3);
2498 std::unique_ptr<CFXJSE_Value> argFive = GetSimpleValue(pThis, args, 4);
2499 if (ValueIsNull(pThis, argOne.get()) || ValueIsNull(pThis, argTwo.get()) ||
2500 ValueIsNull(pThis, argThree.get()) || ValueIsNull(pThis, argFour.get()) ||
2501 ValueIsNull(pThis, argFive.get())) {
dsinclairf27aeec2016-06-07 19:36:18 -07002502 args.GetReturnValue()->SetNull();
dsinclair96a05f42016-06-07 06:48:02 -07002503 return;
2504 }
2505
2506 FX_FLOAT nPrincipalAmount = ValueToFloat(pThis, argOne.get());
2507 FX_FLOAT nRate = ValueToFloat(pThis, argTwo.get());
2508 FX_FLOAT nPayment = ValueToFloat(pThis, argThree.get());
2509 FX_FLOAT nFirstMonth = ValueToFloat(pThis, argFour.get());
2510 FX_FLOAT nNumberOfMonths = ValueToFloat(pThis, argFive.get());
2511 if ((nPrincipalAmount <= 0) || (nRate <= 0) || (nPayment <= 0) ||
2512 (nFirstMonth < 0) || (nNumberOfMonths < 0)) {
2513 pContext->ThrowException(XFA_IDS_ARGUMENT_MISMATCH);
2514 return;
2515 }
2516
2517 FX_FLOAT nRateOfMonth = nRate / 12;
2518 int32_t iNums = (int32_t)(
2519 (FXSYS_log10((FX_FLOAT)(nPayment / nPrincipalAmount)) -
2520 FXSYS_log10((FX_FLOAT)(nPayment / nPrincipalAmount - nRateOfMonth))) /
2521 FXSYS_log10((FX_FLOAT)(1 + nRateOfMonth)));
2522 int32_t iEnd = std::min((int32_t)(nFirstMonth + nNumberOfMonths - 1), iNums);
2523
2524 if (nPayment < nPrincipalAmount * nRateOfMonth) {
dsinclairf27aeec2016-06-07 19:36:18 -07002525 args.GetReturnValue()->SetFloat(0);
dsinclair96a05f42016-06-07 06:48:02 -07002526 return;
2527 }
2528
2529 int32_t i = 0;
2530 for (i = 0; i < nFirstMonth - 1; ++i)
2531 nPrincipalAmount -= nPayment - nPrincipalAmount * nRateOfMonth;
2532
2533 FX_FLOAT nSum = 0;
2534 for (; i < iEnd; ++i) {
2535 nSum += nPrincipalAmount * nRateOfMonth;
2536 nPrincipalAmount -= nPayment - nPrincipalAmount * nRateOfMonth;
2537 }
dsinclairf27aeec2016-06-07 19:36:18 -07002538 args.GetReturnValue()->SetFloat(nSum);
Dan Sinclair1770c022016-03-14 14:14:16 -04002539}
dsinclair48d91dd2016-05-31 11:54:01 -07002540
2541// static
dsinclair12a6b0c2016-05-26 11:14:08 -07002542void CXFA_FM2JSContext::NPV(CFXJSE_Value* pThis,
Dan Sinclair1770c022016-03-14 14:14:16 -04002543 const CFX_ByteStringC& szFuncName,
2544 CFXJSE_Arguments& args) {
dsinclair8f3074b2016-06-02 17:45:25 -07002545 CXFA_FM2JSContext* pContext = ToJSContext(pThis, nullptr);
Dan Sinclair1770c022016-03-14 14:14:16 -04002546 int32_t argc = args.GetLength();
dsinclair96a05f42016-06-07 06:48:02 -07002547 if (argc < 3) {
dsinclair2235b7b2016-06-02 07:42:25 -07002548 pContext->ThrowException(XFA_IDS_INCORRECT_NUMBER_OF_METHOD, L"NPV");
dsinclair96a05f42016-06-07 06:48:02 -07002549 return;
Dan Sinclair1770c022016-03-14 14:14:16 -04002550 }
dsinclair96a05f42016-06-07 06:48:02 -07002551
2552 std::vector<std::unique_ptr<CFXJSE_Value>> argValues;
2553 for (int32_t i = 0; i < argc; i++) {
2554 argValues.push_back(GetSimpleValue(pThis, args, i));
2555 if (ValueIsNull(pThis, argValues[i].get())) {
dsinclairf27aeec2016-06-07 19:36:18 -07002556 args.GetReturnValue()->SetNull();
dsinclair96a05f42016-06-07 06:48:02 -07002557 return;
2558 }
2559 }
2560
2561 FX_DOUBLE nRate = ValueToDouble(pThis, argValues[0].get());
2562 if (nRate <= 0) {
2563 pContext->ThrowException(XFA_IDS_ARGUMENT_MISMATCH);
2564 return;
2565 }
2566
2567 std::vector<FX_DOUBLE> data(argc - 1);
2568 for (int32_t i = 1; i < argc; i++)
2569 data.push_back(ValueToDouble(pThis, argValues[i].get()));
2570
2571 FX_DOUBLE nSum = 0;
2572 int32_t iIndex = 0;
2573 for (int32_t i = 0; i < argc - 1; i++) {
2574 FX_DOUBLE nTemp = 1;
2575 for (int32_t j = 0; j <= i; j++)
2576 nTemp *= 1 + nRate;
2577
2578 FX_DOUBLE nNum = data[iIndex++];
2579 nSum += nNum / nTemp;
2580 }
dsinclairf27aeec2016-06-07 19:36:18 -07002581 args.GetReturnValue()->SetDouble(nSum);
Dan Sinclair1770c022016-03-14 14:14:16 -04002582}
dsinclair48d91dd2016-05-31 11:54:01 -07002583
2584// static
dsinclair12a6b0c2016-05-26 11:14:08 -07002585void CXFA_FM2JSContext::Pmt(CFXJSE_Value* pThis,
Dan Sinclair1770c022016-03-14 14:14:16 -04002586 const CFX_ByteStringC& szFuncName,
2587 CFXJSE_Arguments& args) {
dsinclair8f3074b2016-06-02 17:45:25 -07002588 CXFA_FM2JSContext* pContext = ToJSContext(pThis, nullptr);
dsinclair96a05f42016-06-07 06:48:02 -07002589 if (args.GetLength() != 3) {
dsinclair2235b7b2016-06-02 07:42:25 -07002590 pContext->ThrowException(XFA_IDS_INCORRECT_NUMBER_OF_METHOD, L"Pmt");
dsinclair96a05f42016-06-07 06:48:02 -07002591 return;
Dan Sinclair1770c022016-03-14 14:14:16 -04002592 }
dsinclair96a05f42016-06-07 06:48:02 -07002593
2594 std::unique_ptr<CFXJSE_Value> argOne = GetSimpleValue(pThis, args, 0);
2595 std::unique_ptr<CFXJSE_Value> argTwo = GetSimpleValue(pThis, args, 1);
2596 std::unique_ptr<CFXJSE_Value> argThree = GetSimpleValue(pThis, args, 2);
2597 if (ValueIsNull(pThis, argOne.get()) || ValueIsNull(pThis, argTwo.get()) ||
2598 ValueIsNull(pThis, argThree.get())) {
dsinclairf27aeec2016-06-07 19:36:18 -07002599 args.GetReturnValue()->SetNull();
dsinclair96a05f42016-06-07 06:48:02 -07002600 return;
2601 }
2602
2603 FX_FLOAT nPrincipal = ValueToFloat(pThis, argOne.get());
2604 FX_FLOAT nRate = ValueToFloat(pThis, argTwo.get());
2605 FX_FLOAT nPeriods = ValueToFloat(pThis, argThree.get());
2606 if ((nPrincipal <= 0) || (nRate <= 0) || (nPeriods <= 0)) {
2607 pContext->ThrowException(XFA_IDS_ARGUMENT_MISMATCH);
2608 return;
2609 }
2610
2611 FX_FLOAT nTmp = 1 + nRate;
2612 FX_FLOAT nSum = nTmp;
2613 for (int32_t i = 0; i < nPeriods - 1; ++i)
2614 nSum *= nTmp;
2615
dsinclairf27aeec2016-06-07 19:36:18 -07002616 args.GetReturnValue()->SetFloat((nPrincipal * nRate * nSum) / (nSum - 1));
Dan Sinclair1770c022016-03-14 14:14:16 -04002617}
dsinclair48d91dd2016-05-31 11:54:01 -07002618
2619// static
dsinclair12a6b0c2016-05-26 11:14:08 -07002620void CXFA_FM2JSContext::PPmt(CFXJSE_Value* pThis,
Dan Sinclair1770c022016-03-14 14:14:16 -04002621 const CFX_ByteStringC& szFuncName,
2622 CFXJSE_Arguments& args) {
dsinclair8f3074b2016-06-02 17:45:25 -07002623 CXFA_FM2JSContext* pContext = ToJSContext(pThis, nullptr);
dsinclair96a05f42016-06-07 06:48:02 -07002624 if (args.GetLength() != 5) {
dsinclair2235b7b2016-06-02 07:42:25 -07002625 pContext->ThrowException(XFA_IDS_INCORRECT_NUMBER_OF_METHOD, L"PPmt");
dsinclair96a05f42016-06-07 06:48:02 -07002626 return;
Dan Sinclair1770c022016-03-14 14:14:16 -04002627 }
dsinclair96a05f42016-06-07 06:48:02 -07002628
2629 std::unique_ptr<CFXJSE_Value> argOne = GetSimpleValue(pThis, args, 0);
2630 std::unique_ptr<CFXJSE_Value> argTwo = GetSimpleValue(pThis, args, 1);
2631 std::unique_ptr<CFXJSE_Value> argThree = GetSimpleValue(pThis, args, 2);
2632 std::unique_ptr<CFXJSE_Value> argFour = GetSimpleValue(pThis, args, 3);
2633 std::unique_ptr<CFXJSE_Value> argFive = GetSimpleValue(pThis, args, 4);
2634 if (ValueIsNull(pThis, argOne.get()) || ValueIsNull(pThis, argTwo.get()) ||
2635 ValueIsNull(pThis, argThree.get()) || ValueIsNull(pThis, argFour.get()) ||
2636 ValueIsNull(pThis, argFive.get())) {
dsinclairf27aeec2016-06-07 19:36:18 -07002637 args.GetReturnValue()->SetNull();
dsinclair96a05f42016-06-07 06:48:02 -07002638 return;
2639 }
2640
2641 FX_FLOAT nPrincipalAmount = ValueToFloat(pThis, argOne.get());
2642 FX_FLOAT nRate = ValueToFloat(pThis, argTwo.get());
2643 FX_FLOAT nPayment = ValueToFloat(pThis, argThree.get());
2644 FX_FLOAT nFirstMonth = ValueToFloat(pThis, argFour.get());
2645 FX_FLOAT nNumberOfMonths = ValueToFloat(pThis, argFive.get());
2646 if ((nPrincipalAmount <= 0) || (nRate <= 0) || (nPayment <= 0) ||
2647 (nFirstMonth < 0) || (nNumberOfMonths < 0)) {
2648 pContext->ThrowException(XFA_IDS_ARGUMENT_MISMATCH);
2649 return;
2650 }
2651
2652 FX_FLOAT nRateOfMonth = nRate / 12;
2653 int32_t iNums = (int32_t)(
2654 (FXSYS_log10((FX_FLOAT)(nPayment / nPrincipalAmount)) -
2655 FXSYS_log10((FX_FLOAT)(nPayment / nPrincipalAmount - nRateOfMonth))) /
2656 FXSYS_log10((FX_FLOAT)(1 + nRateOfMonth)));
2657 int32_t iEnd = std::min((int32_t)(nFirstMonth + nNumberOfMonths - 1), iNums);
2658 if (nPayment < nPrincipalAmount * nRateOfMonth) {
2659 pContext->ThrowException(XFA_IDS_ARGUMENT_MISMATCH);
2660 return;
2661 }
2662
2663 int32_t i = 0;
2664 for (i = 0; i < nFirstMonth - 1; ++i)
2665 nPrincipalAmount -= nPayment - nPrincipalAmount * nRateOfMonth;
2666
2667 FX_FLOAT nTemp = 0;
2668 FX_FLOAT nSum = 0;
2669 for (; i < iEnd; ++i) {
2670 nTemp = nPayment - nPrincipalAmount * nRateOfMonth;
2671 nSum += nTemp;
2672 nPrincipalAmount -= nTemp;
2673 }
dsinclairf27aeec2016-06-07 19:36:18 -07002674 args.GetReturnValue()->SetFloat(nSum);
Dan Sinclair1770c022016-03-14 14:14:16 -04002675}
dsinclair48d91dd2016-05-31 11:54:01 -07002676
2677// static
dsinclair12a6b0c2016-05-26 11:14:08 -07002678void CXFA_FM2JSContext::PV(CFXJSE_Value* pThis,
Dan Sinclair1770c022016-03-14 14:14:16 -04002679 const CFX_ByteStringC& szFuncName,
2680 CFXJSE_Arguments& args) {
dsinclair8f3074b2016-06-02 17:45:25 -07002681 CXFA_FM2JSContext* pContext = ToJSContext(pThis, nullptr);
dsinclair96a05f42016-06-07 06:48:02 -07002682 if (args.GetLength() != 3) {
dsinclair2235b7b2016-06-02 07:42:25 -07002683 pContext->ThrowException(XFA_IDS_INCORRECT_NUMBER_OF_METHOD, L"PV");
dsinclair96a05f42016-06-07 06:48:02 -07002684 return;
Dan Sinclair1770c022016-03-14 14:14:16 -04002685 }
dsinclair96a05f42016-06-07 06:48:02 -07002686
2687 std::unique_ptr<CFXJSE_Value> argOne = GetSimpleValue(pThis, args, 0);
2688 std::unique_ptr<CFXJSE_Value> argTwo = GetSimpleValue(pThis, args, 1);
2689 std::unique_ptr<CFXJSE_Value> argThree = GetSimpleValue(pThis, args, 2);
2690 if (ValueIsNull(pThis, argOne.get()) || ValueIsNull(pThis, argTwo.get()) ||
2691 ValueIsNull(pThis, argThree.get())) {
dsinclairf27aeec2016-06-07 19:36:18 -07002692 args.GetReturnValue()->SetNull();
dsinclair96a05f42016-06-07 06:48:02 -07002693 return;
2694 }
2695
2696 FX_DOUBLE nAmount = ValueToDouble(pThis, argOne.get());
2697 FX_DOUBLE nRate = ValueToDouble(pThis, argTwo.get());
2698 FX_DOUBLE nPeriod = ValueToDouble(pThis, argThree.get());
2699 if ((nAmount <= 0) || (nRate < 0) || (nPeriod <= 0)) {
2700 pContext->ThrowException(XFA_IDS_ARGUMENT_MISMATCH);
2701 return;
2702 }
2703
2704 FX_DOUBLE nTemp = 1;
2705 for (int32_t i = 0; i < nPeriod; ++i)
2706 nTemp *= 1 + nRate;
2707
2708 nTemp = 1 / nTemp;
dsinclairf27aeec2016-06-07 19:36:18 -07002709 args.GetReturnValue()->SetDouble(nAmount * ((1 - nTemp) / nRate));
Dan Sinclair1770c022016-03-14 14:14:16 -04002710}
dsinclair48d91dd2016-05-31 11:54:01 -07002711
2712// static
dsinclair12a6b0c2016-05-26 11:14:08 -07002713void CXFA_FM2JSContext::Rate(CFXJSE_Value* pThis,
Dan Sinclair1770c022016-03-14 14:14:16 -04002714 const CFX_ByteStringC& szFuncName,
2715 CFXJSE_Arguments& args) {
dsinclair8f3074b2016-06-02 17:45:25 -07002716 CXFA_FM2JSContext* pContext = ToJSContext(pThis, nullptr);
dsinclair96a05f42016-06-07 06:48:02 -07002717 if (args.GetLength() != 3) {
dsinclair2235b7b2016-06-02 07:42:25 -07002718 pContext->ThrowException(XFA_IDS_INCORRECT_NUMBER_OF_METHOD, L"Rate");
dsinclair96a05f42016-06-07 06:48:02 -07002719 return;
Dan Sinclair1770c022016-03-14 14:14:16 -04002720 }
dsinclair96a05f42016-06-07 06:48:02 -07002721
2722 std::unique_ptr<CFXJSE_Value> argOne = GetSimpleValue(pThis, args, 0);
2723 std::unique_ptr<CFXJSE_Value> argTwo = GetSimpleValue(pThis, args, 1);
2724 std::unique_ptr<CFXJSE_Value> argThree = GetSimpleValue(pThis, args, 2);
2725 if (ValueIsNull(pThis, argOne.get()) || ValueIsNull(pThis, argTwo.get()) ||
2726 ValueIsNull(pThis, argThree.get())) {
dsinclairf27aeec2016-06-07 19:36:18 -07002727 args.GetReturnValue()->SetNull();
dsinclair96a05f42016-06-07 06:48:02 -07002728 return;
2729 }
2730
2731 FX_FLOAT nFuture = ValueToFloat(pThis, argOne.get());
2732 FX_FLOAT nPresent = ValueToFloat(pThis, argTwo.get());
2733 FX_FLOAT nTotalNumber = ValueToFloat(pThis, argThree.get());
2734 if ((nFuture <= 0) || (nPresent < 0) || (nTotalNumber <= 0)) {
2735 pContext->ThrowException(XFA_IDS_ARGUMENT_MISMATCH);
2736 return;
2737 }
2738
dsinclairf27aeec2016-06-07 19:36:18 -07002739 args.GetReturnValue()->SetFloat(
2740 FXSYS_pow((FX_FLOAT)(nFuture / nPresent), (FX_FLOAT)(1 / nTotalNumber)) -
2741 1);
Dan Sinclair1770c022016-03-14 14:14:16 -04002742}
dsinclair48d91dd2016-05-31 11:54:01 -07002743
2744// static
dsinclair12a6b0c2016-05-26 11:14:08 -07002745void CXFA_FM2JSContext::Term(CFXJSE_Value* pThis,
Dan Sinclair1770c022016-03-14 14:14:16 -04002746 const CFX_ByteStringC& szFuncName,
2747 CFXJSE_Arguments& args) {
dsinclair8f3074b2016-06-02 17:45:25 -07002748 CXFA_FM2JSContext* pContext = ToJSContext(pThis, nullptr);
dsinclair96a05f42016-06-07 06:48:02 -07002749 if (args.GetLength() != 3) {
dsinclair2235b7b2016-06-02 07:42:25 -07002750 pContext->ThrowException(XFA_IDS_INCORRECT_NUMBER_OF_METHOD, L"Term");
dsinclair96a05f42016-06-07 06:48:02 -07002751 return;
Dan Sinclair1770c022016-03-14 14:14:16 -04002752 }
dsinclair96a05f42016-06-07 06:48:02 -07002753
2754 std::unique_ptr<CFXJSE_Value> argOne = GetSimpleValue(pThis, args, 0);
2755 std::unique_ptr<CFXJSE_Value> argTwo = GetSimpleValue(pThis, args, 1);
2756 std::unique_ptr<CFXJSE_Value> argThree = GetSimpleValue(pThis, args, 2);
2757 if (ValueIsNull(pThis, argOne.get()) || ValueIsNull(pThis, argTwo.get()) ||
2758 ValueIsNull(pThis, argThree.get())) {
dsinclairf27aeec2016-06-07 19:36:18 -07002759 args.GetReturnValue()->SetNull();
dsinclair96a05f42016-06-07 06:48:02 -07002760 return;
2761 }
2762
2763 FX_FLOAT nMount = ValueToFloat(pThis, argOne.get());
2764 FX_FLOAT nRate = ValueToFloat(pThis, argTwo.get());
2765 FX_FLOAT nFuture = ValueToFloat(pThis, argThree.get());
2766 if ((nMount <= 0) || (nRate <= 0) || (nFuture <= 0)) {
2767 pContext->ThrowException(XFA_IDS_ARGUMENT_MISMATCH);
2768 return;
2769 }
2770
dsinclairf27aeec2016-06-07 19:36:18 -07002771 args.GetReturnValue()->SetFloat(
2772 FXSYS_log((FX_FLOAT)(nFuture / nMount * nRate) + 1) /
2773 FXSYS_log((FX_FLOAT)(1 + nRate)));
Dan Sinclair1770c022016-03-14 14:14:16 -04002774}
dsinclair48d91dd2016-05-31 11:54:01 -07002775
2776// static
dsinclair12a6b0c2016-05-26 11:14:08 -07002777void CXFA_FM2JSContext::Choose(CFXJSE_Value* pThis,
Dan Sinclair1770c022016-03-14 14:14:16 -04002778 const CFX_ByteStringC& szFuncName,
2779 CFXJSE_Arguments& args) {
dsinclair8f3074b2016-06-02 17:45:25 -07002780 CXFA_FM2JSContext* pContext = ToJSContext(pThis, nullptr);
Dan Sinclair1770c022016-03-14 14:14:16 -04002781 int32_t argc = args.GetLength();
dsinclair96a05f42016-06-07 06:48:02 -07002782 if (argc < 2) {
dsinclair2235b7b2016-06-02 07:42:25 -07002783 pContext->ThrowException(XFA_IDS_INCORRECT_NUMBER_OF_METHOD, L"Choose");
dsinclair96a05f42016-06-07 06:48:02 -07002784 return;
Dan Sinclair1770c022016-03-14 14:14:16 -04002785 }
dsinclair96a05f42016-06-07 06:48:02 -07002786
2787 std::unique_ptr<CFXJSE_Value> argOne = args.GetValue(0);
2788 if (ValueIsNull(pThis, argOne.get())) {
dsinclairf27aeec2016-06-07 19:36:18 -07002789 args.GetReturnValue()->SetNull();
dsinclair96a05f42016-06-07 06:48:02 -07002790 return;
2791 }
2792
2793 int32_t iIndex = (int32_t)ValueToFloat(pThis, argOne.get());
2794 if (iIndex < 1) {
dsinclairf27aeec2016-06-07 19:36:18 -07002795 args.GetReturnValue()->SetString("");
dsinclair96a05f42016-06-07 06:48:02 -07002796 return;
2797 }
2798
2799 FX_BOOL bFound = FALSE;
2800 FX_BOOL bStopCounterFlags = FALSE;
2801 int32_t iArgIndex = 1;
2802 int32_t iValueIndex = 0;
2803 v8::Isolate* pIsolate = pContext->GetScriptRuntime();
2804 while (!bFound && !bStopCounterFlags && (iArgIndex < argc)) {
2805 std::unique_ptr<CFXJSE_Value> argIndexValue = args.GetValue(iArgIndex);
dsinclair769b1372016-06-08 13:12:41 -07002806 if (argIndexValue->IsArray()) {
dsinclair96a05f42016-06-07 06:48:02 -07002807 std::unique_ptr<CFXJSE_Value> lengthValue(new CFXJSE_Value(pIsolate));
dsinclairf27aeec2016-06-07 19:36:18 -07002808 argIndexValue->GetObjectProperty("length", lengthValue.get());
2809 int32_t iLength = lengthValue->ToInteger();
dsinclair96a05f42016-06-07 06:48:02 -07002810 if (iLength > 3)
2811 bStopCounterFlags = TRUE;
2812
2813 iValueIndex += (iLength - 2);
2814 if (iValueIndex >= iIndex) {
2815 std::unique_ptr<CFXJSE_Value> propertyValue(new CFXJSE_Value(pIsolate));
2816 std::unique_ptr<CFXJSE_Value> jsObjectValue(new CFXJSE_Value(pIsolate));
2817 std::unique_ptr<CFXJSE_Value> newPropertyValue(
2818 new CFXJSE_Value(pIsolate));
dsinclairf27aeec2016-06-07 19:36:18 -07002819 argIndexValue->GetObjectPropertyByIdx(1, propertyValue.get());
2820 argIndexValue->GetObjectPropertyByIdx(
2821 (iLength - 1) - (iValueIndex - iIndex), jsObjectValue.get());
dsinclair769b1372016-06-08 13:12:41 -07002822 if (propertyValue->IsNull()) {
dsinclair96a05f42016-06-07 06:48:02 -07002823 GetObjectDefaultValue(jsObjectValue.get(), newPropertyValue.get());
2824 } else {
dsinclair2f5582f2016-06-09 11:48:23 -07002825 jsObjectValue->GetObjectProperty(
2826 propertyValue->ToString().AsStringC(), newPropertyValue.get());
dsinclair96a05f42016-06-07 06:48:02 -07002827 }
2828 CFX_ByteString bsChoosed;
2829 ValueToUTF8String(newPropertyValue.get(), bsChoosed);
dsinclairf27aeec2016-06-07 19:36:18 -07002830 args.GetReturnValue()->SetString(bsChoosed.AsStringC());
dsinclair96a05f42016-06-07 06:48:02 -07002831 bFound = TRUE;
2832 }
2833 } else {
2834 iValueIndex++;
2835 if (iValueIndex == iIndex) {
2836 CFX_ByteString bsChoosed;
2837 ValueToUTF8String(argIndexValue.get(), bsChoosed);
dsinclairf27aeec2016-06-07 19:36:18 -07002838 args.GetReturnValue()->SetString(bsChoosed.AsStringC());
dsinclair96a05f42016-06-07 06:48:02 -07002839 bFound = TRUE;
2840 }
2841 }
2842 iArgIndex++;
2843 }
2844 if (!bFound)
dsinclairf27aeec2016-06-07 19:36:18 -07002845 args.GetReturnValue()->SetString("");
Dan Sinclair1770c022016-03-14 14:14:16 -04002846}
dsinclair48d91dd2016-05-31 11:54:01 -07002847
2848// static
dsinclair12a6b0c2016-05-26 11:14:08 -07002849void CXFA_FM2JSContext::Exists(CFXJSE_Value* pThis,
Dan Sinclair1770c022016-03-14 14:14:16 -04002850 const CFX_ByteStringC& szFuncName,
2851 CFXJSE_Arguments& args) {
dsinclair96a05f42016-06-07 06:48:02 -07002852 if (args.GetLength() != 1) {
dsinclair8f3074b2016-06-02 17:45:25 -07002853 ToJSContext(pThis, nullptr)
2854 ->ThrowException(XFA_IDS_INCORRECT_NUMBER_OF_METHOD, L"Exists");
dsinclair96a05f42016-06-07 06:48:02 -07002855 return;
Dan Sinclair1770c022016-03-14 14:14:16 -04002856 }
dsinclair769b1372016-06-08 13:12:41 -07002857 args.GetReturnValue()->SetInteger(args.GetValue(0)->IsObject());
Dan Sinclair1770c022016-03-14 14:14:16 -04002858}
dsinclair48d91dd2016-05-31 11:54:01 -07002859
2860// static
dsinclair12a6b0c2016-05-26 11:14:08 -07002861void CXFA_FM2JSContext::HasValue(CFXJSE_Value* pThis,
Dan Sinclair1770c022016-03-14 14:14:16 -04002862 const CFX_ByteStringC& szFuncName,
2863 CFXJSE_Arguments& args) {
dsinclair96a05f42016-06-07 06:48:02 -07002864 if (args.GetLength() != 1) {
dsinclair8f3074b2016-06-02 17:45:25 -07002865 ToJSContext(pThis, nullptr)
2866 ->ThrowException(XFA_IDS_INCORRECT_NUMBER_OF_METHOD, L"HasValue");
dsinclair96a05f42016-06-07 06:48:02 -07002867 return;
Dan Sinclair1770c022016-03-14 14:14:16 -04002868 }
dsinclair96a05f42016-06-07 06:48:02 -07002869
2870 std::unique_ptr<CFXJSE_Value> argOne = GetSimpleValue(pThis, args, 0);
dsinclair769b1372016-06-08 13:12:41 -07002871 if (!argOne->IsString()) {
2872 args.GetReturnValue()->SetInteger(argOne->IsNumber() ||
2873 argOne->IsBoolean());
dsinclair96a05f42016-06-07 06:48:02 -07002874 return;
2875 }
2876
dsinclair2f5582f2016-06-09 11:48:23 -07002877 CFX_ByteString valueStr = argOne->ToString();
dsinclair96a05f42016-06-07 06:48:02 -07002878 valueStr.TrimLeft();
dsinclairf27aeec2016-06-07 19:36:18 -07002879 args.GetReturnValue()->SetInteger(!valueStr.IsEmpty());
Dan Sinclair1770c022016-03-14 14:14:16 -04002880}
dsinclair48d91dd2016-05-31 11:54:01 -07002881
2882// static
dsinclair12a6b0c2016-05-26 11:14:08 -07002883void CXFA_FM2JSContext::Oneof(CFXJSE_Value* pThis,
Dan Sinclair1770c022016-03-14 14:14:16 -04002884 const CFX_ByteStringC& szFuncName,
2885 CFXJSE_Arguments& args) {
dsinclair96a05f42016-06-07 06:48:02 -07002886 if (args.GetLength() < 2) {
dsinclair8f3074b2016-06-02 17:45:25 -07002887 ToJSContext(pThis, nullptr)
2888 ->ThrowException(XFA_IDS_INCORRECT_NUMBER_OF_METHOD, L"Oneof");
dsinclair96a05f42016-06-07 06:48:02 -07002889 return;
Dan Sinclair1770c022016-03-14 14:14:16 -04002890 }
dsinclair96a05f42016-06-07 06:48:02 -07002891
2892 FX_BOOL bFlags = FALSE;
2893 std::unique_ptr<CFXJSE_Value> argOne = GetSimpleValue(pThis, args, 0);
2894 CFXJSE_Value** parametersValue = nullptr;
2895 int32_t iCount = 0;
2896 unfoldArgs(pThis, args, parametersValue, iCount, 1);
2897 for (int32_t i = 0; i < iCount; i++) {
2898 if (simpleValueCompare(pThis, argOne.get(), parametersValue[i])) {
2899 bFlags = TRUE;
2900 break;
2901 }
2902 }
2903 for (int32_t i = 0; i < iCount; i++)
2904 delete parametersValue[i];
2905 FX_Free(parametersValue);
2906
dsinclairf27aeec2016-06-07 19:36:18 -07002907 args.GetReturnValue()->SetInteger(bFlags);
Dan Sinclair1770c022016-03-14 14:14:16 -04002908}
dsinclair48d91dd2016-05-31 11:54:01 -07002909
2910// static
dsinclair12a6b0c2016-05-26 11:14:08 -07002911void CXFA_FM2JSContext::Within(CFXJSE_Value* pThis,
Dan Sinclair1770c022016-03-14 14:14:16 -04002912 const CFX_ByteStringC& szFuncName,
2913 CFXJSE_Arguments& args) {
dsinclair759de382016-06-07 14:10:16 -07002914 if (args.GetLength() != 3) {
dsinclair8f3074b2016-06-02 17:45:25 -07002915 ToJSContext(pThis, nullptr)
2916 ->ThrowException(XFA_IDS_INCORRECT_NUMBER_OF_METHOD, L"Within");
dsinclair759de382016-06-07 14:10:16 -07002917 return;
Dan Sinclair1770c022016-03-14 14:14:16 -04002918 }
dsinclair759de382016-06-07 14:10:16 -07002919
2920 std::unique_ptr<CFXJSE_Value> argOne = GetSimpleValue(pThis, args, 0);
dsinclair769b1372016-06-08 13:12:41 -07002921 if (argOne->IsNull()) {
dsinclairf27aeec2016-06-07 19:36:18 -07002922 args.GetReturnValue()->SetUndefined();
dsinclair759de382016-06-07 14:10:16 -07002923 return;
2924 }
2925
2926 std::unique_ptr<CFXJSE_Value> argLow = GetSimpleValue(pThis, args, 1);
2927 std::unique_ptr<CFXJSE_Value> argHigh = GetSimpleValue(pThis, args, 2);
dsinclair769b1372016-06-08 13:12:41 -07002928 if (argOne->IsNumber()) {
dsinclair759de382016-06-07 14:10:16 -07002929 FX_FLOAT oneNumber = ValueToFloat(pThis, argOne.get());
2930 FX_FLOAT lowNumber = ValueToFloat(pThis, argLow.get());
2931 FX_FLOAT heightNumber = ValueToFloat(pThis, argHigh.get());
dsinclairf27aeec2016-06-07 19:36:18 -07002932 args.GetReturnValue()->SetInteger((oneNumber >= lowNumber) &&
2933 (oneNumber <= heightNumber));
dsinclair759de382016-06-07 14:10:16 -07002934 return;
2935 }
2936
2937 CFX_ByteString oneString;
2938 CFX_ByteString lowString;
2939 CFX_ByteString heightString;
2940 ValueToUTF8String(argOne.get(), oneString);
2941 ValueToUTF8String(argLow.get(), lowString);
2942 ValueToUTF8String(argHigh.get(), heightString);
dsinclairf27aeec2016-06-07 19:36:18 -07002943 args.GetReturnValue()->SetInteger(
2944 (oneString.Compare(lowString.AsStringC()) >= 0) &&
2945 (oneString.Compare(heightString.AsStringC()) <= 0));
Dan Sinclair1770c022016-03-14 14:14:16 -04002946}
dsinclair48d91dd2016-05-31 11:54:01 -07002947
2948// static
dsinclair12a6b0c2016-05-26 11:14:08 -07002949void CXFA_FM2JSContext::If(CFXJSE_Value* pThis,
Dan Sinclair1770c022016-03-14 14:14:16 -04002950 const CFX_ByteStringC& szFuncName,
2951 CFXJSE_Arguments& args) {
dsinclair759de382016-06-07 14:10:16 -07002952 if (args.GetLength() != 3) {
dsinclair8f3074b2016-06-02 17:45:25 -07002953 ToJSContext(pThis, nullptr)
2954 ->ThrowException(XFA_IDS_INCORRECT_NUMBER_OF_METHOD, L"If");
dsinclair759de382016-06-07 14:10:16 -07002955 return;
Dan Sinclair1770c022016-03-14 14:14:16 -04002956 }
dsinclair759de382016-06-07 14:10:16 -07002957
dsinclairf27aeec2016-06-07 19:36:18 -07002958 args.GetReturnValue()->Assign(GetSimpleValue(pThis, args, 0)->ToBoolean()
2959 ? GetSimpleValue(pThis, args, 1).get()
2960 : GetSimpleValue(pThis, args, 2).get());
Dan Sinclair1770c022016-03-14 14:14:16 -04002961}
dsinclair48d91dd2016-05-31 11:54:01 -07002962
2963// static
dsinclair12a6b0c2016-05-26 11:14:08 -07002964void CXFA_FM2JSContext::Eval(CFXJSE_Value* pThis,
Dan Sinclair1770c022016-03-14 14:14:16 -04002965 const CFX_ByteStringC& szFuncName,
2966 CFXJSE_Arguments& args) {
dsinclair8f3074b2016-06-02 17:45:25 -07002967 CXFA_FM2JSContext* pContext = ToJSContext(pThis, nullptr);
dsinclair759de382016-06-07 14:10:16 -07002968 if (args.GetLength() != 1) {
dsinclair2235b7b2016-06-02 07:42:25 -07002969 pContext->ThrowException(XFA_IDS_INCORRECT_NUMBER_OF_METHOD, L"Eval");
dsinclair759de382016-06-07 14:10:16 -07002970 return;
Dan Sinclair1770c022016-03-14 14:14:16 -04002971 }
dsinclair759de382016-06-07 14:10:16 -07002972
2973 v8::Isolate* pIsolate = pContext->GetScriptRuntime();
2974 std::unique_ptr<CFXJSE_Value> scriptValue = GetSimpleValue(pThis, args, 0);
2975 CFX_ByteString utf8ScriptString;
2976 ValueToUTF8String(scriptValue.get(), utf8ScriptString);
2977 if (utf8ScriptString.IsEmpty()) {
dsinclairf27aeec2016-06-07 19:36:18 -07002978 args.GetReturnValue()->SetNull();
dsinclair759de382016-06-07 14:10:16 -07002979 return;
2980 }
2981
2982 CFX_WideTextBuf wsJavaScriptBuf;
2983 CFX_WideString wsError;
2984 CXFA_FM2JSContext::Translate(
2985 CFX_WideString::FromUTF8(utf8ScriptString.AsStringC()).AsStringC(),
2986 wsJavaScriptBuf, wsError);
dsinclair769b1372016-06-08 13:12:41 -07002987 std::unique_ptr<CFXJSE_Context> pNewContext(
2988 CFXJSE_Context::Create(pIsolate, nullptr, nullptr));
dsinclair759de382016-06-07 14:10:16 -07002989
2990 std::unique_ptr<CFXJSE_Value> returnValue(new CFXJSE_Value(pIsolate));
2991 CFX_WideString javaScript(wsJavaScriptBuf.AsStringC());
dsinclair769b1372016-06-08 13:12:41 -07002992 pNewContext->ExecuteScript(
dsinclair759de382016-06-07 14:10:16 -07002993 FX_UTF8Encode(javaScript.c_str(), javaScript.GetLength()).c_str(),
2994 returnValue.get());
2995
dsinclairf27aeec2016-06-07 19:36:18 -07002996 args.GetReturnValue()->Assign(returnValue.get());
Dan Sinclair1770c022016-03-14 14:14:16 -04002997}
dsinclair48d91dd2016-05-31 11:54:01 -07002998
2999// static
dsinclair12a6b0c2016-05-26 11:14:08 -07003000void CXFA_FM2JSContext::Ref(CFXJSE_Value* pThis,
Dan Sinclair1770c022016-03-14 14:14:16 -04003001 const CFX_ByteStringC& szFuncName,
3002 CFXJSE_Arguments& args) {
dsinclair8f3074b2016-06-02 17:45:25 -07003003 CXFA_FM2JSContext* pContext = ToJSContext(pThis, nullptr);
dsinclairec3da5b2016-05-25 16:42:05 -07003004 v8::Isolate* pIsolate = pContext->GetScriptRuntime();
dsinclair759de382016-06-07 14:10:16 -07003005 if (args.GetLength() != 1) {
dsinclair2235b7b2016-06-02 07:42:25 -07003006 pContext->ThrowException(XFA_IDS_INCORRECT_NUMBER_OF_METHOD, L"Ref");
dsinclair759de382016-06-07 14:10:16 -07003007 return;
Dan Sinclair1770c022016-03-14 14:14:16 -04003008 }
dsinclair759de382016-06-07 14:10:16 -07003009
3010 std::unique_ptr<CFXJSE_Value> argOne = args.GetValue(0);
dsinclair769b1372016-06-08 13:12:41 -07003011 if (!argOne->IsArray() && !argOne->IsObject() && !argOne->IsBoolean() &&
3012 !argOne->IsString() && !argOne->IsNull() && !argOne->IsNumber()) {
dsinclair759de382016-06-07 14:10:16 -07003013 pContext->ThrowException(XFA_IDS_ARGUMENT_MISMATCH);
3014 return;
3015 }
3016
dsinclair769b1372016-06-08 13:12:41 -07003017 if (argOne->IsBoolean() || argOne->IsString() || argOne->IsNumber()) {
dsinclairf27aeec2016-06-07 19:36:18 -07003018 args.GetReturnValue()->Assign(argOne.get());
dsinclair759de382016-06-07 14:10:16 -07003019 return;
3020 }
3021
3022 CFXJSE_Value* rgValues[3];
3023 for (int32_t i = 0; i < 3; i++)
3024 rgValues[i] = new CFXJSE_Value(pIsolate);
3025
3026 int intVal = 3;
dsinclair769b1372016-06-08 13:12:41 -07003027 if (argOne->IsNull()) {
3028 // TODO(dsinclair): Why is this 4 when the others are all 3?
dsinclair759de382016-06-07 14:10:16 -07003029 intVal = 4;
dsinclairf27aeec2016-06-07 19:36:18 -07003030 rgValues[2]->SetNull();
dsinclair769b1372016-06-08 13:12:41 -07003031 } else if (argOne->IsArray()) {
dsinclair759de382016-06-07 14:10:16 -07003032#ifndef NDEBUG
3033 std::unique_ptr<CFXJSE_Value> lengthValue(new CFXJSE_Value(pIsolate));
dsinclairf27aeec2016-06-07 19:36:18 -07003034 argOne->GetObjectProperty("length", lengthValue.get());
3035 ASSERT(lengthValue->ToInteger() >= 3);
dsinclair759de382016-06-07 14:10:16 -07003036#endif
3037
3038 std::unique_ptr<CFXJSE_Value> propertyValue(new CFXJSE_Value(pIsolate));
3039 std::unique_ptr<CFXJSE_Value> jsObjectValue(new CFXJSE_Value(pIsolate));
dsinclairf27aeec2016-06-07 19:36:18 -07003040 argOne->GetObjectPropertyByIdx(1, propertyValue.get());
3041 argOne->GetObjectPropertyByIdx(2, jsObjectValue.get());
dsinclair769b1372016-06-08 13:12:41 -07003042 if (!propertyValue->IsNull() || jsObjectValue->IsNull()) {
dsinclair759de382016-06-07 14:10:16 -07003043 for (int32_t i = 0; i < 3; i++)
3044 delete rgValues[i];
3045
3046 pContext->ThrowException(XFA_IDS_ARGUMENT_MISMATCH);
3047 return;
3048 }
3049
dsinclairf27aeec2016-06-07 19:36:18 -07003050 rgValues[2]->Assign(jsObjectValue.get());
dsinclair769b1372016-06-08 13:12:41 -07003051 } else if (argOne->IsObject()) {
dsinclairf27aeec2016-06-07 19:36:18 -07003052 rgValues[2]->Assign(argOne.get());
dsinclair759de382016-06-07 14:10:16 -07003053 }
3054
dsinclairf27aeec2016-06-07 19:36:18 -07003055 rgValues[0]->SetInteger(intVal);
3056 rgValues[1]->SetNull();
3057 args.GetReturnValue()->SetArray(3, rgValues);
dsinclair759de382016-06-07 14:10:16 -07003058
3059 for (int32_t i = 0; i < 3; i++)
3060 delete rgValues[i];
Dan Sinclair1770c022016-03-14 14:14:16 -04003061}
dsinclair48d91dd2016-05-31 11:54:01 -07003062
3063// static
dsinclair12a6b0c2016-05-26 11:14:08 -07003064void CXFA_FM2JSContext::UnitType(CFXJSE_Value* pThis,
Dan Sinclair1770c022016-03-14 14:14:16 -04003065 const CFX_ByteStringC& szFuncName,
3066 CFXJSE_Arguments& args) {
dsinclair759de382016-06-07 14:10:16 -07003067 if (args.GetLength() != 1) {
dsinclair8f3074b2016-06-02 17:45:25 -07003068 ToJSContext(pThis, nullptr)
3069 ->ThrowException(XFA_IDS_INCORRECT_NUMBER_OF_METHOD, L"UnitType");
dsinclair759de382016-06-07 14:10:16 -07003070 return;
3071 }
3072
3073 std::unique_ptr<CFXJSE_Value> unitspanValue = GetSimpleValue(pThis, args, 0);
dsinclair769b1372016-06-08 13:12:41 -07003074 if (unitspanValue->IsNull()) {
dsinclairf27aeec2016-06-07 19:36:18 -07003075 args.GetReturnValue()->SetNull();
dsinclair759de382016-06-07 14:10:16 -07003076 return;
3077 }
3078
3079 CFX_ByteString unitspanString;
3080 ValueToUTF8String(unitspanValue.get(), unitspanString);
3081 if (unitspanString.IsEmpty()) {
dsinclairf27aeec2016-06-07 19:36:18 -07003082 args.GetReturnValue()->SetString("in");
dsinclair759de382016-06-07 14:10:16 -07003083 return;
3084 }
3085
3086 enum XFA_FM2JS_VALUETYPE_ParserStatus {
3087 VALUETYPE_START,
3088 VALUETYPE_HAVEINVALIDCHAR,
3089 VALUETYPE_HAVEDIGIT,
3090 VALUETYPE_HAVEDIGITWHITE,
3091 VALUETYPE_ISCM,
3092 VALUETYPE_ISMM,
3093 VALUETYPE_ISPT,
3094 VALUETYPE_ISMP,
3095 VALUETYPE_ISIN,
3096 };
3097 unitspanString.MakeLower();
3098 CFX_WideString wsTypeString =
3099 CFX_WideString::FromUTF8(unitspanString.AsStringC());
3100 const FX_WCHAR* pData = wsTypeString.c_str();
3101 int32_t u = 0;
3102 int32_t uLen = wsTypeString.GetLength();
3103 while (IsWhitespace(pData[u]))
3104 u++;
3105
3106 XFA_FM2JS_VALUETYPE_ParserStatus eParserStatus = VALUETYPE_START;
3107 FX_WCHAR typeChar;
3108 // TODO(dsinclair): Cleanup this parser, figure out what the various checks
3109 // are for.
3110 while (u < uLen) {
3111 typeChar = pData[u];
3112 if (IsWhitespace(typeChar)) {
3113 if (eParserStatus != VALUETYPE_HAVEDIGIT &&
3114 eParserStatus != VALUETYPE_HAVEDIGITWHITE) {
3115 eParserStatus = VALUETYPE_ISIN;
3116 break;
3117 }
3118 eParserStatus = VALUETYPE_HAVEDIGITWHITE;
3119 } else if ((typeChar >= '0' && typeChar <= '9') || typeChar == '-' ||
3120 typeChar == '.') {
3121 if (eParserStatus == VALUETYPE_HAVEDIGITWHITE) {
3122 eParserStatus = VALUETYPE_ISIN;
3123 break;
3124 }
3125 eParserStatus = VALUETYPE_HAVEDIGIT;
3126 } else if ((typeChar == 'c' || typeChar == 'p') && (u + 1 < uLen)) {
3127 FX_WCHAR nextChar = pData[u + 1];
3128 if ((eParserStatus == VALUETYPE_START ||
3129 eParserStatus == VALUETYPE_HAVEDIGIT ||
3130 eParserStatus == VALUETYPE_HAVEDIGITWHITE) &&
3131 (nextChar > '9' || nextChar < '0') && nextChar != '.' &&
3132 nextChar != '-') {
3133 eParserStatus = (typeChar == 'c') ? VALUETYPE_ISCM : VALUETYPE_ISPT;
3134 break;
3135 }
3136 eParserStatus = VALUETYPE_HAVEINVALIDCHAR;
3137 } else if (typeChar == 'm' && (u + 1 < uLen)) {
3138 FX_WCHAR nextChar = pData[u + 1];
3139 if ((eParserStatus == VALUETYPE_START ||
3140 eParserStatus == VALUETYPE_HAVEDIGIT ||
3141 eParserStatus == VALUETYPE_HAVEDIGITWHITE) &&
3142 (nextChar > '9' || nextChar < '0') && nextChar != '.' &&
3143 nextChar != '-') {
3144 eParserStatus = VALUETYPE_ISMM;
3145 if (nextChar == 'p' || ((u + 5 < uLen) && pData[u + 1] == 'i' &&
3146 pData[u + 2] == 'l' && pData[u + 3] == 'l' &&
3147 pData[u + 4] == 'i' && pData[u + 5] == 'p')) {
3148 eParserStatus = VALUETYPE_ISMP;
3149 }
3150 break;
3151 }
3152 } else {
3153 eParserStatus = VALUETYPE_HAVEINVALIDCHAR;
3154 }
3155 u++;
3156 }
3157 switch (eParserStatus) {
3158 case VALUETYPE_ISCM:
dsinclairf27aeec2016-06-07 19:36:18 -07003159 args.GetReturnValue()->SetString("cm");
dsinclair759de382016-06-07 14:10:16 -07003160 break;
3161 case VALUETYPE_ISMM:
dsinclairf27aeec2016-06-07 19:36:18 -07003162 args.GetReturnValue()->SetString("mm");
dsinclair759de382016-06-07 14:10:16 -07003163 break;
3164 case VALUETYPE_ISPT:
dsinclairf27aeec2016-06-07 19:36:18 -07003165 args.GetReturnValue()->SetString("pt");
dsinclair759de382016-06-07 14:10:16 -07003166 break;
3167 case VALUETYPE_ISMP:
dsinclairf27aeec2016-06-07 19:36:18 -07003168 args.GetReturnValue()->SetString("mp");
dsinclair759de382016-06-07 14:10:16 -07003169 break;
3170 default:
dsinclairf27aeec2016-06-07 19:36:18 -07003171 args.GetReturnValue()->SetString("in");
dsinclair759de382016-06-07 14:10:16 -07003172 break;
Dan Sinclair1770c022016-03-14 14:14:16 -04003173 }
3174}
dsinclair48d91dd2016-05-31 11:54:01 -07003175
3176// static
dsinclair12a6b0c2016-05-26 11:14:08 -07003177void CXFA_FM2JSContext::UnitValue(CFXJSE_Value* pThis,
Dan Sinclair1770c022016-03-14 14:14:16 -04003178 const CFX_ByteStringC& szFuncName,
3179 CFXJSE_Arguments& args) {
3180 int32_t argc = args.GetLength();
dsinclair759de382016-06-07 14:10:16 -07003181 if (argc < 1 || argc > 2) {
dsinclair8f3074b2016-06-02 17:45:25 -07003182 ToJSContext(pThis, nullptr)
3183 ->ThrowException(XFA_IDS_INCORRECT_NUMBER_OF_METHOD, L"UnitValue");
dsinclair759de382016-06-07 14:10:16 -07003184 return;
Dan Sinclair1770c022016-03-14 14:14:16 -04003185 }
dsinclair759de382016-06-07 14:10:16 -07003186
3187 std::unique_ptr<CFXJSE_Value> unitspanValue = GetSimpleValue(pThis, args, 0);
dsinclair769b1372016-06-08 13:12:41 -07003188 if (unitspanValue->IsNull()) {
dsinclairf27aeec2016-06-07 19:36:18 -07003189 args.GetReturnValue()->SetNull();
dsinclair759de382016-06-07 14:10:16 -07003190 return;
3191 }
3192
3193 CFX_ByteString unitspanString;
3194 ValueToUTF8String(unitspanValue.get(), unitspanString);
3195 const FX_CHAR* pData = unitspanString.c_str();
3196 if (!pData) {
dsinclairf27aeec2016-06-07 19:36:18 -07003197 args.GetReturnValue()->SetInteger(0);
dsinclair759de382016-06-07 14:10:16 -07003198 return;
3199 }
3200
3201 int32_t u = 0;
3202 while (IsWhitespace(pData[u]))
3203 ++u;
3204
3205 while (u < unitspanString.GetLength()) {
3206 if ((pData[u] > '9' || pData[u] < '0') && pData[u] != '.' &&
3207 pData[u] != '-') {
3208 break;
3209 }
3210 ++u;
3211 }
3212
3213 FX_CHAR* pTemp = nullptr;
3214 FX_DOUBLE dFirstNumber = strtod(pData, &pTemp);
3215 while (IsWhitespace(pData[u]))
3216 ++u;
3217
3218 int32_t uLen = unitspanString.GetLength();
3219 CFX_ByteString strFirstUnit;
3220 while (u < uLen) {
3221 if (pData[u] == ' ')
3222 break;
3223
3224 strFirstUnit += pData[u];
3225 ++u;
3226 }
3227 strFirstUnit.MakeLower();
3228
3229 CFX_ByteString strUnit;
3230 if (argc > 1) {
3231 std::unique_ptr<CFXJSE_Value> unitValue = GetSimpleValue(pThis, args, 1);
3232 CFX_ByteString unitTempString;
3233 ValueToUTF8String(unitValue.get(), unitTempString);
3234 const FX_CHAR* pChar = unitTempString.c_str();
3235 int32_t uVal = 0;
3236 while (IsWhitespace(pChar[uVal]))
3237 ++uVal;
3238
3239 while (uVal < unitTempString.GetLength()) {
3240 if ((pChar[uVal] > '9' || pChar[uVal] < '0') && pChar[uVal] != '.') {
3241 break;
3242 }
3243 ++uVal;
3244 }
3245 while (IsWhitespace(pChar[uVal]))
3246 ++uVal;
3247
3248 int32_t uValLen = unitTempString.GetLength();
3249 while (uVal < uValLen) {
3250 if (pChar[uVal] == ' ')
3251 break;
3252
3253 strUnit += pChar[uVal];
3254 ++uVal;
3255 }
3256 strUnit.MakeLower();
3257 } else {
3258 strUnit = strFirstUnit;
3259 }
3260
3261 FX_DOUBLE dResult = 0;
3262 if (strFirstUnit == "in" || strFirstUnit == "inches") {
3263 if (strUnit == "mm" || strUnit == "millimeters")
3264 dResult = dFirstNumber * 25.4;
3265 else if (strUnit == "cm" || strUnit == "centimeters")
3266 dResult = dFirstNumber * 2.54;
3267 else if (strUnit == "pt" || strUnit == "points")
3268 dResult = dFirstNumber / 72;
3269 else if (strUnit == "mp" || strUnit == "millipoints")
3270 dResult = dFirstNumber / 72000;
3271 else
3272 dResult = dFirstNumber;
3273 } else if (strFirstUnit == "mm" || strFirstUnit == "millimeters") {
3274 if (strUnit == "mm" || strUnit == "millimeters")
3275 dResult = dFirstNumber;
3276 else if (strUnit == "cm" || strUnit == "centimeters")
3277 dResult = dFirstNumber / 10;
3278 else if (strUnit == "pt" || strUnit == "points")
3279 dResult = dFirstNumber / 25.4 / 72;
3280 else if (strUnit == "mp" || strUnit == "millipoints")
3281 dResult = dFirstNumber / 25.4 / 72000;
3282 else
3283 dResult = dFirstNumber / 25.4;
3284 } else if (strFirstUnit == "cm" || strFirstUnit == "centimeters") {
3285 if (strUnit == "mm" || strUnit == "millimeters")
3286 dResult = dFirstNumber * 10;
3287 else if (strUnit == "cm" || strUnit == "centimeters")
3288 dResult = dFirstNumber;
3289 else if (strUnit == "pt" || strUnit == "points")
3290 dResult = dFirstNumber / 2.54 / 72;
3291 else if (strUnit == "mp" || strUnit == "millipoints")
3292 dResult = dFirstNumber / 2.54 / 72000;
3293 else
3294 dResult = dFirstNumber / 2.54;
3295 } else if (strFirstUnit == "pt" || strFirstUnit == "points") {
3296 if (strUnit == "mm" || strUnit == "millimeters")
3297 dResult = dFirstNumber / 72 * 25.4;
3298 else if (strUnit == "cm" || strUnit == "centimeters")
3299 dResult = dFirstNumber / 72 * 2.54;
3300 else if (strUnit == "pt" || strUnit == "points")
3301 dResult = dFirstNumber;
3302 else if (strUnit == "mp" || strUnit == "millipoints")
3303 dResult = dFirstNumber * 1000;
3304 else
3305 dResult = dFirstNumber / 72;
3306 } else if (strFirstUnit == "mp" || strFirstUnit == "millipoints") {
3307 if (strUnit == "mm" || strUnit == "millimeters")
3308 dResult = dFirstNumber / 72000 * 25.4;
3309 else if (strUnit == "cm" || strUnit == "centimeters")
3310 dResult = dFirstNumber / 72000 * 2.54;
3311 else if (strUnit == "pt" || strUnit == "points")
3312 dResult = dFirstNumber / 1000;
3313 else if (strUnit == "mp" || strUnit == "millipoints")
3314 dResult = dFirstNumber;
3315 else
3316 dResult = dFirstNumber / 72000;
3317 }
dsinclairf27aeec2016-06-07 19:36:18 -07003318 args.GetReturnValue()->SetDouble(dResult);
Dan Sinclair1770c022016-03-14 14:14:16 -04003319}
dsinclair48d91dd2016-05-31 11:54:01 -07003320
3321// static
dsinclair12a6b0c2016-05-26 11:14:08 -07003322void CXFA_FM2JSContext::At(CFXJSE_Value* pThis,
Dan Sinclair1770c022016-03-14 14:14:16 -04003323 const CFX_ByteStringC& szFuncName,
3324 CFXJSE_Arguments& args) {
dsinclair759de382016-06-07 14:10:16 -07003325 if (args.GetLength() != 2) {
dsinclair8f3074b2016-06-02 17:45:25 -07003326 ToJSContext(pThis, nullptr)
3327 ->ThrowException(XFA_IDS_INCORRECT_NUMBER_OF_METHOD, L"At");
dsinclair759de382016-06-07 14:10:16 -07003328 return;
Dan Sinclair1770c022016-03-14 14:14:16 -04003329 }
dsinclair759de382016-06-07 14:10:16 -07003330
3331 std::unique_ptr<CFXJSE_Value> argOne = GetSimpleValue(pThis, args, 0);
3332 std::unique_ptr<CFXJSE_Value> argTwo = GetSimpleValue(pThis, args, 1);
3333 if (ValueIsNull(pThis, argOne.get()) || ValueIsNull(pThis, argTwo.get())) {
dsinclairf27aeec2016-06-07 19:36:18 -07003334 args.GetReturnValue()->SetNull();
dsinclair759de382016-06-07 14:10:16 -07003335 return;
3336 }
3337
3338 CFX_ByteString stringTwo;
3339 ValueToUTF8String(argTwo.get(), stringTwo);
3340 if (stringTwo.IsEmpty()) {
dsinclairf27aeec2016-06-07 19:36:18 -07003341 args.GetReturnValue()->SetInteger(1);
dsinclair759de382016-06-07 14:10:16 -07003342 return;
3343 }
3344
3345 CFX_ByteString stringOne;
3346 ValueToUTF8String(argOne.get(), stringOne);
3347 FX_STRSIZE iPosition = stringOne.Find(stringTwo.AsStringC());
dsinclairf27aeec2016-06-07 19:36:18 -07003348 args.GetReturnValue()->SetInteger(iPosition + 1);
Dan Sinclair1770c022016-03-14 14:14:16 -04003349}
dsinclair48d91dd2016-05-31 11:54:01 -07003350
3351// static
dsinclair12a6b0c2016-05-26 11:14:08 -07003352void CXFA_FM2JSContext::Concat(CFXJSE_Value* pThis,
Dan Sinclair1770c022016-03-14 14:14:16 -04003353 const CFX_ByteStringC& szFuncName,
3354 CFXJSE_Arguments& args) {
Dan Sinclair1770c022016-03-14 14:14:16 -04003355 int32_t argc = args.GetLength();
dsinclair759de382016-06-07 14:10:16 -07003356 if (argc < 1) {
dsinclair8f3074b2016-06-02 17:45:25 -07003357 ToJSContext(pThis, nullptr)
3358 ->ThrowException(XFA_IDS_INCORRECT_NUMBER_OF_METHOD, L"Concat");
dsinclair759de382016-06-07 14:10:16 -07003359 return;
Dan Sinclair1770c022016-03-14 14:14:16 -04003360 }
dsinclair759de382016-06-07 14:10:16 -07003361
3362 CFX_ByteString resultString;
3363 FX_BOOL bAllNull = TRUE;
3364 for (int32_t i = 0; i < argc; i++) {
3365 std::unique_ptr<CFXJSE_Value> value = GetSimpleValue(pThis, args, i);
3366 if (ValueIsNull(pThis, value.get()))
3367 continue;
3368
3369 bAllNull = FALSE;
3370
3371 CFX_ByteString valueStr;
3372 ValueToUTF8String(value.get(), valueStr);
3373 resultString += valueStr;
3374 }
3375
3376 if (bAllNull) {
dsinclairf27aeec2016-06-07 19:36:18 -07003377 args.GetReturnValue()->SetNull();
dsinclair759de382016-06-07 14:10:16 -07003378 return;
3379 }
3380
dsinclairf27aeec2016-06-07 19:36:18 -07003381 args.GetReturnValue()->SetString(resultString.AsStringC());
Dan Sinclair1770c022016-03-14 14:14:16 -04003382}
dsinclair48d91dd2016-05-31 11:54:01 -07003383
3384// static
dsinclair12a6b0c2016-05-26 11:14:08 -07003385void CXFA_FM2JSContext::Decode(CFXJSE_Value* pThis,
Dan Sinclair1770c022016-03-14 14:14:16 -04003386 const CFX_ByteStringC& szFuncName,
3387 CFXJSE_Arguments& args) {
Dan Sinclair1770c022016-03-14 14:14:16 -04003388 int32_t argc = args.GetLength();
dsinclair759de382016-06-07 14:10:16 -07003389 if (argc < 1 || argc > 2) {
3390 ToJSContext(pThis, nullptr)
3391 ->ThrowException(XFA_IDS_INCORRECT_NUMBER_OF_METHOD, L"Decode");
3392 return;
3393 }
3394
Dan Sinclair1770c022016-03-14 14:14:16 -04003395 if (argc == 1) {
dsinclair86fad992016-05-31 11:34:04 -07003396 std::unique_ptr<CFXJSE_Value> argOne = GetSimpleValue(pThis, args, 0);
3397 if (ValueIsNull(pThis, argOne.get())) {
dsinclairf27aeec2016-06-07 19:36:18 -07003398 args.GetReturnValue()->SetNull();
dsinclair759de382016-06-07 14:10:16 -07003399 return;
Dan Sinclair1770c022016-03-14 14:14:16 -04003400 }
dsinclair759de382016-06-07 14:10:16 -07003401
3402 CFX_ByteString toDecodeString;
3403 ValueToUTF8String(argOne.get(), toDecodeString);
3404 CFX_ByteTextBuf resultBuf;
3405 DecodeURL(toDecodeString.AsStringC(), resultBuf);
dsinclairf27aeec2016-06-07 19:36:18 -07003406 args.GetReturnValue()->SetString(resultBuf.AsStringC());
dsinclair759de382016-06-07 14:10:16 -07003407 return;
Dan Sinclair1770c022016-03-14 14:14:16 -04003408 }
dsinclair759de382016-06-07 14:10:16 -07003409
3410 std::unique_ptr<CFXJSE_Value> argOne = GetSimpleValue(pThis, args, 0);
3411 std::unique_ptr<CFXJSE_Value> argTwo = GetSimpleValue(pThis, args, 1);
3412 if (ValueIsNull(pThis, argOne.get()) || ValueIsNull(pThis, argTwo.get())) {
dsinclairf27aeec2016-06-07 19:36:18 -07003413 args.GetReturnValue()->SetNull();
dsinclair759de382016-06-07 14:10:16 -07003414 return;
3415 }
3416
3417 CFX_ByteString toDecodeString;
3418 ValueToUTF8String(argOne.get(), toDecodeString);
3419
3420 CFX_ByteString identifyString;
3421 ValueToUTF8String(argTwo.get(), identifyString);
3422
3423 CFX_ByteTextBuf resultBuf;
3424 if (identifyString.EqualNoCase("html"))
3425 DecodeHTML(toDecodeString.AsStringC(), resultBuf);
3426 else if (identifyString.EqualNoCase("xml"))
3427 DecodeXML(toDecodeString.AsStringC(), resultBuf);
3428 else
3429 DecodeURL(toDecodeString.AsStringC(), resultBuf);
3430
dsinclairf27aeec2016-06-07 19:36:18 -07003431 args.GetReturnValue()->SetString(resultBuf.AsStringC());
Dan Sinclair1770c022016-03-14 14:14:16 -04003432}
dsinclair48d91dd2016-05-31 11:54:01 -07003433
3434// static
Dan Sinclair1770c022016-03-14 14:14:16 -04003435void CXFA_FM2JSContext::DecodeURL(const CFX_ByteStringC& szURLString,
3436 CFX_ByteTextBuf& szResultString) {
tsepez6fe7d212016-04-06 10:51:14 -07003437 CFX_WideString wsURLString = CFX_WideString::FromUTF8(szURLString);
tsepezbd9748d2016-04-13 21:40:19 -07003438 const FX_WCHAR* pData = wsURLString.c_str();
Dan Sinclair1770c022016-03-14 14:14:16 -04003439 int32_t i = 0;
Dan Sinclair1770c022016-03-14 14:14:16 -04003440 CFX_WideTextBuf wsResultBuf;
dsinclair759de382016-06-07 14:10:16 -07003441 while (i < wsURLString.GetLength()) {
3442 FX_WCHAR ch = pData[i];
3443 if ('%' != ch) {
Dan Sinclair1770c022016-03-14 14:14:16 -04003444 wsResultBuf.AppendChar(ch);
dsinclair759de382016-06-07 14:10:16 -07003445 ++i;
3446 continue;
Dan Sinclair1770c022016-03-14 14:14:16 -04003447 }
dsinclair759de382016-06-07 14:10:16 -07003448
3449 FX_WCHAR chTemp = 0;
3450 int32_t iCount = 0;
3451 while (iCount < 2) {
3452 ++i;
3453 ch = pData[i];
3454 if (ch <= '9' && ch >= '0') {
3455 // TODO(dsinclair): Premultiply and add rather then scale.
3456 chTemp += (ch - '0') * (!iCount ? 16 : 1);
3457 } else if (ch <= 'F' && ch >= 'A') {
3458 chTemp += (ch - 'A' + 10) * (!iCount ? 16 : 1);
3459 } else if (ch <= 'f' && ch >= 'a') {
3460 chTemp += (ch - 'a' + 10) * (!iCount ? 16 : 1);
3461 } else {
3462 wsResultBuf.Clear();
3463 return;
3464 }
3465 ++iCount;
3466 }
3467 wsResultBuf.AppendChar(chTemp);
Dan Sinclair1770c022016-03-14 14:14:16 -04003468 ++i;
3469 }
3470 wsResultBuf.AppendChar(0);
dsinclair759de382016-06-07 14:10:16 -07003471
Dan Sinclair1770c022016-03-14 14:14:16 -04003472 szResultString.Clear();
3473 szResultString << FX_UTF8Encode(wsResultBuf.GetBuffer(),
tsepez28f97ff2016-04-04 16:41:35 -07003474 wsResultBuf.GetLength())
tsepez4c3debb2016-04-08 12:20:38 -07003475 .AsStringC();
Dan Sinclair1770c022016-03-14 14:14:16 -04003476}
dsinclair48d91dd2016-05-31 11:54:01 -07003477
3478// static
Dan Sinclair1770c022016-03-14 14:14:16 -04003479void CXFA_FM2JSContext::DecodeHTML(const CFX_ByteStringC& szHTMLString,
3480 CFX_ByteTextBuf& szResultString) {
tsepez6fe7d212016-04-06 10:51:14 -07003481 CFX_WideString wsHTMLString = CFX_WideString::FromUTF8(szHTMLString);
Dan Sinclair1770c022016-03-14 14:14:16 -04003482 FX_WCHAR strString[9];
3483 int32_t iStrIndex = 0;
3484 int32_t iLen = wsHTMLString.GetLength();
3485 int32_t i = 0;
3486 int32_t iCode = 0;
tsepezbd9748d2016-04-13 21:40:19 -07003487 const FX_WCHAR* pData = wsHTMLString.c_str();
Dan Sinclair1770c022016-03-14 14:14:16 -04003488 CFX_WideTextBuf wsResultBuf;
3489 while (i < iLen) {
dsinclair759de382016-06-07 14:10:16 -07003490 FX_WCHAR ch = pData[i];
3491 if (ch != '&') {
Dan Sinclair1770c022016-03-14 14:14:16 -04003492 wsResultBuf.AppendChar(ch);
3493 ++i;
3494 continue;
3495 }
dsinclair759de382016-06-07 14:10:16 -07003496
3497 ++i;
3498 ch = pData[i];
3499 if (ch == '#') {
3500 ++i;
3501 ch = pData[i];
3502 if (ch != 'x' && ch != 'X') {
3503 wsResultBuf.Clear();
3504 return;
3505 }
3506
3507 ++i;
3508 ch = pData[i];
3509 if ((ch >= '0' && ch <= '9') || (ch <= 'f' && ch >= 'a') ||
3510 (ch <= 'F' && ch >= 'A')) {
3511 while (ch != ';' && i < iLen) {
3512 if (ch >= '0' && ch <= '9') {
3513 iCode += ch - '0';
3514 } else if (ch <= 'f' && ch >= 'a') {
3515 iCode += ch - 'a' + 10;
3516 } else if (ch <= 'F' && ch >= 'A') {
3517 iCode += ch - 'A' + 10;
3518 } else {
3519 wsResultBuf.Clear();
3520 return;
3521 }
3522 ++i;
3523 // TODO(dsinclair): Postmultiply seems wrong, start at zero
3524 // and pre-multiply then can remove the post divide.
3525 iCode *= 16;
3526 ch = pData[i];
3527 }
3528 iCode /= 16;
3529 }
3530 } else {
3531 while (ch != ';' && i < iLen) {
3532 strString[iStrIndex++] = ch;
3533 ++i;
3534 ch = pData[i];
3535 }
3536 strString[iStrIndex] = 0;
3537 }
Dan Sinclair1770c022016-03-14 14:14:16 -04003538 uint32_t iData = 0;
3539 if (HTMLSTR2Code(strString, iData)) {
3540 wsResultBuf.AppendChar((FX_WCHAR)iData);
3541 } else {
3542 wsResultBuf.AppendChar(iCode);
3543 }
3544 iStrIndex = 0;
3545 strString[iStrIndex] = 0;
3546 ++i;
3547 }
3548 wsResultBuf.AppendChar(0);
dsinclair759de382016-06-07 14:10:16 -07003549
Dan Sinclair1770c022016-03-14 14:14:16 -04003550 szResultString.Clear();
3551 szResultString << FX_UTF8Encode(wsResultBuf.GetBuffer(),
tsepez28f97ff2016-04-04 16:41:35 -07003552 wsResultBuf.GetLength())
tsepez4c3debb2016-04-08 12:20:38 -07003553 .AsStringC();
Dan Sinclair1770c022016-03-14 14:14:16 -04003554}
dsinclair48d91dd2016-05-31 11:54:01 -07003555
3556// static
Dan Sinclair1770c022016-03-14 14:14:16 -04003557void CXFA_FM2JSContext::DecodeXML(const CFX_ByteStringC& szXMLString,
3558 CFX_ByteTextBuf& szResultString) {
tsepez6fe7d212016-04-06 10:51:14 -07003559 CFX_WideString wsXMLString = CFX_WideString::FromUTF8(szXMLString);
Dan Sinclair1770c022016-03-14 14:14:16 -04003560 FX_WCHAR strString[9];
3561 int32_t iStrIndex = 0;
3562 int32_t iLen = wsXMLString.GetLength();
3563 int32_t i = 0;
3564 int32_t iCode = 0;
3565 FX_WCHAR ch = 0;
tsepezbd9748d2016-04-13 21:40:19 -07003566 const FX_WCHAR* pData = wsXMLString.c_str();
Dan Sinclair1770c022016-03-14 14:14:16 -04003567 CFX_WideTextBuf wsXMLBuf;
3568 while (i < iLen) {
dsinclair2b6d64e2016-06-06 11:39:42 -07003569 ch = pData[i];
dsinclair759de382016-06-07 14:10:16 -07003570 if (ch != '&') {
Dan Sinclair1770c022016-03-14 14:14:16 -04003571 wsXMLBuf.AppendChar(ch);
3572 ++i;
3573 continue;
3574 }
dsinclair759de382016-06-07 14:10:16 -07003575
3576 // TODO(dsinclair): This is very similar to DecodeHTML, can they be
3577 // combined?
3578 ++i;
3579 ch = pData[i];
3580 if (ch == '#') {
3581 ++i;
3582 ch = pData[i];
3583 if (ch != 'x' && ch != 'X') {
3584 wsXMLBuf.Clear();
3585 return;
3586 }
3587
3588 ++i;
3589 ch = pData[i];
3590 if ((ch >= '0' && ch <= '9') || (ch <= 'f' && ch >= 'a') ||
3591 (ch <= 'F' && ch >= 'A')) {
3592 while (ch != ';') {
3593 if (ch >= '0' && ch <= '9') {
3594 iCode += ch - '0';
3595 } else if (ch <= 'f' && ch >= 'a') {
3596 iCode += ch - 'a' + 10;
3597 } else if (ch <= 'F' && ch >= 'A') {
3598 iCode += ch - 'A' + 10;
3599 } else {
3600 wsXMLBuf.Clear();
3601 return;
3602 }
3603 ++i;
3604 iCode *= 16;
3605 ch = pData[i];
3606 }
3607 iCode /= 16;
3608 }
3609 } else {
3610 while (ch != ';' && i < iLen) {
3611 strString[iStrIndex++] = ch;
3612 ++i;
3613 ch = pData[i];
3614 }
3615 strString[iStrIndex] = 0;
3616 }
3617
Dan Sinclair1770c022016-03-14 14:14:16 -04003618 const FX_WCHAR* const strName[] = {L"quot", L"amp", L"apos", L"lt", L"gt"};
3619 int32_t iIndex = 0;
3620 while (iIndex < 5) {
3621 if (FXSYS_memcmp(strString, strName[iIndex],
3622 FXSYS_wcslen(strName[iIndex])) == 0) {
3623 break;
3624 }
3625 ++iIndex;
3626 }
3627 switch (iIndex) {
3628 case 0:
3629 wsXMLBuf.AppendChar('"');
3630 break;
3631 case 1:
3632 wsXMLBuf.AppendChar('&');
3633 break;
3634 case 2:
3635 wsXMLBuf.AppendChar('\'');
3636 break;
3637 case 3:
3638 wsXMLBuf.AppendChar('<');
3639 break;
3640 case 4:
3641 wsXMLBuf.AppendChar('>');
3642 break;
3643 default:
3644 wsXMLBuf.AppendChar(iCode);
3645 break;
3646 }
3647 iStrIndex = 0;
3648 strString[iStrIndex] = 0;
3649 ++i;
3650 iCode = 0;
3651 }
3652 wsXMLBuf.AppendChar(0);
dsinclair759de382016-06-07 14:10:16 -07003653
Dan Sinclair1770c022016-03-14 14:14:16 -04003654 szResultString.Clear();
tsepez28f97ff2016-04-04 16:41:35 -07003655 szResultString << FX_UTF8Encode(wsXMLBuf.GetBuffer(), wsXMLBuf.GetLength())
tsepez4c3debb2016-04-08 12:20:38 -07003656 .AsStringC();
Dan Sinclair1770c022016-03-14 14:14:16 -04003657}
dsinclair48d91dd2016-05-31 11:54:01 -07003658
3659// static
dsinclair12a6b0c2016-05-26 11:14:08 -07003660void CXFA_FM2JSContext::Encode(CFXJSE_Value* pThis,
Dan Sinclair1770c022016-03-14 14:14:16 -04003661 const CFX_ByteStringC& szFuncName,
3662 CFXJSE_Arguments& args) {
Dan Sinclair1770c022016-03-14 14:14:16 -04003663 int32_t argc = args.GetLength();
dsinclaircf7f3222016-06-08 20:34:02 -07003664 if (argc < 1 || argc > 2) {
3665 ToJSContext(pThis, nullptr)
3666 ->ThrowException(XFA_IDS_INCORRECT_NUMBER_OF_METHOD, L"Encode");
3667 return;
3668 }
3669
Dan Sinclair1770c022016-03-14 14:14:16 -04003670 if (argc == 1) {
dsinclair86fad992016-05-31 11:34:04 -07003671 std::unique_ptr<CFXJSE_Value> argOne = GetSimpleValue(pThis, args, 0);
3672 if (ValueIsNull(pThis, argOne.get())) {
dsinclairf27aeec2016-06-07 19:36:18 -07003673 args.GetReturnValue()->SetNull();
dsinclaircf7f3222016-06-08 20:34:02 -07003674 return;
Dan Sinclair1770c022016-03-14 14:14:16 -04003675 }
dsinclaircf7f3222016-06-08 20:34:02 -07003676
3677 CFX_ByteString toEncodeString;
3678 ValueToUTF8String(argOne.get(), toEncodeString);
3679 CFX_ByteTextBuf resultBuf;
3680 EncodeURL(toEncodeString.AsStringC(), resultBuf);
3681 args.GetReturnValue()->SetString(resultBuf.AsStringC());
3682 return;
Dan Sinclair1770c022016-03-14 14:14:16 -04003683 }
dsinclaircf7f3222016-06-08 20:34:02 -07003684
3685 std::unique_ptr<CFXJSE_Value> argOne = GetSimpleValue(pThis, args, 0);
3686 std::unique_ptr<CFXJSE_Value> argTwo = GetSimpleValue(pThis, args, 1);
3687 if (ValueIsNull(pThis, argOne.get()) || ValueIsNull(pThis, argTwo.get())) {
3688 args.GetReturnValue()->SetNull();
3689 return;
3690 }
3691
3692 CFX_ByteString toEncodeString;
3693 ValueToUTF8String(argOne.get(), toEncodeString);
3694 CFX_ByteString identifyString;
3695 ValueToUTF8String(argTwo.get(), identifyString);
3696 CFX_ByteTextBuf resultBuf;
3697 if (identifyString.EqualNoCase("html"))
3698 EncodeHTML(toEncodeString.AsStringC(), resultBuf);
3699 else if (identifyString.EqualNoCase("xml"))
3700 EncodeXML(toEncodeString.AsStringC(), resultBuf);
3701 else
3702 EncodeURL(toEncodeString.AsStringC(), resultBuf);
3703
3704 args.GetReturnValue()->SetString(resultBuf.AsStringC());
Dan Sinclair1770c022016-03-14 14:14:16 -04003705}
dsinclair48d91dd2016-05-31 11:54:01 -07003706
3707// static
Dan Sinclair1770c022016-03-14 14:14:16 -04003708void CXFA_FM2JSContext::EncodeURL(const CFX_ByteStringC& szURLString,
3709 CFX_ByteTextBuf& szResultBuf) {
tsepez6fe7d212016-04-06 10:51:14 -07003710 CFX_WideString wsURLString = CFX_WideString::FromUTF8(szURLString);
Dan Sinclair1770c022016-03-14 14:14:16 -04003711 CFX_WideTextBuf wsResultBuf;
Dan Sinclair1770c022016-03-14 14:14:16 -04003712 FX_WCHAR strEncode[4];
3713 strEncode[0] = '%';
3714 strEncode[3] = 0;
3715 FX_WCHAR strUnsafe[] = {' ', '<', '>', '"', '#', '%', '{', '}',
3716 '|', '\\', '^', '~', '[', ']', '`'};
3717 FX_WCHAR strReserved[] = {';', '/', '?', ':', '@', '=', '&'};
3718 FX_WCHAR strSpecial[] = {'$', '-', '+', '!', '*', '\'', '(', ')', ','};
3719 const FX_WCHAR* strCode = L"0123456789abcdef";
dsinclaircf7f3222016-06-08 20:34:02 -07003720 for (int32_t u = 0; u < wsURLString.GetLength(); ++u) {
3721 FX_WCHAR ch = wsURLString.GetAt(u);
Dan Sinclair1770c022016-03-14 14:14:16 -04003722 int32_t i = 0;
dsinclaircf7f3222016-06-08 20:34:02 -07003723 int32_t iCount = FX_ArraySize(strUnsafe);
Dan Sinclair1770c022016-03-14 14:14:16 -04003724 while (i < iCount) {
3725 if (ch == strUnsafe[i]) {
3726 int32_t iIndex = ch / 16;
3727 strEncode[1] = strCode[iIndex];
3728 strEncode[2] = strCode[ch - iIndex * 16];
3729 wsResultBuf << FX_WSTRC(strEncode);
3730 break;
3731 }
3732 ++i;
3733 }
dsinclaircf7f3222016-06-08 20:34:02 -07003734 if (i < iCount)
Dan Sinclair1770c022016-03-14 14:14:16 -04003735 continue;
dsinclaircf7f3222016-06-08 20:34:02 -07003736
Dan Sinclair1770c022016-03-14 14:14:16 -04003737 i = 0;
dsinclaircf7f3222016-06-08 20:34:02 -07003738 iCount = FX_ArraySize(strReserved);
Dan Sinclair1770c022016-03-14 14:14:16 -04003739 while (i < iCount) {
3740 if (ch == strReserved[i]) {
3741 int32_t iIndex = ch / 16;
3742 strEncode[1] = strCode[iIndex];
3743 strEncode[2] = strCode[ch - iIndex * 16];
3744 wsResultBuf << FX_WSTRC(strEncode);
3745 break;
3746 }
3747 ++i;
3748 }
dsinclaircf7f3222016-06-08 20:34:02 -07003749 if (i < iCount)
Dan Sinclair1770c022016-03-14 14:14:16 -04003750 continue;
dsinclaircf7f3222016-06-08 20:34:02 -07003751
Dan Sinclair1770c022016-03-14 14:14:16 -04003752 i = 0;
dsinclaircf7f3222016-06-08 20:34:02 -07003753 iCount = FX_ArraySize(strSpecial);
Dan Sinclair1770c022016-03-14 14:14:16 -04003754 while (i < iCount) {
3755 if (ch == strSpecial[i]) {
3756 wsResultBuf.AppendChar(ch);
3757 break;
3758 }
3759 ++i;
3760 }
dsinclaircf7f3222016-06-08 20:34:02 -07003761 if (i < iCount)
Dan Sinclair1770c022016-03-14 14:14:16 -04003762 continue;
dsinclaircf7f3222016-06-08 20:34:02 -07003763
3764 if ((ch >= 0x80 && ch <= 0xff) || ch <= 0x1f || ch == 0x7f) {
Dan Sinclair1770c022016-03-14 14:14:16 -04003765 int32_t iIndex = ch / 16;
3766 strEncode[1] = strCode[iIndex];
3767 strEncode[2] = strCode[ch - iIndex * 16];
3768 wsResultBuf << FX_WSTRC(strEncode);
3769 } else if (ch >= 0x20 && ch <= 0x7e) {
3770 wsResultBuf.AppendChar(ch);
3771 } else {
ochangf6be1452016-06-01 12:20:03 -07003772 const FX_WCHAR iRadix = 16;
Dan Sinclair1770c022016-03-14 14:14:16 -04003773 CFX_WideString strTmp;
3774 while (ch >= iRadix) {
3775 FX_WCHAR tmp = strCode[ch % iRadix];
3776 ch /= iRadix;
3777 strTmp += tmp;
3778 }
3779 strTmp += strCode[ch];
3780 int32_t iLen = strTmp.GetLength();
dsinclaircf7f3222016-06-08 20:34:02 -07003781 if (iLen < 2)
Dan Sinclair1770c022016-03-14 14:14:16 -04003782 break;
dsinclaircf7f3222016-06-08 20:34:02 -07003783
Dan Sinclair1770c022016-03-14 14:14:16 -04003784 int32_t iIndex = 0;
3785 if (iLen % 2 != 0) {
3786 strEncode[1] = '0';
3787 strEncode[2] = strTmp.GetAt(iLen - 1);
3788 iIndex = iLen - 2;
3789 } else {
3790 strEncode[1] = strTmp.GetAt(iLen - 1);
3791 strEncode[2] = strTmp.GetAt(iLen - 2);
3792 iIndex = iLen - 3;
3793 }
3794 wsResultBuf << FX_WSTRC(strEncode);
3795 while (iIndex > 0) {
3796 strEncode[1] = strTmp.GetAt(iIndex);
3797 strEncode[2] = strTmp.GetAt(iIndex - 1);
3798 iIndex -= 2;
3799 wsResultBuf << FX_WSTRC(strEncode);
3800 }
3801 }
3802 }
3803 wsResultBuf.AppendChar(0);
3804 szResultBuf.Clear();
dsinclaircf7f3222016-06-08 20:34:02 -07003805
tsepez28f97ff2016-04-04 16:41:35 -07003806 szResultBuf << FX_UTF8Encode(wsResultBuf.GetBuffer(), wsResultBuf.GetLength())
tsepez4c3debb2016-04-08 12:20:38 -07003807 .AsStringC();
Dan Sinclair1770c022016-03-14 14:14:16 -04003808}
dsinclair48d91dd2016-05-31 11:54:01 -07003809
3810// static
Dan Sinclair1770c022016-03-14 14:14:16 -04003811void CXFA_FM2JSContext::EncodeHTML(const CFX_ByteStringC& szHTMLString,
3812 CFX_ByteTextBuf& szResultBuf) {
dsinclair179bebb2016-04-05 11:02:18 -07003813 CFX_ByteString str = szHTMLString.c_str();
tsepez4c3debb2016-04-08 12:20:38 -07003814 CFX_WideString wsHTMLString = CFX_WideString::FromUTF8(str.AsStringC());
Dan Sinclair1770c022016-03-14 14:14:16 -04003815 const FX_WCHAR* strCode = L"0123456789abcdef";
3816 FX_WCHAR strEncode[9];
3817 strEncode[0] = '&';
3818 strEncode[1] = '#';
3819 strEncode[2] = 'x';
3820 strEncode[5] = ';';
3821 strEncode[6] = 0;
3822 strEncode[7] = ';';
3823 strEncode[8] = 0;
3824 CFX_WideTextBuf wsResultBuf;
Dan Sinclair1770c022016-03-14 14:14:16 -04003825 int32_t iLen = wsHTMLString.GetLength();
3826 int32_t i = 0;
tsepezbd9748d2016-04-13 21:40:19 -07003827 const FX_WCHAR* pData = wsHTMLString.c_str();
Dan Sinclair1770c022016-03-14 14:14:16 -04003828 while (i < iLen) {
dsinclaircf7f3222016-06-08 20:34:02 -07003829 uint32_t ch = pData[i];
3830 CFX_WideString htmlReserve;
Dan Sinclair1770c022016-03-14 14:14:16 -04003831 if (HTMLCode2STR(ch, htmlReserve)) {
3832 wsResultBuf.AppendChar(L'&');
3833 wsResultBuf << htmlReserve;
3834 wsResultBuf.AppendChar(L';');
dsinclaircf7f3222016-06-08 20:34:02 -07003835 } else if (ch >= 32 && ch <= 126) {
3836 wsResultBuf.AppendChar((FX_WCHAR)ch);
3837 } else if (ch < 256) {
3838 int32_t iIndex = ch / 16;
3839 strEncode[3] = strCode[iIndex];
3840 strEncode[4] = strCode[ch - iIndex * 16];
3841 strEncode[5] = ';';
3842 strEncode[6] = 0;
3843 wsResultBuf << FX_WSTRC(strEncode);
Dan Sinclair1770c022016-03-14 14:14:16 -04003844 } else {
dsinclaircf7f3222016-06-08 20:34:02 -07003845 int32_t iBigByte = ch / 256;
3846 int32_t iLittleByte = ch % 256;
3847 strEncode[3] = strCode[iBigByte / 16];
3848 strEncode[4] = strCode[iBigByte % 16];
3849 strEncode[5] = strCode[iLittleByte / 16];
3850 strEncode[6] = strCode[iLittleByte % 16];
3851 wsResultBuf << FX_WSTRC(strEncode);
Dan Sinclair1770c022016-03-14 14:14:16 -04003852 }
3853 ++i;
3854 }
3855 wsResultBuf.AppendChar(0);
3856 szResultBuf.Clear();
dsinclaircf7f3222016-06-08 20:34:02 -07003857
tsepez28f97ff2016-04-04 16:41:35 -07003858 szResultBuf << FX_UTF8Encode(wsResultBuf.GetBuffer(), wsResultBuf.GetLength())
tsepez4c3debb2016-04-08 12:20:38 -07003859 .AsStringC();
Dan Sinclair1770c022016-03-14 14:14:16 -04003860}
dsinclair48d91dd2016-05-31 11:54:01 -07003861
3862// static
Dan Sinclair1770c022016-03-14 14:14:16 -04003863void CXFA_FM2JSContext::EncodeXML(const CFX_ByteStringC& szXMLString,
3864 CFX_ByteTextBuf& szResultBuf) {
tsepez6fe7d212016-04-06 10:51:14 -07003865 CFX_WideString wsXMLString = CFX_WideString::FromUTF8(szXMLString);
Dan Sinclair1770c022016-03-14 14:14:16 -04003866 CFX_WideTextBuf wsResultBuf;
Dan Sinclair1770c022016-03-14 14:14:16 -04003867 FX_WCHAR strEncode[9];
3868 strEncode[0] = '&';
3869 strEncode[1] = '#';
3870 strEncode[2] = 'x';
3871 strEncode[5] = ';';
3872 strEncode[6] = 0;
3873 strEncode[7] = ';';
3874 strEncode[8] = 0;
Dan Sinclair1770c022016-03-14 14:14:16 -04003875 const FX_WCHAR* strCode = L"0123456789abcdef";
tsepezbd9748d2016-04-13 21:40:19 -07003876 const FX_WCHAR* pData = wsXMLString.c_str();
dsinclaircf7f3222016-06-08 20:34:02 -07003877 for (int32_t u = 0; u < wsXMLString.GetLength(); ++u) {
3878 FX_WCHAR ch = pData[u];
Dan Sinclair1770c022016-03-14 14:14:16 -04003879 switch (ch) {
3880 case '"':
3881 wsResultBuf.AppendChar('&');
dsinclaircf7f3222016-06-08 20:34:02 -07003882 wsResultBuf << CFX_WideStringC(L"quot");
Dan Sinclair1770c022016-03-14 14:14:16 -04003883 wsResultBuf.AppendChar(';');
3884 break;
3885 case '&':
3886 wsResultBuf.AppendChar('&');
dsinclaircf7f3222016-06-08 20:34:02 -07003887 wsResultBuf << CFX_WideStringC(L"amp");
Dan Sinclair1770c022016-03-14 14:14:16 -04003888 wsResultBuf.AppendChar(';');
3889 break;
3890 case '\'':
3891 wsResultBuf.AppendChar('&');
dsinclaircf7f3222016-06-08 20:34:02 -07003892 wsResultBuf << CFX_WideStringC(L"apos");
Dan Sinclair1770c022016-03-14 14:14:16 -04003893 wsResultBuf.AppendChar(';');
3894 break;
3895 case '<':
3896 wsResultBuf.AppendChar('&');
dsinclaircf7f3222016-06-08 20:34:02 -07003897 wsResultBuf << CFX_WideStringC(L"lt");
Dan Sinclair1770c022016-03-14 14:14:16 -04003898 wsResultBuf.AppendChar(';');
3899 break;
3900 case '>':
3901 wsResultBuf.AppendChar('&');
dsinclaircf7f3222016-06-08 20:34:02 -07003902 wsResultBuf << CFX_WideStringC(L"gt");
Dan Sinclair1770c022016-03-14 14:14:16 -04003903 wsResultBuf.AppendChar(';');
3904 break;
3905 default: {
3906 if (ch >= 32 && ch <= 126) {
3907 wsResultBuf.AppendChar(ch);
3908 } else if (ch < 256) {
dsinclaircf7f3222016-06-08 20:34:02 -07003909 int32_t iIndex = ch / 16;
Dan Sinclair1770c022016-03-14 14:14:16 -04003910 strEncode[3] = strCode[iIndex];
3911 strEncode[4] = strCode[ch - iIndex * 16];
3912 strEncode[5] = ';';
3913 strEncode[6] = 0;
3914 wsResultBuf << FX_WSTRC(strEncode);
3915 } else {
3916 int32_t iBigByte = ch / 256;
3917 int32_t iLittleByte = ch % 256;
3918 strEncode[3] = strCode[iBigByte / 16];
3919 strEncode[4] = strCode[iBigByte % 16];
3920 strEncode[5] = strCode[iLittleByte / 16];
3921 strEncode[6] = strCode[iLittleByte % 16];
3922 wsResultBuf << FX_WSTRC(strEncode);
3923 }
dsinclaircf7f3222016-06-08 20:34:02 -07003924 break;
3925 }
Dan Sinclair1770c022016-03-14 14:14:16 -04003926 }
3927 }
3928 wsResultBuf.AppendChar(0);
3929 szResultBuf.Clear();
dsinclaircf7f3222016-06-08 20:34:02 -07003930
tsepez28f97ff2016-04-04 16:41:35 -07003931 szResultBuf << FX_UTF8Encode(wsResultBuf.GetBuffer(), wsResultBuf.GetLength())
tsepez4c3debb2016-04-08 12:20:38 -07003932 .AsStringC();
Dan Sinclair1770c022016-03-14 14:14:16 -04003933}
dsinclair48d91dd2016-05-31 11:54:01 -07003934
3935// static
Dan Sinclair1770c022016-03-14 14:14:16 -04003936FX_BOOL CXFA_FM2JSContext::HTMLSTR2Code(const CFX_WideStringC& pData,
3937 uint32_t& iCode) {
tsepezb6853cf2016-04-25 11:23:43 -07003938 uint32_t uHash = FX_HashCode_GetW(pData, false);
3939 int32_t iStart = 0;
3940 int32_t iEnd = FX_ArraySize(reservesForDecode) - 1;
Dan Sinclair1770c022016-03-14 14:14:16 -04003941 do {
tsepezb6853cf2016-04-25 11:23:43 -07003942 int32_t iMid = (iStart + iEnd) / 2;
3943 XFA_FMHtmlHashedReserveCode htmlhashedreservecode = reservesForDecode[iMid];
Dan Sinclair1770c022016-03-14 14:14:16 -04003944 if (uHash == htmlhashedreservecode.m_uHash) {
3945 iCode = htmlhashedreservecode.m_uCode;
3946 return TRUE;
tsepezb6853cf2016-04-25 11:23:43 -07003947 }
dsinclaircf7f3222016-06-08 20:34:02 -07003948
3949 if (uHash < htmlhashedreservecode.m_uHash)
Dan Sinclair1770c022016-03-14 14:14:16 -04003950 iEnd = iMid - 1;
dsinclaircf7f3222016-06-08 20:34:02 -07003951 else
Dan Sinclair1770c022016-03-14 14:14:16 -04003952 iStart = iMid + 1;
Dan Sinclair1770c022016-03-14 14:14:16 -04003953 } while (iStart <= iEnd);
3954 return FALSE;
3955}
dsinclair48d91dd2016-05-31 11:54:01 -07003956
3957// static
Dan Sinclair1770c022016-03-14 14:14:16 -04003958FX_BOOL CXFA_FM2JSContext::HTMLCode2STR(uint32_t iCode,
3959 CFX_WideString& wsHTMLReserve) {
dsinclaircf7f3222016-06-08 20:34:02 -07003960 int32_t iStart = 0;
3961 int32_t iEnd = FX_ArraySize(reservesForEncode) - 1;
Dan Sinclair1770c022016-03-14 14:14:16 -04003962 do {
dsinclaircf7f3222016-06-08 20:34:02 -07003963 int32_t iMid = (iStart + iEnd) / 2;
3964 XFA_FMHtmlReserveCode htmlreservecode = reservesForEncode[iMid];
Dan Sinclair1770c022016-03-14 14:14:16 -04003965 if (iCode == htmlreservecode.m_uCode) {
3966 wsHTMLReserve = htmlreservecode.m_htmlReserve;
3967 return TRUE;
Dan Sinclair1770c022016-03-14 14:14:16 -04003968 }
dsinclaircf7f3222016-06-08 20:34:02 -07003969
3970 if (iCode < htmlreservecode.m_uCode)
3971 iEnd = iMid - 1;
3972 else
3973 iStart = iMid + 1;
Dan Sinclair1770c022016-03-14 14:14:16 -04003974 } while (iStart <= iEnd);
3975 return FALSE;
3976}
dsinclair48d91dd2016-05-31 11:54:01 -07003977
3978// static
dsinclair12a6b0c2016-05-26 11:14:08 -07003979void CXFA_FM2JSContext::Format(CFXJSE_Value* pThis,
Dan Sinclair1770c022016-03-14 14:14:16 -04003980 const CFX_ByteStringC& szFuncName,
3981 CFXJSE_Arguments& args) {
dsinclair8f3074b2016-06-02 17:45:25 -07003982 CXFA_FM2JSContext* pContext = ToJSContext(pThis, nullptr);
dsinclaircf7f3222016-06-08 20:34:02 -07003983 if (args.GetLength() < 2) {
dsinclair2235b7b2016-06-02 07:42:25 -07003984 pContext->ThrowException(XFA_IDS_INCORRECT_NUMBER_OF_METHOD, L"Format");
dsinclaircf7f3222016-06-08 20:34:02 -07003985 return;
Dan Sinclair1770c022016-03-14 14:14:16 -04003986 }
dsinclaircf7f3222016-06-08 20:34:02 -07003987
3988 std::unique_ptr<CFXJSE_Value> argOne = GetSimpleValue(pThis, args, 0);
3989 CFX_ByteString szPattern;
3990 ValueToUTF8String(argOne.get(), szPattern);
3991
3992 std::unique_ptr<CFXJSE_Value> argTwo = GetSimpleValue(pThis, args, 1);
3993 CFX_ByteString szValue;
3994 ValueToUTF8String(argTwo.get(), szValue);
3995
3996 CXFA_Document* pDoc = pContext->GetDocument();
3997 CXFA_LocaleMgr* pMgr = pDoc->GetLocalMgr();
3998 CXFA_Node* pThisNode = ToNode(pDoc->GetScriptContext()->GetThisObject());
3999 ASSERT(pThisNode);
4000
4001 CXFA_WidgetData widgetData(pThisNode);
4002 IFX_Locale* pLocale = widgetData.GetLocal();
4003 uint32_t patternType;
4004 CFX_WideString wsPattern = CFX_WideString::FromUTF8(szPattern.AsStringC());
4005 CFX_WideString wsValue = CFX_WideString::FromUTF8(szValue.AsStringC());
4006 if (!PatternStringType(szPattern.AsStringC(), patternType)) {
4007 switch (patternType) {
4008 case XFA_VT_DATETIME: {
4009 FX_STRSIZE iTChar = wsPattern.Find(L'T');
4010 CFX_WideString wsDatePattern(L"date{");
4011 wsDatePattern += wsPattern.Left(iTChar) + L"} ";
4012
4013 CFX_WideString wsTimePattern(L"time{");
4014 wsTimePattern += wsPattern.Mid(iTChar + 1) + L"}";
4015 wsPattern = wsDatePattern + wsTimePattern;
4016 } break;
4017 case XFA_VT_DATE: {
4018 wsPattern = L"date{" + wsPattern + L"}";
4019 } break;
4020 case XFA_VT_TIME: {
4021 wsPattern = L"time{" + wsPattern + L"}";
4022 } break;
4023 case XFA_VT_TEXT: {
4024 wsPattern = L"text{" + wsPattern + L"}";
4025 } break;
4026 case XFA_VT_FLOAT: {
4027 wsPattern = L"num{" + wsPattern + L"}";
4028 } break;
4029 default: {
4030 CFX_WideString wsTestPattern;
4031 wsTestPattern = L"num{" + wsPattern + L"}";
4032 CXFA_LocaleValue tempLocaleValue(XFA_VT_FLOAT, wsValue, wsTestPattern,
4033 pLocale, pMgr);
4034 if (tempLocaleValue.IsValid()) {
4035 wsPattern = wsTestPattern;
4036 patternType = XFA_VT_FLOAT;
4037 } else {
4038 wsTestPattern = L"text{" + wsPattern + L"}";
4039 wsPattern = wsTestPattern;
4040 patternType = XFA_VT_TEXT;
4041 }
4042 } break;
4043 }
4044 }
4045 CXFA_LocaleValue localeValue(patternType, wsValue, wsPattern, pLocale, pMgr);
4046 CFX_WideString wsRet;
4047 if (!localeValue.FormatPatterns(wsRet, wsPattern, pLocale,
4048 XFA_VALUEPICTURE_Display)) {
4049 args.GetReturnValue()->SetString("");
4050 return;
4051 }
4052
4053 args.GetReturnValue()->SetString(
4054 FX_UTF8Encode(wsRet.c_str(), wsRet.GetLength()).AsStringC());
Dan Sinclair1770c022016-03-14 14:14:16 -04004055}
dsinclair48d91dd2016-05-31 11:54:01 -07004056
4057// static
dsinclair12a6b0c2016-05-26 11:14:08 -07004058void CXFA_FM2JSContext::Left(CFXJSE_Value* pThis,
Dan Sinclair1770c022016-03-14 14:14:16 -04004059 const CFX_ByteStringC& szFuncName,
4060 CFXJSE_Arguments& args) {
dsinclaircf7f3222016-06-08 20:34:02 -07004061 if (args.GetLength() != 2) {
dsinclair8f3074b2016-06-02 17:45:25 -07004062 ToJSContext(pThis, nullptr)
4063 ->ThrowException(XFA_IDS_INCORRECT_NUMBER_OF_METHOD, L"Left");
dsinclaircf7f3222016-06-08 20:34:02 -07004064 return;
Dan Sinclair1770c022016-03-14 14:14:16 -04004065 }
dsinclaircf7f3222016-06-08 20:34:02 -07004066
4067 std::unique_ptr<CFXJSE_Value> argOne = GetSimpleValue(pThis, args, 0);
4068 std::unique_ptr<CFXJSE_Value> argTwo = GetSimpleValue(pThis, args, 1);
4069 if ((ValueIsNull(pThis, argOne.get())) ||
4070 (ValueIsNull(pThis, argTwo.get()))) {
4071 args.GetReturnValue()->SetNull();
4072 return;
4073 }
4074
4075 CFX_ByteString sourceString;
4076 ValueToUTF8String(argOne.get(), sourceString);
4077 int32_t count = std::max(0, ValueToInteger(pThis, argTwo.get()));
4078 args.GetReturnValue()->SetString(sourceString.Left(count).AsStringC());
Dan Sinclair1770c022016-03-14 14:14:16 -04004079}
dsinclair48d91dd2016-05-31 11:54:01 -07004080
4081// static
dsinclair12a6b0c2016-05-26 11:14:08 -07004082void CXFA_FM2JSContext::Len(CFXJSE_Value* pThis,
Dan Sinclair1770c022016-03-14 14:14:16 -04004083 const CFX_ByteStringC& szFuncName,
4084 CFXJSE_Arguments& args) {
dsinclaircf7f3222016-06-08 20:34:02 -07004085 if (args.GetLength() != 1) {
dsinclair8f3074b2016-06-02 17:45:25 -07004086 ToJSContext(pThis, nullptr)
4087 ->ThrowException(XFA_IDS_INCORRECT_NUMBER_OF_METHOD, L"Len");
dsinclaircf7f3222016-06-08 20:34:02 -07004088 return;
Dan Sinclair1770c022016-03-14 14:14:16 -04004089 }
dsinclaircf7f3222016-06-08 20:34:02 -07004090
4091 std::unique_ptr<CFXJSE_Value> argOne = GetSimpleValue(pThis, args, 0);
4092 if (ValueIsNull(pThis, argOne.get())) {
4093 args.GetReturnValue()->SetNull();
4094 return;
4095 }
4096
4097 CFX_ByteString sourceString;
4098 ValueToUTF8String(argOne.get(), sourceString);
4099 args.GetReturnValue()->SetInteger(sourceString.GetLength());
Dan Sinclair1770c022016-03-14 14:14:16 -04004100}
dsinclair48d91dd2016-05-31 11:54:01 -07004101
4102// static
dsinclair12a6b0c2016-05-26 11:14:08 -07004103void CXFA_FM2JSContext::Lower(CFXJSE_Value* pThis,
Dan Sinclair1770c022016-03-14 14:14:16 -04004104 const CFX_ByteStringC& szFuncName,
4105 CFXJSE_Arguments& args) {
4106 int32_t argc = args.GetLength();
dsinclaircf7f3222016-06-08 20:34:02 -07004107 if (argc < 1 || argc > 2) {
dsinclair8f3074b2016-06-02 17:45:25 -07004108 ToJSContext(pThis, nullptr)
4109 ->ThrowException(XFA_IDS_INCORRECT_NUMBER_OF_METHOD, L"Lower");
dsinclaircf7f3222016-06-08 20:34:02 -07004110 return;
Dan Sinclair1770c022016-03-14 14:14:16 -04004111 }
dsinclaircf7f3222016-06-08 20:34:02 -07004112
4113 CFX_ByteString argString;
4114 std::unique_ptr<CFXJSE_Value> argOne = GetSimpleValue(pThis, args, 0);
4115 if (ValueIsNull(pThis, argOne.get())) {
4116 args.GetReturnValue()->SetNull();
4117 return;
4118 }
4119
4120 ValueToUTF8String(argOne.get(), argString);
4121 CFX_WideTextBuf lowStringBuf;
4122 CFX_WideString wsArgString = CFX_WideString::FromUTF8(argString.AsStringC());
4123 const FX_WCHAR* pData = wsArgString.c_str();
4124 int32_t i = 0;
4125 while (i < argString.GetLength()) {
4126 int32_t ch = pData[i];
4127 if ((ch >= 0x41 && ch <= 0x5A) || (ch >= 0xC0 && ch <= 0xDE))
4128 ch += 32;
4129 else if (ch == 0x100 || ch == 0x102 || ch == 0x104)
4130 ch += 1;
4131
4132 lowStringBuf.AppendChar(ch);
4133 ++i;
4134 }
4135 lowStringBuf.AppendChar(0);
4136
4137 args.GetReturnValue()->SetString(
4138 FX_UTF8Encode(lowStringBuf.GetBuffer(), lowStringBuf.GetLength())
4139 .AsStringC());
Dan Sinclair1770c022016-03-14 14:14:16 -04004140}
dsinclair48d91dd2016-05-31 11:54:01 -07004141
4142// static
dsinclair12a6b0c2016-05-26 11:14:08 -07004143void CXFA_FM2JSContext::Ltrim(CFXJSE_Value* pThis,
Dan Sinclair1770c022016-03-14 14:14:16 -04004144 const CFX_ByteStringC& szFuncName,
4145 CFXJSE_Arguments& args) {
dsinclaircf7f3222016-06-08 20:34:02 -07004146 if (args.GetLength() != 1) {
dsinclair8f3074b2016-06-02 17:45:25 -07004147 ToJSContext(pThis, nullptr)
4148 ->ThrowException(XFA_IDS_INCORRECT_NUMBER_OF_METHOD, L"Ltrim");
dsinclaircf7f3222016-06-08 20:34:02 -07004149 return;
Dan Sinclair1770c022016-03-14 14:14:16 -04004150 }
dsinclaircf7f3222016-06-08 20:34:02 -07004151
4152 std::unique_ptr<CFXJSE_Value> argOne = GetSimpleValue(pThis, args, 0);
4153 if (ValueIsNull(pThis, argOne.get())) {
4154 args.GetReturnValue()->SetNull();
4155 return;
4156 }
4157
4158 CFX_ByteString sourceString;
4159 ValueToUTF8String(argOne.get(), sourceString);
4160 sourceString.TrimLeft();
4161 args.GetReturnValue()->SetString(sourceString.AsStringC());
Dan Sinclair1770c022016-03-14 14:14:16 -04004162}
dsinclair48d91dd2016-05-31 11:54:01 -07004163
4164// static
dsinclair12a6b0c2016-05-26 11:14:08 -07004165void CXFA_FM2JSContext::Parse(CFXJSE_Value* pThis,
Dan Sinclair1770c022016-03-14 14:14:16 -04004166 const CFX_ByteStringC& szFuncName,
4167 CFXJSE_Arguments& args) {
dsinclair8f3074b2016-06-02 17:45:25 -07004168 CXFA_FM2JSContext* pContext = ToJSContext(pThis, nullptr);
dsinclaircf7f3222016-06-08 20:34:02 -07004169 if (args.GetLength() != 2) {
dsinclair2235b7b2016-06-02 07:42:25 -07004170 pContext->ThrowException(XFA_IDS_INCORRECT_NUMBER_OF_METHOD, L"Parse");
dsinclaircf7f3222016-06-08 20:34:02 -07004171 return;
4172 }
4173
4174 std::unique_ptr<CFXJSE_Value> argOne = GetSimpleValue(pThis, args, 0);
4175 std::unique_ptr<CFXJSE_Value> argTwo = GetSimpleValue(pThis, args, 1);
4176 if (ValueIsNull(pThis, argTwo.get())) {
4177 args.GetReturnValue()->SetNull();
4178 return;
4179 }
4180
4181 CFX_ByteString szPattern;
4182 ValueToUTF8String(argOne.get(), szPattern);
4183 CFX_ByteString szValue;
4184 ValueToUTF8String(argTwo.get(), szValue);
4185
4186 CXFA_Document* pDoc = pContext->GetDocument();
4187 CXFA_LocaleMgr* pMgr = pDoc->GetLocalMgr();
4188 CXFA_Node* pThisNode = ToNode(pDoc->GetScriptContext()->GetThisObject());
4189 ASSERT(pThisNode);
4190
4191 CXFA_WidgetData widgetData(pThisNode);
4192 IFX_Locale* pLocale = widgetData.GetLocal();
4193 CFX_WideString wsPattern = CFX_WideString::FromUTF8(szPattern.AsStringC());
4194 CFX_WideString wsValue = CFX_WideString::FromUTF8(szValue.AsStringC());
4195 uint32_t patternType;
4196 if (PatternStringType(szPattern.AsStringC(), patternType)) {
4197 CXFA_LocaleValue localeValue(patternType, wsValue, wsPattern, pLocale,
4198 pMgr);
4199 if (!localeValue.IsValid()) {
4200 args.GetReturnValue()->SetString("");
4201 return;
4202 }
4203 args.GetReturnValue()->SetString(
4204 FX_UTF8Encode(localeValue.GetValue()).AsStringC());
4205 return;
4206 }
4207
4208 switch (patternType) {
4209 case XFA_VT_DATETIME: {
4210 FX_STRSIZE iTChar = wsPattern.Find(L'T');
4211 CFX_WideString wsDatePattern(L"date{" + wsPattern.Left(iTChar) + L"} ");
4212 CFX_WideString wsTimePattern(L"time{" + wsPattern.Mid(iTChar + 1) + L"}");
4213 wsPattern = wsDatePattern + wsTimePattern;
4214 CXFA_LocaleValue localeValue(patternType, wsValue, wsPattern, pLocale,
4215 pMgr);
4216 if (!localeValue.IsValid()) {
4217 args.GetReturnValue()->SetString("");
4218 return;
4219 }
4220 args.GetReturnValue()->SetString(
4221 FX_UTF8Encode(localeValue.GetValue()).AsStringC());
4222 return;
4223 }
4224 case XFA_VT_DATE: {
4225 wsPattern = L"date{" + wsPattern + L"}";
4226 CXFA_LocaleValue localeValue(patternType, wsValue, wsPattern, pLocale,
4227 pMgr);
4228 if (!localeValue.IsValid()) {
4229 args.GetReturnValue()->SetString("");
4230 return;
4231 }
4232 args.GetReturnValue()->SetString(
4233 FX_UTF8Encode(localeValue.GetValue()).AsStringC());
4234 return;
4235 }
4236 case XFA_VT_TIME: {
4237 wsPattern = L"time{" + wsPattern + L"}";
4238 CXFA_LocaleValue localeValue(patternType, wsValue, wsPattern, pLocale,
4239 pMgr);
4240 if (!localeValue.IsValid()) {
4241 args.GetReturnValue()->SetString("");
4242 return;
4243 }
4244 args.GetReturnValue()->SetString(
4245 FX_UTF8Encode(localeValue.GetValue()).AsStringC());
4246 return;
4247 }
4248 case XFA_VT_TEXT: {
4249 wsPattern = L"text{" + wsPattern + L"}";
4250 CXFA_LocaleValue localeValue(XFA_VT_TEXT, wsValue, wsPattern, pLocale,
4251 pMgr);
4252 if (!localeValue.IsValid()) {
4253 args.GetReturnValue()->SetString("");
4254 return;
4255 }
4256 args.GetReturnValue()->SetString(
4257 FX_UTF8Encode(localeValue.GetValue()).AsStringC());
4258 return;
4259 }
4260 case XFA_VT_FLOAT: {
4261 wsPattern = L"num{" + wsPattern + L"}";
4262 CXFA_LocaleValue localeValue(XFA_VT_FLOAT, wsValue, wsPattern, pLocale,
4263 pMgr);
4264 if (!localeValue.IsValid()) {
4265 args.GetReturnValue()->SetString("");
4266 return;
4267 }
4268 args.GetReturnValue()->SetDouble(localeValue.GetDoubleNum());
4269 return;
4270 }
4271 default: {
4272 CFX_WideString wsTestPattern;
4273 wsTestPattern = L"num{" + wsPattern + L"}";
4274 CXFA_LocaleValue localeValue(XFA_VT_FLOAT, wsValue, wsTestPattern,
4275 pLocale, pMgr);
4276 if (localeValue.IsValid()) {
4277 args.GetReturnValue()->SetDouble(localeValue.GetDoubleNum());
4278 return;
4279 }
4280
4281 wsTestPattern = L"text{" + wsPattern + L"}";
4282 CXFA_LocaleValue localeValue2(XFA_VT_TEXT, wsValue, wsTestPattern,
4283 pLocale, pMgr);
4284 if (!localeValue2.IsValid()) {
4285 args.GetReturnValue()->SetString("");
4286 return;
4287 }
4288 args.GetReturnValue()->SetString(
4289 FX_UTF8Encode(localeValue2.GetValue()).AsStringC());
4290 return;
4291 }
Dan Sinclair1770c022016-03-14 14:14:16 -04004292 }
4293}
dsinclair48d91dd2016-05-31 11:54:01 -07004294
4295// static
dsinclair12a6b0c2016-05-26 11:14:08 -07004296void CXFA_FM2JSContext::Replace(CFXJSE_Value* pThis,
Dan Sinclair1770c022016-03-14 14:14:16 -04004297 const CFX_ByteStringC& szFuncName,
4298 CFXJSE_Arguments& args) {
4299 int32_t argc = args.GetLength();
dsinclaircf7f3222016-06-08 20:34:02 -07004300 if (argc < 2 || argc > 3) {
dsinclair8f3074b2016-06-02 17:45:25 -07004301 ToJSContext(pThis, nullptr)
4302 ->ThrowException(XFA_IDS_INCORRECT_NUMBER_OF_METHOD, L"Replace");
dsinclaircf7f3222016-06-08 20:34:02 -07004303 return;
Dan Sinclair1770c022016-03-14 14:14:16 -04004304 }
dsinclaircf7f3222016-06-08 20:34:02 -07004305
4306 std::unique_ptr<CFXJSE_Value> argOne = GetSimpleValue(pThis, args, 0);
4307 std::unique_ptr<CFXJSE_Value> argTwo = GetSimpleValue(pThis, args, 1);
4308 CFX_ByteString oneString;
4309 CFX_ByteString twoString;
4310 if (!ValueIsNull(pThis, argOne.get()) && !ValueIsNull(pThis, argTwo.get())) {
4311 ValueToUTF8String(argOne.get(), oneString);
4312 ValueToUTF8String(argTwo.get(), twoString);
4313 }
4314
4315 CFX_ByteString threeString;
4316 if (argc > 2) {
4317 std::unique_ptr<CFXJSE_Value> argThree = GetSimpleValue(pThis, args, 2);
4318 ValueToUTF8String(argThree.get(), threeString);
4319 }
4320
4321 int32_t iFindLen = twoString.GetLength();
4322 CFX_ByteTextBuf resultString;
4323 int32_t iFindIndex = 0;
4324 for (int32_t u = 0; u < oneString.GetLength(); ++u) {
4325 uint8_t ch = oneString.GetAt(u);
4326 if (ch != twoString.GetAt(iFindIndex)) {
4327 resultString.AppendChar(ch);
4328 continue;
4329 }
4330
4331 int32_t iTemp = u + 1;
4332 ++iFindIndex;
4333 while (iFindIndex < iFindLen) {
4334 uint8_t chTemp = oneString.GetAt(iTemp);
4335 if (chTemp != twoString.GetAt(iFindIndex)) {
4336 iFindIndex = 0;
4337 break;
4338 }
4339
4340 ++iTemp;
4341 ++iFindIndex;
4342 }
4343 if (iFindIndex == iFindLen) {
4344 resultString << threeString.AsStringC();
4345 u += iFindLen - 1;
4346 iFindIndex = 0;
4347 } else {
4348 resultString.AppendChar(ch);
4349 }
4350 }
4351 resultString.AppendChar(0);
4352 args.GetReturnValue()->SetString(resultString.AsStringC());
Dan Sinclair1770c022016-03-14 14:14:16 -04004353}
dsinclair48d91dd2016-05-31 11:54:01 -07004354
4355// static
dsinclair12a6b0c2016-05-26 11:14:08 -07004356void CXFA_FM2JSContext::Right(CFXJSE_Value* pThis,
Dan Sinclair1770c022016-03-14 14:14:16 -04004357 const CFX_ByteStringC& szFuncName,
4358 CFXJSE_Arguments& args) {
dsinclaircf7f3222016-06-08 20:34:02 -07004359 if (args.GetLength() != 2) {
dsinclair8f3074b2016-06-02 17:45:25 -07004360 ToJSContext(pThis, nullptr)
4361 ->ThrowException(XFA_IDS_INCORRECT_NUMBER_OF_METHOD, L"Right");
dsinclaircf7f3222016-06-08 20:34:02 -07004362 return;
Dan Sinclair1770c022016-03-14 14:14:16 -04004363 }
dsinclaircf7f3222016-06-08 20:34:02 -07004364
4365 std::unique_ptr<CFXJSE_Value> argOne = GetSimpleValue(pThis, args, 0);
4366 std::unique_ptr<CFXJSE_Value> argTwo = GetSimpleValue(pThis, args, 1);
4367 if ((ValueIsNull(pThis, argOne.get())) ||
4368 (ValueIsNull(pThis, argTwo.get()))) {
4369 args.GetReturnValue()->SetNull();
4370 return;
4371 }
4372
4373 CFX_ByteString sourceString;
4374 ValueToUTF8String(argOne.get(), sourceString);
4375 int32_t count = std::max(0, ValueToInteger(pThis, argTwo.get()));
4376 args.GetReturnValue()->SetString(sourceString.Right(count).AsStringC());
Dan Sinclair1770c022016-03-14 14:14:16 -04004377}
dsinclair48d91dd2016-05-31 11:54:01 -07004378
4379// static
dsinclair12a6b0c2016-05-26 11:14:08 -07004380void CXFA_FM2JSContext::Rtrim(CFXJSE_Value* pThis,
Dan Sinclair1770c022016-03-14 14:14:16 -04004381 const CFX_ByteStringC& szFuncName,
4382 CFXJSE_Arguments& args) {
dsinclaircf7f3222016-06-08 20:34:02 -07004383 if (args.GetLength() != 1) {
dsinclair8f3074b2016-06-02 17:45:25 -07004384 ToJSContext(pThis, nullptr)
4385 ->ThrowException(XFA_IDS_INCORRECT_NUMBER_OF_METHOD, L"Rtrim");
dsinclaircf7f3222016-06-08 20:34:02 -07004386 return;
Dan Sinclair1770c022016-03-14 14:14:16 -04004387 }
dsinclaircf7f3222016-06-08 20:34:02 -07004388
4389 std::unique_ptr<CFXJSE_Value> argOne = GetSimpleValue(pThis, args, 0);
4390 if (ValueIsNull(pThis, argOne.get())) {
4391 args.GetReturnValue()->SetNull();
4392 return;
4393 }
4394
4395 CFX_ByteString sourceString;
4396 ValueToUTF8String(argOne.get(), sourceString);
4397 sourceString.TrimRight();
4398 args.GetReturnValue()->SetString(sourceString.AsStringC());
Dan Sinclair1770c022016-03-14 14:14:16 -04004399}
dsinclair48d91dd2016-05-31 11:54:01 -07004400
4401// static
dsinclair12a6b0c2016-05-26 11:14:08 -07004402void CXFA_FM2JSContext::Space(CFXJSE_Value* pThis,
Dan Sinclair1770c022016-03-14 14:14:16 -04004403 const CFX_ByteStringC& szFuncName,
4404 CFXJSE_Arguments& args) {
dsinclaircf7f3222016-06-08 20:34:02 -07004405 if (args.GetLength() != 1) {
dsinclair8f3074b2016-06-02 17:45:25 -07004406 ToJSContext(pThis, nullptr)
4407 ->ThrowException(XFA_IDS_INCORRECT_NUMBER_OF_METHOD, L"Space");
dsinclaircf7f3222016-06-08 20:34:02 -07004408 return;
Dan Sinclair1770c022016-03-14 14:14:16 -04004409 }
dsinclaircf7f3222016-06-08 20:34:02 -07004410
4411 std::unique_ptr<CFXJSE_Value> argOne = GetSimpleValue(pThis, args, 0);
4412 if (argOne->IsNull()) {
4413 args.GetReturnValue()->SetNull();
4414 return;
4415 }
4416
4417 int32_t count = std::max(0, ValueToInteger(pThis, argOne.get()));
4418 CFX_ByteTextBuf spaceString;
4419 int32_t index = 0;
4420 while (index < count) {
4421 spaceString.AppendByte(' ');
4422 index++;
4423 }
4424 spaceString.AppendByte(0);
4425 args.GetReturnValue()->SetString(spaceString.AsStringC());
Dan Sinclair1770c022016-03-14 14:14:16 -04004426}
dsinclair48d91dd2016-05-31 11:54:01 -07004427
4428// static
dsinclair12a6b0c2016-05-26 11:14:08 -07004429void CXFA_FM2JSContext::Str(CFXJSE_Value* pThis,
Dan Sinclair1770c022016-03-14 14:14:16 -04004430 const CFX_ByteStringC& szFuncName,
4431 CFXJSE_Arguments& args) {
4432 int32_t argc = args.GetLength();
dsinclaircf7f3222016-06-08 20:34:02 -07004433 if (argc < 1 || argc > 3) {
dsinclair8f3074b2016-06-02 17:45:25 -07004434 ToJSContext(pThis, nullptr)
4435 ->ThrowException(XFA_IDS_INCORRECT_NUMBER_OF_METHOD, L"Str");
dsinclaircf7f3222016-06-08 20:34:02 -07004436 return;
Dan Sinclair1770c022016-03-14 14:14:16 -04004437 }
dsinclaircf7f3222016-06-08 20:34:02 -07004438
4439 std::unique_ptr<CFXJSE_Value> numberValue = GetSimpleValue(pThis, args, 0);
4440 if (numberValue->IsNull()) {
4441 args.GetReturnValue()->SetNull();
4442 return;
4443 }
4444 FX_FLOAT fNumber = ValueToFloat(pThis, numberValue.get());
4445
4446 int32_t iWidth = 10;
4447 if (argc > 1) {
4448 std::unique_ptr<CFXJSE_Value> widthValue = GetSimpleValue(pThis, args, 1);
4449 iWidth = static_cast<int32_t>(ValueToFloat(pThis, widthValue.get()));
4450 }
4451
4452 int32_t iPrecision = 0;
4453 if (argc > 2) {
4454 std::unique_ptr<CFXJSE_Value> precisionValue =
4455 GetSimpleValue(pThis, args, 2);
4456 iPrecision = std::max(
4457 0, static_cast<int32_t>(ValueToFloat(pThis, precisionValue.get())));
4458 }
4459
4460 CFX_ByteString numberString;
4461 CFX_ByteString formatStr = "%";
4462 if (iPrecision) {
4463 formatStr += ".";
4464 formatStr += CFX_ByteString::FormatInteger(iPrecision);
4465 }
4466 formatStr += "f";
4467 numberString.Format(formatStr.c_str(), fNumber);
4468
4469 const FX_CHAR* pData = numberString.c_str();
4470 int32_t iLength = numberString.GetLength();
4471 int32_t u = 0;
4472 while (u < iLength) {
4473 if (pData[u] == '.')
4474 break;
4475
4476 ++u;
4477 }
4478
4479 CFX_ByteTextBuf resultBuf;
4480 if (u > iWidth || (iPrecision + u) >= iWidth) {
4481 int32_t i = 0;
4482 while (i < iWidth) {
4483 resultBuf.AppendChar('*');
4484 ++i;
4485 }
4486 resultBuf.AppendChar(0);
4487 args.GetReturnValue()->SetString(resultBuf.AsStringC());
4488 return;
4489 }
4490
4491 if (u == iLength) {
4492 if (iLength > iWidth) {
4493 int32_t i = 0;
4494 while (i < iWidth) {
4495 resultBuf.AppendChar('*');
4496 ++i;
4497 }
4498 } else {
4499 int32_t i = 0;
4500 while (i < iWidth - iLength) {
4501 resultBuf.AppendChar(' ');
4502 ++i;
4503 }
4504 resultBuf << pData;
4505 }
4506 args.GetReturnValue()->SetString(resultBuf.AsStringC());
4507 return;
4508 }
4509
4510 int32_t iLeavingSpace = iWidth - u - iPrecision;
4511 if (iPrecision != 0)
4512 iLeavingSpace--;
4513
4514 int32_t i = 0;
4515 while (i < iLeavingSpace) {
4516 resultBuf.AppendChar(' ');
4517 ++i;
4518 }
4519 i = 0;
4520 while (i < u) {
4521 resultBuf.AppendChar(pData[i]);
4522 ++i;
4523 }
4524 if (iPrecision != 0)
4525 resultBuf.AppendChar('.');
4526
4527 u++;
4528 i = 0;
4529 while (u < iLength) {
4530 if (i >= iPrecision)
4531 break;
4532
4533 resultBuf.AppendChar(pData[u]);
4534 ++i;
4535 ++u;
4536 }
4537 while (i < iPrecision) {
4538 resultBuf.AppendChar('0');
4539 ++i;
4540 }
4541 resultBuf.AppendChar(0);
4542 args.GetReturnValue()->SetString(resultBuf.AsStringC());
Dan Sinclair1770c022016-03-14 14:14:16 -04004543}
dsinclair48d91dd2016-05-31 11:54:01 -07004544
4545// static
dsinclair12a6b0c2016-05-26 11:14:08 -07004546void CXFA_FM2JSContext::Stuff(CFXJSE_Value* pThis,
Dan Sinclair1770c022016-03-14 14:14:16 -04004547 const CFX_ByteStringC& szFuncName,
4548 CFXJSE_Arguments& args) {
4549 int32_t argc = args.GetLength();
dsinclaircf7f3222016-06-08 20:34:02 -07004550 if (argc < 3 || argc > 4) {
dsinclair8f3074b2016-06-02 17:45:25 -07004551 ToJSContext(pThis, nullptr)
4552 ->ThrowException(XFA_IDS_INCORRECT_NUMBER_OF_METHOD, L"Stuff");
dsinclaircf7f3222016-06-08 20:34:02 -07004553 return;
Dan Sinclair1770c022016-03-14 14:14:16 -04004554 }
dsinclaircf7f3222016-06-08 20:34:02 -07004555
4556 CFX_ByteString sourceString;
4557 CFX_ByteString insertString;
4558 int32_t iLength = 0;
4559 int32_t iStart = 0;
4560 int32_t iDelete = 0;
4561 std::unique_ptr<CFXJSE_Value> sourceValue = GetSimpleValue(pThis, args, 0);
4562 std::unique_ptr<CFXJSE_Value> startValue = GetSimpleValue(pThis, args, 1);
4563 std::unique_ptr<CFXJSE_Value> deleteValue = GetSimpleValue(pThis, args, 2);
4564 if (!sourceValue->IsNull() && !startValue->IsNull() &&
4565 !deleteValue->IsNull()) {
4566 ValueToUTF8String(sourceValue.get(), sourceString);
4567 iLength = sourceString.GetLength();
4568 iStart = std::min(iLength, std::max(1, static_cast<int32_t>(ValueToFloat(
4569 pThis, startValue.get()))));
4570 iDelete = std::max(
4571 0, static_cast<int32_t>(ValueToFloat(pThis, deleteValue.get())));
4572 }
4573
4574 if (argc > 3) {
4575 std::unique_ptr<CFXJSE_Value> insertValue = GetSimpleValue(pThis, args, 3);
4576 ValueToUTF8String(insertValue.get(), insertString);
4577 }
4578
4579 iStart -= 1;
4580 CFX_ByteTextBuf resultString;
4581 int32_t i = 0;
4582 while (i < iStart) {
4583 resultString.AppendChar(sourceString.GetAt(i));
4584 ++i;
4585 }
4586 resultString << insertString.AsStringC();
4587 i = iStart + iDelete;
4588 while (i < iLength) {
4589 resultString.AppendChar(sourceString.GetAt(i));
4590 ++i;
4591 }
4592 resultString.AppendChar(0);
4593 args.GetReturnValue()->SetString(resultString.AsStringC());
Dan Sinclair1770c022016-03-14 14:14:16 -04004594}
dsinclair48d91dd2016-05-31 11:54:01 -07004595
4596// static
dsinclair12a6b0c2016-05-26 11:14:08 -07004597void CXFA_FM2JSContext::Substr(CFXJSE_Value* pThis,
Dan Sinclair1770c022016-03-14 14:14:16 -04004598 const CFX_ByteStringC& szFuncName,
4599 CFXJSE_Arguments& args) {
dsinclaircf7f3222016-06-08 20:34:02 -07004600 if (args.GetLength() != 3) {
dsinclair8f3074b2016-06-02 17:45:25 -07004601 ToJSContext(pThis, nullptr)
4602 ->ThrowException(XFA_IDS_INCORRECT_NUMBER_OF_METHOD, L"Substr");
dsinclaircf7f3222016-06-08 20:34:02 -07004603 return;
Dan Sinclair1770c022016-03-14 14:14:16 -04004604 }
dsinclaircf7f3222016-06-08 20:34:02 -07004605
4606 std::unique_ptr<CFXJSE_Value> stringValue = GetSimpleValue(pThis, args, 0);
4607 std::unique_ptr<CFXJSE_Value> startValue = GetSimpleValue(pThis, args, 1);
4608 std::unique_ptr<CFXJSE_Value> endValue = GetSimpleValue(pThis, args, 2);
4609 if (ValueIsNull(pThis, stringValue.get()) ||
4610 (ValueIsNull(pThis, startValue.get())) ||
4611 (ValueIsNull(pThis, endValue.get()))) {
4612 args.GetReturnValue()->SetNull();
4613 return;
4614 }
4615
4616 CFX_ByteString szSourceStr;
4617 int32_t iStart = 0;
4618 int32_t iCount = 0;
4619 ValueToUTF8String(stringValue.get(), szSourceStr);
4620 int32_t iLength = szSourceStr.GetLength();
4621 if (iLength == 0) {
4622 args.GetReturnValue()->SetString("");
4623 return;
4624 }
4625
4626 iStart = std::min(
4627 iLength,
4628 std::max(1, static_cast<int32_t>(ValueToFloat(pThis, startValue.get()))));
4629 iCount =
4630 std::max(0, static_cast<int32_t>(ValueToFloat(pThis, endValue.get())));
4631
4632 iStart -= 1;
4633 args.GetReturnValue()->SetString(szSourceStr.Mid(iStart, iCount).AsStringC());
Dan Sinclair1770c022016-03-14 14:14:16 -04004634}
dsinclair48d91dd2016-05-31 11:54:01 -07004635
4636// static
dsinclair12a6b0c2016-05-26 11:14:08 -07004637void CXFA_FM2JSContext::Uuid(CFXJSE_Value* pThis,
Dan Sinclair1770c022016-03-14 14:14:16 -04004638 const CFX_ByteStringC& szFuncName,
4639 CFXJSE_Arguments& args) {
4640 int32_t argc = args.GetLength();
dsinclaircf7f3222016-06-08 20:34:02 -07004641 if (argc < 0 || argc > 1) {
dsinclair8f3074b2016-06-02 17:45:25 -07004642 ToJSContext(pThis, nullptr)
4643 ->ThrowException(XFA_IDS_INCORRECT_NUMBER_OF_METHOD, L"Uuid");
dsinclaircf7f3222016-06-08 20:34:02 -07004644 return;
Dan Sinclair1770c022016-03-14 14:14:16 -04004645 }
dsinclaircf7f3222016-06-08 20:34:02 -07004646
4647 int32_t iNum = 0;
4648 if (argc > 0) {
4649 std::unique_ptr<CFXJSE_Value> argOne = GetSimpleValue(pThis, args, 0);
4650 iNum = static_cast<int32_t>(ValueToFloat(pThis, argOne.get()));
4651 }
4652 FX_GUID guid;
4653 FX_GUID_CreateV4(&guid);
4654
4655 CFX_ByteString bsUId;
tsepez478ed622016-10-27 14:32:33 -07004656 FX_GUID_ToString(&guid, bsUId, !!iNum);
dsinclaircf7f3222016-06-08 20:34:02 -07004657 args.GetReturnValue()->SetString(bsUId.AsStringC());
Dan Sinclair1770c022016-03-14 14:14:16 -04004658}
dsinclair48d91dd2016-05-31 11:54:01 -07004659
4660// static
dsinclair12a6b0c2016-05-26 11:14:08 -07004661void CXFA_FM2JSContext::Upper(CFXJSE_Value* pThis,
Dan Sinclair1770c022016-03-14 14:14:16 -04004662 const CFX_ByteStringC& szFuncName,
4663 CFXJSE_Arguments& args) {
4664 int32_t argc = args.GetLength();
dsinclaircf7f3222016-06-08 20:34:02 -07004665 if (argc < 1 || argc > 2) {
dsinclair8f3074b2016-06-02 17:45:25 -07004666 ToJSContext(pThis, nullptr)
4667 ->ThrowException(XFA_IDS_INCORRECT_NUMBER_OF_METHOD, L"Upper");
dsinclaircf7f3222016-06-08 20:34:02 -07004668 return;
Dan Sinclair1770c022016-03-14 14:14:16 -04004669 }
dsinclaircf7f3222016-06-08 20:34:02 -07004670
4671 std::unique_ptr<CFXJSE_Value> argOne = GetSimpleValue(pThis, args, 0);
4672 if (ValueIsNull(pThis, argOne.get())) {
4673 args.GetReturnValue()->SetNull();
4674 return;
4675 }
4676
4677 CFX_ByteString argString;
4678 ValueToUTF8String(argOne.get(), argString);
4679
4680 CFX_WideTextBuf upperStringBuf;
4681 CFX_WideString wsArgString = CFX_WideString::FromUTF8(argString.AsStringC());
4682 const FX_WCHAR* pData = wsArgString.c_str();
4683 int32_t i = 0;
4684 while (i < wsArgString.GetLength()) {
4685 int32_t ch = pData[i];
4686 if ((ch >= 0x61 && ch <= 0x7A) || (ch >= 0xE0 && ch <= 0xFE))
4687 ch -= 32;
4688 else if (ch == 0x101 || ch == 0x103 || ch == 0x105)
4689 ch -= 1;
4690
4691 upperStringBuf.AppendChar(ch);
4692 ++i;
4693 }
4694 upperStringBuf.AppendChar(0);
4695
4696 args.GetReturnValue()->SetString(
4697 FX_UTF8Encode(upperStringBuf.GetBuffer(), upperStringBuf.GetLength())
4698 .AsStringC());
Dan Sinclair1770c022016-03-14 14:14:16 -04004699}
dsinclair48d91dd2016-05-31 11:54:01 -07004700
4701// static
dsinclair12a6b0c2016-05-26 11:14:08 -07004702void CXFA_FM2JSContext::WordNum(CFXJSE_Value* pThis,
Dan Sinclair1770c022016-03-14 14:14:16 -04004703 const CFX_ByteStringC& szFuncName,
4704 CFXJSE_Arguments& args) {
4705 int32_t argc = args.GetLength();
dsinclaircf7f3222016-06-08 20:34:02 -07004706 if (argc < 1 || argc > 3) {
dsinclair8f3074b2016-06-02 17:45:25 -07004707 ToJSContext(pThis, nullptr)
4708 ->ThrowException(XFA_IDS_INCORRECT_NUMBER_OF_METHOD, L"WordNum");
dsinclaircf7f3222016-06-08 20:34:02 -07004709 return;
Dan Sinclair1770c022016-03-14 14:14:16 -04004710 }
dsinclaircf7f3222016-06-08 20:34:02 -07004711
4712 std::unique_ptr<CFXJSE_Value> numberValue = GetSimpleValue(pThis, args, 0);
4713 if (numberValue->IsNull()) {
4714 args.GetReturnValue()->SetNull();
4715 return;
4716 }
4717 FX_FLOAT fNumber = ValueToFloat(pThis, numberValue.get());
4718
4719 int32_t iIdentifier = 0;
4720 if (argc > 1) {
4721 std::unique_ptr<CFXJSE_Value> identifierValue =
4722 GetSimpleValue(pThis, args, 1);
4723 if (identifierValue->IsNull()) {
4724 args.GetReturnValue()->SetNull();
4725 return;
4726 }
4727 iIdentifier =
4728 static_cast<int32_t>(ValueToFloat(pThis, identifierValue.get()));
4729 }
4730
4731 CFX_ByteString localeString;
4732 if (argc > 2) {
4733 std::unique_ptr<CFXJSE_Value> localeValue = GetSimpleValue(pThis, args, 2);
4734 if (localeValue->IsNull()) {
4735 args.GetReturnValue()->SetNull();
4736 return;
4737 }
4738 ValueToUTF8String(localeValue.get(), localeString);
4739 }
4740
4741 if (fNumber < 0.0f || fNumber > 922337203685477550.0f) {
4742 args.GetReturnValue()->SetString("*");
4743 return;
4744 }
4745
4746 CFX_ByteString numberString;
4747 numberString.Format("%.2f", fNumber);
4748
4749 CFX_ByteTextBuf resultBuf;
4750 WordUS(numberString.AsStringC(), iIdentifier, resultBuf);
4751 args.GetReturnValue()->SetString(resultBuf.AsStringC());
Dan Sinclair1770c022016-03-14 14:14:16 -04004752}
dsinclair48d91dd2016-05-31 11:54:01 -07004753
4754// static
Dan Sinclair1770c022016-03-14 14:14:16 -04004755void CXFA_FM2JSContext::TrillionUS(const CFX_ByteStringC& szData,
4756 CFX_ByteTextBuf& strBuf) {
4757 CFX_ByteStringC pUnits[] = {"zero", "one", "two", "three", "four",
4758 "five", "six", "seven", "eight", "nine"};
4759 CFX_ByteStringC pCapUnits[] = {"Zero", "One", "Two", "Three", "Four",
4760 "Five", "Six", "Seven", "Eight", "Nine"};
4761 CFX_ByteStringC pTens[] = {"Ten", "Eleven", "Twelve", "Thirteen",
4762 "Fourteen", "Fifteen", "Sixteen", "Seventeen",
4763 "Eighteen", "Nineteen"};
4764 CFX_ByteStringC pLastTens[] = {"Twenty", "Thirty", "Forty", "Fifty",
4765 "Sixty", "Seventy", "Eighty", "Ninety"};
4766 CFX_ByteStringC pComm[] = {" Hundred ", " Thousand ", " Million ",
4767 " Billion ", "Trillion"};
dsinclair179bebb2016-04-05 11:02:18 -07004768 const FX_CHAR* pData = szData.c_str();
Dan Sinclair1770c022016-03-14 14:14:16 -04004769 int32_t iLength = szData.GetLength();
dsinclair947c8732016-06-08 20:40:30 -07004770 int32_t iComm = 0;
4771 if (iLength > 12)
Dan Sinclair1770c022016-03-14 14:14:16 -04004772 iComm = 4;
dsinclair947c8732016-06-08 20:40:30 -07004773 else if (iLength > 9)
Dan Sinclair1770c022016-03-14 14:14:16 -04004774 iComm = 3;
dsinclair947c8732016-06-08 20:40:30 -07004775 else if (iLength > 6)
Dan Sinclair1770c022016-03-14 14:14:16 -04004776 iComm = 2;
dsinclair947c8732016-06-08 20:40:30 -07004777 else if (iLength > 3)
Dan Sinclair1770c022016-03-14 14:14:16 -04004778 iComm = 1;
dsinclair947c8732016-06-08 20:40:30 -07004779
Dan Sinclair1770c022016-03-14 14:14:16 -04004780 int32_t iFirstCount = iLength % 3;
dsinclair947c8732016-06-08 20:40:30 -07004781 if (iFirstCount == 0)
Dan Sinclair1770c022016-03-14 14:14:16 -04004782 iFirstCount = 3;
dsinclair947c8732016-06-08 20:40:30 -07004783
4784 int32_t iIndex = 0;
Dan Sinclair1770c022016-03-14 14:14:16 -04004785 if (iFirstCount == 3) {
dsinclair2b6d64e2016-06-06 11:39:42 -07004786 if (pData[iIndex] != '0') {
4787 strBuf << pCapUnits[pData[iIndex] - '0'];
Dan Sinclair1770c022016-03-14 14:14:16 -04004788 strBuf << pComm[0];
4789 }
dsinclair2b6d64e2016-06-06 11:39:42 -07004790 if (pData[iIndex + 1] == '0') {
4791 strBuf << pCapUnits[pData[iIndex + 2] - '0'];
Dan Sinclair1770c022016-03-14 14:14:16 -04004792 } else {
dsinclair2b6d64e2016-06-06 11:39:42 -07004793 if (pData[iIndex + 1] > '1') {
4794 strBuf << pLastTens[pData[iIndex + 1] - '2'];
Dan Sinclair1770c022016-03-14 14:14:16 -04004795 strBuf << "-";
dsinclair2b6d64e2016-06-06 11:39:42 -07004796 strBuf << pUnits[pData[iIndex + 2] - '0'];
4797 } else if (pData[iIndex + 1] == '1') {
4798 strBuf << pTens[pData[iIndex + 2] - '0'];
4799 } else if (pData[iIndex + 1] == '0') {
4800 strBuf << pCapUnits[pData[iIndex + 2] - '0'];
Dan Sinclair1770c022016-03-14 14:14:16 -04004801 }
4802 }
4803 iIndex += 3;
4804 } else if (iFirstCount == 2) {
dsinclair2b6d64e2016-06-06 11:39:42 -07004805 if (pData[iIndex] == '0') {
4806 strBuf << pCapUnits[pData[iIndex + 1] - '0'];
Dan Sinclair1770c022016-03-14 14:14:16 -04004807 } else {
dsinclair2b6d64e2016-06-06 11:39:42 -07004808 if (pData[iIndex] > '1') {
4809 strBuf << pLastTens[pData[iIndex] - '2'];
Dan Sinclair1770c022016-03-14 14:14:16 -04004810 strBuf << "-";
dsinclair2b6d64e2016-06-06 11:39:42 -07004811 strBuf << pUnits[pData[iIndex + 1] - '0'];
4812 } else if (pData[iIndex] == '1') {
4813 strBuf << pTens[pData[iIndex + 1] - '0'];
4814 } else if (pData[iIndex] == '0') {
4815 strBuf << pCapUnits[pData[iIndex + 1] - '0'];
Dan Sinclair1770c022016-03-14 14:14:16 -04004816 }
4817 }
4818 iIndex += 2;
4819 } else if (iFirstCount == 1) {
dsinclair2b6d64e2016-06-06 11:39:42 -07004820 strBuf << pCapUnits[pData[iIndex] - '0'];
Dan Sinclair1770c022016-03-14 14:14:16 -04004821 iIndex += 1;
4822 }
4823 if (iLength > 3 && iFirstCount > 0) {
4824 strBuf << pComm[iComm];
4825 --iComm;
4826 }
4827 while (iIndex < iLength) {
dsinclair2b6d64e2016-06-06 11:39:42 -07004828 if (pData[iIndex] != '0') {
4829 strBuf << pCapUnits[pData[iIndex] - '0'];
Dan Sinclair1770c022016-03-14 14:14:16 -04004830 strBuf << pComm[0];
4831 }
dsinclair2b6d64e2016-06-06 11:39:42 -07004832 if (pData[iIndex + 1] == '0') {
4833 strBuf << pCapUnits[pData[iIndex + 2] - '0'];
Dan Sinclair1770c022016-03-14 14:14:16 -04004834 } else {
dsinclair2b6d64e2016-06-06 11:39:42 -07004835 if (pData[iIndex + 1] > '1') {
4836 strBuf << pLastTens[pData[iIndex + 1] - '2'];
Dan Sinclair1770c022016-03-14 14:14:16 -04004837 strBuf << "-";
dsinclair2b6d64e2016-06-06 11:39:42 -07004838 strBuf << pUnits[pData[iIndex + 2] - '0'];
4839 } else if (pData[iIndex + 1] == '1') {
4840 strBuf << pTens[pData[iIndex + 2] - '0'];
4841 } else if (pData[iIndex + 1] == '0') {
4842 strBuf << pCapUnits[pData[iIndex + 2] - '0'];
Dan Sinclair1770c022016-03-14 14:14:16 -04004843 }
4844 }
4845 if (iIndex < iLength - 3) {
4846 strBuf << pComm[iComm];
4847 --iComm;
4848 }
4849 iIndex += 3;
4850 }
4851}
dsinclair48d91dd2016-05-31 11:54:01 -07004852
4853// static
Dan Sinclair1770c022016-03-14 14:14:16 -04004854void CXFA_FM2JSContext::WordUS(const CFX_ByteStringC& szData,
4855 int32_t iStyle,
4856 CFX_ByteTextBuf& strBuf) {
dsinclair179bebb2016-04-05 11:02:18 -07004857 const FX_CHAR* pData = szData.c_str();
Dan Sinclair1770c022016-03-14 14:14:16 -04004858 int32_t iLength = szData.GetLength();
dsinclair947c8732016-06-08 20:40:30 -07004859 if (iStyle < 0 || iStyle > 2) {
4860 return;
4861 }
4862
4863 int32_t iIndex = 0;
4864 while (iIndex < iLength) {
4865 if (pData[iIndex] == '.')
Dan Sinclair1770c022016-03-14 14:14:16 -04004866 break;
dsinclair947c8732016-06-08 20:40:30 -07004867 ++iIndex;
4868 }
4869 int32_t iInteger = iIndex;
4870 iIndex = 0;
4871 while (iIndex < iInteger) {
4872 int32_t iCount = (iInteger - iIndex) % 12;
4873 if (!iCount && iInteger - iIndex > 0)
4874 iCount = 12;
4875
4876 TrillionUS(CFX_ByteStringC(pData + iIndex, iCount), strBuf);
4877 iIndex += iCount;
4878 if (iIndex < iInteger)
4879 strBuf << " Trillion ";
4880 }
4881
4882 if (iStyle > 0)
4883 strBuf << " Dollars";
4884
4885 if (iStyle > 1 && iInteger < iLength) {
4886 strBuf << " And ";
4887 iIndex = iInteger + 1;
4888 while (iIndex < iLength) {
4889 int32_t iCount = (iLength - iIndex) % 12;
4890 if (!iCount && iLength - iIndex > 0)
4891 iCount = 12;
4892
4893 TrillionUS(CFX_ByteStringC(pData + iIndex, iCount), strBuf);
4894 iIndex += iCount;
4895 if (iIndex < iLength)
4896 strBuf << " Trillion ";
4897 }
4898 strBuf << " Cents";
Dan Sinclair1770c022016-03-14 14:14:16 -04004899 }
4900}
dsinclair48d91dd2016-05-31 11:54:01 -07004901
4902// static
dsinclair12a6b0c2016-05-26 11:14:08 -07004903void CXFA_FM2JSContext::Get(CFXJSE_Value* pThis,
Dan Sinclair1770c022016-03-14 14:14:16 -04004904 const CFX_ByteStringC& szFuncName,
4905 CFXJSE_Arguments& args) {
dsinclair8f3074b2016-06-02 17:45:25 -07004906 CXFA_FM2JSContext* pContext = ToJSContext(pThis, nullptr);
dsinclair947c8732016-06-08 20:40:30 -07004907 if (args.GetLength() != 1) {
dsinclair2235b7b2016-06-02 07:42:25 -07004908 pContext->ThrowException(XFA_IDS_INCORRECT_NUMBER_OF_METHOD, L"Get");
dsinclair947c8732016-06-08 20:40:30 -07004909 return;
Dan Sinclair1770c022016-03-14 14:14:16 -04004910 }
dsinclair947c8732016-06-08 20:40:30 -07004911
4912 CXFA_Document* pDoc = pContext->GetDocument();
4913 if (!pDoc)
4914 return;
4915
dsinclaira1b07722016-07-11 08:20:58 -07004916 IXFA_AppProvider* pAppProvider = pDoc->GetNotify()->GetAppProvider();
dsinclair947c8732016-06-08 20:40:30 -07004917 if (!pAppProvider)
4918 return;
4919
4920 std::unique_ptr<CFXJSE_Value> argOne = GetSimpleValue(pThis, args, 0);
4921 CFX_ByteString urlString;
4922 ValueToUTF8String(argOne.get(), urlString);
tsepezad2441e2016-10-24 10:19:11 -07004923 IFX_SeekableReadStream* pFile = pAppProvider->DownloadURL(
dsinclair947c8732016-06-08 20:40:30 -07004924 CFX_WideString::FromUTF8(urlString.AsStringC()));
4925 if (!pFile)
4926 return;
4927
4928 int32_t size = pFile->GetSize();
4929 std::unique_ptr<uint8_t> pData(FX_Alloc(uint8_t, size));
4930 pFile->ReadBlock(pData.get(), size);
4931 args.GetReturnValue()->SetString(CFX_ByteStringC(pData.get(), size));
4932 pFile->Release();
Dan Sinclair1770c022016-03-14 14:14:16 -04004933}
dsinclair48d91dd2016-05-31 11:54:01 -07004934
4935// static
dsinclair12a6b0c2016-05-26 11:14:08 -07004936void CXFA_FM2JSContext::Post(CFXJSE_Value* pThis,
Dan Sinclair1770c022016-03-14 14:14:16 -04004937 const CFX_ByteStringC& szFuncName,
4938 CFXJSE_Arguments& args) {
dsinclair8f3074b2016-06-02 17:45:25 -07004939 CXFA_FM2JSContext* pContext = ToJSContext(pThis, nullptr);
Dan Sinclair1770c022016-03-14 14:14:16 -04004940 int32_t argc = args.GetLength();
dsinclair947c8732016-06-08 20:40:30 -07004941 if (argc < 2 || argc > 5) {
dsinclair2235b7b2016-06-02 07:42:25 -07004942 pContext->ThrowException(XFA_IDS_INCORRECT_NUMBER_OF_METHOD, L"Post");
dsinclair947c8732016-06-08 20:40:30 -07004943 return;
Dan Sinclair1770c022016-03-14 14:14:16 -04004944 }
dsinclair947c8732016-06-08 20:40:30 -07004945
4946 CXFA_Document* pDoc = pContext->GetDocument();
4947 if (!pDoc)
4948 return;
4949
dsinclaira1b07722016-07-11 08:20:58 -07004950 IXFA_AppProvider* pAppProvider = pDoc->GetNotify()->GetAppProvider();
dsinclair947c8732016-06-08 20:40:30 -07004951 if (!pAppProvider)
4952 return;
4953
4954 CFX_ByteString bsURL;
4955 std::unique_ptr<CFXJSE_Value> argOne = GetSimpleValue(pThis, args, 0);
4956 ValueToUTF8String(argOne.get(), bsURL);
4957
4958 CFX_ByteString bsData;
4959 std::unique_ptr<CFXJSE_Value> argTwo = GetSimpleValue(pThis, args, 1);
4960 ValueToUTF8String(argTwo.get(), bsData);
4961
4962 CFX_ByteString bsContentType;
4963 if (argc > 2) {
4964 std::unique_ptr<CFXJSE_Value> argThree = GetSimpleValue(pThis, args, 2);
4965 ValueToUTF8String(argThree.get(), bsContentType);
4966 }
4967
4968 CFX_ByteString bsEncode;
4969 if (argc > 3) {
4970 std::unique_ptr<CFXJSE_Value> argFour = GetSimpleValue(pThis, args, 3);
4971 ValueToUTF8String(argFour.get(), bsEncode);
4972 }
4973
4974 CFX_ByteString bsHeader;
4975 if (argc > 4) {
4976 std::unique_ptr<CFXJSE_Value> argFive = GetSimpleValue(pThis, args, 4);
4977 ValueToUTF8String(argFive.get(), bsHeader);
4978 }
4979
4980 CFX_WideString decodedResponse;
4981 if (!pAppProvider->PostRequestURL(
4982 CFX_WideString::FromUTF8(bsURL.AsStringC()),
4983 CFX_WideString::FromUTF8(bsData.AsStringC()),
4984 CFX_WideString::FromUTF8(bsContentType.AsStringC()),
4985 CFX_WideString::FromUTF8(bsEncode.AsStringC()),
4986 CFX_WideString::FromUTF8(bsHeader.AsStringC()), decodedResponse)) {
4987 pContext->ThrowException(XFA_IDS_SERVER_DENY);
4988 return;
4989 }
4990
4991 args.GetReturnValue()->SetString(
4992 FX_UTF8Encode(decodedResponse.c_str(), decodedResponse.GetLength())
4993 .AsStringC());
Dan Sinclair1770c022016-03-14 14:14:16 -04004994}
dsinclair48d91dd2016-05-31 11:54:01 -07004995
4996// static
dsinclair12a6b0c2016-05-26 11:14:08 -07004997void CXFA_FM2JSContext::Put(CFXJSE_Value* pThis,
Dan Sinclair1770c022016-03-14 14:14:16 -04004998 const CFX_ByteStringC& szFuncName,
4999 CFXJSE_Arguments& args) {
dsinclair8f3074b2016-06-02 17:45:25 -07005000 CXFA_FM2JSContext* pContext = ToJSContext(pThis, nullptr);
Dan Sinclair1770c022016-03-14 14:14:16 -04005001 int32_t argc = args.GetLength();
dsinclair947c8732016-06-08 20:40:30 -07005002 if (argc < 2 || argc > 3) {
dsinclair2235b7b2016-06-02 07:42:25 -07005003 pContext->ThrowException(XFA_IDS_INCORRECT_NUMBER_OF_METHOD, L"Put");
dsinclair947c8732016-06-08 20:40:30 -07005004 return;
Dan Sinclair1770c022016-03-14 14:14:16 -04005005 }
dsinclair947c8732016-06-08 20:40:30 -07005006
5007 CXFA_Document* pDoc = pContext->GetDocument();
5008 if (!pDoc)
5009 return;
5010
dsinclaira1b07722016-07-11 08:20:58 -07005011 IXFA_AppProvider* pAppProvider = pDoc->GetNotify()->GetAppProvider();
dsinclair947c8732016-06-08 20:40:30 -07005012 if (!pAppProvider)
5013 return;
5014
5015 CFX_ByteString bsURL;
5016 std::unique_ptr<CFXJSE_Value> argOne = GetSimpleValue(pThis, args, 0);
5017 ValueToUTF8String(argOne.get(), bsURL);
5018
5019 CFX_ByteString bsData;
5020 std::unique_ptr<CFXJSE_Value> argTwo = GetSimpleValue(pThis, args, 1);
5021 ValueToUTF8String(argTwo.get(), bsData);
5022
5023 CFX_ByteString bsEncode;
5024 if (argc > 2) {
5025 std::unique_ptr<CFXJSE_Value> argThree = GetSimpleValue(pThis, args, 2);
5026 ValueToUTF8String(argThree.get(), bsEncode);
5027 }
5028
5029 if (!pAppProvider->PutRequestURL(
5030 CFX_WideString::FromUTF8(bsURL.AsStringC()),
5031 CFX_WideString::FromUTF8(bsData.AsStringC()),
5032 CFX_WideString::FromUTF8(bsEncode.AsStringC()))) {
5033 pContext->ThrowException(XFA_IDS_SERVER_DENY);
5034 return;
5035 }
5036
5037 args.GetReturnValue()->SetString("");
Dan Sinclair1770c022016-03-14 14:14:16 -04005038}
dsinclair48d91dd2016-05-31 11:54:01 -07005039
5040// static
dsinclair12a6b0c2016-05-26 11:14:08 -07005041void CXFA_FM2JSContext::assign_value_operator(CFXJSE_Value* pThis,
Dan Sinclair1770c022016-03-14 14:14:16 -04005042 const CFX_ByteStringC& szFuncName,
5043 CFXJSE_Arguments& args) {
dsinclair8f3074b2016-06-02 17:45:25 -07005044 CXFA_FM2JSContext* pContext = ToJSContext(pThis, nullptr);
dsinclair947c8732016-06-08 20:40:30 -07005045 if (args.GetLength() != 2) {
5046 pContext->ThrowException(XFA_IDS_COMPILER_ERROR);
5047 return;
5048 }
5049
5050 std::unique_ptr<CFXJSE_Value> lValue = args.GetValue(0);
5051 std::unique_ptr<CFXJSE_Value> rValue = GetSimpleValue(pThis, args, 1);
5052 if (lValue->IsArray()) {
5053 v8::Isolate* pIsolate = pContext->GetScriptRuntime();
5054 std::unique_ptr<CFXJSE_Value> leftLengthValue(new CFXJSE_Value(pIsolate));
5055 lValue->GetObjectProperty("length", leftLengthValue.get());
5056 int32_t iLeftLength = leftLengthValue->ToInteger();
5057 std::unique_ptr<CFXJSE_Value> jsObjectValue(new CFXJSE_Value(pIsolate));
5058 std::unique_ptr<CFXJSE_Value> propertyValue(new CFXJSE_Value(pIsolate));
5059 lValue->GetObjectPropertyByIdx(1, propertyValue.get());
5060 if (propertyValue->IsNull()) {
5061 for (int32_t i = 2; i < iLeftLength; i++) {
5062 lValue->GetObjectPropertyByIdx(i, jsObjectValue.get());
5063 if (!SetObjectDefaultValue(jsObjectValue.get(), rValue.get())) {
5064 pContext->ThrowException(XFA_IDS_NOT_DEFAUL_VALUE);
5065 return;
Dan Sinclair1770c022016-03-14 14:14:16 -04005066 }
5067 }
dsinclair947c8732016-06-08 20:40:30 -07005068 } else {
dsinclair947c8732016-06-08 20:40:30 -07005069 for (int32_t i = 2; i < iLeftLength; i++) {
5070 lValue->GetObjectPropertyByIdx(i, jsObjectValue.get());
dsinclair2f5582f2016-06-09 11:48:23 -07005071 jsObjectValue->SetObjectProperty(propertyValue->ToString().AsStringC(),
5072 rValue.get());
Dan Sinclair1770c022016-03-14 14:14:16 -04005073 }
5074 }
dsinclair947c8732016-06-08 20:40:30 -07005075 } else if (lValue->IsObject()) {
5076 if (!SetObjectDefaultValue(lValue.get(), rValue.get())) {
5077 pContext->ThrowException(XFA_IDS_NOT_DEFAUL_VALUE);
5078 return;
5079 }
Dan Sinclair1770c022016-03-14 14:14:16 -04005080 }
dsinclair947c8732016-06-08 20:40:30 -07005081 args.GetReturnValue()->Assign(rValue.get());
Dan Sinclair1770c022016-03-14 14:14:16 -04005082}
dsinclair48d91dd2016-05-31 11:54:01 -07005083
5084// static
dsinclair12a6b0c2016-05-26 11:14:08 -07005085void CXFA_FM2JSContext::logical_or_operator(CFXJSE_Value* pThis,
Dan Sinclair1770c022016-03-14 14:14:16 -04005086 const CFX_ByteStringC& szFuncName,
5087 CFXJSE_Arguments& args) {
dsinclair947c8732016-06-08 20:40:30 -07005088 if (args.GetLength() != 2) {
dsinclair8f3074b2016-06-02 17:45:25 -07005089 ToJSContext(pThis, nullptr)->ThrowException(XFA_IDS_COMPILER_ERROR);
dsinclair947c8732016-06-08 20:40:30 -07005090 return;
Dan Sinclair1770c022016-03-14 14:14:16 -04005091 }
dsinclair947c8732016-06-08 20:40:30 -07005092
5093 std::unique_ptr<CFXJSE_Value> argFirst = GetSimpleValue(pThis, args, 0);
5094 std::unique_ptr<CFXJSE_Value> argSecond = GetSimpleValue(pThis, args, 1);
5095 if (argFirst->IsNull() && argSecond->IsNull()) {
5096 args.GetReturnValue()->SetNull();
5097 return;
5098 }
5099
5100 FX_FLOAT first = ValueToFloat(pThis, argFirst.get());
5101 FX_FLOAT second = ValueToFloat(pThis, argSecond.get());
5102 args.GetReturnValue()->SetInteger((first || second) ? 1 : 0);
Dan Sinclair1770c022016-03-14 14:14:16 -04005103}
dsinclair48d91dd2016-05-31 11:54:01 -07005104
5105// static
dsinclair12a6b0c2016-05-26 11:14:08 -07005106void CXFA_FM2JSContext::logical_and_operator(CFXJSE_Value* pThis,
Dan Sinclair1770c022016-03-14 14:14:16 -04005107 const CFX_ByteStringC& szFuncName,
5108 CFXJSE_Arguments& args) {
dsinclair947c8732016-06-08 20:40:30 -07005109 if (args.GetLength() != 2) {
dsinclair8f3074b2016-06-02 17:45:25 -07005110 ToJSContext(pThis, nullptr)->ThrowException(XFA_IDS_COMPILER_ERROR);
dsinclair947c8732016-06-08 20:40:30 -07005111 return;
Dan Sinclair1770c022016-03-14 14:14:16 -04005112 }
dsinclair947c8732016-06-08 20:40:30 -07005113
5114 std::unique_ptr<CFXJSE_Value> argFirst = GetSimpleValue(pThis, args, 0);
5115 std::unique_ptr<CFXJSE_Value> argSecond = GetSimpleValue(pThis, args, 1);
5116 if (argFirst->IsNull() && argSecond->IsNull()) {
5117 args.GetReturnValue()->SetNull();
5118 return;
5119 }
5120
5121 FX_FLOAT first = ValueToFloat(pThis, argFirst.get());
5122 FX_FLOAT second = ValueToFloat(pThis, argSecond.get());
5123 args.GetReturnValue()->SetInteger((first && second) ? 1 : 0);
Dan Sinclair1770c022016-03-14 14:14:16 -04005124}
dsinclair48d91dd2016-05-31 11:54:01 -07005125
5126// static
dsinclair12a6b0c2016-05-26 11:14:08 -07005127void CXFA_FM2JSContext::equality_operator(CFXJSE_Value* pThis,
Dan Sinclair1770c022016-03-14 14:14:16 -04005128 const CFX_ByteStringC& szFuncName,
5129 CFXJSE_Arguments& args) {
dsinclair947c8732016-06-08 20:40:30 -07005130 if (args.GetLength() != 2) {
dsinclair8f3074b2016-06-02 17:45:25 -07005131 ToJSContext(pThis, nullptr)->ThrowException(XFA_IDS_COMPILER_ERROR);
dsinclair947c8732016-06-08 20:40:30 -07005132 return;
Dan Sinclair1770c022016-03-14 14:14:16 -04005133 }
dsinclair947c8732016-06-08 20:40:30 -07005134
5135 if (fm_ref_equal(pThis, args)) {
5136 args.GetReturnValue()->SetInteger(1);
5137 return;
5138 }
5139
5140 std::unique_ptr<CFXJSE_Value> argFirst = GetSimpleValue(pThis, args, 0);
5141 std::unique_ptr<CFXJSE_Value> argSecond = GetSimpleValue(pThis, args, 1);
5142 if (argFirst->IsNull() || argSecond->IsNull()) {
5143 args.GetReturnValue()->SetInteger(
5144 (argFirst->IsNull() && argSecond->IsNull()) ? 1 : 0);
5145 return;
5146 }
5147
5148 if (argFirst->IsString() && argSecond->IsString()) {
dsinclair2f5582f2016-06-09 11:48:23 -07005149 args.GetReturnValue()->SetInteger(argFirst->ToString() ==
5150 argSecond->ToString());
dsinclair947c8732016-06-08 20:40:30 -07005151 return;
5152 }
5153
5154 FX_DOUBLE first = ValueToDouble(pThis, argFirst.get());
5155 FX_DOUBLE second = ValueToDouble(pThis, argSecond.get());
5156 args.GetReturnValue()->SetInteger((first == second) ? 1 : 0);
Dan Sinclair1770c022016-03-14 14:14:16 -04005157}
dsinclair48d91dd2016-05-31 11:54:01 -07005158
5159// static
dsinclair12a6b0c2016-05-26 11:14:08 -07005160void CXFA_FM2JSContext::notequality_operator(CFXJSE_Value* pThis,
Dan Sinclair1770c022016-03-14 14:14:16 -04005161 const CFX_ByteStringC& szFuncName,
5162 CFXJSE_Arguments& args) {
dsinclair947c8732016-06-08 20:40:30 -07005163 if (args.GetLength() != 2) {
dsinclair8f3074b2016-06-02 17:45:25 -07005164 ToJSContext(pThis, nullptr)->ThrowException(XFA_IDS_COMPILER_ERROR);
dsinclair947c8732016-06-08 20:40:30 -07005165 return;
Dan Sinclair1770c022016-03-14 14:14:16 -04005166 }
dsinclair947c8732016-06-08 20:40:30 -07005167
5168 if (fm_ref_equal(pThis, args)) {
5169 args.GetReturnValue()->SetInteger(0);
5170 return;
5171 }
5172
5173 std::unique_ptr<CFXJSE_Value> argFirst = GetSimpleValue(pThis, args, 0);
5174 std::unique_ptr<CFXJSE_Value> argSecond = GetSimpleValue(pThis, args, 1);
5175 if (argFirst->IsNull() || argSecond->IsNull()) {
5176 args.GetReturnValue()->SetInteger(
5177 (argFirst->IsNull() && argSecond->IsNull()) ? 0 : 1);
5178 return;
5179 }
5180
5181 if (argFirst->IsString() && argSecond->IsString()) {
dsinclair2f5582f2016-06-09 11:48:23 -07005182 args.GetReturnValue()->SetInteger(argFirst->ToString() !=
5183 argSecond->ToString());
dsinclair947c8732016-06-08 20:40:30 -07005184 return;
5185 }
5186
5187 FX_DOUBLE first = ValueToDouble(pThis, argFirst.get());
5188 FX_DOUBLE second = ValueToDouble(pThis, argSecond.get());
5189 args.GetReturnValue()->SetInteger(first != second);
Dan Sinclair1770c022016-03-14 14:14:16 -04005190}
dsinclair48d91dd2016-05-31 11:54:01 -07005191
5192// static
dsinclair12a6b0c2016-05-26 11:14:08 -07005193FX_BOOL CXFA_FM2JSContext::fm_ref_equal(CFXJSE_Value* pThis,
Dan Sinclair1770c022016-03-14 14:14:16 -04005194 CFXJSE_Arguments& args) {
dsinclair86fad992016-05-31 11:34:04 -07005195 std::unique_ptr<CFXJSE_Value> argFirst = args.GetValue(0);
5196 std::unique_ptr<CFXJSE_Value> argSecond = args.GetValue(1);
dsinclair947c8732016-06-08 20:40:30 -07005197 if (!argFirst->IsArray() || !argSecond->IsArray())
5198 return FALSE;
5199
5200 v8::Isolate* pIsolate = ToJSContext(pThis, nullptr)->GetScriptRuntime();
5201 std::unique_ptr<CFXJSE_Value> firstFlagValue(new CFXJSE_Value(pIsolate));
5202 std::unique_ptr<CFXJSE_Value> secondFlagValue(new CFXJSE_Value(pIsolate));
5203 argFirst->GetObjectPropertyByIdx(0, firstFlagValue.get());
5204 argSecond->GetObjectPropertyByIdx(0, secondFlagValue.get());
5205 if (firstFlagValue->ToInteger() != 3 || secondFlagValue->ToInteger() != 3)
5206 return FALSE;
5207
5208 std::unique_ptr<CFXJSE_Value> firstJSObject(new CFXJSE_Value(pIsolate));
5209 std::unique_ptr<CFXJSE_Value> secondJSObject(new CFXJSE_Value(pIsolate));
5210 argFirst->GetObjectPropertyByIdx(2, firstJSObject.get());
5211 argSecond->GetObjectPropertyByIdx(2, secondJSObject.get());
5212 if (firstJSObject->IsNull() || secondJSObject->IsNull())
5213 return FALSE;
5214
5215 return (firstJSObject->ToHostObject(nullptr) ==
5216 secondJSObject->ToHostObject(nullptr));
Dan Sinclair1770c022016-03-14 14:14:16 -04005217}
dsinclair48d91dd2016-05-31 11:54:01 -07005218
5219// static
dsinclair12a6b0c2016-05-26 11:14:08 -07005220void CXFA_FM2JSContext::less_operator(CFXJSE_Value* pThis,
Dan Sinclair1770c022016-03-14 14:14:16 -04005221 const CFX_ByteStringC& szFuncName,
5222 CFXJSE_Arguments& args) {
dsinclair947c8732016-06-08 20:40:30 -07005223 if (args.GetLength() != 2) {
dsinclair8f3074b2016-06-02 17:45:25 -07005224 ToJSContext(pThis, nullptr)->ThrowException(XFA_IDS_COMPILER_ERROR);
dsinclair947c8732016-06-08 20:40:30 -07005225 return;
Dan Sinclair1770c022016-03-14 14:14:16 -04005226 }
dsinclair947c8732016-06-08 20:40:30 -07005227
5228 std::unique_ptr<CFXJSE_Value> argFirst = GetSimpleValue(pThis, args, 0);
5229 std::unique_ptr<CFXJSE_Value> argSecond = GetSimpleValue(pThis, args, 1);
5230 if (argFirst->IsNull() || argSecond->IsNull()) {
5231 args.GetReturnValue()->SetInteger(0);
5232 return;
5233 }
5234
5235 if (argFirst->IsString() && argSecond->IsString()) {
dsinclair947c8732016-06-08 20:40:30 -07005236 args.GetReturnValue()->SetInteger(
dsinclair2f5582f2016-06-09 11:48:23 -07005237 argFirst->ToString().Compare(argSecond->ToString().AsStringC()) == -1);
dsinclair947c8732016-06-08 20:40:30 -07005238 return;
5239 }
5240
5241 FX_DOUBLE first = ValueToDouble(pThis, argFirst.get());
5242 FX_DOUBLE second = ValueToDouble(pThis, argSecond.get());
5243 args.GetReturnValue()->SetInteger((first < second) ? 1 : 0);
Dan Sinclair1770c022016-03-14 14:14:16 -04005244}
dsinclair48d91dd2016-05-31 11:54:01 -07005245
5246// static
dsinclair12a6b0c2016-05-26 11:14:08 -07005247void CXFA_FM2JSContext::lessequal_operator(CFXJSE_Value* pThis,
Dan Sinclair1770c022016-03-14 14:14:16 -04005248 const CFX_ByteStringC& szFuncName,
5249 CFXJSE_Arguments& args) {
dsinclair947c8732016-06-08 20:40:30 -07005250 if (args.GetLength() != 2) {
dsinclair8f3074b2016-06-02 17:45:25 -07005251 ToJSContext(pThis, nullptr)->ThrowException(XFA_IDS_COMPILER_ERROR);
dsinclair947c8732016-06-08 20:40:30 -07005252 return;
Dan Sinclair1770c022016-03-14 14:14:16 -04005253 }
dsinclair947c8732016-06-08 20:40:30 -07005254
5255 std::unique_ptr<CFXJSE_Value> argFirst = GetSimpleValue(pThis, args, 0);
5256 std::unique_ptr<CFXJSE_Value> argSecond = GetSimpleValue(pThis, args, 1);
5257 if (argFirst->IsNull() || argSecond->IsNull()) {
5258 args.GetReturnValue()->SetInteger(
5259 (argFirst->IsNull() && argSecond->IsNull()) ? 1 : 0);
5260 return;
5261 }
5262
5263 if (argFirst->IsString() && argSecond->IsString()) {
dsinclair947c8732016-06-08 20:40:30 -07005264 args.GetReturnValue()->SetInteger(
dsinclair2f5582f2016-06-09 11:48:23 -07005265 argFirst->ToString().Compare(argSecond->ToString().AsStringC()) != 1);
dsinclair947c8732016-06-08 20:40:30 -07005266 return;
5267 }
5268
5269 FX_DOUBLE first = ValueToDouble(pThis, argFirst.get());
5270 FX_DOUBLE second = ValueToDouble(pThis, argSecond.get());
5271 args.GetReturnValue()->SetInteger((first <= second) ? 1 : 0);
Dan Sinclair1770c022016-03-14 14:14:16 -04005272}
dsinclair48d91dd2016-05-31 11:54:01 -07005273
5274// static
dsinclair12a6b0c2016-05-26 11:14:08 -07005275void CXFA_FM2JSContext::greater_operator(CFXJSE_Value* pThis,
Dan Sinclair1770c022016-03-14 14:14:16 -04005276 const CFX_ByteStringC& szFuncName,
5277 CFXJSE_Arguments& args) {
dsinclair947c8732016-06-08 20:40:30 -07005278 if (args.GetLength() != 2) {
dsinclair8f3074b2016-06-02 17:45:25 -07005279 ToJSContext(pThis, nullptr)->ThrowException(XFA_IDS_COMPILER_ERROR);
dsinclair947c8732016-06-08 20:40:30 -07005280 return;
Dan Sinclair1770c022016-03-14 14:14:16 -04005281 }
dsinclair947c8732016-06-08 20:40:30 -07005282
5283 std::unique_ptr<CFXJSE_Value> argFirst = GetSimpleValue(pThis, args, 0);
5284 std::unique_ptr<CFXJSE_Value> argSecond = GetSimpleValue(pThis, args, 1);
5285 if (argFirst->IsNull() || argSecond->IsNull()) {
5286 args.GetReturnValue()->SetInteger(0);
5287 return;
5288 }
5289
5290 if (argFirst->IsString() && argSecond->IsString()) {
dsinclair947c8732016-06-08 20:40:30 -07005291 args.GetReturnValue()->SetInteger(
dsinclair2f5582f2016-06-09 11:48:23 -07005292 argFirst->ToString().Compare(argSecond->ToString().AsStringC()) == 1);
dsinclair947c8732016-06-08 20:40:30 -07005293 return;
5294 }
5295
5296 FX_DOUBLE first = ValueToDouble(pThis, argFirst.get());
5297 FX_DOUBLE second = ValueToDouble(pThis, argSecond.get());
5298 args.GetReturnValue()->SetInteger((first > second) ? 1 : 0);
Dan Sinclair1770c022016-03-14 14:14:16 -04005299}
dsinclair48d91dd2016-05-31 11:54:01 -07005300
5301// static
dsinclair12a6b0c2016-05-26 11:14:08 -07005302void CXFA_FM2JSContext::greaterequal_operator(CFXJSE_Value* pThis,
Dan Sinclair1770c022016-03-14 14:14:16 -04005303 const CFX_ByteStringC& szFuncName,
5304 CFXJSE_Arguments& args) {
dsinclair947c8732016-06-08 20:40:30 -07005305 if (args.GetLength() != 2) {
dsinclair8f3074b2016-06-02 17:45:25 -07005306 ToJSContext(pThis, nullptr)->ThrowException(XFA_IDS_COMPILER_ERROR);
dsinclair947c8732016-06-08 20:40:30 -07005307 return;
Dan Sinclair1770c022016-03-14 14:14:16 -04005308 }
dsinclair947c8732016-06-08 20:40:30 -07005309
5310 std::unique_ptr<CFXJSE_Value> argFirst = GetSimpleValue(pThis, args, 0);
5311 std::unique_ptr<CFXJSE_Value> argSecond = GetSimpleValue(pThis, args, 1);
5312 if (argFirst->IsNull() || argSecond->IsNull()) {
5313 args.GetReturnValue()->SetInteger(
5314 (argFirst->IsNull() && argSecond->IsNull()) ? 1 : 0);
5315 return;
5316 }
5317
5318 if (argFirst->IsString() && argSecond->IsString()) {
dsinclair947c8732016-06-08 20:40:30 -07005319 args.GetReturnValue()->SetInteger(
dsinclair2f5582f2016-06-09 11:48:23 -07005320 argFirst->ToString().Compare(argSecond->ToString().AsStringC()) != -1);
dsinclair947c8732016-06-08 20:40:30 -07005321 return;
5322 }
5323
5324 FX_DOUBLE first = ValueToDouble(pThis, argFirst.get());
5325 FX_DOUBLE second = ValueToDouble(pThis, argSecond.get());
5326 args.GetReturnValue()->SetInteger((first >= second) ? 1 : 0);
Dan Sinclair1770c022016-03-14 14:14:16 -04005327}
dsinclair48d91dd2016-05-31 11:54:01 -07005328
5329// static
dsinclair12a6b0c2016-05-26 11:14:08 -07005330void CXFA_FM2JSContext::plus_operator(CFXJSE_Value* pThis,
Dan Sinclair1770c022016-03-14 14:14:16 -04005331 const CFX_ByteStringC& szFuncName,
5332 CFXJSE_Arguments& args) {
dsinclair947c8732016-06-08 20:40:30 -07005333 if (args.GetLength() != 2) {
dsinclair8f3074b2016-06-02 17:45:25 -07005334 ToJSContext(pThis, nullptr)->ThrowException(XFA_IDS_COMPILER_ERROR);
dsinclair947c8732016-06-08 20:40:30 -07005335 return;
Dan Sinclair1770c022016-03-14 14:14:16 -04005336 }
dsinclair947c8732016-06-08 20:40:30 -07005337
5338 std::unique_ptr<CFXJSE_Value> argFirst = args.GetValue(0);
5339 std::unique_ptr<CFXJSE_Value> argSecond = args.GetValue(1);
5340 if (ValueIsNull(pThis, argFirst.get()) &&
5341 ValueIsNull(pThis, argSecond.get())) {
5342 args.GetReturnValue()->SetNull();
5343 return;
5344 }
5345
5346 FX_DOUBLE first = ValueToDouble(pThis, argFirst.get());
5347 FX_DOUBLE second = ValueToDouble(pThis, argSecond.get());
5348 args.GetReturnValue()->SetDouble(first + second);
Dan Sinclair1770c022016-03-14 14:14:16 -04005349}
dsinclair48d91dd2016-05-31 11:54:01 -07005350
5351// static
dsinclair12a6b0c2016-05-26 11:14:08 -07005352void CXFA_FM2JSContext::minus_operator(CFXJSE_Value* pThis,
Dan Sinclair1770c022016-03-14 14:14:16 -04005353 const CFX_ByteStringC& szFuncName,
5354 CFXJSE_Arguments& args) {
dsinclair947c8732016-06-08 20:40:30 -07005355 if (args.GetLength() != 2) {
dsinclair8f3074b2016-06-02 17:45:25 -07005356 ToJSContext(pThis, nullptr)->ThrowException(XFA_IDS_COMPILER_ERROR);
dsinclair947c8732016-06-08 20:40:30 -07005357 return;
Dan Sinclair1770c022016-03-14 14:14:16 -04005358 }
dsinclair947c8732016-06-08 20:40:30 -07005359
5360 std::unique_ptr<CFXJSE_Value> argFirst = GetSimpleValue(pThis, args, 0);
5361 std::unique_ptr<CFXJSE_Value> argSecond = GetSimpleValue(pThis, args, 1);
5362 if (argFirst->IsNull() && argSecond->IsNull()) {
5363 args.GetReturnValue()->SetNull();
5364 return;
5365 }
5366
5367 FX_DOUBLE first = ValueToDouble(pThis, argFirst.get());
5368 FX_DOUBLE second = ValueToDouble(pThis, argSecond.get());
5369 args.GetReturnValue()->SetDouble(first - second);
Dan Sinclair1770c022016-03-14 14:14:16 -04005370}
dsinclair48d91dd2016-05-31 11:54:01 -07005371
5372// static
dsinclair12a6b0c2016-05-26 11:14:08 -07005373void CXFA_FM2JSContext::multiple_operator(CFXJSE_Value* pThis,
Dan Sinclair1770c022016-03-14 14:14:16 -04005374 const CFX_ByteStringC& szFuncName,
5375 CFXJSE_Arguments& args) {
dsinclair947c8732016-06-08 20:40:30 -07005376 if (args.GetLength() != 2) {
dsinclair8f3074b2016-06-02 17:45:25 -07005377 ToJSContext(pThis, nullptr)->ThrowException(XFA_IDS_COMPILER_ERROR);
dsinclair947c8732016-06-08 20:40:30 -07005378 return;
Dan Sinclair1770c022016-03-14 14:14:16 -04005379 }
dsinclair947c8732016-06-08 20:40:30 -07005380
5381 std::unique_ptr<CFXJSE_Value> argFirst = GetSimpleValue(pThis, args, 0);
5382 std::unique_ptr<CFXJSE_Value> argSecond = GetSimpleValue(pThis, args, 1);
5383 if (argFirst->IsNull() && argSecond->IsNull()) {
5384 args.GetReturnValue()->SetNull();
5385 return;
5386 }
5387
5388 FX_DOUBLE first = ValueToDouble(pThis, argFirst.get());
5389 FX_DOUBLE second = ValueToDouble(pThis, argSecond.get());
5390 args.GetReturnValue()->SetDouble(first * second);
Dan Sinclair1770c022016-03-14 14:14:16 -04005391}
dsinclair48d91dd2016-05-31 11:54:01 -07005392
5393// static
dsinclair12a6b0c2016-05-26 11:14:08 -07005394void CXFA_FM2JSContext::divide_operator(CFXJSE_Value* pThis,
Dan Sinclair1770c022016-03-14 14:14:16 -04005395 const CFX_ByteStringC& szFuncName,
5396 CFXJSE_Arguments& args) {
dsinclair8f3074b2016-06-02 17:45:25 -07005397 CXFA_FM2JSContext* pContext = ToJSContext(pThis, nullptr);
dsinclair947c8732016-06-08 20:40:30 -07005398 if (args.GetLength() != 2) {
dsinclair2235b7b2016-06-02 07:42:25 -07005399 pContext->ThrowException(XFA_IDS_COMPILER_ERROR);
dsinclair947c8732016-06-08 20:40:30 -07005400 return;
Dan Sinclair1770c022016-03-14 14:14:16 -04005401 }
dsinclair947c8732016-06-08 20:40:30 -07005402
5403 std::unique_ptr<CFXJSE_Value> argFirst = GetSimpleValue(pThis, args, 0);
5404 std::unique_ptr<CFXJSE_Value> argSecond = GetSimpleValue(pThis, args, 1);
5405 if (argFirst->IsNull() && argSecond->IsNull()) {
5406 args.GetReturnValue()->SetNull();
5407 return;
5408 }
5409
5410 FX_DOUBLE second = ValueToDouble(pThis, argSecond.get());
5411 if (second == 0.0) {
5412 pContext->ThrowException(XFA_IDS_DIVIDE_ZERO);
5413 return;
5414 }
5415
5416 FX_DOUBLE first = ValueToDouble(pThis, argFirst.get());
5417 args.GetReturnValue()->SetDouble(first / second);
Dan Sinclair1770c022016-03-14 14:14:16 -04005418}
dsinclair48d91dd2016-05-31 11:54:01 -07005419
5420// static
dsinclair12a6b0c2016-05-26 11:14:08 -07005421void CXFA_FM2JSContext::positive_operator(CFXJSE_Value* pThis,
Dan Sinclair1770c022016-03-14 14:14:16 -04005422 const CFX_ByteStringC& szFuncName,
5423 CFXJSE_Arguments& args) {
dsinclair947c8732016-06-08 20:40:30 -07005424 if (args.GetLength() != 1) {
dsinclair8f3074b2016-06-02 17:45:25 -07005425 ToJSContext(pThis, nullptr)->ThrowException(XFA_IDS_COMPILER_ERROR);
dsinclair947c8732016-06-08 20:40:30 -07005426 return;
Dan Sinclair1770c022016-03-14 14:14:16 -04005427 }
dsinclair947c8732016-06-08 20:40:30 -07005428
5429 std::unique_ptr<CFXJSE_Value> argOne = GetSimpleValue(pThis, args, 0);
5430 if (argOne->IsNull()) {
5431 args.GetReturnValue()->SetNull();
5432 return;
5433 }
5434 args.GetReturnValue()->SetDouble(0.0 + ValueToDouble(pThis, argOne.get()));
Dan Sinclair1770c022016-03-14 14:14:16 -04005435}
dsinclair48d91dd2016-05-31 11:54:01 -07005436
5437// static
dsinclair12a6b0c2016-05-26 11:14:08 -07005438void CXFA_FM2JSContext::negative_operator(CFXJSE_Value* pThis,
Dan Sinclair1770c022016-03-14 14:14:16 -04005439 const CFX_ByteStringC& szFuncName,
5440 CFXJSE_Arguments& args) {
dsinclair947c8732016-06-08 20:40:30 -07005441 if (args.GetLength() != 1) {
dsinclair8f3074b2016-06-02 17:45:25 -07005442 ToJSContext(pThis, nullptr)->ThrowException(XFA_IDS_COMPILER_ERROR);
dsinclair947c8732016-06-08 20:40:30 -07005443 return;
Dan Sinclair1770c022016-03-14 14:14:16 -04005444 }
dsinclair947c8732016-06-08 20:40:30 -07005445
5446 std::unique_ptr<CFXJSE_Value> argOne = GetSimpleValue(pThis, args, 0);
5447 if (argOne->IsNull()) {
5448 args.GetReturnValue()->SetNull();
5449 return;
5450 }
5451 args.GetReturnValue()->SetDouble(0.0 - ValueToDouble(pThis, argOne.get()));
Dan Sinclair1770c022016-03-14 14:14:16 -04005452}
dsinclair48d91dd2016-05-31 11:54:01 -07005453
5454// static
dsinclair12a6b0c2016-05-26 11:14:08 -07005455void CXFA_FM2JSContext::logical_not_operator(CFXJSE_Value* pThis,
Dan Sinclair1770c022016-03-14 14:14:16 -04005456 const CFX_ByteStringC& szFuncName,
5457 CFXJSE_Arguments& args) {
dsinclair947c8732016-06-08 20:40:30 -07005458 if (args.GetLength() != 1) {
dsinclair8f3074b2016-06-02 17:45:25 -07005459 ToJSContext(pThis, nullptr)->ThrowException(XFA_IDS_COMPILER_ERROR);
dsinclair947c8732016-06-08 20:40:30 -07005460 return;
Dan Sinclair1770c022016-03-14 14:14:16 -04005461 }
dsinclair947c8732016-06-08 20:40:30 -07005462
5463 std::unique_ptr<CFXJSE_Value> argOne = GetSimpleValue(pThis, args, 0);
5464 if (argOne->IsNull()) {
5465 args.GetReturnValue()->SetNull();
5466 return;
5467 }
5468
5469 FX_DOUBLE first = ValueToDouble(pThis, argOne.get());
5470 args.GetReturnValue()->SetInteger((first == 0.0) ? 1 : 0);
Dan Sinclair1770c022016-03-14 14:14:16 -04005471}
dsinclair48d91dd2016-05-31 11:54:01 -07005472
5473// static
dsinclair12a6b0c2016-05-26 11:14:08 -07005474void CXFA_FM2JSContext::dot_accessor(CFXJSE_Value* pThis,
Dan Sinclair1770c022016-03-14 14:14:16 -04005475 const CFX_ByteStringC& szFuncName,
5476 CFXJSE_Arguments& args) {
dsinclair8f3074b2016-06-02 17:45:25 -07005477 CXFA_FM2JSContext* pContext = ToJSContext(pThis, nullptr);
dsinclairec3da5b2016-05-25 16:42:05 -07005478 v8::Isolate* pIsolate = pContext->GetScriptRuntime();
Dan Sinclair1770c022016-03-14 14:14:16 -04005479 int32_t argc = args.GetLength();
dsinclairbd136fb2016-06-09 11:47:51 -07005480 if (argc < 4 || argc > 5) {
dsinclair2235b7b2016-06-02 07:42:25 -07005481 pContext->ThrowException(XFA_IDS_COMPILER_ERROR);
dsinclairbd136fb2016-06-09 11:47:51 -07005482 return;
Dan Sinclair1770c022016-03-14 14:14:16 -04005483 }
dsinclairbd136fb2016-06-09 11:47:51 -07005484
5485 bool bIsStar = true;
5486 int32_t iIndexValue = 0;
5487 if (argc > 4) {
5488 bIsStar = false;
5489 iIndexValue = ValueToInteger(pThis, args.GetValue(4).get());
5490 }
5491
5492 CFX_ByteString szName = args.GetUTF8String(2);
5493 CFX_ByteString szSomExp;
5494 GenerateSomExpression(szName.AsStringC(), args.GetInt32(3), iIndexValue,
5495 bIsStar, szSomExp);
5496
5497 std::unique_ptr<CFXJSE_Value> argAccessor = args.GetValue(0);
5498 if (argAccessor->IsArray()) {
5499 std::unique_ptr<CFXJSE_Value> pLengthValue(new CFXJSE_Value(pIsolate));
5500 argAccessor->GetObjectProperty("length", pLengthValue.get());
5501 int32_t iLength = pLengthValue->ToInteger();
5502 CFXJSE_Value*** hResolveValues = FX_Alloc(CFXJSE_Value**, iLength - 2);
5503 int32_t* iSizes = FX_Alloc(int32_t, iLength - 2);
5504 for (int32_t i = 0; i < (iLength - 2); i++)
5505 iSizes[i] = 0;
5506
5507 std::unique_ptr<CFXJSE_Value> hJSObjValue(new CFXJSE_Value(pIsolate));
5508 FX_BOOL bAttribute = FALSE;
5509 int32_t iCounter = 0;
5510 for (int32_t i = 2; i < iLength; i++) {
5511 argAccessor->GetObjectPropertyByIdx(i, hJSObjValue.get());
5512
5513 XFA_RESOLVENODE_RS resoveNodeRS;
5514 if (ResolveObjects(pThis, hJSObjValue.get(), szSomExp.AsStringC(),
5515 resoveNodeRS, TRUE, szName.IsEmpty()) > 0) {
5516 ParseResolveResult(pThis, resoveNodeRS, hJSObjValue.get(),
5517 hResolveValues[i - 2], iSizes[i - 2], bAttribute);
5518 iCounter += iSizes[i - 2];
5519 }
5520 }
5521 if (iCounter < 1) {
5522 CFX_WideString wsPropertyName =
5523 CFX_WideString::FromUTF8(szName.AsStringC());
5524 CFX_WideString wsSomExpression =
5525 CFX_WideString::FromUTF8(szSomExp.AsStringC());
5526 pContext->ThrowException(XFA_IDS_ACCESS_PROPERTY_IN_NOT_OBJECT,
5527 wsPropertyName.c_str(), wsSomExpression.c_str());
5528 return;
5529 }
5530
5531 CFXJSE_Value** rgValues = FX_Alloc(CFXJSE_Value*, iCounter + 2);
5532 for (int32_t i = 0; i < (iCounter + 2); i++)
5533 rgValues[i] = new CFXJSE_Value(pIsolate);
5534
5535 rgValues[0]->SetInteger(1);
5536 if (bAttribute)
5537 rgValues[1]->SetString(szName.AsStringC());
5538 else
5539 rgValues[1]->SetNull();
5540
5541 int32_t iIndex = 2;
5542 for (int32_t i = 0; i < iLength - 2; i++) {
5543 for (int32_t j = 0; j < iSizes[i]; j++) {
5544 rgValues[iIndex]->Assign(hResolveValues[i][j]);
5545 iIndex++;
5546 }
5547 }
5548 args.GetReturnValue()->SetArray(iCounter + 2, rgValues);
5549
5550 for (int32_t i = 0; i < (iCounter + 2); i++)
5551 delete rgValues[i];
5552 FX_Free(rgValues);
5553
5554 for (int32_t i = 0; i < iLength - 2; i++) {
5555 for (int32_t j = 0; j < iSizes[i]; j++)
5556 delete hResolveValues[i][j];
5557
5558 if (iSizes[i] > 0)
5559 FX_Free(hResolveValues[i]);
5560 }
5561 FX_Free(hResolveValues);
5562 FX_Free(iSizes);
5563
5564 return;
5565 }
5566
5567 XFA_RESOLVENODE_RS resoveNodeRS;
5568 int32_t iRet = 0;
5569 CFX_ByteString bsAccessorName = args.GetUTF8String(1);
5570 if (argAccessor->IsObject() ||
5571 (argAccessor->IsNull() && bsAccessorName.IsEmpty())) {
5572 iRet = ResolveObjects(pThis, argAccessor.get(), szSomExp.AsStringC(),
5573 resoveNodeRS, TRUE, szName.IsEmpty());
5574 } else if (!argAccessor->IsObject() && !bsAccessorName.IsEmpty() &&
dsinclair38fd8442016-09-15 10:15:32 -07005575 GetObjectForName(pThis, argAccessor.get(),
5576 bsAccessorName.AsStringC())) {
dsinclairbd136fb2016-06-09 11:47:51 -07005577 iRet = ResolveObjects(pThis, argAccessor.get(), szSomExp.AsStringC(),
5578 resoveNodeRS, TRUE, szName.IsEmpty());
5579 }
5580 if (iRet < 1) {
5581 CFX_WideString wsPropertyName =
5582 CFX_WideString::FromUTF8(szName.AsStringC());
5583 CFX_WideString wsSomExpression =
5584 CFX_WideString::FromUTF8(szSomExp.AsStringC());
5585 pContext->ThrowException(XFA_IDS_ACCESS_PROPERTY_IN_NOT_OBJECT,
5586 wsPropertyName.c_str(), wsSomExpression.c_str());
5587 return;
5588 }
5589
5590 CFXJSE_Value** hResolveValues;
5591 int32_t iSize = 0;
5592 FX_BOOL bAttribute = FALSE;
5593 ParseResolveResult(pThis, resoveNodeRS, argAccessor.get(), hResolveValues,
5594 iSize, bAttribute);
5595 CFXJSE_Value** rgValues = FX_Alloc(CFXJSE_Value*, iSize + 2);
5596 for (int32_t i = 0; i < (iSize + 2); i++)
5597 rgValues[i] = new CFXJSE_Value(pIsolate);
5598
5599 rgValues[0]->SetInteger(1);
5600 if (bAttribute)
5601 rgValues[1]->SetString(szName.AsStringC());
5602 else
5603 rgValues[1]->SetNull();
5604
5605 for (int32_t i = 0; i < iSize; i++)
5606 rgValues[i + 2]->Assign(hResolveValues[i]);
5607
5608 args.GetReturnValue()->SetArray(iSize + 2, rgValues);
5609 for (int32_t i = 0; i < (iSize + 2); i++)
5610 delete rgValues[i];
5611 FX_Free(rgValues);
5612
5613 for (int32_t i = 0; i < iSize; i++)
5614 delete hResolveValues[i];
5615 FX_Free(hResolveValues);
Dan Sinclair1770c022016-03-14 14:14:16 -04005616}
dsinclair48d91dd2016-05-31 11:54:01 -07005617
5618// static
dsinclair12a6b0c2016-05-26 11:14:08 -07005619void CXFA_FM2JSContext::dotdot_accessor(CFXJSE_Value* pThis,
Dan Sinclair1770c022016-03-14 14:14:16 -04005620 const CFX_ByteStringC& szFuncName,
5621 CFXJSE_Arguments& args) {
dsinclair8f3074b2016-06-02 17:45:25 -07005622 CXFA_FM2JSContext* pContext = ToJSContext(pThis, nullptr);
dsinclairec3da5b2016-05-25 16:42:05 -07005623 v8::Isolate* pIsolate = pContext->GetScriptRuntime();
Dan Sinclair1770c022016-03-14 14:14:16 -04005624 int32_t argc = args.GetLength();
dsinclairbd136fb2016-06-09 11:47:51 -07005625 if (argc < 4 || argc > 5) {
dsinclair2235b7b2016-06-02 07:42:25 -07005626 pContext->ThrowException(XFA_IDS_COMPILER_ERROR);
dsinclairbd136fb2016-06-09 11:47:51 -07005627 return;
Dan Sinclair1770c022016-03-14 14:14:16 -04005628 }
dsinclairbd136fb2016-06-09 11:47:51 -07005629
5630 bool bIsStar = true;
5631 int32_t iIndexValue = 0;
5632 if (argc > 4) {
5633 bIsStar = false;
5634 iIndexValue = ValueToInteger(pThis, args.GetValue(4).get());
5635 }
5636
5637 CFX_ByteString szSomExp;
5638 CFX_ByteString szName = args.GetUTF8String(2);
5639 GenerateSomExpression(szName.AsStringC(), args.GetInt32(3), iIndexValue,
5640 bIsStar, szSomExp);
5641
5642 std::unique_ptr<CFXJSE_Value> argAccessor = args.GetValue(0);
5643 if (argAccessor->IsArray()) {
5644 std::unique_ptr<CFXJSE_Value> pLengthValue(new CFXJSE_Value(pIsolate));
5645 argAccessor->GetObjectProperty("length", pLengthValue.get());
5646 int32_t iLength = pLengthValue->ToInteger();
5647 int32_t iCounter = 0;
5648
5649 CFXJSE_Value*** hResolveValues = FX_Alloc(CFXJSE_Value**, iLength - 2);
5650 int32_t* iSizes = FX_Alloc(int32_t, iLength - 2);
5651 std::unique_ptr<CFXJSE_Value> hJSObjValue(new CFXJSE_Value(pIsolate));
5652 FX_BOOL bAttribute = FALSE;
5653 for (int32_t i = 2; i < iLength; i++) {
5654 argAccessor->GetObjectPropertyByIdx(i, hJSObjValue.get());
5655 XFA_RESOLVENODE_RS resoveNodeRS;
5656 if (ResolveObjects(pThis, hJSObjValue.get(), szSomExp.AsStringC(),
5657 resoveNodeRS, FALSE) > 0) {
5658 ParseResolveResult(pThis, resoveNodeRS, hJSObjValue.get(),
5659 hResolveValues[i - 2], iSizes[i - 2], bAttribute);
5660 iCounter += iSizes[i - 2];
5661 }
5662 }
5663 if (iCounter < 1) {
5664 CFX_WideString wsPropertyName =
5665 CFX_WideString::FromUTF8(szName.AsStringC());
5666 CFX_WideString wsSomExpression =
5667 CFX_WideString::FromUTF8(szSomExp.AsStringC());
5668 pContext->ThrowException(XFA_IDS_ACCESS_PROPERTY_IN_NOT_OBJECT,
5669 wsPropertyName.c_str(), wsSomExpression.c_str());
5670 return;
5671 }
5672
5673 CFXJSE_Value** rgValues = FX_Alloc(CFXJSE_Value*, iCounter + 2);
5674 for (int32_t i = 0; i < (iCounter + 2); i++)
5675 rgValues[i] = new CFXJSE_Value(pIsolate);
5676
5677 rgValues[0]->SetInteger(1);
5678 if (bAttribute)
5679 rgValues[1]->SetString(szName.AsStringC());
5680 else
5681 rgValues[1]->SetNull();
5682
5683 int32_t iIndex = 2;
5684 for (int32_t i = 0; i < iLength - 2; i++) {
5685 for (int32_t j = 0; j < iSizes[i]; j++) {
5686 rgValues[iIndex]->Assign(hResolveValues[i][j]);
5687 iIndex++;
5688 }
5689 }
5690 args.GetReturnValue()->SetArray(iCounter + 2, rgValues);
5691 for (int32_t i = 0; i < (iCounter + 2); i++)
5692 delete rgValues[i];
5693 FX_Free(rgValues);
5694
5695 for (int32_t i = 0; i < iLength - 2; i++) {
5696 for (int32_t j = 0; j < iSizes[i]; j++)
5697 delete hResolveValues[i][j];
5698 FX_Free(hResolveValues[i]);
5699 }
5700 FX_Free(hResolveValues);
5701 FX_Free(iSizes);
5702 return;
5703 }
5704
5705 XFA_RESOLVENODE_RS resoveNodeRS;
5706 int32_t iRet = 0;
5707 CFX_ByteString bsAccessorName = args.GetUTF8String(1);
5708 if (argAccessor->IsObject() ||
5709 (argAccessor->IsNull() && bsAccessorName.IsEmpty())) {
5710 iRet = ResolveObjects(pThis, argAccessor.get(), szSomExp.AsStringC(),
5711 resoveNodeRS, FALSE);
5712 } else if (!argAccessor->IsObject() && !bsAccessorName.IsEmpty() &&
dsinclair38fd8442016-09-15 10:15:32 -07005713 GetObjectForName(pThis, argAccessor.get(),
5714 bsAccessorName.AsStringC())) {
dsinclairbd136fb2016-06-09 11:47:51 -07005715 iRet = ResolveObjects(pThis, argAccessor.get(), szSomExp.AsStringC(),
5716 resoveNodeRS, FALSE);
5717 }
5718 if (iRet < 1) {
5719 CFX_WideString wsPropertyName =
5720 CFX_WideString::FromUTF8(szName.AsStringC());
5721 CFX_WideString wsSomExpression =
5722 CFX_WideString::FromUTF8(szSomExp.AsStringC());
5723 pContext->ThrowException(XFA_IDS_ACCESS_PROPERTY_IN_NOT_OBJECT,
5724 wsPropertyName.c_str(), wsSomExpression.c_str());
5725 return;
5726 }
5727
5728 CFXJSE_Value** hResolveValues;
5729 int32_t iSize = 0;
5730 FX_BOOL bAttribute = FALSE;
5731 ParseResolveResult(pThis, resoveNodeRS, argAccessor.get(), hResolveValues,
5732 iSize, bAttribute);
5733 CFXJSE_Value** rgValues = FX_Alloc(CFXJSE_Value*, iSize + 2);
5734 for (int32_t i = 0; i < (iSize + 2); i++)
5735 rgValues[i] = new CFXJSE_Value(pIsolate);
5736
5737 rgValues[0]->SetInteger(1);
5738 if (bAttribute)
5739 rgValues[1]->SetString(szName.AsStringC());
5740 else
5741 rgValues[1]->SetNull();
5742
5743 for (int32_t i = 0; i < iSize; i++)
5744 rgValues[i + 2]->Assign(hResolveValues[i]);
5745
5746 args.GetReturnValue()->SetArray(iSize + 2, rgValues);
5747
5748 for (int32_t i = 0; i < (iSize + 2); i++)
5749 delete rgValues[i];
5750 FX_Free(rgValues);
5751
5752 for (int32_t i = 0; i < iSize; i++)
5753 delete hResolveValues[i];
5754 FX_Free(hResolveValues);
Dan Sinclair1770c022016-03-14 14:14:16 -04005755}
dsinclair48d91dd2016-05-31 11:54:01 -07005756
5757// static
dsinclair12a6b0c2016-05-26 11:14:08 -07005758void CXFA_FM2JSContext::eval_translation(CFXJSE_Value* pThis,
Dan Sinclair1770c022016-03-14 14:14:16 -04005759 const CFX_ByteStringC& szFuncName,
5760 CFXJSE_Arguments& args) {
dsinclair8f3074b2016-06-02 17:45:25 -07005761 CXFA_FM2JSContext* pContext = ToJSContext(pThis, nullptr);
dsinclairbd136fb2016-06-09 11:47:51 -07005762 if (args.GetLength() != 1) {
dsinclair2235b7b2016-06-02 07:42:25 -07005763 pContext->ThrowException(XFA_IDS_INCORRECT_NUMBER_OF_METHOD, L"Eval");
dsinclairbd136fb2016-06-09 11:47:51 -07005764 return;
Dan Sinclair1770c022016-03-14 14:14:16 -04005765 }
dsinclairbd136fb2016-06-09 11:47:51 -07005766
5767 std::unique_ptr<CFXJSE_Value> argOne = GetSimpleValue(pThis, args, 0);
5768 CFX_ByteString argString;
5769 ValueToUTF8String(argOne.get(), argString);
5770 if (argString.IsEmpty()) {
5771 pContext->ThrowException(XFA_IDS_ARGUMENT_MISMATCH);
5772 return;
5773 }
5774
5775 CFX_WideString scriptString = CFX_WideString::FromUTF8(argString.AsStringC());
5776 CFX_WideTextBuf wsJavaScriptBuf;
5777 CFX_WideString wsError;
5778 CXFA_FM2JSContext::Translate(scriptString.AsStringC(), wsJavaScriptBuf,
5779 wsError);
5780 if (!wsError.IsEmpty()) {
5781 pContext->ThrowException(XFA_IDS_COMPILER_ERROR);
5782 return;
5783 }
5784
5785 CFX_WideString javaScript = wsJavaScriptBuf.MakeString();
5786 args.GetReturnValue()->SetString(
5787 FX_UTF8Encode(javaScript.c_str(), javaScript.GetLength()).AsStringC());
Dan Sinclair1770c022016-03-14 14:14:16 -04005788}
dsinclair48d91dd2016-05-31 11:54:01 -07005789
5790// static
dsinclair12a6b0c2016-05-26 11:14:08 -07005791void CXFA_FM2JSContext::is_fm_object(CFXJSE_Value* pThis,
Dan Sinclair1770c022016-03-14 14:14:16 -04005792 const CFX_ByteStringC& szFuncName,
5793 CFXJSE_Arguments& args) {
dsinclairbd136fb2016-06-09 11:47:51 -07005794 if (args.GetLength() != 1) {
dsinclairf27aeec2016-06-07 19:36:18 -07005795 args.GetReturnValue()->SetBoolean(FALSE);
dsinclairbd136fb2016-06-09 11:47:51 -07005796 return;
Dan Sinclair1770c022016-03-14 14:14:16 -04005797 }
dsinclairbd136fb2016-06-09 11:47:51 -07005798
5799 std::unique_ptr<CFXJSE_Value> argOne = args.GetValue(0);
5800 args.GetReturnValue()->SetBoolean(argOne->IsObject());
Dan Sinclair1770c022016-03-14 14:14:16 -04005801}
dsinclair48d91dd2016-05-31 11:54:01 -07005802
5803// static
dsinclair12a6b0c2016-05-26 11:14:08 -07005804void CXFA_FM2JSContext::is_fm_array(CFXJSE_Value* pThis,
Dan Sinclair1770c022016-03-14 14:14:16 -04005805 const CFX_ByteStringC& szFuncName,
5806 CFXJSE_Arguments& args) {
dsinclairbd136fb2016-06-09 11:47:51 -07005807 if (args.GetLength() != 1) {
dsinclairf27aeec2016-06-07 19:36:18 -07005808 args.GetReturnValue()->SetBoolean(FALSE);
dsinclairbd136fb2016-06-09 11:47:51 -07005809 return;
Dan Sinclair1770c022016-03-14 14:14:16 -04005810 }
dsinclairbd136fb2016-06-09 11:47:51 -07005811
5812 std::unique_ptr<CFXJSE_Value> argOne = args.GetValue(0);
5813 args.GetReturnValue()->SetBoolean(argOne->IsArray());
Dan Sinclair1770c022016-03-14 14:14:16 -04005814}
dsinclair48d91dd2016-05-31 11:54:01 -07005815
5816// static
dsinclair12a6b0c2016-05-26 11:14:08 -07005817void CXFA_FM2JSContext::get_fm_value(CFXJSE_Value* pThis,
Dan Sinclair1770c022016-03-14 14:14:16 -04005818 const CFX_ByteStringC& szFuncName,
5819 CFXJSE_Arguments& args) {
dsinclair8f3074b2016-06-02 17:45:25 -07005820 CXFA_FM2JSContext* pContext = ToJSContext(pThis, nullptr);
dsinclairbd136fb2016-06-09 11:47:51 -07005821 if (args.GetLength() != 1) {
dsinclair2235b7b2016-06-02 07:42:25 -07005822 pContext->ThrowException(XFA_IDS_COMPILER_ERROR);
dsinclairbd136fb2016-06-09 11:47:51 -07005823 return;
Dan Sinclair1770c022016-03-14 14:14:16 -04005824 }
dsinclairbd136fb2016-06-09 11:47:51 -07005825
5826 std::unique_ptr<CFXJSE_Value> argOne = args.GetValue(0);
5827 if (argOne->IsArray()) {
5828 v8::Isolate* pIsolate = pContext->GetScriptRuntime();
5829 std::unique_ptr<CFXJSE_Value> propertyValue(new CFXJSE_Value(pIsolate));
5830 std::unique_ptr<CFXJSE_Value> jsObjectValue(new CFXJSE_Value(pIsolate));
5831 argOne->GetObjectPropertyByIdx(1, propertyValue.get());
5832 argOne->GetObjectPropertyByIdx(2, jsObjectValue.get());
5833 if (propertyValue->IsNull()) {
5834 GetObjectDefaultValue(jsObjectValue.get(), args.GetReturnValue());
5835 return;
5836 }
5837
dsinclair2f5582f2016-06-09 11:48:23 -07005838 jsObjectValue->GetObjectProperty(propertyValue->ToString().AsStringC(),
dsinclairbd136fb2016-06-09 11:47:51 -07005839 args.GetReturnValue());
5840 return;
5841 }
5842
5843 if (argOne->IsObject()) {
5844 GetObjectDefaultValue(argOne.get(), args.GetReturnValue());
5845 return;
5846 }
5847
5848 args.GetReturnValue()->Assign(argOne.get());
Dan Sinclair1770c022016-03-14 14:14:16 -04005849}
dsinclair48d91dd2016-05-31 11:54:01 -07005850
5851// static
dsinclair12a6b0c2016-05-26 11:14:08 -07005852void CXFA_FM2JSContext::get_fm_jsobj(CFXJSE_Value* pThis,
Dan Sinclair1770c022016-03-14 14:14:16 -04005853 const CFX_ByteStringC& szFuncName,
5854 CFXJSE_Arguments& args) {
dsinclairbd136fb2016-06-09 11:47:51 -07005855 if (args.GetLength() != 1) {
5856 ToJSContext(pThis, nullptr)->ThrowException(XFA_IDS_COMPILER_ERROR);
5857 return;
Dan Sinclair1770c022016-03-14 14:14:16 -04005858 }
dsinclairbd136fb2016-06-09 11:47:51 -07005859
5860 std::unique_ptr<CFXJSE_Value> argOne = args.GetValue(0);
5861 if (!argOne->IsArray()) {
5862 args.GetReturnValue()->Assign(argOne.get());
5863 return;
5864 }
5865
5866#ifndef NDEBUG
5867 CXFA_FM2JSContext* pContext = ToJSContext(pThis, nullptr);
5868 v8::Isolate* pIsolate = pContext->GetScriptRuntime();
5869 std::unique_ptr<CFXJSE_Value> lengthValue(new CFXJSE_Value(pIsolate));
5870 argOne->GetObjectProperty("length", lengthValue.get());
5871 ASSERT(lengthValue->ToInteger() >= 3);
5872#endif
5873
5874 argOne->GetObjectPropertyByIdx(2, args.GetReturnValue());
Dan Sinclair1770c022016-03-14 14:14:16 -04005875}
dsinclair48d91dd2016-05-31 11:54:01 -07005876
5877// static
dsinclair12a6b0c2016-05-26 11:14:08 -07005878void CXFA_FM2JSContext::fm_var_filter(CFXJSE_Value* pThis,
Dan Sinclair1770c022016-03-14 14:14:16 -04005879 const CFX_ByteStringC& szFuncName,
5880 CFXJSE_Arguments& args) {
dsinclair8f3074b2016-06-02 17:45:25 -07005881 CXFA_FM2JSContext* pContext = ToJSContext(pThis, nullptr);
dsinclairbd136fb2016-06-09 11:47:51 -07005882 if (args.GetLength() != 1) {
dsinclair2235b7b2016-06-02 07:42:25 -07005883 pContext->ThrowException(XFA_IDS_COMPILER_ERROR);
dsinclairbd136fb2016-06-09 11:47:51 -07005884 return;
Dan Sinclair1770c022016-03-14 14:14:16 -04005885 }
dsinclairbd136fb2016-06-09 11:47:51 -07005886
5887 v8::Isolate* pIsolate = pContext->GetScriptRuntime();
5888 std::unique_ptr<CFXJSE_Value> argOne = args.GetValue(0);
5889 if (!argOne->IsArray()) {
5890 std::unique_ptr<CFXJSE_Value> simpleValue = GetSimpleValue(pThis, args, 0);
5891 args.GetReturnValue()->Assign(simpleValue.get());
5892 return;
5893 }
5894
5895#ifndef NDEBUG
5896 std::unique_ptr<CFXJSE_Value> lengthValue(new CFXJSE_Value(pIsolate));
5897 argOne->GetObjectProperty("length", lengthValue.get());
5898 ASSERT(lengthValue->ToInteger() >= 3);
5899#endif
5900
5901 std::unique_ptr<CFXJSE_Value> flagsValue(new CFXJSE_Value(pIsolate));
5902 argOne->GetObjectPropertyByIdx(0, flagsValue.get());
5903 int32_t iFlags = flagsValue->ToInteger();
5904 if (iFlags != 3 && iFlags != 4) {
5905 std::unique_ptr<CFXJSE_Value> simpleValue = GetSimpleValue(pThis, args, 0);
5906 args.GetReturnValue()->Assign(simpleValue.get());
5907 return;
5908 }
5909
5910 if (iFlags == 4) {
5911 CFXJSE_Value* rgValues[3];
5912 for (int32_t i = 0; i < 3; i++)
5913 rgValues[i] = new CFXJSE_Value(pIsolate);
5914
5915 rgValues[0]->SetInteger(3);
5916 rgValues[1]->SetNull();
5917 rgValues[2]->SetNull();
5918 args.GetReturnValue()->SetArray(3, rgValues);
5919 for (int32_t i = 0; i < 3; i++)
5920 delete rgValues[i];
5921
5922 return;
5923 }
5924
5925 std::unique_ptr<CFXJSE_Value> objectValue(new CFXJSE_Value(pIsolate));
5926 argOne->GetObjectPropertyByIdx(2, objectValue.get());
5927 if (objectValue->IsNull()) {
5928 pContext->ThrowException(XFA_IDS_COMPILER_ERROR);
5929 return;
5930 }
5931 args.GetReturnValue()->Assign(argOne.get());
Dan Sinclair1770c022016-03-14 14:14:16 -04005932}
dsinclair48d91dd2016-05-31 11:54:01 -07005933
5934// static
dsinclair12a6b0c2016-05-26 11:14:08 -07005935void CXFA_FM2JSContext::concat_fm_object(CFXJSE_Value* pThis,
Dan Sinclair1770c022016-03-14 14:14:16 -04005936 const CFX_ByteStringC& szFuncName,
5937 CFXJSE_Arguments& args) {
dsinclair8f3074b2016-06-02 17:45:25 -07005938 v8::Isolate* pIsolate = ToJSContext(pThis, nullptr)->GetScriptRuntime();
Dan Sinclair1770c022016-03-14 14:14:16 -04005939 uint32_t iLength = 0;
dsinclair48d91dd2016-05-31 11:54:01 -07005940 int32_t argc = args.GetLength();
dsinclair86fad992016-05-31 11:34:04 -07005941 std::vector<std::unique_ptr<CFXJSE_Value>> argValues;
dsinclair48d91dd2016-05-31 11:54:01 -07005942 for (int32_t i = 0; i < argc; i++) {
dsinclair86fad992016-05-31 11:34:04 -07005943 argValues.push_back(args.GetValue(i));
dsinclair769b1372016-06-08 13:12:41 -07005944 if (argValues[i]->IsArray()) {
dsinclair86fad992016-05-31 11:34:04 -07005945 std::unique_ptr<CFXJSE_Value> lengthValue(new CFXJSE_Value(pIsolate));
dsinclairf27aeec2016-06-07 19:36:18 -07005946 argValues[i]->GetObjectProperty("length", lengthValue.get());
5947 int32_t length = lengthValue->ToInteger();
Dan Sinclair1770c022016-03-14 14:14:16 -04005948 iLength = iLength + ((length > 2) ? (length - 2) : 0);
Dan Sinclair1770c022016-03-14 14:14:16 -04005949 }
5950 iLength += 1;
5951 }
dsinclairbd136fb2016-06-09 11:47:51 -07005952
dsinclair12a6b0c2016-05-26 11:14:08 -07005953 CFXJSE_Value** returnValues = FX_Alloc(CFXJSE_Value*, iLength);
dsinclair86fad992016-05-31 11:34:04 -07005954 for (int32_t i = 0; i < (int32_t)iLength; i++)
5955 returnValues[i] = new CFXJSE_Value(pIsolate);
5956
Dan Sinclair1770c022016-03-14 14:14:16 -04005957 int32_t index = 0;
dsinclair48d91dd2016-05-31 11:54:01 -07005958 for (int32_t i = 0; i < argc; i++) {
dsinclair769b1372016-06-08 13:12:41 -07005959 if (argValues[i]->IsArray()) {
dsinclair86fad992016-05-31 11:34:04 -07005960 std::unique_ptr<CFXJSE_Value> lengthValue(new CFXJSE_Value(pIsolate));
dsinclairf27aeec2016-06-07 19:36:18 -07005961 argValues[i]->GetObjectProperty("length", lengthValue.get());
5962 int32_t length = lengthValue->ToInteger();
Dan Sinclair1770c022016-03-14 14:14:16 -04005963 for (int32_t j = 2; j < length; j++) {
dsinclairf27aeec2016-06-07 19:36:18 -07005964 argValues[i]->GetObjectPropertyByIdx(j, returnValues[index]);
Dan Sinclair1770c022016-03-14 14:14:16 -04005965 index++;
5966 }
Dan Sinclair1770c022016-03-14 14:14:16 -04005967 }
dsinclairf27aeec2016-06-07 19:36:18 -07005968 returnValues[index]->Assign(argValues[i].get());
Dan Sinclair1770c022016-03-14 14:14:16 -04005969 index++;
5970 }
dsinclairf27aeec2016-06-07 19:36:18 -07005971 args.GetReturnValue()->SetArray(iLength, returnValues);
dsinclair86fad992016-05-31 11:34:04 -07005972 for (int32_t i = 0; i < (int32_t)iLength; i++)
5973 delete returnValues[i];
5974
Dan Sinclair1770c022016-03-14 14:14:16 -04005975 FX_Free(returnValues);
5976}
dsinclair48d91dd2016-05-31 11:54:01 -07005977
5978// static
dsinclair86fad992016-05-31 11:34:04 -07005979std::unique_ptr<CFXJSE_Value> CXFA_FM2JSContext::GetSimpleValue(
5980 CFXJSE_Value* pThis,
5981 CFXJSE_Arguments& args,
5982 uint32_t index) {
dsinclair8f3074b2016-06-02 17:45:25 -07005983 v8::Isolate* pIsolate = ToJSContext(pThis, nullptr)->GetScriptRuntime();
dsinclair43854a52016-04-27 12:26:00 -07005984 ASSERT(index < (uint32_t)args.GetLength());
dsinclairbd136fb2016-06-09 11:47:51 -07005985
dsinclair86fad992016-05-31 11:34:04 -07005986 std::unique_ptr<CFXJSE_Value> argIndex = args.GetValue(index);
dsinclairbd136fb2016-06-09 11:47:51 -07005987 if (!argIndex->IsArray() && !argIndex->IsObject())
5988 return argIndex;
5989
dsinclair769b1372016-06-08 13:12:41 -07005990 if (argIndex->IsArray()) {
dsinclair86fad992016-05-31 11:34:04 -07005991 std::unique_ptr<CFXJSE_Value> lengthValue(new CFXJSE_Value(pIsolate));
dsinclairf27aeec2016-06-07 19:36:18 -07005992 argIndex->GetObjectProperty("length", lengthValue.get());
5993 int32_t iLength = lengthValue->ToInteger();
dsinclair86fad992016-05-31 11:34:04 -07005994 std::unique_ptr<CFXJSE_Value> simpleValue(new CFXJSE_Value(pIsolate));
dsinclairbd136fb2016-06-09 11:47:51 -07005995 if (iLength < 3) {
dsinclairf27aeec2016-06-07 19:36:18 -07005996 simpleValue.get()->SetUndefined();
dsinclairbd136fb2016-06-09 11:47:51 -07005997 return simpleValue;
Dan Sinclair1770c022016-03-14 14:14:16 -04005998 }
dsinclairbd136fb2016-06-09 11:47:51 -07005999
6000 std::unique_ptr<CFXJSE_Value> propertyValue(new CFXJSE_Value(pIsolate));
6001 std::unique_ptr<CFXJSE_Value> jsObjectValue(new CFXJSE_Value(pIsolate));
6002 argIndex->GetObjectPropertyByIdx(1, propertyValue.get());
6003 argIndex->GetObjectPropertyByIdx(2, jsObjectValue.get());
6004 if (propertyValue->IsNull()) {
6005 GetObjectDefaultValue(jsObjectValue.get(), simpleValue.get());
6006 return simpleValue;
6007 }
6008
dsinclair2f5582f2016-06-09 11:48:23 -07006009 jsObjectValue->GetObjectProperty(propertyValue->ToString().AsStringC(),
dsinclairbd136fb2016-06-09 11:47:51 -07006010 simpleValue.get());
Dan Sinclair1770c022016-03-14 14:14:16 -04006011 return simpleValue;
Dan Sinclair1770c022016-03-14 14:14:16 -04006012 }
dsinclairbd136fb2016-06-09 11:47:51 -07006013
6014 std::unique_ptr<CFXJSE_Value> defaultValue(new CFXJSE_Value(pIsolate));
6015 GetObjectDefaultValue(argIndex.get(), defaultValue.get());
6016 return defaultValue;
Dan Sinclair1770c022016-03-14 14:14:16 -04006017}
dsinclair12a6b0c2016-05-26 11:14:08 -07006018
dsinclair48d91dd2016-05-31 11:54:01 -07006019// static
dsinclair12a6b0c2016-05-26 11:14:08 -07006020FX_BOOL CXFA_FM2JSContext::ValueIsNull(CFXJSE_Value* pThis, CFXJSE_Value* arg) {
dsinclairbd136fb2016-06-09 11:47:51 -07006021 if (!arg || arg->IsNull())
6022 return TRUE;
6023
6024 if (!arg->IsArray() && !arg->IsObject())
6025 return FALSE;
6026
dsinclair8f3074b2016-06-02 17:45:25 -07006027 v8::Isolate* pIsolate = ToJSContext(pThis, nullptr)->GetScriptRuntime();
dsinclairbd136fb2016-06-09 11:47:51 -07006028 if (arg->IsArray()) {
dsinclair12a6b0c2016-05-26 11:14:08 -07006029 int32_t iLength = hvalue_get_array_length(pThis, arg);
dsinclairbd136fb2016-06-09 11:47:51 -07006030 if (iLength < 3)
6031 return TRUE;
6032
6033 std::unique_ptr<CFXJSE_Value> propertyValue(new CFXJSE_Value(pIsolate));
6034 std::unique_ptr<CFXJSE_Value> jsObjectValue(new CFXJSE_Value(pIsolate));
6035 arg->GetObjectPropertyByIdx(1, propertyValue.get());
6036 arg->GetObjectPropertyByIdx(2, jsObjectValue.get());
6037 if (propertyValue->IsNull()) {
6038 std::unique_ptr<CFXJSE_Value> defaultValue(new CFXJSE_Value(pIsolate));
6039 GetObjectDefaultValue(jsObjectValue.get(), defaultValue.get());
6040 return defaultValue->IsNull();
Dan Sinclair1770c022016-03-14 14:14:16 -04006041 }
dsinclairbd136fb2016-06-09 11:47:51 -07006042
dsinclairbd136fb2016-06-09 11:47:51 -07006043 std::unique_ptr<CFXJSE_Value> newPropertyValue(new CFXJSE_Value(pIsolate));
dsinclair2f5582f2016-06-09 11:48:23 -07006044 jsObjectValue->GetObjectProperty(propertyValue->ToString().AsStringC(),
dsinclairbd136fb2016-06-09 11:47:51 -07006045 newPropertyValue.get());
6046 return newPropertyValue->IsNull();
Dan Sinclair1770c022016-03-14 14:14:16 -04006047 }
dsinclairbd136fb2016-06-09 11:47:51 -07006048
6049 std::unique_ptr<CFXJSE_Value> defaultValue(new CFXJSE_Value(pIsolate));
6050 GetObjectDefaultValue(arg, defaultValue.get());
6051 return defaultValue->IsNull();
Dan Sinclair1770c022016-03-14 14:14:16 -04006052}
dsinclair12a6b0c2016-05-26 11:14:08 -07006053
dsinclair48d91dd2016-05-31 11:54:01 -07006054// static
dsinclair12a6b0c2016-05-26 11:14:08 -07006055int32_t CXFA_FM2JSContext::hvalue_get_array_length(CFXJSE_Value* pThis,
6056 CFXJSE_Value* arg) {
dsinclair769b1372016-06-08 13:12:41 -07006057 if (!arg || !arg->IsArray())
6058 return 0;
6059
dsinclair8f3074b2016-06-02 17:45:25 -07006060 v8::Isolate* pIsolate = ToJSContext(pThis, nullptr)->GetScriptRuntime();
dsinclair769b1372016-06-08 13:12:41 -07006061 std::unique_ptr<CFXJSE_Value> lengthValue(new CFXJSE_Value(pIsolate));
6062 arg->GetObjectProperty("length", lengthValue.get());
6063 return lengthValue->ToInteger();
Dan Sinclair1770c022016-03-14 14:14:16 -04006064}
dsinclair48d91dd2016-05-31 11:54:01 -07006065
6066// static
dsinclair12a6b0c2016-05-26 11:14:08 -07006067FX_BOOL CXFA_FM2JSContext::simpleValueCompare(CFXJSE_Value* pThis,
6068 CFXJSE_Value* firstValue,
6069 CFXJSE_Value* secondValue) {
dsinclair769b1372016-06-08 13:12:41 -07006070 if (!firstValue)
6071 return FALSE;
6072
dsinclair769b1372016-06-08 13:12:41 -07006073 if (firstValue->IsString()) {
Dan Sinclair1770c022016-03-14 14:14:16 -04006074 CFX_ByteString firstString, secondString;
dsinclair12a6b0c2016-05-26 11:14:08 -07006075 ValueToUTF8String(firstValue, firstString);
6076 ValueToUTF8String(secondValue, secondString);
dsinclairbd136fb2016-06-09 11:47:51 -07006077 return firstString == secondString;
6078 }
6079 if (firstValue->IsNumber()) {
dsinclair12a6b0c2016-05-26 11:14:08 -07006080 FX_FLOAT first = ValueToFloat(pThis, firstValue);
6081 FX_FLOAT second = ValueToFloat(pThis, secondValue);
dsinclairbd136fb2016-06-09 11:47:51 -07006082 return (first == second);
Dan Sinclair1770c022016-03-14 14:14:16 -04006083 }
dsinclairbd136fb2016-06-09 11:47:51 -07006084 if (firstValue->IsBoolean())
6085 return (firstValue->ToBoolean() == secondValue->ToBoolean());
6086
6087 return firstValue->IsNull() && secondValue && secondValue->IsNull();
Dan Sinclair1770c022016-03-14 14:14:16 -04006088}
dsinclair48d91dd2016-05-31 11:54:01 -07006089
6090// static
dsinclair12a6b0c2016-05-26 11:14:08 -07006091void CXFA_FM2JSContext::unfoldArgs(CFXJSE_Value* pThis,
Dan Sinclair1770c022016-03-14 14:14:16 -04006092 CFXJSE_Arguments& args,
dsinclair12a6b0c2016-05-26 11:14:08 -07006093 CFXJSE_Value**& resultValues,
Dan Sinclair1770c022016-03-14 14:14:16 -04006094 int32_t& iCount,
6095 int32_t iStart) {
Dan Sinclair1770c022016-03-14 14:14:16 -04006096 iCount = 0;
dsinclairbd136fb2016-06-09 11:47:51 -07006097
6098 v8::Isolate* pIsolate = ToJSContext(pThis, nullptr)->GetScriptRuntime();
Dan Sinclair1770c022016-03-14 14:14:16 -04006099 int32_t argc = args.GetLength();
dsinclair86fad992016-05-31 11:34:04 -07006100 std::vector<std::unique_ptr<CFXJSE_Value>> argsValue;
6101 for (int32_t i = 0; i < argc - iStart; i++) {
6102 argsValue.push_back(args.GetValue(i + iStart));
dsinclair769b1372016-06-08 13:12:41 -07006103 if (argsValue[i]->IsArray()) {
dsinclair86fad992016-05-31 11:34:04 -07006104 std::unique_ptr<CFXJSE_Value> lengthValue(new CFXJSE_Value(pIsolate));
dsinclairf27aeec2016-06-07 19:36:18 -07006105 argsValue[i]->GetObjectProperty("length", lengthValue.get());
6106 int32_t iLength = lengthValue->ToInteger();
Dan Sinclair1770c022016-03-14 14:14:16 -04006107 iCount += ((iLength > 2) ? (iLength - 2) : 0);
6108 } else {
6109 iCount += 1;
6110 }
6111 }
dsinclair12a6b0c2016-05-26 11:14:08 -07006112 resultValues = FX_Alloc(CFXJSE_Value*, iCount);
dsinclair86fad992016-05-31 11:34:04 -07006113 for (int32_t i = 0; i < iCount; i++)
6114 resultValues[i] = new CFXJSE_Value(pIsolate);
6115
Dan Sinclair1770c022016-03-14 14:14:16 -04006116 int32_t index = 0;
dsinclair86fad992016-05-31 11:34:04 -07006117 for (int32_t i = 0; i < argc - iStart; i++) {
dsinclair769b1372016-06-08 13:12:41 -07006118 if (argsValue[i]->IsArray()) {
dsinclair86fad992016-05-31 11:34:04 -07006119 std::unique_ptr<CFXJSE_Value> lengthValue(new CFXJSE_Value(pIsolate));
dsinclairf27aeec2016-06-07 19:36:18 -07006120 argsValue[i]->GetObjectProperty("length", lengthValue.get());
6121 int32_t iLength = lengthValue->ToInteger();
dsinclairbd136fb2016-06-09 11:47:51 -07006122 if (iLength < 3)
6123 continue;
6124
6125 std::unique_ptr<CFXJSE_Value> propertyValue(new CFXJSE_Value(pIsolate));
6126 std::unique_ptr<CFXJSE_Value> jsObjectValue(new CFXJSE_Value(pIsolate));
6127 argsValue[i]->GetObjectPropertyByIdx(1, propertyValue.get());
6128 if (propertyValue->IsNull()) {
6129 for (int32_t j = 2; j < iLength; j++) {
6130 argsValue[i]->GetObjectPropertyByIdx(j, jsObjectValue.get());
6131 GetObjectDefaultValue(jsObjectValue.get(), resultValues[index]);
6132 index++;
6133 }
6134 } else {
dsinclairbd136fb2016-06-09 11:47:51 -07006135 for (int32_t j = 2; j < iLength; j++) {
6136 argsValue[i]->GetObjectPropertyByIdx(j, jsObjectValue.get());
dsinclair2f5582f2016-06-09 11:48:23 -07006137 jsObjectValue->GetObjectProperty(
6138 propertyValue->ToString().AsStringC(), resultValues[index]);
dsinclairbd136fb2016-06-09 11:47:51 -07006139 index++;
Dan Sinclair1770c022016-03-14 14:14:16 -04006140 }
Dan Sinclair1770c022016-03-14 14:14:16 -04006141 }
dsinclair769b1372016-06-08 13:12:41 -07006142 } else if (argsValue[i]->IsObject()) {
dsinclair86fad992016-05-31 11:34:04 -07006143 GetObjectDefaultValue(argsValue[i].get(), resultValues[index]);
Dan Sinclair1770c022016-03-14 14:14:16 -04006144 index++;
6145 } else {
dsinclairf27aeec2016-06-07 19:36:18 -07006146 resultValues[index]->Assign(argsValue[i].get());
Dan Sinclair1770c022016-03-14 14:14:16 -04006147 index++;
6148 }
6149 }
Dan Sinclair1770c022016-03-14 14:14:16 -04006150}
dsinclair86fad992016-05-31 11:34:04 -07006151
dsinclair48d91dd2016-05-31 11:54:01 -07006152// static
dsinclair8f3074b2016-06-02 17:45:25 -07006153void CXFA_FM2JSContext::GetObjectDefaultValue(CFXJSE_Value* pValue,
dsinclair12a6b0c2016-05-26 11:14:08 -07006154 CFXJSE_Value* pDefaultValue) {
dsinclair8f3074b2016-06-02 17:45:25 -07006155 CXFA_Node* pNode = ToNode(CXFA_ScriptContext::ToObject(pValue, nullptr));
6156 if (!pNode) {
dsinclairf27aeec2016-06-07 19:36:18 -07006157 pDefaultValue->SetNull();
dsinclair8f3074b2016-06-02 17:45:25 -07006158 return;
Dan Sinclair1770c022016-03-14 14:14:16 -04006159 }
dsinclair8f3074b2016-06-02 17:45:25 -07006160 pNode->Script_Som_DefaultValue(pDefaultValue, FALSE, (XFA_ATTRIBUTE)-1);
Dan Sinclair1770c022016-03-14 14:14:16 -04006161}
dsinclair48d91dd2016-05-31 11:54:01 -07006162
6163// static
dsinclair8f3074b2016-06-02 17:45:25 -07006164FX_BOOL CXFA_FM2JSContext::SetObjectDefaultValue(CFXJSE_Value* pValue,
dsinclair12a6b0c2016-05-26 11:14:08 -07006165 CFXJSE_Value* hNewValue) {
dsinclair8f3074b2016-06-02 17:45:25 -07006166 CXFA_Node* pNode = ToNode(CXFA_ScriptContext::ToObject(pValue, nullptr));
6167 if (!pNode)
6168 return FALSE;
6169
6170 pNode->Script_Som_DefaultValue(hNewValue, TRUE, (XFA_ATTRIBUTE)-1);
6171 return TRUE;
Dan Sinclair1770c022016-03-14 14:14:16 -04006172}
dsinclair48d91dd2016-05-31 11:54:01 -07006173
6174// static
Dan Sinclair1770c022016-03-14 14:14:16 -04006175void CXFA_FM2JSContext::GenerateSomExpression(const CFX_ByteStringC& szName,
6176 int32_t iIndexFlags,
6177 int32_t iIndexValue,
dsinclairbd136fb2016-06-09 11:47:51 -07006178 bool bIsStar,
Dan Sinclair1770c022016-03-14 14:14:16 -04006179 CFX_ByteString& szSomExp) {
6180 if (bIsStar) {
6181 szSomExp = szName + "[*]";
6182 return;
6183 }
6184 if (iIndexFlags == 0) {
6185 szSomExp = szName;
6186 return;
6187 }
6188 if (iIndexFlags == 1 || iIndexValue == 0) {
6189 szSomExp = szName + "[" +
6190 CFX_ByteString::FormatInteger(iIndexValue, FXFORMAT_SIGNED) +
6191 "]";
6192 } else if (iIndexFlags == 2) {
6193 szSomExp = (iIndexValue < 0) ? (szName + "[-") : (szName + "[+");
6194 iIndexValue = (iIndexValue < 0) ? (0 - iIndexValue) : iIndexValue;
6195 szSomExp += CFX_ByteString::FormatInteger(iIndexValue);
6196 szSomExp += "]";
6197 } else {
6198 szSomExp = (iIndexValue < 0) ? (szName + "[") : (szName + "[-");
6199 iIndexValue = (iIndexValue < 0) ? (0 - iIndexValue) : iIndexValue;
6200 szSomExp += CFX_ByteString::FormatInteger(iIndexValue);
6201 szSomExp += "]";
6202 }
6203}
dsinclair48d91dd2016-05-31 11:54:01 -07006204
6205// static
dsinclair38fd8442016-09-15 10:15:32 -07006206FX_BOOL CXFA_FM2JSContext::GetObjectForName(
dsinclair12a6b0c2016-05-26 11:14:08 -07006207 CFXJSE_Value* pThis,
6208 CFXJSE_Value* accessorValue,
Dan Sinclair1770c022016-03-14 14:14:16 -04006209 const CFX_ByteStringC& szAccessorName) {
dsinclair8f3074b2016-06-02 17:45:25 -07006210 CXFA_Document* pDoc = ToJSContext(pThis, nullptr)->GetDocument();
dsinclairbd136fb2016-06-09 11:47:51 -07006211 if (!pDoc)
6212 return FALSE;
6213
dsinclairdf4bc592016-03-31 20:34:43 -07006214 CXFA_ScriptContext* pScriptContext = pDoc->GetScriptContext();
Dan Sinclair1770c022016-03-14 14:14:16 -04006215 XFA_RESOLVENODE_RS resoveNodeRS;
tsepez736f28a2016-03-25 14:19:51 -07006216 uint32_t dwFlags = XFA_RESOLVENODE_Children | XFA_RESOLVENODE_Properties |
Dan Sinclair1770c022016-03-14 14:14:16 -04006217 XFA_RESOLVENODE_Siblings | XFA_RESOLVENODE_Parent;
6218 int32_t iRet = pScriptContext->ResolveObjects(
6219 pScriptContext->GetThisObject(),
tsepez4c3debb2016-04-08 12:20:38 -07006220 CFX_WideString::FromUTF8(szAccessorName).AsStringC(), resoveNodeRS,
tsepez6fe7d212016-04-06 10:51:14 -07006221 dwFlags);
Dan Sinclair1770c022016-03-14 14:14:16 -04006222 if (iRet >= 1 && resoveNodeRS.dwFlags == XFA_RESOVENODE_RSTYPE_Nodes) {
dsinclairf27aeec2016-06-07 19:36:18 -07006223 accessorValue->Assign(
6224 pScriptContext->GetJSValueFromMap(resoveNodeRS.nodes.GetAt(0)));
dsinclairbd136fb2016-06-09 11:47:51 -07006225 return TRUE;
Dan Sinclair1770c022016-03-14 14:14:16 -04006226 }
dsinclairbd136fb2016-06-09 11:47:51 -07006227 return FALSE;
Dan Sinclair1770c022016-03-14 14:14:16 -04006228}
dsinclair48d91dd2016-05-31 11:54:01 -07006229
6230// static
dsinclair12a6b0c2016-05-26 11:14:08 -07006231int32_t CXFA_FM2JSContext::ResolveObjects(CFXJSE_Value* pThis,
6232 CFXJSE_Value* pRefValue,
Dan Sinclair1770c022016-03-14 14:14:16 -04006233 const CFX_ByteStringC& bsSomExp,
6234 XFA_RESOLVENODE_RS& resoveNodeRS,
6235 FX_BOOL bdotAccessor,
6236 FX_BOOL bHasNoResolveName) {
dsinclair8f3074b2016-06-02 17:45:25 -07006237 CXFA_Document* pDoc = ToJSContext(pThis, nullptr)->GetDocument();
dsinclairbd136fb2016-06-09 11:47:51 -07006238 if (!pDoc)
6239 return -1;
6240
6241 CFX_WideString wsSomExpression = CFX_WideString::FromUTF8(bsSomExp);
dsinclairdf4bc592016-03-31 20:34:43 -07006242 CXFA_ScriptContext* pScriptContext = pDoc->GetScriptContext();
dsinclair48d91dd2016-05-31 11:54:01 -07006243 CXFA_Object* pNode = nullptr;
tsepez736f28a2016-03-25 14:19:51 -07006244 uint32_t dFlags = 0UL;
Dan Sinclair1770c022016-03-14 14:14:16 -04006245 if (bdotAccessor) {
dsinclair769b1372016-06-08 13:12:41 -07006246 if (pRefValue && pRefValue->IsNull()) {
Dan Sinclair1770c022016-03-14 14:14:16 -04006247 pNode = pScriptContext->GetThisObject();
6248 dFlags = XFA_RESOLVENODE_Siblings | XFA_RESOLVENODE_Parent;
6249 } else {
dsinclair8f3074b2016-06-02 17:45:25 -07006250 pNode = CXFA_ScriptContext::ToObject(pRefValue, nullptr);
dsinclair43854a52016-04-27 12:26:00 -07006251 ASSERT(pNode);
Dan Sinclair1770c022016-03-14 14:14:16 -04006252 if (bHasNoResolveName) {
6253 CFX_WideString wsName;
dsinclairbd136fb2016-06-09 11:47:51 -07006254 if (CXFA_Node* pXFANode = pNode->AsNode())
Dan Sinclair1770c022016-03-14 14:14:16 -04006255 pXFANode->GetAttribute(XFA_ATTRIBUTE_Name, wsName, FALSE);
dsinclair017052a2016-06-28 07:43:51 -07006256 if (wsName.IsEmpty())
6257 wsName = FX_WSTRC(L"#") + pNode->GetClassName();
dsinclairbd136fb2016-06-09 11:47:51 -07006258
Dan Sinclair1770c022016-03-14 14:14:16 -04006259 wsSomExpression = wsName + wsSomExpression;
6260 dFlags = XFA_RESOLVENODE_Siblings;
6261 } else {
6262 dFlags = (bsSomExp == "*")
6263 ? (XFA_RESOLVENODE_Children)
6264 : (XFA_RESOLVENODE_Children | XFA_RESOLVENODE_Attributes |
6265 XFA_RESOLVENODE_Properties);
6266 }
6267 }
6268 } else {
dsinclair8f3074b2016-06-02 17:45:25 -07006269 pNode = CXFA_ScriptContext::ToObject(pRefValue, nullptr);
Dan Sinclair1770c022016-03-14 14:14:16 -04006270 dFlags = XFA_RESOLVENODE_AnyChild;
6271 }
dsinclairbd136fb2016-06-09 11:47:51 -07006272 return pScriptContext->ResolveObjects(pNode, wsSomExpression.AsStringC(),
tsepezfc58ad12016-04-05 12:22:15 -07006273 resoveNodeRS, dFlags);
Dan Sinclair1770c022016-03-14 14:14:16 -04006274}
dsinclair48d91dd2016-05-31 11:54:01 -07006275
6276// static
Dan Sinclair1770c022016-03-14 14:14:16 -04006277void CXFA_FM2JSContext::ParseResolveResult(
dsinclair12a6b0c2016-05-26 11:14:08 -07006278 CFXJSE_Value* pThis,
Dan Sinclair1770c022016-03-14 14:14:16 -04006279 const XFA_RESOLVENODE_RS& resoveNodeRS,
dsinclair12a6b0c2016-05-26 11:14:08 -07006280 CFXJSE_Value* pParentValue,
6281 CFXJSE_Value**& resultValues,
Dan Sinclair1770c022016-03-14 14:14:16 -04006282 int32_t& iSize,
6283 FX_BOOL& bAttribute) {
Dan Sinclair1770c022016-03-14 14:14:16 -04006284 iSize = 0;
dsinclair48d91dd2016-05-31 11:54:01 -07006285 resultValues = nullptr;
dsinclairbd136fb2016-06-09 11:47:51 -07006286
6287 CXFA_FM2JSContext* pContext = ToJSContext(pThis, nullptr);
6288 v8::Isolate* pIsolate = pContext->GetScriptRuntime();
Dan Sinclair1770c022016-03-14 14:14:16 -04006289 if (resoveNodeRS.dwFlags == XFA_RESOVENODE_RSTYPE_Nodes) {
6290 bAttribute = FALSE;
6291 iSize = resoveNodeRS.nodes.GetSize();
dsinclair12a6b0c2016-05-26 11:14:08 -07006292 resultValues = FX_Alloc(CFXJSE_Value*, iSize);
Dan Sinclair1770c022016-03-14 14:14:16 -04006293 for (int32_t i = 0; i < iSize; i++) {
dsinclair86fad992016-05-31 11:34:04 -07006294 resultValues[i] = new CFXJSE_Value(pIsolate);
dsinclairf27aeec2016-06-07 19:36:18 -07006295 resultValues[i]->Assign(
Dan Sinclair1770c022016-03-14 14:14:16 -04006296 pContext->GetDocument()->GetScriptContext()->GetJSValueFromMap(
6297 resoveNodeRS.nodes.GetAt(i)));
6298 }
dsinclairbd136fb2016-06-09 11:47:51 -07006299 return;
Dan Sinclair1770c022016-03-14 14:14:16 -04006300 }
dsinclairbd136fb2016-06-09 11:47:51 -07006301
6302 CXFA_ValueArray objectProperties(pIsolate);
6303 int32_t iRet = resoveNodeRS.GetAttributeResult(objectProperties);
6304 bAttribute = (iRet == 0);
6305 if (!bAttribute) {
6306 iSize = iRet;
6307 resultValues = FX_Alloc(CFXJSE_Value*, iSize);
6308 for (int32_t i = 0; i < iSize; i++) {
6309 resultValues[i] = new CFXJSE_Value(pIsolate);
6310 resultValues[i]->Assign(objectProperties[i]);
6311 }
6312 return;
6313 }
6314
6315 if (!pParentValue || !pParentValue->IsObject())
6316 return;
6317
6318 iSize = 1;
6319 resultValues = FX_Alloc(CFXJSE_Value*, 1);
6320 resultValues[0] = new CFXJSE_Value(pIsolate);
6321 resultValues[0]->Assign(pParentValue);
Dan Sinclair1770c022016-03-14 14:14:16 -04006322}
dsinclair48d91dd2016-05-31 11:54:01 -07006323
6324// static
dsinclair12a6b0c2016-05-26 11:14:08 -07006325int32_t CXFA_FM2JSContext::ValueToInteger(CFXJSE_Value* pThis,
6326 CFXJSE_Value* pValue) {
dsinclair769b1372016-06-08 13:12:41 -07006327 if (!pValue)
6328 return 0;
6329
dsinclair8f3074b2016-06-02 17:45:25 -07006330 v8::Isolate* pIsolate = ToJSContext(pThis, nullptr)->GetScriptRuntime();
dsinclair769b1372016-06-08 13:12:41 -07006331 if (pValue->IsArray()) {
dsinclair86fad992016-05-31 11:34:04 -07006332 std::unique_ptr<CFXJSE_Value> propertyValue(new CFXJSE_Value(pIsolate));
6333 std::unique_ptr<CFXJSE_Value> jsObjectValue(new CFXJSE_Value(pIsolate));
6334 std::unique_ptr<CFXJSE_Value> newPropertyValue(new CFXJSE_Value(pIsolate));
dsinclairf27aeec2016-06-07 19:36:18 -07006335 pValue->GetObjectPropertyByIdx(1, propertyValue.get());
6336 pValue->GetObjectPropertyByIdx(2, jsObjectValue.get());
dsinclair769b1372016-06-08 13:12:41 -07006337 if (propertyValue->IsNull()) {
dsinclair86fad992016-05-31 11:34:04 -07006338 GetObjectDefaultValue(jsObjectValue.get(), newPropertyValue.get());
dsinclairbd136fb2016-06-09 11:47:51 -07006339 return ValueToInteger(pThis, newPropertyValue.get());
Dan Sinclair1770c022016-03-14 14:14:16 -04006340 }
dsinclairbd136fb2016-06-09 11:47:51 -07006341
dsinclair2f5582f2016-06-09 11:48:23 -07006342 jsObjectValue->GetObjectProperty(propertyValue->ToString().AsStringC(),
dsinclairbd136fb2016-06-09 11:47:51 -07006343 newPropertyValue.get());
6344 return ValueToInteger(pThis, newPropertyValue.get());
6345 }
6346 if (pValue->IsObject()) {
dsinclair86fad992016-05-31 11:34:04 -07006347 std::unique_ptr<CFXJSE_Value> newPropertyValue(new CFXJSE_Value(pIsolate));
6348 GetObjectDefaultValue(pValue, newPropertyValue.get());
dsinclairbd136fb2016-06-09 11:47:51 -07006349 return ValueToInteger(pThis, newPropertyValue.get());
6350 }
dsinclair2f5582f2016-06-09 11:48:23 -07006351 if (pValue->IsString())
6352 return FXSYS_atoi(pValue->ToString().c_str());
dsinclairbd136fb2016-06-09 11:47:51 -07006353 return pValue->ToInteger();
Dan Sinclair1770c022016-03-14 14:14:16 -04006354}
dsinclair48d91dd2016-05-31 11:54:01 -07006355
6356// static
dsinclair12a6b0c2016-05-26 11:14:08 -07006357FX_FLOAT CXFA_FM2JSContext::ValueToFloat(CFXJSE_Value* pThis,
6358 CFXJSE_Value* arg) {
dsinclair769b1372016-06-08 13:12:41 -07006359 if (!arg)
6360 return 0.0f;
6361
dsinclair8f3074b2016-06-02 17:45:25 -07006362 v8::Isolate* pIsolate = ToJSContext(pThis, nullptr)->GetScriptRuntime();
dsinclair769b1372016-06-08 13:12:41 -07006363 if (arg->IsArray()) {
dsinclair86fad992016-05-31 11:34:04 -07006364 std::unique_ptr<CFXJSE_Value> propertyValue(new CFXJSE_Value(pIsolate));
6365 std::unique_ptr<CFXJSE_Value> jsObjectValue(new CFXJSE_Value(pIsolate));
6366 std::unique_ptr<CFXJSE_Value> newPropertyValue(new CFXJSE_Value(pIsolate));
dsinclairf27aeec2016-06-07 19:36:18 -07006367 arg->GetObjectPropertyByIdx(1, propertyValue.get());
6368 arg->GetObjectPropertyByIdx(2, jsObjectValue.get());
dsinclair769b1372016-06-08 13:12:41 -07006369 if (propertyValue->IsNull()) {
dsinclair86fad992016-05-31 11:34:04 -07006370 GetObjectDefaultValue(jsObjectValue.get(), newPropertyValue.get());
dsinclairbd136fb2016-06-09 11:47:51 -07006371 return ValueToFloat(pThis, newPropertyValue.get());
Dan Sinclair1770c022016-03-14 14:14:16 -04006372 }
dsinclair2f5582f2016-06-09 11:48:23 -07006373 jsObjectValue->GetObjectProperty(propertyValue->ToString().AsStringC(),
dsinclairbd136fb2016-06-09 11:47:51 -07006374 newPropertyValue.get());
6375 return ValueToFloat(pThis, newPropertyValue.get());
6376 }
6377 if (arg->IsObject()) {
dsinclair86fad992016-05-31 11:34:04 -07006378 std::unique_ptr<CFXJSE_Value> newPropertyValue(new CFXJSE_Value(pIsolate));
6379 GetObjectDefaultValue(arg, newPropertyValue.get());
dsinclairbd136fb2016-06-09 11:47:51 -07006380 return ValueToFloat(pThis, newPropertyValue.get());
6381 }
dsinclair2f5582f2016-06-09 11:48:23 -07006382 if (arg->IsString())
6383 return (FX_FLOAT)XFA_ByteStringToDouble(arg->ToString().AsStringC());
dsinclairbd136fb2016-06-09 11:47:51 -07006384 if (arg->IsUndefined())
6385 return 0;
6386
6387 return arg->ToFloat();
Dan Sinclair1770c022016-03-14 14:14:16 -04006388}
dsinclair48d91dd2016-05-31 11:54:01 -07006389
6390// static
dsinclair12a6b0c2016-05-26 11:14:08 -07006391FX_DOUBLE CXFA_FM2JSContext::ValueToDouble(CFXJSE_Value* pThis,
6392 CFXJSE_Value* arg) {
dsinclair769b1372016-06-08 13:12:41 -07006393 if (!arg)
6394 return 0;
6395
dsinclair8f3074b2016-06-02 17:45:25 -07006396 v8::Isolate* pIsolate = ToJSContext(pThis, nullptr)->GetScriptRuntime();
dsinclair769b1372016-06-08 13:12:41 -07006397 if (arg->IsArray()) {
dsinclair86fad992016-05-31 11:34:04 -07006398 std::unique_ptr<CFXJSE_Value> propertyValue(new CFXJSE_Value(pIsolate));
6399 std::unique_ptr<CFXJSE_Value> jsObjectValue(new CFXJSE_Value(pIsolate));
6400 std::unique_ptr<CFXJSE_Value> newPropertyValue(new CFXJSE_Value(pIsolate));
dsinclairf27aeec2016-06-07 19:36:18 -07006401 arg->GetObjectPropertyByIdx(1, propertyValue.get());
6402 arg->GetObjectPropertyByIdx(2, jsObjectValue.get());
dsinclair769b1372016-06-08 13:12:41 -07006403 if (propertyValue->IsNull()) {
dsinclair86fad992016-05-31 11:34:04 -07006404 GetObjectDefaultValue(jsObjectValue.get(), newPropertyValue.get());
dsinclairbd136fb2016-06-09 11:47:51 -07006405 return ValueToDouble(pThis, newPropertyValue.get());
Dan Sinclair1770c022016-03-14 14:14:16 -04006406 }
dsinclair2f5582f2016-06-09 11:48:23 -07006407 jsObjectValue->GetObjectProperty(propertyValue->ToString().AsStringC(),
dsinclairbd136fb2016-06-09 11:47:51 -07006408 newPropertyValue.get());
6409 return ValueToDouble(pThis, newPropertyValue.get());
6410 }
6411 if (arg->IsObject()) {
dsinclair86fad992016-05-31 11:34:04 -07006412 std::unique_ptr<CFXJSE_Value> newPropertyValue(new CFXJSE_Value(pIsolate));
6413 GetObjectDefaultValue(arg, newPropertyValue.get());
dsinclairbd136fb2016-06-09 11:47:51 -07006414 return ValueToDouble(pThis, newPropertyValue.get());
6415 }
dsinclair2f5582f2016-06-09 11:48:23 -07006416 if (arg->IsString())
6417 return XFA_ByteStringToDouble(arg->ToString().AsStringC());
dsinclairbd136fb2016-06-09 11:47:51 -07006418 if (arg->IsUndefined())
6419 return 0;
6420 return arg->ToDouble();
Dan Sinclair1770c022016-03-14 14:14:16 -04006421}
tsepez1c9cfe12016-05-26 13:30:56 -07006422
dsinclairdbdcb812016-06-01 20:07:22 -07006423// static.
6424double CXFA_FM2JSContext::ExtractDouble(CFXJSE_Value* pThis,
6425 CFXJSE_Value* src,
6426 bool* ret) {
6427 ASSERT(ret);
dsinclairdbdcb812016-06-01 20:07:22 -07006428 *ret = true;
6429
dsinclair769b1372016-06-08 13:12:41 -07006430 if (!src)
6431 return 0;
6432
dsinclairbd136fb2016-06-09 11:47:51 -07006433 if (!src->IsArray())
6434 return ValueToDouble(pThis, src);
dsinclairdbdcb812016-06-01 20:07:22 -07006435
dsinclairbd136fb2016-06-09 11:47:51 -07006436 v8::Isolate* pIsolate = ToJSContext(pThis, nullptr)->GetScriptRuntime();
6437 std::unique_ptr<CFXJSE_Value> lengthValue(new CFXJSE_Value(pIsolate));
6438 src->GetObjectProperty("length", lengthValue.get());
6439 int32_t iLength = lengthValue->ToInteger();
6440 if (iLength <= 2) {
6441 *ret = false;
6442 return 0.0;
dsinclairdbdcb812016-06-01 20:07:22 -07006443 }
dsinclairbd136fb2016-06-09 11:47:51 -07006444
6445 std::unique_ptr<CFXJSE_Value> propertyValue(new CFXJSE_Value(pIsolate));
6446 std::unique_ptr<CFXJSE_Value> jsObjectValue(new CFXJSE_Value(pIsolate));
6447 src->GetObjectPropertyByIdx(1, propertyValue.get());
6448 src->GetObjectPropertyByIdx(2, jsObjectValue.get());
6449 if (propertyValue->IsNull())
6450 return ValueToDouble(pThis, jsObjectValue.get());
6451
dsinclairbd136fb2016-06-09 11:47:51 -07006452 std::unique_ptr<CFXJSE_Value> newPropertyValue(new CFXJSE_Value(pIsolate));
dsinclair2f5582f2016-06-09 11:48:23 -07006453 jsObjectValue->GetObjectProperty(propertyValue->ToString().AsStringC(),
dsinclairbd136fb2016-06-09 11:47:51 -07006454 newPropertyValue.get());
6455 return ValueToDouble(pThis, newPropertyValue.get());
dsinclairdbdcb812016-06-01 20:07:22 -07006456}
6457
dsinclair48d91dd2016-05-31 11:54:01 -07006458// static
dsinclair12a6b0c2016-05-26 11:14:08 -07006459void CXFA_FM2JSContext::ValueToUTF8String(CFXJSE_Value* arg,
6460 CFX_ByteString& szOutputString) {
dsinclair769b1372016-06-08 13:12:41 -07006461 if (!arg)
6462 return;
6463
dsinclair2f5582f2016-06-09 11:48:23 -07006464 if (arg->IsNull() || arg->IsUndefined())
Dan Sinclair1770c022016-03-14 14:14:16 -04006465 szOutputString = "";
dsinclair2f5582f2016-06-09 11:48:23 -07006466 else if (arg->IsBoolean())
dsinclairf27aeec2016-06-07 19:36:18 -07006467 szOutputString = arg->ToBoolean() ? "1" : "0";
dsinclair2f5582f2016-06-09 11:48:23 -07006468 else
6469 szOutputString = arg->ToString();
Dan Sinclair1770c022016-03-14 14:14:16 -04006470}
tsepez1c9cfe12016-05-26 13:30:56 -07006471
dsinclaire80e9f82016-06-01 06:10:04 -07006472// static.
6473int32_t CXFA_FM2JSContext::Translate(const CFX_WideStringC& wsFormcalc,
6474 CFX_WideTextBuf& wsJavascript,
6475 CFX_WideString& wsError) {
6476 if (wsFormcalc.IsEmpty()) {
6477 wsJavascript.Clear();
6478 wsError.clear();
6479 return 0;
6480 }
6481 int32_t status = 0;
6482 CXFA_FMProgram program;
6483 status = program.Init(wsFormcalc);
6484 if (status) {
6485 wsError = program.GetError().message;
6486 return status;
6487 }
6488 status = program.ParseProgram();
6489 if (status) {
6490 wsError = program.GetError().message;
6491 return status;
6492 }
6493 program.TranslateProgram(wsJavascript);
6494 return 0;
6495}
6496
dsinclair48d91dd2016-05-31 11:54:01 -07006497CXFA_FM2JSContext::CXFA_FM2JSContext(v8::Isolate* pScriptIsolate,
6498 CFXJSE_Context* pScriptContext,
6499 CXFA_Document* pDoc)
6500 : m_pIsolate(pScriptIsolate),
dsinclair769b1372016-06-08 13:12:41 -07006501 m_pFMClass(
6502 CFXJSE_Class::Create(pScriptContext, &formcalc_fm2js_descriptor)),
dsinclair48d91dd2016-05-31 11:54:01 -07006503 m_pValue(new CFXJSE_Value(pScriptIsolate)),
6504 m_pDocument(pDoc) {
dsinclairf27aeec2016-06-07 19:36:18 -07006505 m_pValue.get()->SetNull();
6506 m_pValue.get()->SetObject(this, m_pFMClass);
Dan Sinclair1770c022016-03-14 14:14:16 -04006507}
tsepez1c9cfe12016-05-26 13:30:56 -07006508
dsinclair48d91dd2016-05-31 11:54:01 -07006509CXFA_FM2JSContext::~CXFA_FM2JSContext() {}
6510
dsinclair12a6b0c2016-05-26 11:14:08 -07006511void CXFA_FM2JSContext::GlobalPropertyGetter(CFXJSE_Value* pValue) {
dsinclairf27aeec2016-06-07 19:36:18 -07006512 pValue->Assign(m_pValue.get());
Dan Sinclair1770c022016-03-14 14:14:16 -04006513}
tsepez5c4dd352016-05-26 13:57:58 -07006514
dsinclair2235b7b2016-06-02 07:42:25 -07006515void CXFA_FM2JSContext::ThrowException(int32_t iStringID, ...) {
Dan Sinclair1770c022016-03-14 14:14:16 -04006516 IXFA_AppProvider* pAppProvider = m_pDocument->GetNotify()->GetAppProvider();
dsinclair43854a52016-04-27 12:26:00 -07006517 ASSERT(pAppProvider);
Dan Sinclair1770c022016-03-14 14:14:16 -04006518 CFX_WideString wsFormat;
6519 pAppProvider->LoadString(iStringID, wsFormat);
6520 CFX_WideString wsMessage;
6521 va_list arg_ptr;
6522 va_start(arg_ptr, iStringID);
tsepezbd9748d2016-04-13 21:40:19 -07006523 wsMessage.FormatV(wsFormat.c_str(), arg_ptr);
Dan Sinclair1770c022016-03-14 14:14:16 -04006524 va_end(arg_ptr);
tsepez28f97ff2016-04-04 16:41:35 -07006525 FXJSE_ThrowMessage(
dsinclair769b1372016-06-08 13:12:41 -07006526 FX_UTF8Encode(wsMessage.c_str(), wsMessage.GetLength()).AsStringC());
Dan Sinclair1770c022016-03-14 14:14:16 -04006527}